]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary integrated commit (OSPF), unfinished.
authorOndrej Zajicek <santiago@crfreenet.org>
Tue, 2 Oct 2012 09:44:05 +0000 (11:44 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Tue, 2 Oct 2012 09:44:05 +0000 (11:44 +0200)
19 files changed:
lib/ip.h
proto/ospf/config.Y
proto/ospf/dbdes.c
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsack.c
proto/ospf/lsalib.c
proto/ospf/lsalib.h
proto/ospf/lsreq.c
proto/ospf/lsupd.c
proto/ospf/lsupd.h
proto/ospf/neighbor.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/packet.h
proto/ospf/rt.c
proto/ospf/topology.c
proto/ospf/topology.h

index 056207f9cc990f116ffa4aa523285b58ef216bcf..e38137e69a032fc4733051926ef76b29e63e615c 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
 #define IP4_MIN_MTU            576     /* RFC 2328 A.1 */
 #define IP6_MIN_MTU            1280    /* RFC 5340 A.1 */
 
-#define IP4_ALL_SPF_ROUTERS    ipa_build4(224, 0, 0, 5)
-#define IP4_ALL_D_ROUTERS      ipa_build4(224, 0, 0, 6)
+#define IP4_OSPF_ALL_ROUTERS   ipa_build4(224, 0, 0, 5)
+#define IP4_OSPF_DES_ROUTERS   ipa_build4(224, 0, 0, 6)
 
-#define IP6_All_NODES          ipa_build6(0xFF020000, 0, 0, 1)
+#define IP6_ALL_NODES          ipa_build6(0xFF020000, 0, 0, 1)
 #define IP6_ALL_ROUTERS                ipa_build6(0xFF020000, 0, 0, 2)
-#define IP6_ALL_OSPF_ROUTERS   ipa_build6(0xFF020000, 0, 0, 5)
-#define IP6_ALL_OSPF_D_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
+#define IP6_OSPF_ALL_ROUTERS   ipa_build6(0xFF020000, 0, 0, 5)
+#define IP6_OSPF_DES_ROUTERS   ipa_build6(0xFF020000, 0, 0, 6)
 
 #define IP4_NONE _MI4(0)
 #define IP6_NONE _MI6(0,0,0,0)
index 40d3f1f14a8873139f164e4bc909a0a853abbaee..46e78761332ea91f6a0014962f47aeb144b371d1 100644 (file)
@@ -143,8 +143,7 @@ ospf_proto_start: proto_start OSPF {
      this_proto = proto_config_new(&proto_ospf, sizeof(struct ospf_config), $1);
      init_list(&OSPF_CFG->area_list);
      init_list(&OSPF_CFG->vlink_list);
-     OSPF_CFG->rfc1583 = DEFAULT_RFC1583;
-     OSPF_CFG->tick = DEFAULT_OSPFTICK;
+     OSPF_CFG->tick = OSPF_DEFAULT_TICK;
   }
  ;
 
@@ -166,9 +165,9 @@ ospf_area_start: AREA idval {
   this_area = cfg_allocz(sizeof(struct ospf_area_config));
   add_tail(&OSPF_CFG->area_list, NODE this_area);
   this_area->areaid = $2;
-  this_area->default_cost = DEFAULT_STUB_COST;
+  this_area->default_cost = OSPF_DEFAULT_STUB_COST;
   this_area->type = OPT_E;
-  this_area->transint = DEFAULT_TRANSINT;
+  this_area->transint = OSPF_DEFAULT_TRANSINT;
 
   init_list(&this_area->patt_list);
   init_list(&this_area->net_list);
index e1e0e81f9171d36ca6c7216e6e9e22d5fb866fdb..120c20e8501024a91a3e9810fc05662b4095f6f8 100644 (file)
@@ -36,20 +36,6 @@ struct ospf_dbdes3_packet
 };
 
 
-
-#ifdef OSPFv2
-
-#define hton_opt(X) X
-#define ntoh_opt(X) X
-#endif
-
-
-#ifdef OSPFv3
-
-#define hton_opt(X) htonl(X)
-#define ntoh_opt(X) ntohl(X)
-#endif
-
 static inline unsigned
 ospf_dbdes_hdrlen(struct proto_ospf *po)
 {
@@ -69,30 +55,113 @@ ospf_dbdes_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
   
 static void ospf_dbdes_dump(struct proto_ospf *po, struct ospf_packet *pkt)
 {
-  struct proto *p = &po->proto;
   struct ospf_lsa_header *lsas;
   unsigned i, lsa_count;
+  u32 pkt_ddseq;
+  u16 pkt_iface_mtu;
+  u8 pkt_imms;
 
   ASSERT(pkt->type == DBDES_P);
   ospf_dump_common(po, pkt);
 
-  log(L_TRACE "%s:     imms     %s%s%s", p->name,
-      (imms & DBDES_I) ? "I " : "",
-      (imms & DBDES_M) ? "M " : "",
-      (imms & DBDES_MS) ? "MS" : "");
-  log(L_TRACE "%s:     ddseq    %u", p->name, ntohl(pkt->ddseq));
-
-  struct ospf_lsa_header *plsa = (void *) (pkt + 1);
-  unsigned int i, j;
+  if (ospf_is_v2(po))
+  {
+    struct ospf_dbdes2_packet *ps = (void *) pkt;
+    pkt_iface_mtu = ntohs(ps->iface_mtu);
+    pkt_imms = ps->imms;
+    pkt_ddseq = ntohl(ps->ddseq);
+  }
+  else /* OSPFv3 */
+  {
+    struct ospf_dbdes3_packet *ps = (void *) pkt;
+    pkt_iface_mtu = ntohs(ps->iface_mtu);
+    pkt_imms = ps->imms;
+    pkt_ddseq = ntohl(ps->ddseq);
+  }
 
-  j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
-    sizeof(struct ospf_lsa_header);
+  log(L_TRACE "%s:     mtu      %u", po->proto.name, pkt_iface_mtu);
+  log(L_TRACE "%s:     imms     %s%s%s", po->proto.name,
+      (pkt_imms & DBDES_I) ? "I " : "",
+      (pkt_imms & DBDES_M) ? "M " : "",
+      (pkt_imms & DBDES_MS) ? "MS" : "");
+  log(L_TRACE "%s:     ddseq    %u", po->proto.name, pkt_ddseq);
 
-  for (i = 0; i < j; i++)
-    ospf_dump_lsahdr(p, &lsas[i]);
+  ospf_dbdes_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
+  for (i = 0; i < lsa_count; i++)
+    ospf_dump_lsahdr(po, lsas + i);
 }
 
 
+static void
+ospf_dbdes_prepare(struct ospf_neighbor *n, struct ospf_packet *pkt, int lsdb)
+{
+  struct ospf_iface *ifa = n->ifa;
+  struct proto_ospf *po = ifa->oa->po;
+  int i = 0;
+
+  ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
+
+  if (lsdb && (n->myimms & DBDES_M))
+  {
+    struct ospf_lsa_header *lsas;
+    unsigned lsa_max;
+    snode *sn;
+
+    ospf_dbdes_body(po, pkt, ospf_pkt_maxsize(ifa), &lsas, &lsa_max);
+    sn = s_get(&(n->dbsi));
+
+    while (i < lsa_max)
+    {
+      struct top_hash_entry *en = (struct top_hash_entry *) sn;
+
+      if (lsa_flooding_allowed(en->lsa_type, en->domain, ifa))
+      {
+       lsa_hton_hdr(&(en->lsa), lsas + i);
+       i++;
+      }
+
+      if (sn == STAIL(po->lsal))
+      {
+       n->myimms &= ~DBDES_M;  /* Unset more bit */
+       break;
+      }
+
+      sn = sn->next;
+    }
+
+    s_put(&(n->dbsi), sn);
+  }
+
+  u16 iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : ifa->iface->mtu;
+  unsigned length;
+
+  if (ospf_is_v2(po))
+  {
+    struct ospf_dbdes2_packet *ps = (void *) pkt;
+
+    ps->iface_mtu = htons(iface_mtu);
+    ps->options = ifa->oa->options;
+    ps->imms = n->myimms;
+    ps->ddseq = htonl(n->dds);
+
+    length = sizeof(struct ospf_dbdes2_packet);
+  }
+  else /* OSPFv3 */
+  {
+    struct ospf_dbdes3_packet *ps = (void *) pkt;
+
+    ps->options = htonl(ifa->oa->options);
+    ps->iface_mtu = htons(iface_mtu);
+    ps->imms = n->myimms;
+    ps->ddseq = htonl(n->dds);
+
+    length = sizeof(struct ospf_dbdes3_packet);
+  }
+
+  length += i * sizeof(struct ospf_lsa_header);
+  pkt->length = htons(length);
+}
+
 /**
  * ospf_dbdes_send - transmit database description packet
  * @n: neighbor
@@ -110,10 +179,8 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
   struct ospf_iface *ifa = n->ifa;
   struct ospf_area *oa = ifa->oa;
   struct proto_ospf *po = oa->po;
-
-  struct ospf_dbdes_packet *pkt;
-  struct ospf_packet *op;
-  u16 length, i, j;
+  struct ospf_packet *pkt;
+  unsigned length;
 
   /* FIXME ??? */
   if ((oa->rt == NULL) || (EMPTY_LIST(po->lsal)))
@@ -121,19 +188,13 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
 
   switch (n->state)
   {
-  case NEIGHBOR_EXSTART:       /* Send empty packets */
+  case NEIGHBOR_EXSTART:
     n->myimms |= DBDES_I;
+
+    /* Send empty packets */
     pkt = ospf_tx_buffer(ifa);
-    op = &pkt->ospf_packet;
-    ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
-    pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu);
-    pkt->options = hton_opt(oa->options);
-    pkt->imms = n->myimms;
-    pkt->ddseq = htonl(n->dds);
-    length = sizeof(struct ospf_dbdes_packet);
-    op->length = htons(length);
-
-    OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
+    ospf_dbdes_prepare(n, pkt, 0);
+    OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
     ospf_send_to(ifa, n->ip);
     break;
 
@@ -141,72 +202,12 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
     n->myimms &= ~DBDES_I;
 
     if (next)
-    {
-      snode *sn;
-      struct ospf_lsa_header *lsa;
-
-      pkt = n->ldbdes;
-      op = (struct ospf_packet *) pkt;
-
-      ospf_pkt_fill_hdr(ifa, pkt, DBDES_P);
-      pkt->iface_mtu = (ifa->type == OSPF_IT_VLINK) ? 0 : htons(ifa->iface->mtu);
-      pkt->ddseq = htonl(n->dds);
-      pkt->options = hton_opt(oa->options);
-
-      j = i = (ospf_pkt_maxsize(ifa) - sizeof(struct ospf_dbdes_packet)) / sizeof(struct ospf_lsa_header);     /* Number of possible lsaheaders to send */
-      lsa = (n->ldbdes + sizeof(struct ospf_dbdes_packet));
-
-      if (n->myimms & DBDES_M)
-      {
-       sn = s_get(&(n->dbsi));
-
-       DBG("Number of LSA: %d\n", j);
-       for (; i > 0; i--)
-       {
-         struct top_hash_entry *en= (struct top_hash_entry *) sn;
-
-          if (ospf_lsa_flooding_allowed(&en->lsa, en->domain, ifa))
-          {
-           htonlsah(&(en->lsa), lsa);
-           DBG("Working on: %d\n", i);
-           DBG("\tX%01x %-1R %-1R %p\n", en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa_body);
-
-           lsa++;
-          }
-          else i++;    /* No lsa added */
-
-         if (sn == STAIL(po->lsal))
-          {
-            i--;
-           break;
-          }
-
-         sn = sn->next;
-       }
-
-       if (sn == STAIL(po->lsal))
-       {
-         DBG("Number of LSA NOT sent: %d\n", i);
-         DBG("M bit unset.\n");
-         n->myimms &= ~DBDES_M;        /* Unset more bit */
-       }
-
-       s_put(&(n->dbsi), sn);
-      }
-
-      pkt->imms = n->myimms;
-
-      length = (j - i) * sizeof(struct ospf_lsa_header) +
-       sizeof(struct ospf_dbdes_packet);
-      op->length = htons(length);
-
-      DBG("%s: DB_DES (M) prepared for %I.\n", p->name, n->ip);
-    }
+      ospf_dbdes_prepare(n, n->ldbdes, 1);
 
   case NEIGHBOR_LOADING:
   case NEIGHBOR_FULL:
-    length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
 
+    length = ntohs(((struct ospf_packet *) n->ldbdes)->length);
     if (!length)
     {
       OSPF_TRACE(D_PACKETS, "No packet in my buffer for repeating");
@@ -218,21 +219,19 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
     pkt = ospf_tx_buffer(ifa);
     memcpy(pkt, n->ldbdes, length);
 
-    OSPF_PACKET(ospf_dump_dbdes, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
+    OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet sent to %I via %s", n->ip, ifa->iface->name);
     ospf_send_to(ifa, n->ip);
 
+    /* XXXX remove this? */
     if (n->myimms & DBDES_MS)
       tm_start(n->rxmt_timer, n->ifa->rxmtint);                /* Restart timer */
 
     if (!(n->myimms & DBDES_MS))
-    {
       if (!(n->myimms & DBDES_M) && 
          !(n->imms & DBDES_M) &&
          (n->state == NEIGHBOR_EXCHANGE))
-      {
        ospf_neigh_sm(n, INM_EXDONE);
-      }
-    }
+
     break;
 
   default:                     /* Ignore it */
@@ -241,36 +240,35 @@ ospf_dbdes_send(struct ospf_neighbor *n, int next)
 }
 
 static void
-ospf_dbdes_reqladd(struct ospf_dbdes_packet *ps, struct ospf_neighbor *n)
+ospf_dbdes_process(struct ospf_neighbor *n, struct ospf_packet *pkt, unsigned plen)
 {
-  struct ospf_lsa_header *plsa, lsa;
-  struct top_hash_entry *he, *sn;
-  struct ospf_area *oa = n->ifa->oa;
-  struct top_graph *gr = oa->po->gr;
-  struct ospf_packet *op;
-  int i, j;
+  struct ospf_iface *ifa = n->ifa;
+  struct proto_ospf *po = ifa->oa->po;
+  struct ospf_lsa_header *lsas;
+  unsigned i, lsa_count;
+
+  ospf_dbdes_body(po, pkt, plen, &lsas, &lsa_count);
 
-  op = (struct ospf_packet *) ps;
+  for (i = 0; i < lsa_count; i++)
+  {
+    struct top_hash_entry *en, *req;
+    struct ospf_lsa_header lsa;
+    u32 lsa_type, lsa_domain;
 
-  plsa = (void *) (ps + 1);
+    lsa_ntoh_hdr(lsas + i, &lsa);
+    lsa_xxxxtype(lsa.type_raw, ifa, &lsa_type, &lsa_domain);
 
-  j = (ntohs(op->length) - sizeof(struct ospf_dbdes_packet)) /
-    sizeof(struct ospf_lsa_header);
+    /* XXXX: Add check for 0-type or flooding_allowed */
 
-  for (i = 0; i < j; i++)
-  {
-    ntohlsah(plsa + i, &lsa);
-    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
-    if (((he = ospf_hash_find_header(gr, dom, &lsa)) == NULL) ||
-       (lsa_comp(&lsa, &(he->lsa)) == 1))
+    en = ospf_hash_find(po->gr, lsa_domain, lsa.id, lsa.rt, lsa_type);
+    if (!en || (lsa_comp(&lsa, &(en->lsa)) == CMP_NEWER))
     {
-      /* Is this condition necessary? */
-      if (ospf_hash_find_header(n->lsrqh, dom, &lsa) == NULL)
-      {
-       sn = ospf_hash_get_header(n->lsrqh, dom, &lsa);
-       ntohlsah(plsa + i, &(sn->lsa));
-       s_add_tail(&(n->lsrql), SNODE sn);
-      }
+      req = ospf_hash_get(n->lsrqh, lsa_domain, lsa.id, lsa.rt, lsa_type);
+
+      if (ospf_hash_is_new(req))
+       s_add_tail(&(n->lsrql), SNODE req);
+
+      en->lsa = lsa;
     }
   }
 }
@@ -280,19 +278,22 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
                   struct ospf_neighbor *n)
 {
   struct proto_ospf *po = ifa->oa->po;
-
   u32 rcv_ddseq, rcv_options;
   u16 rcv_iface_mtu;
   u8 rcv_imms;
+  unsigned plen;
 
-
-  unsigned int size = ntohs(ps_i->length);
-  if (size < sizeof(struct ospf_dbdes_packet))
+  plen = ntohs(pkt->length);
+  if (plen < ospf_dbdes_hdrlen(po))
   {
-    log(L_ERR "Bad OSPF DBDES packet from %I -  too short (%u B)", n->ip, size);
+    log(L_ERR "OSPF: Bad DBDES packet from %I - too short (%u B)", n->ip, plen);
     return;
   }
 
+  OSPF_PACKET(ospf_dbdes_dump, pkt, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
+
+  ospf_neigh_sm(n, INM_HELLOREC);
+
   if (ospf_is_v2(po))
   {
     struct ospf_dbdes2_packet *ps = (void *) pkt;
@@ -310,10 +311,6 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
     rcv_ddseq = ntohl(ps->ddseq);
   }
   
-  OSPF_PACKET(ospf_dbdes_dump, ps, "DBDES packet received from %I via %s", n->ip, ifa->iface->name);
-
-  ospf_neigh_sm(n, INM_HELLOREC);
-
   switch (n->state)
   {
   case NEIGHBOR_DOWN:
@@ -331,12 +328,12 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_iface_mtu != 0) &&
        (ifa->iface->mtu != 0) && 
        (ifa->type != OSPF_IT_VLINK))
-      log(L_WARN "OSPF: MTU mismatch with neighbour %I on interface %s (remote %d, local %d)",
+      log(L_WARN "OSPF: MTU mismatch with neighbor %I on interface %s (remote %d, local %d)",
          n->ip, ifa->iface->name, rcv_iface_mtu, ifa->iface->mtu);
 
     if ((rcv_imms == DBDES_IMMS) &&
        (n->rid > po->router_id) &&
-       (size == sizeof(struct ospf_dbdes_packet)))
+       (plen == ospf_dbdes_hdrlen(po)))
     {
       /* I'm slave! */
       n->dds = rcv_ddseq;
@@ -374,7 +371,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_ddseq == n->ddr))
     {
       /* Duplicate packet */
-      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
+      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
       if (!(n->myimms & DBDES_MS))
       {
        /* Slave should retransmit dbdes packet */
@@ -417,7 +414,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
       }
       n->dds++;
       DBG("Incrementing dds\n");
-      ospf_dbdes_reqladd(ps, n);
+      ospf_dbdes_process(n, pkt, plen);
       if (!(n->myimms & DBDES_M) &&
          !(rcv_imms & DBDES_M))
       {
@@ -439,7 +436,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
       }
       n->ddr = rcv_ddseq;
       n->dds = rcv_ddseq;
-      ospf_dbdes_reqladd(ps, n);
+      ospf_dbdes_process(n, pkt, plen);
       ospf_dbdes_send(n, 1);
     }
     break;
@@ -451,7 +448,7 @@ ospf_dbdes_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
        (rcv_ddseq == n->ddr))
       /* Only duplicate are accepted */
     {
-      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I.", n->ip);
+      OSPF_TRACE(D_PACKETS, "Received duplicate dbdes from %I", n->ip);
       if (!(n->myimms & DBDES_MS))
       {
        /* Slave should retransmit dbdes packet */
index b699dd7e59c1c90da3346c51d924469cc29f04b0..08ad6f919a7daee0e8cd433414d9e55c49ed116b 100644 (file)
@@ -48,7 +48,6 @@ ospf_hello_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
                   struct ospf_neighbor *n, ip_addr faddr)
 {
   struct proto_ospf *po = ifa->oa->po;
-  struct proto *p = &po->proto;
   char *beg = "OSPF: Bad HELLO packet from ";
   unsigned int size, i, two_way;
 
index e004c05e785a8dd3fe3591a39013c106cb59d033..d029545b972ea0b8c0cb4a35afa22652bc224099 100644 (file)
@@ -72,6 +72,8 @@ find_nbma_node_in(list *nnl, ip_addr ip)
 static int
 ospf_sk_open(struct ospf_iface *ifa)
 {
+  struct proto_ospf *po = ifa->oa->po;
+
   sock *sk = sk_new(ifa->pool);
   sk->type = SK_IP;
   sk->dport = OSPF_PROTO;
@@ -90,11 +92,10 @@ ospf_sk_open(struct ospf_iface *ifa)
   if (sk_open(sk) != 0)
     goto err;
 
-#ifdef OSPFv3
-  /* 12 is an offset of the checksum in an OSPF packet */
-  if (sk_set_ipv6_checksum(sk, 12) < 0)
-    goto err;
-#endif
+  /* 12 is an offset of the checksum in an OSPFv3 packet */
+  if (ospf_is_v3(po))
+    if (sk_set_ipv6_checksum(sk, 12) < 0)
+      goto err;
 
   /*
    * For OSPFv2: When sending a packet, it is important to have a
@@ -123,14 +124,16 @@ ospf_sk_open(struct ospf_iface *ifa)
     if (ifa->cf->real_bcast)
     {
       ifa->all_routers = ifa->addr->brd;
+      ifa->des_routers = IPA_NONE;
 
       if (sk_set_broadcast(sk, 1) < 0)
         goto err;
     }
     else
     {
-      ifa->all_routers = AllSPFRouters;
-      sk->ttl = 1;     /* Hack, this will affect just multicast packets */
+      ifa->all_routers = ospf_is_v2(po) ? IP4_OSPF_ALL_ROUTERS : IP6_OSPF_ALL_ROUTERS;
+      ifa->des_routers = ospf_is_v2(po) ? IP4_OSPF_DES_ROUTERS : IP6_OSPF_DES_ROUTERS;
+      sk->ttl = 1;     /* Hack, this will affect just the multicast packets */
 
       if (sk_setup_multicast(sk) < 0)
         goto err;
@@ -155,7 +158,7 @@ ospf_sk_join_dr(struct ospf_iface *ifa)
   if (ifa->sk_dr)
     return;
 
-  sk_join_group(ifa->sk, AllDRouters);
+  sk_join_group(ifa->sk, ifa->des_routers);
   ifa->sk_dr = 1;
 }
 
@@ -165,7 +168,7 @@ ospf_sk_leave_dr(struct ospf_iface *ifa)
   if (!ifa->sk_dr)
     return;
 
-  sk_leave_group(ifa->sk, AllDRouters);
+  sk_leave_group(ifa->sk, ifa->des_routers);
   ifa->sk_dr = 0;
 }
 
@@ -178,13 +181,15 @@ ospf_iface_down(struct ospf_iface *ifa)
 
   if (ifa->type != OSPF_IT_VLINK)
   {
-#ifdef OSPFv2
-    OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
-              ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
-#else
-    OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
-              ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
-#endif
+    if (ospf_is_v3(ifa->oa->po))
+      OSPF_TRACE(D_EVENTS, "Removing interface %s (IID %d) from area %R",
+                ifa->iface->name, ifa->instance_id, ifa->oa->areaid);
+    else if (ifa->addr->flags & IA_PEER)
+      OSPF_TRACE(D_EVENTS, "Removing interface %s (peer %I) from area %R",
+                ifa->iface->name, ifa->addr->opposite, ifa->oa->areaid);
+    else
+      OSPF_TRACE(D_EVENTS, "Removing interface %s (%I/%d) from area %R",
+                ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen, ifa->oa->areaid);
 
     /* First of all kill all the related vlinks */
     WALK_LIST(iff, po->iface_list)
@@ -221,10 +226,8 @@ ospf_iface_down(struct ospf_iface *ifa)
 
   ifa->rt_pos_beg = 0;
   ifa->rt_pos_end = 0;
-#ifdef OSPFv3
   ifa->px_pos_beg = 0;
   ifa->px_pos_end = 0;
-#endif
 }
 
 
@@ -275,7 +278,7 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
     OSPF_TRACE(D_EVENTS, "Changing state of iface %s from %s to %s",
               ifa->iface->name, ospf_is[oldstate], ospf_is[state]);
 
-  if ((ifa->type == OSPF_IT_BCAST) && !ifa->cf->real_bcast && ifa->sk)
+  if ((ifa->type == OSPF_IT_BCAST) && ipa_nonzero(ifa->des_routers) && ifa->sk)
   {
     if ((state == OSPF_IS_BACKUP) || (state == OSPF_IS_DR))
       ospf_sk_join_dr(ifa);
@@ -499,16 +502,15 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
 
   if (ip->type == OSPF_IT_VLINK)
     OSPF_TRACE(D_EVENTS, "Adding vlink to %R via area %R", ip->vid, ip->voa);
+  else if (ospf_is_v3(po))
+    OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
+              iface->name, ip->instance_id, oa->areaid);
+  else if (ifa->addr->flags & IA_PEER)
+    OSPF_TRACE(D_EVENTS, "Adding interface %s (peer %I) to area %R",
+              iface->name, addr->opposite, oa->areaid);
   else
-  {
-#ifdef OSPFv2
     OSPF_TRACE(D_EVENTS, "Adding interface %s (%I/%d) to area %R",
               iface->name, addr->prefix, addr->pxlen, oa->areaid);
-#else
-    OSPF_TRACE(D_EVENTS, "Adding interface %s (IID %d) to area %R",
-              iface->name, ip->instance_id, oa->areaid);
-#endif
-  }
 
   pool = rp_new(po->proto.pool, "OSPF Interface");
   ifa = mb_allocz(pool, sizeof(struct ospf_iface));
@@ -532,15 +534,9 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
   ifa->rxbuf = ip->rxbuf;
   ifa->check_link = ip->check_link;
   ifa->ecmp_weight = ip->ecmp_weight;
-
-#ifdef OSPFv2
   ifa->autype = ip->autype;
   ifa->passwords = ip->passwords;
-#endif
-
-#ifdef OSPFv3
   ifa->instance_id = ip->instance_id;
-#endif
 
   ifa->type = ospf_iface_classify(ip->type, addr);
 
@@ -548,13 +544,11 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
   int old_type = ifa->type;
   u32 if_multi_flag = ip->real_bcast ? IF_BROADCAST : IF_MULTICAST;
 
-#ifdef OSPFv2
-  if ((ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
+  if (ospf_is_v2(po) && (ifa->type == OSPF_IT_BCAST) && (addr->flags & IA_PEER))
     ifa->type = OSPF_IT_PTP;
 
-  if ((ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
+  if (ospf_is_v2(po) && (ifa->type == OSPF_IT_NBMA) && (addr->flags & IA_PEER))
     ifa->type = OSPF_IT_PTMP;
-#endif
 
   if ((ifa->type == OSPF_IT_BCAST) && !(iface->flags & if_multi_flag))
     ifa->type = OSPF_IT_NBMA;
@@ -564,7 +558,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
 
   if (ifa->type != old_type)
     log(L_WARN "%s: Cannot use interface %s as %s, forcing %s",
-       p->name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
+       po->proto.name, iface->name, ospf_it[old_type], ospf_it[ifa->type]);
 
 
   init_list(&ifa->neigh_list);
@@ -595,11 +589,7 @@ ospf_iface_new(struct ospf_area *oa, struct ifa *addr, struct ospf_iface_patt *i
    */
 
   lock = olock_new(pool);
-#ifdef OSPFv2
-  lock->addr = ifa->addr->prefix;
-#else /* OSPFv3 */
-  lock->addr = _MI(0,0,0,ifa->instance_id);
-#endif
+  lock->addr = ospf_is_v2(po) ? ifa->addr->prefix : _MI6(0,0,0,ifa->instance_id);
   lock->type = OBJLOCK_IP;
   lock->port = OSPF_PROTO;
   lock->iface = iface;
@@ -702,7 +692,6 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
     ifa->inftransdelay = new->inftransdelay;
   }
 
-#ifdef OSPFv2  
   /* AUTHENTICATION */
   if (ifa->autype != new->autype)
   {
@@ -712,7 +701,6 @@ ospf_iface_reconfigure(struct ospf_iface *ifa, struct ospf_iface_patt *new)
 
   /* Update passwords */
   ifa->passwords = new->passwords;
-#endif
 
   /* Remaining options are just for proper interfaces */
   if (ifa->type == OSPF_IT_VLINK)
@@ -1133,14 +1121,13 @@ ospf_iface_info(struct ospf_iface *ifa)
   }
   else
   {
-#ifdef OSPFv2
-    if (ifa->addr->flags & IA_PEER)
+    if (ospf_is_v3(ifa->oa->po))
+      cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
+    else if (ifa->addr->flags & IA_PEER)
       cli_msg(-1015, "Interface %s (peer %I)", ifa->iface->name, ifa->addr->opposite);
     else
       cli_msg(-1015, "Interface %s (%I/%d)", ifa->iface->name, ifa->addr->prefix, ifa->addr->pxlen);
-#else /* OSPFv3 */
-    cli_msg(-1015, "Interface %s (IID %d)", ifa->iface->name, ifa->instance_id);
-#endif
+
     cli_msg(-1015, "\tType: %s%s", ospf_it[ifa->type], more);
     cli_msg(-1015, "\tArea: %R (%u)", ifa->oa->areaid, ifa->oa->areaid);
   }
index dc59dde081047b38538f1dd9a946196356045d75..35ddfec6387abf79fa6c52b643257e904952ebe8 100644 (file)
@@ -96,10 +96,8 @@ ospf_lsack_send_one(struct ospf_neighbor *n, int queue)
   {
     if ((ifa->state == OSPF_IS_DR) || (ifa->state == OSPF_IS_BACKUP))
       ospf_send_to_all(ifa);
-    else if (ifa->cf->real_bcast)
-      ospf_send_to_bdr(ifa);
     else
-      ospf_send_to(ifa, AllDRouters);
+      ospf_send_to_des(ifa);
   }
   else
     ospf_send_to_agt(ifa, NEIGHBOR_EXCHANGE);
@@ -127,6 +125,7 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
   struct ospf_lsa_header lsa, *lsas;
   struct top_hash_entry *en;
   unsigned i, lsa_count;
+  u32 lsa_dom, lsa_type;
 
 
   /* No need to check length, lsack has only basic header */
@@ -142,9 +141,11 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
   ospf_lsack_body(po, pkt, ntohs(pkt->length), &lsas, &lsa_count);
   for (i = 0; i < lsa_count; i++)
   {
-    ntohlsah(&lsas[i], &lsa);
-    u32 dom = ospf_lsa_domain(lsa.type, n->ifa);
-    if ((en = ospf_hash_find_header(n->lsrth, dom, &lsa)) == NULL)
+    lsa_ntoh_hdr(&lsas[i], &lsa);
+    lsa_xxxxtype(lsa.type_raw, n->ifa, &lsa_type, &lsa_dom);
+
+    en = ospf_hash_find(n->lsrth, lsa_dom, lsa.id, lsa.rt, lsa_type);
+    if (!en)
       continue;                        /* pg 155 */
 
     if (lsa_comp(&lsa, &en->lsa) != CMP_SAME)  /* pg 156 */
@@ -154,7 +155,7 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
       OSPF_TRACE(D_PACKETS, "Strange LSACK from %I", n->ip);
       OSPF_TRACE(D_PACKETS, "Type: %04x, Id: %R, Rt: %R",
-                lsa.type, lsa.id, lsa.rt);
+                lsa_type, lsa.id, lsa.rt);
       OSPF_TRACE(D_PACKETS, "I have: Age: %4u, Seq: %08x, Sum: %04x",
                 en->lsa.age, en->lsa.sn, en->lsa.checksum);
       OSPF_TRACE(D_PACKETS, "He has: Age: %4u, Seq: %08x, Sum: %04x",
@@ -162,8 +163,8 @@ ospf_lsack_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
       continue;
     }
 
-    DBG("Deleting LS Id: %R RT: %R Type: %u from LS Retl for neighbor %R\n",
-       lsa.id, lsa.rt, lsa.type, n->rid);
+    DBG("Deleting LSA (Type: %04x Id: %R Rt: %R) from lsrtl for neighbor %R\n",
+       lsa_type, lsa.id, lsa.rt, n->rid);
     s_rem_node(SNODE en);
     ospf_hash_delete(n->lsrth, en);
   }
index 00dd2893a6e14965eae8f873b8a9447943b90305..aa3dc7411e66a15d4071594c35cbf09155b37c30 100644 (file)
@@ -89,10 +89,10 @@ ospf_age(struct proto_ospf *po)
 
 #ifndef CPU_BIG_ENDIAN
 void
-htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
+lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
 {
   n->age = htons(h->age);
-  n->type_raw = htont(h->type_raw);
+  n->type_raw = htons(h->type_raw);
   n->id = htonl(h->id);
   n->rt = htonl(h->rt);
   n->sn = htonl(h->sn);
@@ -101,10 +101,10 @@ htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
 }
 
 void
-ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
+lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
 {
   h->age = ntohs(n->age);
-  h->type_raw = ntoht(n->type_raw);
+  h->type_raw = ntohs(n->type_raw);
   h->id = ntohl(n->id);
   h->rt = ntohl(n->rt);
   h->sn = ntohl(n->sn);
@@ -113,7 +113,7 @@ ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
 }
 
 void
-htonlsab(void *h, void *n, u16 len)
+lsa_hton_body(void *h, void *n, u16 len)
 {
   u32 *hid = h;
   u32 *nid = n;
@@ -124,7 +124,7 @@ htonlsab(void *h, void *n, u16 len)
 }
 
 void
-ntohlsab(void *n, void *h, u16 len)
+lsa_ntoh_body(void *n, void *h, u16 len)
 {
   u32 *nid = n;
   u32 *hid = h;
@@ -135,6 +135,95 @@ ntohlsab(void *n, void *h, u16 len)
 }
 #endif /* little endian */
 
+
+
+int
+lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa)
+{    
+  /* 4.5.2 (Case 2) */
+
+  switch (LSA_SCOPE(type))
+  {
+  case LSA_SCOPE_LINK:
+    return ifa->iface->index == domain;
+
+  case LSA_SCOPE_AREA:
+    return ifa->oa->areaid == domain;
+
+  case LSA_SCOPE_AS:
+    if (ifa->type == OSPF_IT_VLINK)
+      return 0;
+    if (!oa_is_ext(ifa->oa))
+      return 0;
+    return 1;
+
+  default:
+    log(L_ERR "OSPF: LSA with invalid scope");
+    return 0;
+  }
+}
+
+
+static int
+unknown_lsa_type(u32 type)
+{
+  switch (type)
+  {
+  case LSA_T_RT:
+  case LSA_T_NET:
+  case LSA_T_SUM_NET:
+  case LSA_T_SUM_RT:
+  case LSA_T_EXT:
+  case LSA_T_NSSA:
+  case LSA_T_LINK:
+  case LSA_T_PREFIX:
+    return 0;
+
+  default:
+    return 1;
+  }
+}
+
+#define LSA_V2_TMAX 8
+static const u16 lsa_v2_types[LSA_V2_TMAX] =
+  {0, LSA_T_RT, LSA_T_NET, LSA_T_SUM_NET, LSA_T_SUM_RT, LSA_T_EXT, 0, LSA_T_NSSA};
+
+void
+lsa_xxxxtype(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain)
+{
+  if (ospf_is_v2(ifa->oa->po))
+  {
+    itype = itype & LSA_T_V2_MASK;
+    itype = (itype < LSA_V2_TMAX) ? lsa_v2_types[itype] : 0;
+  }
+  else
+  {
+    /* For unkown LSAs without U-bit change scope to LSA_SCOPE_LINK */
+    if (unknown_lsa_type(itype) && !(itype & LSA_UBIT))
+      itype = itype & ~LSA_SCOPE_MASK;
+  }
+
+  *otype = itype;
+
+  switch (LSA_SCOPE(itype))
+  {
+  case LSA_SCOPE_LINK:
+    *domain = ifa->iface->index;
+    return;
+
+  case LSA_SCOPE_AREA:
+    *domain = ifa->oa->areaid;
+    return;
+
+  case LSA_SCOPE_AS:
+  default:
+    *domain = 0;
+    return;
+  }
+}
+
+
+
 /*
 void
 buf_dump(const char *hdr, const byte *buf, int blen)
@@ -179,8 +268,8 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
   u16 length = h->length;
 
   //  log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
-  htonlsah(h, h);
-  htonlsab1(body, length - sizeof(struct ospf_lsa_header));
+  lsa_hton_hdr(h, h);
+  lsa_hton_body1(body, length - sizeof(struct ospf_lsa_header));
 
   /*
   char buf[1024];
@@ -193,8 +282,8 @@ lsasum_calculate(struct ospf_lsa_header *h, void *body)
 
   //  log(L_WARN "Checksum result %4x", h->checksum);
 
-  ntohlsah(h, h);
-  ntohlsab1(body, length - sizeof(struct ospf_lsa_header));
+  lsa_ntoh_hdr(h, h);
+  lsa_ntoh_body1(body, length - sizeof(struct ospf_lsa_header));
 }
 
 /*
@@ -427,76 +516,87 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
 #define HDRLEN sizeof(struct ospf_lsa_header)
 
 static int
-lsa_validate_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
+lsa_validate_rt2(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  
+  unsigned i = 0;
+  void *buf = body;
+  void *bufend = buf + lsa->length - HDRLEN;
+  buf += sizeof(struct ospf_lsa_rt);
 
-  for (i = 0; i < max; i++)
+  while (buf < bufend)
   {
-    u8 type = rtl[i].type;
-    if (!((type == LSART_PTP) ||
-         (type == LSART_NET) ||
-#ifdef OSPFv2
-         (type == LSART_STUB) ||
-#endif
-         (type == LSART_VLNK)))
+    struct ospf_lsa_rt2_link *l = buf;
+    buf += sizeof(struct ospf_lsa_rt2_link) + l->no_tos * sizeof(struct ospf_lsa_rt2_tos);
+    i++;
+
+    if (buf > bufend)
+      return 0;
+
+    if (!((l->type == LSART_PTP) ||
+         (l->type == LSART_NET) ||
+         (l->type == LSART_STUB) ||
+         (l->type == LSART_VLNK)))
       return 0;
   }
+
+  if ((body->options & LSA_RT2_LINKS) != i)
+    return 0;
+
   return 1;
 }
 
+
 static int
-lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
+lsa_validate_rt3(struct ospf_lsa_header *lsa, struct ospf_lsa_rt *body)
 {
-  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
+  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_rt)))
     return 0;
 
+  void *buf = body;
+  void *bufend = buf + lsa->length - HDRLEN;
+  buf += sizeof(struct ospf_lsa_rt);
+
+  while (buf < bufend)
+  {
+    struct ospf_lsa_rt3_link *l = buf;
+    buf += sizeof(struct ospf_lsa_rt3_link);
+
+    if (buf > bufend)
+      return 0;
+
+    if (!((l->type == LSART_PTP) ||
+         (l->type == LSART_NET) ||
+         (l->type == LSART_VLNK)))
+      return 0;
+  }
   return 1;
 }
 
-#ifdef OSPFv2
-
 static int
-lsa_validate_sum(struct ospf_lsa_header *lsa, struct ospf_lsa_sum *body)
+lsa_validate_net(struct ospf_lsa_header *lsa, struct ospf_lsa_net *body UNUSED)
 {
-  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)
+  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_net)))
     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)
+lsa_validate_sum2(struct ospf_lsa_header *lsa, struct ospf_lsa_sum2 *body)
 {
-  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext)))
+  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum2)))
     return 0;
 
   /* First field should have TOS = 0, we ignore other TOS fields */
-  if ((body->metric & LSA_EXT_TOS) != 0)
+  if ((body->metric & LSA_SUM2_TOS) != 0)
     return 0;
 
   return 1;
 }
 
-#else /* OSPFv3 */
-
 static inline int
 pxlen(u32 *buf)
 {
@@ -504,7 +604,7 @@ pxlen(u32 *buf)
 }
 
 static int
-lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
+lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body)
 {
   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_sum3_net) + 4))
     return 0;
@@ -520,9 +620,8 @@ lsa_validate_sum_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *body
   return 1;
 }
 
