summaryrefslogtreecommitdiff
path: root/proto/ospf/dbdes.c
diff options
context:
space:
mode:
Diffstat (limited to 'proto/ospf/dbdes.c')
-rw-r--r--proto/ospf/dbdes.c595
1 files changed, 342 insertions, 253 deletions
diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c
index 6b291344..2b076157 100644
--- a/proto/ospf/dbdes.c
+++ b/proto/ospf/dbdes.c
@@ -2,6 +2,8 @@
* BIRD -- OSPF
*
* (c) 1999--2004 Ondrej Filip <feela@network.cz>
+ * (c) 2009--2014 Ondrej Zajicek <santiago@crfreenet.org>
+ * (c) 2009--2014 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -9,62 +11,185 @@
#include "ospf.h"
-#ifdef OSPFv2
-struct ospf_dbdes_packet
+struct ospf_dbdes2_packet
{
- struct ospf_packet ospf_packet;
+ struct ospf_packet hdr;
+ union ospf_auth auth;
+
u16 iface_mtu;
u8 options;
- union imms imms; /* I, M, MS bits */
+ u8 imms; /* I, M, MS bits */
u32 ddseq;
-};
-
-#define hton_opt(X) X
-#define ntoh_opt(X) X
-#endif
+ struct ospf_lsa_header lsas[];
+};
-#ifdef OSPFv3
-struct ospf_dbdes_packet
+struct ospf_dbdes3_packet
{
- struct ospf_packet ospf_packet;
+ struct ospf_packet hdr;
+
u32 options;
u16 iface_mtu;
u8 padding;
- union imms imms; /* I, M, MS bits */
+ u8 imms; /* I, M, MS bits */
u32 ddseq;
+
+ struct ospf_lsa_header lsas[];
};
-#define hton_opt(X) htonl(X)
-#define ntoh_opt(X) ntohl(X)
-#endif
-
-static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
+static inline uint
+ospf_dbdes_hdrlen(struct ospf_proto *p)
+{
+ return ospf_is_v2(p) ?
+ sizeof(struct ospf_dbdes2_packet) : sizeof(struct ospf_dbdes3_packet);
+}
+
+
+static void
+ospf_dbdes_body(struct ospf_proto *p, struct ospf_packet *pkt,
+ struct ospf_lsa_header **body, uint *count)
{
- struct ospf_packet *op = &pkt->ospf_packet;
+ uint plen = ntohs(pkt->length);
+ uint hlen = ospf_dbdes_hdrlen(p);
- ASSERT(op->type == DBDES_P);
- ospf_dump_common(p, op);
- log(L_TRACE "%s: imms %s%s%s",
- p->name, pkt->imms.bit.ms ? "MS " : "",
- pkt->imms.bit.m ? "M " : "",
- pkt->imms.bit.i ? "I " : "" );
- log(L_TRACE "%s: ddseq %u", p->name, ntohl(pkt->ddseq));
+ *body = ((void *) pkt) + hlen;
+ *count = (plen - hlen) / sizeof(struct ospf_lsa_header);
+}
- struct ospf_lsa_header *plsa = (void *) (pkt + 1);
- unsigned int i, j;
+static void
+ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
+{
+ struct ospf_lsa_header *lsas;
+ uint i, lsa_count;
+ u32 pkt_ddseq;
+ u16 pkt_iface_mtu;
+ u8 pkt_imms;
- j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
- sizeof(struct ospf_lsa_header);
+ ASSERT(pkt->type == DBDES_P);
+ ospf_dump_common(p, pkt);
- for (i = 0; i < j; i++)
- ospf_dump_lsahdr(p, plsa + i);
+ if (ospf_is_v2(p))
+ {
+ 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);
+ }
+
+ log(L_TRACE "%s: mtu %u", p->p.name, pkt_iface_mtu);
+ log(L_TRACE "%s: imms %s%s%s", p->p.name,
+ (pkt_imms & DBDES_I) ? "I " : "",
+ (pkt_imms & DBDES_M) ? "M " : "",
+ (pkt_imms & DBDES_MS) ? "MS" : "");
+ log(L_TRACE "%s: ddseq %u", p->p.name, pkt_ddseq);
+
+ ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
+ for (i = 0; i < lsa_count; i++)
+ ospf_dump_lsahdr(p, lsas + i);
}
+static void
+ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body)
+{
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_packet *pkt;
+ uint length;
+
+ u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
+
+ if (n->ldd_bsize != ifa->tx_length)
+ {
+ mb_free(n->ldd_buffer);
+ n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
+ n->ldd_bsize = ifa->tx_length;
+ }
+
+ pkt = n->ldd_buffer;
+ ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
+
+ if (ospf_is_v2(p))
+ {
+ struct ospf_dbdes2_packet *ps = (void *) pkt;
+ ps->iface_mtu = htons(iface_mtu);
+ ps->options = ifa->oa->options;
+ ps->imms = 0; /* Will be set later */
+ 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->padding = 0;
+ ps->imms = 0; /* Will be set later */
+ ps->ddseq = htonl(n->dds);
+ length = sizeof(struct ospf_dbdes3_packet);
+ }
+
+ if (body && (n->myimms & DBDES_M))
+ {
+ struct ospf_lsa_header *lsas;
+ struct top_hash_entry *en;
+ uint i = 0, lsa_max;
+
+ ospf_dbdes_body(p, pkt, &lsas, &lsa_max);
+ en = (void *) s_get(&(n->dbsi));
+
+ while (i < lsa_max)
+ {
+ if (!SNODE_VALID(en))
+ {
+ n->myimms &= ~DBDES_M; /* Unset More bit */
+ break;
+ }
+
+ if ((en->lsa.age < LSA_MAXAGE) &&
+ lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
+ {
+ lsa_hton_hdr(&(en->lsa), lsas + i);
+ i++;
+ }
+
+ en = SNODE_NEXT(en);
+ }
+
+ s_put(&(n->dbsi), SNODE en);
+
+ length += i * sizeof(struct ospf_lsa_header);
+ }
+
+ if (ospf_is_v2(p))
+ ((struct ospf_dbdes2_packet *) pkt)->imms = n->myimms;
+ else
+ ((struct ospf_dbdes3_packet *) pkt)->imms = n->myimms;
+
+ pkt->length = htons(length);
+}
+
+static void
+ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
+{
+ struct ospf_iface *ifa = n->ifa;
+
+ OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer,
+ "DBDES packet sent to %I via %s", n->ip, ifa->ifname);
+ sk_set_tbuf(ifa->sk, n->ldd_buffer);
+ ospf_send_to(ifa, n->ip);
+ sk_set_tbuf(ifa->sk, NULL);
+}
+
/**
- * ospf_dbdes_send - transmit database description packet
+ * ospf_send_dbdes - transmit database description packet
* @n: neighbor
* @next: whether to send a next packet in a sequence (1) or to retransmit the old one (0)
*
@@ -75,355 +200,319 @@ static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
* of the buffer.
*/
void
-ospf_dbdes_send(struct ospf_neighbor *n, int next)
+ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next)
{
- struct ospf_dbdes_packet *pkt;
- struct ospf_packet *op;
- struct ospf_iface *ifa = n->ifa;
- struct ospf_area *oa = ifa->oa;
- struct proto_ospf *po = oa->po;
- struct proto *p = &po->proto;
- u16 length, i, j;
+ /* RFC 2328 10.8 */
- /* FIXME ??? */
- if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
- update_rt_lsa(oa);
+ if (n->ifa->oa->rt == NULL)
+ return;
switch (n->state)
{
- case NEIGHBOR_EXSTART: /* Send empty packets */
- n->myimms.bit.i = 1;
- 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->ifname);
- ospf_send_to(ifa, n->ip);
+ case NEIGHBOR_EXSTART:
+ n->myimms |= DBDES_I;
+
+ /* Send empty packets */
+ ospf_prepare_dbdes(p, n, 0);
+ ospf_do_send_dbdes(p, n);
break;
case NEIGHBOR_EXCHANGE:
- n->myimms.bit.i = 0;
+ n->myimms &= ~DBDES_I;
if (next)
- {
- snode *sn;
- struct ospf_lsa_header *lsa;
-
- if (n->ldd_bsize != ifa->tx_length)
- {
- mb_free(n->ldd_buffer);
- n->ldd_buffer = mb_allocz(n->pool, ifa->tx_length);
- n->ldd_bsize = ifa->tx_length;
- }
+ ospf_prepare_dbdes(p, n, 1);
- pkt = n->ldd_buffer;
- op = (struct ospf_packet *) pkt;
+ /* Send prepared packet */
+ ospf_do_send_dbdes(p, n);
- 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);
+ /* Master should restart RXMT timer for each DBDES exchange */
+ if (n->myimms & DBDES_MS)
+ tm_start(n->rxmt_timer, n->ifa->rxmtint);
- j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header); /* Number of possible lsaheaders to send */
- lsa = (n->ldd_buffer + sizeof(struct ospf_dbdes_packet));
-
- if (n->myimms.bit.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.bit.m = 0; /* Unset more bit */
- }
-
- s_put(&(n->dbsi), sn);
- }
-
- pkt->imms.byte = n->myimms.byte;
-
- 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);
- }
+ if (!(n->myimms & DBDES_MS))
+ if (!(n->myimms & DBDES_M) &&
+ !(n->imms & DBDES_M))
+ ospf_neigh_sm(n, INM_EXDONE);
+ break;
case NEIGHBOR_LOADING:
case NEIGHBOR_FULL:
- length = n->ldd_buffer ? ntohs(((struct ospf_packet *) n->ldd_buffer)->length) : 0;
- if (!length)
+ if (!n->ldd_buffer)
{
- OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating");
+ OSPF_TRACE(D_PACKETS, "No DBDES packet for repeating");
ospf_neigh_sm(n, INM_KILLNBR);
return;
}
- /* Send last packet from ldd buffer */
+ /* Send last packet */
+ ospf_do_send_dbdes(p, n);
+ break;
+ }
+}
+
+
+static int
+ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
+{
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_lsa_header *lsas;
+ uint i, lsa_count;
+
+ ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
- OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer, "DBDES packet sent to %I via %s", n->ip, ifa->ifname);
+ for (i = 0; i < lsa_count; i++)
+ {
+ struct top_hash_entry *en, *req;
+ struct ospf_lsa_header lsa;
+ u32 lsa_type, lsa_domain;
- sk_set_tbuf(ifa->sk, n->ldd_buffer);
- ospf_send_to(ifa, n->ip);
- sk_set_tbuf(ifa->sk, NULL);
+ lsa_ntoh_hdr(lsas + i, &lsa);
+ lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
- if(n->myimms.bit.ms) tm_start(n->rxmt_timer, n->ifa->rxmtint); /* Restart timer */
+ /* RFC 2328 10.6 and RFC 5340 4.2.2 */
- if (!n->myimms.bit.ms)
+ if (!lsa_type)
{
- if ((n->myimms.bit.m == 0) && (n->imms.bit.m == 0) &&
- (n->state == NEIGHBOR_EXCHANGE))
- {
- ospf_neigh_sm(n, INM_EXDONE);
- }
+ log(L_WARN "%s: Bad DBDES from %I - LSA of unknown type", p->p.name, n->ip);
+ goto err;
}
- break;
- default: /* Ignore it */
- break;
- }
-}
+ if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
+ {
+ log(L_WARN "%s: Bad DBDES from %I - LSA with AS scope in stub area", p->p.name, n->ip);
+ goto err;
+ }
-static void
-ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
-{
- 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;
+ /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
+ if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
+ {
+ log(L_WARN "%s: Bad DBDES from %I - rt-summary-LSA in stub area", p->p.name, n->ip);
+ goto err;
+ }
- op = (struct ospf_packet *) ps;
+ /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
+ if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
+ {
+ log(L_WARN "%s: Bad DBDES from %I - LSA with invalid scope", p->p.name, n->ip);
+ goto err;
+ }
- plsa = (void *) (ps + 1);
+ en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
+ if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
+ {
+ req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
- j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
- sizeof(struct ospf_lsa_header);
+ if (!SNODE_VALID(req))
+ s_add_tail(&n->lsrql, SNODE req);
- for (i = 0; i < j; 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))
- {
- /* 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->lsa = lsa;
+ req->lsa_body = LSA_BODY_DUMMY;
}
}
+
+ return 0;
+
+ err:
+ ospf_neigh_sm(n, INM_SEQMIS);
+ return -1;
}
void
-ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
- struct proto_ospf *po = ifa->oa->po;
- struct proto *p = &po->proto;
+ struct ospf_proto *p = ifa->oa->po;
+ u32 rcv_ddseq, rcv_options;
+ u16 rcv_iface_mtu;
+ u8 rcv_imms;
+ uint plen;
+
+ /* RFC 2328 10.6 */
- unsigned int size = ntohs(ps_i->length);
- if (size < sizeof(struct ospf_dbdes_packet))
+ plen = ntohs(pkt->length);
+ if (plen < ospf_dbdes_hdrlen(p))
{
- 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;
}
- struct ospf_dbdes_packet *ps = (void *) ps_i;
- u32 ps_ddseq = ntohl(ps->ddseq);
- u32 ps_options = ntoh_opt(ps->options);
- u16 ps_iface_mtu = ntohs(ps->iface_mtu);
-
- OSPF_PACKET(ospf_dump_dbdes, ps, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
ospf_neigh_sm(n, INM_HELLOREC);
+ if (ospf_is_v2(p))
+ {
+ struct ospf_dbdes2_packet *ps = (void *) pkt;
+ rcv_iface_mtu = ntohs(ps->iface_mtu);
+ rcv_options = ps->options;
+ rcv_imms = ps->imms;
+ rcv_ddseq = ntohl(ps->ddseq);
+ }
+ else /* OSPFv3 */
+ {
+ struct ospf_dbdes3_packet *ps = (void *) pkt;
+ rcv_options = ntohl(ps->options);
+ rcv_iface_mtu = ntohs(ps->iface_mtu);
+ rcv_imms = ps->imms;
+ rcv_ddseq = ntohl(ps->ddseq);
+ }
+
switch (n->state)
{
case NEIGHBOR_DOWN:
case NEIGHBOR_ATTEMPT:
case NEIGHBOR_2WAY:
return;
- break;
+
case NEIGHBOR_INIT:
ospf_neigh_sm(n, INM_2WAYREC);
if (n->state != NEIGHBOR_EXSTART)
return;
- case NEIGHBOR_EXSTART:
- if ((ifa->type != OSPF_IT_VLINK) && (ps_iface_mtu != ifa->iface->mtu)
- && (ps_iface_mtu != 0) && (ifa->iface->mtu != 0))
- log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
- n->ip, ifa->ifname, ps_iface_mtu, ifa->iface->mtu);
-
- if ((ps->imms.bit.m && ps->imms.bit.ms && ps->imms.bit.i)
- && (n->rid > po->router_id) && (size == sizeof(struct ospf_dbdes_packet)))
+ case NEIGHBOR_EXSTART:
+ if ((ifa->type != OSPF_IT_VLINK) &&
+ (rcv_iface_mtu != ifa->iface->mtu) &&
+ (rcv_iface_mtu != 0) &&
+ (ifa->iface->mtu != 0))
+ log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)",
+ n->ip, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
+
+ if ((rcv_imms == DBDES_IMMS) &&
+ (n->rid > p->router_id) &&
+ (plen == ospf_dbdes_hdrlen(p)))
{
/* I'm slave! */
- n->dds = ps_ddseq;
- n->ddr = ps_ddseq;
- n->options = ps_options;
- n->myimms.bit.ms = 0;
- n->imms.byte = ps->imms.byte;
- OSPF_TRACE(D_PACKETS, "I'm slave to %I.", n->ip);
+ n->dds = rcv_ddseq;
+ n->ddr = rcv_ddseq;
+ n->options = rcv_options;
+ n->myimms &= ~DBDES_MS;
+ n->imms = rcv_imms;
+ OSPF_TRACE(D_PACKETS, "I'm slave to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE);
- ospf_dbdes_send(n, 1);
+ ospf_send_dbdes(p, n, 1);
break;
}
- if (((ps->imms.bit.i == 0) && (ps->imms.bit.ms == 0)) &&
- (n->rid < po->router_id) && (n->dds == ps_ddseq))
+ if (!(rcv_imms & DBDES_I) &&
+ !(rcv_imms & DBDES_MS) &&
+ (n->rid < p->router_id) &&
+ (n->dds == rcv_ddseq))
{
/* I'm master! */
- n->options = ps_options;
- n->ddr = ps_ddseq - 1; /* It will be set corectly a few lines down */
- n->imms.byte = ps->imms.byte;
- OSPF_TRACE(D_PACKETS, "I'm master to %I.", n->ip);
+ n->options = rcv_options;
+ n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */
+ n->imms = rcv_imms;
+ OSPF_TRACE(D_PACKETS, "I'm master to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE);
}
else
{
- DBG("%s: Nothing happend to %I (imms=%u)\n", p->name, n->ip,
- ps->imms.byte);
+ DBG("%s: Nothing happend to %I (imms=%d)\n", p->name, n->ip, rcv_imms);
break;
}
+
case NEIGHBOR_EXCHANGE:
- if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options) &&
- (ps_ddseq == n->ddr))
+ if ((rcv_imms == n->imms) &&
+ (rcv_options == n->options) &&
+ (rcv_ddseq == n->ddr))
{
/* Duplicate packet */
- OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
- if (n->myimms.bit.ms == 0)
+ OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
+ if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */
- ospf_dbdes_send(n, 0);
+ ospf_send_dbdes(p, n, 0);
}
return;
}
- n->ddr = ps_ddseq;
-
- if (ps->imms.bit.ms != n->imms.bit.ms) /* M/S bit differs */
+ if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) /* M/S bit differs */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- if (ps->imms.bit.i) /* I bit is set */
+ if (rcv_imms & DBDES_I) /* I bit is set */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- n->imms.byte = ps->imms.byte;
-
- if (ps_options != n->options) /* Options differs */
+ if (rcv_options != n->options) /* Options differs */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- if (n->myimms.bit.ms)
+ n->ddr = rcv_ddseq;
+ n->imms = rcv_imms;
+
+ if (n->myimms & DBDES_MS)
{
- if (ps_ddseq != n->dds) /* MASTER */
+ if (rcv_ddseq != n->dds) /* MASTER */
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)",
- n->ip);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
+
n->dds++;
- DBG("Incrementing dds\n");
- ospf_dbdes_reqladd(ps, n);
- if ((n->myimms.bit.m == 0) && (ps->imms.bit.m == 0))
- {
+
+ if (ospf_process_dbdes(p, pkt, n) < 0)
+ return;
+
+ if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
ospf_neigh_sm(n, INM_EXDONE);
- }
else
- {
- ospf_dbdes_send(n, 1);
- }
-
+ ospf_send_dbdes(p, n, 1);
}
else
{
- if (ps_ddseq != (n->dds + 1)) /* SLAVE */
+ if (rcv_ddseq != (n->dds + 1)) /* SLAVE */
{
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
- n->ddr = ps_ddseq;
- n->dds = ps_ddseq;
- ospf_dbdes_reqladd(ps, n);
- ospf_dbdes_send(n, 1);
- }
+ n->ddr = rcv_ddseq;
+ n->dds = rcv_ddseq;
+
+ if (ospf_process_dbdes(p, pkt, n) < 0)
+ return;
+
+ ospf_send_dbdes(p, n, 1);
+ }
break;
+
case NEIGHBOR_LOADING:
case NEIGHBOR_FULL:
- if ((ps->imms.byte == n->imms.byte) && (ps_options == n->options)
- && (ps_ddseq == n->ddr))
- /* Only duplicate are accepted */
+ if ((rcv_imms == n->imms) &&
+ (rcv_options == n->options) &&
+ (rcv_ddseq == n->ddr))
{
- OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
- if (n->myimms.bit.ms == 0)
+ /* Duplicate packet */
+ OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
+ if (!(n->myimms & DBDES_MS))
{
/* Slave should retransmit dbdes packet */
- ospf_dbdes_send(n, 0);
+ ospf_send_dbdes(p, n, 0);
}
return;
}
else
{
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)",
- n->ip);
- DBG("PS=%u, DDR=%u, DDS=%u\n", ps_ddseq, n->ddr, n->dds);
+ OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (full)", n->ip);
+ DBG("PS=%u, DDR=%u, DDS=%u\n", rcv_ddseq, n->ddr, n->dds);
ospf_neigh_sm(n, INM_SEQMIS);
}
break;
+
default:
bug("Received dbdes from %I in undefined state.", n->ip);
}