diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2009-10-29 23:57:42 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2009-10-29 23:57:42 +0100 |
commit | a6bc04d59130c49a1dbfadffa4285b11e2ff4939 (patch) | |
tree | b5f453dc5fbe20204883149e1bc153905f356709 | |
parent | 9d4d38d1a5d67f5485d2b2fa439c879583dfdcb0 (diff) |
Implements better checks on incoming packets and LSAs in OSPF.
-rw-r--r-- | proto/ospf/dbdes.c | 12 | ||||
-rw-r--r-- | proto/ospf/hello.c | 18 | ||||
-rw-r--r-- | proto/ospf/lsack.c | 28 | ||||
-rw-r--r-- | proto/ospf/lsalib.c | 213 | ||||
-rw-r--r-- | proto/ospf/lsalib.h | 1 | ||||
-rw-r--r-- | proto/ospf/lsreq.c | 21 | ||||
-rw-r--r-- | proto/ospf/lsupd.c | 69 | ||||
-rw-r--r-- | proto/ospf/ospf.h | 28 | ||||
-rw-r--r-- | proto/ospf/packet.c | 18 | ||||
-rw-r--r-- | proto/ospf/topology.c | 31 |
10 files changed, 339 insertions, 100 deletions
diff --git a/proto/ospf/dbdes.c b/proto/ospf/dbdes.c index c9d318c6..2cb2dd8d 100644 --- a/proto/ospf/dbdes.c +++ b/proto/ospf/dbdes.c @@ -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); diff --git a/proto/ospf/hello.c b/proto/ospf/hello.c index 783761fe..855b0700 100644 --- a/proto/ospf/hello.c +++ b/proto/ospf/hello.c @@ -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); diff --git a/proto/ospf/lsack.c b/proto/ospf/lsack.c index 2aafd9d4..857f0c12 100644 --- a/proto/ospf/lsack.c +++ b/proto/ospf/lsack.c @@ -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 proto *p = &ifa->oa->po->proto; 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; + 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); diff --git a/proto/ospf/lsalib.c b/proto/ospf/lsalib.c index 64e94a92..7ee3aa4b 100644 --- a/proto/ospf/lsalib.c +++ b/proto/ospf/lsalib.c @@ -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 diff --git a/proto/ospf/lsalib.h b/proto/ospf/lsalib.h index 640fa173..ed929beb 100644 --- a/proto/ospf/lsalib.h +++ b/proto/ospf/lsalib.h @@ -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); diff --git a/proto/ospf/lsreq.c b/proto/ospf/lsreq.c index 1b5da273..67856442 100644 --- a/proto/ospf/lsreq.c +++ b/proto/ospf/lsreq.c @@ -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); diff --git a/proto/ospf/lsupd.c b/proto/ospf/lsupd.c index 5278f1b2..7ae2f2a2 100644 --- a/proto/ospf/lsupd.c +++ b/proto/ospf/lsupd.c @@ -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,50 +407,51 @@ 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; - OSPF_PACKET(ospf_dump_lsupd, ps, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name); - - if (n->state < NEIGHBOR_EXCHANGE) + unsigned int size = ntohs(ps_i->length); + if (size < (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header))) { - OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", n->ip); + log(L_ERR "Bad OSPF LSUPD packet from %I - too short (%u B)", n->ip, size); return; } - if (size <= - (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header))) + 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) { - log(L_WARN "Received lsupd from %I is too short!", n->ip); + OSPF_TRACE(D_PACKETS, "Received lsupd in lesser state than EXCHANGE from (%I)", 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"); diff --git a/proto/ospf/ospf.h b/proto/ospf/ospf.h index d826c734..3e33e453 100644 --- a/proto/ospf/ospf.h +++ b/proto/ospf/ospf.h @@ -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 diff --git a/proto/ospf/packet.c b/proto/ospf/packet.c index 0bb1f511..9422a9f3 100644 --- a/proto/ospf/packet.c +++ b/proto/ospf/packet.c @@ -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)) { diff --git a/proto/ospf/topology.c b/proto/ospf/topology.c index 24b274e1..5d437d95 100644 --- a/proto/ospf/topology.c +++ b/proto/ospf/topology.c @@ -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) |