]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary OSPFv3 development commit
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 27 Aug 2009 16:25:46 +0000 (18:25 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 27 Aug 2009 16:25:46 +0000 (18:25 +0200)
lib/ipv6.c
lib/ipv6.h
nest/neighbor.c
proto/ospf/iface.c
proto/ospf/lsalib.c
proto/ospf/lsupd.c
proto/ospf/neighbor.c
proto/ospf/ospf.h
proto/ospf/rt.c
proto/ospf/topology.c
sysdep/unix/io.c

index 3334b976ce6ccf39f6545026784531e1a8a7d982..88c54eb6e733550a3ecbfa9640bc46dca3c4f953 100644 (file)
@@ -136,60 +136,6 @@ ipv6_compare(ip_addr X, ip_addr Y)
   return 0;
 }
 
-/* From Linux include/net/ipv6.h */
-#define NEXTHDR_HOP             0       /* Hop-by-hop option header. */
-#define NEXTHDR_ROUTING         43      /* Routing header. */
-#define NEXTHDR_FRAGMENT        44      /* Fragmentation/reassembly header. */
-#define NEXTHDR_DEST            60      /* Destination options header. */
-#define NEXTHDR_NONE            59      /* No next header */
-
-#define NEXTHDR_ESP             50      /* Encapsulating security payload. */
-#define NEXTHDR_AUTH            51      /* Authentication header. */
-
-
-byte *
-ipv6_skip_header(byte *pkt, int *len)
-{
-  int l = *len;
-  int q;
-  u8 nh;
-
-  if (l < 40 || (*pkt & 0xf0) != 0x60)
-    return NULL;
-
-  /* Skip IPv6 header */
-  nh = pkt[6];
-  pkt += 40;
-
-  while ()
-    {
-      switch (nw)
-       {
-       case NEXTHDR_FRAGMENT:
-
-       case NEXTHDR_HOP:
-       case NEXTHDR_ROUTING:
-       case NEXTHDR_DEST:
-
-       case NEXTHDR_AUTH:
-         break;
-
-       case NEXTHDR_NONE:
-         return NULL;
-
-       default:
-         return pkt;
-       }
-    }
-
-  q = (*pkt & 0x0f) * 4;
-  if (q > l)
-    return NULL;
-  *len -= q;
-  return pkt + q;
-}
-
-
 /*
  *  Conversion of IPv6 address to presentation format and vice versa.
  *  Heavily inspired by routines written by Paul Vixie for the BIND project
index d2b77c01dd5e014029225a567ac7d7ca6112c75d..592e57c7c82c7c2a2b6f62b400cf56f4f92ce18b 100644 (file)
@@ -69,6 +69,9 @@ typedef struct ipv6_addr {
 #define ipa_getbit(x, y) ipv6_getbit(x, y)
 #define ipa_absolutize(x,y) ipv6_absolutize(x,y)
 
+/* In IPv6, SOCK_RAW does not return packet header */
+#define ip_skip_header(x, y) x
+
 ip_addr ipv6_mkmask(unsigned);
 unsigned ipv6_mklen(ip_addr *);
 int ipv6_classify(ip_addr *);
index 2c5af6a626376bf27a9d6a4b8f8e0c4d234899ff..01dd2adaf486b900c55527893fb8d582e9383797 100644 (file)
@@ -102,6 +102,12 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
 
 neighbor *
 neigh_find(struct proto *p, ip_addr *a, unsigned flags)
