0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 17:51:53 +00:00

Temporary integrated commit (OSPF), unfinished.

This commit is contained in:
Ondrej Zajicek 2012-10-02 11:44:05 +02:00
parent a7b7b2bd0f
commit 5aa9d7447c
19 changed files with 895 additions and 894 deletions

View File

@ -19,13 +19,13 @@
#define IP4_MIN_MTU 576 /* RFC 2328 A.1 */
#define IP6_MIN_MTU 1280 /* RFC 5340 A.1 */
#define IP4_ALL_SPF_ROUTERS ipa_build4(224, 0, 0, 5)
#define IP4_ALL_D_ROUTERS ipa_build4(224, 0, 0, 6)
#define IP4_OSPF_ALL_ROUTERS ipa_build4(224, 0, 0, 5)
#define IP4_OSPF_DES_ROUTERS ipa_build4(224, 0, 0, 6)
#define IP6_All_NODES ipa_build6(0xFF020000, 0, 0, 1)
#define IP6_ALL_NODES ipa_build6(0xFF020000, 0, 0, 1)
#define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2)
#define IP6_ALL_OSPF_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
#define IP6_ALL_OSPF_D_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
#define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
#define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
#define IP4_NONE _MI4(0)
#define IP6_NONE _MI6(0,0,0,0)

View File

