summaryrefslogtreecommitdiff
path: root/proto/ospf
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2014-10-24 10:27:21 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2014-10-24 11:07:38 +0200
commitf8fefde318c6248ad94e7b6d60155deed9ab8eed (patch)
tree4edd3eb9b152f016afc2482555fb62b04f96eeb2 /proto/ospf
parent78342404ff573e85e396f0611014b90cea9b4c0a (diff)
Refactoring of OSPF messages.
Diffstat (limited to 'proto/ospf')
-rw-r--r--proto/ospf/dbdes.c230
-rw-r--r--proto/ospf/hello.c78
-rw-r--r--proto/ospf/iface.c71
-rw-r--r--proto/ospf/lsack.c5
-rw-r--r--proto/ospf/lsreq.c12
-rw-r--r--proto/ospf/lsupd.c96
-rw-r--r--proto/ospf/neighbor.c455
-rw-r--r--proto/ospf/ospf.c5
-rw-r--r--proto/ospf/ospf.h40
-rw-r--r--proto/ospf/packet.c213
-rw-r--r--proto/ospf/rt.c8
-rw-r--r--proto/ospf/topology.c4
12 files changed, 568 insertions, 649 deletions
diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c
index 2b076157..88c87164 100644
--- a/proto/ospf/dbdes.c
+++ b/proto/ospf/dbdes.c
@@ -98,7 +98,7 @@ ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
static void
-ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body)
+ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
{
struct ospf_iface *ifa = n->ifa;
struct ospf_packet *pkt;
@@ -106,6 +106,7 @@ ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body)
u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
+ /* Update DBDES buffer */
if (n->ldd_bsize != ifa->tx_length)
{
mb_free(n->ldd_buffer);
@@ -136,7 +137,8 @@ ospf_prepare_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int body)
length = sizeof(struct ospf_dbdes3_packet);
}
- if (body && (n->myimms & DBDES_M))
+ /* Prepare DBDES body */
+ if (!(n->myimms & DBDES_I) && (n->myimms & DBDES_M))
{
struct ospf_lsa_header *lsas;
struct top_hash_entry *en;
@@ -182,7 +184,7 @@ 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);
+ "DBDES packet sent to nbr %R on %s", n->rid, ifa->ifname);
sk_set_tbuf(ifa->sk, n->ldd_buffer);
ospf_send_to(ifa, n->ip);
sk_set_tbuf(ifa->sk, NULL);
@@ -191,7 +193,6 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
/**
* 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)
*
* Sending of a database description packet is described in 10.8 of RFC 2328.
* Reception of each packet is acknowledged in the sequence number of another.
@@ -200,104 +201,78 @@ ospf_do_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
* of the buffer.
*/
void
-ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next)
+ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
{
/* RFC 2328 10.8 */
+ ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE));
+
if (n->ifa->oa->rt == NULL)
return;
- switch (n->state)
- {
- 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 &= ~DBDES_I;
-
- if (next)
- ospf_prepare_dbdes(p, n, 1);
-
- /* Send prepared packet */
- ospf_do_send_dbdes(p, n);
+ ospf_prepare_dbdes(p, n);
+ ospf_do_send_dbdes(p, n);
- /* Master should restart RXMT timer for each DBDES exchange */
- if (n->myimms & DBDES_MS)
- tm_start(n->rxmt_timer, n->ifa->rxmtint);
+ if (n->state == NEIGHBOR_EXSTART)
+ return;
- if (!(n->myimms & DBDES_MS))
- if (!(n->myimms & DBDES_M) &&
- !(n->imms & DBDES_M))
- ospf_neigh_sm(n, INM_EXDONE);
- break;
+ /* Master should restart RXMT timer for each DBDES exchange */
+ if (n->myimms & DBDES_MS)
+ tm_start(n->rxmt_timer, n->ifa->rxmtint);
- case NEIGHBOR_LOADING:
- case NEIGHBOR_FULL:
+ if (!(n->myimms & DBDES_MS))
+ if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
+ ospf_neigh_sm(n, INM_EXDONE);
+}
- if (!n->ldd_buffer)
- {
- OSPF_TRACE(D_PACKETS, "No DBDES packet for repeating");
- ospf_neigh_sm(n, INM_KILLNBR);
- return;
- }
+void
+ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
+{
+ ASSERT(n->state > NEIGHBOR_EXSTART);
- /* Send last packet */
- ospf_do_send_dbdes(p, n);
- break;
+ if (!n->ldd_buffer)
+ {
+ log(L_WARN "%s: No DBDES packet for retransmit", p->p.name);
+ ospf_neigh_sm(n, INM_SEQMIS);
+ return;
}
-}
+ /* Send last packet */
+ ospf_do_send_dbdes(p, n);
+}
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;
+ struct ospf_lsa_header *lsas, lsa;
+ struct top_hash_entry *en, *req;
+ const char *err_dsc = NULL;
+ u32 lsa_type, lsa_domain;
uint i, lsa_count;
ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
for (i = 0; i < lsa_count; i++)
{
- struct top_hash_entry *en, *req;
- struct ospf_lsa_header lsa;
- u32 lsa_type, lsa_domain;
-
lsa_ntoh_hdr(lsas + i, &lsa);
lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
/* RFC 2328 10.6 and RFC 5340 4.2.2 */
if (!lsa_type)
- {
- log(L_WARN "%s: Bad DBDES from %I - LSA of unknown type", p->p.name, n->ip);
- goto err;
- }
+ DROP1("LSA of unknown type");
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;
- }
+ DROP1("LSA with AS scope in stub area");
/* 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;
- }
+ DROP1("rt-summary-LSA in stub area");
/* 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;
- }
+ DROP1("LSA with invalid scope");
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
@@ -314,7 +289,10 @@ ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_ne
return 0;
- err:
+drop:
+ LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in DBDES", lsa_type, lsa.id, lsa.rt);
+ LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
+
ospf_neigh_sm(n, INM_SEQMIS);
return -1;
}
@@ -324,21 +302,19 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
struct ospf_proto *p = ifa->oa->po;
+ const char *err_dsc = NULL;
u32 rcv_ddseq, rcv_options;
u16 rcv_iface_mtu;
u8 rcv_imms;
- uint plen;
+ uint plen, err_val = 0, err_seqmis = 0;
/* RFC 2328 10.6 */
plen = ntohs(pkt->length);
if (plen < ospf_dbdes_hdrlen(p))
- {
- log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen);
- return;
- }
+ DROP("too short", plen);
- OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet received from nbr %R on %s", n->rid, ifa->ifname);
ospf_neigh_sm(n, INM_HELLOREC);
@@ -364,6 +340,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
case NEIGHBOR_DOWN:
case NEIGHBOR_ATTEMPT:
case NEIGHBOR_2WAY:
+ OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart");
return;
case NEIGHBOR_INIT:
@@ -376,8 +353,8 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
(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);
+ LOG_PKT_WARN("MTU mismatch with nbr %R on %s (remote %d, local %d)",
+ n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
if ((rcv_imms == DBDES_IMMS) &&
(n->rid > p->router_id) &&
@@ -389,9 +366,8 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
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_send_dbdes(p, n, 1);
+ ospf_send_dbdes(p, n);
break;
}
@@ -404,7 +380,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
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
@@ -417,49 +392,29 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
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 & DBDES_MS))
- {
- /* Slave should retransmit dbdes packet */
- ospf_send_dbdes(p, n, 0);
- }
- return;
- }
+ goto duplicate;
- 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_neigh_sm(n, INM_SEQMIS);
- break;
- }
+ /* Do INM_SEQMIS during packet error */
+ err_seqmis = 1;
- if (rcv_imms & DBDES_I) /* I bit is set */
- {
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
- ospf_neigh_sm(n, INM_SEQMIS);
- break;
- }
+ if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
+ DROP("MS-bit mismatch", rcv_imms);
- if (rcv_options != n->options) /* Options differs */
- {
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
- ospf_neigh_sm(n, INM_SEQMIS);
- break;
- }
+ if (rcv_imms & DBDES_I)
+ DROP("I-bit mismatch", rcv_imms);
+
+ if (rcv_options != n->options)
+ DROP("options mismatch", rcv_options);
n->ddr = rcv_ddseq;
n->imms = rcv_imms;
if (n->myimms & DBDES_MS)
{
- if (rcv_ddseq != n->dds) /* MASTER */
- {
- OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip);
- ospf_neigh_sm(n, INM_SEQMIS);
- break;
- }
+ /* MASTER */
+
+ if (rcv_ddseq != n->dds)
+ DROP("DD sequence number mismatch", rcv_ddseq);
n->dds++;
@@ -469,16 +424,14 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
ospf_neigh_sm(n, INM_EXDONE);
else
- ospf_send_dbdes(p, n, 1);
+ ospf_send_dbdes(p, n);
}
else
{
- 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;
- }
+ /* SLAVE */
+
+ if (rcv_ddseq != (n->dds + 1))
+ DROP("DD sequence number mismatch", rcv_ddseq);
n->ddr = rcv_ddseq;
n->dds = rcv_ddseq;
@@ -486,7 +439,7 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (ospf_process_dbdes(p, pkt, n) < 0)
return;
- ospf_send_dbdes(p, n, 1);
+ ospf_send_dbdes(p, n);
}
break;
@@ -495,25 +448,30 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
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 & DBDES_MS))
- {
- /* Slave should retransmit dbdes packet */
- 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", rcv_ddseq, n->ddr, n->dds);
- ospf_neigh_sm(n, INM_SEQMIS);
- }
- break;
+ goto duplicate;
+
+ err_seqmis = 1;
+
+ DROP("too late for DD exchange", n->state);
default:
- bug("Received dbdes from %I in undefined state.", n->ip);
+ bug("Undefined interface state");
}
+ return;
+
+duplicate:
+ OSPF_TRACE(D_PACKETS, "DBDES packet is duplicate");
+
+ /* Slave should retransmit DBDES packet */
+ if (!(n->myimms & DBDES_MS))
+ ospf_rxmt_dbdes(p, n);
+ return;
+
+drop:
+ LOG_PKT("Bad DBDES packet from nbr %R on %s - %s (%u)",
+ n->rid, ifa->ifname, err_dsc, err_val);
+
+ if (err_seqmis)
+ ospf_neigh_sm(n, INM_SEQMIS);
+ return;
}
diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c
index 3aeb9f9a..e8b1c702 100644
--- a/proto/ospf/hello.c
+++ b/proto/ospf/hello.c
@@ -114,7 +114,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{
if (i == max)
{
- log(L_WARN "%s: Too many neighbors on interface %s", p->p.name, ifa->ifname);
+ log(L_WARN "%s: Too many neighbors on %s", p->p.name, ifa->ifname);
break;
}
neighbors[i] = htonl(neigh->rid);
@@ -188,16 +188,21 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n, ip_addr faddr)
{
struct ospf_proto *p = ifa->oa->po;
- char *beg = "OSPF: Bad HELLO packet from ";
+ const char *err_dsc = NULL;
u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
u8 rcv_options, rcv_priority;
u32 *neighbors;
u32 neigh_count;
- uint plen, i;
+ uint plen, i, err_val = 0;
/* RFC 2328 10.5 */
- OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s", faddr, ifa->ifname);
+ /*
+ * We may not yet havethe associate neighbor, so we use Router ID from the
+ * packet instead of one from the neighbor structure for log messages.
+ */
+ u32 rcv_rid = ntohl(pkt->routerid);
+ OSPF_TRACE(D_PACKETS, "HELLO packet received from nbr %R on %s", rcv_rid, ifa->ifname);
plen = ntohs(pkt->length);
@@ -206,10 +211,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_hello2_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello2_packet))
- {
- log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen);
- return;
- }
+ DROP("too short", plen);
rcv_iface_id = 0;
rcv_helloint = ntohs(ps->helloint);
@@ -223,10 +225,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
if ((ifa->type != OSPF_IT_VLINK) &&
(ifa->type != OSPF_IT_PTP) &&
(pxlen != ifa->addr->pxlen))
- {
- log(L_ERR "%s%I - prefix length mismatch (%d)", beg, faddr, pxlen);
- return;
- }
+ DROP("prefix length mismatch", pxlen);
neighbors = ps->neighbors;
neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32);
@@ -236,10 +235,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_hello3_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello3_packet))
- {
- log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen);
- return;
- }
+ DROP("too short", plen);
rcv_iface_id = ntohl(ps->iface_id);
rcv_helloint = ntohs(ps->helloint);
@@ -254,23 +250,14 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
}
if (rcv_helloint != ifa->helloint)
- {
- log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, rcv_helloint);
- return;
- }
+ DROP("hello interval mismatch", rcv_helloint);
if (rcv_deadint != ifa->deadint)
- {
- log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, rcv_deadint);
- return;
- }
+ DROP("dead interval mismatch", rcv_deadint);
/* Check whether bits E, N match */
if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
- {
- log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, rcv_options);
- return;
- }
+ DROP("area type mismatch", rcv_options);
/* Check consistency of existing neighbor entry */
if (n)
@@ -279,11 +266,11 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
{
/* Neighbor identified by IP address; Router ID may change */
- if (n->rid != ntohl(pkt->routerid))
+ if (n->rid != rcv_rid)
{
- OSPF_TRACE(D_EVENTS, "Neighbor %I has changed Router ID from %R to %R",
- n->ip, n->rid, ntohl(pkt->routerid));
- ospf_neigh_remove(n);
+ OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R",
+ n->rid, ifa->ifname, rcv_rid);
+ ospf_neigh_sm(n, INM_KILLNBR);
n = NULL;
}
}
@@ -292,7 +279,8 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* Neighbor identified by Router ID; IP address may change */
if (!ipa_equal(faddr, n->ip))
{
- OSPF_TRACE(D_EVENTS, "Neighbor address changed from %I to %I", n->ip, faddr);
+ OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed IP address to %I",
+ n->rid, ifa->ifname, n->ip, faddr);
n->ip = faddr;
}
}
@@ -305,28 +293,26 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct nbma_node *nn = find_nbma_node(ifa, faddr);
if (!nn && ifa->strictnbma)
- {
- log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname);
- return;
- }
+ DROP1("new neighbor denied");
if (nn && (ifa->type == OSPF_IT_NBMA) &&
(((rcv_priority == 0) && nn->eligible) ||
((rcv_priority > 0) && !nn->eligible)))
- {
- log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname);
- return;
- }
+ DROP("eligibility mismatch", rcv_priority);
if (nn)
nn->found = 1;
}
+ // XXXX format
+ // "ospf1: New neighbor found: 192.168.1.1/fe80:1234:1234:1234:1234 on eth0";
+ // "ospf1: New neighbor found: 192.168.1.1 on eth0 at fe80:1234:1234:1234:1234";
+ // "ospf1: Neighbor 192.168.1.1 on eth0 found, IP adress fe80:1234:1234:1234:1234";
OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
n = ospf_neighbor_new(ifa);
- n->rid = ntohl(pkt->routerid);
+ n->rid = rcv_rid;
n->ip = faddr;
n->dr = rcv_dr;
n->bdr = rcv_bdr;
@@ -367,7 +353,7 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
ospf_neigh_sm(n, INM_1WAYREC);
return;
- found_self:
+found_self:
ospf_neigh_sm(n, INM_2WAYREC);
@@ -400,4 +386,10 @@ ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa,
((n->bdr != n_id) && (old_bdr == n_id)))
ospf_iface_sm(ifa, ISM_NEICH);
}
+
+ return;
+
+drop:
+ LOG_PKT("Bad HELLO packet from nbr %R on %s - %s (%u)",
+ rcv_rid, ifa->ifname, err_dsc, err_val);
}
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index 892e8a77..e14f09cb 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -11,15 +11,16 @@
#include "ospf.h"
-char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother",
- "backup", "dr"
+const char *ospf_is_names[] = {
+ "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR"
};
-char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen",
- "neighbor change", "loop indicated", "unloop indicated", "interface down"
+const char *ospf_ism_names[] = {
+ "InterfaceUp", "WaitTimer", "BackupSeen", "NeighborChange",
+ "LoopInd", "UnloopInd", "InterfaceDown"
};
-char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
+const char *ospf_it[] = { "broadcast", "nbma", "ptp", "ptmp", "virtual link" };
static void
@@ -40,7 +41,7 @@ wait_timer_hook(timer * timer)
struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
struct ospf_proto *p = ifa->oa->po;
- OSPF_TRACE(D_EVENTS, "Wait timer fired on interface %s", ifa->ifname);
+ OSPF_TRACE(D_EVENTS, "Wait timer fired on %s", ifa->ifname);
ospf_iface_sm(ifa, ISM_WAITF);
}
@@ -240,10 +241,7 @@ ospf_iface_down(struct ospf_iface *ifa)
}
WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
- {
- OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
- ospf_neigh_remove(n);
- }
+ ospf_neigh_sm(n, INM_KILLNBR);
if (ifa->hello_timer)
tm_stop(ifa->hello_timer);
@@ -311,8 +309,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
if (state == oldstate)
return;
- OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
- ifa->ifname, ospf_is[oldstate], ospf_is[state]);
+ OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s",
+ ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]);
ifa->state = state;
@@ -351,7 +349,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
void
ospf_iface_sm(struct ospf_iface *ifa, int event)
{
- DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism[event]);
+ DBG("SM on %s. Event is '%s'\n", ifa->ifname, ospf_ism_names[event]);
switch (event)
{
@@ -613,7 +611,8 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
continue;
if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
- log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip);
+ log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
+ p->p.name, nb->ip);
add_nbma_node(ifa, nb, 0);
}
@@ -726,7 +725,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* HELLO TIMER */
if (ifa->helloint != new->helloint)
{
- OSPF_TRACE(D_EVENTS, "Changing hello interval on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing hello interval of %s from %d to %d",
ifname, ifa->helloint, new->helloint);
ifa->helloint = new->helloint;
@@ -736,7 +735,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* RXMT TIMER */
if (ifa->rxmtint != new->rxmtint)
{
- OSPF_TRACE(D_EVENTS, "Changing retransmit interval on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing retransmit interval of %s from %d to %d",
ifname, ifa->rxmtint, new->rxmtint);
ifa->rxmtint = new->rxmtint;
@@ -745,7 +744,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* POLL TIMER */
if (ifa->pollint != new->pollint)
{
- OSPF_TRACE(D_EVENTS, "Changing poll interval on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing poll interval of %s from %d to %d",
ifname, ifa->pollint, new->pollint);
ifa->pollint = new->pollint;
@@ -755,7 +754,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* WAIT TIMER */
if (ifa->waitint != new->waitint)
{
- OSPF_TRACE(D_EVENTS, "Changing wait interval on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing wait interval of %s from %d to %d",
ifname, ifa->waitint, new->waitint);
ifa->waitint = new->waitint;
@@ -766,7 +765,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* DEAD TIMER */
if (ifa->deadint != new->deadint)
{
- OSPF_TRACE(D_EVENTS, "Changing dead interval on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing dead interval of %s from %d to %d",
ifname, ifa->deadint, new->deadint);
ifa->deadint = new->deadint;
}
@@ -774,7 +773,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* INFTRANS */
if (ifa->inftransdelay != new->inftransdelay)
{
- OSPF_TRACE(D_EVENTS, "Changing transmit delay on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing transmit delay of %s from %d to %d",
ifname, ifa->inftransdelay, new->inftransdelay);
ifa->inftransdelay = new->inftransdelay;
}
@@ -782,7 +781,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* AUTHENTICATION */
if (ifa->autype != new->autype)
{
- OSPF_TRACE(D_EVENTS, "Changing authentication type on interface %s", ifname);
+ OSPF_TRACE(D_EVENTS, "Changing authentication type of %s", ifname);
ifa->autype = new->autype;
}
@@ -797,7 +796,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* COST */
if (ifa->cost != new->cost)
{
- OSPF_TRACE(D_EVENTS, "Changing cost on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing cost of %s from %d to %d",
ifname, ifa->cost, new->cost);
ifa->cost = new->cost;
@@ -806,7 +805,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* PRIORITY */
if (ifa->priority != new->priority)
{
- OSPF_TRACE(D_EVENTS, "Changing priority on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing priority of %s from %d to %d",
ifname, ifa->priority, new->priority);
ifa->priority = new->priority;
@@ -816,7 +815,8 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* STRICT NBMA */
if (ifa->strictnbma != new->strictnbma)
{
- OSPF_TRACE(D_EVENTS, "Changing NBMA strictness on interface %s", ifname);
+ OSPF_TRACE(D_EVENTS, "Changing NBMA strictness of %s from %d to %d",
+ ifname, ifa->strictnbma, new->strictnbma);
ifa->strictnbma = new->strictnbma;
}
@@ -830,14 +830,14 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
{
if (nb->eligible != nb2->eligible)
{
- OSPF_TRACE(D_EVENTS, "Changing eligibility of neighbor %I on interface %s",
+ OSPF_TRACE(D_EVENTS, "Changing eligibility of NBMA neighbor %I on %s",
nb->ip, ifname);
nb->eligible = nb2->eligible;
}
}
else
{
- OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on interface %s",
+ OSPF_TRACE(D_EVENTS, "Removing NBMA neighbor %I on %s",
nb->ip, ifname);
rem_node(NODE nb);
mb_free(nb);
@@ -852,11 +852,12 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
continue;
if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip))
- log(L_WARN "In OSPFv3, configured neighbor address (%I) should be link-local", nb->ip);
+ log(L_WARN "%s: Configured neighbor address (%I) should be link-local",
+ p->p.name, nb->ip);
if (! find_nbma_node(ifa, nb->ip))
{
- OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on interface %s",
+ OSPF_TRACE(D_EVENTS, "Adding NBMA neighbor %I on %s",
nb->ip, ifname);
add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip));
}
@@ -867,7 +868,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* TX LENGTH */
if (old->tx_length != new->tx_length)
{
- OSPF_TRACE(D_EVENTS, "Changing TX length on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing TX length of %s from %d to %d",
ifname, old->tx_length, new->tx_length);
/* ifa cannot be vlink */
@@ -878,7 +879,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* RX BUFFER */
if (old->rx_buffer != new->rx_buffer)
{
- OSPF_TRACE(D_EVENTS, "Changing buffer size on interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing buffer size of %s from %d to %d",
ifname, old->rx_buffer, new->rx_buffer);
/* ifa cannot be vlink */
@@ -896,7 +897,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* LINK */
if (ifa->check_link != new->check_link)
{
- OSPF_TRACE(D_EVENTS, "%s link check on interface %s",
+ OSPF_TRACE(D_EVENTS, "%s link check for %s",
new->check_link ? "Enabling" : "Disabling", ifname);
ifa->check_link = new->check_link;
@@ -908,7 +909,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* ECMP weight */
if (ifa->ecmp_weight != new->ecmp_weight)
{
- OSPF_TRACE(D_EVENTS, "Changing ECMP weight of interface %s from %d to %d",
+ OSPF_TRACE(D_EVENTS, "Changing ECMP weight of %s from %d to %d",
ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
ifa->ecmp_weight = new->ecmp_weight;
}
@@ -927,7 +928,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* BFD */
if (ifa->bfd != new->bfd)
{
- OSPF_TRACE(D_EVENTS, "%s BFD on interface %s",
+ OSPF_TRACE(D_EVENTS, "%s BFD for %s",
new->bfd ? "Enabling" : "Disabling", ifname);
ifa->bfd = new->bfd;
@@ -1197,7 +1198,7 @@ ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
{
/* ifa is not vlink */
- OSPF_TRACE(D_EVENTS, "Changing MTU on interface %s", ifa->ifname);
+ OSPF_TRACE(D_EVENTS, "Interface %s changed MTU to %d", ifa->iface->mtu);
ifa->tx_length = ifa_tx_length(ifa);
@@ -1285,7 +1286,7 @@ ospf_iface_info(struct ospf_iface *ifa)
cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
}
- cli_msg(-1015, "\tState: %s%s", ospf_is[ifa->state], ifa->stub ? " (stub)" : "");
+ cli_msg(-1015, "\tState: %s%s", ospf_is_names[ifa->state], ifa->stub ? " (stub)" : "");
cli_msg(-1015, "\tPriority: %u", ifa->priority);
cli_msg(-1015, "\tCost: %u", ifa->cost);
if (ifa->oa->po->ecmp)
diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c
index 5cac3f69..e590817e 100644
--- a/proto/ospf/lsack.c
+++ b/proto/ospf/lsack.c
@@ -140,10 +140,13 @@ ospf_receive_lsack(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* No need to check length, lsack has only basic header */
- OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_lsack, pkt, "LSACK packet received from nbr %R on %s", n->rid, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE)
+ {
+ OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
return;
+ }
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c
index a6c0cf24..067ad79b 100644
--- a/proto/ospf/lsreq.c
+++ b/proto/ospf/lsreq.c
@@ -93,7 +93,7 @@ ospf_send_lsreq(struct ospf_proto *p, struct ospf_neighbor *n)
length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header);
pkt->length = htons(length);
- OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet sent to nbr %R on %s", n->rid, ifa->ifname);
ospf_send_to(ifa, n->ip);
}
@@ -110,10 +110,13 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* No need to check length, lsreq has only basic header */
- OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet received from %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_lsreq, pkt, "LSREQ packet received from nbr %R on %s", n->rid, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE)
+ {
+ OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange");
return;
+ }
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */
@@ -134,8 +137,9 @@ ospf_receive_lsreq(struct ospf_packet *pkt, struct ospf_iface *ifa,
en = ospf_hash_find(p->gr, domain, id, rt, type);
if (!en)
{
- log(L_WARN "%s: Received LSREQ from %I for missing LSA (Type: %04x, Id: %R, Rt: %R)",
- p->p.name, n->ip, type, id, rt);
+ LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt);
+ LOG_LSA2(" received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname);
+
ospf_neigh_sm(n, INM_BADLSREQ);
return;
}
diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c
index 13ae54d1..0aa45f6a 100644
--- a/proto/ospf/lsupd.c
+++ b/proto/ospf/lsupd.c
@@ -338,7 +338,7 @@ ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa
{ i++; continue; }
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa),
- "LSUPD packet sent to %I via %s", n->ip, ifa->ifname);
+ "LSUPD packet sent to nbr %R on %s", n->rid, ifa->ifname);
ospf_send_to(ifa, n->ip);
}
@@ -396,24 +396,22 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n)
{
struct ospf_proto *p = ifa->oa->po;
-
- /* RFC 2328 13. */
-
+ const char *err_dsc = NULL;
+ uint plen, err_val = 0;
int skip_lsreq = 0;
n->want_lsreq = 0;
- uint plen = ntohs(pkt->length);
+ /* RFC 2328 13. */
+
+ plen = ntohs(pkt->length);
if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header)))
- {
- log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen);
- return;
- }
+ DROP("too short", plen);
- OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->ifname);
+ OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE)
{
- OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", n->ip);
+ OSPF_TRACE(D_PACKETS, "LSUPD packet ignored - lesser state than Exchange");
return;
}
@@ -429,33 +427,18 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
u32 lsa_len, lsa_type, lsa_domain;
if (offset > bound)
- {
- log(L_WARN "%s: Received LSUPD from %I is too short", p->p.name, n->ip);
- ospf_neigh_sm(n, INM_BADLSREQ);
- return;
- }
+ DROP("too short", plen);
/* LSA header in network order */
lsa_n = ((void *) pkt) + offset;
lsa_len = ntohs(lsa_n->length);
offset += lsa_len;
- if ((offset > plen) || ((lsa_len % 4) != 0) ||
- (lsa_len <= sizeof(struct ospf_lsa_header)))
- {
- log(L_WARN "%s: Received LSA from %I with bad length", p->p.name, n->ip);
- ospf_neigh_sm(n, INM_BADLSREQ);
- return;
- }
+ if (offset > plen)
+ DROP("too short", plen);
- /* RFC 2328 13. (1) - validate LSA checksum */
- u16 chsum = lsa_n->checksum;
- if (chsum != lsasum_check(lsa_n, NULL))
- {
- log(L_WARN "%s: Received LSA from %I with bad checksum: %x %x",
- p->p.name, n->ip, chsum, lsa_n->checksum);
- continue;
- }
+ if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
+ DROP("invalid LSA length", lsa_len);
/* LSA header in host order */
lsa_ntoh_hdr(lsa_n, &lsa);
@@ -464,33 +447,25 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
lsa_type, lsa.id, lsa.rt, lsa.sn, lsa.age, lsa.checksum);
+ /* RFC 2328 13. (1) - validate LSA checksum */
+ if (lsa_n->checksum != lsasum_check(lsa_n, NULL))
+ SKIP("invalid checksum");
+
/* RFC 2328 13. (2) */
if (!lsa_type)
- {
- log(L_WARN "%s: Received unknown LSA type from %I", p->p.name, n->ip);
- continue;
- }
+ SKIP("unknown type");
/* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */
if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
- {
- log(L_WARN "%s: Received LSA with AS scope in stub area from %I", p->p.name, n->ip);
- continue;
- }
+ SKIP("AS scope in stub area");
/* 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: Received rt-summary-LSA in stub area from %I", p->p.name, n->ip);
- continue;
- }
+ SKIP("rt-summary-LSA in stub area");
/* RFC 5340 4.5.1 (3) */
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
- {
- log(L_WARN "%s: Received LSA with invalid scope from %I", p->p.name, n->ip);
- continue;
- }
+ SKIP("invalid scope");
/* Find local copy of LSA in link state database */
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
@@ -528,9 +503,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
if (lsa_validate(&lsa, lsa_type, ospf_is_v2(p), body) == 0)
{
- log(L_WARN "%s: Received invalid LSA from %I", p->p.name, n->ip);
mb_free(body);
- continue;
+ SKIP("invalid body");
}
/* 13. (5f) - handle self-originated LSAs, see also 13.4. */
@@ -542,8 +516,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
continue;
}
- /* 13. (5c) - remove old LSA from all retransmission lists */
- /*
+ /* 13. (5c) - remove old LSA from all retransmission lists
+ *
* We only need to remove it from the retransmission list of the neighbor
* that send us the new LSA. The old LSA is automatically replaced in
* retransmission lists by the new LSA.
@@ -561,8 +535,8 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
WALK_LIST(ifi, p->iface_list)
WALK_LIST(ni, ifi->neigh_list)
- if (ni->state > NEIGHBOR_EXSTART)
- ospf_lsa_lsrt_down(en, ni);
+ if (ni->state > NEIGHBOR_EXSTART)
+ ospf_lsa_lsrt_down(en, ni);
#endif
/* 13. (5d) - install new LSA into database */
@@ -615,7 +589,13 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
/* Send newer local copy back to neighbor */
/* FIXME - check for MinLSArrival ? */
ospf_send_lsupd(p, &en, 1, n);
+
+ continue;
}
+
+ skip:
+ LOG_LSA1("Bad LSA (Type: %04x, Id: %R, Rt: %R) in LSUPD", lsa_type, lsa.id, lsa.rt);
+ LOG_LSA2(" received from nbr %R on %s - %s", n->rid, ifa->ifname, err_dsc);
}
/* Send direct LSACKs */
@@ -630,4 +610,14 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
*/
if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq)
ospf_send_lsreq(p, n);
+
+ return;
+
+drop:
+ LOG_PKT("Bad LSUPD packet from nbr %R on %s - %s (%u)",
+ n->rid, ifa->ifname, err_dsc, err_val);
+
+ // XXXX realy?
+ ospf_neigh_sm(n, INM_SEQMIS);
+ return;
}
diff --git a/proto/ospf/neighbor.c b/proto/ospf/neighbor.c
index ee1e8d0f..c75b1b93 100644
--- a/proto/ospf/neighbor.c
+++ b/proto/ospf/neighbor.c
@@ -10,24 +10,19 @@
#include "ospf.h"
-char *ospf_ns[] = { " down",
- " attempt",
- " init",
- " 2way",
- " exstart",
- "exchange",
- " loading",
- " full"
+
+const char *ospf_ns_names[] = {
+ "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
};
-const char *ospf_inm[] =
- { "hello received", "neighbor start", "2-way received",
- "negotiation done", "exstart done", "bad ls request", "load done",
- "adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor",
- "inactivity timer", "line down"
+const char *ospf_inm_names[] = {
+ "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
+ "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
+ "KillNbr", "InactivityTimer", "LLDown"
};
-static void neigh_chstate(struct ospf_neighbor *n, u8 state);
+
+static int can_do_adj(struct ospf_neighbor *n);
static void neighbor_timer_hook(timer * timer);
static void rxmt_timer_hook(timer * timer);
static void ackd_timer_hook(timer * t);
@@ -113,8 +108,29 @@ ospf_neighbor_new(struct ospf_iface *ifa)
return (n);
}
+static void
+ospf_neigh_down(struct ospf_neighbor *n)
+{
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_proto *p = ifa->oa->po;
+
+ if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
+ {
+ struct nbma_node *nn = find_nbma_node(ifa, n->ip);
+ if (nn)
+ nn->found = 0;
+ }
+
+ s_get(&(n->dbsi));
+ release_lsrtl(p, n);
+ rem_node(NODE n);
+ rfree(n->pool);
+
+ OSPF_TRACE(D_EVENTS, "Neighbor %R on %s removed", n->rid, ifa->ifname);
+}
+
/**
- * neigh_chstate - handles changes related to new or lod state of neighbor
+ * ospf_neigh_chstate - handles changes related to new or lod state of neighbor
* @n: OSPF neighbor
* @state: new state
*
@@ -122,7 +138,7 @@ ospf_neighbor_new(struct ospf_iface *ifa)
* starts rxmt timers, call interface state machine etc.
*/
static void
-neigh_chstate(struct ospf_neighbor *n, u8 state)
+ospf_neigh_chstate(struct ospf_neighbor *n, u8 state)
{
struct ospf_iface *ifa = n->ifa;
struct ospf_proto *p = ifa->oa->po;
@@ -132,16 +148,11 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
if (state == old_state)
return;
- OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from %s to %s",
- n->ip, ospf_ns[old_state], ospf_ns[state]);
+ OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
+ n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
n->state = state;
- if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
- ospf_iface_sm(ifa, ISM_NEICH);
- if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
- ospf_iface_sm(ifa, ISM_NEICH);
-
/* Increase number of partial adjacencies */
if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
p->padj++;
@@ -181,145 +192,12 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
if (state > NEIGHBOR_EXSTART)
n->myimms &= ~DBDES_I;
-}
-static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
-{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
-
-static struct ospf_neighbor *
-elect_bdr(struct ospf_proto *p, list nl)
-{
- struct ospf_neighbor *neigh, *n1, *n2;
- u32 nid;
-
- n1 = NULL;
- n2 = NULL;
- WALK_LIST(neigh, nl) /* First try those decl. themselves */
- {
- nid = neigh_get_id(p, neigh);
-
- if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
- if (neigh->priority > 0) /* Eligible */
- if (neigh->dr != nid) /* And not decl. itself DR */
- {
- if (neigh->bdr == nid) /* Declaring BDR */
- {
- if (n1 != NULL)
- {
- if (neigh->priority > n1->priority)
- n1 = neigh;
- else if (neigh->priority == n1->priority)
- if (neigh->rid > n1->rid)
- n1 = neigh;
- }
- else
- {
- n1 = neigh;
- }
- }
- else /* And NOT declaring BDR */
- {
- if (n2 != NULL)
- {
- if (neigh->priority > n2->priority)
- n2 = neigh;
- else if (neigh->priority == n2->priority)
- if (neigh->rid > n2->rid)
- n2 = neigh;
- }
- else
- {
- n2 = neigh;
- }
- }
- }
- }
- if (n1 == NULL)
- n1 = n2;
-
- return (n1);
-}
-
-static struct ospf_neighbor *
-elect_dr(struct ospf_proto *p, list nl)
-{
- struct ospf_neighbor *neigh, *n;
- u32 nid;
-
- n = NULL;
- WALK_LIST(neigh, nl) /* And now DR */
- {
- nid = neigh_get_id(p, neigh);
-
- if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
- if (neigh->priority > 0) /* Eligible */
- if (neigh->dr == nid) /* And declaring itself DR */
- {
- if (n != NULL)
- {
- if (neigh->priority > n->priority)
- n = neigh;
- else if (neigh->priority == n->priority)
- if (neigh->rid > n->rid)
- n = neigh;
- }
- else
- {
- n = neigh;
- }
- }
- }
-
- return (n);
-}
-
-static int
-can_do_adj(struct ospf_neighbor *n)
-{
- struct ospf_iface *ifa = n->ifa;
- struct ospf_proto *p = ifa->oa->po;
- int i = 0;
-
- switch (ifa->type)
- {
- case OSPF_IT_PTP:
- case OSPF_IT_PTMP:
- case OSPF_IT_VLINK:
- i = 1;
- break;
- case OSPF_IT_BCAST:
- case OSPF_IT_NBMA:
- switch (ifa->state)
- {
- case OSPF_IS_DOWN:
- case OSPF_IS_LOOP:
- bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
- break;
- case OSPF_IS_WAITING:
- DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
- break;
- case OSPF_IS_DROTHER:
- if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
- && (n->state >= NEIGHBOR_2WAY))
- i = 1;
- break;
- case OSPF_IS_PTP:
- case OSPF_IS_BACKUP:
- case OSPF_IS_DR:
- if (n->state >= NEIGHBOR_2WAY)
- i = 1;
- break;
- default:
- bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
- break;
- }
- break;
- default:
- bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
- break;
- }
- DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
- return i;
+ /* Generate NeighborChange event if needed, see RFC 2328 9.2 */
+ if ((state == NEIGHBOR_2WAY) && (old_state < NEIGHBOR_2WAY))
+ ospf_iface_sm(ifa, ISM_NEICH);
+ if ((state < NEIGHBOR_2WAY) && (old_state >= NEIGHBOR_2WAY))
+ ospf_iface_sm(ifa, ISM_NEICH);
}
/**
@@ -339,20 +217,19 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
{
struct ospf_proto *p = n->ifa->oa->po;
- DBG("Neighbor state machine for neighbor %I, event '%s'\n", n->ip,
- ospf_inm[event]);
+ DBG("Neighbor state machine for %R on %s, event %s\n",
+ n->rid, n->ifa->ifname, ospf_inm_names[event]);
switch (event)
{
case INM_START:
- neigh_chstate(n, NEIGHBOR_ATTEMPT);
+ ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
/* NBMA are used different way */
break;
case INM_HELLOREC:
- if ((n->state == NEIGHBOR_DOWN) ||
- (n->state == NEIGHBOR_ATTEMPT))
- neigh_chstate(n, NEIGHBOR_INIT);
+ if (n->state < NEIGHBOR_INIT)
+ ospf_neigh_chstate(n, NEIGHBOR_INIT);
/* Restart inactivity timer */
tm_start(n->inactim, n->ifa->deadint);
@@ -360,15 +237,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
case INM_2WAYREC:
if (n->state < NEIGHBOR_2WAY)
- neigh_chstate(n, NEIGHBOR_2WAY);
+ ospf_neigh_chstate(n, NEIGHBOR_2WAY);
if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
- neigh_chstate(n, NEIGHBOR_EXSTART);
+ ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
break;
case INM_NEGDONE:
if (n->state == NEIGHBOR_EXSTART)
{
- neigh_chstate(n, NEIGHBOR_EXCHANGE);
+ ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
/* Reset DB summary list iterator */
s_get(&(n->dbsi));
@@ -385,11 +262,11 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
break;
case INM_EXDONE:
- neigh_chstate(n, NEIGHBOR_LOADING);
+ ospf_neigh_chstate(n, NEIGHBOR_LOADING);
break;
case INM_LOADDONE:
- neigh_chstate(n, NEIGHBOR_FULL);
+ ospf_neigh_chstate(n, NEIGHBOR_FULL);
break;
case INM_ADJOK:
@@ -399,15 +276,15 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
/* Can In build adjacency? */
if (can_do_adj(n))
{
- neigh_chstate(n, NEIGHBOR_EXSTART);
+ ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
}
break;
default:
if (n->state >= NEIGHBOR_EXSTART)
if (!can_do_adj(n))
{
- reset_lists(p,n);
- neigh_chstate(n, NEIGHBOR_2WAY);
+ reset_lists(p, n);
+ ospf_neigh_chstate(n, NEIGHBOR_2WAY);
}
break;
}
@@ -418,20 +295,21 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
if (n->state >= NEIGHBOR_EXCHANGE)
{
reset_lists(p, n);
- neigh_chstate(n, NEIGHBOR_EXSTART);
+ ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
}
break;
case INM_KILLNBR:
case INM_LLDOWN:
case INM_INACTTIM:
- reset_lists(p, n);
- neigh_chstate(n, NEIGHBOR_DOWN);
+ /* No need for reset_lists() */
+ ospf_neigh_chstate(n, NEIGHBOR_DOWN);
+ ospf_neigh_down(n);
break;
case INM_1WAYREC:
reset_lists(p, n);
- neigh_chstate(n, NEIGHBOR_INIT);
+ ospf_neigh_chstate(n, NEIGHBOR_INIT);
break;
default:
@@ -440,14 +318,156 @@ ospf_neigh_sm(struct ospf_neighbor *n, int event)
}
}
+static int
+can_do_adj(struct ospf_neighbor *n)
+{
+ struct ospf_iface *ifa = n->ifa;
+ struct ospf_proto *p = ifa->oa->po;
+ int i = 0;
+
+ switch (ifa->type)
+ {
+ case OSPF_IT_PTP:
+ case OSPF_IT_PTMP:
+ case OSPF_IT_VLINK:
+ i = 1;
+ break;
+ case OSPF_IT_BCAST:
+ case OSPF_IT_NBMA:
+ switch (ifa->state)
+ {
+ case OSPF_IS_DOWN:
+ case OSPF_IS_LOOP:
+ bug("%s: Iface %s in down state?", p->p.name, ifa->ifname);
+ break;
+ case OSPF_IS_WAITING:
+ DBG("%s: Neighbor? on iface %s\n", p->p.name, ifa->ifname);
+ break;
+ case OSPF_IS_DROTHER:
+ if (((n->rid == ifa->drid) || (n->rid == ifa->bdrid))
+ && (n->state >= NEIGHBOR_2WAY))
+ i = 1;
+ break;
+ case OSPF_IS_PTP:
+ case OSPF_IS_BACKUP:
+ case OSPF_IS_DR:
+ if (n->state >= NEIGHBOR_2WAY)
+ i = 1;
+ break;
+ default:
+ bug("%s: Iface %s in unknown state?", p->p.name, ifa->ifname);
+ break;
+ }
+ break;
+ default:
+ bug("%s: Iface %s is unknown type?", p->p.name, ifa->ifname);
+ break;
+ }
+ DBG("%s: Iface %s can_do_adj=%d\n", p->p.name, ifa->ifname, i);
+ return i;
+}
+
+
+static inline u32 neigh_get_id(struct ospf_proto *p, struct ospf_neighbor *n)
+{ return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
+
+static struct ospf_neighbor *
+elect_bdr(struct ospf_proto *p, list nl)
+{
+ struct ospf_neighbor *neigh, *n1, *n2;
+ u32 nid;
+
+ n1 = NULL;
+ n2 = NULL;
+ WALK_LIST(neigh, nl) /* First try those decl. themselves */
+ {
+ nid = neigh_get_id(p, neigh);
+
+ if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
+ if (neigh->priority > 0) /* Eligible */
+ if (neigh->dr != nid) /* And not decl. itself DR */
+ {
+ if (neigh->bdr == nid) /* Declaring BDR */
+ {
+ if (n1 != NULL)
+ {
+ if (neigh->priority > n1->priority)
+ n1 = neigh;
+ else if (neigh->priority == n1->priority)
+ if (neigh->rid > n1->rid)
+ n1 = neigh;
+ }
+ else
+ {
+ n1 = neigh;
+ }
+ }
+ else /* And NOT declaring BDR */
+ {
+ if (n2 != NULL)
+ {
+ if (neigh->priority > n2->priority)
+ n2 = neigh;
+ else if (neigh->priority == n2->priority)
+ if (neigh->rid > n2->rid)
+ n2 = neigh;
+ }
+ else
+ {
+ n2 = neigh;
+ }
+ }
+ }
+ }
+ if (n1 == NULL)
+ n1 = n2;
+
+ return (n1);
+}
+
+static struct ospf_neighbor *
+elect_dr(struct ospf_proto *p, list nl)
+{
+ struct ospf_neighbor *neigh, *n;
+ u32 nid;
+
+ n = NULL;
+ WALK_LIST(neigh, nl) /* And now DR */
+ {
+ nid = neigh_get_id(p, neigh);
+
+ if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
+ if (neigh->priority > 0) /* Eligible */
+ if (neigh->dr == nid) /* And declaring itself DR */
+ {
+ if (n != NULL)
+ {
+ if (neigh->priority > n->priority)
+ n = neigh;
+ else if (neigh->priority == n->priority)
+ if (neigh->rid > n->rid)
+ n = neigh;
+ }
+ else
+ {
+ n = neigh;
+ }
+ }
+ }
+
+ return (n);
+}
+
/**
* ospf_dr_election - (Backup) Designed Router election
* @ifa: actual interface
*
* When the wait timer fires, it is time to elect (Backup) Designated Router.
- * Structure describing me is added to this list so every electing router
- * has the same list. Backup Designated Router is elected before Designated
- * Router. This process is described in 9.4 of RFC 2328.
+ * Structure describing me is added to this list so every electing router has
+ * the same list. Backup Designated Router is elected before Designated
+ * Router. This process is described in 9.4 of RFC 2328. The function is
+ * supposed to be called only from ospf_iface_sm() as a part of the interface
+ * state machine.
*/
void
ospf_dr_election(struct ospf_iface *ifa)
@@ -506,6 +526,7 @@ ospf_dr_election(struct ospf_iface *ifa)
DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
+ /* We are part of the interface state machine */
if (ifa->drid == myid)
ospf_iface_chstate(ifa, OSPF_IS_DR);
else if (ifa->bdrid == myid)
@@ -544,39 +565,15 @@ find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
return NULL;
}
-/* Neighbor is inactive for a long time. Remove it. */
static void
neighbor_timer_hook(timer * timer)
{
struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
- struct ospf_iface *ifa = n->ifa;
- struct ospf_proto *p = ifa->oa->po;
-
- OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I",
- ifa->ifname, n->ip);
- ospf_neigh_remove(n);
-}
-
-void
-ospf_neigh_remove(struct ospf_neighbor *n)
-{
- struct ospf_iface *ifa = n->ifa;
- struct ospf_proto *p = ifa->oa->po;
-
- if ((ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
- {
- struct nbma_node *nn = find_nbma_node(ifa, n->ip);
- if (nn)
- nn->found = 0;
- }
-
- neigh_chstate(n, NEIGHBOR_DOWN);
+ struct ospf_proto *p = n->ifa->oa->po;
- s_get(&(n->dbsi));
- release_lsrtl(p, n);
- rem_node(NODE n);
- rfree(n->pool);
- OSPF_TRACE(D_EVENTS, "Deleting neigbor %R", n->rid);
+ OSPF_TRACE(D_EVENTS, "Inactivity timer expired for neighbor %R on %s",
+ n->rid, n->ifa->ifname);
+ ospf_neigh_sm(n, INM_INACTTIM);
}
static void
@@ -587,8 +584,9 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
if (req->down)
{
- OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s", n->ip, n->ifa->ifname);
- ospf_neigh_remove(n);
+ OSPF_TRACE(D_EVENTS, "BFD session down for neighbor %R on %s",
+ n->rid, n->ifa->ifname);
+ ospf_neigh_sm(n, INM_INACTTIM);
}
}
@@ -611,7 +609,7 @@ void
ospf_sh_neigh_info(struct ospf_neighbor *n)
{
struct ospf_iface *ifa = n->ifa;
- char *pos = "other";
+ char *pos = "ptp ";
char etime[6];
int exp, sec, min;
@@ -627,16 +625,18 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
bsprintf(etime, "%02u:%02u", min, sec);
}
- if (n->rid == ifa->drid)
- pos = "dr ";
- else if (n->rid == ifa->bdrid)
- pos = "bdr ";
- else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) ||
- (n->ifa->type == OSPF_IT_VLINK))
- pos = "ptp ";
+ if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
+ {
+ if (n->rid == ifa->drid)
+ pos = "dr ";
+ else if (n->rid == ifa->bdrid)
+ pos = "bdr ";
+ else
+ pos = "other";
+ }
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority,
- ospf_ns[n->state], pos, etime, ifa->ifname, n->ip);
+ ospf_ns_names[n->state], pos, etime, ifa->ifname, n->ip);
}
static void
@@ -645,18 +645,18 @@ rxmt_timer_hook(timer *t)
struct ospf_neighbor *n = t->data;
struct ospf_proto *p = n->ifa->oa->po;
- DBG("%s: RXMT timer fired on interface %s for neigh %I\n",
+ DBG("%s: RXMT timer fired on %s for neigh %I\n",
p->p.name, n->ifa->ifname, n->ip);
switch (n->state)
{
case NEIGHBOR_EXSTART:
- ospf_send_dbdes(p, n, 1);
+ ospf_send_dbdes(p, n);
return;
case NEIGHBOR_EXCHANGE:
- if (n->myimms & DBDES_MS)
- ospf_send_dbdes(p, n, 0);
+ if (n->myimms & DBDES_MS)
+ ospf_rxmt_dbdes(p, n);
case NEIGHBOR_LOADING:
ospf_send_lsreq(p, n);
return;
@@ -666,9 +666,6 @@ rxmt_timer_hook(timer *t)
if (!EMPTY_SLIST(n->lsrtl))
ospf_rxmt_lsupd(p, n);
return;
-
- default:
- return;
}
}
@@ -678,7 +675,7 @@ ackd_timer_hook(timer *t)
struct ospf_neighbor *n = t->data;
struct ospf_proto *p = n->ifa->oa->po;
- DBG("%s: ACKD timer fired on interface %s for neigh %I\n",
+ DBG("%s: ACKD timer fired on %s for neigh %I\n",
p->p.name, n->ifa->ifname, n->ip);
ospf_send_lsack(p, n, ACKL_DELAY);
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index 470a8633..01e53922 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -252,6 +252,9 @@ ospf_start(struct proto *P)
p->gr = ospf_top_new(p, P->pool);
s_init_list(&(p->lsal));
+ p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
+ p->log_lsa_tbf = (struct tbf){ .rate = 4, .burst = 20 };
+
WALK_LIST(ac, c->area_list)
ospf_area_add(p, ac);
@@ -742,7 +745,7 @@ ospf_sh(struct proto *P)
}
cli_msg(-1014, "%s:", p->p.name);
- cli_msg(-1014, "RFC1583 compatibility: %s", (p->rfc1583 ? "enable" : "disabled"));
+ cli_msg(-1014, "RFC1583 compatibility: %s", (p->rfc1583 ? "enabled" : "disabled"));
cli_msg(-1014, "Stub router: %s", (p->stub_router ? "Yes" : "No"));
cli_msg(-1014, "RT scheduler tick: %d", p->tick);
cli_msg(-1014, "Number of areas: %u", p->areano);
diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h
index f464a3ed..6df5df08 100644
--- a/proto/ospf/ospf.h
+++ b/proto/ospf/ospf.h
@@ -73,12 +73,28 @@
// FIXME: MAX_PREFIX_LENGTH
#define OSPF_TRACE(flags, msg, args...) \
-do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \
- log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0)
+ do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \
+ log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0)
#define OSPF_PACKET(dumpfn, buffer, msg, args...) \
-do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
- { log(L_TRACE "%s: " msg, p->p.name, ## args ); dumpfn(p, buffer); } } while(0)
+ do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
+ { log(L_TRACE "%s: " msg, p->p.name, ## args ); dumpfn(p, buffer); } } while(0)
+
+#define LOG_PKT(msg, args...) \
+ log_rl(&p->log_pkt_tbf, L_REMOTE "%s: " msg, p->p.name, args)
+
+#define LOG_PKT_AUTH(msg, args...) \
+ log_rl(&p->log_pkt_tbf, L_AUTH "%s: " msg, p->p.name, args)
+
+#define LOG_PKT_WARN(msg, args...) \
+ log_rl(&p->log_pkt_tbf, L_WARN "%s: " msg, p->p.name, args)
+
+#define LOG_LSA1(msg, args...) \
+ log_rl(&p->log_lsa_tbf, L_REMOTE "%s: " msg, p->p.name, args)
+
+#define LOG_LSA2(msg, args...) \
+ do { if (! p->log_lsa_tbf.mark) \
+ log(L_REMOTE "%s: " msg, p->p.name, args); } while(0)
#define OSPF_PROTO 89
@@ -248,6 +264,8 @@ struct ospf_proto
sock *vlink_sk; /* IP socket used for vlink TX */
u32 router_id;
u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */
+ struct tbf log_pkt_tbf; /* TBF for packet messages */
+ struct tbf log_lsa_tbf; /* TBF for LSA messages */
};
struct ospf_area
@@ -283,7 +301,7 @@ struct ospf_iface
pool *pool;
sock *sk; /* IP socket */
- list neigh_list; /* List of neigbours (struct ospf_neighbor) */
+ list neigh_list; /* List of neighbors (struct ospf_neighbor) */
u32 cost; /* Cost of iface */
u32 waitint; /* number of sec before changing state from wait */
u32 rxmtint; /* number of seconds between LSA retransmissions */
@@ -368,8 +386,8 @@ struct ospf_neighbor
/* 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 dr; /* Neighbor's idea of DR */
+ u32 bdr; /* Neighbor's idea of BDR */
u32 iface_id; /* ID of Neighbour's iface connected to common network */
/* Database summary list iterator, controls initial dbdes exchange.
@@ -890,7 +908,6 @@ void ospf_neigh_sm(struct ospf_neighbor *n, int event);
void ospf_dr_election(struct ospf_iface *ifa);
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid);
struct ospf_neighbor *find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip);
-void ospf_neigh_remove(struct ospf_neighbor *n);
void ospf_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd);
void ospf_sh_neigh_info(struct ospf_neighbor *n);
@@ -916,6 +933,10 @@ static inline void ospf_send_to_des(struct ospf_iface *ifa)
ospf_send_to_bdr(ifa);
}
+#define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
+#define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0)
+#define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0)
+
static inline uint ospf_pkt_hdrlen(struct ospf_proto *p)
{ return ospf_is_v2(p) ? (sizeof(struct ospf_packet) + sizeof(union ospf_auth)) : sizeof(struct ospf_packet); }
@@ -931,7 +952,8 @@ void ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dir
void ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr);
/* dbdes.c */
-void ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n, int next);
+void ospf_send_dbdes(struct ospf_proto *p, struct ospf_neighbor *n);
+void ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n);
void ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n);
/* lsreq.c */
diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c
index d64d7d6b..2814712d 100644
--- a/proto/ospf/packet.c
+++ b/proto/ospf/packet.c
@@ -66,7 +66,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
log(L_ERR "No suitable password found for authentication");
return;
}
- password_cpy(auth->password, passwd->password, sizeof(union ospf_auth));
+ strncpy(auth->password, passwd->password, sizeof(auth->password));
case OSPF_AUTH_NONE:
{
@@ -106,7 +106,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
void *tail = ((void *) pkt) + plen;
char password[OSPF_AUTH_CRYPT_SIZE];
- password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
+ strncpy(password, passwd->password, sizeof(password));
struct MD5Context ctxt;
MD5Init(&ctxt);
@@ -120,23 +120,22 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
}
}
+
/* 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)
+ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int len)
{
struct ospf_proto *p = ifa->oa->po;
union ospf_auth *auth = (void *) (pkt + 1);
- struct password_item *pass = NULL, *ptmp;
- char password[OSPF_AUTH_CRYPT_SIZE];
+ struct password_item *pass = NULL;
+ const char *err_dsc = NULL;
+ uint err_val = 0;
uint plen = ntohs(pkt->length);
u8 autype = pkt->autype;
if (autype != ifa->autype)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype);
- return 0;
- }
+ DROP("authentication method mismatch", autype);
switch (autype)
{
@@ -146,85 +145,65 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
case OSPF_AUTH_SIMPLE:
pass = password_find(ifa->passwords, 1);
if (!pass)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found");
- return 0;
- }
+ DROP1("no password found");
+
+ if (!password_verify(pass, auth->password, sizeof(auth->password)))
+ DROP("wrong password", pass->id);
- password_cpy(password, pass->password, sizeof(union ospf_auth));
- if (memcmp(auth->password, password, sizeof(union ospf_auth)))
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords");
- return 0;
- }
return 1;
case OSPF_AUTH_CRYPT:
if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
- return 0;
- }
-
- if (plen + OSPF_AUTH_CRYPT_SIZE > size)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
- plen + OSPF_AUTH_CRYPT_SIZE, size);
- return 0;
- }
-
- 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;
- }
+ DROP("invalid MD5 digest length", auth->md5.len);
- n->csn = rcv_csn;
- }
+ if (plen + OSPF_AUTH_CRYPT_SIZE > len)
+ DROP("length mismatch", len);
- if (ifa->passwords)
+ u32 rcv_csn = ntohl(auth->md5.csn);
+ if (n && (rcv_csn < n->csn))
+ // DROP("lower sequence number", rcv_csn);
{
- WALK_LIST(ptmp, *(ifa->passwords))
- {
- if (auth->md5.keyid != ptmp->id) continue;
- if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
- pass = ptmp;
- break;
- }
+ /* We want to report both new and old CSN */
+ LOG_PKT_AUTH("Authentication failed for nbr %R on %s - "
+ "lower sequence number (rcv %u, old %u)",
+ n->rid, ifa->ifname, rcv_csn, n->csn);
+ return 0;
}
+ pass = password_find_by_id(ifa->passwords, auth->md5.keyid);
if (!pass)
- {
- OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found");
- return 0;
- }
+ DROP("no suitable password found", auth->md5.keyid);
void *tail = ((void *) pkt) + plen;
+ char passwd[OSPF_AUTH_CRYPT_SIZE];
char md5sum[OSPF_AUTH_CRYPT_SIZE];
- password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
+
+ strncpy(passwd, pass->password, OSPF_AUTH_CRYPT_SIZE);
struct MD5Context ctxt;
MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, plen);
- MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
+ MD5Update(&ctxt, passwd, 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;
- }
+ DROP("wrong MD5 digest", pass->id);
+
+ if (n)
+ n->csn = rcv_csn;
+
return 1;
default:
- OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
- return 0;
+ bug("Unknown authentication type");
}
-}
+drop:
+ LOG_PKT_AUTH("Authentication failed for nbr %R on %s - %s (%u)",
+ (n ? n->rid : ntohl(pkt->routerid)), ifa->ifname, err_dsc, err_val);
+
+ return 0;
+}
/**
* ospf_rx_hook
@@ -236,13 +215,10 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
* non generic functions.
*/
int
-ospf_rx_hook(sock *sk, int size)
+ospf_rx_hook(sock *sk, int len)
{
- char *mesg = "OSPF: Bad packet from ";
-
- /* We want just packets from sk->iface. Unfortunately, on BSD we
- cannot filter out other packets at kernel level and we receive
- all packets on all sockets */
+ /* We want just packets from sk->iface. Unfortunately, on BSD we cannot filter
+ out other packets at kernel level and we receive all packets on all sockets */
if (sk->lifindex != sk->iface->index)
return 1;
@@ -252,6 +228,8 @@ ospf_rx_hook(sock *sk, int size)
/* Initially, the packet is associated with the 'master' iface */
struct ospf_iface *ifa = sk->data;
struct ospf_proto *p = ifa->oa->po;
+ const char *err_dsc = NULL;
+ uint err_val = 0;
int src_local, dst_local, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
@@ -282,41 +260,31 @@ ospf_rx_hook(sock *sk, int size)
* 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);
+ LOG_PKT_WARN("Multicast packet received from not-link-local %I via %s",
+ sk->faddr, ifa->ifname);
}
- /* Second, we check packet size, checksum, and the protocol version */
- struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
+ /* Second, we check packet length, checksum, and the protocol version */
+ struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &len);
if (pkt == NULL)
- {
- log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
- return 1;
- }
+ DROP("bad IP header", len);
if (ifa->check_ttl && (sk->rcv_ttl < 255))
- {
- log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
- return 1;
- }
+ DROP("wrong TTL", sk->rcv_ttl);
- if ((uint) size < sizeof(struct ospf_packet))
- {
- log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
- return 1;
- }
+ if (len < sizeof(struct ospf_packet))
+ DROP("too short", len);
+
+ if (pkt->version != ospf_get_version(p))
+ DROP("version mismatch", pkt->version);
uint plen = ntohs(pkt->length);
if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
- {
- log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
- return 1;
- }
+ DROP("invalid length", plen);
if (sk->flags & SKF_TRUNCATED)
{
- log(L_WARN "%s%I - too large (%d/%d)", mesg, sk->faddr, plen, size);
-
/* If we have dynamic buffers and received truncated message, we expand RX buffer */
uint bs = plen + 256;
@@ -325,20 +293,11 @@ ospf_rx_hook(sock *sk, int size)
if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
sk_set_rbsize(sk, bs);
- return 1;
+ DROP("truncated", plen);
}
- if (plen > size)
- {
- log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
- return 1;
- }
-
- if (pkt->version != ospf_get_version(p))
- {
- log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
- return 1;
- }
+ if (plen > len)
+ DROP("length mismatch", plen);
if (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT))
{
@@ -346,11 +305,8 @@ ospf_rx_hook(sock *sk, int size)
uint 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;
- }
+ if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
+ DROP1("invalid checksum");
}
/* Third, we resolve associated iface and handle vlinks. */
@@ -368,10 +324,7 @@ ospf_rx_hook(sock *sk, int size)
/* It is real iface, source should be local (in OSPFv2) */
if (ospf_is_v2(p) && !src_local)
- {
- log(L_ERR "%s%I - strange source address for %s", mesg, sk->faddr, ifa->ifname);
- return 1;
- }
+ DROP1("strange source address");
goto found;
}
@@ -415,13 +368,11 @@ ospf_rx_hook(sock *sk, int size)
if (instance_id != ifa->instance_id)
return 1;
- log(L_ERR "%s%I - area does not match (%R vs %R)",
- mesg, sk->faddr, areaid, ifa->oa->areaid);
- return 1;
+ DROP("area mismatch", areaid);
}
- found:
+found:
if (ifa->stub) /* This shouldn't happen */
return 1;
@@ -429,18 +380,12 @@ ospf_rx_hook(sock *sk, int size)
return 1;
if (rid == p->router_id)
- {
- log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
- return 1;
- }
+ DROP1("my own router ID");
if (rid == 0)
- {
- log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr);
- return 1;
- }
+ DROP1("zero router ID");
- /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
+ /* In OSPFv2, neighbors are identified by either IP or Router ID, based on network type */
uint t = ifa->type;
struct ospf_neighbor *n;
if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
@@ -450,16 +395,15 @@ ospf_rx_hook(sock *sk, int size)
if (!n && (pkt->type != HELLO_P))
{
- log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
- sk->faddr, ifa->ifname);
+ // XXXX format
+ OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown neighbor %R on %s (%I)",
+ rid, ifa->ifname, sk->faddr);
return 1;
}
- if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, size))
- {
- log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
+ /* ospf_pkt_checkauth() has its own error logging */
+ if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
return 1;
- }
switch (pkt->type)
{
@@ -484,10 +428,15 @@ ospf_rx_hook(sock *sk, int size)
break;
default:
- log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type);
- return 1;
+ DROP("invalid packet type", pkt->type);
};
return 1;
+
+drop:
+ LOG_PKT("Bad packet from %I via %s - %s (%u)",
+ sk->faddr, ifa->ifname, err_dsc, err_val);
+
+ return 1;
}
/*
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index 16453b87..08f90b49 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -1204,7 +1204,7 @@ ospf_check_vlinks(struct ospf_proto *p)
|| (ifa->vifa != nhi)
|| !ipa_equal(ifa->vip, tmp->lb))
{
- OSPF_TRACE(D_EVENTS, "Vlink peer %R found", tmp->lsa.id);
+ OSPF_TRACE(D_EVENTS, "Vlink peer %R found", ifa->vid);
ospf_iface_sm(ifa, ISM_DOWN);
ifa->vifa = nhi;
ifa->addr = nhi->addr;
@@ -1831,7 +1831,7 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
bad:
/* Probably bug or some race condition, we log it */
- log(L_ERR "Unexpected case in next hop calculation");
+ log(L_ERR "%s: Unexpected case in next hop calculation", p->p.name);
return NULL;
}
@@ -1875,8 +1875,8 @@ add_cand(list * l, struct top_hash_entry *en, struct top_hash_entry *par,
struct mpnh *nhs = calc_next_hop(oa, en, par, pos);
if (!nhs)
{
- log(L_WARN "Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
- en->lsa_type, en->lsa.id, en->lsa.rt);
+ log(L_WARN "%s: Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
+ p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
return;
}
diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c
index 4e3da0de..15ba013a 100644
--- a/proto/ospf/topology.c
+++ b/proto/ospf/topology.c
@@ -758,7 +758,7 @@ prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
break;
default:
- log("Unknown interface type %s", ifa->ifname);
+ log(L_BUG "OSPF: Unknown interface type");
break;
}
@@ -855,7 +855,7 @@ prepare_rt3_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
break;
default:
- log("Unknown interface type %s", ifa->ifname);
+ log(L_BUG "OSPF: Unknown interface type");
break;
}