+{
+  return neigh_find2(p, a, NULL, flags);
+}
+
+neighbor *
+neigh_find2(struct proto *p, ip_addr *a, unsigned flags)
 {
   neighbor *n;
   int class, scope = SCOPE_HOST;
index cae36ad38637e85d94496f093ad6ef695b58dfc1..c902a878d3b5809911f42f292d2176a395e65223 100644 (file)
@@ -67,7 +67,13 @@ ospf_open_ip_socket(struct ospf_iface *ifa)
   ipsk = sk_new(p->pool);
   ipsk->type = SK_IP;
   ipsk->dport = OSPF_PROTO;
+
+#ifdef OSPFv2
   ipsk->saddr = ifa->iface->addr->ip;
+#else /* OSPFv3 */
+  ipsk->saddr = ifa->lladdr;
+#endif
+
   ipsk->tos = IP_PREC_INTERNET_CONTROL;
   ipsk->ttl = 1;
   if (ifa->type == OSPF_IT_VLINK)
@@ -135,7 +141,13 @@ ospf_iface_chstate(struct ospf_iface *ifa, u8 state)
            ifa->dr_sk->type = SK_IP_MC;
            ifa->dr_sk->sport = 0;
            ifa->dr_sk->dport = OSPF_PROTO;
+
+#ifdef OSPFv2
            ifa->dr_sk->saddr = AllDRouters;
+#else /* OSPFv3 */
+           ifa->dr_sk->saddr = ifa->lladdr;
+#endif
+
            ifa->dr_sk->daddr = AllDRouters;
            ifa->dr_sk->tos = IP_PREC_INTERNET_CONTROL;
            ifa->dr_sk->ttl = 1;
@@ -308,7 +320,13 @@ ospf_open_mc_socket(struct ospf_iface *ifa)
   mcsk->type = SK_IP_MC;
   mcsk->sport = 0;
   mcsk->dport = OSPF_PROTO;
-  mcsk->saddr = AllSPFRouters;
+
+#ifdef OSPFv2
+  mcsk->saddr = AllDRouters;
+#else /* OSPFv3 */
+  mcsk->saddr = ifa->lladdr;
+#endif
+
   mcsk->daddr = AllSPFRouters;
   mcsk->tos = IP_PREC_INTERNET_CONTROL;
   mcsk->ttl = 1;
index 4cbabcc13f660594da595822f0593165db52c433..3bc5986c55726fee2844f39d7e14c17514f56bbc 100644 (file)
@@ -99,7 +99,7 @@ htonlsah(struct ospf_lsa_header *h, struct ospf_lsa_header *n)
 #ifdef OSPFv2
   n->options = h->options;
 #endif
-  n->type = h->type;
+  n->type = htont(h->type);
   n->id = htonl(h->id);
   n->rt = htonl(h->rt);
   n->sn = htonl(h->sn);
@@ -114,7 +114,7 @@ ntohlsah(struct ospf_lsa_header *n, struct ospf_lsa_header *h)
 #ifdef OSPFv2
   h->options = n->options;
 #endif
-  h->type = n->type;
+  h->type = ntoht(n->type);
   h->id = ntohl(n->id);
   h->rt = ntohl(n->rt);
   h->sn = ntohl(n->sn);
@@ -143,7 +143,7 @@ htonlsab(void *h, void *n, u16 type, u16 len)
       nrt->links = htons(hrt->links);
       links = hrt->links;
 #else /* OSPFv3 */
-      hrt->options = htonl(nrt->options);
+      nrt->options = htonl(hrt->options);
       links = (len - sizeof(struct ospf_lsa_rt)) /
        sizeof(struct ospf_lsa_rt_link);
 #endif
@@ -173,6 +173,10 @@ htonlsab(void *h, void *n, u16 type, u16 len)
   case LSA_T_SUM_NET:
   case LSA_T_SUM_RT:
   case LSA_T_EXT:
+#ifdef OSPFv3
+  case LSA_T_LINK:
+  case LSA_T_PREFIX:
+#endif
     {
       u32 *hid, *nid;
 
@@ -241,6 +245,10 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
   case LSA_T_SUM_NET:
   case LSA_T_SUM_RT:
   case LSA_T_EXT:
+#ifdef OSPFv3
+  case LSA_T_LINK:
+  case LSA_T_PREFIX:
+#endif
     {
       u32 *hid, *nid;
 
@@ -258,6 +266,35 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
   }
 };
 
+void
+buf_dump(const char *hdr, const byte *buf, int blen)
+{
+  char b2[1024];
+  char *bp;
+  int first = 1;
+  int i;
+
+  const char *lhdr = hdr;
+
+  bp = b2;
+  for(i = 0; i < blen; i++)
+    {
+      if ((i > 0) && ((i % 16) == 0))
+       {
+             *bp = 0;
+             log(L_WARN "%s\t%s", lhdr, b2);
+             lhdr = "";
+             bp = b2;
+       }
+
+      bp += snprintf(bp, 1022, "%02x ", buf[i]);
+
+    }
+
+  *bp = 0;
+  log(L_WARN "%s\t%s", lhdr, b2);
+}
+
 #define MODX 4102              /* larges signed value without overflow */
 
 /* Fletcher Checksum -- Refer to RFC1008. */
@@ -268,17 +305,25 @@ ntohlsab(void *n, void *h, u16 type, u16 len)
 void
 lsasum_calculate(struct ospf_lsa_header *h, void *body)
 {
-  u16 length;
-
-  length = h->length;
+  u16 length = h->length;
+  u16 type = h->type;
 
+  log(L_WARN "Checksum %R %R %d start (len %d)", h->id, h->rt, h->type, length);
   htonlsah(h, h);
-  htonlsab(body, body, h->type, length - sizeof(struct ospf_lsa_header));
+
+  htonlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
+
+  char buf[1024];
+  memcpy(buf, h, sizeof(struct ospf_lsa_header));
+  memcpy(buf + sizeof(struct ospf_lsa_header), body, length - sizeof(struct ospf_lsa_header));
+  buf_dump("CALC", buf, length);
 
   (void) lsasum_check(h, body);
 
+  log(L_WARN "Checksum result %4x", h->checksum);
+
   ntohlsah(h, h);
-  ntohlsab(body, body, h->type, length - sizeof(struct ospf_lsa_header));
+  ntohlsab(body, body, type, length - sizeof(struct ospf_lsa_header));
 }
 
 /*
@@ -294,7 +339,7 @@ lsasum_check(struct ospf_lsa_header *h, void *body)
   u16 length;
 
   b = body;
-  sp = (char *) &h;
+  sp = (char *) h;
   sp += 2; /* Skip Age field */
   length = ntohs(h->length) - 2;
   h->checksum = 0;
index efaafe866bee25dee79de1df42c77a2987b234b0..72861bd533681256bb6c8a1cf919297a6705434e 100644 (file)
@@ -78,13 +78,32 @@ ospf_lsa_flooding_allowed(struct ospf_lsa_header *lsa, u32 domain, struct ospf_i
 
 #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_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_type(lsa) && !(lsa->type & LSA_UBIT))
+  if (unknown_lsa_type(lsa) && !(lsa->type & LSA_UBIT))
     scope = LSA_SCOPE_LINK;
 
   switch (scope)
@@ -444,9 +463,11 @@ ospf_lsupd_receive(struct ospf_packet *ps_i, struct ospf_iface *ifa,
 
     /* pg 143 (1) */
     chsum = lsa->checksum;
+    log(L_WARN "Checking rcv %R %R %d (len %d)", ntohl(lsa->id), ntohl(lsa->rt), ntoht(lsa->type), ntohs(lsa->length));
+    buf_dump("RCV", lsa, ntohs(lsa->length));
     if (chsum != lsasum_check(lsa, NULL))
     {
-      log(L_WARN "Received bad lsa checksum from %I", n->ip);
+      log(L_WARN "Received bad lsa checksum from %I: %x %x", n->ip, chsum, lsa->checksum);
       continue;
     }
 
index 374da636fc02aa5a5ac35c062ab97e9898b463fa..7847654117a2fdd22ed74289472c6bbd098c16c8 100644 (file)
@@ -451,12 +451,13 @@ bdr_election(struct ospf_iface *ifa)
   me.state = NEIGHBOR_2WAY;
   me.rid = myid;
   me.priority = ifa->priority;
-  me.ip = ifa->iface->addr->ip;
 
 #ifdef OSPFv2
+  me.ip = ifa->iface->addr->ip;
   me.dr = ipa_to_u32(ifa->drip);
   me.bdr = ipa_to_u32(ifa->bdrip);
 #else /* OSPFv3 */
+  me.ip = ifa->lladdr;
   me.dr = ifa->drid;
   me.bdr = ifa->bdrid;
   me.iface_id = ifa->iface->index;
index da0104de5cdb8fd706e9311af3501594589dd0aa..c1d5de76c04e07cfdac5905a1ccaef752f9170c3 100644 (file)
@@ -424,6 +424,10 @@ struct ospf_lsa_ext
 
 #define LSA_EXT_EBIT 0x80000000
 
+/* Endianity swap for lsa->type */
+#define ntoht(x) x
+#define htont(x) x
+
 
 #else  /* OSPFv3 */
 
@@ -488,6 +492,10 @@ struct ospf_lsa_prefix
 #define LSA_EXT_FBIT 0x2000000
 #define LSA_EXT_TBIT 0x1000000
 
+/* Endianity swap for lsa->type */
+#define ntoht(x) ntohs(x)
+#define htont(x) htons(x)
+
 #endif
 
 #define METRIC_MASK  0x00FFFFFF
index 677ce5b448707df6a1f198877cf075a416ef6900..27bd22665975fce9287c32df098e5fd573ad2745 100644 (file)
@@ -312,7 +312,7 @@ ospf_rt_spfa(struct ospf_area *oa)
          nf.ar = act;
          nf.nh = act->nh;
          nf.ifa = act->nhi;
-         ri_install(po, ipa_from_rid(act->lsa.rt), 32, ORT_ROUTER, &nf, NULL);
+         ri_install(po, ipa_from_rid(act->lsa.rt), MAX_PREFIX_LENGTH, ORT_ROUTER, &nf, NULL);
        }
 
       rr = (struct ospf_lsa_rt_link *) (rt + 1);
@@ -582,7 +582,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
 #endif
 
       ip = ipa_from_rid(dst_rid);
-      pxlen = 32;
+      pxlen = MAX_PREFIX_LENGTH;
       metric = ls->metric & METRIC_MASK;
       options |= ORTA_ASBR;
       type = ORT_ROUTER;
@@ -595,7 +595,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
 
     abrip = ipa_from_rid(en->lsa.rt);
 
-    abr = fib_find(&oa->rtr, &abrip, 32);
+    abr = fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH);
     if (!abr) continue;
 
     nf.type = re->n.type;
@@ -691,7 +691,7 @@ ospf_rt_sum(struct ospf_area *oa)
 #endif
 
       ip = ipa_from_rid(dst_rid);
-      pxlen = 32;
+      pxlen = MAX_PREFIX_LENGTH;
       metric = ls->metric & METRIC_MASK;
       options |= ORTA_ASBR;
       type = ORT_ROUTER;
@@ -703,7 +703,7 @@ ospf_rt_sum(struct ospf_area *oa)
 
     /* Page 169 (4) */
     abrip = ipa_from_rid(en->lsa.rt);
-    if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, 32))) continue;
+    if (!(abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH))) continue;
     if (abr->n.metric1 == LSINFINITY) continue;
     if (!(abr->n.options & ORTA_ABR)) continue;
 
