]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Implements better checks on incoming packets and LSAs in OSPF.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 29 Oct 2009 22:57:42 +0000 (23:57 +0100)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 29 Oct 2009 22:57:42 +0000 (23:57 +0100)
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/lsack.c
proto/ospf/lsalib.c
proto/ospf/lsalib.h
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/topology.c

index c9d318c65ec10be2885eea5ce6d028a160f8496d..2cb2dd8d92b100bff5cfc8b155b8aa6a5f2f55ca 100644 (file)
@@ -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);
   
index 783761fe1dfc8ae329e9d6706a41ec7215916fdd..855b07008543583f5857c5eb58a35573ba6f7327 100644 (file)
@@ -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);
index 2aafd9d4496b9cfcfb564b76ab761c02f28d0785..857f0c12695bbdcc6a5f54810bfd78f5b65b9948 100644 (file)
@@ -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);
index 64e94a92ec6827cef1d328d7e455bd200dfbd4f3..7ee3aa4bdf52ed843ff1bf0948feb9a2a7dd7f15 100644 (file)
@@ -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
index 640fa1731b69f05b13cc60b57a05a99120faaa98..ed929beb28b8450181082784868241eb5db889a8 100644 (file)
@@ -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);
index 1b5da273f13a0068c5da3ff904319224034c1d2d..6785644245ed4b1207a6f1326a5a7f05ddc5d354 100644 (file)
@@ -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);
index 5278f1b20e9fed306934dd03e09f0e14229df250..7ae2f2a2f1e1dba49ce3183f189296eaed218129 100644 (file)
@@ -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");
 
index d826c734236bac1355b1a23efe994b22cf94d33b..3e33e453e18f0f908c0cf8d0bc903fa960d42907 100644 (file)
@@ -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
 
 
index 0bb1f511412bc0c69eab805c5a6cd14c28d323c3..9422a9f3dce722d0c14f2bc8efdaf84dd0bca365 100644 (file)
@@ -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))
   {
index 24b274e1f073a1c52d9168e5053a3856016d4b39..5d437d954cd391e96f78d5133e40dd8126a174e5 100644 (file)
@@ -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)