]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Several minor fixes
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 20 Feb 2017 01:26:45 +0000 (02:26 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Mon, 20 Feb 2017 01:26:45 +0000 (02:26 +0100)
22 files changed:
conf/cf-lex.l
conf/confbase.Y
doc/bird.sgml
filter/filter.h
lib/alloca.h
lib/net.c
lib/net.h
nest/route.h
nest/rt-attr.c
nest/rt-dev.c
nest/rt-table.c
proto/bgp/attrs.c
proto/bgp/packets.c
proto/ospf/rt.c
proto/pipe/pipe.c
proto/rip/rip.c
proto/rpki/rpki.c
proto/static/config.Y
proto/static/static.c
sysdep/bsd/krt-sock.c
sysdep/linux/netlink.c
sysdep/unix/krt.c

index 8e1f60a60cebf873678175fc698e8a6b3b376fd9..fb3d59e4a3ee4e9e42da90ed627edc6282cacc8d 100644 (file)
@@ -124,39 +124,56 @@ include   ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
 }
 
 [02]:{DIGIT}+:{DIGIT}+ {
+  unsigned long int l, len1, len2;
   char *e;
-  unsigned long int l;
 
   if (yytext[0] == '0')
+  {
     cf_lval.i64 = 0;
+    len1 = 16;
+    len2 = 32;
+  }
   else
-    cf_lval.i64 = 0x2000000000000ULL;
+  {
+    cf_lval.i64 = 2ULL << 48;
+    len1 = 32;
+    len2 = 16;
+  }
 
   errno = 0;
   l = strtoul(yytext+2, &e, 10);
-  if (e && (*e != ':') || errno == ERANGE || (yytext[0] == '0') && (l >= (1<<16)))
+  if (e && (*e != ':') || (errno == ERANGE) || (l >> len1))
     cf_error("ASN out of range");
-  cf_lval.i64 |= (((u64) l) << 32);
+  cf_lval.i64 |= ((u64) l) << len2;
+
   errno = 0;
   l = strtoul(e+1, &e, 10);
-  if (e && *e || errno == ERANGE || (yytext[0] == '2') && (l >= (1<<16)))
-    cf_error("Assigned number out of range");
+  if (e && *e || (errno == ERANGE) || (l >> len2))
+    cf_error("Number out of range");
   cf_lval.i64 |= l;
+
   return VPN_RD;
 }
 
 1:{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+:{DIGIT}+ {
   unsigned long int l;
-  char *e = strchr(yytext+2, ':');
-  *e++ = '\0';
   ip4_addr ip4;
+  char *e;
+
+  cf_lval.i64 = 1ULL << 48;
+
+  e = strchr(yytext+2, ':');
+  *e++ = '\0';
   if (!ip4_pton(yytext+2, &ip4))
     cf_error("Invalid IPv4 address %s in Route Distinguisher", yytext+2);
+  cf_lval.i64 |= ((u64) ip4_to_u32(ip4)) << 16;
+
   errno = 0;
   l = strtoul(e, &e, 10);
-  if (e && *e || errno == ERANGE || (l >= (1<<16)))
-    cf_error("Assigned number out of range");
-  cf_lval.i64 = (1ULL<<48) | (((u64)ip4_to_u32(ip4)) << 16) | ((u64)l);
+  if (e && *e || (errno == ERANGE) || (l >> 16))
+    cf_error("Number out of range");
+  cf_lval.i64 |= l;
+
   return VPN_RD;
 }
 
index a5b8b692b0a48f3177f53d7f2a7cd7d7ea141b8d..291dc6a029a8416b2e6332bc75aa495b217f167d 100644 (file)
@@ -203,13 +203,13 @@ net_ip6_: IP6 '/' NUM
 net_vpn4_: VPN_RD net_ip4_
 {
   $$ = cfg_alloc(sizeof(net_addr_vpn4));
-  net_fill_vpn4($$, ((net_addr_ip4 *)&$2)->prefix, $2.pxlen, $1);
+  net_fill_vpn4($$, net4_prefix(&$2), net4_pxlen(&$2), $1);
 }
 
 net_vpn6_: VPN_RD net_ip6_
 {
   $$ = cfg_alloc(sizeof(net_addr_vpn6));
-  net_fill_vpn6($$, ((net_addr_ip6 *)&$2)->prefix, $2.pxlen, $1);
+  net_fill_vpn6($$, net6_prefix(&$2), net6_pxlen(&$2), $1);
 }
 
 net_roa4_: net_ip4_ MAX NUM AS NUM
@@ -229,8 +229,8 @@ net_roa6_: net_ip6_ MAX NUM AS NUM
 };
 
 net_ip_: net_ip4_ | net_ip6_ ;
-net_roa_: net_roa4_ | net_roa6_ ;
 net_vpn_: net_vpn4_ | net_vpn6_ ;
+net_roa_: net_roa4_ | net_roa6_ ;
 
 net_:
    net_ip_ { $$ = cfg_alloc($1.length); net_copy($$, &($1)); }
@@ -297,8 +297,9 @@ label_stack:
     label_stack_start
   | label_stack '/' NUM {
     if ($1[0] >= MPLS_MAX_LABEL_STACK)
-      cf_error("Too many labels in stack.");
-    $1[++$1[0]] = $3;
+      cf_error("Too many labels in stack");
+    $1[0]++;
+    $1[*$1] = $3;
     $$ = $1;
   }
 ;
