mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-08 12:18:42 +00:00
Refactoring of OSPF messages.
This commit is contained in:
parent
78342404ff
commit
f8fefde318
@ -36,9 +36,18 @@ password_find(list *l, int first_fit)
|
||||
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);
|
||||
memcpy(dst, src, (strlen(src) < (unsigned) size ? strlen(src) : (unsigned) size));
|
||||
struct password_item *pi;
|
||||
|
||||
if (!l)
|
||||
return NULL;
|
||||
|
||||
WALK_LIST(pi, *l)
|
||||
if ((pi->id == id) && (pi->accfrom <= now_real) && (now_real < pi->accto))
|
||||
return pi;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,13 @@ struct password_item {
|
||||
extern struct password_item *last_password_item;
|
||||
|
||||
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
|
||||
|
@ -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;
|
||||
ospf_prepare_dbdes(p, n);
|
||||
ospf_do_send_dbdes(p, n);
|
||||
|
||||
/* Send empty packets */
|
||||
ospf_prepare_dbdes(p, n, 0);
|
||||
ospf_do_send_dbdes(p, n);
|
||||
break;
|
||||
if (n->state == NEIGHBOR_EXSTART)
|
||||
return;
|
||||
|
||||
case NEIGHBOR_EXCHANGE:
|
||||
n->myimms &= ~DBDES_I;
|
||||
/* Master should restart RXMT timer for each DBDES exchange */
|
||||
if (n->myimms & DBDES_MS)
|
||||
tm_start(n->rxmt_timer, n->ifa->rxmtint);
|
||||
|
||||
if (next)
|
||||
ospf_prepare_dbdes(p, n, 1);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
if (!(n->myimms & DBDES_MS))
|
||||
if (!(n->myimms & DBDES_M) && !(n->imms & DBDES_M))
|
||||
ospf_neigh_sm(n, INM_EXDONE);
|
||||
}
|
||||
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
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;
|
||||
}
|
||||
/* RFC 2328 13. */
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -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,8 +192,182 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
|
||||
|
||||
if (state > NEIGHBOR_EXSTART)
|
||||
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)
|
||||
{ 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);
|
||||
}
|
||||
|
||||
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
|
||||
* @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;
|
||||
struct ospf_proto *p = n->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);
|
||||
|
||||
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);
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, stru
|
||||
}
|
||||
|
||||
memcpy(md5sum_packet, tail->md5, 16);
|
||||
password_cpy(tail->md5, pass->password, 16);
|
||||
strncpy(tail->md5, pass->password, 16);
|
||||
|
||||
MD5Init(&ctxt);
|
||||
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;
|
||||
switch (P_CF->authtype) {
|
||||
case AT_PLAINTEXT:
|
||||
password_cpy( (char *) (&block->packetlen), passwd->password, 16);
|
||||
strncpy( (char *) (&block->packetlen), passwd->password, 16);
|
||||
return PACKETLEN(num);
|
||||
case AT_MD5:
|
||||
{
|
||||
@ -156,7 +156,7 @@ rip_outgoing_authentication( struct proto *p, struct rip_block_auth *block, stru
|
||||
tail->mustbeFFFF = 0xffff;
|
||||
tail->mustbe0001 = 0x0100;
|
||||
|
||||
password_cpy(tail->md5, passwd->password, 16);
|
||||
strncpy(tail->md5, passwd->password, 16);
|
||||
MD5Init(&ctxt);
|
||||
MD5Update(&ctxt, (char *) packet, PACKETLEN(num) + sizeof(struct rip_md5_tail));
|
||||
MD5Final(tail->md5, &ctxt);
|
||||
|
Loading…
Reference in New Issue
Block a user