-
 static int
-lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
+lsa_validate_sum3_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
 {
   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_rt)))
     return 0;
@@ -531,7 +630,20 @@ lsa_validate_sum_rt(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_rt *body)
 }
 
 static int
-lsa_validate_ext(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
+lsa_validate_ext2(struct ospf_lsa_header *lsa, struct ospf_lsa_ext2 *body)
+{
+  if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext2)))
+    return 0;
+
+  /* First field should have TOS = 0, we ignore other TOS fields */
+  if ((body->metric & LSA_EXT2_TOS) != 0)
+    return 0;
+
+  return 1;
+}
+
+static int
+lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
 {
   if (lsa->length < (HDRLEN + sizeof(struct ospf_lsa_ext3) + 4))
     return 0;
@@ -596,8 +708,6 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
   return lsa_validate_pxlist(lsa, body->pxcount, sizeof(struct ospf_lsa_prefix), (u8 *) body);
 }
 
-#endif
-
 
 /**
  * lsa_validate - check whether given LSA is valid
@@ -609,31 +719,50 @@ lsa_validate_prefix(struct ospf_lsa_header *lsa, struct ospf_lsa_prefix *body)
  */
 
 int
-lsa_validate(struct ospf_lsa_header *lsa, void *body)
+lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, void *body)
 {
-  switch (lsa->type)
+  if (ospf2)
+  {
+    switch (lsa_type)
+    {
+    case LSA_T_RT:
+      return lsa_validate_rt2(lsa, body);
+    case LSA_T_NET:
+      return lsa_validate_net(lsa, body);
+    case LSA_T_SUM_NET:
+      return lsa_validate_sum2(lsa, body);
+    case LSA_T_SUM_RT:
+      return lsa_validate_sum2(lsa, body);
+    case LSA_T_EXT:
+    case LSA_T_NSSA:
+      return lsa_validate_ext2(lsa, body);
+    default:
+      return 0;        /* Should not happen, unknown LSAs are already rejected */
+    }
+  }
+  else
+  {
+    switch (lsa_type)
     {
     case LSA_T_RT:
-      return lsa_validate_rt(lsa, body);
+      return lsa_validate_rt3(lsa, body);
     case LSA_T_NET:
       return lsa_validate_net(lsa, body);
     case LSA_T_SUM_NET:
-      return lsa_validate_sum_net(lsa, body);
+      return lsa_validate_sum3_net(lsa, body);
     case LSA_T_SUM_RT:
-      return lsa_validate_sum_rt(lsa, body);
+      return lsa_validate_sum3_rt(lsa, body);
     case LSA_T_EXT:
     case LSA_T_NSSA:
-      return lsa_validate_ext(lsa, body);
+      return lsa_validate_ext3(lsa, body);
     case LSA_T_LINK:
       return lsa_validate_link(lsa, body);
     case LSA_T_PREFIX:
       return lsa_validate_prefix(lsa, body);
     default:
-      /* In OSPFv3, unknown LSAs are OK,
-        In OSPFv2, unknown LSAs are already rejected
-      */
-      return 1;
+      return 1;        /* Unknown LSAs are OK in OSPFv3 */
     }
+  }
 }
 
 /**
index 3bdd814f6a1ca0f5ca68d9c4f8feb50fa6f94cae..5bad1cebfc08be56495323fea0bd5b1f4dfa2a30 100644 (file)
 #define _BIRD_OSPF_LSALIB_H_
 
 #ifdef CPU_BIG_ENDIAN
-static inline void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n) { *n = *h; };
-static inline void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h) { *h = *n; };
-static inline void htonlsab(void *h, void *n, u16 len) { ASSERT(h != n); memcpy(n, h, len); };
-static inline void ntohlsab(void *n, void *h, u16 len) { ASSERT(n != h); memcpy(h, n, len); };
-static inline void htonlsab1(void *h, u16 len) { };
-static inline void ntohlsab1(void *n, u16 len) { };
+static inline void lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n) { *n = *h; };
+static inline void lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h) { *h = *n; };
+static inline void lsa_hton_body(void *h, void *n, u16 len) { ASSERT(h != n); memcpy(n, h, len); };
+static inline void lsa_ntoh_body(void *n, void *h, u16 len) { ASSERT(n != h); memcpy(h, n, len); };
+static inline void lsa_hton_body1(void *h, u16 len) { };
+static inline void lsa_ntoh_body1(void *n, u16 len) { };
 #else
-void htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
-void ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
-void htonlsab(void *h, void *n, u16 len);
-void ntohlsab(void *n, void *h, u16 len);
-static inline void htonlsab1(void *h, u16 len) { htonlsab(h, h, len); };
-static inline void ntohlsab1(void *n, u16 len) { ntohlsab(n, n, len); };
+void lsa_hton_hdr(struct ospf_lsa_header *h, struct ospf_lsa_header *n);
+void lsa_ntoh_hdr(struct ospf_lsa_header *n, struct ospf_lsa_header *h);
+void lsa_hton_body(void *h, void *n, u16 len);
+void lsa_ntoh_body(void *n, void *h, u16 len);
+static inline void lsa_hton_body1(void *h, u16 len) { lsa_hton_body(h, h, len); };
+static inline void lsa_ntoh_body1(void *n, u16 len) { lsa_ntoh_body(n, n, len); };
 #endif
 
 struct ospf_lsa_rt_walk {
@@ -34,6 +34,11 @@ struct ospf_lsa_rt_walk {
   u32 id, data, lif, nif;
 };
 
+static inline u32 lsa_get_type(struct proto_ospf *po, u32 type_raw)
+{ return ospf_is_v2(po) ? (type_raw & LSA_T_V2_MASK) : type_raw; }
+
+int lsa_flooding_allowed(u32 type, u32 domain, struct ospf_iface *ifa);
+void lsa_xxxxtype(u32 itype, struct ospf_iface *ifa, u32 *otype, u32 *domain);
 void lsasum_calculate(struct ospf_lsa_header *header, void *body);
 u16 lsasum_check(struct ospf_lsa_header *h, void *body);
 #define CMP_NEWER 1
@@ -45,7 +50,7 @@ int lsa_walk_rt(struct ospf_lsa_rt_walk *rt);
 void lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, ip_addr *ip, int *pxlen, u8 *pxopts, u32 *metric);
 void lsa_parse_sum_rt(struct top_hash_entry *en, int ospf2, u32 *drid, u32 *metric, u32 *options);
 void lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *rt);
-int lsa_validate(struct ospf_lsa_header *lsa, void *body);
+int lsa_validate(struct ospf_lsa_header *lsa, u32 lsa_type, int ospf2, 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 ae9e7e4114edf334e5d84a6282b6152e6d72da59..721e0379e3d1c3bdbca1cf9e29fd15a37f65eb4c 100644 (file)
@@ -19,7 +19,7 @@ struct ospf_lsreq_packet
 };
 */
 