@@ -891,7 +891,7 @@ ospf_ext_spf(struct proto_ospf *po)
     nf1 = NULL;
     WALK_LIST(atmp, po->area_list)
     {
-      nfh = fib_find(&atmp->rtr, &rtid, 32);
+      nfh = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH);
       if (nfh == NULL) continue;
       if (nf1 == NULL) nf1 = nfh;
       else if (ri_better(po, &nfh->n, NULL, &nf1->n, NULL, po->rfc1583)) nf1 = nfh;
@@ -915,7 +915,7 @@ ospf_ext_spf(struct proto_ospf *po)
     }
     else
     {
-      nf2 = fib_route(&po->rtf, rt_fwaddr, 32);
+      nf2 = fib_route(&po->rtf, rt_fwaddr, MAX_PREFIX_LENGTH);
 
       if (!nf2)
       {
@@ -923,7 +923,6 @@ ospf_ext_spf(struct proto_ospf *po)
        continue;
       }
 
-
       if ((nn = neigh_find(p, &rt_fwaddr, 0)) != NULL)
       {
        nh = rt_fwaddr;
@@ -1179,7 +1178,7 @@ again1:
         int found = 0;
         struct ospf_iface *ifa;
         struct top_hash_entry *en;
-        OSPF_TRACE(D_EVENTS, "Trying to find correct next hop");
+        OSPF_TRACE(D_EVENTS, "Trying to find correct next hop %I/%d via %I", nf->fn.prefix, nf->fn.pxlen, nf->n.nh);
         WALK_LIST(ifa, po->iface_list)
         {
           if ((ifa->type == OSPF_IT_VLINK) && ipa_equal(ifa->vip, nf->n.nh))
index 360e36278c58234a76ea8e0514baa59d2fba3e18..8263010413124e2b048833405e1e3c80247d86a0 100644 (file)
@@ -22,6 +22,7 @@
 
 void originate_prefix_rt_lsa(struct ospf_area *oa);
 void originate_prefix_net_lsa(struct ospf_iface *ifa);
+void flush_prefix_net_lsa(struct ospf_iface *ifa);
 
 #ifdef OSPFv2
 #define ipa_to_rid(x) _I(x)
@@ -557,8 +558,6 @@ flush_net_lsa(struct ospf_iface *ifa)
   ifa->net_lsa->lsa.age = LSA_MAXAGE;
   lsasum_calculate(&ifa->net_lsa->lsa, ifa->net_lsa->lsa_body);
   ospf_lsupd_flood(po, NULL, NULL, &ifa->net_lsa->lsa, dom, 0);
-
-
   flush_lsa(ifa->net_lsa, po);
   ifa->net_lsa = NULL;
 }
@@ -1215,6 +1214,28 @@ originate_prefix_net_lsa(struct ospf_iface *ifa)
   ospf_lsupd_flood(po, NULL, NULL, &lsa, dom, 1);
 }
 
+void
+flush_prefix_net_lsa(struct ospf_iface *ifa)
+{
+  struct proto_ospf *po = ifa->oa->po;
+  struct proto *p = &po->proto;
+  struct top_hash_entry *en = ifa->pxn_lsa;
+  u32 dom = ifa->oa->areaid;
+
+  if (en == NULL)
+    return;
+
+  OSPF_TRACE(D_EVENTS, "Flushing Net Prefix lsa for iface \"%s\".",
+            ifa->iface->name);
+  en->lsa.sn += 1;
+  en->lsa.age = LSA_MAXAGE;
+  lsasum_calculate(&en->lsa, en->lsa_body);
+  ospf_lsupd_flood(po, NULL, NULL, &en->lsa, dom, 0);
+  flush_lsa(en, po);
+  ifa->pxn_lsa = NULL;
+}
+
+
 #endif
 
 
index a5e0522255255c5c6d9a143aba5c67b4e75d4370..d95471619c5d436fbbcf42579f6cdcd136b526e2 100644 (file)
@@ -636,6 +636,12 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
   set_inaddr(&sa->sin6_addr, a);
 }
 
