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

Refactoring of OSPF messages.

This commit is contained in:
Ondrej Zajicek 2014-10-24 10:27:21 +02:00
parent 78342404ff
commit f8fefde318
15 changed files with 606 additions and 671 deletions

View File

@ -36,9 +36,18 @@ password_find(list *l, int first_fit)
return pf; return pf;
} }
void password_cpy(char *dst, char *src, int size) struct password_item *
password_find_by_id(list *l, int id)
{ {
bzero(dst, size); struct password_item *pi;
memcpy(dst, src, (strlen(src) < (unsigned) size ? strlen(src) : (unsigned) size));
if (!l)
return NULL;
WALK_LIST(pi, *l)
if ((pi->id == id) && (pi->accfrom <= now_real) && (now_real < pi->accto))
return pi;
return NULL;
} }

View File

@ -23,6 +23,13 @@ struct password_item {
extern struct password_item *last_password_item; extern struct password_item *last_password_item;
struct password_item *password_find(list *l, int first_fit); struct password_item *password_find(list *l, int first_fit);
void password_cpy(char *dst, char *src, int size); struct password_item *password_find_by_id(list *l, int id);
static inline int password_verify(struct password_item *p1, char *p2, uint size)
{
char buf[size];
strncpy(buf, p1->password, size);
return !memcmp(buf, p2, size);
}
#endif #endif

View File

@ -98,7 +98,7 @@ ospf_dump_dbdes(struct ospf_proto *p, struct ospf_packet *pkt)
static void 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_iface *ifa = n->ifa;
struct ospf_packet *pkt; 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; u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
/* Update DBDES buffer */
if (n->ldd_bsize != ifa->tx_length) if (n->ldd_bsize != ifa->tx_length)
{ {
mb_free(n->ldd_buffer); 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); 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 ospf_lsa_header *lsas;
struct top_hash_entry *en; 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; struct ospf_iface *ifa = n->ifa;
OSPF_PACKET(ospf_dump_dbdes, n->ldd_buffer, 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); sk_set_tbuf(ifa->sk, n->ldd_buffer);
ospf_send_to(ifa, n->ip); ospf_send_to(ifa, n->ip);
sk_set_tbuf(ifa->sk, NULL); 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 * ospf_send_dbdes - transmit database description packet
* @n: neighbor * @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. * 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. * 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. * of the buffer.
*/ */
void 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 */ /* RFC 2328 10.8 */
ASSERT((n->state == NEIGHBOR_EXSTART) || (n->state == NEIGHBOR_EXCHANGE));
if (n->ifa->oa->rt == NULL) if (n->ifa->oa->rt == NULL)
return; return;
switch (n->state) ospf_prepare_dbdes(p, n);
{ ospf_do_send_dbdes(p, n);
case NEIGHBOR_EXSTART:
n->myimms |= DBDES_I;
/* Send empty packets */ if (n->state == NEIGHBOR_EXSTART)
ospf_prepare_dbdes(p, n, 0); return;
ospf_do_send_dbdes(p, n);
break;
case NEIGHBOR_EXCHANGE: /* Master should restart RXMT timer for each DBDES exchange */
n->myimms &= ~DBDES_I; if (n->myimms & DBDES_MS)
tm_start(n->rxmt_timer, n->ifa->rxmtint);
if (next) if (!(n->myimms & DBDES_MS))
ospf_prepare_dbdes(p, n, 1); if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
ospf_neigh_sm(n, INM_EXDONE);
/* Send prepared packet */
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->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:
if (!n->ldd_buffer)
{
OSPF_TRACE(D_PACKETS, "No DBDES packet for repeating");
ospf_neigh_sm(n, INM_KILLNBR);
return;
}
/* Send last packet */
ospf_do_send_dbdes(p, n);
break;
}
} }
void
ospf_rxmt_dbdes(struct ospf_proto *p, struct ospf_neighbor *n)
{
ASSERT(n->state > NEIGHBOR_EXSTART);
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 static int
ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n) ospf_process_dbdes(struct ospf_proto *p, struct ospf_packet *pkt, struct ospf_neighbor *n)
{ {
struct ospf_iface *ifa = n->ifa; 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; uint i, lsa_count;
ospf_dbdes_body(p, pkt, &lsas, &lsa_count); ospf_dbdes_body(p, pkt, &lsas, &lsa_count);
for (i = 0; i < lsa_count; i++) 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_ntoh_hdr(lsas + i, &lsa);
lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain); lsa_get_type_domain(&lsa, ifa, &lsa_type, &lsa_domain);
/* RFC 2328 10.6 and RFC 5340 4.2.2 */ /* RFC 2328 10.6 and RFC 5340 4.2.2 */
if (!lsa_type) if (!lsa_type)
{ DROP1("LSA of unknown type");
log(L_WARN "%s: Bad DBDES from %I - LSA of unknown type", p->p.name, n->ip);
goto err;
}
if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
{ DROP1("LSA with AS scope in stub area");
log(L_WARN "%s: Bad DBDES from %I - LSA with AS scope in stub area", p->p.name, n->ip);
goto err;
}
/* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
{ DROP1("rt-summary-LSA in stub area");
log(L_WARN "%s: Bad DBDES from %I - rt-summary-LSA in stub area", p->p.name, n->ip);
goto err;
}
/* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */ /* Not explicitly mentioned in RFC 5340 4.2.2 but makes sense */
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
{ DROP1("LSA with invalid scope");
log(L_WARN "%s: Bad DBDES from %I - LSA with invalid scope", p->p.name, n->ip);
goto err;
}
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER)) 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; 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); ospf_neigh_sm(n, INM_SEQMIS);
return -1; return -1;
} }
@ -324,21 +302,19 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
struct ospf_neighbor *n) struct ospf_neighbor *n)
{ {
struct ospf_proto *p = ifa->oa->po; struct ospf_proto *p = ifa->oa->po;
const char *err_dsc = NULL;
u32 rcv_ddseq, rcv_options; u32 rcv_ddseq, rcv_options;
u16 rcv_iface_mtu; u16 rcv_iface_mtu;
u8 rcv_imms; u8 rcv_imms;
uint plen; uint plen, err_val = 0, err_seqmis = 0;
/* RFC 2328 10.6 */ /* RFC 2328 10.6 */
plen = ntohs(pkt->length); plen = ntohs(pkt->length);
if (plen < ospf_dbdes_hdrlen(p)) if (plen < ospf_dbdes_hdrlen(p))
{ DROP("too short", plen);
log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen);
return;
}
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); 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_DOWN:
case NEIGHBOR_ATTEMPT: case NEIGHBOR_ATTEMPT:
case NEIGHBOR_2WAY: case NEIGHBOR_2WAY:
OSPF_TRACE(D_PACKETS, "DBDES packet ignored - lesser state than ExStart");
return; return;
case NEIGHBOR_INIT: 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 != ifa->iface->mtu) &&
(rcv_iface_mtu != 0) && (rcv_iface_mtu != 0) &&
(ifa->iface->mtu != 0)) (ifa->iface->mtu != 0))
log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)", LOG_PKT_WARN("MTU mismatch with nbr %R on %s (remote %d, local %d)",
n->ip, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu); n->rid, ifa->ifname, rcv_iface_mtu, ifa->iface->mtu);
if ((rcv_imms == DBDES_IMMS) && if ((rcv_imms == DBDES_IMMS) &&
(n->rid > p->router_id) && (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->options = rcv_options;
n->myimms &= ~DBDES_MS; n->myimms &= ~DBDES_MS;
n->imms = rcv_imms; n->imms = rcv_imms;
OSPF_TRACE(D_PACKETS, "I'm slave to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE); ospf_neigh_sm(n, INM_NEGDONE);
ospf_send_dbdes(p, n, 1); ospf_send_dbdes(p, n);
break; break;
} }
@ -404,7 +380,6 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
n->options = rcv_options; n->options = rcv_options;
n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */ n->ddr = rcv_ddseq - 1; /* It will be set corectly a few lines down */
n->imms = rcv_imms; n->imms = rcv_imms;
OSPF_TRACE(D_PACKETS, "I'm master to %I", n->ip);
ospf_neigh_sm(n, INM_NEGDONE); ospf_neigh_sm(n, INM_NEGDONE);
} }
else else
@ -417,49 +392,29 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if ((rcv_imms == n->imms) && if ((rcv_imms == n->imms) &&
(rcv_options == n->options) && (rcv_options == n->options) &&
(rcv_ddseq == n->ddr)) (rcv_ddseq == n->ddr))
{ goto duplicate;
/* 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;
}
if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS)) /* M/S bit differs */ /* Do INM_SEQMIS during packet error */
{ err_seqmis = 1;
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit MS)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
if (rcv_imms & DBDES_I) /* I bit is set */ if ((rcv_imms & DBDES_MS) != (n->imms & DBDES_MS))
{ DROP("MS-bit mismatch", rcv_imms);
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (bit I)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS);
break;
}
if (rcv_options != n->options) /* Options differs */ if (rcv_imms & DBDES_I)
{ DROP("I-bit mismatch", rcv_imms);
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (options)", n->ip);
ospf_neigh_sm(n, INM_SEQMIS); if (rcv_options != n->options)
break; DROP("options mismatch", rcv_options);
}
n->ddr = rcv_ddseq; n->ddr = rcv_ddseq;
n->imms = rcv_imms; n->imms = rcv_imms;
if (n->myimms & DBDES_MS) if (n->myimms & DBDES_MS)
{ {
if (rcv_ddseq != n->dds) /* MASTER */ /* MASTER */
{
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (master)", n->ip); if (rcv_ddseq != n->dds)
ospf_neigh_sm(n, INM_SEQMIS); DROP("DD sequence number mismatch", rcv_ddseq);
break;
}
n->dds++; 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)) if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
ospf_neigh_sm(n, INM_EXDONE); ospf_neigh_sm(n, INM_EXDONE);
else else
ospf_send_dbdes(p, n, 1); ospf_send_dbdes(p, n);
} }
else else
{ {
if (rcv_ddseq != (n->dds + 1)) /* SLAVE */ /* SLAVE */
{
OSPF_TRACE(D_PACKETS, "dbdes - sequence mismatch neighbor %I (slave)", n->ip); if (rcv_ddseq != (n->dds + 1))
ospf_neigh_sm(n, INM_SEQMIS); DROP("DD sequence number mismatch", rcv_ddseq);
break;
}
n->ddr = rcv_ddseq; n->ddr = rcv_ddseq;
n->dds = 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) if (ospf_process_dbdes(p, pkt, n) < 0)
return; return;
ospf_send_dbdes(p, n, 1); ospf_send_dbdes(p, n);
} }
break; break;
@ -495,25 +448,30 @@ ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa,
if ((rcv_imms == n->imms) && if ((rcv_imms == n->imms) &&
(rcv_options == n->options) && (rcv_options == n->options) &&
(rcv_ddseq == n->ddr)) (rcv_ddseq == n->ddr))
{ goto duplicate;
/* Duplicate packet */
OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip); err_seqmis = 1;
if (!(n->myimms & DBDES_MS))
{ DROP("too late for DD exchange", n->state);
/* 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;
default: 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;
} }

View File

@ -114,7 +114,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
{ {
if (i == max) 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; break;
} }
neighbors[i] = htonl(neigh->rid); 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_neighbor *n, ip_addr faddr)
{ {
struct ospf_proto *p = ifa->oa->po; 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; u32 rcv_iface_id, rcv_helloint, rcv_deadint, rcv_dr, rcv_bdr;
u8 rcv_options, rcv_priority; u8 rcv_options, rcv_priority;
u32 *neighbors; u32 *neighbors;
u32 neigh_count; u32 neigh_count;
uint plen, i; uint plen, i, err_val = 0;
/* RFC 2328 10.5 */ /* 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); 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; struct ospf_hello2_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello2_packet)) if (plen < sizeof(struct ospf_hello2_packet))
{ DROP("too short", plen);
log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen);
return;
}
rcv_iface_id = 0; rcv_iface_id = 0;
rcv_helloint = ntohs(ps->helloint); 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) && if ((ifa->type != OSPF_IT_VLINK) &&
(ifa->type != OSPF_IT_PTP) && (ifa->type != OSPF_IT_PTP) &&
(pxlen != ifa->addr->pxlen)) (pxlen != ifa->addr->pxlen))
{ DROP("prefix length mismatch", pxlen);
log(L_ERR "%s%I - prefix length mismatch (%d)", beg, faddr, pxlen);
return;
}
neighbors = ps->neighbors; neighbors = ps->neighbors;
neigh_count = (plen - sizeof(struct ospf_hello2_packet)) / sizeof(u32); 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; struct ospf_hello3_packet *ps = (void *) pkt;
if (plen < sizeof(struct ospf_hello3_packet)) if (plen < sizeof(struct ospf_hello3_packet))
{ DROP("too short", plen);
log(L_ERR "%s%I - too short (%u B)", beg, faddr, plen);
return;
}
rcv_iface_id = ntohl(ps->iface_id); rcv_iface_id = ntohl(ps->iface_id);
rcv_helloint = ntohs(ps->helloint); 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) if (rcv_helloint != ifa->helloint)
{ DROP("hello interval mismatch", rcv_helloint);
log(L_ERR "%s%I - hello interval mismatch (%d)", beg, faddr, rcv_helloint);
return;
}
if (rcv_deadint != ifa->deadint) if (rcv_deadint != ifa->deadint)
{ DROP("dead interval mismatch", rcv_deadint);
log(L_ERR "%s%I - dead interval mismatch (%d)", beg, faddr, rcv_deadint);
return;
}
/* Check whether bits E, N match */ /* Check whether bits E, N match */
if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N)) if ((rcv_options ^ ifa->oa->options) & (OPT_E | OPT_N))
{ DROP("area type mismatch", rcv_options);
log(L_ERR "%s%I - area type mismatch (%x)", beg, faddr, rcv_options);
return;
}
/* Check consistency of existing neighbor entry */ /* Check consistency of existing neighbor entry */
if (n) 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))) 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 */ /* 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", OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed Router ID to %R",
n->ip, n->rid, ntohl(pkt->routerid)); n->rid, ifa->ifname, rcv_rid);
ospf_neigh_remove(n); ospf_neigh_sm(n, INM_KILLNBR);
n = NULL; 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 */ /* Neighbor identified by Router ID; IP address may change */
if (!ipa_equal(faddr, n->ip)) 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; 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); struct nbma_node *nn = find_nbma_node(ifa, faddr);
if (!nn && ifa->strictnbma) if (!nn && ifa->strictnbma)
{ DROP1("new neighbor denied");
log(L_WARN "Ignoring new neighbor: %I on %s", faddr, ifa->ifname);
return;
}
if (nn && (ifa->type == OSPF_IT_NBMA) && if (nn && (ifa->type == OSPF_IT_NBMA) &&
(((rcv_priority == 0) && nn->eligible) || (((rcv_priority == 0) && nn->eligible) ||
((rcv_priority > 0) && !nn->eligible))) ((rcv_priority > 0) && !nn->eligible)))
{ DROP("eligibility mismatch", rcv_priority);
log(L_ERR "Eligibility mismatch for neighbor: %I on %s", faddr, ifa->ifname);
return;
}
if (nn) if (nn)
nn->found = 1; 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); OSPF_TRACE(D_EVENTS, "New neighbor found: %I on %s", faddr, ifa->ifname);
n = ospf_neighbor_new(ifa); n = ospf_neighbor_new(ifa);
n->rid = ntohl(pkt->routerid); n->rid = rcv_rid;
n->ip = faddr; n->ip = faddr;
n->dr = rcv_dr; n->dr = rcv_dr;
n->bdr = rcv_bdr; 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); ospf_neigh_sm(n, INM_1WAYREC);
return; return;
found_self: found_self:
ospf_neigh_sm(n, INM_2WAYREC); 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))) ((n->bdr != n_id) && (old_bdr == n_id)))
ospf_iface_sm(ifa, ISM_NEICH); 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);
} }

