mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Implements better checks on incoming packets and LSAs in OSPF.
This commit is contained in:
parent
9d4d38d1a5
commit
a6bc04d591
@ -53,7 +53,7 @@ static void ospf_dump_dbdes(struct proto *p, struct ospf_dbdes_packet *pkt)
|
||||
log(L_TRACE "%s: ddseq %u", p->name, ntohl(pkt->ddseq));
|
||||
|
||||
struct ospf_lsa_header *plsa = (void *) (pkt + 1);
|
||||
int i, j;
|
||||
unsigned int i, j;
|
||||
|
||||
j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
|
||||
sizeof(struct ospf_lsa_header);
|
||||
@ -247,11 +247,17 @@ void
|
||||
ospf_dbdes_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_dbdes_packet *ps = (void *) ps_i;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
u32 myrid = p->cf->global->router_id;
|
||||
unsigned int size = ntohs(ps->ospf_packet.length);
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_dbdes_packet))
|
||||
{
|
||||
log(L_ERR "Bad OSPF DBDES packet from %I - too short (%u B)", n->ip, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_dbdes_packet *ps = (void *) ps_i;
|
||||
u32 ps_ddseq = ntohl(ps->ddseq);
|
||||
u32 ps_options = ntoh_opt(ps->options);
|
||||
|
||||
|
@ -45,12 +45,20 @@ void
|
||||
ospf_hello_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n, ip_addr faddr)
|
||||
{
|
||||
struct ospf_hello_packet *ps = (void *) ps_i;
|
||||
u32 *pnrid;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
char *beg = "Bad OSPF HELLO packet from ", *rec = " received: ";
|
||||
unsigned int size, i, twoway, oldpriority, eligible, peers;
|
||||
u32 olddr, oldbdr, oldiface_id, tmp;
|
||||
char *beg = "Bad OSPF hello packet from ", *rec = " received: ";
|
||||
struct proto *p = (struct proto *) ifa->oa->po;
|
||||
unsigned int size = ntohs(ps->ospf_packet.length), i, twoway, oldpriority, eligible = 0, peers;
|
||||
u32 *pnrid;
|
||||
|
||||
size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_hello_packet))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u B)", beg, faddr, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_hello_packet *ps = (void *) ps_i;
|
||||
|
||||
OSPF_TRACE(D_PACKETS, "HELLO packet received from %I via %s%s", faddr,
|
||||
(ifa->type == OSPF_IT_VLINK ? "vlink-" : ""), ifa->iface->name);
|
||||
|
@ -26,7 +26,7 @@ static void ospf_dump_lsack(struct proto *p, struct ospf_lsack_packet *pkt)
|
||||
ASSERT(op->type == LSACK_P);
|
||||
ospf_dump_common(p, op);
|
||||
|
||||
int i, j;
|
||||
unsigned int i, j;
|
||||
j = (ntohs(op->length) - sizeof(struct ospf_lsack_packet)) /
|
||||
sizeof(struct ospf_lsa_header);
|
||||
|
||||
@ -138,13 +138,19 @@ void
|
||||
ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_lsack_packet *ps = (void *) ps_i;
|
||||
struct ospf_lsa_header lsa;
|
||||
u16 nolsa;
|
||||
struct top_hash_entry *en;
|
||||
struct proto *p = &ifa->oa->po->proto;
|
||||
unsigned int size = ntohs(ps->ospf_packet.length), i;
|
||||
struct ospf_lsa_header lsa;
|
||||
struct top_hash_entry *en;
|
||||
unsigned int i, lsano;
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_lsack_packet))
|
||||
{
|
||||
log(L_ERR "Bad OSPF LSACK packet from %I - too short (%u B)", n->ip, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_lsack_packet *ps = (void *) ps_i;
|
||||
OSPF_PACKET(ospf_dump_lsack, ps, "LSACK packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC);
|
||||
@ -152,17 +158,9 @@ ospf_lsack_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
return;
|
||||
|
||||
nolsa = (size - sizeof(struct ospf_lsack_packet)) /
|
||||
lsano = (size - sizeof(struct ospf_lsack_packet)) /
|
||||
sizeof(struct ospf_lsa_header);
|
||||
|
||||
if ((nolsa < 1) || ((size - sizeof(struct ospf_lsack_packet)) !=
|
||||
(nolsa * sizeof(struct ospf_lsa_header))))
|
||||
{
|
||||
log(L_ERR "Received corrupted LS ack from %I", n->ip);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nolsa; i++)
|
||||
for (i = 0; i < lsano; i++)
|
||||
{
|
||||
ntohlsah(ps->lsh + i, &lsa);
|
||||
u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
|
||||
|
@ -291,6 +291,219 @@ lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2)
|
||||
return CMP_SAME;
|
||||
}
|
||||
|
||||
#define HDRLEN sizeof(struct ospf_lsa_header)
|
||||
|
||||
static int
|
||||
lsa_validate_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
|
||||
{
|
||||
unsigned int i, max;
|
||||
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
|
||||
return 0;
|
||||
|
||||
struct ospf_lsa_rt_link *rtl = (struct ospf_lsa_rt_link *) (body + 1);
|
||||
max = lsa_rt_count(lsa);
|
||||
|
||||
#ifdef OSPFv2
|
||||
if (body->links != max)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
u8 type = rtl[i].type;
|
||||
if (!((type == LSART_PTP) ||
|
||||
(type == LSART_NET) ||
|
||||
#ifdef OSPFv2
|
||||
(type == LSART_STUB) ||
|
||||
#endif
|
||||
(type == LSART_VLNK)))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef OSPFv2
|
||||
|
||||
static int
|
||||
lsa_validate_sum(struct ospf_lsa_header *lsa, struct ospf_lsa_sum *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum)))
|
||||
return 0;
|
||||
|
||||
/* First field should have TOS = 0, we ignore other TOS fields */
|
||||
if ((body->metric & LSA_SUM_TOS) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#define lsa_validate_sum_net(A,B) lsa_validate_sum(A,B)
|
||||
#define lsa_validate_sum_rt(A,B) lsa_validate_sum(A,B)
|
||||
|
||||
static int
|
||||
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext)))
|
||||
return 0;
|
||||
|
||||
/* First field should have TOS = 0, we ignore other TOS fields */
|
||||
if ((body->metric & LSA_EXT_TOS) != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* OSPFv3 */
|
||||
|
||||
static inline int
|
||||
pxlen(u32 *buf)
|
||||
{
|
||||
return *buf >> 24;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_net *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum_net) + 4))
|
||||
return 0;
|
||||
|
||||
u8 pxl = pxlen(body->prefix);
|
||||
if (pxl > MAX_PREFIX_LENGTH)
|
||||
return 0;
|
||||
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_net) +
|
||||
IPV6_PREFIX_SPACE(pxl)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum_rt *body)
|
||||
{
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum_rt)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext) + 4))
|
||||
return 0;
|
||||
|
||||
u8 pxl = pxlen(body->rest);
|
||||
if (pxl > MAX_PREFIX_LENGTH)
|
||||
return 0;
|
||||
|
||||
int len = IPV6_PREFIX_SPACE(pxl);
|
||||
if (body->metric & LSA_EXT_FBIT) // forwardinf address
|
||||
len += 16;
|
||||
if (body->metric & LSA_EXT_TBIT) // route tag
|
||||
len += 4;
|
||||
if (*body->rest & 0xFFFF) // referenced LS type field
|
||||
len += 4;
|
||||
|
||||
if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_ext) + len))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, unsigned int offset, u8 *pbuf)
|
||||
{
|
||||
unsigned int bound = lsa->length - HDRLEN - 4;
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < pxcount; i++)
|
||||
{
|
||||
if (offset > bound)
|
||||
return 0;
|
||||
|
||||
u8 pxl = pxlen((u32 *) (pbuf + offset));
|
||||
if (pxl > MAX_PREFIX_LENGTH)
|
||||
return 0;
|
||||
|
||||
offset += IPV6_PREFIX_SPACE(pxl);
|
||||
}
|
||||
|
||||
if (lsa->length != (HDRLEN + offset))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_link(struct ospf_lsa_header *lsa, struct ospf_lsa_link *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_link)))
|
||||
return 0;
|
||||
|
||||
return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_link), (u8 *) body);
|
||||
}
|
||||
|
||||
static int
|
||||
lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
|
||||
{
|
||||
if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_prefix)))
|
||||
return 0;
|
||||
|
||||
return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* lsa_validate - check whether given LSA is valid
|
||||
* @lsa: LSA header
|
||||
* @body: pointer to LSA body
|
||||
*
|
||||
* Checks internal structure of given LSA body (minimal length,
|
||||
* consistency). Returns true if valid.
|
||||
*/
|
||||
|
||||
int
|
||||
lsa_validate(struct ospf_lsa_header *lsa, void *body)
|
||||
{
|
||||
switch (lsa->type)
|
||||
{
|
||||
case LSA_T_RT:
|
||||
return lsa_validate_rt(lsa, body);
|
||||
case LSA_T_NET:
|
||||
return lsa_validate_net(lsa, body);
|
||||
case LSA_T_SUM_NET:
|
||||
return lsa_validate_sum_net(lsa, body);
|
||||
case LSA_T_SUM_RT:
|
||||
return lsa_validate_sum_rt(lsa, body);
|
||||
case LSA_T_EXT:
|
||||
return lsa_validate_ext(lsa, body);
|
||||
#ifdef OSPFv3
|
||||
case LSA_T_LINK:
|
||||
return lsa_validate_link(lsa, body);
|
||||
case LSA_T_PREFIX:
|
||||
return lsa_validate_prefix(lsa, body);
|
||||
#endif
|
||||
default:
|
||||
/* In OSPFv3, unknown LSAs are OK,
|
||||
In OSPFv2, unknown LSAs are already rejected
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* lsa_install_new - install new LSA into database
|
||||
* @po: OSPF protocol
|
||||
|
@ -20,6 +20,7 @@ u16 lsasum_check(struct ospf_lsa_header *h, void *body);
|
||||
#define CMP_SAME 0
|
||||
#define CMP_OLDER -1
|
||||
int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
|
||||
int lsa_validate(struct ospf_lsa_header *lsa, void *body);
|
||||
struct top_hash_entry * lsa_install_new(struct proto_ospf *po, struct ospf_lsa_header *lsa, u32 domain, void *body);
|
||||
void ospf_age(struct proto_ospf *po);
|
||||
void flush_lsa(struct top_hash_entry *en, struct proto_ospf *po);
|
||||
|
@ -23,7 +23,7 @@ static void ospf_dump_lsreq(struct proto *p, struct ospf_lsreq_packet *pkt)
|
||||
ASSERT(op->type == LSREQ_P);
|
||||
ospf_dump_common(p, op);
|
||||
|
||||
int i, j;
|
||||
unsigned int i, j;
|
||||
j = (ntohs(op->length) - sizeof(struct ospf_lsreq_packet)) /
|
||||
sizeof(struct ospf_lsreq_header);
|
||||
|
||||
@ -91,17 +91,23 @@ void
|
||||
ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_lsreq_packet *ps = (void *) ps_i;
|
||||
struct ospf_area *oa = ifa->oa;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
struct ospf_lsreq_header *lsh;
|
||||
struct l_lsr_head *llsh;
|
||||
list uplist;
|
||||
slab *upslab;
|
||||
unsigned int size = ntohs(ps->ospf_packet.length);
|
||||
int i, lsano;
|
||||
struct ospf_area *oa = ifa->oa;
|
||||
struct proto_ospf *po = oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < sizeof(struct ospf_lsreq_packet))
|
||||
{
|
||||
log(L_ERR "Bad OSPF LSREQ packet from %I - too short (%u B)", n->ip, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_lsreq_packet *ps = (void *) ps_i;
|
||||
OSPF_PACKET(ospf_dump_lsreq, ps, "LSREQ packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
@ -129,8 +135,7 @@ ospf_lsreq_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
add_tail(&uplist, NODE llsh);
|
||||
if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
|
||||
{
|
||||
log(L_WARN
|
||||
"Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
|
||||
log(L_WARN "Received bad LS req from: %I looking: Type: %u, ID: %R, RT: %R",
|
||||
n->ip, htype, hid, hrt);
|
||||
ospf_neigh_sm(n, INM_BADLSREQ);
|
||||
rfree(upslab);
|
||||
|
@ -16,6 +16,7 @@ struct ospf_lsupd_packet
|
||||
};
|
||||
|
||||
|
||||
/* Beware of unaligned access */
|
||||
void ospf_dump_lsahdr(struct proto *p, struct ospf_lsa_header *lsa_n)
|
||||
{
|
||||
struct ospf_lsa_header lsa;
|
||||
@ -38,15 +39,16 @@ static void ospf_dump_lsupd(struct proto *p, struct ospf_lsupd_packet *pkt)
|
||||
ASSERT(op->type == LSUPD_P);
|
||||
ospf_dump_common(p, op);
|
||||
|
||||
/* We know that ntohs(op->length) >= sizeof(struct ospf_lsa_header) */
|
||||
u8 *pbuf= (u8 *) pkt;
|
||||
int offset = sizeof(struct ospf_lsupd_packet);
|
||||
int bound = ntohs(op->length) - sizeof(struct ospf_lsa_header);
|
||||
int i, j;
|
||||
unsigned int offset = sizeof(struct ospf_lsupd_packet);
|
||||
unsigned int bound = ntohs(op->length) - sizeof(struct ospf_lsa_header);
|
||||
unsigned int i, j;
|
||||
|
||||
j = ntohl(pkt->lsano);
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
if (offset > bound)
|
||||
if ((offset > bound) || ((offset % 4) != 0))
|
||||
{
|
||||
log(L_TRACE "%s: LSA invalid", p->name);
|
||||
return;
|
||||
@ -405,13 +407,20 @@ void
|
||||
ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
struct ospf_neighbor *n)
|
||||
{
|
||||
struct ospf_lsupd_packet *ps = (void *) ps_i;
|
||||
|
||||
struct ospf_neighbor *ntmp;
|
||||
struct ospf_lsa_header *lsa;
|
||||
struct proto_ospf *po = ifa->oa->po;
|
||||
struct proto *p = &po->proto;
|
||||
unsigned int i, sendreq = 1, size = ntohs(ps->ospf_packet.length);
|
||||
unsigned int i, max, sendreq = 1;
|
||||
|
||||
unsigned int size = ntohs(ps_i->length);
|
||||
if (size < (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
|
||||
{
|
||||
log(L_ERR "Bad OSPF LSUPD packet from %I - too short (%u B)", n->ip, size);
|
||||
return;
|
||||
}
|
||||
|
||||
struct ospf_lsupd_packet *ps = (void *) ps_i;
|
||||
OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
|
||||
|
||||
if (n->state < NEIGHBOR_EXCHANGE)
|
||||
@ -420,35 +429,29 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
return;
|
||||
}
|
||||
|
||||
if (size <=
|
||||
(sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
|
||||
{
|
||||
log(L_WARN "Received lsupd from %I is too short!", n->ip);
|
||||
return;
|
||||
}
|
||||
|
||||
ospf_neigh_sm(n, INM_HELLOREC); /* Questionable */
|
||||
|
||||
lsa = (struct ospf_lsa_header *) (ps + 1);
|
||||
unsigned int offset = sizeof(struct ospf_lsupd_packet);
|
||||
unsigned int bound = size - sizeof(struct ospf_lsa_header);
|
||||
|
||||
for (i = 0; i < ntohl(ps->lsano); i++,
|
||||
lsa = (struct ospf_lsa_header *) (((u8 *) lsa) + ntohs(lsa->length)))
|
||||
max = ntohl(ps->lsano);
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
struct ospf_lsa_header lsatmp;
|
||||
struct top_hash_entry *lsadb;
|
||||
unsigned diff = ((u8 *) lsa) - ((u8 *) ps), lenn = ntohs(lsa->length);
|
||||
u16 chsum;
|
||||
|
||||
if (((diff + sizeof(struct ospf_lsa_header)) >= size)
|
||||
|| ((lenn + diff) > size))
|
||||
if (offset > bound)
|
||||
{
|
||||
log(L_WARN "Received lsupd from %I is too short!", n->ip);
|
||||
ospf_neigh_sm(n, INM_BADLSREQ);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((lenn <= sizeof(struct ospf_lsa_header))
|
||||
|| (lenn != (4 * (lenn / 4))))
|
||||
struct ospf_lsa_header *lsa = (void *) (((u8 *) ps) + offset);
|
||||
unsigned int lsalen = ntohs(lsa->length);
|
||||
|
||||
if (((offset + lsalen) > size) || ((lsalen % 4) != 0) ||
|
||||
(lsalen <= sizeof(struct ospf_lsa_header)))
|
||||
{
|
||||
log(L_WARN "Received LSA from %I with bad length", n->ip);
|
||||
ospf_neigh_sm(n, INM_BADLSREQ);
|
||||
@ -456,14 +459,13 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
}
|
||||
|
||||
/* pg 143 (1) */
|
||||
chsum = lsa->checksum;
|
||||
u16 chsum = lsa->checksum;
|
||||
if (chsum != lsasum_check(lsa, NULL))
|
||||
{
|
||||
log(L_WARN "Received bad lsa checksum from %I: %x %x", n->ip, chsum, lsa->checksum);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
#ifdef OSPFv2
|
||||
/* pg 143 (2) */
|
||||
if ((lsa->type < LSA_T_RT) || (lsa->type > LSA_T_EXT))
|
||||
@ -520,7 +522,6 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
if ((lsadb == NULL) || (lsa_comp(&lsatmp, &lsadb->lsa) == CMP_NEWER))
|
||||
{
|
||||
struct ospf_iface *ift = NULL;
|
||||
void *body;
|
||||
int self = (lsatmp.rt == p->cf->global->router_id);
|
||||
|
||||
DBG("PG143(5): Received LSA is newer\n");
|
||||
@ -618,10 +619,20 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
|
||||
} /* FIXME lsack? */
|
||||
|
||||
/* pg 144 (5d) */
|
||||
body =
|
||||
mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
|
||||
void *body = mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
|
||||
ntohlsab(lsa + 1, body, lsatmp.type,
|
||||
lsatmp.length - sizeof(struct ospf_lsa_header));
|
||||
|
||||
/* We will do validation check after flooding and
|
||||
acknowledging given LSA to minimize problems
|
||||
when communicating with non-validating peer */
|
||||
if (lsa_validate(&lsatmp, body) == 0)
|
||||
{
|
||||
log(L_WARN "Received invalid LSA from %I", n->ip);
|
||||
mb_free(body);
|
||||
continue;
|
||||
}
|
||||
|
||||
lsadb = lsa_install_new(po, &lsatmp, domain, body);
|
||||
DBG("New LSA installed in DB\n");
|
||||
|
||||
|
@ -438,6 +438,8 @@ struct ospf_lsa_ext
|
||||
u32 tag;
|
||||
};
|
||||
|
||||
#define LSA_SUM_TOS 0xFF000000
|
||||
#define LSA_EXT_TOS 0x7F000000
|
||||
#define LSA_EXT_EBIT 0x80000000
|
||||
|
||||
/* Endianity swap for lsa->type */
|
||||
@ -545,6 +547,9 @@ lsa_net_count(struct ospf_lsa_header *lsa)
|
||||
|
||||
#ifdef OSPFv3
|
||||
|
||||
#define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
|
||||
#define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
|
||||
|
||||
static inline u32 *
|
||||
lsa_get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
|
||||
{
|
||||
@ -575,6 +580,29 @@ lsa_get_ipv6_addr(u32 *buf, ip_addr *addr)
|
||||
return buf + 4;
|
||||
}
|
||||
|
||||
static inline u32 *
|
||||
put_ipv6_prefix(u32 *buf, ip_addr addr, u8 pxlen, u8 pxopts, u16 lh)
|
||||
{
|
||||
*buf++ = ((pxlen << 24) | (pxopts << 16) | lh);
|
||||
|
||||
if (pxlen > 0)
|
||||
*buf++ = _I0(addr);
|
||||
if (pxlen > 32)
|
||||
*buf++ = _I1(addr);
|
||||
if (pxlen > 64)
|
||||
*buf++ = _I2(addr);
|
||||
if (pxlen > 96)
|
||||
*buf++ = _I3(addr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline u32 *
|
||||
put_ipv6_addr(u32 *buf, ip_addr addr)
|
||||
{
|
||||
*(ip_addr *) buf = addr;
|
||||
return buf + 4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -286,6 +286,7 @@ ospf_rx_hook(sock * sk, int size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is strange! */
|
||||
if ((ifa->oa->areaid != 0) && (ntohl(ps->areaid) == 0))
|
||||
{
|
||||
WALK_LIST(iff, po->iface_list)
|
||||
@ -300,17 +301,16 @@ ospf_rx_hook(sock * sk, int size)
|
||||
|
||||
DBG("%s: RX_Hook called on interface %s.\n", p->name, sk->iface->name);
|
||||
|
||||
osize = ntohs(ps->length);
|
||||
|
||||
if ((unsigned) size < sizeof(struct ospf_packet))
|
||||
{
|
||||
log(L_ERR "%s%I - too short (%u bytes)", mesg, sk->faddr, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((osize > size) || (osize != (4 * (osize / 4))))
|
||||
osize = ntohs(ps->length);
|
||||
if ((osize > size) || ((osize % 4) != 0))
|
||||
{
|
||||
log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, ntohs(ps->length), size );
|
||||
log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -324,7 +324,7 @@ ospf_rx_hook(sock * sk, int size)
|
||||
#ifdef OSPFv2
|
||||
if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
|
||||
(!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
|
||||
ntohs(ps->length) - sizeof(struct ospf_packet), NULL)))
|
||||
osize - sizeof(struct ospf_packet), NULL)))
|
||||
{
|
||||
log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
|
||||
return 1;
|
||||
@ -358,17 +358,17 @@ ospf_rx_hook(sock * sk, int size)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (((unsigned) size > sk->rbsize) || (ntohs(ps->length) > sk->rbsize))
|
||||
if ((unsigned) size > sk->rbsize)
|
||||
{
|
||||
log(L_ERR "%s%I - packet is too large (%d-%d vs %d)",
|
||||
mesg, sk->faddr, size, ntohs(ps->length), sk->rbsize);
|
||||
log(L_ERR "%s%I - packet is too large (%d vs %d)",
|
||||
mesg, sk->faddr, size, sk->rbsize);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is deviation from RFC 2328 - neighbours should be identified by
|
||||
* IP address on broadcast and NBMA networks.
|
||||
*/
|
||||
n = find_neigh(ifa, ntohl(((struct ospf_packet *) ps)->routerid));
|
||||
n = find_neigh(ifa, ntohl(ps->routerid));
|
||||
|
||||
if(!n && (ps->type != HELLO_P))
|
||||
{
|
||||
|
@ -133,37 +133,6 @@ lsab_end(struct proto_ospf *po)
|
||||
return ((byte *) po->lsab) + po->lsab_used;
|
||||
}
|
||||
|
||||
#ifdef OSPFv3
|
||||
|
||||
#define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
|
||||
#define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
|
||||
|
||||
static inline u32 *
|
||||
put_ipv6_prefix(u32 *buf, ip_addr addr, u8 pxlen, u8 pxopts, u16 lh)
|
||||
{
|
||||
*buf++ = ((pxlen << 24) | (pxopts << 16) | lh);
|
||||
|
||||
if (pxlen > 0)
|
||||
*buf++ = _I0(addr);
|
||||
if (pxlen > 32)
|
||||
*buf++ = _I1(addr);
|
||||
if (pxlen > 64)
|
||||
*buf++ = _I2(addr);
|
||||
if (pxlen > 96)
|
||||
*buf++ = _I3(addr);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
static inline u32 *
|
||||
put_ipv6_addr(u32 *buf, ip_addr addr)
|
||||
{
|
||||
*(ip_addr *) buf = addr;
|
||||
return buf + 4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
configured_stubnet(struct ospf_area *oa, struct ifa *a)
|
||||
|
Loading…
Reference in New Issue
Block a user