-static void
+static inline void
 ospf_lsreq_body(struct proto_ospf *po, struct ospf_packet *pkt, unsigned plen,
                struct ospf_lsreq_header **body, unsigned *count)
 {
@@ -71,9 +71,10 @@ ospf_lsreq_send(struct ospf_neighbor *n)
   {
     en = (struct top_hash_entry *) sn;
     DBG("Requesting %uth LSA: Type: %u, ID: %R, RT: %R, SN: 0x%x, Age %u\n",
-       i, en->lsa.type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
+       i, en->lsa_type, en->lsa.id, en->lsa.rt, en->lsa.sn, en->lsa.age);
 
-    lsrs[i].type = htonl(en->lsa.type);
+    u32 rtype = lsa_get_type(po, en->lsa.type_raw);
+    lsrs[i].type = htonl(rtype);
     lsrs[i].rt = htonl(en->lsa.rt);
     lsrs[i].id = htonl(en->lsa.id);
 
@@ -97,7 +98,9 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
   struct proto_ospf *po = ifa->oa->po;
   struct ospf_lsreq_header *lsrs;
   unsigned i, lsr_count;
-  list uplist;
+
+  struct ospf_lsreq_item *lsr_head, *lsr;
+  struct ospf_lsreq_item **lsr_pos = &lsr_head;
   slab *upslab;
 
 
@@ -111,35 +114,39 @@ ospf_lsreq_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
 
   ospf_neigh_sm(n, INM_HELLOREC);      /* Not in RFC */
 
-  init_list(&uplist);
-  upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
+  upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
 
   ospf_lsreq_body(po, pkt, ntohs(pkt->length), &lsrs, &lsr_count);
   for (i = 0; i < lsr_count; i++)
   {
-    u32 hid = ntohl(lsrs[i].id);
-    u32 hrt = ntohl(lsrs[i].rt);
-    u32 htype = ntohl(lsrs[i].type);
-    u32 dom = ospf_lsa_domain(htype, ifa);
-    // XXXX check
-    DBG("Processing requested LSA: Type: %u, ID: %R, RT: %R\n", htype, hid, hrt);
-
-    if (ospf_hash_find(po->gr, dom, hid, hrt, htype) == NULL)
+    u32 id, rt, type, dom;
+
+    id = ntohl(lsrs[i].id);
+    rt = ntohl(lsrs[i].rt);
+    lsa_xxxxtype(ntohl(lsrs[i].type), ifa, &type, &dom);
+
+    DBG("Processing requested LSA: Type: %04x, Id: %R, Rt: %R\n", type, id, rt);
+
+    if (ospf_hash_find(po->gr, dom, id, rt, type) == NULL)
     {
       log(L_WARN "Received bad LSREQ from %I: Type: %04x, Id: %R, Rt: %R",
-         n->ip, htype, hid, hrt);
+         n->ip, type, id, rt);
       ospf_neigh_sm(n, INM_BADLSREQ);
       rfree(upslab);
       return;
     }
 
-    struct l_lsr_head *llsh = sl_alloc(upslab);
-    llsh->lsh.id = hid;
-    llsh->lsh.rt = hrt;
-    llsh->lsh.type = htype;
-    add_tail(&uplist, NODE llsh);
+    lsr = sl_alloc(upslab);
+    lsr->domain = dom;
+    lsr->type = type;
+    lsr->id = id;
+    lsr->rt = rt;
+
+    *lsr_pos = lsr;
+    lsr_pos = &(lsr->next);
   }
+  *lsr_pos = NULL;
 
-  ospf_lsupd_send_list(n, &uplist);
+  ospf_lsupd_send_list(n, lsr_head);
   rfree(upslab);
 }