View File

@ -11,15 +11,16 @@
#include "ospf.h" #include "ospf.h"
char *ospf_is[] = { "down", "loop", "waiting", "ptp", "drother", const char *ospf_is_names[] = {
"backup", "dr" "Down", "Loopback", "Waiting", "PtP", "DROther", "Backup", "DR"
}; };
char *ospf_ism[] = { "interface up", "wait timer fired", "backup seen", const char *ospf_ism_names[] = {
"neighbor change", "loop indicated", "unloop indicated", "interface down" "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 static void
@ -40,7 +41,7 @@ wait_timer_hook(timer * timer)
struct ospf_iface *ifa = (struct ospf_iface *) timer->data; struct ospf_iface *ifa = (struct ospf_iface *) timer->data;
struct ospf_proto *p = ifa->oa->po; 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); 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) WALK_LIST_DELSAFE(n, nx, ifa->neigh_list)
{ ospf_neigh_sm(n, INM_KILLNBR);
OSPF_TRACE(D_EVENTS, "Removing neighbor %I", n->ip);
ospf_neigh_remove(n);
}
if (ifa->hello_timer) if (ifa->hello_timer)
tm_stop(ifa->hello_timer); tm_stop(ifa->hello_timer);
@ -311,8 +309,8 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
if (state == oldstate) if (state == oldstate)
return; return;
OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s", OSPF_TRACE(D_EVENTS, "Interface %s changed state from %s to %s",
ifa->ifname, ospf_is[oldstate], ospf_is[state]); ifa->ifname, ospf_is_names[oldstate], ospf_is_names[state]);
ifa->state = state; ifa->state = state;
@ -351,7 +349,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
void void
ospf_iface_sm(struct ospf_iface *ifa, int event) 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) switch (event)
{ {
@ -613,7 +611,8 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
continue; continue;
if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) 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); add_nbma_node(ifa, nb, 0);
} }
@ -726,7 +725,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* HELLO TIMER */ /* HELLO TIMER */
if (ifa->helloint != new->helloint) 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); ifname, ifa->helloint, new->helloint);
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 */ /* RXMT TIMER */
if (ifa->rxmtint != new->rxmtint) 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); ifname, ifa->rxmtint, new->rxmtint);
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 */ /* POLL TIMER */
if (ifa->pollint != new->pollint) 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); ifname, ifa->pollint, new->pollint);
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 */ /* WAIT TIMER */
if (ifa->waitint != new->waitint) 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); ifname, ifa->waitint, new->waitint);
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 */ /* DEAD TIMER */
if (ifa->deadint != new->deadint) 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); ifname, ifa->deadint, new->deadint);
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 */ /* INFTRANS */
if (ifa->inftransdelay != new->inftransdelay) 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); ifname, ifa->inftransdelay, new->inftransdelay);
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 */ /* AUTHENTICATION */
if (ifa->autype != new->autype) 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; ifa->autype = new->autype;
} }
@ -797,7 +796,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* COST */ /* COST */
if (ifa->cost != 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); ifname, ifa->cost, new->cost);
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 */ /* PRIORITY */
if (ifa->priority != 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); ifname, ifa->priority, new->priority);
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 */ /* STRICT NBMA */
if (ifa->strictnbma != new->strictnbma) 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; 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) 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->ip, ifname);
nb->eligible = nb2->eligible; nb->eligible = nb2->eligible;
} }
} }
else 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); nb->ip, ifname);
rem_node(NODE nb); rem_node(NODE nb);
mb_free(nb); mb_free(nb);
@ -852,11 +852,12 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
continue; continue;
if (ospf_is_v3(p) && !ipa_is_link_local(nb->ip)) 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)) 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); nb->ip, ifname);
add_nbma_node(ifa, nb, !!find_neigh_by_ip(ifa, nb->ip)); 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 */ /* TX LENGTH */
if (old->tx_length != 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); ifname, old->tx_length, new->tx_length);
/* ifa cannot be vlink */ /* ifa cannot be vlink */
@ -878,7 +879,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* RX BUFFER */ /* RX BUFFER */
if (old->rx_buffer != 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); ifname, old->rx_buffer, new->rx_buffer);
/* ifa cannot be vlink */ /* ifa cannot be vlink */
@ -896,7 +897,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* LINK */ /* LINK */
if (ifa->check_link != new->check_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); new->check_link ? "Enabling" : "Disabling", ifname);
ifa->check_link = new->check_link; ifa->check_link = new->check_link;
@ -908,7 +909,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* ECMP weight */ /* ECMP weight */
if (ifa->ecmp_weight != 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); ifname, (int)ifa->ecmp_weight + 1, (int)new->ecmp_weight + 1);
ifa->ecmp_weight = new->ecmp_weight; ifa->ecmp_weight = new->ecmp_weight;
} }
@ -927,7 +928,7 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
/* BFD */ /* BFD */
if (ifa->bfd != 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); new->bfd ? "Enabling" : "Disabling", ifname);
ifa->bfd = new->bfd; ifa->bfd = new->bfd;
@ -1197,7 +1198,7 @@ ospf_iface_change_mtu(struct ospf_proto *p, struct ospf_iface *ifa)
{ {
/* ifa is not vlink */ /* 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); 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, "\tType: %s%s", ospf_it[ifa->type], more);
cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid); 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, "\tPriority: %u", ifa->priority);
cli_msg(-1015, "\tCost: %u", ifa->cost); cli_msg(-1015, "\tCost: %u", ifa->cost);
if (ifa->oa->po->ecmp) if (ifa->oa->po->ecmp)

View File

@ -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 */ /* 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) if (n->state < NEIGHBOR_EXCHANGE)
{
OSPF_TRACE(D_PACKETS, "LSACK packet ignored - lesser state than Exchange");
return; return;
}
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */

View File

@ -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); length = ospf_pkt_hdrlen(p) + i * sizeof(struct ospf_lsreq_header);
pkt->length = htons(length); 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); 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 */ /* 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) if (n->state < NEIGHBOR_EXCHANGE)
{
OSPF_TRACE(D_PACKETS, "LSREQ packet ignored - lesser state than Exchange");
return; return;
}
ospf_neigh_sm(n, INM_HELLOREC); /* Not in RFC */ 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); en = ospf_hash_find(p->gr, domain, id, rt, type);
if (!en) if (!en)
{ {
log(L_WARN "%s: Received LSREQ from %I for missing LSA (Type: %04x, Id: %R, Rt: %R)", LOG_LSA1("Bad LSR (Type: %04x, Id: %R, Rt: %R) in LSREQ", type, id, rt);
p->p.name, n->ip, type, id, rt); LOG_LSA2(" received from nbr %R on %s - LSA is missing", n->rid, ifa->ifname);
ospf_neigh_sm(n, INM_BADLSREQ); ospf_neigh_sm(n, INM_BADLSREQ);
return; return;
} }