@ -143,8 +143,7 @@ ospf_proto_start: proto_start OSPF {
this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
init_list(&OSPF_CFG->area_list);
init_list(&OSPF_CFG->vlink_list);
OSPF_CFG->rfc1583 = DEFAULT_RFC1583;
OSPF_CFG->tick = DEFAULT_OSPFTICK;
OSPF_CFG->tick = OSPF_DEFAULT_TICK;
}
;
@ -166,9 +165,9 @@ ospf_area_start: AREA idval {
this_area = cfg_allocz(sizeof(struct ospf_area_config));
add_tail(&OSPF_CFG->area_list, NODE this_area);
this_area->areaid = $2;
this_area->default_cost = DEFAULT_STUB_COST;
this_area->default_cost = OSPF_DEFAULT_STUB_COST;
this_area->type = OPT_E;
this_area->transint = DEFAULT_TRANSINT;
this_area->transint = OSPF_DEFAULT_TRANSINT;
init_list(&this_area->patt_list);
init_list(&this_area->net_list);

View File

@ -36,20 +36,6 @@ struct ospf_dbdes3_packet
};
#ifdef OSPFv2
#define hton_opt(X) X
#define ntoh_opt(X) X
#endif
#ifdef OSPFv3
#define hton_opt(X) htonl(X)
#define ntoh_opt(X) ntohl(X)
#endif
static inline unsigned
ospf_dbdes_hdrlen(struct proto_ospf *po)
{
@ -69,30 +55,113 @@ ospf_dbdes_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
static void ospf_dbdes_dump(struct proto_ospf *po, struct ospf_packet *pkt)
{
struct proto *p = &po->proto;
struct ospf_lsa_header *lsas;
unsigned i, lsa_count;
u32 pkt_ddseq;
u16 pkt_iface_mtu;
u8 pkt_imms;
ASSERT(pkt->type == DBDES_P);
ospf_dump_common(po, pkt);
log(L_TRACE "%s: imms %s%s%s", p->name,
(imms & DBDES_I) ? "I " : "",
(imms & DBDES_M) ? "M " : "",
(imms & DBDES_MS) ? "MS" : "");
log(L_TRACE "%s: ddseq %u", p->name, ntohl(pkt->ddseq));
if (ospf_is_v2(po))
{
struct ospf_dbdes2_packet *ps = (void *) pkt;
pkt_iface_mtu = ntohs(ps->iface_mtu);
pkt_imms = ps->imms;
pkt_ddseq = ntohl(ps->ddseq);
}
else /* OSPFv3 */
{
struct ospf_dbdes3_packet *ps = (void *) pkt;
pkt_iface_mtu = ntohs(ps->iface_mtu);
pkt_imms = ps->imms;
pkt_ddseq = ntohl(ps->ddseq);
}
struct ospf_lsa_header *plsa = (void *) (pkt + 1);
unsigned int i, j;
log(L_TRACE "%s: mtu %u", po->proto.name, pkt_iface_mtu);
log(L_TRACE "%s: imms %s%s%s", po->proto.name,
(pkt_imms & DBDES_I) ? "I " : "",
(pkt_imms & DBDES_M) ? "M " : "",
(pkt_imms & DBDES_MS) ? "MS" : "");
log(L_TRACE "%s: ddseq %u", po->proto.name, pkt_ddseq);
j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
sizeof(struct ospf_lsa_header);
for (i = 0; i < j; i++)
ospf_dump_lsahdr(p, &lsas[i]);
ospf_dbdes_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
for (i = 0; i < lsa_count; i++)
ospf_dump_lsahdr(po, lsas + i);
}
static void
ospf_dbdes_prepare(struct ospf_neighbor *n, struct ospf_packet *pkt, int lsdb)
{
struct ospf_iface *ifa = n->ifa;
struct proto_ospf *po = ifa->oa->po;
int i = 0;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
if (lsdb && (n->myimms & DBDES_M))
{
struct ospf_lsa_header *lsas;
unsigned lsa_max;
snode *sn;
ospf_dbdes_body(po, pkt, ospf_pkt_maxsize(ifa), &lsas, &lsa_max);
sn = s_get(&(n->dbsi));
while (i < lsa_max)
{
struct top_hash_entry *en = (struct top_hash_entry *) sn;
if (lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
{
lsa_hton_hdr(&(en->lsa), lsas + i);
i++;
}
if (sn == STAIL(po->lsal))
{
n->myimms &= ~DBDES_M; /* Unset more bit */
break;
}
sn = sn->next;
}
s_put(&(n->dbsi), sn);
}
u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
unsigned length;
if (ospf_is_v2(po))
{
struct ospf_dbdes2_packet *ps = (void *) pkt;
ps->iface_mtu = htons(iface_mtu);
ps->options = ifa->oa->options;
ps->imms = n->myimms;
ps->ddseq = htonl(n->dds);
length = sizeof(struct ospf_dbdes2_packet);
}
else /* OSPFv3 */
{
struct ospf_dbdes3_packet *ps = (void *) pkt;
ps->options = htonl(ifa->oa->options);
ps->iface_mtu = htons(iface_mtu);
ps->imms = n->myimms;
ps->ddseq = htonl(n->dds);
length = sizeof(struct ospf_dbdes3_packet);
}
length += i * sizeof(struct ospf_lsa_header);
pkt->length = htons(length);
}
/**
* ospf_dbdes_send - transmit database description packet
* @n: neighbor
@ -110,10 +179,8 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
struct ospf_iface *ifa = n->ifa;
struct ospf_area *oa = ifa->oa;
struct proto_ospf *po = oa->po;
struct ospf_dbdes_packet *pkt;
struct ospf_packet *op;
u16 length, i, j;
struct ospf_packet *pkt;
unsigned length;
/* FIXME ??? */
if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
@ -121,19 +188,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
switch (n->state)
{
case NEIGHBOR_EXSTART: /* Send empty packets */
case NEIGHBOR_EXSTART:
n->myimms |= DBDES_I;
pkt = ospf_tx_buffer(ifa);
op = &pkt->ospf_packet;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu);
pkt->options = hton_opt(oa->options);
pkt->imms = n->myimms;
pkt->ddseq = htonl(n->dds);
length = sizeof(struct ospf_dbdes_packet);
op->length = htons(length);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
/* Send empty packets */
pkt = ospf_tx_buffer(ifa);
ospf_dbdes_prepare(n, pkt, 0);
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
ospf_send_to(ifa, n->ip);
break;
@ -141,72 +202,12 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
n->myimms &= ~DBDES_I;
if (next)
{
snode *sn;
struct ospf_lsa_header *lsa;
pkt = n->ldbdes;
op = (struct ospf_packet *) pkt;
ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu);
pkt->ddseq = htonl(n->dds);
pkt->options = hton_opt(oa->options);
j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
if (n->myimms & DBDES_M)
{
sn = s_get(&(n->dbsi));
DBG("Number of LSA: %d\n", j);
for (; i > 0; i--)
{
struct top_hash_entry *en= (struct top_hash_entry *) sn;
if (ospf_lsa_flooding_allowed(&en->lsa, en->domain, ifa))
{
htonlsah(&(en->lsa), lsa);
DBG("Working on: %d\n", i);
DBG("\tX%01x %-1R %-1R %p\n", en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa_body);
lsa++;
}
else i++; /* No lsa added */
if (sn == STAIL(po->lsal))
{
i--;
break;
}
sn = sn->next;
}
if (sn == STAIL(po->lsal))
{
DBG("Number of LSA NOT sent: %d\n", i);
DBG("M bit unset.\n");
n->myimms &= ~DBDES_M; /* Unset more bit */
}
s_put(&(n->dbsi), sn);
}
pkt->imms = n->myimms;
length = (j - i) * sizeof(struct ospf_lsa_header) +
sizeof(struct ospf_dbdes_packet);
op->length = htons(length);
DBG("%s: DB_DES (M) prepared for %I.\n", p->name, n->ip);
}
ospf_dbdes_prepare(n, n->ldbdes, 1);
case NEIGHBOR_LOADING:
case NEIGHBOR_FULL:
length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
if (!length)
{
OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating");
@ -218,21 +219,19 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
pkt = ospf_tx_buffer(ifa);
memcpy(pkt, n->ldbdes, length);
OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
ospf_send_to(ifa, n->ip);
/* XXXX remove this? */
if (n->myimms & DBDES_MS)
tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
if (!(n->myimms & DBDES_MS))
{
if (!(n->myimms & DBDES_M) &&
!(n->imms & DBDES_M) &&
(n->state == NEIGHBOR_EXCHANGE))
{
ospf_neigh_sm(n, INM_EXDONE);
}
}
break;
default: /* Ignore it */
@ -241,36 +240,35 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
}
static void
ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
ospf_dbdes_process(struct ospf_neighbor *n, struct ospf_packet *pkt, unsigned plen)
{
struct ospf_lsa_header *plsa, lsa;
struct top_hash_entry *he, *sn;
struct ospf_area *oa = n->ifa->oa;
struct top_graph *gr = oa->po->gr;
struct ospf_packet *op;
int i, j;
struct ospf_iface *ifa = n->ifa;
struct proto_ospf *po = ifa->oa->po;
struct ospf_lsa_header *lsas;
unsigned i, lsa_count;
op = (struct ospf_packet *) ps;
ospf_dbdes_body(po, pkt, plen, &lsas, &lsa_count);
plsa = (void *) (ps + 1);
j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
sizeof(struct ospf_lsa_header);
for (i = 0; i < j; i++)
for (i = 0; i < lsa_count; i++)
{
ntohlsah(plsa + i, &lsa);
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
if (((he = ospf_hash_find_header(gr, dom, &lsa)) == NULL) ||
(lsa_comp(&lsa, &(he->lsa)) == 1))
struct top_hash_entry *en, *req;
struct ospf_lsa_header lsa;
u32 lsa_type, lsa_domain;
lsa_ntoh_hdr(lsas + i, &lsa);
lsa_xxxxtype(lsa.type_raw, ifa, &lsa_type, &lsa_domain);
/* XXXX: Add check for 0-type or flooding_allowed */
en = ospf_hash_find(po->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
{
/* Is this condition necessary? */
if (ospf_hash_find_header(n->lsrqh, dom, &lsa) == NULL)
{
sn = ospf_hash_get_header(n->lsrqh, dom, &lsa);
ntohlsah(plsa + i, &(sn->lsa));
s_add_tail(&(n->lsrql), SNODE sn);
}
req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
if (ospf_hash_is_new(req))
s_add_tail(&(n->lsrql), SNODE req);
en->lsa = lsa;
}
}
}
@ -280,19 +278,22 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
struct proto_ospf *po = ifa->oa->po;
u32 rcv_ddseq, rcv_options;
u16 rcv_iface_mtu;
u8 rcv_imms;
unsigned plen;
unsigned int size = ntohs(ps_i->length);
if (size < sizeof(struct ospf_dbdes_packet))
plen = ntohs(pkt->length);
if (plen < ospf_dbdes_hdrlen(po))
{
log(L_ERR "Bad OSPF DBDES packet from %I - too short (%u B)", n->ip, size);
log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen);
return;
}
OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
ospf_neigh_sm(n, INM_HELLOREC);
if (ospf_is_v2(po))
{
struct ospf_dbdes2_packet *ps = (void *) pkt;
@ -310,10 +311,6 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
rcv_ddseq = ntohl(ps->ddseq);
}
OSPF_PACKET(ospf_dbdes_dump, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
ospf_neigh_sm(n, INM_HELLOREC);
switch (n->state)
{
case NEIGHBOR_DOWN:
@ -331,12 +328,12 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
(rcv_iface_mtu != 0) &&
(ifa->iface->mtu != 0) &&
(ifa->type != OSPF_IT_VLINK))
log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)",
n->ip, ifa->iface->name, rcv_iface_mtu, ifa->iface->mtu);
if ((rcv_imms == DBDES_IMMS) &&
(n->rid > po->router_id) &&
(size == sizeof(struct ospf_dbdes_packet)))
(plen == ospf_dbdes_hdrlen(po)))
{
/* I'm slave! */
n->dds = rcv_ddseq;
@ -374,7 +371,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
(rcv_ddseq == n->ddr))
{
/* Duplicate packet */
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */
@ -417,7 +414,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
n->dds++;
DBG("Incrementing dds\n");
ospf_dbdes_reqladd(ps, n);
ospf_dbdes_process(n, pkt, plen);
if (!(n->myimms & DBDES_M) &&
!(rcv_imms & DBDES_M))
{
@ -439,7 +436,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
n->ddr = rcv_ddseq;
n->dds = rcv_ddseq;
ospf_dbdes_reqladd(ps, n);
ospf_dbdes_process(n, pkt, plen);
ospf_dbdes_send(n, 1);
}
break;
@ -451,7 +448,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
(rcv_ddseq == n->ddr))
/* Only duplicate are accepted */
{
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */

View File

@ -48,7 +48,6 @@ ospf_hello_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n, ip_addr faddr)
{
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
char *beg = "OSPF: Bad HELLO packet from ";
unsigned int size, i, two_way;

View File

@ -72,6 +72,8 @@ find_nbma_node_in(list *nnl, ip_addr ip)
static int
ospf_sk_open(struct ospf_iface *ifa)
{
struct proto_ospf *po = ifa->oa->po;
sock *sk = sk_new(ifa->pool);
sk->type = SK_IP;
sk->dport = OSPF_PROTO;
@ -90,11 +92,10 @@ ospf_sk_open(struct ospf_iface *ifa)
if (sk_open(sk) != 0)
goto err;
#ifdef OSPFv3
/* 12 is an offset of the checksum in an OSPF packet */
if (sk_set_ipv6_checksum(sk, 12) < 0)
goto err;
#endif
/* 12 is an offset of the checksum in an OSPFv3 packet */
if (ospf_is_v3(po))
if (sk_set_ipv6_checksum(sk, 12) < 0)
goto err;
/*
* For OSPFv2: When sending a packet, it is important to have a
@ -123,14 +124,16 @@ ospf_sk_open(struct ospf_iface *ifa)
if (ifa->cf->real_bcast)
{
ifa->all_routers = ifa->addr->brd;
ifa->des_routers = IPA_NONE;
if (sk_set_broadcast(sk, 1) < 0)
goto err;
}
else
{
ifa->all_routers = AllSPFRouters;
sk->ttl = 1; /* Hack, this will affect just multicast packets */
ifa->all_routers = ospf_is_v2(po) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
ifa->des_routers = ospf_is_v2(po) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
sk->ttl = 1; /* Hack, this will affect just the multicast packets */
if (sk_setup_multicast(sk) < 0)
goto err;
@ -155,7 +158,7 @@ ospf_sk_join_dr(struct ospf_iface *ifa)
if (ifa->sk_dr)
return;
sk_join_group(ifa->sk, AllDRouters);
sk_join_group(ifa->sk, ifa->des_routers);
ifa->sk_dr = 1;
}
@ -165,7 +168,7 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
if (!ifa->sk_dr)
return;
sk_leave_group(ifa->sk, AllDRouters);
sk_leave_group(ifa->sk, ifa->des_routers);
ifa->sk_dr = 0;
}
@ -178,13 +181,15 @@ ospf_iface_down(struct ospf_iface *ifa)
if (ifa->type != OSPF_IT_VLINK)
{
#ifdef OSPFv2
OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
#else
OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
#endif
if (ospf_is_v3(ifa->oa->po))
OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
else if (ifa->addr->flags & IA_PEER)
OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
ifa->iface->name, ifa->addr->opposite, ifa->oa->areaid);
else
OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
/* First of all kill all the related vlinks */
WALK_LIST(iff, po->iface_list)
@ -221,10 +226,8 @@ ospf_iface_down(struct ospf_iface *ifa)
ifa->rt_pos_beg = 0;
ifa->rt_pos_end = 0;
#ifdef OSPFv3
ifa->px_pos_beg = 0;
ifa->px_pos_end = 0;
#endif
}
@ -275,7 +278,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
{
if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
ospf_sk_join_dr(ifa);
@ -499,16 +502,15 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
if (ip->type == OSPF_IT_VLINK)
OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
else
{
#ifdef OSPFv2
OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
iface->name, addr->prefix, addr->pxlen, oa->areaid);
#else
else if (ospf_is_v3(po))
OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
iface->name, ip->instance_id, oa->areaid);
#endif
}
else if (ifa->addr->flags & IA_PEER)
OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
iface->name, addr->opposite, oa->areaid);
else
OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
iface->name, addr->prefix, addr->pxlen, oa->areaid);
pool = rp_new(po->proto.pool, "OSPF Interface");
ifa = mb_allocz(pool, sizeof(struct ospf_iface));
@ -532,15 +534,9 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
ifa->rxbuf = ip->rxbuf;
ifa->check_link = ip->check_link;
ifa->ecmp_weight = ip->ecmp_weight;
#ifdef OSPFv2
ifa->autype = ip->autype;
ifa->passwords = ip->passwords;
#endif
#ifdef OSPFv3
ifa->instance_id = ip->instance_id;
#endif
ifa->type = ospf_iface_classify(ip->type, addr);
@ -548,13 +544,11 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
int old_type = ifa->type;
u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
#ifdef OSPFv2
if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
if (ospf_is_v2(po) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
ifa->type = OSPF_IT_PTP;
if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
if (ospf_is_v2(po) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
ifa->type = OSPF_IT_PTMP;
#endif
if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
ifa->type = OSPF_IT_NBMA;
@ -564,7 +558,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
if (ifa->type != old_type)
log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
p->name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
po->proto.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
init_list(&ifa->neigh_list);
@ -595,11 +589,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
*/
lock = olock_new(pool);
#ifdef OSPFv2
lock->addr = ifa->addr->prefix;
#else /* OSPFv3 */
lock->addr = _MI(0,0,0,ifa->instance_id);
#endif
lock->addr = ospf_is_v2(po) ? ifa->addr->prefix : _MI6(0,0,0,ifa->instance_id);
lock->type = OBJLOCK_IP;
lock->port = OSPF_PROTO;
lock->iface = iface;
@ -702,7 +692,6 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
ifa->inftransdelay = new->inftransdelay;
}
#ifdef OSPFv2
/* AUTHENTICATION */
if (ifa->autype != new->autype)
{
@ -712,7 +701,6 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* Update passwords */
ifa->passwords = new->passwords;
#endif
/* Remaining options are just for proper interfaces */
if (ifa->type == OSPF_IT_VLINK)
@ -1133,14 +1121,13 @@ ospf_iface_info(struct ospf_iface *ifa)
}
else
{
#ifdef OSPFv2
if (ifa->addr->flags & IA_PEER)
if (ospf_is_v3(ifa->oa->po))
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
else if (ifa->addr->flags & IA_PEER)
cli_msg(-1015, "Interface %s (peer %I)", ifa->iface->name, ifa->addr->opposite);
else
cli_msg(-1015, "Interface %s (%I/%d)", ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen);
#else /* OSPFv3 */
cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
#endif
cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
}

View File

@ -96,10 +96,8 @@ ospf_lsack_send_one(struct ospf_neighbor *n, int queue)
{
if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
ospf_send_to_all(ifa);
else if (ifa->cf->real_bcast)
ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
ospf_send_to_des(ifa);
}
else
ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
@ -127,6 +125,7 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_lsa_header lsa, *lsas;
struct top_hash_entry *en;
unsigned i, lsa_count;
u32 lsa_dom, lsa_type;
/* No need to check length, lsack has only basic header */
@ -142,9 +141,11 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
for (i = 0; i < lsa_count; i++)
{
ntohlsah(&lsas[i], &lsa);
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
lsa_ntoh_hdr(&lsas[i], &lsa);
lsa_xxxxtype(lsa.type_raw, n->ifa, &lsa_type, &lsa_dom);
en = ospf_hash_find(n->lsrth, lsa_dom, lsa.id, lsa.rt, lsa_type);
if (!en)
continue; /* pg 155 */
if (lsa_comp(&lsa, &en->lsa) != CMP_SAME) /* pg 156 */
@ -154,7 +155,7 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
lsa.type, lsa.id, lsa.rt);
lsa_type, lsa.id, lsa.rt);
OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
en->lsa.age, en->lsa.sn, en->lsa.checksum);
OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
@ -162,8 +163,8 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
continue;
}
DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n",
lsa.id, lsa.rt, lsa.type, n->rid);
DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
lsa_type, lsa.id, lsa.rt, n->rid);
s_rem_node(SNODE en);
ospf_hash_delete(n->lsrth, en);
}

View File