index 23026eaef789a9046f5289665314f2b441926096..c49e7e8ee1a46b216e2145bb1713fc6b3d488c6a 100644 (file)
@@ -4140,12 +4140,12 @@ return packets as undeliverable if they are in your IP block, you don't have any
 specific destination for them and you don't want to send them out through the
 default route to prevent routing loops).
 
-<p>There are five types of static routes: `classical' routes telling to forward
+<p>There are four types of static routes: `classical' routes telling to forward
 packets to a neighboring router (single path or multipath, possibly weighted),
-device routes specifying forwarding to hosts on a
-directly connected network, recursive routes computing their nexthops by doing
-route table lookups for a given IP, and special routes (sink, blackhole etc.)
-which specify a special action to be done instead of forwarding the packet.
+device routes specifying forwarding to hosts on a directly connected network,
+recursive routes computing their nexthops by doing route table lookups for a
+given IP, and special routes (sink, blackhole etc.)  which specify a special
+action to be done instead of forwarding the packet.
 
 <p>When the particular destination is not available (the interface is down or
 the next hop of the route is not a neighbor at the moment), Static just
index 0482b83b1dd40b34761d3c31d09a67f346f7fb7f..855219ec510c78a23a0d4838a7aa47037ef53b18 100644 (file)
@@ -174,9 +174,9 @@ void val_format(struct f_val v, buffer *buf);
 #define SA_PROTO        4
 #define SA_SOURCE       5
 #define SA_SCOPE        6