index 9255785e05c9af069023f0f08dc36fea31663978..80c9b0b2ed22d741925eb8dcf93db0fb1424a01a 100644 (file)
@@ -9,21 +9,29 @@
 #include "ospf.h"
 
 
+/*
 struct ospf_lsupd_packet
 {
-  struct ospf_packet ospf_packet;
-  u32 lsano;                   /* Number of LSA's */
+  struct ospf_packet hdr;
+  // union ospf_auth auth;
+
+  u32 lsa_count;
+  void lsas[];
 };
+*/
 
 
 /* Beware of unaligned access */
 void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n)
 {
   struct ospf_lsa_header lsa;
-  ntohlsah(lsa_n, &lsa);
+  u32 lsa_type;
+
+  lsa_ntoh_hdr(lsa_n, &lsa);
+  lsa_type = lsa_get_type(po, lsa.type_raw);
 
   log(L_TRACE "%s:     LSA      Type: %04x, Id: %R, Rt: %R, Age: %u, Seq: %08x, Sum: %04x",
-      po->proto.name, lsa.type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
+      po->proto.name, lsa_type, lsa.id, lsa.rt, lsa.age, lsa.sn, lsa.checksum);
 }
 
 void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
@@ -33,22 +41,38 @@ void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt)
   log(L_TRACE "%s:     router   %R", p->name, ntohl(pkt->routerid));
 }
 
-static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt)
+static inline unsigned
+ospf_lsupd_hdrlen(struct proto_ospf *po)
+{
+  return ospf_pkt_hdrlen(po) + 4; /* + u32 lsa count field */
+}
+
+static inline u32 *
+ospf_lsupd_lsa_count(struct ospf_packet *pkt, unsigned hdrlen)
+{ return ((void *) pkt) + hdrlen - 4; }
+
+static inline void
+ospf_lsupd_body(struct proto_ospf *po, struct ospf_packet *pkt,
+               unsigned *offset, unsigned *bound, unsigned *lsa_count)
+{
+  unsigned hlen = ospf_lsupd_hdrlen(po);
+  *offset = hlen;
+  *bound = ntohs(pkt->length) - sizeof(struct ospf_lsa_header);
+  *lsa_count = ntohl(*ospf_lsupd_lsa_count(pkt, hlen));
+}
+
+static void ospf_lsupd_dump(struct proto_ospf *po, struct ospf_packet *pkt)
 {
   struct proto *p = &po->proto;
-  struct ospf_packet *op = &pkt->ospf_packet;
 
-  ASSERT(op->type == LSUPD_P);
-  ospf_dump_common(po, op);
+  ASSERT(pkt->type == LSUPD_P);
+  ospf_dump_common(po, pkt);
 
-  /* We know that ntohs(op->length) >= sizeof(struct ospf_lsa_header) */
-  u8 *pbuf= (u8 *) pkt;
-  unsigned int offset = sizeof(struct ospf_lsupd_packet);
-  unsigned int bound = ntohs(op->length) - sizeof(struct ospf_lsa_header);
-  unsigned int i, j, lsalen;
+  /* We know that ntohs(pkt->length) >= sizeof(struct ospf_lsa_header) */
+  unsigned offset, bound, i, lsa_count, lsalen;
+  ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
 
-  j = ntohl(pkt->lsano);
-  for (i = 0; i < j; i++)
+  for (i = 0; i < lsa_count; i++)
     {
       if (offset > bound)
        {
@@ -56,8 +80,8 @@ static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt
          return;
        }
 
-      struct ospf_lsa_header *lsa = (void *) (pbuf + offset);
-      ospf_dump_lsahdr(p, lsa);
+      struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
+      ospf_dump_lsahdr(po, lsa);
       lsalen = ntohs(lsa->length);
       offset += lsalen;
 
@@ -70,77 +94,6 @@ static void ospf_dump_lsupd(struct proto_ospf *po, struct ospf_lsupd_packet *pkt
 }
 
 
-#ifdef OSPFv2
-
-int
-ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
-{
-  if (lsa->type == LSA_T_EXT)
-    {
-      if (ifa->type == OSPF_IT_VLINK)
-       return 0;
-      if (!oa_is_ext(ifa->oa))
-       return 0;
-      return 1;
-    }
-  else
-    return ifa->oa->areaid == domain;
-}
-
-#else /* OSPFv3 */
-
-static int
-unknown_lsa_type(struct ospf_lsa_header *lsa)
-{
-  switch (lsa->type)
-    {
-    case LSA_T_RT:
-    case LSA_T_NET:
-    case LSA_T_SUM_NET:
-    case LSA_T_SUM_RT:
-    case LSA_T_EXT:
-    case LSA_T_NSSA:
-    case LSA_T_LINK:
-    case LSA_T_PREFIX:
-      return 0;
-
-    default:
-      return 1;
-    }
-}
-
-int
-ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_iface *ifa)
-{    
-  u32 scope = LSA_SCOPE(lsa);
-
-  /* 4.5.2 (Case 2) */
-  if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
-    scope = LSA_SCOPE_LINK;
-
-  switch (scope)
-    {
-    case LSA_SCOPE_LINK:
-      return ifa->iface->index == domain;
-
-    case LSA_SCOPE_AREA:
-      return ifa->oa->areaid == domain;
-
-    case LSA_SCOPE_AS:
-      if (ifa->type == OSPF_IT_VLINK)
-       return 0;
-      if (!oa_is_ext(ifa->oa))
-       return 0;
-      return 1;
-
-    default:
-      log(L_ERR "LSA with invalid scope");
-      return 0;
-    }
-}
-
-#endif
-
 /**
  * ospf_lsupd_flood - send received or generated lsa to the neighbors
  * @po: OSPF protocol
@@ -271,17 +224,16 @@ ospf_lsupd_flood(struct proto_ospf *po,
 
     {
       u16 len, age;
-      struct ospf_lsupd_packet *pk;
-      struct ospf_packet *op;
+      unsigned hlen;
+      struct ospf_packet *pkt;
       struct ospf_lsa_header *lh;
 
-      pk = ospf_tx_buffer(ifa);
-      op = &pk->ospf_packet;
+      pkt = ospf_tx_buffer(ifa);
+      hlen = ospf_lsupd_hdrlen(po);
 
-      ospf_pkt_fill_hdr(ifa, pk, LSUPD_P);
-      pk->lsano = htonl(1);
-
-      lh = (struct ospf_lsa_header *) (pk + 1);
+      ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
+      *ospf_lsupd_lsa_count(pkt, hlen) = htonl(1);
+      lh = (((void *) pkt) + hlen);
 
       /* Copy LSA into the packet */
       if (hn)
@@ -293,33 +245,30 @@ ospf_lsupd_flood(struct proto_ospf *po,
        u8 *help;
        struct top_hash_entry *en;
 
-       htonlsah(hh, lh);
+       lsa_hton_hdr(hh, lh);
        help = (u8 *) (lh + 1);
        en = ospf_hash_find_header(po->gr, domain, hh);
-       htonlsab(en->lsa_body, help, hh->length - sizeof(struct ospf_lsa_header));
+       lsa_hton_body(en->lsa_body, help, hh->length - sizeof(struct ospf_lsa_header));
       }
 
-      len = sizeof(struct ospf_lsupd_packet) + ntohs(lh->length);
-
       age = ntohs(lh->age);
       age += ifa->inftransdelay;
       if (age > LSA_MAXAGE)
        age = LSA_MAXAGE;
       lh->age = htons(age);
 
-      op->length = htons(len);
+      len = hlen + ntohs(lh->length);
+      pkt->length = htons(len);
 
-      OSPF_PACKET(ospf_dump_lsupd, pk, "LSUPD packet flooded via %s", ifa->iface->name);
+      OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet flooded via %s", ifa->iface->name);
 
       switch (ifa->type)
       {
       case OSPF_IT_BCAST:
        if ((ifa->state == OSPF_IS_BACKUP) || (ifa->state == OSPF_IS_DR))
          ospf_send_to_all(ifa);
-       else if (ifa->cf->real_bcast)
-         ospf_send_to_bdr(ifa);
        else
-         ospf_send_to(ifa, AllDRouters);
+         ospf_send_to_des(ifa);
        break;
 
       case OSPF_IT_NBMA:
@@ -350,99 +299,96 @@ ospf_lsupd_flood(struct proto_ospf *po,
 }
 
 void                           /* I send all I received in LSREQ */
-ospf_lsupd_send_list(struct ospf_neighbor *n, list * l)
+ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr)
 {
   struct ospf_area *oa = n->ifa->oa;
   struct proto_ospf *po = oa->po;
-  struct l_lsr_head *lsr;
   struct top_hash_entry *en;
-  struct ospf_lsupd_packet *pkt;
-  u32 len, len2, lsano;
-  char *buf;
+  struct ospf_packet *pkt;
+  unsigned hlen, pos, pos2, maxsize, lsano;
 
   pkt = ospf_tx_buffer(n->ifa);
-  buf = (void *) pkt;
+  hlen = ospf_lsupd_hdrlen(po);
+  maxsize = ospf_pkt_maxsize(n->ifa);
 
-  lsr = HEAD(*l);
-  while(NODE_NEXT(lsr))
+  while (lsr)
   {
     /* Prepare the packet */
     ospf_pkt_fill_hdr(n->ifa, pkt, LSUPD_P);
-    len = sizeof(struct ospf_lsupd_packet);
+    pos = hlen;
     lsano = 0;
 
     /* Fill the packet with LSAs */
-    while(NODE_NEXT(lsr))
+    while (lsr)
     {
-      u32 domain = ospf_lsa_domain(lsr->lsh.type, n->ifa);
-      en = ospf_hash_find(oa->po->gr, domain, lsr->lsh.id, lsr->lsh.rt, lsr->lsh.type);
-      if (en == NULL)
+      en = ospf_hash_find(oa->po->gr, lsr->domain, lsr->id, lsr->rt, lsr->type);
+      if (!en)
       {
        /* Probably flushed LSA, this should not happen */
        log(L_WARN "OSPF: LSA disappeared (Type: %04x, Id: %R, Rt: %R)", 
-           lsr->lsh.type, lsr->lsh.id, lsr->lsh.rt);
-       lsr = NODE_NEXT(lsr);
-       continue;                       
+           lsr->type, lsr->id, lsr->rt);
+       lsr = lsr->next;
+       continue;
       }
 
-      len2 = len + en->lsa.length;
-      if (len2 > ospf_pkt_maxsize(n->ifa))
+      pos2 = pos + en->lsa.length;
+      if (pos2 > maxsize)
       {
        /* The packet if full, stop adding LSAs and sent it */
        if (lsano > 0)
          break;
 
        /* LSA is larger than MTU, check buffer size */
-       if (len2 > ospf_pkt_bufsize(n->ifa))
+       if (pos2 > ospf_pkt_bufsize(n->ifa))
        {
          /* Cannot fit in a tx buffer, skip that */
          log(L_WARN "OSPF: LSA too large to send (Type: %04x, Id: %R, Rt: %R)", 
-             lsr->lsh.type, lsr->lsh.id, lsr->lsh.rt);
-         lsr = NODE_NEXT(lsr);
+             lsr->type, lsr->id, lsr->rt);
+         lsr = lsr->next;
          continue;
        }
       }
 
       /* Copy the LSA to the packet */
-      htonlsah(&(en->lsa), (struct ospf_lsa_header *) (buf + len));
-      htonlsab(en->lsa_body, buf + len + sizeof(struct ospf_lsa_header),
-              en->lsa.length - sizeof(struct ospf_lsa_header));
-      len = len2;
+      void *lsabuf = ((void *) pkt) + pos;
+      lsa_hton_hdr(&(en->lsa), (struct ospf_lsa_header *) lsabuf);
+      lsa_hton_body(en->lsa_body, lsabuf + sizeof(struct ospf_lsa_header),
+                   en->lsa.length - sizeof(struct ospf_lsa_header));
+      pos = pos2;
       lsano++;
-      lsr = NODE_NEXT(lsr);
+      lsr = lsr->next;
     }
 
     if (lsano == 0)
       break;
 
     /* Send the packet */
-    pkt->lsano = htonl(lsano);
-    pkt->ospf_packet.length = htons(len);
-    OSPF_PACKET(ospf_dump_lsupd, pkt, "LSUPD packet sent to %I via %s",
+    pkt->length = htons(pos);
+    *ospf_lsupd_lsa_count(pkt, hlen) = htonl(lsano);
+    OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet sent to %I via %s",
                n->ip, n->ifa->iface->name);
     ospf_send_to(n->ifa, n->ip);
   }
 }
 
 void
-ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
+ospf_lsupd_receive(struct ospf_packet *pkt, struct ospf_iface *ifa,
                   struct ospf_neighbor *n)
 {
 
   struct ospf_neighbor *ntmp;
   struct proto_ospf *po = ifa->oa->po;
   struct proto *p = &po->proto;
-  unsigned int i, max, sendreq = 1;
+  unsigned sendreq = 1;
 
-  unsigned int size = ntohs(ps_i->length);
-  if (size < (sizeof(struct ospf_lsupd_packet) + sizeof(struct ospf_lsa_header)))
+  unsigned plen = ntohs(pkt->length);
+  if (plen < (ospf_lsupd_hdrlen(po) + sizeof(struct ospf_lsa_header)))
   {
-    log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, size);
+    log(L_ERR "OSPF: Bad LSUPD packet from %I - too short (%u B)", n->ip, plen);
     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);
+  OSPF_PACKET(ospf_lsupd_dump, pkt, "LSUPD packet received from %I via %s", n->ip, ifa->iface->name);
 
   if (n->state < NEIGHBOR_EXCHANGE)
   {
@@ -452,30 +398,29 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
 
   ospf_neigh_sm(n, INM_HELLOREC);      /* Questionable */
 
-  unsigned int offset = sizeof(struct ospf_lsupd_packet);
-  unsigned int bound = size - sizeof(struct ospf_lsa_header);
+  unsigned offset, bound, i, lsa_count;
+  ospf_lsupd_body(po, pkt, &offset, &bound, &lsa_count);
 
-  max = ntohl(ps->lsano);
-  for (i = 0; i < max; i++)
+  for (i = 0; i < lsa_count; i++)
   {
     struct ospf_lsa_header lsatmp;
     struct top_hash_entry *lsadb;
 
     if (offset > bound)
     {
-      log(L_WARN "Received lsupd from %I is too short!", n->ip);
+      log(L_WARN "OSPF: Received LSUPD from %I is too short", n->ip);
       ospf_neigh_sm(n, INM_BADLSREQ);
       return;
     }
 
-    struct ospf_lsa_header *lsa = (void *) (((u8 *) ps) + offset);
+    struct ospf_lsa_header *lsa = ((void *) pkt) + offset;
     unsigned int lsalen = ntohs(lsa->length);
     offset += lsalen;
  
-    if ((offset > size) || ((lsalen % 4) != 0) ||
+    if ((offset > plen) || ((lsalen % 4) != 0) ||
        (lsalen <= sizeof(struct ospf_lsa_header)))
     {
-      log(L_WARN "Received LSA from %I with bad length", n->ip);
+      log(L_WARN "OSPF: Received LSA from %I with bad length", n->ip);
       ospf_neigh_sm(n, INM_BADLSREQ);
       break;
     }
@@ -484,55 +429,45 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
     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);
+      log(L_WARN "OSPF: Received LSA from %I with bad checskum: %x %x",
+         n->ip, chsum, lsa->checksum);
       continue;
     }
 
-    u16 lsa_type = ntohs(lsa->type_raw);
-    lsa_type = xxxx(lsa_type); // XXXX finish
-#ifdef OSPFv2
+    u32 lsa_type, lsa_domain;
+    lsa_ntoh_hdr(lsa, &lsatmp);
+    lsa_xxxxtype(lsatmp.type_raw, ifa, &lsa_type, &lsa_domain);
+
     /* pg 143 (2) */
-    if ((lsa->type == 0) || (lsa->type == 6) || (lsa->type > LSA_T_NSSA))
+    if (!lsa_type)
     {
-      log(L_WARN "Unknown LSA type from %I", n->ip);
+      log(L_WARN "OSPF: Received unknown LSA type from %I", n->ip);
       continue;
     }
 
-    /* pg 143 (3) */
-    if ((lsa_type == LSA_T_EXT) && !oa_is_ext(ifa->oa))
-    {
-      log(L_WARN "Received External LSA in stub area from %I", n->ip);
-      continue;
-    }
-#else /* OSPFv3 */
     /* 4.5.1 (2) */
     if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_AS) && !oa_is_ext(ifa->oa))
     {
-      log(L_WARN "Received LSA with AS scope in stub area from %I", n->ip);
+      log(L_WARN "OSPF: Received LSA with AS scope in stub area from %I", n->ip);
       continue;
     }
 
     /* 4.5.1 (3) */
-    if ((LSA_SCOPE(lsa_type) == LSA_SCOPE_RES))
+    if (LSA_SCOPE(lsa_type) == LSA_SCOPE_RES)
     {
-      log(L_WARN "Received LSA with invalid scope from %I", n->ip);
+      log(L_WARN "OSPF: Received LSA with invalid scope from %I", n->ip);
       continue;
     }
-#endif
-
-    ntohlsah(lsa, &lsatmp);
 
-    DBG("Update Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
+    DBG("Update Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
        lsa_type, lsatmp.id, lsatmp.rt, lsatmp.sn, lsatmp.age, lsatmp.checksum);
 
-    /* FIXME domain should be link id for unknown LSA types with zero Ubit */
-    u32 domain = ospf_lsa_domain(lsa_type, ifa);
-    lsadb = ospf_hash_find_header(po->gr, domain, &lsatmp);
+    lsadb = ospf_hash_find(po->gr, lsa_domain, lsatmp.id, lsatmp.rt, lsa_type);
 
 #ifdef LOCAL_DEBUG
     if (lsadb)
-      DBG("I have Type: %u ID: %R RT: %R, Sn: 0x%08x Age: %u, Sum: %u\n",
-         lsadb->lsa.type, lsadb->lsa.id, lsadb->lsa.rt,
+      DBG("I have Type: %04x, Id: %R, Rt: %R, Sn: 0x%08x, Age: %u, Sum: %u\n",
+         lsadb->lsa_type, lsadb->lsa.id, lsadb->lsa.rt,
          lsadb->lsa.sn, lsadb->lsa.age, lsadb->lsa.checksum);
 #endif
 
@@ -589,7 +524,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
          lsadb->inst_t = now;
          lsadb->ini_age = 0;
          lsasum_calculate(&lsadb->lsa, lsadb->lsa_body);
-         ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, domain, 1);
+         ospf_lsupd_flood(po, NULL, NULL, &lsadb->lsa, lsa_domain, 1);
        }
        else
        {
@@ -600,7 +535,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
          lsa->sn = htonl(LSA_MAXSEQNO);
          lsasum_check(lsa, (lsa + 1)); /* It also calculates chsum! */
          lsatmp.checksum = ntohs(lsa->checksum);
-         ospf_lsupd_flood(po, NULL, lsa, &lsatmp, domain, 0);
+         ospf_lsupd_flood(po, NULL, lsa, &lsatmp, lsa_domain, 0);
        }
        continue;
       }
@@ -622,7 +557,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       {
        struct top_hash_entry *en;
        if (ntmp->state > NEIGHBOR_EXSTART)
-         if ((en = ospf_hash_find_header(ntmp->lsrth, domain, &lsadb->lsa)) != NULL)
+         if ((en = ospf_hash_find_header(ntmp->lsrth, lsa_domain, &lsadb->lsa)) != NULL)
          {
            s_rem_node(SNODE en);
            ospf_hash_delete(ntmp->lsrth, en);
@@ -630,7 +565,7 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       }
 
       /* pg 144 (5b) */
-      if (ospf_lsupd_flood(po, n, lsa, &lsatmp, domain, 1) == 0)
+      if (ospf_lsupd_flood(po, n, lsa, &lsatmp, lsa_domain, 1) == 0)
       {
        DBG("Wasn't flooded back\n");   /* ps 144(5e), pg 153 */
        if (ifa->state == OSPF_IS_BACKUP)
@@ -652,26 +587,24 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
 
       /* pg 144 (5d) */
       void *body = mb_alloc(p->pool, lsatmp.length - sizeof(struct ospf_lsa_header));
-      ntohlsab(lsa + 1, body, lsatmp.length - sizeof(struct ospf_lsa_header));
+      lsa_ntoh_body(lsa + 1, body, 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)
+      if (lsa_validate(&lsatmp, lsa_type, ospf_is_v2(po), body) == 0)
       {
        log(L_WARN "Received invalid LSA from %I", n->ip);
        mb_free(body);
        continue;       
       }
 
-      lsadb = lsa_install_new(po, &lsatmp, domain, body);
+      lsadb = lsa_install_new(po, &lsatmp, lsa_domain, body);
       DBG("New LSA installed in DB\n");
 
-#ifdef OSPFv3
       /* Events 6,7 from RFC5340 4.4.3. */
       if ((lsa_type == LSA_T_LINK) && (ifa->state == OSPF_IS_DR))
        schedule_net_lsa(ifa);
-#endif
 
       continue;
     }
@@ -710,16 +643,13 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
       continue;
     }
 
-    {
-      list l;
-      struct l_lsr_head ll;
-      init_list(&l);
-      ll.lsh.id = lsadb->lsa.id;
-      ll.lsh.rt = lsadb->lsa.rt;
-      ll.lsh.type = lsadb->lsa.type;
-      add_tail(&l, NODE & ll);
-      ospf_lsupd_send_list(n, &l);
-    }
+    struct ospf_lsreq_item lsr = {
+      .domain = lsadb->domain,
+      .type = lsadb->lsa_type,
+      .id = lsadb->lsa.id,
+      .rt = lsadb->lsa.rt
+    };
+    ospf_lsupd_send_list(n, &lsr);
   }
 
   /* Send direct LSAs */
index 29ea491f4aa9e0cdff66cf3daec895905cb95fe7..476775e28185c6948426e2b8640e258db286615a 100644 (file)
@@ -12,7 +12,7 @@
 
 void ospf_dump_lsahdr(struct proto_ospf *po, struct ospf_lsa_header *lsa_n);
 void ospf_dump_common(struct proto_ospf *po, struct ospf_packet *pkt);
-void ospf_lsupd_send_list(struct ospf_neighbor *n, list * l);
+void ospf_lsupd_send_list(struct ospf_neighbor *n, struct ospf_lsreq_item *lsr);
 void ospf_lsupd_receive(struct ospf_packet *ps_i,
                        struct ospf_iface *ifa, struct ospf_neighbor *n);
 int ospf_lsupd_flood(struct proto_ospf *po,
index 2c55f58c405e5cd2c710fe05f5746c23758c50cd..118919d49cdfb1627e3b67ea32c83ed4a41033f5 100644 (file)
@@ -26,8 +26,8 @@ const char *ospf_inm[] =
 };
 
 static void neigh_chstate(struct ospf_neighbor *n, u8 state);
-static struct ospf_neighbor *electbdr(list nl);
-static struct ospf_neighbor *electdr(list nl);
+static struct ospf_neighbor *electbdr(struct proto_ospf *, list nl);
+static struct ospf_neighbor *electdr(struct proto_ospf *, list nl);
 static void neighbor_timer_hook(timer * timer);
 static void rxmt_timer_hook(timer * timer);
 static void ackd_timer_hook(timer * t);
@@ -37,11 +37,9 @@ init_lists(struct ospf_neighbor *n)
 {
   s_init_list(&(n->lsrql));
   n->lsrqh = ospf_top_new(n->pool);
-  s_init(&(n->lsrqi), &(n->lsrql));
 
   s_init_list(&(n->lsrtl));
   n->lsrth = ospf_top_new(n->pool);
-  s_init(&(n->lsrti), &(n->lsrtl));
 }
 
 /* Resets LSA request and retransmit lists.
@@ -163,8 +161,11 @@ neigh_chstate(struct ospf_neighbor *n, u8 state)
   }
 }
 
+static inline u32 neigh_get_id(struct proto_ospf *po, struct ospf_neighbor *n)
+{ return ospf_is_v2(po) ? ipa_to_u32(n->ip) : n->rid; }
+
 static struct ospf_neighbor *
-electbdr(list nl)
+electbdr(struct proto_ospf *po, list nl)
 {
   struct ospf_neighbor *neigh, *n1, *n2;
   u32 nid;
@@ -173,11 +174,7 @@ electbdr(list nl)
   n2 = NULL;
   WALK_LIST(neigh, nl)                 /* First try those decl. themselves */
   {
-#ifdef OSPFv2
-    nid = ipa_to_u32(neigh->ip);
-#else /* OSPFv3 */
-    nid = neigh->rid;
-#endif
+    nid = neigh_get_id(po, neigh);
 
     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
       if (neigh->priority > 0)         /* Eligible */
@@ -222,7 +219,7 @@ electbdr(list nl)
 }
 
 static struct ospf_neighbor *