@ -89,10 +89,10 @@ ospf_age(struct proto_ospf *po)
#ifndef CPU_BIG_ENDIAN
void
htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
{
n->age = htons(h->age);
n->type_raw = htont(h->type_raw);
n->type_raw = htons(h->type_raw);
n->id = htonl(h->id);
n->rt = htonl(h->rt);
n->sn = htonl(h->sn);
@ -101,10 +101,10 @@ htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
}
void
ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
{
h->age = ntohs(n->age);
h->type_raw = ntoht(n->type_raw);
h->type_raw = ntohs(n->type_raw);
h->id = ntohl(n->id);
h->rt = ntohl(n->rt);
h->sn = ntohl(n->sn);
@ -113,7 +113,7 @@ ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
}
void
htonlsab(void *h, void *n, u16 len)
lsa_hton_body(void *h, void *n, u16 len)
{
u32 *hid = h;
u32 *nid = n;
@ -124,7 +124,7 @@ htonlsab(void *h, void *n, u16 len)
}
void
ntohlsab(void *n, void *h, u16 len)
lsa_ntoh_body(void *n, void *h, u16 len)
{
u32 *nid = n;
u32 *hid = h;
@ -135,6 +135,95 @@ ntohlsab(void *n, void *h, u16 len)
}
#endif /* little endian */
int
lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
{
/* 4.5.2 (Case 2) */
switch (LSA_SCOPE(type))
{
case LSA_SCOPE_LINK:
return ifa->iface->index == domain;
case LSA_SCOPE_AREA:
return ifa->oa->areaid == domain;
case LSA_SCOPE_AS:
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (!oa_is_ext(ifa->oa))
return 0;
return 1;
default:
log(L_ERR "OSPF: LSA with invalid scope");
return 0;
}
}
static int
unknown_lsa_type(u32 type)
{
switch (type)
{
case LSA_T_RT:
case LSA_T_NET:
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
case LSA_T_NSSA:
case LSA_T_LINK:
case LSA_T_PREFIX:
return 0;
default:
return 1;
}
}
#define LSA_V2_TMAX 8
static const u16 lsa_v2_types[LSA_V2_TMAX] =
{0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA};
void
lsa_xxxxtype(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain)
{
if (ospf_is_v2(ifa->oa->po))
{
itype = itype & LSA_T_V2_MASK;
itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0;
}
else
{
/* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
if (unknown_lsa_type(itype) && !(itype & LSA_UBIT))
itype = itype & ~LSA_SCOPE_MASK;
}
*otype = itype;
switch (LSA_SCOPE(itype))
{
case LSA_SCOPE_LINK:
*domain = ifa->iface->index;
return;
case LSA_SCOPE_AREA:
*domain = ifa->oa->areaid;
return;
case LSA_SCOPE_AS:
default:
*domain = 0;
return;
}
}
/*
void
buf_dump(const char *hdr, const byte *buf, int blen)
@ -179,8 +268,8 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
u16 length = h->length;
// log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
htonlsah(h, h);
htonlsab1(body, length - sizeof(struct ospf_lsa_header));
lsa_hton_hdr(h, h);
lsa_hton_body1(body, length - sizeof(struct ospf_lsa_header));
/*
char buf[1024];
@ -193,8 +282,8 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
// log(L_WARN "Checksum result %4x", h->checksum);
ntohlsah(h, h);
ntohlsab1(body, length - sizeof(struct ospf_lsa_header));
lsa_ntoh_hdr(h, h);
lsa_ntoh_body1(body, length - sizeof(struct ospf_lsa_header));
}
/*
@ -427,30 +516,60 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
#define HDRLEN sizeof(struct ospf_lsa_header)
static int
lsa_validate_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
lsa_validate_rt2(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
{
unsigned int i, max;
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
return 0;
struct ospf_lsa_rt_link *rtl = (struct ospf_lsa_rt_link *) (body + 1);
max = lsa_rt_count(lsa);
unsigned i = 0;
void *buf = body;
void *bufend = buf + lsa->length - HDRLEN;
buf += sizeof(struct ospf_lsa_rt);
#ifdef OSPFv2
if (body->links != max)
return 0;
#endif
for (i = 0; i < max; i++)
while (buf < bufend)
{
u8 type = rtl[i].type;
if (!((type == LSART_PTP) ||
(type == LSART_NET) ||
#ifdef OSPFv2
(type == LSART_STUB) ||
#endif
(type == LSART_VLNK)))
struct ospf_lsa_rt2_link *l = buf;
buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
i++;
if (buf > bufend)
return 0;
if (!((l->type == LSART_PTP) ||
(l->type == LSART_NET) ||
(l->type == LSART_STUB) ||
(l->type == LSART_VLNK)))
return 0;
}
if ((body->options & LSA_RT2_LINKS) != i)
return 0;
return 1;
}
static int
lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
return 0;
void *buf = body;
void *bufend = buf + lsa->length - HDRLEN;
buf += sizeof(struct ospf_lsa_rt);
while (buf < bufend)
{
struct ospf_lsa_rt3_link *l = buf;
buf += sizeof(struct ospf_lsa_rt3_link);
if (buf > bufend)
return 0;
if (!((l->type == LSART_PTP) ||
(l->type == LSART_NET) ||
(l->type == LSART_VLNK)))
return 0;
}
return 1;
@ -465,37 +584,18 @@ lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
return 1;
}
#ifdef OSPFv2
static int
lsa_validate_sum(struct ospf_lsa_header *lsa, struct ospf_lsa_sum *body)
lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum)))
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2)))
return 0;
/* First field should have TOS = 0, we ignore other TOS fields */
if ((body->metric & LSA_SUM_TOS) != 0)
if ((body->metric & LSA_SUM2_TOS) != 0)
return 0;
return 1;
}
#define lsa_validate_sum_net(A,B) lsa_validate_sum(A,B)
#define lsa_validate_sum_rt(A,B) lsa_validate_sum(A,B)
static int
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext)))
return 0;
/* First field should have TOS = 0, we ignore other TOS fields */
if ((body->metric & LSA_EXT_TOS) != 0)
return 0;
return 1;
}
#else /* OSPFv3 */
static inline int
pxlen(u32 *buf)
@ -504,7 +604,7 @@ pxlen(u32 *buf)
}
static int
lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
return 0;
@ -520,9 +620,8 @@ lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body
return 1;
}
static int
lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
{
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
return 0;
@ -531,7 +630,20 @@ lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
}
static int
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2)))
return 0;
/* First field should have TOS = 0, we ignore other TOS fields */
if ((body->metric & LSA_EXT2_TOS) != 0)
return 0;
return 1;
}
static int
lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
{
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
return 0;
@ -596,8 +708,6 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
}
#endif
/**
* lsa_validate - check whether given LSA is valid
@ -609,31 +719,50 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
*/
int
lsa_validate(struct ospf_lsa_header *lsa, void *body)
lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
{
switch (lsa->type)
if (ospf2)
{
switch (lsa_type)
{
case LSA_T_RT:
return lsa_validate_rt(lsa, body);
return lsa_validate_rt2(lsa, body);
case LSA_T_NET:
return lsa_validate_net(lsa, body);
case LSA_T_SUM_NET:
return lsa_validate_sum_net(lsa, body);
return lsa_validate_sum2(lsa, body);
case LSA_T_SUM_RT:
return lsa_validate_sum_rt(lsa, body);
return lsa_validate_sum2(lsa, body);
case LSA_T_EXT:
case LSA_T_NSSA:
return lsa_validate_ext(lsa, body);
return lsa_validate_ext2(lsa, body);
default:
return 0; /* Should not happen, unknown LSAs are already rejected */
}
}
else
{
switch (lsa_type)
{
case LSA_T_RT:
return lsa_validate_rt3(lsa, body);
case LSA_T_NET:
return lsa_validate_net(lsa, body);
case LSA_T_SUM_NET:
return lsa_validate_sum3_net(lsa, body);
case LSA_T_SUM_RT:
return lsa_validate_sum3_rt(lsa, body);
case LSA_T_EXT:
case LSA_T_NSSA:
return lsa_validate_ext3(lsa, body);
case LSA_T_LINK:
return lsa_validate_link(lsa, body);
case LSA_T_PREFIX:
return lsa_validate_prefix(lsa, body);
default:
/* In OSPFv3, unknown LSAs are OK,
In OSPFv2, unknown LSAs are already rejected
*/
return 1;
return 1; /* Unknown LSAs are OK in OSPFv3 */
}
}
}
/**

View File

@ -11,19 +11,19 @@
#define _BIRD_OSPF_LSALIB_H_
#ifdef CPU_BIG_ENDIAN
static inline void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n) { *n = *h; };
static inline void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h) { *h = *n; };
static inline void htonlsab(void *h, void *n, u16 len) { ASSERT(h != n); memcpy(n, h, len); };
static inline void ntohlsab(void *n, void *h, u16 len) { ASSERT(n != h); memcpy(h, n, len); };
static inline void htonlsab1(void *h, u16 len) { };
static inline void ntohlsab1(void *n, u16 len) { };
static inline void lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n) { *n = *h; };
static inline void lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h) { *h = *n; };
static inline void lsa_hton_body(void *h, void *n, u16 len) { ASSERT(h != n); memcpy(n, h, len); };
static inline void lsa_ntoh_body(void *n, void *h, u16 len) { ASSERT(n != h); memcpy(h, n, len); };
static inline void lsa_hton_body1(void *h, u16 len) { };
static inline void lsa_ntoh_body1(void *n, u16 len) { };
#else
void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
void htonlsab(void *h, void *n, u16 len);
void ntohlsab(void *n, void *h, u16 len);
static inline void htonlsab1(void *h, u16 len) { htonlsab(h, h, len); };
static inline void ntohlsab1(void *n, u16 len) { ntohlsab(n, n, len); };
void lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
void lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
void lsa_hton_body(void *h, void *n, u16 len);
void lsa_ntoh_body(void *n, void *h, u16 len);
static inline void lsa_hton_body1(void *h, u16 len) { lsa_hton_body(h, h, len); };
static inline void lsa_ntoh_body1(void *n, u16 len) { lsa_ntoh_body(n, n, len); };
#endif
struct ospf_lsa_rt_walk {
@ -34,6 +34,11 @@ struct ospf_lsa_rt_walk {
u32 id, data, lif, nif;
};
static inline u32 lsa_get_type(struct proto_ospf *po, u32 type_raw)
{ return ospf_is_v2(po) ? (type_raw & LSA_T_V2_MASK) : type_raw; }
int lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa);
void lsa_xxxxtype(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain);
void lsasum_calculate(struct ospf_lsa_header *header, void *body);
u16 lsasum_check(struct ospf_lsa_header *h, void *body);
#define CMP_NEWER 1
@ -45,7 +50,7 @@ int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric);
void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
int lsa_validate(struct ospf_lsa_header *lsa, void *body);
int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body);
struct top_hash_entry * lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body);
void ospf_age(struct proto_ospf *po);
void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);

View File

@ -19,7 +19,7 @@ struct ospf_lsreq_packet
};
*/
static void
static inline void
ospf_lsreq_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
struct ospf_lsreq_header **body, unsigned *count)
{
@ -71,9 +71,10 @@ ospf_lsreq_send(struct ospf_neighbor *n)
{
en = (struct top_hash_entry *) sn;
DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
i, en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
i, en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
lsrs[i].type = htonl(en->lsa.type);
u32 rtype = lsa_get_type(po, en->lsa.type_raw);
lsrs[i].type = htonl(rtype);
lsrs[i].rt = htonl(en->lsa.rt);
lsrs[i].id = htonl(en->lsa.id);
@ -97,7 +98,9 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct proto_ospf *po = ifa->oa->po;
struct ospf_lsreq_header *lsrs;
unsigned i, lsr_count;
list uplist;
struct ospf_lsreq_item *lsr_head, *lsr;
struct ospf_lsreq_item **lsr_pos = &lsr_head;
slab *upslab;
@ -111,35 +114,39 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
init_list(&uplist);
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
for (i = 0; i < lsr_count; i++)
{
u32 hid = ntohl(lsrs[i].id);
u32 hrt = ntohl(lsrs[i].rt);
u32 htype = ntohl(lsrs[i].type);
u32 dom = ospf_lsa_domain(htype, ifa);
// XXXX check
DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", htype, hid, hrt);
u32 id, rt, type, dom;
if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
id = ntohl(lsrs[i].id);
rt = ntohl(lsrs[i].rt);
lsa_xxxxtype(ntohl(lsrs[i].type), ifa, &type, &dom);
DBG("Processing requested LSA: Type: %04x, Id: %R, Rt: %R\n", type, id, rt);
if (ospf_hash_find(po->gr, dom, id, rt, type) == NULL)
{
log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
n->ip, htype, hid, hrt);
n->ip, type, id, rt);
ospf_neigh_sm(n, INM_BADLSREQ);
rfree(upslab);
return;
}
struct l_lsr_head *llsh = sl_alloc(upslab);
llsh->lsh.id = hid;
llsh->lsh.rt = hrt;
llsh->lsh.type = htype;
add_tail(&uplist, NODE llsh);
}
lsr = sl_alloc(upslab);
lsr->domain = dom;
lsr->type = type;
lsr->id = id;
lsr->rt = rt;
ospf_lsupd_send_list(n, &uplist);
*lsr_pos = lsr;
lsr_pos = &(lsr->next);
}
*lsr_pos = NULL;
ospf_lsupd_send_list(n, lsr_head);
rfree(upslab);
}