-#define SA_DEST         8
-#define SA_IFNAME       9
-#define SA_IFINDEX     10
+#define SA_DEST         7
+#define SA_IFNAME       8
+#define SA_IFINDEX      9
 
 
 struct f_tree {
index f0d61bb4934a9f106d3953931aaf5aab6c28e07c..e5557cdbc26bdf9172b6de6fbd0d889107855a56 100644 (file)
@@ -15,4 +15,6 @@
 #include <stdlib.h>
 #endif
 
+#define allocz(len) ({ void *_x = alloca(len); memset(_x, 0, len); _x; })
+
 #endif
index e46be8b2c054ce3a64b190d98d19f8d07222f07a..74cea277f49e163f2f91664f2181fdc20efe5b29 100644 (file)
--- a/lib/net.c
+++ b/lib/net.c
@@ -69,21 +69,20 @@ net_format(const net_addr *N, char *buf, int buflen)
   case NET_VPN4:
     switch (n->vpn4.rd >> 48)
     {
-      case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
-      case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
-      case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
+    case 0: return bsnprintf(buf, buflen, "0:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
+    case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I4/%d", ip4_from_u32(n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
+    case 2: return bsnprintf(buf, buflen, "2:%u:%u %I4/%d", (u32) (n->vpn4.rd >> 16), (u32) (n->vpn4.rd & 0xffff), n->vpn4.prefix, n->vpn4.pxlen);
+    default: return bsnprintf(buf, buflen, "X:%08x:%08x %I4/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
     }
-    return bsnprintf(buf, buflen, "X: %016x %I4/%d", (n->vpn4.rd), n->vpn4.prefix, n->vpn4.pxlen);
-
-    /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4. */
   case NET_VPN6:
+    /* XXX: RD format is specified for VPN4; not found any for VPN6, reusing the same as for VPN4 */
     switch (n->vpn6.rd >> 48)
     {
-      case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
-      case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
-      case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
+    case 0: return bsnprintf(buf, buflen, "0:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
+    case 1: return bsnprintf(buf, buflen, "1:%I4:%u %I6/%d", ip4_from_u32(n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
+    case 2: return bsnprintf(buf, buflen, "2:%u:%u %I6/%d", (u32) (n->vpn6.rd >> 16), (u32) (n->vpn6.rd & 0xffff), n->vpn6.prefix, n->vpn6.pxlen);
+    default: return bsnprintf(buf, buflen, "X:%08x:%08x %I6/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
     }
-    return bsnprintf(buf, buflen, "X: %016x %I6/%d", (n->vpn6.rd), n->vpn6.prefix, n->vpn6.pxlen);
   case NET_ROA4:
     return bsnprintf(buf, buflen, "%I4/%u-%u AS%u",  n->roa4.prefix, n->roa4.pxlen, n->roa4.max_pxlen, n->roa4.asn);
   case NET_ROA6:
index 7c124fc0ca3b87c0ea09c0fc1d279e1fb94455e1..7144bcb91ecf21b1724ab19be4d718b183dc6f2a 100644 (file)
--- a/lib/net.h
+++ b/lib/net.h
@@ -306,6 +306,9 @@ static inline int net_equal_flow4(const net_addr_flow4 *a, const net_addr_flow4
 static inline int net_equal_flow6(const net_addr_flow6 *a, const net_addr_flow6 *b)
 { return net_equal((const net_addr *) a, (const net_addr *) b); }
 
+static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
+{ return !memcmp(a, b, sizeof(net_addr_mpls)); }
+
 
 static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_roa4 *b)
 { return ip4_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
@@ -313,8 +316,6 @@ static inline int net_equal_prefix_roa4(const net_addr_roa4 *a, const net_addr_r
 static inline int net_equal_prefix_roa6(const net_addr_roa6 *a, const net_addr_roa6 *b)
 { return ip6_equal(a->prefix, b->prefix) && (a->pxlen == b->pxlen); }
 
-static inline int net_equal_mpls(const net_addr_mpls *a, const net_addr_mpls *b)
-{ return !memcmp(a, b, sizeof(net_addr_mpls)); }
 
 static inline int net_zero_ip4(const net_addr_ip4 *a)
 { return !a->pxlen && ip4_zero(a->prefix); }
@@ -404,16 +405,17 @@ static inline void net_copy_flow6(net_addr_flow6 *dst, const net_addr_flow6 *src
 static inline void net_copy_mpls(net_addr_mpls *dst, const net_addr_mpls *src)
 { memcpy(dst, src, sizeof(net_addr_mpls)); }
 
+
+/* XXXX */
+static inline u32 u64_hash(u64 a)
+{ return u32_hash(a); }
+
 static inline u32 net_hash_ip4(const net_addr_ip4 *n)
 { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
 
 static inline u32 net_hash_ip6(const net_addr_ip6 *n)
 { return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); }
 
-/* XXXX */
-static inline u32 u64_hash(u64 a)
-{ return u32_hash(a); }
-
 static inline u32 net_hash_vpn4(const net_addr_vpn4 *n)
 { return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
 
@@ -452,7 +454,7 @@ static inline int net_validate_ip6(const net_addr_ip6 *n)
 
 static inline int net_validate_mpls(const net_addr_mpls *n)
 {
-  return n->label < (1<<20);
+  return n->label < (1 << 20);
 }
 
 int net_validate(const net_addr *N);
index eb98b609081a05d0de698d50e5d6f0733054f757..1e0a14bc9083ac2e4afb43e43aee407f52b44a52 100644 (file)
@@ -390,11 +390,11 @@ typedef struct rta {
 #define RTC_MULTICAST 2
 #define RTC_ANYCAST 3                  /* IPv6 Anycast */
 
-#define RTD_UNICAST 0                  /* Next hop is neighbor router */
+#define RTD_NONE 0                     /* Undefined next hop */
+#define RTD_UNICAST 1                  /* Next hop is neighbor router */
 #define RTD_BLACKHOLE 2                        /* Silently drop packets */
 #define RTD_UNREACHABLE 3              /* Reject as unreachable */
 #define RTD_PROHIBIT 4                 /* Administratively prohibited */
-#define RTD_NONE 6                     /* Invalid RTD */
 
                                        /* Flags for net->n.flags, used by kernel syncer */
 #define KRF_INSTALLED 0x80             /* This route should be installed in the kernel */
@@ -408,7 +408,7 @@ typedef struct rta {
 
 /* Route has regular, reachable nexthop (i.e. not RTD_UNREACHABLE and like) */
 static inline int rte_is_reachable(rte *r)
-{ uint d = r->attrs->dest; return (d == RTD_UNICAST); }
+{ return r->attrs->dest == RTD_UNICAST; }
 
 
 /*
@@ -523,7 +523,7 @@ static inline int nexthop_same(struct nexthop *x, struct nexthop *y)
 struct nexthop *nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, linpool *lp);
 static inline void nexthop_link(struct rta *a, struct nexthop *from)
 { memcpy(&a->nh, from, nexthop_size(from)); }
-void nexthop_insert(struct nexthop *n, struct nexthop *y);
+void nexthop_insert(struct nexthop **n, struct nexthop *y);
 int nexthop_is_sorted(struct nexthop *x);
 
 void rta_init(void);
index 120a8e24ffd880d80615f9dbaabd4c7076f3c004..afc97e221db0001b4f49f2a59826ceee906a55b9 100644 (file)
@@ -150,7 +150,8 @@ nexthop_hash(struct nexthop *x)
   for (; x; x = x->next)
   {
     h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9);
-    for (int i=0; i<x->labels; i++)
+
+    for (int i = 0; i < x->labels; i++)
       h ^= x->label[i] ^ (h << 6) ^ (h >> 7);
   }
 
@@ -164,12 +165,13 @@ nexthop__same(struct nexthop *x, struct nexthop *y)
   {
     if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
       return 0;
-    for (int i=0; i<x->labels; i++)
+
+    for (int i = 0; i < x->labels; i++)
       if (x->label[i] != y->label[i])
        return 0;
   }
 
-  return 1;
+  return x == y;
 }
 
 static int
@@ -195,7 +197,7 @@ nexthop_compare_node(struct nexthop *x, struct nexthop *y)
   if (r)
     return r;
 
-  for (int i=0; i<y->labels; i++)
+  for (int i = 0; i < y->labels; i++)
   {
     r = ((int) y->label[i]) - ((int) x->label[i]);
     if (r)
@@ -271,34 +273,22 @@ nexthop_merge(struct nexthop *x, struct nexthop *y, int rx, int ry, int max, lin
 }
 
 void
-nexthop_insert(struct nexthop *n, struct nexthop *x)
+nexthop_insert(struct nexthop **n, struct nexthop *x)
 {
-  struct nexthop tmp;
-  memcpy(&tmp, n, sizeof(struct nexthop));
-  if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */
-  {
-    memcpy(n, x, sizeof(struct nexthop));
-    memcpy(x, &tmp, sizeof(struct nexthop));
-    n->next = x;
-    return;
-  }
-
-  for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next))
+  for (; *n; n = &((*n)->next))
   {
-    int cmp = nexthop_compare_node(*nn, x);
+    int cmp = nexthop_compare_node(*n, x);
 
     if (cmp < 0)
       continue;
-    
-    if (cmp > 0)
-    {
-      x->next = *nn;
-      *nn = x;
-    }
-    
-    return;
+    else if (cmp > 0)
+      break;
+    else
+      return;
   }
 
+  x->next = *n;
+  *n = x;
 }
 
 int
@@ -314,7 +304,7 @@ nexthop_is_sorted(struct nexthop *x)
 static inline slab *
 nexthop_slab(struct nexthop *nh)
 {
-  return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels];
+  return nexthop_slab_[MIN(nh->labels, 3)];
 }
 
 static struct nexthop *
index 5edd1c5d8c5f3dbe25dddee72112efe3ec88ecb7..9993da24d3afa5c22e7f94621a9d3943b530a5da 100644 (file)
@@ -79,9 +79,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
        .source = RTS_DEVICE,
        .scope = SCOPE_UNIVERSE,
        .dest = RTD_UNICAST,
-       .nh = {
-         .iface = ad->iface
-       }
+       .nh.iface = ad->iface,
       };
 
       a = rta_lookup(&a0);
index ef402f2851632a56939e282e99546e292c22220d..a33b790963d9ad09b95b8b7b478dfa98e37aaa04 100644 (file)
@@ -1768,7 +1768,6 @@ static inline void
 rta_apply_hostentry(rta *a, struct hostentry *he)
 {
   a->hostentry = he;
-  
   a->dest = he->dest;
   a->igp_metric = he->igp_metric;
 
@@ -1810,14 +1809,14 @@ rta_apply_hostentry(rta *a, struct hostentry *he)
 static inline rte *
 rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
 {
-  rta *ap = alloca(RTA_MAX_SIZE);
-  memcpy(ap, old->attrs, rta_size(old->attrs));
-  rta_apply_hostentry(ap, old->attrs->hostentry);
-  ap->aflags = 0;
+  rta *a = alloca(RTA_MAX_SIZE);
+  memcpy(a, old->attrs, rta_size(old->attrs));
+  rta_apply_hostentry(a, old->attrs->hostentry);
+  a->aflags = 0;
 
   rte *e = sl_alloc(rte_slab);
   memcpy(e, old, sizeof(rte));
-  e->attrs = rta_lookup(ap);
+  e->attrs = rta_lookup(a);
 
   return e;
 }
@@ -2373,7 +2372,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
        }
 
       if ((a->dest == RTD_UNICAST) && ipa_zero(a->nh.gw) && !a->next)
-       { /* We have singlepath device route */
+       {
+         /* We have singlepath device route */
          if (if_local_addr(he->addr, a->nh.iface))
            {
              /* The host address is a local address, this is not valid */
@@ -2389,7 +2389,7 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
       else
        {
          /* The host is reachable through some route entry */
-         he->nh = (&a->nh);
+         he->nh = &(a->nh);
          he->dest = a->dest;
        }
 
index 11666f30d6e5c9ef14855385683987fd2ab78f7a..1b124a17221d4f5ecc7d868e8d208d69339afe64 100644 (file)
@@ -1461,8 +1461,7 @@ bgp_get_neighbor(rte *r)
 static inline int
 rte_resolvable(rte *rt)
 {
-  int rd = rt->attrs->dest;
-  return (rd == RTD_UNICAST);
+  return rt->attrs->dest == RTD_UNICAST;
 }
 
 int
index 9c59e6d87cd9c0a2abe84bc70395dd1583ea627a..9380f999dd6393bbe10eba538dc29e406d5749a6 100644 (file)
@@ -700,9 +700,7 @@ bgp_apply_next_hop(struct bgp_parse_state *s, rta *a, ip_addr gw, ip_addr ll)
       WITHDRAW(BAD_NEXT_HOP);
 
     a->dest = RTD_UNICAST;
-    a->nh.gw = nbr->addr;
-    a->nh.iface = nbr->iface;
-    a->nh.next = NULL;
+    a->nh = (struct nexthop){ .gw = nbr->addr, .iface = nbr->iface };
     a->hostentry = NULL;
     a->igp_metric = 0;
   }
@@ -749,8 +747,8 @@ bgp_use_gateway(struct bgp_export_state *s)
   if (s->channel->cf->next_hop_self)
     return 0;
 
-  /* We need valid global gateway */
-  if ((ra->dest != RTD_UNICAST) || (ra->nh.next) || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
+  /* We need one valid global gateway */
+  if ((ra->dest != RTD_UNICAST) || ra->nh.next || ipa_zero(ra->nh.gw) || ipa_is_link_local(ra->nh.gw))
     return 0;
 
   /* Use it when exported to internal peers */
@@ -1434,12 +1432,10 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
 
   if (ea)
   {
-    a = alloca(sizeof(struct rta));
-    memset(a, 0, sizeof(struct rta));
+    a = allocz(sizeof(struct rta));
 
     a->source = RTS_BGP;
     a->scope = SCOPE_UNIVERSE;
-    a->dest = RTD_UNREACHABLE;
     a->from = s->proto->cf->remote_ip;
     a->eattrs = ea;
 
index 74f47810838ca8929e99e70d22523d38e90a15e9..1b0ac5e968d3c5eede4919a91b68cd2bd7dd160d 100644 (file)
@@ -36,11 +36,9 @@ unresolved_vlink(ort *ort)
 static inline struct nexthop *
 new_nexthop(struct ospf_proto *p, ip_addr gw, struct iface *iface, byte weight)
 {
-  struct nexthop *nh = lp_alloc(p->nhpool, sizeof(struct nexthop));
-  nh->labels = 0;
+  struct nexthop *nh = lp_allocz(p->nhpool, sizeof(struct nexthop));
   nh->gw = gw;
   nh->iface = iface;
-  nh->next = NULL;
   nh->weight = weight;
   return nh;
 }
@@ -1907,7 +1905,6 @@ ort_changed(ort *nf, rta *nr)
     (nf->n.metric1 != nf->old_metric1) || (nf->n.metric2 != nf->old_metric2) ||
     (nf->n.tag != nf->old_tag) || (nf->n.rid != nf->old_rid) ||
     (nr->source != or->source) || (nr->dest != or->dest) ||
-    (nr->nh.iface != or->nh.iface) || !ipa_equal(nr->nh.gw, or->nh.gw) ||
     !nexthop_same(&(nr->nh), &(or->nh));
 }
 
@@ -1952,11 +1949,10 @@ again1:
        .src = p->p.main_source,
        .source = nf->n.type,
        .scope = SCOPE_UNIVERSE,
+       .dest = RTD_UNICAST,
+       .nh = *(nf->n.nhs),
       };
 
-      nexthop_link(&a0, nf->n.nhs);
-      a0.dest = RTD_UNICAST;
-
       if (reload || ort_changed(nf, &a0))
       {
        rta *a = rta_lookup(&a0);
index a4d371fe735a676810766e5b1a8bb2b0f16c1dda..310f3c01c3fe83b0575644ef39c2daa81cc4eda2 100644 (file)
@@ -43,8 +43,6 @@
 
 #include "pipe.h"
 
-#include <alloca.h>
-
 static void
 pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
 {
index 9bed9249f3dabd77571c2c282ad53bccd52d7831..157093aabaf3babaa01d07d6ba24e89032cc2061 100644 (file)
@@ -147,20 +147,16 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
       .src = p->p.main_source,
       .source = RTS_RIP,
       .scope = SCOPE_UNIVERSE,
+      .dest = RTD_UNICAST,
     };
 
     u8 rt_metric = rt->metric;
     u16 rt_tag = rt->tag;
-    struct rip_rte *rt2 = rt->next;
 
-    /* Find second valid rte */
-    while (rt2 && !rip_valid_rte(rt2))
-      rt2 = rt2->next;
-
-    a0.dest = RTD_UNICAST;
-    if (p->ecmp && rt2)
+    if (p->ecmp)
     {
       /* ECMP route */
+      struct nexthop *nhs = NULL;
       int num = 0;
 
       for (rt = en->routes; rt && (num < p->ecmp); rt = rt->next)
@@ -168,28 +164,27 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
        if (!rip_valid_rte(rt))
            continue;
 
-       struct nexthop *nh = (a0.nh.next ? &(a0.nh) : alloca(sizeof(struct nexthop)));
+       struct nexthop *nh = allocz(sizeof(struct nexthop));
 
        nh->gw = rt->next_hop;
        nh->iface = rt->from->nbr->iface;
        nh->weight = rt->from->ifa->cf->ecmp_weight;
 
-       if (a0.nh.next)
-         nexthop_insert(&(a0.nh), nh);
-
+       nexthop_insert(&nhs, nh);
        num++;
 
        if (rt->tag != rt_tag)
          rt_tag = 0;
       }
+
+      a0.nh = *nhs;
     }
     else
     {
       /* Unipath route */
-      a0.nh.next = NULL;
+      a0.from = rt->from->nbr->addr;
       a0.nh.gw = rt->next_hop;
       a0.nh.iface = rt->from->nbr->iface;
-      a0.from = rt->from->nbr->addr;
     }
 
     rta *a = rta_lookup(&a0);
index 81268e83e41753df097a8851e773585a8bcdc574..497edd3ce3b8743e4412f181e4427c9281c32180 100644 (file)
@@ -124,7 +124,7 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
     .src = p->p.main_source,
     .source = RTS_RPKI,
     .scope = SCOPE_UNIVERSE,
-    .dest = RTD_BLACKHOLE,
+    .dest = RTD_NONE,
   };
 
   rta *a = rta_lookup(&a0);
index 2fb544483e8848699428bcffcb0a58ad8ce799ad..16c276ce27f77c06d660dc30ddfcb6c7c4a4ab55 100644 (file)
@@ -13,9 +13,33 @@ CF_HDR
 CF_DEFINES
 
 #define STATIC_CFG ((struct static_config *) this_proto)
-static struct static_route *this_srt, *last_srt;
+static struct static_route *this_srt, *this_snh;
 static struct f_inst **this_srt_last_cmd;
 
+static struct static_route *
+static_nexthop_new(void)
+{
+  struct static_route *nh;
+
+  if (!this_snh)
+  {
+    /* First next hop */
+    nh = this_srt;
+    rem_node(&this_srt->n);
+  }
+  else
+  {
+    /* Additional next hop */
+    nh = cfg_allocz(sizeof(struct static_route));
+    nh->net = this_srt->net;
+    this_snh->mp_next = nh;
+  }
+
+  nh->dest = RTD_UNICAST;
+  nh->mp_head = this_srt;
+  return nh;
+};
+
 static void
 static_route_finish(void)
 { }
@@ -45,48 +69,35 @@ static_proto:
  | static_proto stat_route stat_route_opt_list ';' { static_route_finish(); }
  ;
 
-stat_nexthop_via: VIA
-{
-  if (last_srt)
-  {
-    last_srt = (last_srt->mp_next = cfg_allocz(sizeof(struct static_route)));
-    last_srt->net = this_srt->net;
-  }
-  else
-  {
-    last_srt = this_srt;
-    rem_node(&this_srt->n);
-  }
-
-  last_srt->mp_head = this_srt;
-  last_srt->dest = RTD_UNICAST;
-};
-
-stat_nexthop_ident:
-    stat_nexthop_via ipa ipa_scope {
-      last_srt->via = $2;
-      last_srt->iface = $3;
-      add_tail(&STATIC_CFG->neigh_routes, &last_srt->n);
+stat_nexthop:
+    VIA ipa ipa_scope {
+      this_snh = static_nexthop_new();
+      this_snh->via = $2;
+      this_snh->iface = $3;
+      add_tail(&STATIC_CFG->neigh_routes, &this_snh->n);
     }
-  | stat_nexthop_via TEXT {
-      last_srt->via = IPA_NONE;
-      last_srt->if_name = $2;
-      add_tail(&STATIC_CFG->iface_routes, &last_srt->n);
+  | VIA TEXT {
+      this_snh = static_nexthop_new();
+      this_snh->via = IPA_NONE;
+      this_snh->if_name = $2;
+      add_tail(&STATIC_CFG->iface_routes, &this_snh->n);
     }
-  | stat_nexthop_ident MPLS label_stack {
-    last_srt->label_count = $3[0];
-    last_srt->label_stack = &($3[1]);
+  | stat_nexthop MPLS label_stack {
+    this_snh->label_count = $3[0];
+    this_snh->label_stack = &($3[1]);
   }
-  | stat_nexthop_ident WEIGHT expr {
-    last_srt->weight = $3 - 1;
+  | stat_nexthop WEIGHT expr {
+    this_snh->weight = $3 - 1;
     if (($3<1) || ($3>256)) cf_error("Weight must be in range 1-256");
   }
-  | stat_nexthop_ident BFD bool { last_srt->use_bfd = $3; cf_check_bfd($3); }
+  | stat_nexthop BFD bool {
+    this_snh->use_bfd = $3; cf_check_bfd($3);
+  }
 ;
 
-stat_nexthop:
-    stat_nexthop_ident
-  | stat_nexthop stat_nexthop_ident
+stat_nexthops:
+    stat_nexthop
+  | stat_nexthops stat_nexthop
 ;
 
 stat_route0: ROUTE net_any {
@@ -95,12 +106,12 @@ stat_route0: ROUTE net_any {
      this_srt->net = $2;
      this_srt_last_cmd = &(this_srt->cmds);
      this_srt->mp_next = NULL;
-     last_srt = NULL;
+     this_snh = NULL;
   }
  ;
 
 stat_route:
-   stat_route0 stat_nexthop
+   stat_route0 stat_nexthops
  | stat_route0 RECURSIVE ipa {
       this_srt->dest = RTDX_RECURSIVE;
       this_srt->via = $3;
index 3e03708c35ecd017c343ac048dafc9a32408d2c6..e5251bf6ca46680b9ec096864741d69dad3c1be0 100644 (file)
@@ -60,54 +60,44 @@ p_igp_table(struct proto *p)
 static void
 static_install(struct proto *p, struct static_route *r)
 {
-  rta *ap = alloca(RTA_MAX_SIZE);
+  rta *ap = allocz(RTA_MAX_SIZE);
   rte *e;
 
   if (!(r->state & STS_WANT) && (r->state & (STS_INSTALLED | STS_FORCE)) && r->dest != RTD_UNICAST)
     goto drop;
 
   DBG("Installing static route %N, rtd=%d\n", r->net, r->dest);
-  bzero(ap, RTA_MAX_SIZE);
   ap->src = p->main_source;
-  ap->source = ((r->dest == RTD_UNICAST) && ipa_zero(r->via)) ? RTS_STATIC_DEVICE : RTS_STATIC;
+  ap->source = RTS_STATIC;
   ap->scope = SCOPE_UNIVERSE;
   ap->dest = r->dest;
 
   if (r->dest == RTD_UNICAST)
     {
+      struct nexthop *nhs = NULL;
       struct static_route *r2;
-      int num = 0, update = 0;
+      int update = 0;
 
+      r = r->mp_head;
       for (r2 = r; r2; r2 = r2->mp_next)
       {
-
        if ((r2->state & STS_FORCE) ||
            (!!(r2->state & STS_INSTALLED) != !!(r2->state & STS_WANT)))
          update++;
 
        if (r2->state & STS_WANT)
-         {
-           struct nexthop *nh = (ap->nh.next) ? alloca(NEXTHOP_MAX_SIZE) : &(ap->nh);
-           if (ipa_zero(r2->via)) // Device nexthop
-             {
-               nh->gw = IPA_NONE;
-               nh->iface = r2->iface;
-             }
-           else // Router nexthop
-             {
-               nh->gw = r2->via;
-               nh->iface = r2->neigh->iface;
-             }
-           nh->weight = r2->weight;
-           nh->labels = r2->label_count;
-           for (int i=0; i<nh->labels; i++)
-             nh->label[i] = r2->label_stack[i];
-
-           if (ap->nh.next)
-             nexthop_insert(&(ap->nh), nh);
-           r2->state |= STS_INSTALLED;
-           num++;
-         }
+       {
+         struct nexthop *nh = allocz(NEXTHOP_MAX_SIZE);
+
+         nh->gw = r2->via;
+         nh->iface = r2->neigh ? r2->neigh->iface : r2->iface;
+         nh->weight = r2->weight;
+         nh->labels = r2->label_count;
+         memcpy(nh->label, r2->label_stack, r2->label_count * sizeof(u32));
+
+         r2->state |= STS_INSTALLED;
+         nexthop_insert(&nhs, nh);
+       }
        else
          r2->state = 0;
       }
@@ -115,18 +105,19 @@ static_install(struct proto *p, struct static_route *r)
       if (!update) // Nothing changed
        return;
 
-      r = r->mp_head;
-
-      if (!num) // No nexthop to install
+      if (!nhs) // No nexthop to install
       {
 drop:
        rte_update(p, r->net, NULL);
        return;
       }
+
+      ap->dest = RTD_UNICAST;
+      nexthop_link(ap, nhs);
     }
   else
     r->state |= STS_INSTALLED;
-  
+
   if (r->dest == RTDX_RECURSIVE)
     {
       ap->nh.labels_append = ap->nh.labels = r->label_count;
index 2e0f194b5ab5b6d92c20197f7da60225cba5f795..c65cba654c784536057a045c5e512ee57de14b82 100644 (file)
@@ -193,7 +193,6 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
   struct ks_msg msg;
   char *body = (char *)msg.buf;
   sockaddr gate, mask, dst;
-  ip_addr gw;
 
   DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
 
@@ -223,14 +222,12 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
     msg.rtm.rtm_flags |= RTF_BLACKHOLE;
 #endif
 
-  /* This is really very nasty, but I'm not able
-   * to add "(reject|blackhole)" route without
-   * gateway set
+  /*
+   * This is really very nasty, but I'm not able to add reject/blackhole route
+   * without gateway address.
    */
-  if(!i)
+  if (!i)
   {
-    i = HEAD(iface_list);
-
     WALK_LIST(j, iface_list)
     {
       if (j->flags & IF_LOOPBACK)
@@ -239,13 +236,13 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
         break;
       }
     }
-  }
 
-  gw = a->nh.gw;
-
-  /* Embed interface ID to link-local address */
-  if (ipa_is_link_local(gw))
-    _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
+    if (!i)
+    {
+      log(L_ERR "KRT: Cannot find loopback iface");
+      return -1;
+    }
+  }
 
   int af = AF_UNSPEC;
 
@@ -261,45 +258,51 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
       return -1;
   }
 
-
   sockaddr_fill(&dst,  af, net_prefix(net->n.addr), NULL, 0);
   sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
-  sockaddr_fill(&gate, af, gw, NULL, 0);
 
   switch (a->dest)
   {
-    case RTD_UNICAST:
-      if (ipa_zero(gw))
-      {
-       if(i)
-       {
-#ifdef RTF_CLONING
-         if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS)  /* PTP */
-           msg.rtm.rtm_flags |= RTF_CLONING;
-#endif
+  case RTD_UNICAST:
+    if (ipa_nonzero(a->nh.gw))
+    {
+      ip_addr gw = a->nh.gw;
 
-         if(!i->addr) {
-           log(L_ERR "KRT: interface %s has no IP addess", i->name);
-           return -1;
-         }
-
-         sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
-         msg.rtm.rtm_addrs |= RTA_GATEWAY;
-       }
-      } else {
-       msg.rtm.rtm_flags |= RTF_GATEWAY;
-       msg.rtm.rtm_addrs |= RTA_GATEWAY;
-      }
+      /* Embed interface ID to link-local address */
+      if (ipa_is_link_local(gw))
+       _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
+
+      sockaddr_fill(&gate, af, gw, NULL, 0);
+      msg.rtm.rtm_flags |= RTF_GATEWAY;
+      msg.rtm.rtm_addrs |= RTA_GATEWAY;
       break;
+    }
 
 #ifdef RTF_REJECT
-    case RTD_UNREACHABLE:
+  case RTD_UNREACHABLE:
 #endif
 #ifdef RTF_BLACKHOLE
-    case RTD_BLACKHOLE:
+  case RTD_BLACKHOLE:
 #endif
-    default:
-      bug("krt-sock: unknown flags, but not filtered");
+  {
+    /* Fallback for all other valid cases */
+    if (!i->addr)
+    {
+      log(L_ERR "KRT: interface %s has no IP addess", i->name);
+      return -1;
+    }
+
+#ifdef RTF_CLONING
+    if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS)       /* PTP */
+      msg.rtm.rtm_flags |= RTF_CLONING;
+#endif
+
+    sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
+    msg.rtm.rtm_addrs |= RTA_GATEWAY;
+  }
+
+  default:
+    bug("krt-sock: unknown flags, but not filtered");
   }
 
   msg.rtm.rtm_index = i->index;
@@ -497,7 +500,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
     }
 
   a.dest = RTD_UNICAST;
-  a.nh.next = NULL;
   if (flags & RTF_GATEWAY)
   {
     neighbor *ng;
@@ -520,8 +522,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
        return;
       }
   }
-  else
-    a.nh.gw = IPA_NONE;
 
  done:
   e = rte_get_temp(&a);
index 23431172a025e17416c4ec7d0f5a5a4e7779d51f..80439c474f6a40fa479fdee71072398138f1798e 100644 (file)
@@ -320,6 +320,7 @@ static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = {
   [IFA_ADDRESS]          = { 1, 1, sizeof(ip4_addr) },
   [IFA_LOCAL]    = { 1, 1, sizeof(ip4_addr) },
   [IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) },
+  [IFA_FLAGS]     = { 1, 1, sizeof(u32) },
 };
 
 static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = {
@@ -543,18 +544,17 @@ nl_add_attr_via(struct nlmsghdr *h, uint bufsize, ip_addr ipa)
 
   h->nlmsg_len += sizeof(*via);
 
-  if (ipa_is_ip4(ipa)) {
-    ip4_addr ip4 = ipa_to_ip4(ipa);
-    ip4 = ip4_hton(ip4);
+  if (ipa_is_ip4(ipa))
+  {
     via->rtvia_family = AF_INET;
-    memcpy(via->rtvia_addr, &ip4, sizeof(ip4));
-    h->nlmsg_len += sizeof(ip4);
-  } else {
-    ip6_addr ip6 = ipa_to_ip6(ipa);
-    ip6 = ip6_hton(ip6);
+    put_ip4(via->rtvia_addr, ipa_to_ip4(ipa));
+    h->nlmsg_len += sizeof(ip4_addr);
+  }
+  else
+  {
     via->rtvia_family = AF_INET6;
-    memcpy(via->rtvia_addr, &ip6, sizeof(ip6));
-    h->nlmsg_len += sizeof(ip6);
+    put_ip6(via->rtvia_addr, ipa_to_ip6(ipa));
+    h->nlmsg_len += sizeof(ip6_addr);
   }
 
   nl_close_attr(h, nest);
@@ -669,6 +669,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
        }
       else
        rv->gw = IPA_NONE;
+
       if (a[RTA_ENCAP_TYPE])
        {
          if (rta_get_u16(a[RTA_ENCAP_TYPE]) != LWTUNNEL_ENCAP_MPLS) {
@@ -1092,20 +1093,16 @@ krt_capable(rte *e)
   rta *a = e->attrs;
 
   switch (a->dest)
-    {
+  {
     case RTD_UNICAST:
-      for (struct nexthop *nh = &(a->nh); nh; nh = nh->next)
-       if (nh->iface)
-         return 1;
-      return 0;
     case RTD_BLACKHOLE:
     case RTD_UNREACHABLE:
     case RTD_PROHIBIT:
-      break;
+      return 1;
+
     default:
       return 0;
-    }
-  return 1;
+  }
 }
 
 static inline int
@@ -1210,7 +1207,6 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int d
 
 
 dest:
-  /* a->iface != NULL checked in krt_capable() for router and device routes */
   switch (dest)
     {
     case RTD_UNICAST:
@@ -1502,6 +1498,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
   switch (i->rtm_type)
     {
     case RTN_UNICAST:
+      ra->dest = RTD_UNICAST;
 
       if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
        {
@@ -1512,7 +1509,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
              return;
            }
 
-         nexthop_link(ra, nh);
+         ra->nh = *nh;
          break;
        }
 
@@ -1698,9 +1695,20 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
   else
   {
     /* Merge next hops with the stored route */
-    rta *a = s->attrs;
+    rta *oa = s->attrs;
 
-    nexthop_insert(&a->nh, &ra->nh);
+    struct nexthop *nhs = &oa->nh;
+    nexthop_insert(&nhs, &ra->nh);
+
+    /* Perhaps new nexthop is inserted at the first position */
+    if (nhs == &ra->nh)
+    {
+      /* Swap rtas */
+      s->attrs = ra;
+
+      /* Keep old eattrs */
+      ra->eattrs = oa->eattrs;
+    }
   }
 }
 
index c273cb10d9446f6b5e318c7e088a0ce13a700fa6..c6ff6275e75d3ca6ddfbb5c3a23267748d91e8d3 100644 (file)
@@ -984,7 +984,7 @@ krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
 static int
 krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
 {
-  struct krt_proto *p = (struct krt_proto *) P;
+  // struct krt_proto *p = (struct krt_proto *) P;
   rte *e = *new;
 
   if (e->attrs->src->proto == P)
@@ -1005,17 +1005,6 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
     return -1;
   }
 
-  if (!KRT_CF->devroutes && (e->attrs->source != RTS_STATIC_DEVICE))
-  {
-    struct nexthop *nh = &(e->attrs->nh);
-    for (; nh; nh = nh->next)
-      if (ipa_nonzero(nh->gw))
-       break;
-
-    if (!nh) /* Gone through all the nexthops and no explicit GW found */
-      return -1;
-  }
-
   if (!krt_capable(e))
     return -1;