View File

@ -338,7 +338,7 @@ ospf_send_lsupd(struct ospf_proto *p, struct top_hash_entry **lsa_list, uint lsa
{ i++; continue; } { i++; continue; }
OSPF_PACKET(ospf_dump_lsupd, ospf_tx_buffer(ifa), 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); 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_neighbor *n)
{ {
struct ospf_proto *p = ifa->oa->po; struct ospf_proto *p = ifa->oa->po;
const char *err_dsc = NULL;
/* RFC 2328 13. */ uint plen, err_val = 0;
int skip_lsreq = 0; int skip_lsreq = 0;
n->want_lsreq = 0; n->want_lsreq = 0;
uint plen = ntohs(pkt->length); /* RFC 2328 13. */
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;
}
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->ifname); plen = ntohs(pkt->length);
if (plen < (ospf_lsupd_hdrlen(p) + sizeof(struct ospf_lsa_header)))
DROP("too short", plen);
OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet received from nbr %R on %s", n->rid, ifa->ifname);
if (n->state < NEIGHBOR_EXCHANGE) 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; return;
} }
@ -429,33 +427,18 @@ ospf_receive_lsupd(struct ospf_packet *pkt, struct ospf_iface *ifa,
u32 lsa_len, lsa_type, lsa_domain; u32 lsa_len, lsa_type, lsa_domain;
if (offset > bound) if (offset > bound)
{ DROP("too short", plen);
log(L_WARN "%s: Received LSUPD from %I is too short", p->p.name, n->ip);
ospf_neigh_sm(n, INM_BADLSREQ);
return;
}
/* LSA header in network order */ /* LSA header in network order */
lsa_n = ((void *) pkt) + offset; lsa_n = ((void *) pkt) + offset;
lsa_len = ntohs(lsa_n->length); lsa_len = ntohs(lsa_n->length);
offset += lsa_len; offset += lsa_len;
if ((offset > plen) || ((lsa_len % 4) != 0) || if (offset > plen)
(lsa_len <= sizeof(struct ospf_lsa_header))) DROP("too short", plen);
{
log(L_WARN "%s: Received LSA from %I with bad length", p->p.name, n->ip);
ospf_neigh_sm(n, INM_BADLSREQ);
return;
}
/* RFC 2328 13. (1) - validate LSA checksum */ if (((lsa_len % 4) != 0) || (lsa_len <= sizeof(struct ospf_lsa_header)))
u16 chsum = lsa_n->checksum; DROP("invalid LSA length", lsa_len);
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;
}
/* LSA header in host order */ /* LSA header in host order */
lsa_ntoh_hdr(lsa_n, &lsa); 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", 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); 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) */ /* RFC 2328 13. (2) */
if (!lsa_type) if (!lsa_type)
{ SKIP("unknown type");
log(L_WARN "%s: Received unknown LSA type from %I", p->p.name, n->ip);
continue;
}
/* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */ /* RFC 5340 4.5.1 (2) and RFC 2328 13. (3) */
if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS)) if (!oa_is_ext(ifa->oa) && (LSA_SCOPE(lsa_type) == LSA_SCOPE_AS))
{ SKIP("AS scope in stub area");
log(L_WARN "%s: Received LSA with AS scope in stub area from %I", p->p.name, n->ip);
continue;
}
/* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */ /* Errata 3746 to RFC 2328 - rt-summary-LSAs forbidden in stub areas */
if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT)) if (!oa_is_ext(ifa->oa) && (lsa_type == LSA_T_SUM_RT))
{ SKIP("rt-summary-LSA in stub area");
log(L_WARN "%s: Received rt-summary-LSA in stub area from %I", p->p.name, n->ip);
continue;
}
/* RFC 5340 4.5.1 (3) */ /* RFC 5340 4.5.1 (3) */
if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES) if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
{ SKIP("invalid scope");
log(L_WARN "%s: Received LSA with invalid scope from %I", p->p.name, n->ip);
continue;
}
/* Find local copy of LSA in link state database */ /* Find local copy of LSA in link state database */
en = ospf_hash_find(p->gr, lsa_domain, lsa.id, lsa.rt, lsa_type); 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) 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); mb_free(body);
continue; SKIP("invalid body");
} }
/* 13. (5f) - handle self-originated LSAs, see also 13.4. */ /* 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; 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 * 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 * that send us the new LSA. The old LSA is automatically replaced in
* retransmission lists by the new LSA. * 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(ifi, p->iface_list)
WALK_LIST(ni, ifi->neigh_list) WALK_LIST(ni, ifi->neigh_list)
if (ni->state > NEIGHBOR_EXSTART) if (ni->state > NEIGHBOR_EXSTART)
ospf_lsa_lsrt_down(en, ni); ospf_lsa_lsrt_down(en, ni);
#endif #endif
/* 13. (5d) - install new LSA into database */ /* 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 */ /* Send newer local copy back to neighbor */
/* FIXME - check for MinLSArrival ? */ /* FIXME - check for MinLSArrival ? */
ospf_send_lsupd(p, &en, 1, n); 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 */ /* 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) if ((n->state == NEIGHBOR_LOADING) && n->want_lsreq && !skip_lsreq)
ospf_send_lsreq(p, n); 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;
} }

View File

@ -10,24 +10,19 @@
#include "ospf.h" #include "ospf.h"
char *ospf_ns[] = { " down",
" attempt", const char *ospf_ns_names[] = {
" init", "Down", "Attempt", "Init", "2-Way", "ExStart", "Exchange", "Loading", "Full"
" 2way",
" exstart",
"exchange",
" loading",
" full"
}; };
const char *ospf_inm[] = const char *ospf_inm_names[] = {
{ "hello received", "neighbor start", "2-way received", "HelloReceived", "Start", "2-WayReceived", "NegotiationDone", "ExchangeDone",
"negotiation done", "exstart done", "bad ls request", "load done", "BadLSReq", "LoadingDone", "AdjOK?", "SeqNumberMismatch", "1-WayReceived",
"adjacency ok?", "sequence mismatch", "1-way received", "kill neighbor", "KillNbr", "InactivityTimer", "LLDown"
"inactivity timer", "line down"
}; };
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 neighbor_timer_hook(timer * timer);
static void rxmt_timer_hook(timer * timer); static void rxmt_timer_hook(timer * timer);
static void ackd_timer_hook(timer * t); static void ackd_timer_hook(timer * t);
@ -113,8 +108,29 @@ ospf_neighbor_new(struct ospf_iface *ifa)
return (n); 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 * @n: OSPF neighbor
* @state: new state * @state: new state
* *
@ -122,7 +138,7 @@ ospf_neighbor_new(struct ospf_iface *ifa)
* starts rxmt timers, call interface state machine etc. * starts rxmt timers, call interface state machine etc.
*/ */
static void 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_iface *ifa = n->ifa;
struct ospf_proto *p = ifa->oa->po; struct ospf_proto *p = ifa->oa->po;
@ -132,16 +148,11 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
if (state == old_state) if (state == old_state)
return; return;
OSPF_TRACE(D_EVENTS, "Neighbor %I changes state from %s to %s", OSPF_TRACE(D_EVENTS, "Neighbor %R on %s changed state from %s to %s",
n->ip, ospf_ns[old_state], ospf_ns[state]); n->rid, ifa->ifname, ospf_ns_names[old_state], ospf_ns_names[state]);
n->state = 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 */ /* Increase number of partial adjacencies */
if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING)) if ((state == NEIGHBOR_EXCHANGE) || (state == NEIGHBOR_LOADING))
p->padj++; p->padj++;
@ -181,8 +192,182 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
if (state > NEIGHBOR_EXSTART) if (state > NEIGHBOR_EXSTART)
n->myimms &= ~DBDES_I; n->myimms &= ~DBDES_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);
} }
/**
* ospf_neigh_sm - ospf neighbor state machine
* @n: neighor
* @event: actual event
*
* This part implements the neighbor state machine as described in 10.3 of
* RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
* used. We discover neighbors on nonbroadcast networks in the
* same way as on broadcast networks. The only difference is in
* sending hello packets. These are sent to IPs listed in
* @ospf_iface->nbma_list .
*/
void
ospf_neigh_sm(struct ospf_neighbor *n, int event)
{
struct ospf_proto *p = n->ifa->oa->po;
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:
ospf_neigh_chstate(n, NEIGHBOR_ATTEMPT);
/* NBMA are used different way */
break;
case INM_HELLOREC:
if (n->state < NEIGHBOR_INIT)
ospf_neigh_chstate(n, NEIGHBOR_INIT);
/* Restart inactivity timer */
tm_start(n->inactim, n->ifa->deadint);
break;
case INM_2WAYREC:
if (n->state < NEIGHBOR_2WAY)
ospf_neigh_chstate(n, NEIGHBOR_2WAY);
if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
break;
case INM_NEGDONE:
if (n->state == NEIGHBOR_EXSTART)
{
ospf_neigh_chstate(n, NEIGHBOR_EXCHANGE);
/* Reset DB summary list iterator */
s_get(&(n->dbsi));
s_init(&(n->dbsi), &p->lsal);
/* Add MaxAge LSA entries to retransmission list */
ospf_add_flushed_to_lsrt(p, n);
/* FIXME: Why is this here ? */
ospf_reset_lsack_queue(n);
}
else
bug("NEGDONE and I'm not in EXSTART?");
break;
case INM_EXDONE:
ospf_neigh_chstate(n, NEIGHBOR_LOADING);
break;
case INM_LOADDONE:
ospf_neigh_chstate(n, NEIGHBOR_FULL);
break;
case INM_ADJOK:
switch (n->state)
{
case NEIGHBOR_2WAY:
/* Can In build adjacency? */
if (can_do_adj(n))
{
ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
}
break;
default:
if (n->state >= NEIGHBOR_EXSTART)
if (!can_do_adj(n))
{
reset_lists(p, n);
ospf_neigh_chstate(n, NEIGHBOR_2WAY);
}
break;
}
break;
case INM_SEQMIS:
case INM_BADLSREQ:
if (n->state >= NEIGHBOR_EXCHANGE)
{
reset_lists(p, n);
ospf_neigh_chstate(n, NEIGHBOR_EXSTART);
}
break;
case INM_KILLNBR:
case INM_LLDOWN:
case INM_INACTTIM:
/* No need for reset_lists() */
ospf_neigh_chstate(n, NEIGHBOR_DOWN);
ospf_neigh_down(n);
break;
case INM_1WAYREC:
reset_lists(p, n);
ospf_neigh_chstate(n, NEIGHBOR_INIT);
break;
default:
bug("%s: INM - Unknown event?", p->p.name);
break;
}
}
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) 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; } { return ospf_is_v2(p) ? ipa_to_u32(n->ip) : n->rid; }
@ -273,181 +458,16 @@ elect_dr(struct ospf_proto *p, list nl)
return (n); 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;
}
/**
* ospf_neigh_sm - ospf neighbor state machine
* @n: neighor
* @event: actual event
*
* This part implements the neighbor state machine as described in 10.3 of
* RFC 2328. The only difference is that state %NEIGHBOR_ATTEMPT is not
* used. We discover neighbors on nonbroadcast networks in the
* same way as on broadcast networks. The only difference is in
* sending hello packets. These are sent to IPs listed in
* @ospf_iface->nbma_list .
*/
void
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]);
switch (event)
{
case INM_START:
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);
/* Restart inactivity timer */
tm_start(n->inactim, n->ifa->deadint);
break;
case INM_2WAYREC:
if (n->state < NEIGHBOR_2WAY)
neigh_chstate(n, NEIGHBOR_2WAY);
if ((n->state == NEIGHBOR_2WAY) && can_do_adj(n))
neigh_chstate(n, NEIGHBOR_EXSTART);
break;
case INM_NEGDONE:
if (n->state == NEIGHBOR_EXSTART)
{
neigh_chstate(n, NEIGHBOR_EXCHANGE);
/* Reset DB summary list iterator */
s_get(&(n->dbsi));
s_init(&(n->dbsi), &p->lsal);
/* Add MaxAge LSA entries to retransmission list */
ospf_add_flushed_to_lsrt(p, n);
/* FIXME: Why is this here ? */
ospf_reset_lsack_queue(n);
}
else
bug("NEGDONE and I'm not in EXSTART?");
break;
case INM_EXDONE:
neigh_chstate(n, NEIGHBOR_LOADING);
break;
case INM_LOADDONE:
neigh_chstate(n, NEIGHBOR_FULL);
break;
case INM_ADJOK:
switch (n->state)
{
case NEIGHBOR_2WAY:
/* Can In build adjacency? */
if (can_do_adj(n))
{
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);
}
break;
}
break;
case INM_SEQMIS:
case INM_BADLSREQ:
if (n->state >= NEIGHBOR_EXCHANGE)
{
reset_lists(p, n);
neigh_chstate(n, NEIGHBOR_EXSTART);
}
break;
case INM_KILLNBR:
case INM_LLDOWN:
case INM_INACTTIM:
reset_lists(p, n);
neigh_chstate(n, NEIGHBOR_DOWN);
break;
case INM_1WAYREC:
reset_lists(p, n);
neigh_chstate(n, NEIGHBOR_INIT);
break;
default:
bug("%s: INM - Unknown event?", p->p.name);
break;
}
}
/** /**
* ospf_dr_election - (Backup) Designed Router election * ospf_dr_election - (Backup) Designed Router election
* @ifa: actual interface * @ifa: actual interface
* *
* When the wait timer fires, it is time to elect (Backup) Designated Router. * 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 * Structure describing me is added to this list so every electing router has
* has the same list. Backup Designated Router is elected before Designated * the same list. Backup Designated Router is elected before Designated
* Router. This process is described in 9.4 of RFC 2328. * 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 void
ospf_dr_election(struct ospf_iface *ifa) 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); DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
/* We are part of the interface state machine */
if (ifa->drid == myid) if (ifa->drid == myid)
ospf_iface_chstate(ifa, OSPF_IS_DR); ospf_iface_chstate(ifa, OSPF_IS_DR);
else if (ifa->bdrid == myid) else if (ifa->bdrid == myid)
@ -544,39 +565,15 @@ find_neigh_by_ip(struct ospf_iface *ifa, ip_addr ip)
return NULL; return NULL;
} }
/* Neighbor is inactive for a long time. Remove it. */
static void static void
neighbor_timer_hook(timer * timer) neighbor_timer_hook(timer * timer)
{ {
struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data; struct ospf_neighbor *n = (struct ospf_neighbor *) timer->data;
struct ospf_iface *ifa = n->ifa; struct ospf_proto *p = n->ifa->oa->po;
struct ospf_proto *p = ifa->oa->po;
OSPF_TRACE(D_EVENTS, "Inactivity timer fired on interface %s for neighbor %I", OSPF_TRACE(D_EVENTS, "Inactivity timer expired for neighbor %R on %s",
ifa->ifname, n->ip); n->rid, n->ifa->ifname);
ospf_neigh_remove(n); ospf_neigh_sm(n, INM_INACTTIM);
}
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);
s_get(&(n->dbsi));
release_lsrtl(p, n);
rem_node(NODE n);
rfree(n->pool);
OSPF_TRACE(D_EVENTS, "Deleting neigbor %R", n->rid);
} }
static void static void
@ -587,8 +584,9 @@ ospf_neigh_bfd_hook(struct bfd_request *req)
if (req->down) if (req->down)
{ {
OSPF_TRACE(D_EVENTS, "BFD session down for %I on %s", n->ip, n->ifa->ifname); OSPF_TRACE(D_EVENTS, "BFD session down for neighbor %R on %s",
ospf_neigh_remove(n); n->rid, n->ifa->ifname);
ospf_neigh_sm(n, INM_INACTTIM);
} }
} }
@ -611,7 +609,7 @@ void
ospf_sh_neigh_info(struct ospf_neighbor *n) ospf_sh_neigh_info(struct ospf_neighbor *n)
{ {
struct ospf_iface *ifa = n->ifa; struct ospf_iface *ifa = n->ifa;
char *pos = "other"; char *pos = "ptp ";
char etime[6]; char etime[6];
int exp, sec, min; int exp, sec, min;
@ -627,16 +625,18 @@ ospf_sh_neigh_info(struct ospf_neighbor *n)
bsprintf(etime, "%02u:%02u", min, sec); bsprintf(etime, "%02u:%02u", min, sec);
} }
if (n->rid == ifa->drid) if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA))
pos = "dr "; {
else if (n->rid == ifa->bdrid) if (n->rid == ifa->drid)
pos = "bdr "; pos = "dr ";
else if ((n->ifa->type == OSPF_IT_PTP) || (n->ifa->type == OSPF_IT_PTMP) || else if (n->rid == ifa->bdrid)
(n->ifa->type == OSPF_IT_VLINK)) pos = "bdr ";
pos = "ptp "; else
pos = "other";
}
cli_msg(-1013, "%-1R\t%3u\t%s/%s\t%-5s\t%-10s %-1I", n->rid, n->priority, 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 static void
@ -645,18 +645,18 @@ rxmt_timer_hook(timer *t)
struct ospf_neighbor *n = t->data; struct ospf_neighbor *n = t->data;
struct ospf_proto *p = n->ifa->oa->po; 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); p->p.name, n->ifa->ifname, n->ip);
switch (n->state) switch (n->state)
{ {
case NEIGHBOR_EXSTART: case NEIGHBOR_EXSTART:
ospf_send_dbdes(p, n, 1); ospf_send_dbdes(p, n);
return; return;
case NEIGHBOR_EXCHANGE: case NEIGHBOR_EXCHANGE:
if (n->myimms & DBDES_MS) if (n->myimms & DBDES_MS)
ospf_send_dbdes(p, n, 0); ospf_rxmt_dbdes(p, n);
case NEIGHBOR_LOADING: case NEIGHBOR_LOADING:
ospf_send_lsreq(p, n); ospf_send_lsreq(p, n);
return; return;
@ -666,9 +666,6 @@ rxmt_timer_hook(timer *t)
if (!EMPTY_SLIST(n->lsrtl)) if (!EMPTY_SLIST(n->lsrtl))
ospf_rxmt_lsupd(p, n); ospf_rxmt_lsupd(p, n);
return; return;
default:
return;
} }
} }
@ -678,7 +675,7 @@ ackd_timer_hook(timer *t)
struct ospf_neighbor *n = t->data; struct ospf_neighbor *n = t->data;
struct ospf_proto *p = n->ifa->oa->po; 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); p->p.name, n->ifa->ifname, n->ip);
ospf_send_lsack(p, n, ACKL_DELAY); ospf_send_lsack(p, n, ACKL_DELAY);