-electdr(list nl)
+electdr(struct proto_ospf *po, list nl)
 {
   struct ospf_neighbor *neigh, *n;
   u32 nid;
@@ -230,11 +227,7 @@ electdr(list nl)
   n = NULL;
   WALK_LIST(neigh, nl)                 /* And now DR */
   {
-#ifdef OSPFv2
-    nid = ipa_to_u32(neigh->ip);
-#else /* OSPFv3 */
-    nid = neigh->rid;
-#endif
+    nid = neigh_get_id(po, neigh);
 
     if (neigh->state >= NEIGHBOR_2WAY) /* Higher than 2WAY */
       if (neigh->priority > 0)         /* Eligible */
@@ -449,19 +442,14 @@ bdr_election(struct ospf_iface *ifa)
   me.priority = ifa->priority;
   me.ip = ifa->addr->ip;
 
-#ifdef OSPFv2
-  me.dr = ipa_to_u32(ifa->drip);
-  me.bdr = ipa_to_u32(ifa->bdrip);
-#else /* OSPFv3 */
-  me.dr = ifa->drid;
-  me.bdr = ifa->bdrid;
+  me.dr  = ospf_is_v2(po) ? ipa_to_u32(ifa->drip) : ifa->drid;
+  me.bdr = ospf_is_v2(po) ? ipa_to_u32(ifa->bdrip) : ifa->bdrid;
   me.iface_id = ifa->iface->index;
-#endif
 
   add_tail(&ifa->neigh_list, NODE & me);
 
-  nbdr = electbdr(ifa->neigh_list);
-  ndr = electdr(ifa->neigh_list);
+  nbdr = electbdr(po, ifa->neigh_list);
+  ndr = electdr(po, ifa->neigh_list);
 
   if (ndr == NULL)
     ndr = nbdr;
@@ -472,16 +460,11 @@ bdr_election(struct ospf_iface *ifa)
       || ((ifa->bdrid == myid) && (nbdr != &me))
       || ((ifa->bdrid != myid) && (nbdr == &me)))
   {
-#ifdef OSPFv2
-    me.dr = ndr ? ipa_to_u32(ndr->ip) : 0;
-    me.bdr = nbdr ? ipa_to_u32(nbdr->ip) : 0;
-#else /* OSPFv3 */
-    me.dr = ndr ? ndr->rid : 0;
-    me.bdr = nbdr ? nbdr->rid : 0;
-#endif
+    me.dr = ndr ? neigh_get_id(po, ndr) : 0;
+    me.bdr = nbdr ? neigh_get_id(po, nbdr) : 0;
 
-    nbdr = electbdr(ifa->neigh_list);
-    ndr = electdr(ifa->neigh_list);
+    nbdr = electbdr(po, ifa->neigh_list);
+    ndr = electdr(po, ifa->neigh_list);
 
     if (ndr == NULL)
       ndr = nbdr;
@@ -492,13 +475,11 @@ bdr_election(struct ospf_iface *ifa)
  
   ifa->drid = ndr ? ndr->rid : 0;
   ifa->drip = ndr ? ndr->ip  : IPA_NONE;
+  ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
+
   ifa->bdrid = nbdr ? nbdr->rid : 0;
   ifa->bdrip = nbdr ? nbdr->ip  : IPA_NONE;
 
-#ifdef OSPFv3
-  ifa->dr_iface_id = ndr ? ndr->iface_id : 0;
-#endif
-
   DBG("DR=%R, BDR=%R\n", ifa->drid, ifa->bdrid);
 
   doadj = ((ifa->drid != odrid) || (ifa->bdrid != obdrid));
@@ -640,26 +621,28 @@ rxmt_timer_hook(timer * timer)
   {
     if (!EMPTY_SLIST(n->lsrtl))        /* FULL */
     {
-      list uplist;
-      slab *upslab;
-      struct l_lsr_head *llsh;
+      struct ospf_lsreq_item *lsr_head, *lsr;
+      struct ospf_lsreq_item **lsr_pos = &lsr_head;
 
-      init_list(&uplist);
-      upslab = sl_new(n->pool, sizeof(struct l_lsr_head));
+      slab *upslab = sl_new(n->pool, sizeof(struct ospf_lsreq_item));
 
       WALK_SLIST(en, n->lsrtl)
       {
        if ((SNODE en)->next == (SNODE en))
          bug("RTList is cycled");
-       llsh = sl_alloc(upslab);
-       llsh->lsh.id = en->lsa.id;
-       llsh->lsh.rt = en->lsa.rt;
-       llsh->lsh.type = en->lsa.type;
-       DBG("Working on ID: %R, RT: %R, Type: %u\n",
-           en->lsa.id, en->lsa.rt, en->lsa.type);
-       add_tail(&uplist, NODE llsh);
+
+       lsr = sl_alloc(upslab);
+       lsr->domain = en->domain;
+       lsr->type = en->lsa_type;
+       lsr->id = en->lsa.id;
+       lsr->rt = en->lsa.rt;
+
+       *lsr_pos = lsr;
+       lsr_pos = &(lsr->next);
       }
-      ospf_lsupd_send_list(n, &uplist);
+      *lsr_pos = NULL;
+
+      ospf_lsupd_send_list(n, lsr_head);
       rfree(upslab);
     }
   }
index 556e54842f0944157f55d5dc9432998dc3c8f8ee..d8296b9eba24cdfc5e20abcb94cb0ac8d745cdd1 100644 (file)
@@ -164,11 +164,7 @@ ospf_area_add(struct proto_ospf *po, struct ospf_area_config *ac, int reconf)
   if (oa->areaid == 0)
     po->backbone = oa;
 
-#ifdef OSPFv2
-  oa->options = ac->type;
-#else /* OSPFv3 */
-  oa->options = OPT_R | ac->type | OPT_V6;
-#endif
+  oa->options = ospf_is_v2(po) ? ac->type : (OPT_R | ac->type | OPT_V6);
 
   /*
    * Set E-bit for NSSA ABR routers. No need to explicitly call
@@ -383,7 +379,6 @@ schedule_net_lsa(struct ospf_iface *ifa)
   ifa->orignet = 1;
 }
 
-#ifdef OSPFv3
 void
 schedule_link_lsa(struct ospf_iface *ifa)
 {
@@ -392,7 +387,6 @@ schedule_link_lsa(struct ospf_iface *ifa)
   OSPF_TRACE(D_EVENTS, "Scheduling link-LSA origination for iface %s", ifa->iface->name);
   ifa->origlink = 1;
 }
-#endif
 
 void
 schedule_rt_lsa(struct ospf_area *oa)
@@ -589,7 +583,7 @@ ospf_rt_notify(struct proto *p, rtable *tbl UNUSED, net * n, rte * new, rte * ol
   // FIXME check for gw should be per ifa, not per iface
   if ((new->attrs->dest == RTD_ROUTER) &&
       ipa_nonzero(new->attrs->gw) &&
-      !ipa_has_link_scope(new->attrs->gw) &&
+      !ipa_is_link_local(new->attrs->gw) &&
       (ospf_iface_find((struct proto_ospf *) p, new->attrs->iface) != NULL))
     gw = new->attrs->gw;
 
@@ -682,11 +676,8 @@ ospf_area_reconfigure(struct ospf_area *oa, struct ospf_area_config *nac)
   oa->ac = nac;
 
   // FIXME better area type reconfiguration
-#ifdef OSPFv2
-  oa->options = nac->type;
-#else /* OSPFv3 */
-  oa->options = OPT_R | nac->type | OPT_V6;
-#endif
+  oa->options = ospf_is_v2(oa->po) ? nac->type : (OPT_R | nac->type | OPT_V6);
+
   if (oa_is_nssa(oa) && (oa->po->areano > 1))
     oa->po->ebit = 1;
 
@@ -986,7 +977,7 @@ lsa_compare_for_state(const void *p1, const void *p2)
   if (nt1)
   {
 #ifdef OSPFv3
-    /* In OSPFv3, neworks are named base on ID of DR */
+    /* In OSPFv3, networks are named based on ID of DR */
     if (lsa1->rt != lsa2->rt)
       return lsa1->rt - lsa2->rt;
 #endif
@@ -1488,17 +1479,17 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
        case LSA_SCOPE_AS:
          cli_msg(-1017, "Global");
          break;
+
        case LSA_SCOPE_AREA:
          cli_msg(-1017, "Area %R", hea[i]->domain);
          break;
-#ifdef OSPFv3
+
        case LSA_SCOPE_LINK:
          {
            struct iface *ifa = if_find_by_index(hea[i]->domain);
            cli_msg(-1017, "Link %s", (ifa != NULL) ? ifa->name : "?");
          }
          break;
-#endif
       }
       cli_msg(-1017, "");
       cli_msg(-1017," Type   LS ID           Router           Age  Sequence  Checksum");
@@ -1507,7 +1498,6 @@ ospf_sh_lsadb(struct lsadb_show_data *ld)
       last_domain = hea[i]->domain;
     }
 
-
     cli_msg(-1017," %04x  %-15R %-15R %5u  %08x    %04x",
            lsa->type, lsa->id, lsa->rt, lsa->age, lsa->sn, lsa->checksum);
   }
index 4d4cf67540a43d0bd39ff0a087f559938daa6d4f..0c12a506e55eb3648f658a2f6b0719be1ea2366f 100644 (file)
@@ -65,11 +65,10 @@ do { if ((po->proto.debug & D_PACKETS) || OSPF_FORCE_DEBUG) \
 #define MINLSARRIVAL 1
 #define LSINFINITY 0xffffff
 
-#define DEFAULT_OSPFTICK 1
-#define DEFAULT_RFC1583 0      /* compatibility with rfc1583 */
-#define DEFAULT_STUB_COST 1000
-#define DEFAULT_ECMP_LIMIT 16
-#define DEFAULT_TRANSINT 40
+#define OSPF_DEFAULT_TICK 1
+#define OSPF_DEFAULT_STUB_COST 1000
+#define OSPF_DEFAULT_ECMP_LIMIT 16
+#define OSPF_DEFAULT_TRANSINT 40
 
 
 struct ospf_config
@@ -202,11 +201,12 @@ struct ospf_iface
   u16 autype;
   u32 csn;                      /* Last used crypt seq number */
   bird_clock_t csn_use;         /* Last time when packet with that CSN was sent */
-  ip_addr all_routers;         /*  */
-  ip_addr drip;                        /* Designated router */
-  ip_addr bdrip;               /* Backup DR */
-  u32 drid;
-  u32 bdrid;
+  ip_addr all_routers;         /* XXXX */
+  ip_addr des_routers;         /* XXXX */
+  ip_addr drip;                        /* Designated router IP */
+  ip_addr bdrip;               /* Backup DR IP */
+  u32 drid;                    /* DR Router ID */
+  u32 bdrid;                   /* BDR Router ID */
   s16 rt_pos_beg;              /* Position of iface in Router-LSA, begin, inclusive */
   s16 rt_pos_end;              /* Position of iface in Router-LSA, end, exclusive */
   s16 px_pos_beg;              /* Position of iface in Rt Prefix-LSA, begin, inclusive */
@@ -244,7 +244,7 @@ struct ospf_iface
 #define OSPF_I_OK 0            /* Everything OK */
 #define OSPF_I_SK 1            /* Socket open failed */
 #define OSPF_I_LL 2            /* Missing link-local address (OSPFv3) */
-  u8 sk_dr;                    /* Socket is a member of DRouters group */
+  u8 sk_dr;                    /* Socket is a member of designated routers group */
   u8 marked;                   /* Used in OSPF reconfigure */
   u16 rxbuf;                   /* Buffer size */
   u8 check_link;               /* Whether iface link change is used */
@@ -276,7 +276,6 @@ union ospf_auth
 /* Area IDs */
 #define BACKBONE       0
 
-
 #define DBDES_I                4       /* Init bit */
 #define DBDES_M                2       /* More bit */
 #define DBDES_MS       1       /* Master/Slave bit */
@@ -284,7 +283,6 @@ union ospf_auth
 
 
 
-
 /*
  * There is slight difference in OSPF packet header between v2 and v3
  * in vdep field. For OSPFv2, vdep is u16 authentication type and
@@ -303,6 +301,18 @@ struct ospf_packet
   u16 vdep;
 };
 
+static inline u16 ospf_pkt_get_autype(struct ospf_packet *pkt)
+{ return ntohs(pkt->vdep); }
+
+static inline void ospf_pkt_set_autype(struct ospf_packet *pkt, u16 val)
+{ pkt->vdep = htons(val); }
+
+static inline u8 ospf_pkt_get_instance_id(struct ospf_packet *pkt)
+{ return ntohs(pkt->vdep) >> 8; }
+
+static inline void ospf_pkt_set_instance_id(struct ospf_packet *pkt, u16 val)
+{ pkt->vdep = htons(val << 8); }
+
 
 // XXXX
 /*
@@ -323,6 +333,8 @@ struct ospf_packet
 #define LSA_T_LINK     0x0008
 #define LSA_T_PREFIX   0x2009
 
+#define LSA_T_V2_MASK  0x00ff
+
 #define LSA_UBIT       0x8000
 
 #define LSA_SCOPE_LINK 0x0000
@@ -330,7 +342,7 @@ struct ospf_packet
 #define LSA_SCOPE_AS   0x4000
 #define LSA_SCOPE_RES  0x6000
 #define LSA_SCOPE_MASK 0x6000
-#define LSA_SCOPE(lsa) ((lsa) & LSA_SCOPE_MASK)
+#define LSA_SCOPE(type)        ((type) & LSA_SCOPE_MASK)
 
 
 #define LSA_MAXAGE     3600    /* 1 hour */
@@ -346,6 +358,8 @@ struct ospf_packet
 #define LSART_STUB     3
 #define LSART_VLNK     4
 
+#define LSA_RT2_LINKS  0x0000FFFF
+
 #define LSA_SUM2_TOS   0xFF000000
 
 #define LSA_EXT2_TOS   0x7F000000
@@ -399,6 +413,19 @@ struct ospf_lsa_rt2_link
 #endif
 };
 
+struct ospf_lsa_rt2_tos
+{
+#ifdef CPU_BIG_ENDIAN
+  u8 tos;
+  u8 padding;
+  u16 metric;
+#else
+  u16 metric;
+  u8 padding;
+  u8 tos;
+#endif
+};
+
 struct ospf_lsa_rt3_link
 {
 #ifdef CPU_BIG_ENDIAN
@@ -486,27 +513,6 @@ struct ospf_lsa_prefix
 };
 
 
-
-
-#ifdef OSPFv2
-
-
-/* Endianity swap for lsa->type */
-#define ntoht(x) x
-#define htont(x) x
-
-
-#else  /* OSPFv3 */
-
-
-
-
-/* Endianity swap for lsa->type */
-#define ntoht(x) ntohs(x)
-#define htont(x) htons(x)
-
-#endif
-
 #define METRIC_MASK  0x00FFFFFF
 #define OPTIONS_MASK 0x00FFFFFF
 
@@ -519,8 +525,6 @@ 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)
 
@@ -581,21 +585,21 @@ put_ipv6_addr(u32 *buf, ip_addr addr)
   return buf + 4;
 }
 
-#endif
-
-
 
 struct ospf_lsreq_header
 {
   u32 type;
   u32 id;
-  u32 rt;                      /* Advertising router */
+  u32 rt;
 };
 
-struct l_lsr_head
+struct ospf_lsreq_item
 {
-  node n;
-  struct ospf_lsreq_header lsh;
+  struct ospf_lsreq_item *next;
+  u32 domain;
+  u32 type;
+  u32 id;
+  u32 rt;
 };
 
 
@@ -625,19 +629,30 @@ struct ospf_neighbor
   u8 adj;                      /* built adjacency? */
   u32 options;                 /* Options received */
 
-  /* dr and bdr store IP address in OSPFv2 and router ID in OSPFv3,
-     we use the same type to simplify handling */
+  /* 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 iface_id;                        /* ID of Neighbour's iface connected to common network */
 
-  siterator dbsi;              /* Database summary list iterator */
-  slist lsrql;                 /* Link state request */
-  struct top_graph *lsrqh;     /* LSA graph */
-  siterator lsrqi;
-  slist lsrtl;                 /* Link state retransmission list */
-  siterator lsrti;
+  /* Database summary list iterator, controls initial dbdes exchange.
+   * Advances in the LSA list as dbdes packets are sent.
+   */
+  siterator dbsi;              /* iterator of po->lsal */
+
+  /* Link state request list, controls initial LSA exchange.
+   * Entries added when received in dbdes packets, removed as sent in lsreq packets.
+   */
+  slist lsrql;                 /* slist of struct top_hash_entry from n->lsrqh */
+  struct top_graph *lsrqh;
+
+  /* Link state retransmission list, controls LSA retransmission during flood.
+   * Entries added as sent in lsupd packets, removed when received in lsack packets.
+   */
+  slist lsrtl;                 /* slist of struct top_hash_entry from n->lsrth */
   struct top_graph *lsrth;
+
   void *ldbdes;                        /* Last database description packet */
   timer *rxmt_timer;           /* RXMT timer */
   list ackl[2];
index f42f6a10b7a9ecda7d2d377428c78470c2fd1f7d..c097a46757cf5a082e190a9cadc658e2bd534b29 100644 (file)
@@ -24,16 +24,12 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 
   pkt->routerid = htonl(po->router_id);
   pkt->areaid = htonl(ifa->oa->areaid);
-
-#ifdef OSPFv3
-  pkt->instance_id = ifa->instance_id;
-#endif
-
-#ifdef OSPFv2
-  pkt->autype = htons(ifa->autype);
-#endif
-
   pkt->checksum = 0;