View File

@ -9,21 +9,29 @@
#include "ospf.h"
/*
struct ospf_lsupd_packet
{
struct ospf_packet ospf_packet;
u32 lsano; /* Number of LSA's */
struct ospf_packet hdr;
// union ospf_auth auth;
u32 lsa_count;
void lsas[];
};
*/
/* Beware of unaligned access */
void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n)
{
struct ospf_lsa_header lsa;
ntohlsah(lsa_n, &lsa);
u32 lsa_type;
lsa_ntoh_hdr(lsa_n, &lsa);
lsa_type = lsa_get_type(po, lsa.type_raw);
log(L_TRACE "%s: LSA Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
po->proto.name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
po->proto.name, lsa_type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
}
void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
@ -33,22 +41,38 @@ void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
log(L_TRACE "%s: router %R", p->name, ntohl(pkt->routerid));
}
static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt)
static inline unsigned
ospf_lsupd_hdrlen(struct proto_ospf *po)
{
return ospf_pkt_hdrlen(po) + 4; /* + u32 lsa count field */
}
static inline u32 *
ospf_lsupd_lsa_count(struct ospf_packet *pkt, unsigned hdrlen)
{ return ((void *) pkt) + hdrlen - 4; }
static inline void
ospf_lsupd_body(struct proto_ospf *po, struct ospf_packet *pkt,
unsigned *offset, unsigned *bound, unsigned *lsa_count)
{
unsigned hlen = ospf_lsupd_hdrlen(po);
*offset = hlen;
*bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
*lsa_count = ntohl(*ospf_lsupd_lsa_count(pkt, hlen));
}
static void ospf_lsupd_dump(struct proto_ospf *po, struct ospf_packet *pkt)
{
struct proto *p = &po->proto;
struct ospf_packet *op = &pkt->ospf_packet;
ASSERT(op->type == LSUPD_P);
ospf_dump_common(po, op);
ASSERT(pkt->type == LSUPD_P);
ospf_dump_common(po, pkt);
/* We know that ntohs(op->length) >= sizeof(struct ospf_lsa_header) */
u8 *pbuf= (u8 *) pkt;
unsigned int offset = sizeof(struct ospf_lsupd_packet);
unsigned int bound = ntohs(op->length) - sizeof(struct ospf_lsa_header);
unsigned int i, j, lsalen;
/* We know that ntohs(pkt->length) >= sizeof(struct ospf_lsa_header) */
unsigned offset, bound, i, lsa_count, lsalen;
ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
j = ntohl(pkt->lsano);
for (i = 0; i < j; i++)
for (i = 0; i < lsa_count; i++)
{
if (offset > bound)
{
@ -56,8 +80,8 @@ static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt
return;
}
struct ospf_lsa_header *lsa = (void *) (pbuf + offset);
ospf_dump_lsahdr(p, lsa);
struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
ospf_dump_lsahdr(po, lsa);
lsalen = ntohs(lsa->length);
offset += lsalen;
@ -70,77 +94,6 @@ static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt
}
#ifdef OSPFv2
int
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
{
if (lsa->type == LSA_T_EXT)
{
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (!oa_is_ext(ifa->oa))
return 0;
return 1;
}
else
return ifa->oa->areaid == domain;
}
#else /* OSPFv3 */
static int
unknown_lsa_type(struct ospf_lsa_header *lsa)
{
switch (lsa->type)
{
case LSA_T_RT:
case LSA_T_NET:
case LSA_T_SUM_NET:
case LSA_T_SUM_RT:
case LSA_T_EXT:
case LSA_T_NSSA:
case LSA_T_LINK:
case LSA_T_PREFIX:
return 0;
default:
return 1;
}
}
int
ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
{
u32 scope = LSA_SCOPE(lsa);
/* 4.5.2 (Case 2) */
if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
scope = LSA_SCOPE_LINK;
switch (scope)
{
case LSA_SCOPE_LINK:
return ifa->iface->index == domain;
case LSA_SCOPE_AREA:
return ifa->oa->areaid == domain;
case LSA_SCOPE_AS:
if (ifa->type == OSPF_IT_VLINK)
return 0;
if (!oa_is_ext(ifa->oa))
return 0;
return 1;
default:
log(L_ERR "LSA with invalid scope");
return 0;
}
}
#endif
/**
* ospf_lsupd_flood - send received or generated lsa to the neighbors
* @po: OSPF protocol
@ -271,17 +224,16 @@ ospf_lsupd_flood(struct proto_ospf *po,
{
u16 len, age;
struct ospf_lsupd_packet *pk;
struct ospf_packet *op;
unsigned hlen;
struct ospf_packet *pkt;
struct ospf_lsa_header *lh;
pk = ospf_tx_buffer(ifa);
op = &pk->ospf_packet;
pkt = ospf_tx_buffer(ifa);
hlen = ospf_lsupd_hdrlen(po);
ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
pk->lsano = htonl(1);
lh = (struct ospf_lsa_header *) (pk + 1);
ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
*ospf_lsupd_lsa_count(pkt, hlen) = htonl(1);
lh = (((void *) pkt) + hlen);
/* Copy LSA into the packet */
if (hn)
@ -293,33 +245,30 @@ ospf_lsupd_flood(struct proto_ospf *po,
u8 *help;
struct top_hash_entry *en;
htonlsah(hh, lh);
lsa_hton_hdr(hh, lh);
help = (u8 *) (lh + 1);
en = ospf_hash_find_header(po->gr, domain, hh);
htonlsab(en->lsa_body, help, hh->length - sizeof(struct ospf_lsa_header));
lsa_hton_body(en->lsa_body, help, hh->length - sizeof(struct ospf_lsa_header));
}
len = sizeof(struct ospf_lsupd_packet) + ntohs(lh->length);
age = ntohs(lh->age);
age += ifa->inftransdelay;
if (age > LSA_MAXAGE)
age = LSA_MAXAGE;
lh->age = htons(age);
op->length = htons(len);
len = hlen + ntohs(lh->length);
pkt->length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet flooded via %s", ifa->iface->name);
OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet flooded via %s", ifa->iface->name);
switch (ifa->type)
{
case OSPF_IT_BCAST:
if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
ospf_send_to_all(ifa);
else if (ifa->cf->real_bcast)
ospf_send_to_bdr(ifa);
else
ospf_send_to(ifa, AllDRouters);
ospf_send_to_des(ifa);
break;
case OSPF_IT_NBMA:
@ -350,99 +299,96 @@ ospf_lsupd_flood(struct proto_ospf *po,
}
void /* I send all I received in LSREQ */
ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr)
{
struct ospf_area *oa = n->ifa->oa;
struct proto_ospf *po = oa->po;
struct l_lsr_head *lsr;
struct top_hash_entry *en;
struct ospf_lsupd_packet *pkt;
u32 len, len2, lsano;
char *buf;
struct ospf_packet *pkt;
unsigned hlen, pos, pos2, maxsize, lsano;
pkt = ospf_tx_buffer(n->ifa);
buf = (void *) pkt;
hlen = ospf_lsupd_hdrlen(po);
maxsize = ospf_pkt_maxsize(n->ifa);
lsr = HEAD(*l);
while(NODE_NEXT(lsr))
while (lsr)
{
/* Prepare the packet */
ospf_pkt_fill_hdr(n->ifa, pkt, LSUPD_P);
len = sizeof(struct ospf_lsupd_packet);
pos = hlen;
lsano = 0;
/* Fill the packet with LSAs */
while(NODE_NEXT(lsr))
while (lsr)
{
u32 domain = ospf_lsa_domain(lsr->lsh.type, n->ifa);
en = ospf_hash_find(oa->po->gr, domain, lsr->lsh.id, lsr->lsh.rt, lsr->lsh.type);
if (en == NULL)
en = ospf_hash_find(oa->po->gr, lsr->domain, lsr->id, lsr->rt, lsr->type);
if (!en)
{
/* Probably flushed LSA, this should not happen */
log(L_WARN "OSPF: LSA disappeared (Type: %04x, Id: %R, Rt: %R)",
lsr->lsh.type, lsr->lsh.id, lsr->lsh.rt);
lsr = NODE_NEXT(lsr);
continue;
lsr->type, lsr->id, lsr->rt);
lsr = lsr->next;
continue;
}
len2 = len + en->lsa.length;
if (len2 > ospf_pkt_maxsize(n->ifa))
pos2 = pos + en->lsa.length;
if (pos2 > maxsize)
{
/* The packet if full, stop adding LSAs and sent it */
if (lsano > 0)
break;
/* LSA is larger than MTU, check buffer size */
if (len2 > ospf_pkt_bufsize(n->ifa))
if (pos2 > ospf_pkt_bufsize(n->ifa))
{
/* Cannot fit in a tx buffer, skip that */
log(L_WARN "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)",
lsr->lsh.type, lsr->lsh.id, lsr->lsh.rt);
lsr = NODE_NEXT(lsr);
lsr->type, lsr->id, lsr->rt);
lsr = lsr->next;
continue;
}
}
/* Copy the LSA to the packet */
htonlsah(&(en->lsa), (struct ospf_lsa_header *) (buf + len));
htonlsab(en->lsa_body, buf + len + sizeof(struct ospf_lsa_header),
en->lsa.length - sizeof(struct ospf_lsa_header));
len = len2;
void *lsabuf = ((void *) pkt) + pos;
lsa_hton_hdr(&(en->lsa), (struct ospf_lsa_header *) lsabuf);
lsa_hton_body(en->lsa_body, lsabuf + sizeof(struct ospf_lsa_header),
en->lsa.length - sizeof(struct ospf_lsa_header));
pos = pos2;
lsano++;
lsr = NODE_NEXT(lsr);
lsr = lsr->next;
}
if (lsano == 0)
break;
/* Send the packet */
pkt->lsano = htonl(lsano);
pkt->ospf_packet.length = htons(len);
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet sent to %I via %s",
pkt->length = htons(pos);
*ospf_lsupd_lsa_count(pkt, hlen) = htonl(lsano);
OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet sent to %I via %s",
n->ip, n->ifa->iface->name);
ospf_send_to(n->ifa, n->ip);
}
}
void
ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
struct ospf_neighbor *ntmp;
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
unsigned int i, max, sendreq = 1;
unsigned sendreq = 1;
unsigned int size = ntohs(ps_i->length);
if (size < (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
unsigned plen = ntohs(pkt->length);
if (plen < (ospf_lsupd_hdrlen(po) + sizeof(struct ospf_lsa_header)))
{
log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, size);
log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen);
return;
}
struct ospf_lsupd_packet *ps = (void *) ps_i;
OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
if (n->state < NEIGHBOR_EXCHANGE)
{
@ -452,30 +398,29 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
unsigned int offset = sizeof(struct ospf_lsupd_packet);
unsigned int bound = size - sizeof(struct ospf_lsa_header);
unsigned offset, bound, i, lsa_count;
ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
max = ntohl(ps->lsano);
for (i = 0; i < max; i++)
for (i = 0; i < lsa_count; i++)
{
struct ospf_lsa_header lsatmp;
struct top_hash_entry *lsadb;
if (offset > bound)
{
log(L_WARN "Received lsupd from %I is too short!", n->ip);
log(L_WARN "OSPF: Received LSUPD from %I is too short", n->ip);
ospf_neigh_sm(n, INM_BADLSREQ);
return;
}
struct ospf_lsa_header *lsa = (void *) (((u8 *) ps) + offset);
struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
unsigned int lsalen = ntohs(lsa->length);
offset += lsalen;
if ((offset > size) || ((lsalen % 4) != 0) ||
if ((offset > plen) || ((lsalen % 4) != 0) ||
(lsalen <= sizeof(struct ospf_lsa_header)))
{
log(L_WARN "Received LSA from %I with bad length", n->ip);
log(L_WARN "OSPF: Received LSA from %I with bad length", n->ip);
ospf_neigh_sm(n, INM_BADLSREQ);
break;
}
@ -484,55 +429,45 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
u16 chsum = lsa->checksum;
if (chsum != lsasum_check(lsa, NULL))
{
log(L_WARN "Received bad lsa checksum from %I: %x %x", n->ip, chsum, lsa->checksum);
log(L_WARN "OSPF: Received LSA from %I with bad checskum: %x %x",
n->ip, chsum, lsa->checksum);
continue;
}
u16 lsa_type = ntohs(lsa->type_raw);
lsa_type = xxxx(lsa_type); // XXXX finish
#ifdef OSPFv2
u32 lsa_type, lsa_domain;
lsa_ntoh_hdr(lsa, &lsatmp);
lsa_xxxxtype(lsatmp.type_raw, ifa, &lsa_type, &lsa_domain);
/* pg 143 (2) */
if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
if (!lsa_type)
{
log(L_WARN "Unknown LSA type from %I", n->ip);
log(L_WARN "OSPF: Received unknown LSA type from %I", n->ip);
continue;
}
/* pg 143 (3) */
if ((lsa_type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received External LSA in stub area from %I", n->ip);
continue;
}
#else /* OSPFv3 */
/* 4.5.1 (2) */
if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
{
log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
log(L_WARN "OSPF: Received LSA with AS scope in stub area from %I", n->ip);
continue;
}
/* 4.5.1 (3) */
if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_RES))
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
{
log(L_WARN "Received LSA with invalid scope from %I", n->ip);
log(L_WARN "OSPF: Received LSA with invalid scope from %I", n->ip);
continue;
}
#endif
ntohlsah(lsa, &lsatmp);
DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
lsa_type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
/* FIXME domain should be link id for unknown LSA types with zero Ubit */
u32 domain = ospf_lsa_domain(lsa_type, ifa);
lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
lsadb = ospf_hash_find(po->gr, lsa_domain, lsatmp.id, lsatmp.rt, lsa_type);
#ifdef LOCAL_DEBUG
if (lsadb)
DBG("I have Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
lsadb->lsa.type, lsadb->lsa.id, lsadb->lsa.rt,
DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
lsadb->lsa_type, lsadb->lsa.id, lsadb->lsa.rt,
lsadb->lsa.sn, lsadb->lsa.age, lsadb->lsa.checksum);
#endif
@ -589,7 +524,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
lsadb->inst_t = now;
lsadb->ini_age = 0;
lsasum_calculate(&lsadb->lsa, lsadb->lsa_body);
ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, domain, 1);
ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, lsa_domain, 1);
}
else
{
@ -600,7 +535,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
lsa->sn = htonl(LSA_MAXSEQNO);
lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
lsatmp.checksum = ntohs(lsa->checksum);
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
ospf_lsupd_flood(po, NULL, lsa, &lsatmp, lsa_domain, 0);
}
continue;
}
@ -622,7 +557,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
{
struct top_hash_entry *en;
if (ntmp->state > NEIGHBOR_EXSTART)
if ((en = ospf_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
if ((en = ospf_hash_find_header(ntmp->lsrth, lsa_domain, &lsadb->lsa)) != NULL)
{
s_rem_node(SNODE en);
ospf_hash_delete(ntmp->lsrth, en);
@ -630,7 +565,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
}
/* pg 144 (5b) */
if (ospf_lsupd_flood(po, n, lsa, &lsatmp, domain, 1) == 0)
if (ospf_lsupd_flood(po, n, lsa, &lsatmp, lsa_domain, 1) == 0)
{
DBG("Wasn't flooded back\n"); /* ps 144(5e), pg 153 */
if (ifa->state == OSPF_IS_BACKUP)
@ -652,26 +587,24 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
/* pg 144 (5d) */
void *body = mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
ntohlsab(lsa + 1, body, lsatmp.length - sizeof(struct ospf_lsa_header));
lsa_ntoh_body(lsa + 1, body, lsatmp.length - sizeof(struct ospf_lsa_header));
/* We will do validation check after flooding and
acknowledging given LSA to minimize problems
when communicating with non-validating peer */
if (lsa_validate(&lsatmp, body) == 0)
if (lsa_validate(&lsatmp, lsa_type, ospf_is_v2(po), body) == 0)
{
log(L_WARN "Received invalid LSA from %I", n->ip);
mb_free(body);
continue;
}
lsadb = lsa_install_new(po, &lsatmp, domain, body);
lsadb = lsa_install_new(po, &lsatmp, lsa_domain, body);
DBG("New LSA installed in DB\n");
#ifdef OSPFv3
/* Events 6,7 from RFC5340 4.4.3. */
if ((lsa_type == LSA_T_LINK) && (ifa->state == OSPF_IS_DR))
schedule_net_lsa(ifa);
#endif
continue;
}
@ -710,16 +643,13 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
continue;
}
{
list l;
struct l_lsr_head ll;
init_list(&l);
ll.lsh.id = lsadb->lsa.id;
ll.lsh.rt = lsadb->lsa.rt;
ll.lsh.type = lsadb->lsa.type;
add_tail(&l, NODE & ll);
ospf_lsupd_send_list(n, &l);
}
struct ospf_lsreq_item lsr = {
.domain = lsadb->domain,
.type = lsadb->lsa_type,
.id = lsadb->lsa.id,
.rt = lsadb->lsa.rt
};
ospf_lsupd_send_list(n, &lsr);
}
/* Send direct LSAs */

View File

@ -12,7 +12,7 @@
void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n);
void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt);
void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
void ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr);
void ospf_lsupd_receive(struct ospf_packet *ps_i,
struct ospf_iface *ifa, struct ospf_neighbor *n);
int ospf_lsupd_flood(struct proto_ospf *po,

View File

@ -26,8 +26,8 @@ const char *ospf_inm[] =
};
static void neigh_chstate(struct ospf_neighbor *n, u8 state);
static struct ospf_neighbor *electbdr(list nl);
static struct ospf_neighbor *electdr(list nl);
static struct ospf_neighbor *electbdr(struct proto_ospf *, list nl);
static struct ospf_neighbor *electdr(struct proto_ospf *, list nl);
static void neighbor_timer_hook(timer * timer);
static void rxmt_timer_hook(timer * timer);
static void ackd_timer_hook(timer * t);
@ -37,11 +37,9 @@ init_lists(struct ospf_neighbor *n)
{
s_init_list(&(n->lsrql));
n->lsrqh = ospf_top_new(n->pool);
s_init(&(n->lsrqi), &(n->lsrql));
s_init_list(&(n->lsrtl));
n->lsrth = ospf_top_new(n->pool);
s_init(&(n->lsrti), &(n->lsrtl));
}
/* Resets LSA request and retransmit lists.
@ -163,8 +161,11 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
}
}
static inline u32 neigh_get_id(struct proto_ospf *po, struct ospf_neighbor *n)
{ return ospf_is_v2(po) ? ipa_to_u32(n->ip) : n->rid; }
static struct ospf_neighbor *
electbdr(list nl)
electbdr(struct proto_ospf *po, list nl)
{
struct ospf_neighbor *neigh, *n1, *n2;
u32 nid;
@ -173,11 +174,7 @@ electbdr(list nl)
n2 = NULL;
WALK_LIST(neigh, nl) /* First try those decl. themselves */
{
#ifdef OSPFv2
nid = ipa_to_u32(neigh->ip);
#else /* OSPFv3 */
nid = neigh->rid;
#endif
nid = neigh_get_id(po, neigh);
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
if (neigh->priority > 0) /* Eligible */
@ -222,7 +219,7 @@ electbdr(list nl)
}
static struct ospf_neighbor *
electdr(list nl)
electdr(struct proto_ospf *po, list nl)
{
struct ospf_neighbor *neigh, *n;
u32 nid;
@ -230,11 +227,7 @@ electdr(list nl)
n = NULL;
WALK_LIST(neigh, nl) /* And now DR */
{
#ifdef OSPFv2
nid = ipa_to_u32(neigh->ip);
#else /* OSPFv3 */
nid = neigh->rid;
#endif
nid = neigh_get_id(po, neigh);
if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
if (neigh->priority > 0) /* Eligible */
@ -449,19 +442,14 @@ bdr_election(struct ospf_iface *ifa)
me.priority = ifa->priority;
me.ip = ifa->addr->ip;
#ifdef OSPFv2
me.dr = ipa_to_u32(ifa->drip);
me.bdr = ipa_to_u32(ifa->bdrip);
#else /* OSPFv3 */
me.dr = ifa->drid;
me.bdr = ifa->bdrid;
me.dr = ospf_is_v2(po) ? ipa_to_u32(ifa->drip) : ifa->drid;
me.bdr = ospf_is_v2(po) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
me.iface_id = ifa->iface->index;
#endif
add_tail(&ifa->neigh_list, NODE & me);
nbdr = electbdr(ifa->neigh_list);
ndr = electdr(ifa->neigh_list);
nbdr = electbdr(po, ifa->neigh_list);
ndr = electdr(po, ifa->neigh_list);
if (ndr == NULL)
ndr = nbdr;
@ -472,16 +460,11 @@ bdr_election(struct ospf_iface *ifa)
|| ((ifa->bdrid == myid) && (nbdr != &me))
|| ((ifa->bdrid != myid) && (nbdr == &me)))
{
#ifdef OSPFv2
me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
#else /* OSPFv3 */
me.dr = ndr ? ndr->rid : 0;
me.bdr = nbdr ? nbdr->rid : 0;
#endif
me.dr = ndr ? neigh_get_id(po, ndr) : 0;
me.bdr = nbdr ? neigh_get_id(po, nbdr) : 0;
nbdr = electbdr(ifa->neigh_list);
ndr = electdr(ifa->neigh_list);
nbdr = electbdr(po, ifa->neigh_list);
ndr = electdr(po, ifa->neigh_list);
if (ndr == NULL)
ndr = nbdr;
@ -492,13 +475,11 @@ bdr_election(struct ospf_iface *ifa)
ifa->drid = ndr ? ndr->rid : 0;
ifa->drip = ndr ? ndr->ip : IPA_NONE;
ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
ifa->bdrid = nbdr ? nbdr->rid : 0;
ifa->bdrip = nbdr ? nbdr->ip : IPA_NONE;
#ifdef OSPFv3
ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
#endif
DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
@ -640,26 +621,28 @@ rxmt_timer_hook(timer * timer)
{
if (!EMPTY_SLIST(n->lsrtl)) /* FULL */
{
list uplist;
slab *upslab;
struct l_lsr_head *llsh;
struct ospf_lsreq_item *lsr_head, *lsr;
struct ospf_lsreq_item **lsr_pos = &lsr_head;
init_list(&uplist);
upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
slab *upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
WALK_SLIST(en, n->lsrtl)
{
if ((SNODE en)->next == (SNODE en))
bug("RTList is cycled");
llsh = sl_alloc(upslab);
llsh->lsh.id = en->lsa.id;
llsh->lsh.rt = en->lsa.rt;
llsh->lsh.type = en->lsa.type;
DBG("Working on ID: %R, RT: %R, Type: %u\n",
en->lsa.id, en->lsa.rt, en->lsa.type);
add_tail(&uplist, NODE llsh);
lsr = sl_alloc(upslab);
lsr->domain = en->domain;
lsr->type = en->lsa_type;
lsr->id = en->lsa.id;
lsr->rt = en->lsa.rt;
*lsr_pos = lsr;
lsr_pos = &(lsr->next);
}
ospf_lsupd_send_list(n, &uplist);
*lsr_pos = NULL;
ospf_lsupd_send_list(n, lsr_head);
rfree(upslab);
}
}

View File

@ -164,11 +164,7 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
if (oa->areaid == 0)
po->backbone = oa;
#ifdef OSPFv2
oa->options = ac->type;
#else /* OSPFv3 */
oa->options = OPT_R | ac->type | OPT_V6;
#endif
oa->options = ospf_is_v2(po) ? ac->type : (OPT_R | ac->type | OPT_V6);
/*
* Set E-bit for NSSA ABR routers. No need to explicitly call
@ -383,7 +379,6 @@ schedule_net_lsa(struct ospf_iface *ifa)
ifa->orignet = 1;
}
#ifdef OSPFv3
void
schedule_link_lsa(struct ospf_iface *ifa)
{
@ -392,7 +387,6 @@ schedule_link_lsa(struct ospf_iface *ifa)
OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
ifa->origlink = 1;
}
#endif
void
schedule_rt_lsa(struct ospf_area *oa)
@ -589,7 +583,7 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
// FIXME check for gw should be per ifa, not per iface
if ((new->attrs->dest == RTD_ROUTER) &&
ipa_nonzero(new->attrs->gw) &&
!ipa_has_link_scope(new->attrs->gw) &&
!ipa_is_link_local(new->attrs->gw) &&
(ospf_iface_find((struct proto_ospf *) p, new->attrs->iface) != NULL))
gw = new->attrs->gw;
@ -682,11 +676,8 @@ ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
oa->ac = nac;
// FIXME better area type reconfiguration
#ifdef OSPFv2
oa->options = nac->type;
#else /* OSPFv3 */
oa->options = OPT_R | nac->type | OPT_V6;
#endif
oa->options = ospf_is_v2(oa->po) ? nac->type : (OPT_R | nac->type | OPT_V6);
if (oa_is_nssa(oa) && (oa->po->areano > 1))
oa->po->ebit = 1;
@ -986,7 +977,7 @@ lsa_compare_for_state(const void *p1, const void *p2)
if (nt1)
{
#ifdef OSPFv3
/* In OSPFv3, neworks are named base on ID of DR */
/* In OSPFv3, networks are named based on ID of DR */
if (lsa1->rt != lsa2->rt)
return lsa1->rt - lsa2->rt;
#endif
@ -1488,17 +1479,17 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
case LSA_SCOPE_AS:
cli_msg(-1017, "Global");
break;
case LSA_SCOPE_AREA:
cli_msg(-1017, "Area %R", hea[i]->domain);
break;
#ifdef OSPFv3
case LSA_SCOPE_LINK:
{
struct iface *ifa = if_find_by_index(hea[i]->domain);
cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
}
break;
#endif
}
cli_msg(-1017, "");
cli_msg(-1017," Type LS ID Router Age Sequence Checksum");
@ -1507,7 +1498,6 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
last_domain = hea[i]->domain;
}
cli_msg(-1017," %04x %-15R %-15R %5u %08x %04x",
lsa->type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
}

View File

@ -65,11 +65,10 @@ do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
#define MINLSARRIVAL 1
#define LSINFINITY 0xffffff
#define DEFAULT_OSPFTICK 1
#define DEFAULT_RFC1583 0 /* compatibility with rfc1583 */
#define DEFAULT_STUB_COST 1000
#define DEFAULT_ECMP_LIMIT 16
#define DEFAULT_TRANSINT 40
#define OSPF_DEFAULT_TICK 1
#define OSPF_DEFAULT_STUB_COST 1000
#define OSPF_DEFAULT_ECMP_LIMIT 16
#define OSPF_DEFAULT_TRANSINT 40
struct ospf_config
@ -202,11 +201,12 @@ struct ospf_iface
u16 autype;
u32 csn; /* Last used crypt seq number */
bird_clock_t csn_use; /* Last time when packet with that CSN was sent */
ip_addr all_routers; /* */
ip_addr drip; /* Designated router */
ip_addr bdrip; /* Backup DR */
u32 drid;
u32 bdrid;
ip_addr all_routers; /* XXXX */
ip_addr des_routers; /* XXXX */
ip_addr drip; /* Designated router IP */
ip_addr bdrip; /* Backup DR IP */
u32 drid; /* DR Router ID */
u32 bdrid; /* BDR Router ID */
s16 rt_pos_beg; /* Position of iface in Router-LSA, begin, inclusive */
s16 rt_pos_end; /* Position of iface in Router-LSA, end, exclusive */
s16 px_pos_beg; /* Position of iface in Rt Prefix-LSA, begin, inclusive */
@ -244,7 +244,7 @@ struct ospf_iface
#define OSPF_I_OK 0 /* Everything OK */
#define OSPF_I_SK 1 /* Socket open failed */
#define OSPF_I_LL 2 /* Missing link-local address (OSPFv3) */
u8 sk_dr; /* Socket is a member of DRouters group */
u8 sk_dr; /* Socket is a member of designated routers group */
u8 marked; /* Used in OSPF reconfigure */
u16 rxbuf; /* Buffer size */
u8 check_link; /* Whether iface link change is used */
@ -276,7 +276,6 @@ union ospf_auth
/* Area IDs */
#define BACKBONE 0
#define DBDES_I 4 /* Init bit */
#define DBDES_M 2 /* More bit */
#define DBDES_MS 1 /* Master/Slave bit */
@ -284,7 +283,6 @@ union ospf_auth
/*
* There is slight difference in OSPF packet header between v2 and v3
* in vdep field. For OSPFv2, vdep is u16 authentication type and
@ -303,6 +301,18 @@ struct ospf_packet
u16 vdep;
};
static inline u16 ospf_pkt_get_autype(struct ospf_packet *pkt)
{ return ntohs(pkt->vdep); }
static inline void ospf_pkt_set_autype(struct ospf_packet *pkt, u16 val)
{ pkt->vdep = htons(val); }
static inline u8 ospf_pkt_get_instance_id(struct ospf_packet *pkt)
{ return ntohs(pkt->vdep) >> 8; }
static inline void ospf_pkt_set_instance_id(struct ospf_packet *pkt, u16 val)
{ pkt->vdep = htons(val << 8); }
// XXXX
/*
@ -323,6 +333,8 @@ struct ospf_packet
#define LSA_T_LINK 0x0008
#define LSA_T_PREFIX 0x2009
#define LSA_T_V2_MASK 0x00ff
#define LSA_UBIT 0x8000
#define LSA_SCOPE_LINK 0x0000
@ -330,7 +342,7 @@ struct ospf_packet
#define LSA_SCOPE_AS 0x4000
#define LSA_SCOPE_RES 0x6000
#define LSA_SCOPE_MASK 0x6000
#define LSA_SCOPE(lsa) ((lsa) & LSA_SCOPE_MASK)
#define LSA_SCOPE(type) ((type) & LSA_SCOPE_MASK)
#define LSA_MAXAGE 3600 /* 1 hour */
@ -346,6 +358,8 @@ struct ospf_packet
#define LSART_STUB 3
#define LSART_VLNK 4
#define LSA_RT2_LINKS 0x0000FFFF
#define LSA_SUM2_TOS 0xFF000000
#define LSA_EXT2_TOS 0x7F000000
@ -399,6 +413,19 @@ struct ospf_lsa_rt2_link
#endif
};
struct ospf_lsa_rt2_tos
{
#ifdef CPU_BIG_ENDIAN
u8 tos;
u8 padding;
u16 metric;
#else
u16 metric;
u8 padding;
u8 tos;
#endif
};
struct ospf_lsa_rt3_link
{
#ifdef CPU_BIG_ENDIAN
@ -486,27 +513,6 @@ struct ospf_lsa_prefix
};
#ifdef OSPFv2
/* Endianity swap for lsa->type */
#define ntoht(x) x
#define htont(x) x
#else /* OSPFv3 */
/* Endianity swap for lsa->type */
#define ntoht(x) ntohs(x)
#define htont(x) htons(x)
#endif
#define METRIC_MASK 0x00FFFFFF
#define OPTIONS_MASK 0x00FFFFFF
@ -519,8 +525,6 @@ lsa_net_count(struct ospf_lsa_header *lsa)
}
#ifdef OSPFv3
#define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
#define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
@ -581,21 +585,21 @@ put_ipv6_addr(u32 *buf, ip_addr addr)
return buf + 4;
}
#endif
struct ospf_lsreq_header
{
u32 type;
u32 id;
u32 rt; /* Advertising router */
u32 rt;
};
struct l_lsr_head
struct ospf_lsreq_item
{
node n;
struct ospf_lsreq_header lsh;
struct ospf_lsreq_item *next;
u32 domain;
u32 type;
u32 id;
u32 rt;
};
@ -625,19 +629,30 @@ struct ospf_neighbor
u8 adj; /* built adjacency? */
u32 options; /* Options received */
/* dr and bdr store IP address in OSPFv2 and router ID in OSPFv3,
we use the same type to simplify handling */
/* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in
* OSPFv3, we use the same type to simplify handling
*/
u32 dr; /* Neigbour's idea of DR */
u32 bdr; /* Neigbour's idea of BDR */
u32 iface_id; /* ID of Neighbour's iface connected to common network */
siterator dbsi; /* Database summary list iterator */
slist lsrql; /* Link state request */
struct top_graph *lsrqh; /* LSA graph */
siterator lsrqi;
slist lsrtl; /* Link state retransmission list */
siterator lsrti;
/* Database summary list iterator, controls initial dbdes exchange.
* Advances in the LSA list as dbdes packets are sent.
*/
siterator dbsi; /* iterator of po->lsal */
/* Link state request list, controls initial LSA exchange.
* Entries added when received in dbdes packets, removed as sent in lsreq packets.
*/
slist lsrql; /* slist of struct top_hash_entry from n->lsrqh */
struct top_graph *lsrqh;
/* Link state retransmission list, controls LSA retransmission during flood.
* Entries added as sent in lsupd packets, removed when received in lsack packets.
*/
slist lsrtl; /* slist of struct top_hash_entry from n->lsrth */
struct top_graph *lsrth;
void *ldbdes; /* Last database description packet */
timer *rxmt_timer; /* RXMT timer */
list ackl[2];