View File

@ -252,6 +252,9 @@ ospf_start(struct proto *P)
p->gr = ospf_top_new(p, P->pool); p->gr = ospf_top_new(p, P->pool);
s_init_list(&(p->lsal)); 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) WALK_LIST(ac, c->area_list)
ospf_area_add(p, ac); ospf_area_add(p, ac);
@ -742,7 +745,7 @@ ospf_sh(struct proto *P)
} }
cli_msg(-1014, "%s:", p->p.name); 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, "Stub router: %s", (p->stub_router ? "Yes" : "No"));
cli_msg(-1014, "RT scheduler tick: %d", p->tick); cli_msg(-1014, "RT scheduler tick: %d", p->tick);
cli_msg(-1014, "Number of areas: %u", p->areano); cli_msg(-1014, "Number of areas: %u", p->areano);

View File

@ -73,12 +73,28 @@
// FIXME: MAX_PREFIX_LENGTH // FIXME: MAX_PREFIX_LENGTH
#define OSPF_TRACE(flags, msg, args...) \ #define OSPF_TRACE(flags, msg, args...) \
do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \ do { if ((p->p.debug & flags) || OSPF_FORCE_DEBUG) \
log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0) log(L_TRACE "%s: " msg, p->p.name , ## args ); } while(0)
#define OSPF_PACKET(dumpfn, buffer, msg, args...) \ #define OSPF_PACKET(dumpfn, buffer, msg, args...) \
do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \ do { if ((p->p.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
{ log(L_TRACE "%s: " msg, p->p.name, ## args ); dumpfn(p, buffer); } } while(0) { 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 #define OSPF_PROTO 89
@ -248,6 +264,8 @@ struct ospf_proto
sock *vlink_sk; /* IP socket used for vlink TX */ sock *vlink_sk; /* IP socket used for vlink TX */
u32 router_id; u32 router_id;
u32 last_vlink_id; /* Interface IDs for vlinks (starts at 0x80000000) */ 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 struct ospf_area
@ -283,7 +301,7 @@ struct ospf_iface
pool *pool; pool *pool;
sock *sk; /* IP socket */ 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 cost; /* Cost of iface */
u32 waitint; /* number of sec before changing state from wait */ u32 waitint; /* number of sec before changing state from wait */
u32 rxmtint; /* number of seconds between LSA retransmissions */ 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 /* Entries dr and bdr store IP addresses in OSPFv2 and router IDs in
OSPFv3, we use the same type to simplify handling */ OSPFv3, we use the same type to simplify handling */
u32 dr; /* Neigbour's idea of DR */ u32 dr; /* Neighbor's idea of DR */
u32 bdr; /* Neigbour's idea of BDR */ u32 bdr; /* Neighbor's idea of BDR */
u32 iface_id; /* ID of Neighbour's iface connected to common network */ u32 iface_id; /* ID of Neighbour's iface connected to common network */
/* Database summary list iterator, controls initial dbdes exchange. /* 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); void ospf_dr_election(struct ospf_iface *ifa);
struct ospf_neighbor *find_neigh(struct ospf_iface *ifa, u32 rid); 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); 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_neigh_update_bfd(struct ospf_neighbor *n, int use_bfd);
void ospf_sh_neigh_info(struct ospf_neighbor *n); 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); 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) 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); } { 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); void ospf_receive_hello(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n, ip_addr faddr);
/* dbdes.c */ /* 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); void ospf_receive_dbdes(struct ospf_packet *pkt, struct ospf_iface *ifa, struct ospf_neighbor *n);
/* lsreq.c */ /* lsreq.c */

View File

@ -66,7 +66,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
log(L_ERR "No suitable password found for authentication"); log(L_ERR "No suitable password found for authentication");
return; return;
} }
password_cpy(auth->password, passwd->password, sizeof(union ospf_auth)); strncpy(auth->password, passwd->password, sizeof(auth->password));
case OSPF_AUTH_NONE: case OSPF_AUTH_NONE:
{ {
@ -106,7 +106,7 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
void *tail = ((void *) pkt) + plen; void *tail = ((void *) pkt) + plen;
char password[OSPF_AUTH_CRYPT_SIZE]; char password[OSPF_AUTH_CRYPT_SIZE];
password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE); strncpy(password, passwd->password, sizeof(password));
struct MD5Context ctxt; struct MD5Context ctxt;
MD5Init(&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() */ /* We assume OSPFv2 in ospf_pkt_checkauth() */
static int 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; struct ospf_proto *p = ifa->oa->po;
union ospf_auth *auth = (void *) (pkt + 1); union ospf_auth *auth = (void *) (pkt + 1);
struct password_item *pass = NULL, *ptmp; struct password_item *pass = NULL;
char password[OSPF_AUTH_CRYPT_SIZE]; const char *err_dsc = NULL;
uint err_val = 0;
uint plen = ntohs(pkt->length); uint plen = ntohs(pkt->length);
u8 autype = pkt->autype; u8 autype = pkt->autype;
if (autype != ifa->autype) if (autype != ifa->autype)
{ DROP("authentication method mismatch", autype);
OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype);
return 0;
}
switch (autype) switch (autype)
{ {
@ -146,85 +145,65 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
case OSPF_AUTH_SIMPLE: case OSPF_AUTH_SIMPLE:
pass = password_find(ifa->passwords, 1); pass = password_find(ifa->passwords, 1);
if (!pass) if (!pass)
{ DROP1("no password found");
OSPF_TRACE(D_PACKETS, "OSPF_auth: no password found");
return 0; 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; return 1;
case OSPF_AUTH_CRYPT: case OSPF_AUTH_CRYPT:
if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE) if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
DROP("invalid MD5 digest length", auth->md5.len);
if (plen + OSPF_AUTH_CRYPT_SIZE > len)
DROP("length mismatch", len);
u32 rcv_csn = ntohl(auth->md5.csn);
if (n && (rcv_csn < n->csn))
// DROP("lower sequence number", rcv_csn);
{ {
OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest"); /* 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; return 0;
} }
if (plen + OSPF_AUTH_CRYPT_SIZE > size) pass = password_find_by_id(ifa->passwords, auth->md5.keyid);
{
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;
}
n->csn = rcv_csn;
}
if (ifa->passwords)
{
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;
}
}
if (!pass) if (!pass)
{ DROP("no suitable password found", auth->md5.keyid);
OSPF_TRACE(D_PACKETS, "OSPF_auth: no suitable md5 password found");
return 0;
}
void *tail = ((void *) pkt) + plen; void *tail = ((void *) pkt) + plen;
char passwd[OSPF_AUTH_CRYPT_SIZE];
char md5sum[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; struct MD5Context ctxt;
MD5Init(&ctxt); MD5Init(&ctxt);
MD5Update(&ctxt, (char *) pkt, plen); MD5Update(&ctxt, (char *) pkt, plen);
MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE); MD5Update(&ctxt, passwd, OSPF_AUTH_CRYPT_SIZE);
MD5Final(md5sum, &ctxt); MD5Final(md5sum, &ctxt);
if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE)) if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
{ DROP("wrong MD5 digest", pass->id);
OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
return 0; if (n)
} n->csn = rcv_csn;
return 1; return 1;
default: default:
OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type"); bug("Unknown authentication type");
return 0;
} }
}
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 * ospf_rx_hook
@ -236,13 +215,10 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
* non generic functions. * non generic functions.
*/ */
int 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) if (sk->lifindex != sk->iface->index)
return 1; return 1;
@ -252,6 +228,8 @@ ospf_rx_hook(sock *sk, int size)
/* Initially, the packet is associated with the 'master' iface */ /* Initially, the packet is associated with the 'master' iface */
struct ospf_iface *ifa = sk->data; struct ospf_iface *ifa = sk->data;
struct ospf_proto *p = ifa->oa->po; struct ospf_proto *p = ifa->oa->po;
const char *err_dsc = NULL;
uint err_val = 0;
int src_local, dst_local, dst_mcast; int src_local, dst_local, dst_mcast;
src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen); 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. * link-local src address, but does not enforce it. Strange.
*/ */
if (dst_mcast && !src_local) 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 */ /* Second, we check packet length, checksum, and the protocol version */
struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size); struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &len);
if (pkt == NULL) if (pkt == NULL)
{ DROP("bad IP header", len);
log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
return 1;
}
if (ifa->check_ttl && (sk->rcv_ttl < 255)) if (ifa->check_ttl && (sk->rcv_ttl < 255))
{ DROP("wrong TTL", sk->rcv_ttl);
log(L_ERR "%s%I - TTL %d (< 255)", mesg, sk->faddr, sk->rcv_ttl);
return 1;
}
if ((uint) size < sizeof(struct ospf_packet)) if (len < sizeof(struct ospf_packet))
{ DROP("too short", len);
log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
return 1; if (pkt->version != ospf_get_version(p))
} DROP("version mismatch", pkt->version);
uint plen = ntohs(pkt->length); uint plen = ntohs(pkt->length);
if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0)) if ((plen < sizeof(struct ospf_packet)) || ((plen % 4) != 0))
{ DROP("invalid length", plen);
log(L_ERR "%s%I - invalid length (%u)", mesg, sk->faddr, plen);
return 1;
}
if (sk->flags & SKF_TRUNCATED) 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 */ /* If we have dynamic buffers and received truncated message, we expand RX buffer */
uint bs = plen + 256; uint bs = plen + 256;
@ -325,20 +293,11 @@ ospf_rx_hook(sock *sk, int size)
if (!ifa->cf->rx_buffer && (bs > sk->rbsize)) if (!ifa->cf->rx_buffer && (bs > sk->rbsize))
sk_set_rbsize(sk, bs); sk_set_rbsize(sk, bs);
return 1; DROP("truncated", plen);
} }
if (plen > size) if (plen > len)
{ DROP("length mismatch", plen);
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 (ospf_is_v2(p) && (pkt->autype != OSPF_AUTH_CRYPT)) 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; uint blen = plen - hlen;
void *body = ((void *) pkt) + hlen; void *body = ((void *) pkt) + hlen;
if (! ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL)) if (!ipsum_verify(pkt, sizeof(struct ospf_packet), body, blen, NULL))
{ DROP1("invalid checksum");
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
return 1;
}
} }
/* Third, we resolve associated iface and handle vlinks. */ /* 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) */ /* It is real iface, source should be local (in OSPFv2) */
if (ospf_is_v2(p) && !src_local) if (ospf_is_v2(p) && !src_local)
{ DROP1("strange source address");
log(L_ERR "%s%I - strange source address for %s", mesg, sk->faddr, ifa->ifname);
return 1;
}
goto found; goto found;
} }
@ -415,13 +368,11 @@ ospf_rx_hook(sock *sk, int size)
if (instance_id != ifa->instance_id) if (instance_id != ifa->instance_id)
return 1; return 1;
log(L_ERR "%s%I - area does not match (%R vs %R)", DROP("area mismatch", areaid);
mesg, sk->faddr, areaid, ifa->oa->areaid);
return 1;
} }
found: found:
if (ifa->stub) /* This shouldn't happen */ if (ifa->stub) /* This shouldn't happen */
return 1; return 1;
@ -429,18 +380,12 @@ ospf_rx_hook(sock *sk, int size)
return 1; return 1;
if (rid == p->router_id) if (rid == p->router_id)
{ DROP1("my own router ID");
log(L_ERR "%s%I - received my own router ID!", mesg, sk->faddr);
return 1;
}
if (rid == 0) if (rid == 0)
{ DROP1("zero router ID");
log(L_ERR "%s%I - router id = 0.0.0.0", mesg, sk->faddr);
return 1;
}
/* 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; uint t = ifa->type;
struct ospf_neighbor *n; struct ospf_neighbor *n;
if (ospf_is_v2(p) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP))) 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)) if (!n && (pkt->type != HELLO_P))
{ {
log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)", // XXXX format
sk->faddr, ifa->ifname); OSPF_TRACE(D_PACKETS, "Non-HELLO packet received from unknown neighbor %R on %s (%I)",
rid, ifa->ifname, sk->faddr);
return 1; return 1;
} }
if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, size)) /* ospf_pkt_checkauth() has its own error logging */
{ if (ospf_is_v2(p) && !ospf_pkt_checkauth(n, ifa, pkt, len))
log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
return 1; return 1;
}
switch (pkt->type) switch (pkt->type)
{ {
@ -484,10 +428,15 @@ ospf_rx_hook(sock *sk, int size)
break; break;
default: default:
log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type); DROP("invalid packet type", pkt->type);
return 1;
}; };
return 1; return 1;
drop:
LOG_PKT("Bad packet from %I via %s - %s (%u)",
sk->faddr, ifa->ifname, err_dsc, err_val);
return 1;
} }
/* /*

View File

@ -1204,7 +1204,7 @@ ospf_check_vlinks(struct ospf_proto *p)
|| (ifa->vifa != nhi) || (ifa->vifa != nhi)
|| !ipa_equal(ifa->vip, tmp->lb)) || !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); ospf_iface_sm(ifa, ISM_DOWN);
ifa->vifa = nhi; ifa->vifa = nhi;
ifa->addr = nhi->addr; ifa->addr = nhi->addr;
@ -1831,7 +1831,7 @@ calc_next_hop(struct ospf_area *oa, struct top_hash_entry *en,
bad: bad:
/* Probably bug or some race condition, we log it */ /* 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; 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); struct mpnh *nhs = calc_next_hop(oa, en, par, pos);
if (!nhs) if (!nhs)
{ {
log(L_WARN "Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)", log(L_WARN "%s: Cannot find next hop for LSA (Type: %04x, Id: %R, Rt: %R)",
en->lsa_type, en->lsa.id, en->lsa.rt); p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
return; return;
} }

View File

@ -758,7 +758,7 @@ prepare_rt2_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
break; break;
default: default:
log("Unknown interface type %s", ifa->ifname); log(L_BUG "OSPF: Unknown interface type");
break; break;
} }
@ -855,7 +855,7 @@ prepare_rt3_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
break; break;
default: default:
log("Unknown interface type %s", ifa->ifname); log(L_BUG "OSPF: Unknown interface type");
break; break;
} }

View File

@ -95,7 +95,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru
} }
memcpy(md5sum_packet, tail->md5, 16); memcpy(md5sum_packet, tail->md5, 16);
password_cpy(tail->md5, pass->password, 16); strncpy(tail->md5, pass->password, 16);
MD5Init(&ctxt); MD5Init(&ctxt);
MD5Update(&ctxt, (char *) packet, ntohs(block->packetlen) + sizeof(struct rip_block_auth) ); MD5Update(&ctxt, (char *) packet, ntohs(block->packetlen) + sizeof(struct rip_block_auth) );
@ -131,7 +131,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru
block->mustbeFFFF = 0xffff; block->mustbeFFFF = 0xffff;
switch (P_CF->authtype) { switch (P_CF->authtype) {
case AT_PLAINTEXT: case AT_PLAINTEXT:
password_cpy( (char *) (&block->packetlen), passwd->password, 16); strncpy( (char *) (&block->packetlen), passwd->password, 16);
return PACKETLEN(num); return PACKETLEN(num);
case AT_MD5: case AT_MD5:
{ {
@ -156,7 +156,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru
tail->mustbeFFFF = 0xffff; tail->mustbeFFFF = 0xffff;
tail->mustbe0001 = 0x0100; tail->mustbe0001 = 0x0100;
password_cpy(tail->md5, passwd->password, 16); strncpy(tail->md5, passwd->password, 16);
MD5Init(&ctxt); MD5Init(&ctxt);
MD5Update(&ctxt, (char *) packet, PACKETLEN(num) + sizeof(struct rip_md5_tail)); MD5Update(&ctxt, (char *) packet, PACKETLEN(num) + sizeof(struct rip_md5_tail));
MD5Final(tail->md5, &ctxt); MD5Final(tail->md5, &ctxt);