+
+  if (ospf_is_v2(po))
+    ospf_pkt_set_autype(pkt, ifa->autype);
+  else
+    ospf_pkt_set_instance_id(pkt, ifa->instance_id);
 }
 
 unsigned
@@ -42,47 +38,48 @@ ospf_pkt_maxsize(struct ospf_iface *ifa)
   unsigned mtu = (ifa->type == OSPF_IT_VLINK) ? OSPF_VLINK_MTU : ifa->iface->mtu;
   unsigned headers = SIZE_OF_IP_HEADER;
 
-#ifdef OSPFv2
+  /* For OSPFv2 */
   if (ifa->autype == OSPF_AUTH_CRYPT)
     headers += OSPF_AUTH_CRYPT_SIZE;
-#endif
 
   return mtu - headers;
 }
 
-#ifdef OSPFv2
 
+/* We assume OSPFv2 in ospf_pkt_finalize() */
 static void
 ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
 {
   struct password_item *passwd = NULL;
-  void *tail;
-  struct MD5Context ctxt;
-  char password[OSPF_AUTH_CRYPT_SIZE];
+  union ospf_auth *auth = (void *) (pkt + 1);
+  unsigned plen = ntohs(pkt->length);
 
   pkt->checksum = 0;
-  pkt->autype = htons(ifa->autype);
-  bzero(&pkt->u, sizeof(union ospf_auth));
+  ospf_pkt_set_autype(pkt, ifa->autype);
+  bzero(auth, sizeof(union ospf_auth));
 
-  /* Compatibility note: pkt->u may contain anything if autype is
+  /* Compatibility note: auth may contain anything if autype is
      none, but nonzero values do not work with Mikrotik OSPF */
 
-  switch(ifa->autype)
+  switch (ifa->autype)
   {
     case OSPF_AUTH_SIMPLE:
       passwd = password_find(ifa->passwords, 1);
       if (!passwd)
       {
-        log( L_ERR "No suitable password found for authentication" );
+        log(L_ERR "No suitable password found for authentication");
         return;
       }
-      password_cpy(pkt->u.password, passwd->password, sizeof(union ospf_auth));
+      password_cpy(auth->password, passwd->password, sizeof(union ospf_auth));
+
     case OSPF_AUTH_NONE:
-      pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet) -
-                                  sizeof(union ospf_auth), (pkt + 1),
-                                 ntohs(pkt->length) -
-                                 sizeof(struct ospf_packet), NULL);
+      {
+       void *body = (void *) (auth + 1);
+       unsigned blen = plen - sizeof(struct ospf_packet) - sizeof(union ospf_auth);
+       pkt->checksum = ipsum_calculate(pkt, sizeof(struct ospf_packet), body, blen, NULL);
+      }
       break;
+
     case OSPF_AUTH_CRYPT:
       passwd = password_find(ifa->passwords, 0);
       if (!passwd)
@@ -106,45 +103,53 @@ ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
 
       ifa->csn_use = now;
 
-      pkt->u.md5.keyid = passwd->id;
-      pkt->u.md5.len = OSPF_AUTH_CRYPT_SIZE;
-      pkt->u.md5.zero = 0;
-      pkt->u.md5.csn = htonl(ifa->csn);
-      tail = ((void *)pkt) + ntohs(pkt->length);
-      MD5Init(&ctxt);
-      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
-      password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
-      MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
-      MD5Final(tail, &ctxt);
+      auth->md5.zero = 0;
+      auth->md5.keyid = passwd->id;
+      auth->md5.len = OSPF_AUTH_CRYPT_SIZE;
+      auth->md5.csn = htonl(ifa->csn);
+
+      {
+       void *tail = ((void *) pkt) + plen;
+       char password[OSPF_AUTH_CRYPT_SIZE];
+       password_cpy(password, passwd->password, OSPF_AUTH_CRYPT_SIZE);
+
+       struct MD5Context ctxt;
+       MD5Init(&ctxt);
+       MD5Update(&ctxt, (char *) pkt, plen);
+       MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
+       MD5Final(tail, &ctxt);
+      }
       break;
+
     default:
       bug("Unknown authentication type");
   }
 }
 
+/* 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)
 {
   struct proto_ospf *po = ifa->oa->po;
-  struct proto *p = &po->proto;
+  union ospf_auth *auth = (void *) (pkt + 1);
   struct password_item *pass = NULL, *ptmp;
-  void *tail;
-  char md5sum[OSPF_AUTH_CRYPT_SIZE];
   char password[OSPF_AUTH_CRYPT_SIZE];
-  struct MD5Context ctxt;
 
+  unsigned plen = ntohs(pkt->length);
+  u16 autype = ospf_pkt_get_autype(pkt);
 
-  if (pkt->autype != htons(ifa->autype))
+  if (autype != ifa->autype)
   {
-    OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", ntohs(pkt->autype));
+    OSPF_TRACE(D_PACKETS, "OSPF_auth: Method differs (%d)", autype);
     return 0;
   }
 
-  switch(ifa->autype)
+  switch (autype)
   {
     case OSPF_AUTH_NONE:
       return 1;
       break;
+
     case OSPF_AUTH_SIMPLE:
       pass = password_find(ifa->passwords, 1);
       if (!pass)
@@ -154,37 +159,48 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
       }
       password_cpy(password, pass->password, sizeof(union ospf_auth));
 
-      if (memcmp(pkt->u.password, password, sizeof(union ospf_auth)))
+      if (memcmp(auth->password, password, sizeof(union ospf_auth)))
       {
         char ppass[sizeof(union ospf_auth) + 1];
         bzero(ppass, (sizeof(union ospf_auth) + 1));
-        memcpy(ppass, pkt->u.password, sizeof(union ospf_auth));
+        memcpy(ppass, auth->password, sizeof(union ospf_auth));
         OSPF_TRACE(D_PACKETS, "OSPF_auth: different passwords (%s)", ppass);
        return 0;
       }
       return 1;
       break;
+
     case OSPF_AUTH_CRYPT:
-      if (pkt->u.md5.len != OSPF_AUTH_CRYPT_SIZE)
+      if (auth->md5.len != OSPF_AUTH_CRYPT_SIZE)
       {
         OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong size of md5 digest");
         return 0;
       }
 
-      if (ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE > size)
+      if (plen + OSPF_AUTH_CRYPT_SIZE > size)
       {
         OSPF_TRACE(D_PACKETS, "OSPF_auth: size mismatch (%d vs %d)",
-         ntohs(pkt->length) + OSPF_AUTH_CRYPT_SIZE, size);
+                  plen + OSPF_AUTH_CRYPT_SIZE, size);
         return 0;
       }
 
-      tail = ((void *)pkt) + ntohs(pkt->length);
+      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 (pkt->u.md5.keyid != ptmp->id) continue;
+         if (auth->md5.keyid != ptmp->id) continue;
          if ((ptmp->accfrom > now_real) || (ptmp->accto < now_real)) continue;
          pass = ptmp;
          break;
@@ -197,50 +213,32 @@ ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_
         return 0;
       }
 
-      if (n)
+      password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
+
       {
-       u32 rcv_csn = ntohl(pkt->u.md5.csn);
-       if(rcv_csn < n->csn)
+       void *tail = ((void *) pkt) + plen;
+       char md5sum[OSPF_AUTH_CRYPT_SIZE];
+
+       struct MD5Context ctxt;
+       MD5Init(&ctxt);
+       MD5Update(&ctxt, (char *) pkt, plen);
+       MD5Update(&ctxt, password, OSPF_AUTH_CRYPT_SIZE);
+       MD5Final(md5sum, &ctxt);
+       if (memcmp(md5sum, tail, OSPF_AUTH_CRYPT_SIZE))
        {
-         OSPF_TRACE(D_PACKETS, "OSPF_auth: lower sequence number (rcv %d, old %d)", rcv_csn, n->csn);
+         OSPF_TRACE(D_PACKETS, "OSPF_auth: wrong md5 digest");
          return 0;
        }
-
-       n->csn = rcv_csn;
-      }
-
-      MD5Init(&ctxt);
-      MD5Update(&ctxt, (char *) pkt, ntohs(pkt->length));
-      password_cpy(password, pass->password, OSPF_AUTH_CRYPT_SIZE);
-      MD5Update(&ctxt, password, 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;
       }
       return 1;
       break;
+
     default:
       OSPF_TRACE(D_PACKETS, "OSPF_auth: unknown auth type");
       return 0;
   }
 }
 
-#else
-
-/* OSPFv3 authentication not yet supported */
-
-static inline void
-ospf_pkt_finalize(struct ospf_iface *ifa, struct ospf_packet *pkt)
-{ }
-
-static int
-ospf_pkt_checkauth(struct ospf_neighbor *n, struct ospf_iface *ifa, struct ospf_packet *pkt, int size)
-{ return 1; }
-#endif
-
 
 /**
  * ospf_rx_hook
@@ -273,37 +271,39 @@ ospf_rx_hook(sock *sk, int size)
   int src_local, dst_local UNUSED, dst_mcast; 
   src_local = ipa_in_net(sk->faddr, ifa->addr->prefix, ifa->addr->pxlen);
   dst_local = ipa_equal(sk->laddr, ifa->addr->ip);
-  dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, AllDRouters);
-
-#ifdef OSPFv2
-  /* First, we eliminate packets with strange address combinations.
-   * In OSPFv2, they might be for other ospf_ifaces (with different IP
-   * prefix) on the same real iface, so we don't log it. We enforce
-   * that (src_local || dst_local), therefore we are eliminating all
-   * such cases. 
-   */
-  if (dst_mcast && !src_local)
-    return 1;
-  if (!dst_mcast && !dst_local)
-    return 1;
+  dst_mcast = ipa_equal(sk->laddr, ifa->all_routers) || ipa_equal(sk->laddr, ifa->des_routers);
 
-  /* Ignore my own broadcast packets */
-  if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
-    return 1;
-#else /* OSPFv3 */
+  if (ospf_is_v2(po))
+  {
+    /* First, we eliminate packets with strange address combinations.
+     * In OSPFv2, they might be for other ospf_ifaces (with different IP
+     * prefix) on the same real iface, so we don't log it. We enforce
+     * that (src_local || dst_local), therefore we are eliminating all
+     * such cases. 
+     */
+    if (dst_mcast && !src_local)
+      return 1;
+    if (!dst_mcast && !dst_local)
+      return 1;
 
-  /* In OSPFv3, src_local and dst_local mean link-local. 
-   * RFC 5340 says that local (non-vlink) packets use
-   * 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);
-#endif
+    /* Ignore my own broadcast packets */
+    if (ifa->cf->real_bcast && ipa_equal(sk->faddr, ifa->addr->ip))
+      return 1;
+  }
+  else
+  {
+    /* In OSPFv3, src_local and dst_local mean link-local. 
+     * RFC 5340 says that local (non-vlink) packets use
+     * 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);
+  }
 
   /* Second, we check packet size, checksum, and the protocol version */
-  struct ospf_packet *ps = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
+  struct ospf_packet *pkt = (struct ospf_packet *) ip_skip_header(sk->rbuf, &size);
 
-  if (ps == NULL)
+  if (pkt == NULL)
   {
     log(L_ERR "%s%I - bad IP header", mesg, sk->faddr);
     return 1;
@@ -315,16 +315,16 @@ ospf_rx_hook(sock *sk, int size)
     return 1;
   }
 
-  int osize = ntohs(ps->length);
-  if ((unsigned) osize < sizeof(struct ospf_packet))
+  unsigned plen = ntohs(pkt->length);
+  if (plen < sizeof(struct ospf_packet))
   {
-    log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, osize);
+    log(L_ERR "%s%I - too low value in size field (%u bytes)", mesg, sk->faddr, plen);
     return 1;
   }
 
-  if ((osize > size) || ((osize % 4) != 0))
+  if ((plen > size) || ((plen % 4) != 0))
   {
-    log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, osize, size);
+    log(L_ERR "%s%I - size field does not match (%d/%d)", mesg, sk->faddr, plen, size);
     return 1;
   }
 
@@ -334,50 +334,47 @@ ospf_rx_hook(sock *sk, int size)
     return 1;
   }
 
-  if (ps->version != OSPF_VERSION)
+  if (pkt->version != OSPF_VERSION)
   {
-    log(L_ERR "%s%I - version %u", mesg, sk->faddr, ps->version);
+    log(L_ERR "%s%I - version %u", mesg, sk->faddr, pkt->version);
     return 1;
   }
 
-#ifdef OSPFv2
-  if ((ps->autype != htons(OSPF_AUTH_CRYPT)) &&
-      (!ipsum_verify(ps, 16, (void *) ps + sizeof(struct ospf_packet),
-                    osize - sizeof(struct ospf_packet), NULL)))
+  if (ospf_is_v2(po) && ospf_pkt_get_autype(pkt) != OSPF_AUTH_CRYPT)
   {
-    log(L_ERR "%s%I - bad checksum", mesg, sk->faddr);
-    return 1;
-  }
-#endif
+    unsigned hlen = sizeof(struct ospf_packet) - sizeof(union ospf_auth);
+    unsigned 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;
+    }
+  }
 
   /* Third, we resolve associated iface and handle vlinks. */
 
-  u32 areaid = ntohl(ps->areaid);
-  u32 rid = ntohl(ps->routerid);
+  u32 areaid = ntohl(pkt->areaid);
+  u32 rid = ntohl(pkt->routerid);
+  u8 instance_id = ospf_is_v2(po) ? 0 : ospf_pkt_get_instance_id(pkt);
 
-  if ((areaid == ifa->oa->areaid)
-#ifdef OSPFv3
-      && (ps->instance_id == ifa->instance_id)
-#endif
-      )
+  if ((areaid == ifa->oa->areaid) &&
+      (instance_id == ifa->instance_id))
   {
     /* It is real iface, source should be local (in OSPFv2) */
-#ifdef OSPFv2
-    if (!src_local)
+    if (ospf_is_v2(po) && !src_local)
       return 1;
-#endif
   }
   else if (dst_mcast || (areaid != 0))
   {
     /* Obvious mismatch */
 
-#ifdef OSPFv2
-    /* We ignore mismatch in OSPFv3, because there might be
-       other instance with different instance ID */
-    log(L_ERR "%s%I - area does not match (%R vs %R)",
-       mesg, sk->faddr, areaid, ifa->oa->areaid);
-#endif
+    /* We ignore mismatch in OSPFv3 when there might be
+       another instance with a different instance ID */
+    if (instance_id == ifa->instance_id)
+      log(L_ERR "%s%I - area does not match (%R vs %R)",
+         mesg, sk->faddr, areaid, ifa->oa->areaid);
     return 1;
   }
   else
@@ -389,9 +386,7 @@ ospf_rx_hook(sock *sk, int size)
     {
       if ((iff->type == OSPF_IT_VLINK) && 
          (iff->voa == ifa->oa) &&
-#ifdef OSPFv3
-         (iff->instance_id == ps->instance_id) &&
-#endif
+         (iff->instance_id == instance_id) &&
          (iff->vid == rid))
        {
          /* Vlink should be UP */
@@ -403,9 +398,10 @@ ospf_rx_hook(sock *sk, int size)
        }
     }
 
-#ifdef OSPFv2
-    log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
-#endif
+    /* FIXME: this warning is strange - NBMA could trigger it too */
+    if (ospf_is_v2(po))
+      log(L_WARN "OSPF: Received packet for unknown vlink (ID %R, IP %I)", rid, sk->faddr);
+
     return 1;
   }
 
@@ -413,7 +409,7 @@ ospf_rx_hook(sock *sk, int size)
   if (ifa->stub)           /* This shouldn't happen */
     return 1;
 
