0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-22 01:31:55 +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;
}
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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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)

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 */
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 */

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);
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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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 */

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");
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;
}
/*

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);