View File

@ -24,16 +24,12 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
pkt->routerid = htonl(po->router_id);
pkt->areaid = htonl(ifa->oa->areaid);
#ifdef OSPFv3
pkt->instance_id = ifa->instance_id;
#endif
#ifdef OSPFv2
pkt->autype = htons(ifa->autype);
#endif
pkt->checksum = 0;
if (ospf_is_v2(po))
ospf_pkt_set_autype(pkt, ifa->autype);
else
ospf_pkt_set_instance_id(pkt, ifa->instance_id);
}
unsigned
@ -42,47 +38,48 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)
unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
unsigned headers = SIZE_OF_IP_HEADER;
#ifdef OSPFv2
/* For OSPFv2 */
if (ifa->autype == OSPF_AUTH_CRYPT)
headers += OSPF_AUTH_CRYPT_SIZE;
#endif
return mtu - headers;
}
#ifdef OSPFv2
/* We assume OSPFv2 in ospf_pkt_finalize() */
static void
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
{
struct password_item *passwd = NULL;
void *tail;
struct MD5Context ctxt;
char password[OSPF_AUTH_CRYPT_SIZE];
union ospf_auth *auth = (void *) (pkt + 1);
unsigned plen = ntohs(pkt->length);
pkt->checksum = 0;
pkt->autype = htons(ifa->autype);
bzero(&pkt->u, sizeof(union ospf_auth));
ospf_pkt_set_autype(pkt, ifa->autype);
bzero(auth, sizeof(union ospf_auth));
/* Compatibility note: pkt->u may contain anything if autype is
/* Compatibility note: auth may contain anything if autype is
none, but nonzero values do not work with Mikrotik OSPF */
switch(ifa->autype)
switch (ifa->autype)
{
case OSPF_AUTH_SIMPLE:
passwd = password_find(ifa->passwords, 1);
if (!passwd)
{
log( L_ERR "No suitable password found for authentication" );
log(L_ERR "No suitable password found for authentication");
return;
}
password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth));
password_cpy(auth->password, passwd->password, sizeof(union ospf_auth));
case OSPF_AUTH_NONE:
pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) -
sizeof(union ospf_auth), (pkt + 1),
ntohs(pkt->length) -
sizeof(struct ospf_packet), NULL);
{
void *body = (void *) (auth + 1);
unsigned blen = plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
}
break;
case OSPF_AUTH_CRYPT:
passwd = password_find(ifa->passwords, 0);
if (!passwd)
@ -106,45 +103,53 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
ifa->csn_use = now;
pkt->u.md5.keyid = passwd->id;
pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE;
pkt->u.md5.zero = 0;
pkt->u.md5.csn = htonl(ifa->csn);
tail = ((void *)pkt) + ntohs(pkt->length);
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
MD5Final(tail, &ctxt);
auth->md5.zero = 0;
auth->md5.keyid = passwd->id;
auth->md5.len = OSPF_AUTH_CRYPT_SIZE;
auth->md5.csn = htonl(ifa->csn);
{
void *tail = ((void *) pkt) + plen;
char password[OSPF_AUTH_CRYPT_SIZE];
password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
struct MD5Context ctxt;
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, plen);
MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
MD5Final(tail, &ctxt);
}
break;
default:
bug("Unknown authentication type");
}
}
/* We assume OSPFv2 in ospf_pkt_checkauth() */
static int
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
{
struct proto_ospf *po = ifa->oa->po;
struct proto *p = &po->proto;
union ospf_auth *auth = (void *) (pkt + 1);
struct password_item *pass = NULL, *ptmp;
void *tail;
char md5sum[OSPF_AUTH_CRYPT_SIZE];
char password[OSPF_AUTH_CRYPT_SIZE];
struct MD5Context ctxt;
unsigned plen = ntohs(pkt->length);
u16 autype = ospf_pkt_get_autype(pkt);
if (pkt->autype != htons(ifa->autype))
if (autype != ifa->autype)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype));
OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype);
return 0;
}
switch(ifa->autype)
switch (autype)
{
case OSPF_AUTH_NONE:
return 1;
break;
case OSPF_AUTH_SIMPLE:
pass = password_find(ifa->passwords, 1);
if (!pass)
@ -154,37 +159,48 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
}
password_cpy(password, pass->password, sizeof(union ospf_auth));
if (memcmp(pkt->u.password, password, sizeof(union ospf_auth)))
if (memcmp(auth->password, password, sizeof(union ospf_auth)))
{
char ppass[sizeof(union ospf_auth) + 1];
bzero(ppass, (sizeof(union ospf_auth) + 1));
memcpy(ppass, pkt->u.password, sizeof(union ospf_auth));
memcpy(ppass, auth->password, sizeof(union ospf_auth));
OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords (%s)", ppass);
return 0;
}
return 1;
break;
case OSPF_AUTH_CRYPT:
if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE)
if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
return 0;
}
if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size)
if (plen + OSPF_AUTH_CRYPT_SIZE > size)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
plen + OSPF_AUTH_CRYPT_SIZE, size);
return 0;
}
tail = ((void *)pkt) + ntohs(pkt->length);
if (n)
{
u32 rcv_csn = ntohl(auth->md5.csn);
if(rcv_csn < n->csn)
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
return 0;
}
n->csn = rcv_csn;
}
if (ifa->passwords)
{
WALK_LIST(ptmp, *(ifa->passwords))
{
if (pkt->u.md5.keyid != ptmp->id) continue;
if (auth->md5.keyid != ptmp->id) continue;
if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
pass = ptmp;
break;
@ -197,50 +213,32 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
return 0;
}
if (n)
password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
{
u32 rcv_csn = ntohl(pkt->u.md5.csn);
if(rcv_csn < n->csn)
void *tail = ((void *) pkt) + plen;
char md5sum[OSPF_AUTH_CRYPT_SIZE];
struct MD5Context ctxt;
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, plen);
MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
MD5Final(md5sum, &ctxt);
if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
return 0;
}
n->csn = rcv_csn;
}
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
MD5Final(md5sum, &ctxt);
if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
{
OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
return 0;
}
return 1;
break;
default:
OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
return 0;
}
}
#else
/* OSPFv3 authentication not yet supported */
static inline void
ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
{ }
static int
ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
{ return 1; }
#endif
/**
* ospf_rx_hook
@ -273,37 +271,39 @@ ospf_rx_hook(sock *sk, int size)
int src_local, dst_local UNUSED, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
#ifdef OSPFv2
/* First, we eliminate packets with strange address combinations.
* In OSPFv2, they might be for other ospf_ifaces (with different IP
* prefix) on the same real iface, so we don't log it. We enforce
* that (src_local || dst_local), therefore we are eliminating all
* such cases.
*/
if (dst_mcast && !src_local)
return 1;
if (!dst_mcast && !dst_local)
return 1;
if (ospf_is_v2(po))
{
/* First, we eliminate packets with strange address combinations.
* In OSPFv2, they might be for other ospf_ifaces (with different IP
* prefix) on the same real iface, so we don't log it. We enforce
* that (src_local || dst_local), therefore we are eliminating all
* such cases.
*/
if (dst_mcast && !src_local)
return 1;
if (!dst_mcast && !dst_local)
return 1;
/* Ignore my own broadcast packets */
if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
return 1;
#else /* OSPFv3 */
/* In OSPFv3, src_local and dst_local mean link-local.
* RFC 5340 says that local (non-vlink) packets use
* link-local src address, but does not enforce it. Strange.
*/
if (dst_mcast && !src_local)
log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr);
#endif
/* Ignore my own broadcast packets */
if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
return 1;
}
else
{
/* In OSPFv3, src_local and dst_local mean link-local.
* RFC 5340 says that local (non-vlink) packets use
* link-local src address, but does not enforce it. Strange.
*/
if (dst_mcast && !src_local)
log(L_WARN "OSPF: Received multicast packet from %I (not link-local)", sk->faddr);
}
/* Second, we check packet size, checksum, and the protocol version */
struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
if (ps == NULL)
if (pkt == NULL)
{
log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
return 1;
@ -315,16 +315,16 @@ ospf_rx_hook(sock *sk, int size)
return 1;
}
int osize = ntohs(ps->length);
if ((unsigned) osize < sizeof(struct ospf_packet))
unsigned plen = ntohs(pkt->length);
if (plen < sizeof(struct ospf_packet))
{
log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, osize);
log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, plen);
return 1;
}
if ((osize > size) || ((osize % 4) != 0))
if ((plen > size) || ((plen % 4) != 0))
{
log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size);
log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
return 1;
}
@ -334,50 +334,47 @@ ospf_rx_hook(sock *sk, int size)
return 1;
}
if (ps->version != OSPF_VERSION)
if (pkt->version != OSPF_VERSION)
{
log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version);
log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
return 1;
}
#ifdef OSPFv2
if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
(!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
osize - sizeof(struct ospf_packet), NULL)))
if (ospf_is_v2(po) && ospf_pkt_get_autype(pkt) != OSPF_AUTH_CRYPT)
{
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
return 1;
}
#endif
unsigned hlen = sizeof(struct ospf_packet) - sizeof(union ospf_auth);
unsigned blen = plen - hlen;
void *body = ((void *) pkt) + hlen;
if (! ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
{
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
return 1;
}
}
/* Third, we resolve associated iface and handle vlinks. */
u32 areaid = ntohl(ps->areaid);
u32 rid = ntohl(ps->routerid);
u32 areaid = ntohl(pkt->areaid);
u32 rid = ntohl(pkt->routerid);
u8 instance_id = ospf_is_v2(po) ? 0 : ospf_pkt_get_instance_id(pkt);
if ((areaid == ifa->oa->areaid)
#ifdef OSPFv3
&& (ps->instance_id == ifa->instance_id)
#endif
)
if ((areaid == ifa->oa->areaid) &&
(instance_id == ifa->instance_id))
{
/* It is real iface, source should be local (in OSPFv2) */
#ifdef OSPFv2
if (!src_local)
if (ospf_is_v2(po) && !src_local)
return 1;
#endif
}
else if (dst_mcast || (areaid != 0))
{
/* Obvious mismatch */
#ifdef OSPFv2
/* We ignore mismatch in OSPFv3, because there might be
other instance with different instance ID */
log(L_ERR "%s%I - area does not match (%R vs %R)",
mesg, sk->faddr, areaid, ifa->oa->areaid);
#endif
/* We ignore mismatch in OSPFv3 when there might be
another instance with a different instance ID */
if (instance_id == ifa->instance_id)
log(L_ERR "%s%I - area does not match (%R vs %R)",
mesg, sk->faddr, areaid, ifa->oa->areaid);
return 1;
}
else
@ -389,9 +386,7 @@ ospf_rx_hook(sock *sk, int size)
{
if ((iff->type == OSPF_IT_VLINK) &&
(iff->voa == ifa->oa) &&
#ifdef OSPFv3
(iff->instance_id == ps->instance_id) &&
#endif
(iff->instance_id == instance_id) &&
(iff->vid == rid))
{
/* Vlink should be UP */
@ -403,9 +398,10 @@ ospf_rx_hook(sock *sk, int size)
}
}
#ifdef OSPFv2
log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
#endif
/* FIXME: this warning is strange - NBMA could trigger it too */
if (ospf_is_v2(po))
log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
return 1;
}
@ -413,7 +409,7 @@ ospf_rx_hook(sock *sk, int size)
if (ifa->stub) /* This shouldn't happen */
return 1;
if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0))
if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
return 1;
if (rid == po->router_id)
@ -428,25 +424,22 @@ ospf_rx_hook(sock *sk, int size)
return 1;
}
#ifdef OSPFv2
/* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
unsigned t = ifa->type;
struct ospf_neighbor *n;
if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
if (ospf_is_v2(po) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
n = find_neigh_by_ip(ifa, sk->faddr);
else
n = find_neigh(ifa, rid);
#else
struct ospf_neighbor *n = find_neigh(ifa, rid);
#endif
if (!n && (ps->type != HELLO_P))
if (!n && (pkt->type != HELLO_P))
{
log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
sk->faddr, ifa->iface->name);
return 1;
}
if (!ospf_pkt_checkauth(n, ifa, ps, size))
if (ospf_is_v2(po) && ! ospf_pkt_checkauth(n, ifa, pkt, size))
{
log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
return 1;
@ -454,36 +447,36 @@ ospf_rx_hook(sock *sk, int size)
/* Dump packet
pu8=(u8 *)(sk->rbuf+5*4);
for(i=0;i<ntohs(ps->length);i+=4)
for(i=0;i<ntohs(pkt->length);i+=4)
DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
pu8[i+3]);
DBG("%s: received size: %u\n",p->name,size);
*/
switch (ps->type)
switch (pkt->type)
{
case HELLO_P:
DBG("%s: Hello received.\n", p->name);
ospf_hello_receive(ps, ifa, n, sk->faddr);
ospf_hello_receive(pkt, ifa, n, sk->faddr);
break;
case DBDES_P:
DBG("%s: Database description received.\n", p->name);
ospf_dbdes_receive(ps, ifa, n);
ospf_dbdes_receive(pkt, ifa, n);
break;
case LSREQ_P:
DBG("%s: Link state request received.\n", p->name);
ospf_lsreq_receive(ps, ifa, n);
ospf_lsreq_receive(pkt, ifa, n);
break;
case LSUPD_P:
DBG("%s: Link state update received.\n", p->name);
ospf_lsupd_receive(ps, ifa, n);
ospf_lsupd_receive(pkt, ifa, n);
break;
case LSACK_P:
DBG("%s: Link state ack received.\n", p->name);
ospf_lsack_receive(ps, ifa, n);
ospf_lsack_receive(pkt, ifa, n);
break;
default:
log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type);
return 1;
};
return 1;
@ -505,6 +498,27 @@ ospf_err_hook(sock * sk, int err)
log(L_ERR "OSPF: Socket error on %s: %M", ifa->iface->name, err);
}
void
ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
{
sock *sk = ifa->sk;
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
int plen = ntohs(pkt->length);
if (sk->tbuf != sk->tpos)
log(L_ERR "Aiee, old packet was overwritten in TX buffer");
if (ospf_is_v2(ifa->oa->po))
{
if (ifa->autype == OSPF_AUTH_CRYPT)
plen += OSPF_AUTH_CRYPT_SIZE;
ospf_pkt_finalize(ifa, pkt);
}
sk_send_to(sk, plen, dst, 0);
}
void
ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
{
@ -518,28 +532,8 @@ ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
void
ospf_send_to_bdr(struct ospf_iface *ifa)
{
if (!ipa_equal(ifa->drip, IPA_NONE))
if (ipa_nonzero(ifa->drip))
ospf_send_to(ifa, ifa->drip);
if (!ipa_equal(ifa->bdrip, IPA_NONE))
if (ipa_nonzero(ifa->bdrip))
ospf_send_to(ifa, ifa->bdrip);
}
void
ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
{
sock *sk = ifa->sk;
struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
int len = ntohs(pkt->length);
#ifdef OSPFv2
if (ifa->autype == OSPF_AUTH_CRYPT)
len += OSPF_AUTH_CRYPT_SIZE;
#endif
ospf_pkt_finalize(ifa, pkt);
if (sk->tbuf != sk->tpos)
log(L_ERR "Aiee, old packet was overwritten in TX buffer");
sk_send_to(sk, len, dst, 0);
}

View File

@ -15,24 +15,32 @@ unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
int ospf_rx_hook(sock * sk, int size);
void ospf_tx_hook(sock * sk);
void ospf_err_hook(sock * sk, int err);
void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
void ospf_send_to_bdr(struct ospf_iface *ifa);
void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
void ospf_send_to_bdr(struct ospf_iface *ifa);
static inline void ospf_send_to_all(struct ospf_iface *ifa)
{
ospf_send_to(ifa, ifa->all_routers);
}
static inline void ospf_send_to_des(struct ospf_iface *ifa)
{
if (ipa_nonzero(ifa->des_routers))
ospf_send_to(ifa, ifa->des_routers);
else
ospf_send_to_bdr(ifa);
}
static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
static inline unsigned
ospf_pkt_bufsize(struct ospf_iface *ifa)
{
#ifdef OSPFv2
unsigned headers = (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
#else
unsigned headers = 0;
#endif
return ifa->sk->tbsize - headers;
/* Reserve buffer space for authentication footer */
return ifa->sk->tbsize -
(ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
}

View File

@ -15,12 +15,8 @@ static void rt_sync(struct proto_ospf *po);
/* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
as index, so we need to encapsulate RID to IP address */
#ifdef OSPFv2
#define ipa_from_rid(x) _MI(x)
#else /* OSPFv3 */
#define ipa_from_rid(x) _MI6(0,0,0,x)
#endif
#define ipa_from_rid(x) ipa_from_u32(x)
static inline void reset_ri(ort *ort)
{
@ -311,7 +307,7 @@ spfa_process_rt(struct ospf_area *oa, struct top_hash_entry *act)
struct ospf_lsa_rt_walk rtl;
struct top_hash_entry *tmp;
ip_addr prefix;
int pxlen;
int pxlen, i;
if (rt->options & OPT_RT_V)
oa->trcap = 1;
@ -339,8 +335,7 @@ spfa_process_rt(struct ospf_area *oa, struct top_hash_entry *act)
}
/* Now process Rt links */
lsa_walk_rt_init(po, act, &rtl);
while (lsa_walk_rt(&rtl))
for (lsa_walk_rt_init(po, act, &rtl), i = 0; lsa_walk_rt(&rtl); i++)
{
tmp = NULL;

View File

@ -31,12 +31,11 @@ void flush_prefix_net_lsa(struct ospf_iface *ifa);
#endif
#ifdef OSPFv2
static inline u32
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
{
/* We have to map IP prefixes to u32 in such manner that resulting
u32 interpreted as IP address is a member of given
/* In OSPFv2, We have to map IP prefixes to u32 in such manner
that resulting u32 interpreted as IP address is a member of given
prefix. Therefore, /32 prefix have to be mapped on itself.
All received prefixes have to be mapped on different u32s.
@ -63,7 +62,18 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
possible to have both reliably and the suggested algorithm was
unnecessary complicated and it does crazy things like changing
LSA ID for a network because different network appeared, we
choose a different way. */
choose a different way.
In OSPFv3, it is simpler. There is not a requirement for
membership of the result in the input network, so we just use a
hash-based unique ID of a routing table entry for a route that
originated given LSA. For ext-LSA, it is an imported route in the
nest's routing table (p->table). For summary-LSA, it is a
'source' route in the protocol internal routing table (po->rtf).
*/
if (ospf_is_v3(po))
return fn->uid;
u32 id = _I(fn->prefix);
@ -76,24 +86,6 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
return id | ~u32_mkmask(fn->pxlen);
}
#else /* OSPFv3 */
static inline u32
fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
{
/*
* In OSPFv3, it is simpler. There is not a requirement for
* membership of the result in the input network, so we just use a
* hash-based unique ID of a routing table entry for a route that
* originated given LSA. For ext-LSA, it is an imported route in the
* nest's routing table (p->table). For summary-LSA, it is a
* 'source' route in the protocol internal routing table (po->rtf).
*/
return fn->uid;
}
#endif
static void *
lsab_alloc(struct proto_ospf *po, unsigned size)
@ -1611,7 +1603,7 @@ ospf_top_rehash(struct top_graph *f, int step)
while (e)
{
x = e->next;
n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
e->next = *n;
*n = e;
e = x;
@ -1620,35 +1612,6 @@ ospf_top_rehash(struct top_graph *f, int step)
ospf_top_ht_free(oldt);
}
#ifdef OSPFv2
u32
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
{
return (type == LSA_T_EXT) ? 0 : ifa->oa->areaid;
}
#else /* OSPFv3 */
u32
ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
{
switch (type & LSA_SCOPE_MASK)
{
case LSA_SCOPE_LINK:
return ifa->iface->index;
case LSA_SCOPE_AREA:
return ifa->oa->areaid;
case LSA_SCOPE_AS:
default:
return 0;
}
}
#endif
struct top_hash_entry *
ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
{
@ -1667,7 +1630,8 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
struct top_hash_entry *e;
e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->domain != domain))
while (e && (e->lsa.id != lsa || e->lsa.rt != rtr ||
e->lsa_type != type || e->domain != domain))
e = e->next;
return e;
@ -1749,7 +1713,8 @@ ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
ee = f->hash_table + ospf_top_hash(f, domain, lsa, rtr, type);
e = *ee;
while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type || e->domain != domain))
while (e && (e->lsa.id != lsa || e->lsa.rt != rtr ||
e->lsa_type != type || e->domain != domain))
e = e->next;
if (e)
@ -1762,8 +1727,9 @@ ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
e->lb = IPA_NONE;
e->lsa.id = lsa;
e->lsa.rt = rtr;
e->lsa.type = type;
e->lsa.type = type;
e->lsa_body = NULL;
e->lsa_type = type;
e->domain = domain;
e->next = *ee;
*ee = e;
@ -1776,7 +1742,7 @@ void
ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
{
struct top_hash_entry **ee = f->hash_table +
ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
while (*ee)
{

View File

@ -23,9 +23,7 @@ struct top_hash_entry
bird_clock_t inst_t; /* Time of installation into DB */
struct mpnh *nhs; /* Computed nexthops - valid only in ospf_rt_spf() */
ip_addr lb; /* In OSPFv2, link back address. In OSPFv3, any global address in the area useful for vlinks */
#ifdef OSPFv3
u32 lb_id; /* Interface ID of link back iface (for bcast or NBMA networks) */
#endif
u32 dist; /* Distance from the root */
u16 ini_age;
u8 color;
@ -51,16 +49,14 @@ struct top_graph
struct top_graph *ospf_top_new(pool *);
void ospf_top_free(struct top_graph *);
void ospf_top_dump(struct top_graph *, struct proto *);
u32 ospf_lsa_domain(u32 type, struct ospf_iface *ifa);
struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 domain,
struct ospf_lsa_header *h);
struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, u32 domain,
struct ospf_lsa_header *h);
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
u32 type);
struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
u32 type);
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
void originate_rt_lsa(struct ospf_area *oa);
void update_rt_lsa(struct ospf_area *oa);