-  if (ipa_equal(sk->laddr, AllDRouters) && (ifa->sk_dr == 0))
+  if (ipa_equal(sk->laddr, ifa->des_routers) && (ifa->sk_dr == 0))
     return 1;
 
   if (rid == po->router_id)
@@ -428,25 +424,22 @@ ospf_rx_hook(sock *sk, int size)
     return 1;
   }
 
-#ifdef OSPFv2
   /* In OSPFv2, neighbors are identified by either IP or Router ID, base on network type */
+  unsigned t = ifa->type;
   struct ospf_neighbor *n;
-  if ((ifa->type == OSPF_IT_BCAST) || (ifa->type == OSPF_IT_NBMA) || (ifa->type == OSPF_IT_PTMP))
+  if (ospf_is_v2(po) && ((t == OSPF_IT_BCAST) || (t == OSPF_IT_NBMA) || (t == OSPF_IT_PTMP)))
     n = find_neigh_by_ip(ifa, sk->faddr);
   else
     n = find_neigh(ifa, rid);
-#else
-  struct ospf_neighbor *n = find_neigh(ifa, rid);
-#endif
 
-  if (!n && (ps->type != HELLO_P))
+  if (!n && (pkt->type != HELLO_P))
   {
     log(L_WARN "OSPF: Received non-hello packet from unknown neighbor (src %I, iface %s)",
        sk->faddr, ifa->iface->name);
     return 1;
   }
 
-  if (!ospf_pkt_checkauth(n, ifa, ps, size))
+  if (ospf_is_v2(po) && ! ospf_pkt_checkauth(n, ifa, pkt, size))
   {
     log(L_ERR "%s%I - authentication failed", mesg, sk->faddr);
     return 1;
@@ -454,36 +447,36 @@ ospf_rx_hook(sock *sk, int size)
 
   /* Dump packet 
      pu8=(u8 *)(sk->rbuf+5*4);
-     for(i=0;i<ntohs(ps->length);i+=4)
+     for(i=0;i<ntohs(pkt->length);i+=4)
      DBG("%s: received %u,%u,%u,%u\n",p->name, pu8[i+0], pu8[i+1], pu8[i+2],
      pu8[i+3]);
      DBG("%s: received size: %u\n",p->name,size);
    */
 
-  switch (ps->type)
+  switch (pkt->type)
   {
   case HELLO_P:
     DBG("%s: Hello received.\n", p->name);
-    ospf_hello_receive(ps, ifa, n, sk->faddr);
+    ospf_hello_receive(pkt, ifa, n, sk->faddr);
     break;
   case DBDES_P:
     DBG("%s: Database description received.\n", p->name);
-    ospf_dbdes_receive(ps, ifa, n);
+    ospf_dbdes_receive(pkt, ifa, n);
     break;
   case LSREQ_P:
     DBG("%s: Link state request received.\n", p->name);
-    ospf_lsreq_receive(ps, ifa, n);
+    ospf_lsreq_receive(pkt, ifa, n);
     break;
   case LSUPD_P:
     DBG("%s: Link state update received.\n", p->name);
-    ospf_lsupd_receive(ps, ifa, n);
+    ospf_lsupd_receive(pkt, ifa, n);
     break;
   case LSACK_P:
     DBG("%s: Link state ack received.\n", p->name);
-    ospf_lsack_receive(ps, ifa, n);
+    ospf_lsack_receive(pkt, ifa, n);
     break;
   default:
-    log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, ps->type);
+    log(L_ERR "%s%I - wrong type %u", mesg, sk->faddr, pkt->type);
     return 1;
   };
   return 1;
@@ -505,6 +498,27 @@ ospf_err_hook(sock * sk, int err)
   log(L_ERR "OSPF: Socket error on %s: %M", ifa->iface->name, err);
 }
 
+void
+ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
+{
+  sock *sk = ifa->sk;
+  struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
+  int plen = ntohs(pkt->length);
+
+  if (sk->tbuf != sk->tpos)
+    log(L_ERR "Aiee, old packet was overwritten in TX buffer");
+
+  if (ospf_is_v2(ifa->oa->po))
+  {
+    if (ifa->autype == OSPF_AUTH_CRYPT)
+      plen += OSPF_AUTH_CRYPT_SIZE;
+
+    ospf_pkt_finalize(ifa, pkt);
+  }
+
+  sk_send_to(sk, plen, dst, 0);
+}
+
 void
 ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
 {
@@ -518,28 +532,8 @@ ospf_send_to_agt(struct ospf_iface *ifa, u8 state)
 void
 ospf_send_to_bdr(struct ospf_iface *ifa)
 {
-  if (!ipa_equal(ifa->drip, IPA_NONE))
+  if (ipa_nonzero(ifa->drip))
     ospf_send_to(ifa, ifa->drip);
-  if (!ipa_equal(ifa->bdrip, IPA_NONE))
+  if (ipa_nonzero(ifa->bdrip))
     ospf_send_to(ifa, ifa->bdrip);
 }
-
-void
-ospf_send_to(struct ospf_iface *ifa, ip_addr dst)
-{
-  sock *sk = ifa->sk;
-  struct ospf_packet *pkt = (struct ospf_packet *) sk->tbuf;
-  int len = ntohs(pkt->length);
-
-#ifdef OSPFv2
-  if (ifa->autype == OSPF_AUTH_CRYPT)
-    len += OSPF_AUTH_CRYPT_SIZE;
-#endif
-
-  ospf_pkt_finalize(ifa, pkt);
-  if (sk->tbuf != sk->tpos)
-    log(L_ERR "Aiee, old packet was overwritten in TX buffer");
-
-  sk_send_to(sk, len, dst, 0);
-}
-
index fbcb4288a9c5f37e46c651c198b609e8bcdf51f8..863a0293bcfd5024bf60d283a66441df7df08a30 100644 (file)
@@ -15,24 +15,32 @@ unsigned ospf_pkt_maxsize(struct ospf_iface *ifa);
 int ospf_rx_hook(sock * sk, int size);
 void ospf_tx_hook(sock * sk);
 void ospf_err_hook(sock * sk, int err);
+void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
+
 void ospf_send_to_agt(struct ospf_iface *ifa, u8 state);
 void ospf_send_to_bdr(struct ospf_iface *ifa);
-void ospf_send_to(struct ospf_iface *ifa, ip_addr ip);
 
-static inline void ospf_send_to_all(struct ospf_iface *ifa) { ospf_send_to(ifa, ifa->all_routers); }
+static inline void ospf_send_to_all(struct ospf_iface *ifa)
+{
+  ospf_send_to(ifa, ifa->all_routers);
+}
+
+static inline void ospf_send_to_des(struct ospf_iface *ifa)
+{
+  if (ipa_nonzero(ifa->des_routers))
+    ospf_send_to(ifa, ifa->des_routers);
+  else
+    ospf_send_to_bdr(ifa);
+}
 
 static inline void * ospf_tx_buffer(struct ospf_iface *ifa) { return ifa->sk->tbuf; }
 
 static inline unsigned
 ospf_pkt_bufsize(struct ospf_iface *ifa)
 {
-#ifdef OSPFv2
-  unsigned headers = (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
-#else
-  unsigned headers = 0;
-#endif
-
-  return ifa->sk->tbsize - headers;
+  /* Reserve buffer space for authentication footer */
+  return ifa->sk->tbsize - 
+    (ifa->autype == OSPF_AUTH_CRYPT) ? OSPF_AUTH_CRYPT_SIZE : 0;
 }
 
 
index 40de6561eab9986539c318575bec2c3d00acf73b..68a577bd08f84444a4094e682c5654c0543ada94 100644 (file)
@@ -15,12 +15,8 @@ static void rt_sync(struct proto_ospf *po);
 
 /* In ospf_area->rtr we store paths to routers, but we use RID (and not IP address)
    as index, so we need to encapsulate RID to IP address */
-#ifdef OSPFv2
-#define ipa_from_rid(x) _MI(x)
-#else /* OSPFv3 */
-#define ipa_from_rid(x) _MI6(0,0,0,x)
-#endif
 
+#define ipa_from_rid(x) ipa_from_u32(x)
 
 static inline void reset_ri(ort *ort)
 {
@@ -311,7 +307,7 @@ spfa_process_rt(struct ospf_area *oa, struct top_hash_entry *act)
   struct ospf_lsa_rt_walk rtl;
   struct top_hash_entry *tmp;
   ip_addr prefix;
-  int pxlen;
+  int pxlen, i;
 
   if (rt->options & OPT_RT_V)
     oa->trcap = 1;
@@ -339,8 +335,7 @@ spfa_process_rt(struct ospf_area *oa, struct top_hash_entry *act)
   }
 
   /* Now process Rt links */
-  lsa_walk_rt_init(po, act, &rtl);
-  while (lsa_walk_rt(&rtl))
+  for (lsa_walk_rt_init(po, act, &rtl), i = 0; lsa_walk_rt(&rtl); i++)
   {
     tmp = NULL;
 
index 7e625493fb5ebd1f701f0115d21a6f4ff819adcf..fd4e9cd898afd26f840a038413c7f6dcd5540e30 100644 (file)
@@ -31,12 +31,11 @@ void flush_prefix_net_lsa(struct ospf_iface *ifa);
 #endif
 
 
-#ifdef OSPFv2
 static inline u32
 fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
 {
-  /* We have to map IP prefixes to u32 in such manner that resulting
-     u32 interpreted as IP address is a member of given
+  /* In OSPFv2, We have to map IP prefixes to u32 in such manner 
+     that resulting u32 interpreted as IP address is a member of given
      prefix. Therefore, /32 prefix have to be mapped on itself.
      All received prefixes have to be mapped on different u32s.
 
@@ -63,7 +62,18 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
      possible to have both reliably and the suggested algorithm was
      unnecessary complicated and it does crazy things like changing
      LSA ID for a network because different network appeared, we
-     choose a different way. */
+     choose a different way.
+
+     In OSPFv3, it is simpler. There is not a requirement for
+     membership of the result in the input network, so we just use a
+     hash-based unique ID of a routing table entry for a route that
+     originated given LSA. For ext-LSA, it is an imported route in the
+     nest's routing table (p->table). For summary-LSA, it is a
+     'source' route in the protocol internal routing table (po->rtf).
+  */
+
+  if (ospf_is_v3(po))
+    return fn->uid;
 
   u32 id = _I(fn->prefix);
 
@@ -76,24 +86,6 @@ fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
     return id | ~u32_mkmask(fn->pxlen);
 }
 
-#else /* OSPFv3 */
-
-static inline u32
-fibnode_to_lsaid(struct proto_ospf *po, struct fib_node *fn)
-{
-  /*
-   * In OSPFv3, it is simpler. There is not a requirement for
-   * membership of the result in the input network, so we just use a
-   * hash-based unique ID of a routing table entry for a route that
-   * originated given LSA. For ext-LSA, it is an imported route in the
-   * nest's routing table (p->table). For summary-LSA, it is a
-   * 'source' route in the protocol internal routing table (po->rtf).
-   */
-  return fn->uid;
-}
-
-#endif
-
 
 static void *
 lsab_alloc(struct proto_ospf *po, unsigned size)
@@ -1611,7 +1603,7 @@ ospf_top_rehash(struct top_graph *f, int step)
     while (e)
     {
       x = e->next;
-      n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
+      n = newt + ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
       e->next = *n;
       *n = e;
       e = x;
@@ -1620,35 +1612,6 @@ ospf_top_rehash(struct top_graph *f, int step)
   ospf_top_ht_free(oldt);
 }
 
-#ifdef OSPFv2
-
-u32
-ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
-{
-  return (type == LSA_T_EXT) ? 0 : ifa->oa->areaid;
-}
-
-#else /* OSPFv3 */
-
-u32
-ospf_lsa_domain(u32 type, struct ospf_iface *ifa)
-{
-  switch (type & LSA_SCOPE_MASK)
-    {
-    case LSA_SCOPE_LINK:
-      return ifa->iface->index;
-
-    case LSA_SCOPE_AREA:
-      return ifa->oa->areaid;
-
-    case LSA_SCOPE_AS:
-    default:
-      return 0;
-    }
-}
-
-#endif
-
 struct top_hash_entry *
 ospf_hash_find_header(struct top_graph *f, u32 domain, struct ospf_lsa_header *h)
 {
@@ -1667,7 +1630,8 @@ ospf_hash_find(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
   struct top_hash_entry *e;
   e = f->hash_table[ospf_top_hash(f, domain, lsa, rtr, type)];
 
-  while (e && (e->lsa.id != lsa || e->lsa.type != type || e->lsa.rt != rtr || e->domain != domain))
+  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr ||
+              e->lsa_type != type || e->domain != domain))
     e = e->next;
 
   return e;
@@ -1749,7 +1713,8 @@ ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
   ee = f->hash_table + ospf_top_hash(f, domain, lsa, rtr, type);
   e = *ee;
 
-  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || e->lsa.type != type || e->domain != domain))
+  while (e && (e->lsa.id != lsa || e->lsa.rt != rtr || 
+              e->lsa_type != type || e->domain != domain))
     e = e->next;
 
   if (e)
@@ -1762,8 +1727,9 @@ ospf_hash_get(struct top_graph *f, u32 domain, u32 lsa, u32 rtr, u32 type)
   e->lb = IPA_NONE;
   e->lsa.id = lsa;
   e->lsa.rt = rtr;
-  e->lsa.type = type;
+  e->lsa.type = type; 
   e->lsa_body = NULL;
+  e->lsa_type = type;
   e->domain = domain;
   e->next = *ee;
   *ee = e;
@@ -1776,7 +1742,7 @@ void
 ospf_hash_delete(struct top_graph *f, struct top_hash_entry *e)
 {
   struct top_hash_entry **ee = f->hash_table + 
-    ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa.type);
+    ospf_top_hash(f, e->domain, e->lsa.id, e->lsa.rt, e->lsa_type);
 
   while (*ee)
   {
index 909f9d30294d4cebad3b20dd86775c3411bc4b1e..4d7a17560a60850750c0e81003007d027ff3652a 100644 (file)
@@ -23,9 +23,7 @@ struct top_hash_entry
   bird_clock_t inst_t;         /* Time of installation into DB */
   struct mpnh *nhs;            /* Computed nexthops - valid only in ospf_rt_spf() */
   ip_addr lb;                  /* In OSPFv2, link back address. In OSPFv3, any global address in the area useful for vlinks */
-#ifdef OSPFv3
   u32 lb_id;                   /* Interface ID of link back iface (for bcast or NBMA networks) */
-#endif
   u32 dist;                    /* Distance from the root */
   u16 ini_age;
   u8 color;
@@ -51,16 +49,14 @@ struct top_graph
 struct top_graph *ospf_top_new(pool *);
 void ospf_top_free(struct top_graph *);
 void ospf_top_dump(struct top_graph *, struct proto *);
-u32 ospf_lsa_domain(u32 type, struct ospf_iface *ifa);
+
 struct top_hash_entry *ospf_hash_find_header(struct top_graph *f, u32 domain,
                                             struct ospf_lsa_header *h);
 struct top_hash_entry *ospf_hash_get_header(struct top_graph *f, u32 domain,
                                            struct ospf_lsa_header *h);
 
-struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
-                                     u32 type);
-struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr,
-                                    u32 type);
+struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
+struct top_hash_entry *ospf_hash_get(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
 void ospf_hash_delete(struct top_graph *, struct top_hash_entry *);
 void originate_rt_lsa(struct ospf_area *oa);
 void update_rt_lsa(struct ospf_area *oa);