+static inline void
+fill_in_sockifa(sockaddr *sa, struct iface *ifa)
+{
+  sa->sin6_scope_id = ifa ? ifa->index : 0;
+}
+
 void
 get_sockaddr(struct sockaddr_in6 *sa, ip_addr *a, unsigned *port, int check)
 {
@@ -661,6 +667,11 @@ fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
   set_inaddr(&sa->sin_addr, a);
 }
 
+static inline void
+fill_in_sockifa(sockaddr *sa, struct iface *ifa)
+{
+}
+
 void
 get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port, int check)
 {
@@ -874,10 +885,8 @@ sk_open(sock *s)
     {
     case SK_UDP:
     case SK_IP:
+#ifndef IPV6
       if (s->iface)                    /* It's a broadcast socket */
-#ifdef IPV6
-       bug("IPv6 has no broadcasts");
-#else
        if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
          ERR("SO_BROADCAST");
 #endif
@@ -911,7 +920,7 @@ sk_open(sock *s)
            if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
              ERR("IPV6_ADD_MEMBERSHIP");
          }
-#else
+#else /* IPv4 */
        /* With IPv4 there are zillions of different socket interface variants. Ugh. */
        ASSERT(s->iface && s->iface->addr);
        if (err = sysio_mcast_join(s))
@@ -933,6 +942,7 @@ sk_open(sock *s)
            ERR("SO_REUSEADDR");
        }
       fill_in_sockaddr(&sa, s->saddr, port);
+      fill_in_sockifa(&sa, s->iface);
 #ifdef CONFIG_SKIP_MC_BIND
       if ((type != SK_UDP_MC) && (type != SK_IP_MC) &&
          bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
@@ -1067,8 +1077,9 @@ sk_maybe_write(sock *s)
 
        if (s->tbuf == s->tpos)
          return 1;
-       fill_in_sockaddr(&sa, s->faddr, s->fport);
 
+       fill_in_sockaddr(&sa, s->faddr, s->fport);
+       fill_in_sockifa(&sa, s->iface);
        e = sendto(s->fd, s->tbuf, s->tpos - s->tbuf, 0, (struct sockaddr *) &sa, sizeof(sa));
        if (e < 0)
          {