]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Initial commit on integrated BIRD
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 5 Nov 2015 11:48:52 +0000 (12:48 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Thu, 5 Nov 2015 11:48:52 +0000 (12:48 +0100)
New data types net_addr and variants (in lib/net.h) describing
network addresses (prefix/pxlen). Modifications of FIB structures
to handle these data types and changing everything to use these
data types instead of prefix/pxlen pairs where possible.

The commit is WiP, some protocols are not yet updated (BGP, Kernel),
and the code contains some temporary scaffolding.

Comments are welcome.

42 files changed:
conf/cf-lex.l
conf/conf.c
conf/confbase.Y
configure.in
filter/config.Y
filter/filter.c
lib/bitops.c
lib/bitops.h
lib/ip.c
lib/ip.h
lib/net.c [new file with mode: 0644]
lib/net.h [new file with mode: 0644]
lib/printf.c
nest/Makefile
nest/bird.h
nest/config.Y
nest/route.h
nest/rt-dev.c
nest/rt-fib.c
nest/rt-table.c
proto/ospf/config.Y
proto/ospf/hello.c
proto/ospf/iface.c
proto/ospf/lsalib.c
proto/ospf/lsalib.h
proto/ospf/lsupd.c
proto/ospf/ospf.c
proto/ospf/ospf.h
proto/ospf/packet.c
proto/ospf/rt.c
proto/ospf/rt.h
proto/ospf/topology.c
proto/ospf/topology.h
proto/pipe/pipe.c
proto/radv/radv.c
proto/radv/radv.h
proto/rip/packets.c
proto/rip/rip.c
proto/rip/rip.h
proto/static/static.c
sysdep/linux/netlink.c
sysdep/unix/krt.c

index 61e0407585dec08d1589ce3ec628a5a5b34766e5..8baa1ee779ea1dde8986b566018d02bcc163bf23 100644 (file)
@@ -123,27 +123,15 @@ include   ^{WHITE}*include{WHITE}*\".*\"{WHITE}*;
 }
 
 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
-  ip4_addr a;
-  if (!ip4_pton(yytext, &a))
+  if (!ip4_pton(yytext, &cf_lval.ip4))
     cf_error("Invalid IPv4 address %s", yytext);
-
-#ifdef IPV6
-  cf_lval.i32 = ip4_to_u32(a);
-  return RTRID;
-#else
-  cf_lval.a = ipa_from_ip4(a);
-  return IPA;
-#endif
+  return IP4;
 }
 
 ({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
-#ifdef IPV6
-  if (ipa_pton(yytext, &cf_lval.a))
-    return IPA;
-  cf_error("Invalid IPv6 address %s", yytext);
-#else
-  cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
-#endif
+  if (!ip6_pton(yytext, &cf_lval.ip6))
+    cf_error("Invalid IPv6 address %s", yytext);
+  return IP6;
 }
 
 0x{XIGIT}+ {
index a907402d936ef34062326ce65b196213de7ce8f8..cc5d5115463297582f80d7537667b2b773711b36 100644 (file)
@@ -133,10 +133,10 @@ config_parse(struct config *c)
   protos_postconfig(c);
   if (EMPTY_LIST(c->protos))
     cf_error("No protocol is specified in the config file");
-#ifdef IPV6
+  /* XXXX */
   if (!c->router_id)
-    cf_error("Router ID must be configured manually on IPv6 routers");
-#endif
+    cf_error("Router ID must be configured manually");
+
   return 1;
 }
 
index 5f487c1dd0503dab783883fa6ef08c570d78349e..64a636cf0a50e61a4f5c12019da08bbdacc4caea 100644 (file)
@@ -39,6 +39,8 @@ CF_DECLS
   int i;
   u32 i32;
   ip_addr a;
+  ip4_addr ip4;
+  ip6_addr ip6;
   struct symbol *s;
   char *t;
   struct rtable_config *r;
@@ -66,8 +68,8 @@ CF_DECLS
 %token GEQ LEQ NEQ AND OR
 %token PO PC
 %token <i> NUM ENUM
-%token <i32> RTRID
-%token <a> IPA
+%token <ip4> IP4
+%token <ip6> IP6
 %token <s> SYM
 %token <t> TEXT
 %type <iface> ipa_scope
@@ -75,10 +77,11 @@ CF_DECLS
 %type <i> expr bool pxlen
 %type <i32> expr_us
 %type <time> datetime
-%type <a> ipa
+%type <a> ipa ipa_raw
 %type <px> prefix prefix_or_ipa
 %type <t> text
 %type <t> text_or_none
+%type <t> opttext
 
 %nonassoc PREFIX_DUMMY
 %left AND OR
@@ -148,8 +151,13 @@ bool:
 
 /* Addresses, prefixes and netmasks */
 
+ipa_raw:
+   IP4 { $$ = ipa_from_ip4($1); }
+ | IP6 { $$ = ipa_from_ip6($1); }
+ ;
+
 ipa:
-   IPA
+   ipa_raw
  | SYM {
      if ($1->class != (SYM_CONSTANT | T_IP)) cf_error("IP address expected");
      $$ = SYM_VAL($1).px.ip;
@@ -205,6 +213,12 @@ text_or_none:
  |      { $$ = NULL; }
  ;
 
+opttext:
+    TEXT
+ | /* empty */ { $$ = NULL; }
+ ;
+
+
 CF_CODE
 
 CF_END
index c81709e61bf4fec0d099306845814002b92d1e1a..dd1ff7a5268a9533dcdcadf506594f26264d0b20 100644 (file)
@@ -205,7 +205,7 @@ fi
 
 AC_SUBST(iproutedir)
 
-all_protocols="$proto_bfd bgp ospf pipe $proto_radv rip static"
+all_protocols="$proto_bfd ospf pipe $proto_radv rip static"
 all_protocols=`echo $all_protocols | sed 's/ /,/g'`
 
 if test "$with_protocols" = all ; then
index 7eb2c0a37324d78bca1511fc85f2fe778b05d049..312506c4e2916e05f94c8ff794f2e1d11b76097c 100644 (file)
@@ -477,7 +477,7 @@ block:
  * Complex types, their bison value is struct f_val
  */
 fipa:
-   IPA %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
+   ipa_raw %prec PREFIX_DUMMY { $$.type = T_IP; $$.val.px.ip = $1; }
  ;
 
 
@@ -491,7 +491,6 @@ fipa:
 
 set_atom:
    NUM   { $$.type = T_INT; $$.val.i = $1; }
- | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
  | fipa  { $$ = $1; }
  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  | '(' term ')' {
@@ -508,7 +507,6 @@ set_atom:
 switch_atom:
    NUM   { $$.type = T_INT; $$.val.i = $1; }
  | '(' term ')' { $$.type = T_INT; $$.val.i = f_eval_int($2); }
- | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
  | fipa  { $$ = $1; }
  | ENUM  { $$.type = pair_a($1); $$.val.i = pair_b($1); }
  ;
@@ -575,7 +573,7 @@ switch_items:
  ;
 
 fprefix_s:
-   IPA '/' NUM %prec '/' {
+   ipa_raw '/' NUM %prec '/' {
      if (($3 < 0) || ($3 > MAX_PREFIX_LENGTH) || !ip_is_prefix($1, $3)) cf_error("Invalid network prefix: %I/%d.", $1, $3);
      $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3;
    }
@@ -646,7 +644,6 @@ constant:
  | TEXT   { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
  | fipa           { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
  | fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
- | RTRID  { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD;  $$->a2.i = $1; }
  | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
  | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET;  $$->a2.p = $2; }
  | ENUM          { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
index 55062acadec94f9309ca21588630876a460da6e5..1383961c7b5792dc9f029bc5a7f23fbf7d8cfe3d 100644 (file)
@@ -792,8 +792,8 @@ interpret(struct f_inst *what)
       {
       case SA_FROM:    res.val.px.ip = rta->from; break;
       case SA_GW:      res.val.px.ip = rta->gw; break;
-      case SA_NET:     res.val.px.ip = (*f_rte)->net->n.prefix;
-                       res.val.px.len = (*f_rte)->net->n.pxlen; break;
+      case SA_NET:     res.val.px.ip = net_prefix((*f_rte)->net->n.addr);
+                       res.val.px.len = net_pxlen((*f_rte)->net->n.addr); break;
       case SA_PROTO:   res.val.s = rta->src->proto->name; break;
       case SA_SOURCE:  res.val.i = rta->source; break;
       case SA_SCOPE:   res.val.i = rta->scope; break;
@@ -1292,8 +1292,8 @@ interpret(struct f_inst *what)
     else
     {
       ACCESS_RTE;
-      v1.val.px.ip = (*f_rte)->net->n.prefix;
-      v1.val.px.len = (*f_rte)->net->n.pxlen;
+      v1.val.px.ip = net_prefix((*f_rte)->net->n.addr);
+      v1.val.px.len = net_pxlen((*f_rte)->net->n.addr);
 
       /* We ignore temporary attributes, probably not a problem here */
       /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
index 81586e8798b15a73e130368d4f1638aee7f8aede..efb8710e652c8faff23e4c1e9b2314a0817e5d75 100644 (file)
@@ -28,15 +28,15 @@ u32_mkmask(uint n)
  *
  * This function checks whether the given integer @x represents
  * a valid bit mask (binary representation contains first ones, then
- * zeroes) and returns the number of ones or -1 if the mask is invalid.
+ * zeroes) and returns the number of ones or 255 if the mask is invalid.
  */
-int
+uint
 u32_masklen(u32 x)
 {
   int l = 0;
   u32 n = ~x;
 
-  if (n & (n+1)) return -1;
+  if (n & (n+1)) return 255;
   if (x & 0x0000ffff) { x &= 0x0000ffff; l += 16; }
   if (x & 0x00ff00ff) { x &= 0x00ff00ff; l += 8; }
   if (x & 0x0f0f0f0f) { x &= 0x0f0f0f0f; l += 4; }
index c0ad1a708a08fe0812009fba84f61f353e79f5cf..82bef699e759d6f1115776316a82494bea70ce61 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 u32 u32_mkmask(uint n);
-int u32_masklen(u32 x);
+uint u32_masklen(u32 x);
 
 u32 u32_log2(u32 v);
 
index 3dc8919a5c7aa4ed82f3d66c240898fb89c96fa7..6b0b0bc2b0d197a2515a39347bb4385aaf239bee 100644 (file)
--- a/lib/ip.c
+++ b/lib/ip.c
@@ -58,7 +58,7 @@ ip6_mkmask(uint n)
   return a;
 }
 
-int
+uint
 ip6_masklen(ip6_addr *a)
 {
   int i, j, n;
@@ -72,7 +72,7 @@ ip6_masklen(ip6_addr *a)
       n += j;
       while (++i < 4)
        if (a->addr[i])
-         return -1;
+         return 255;
       break;
     }
 
index 9ac5798a5adf9ff2401895d97e71cad57082ddf9..9b4400bab00c49f033c28e78417818f4631cd62f 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -30,6 +30,9 @@
 #define IP4_NONE               _MI4(0)
 #define IP6_NONE               _MI6(0,0,0,0)
 
+#define IP4_MAX_PREFIX_LENGTH  32
+#define IP6_MAX_PREFIX_LENGTH  128
+
 #define IP4_MIN_MTU            576
 #define IP6_MIN_MTU            1280
 
 #define IP6_HEADER_LENGTH      40
 #define UDP_HEADER_LENGTH      8
 
-
 #ifdef IPV6
 #define MAX_PREFIX_LENGTH 128
 #define BITS_PER_IP_ADDRESS 128
 #define STD_ADDRESS_P_LENGTH 39
-#define SIZE_OF_IP_HEADER 40
 #else
 #define MAX_PREFIX_LENGTH 32
 #define BITS_PER_IP_ADDRESS 32
 #define STD_ADDRESS_P_LENGTH 15
-#define SIZE_OF_IP_HEADER 24
 #endif
 
 
@@ -319,11 +319,11 @@ static inline int ipa_classify_net(ip_addr a)
 static inline ip4_addr ip4_mkmask(uint n)
 { return _MI4(u32_mkmask(n)); }
 
-static inline int ip4_masklen(ip4_addr a)
+static inline uint ip4_masklen(ip4_addr a)
 { return u32_masklen(_I(a)); }
 
 ip6_addr ip6_mkmask(uint n);
-int ip6_masklen(ip6_addr *a);
+uint ip6_masklen(ip6_addr *a);
 
 /* ipX_pxlen() requires that x != y */
 static inline uint ip4_pxlen(ip4_addr a, ip4_addr b)
@@ -345,6 +345,18 @@ static inline u32 ip4_getbit(ip4_addr a, uint pos)
 static inline u32 ip6_getbit(ip6_addr a, uint pos)
 { return a.addr[pos / 32] & (0x80000000 >> (pos % 32)); }
 
+static inline u32 ip4_setbit(ip4_addr *a, uint pos)
+{ return _I(*a) |= (0x80000000 >> pos); }
+
+static inline u32 ip6_setbit(ip6_addr *a, uint pos)
+{ return a->addr[pos / 32] |= (0x80000000 >> (pos % 32)); }
+
+static inline u32 ip4_clrbit(ip4_addr *a, uint pos)
+{ return _I(*a) &= ~(0x80000000 >> pos); }
+
+static inline u32 ip6_clrbit(ip6_addr *a, uint pos)
+{ return a->addr[pos / 32] &= ~(0x80000000 >> (pos % 32)); }
+
 static inline ip4_addr ip4_opposite_m1(ip4_addr a)
 { return _MI4(_I(a) ^ 1); }
 
@@ -364,6 +376,8 @@ ip4_addr ip4_class_mask(ip4_addr ad);
 #define ipa_masklen(x) ip6_masklen(&x)
 #define ipa_pxlen(x,y) ip6_pxlen(x,y)
 #define ipa_getbit(x,n) ip6_getbit(x,n)
+#define ipa_setbit(x,n) ip6_setbit(x,n)
+#define ipa_clrbit(x,n) ip6_clrbit(x,n)
 #define ipa_opposite_m1(x) ip6_opposite_m1(x)
 #define ipa_opposite_m2(x) ip6_opposite_m2(x)
 #else
@@ -371,6 +385,8 @@ ip4_addr ip4_class_mask(ip4_addr ad);
 #define ipa_masklen(x) ip4_masklen(x)
 #define ipa_pxlen(x,y) ip4_pxlen(x,y)
 #define ipa_getbit(x,n) ip4_getbit(x,n)
+#define ipa_setbit(x,n) ip4_setbit(x,n)
+#define ipa_clrbit(x,n) ip4_clrbit(x,n)
 #define ipa_opposite_m1(x) ip4_opposite_m1(x)
 #define ipa_opposite_m2(x) ip4_opposite_m2(x)
 #endif
diff --git a/lib/net.c b/lib/net.c
new file mode 100644 (file)
index 0000000..87d4aa1
--- /dev/null
+++ b/lib/net.c
@@ -0,0 +1,47 @@
+
+#include "nest/bird.h"
+#include "lib/ip.h"
+#include "lib/net.h"
+
+const u16 net_addr_length[] = {
+  [NET_IP4] = sizeof(net_addr_ip4),
+  [NET_IP6] = sizeof(net_addr_ip6),
+  [NET_VPN4] = sizeof(net_addr_vpn4),
+  [NET_VPN6] = sizeof(net_addr_vpn6)
+}
+
+char *
+net_format(const net_addr *N, char *buf, int buflen)
+{
+  net_addr_union *n = (void *) N;
+
+  /* FIXME: quick hack */
+  switch (n->n.type)
+  {
+  case NET_IP4:
+    return bsnprintf(buf, buflen, "%I/%d", n->ip4.prefix, n->ip4.pxlen);
+  case NET_IP6:
+    return bsnprintf(buf, buflen, "%I/%d", n->ip6.prefix, n->ip6.pxlen);
+  case NET_VPN4:
+    return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn4.rd >> 32), (u32) n->vpn4.rd, n->vpn4.prefix, n->vpn4.pxlen);
+  case NET_VPN6:
+    return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
+  }
+}
+
+int
+net_classify(const net_addr *N)
+{
+  net_addr_union *n = (void *) N;
+
+  switch (n->n.type)
+  {
+  case NET_IP4:
+  case NET_VPN4:
+    return ip4_zero(n->ip4.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip4_classify(n->ip4.prefix);
+
+  case NET_IP6:
+  case NET_VPN6:
+    return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(n->ip6.prefix);
+  }
+}
diff --git a/lib/net.h b/lib/net.h
new file mode 100644 (file)
index 0000000..f6bf95f
--- /dev/null
+++ b/lib/net.h
@@ -0,0 +1,214 @@
+/*
+ *     BIRD Internet Routing Daemon -- Network addresses
+ *
+ *     (c) 2015 Ondrej Zajicek <santiago@crfreenet.org>
+ *     (c) 2015 CZ.NIC z.s.p.o.
+ *
+ *     Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#ifndef _BIRD_NET_H_
+#define _BIRD_NET_H_
+
+#include "lib/ip.h"
+
+
+#define NET_IP4                1
+#define NET_IP6                2
+#define NET_VPN4       3
+#define NET_VPN6       4
+#define NET_MAX                5
+
+
+typedef struct net_addr {
+  u8 type;
+  u8 pxlen;
+  u16 length;
+  u64 align[0];
+  u32 space[4];
+} net_addr;
+
+typedef struct net_addr_ip4 {
+  u8 type;
+  u8 pxlen;
+  u16 length;
+  ip4_addr prefix;
+} net_addr_ip4;
+
+typedef struct net_addr_ip6 {
+  u8 type;
+  u8 pxlen;
+  u16 length;
+  ip6_addr prefix;
+} net_addr_ip6;
+
+typedef struct net_addr_vpn4 {
+  u8 type;
+  u8 pxlen;
+  u16 length;
+  ip4_addr prefix;
+  u64 rd;
+} net_addr_vpn4;
+
+typedef struct net_addr_vpn6 {
+  u8 type;
+  u8 pxlen;
+  u16 length;
+  ip6_addr prefix;
+  u64 rd;
+} net_addr_vpn6;
+
+
+typedef union net_addr_union {
+  net_addr n;
+  net_addr_ip4 ip4;
+  net_addr_ip6 ip6;
+  net_addr_vpn4 vpn4;
+  net_addr_vpn6 vpn6;
+} net_addr_union;
+
+
+extern const u16 net_addr_length[];
+
+
+#define NET_ADDR_IP4(prefix,pxlen) \
+  ((net_addr_ip4) { NET_IP4, pxlen, sizeof(net_addr_ip4), prefix })
+
+#define NET_ADDR_IP6(prefix,pxlen) \
+  ((net_addr_ip6) { NET_IP6, pxlen, sizeof(net_addr_ip6), prefix })
+
+#define NET_ADDR_VPN4(prefix,pxlen,rd) \
+  ((net_addr_vpn4) { NET_VPN4, pxlen, sizeof(net_addr_vpn4), prefix, rd })
+
+#define NET_ADDR_VPN6(prefix,pxlen,rd) \
+  ((net_addr_vpn6) { NET_VPN6, pxlen, sizeof(net_addr_vpn6), prefix, rd })
+
+
+static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen)
+{ *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); }
+
+static inline void net_fill_ip6(net_addr *a, ip6_addr prefix, uint pxlen)
+{ *(net_addr_ip6 *)a = NET_ADDR_IP6(prefix, pxlen); }
+
+static inline void net_fill_vpn4(net_addr *a, ip4_addr prefix, uint pxlen, u64 rd)
+{ *(net_addr_vpn4 *)a = NET_ADDR_VPN4(prefix, pxlen, rd); }
+
+static inline void net_fill_vpn6(net_addr *a, ip6_addr prefix, uint pxlen, u64 rd)
+{ *(net_addr_vpn6 *)a = NET_ADDR_VPN6(prefix, pxlen, rd); }
+
+static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen)
+{
+  if (ipa_is_ip4(prefix))
+    net_fill_ip4(a, ipa_to_ip4(prefix), pxlen);
+  else
+    net_fill_ip6(a, ipa_to_ip6(prefix), pxlen);
+}
+
+static inline ip4_addr net4_prefix(const net_addr *a)
+{ return ((net_addr_ip4 *) a)->prefix; }
+
+static inline ip6_addr net6_prefix(const net_addr *a)
+{ return ((net_addr_ip6 *) a)->prefix; }
+
+static inline ip_addr net_prefix(const net_addr *a)
+{
+  switch (a->type)
+  {
+  case NET_IP4:
+  case NET_VPN4: return ipa_from_ip4(net4_prefix(a));
+  case NET_IP6:
+  case NET_VPN6: return ipa_from_ip6(net6_prefix(a));
+  default: return IPA_NONE;
+  }
+}
+
+static inline uint net4_pxlen(const net_addr *a)
+{ return a->pxlen; }
+
+static inline uint net6_pxlen(const net_addr *a)
+{ return a->pxlen; }
+
+static inline uint net_pxlen(const net_addr *a)
+{ return a->pxlen; }
+
+
+static inline int net_equal(const net_addr *a, const net_addr *b)
+{ return (a->length == b->length) && !memcmp(a, b, a->length); }
+
+static inline int net_equal_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b)
+{ return !memcmp(a, b, sizeof(net_addr_ip4)); }
+
+static inline int net_equal_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b)
+{ return !memcmp(a, b, sizeof(net_addr_ip6)); }
+
+static inline int net_equal_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b)
+{ return !memcmp(a, b, sizeof(net_addr_vpn4)); }
+
+static inline int net_equal_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b)
+{ return !memcmp(a, b, sizeof(net_addr_vpn6)); }
+
+
+static inline int net_zero_ip4(const net_addr_ip4 *a)
+{ return !a->pxlen && ip4_zero(a->prefix); }
+
+static inline int net_zero_ip6(const net_addr_ip6 *a)
+{ return !a->pxlen && ip6_zero(a->prefix); }
+
+static inline int net_zero_vpn4(const net_addr_vpn4 *a)
+{ return !a->pxlen && ip4_zero(a->prefix) && !a->rd; }
+
+static inline int net_zero_vpn6(const net_addr_vpn6 *a)
+{ return !a->pxlen && ip6_zero(a->prefix) && !a->rd; }
+
+
+static inline void net_copy(net_addr *dst, const net_addr *src)
+{ memcpy(dst, src, src->length); }
+
+static inline void net_copy_ip4(net_addr_ip4 *dst, const net_addr_ip4 *src)
+{ memcpy(dst, src, sizeof(net_addr_ip4)); }
+
+static inline void net_copy_ip6(net_addr_ip6 *dst, const net_addr_ip6 *src)
+{ memcpy(dst, src, sizeof(net_addr_ip6)); }
+
+static inline void net_copy_vpn4(net_addr_vpn4 *dst, const net_addr_vpn4 *src)
+{ memcpy(dst, src, sizeof(net_addr_vpn4)); }
+
+static inline void net_copy_vpn6(net_addr_vpn6 *dst, const net_addr_vpn6 *src)
+{ memcpy(dst, src, sizeof(net_addr_vpn6)); }
+
+
+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(u32 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); }
+
+static inline u32 net_hash_vpn6(const net_addr_vpn6 *n)
+{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); }
+
+
+static inline void net_normalize_ip4(net_addr_ip4 *n)
+{ n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); }
+
+static inline void net_normalize_ip6(net_addr_ip6 *n)
+{ n->prefix = ip6_and(n->prefix, ip6_mkmask(n->pxlen)); }
+
+void net_normalize(net_addr *N);
+
+int net_validate(const net_addr *N);
+int net_classify(const net_addr *N);
+char * net_format(const net_addr *N, char *buf, int buflen);
+
+
+
+#endif
+
+
+
index e4cc3006797541975b1dc3df554d983bbf407b9c..1a8c2a9069c770e6c7c40f3c11e4371e47a12692 100644 (file)
@@ -236,6 +236,12 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
                case 'M':
                        s = strerror(va_arg(args, int));
                        goto str;
+               case 'N':
+                       if (field_width == 1)
+                               field_width = STD_ADDRESS_P_LENGTH; /* XXXX */
+                       net_format(va_arg(args, net_addr *), ipbuf, sizeof(ipbuf));
+                       s = ipbuf;
+                       goto str;
                case 's':
                        s = va_arg(args, char *);
                        if (!s)
index e69286684f0a3c9a6943ea9ff030af7c50a5a2a2..478a82b78bd7f1982ed263b698fa9f07c34a817c 100644 (file)
@@ -1,4 +1,4 @@
-source=rt-table.c rt-fib.c rt-attr.c rt-roa.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \
+source=rt-table.c rt-fib.c rt-attr.c proto.c iface.c rt-dev.c password.c cli.c locks.c cmds.c neighbor.c \
        a-path.c a-set.c
 root-rel=../
 dir-name=nest
index 3c7d749b596ad782473a3bf0856ca3037f8ed0af..55712abe82450c0d050846168f6f6a7a144bc976 100644 (file)
@@ -12,5 +12,6 @@
 #include "sysdep/config.h"
 #include "lib/birdlib.h"
 #include "lib/ip.h"
+#include "lib/net.h"
 
 #endif
index 799a09f90a85672e337b1f5df06b3ac5e6e8da99..4353db79e303659b813be93983b26884ffb657ac 100644 (file)
@@ -55,6 +55,7 @@ CF_DECLS
 
 CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
 CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(IPV4, IPVX, VPN4, VPN6)
 CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
 CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
 CF_KEYWORDS(PRIMARY, STATS, COUNT, FOR, COMMANDS, PREEXPORT, NOEXPORT, GENERATE, ROA)
@@ -77,7 +78,7 @@ CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID)
 %type <ro> roa_args
 %type <rot> roa_table_arg
 %type <sd> sym_args
-%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action tab_sorted tos
+%type <i> proto_start echo_mask echo_size debug_mask debug_list debug_flag mrtdump_mask mrtdump_list mrtdump_flag export_mode roa_mode limit_action table_type table_sorted tos
 %type <ps> proto_patt proto_patt2
 %type <g> limit_spec
 
@@ -95,14 +96,7 @@ rtrid:
 idval:
    NUM { $$ = $1; }
  | '(' term ')' { $$ = f_eval_int($2); }
- | RTRID
- | IPA {
-#ifndef IPV6
-     $$ = ipa_to_u32($1);
-#else
-     cf_error("Router IDs must be entered as hexadecimal numbers or IPv4 addresses in IPv6 version");
-#endif
-   }
+ | IP4 { $$ = ip4_to_u32($1); }
  | SYM {
      if ($1->class == (SYM_CONSTANT | T_INT) || $1->class == (SYM_CONSTANT | T_QUAD))
        $$ = SYM_VAL($1).i;
@@ -140,17 +134,25 @@ gr_opts: GRACEFUL RESTART WAIT expr ';' { new_config->gr_wait = $4; } ;
 
 /* Creation of routing tables */
 
-tab_sorted:
+CF_ADDTO(conf, table)
+
+table_type:
+   /* empty */ { $$ = NET_IP4; }
+ | IPV4 { $$ = NET_IP4; }
+ | IPVX { $$ = NET_IP6; } /* XXXX */
+ | VPN4 { $$ = NET_VPN4; }
+ | VPN6 { $$ = NET_VPN6; }
+ ;
+
+table_sorted:
           { $$ = 0; }
  | SORTED { $$ = 1; }
  ;
 
-CF_ADDTO(conf, newtab)
-
-newtab: TABLE SYM tab_sorted {
+table: table_type TABLE SYM table_sorted {
    struct rtable_config *cf;
-   cf = rt_new_table($2);
-   cf->sorted = $3;
+   cf = rt_new_table($3, $1);
+   cf->sorted = $4;
    }
  ;
 
index c435b9e0758d43c7efbac5b6e27fe9229dcfc8c9..4480d17bbfdaeddec93d09473d2e748233c5f23d 100644 (file)
@@ -35,11 +35,9 @@ struct cli;
 struct fib_node {
   struct fib_node *next;               /* Next in hash chain */
   struct fib_iterator *readers;                /* List of readers of this node */
-  byte pxlen;
-  byte flags;                          /* User-defined */
-  byte x0, x1;                         /* User-defined */
-  u32 uid;                             /* Unique ID based on hash */
-  ip_addr prefix;                      /* In host order */
+  byte flags;                          /* User-defined, will be removed */
+  u32 uid;                             /* Unique ID based on hash, will be removed */
+  net_addr addr[0];
 };
 
 struct fib_iterator {                  /* See lib/slists.h for an explanation */
@@ -50,7 +48,7 @@ struct fib_iterator {                 /* See lib/slists.h for an explanation */
   uint hash;
 };
 
-typedef void (*fib_init_func)(struct fib_node *);
+typedef void (*fib_init_fn)(void *);
 
 struct fib {
   pool *fib_pool;                      /* Pool holding all our data */
@@ -59,15 +57,18 @@ struct fib {
   uint hash_size;                      /* Number of hash table entries (a power of two) */
   uint hash_order;                     /* Binary logarithm of hash_size */
   uint hash_shift;                     /* 16 - hash_log */
+  uint addr_type;                      /* Type of address data stored in fib (NET_*) */
+  uint node_size;      /* XXXX */
+  uint node_offset;    /* XXXX */
   uint entries;                                /* Number of entries */
   uint entries_min, entries_max;       /* Entry count limits (else start rehashing) */
-  fib_init_func init;                  /* Constructor */
+  fib_init_fn init;                    /* Constructor */
 };
 
-void fib_init(struct fib *, pool *, unsigned node_size, unsigned hash_order, fib_init_func init);
-void *fib_find(struct fib *, ip_addr *, int);  /* Find or return NULL if doesn't exist */
-void *fib_get(struct fib *, ip_addr *, int);   /* Find or create new if nonexistent */
-void *fib_route(struct fib *, ip_addr, int);   /* Longest-match routing lookup */
+void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
+void *fib_find(struct fib *, net_addr *);      /* Find or return NULL if doesn't exist */
+void *fib_get(struct fib *, net_addr *);       /* Find or create new if nonexistent */
+void *fib_route(struct fib *, net_addr *);     /* Longest-match routing lookup */
 void fib_delete(struct fib *, void *); /* Remove fib entry */
 void fib_free(struct fib *);           /* Destroy the fib */
 void fib_check(struct fib *);          /* Consistency check for debugging */
@@ -77,7 +78,7 @@ struct fib_node *fit_get(struct fib *, struct fib_iterator *);
 void fit_put(struct fib_iterator *, struct fib_node *);
 void fit_put_next(struct fib *f, struct fib_iterator *i, struct fib_node *n, uint hpos);
 
-
+/* XXXX: return user entries */
 #define FIB_WALK(fib, z) do {                                  \
        struct fib_node *z, **ff = (fib)->hash_table;           \
        uint count = (fib)->hash_size;                          \
@@ -126,6 +127,7 @@ struct rtable_config {
   char *name;
   struct rtable *table;
   struct proto_config *krt_attached;   /* Kernel syncer attached to this table */
+  uint addr_type;                      /* Type of address data stored in table (NET_*) */
   int gc_max_ops;                      /* Maximum number of operations before GC is run */
   int gc_min_time;                     /* Minimum time between two consecutive GC runs */
   byte sorted;                         /* Routes of network are sorted according to rte_better() */
@@ -136,6 +138,7 @@ typedef struct rtable {
   struct fib fib;
   char *name;                          /* Name of this table */
   list hooks;                          /* List of announcement hooks */
+  uint addr_type;                      /* Type of address data stored in table (NET_*) */
   int pipe_busy;                       /* Pipe loop detection */
   int use_count;                       /* Number of protocols using this table */
   struct hostcache *hostcache;
@@ -160,8 +163,8 @@ typedef struct rtable {
 #define RPS_RUNNING    2
 
 typedef struct network {
-  struct fib_node n;                   /* FIB flags reserved for kernel syncer */
   struct rte *routes;                  /* Available routes for this network */
+  struct fib_node n;                   /* FIB flags reserved for kernel syncer */
 } net;
 
 struct hostcache {
@@ -262,14 +265,20 @@ void rt_commit(struct config *new, struct config *old);
 void rt_lock_table(rtable *);
 void rt_unlock_table(rtable *);
 void rt_setup(pool *, rtable *, char *, struct rtable_config *);
-static inline net *net_find(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_find(&tab->fib, &addr, len); }
-static inline net *net_get(rtable *tab, ip_addr addr, unsigned len) { return (net *) fib_get(&tab->fib, &addr, len); }
+static inline net *net_find(rtable *tab, net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
+static inline net *net_get(rtable *tab, net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
+
+static inline net *net_find_ipa(rtable *tab, ip_addr px, uint pxlen)
+{ net_addr addr; net_fill_ipa(&addr, px, pxlen); return (net *) fib_find(&tab->fib, &addr); }
+static inline net *net_get_ipa(rtable *tab, ip_addr px, uint pxlen)
+{ net_addr addr; net_fill_ipa(&addr, px, pxlen); return (net *) fib_get(&tab->fib, &addr); }
+
 rte *rte_find(net *net, struct rte_src *src);
 rte *rte_get_temp(struct rta *);
 void rte_update2(struct announce_hook *ah, net *net, rte *new, struct rte_src *src);
 static inline void rte_update(struct proto *p, net *net, rte *new) { rte_update2(p->main_ahook, net, new, p->main_source); }
 void rte_discard(rtable *tab, rte *old);
-int rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter);
+int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
 rte *rt_export_merged(struct announce_hook *ah, net *net, rte **rt_free, struct ea_list **tmpa, int silent);
 void rt_refresh_begin(rtable *t, struct announce_hook *ah);
 void rt_refresh_end(rtable *t, struct announce_hook *ah);
@@ -283,7 +292,7 @@ void rt_dump_all(void);
 int rt_feed_baby(struct proto *p);
 void rt_feed_baby_abort(struct proto *p);
 int rt_prune_loop(void);
-struct rtable_config *rt_new_table(struct symbol *s);
+struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
 
 static inline void
 rt_mark_for_prune(rtable *tab)
index f6bc1432b7da24dbf00adac5334860811d02bb5c..e84081164bb1c49d2526f977ce79ac17093df689 100644 (file)
@@ -45,7 +45,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
       net *n;
 
       DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
-      n = net_find(p->table, ad->prefix, ad->pxlen);
+      n = net_find_ipa(p->table, ad->prefix, ad->pxlen);
       if (!n)
        {
          DBG("dev_if_notify: device shutdown: prefix not found\n");
@@ -77,7 +77,7 @@ dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
       };
 
       a = rta_lookup(&a0);
-      n = net_get(p->table, ad->prefix, ad->pxlen);
+      n = net_get_ipa(p->table, ad->prefix, ad->pxlen);
       e = rte_get_temp(a);
       e->net = n;
       e->pflags = 0;
index a73de1fd1501dac870c361559e4e36b671de965e..d726714ba7dd2e92d8d1e1cc05f0ee9300597b7d 100644 (file)
 #define HASH_LO_STEP 2
 #define HASH_LO_MIN 10
 
+
+static inline void * fib_node_to_user(struct fib *f, struct fib_node *e)
+{ return (void *) ((char *) e - f->node_offset); }
+
+static inline struct fib_node * fib_user_to_node(struct fib *f, void *e)
+{ return (void *) ((char *) e + f->node_offset); }
+
 static void
 fib_ht_alloc(struct fib *f)
 {
@@ -72,16 +79,9 @@ fib_ht_free(struct fib_node **h)
   mb_free(h);
 }
 
-static inline unsigned
-fib_hash(struct fib *f, ip_addr *a)
-{
-  return ipa_hash(*a) >> f->hash_shift;
-}
 
-static void
-fib_dummy_init(struct fib_node *dummy UNUSED)
-{
-}
+static u32
+fib_hash(struct fib *f, net_addr *a);
 
 /**
  * fib_init - initialize a new FIB
@@ -96,18 +96,23 @@ fib_dummy_init(struct fib_node *dummy UNUSED)
  * This function initializes a newly allocated FIB and prepares it for use.
  */
 void
-fib_init(struct fib *f, pool *p, unsigned node_size, unsigned hash_order, fib_init_func init)
+fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init)
 {
+  uint addr_length = net_addr_length[addr_type];
+
   if (!hash_order)
     hash_order = HASH_DEF_ORDER;
   f->fib_pool = p;
-  f->fib_slab = sl_new(p, node_size);
+  f->fib_slab = addr_length ? sl_new(p, node_size + addr_length) : NULL;
+  f->addr_type = addr_type;
+  f->node_size = node_size;
+  f->node_offset = node_offset;
   f->hash_order = hash_order;
   fib_ht_alloc(f);
   bzero(f->hash_table, f->hash_size * sizeof(struct fib_node *));
   f->entries = 0;
   f->entries_min = 0;
-  f->init = init ? : fib_dummy_init;
+  f->init = init;
 }
 
 static void
@@ -133,7 +138,7 @@ fib_rehash(struct fib *f, int step)
       while (e = x)
        {
          x = e->next;
-         nh = fib_hash(f, &e->prefix);
+         nh = fib_hash(f, e->addr);
          while (nh > ni)
            {
              *t = NULL;
@@ -153,6 +158,76 @@ fib_rehash(struct fib *f, int step)
   fib_ht_free(m);
 }
 
+#define CAST(t) (net_addr_##t *)
+
+#define FIB_HASH(f,a,t) (net_hash_##t(CAST(t) a) >> f->hash_shift)
+
+#define FIB_FIND(f,a,t)                                                        \
+  ({                                                                   \
+    struct fib_node *e = f->hash_table[FIB_HASH(f, a, t)];             \
+    while (e && !net_equal_##t(CAST(t) e->addr, CAST(t) a))            \
+      e = e->next;                                                     \
+    fib_node_to_user(f, e);                                            \
+  })
+
+#define FIB_INSERT(f,a,e,t)                                            \
+  ({                                                                   \
+  u32 h = net_hash_##t(CAST(t) a);                                     \
+  struct fib_node **ee = f->hash_table + (h >> f->hash_shift);         \
+  struct fib_node *g;                                                  \
+                                                                       \
+  while ((g = *ee) && (net_hash_##t(CAST(t) g->addr) < h))             \
+    ee = &g->next;                                                     \
+                                                                       \
+  net_copy_##t(CAST(t) e->addr, CAST(t) a);                            \
+  e->next = *ee;                                                       \
+  *ee = e;                                                             \
+  })
+
+
+static u32
+fib_hash(struct fib *f, net_addr *a)
+{
+  switch (f->addr_type)
+  {
+  case NET_IP4: return FIB_HASH(f, a, ip4);
+  case NET_IP6: return FIB_HASH(f, a, ip6);
+  case NET_VPN4: return FIB_HASH(f, a, vpn4);
+  case NET_VPN6: return FIB_HASH(f, a, vpn6);
+  default: bug("invalid type");
+  }
+}
+
+void *
+fib_find(struct fib *f, net_addr *a)
+{
+  ASSERT(f->addr_type == a->type);
+
+  switch (f->addr_type)
+  {
+  case NET_IP4: return FIB_FIND(f, a, ip4);
+  case NET_IP6: return FIB_FIND(f, a, ip6);
+  case NET_VPN4: return FIB_FIND(f, a, vpn4);
+  case NET_VPN6: return FIB_FIND(f, a, vpn6);
+  default: bug("invalid type");
+  }
+}
+
+static void
+fib_insert(struct fib *f, net_addr *a, struct fib_node *e)
+{
+  switch (f->addr_type)
+  {
+  case NET_IP4: FIB_INSERT(f, a, e, ip4); return;
+  case NET_IP6: FIB_INSERT(f, a, e, ip6); return;
+  case NET_VPN4: FIB_INSERT(f, a, e, vpn4); return;
+  case NET_VPN6: FIB_INSERT(f, a, e, vpn6); return;
+  default: bug("invalid type");
+  }
+}
+
+
+
 /**
  * fib_find - search for FIB node by prefix
  * @f: FIB to search in
@@ -162,8 +237,9 @@ fib_rehash(struct fib *f, int step)
  * Search for a FIB node corresponding to the given prefix, return
  * a pointer to it or %NULL if no such node exists.
  */
+/*
 void *
-fib_find(struct fib *f, ip_addr *a, int len)
+fib_find(struct fib *f, net_addr *a)
 {
   struct fib_node *e = f->hash_table[fib_hash(f, a)];
 
@@ -171,27 +247,6 @@ fib_find(struct fib *f, ip_addr *a, int len)
     e = e->next;
   return e;
 }
-
-/*
-int
-fib_histogram(struct fib *f)
-{
-  log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries);
-
-  int i, j;
-  struct fib_node *e;
-
-  for (i = 0; i < f->hash_size; i++)
-    {
-      j = 0;
-      for (e = f->hash_table[i]; e != NULL; e = e->next)
-       j++;
-      if (j > 0)
-        log(L_WARN "Histogram line %d: %d", i, j);
-    }
-
-  log(L_WARN "Histogram dump end");
-}
 */
 
 /**
@@ -204,47 +259,31 @@ fib_histogram(struct fib *f)
  * return a pointer to it. If no such node exists, create it.
  */
 void *
-fib_get(struct fib *f, ip_addr *a, int len)
+fib_get(struct fib *f, net_addr *a)
 {
-  uint h = ipa_hash(*a);
-  struct fib_node **ee = f->hash_table + (h >> f->hash_shift);
-  struct fib_node *g, *e = *ee;
-  u32 uid = h << 16;
-
-  while (e && (e->pxlen != len || !ipa_equal(*a, e->prefix)))
-    e = e->next;
-  if (e)
-    return e;
-#ifdef DEBUGGING
-  if (len < 0 || len > BITS_PER_IP_ADDRESS || !ip_is_prefix(*a,len))
-    bug("fib_get() called for invalid address");
-#endif
+  char *b = fib_find(f, a);
+  if (b)
+    return b;
 
-  while ((g = *ee) && g->uid < uid)
-    ee = &g->next;
-  while ((g = *ee) && g->uid == uid)
-    {
-      ee = &g->next;
-      uid++;
-    }
+  if (f->fib_slab)
+    b = sl_alloc(f->fib_slab);
+  else
+    b = mb_alloc(f->fib_pool, f->node_size + a->length);
 
-  if ((uid >> 16) != h)
-    log(L_ERR "FIB hash table chains are too long");
+  struct fib_node *e = (void *) (b + f->node_offset);
+  e->readers = NULL;
+  e->flags = 0;
+  e->uid = 0;
+  fib_insert(f, a, e);
 
-  // log (L_WARN "FIB_GET %I %x %x", *a, h, uid);
+  memset(b, 0, f->node_offset);
+  if (f->init)
+    f->init(b);
 
-  e = sl_alloc(f->fib_slab);
-  e->prefix = *a;
-  e->pxlen = len;
-  e->next = *ee;
-  e->uid = uid;
-  *ee = e;
-  e->readers = NULL;
-  f->init(e);
   if (f->entries++ > f->entries_max)
     fib_rehash(f, HASH_HI_STEP);
 
-  return e;
+  return b;
 }
 
 /**
@@ -257,6 +296,7 @@ fib_get(struct fib *f, ip_addr *a, int len)
  * network, that is a node which a CIDR router would use for routing
  * that network.
  */
+/*
 void *
 fib_route(struct fib *f, ip_addr a, int len)
 {
@@ -273,6 +313,7 @@ fib_route(struct fib *f, ip_addr a, int len)
     }
   return NULL;
 }
+*/
 
 static inline void
 fib_merge_readers(struct fib_iterator *i, struct fib_node *to)
@@ -320,8 +361,8 @@ fib_merge_readers(struct fib_iterator *i, struct fib_node *to)
 void
 fib_delete(struct fib *f, void *E)
 {
-  struct fib_node *e = E;
-  uint h = fib_hash(f, &e->prefix);
+  struct fib_node *e = fib_user_to_node(f, E);
+  uint h = fib_hash(f, e->addr);
   struct fib_node **ee = f->hash_table + h;
   struct fib_iterator *it;
 
@@ -413,7 +454,7 @@ fit_get(struct fib *f, struct fib_iterator *i)
   if (k = i->next)
     k->prev = j;
   j->next = k;
-  i->hash = fib_hash(f, &n->prefix);
+  i->hash = fib_hash(f, n->addr);
   return n;
 }
 
@@ -498,6 +539,28 @@ fib_check(struct fib *f)
     bug("fib_check: invalid entry count (%d != %d)", ec, f->entries);
 }
 
+/*
+int
+fib_histogram(struct fib *f)
+{
+  log(L_WARN "Histogram dump start %d %d", f->hash_size, f->entries);
+
+  int i, j;
+  struct fib_node *e;
+
+  for (i = 0; i < f->hash_size; i++)
+    {
+      j = 0;
+      for (e = f->hash_table[i]; e != NULL; e = e->next)
+       j++;
+      if (j > 0)
+        log(L_WARN "Histogram line %d: %d", i, j);
+    }
+
+  log(L_WARN "Histogram dump end");
+}
+*/
+
 #endif
 
 #ifdef TEST
@@ -517,7 +580,7 @@ void dump(char *m)
       struct fib_iterator *j;
       for(n=f.hash_table[i]; n; n=n->next)
        {
-         debug("%04x %04x %p %I/%2d", i, ipa_hash(n->prefix), n, n->prefix, n->pxlen);
+         debug("%04x %08x %p %N", i, ipa_hash(n->prefix), n, n->addr);
          for(j=n->readers; j; j=j->next)
            debug(" %p[%p]", j, j->node);
          debug("\n");
index b39f2a69febf470f70d648ead6565497173740cd..88c6883ac5793bf3c8090b9ba8d0296af922e14c 100644 (file)
@@ -69,6 +69,7 @@ make_tmp_attrs(struct rte *rt, struct linpool *pool)
 }
 
 /* Like fib_route(), but skips empty net entries */
+/*
 static net *
 net_route(rtable *tab, ip_addr a, int len)
 {
@@ -85,15 +86,7 @@ net_route(rtable *tab, ip_addr a, int len)
     }
   return NULL;
 }
-
-static void
-rte_init(struct fib_node *N)
-{
-  net *n = (net *) N;
-
-  N->flags = 0;
-  n->routes = NULL;
-}
+*/
 
 /**
  * rte_find - find a route
@@ -230,7 +223,7 @@ rte_trace(struct proto *p, rte *e, int dir, char *msg)
   byte via[STD_ADDRESS_P_LENGTH+32];
 
   rt_format_via(e, via);
-  log(L_TRACE "%s %c %s %I/%d %s", p->name, dir, msg, e->net->n.prefix, e->net->n.pxlen, via);
+  log(L_TRACE "%s %c %s %N %s", p->name, dir, msg, e->net->n.addr, via);
 }
 
 static inline void
@@ -788,20 +781,21 @@ rte_validate(rte *e)
   int c;
   net *n = e->net;
 
-  if ((n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
-    {
-      log(L_WARN "Ignoring bogus prefix %I/%d received via %s",
-         n->n.prefix, n->n.pxlen, e->sender->proto->name);
-      return 0;
-    }
+  // (n->n.pxlen > BITS_PER_IP_ADDRESS) || !ip_is_prefix(n->n.prefix,n->n.pxlen))
+  if (!net_validate(n->n.addr))
+  {
+    log(L_WARN "Ignoring bogus prefix %N received via %s",
+       n->n.addr, e->sender->proto->name);
+    return 0;
+  }
 
-  c = ipa_classify_net(n->n.prefix);
+  c = net_classify(n->n.addr);
   if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
-    {
-      log(L_WARN "Ignoring bogus route %I/%d received via %s",
-         n->n.prefix, n->n.pxlen, e->sender->proto->name);
-      return 0;
-    }
+  {
+    log(L_WARN "Ignoring bogus route %N received via %s",
+       n->n.addr, e->sender->proto->name);
+    return 0;
+  }
 
   return 1;
 }
@@ -870,8 +864,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, struct rte_src *sr
            {
              if (new)
                {
-                 log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %I/%d to table %s",
-                     net->n.prefix, net->n.pxlen, table->name);
+                 log_rl(&rl_pipe, L_ERR "Pipe collision detected when sending %N to table %s",
+                     net->n.addr, table->name);
                  rte_free_quick(new);
                }
              return;
@@ -1278,9 +1272,9 @@ rte_discard(rtable *t, rte *old)  /* Non-filtered route deletion, used during gar
 
 /* Check rtable for best route to given net whether it would be exported do p */
 int
-rt_examine(rtable *t, ip_addr prefix, int pxlen, struct proto *p, struct filter *filter)
+rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
 {
-  net *n = net_find(t, prefix, pxlen);
+  net *n = net_find(t, a);
   rte *rt = n ? n->routes : NULL;
 
   if (!rte_is_valid(rt))
@@ -1376,7 +1370,7 @@ void
 rte_dump(rte *e)
 {
   net *n = e->net;
-  debug("%-1I/%2d ", n->n.prefix, n->n.pxlen);
+  debug("%-1N ", n->n.addr);
   debug("KF=%02x PF=%02x pref=%d lm=%d ", n->n.flags, e->pflags, e->pref, now-e->lastmod);
   rta_dump(e->attrs);
   if (e->attrs->src->proto->proto->dump_attrs)
@@ -1527,9 +1521,10 @@ void
 rt_setup(pool *p, rtable *t, char *name, struct rtable_config *cf)
 {
   bzero(t, sizeof(*t));
-  fib_init(&t->fib, p, sizeof(net), 0, rte_init);
   t->name = name;
   t->config = cf;
+  t->addr_type = cf ? cf->addr_type : NET_IP4;
+  fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL);
   init_list(&t->hooks);
   if (cf)
     {
@@ -1660,7 +1655,7 @@ rt_preconfig(struct config *c)
   struct symbol *s = cf_find_symbol("master");
 
   init_list(&c->tables);
-  c->master_rtc = rt_new_table(s);
+  c->master_rtc = rt_new_table(s, NET_IP4);
 }
 
 
@@ -1817,7 +1812,7 @@ rt_next_hop_update(rtable *tab)
 
 
 struct rtable_config *
-rt_new_table(struct symbol *s)
+rt_new_table(struct symbol *s, uint addr_type)
 {
   /* Hack that allows to 'redefine' the master table */
   if ((s->class == SYM_TABLE) && (s->def == new_config->master_rtc))
@@ -1827,6 +1822,7 @@ rt_new_table(struct symbol *s)
 
   cf_define_symbol(s, SYM_TABLE, c);
   c->name = s->name;
+  c->addr_type = addr_type;
   add_tail(&new_config->tables, &c->n);
   c->gc_max_ops = 1000;
   c->gc_min_time = 5;
@@ -2196,8 +2192,9 @@ rt_notify_hostcache(rtable *tab, net *net)
   if (tab->hcu_scheduled)
     return;
 
-  if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
-    rt_schedule_hcu(tab);
+  // XXXX
+  // if (trie_match_prefix(hc->trie, net->n.prefix, net->n.pxlen))
+  // rt_schedule_hcu(tab);
 }
 
 static int
@@ -2253,18 +2250,20 @@ rt_update_hostentry(rtable *tab, struct hostentry *he)
   he->dest = RTD_UNREACHABLE;
   he->igp_metric = 0;
 
-  net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
+  // XXXX
+  // net *n = net_route(tab, he->addr, MAX_PREFIX_LENGTH);
+  net *n = NULL;
   if (n)
     {
       rte *e = n->routes;
       rta *a = e->attrs;
-      pxlen = n->n.pxlen;
+      pxlen = n->n.addr->pxlen;
 
       if (a->hostentry)
        {
          /* Recursive route should not depend on another recursive route */
-         log(L_WARN "Next hop address %I resolvable through recursive route for %I/%d",
-             he->addr, n->n.prefix, pxlen);
+         log(L_WARN "Next hop address %I resolvable through recursive route for %N",
+             he->addr, n->n.addr);
          goto done;
        }
 
@@ -2425,7 +2424,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
   int first = 1;
   int pass = 0;
 
-  bsprintf(ia, "%I/%d", n->n.prefix, n->n.pxlen);
+  bsprintf(ia, "%N", n->n.addr);
 
   if (d->export_mode)
     {
@@ -2589,10 +2588,13 @@ rt_show(struct rt_show_data *d)
     }
   else
     {
+      /* XXXX 
       if (d->show_for)
        n = net_route(d->table, d->prefix, d->pxlen);
       else
        n = net_find(d->table, d->prefix, d->pxlen);
+      */
+      n = NULL;
 
       if (n)
        rt_show_net(this_cli, n, d);
@@ -2613,26 +2615,24 @@ rt_show(struct rt_show_data *d)
  * net_find - find a network entry
  * @tab: a routing table
  * @addr: address of the network
- * @len: length of the network prefix
  *
  * net_find() looks up the given network in routing table @tab and
  * returns a pointer to its &net entry or %NULL if no such network
  * exists.
  */
-static inline net *net_find(rtable *tab, ip_addr addr, unsigned len)
+static inline net *net_find(rtable *tab, net_addr *addr)
 { DUMMY; }
 
 /**
  * net_get - obtain a network entry
  * @tab: a routing table
  * @addr: address of the network
- * @len: length of the network prefix
  *
  * net_get() looks up the given network in routing table @tab and
  * returns a pointer to its &net entry. If no such entry exists, it's
  * created.
  */
-static inline net *net_get(rtable *tab, ip_addr addr, unsigned len)
+static inline net *net_get(rtable *tab, net_addr *addr)
 { DUMMY; }
 
 /**
index c859960fb778354363a4ae855d4f602dc198c04e..706ab7ac4b8ede943821cb78c0546f0fbaac2601 100644 (file)
@@ -132,7 +132,6 @@ CF_KEYWORDS(WAIT, DELAY, LSADB, ECMP, LIMIT, WEIGHT, NSSA, TRANSLATOR, STABILITY
 CF_KEYWORDS(GLOBAL, LSID, ROUTER, SELF, INSTANCE, REAL, NETMASK, TX, PRIORITY, LENGTH)
 CF_KEYWORDS(SECONDARY, MERGE, LSA, SUPPRESSION)
 
-%type <t> opttext
 %type <ld> lsadb_args
 %type <i> nbma_eligible
 
@@ -401,11 +400,6 @@ ospf_iface:
   ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
  ;
 
-opttext:
-    TEXT
- | /* empty */ { $$ = NULL; }
- ;
-
 CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); })
 CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); })
 CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); })
index 50cf1407e88126490883c9fdb6e5b6a7d10c219d..8b550e7100bd00ff85b51cf5954d4e377c08b3ce 100644 (file)
@@ -105,7 +105,7 @@ ospf_send_hello(struct ospf_iface *ifa, int kind, struct ospf_neighbor *dirn)
   }
 
   i = 0;
-  max = (ospf_pkt_maxsize(ifa) - length) / sizeof(u32);
+  max = (ospf_pkt_maxsize(p, ifa) - length) / sizeof(u32);
 
   /* Fill all neighbors */
   if (kind != OHS_SHUTDOWN)
index 77ce839a4fb166f602be3b8da38e92e1eaa14442..3c0cee18831266befb75700804c13423d5075b8c 100644 (file)
@@ -67,7 +67,9 @@ ifa_flood_queue_size(struct ospf_iface *ifa)
 int
 ospf_iface_assure_bufsize(struct ospf_iface *ifa, uint plen)
 {
-  plen += SIZE_OF_IP_HEADER;
+  struct ospf_proto *p = ifa->oa->po;
+
+  plen += ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
 
   /* This is relevant just for OSPFv2 */
   if (ifa->autype == OSPF_AUTH_CRYPT)
index 66a3a23d0bfe8b35a2dc16edb1845e3badeb8d8d..9a6b04570cf7d8c7ee1db0e721687be6569a61cb 100644 (file)
@@ -280,21 +280,19 @@ 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)
+lsa_parse_sum_net(struct top_hash_entry *en, int ospf2, net_addr *net, u8 *pxopts, u32 *metric)
 {
   if (ospf2)
   {
     struct ospf_lsa_sum2 *ls = en->lsa_body;
-    *ip = ipa_from_u32(en->lsa.id & ls->netmask);
-    *pxlen = u32_masklen(ls->netmask);
+    net_fill_ip4(net, ip4_from_u32(en->lsa.id & ls->netmask), u32_masklen(ls->netmask));
     *pxopts = 0;
     *metric = ls->metric & LSA_METRIC_MASK;
   }
   else
   {
     struct ospf_lsa_sum3_net *ls = en->lsa_body;
-    u16 rest;
-    lsa_get_ipv6_prefix(ls->prefix, ip, pxlen, pxopts, &rest);
+    ospf_get_ipv6_prefix(ls->prefix, net, pxopts, NULL);
     *metric = ls->metric & LSA_METRIC_MASK;
   }
 }
@@ -324,8 +322,9 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
   if (ospf2)
   {
     struct ospf_lsa_ext2 *ext = en->lsa_body;
-    rt->ip = ipa_from_u32(en->lsa.id & ext->netmask);
-    rt->pxlen = u32_masklen(ext->netmask);
+    net_fill_ip4(&rt->net,
+                ip4_from_u32(en->lsa.id & ext->netmask),
+                u32_masklen(ext->netmask));
     rt->pxopts = 0;
     rt->metric = ext->metric & LSA_METRIC_MASK;
     rt->ebit = ext->metric & LSA_EXT2_EBIT;
@@ -339,14 +338,13 @@ lsa_parse_ext(struct top_hash_entry *en, int ospf2, struct ospf_lsa_ext_local *r
   else
   {
     struct ospf_lsa_ext3 *ext = en->lsa_body;
-    u16 rest;
-    u32 *buf = lsa_get_ipv6_prefix(ext->rest, &rt->ip, &rt->pxlen, &rt->pxopts, &rest);
+    u32 *buf = ospf_get_ipv6_prefix(ext->rest, &rt->net, &rt->pxopts, NULL);
     rt->metric = ext->metric & LSA_METRIC_MASK;
     rt->ebit = ext->metric & LSA_EXT3_EBIT;
 
     rt->fbit = ext->metric & LSA_EXT3_FBIT;
     if (rt->fbit)
-      buf = lsa_get_ipv6_addr(buf, &rt->fwaddr);
+      buf = ospf_get_ipv6_addr(buf, &rt->fwaddr);
     else
       rt->fwaddr = IPA_NONE;
 
@@ -452,7 +450,7 @@ lsa_validate_sum3_net(struct ospf_lsa_header *lsa, struct ospf_lsa_sum3_net *bod
     return 0;
 
   u8 pxl = pxlen(body->prefix);
-  if (pxl > MAX_PREFIX_LENGTH)
+  if (pxl > IP6_MAX_PREFIX_LENGTH)
     return 0;
 
   if (lsa->length != (HDRLEN + sizeof(struct ospf_lsa_sum3_net) +
@@ -491,7 +489,7 @@ lsa_validate_ext3(struct ospf_lsa_header *lsa, struct ospf_lsa_ext3 *body)
     return 0;
 
   u8 pxl = pxlen(body->rest);
-  if (pxl > MAX_PREFIX_LENGTH)
+  if (pxl > IP6_MAX_PREFIX_LENGTH)
     return 0;
 
   int len = IPV6_PREFIX_SPACE(pxl);
@@ -520,7 +518,7 @@ lsa_validate_pxlist(struct ospf_lsa_header *lsa, u32 pxcount, uint offset, u8 *p
        return 0;
 
       u8 pxl = pxlen((u32 *) (pbuf + offset));
-      if (pxl > MAX_PREFIX_LENGTH)
+      if (pxl > IP6_MAX_PREFIX_LENGTH)
        return 0;
 
       offset += IPV6_PREFIX_SPACE(pxl);
index ae6af044141f40cf178659313a86fa4cfda30b4d..c93f029566694a7ee38dda8b60e5c53d415c962f 100644 (file)
@@ -55,7 +55,7 @@ u16 lsa_verify_checksum(const void *lsa_n, int lsa_len);
 int lsa_comp(struct ospf_lsa_header *l1, struct ospf_lsa_header *l2);
 void lsa_walk_rt_init(struct ospf_proto *po, struct top_hash_entry *act, struct ospf_lsa_rt_walk *rt);
 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_net(struct top_hash_entry *en, int ospf2, net_addr *net, 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, u32 lsa_type, int ospf2, void *body);
index c6a734ca48a2503f4b274bca6ffcf32fc1f76ace..65ad8e3da85914999e54978cbf4eeed96eb53e57 100644 (file)
@@ -330,7 +330,7 @@ ospf_prepare_lsupd(struct ospf_proto *p, struct ospf_iface *ifa,
 
   pkt = ospf_tx_buffer(ifa);
   hlen = ospf_lsupd_hdrlen(p);
-  maxsize = ospf_pkt_maxsize(ifa);
+  maxsize = ospf_pkt_maxsize(p, ifa);
 
   ospf_pkt_fill_hdr(ifa, pkt, LSUPD_P);
   pos = hlen;
index d5d5d354bff2ddd66b029a6fd790bc34e175a6f7..bfe51e66739645806724882ff3dc26d3ed52b894 100644 (file)
@@ -107,13 +107,6 @@ static int ospf_rte_better(struct rte *new, struct rte *old);
 static int ospf_rte_same(struct rte *new, struct rte *old);
 static void ospf_disp(timer *timer);
 
-static void
-ospf_area_initfib(struct fib_node *fn)
-{
-  struct area_net *an = (struct area_net *) fn;
-  an->hidden = 0;
-  an->active = 0;
-}
 
 static void
 add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
@@ -121,19 +114,26 @@ add_area_nets(struct ospf_area *oa, struct ospf_area_config *ac)
   struct ospf_proto *p = oa->po;
   struct area_net_config *anc;
   struct area_net *an;
+  net_addr net;
 
-  fib_init(&oa->net_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib);
-  fib_init(&oa->enet_fib, p->p.pool, sizeof(struct area_net), 0, ospf_area_initfib);
+  fib_init(&oa->net_fib,  p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6,
+          sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
+  fib_init(&oa->enet_fib, p->p.pool, ospf_is_v2(p) ? NET_IP4 : NET_IP6,
+          sizeof(struct area_net), OFFSETOF(struct area_net, fn), 0, NULL);
 
   WALK_LIST(anc, ac->net_list)
   {
-    an = (struct area_net *) fib_get(&oa->net_fib, &anc->px.addr, anc->px.len);
+    /* XXXX we should dispatch by ospf version, not by px.addr */
+    net_fill_ipa(&net, anc->px.addr, anc->px.len);
+    an = fib_get(&oa->net_fib, &net);
     an->hidden = anc->hidden;
   }
 
   WALK_LIST(anc, ac->enet_list)
   {
-    an = (struct area_net *) fib_get(&oa->enet_fib, &anc->px.addr, anc->px.len);
+    /* XXXX ditto */
+    net_fill_ipa(&net, anc->px.addr, anc->px.len);
+    an = fib_get(&oa->enet_fib, &net);
     an->hidden = anc->hidden;
     an->tag = anc->tag;
   }
@@ -154,7 +154,7 @@ ospf_area_add(struct ospf_proto *p, struct ospf_area_config *ac)
   oa->areaid = ac->areaid;
   oa->rt = NULL;
   oa->po = p;
-  fib_init(&oa->rtr, p->p.pool, sizeof(ort), 0, ospf_rt_initort);
+  fib_init(&oa->rtr, p->p.pool, NET_IP4, sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
   add_area_nets(oa, ac);
 
   if (oa->areaid == 0)
@@ -243,7 +243,8 @@ ospf_start(struct proto *P)
   p->nhpool = lp_new(P->pool, 12*sizeof(struct mpnh));
   init_list(&(p->iface_list));
   init_list(&(p->area_list));
-  fib_init(&p->rtf, P->pool, sizeof(ort), 0, ospf_rt_initort);
+  fib_init(&p->rtf, P->pool, p->ospf2 ? NET_IP4 : NET_IP6,
+          sizeof(ort), OFFSETOF(ort, fn), 0, NULL);
   p->areano = 0;
   p->gr = ospf_top_new(p, P->pool);
   s_init_list(&(p->lsal));
@@ -803,7 +804,7 @@ ospf_sh(struct proto *P)
        cli_msg(-1014, "\t\tArea networks:");
        firstfib = 0;
       }
-      cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
+      cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
     }
     FIB_WALK_END;
@@ -817,7 +818,7 @@ ospf_sh(struct proto *P)
        cli_msg(-1014, "\t\tArea external networks:");
        firstfib = 0;
       }
-      cli_msg(-1014, "\t\t\t%1I/%u\t%s\t%s", anet->fn.prefix, anet->fn.pxlen,
+      cli_msg(-1014, "\t\t\t%1N\t%s\t%s", anet->fn.addr,
                anet->hidden ? "Hidden" : "Advertise", anet->active ? "Active" : "");
     }
     FIB_WALK_END;
@@ -1074,13 +1075,12 @@ show_lsa_network(struct top_hash_entry *he, int ospf2)
 static inline void
 show_lsa_sum_net(struct top_hash_entry *he, int ospf2)
 {
-  ip_addr ip;
-  int pxlen;
+  net_addr net;
   u8 pxopts;
   u32 metric;
 
-  lsa_parse_sum_net(he, ospf2, &ip, &pxlen, &pxopts, &metric);
-  cli_msg(-1016, "\t\txnetwork %I/%d metric %u", ip, pxlen, metric);
+  lsa_parse_sum_net(he, ospf2, &net, &pxopts, &metric);
+  cli_msg(-1016, "\t\txnetwork %N metric %u", &net, metric);
 }
 
 static inline void
@@ -1113,19 +1113,15 @@ show_lsa_external(struct top_hash_entry *he, int ospf2)
   if (rt.tag)
     bsprintf(str_tag, " tag %08x", rt.tag);
 
-  cli_msg(-1016, "\t\t%s %I/%d metric%s %u%s%s",
+  cli_msg(-1016, "\t\t%s %N metric%s %u%s%s",
          (he->lsa_type == LSA_T_NSSA) ? "nssa-ext" : "external",
-         rt.ip, rt.pxlen, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
+         &rt.net, rt.ebit ? "2" : "", rt.metric, str_via, str_tag);
 }
 
 static inline void
 show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
 {
   struct ospf_lsa_prefix *px = he->lsa_body;
-  ip_addr pxa;
-  int pxlen;
-  u8 pxopts;
-  u16 metric;
   u32 *buf;
   int i;
 
@@ -1141,14 +1137,18 @@ show_lsa_prefix(struct top_hash_entry *he, struct top_hash_entry *cnode)
 
   buf = px->rest;
   for (i = 0; i < px->pxcount; i++)
-    {
-      buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric);
+  {
+    net_addr net;
+    u8 pxopts;
+    u16 metric;
 
-      if (px->ref_type == LSA_T_RT)
-       cli_msg(-1016, "\t\tstubnet %I/%d metric %u", pxa, pxlen, metric);
-      else
-       cli_msg(-1016, "\t\taddress %I/%d", pxa, pxlen);
-    }
+    buf = ospf_get_ipv6_prefix(buf, &net, &pxopts, &metric);
+
+    if (px->ref_type == LSA_T_RT)
+      cli_msg(-1016, "\t\tstubnet %N metric %u", &net, metric);
+    else
+      cli_msg(-1016, "\t\taddress %N", &net);
+  }
 }
 
 void
index a4e525ec23c5b3649baf5daf7cbd96dfdd7fdc19..df77dda901cd4f7a429290100b51414e31fae6b2 100644 (file)
@@ -132,11 +132,11 @@ struct area_net_config
 
 struct area_net
 {
-  struct fib_node fn;
   u32 metric;                  /* With possible LSA_EXT3_EBIT for NSSA area nets */
   u32 tag;
   u8 hidden;
   u8 active;
+  struct fib_node fn;
 };
 
 struct ospf_stubnet_config
@@ -681,8 +681,8 @@ struct ospf_lsa_ext3
 
 struct ospf_lsa_ext_local
 {
-  ip_addr ip, fwaddr;
-  int pxlen;
+  net_addr net;
+  ip_addr fwaddr;
   u32 metric, ebit, fbit, tag, propagate;
   u8 pxopts;
 };
@@ -720,8 +720,8 @@ lsa_net_count(struct ospf_lsa_header *lsa)
 /* 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 */
 
-#define ipa_from_rid(x) ipa_from_u32(x)
-#define ipa_to_rid(x) ipa_to_u32(x)
+#define net_from_rid(x) NET_ADDR_IP4(ip4_from_u32(x), IP4_MAX_PREFIX_LENGTH)
+#define rid_from_net(x) ip4_to_u32(((net_addr_ip4 *) x)->prefix)
 
 #define IPV6_PREFIX_SPACE(x) ((((x) + 63) / 32) * 4)
 #define IPV6_PREFIX_WORDS(x) (((x) + 63) / 32)
@@ -730,63 +730,63 @@ lsa_net_count(struct ospf_lsa_header *lsa)
    also should be named as ospf3_* instead of *_ipv6_* */
 
 static inline u32 *
-lsa_get_ipv6_prefix(u32 *buf, ip_addr *addr, int *pxlen, u8 *pxopts, u16 *rest)
+ospf_get_ipv6_prefix(u32 *buf, net_addr *N, u8 *pxopts, u16 *rest)
 {
-  u8 pxl = (*buf >> 24);
-  *pxopts = (*buf >> 16);
-  *rest = *buf;
-  *pxlen = pxl;
+  net_addr_ip6 *net = (void *) N;
+  u8 pxlen = (*buf >> 24);
+  *pxopts = (*buf >> 16) & 0xff;
+  if (rest) *rest = *buf & 0xffff;
   buf++;
 
-  *addr = IPA_NONE;
+  *net = NET_ADDR_IP6(IP6_NONE, pxlen);
 
-#ifdef IPV6
-  if (pxl > 0)
-    _I0(*addr) = *buf++;
-  if (pxl > 32)
-    _I1(*addr) = *buf++;
-  if (pxl > 64)
-    _I2(*addr) = *buf++;
-  if (pxl > 96)
-    _I3(*addr) = *buf++;
+  if (pxlen > 0)
+    _I0(net->prefix) = *buf++;
+  if (pxlen > 32)
+    _I1(net->prefix) = *buf++;
+  if (pxlen > 64)
+    _I2(net->prefix) = *buf++;
+  if (pxlen > 96)
+    _I3(net->prefix) = *buf++;
 
   /* Clean up remaining bits */
-  if (pxl < 128)
-    addr->addr[pxl / 32] &= u32_mkmask(pxl % 32);
-#endif
+  if (pxlen < 128)
+    net->prefix.addr[pxlen / 32] &= u32_mkmask(pxlen % 32);
 
   return buf;
 }
 
 static inline u32 *
-lsa_get_ipv6_addr(u32 *buf, ip_addr *addr)
+ospf_get_ipv6_addr(u32 *buf, ip_addr *addr)
 {
-  *addr = *(ip_addr *) buf;
+  *addr = ipa_from_ip6(*(ip6_addr *) buf);
   return buf + 4;
 }
 
 static inline u32 *
-put_ipv6_prefix(u32 *buf, ip_addr addr, u8 pxlen, u8 pxopts, u16 lh)
+ospf_put_ipv6_prefix(u32 *buf, net_addr *N, u8 pxopts, u16 rest)
 {
-#ifdef IPV6
-  *buf++ = ((pxlen << 24) | (pxopts << 16) | lh);
+  net_addr_ip6 *net = (void *) N;
+  u32 pxlen = net->pxlen;
+
+  *buf++ = ((pxlen << 24) | (pxopts << 16) | rest);
 
   if (pxlen > 0)
-    *buf++ = _I0(addr);
+    *buf++ = _I0(net->prefix);
   if (pxlen > 32)
-    *buf++ = _I1(addr);
+    *buf++ = _I1(net->prefix);
   if (pxlen > 64)
-    *buf++ = _I2(addr);
+    *buf++ = _I2(net->prefix);
   if (pxlen > 96)
-    *buf++ = _I3(addr);
-#endif
+    *buf++ = _I3(net->prefix);
+
   return buf;
 }
 
 static inline u32 *
-put_ipv6_addr(u32 *buf, ip_addr addr)
+ospf_put_ipv6_addr(u32 *buf, ip_addr addr)
 {
-  *(ip_addr *) buf = addr;
+  *(ip6_addr *) buf = ipa_to_ip6(addr);
   return buf + 4;
 }
 
@@ -896,7 +896,7 @@ void ospf_sh_neigh_info(struct ospf_neighbor *n);
 
 /* packet.c */
 void ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type);
-uint ospf_pkt_maxsize(struct ospf_iface *ifa);
+uint ospf_pkt_maxsize(struct ospf_proto *p, 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);
index 5af9e87571fb12693201967f8886447bb03afa32..606127f2b31c5a205171665ec07a3b916428fba7 100644 (file)
@@ -22,7 +22,7 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 
   pkt->version = ospf_get_version(p);
   pkt->type = h_type;
-  pkt->length = htons(ospf_pkt_maxsize(ifa));
+  pkt->length = htons(ospf_pkt_maxsize(p, ifa));
   pkt->routerid = htonl(p->router_id);
   pkt->areaid = htonl(ifa->oa->areaid);
   pkt->checksum = 0;
@@ -31,9 +31,9 @@ ospf_pkt_fill_hdr(struct ospf_iface *ifa, void *buf, u8 h_type)
 }
 
 uint
-ospf_pkt_maxsize(struct ospf_iface *ifa)
+ospf_pkt_maxsize(struct ospf_proto *p, struct ospf_iface *ifa)
 {
-  uint headers = SIZE_OF_IP_HEADER;
+  uint headers = ospf_is_v2(p) ? IP4_HEADER_LENGTH : IP6_HEADER_LENGTH;
 
   /* Relevant just for OSPFv2 */
   if (ifa->autype == OSPF_AUTH_CRYPT)
index cdf8012a56fcf700fbe11b34800b698fab9d2ada..aee0368a3653bdeadbc1d4f836ded5a31f12b04a 100644 (file)
@@ -21,15 +21,6 @@ static inline void reset_ri(ort *ort)
   bzero(&ort->n, sizeof(orta));
 }
 
-void
-ospf_rt_initort(struct fib_node *fn)
-{
-  ort *ri = (ort *) fn;
-  reset_ri(ri);
-  ri->old_rta = NULL;
-  ri->fn.flags = 0;
-}
-
 static inline int
 nh_is_vlink(struct mpnh *nhs)
 {
@@ -334,9 +325,9 @@ ort_merge_ext(struct ospf_proto *p, ort *o, const orta *new)
 
 
 static inline void
-ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new)
+ri_install_net(struct ospf_proto *p, net_addr *net, const orta *new)
 {
-  ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen);
+  ort *old = fib_get(&p->rtf, net);
   int cmp = orta_compare(p, new, &old->n);
 
   if (cmp > 0)
@@ -348,8 +339,8 @@ ri_install_net(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new)
 static inline void
 ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new)
 {
-  ip_addr addr = ipa_from_rid(rid);
-  ort *old = (ort *) fib_get(&oa->rtr, &addr, MAX_PREFIX_LENGTH);
+  net_addr_ip4 nrid = net_from_rid(rid);
+  ort *old = fib_get(&oa->rtr, (net_addr *) &nrid);
   int cmp = orta_compare(oa->po, new, &old->n);
 
   if (cmp > 0)
@@ -359,17 +350,19 @@ ri_install_rt(struct ospf_area *oa, u32 rid, const orta *new)
 }
 
 static inline void
-ri_install_asbr(struct ospf_proto *p, ip_addr *addr, const orta *new)
+ri_install_asbr(struct ospf_proto *p, u32 rid, const orta *new)
 {
-  ort *old = (ort *) fib_get(&p->backbone->rtr, addr, MAX_PREFIX_LENGTH);
+  net_addr_ip4 nrid = net_from_rid(rid);
+  ort *old = fib_get(&p->backbone->rtr, (net_addr *) &nrid);
+
   if (orta_compare_asbr(p, new, &old->n) > 0)
     ort_replace(old, new);
 }
 
 static inline void
-ri_install_ext(struct ospf_proto *p, ip_addr prefix, int pxlen, const orta *new)
+ri_install_ext(struct ospf_proto *p, net_addr *net, const orta *new)
 {
-  ort *old = (ort *) fib_get(&p->rtf, &prefix, pxlen);
+  ort *old = fib_get(&p->rtf, net);
   int cmp = orta_compare_ext(p, new, &old->n);
 
   if (cmp > 0)
@@ -404,7 +397,7 @@ px_pos_to_ifa(struct ospf_area *oa, int pos)
 
 
 static void
-add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_hash_entry *en, int pos)
+add_network(struct ospf_area *oa, net_addr *net, int metric, struct top_hash_entry *en, int pos)
 {
   struct ospf_proto *p = oa->po;
 
@@ -419,7 +412,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
     .nhs = en->nhs
   };
 
-  if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+  if (net->pxlen > MAX_PREFIX_LENGTH)
   {
     log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
        p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@@ -441,7 +434,7 @@ add_network(struct ospf_area *oa, ip_addr px, int pxlen, int metric, struct top_
     nf.nhs = ifa ? new_nexthop(p, IPA_NONE, ifa->iface, ifa->ecmp_weight) : NULL;
   }
 
-  ri_install_net(p, px, pxlen, &nf);
+  ri_install_net(p, net, &nf);
 }
 
 
@@ -452,8 +445,7 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr
   struct ospf_lsa_rt *rt = act->lsa_body;
   struct ospf_lsa_rt_walk rtl;
   struct top_hash_entry *tmp;
-  ip_addr prefix;
-  int pxlen, i;
+  int i;
 
   if (rt->options & OPT_RT_V)
     oa->trcap = 1;
@@ -503,9 +495,10 @@ spfa_process_rt(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_entr
        * the same result by handing them here because add_network()
        * will keep the best (not the first) found route.
        */
-      prefix = ipa_from_u32(rtl.id & rtl.data);
-      pxlen = u32_masklen(rtl.data);
-      add_network(oa, prefix, pxlen, act->dist + rtl.metric, act, i);
+      net_addr_ip4 net =
+       NET_ADDR_IP4(ip4_from_u32(rtl.id & rtl.data), u32_masklen(rtl.data));
+
+      add_network(oa, (net_addr *) &net, act->dist + rtl.metric, act, i);
       break;
 
     case LSART_NET:
@@ -527,14 +520,14 @@ spfa_process_net(struct ospf_proto *p, struct ospf_area *oa, struct top_hash_ent
 {
   struct ospf_lsa_net *ln = act->lsa_body;
   struct top_hash_entry *tmp;
-  ip_addr prefix;
-  int pxlen, i, cnt;
+  int i, cnt;
 
   if (ospf_is_v2(p))
   {
-    prefix = ipa_from_u32(act->lsa.id & ln->optx);
-    pxlen = u32_masklen(ln->optx);
-    add_network(oa, prefix, pxlen, act->dist, act, -1);
+    net_addr_ip4 net =
+      NET_ADDR_IP4(ip4_from_u32(act->lsa.id & ln->optx), u32_masklen(ln->optx));
+
+    add_network(oa, (net_addr *) &net, act->dist, act, -1);
   }
 
   cnt = lsa_net_count(&act->lsa);
@@ -550,10 +543,6 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa)
 {
   struct top_hash_entry *en, *src;
   struct ospf_lsa_prefix *px;
-  ip_addr pxa;
-  int pxlen;
-  u8 pxopts;
-  u16 metric;
   u32 *buf;
   int i;
 
@@ -588,18 +577,22 @@ spfa_process_prefixes(struct ospf_proto *p, struct ospf_area *oa)
 
     buf = px->rest;
     for (i = 0; i < px->pxcount; i++)
-      {
-       buf = lsa_get_ipv6_prefix(buf, &pxa, &pxlen, &pxopts, &metric);
+    {
+      net_addr_ip6 net;
+      u8 pxopts;
+      u16 metric;
 
-       if (pxopts & OPT_PX_NU)
-         continue;
+      buf = ospf_get_ipv6_prefix(buf, (net_addr *) &net, &pxopts, &metric);
 
-       /* Store the first global address to use it later as a vlink endpoint */
-       if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb))
-         src->lb = pxa;
+      if (pxopts & OPT_PX_NU)
+       continue;
 
-       add_network(oa, pxa, pxlen, src->dist + metric, src, i);
-      }
+      /* Store the first global address to use it later as a vlink endpoint */
+      if ((pxopts & OPT_PX_LA) && ipa_zero(src->lb))
+       src->lb = ipa_from_ip6(net.prefix);
+
+      add_network(oa, (net_addr *) &net, src->dist + metric, src, i);
+    }
   }
 }
 
@@ -742,13 +735,12 @@ ospf_rt_sum(struct ospf_area *oa)
 {
   struct ospf_proto *p = oa->po;
   struct top_hash_entry *en;
-  ip_addr ip, abrip;
+  net_addr net;
   u32 dst_rid, metric, options;
   ort *abr;
-  int pxlen = -1, type = -1;
+  int type;
   u8 pxopts;
 
-
   OSPF_TRACE(D_EVENTS, "Starting routing table calculation for inter-area (area %R)", oa->areaid);
 
   WALK_SLIST(en, p->lsal)
@@ -771,12 +763,12 @@ ospf_rt_sum(struct ospf_area *oa)
 
     if (en->lsa_type == LSA_T_SUM_NET)
     {
-      lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric);
+      lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric);
 
       if (pxopts & OPT_PX_NU)
        continue;
 
-      if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+      if (net.pxlen > MAX_PREFIX_LENGTH)
       {
        log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
            p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@@ -803,8 +795,8 @@ ospf_rt_sum(struct ospf_area *oa)
       continue;
 
     /* 16.2. (4) */
-    abrip = ipa_from_rid(en->lsa.rt);
-    abr = (ort *) fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH);
+    net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
+    abr = fib_find(&oa->rtr, (net_addr *) &nrid);
     if (!abr || !abr->n.type)
       continue;
 
@@ -828,7 +820,7 @@ ospf_rt_sum(struct ospf_area *oa)
     };
 
     if (type == ORT_NET)
-      ri_install_net(p, ip, pxlen, &nf);
+      ri_install_net(p, &net, &nf);
     else
       ri_install_rt(oa, dst_rid, &nf);
   }
@@ -842,11 +834,7 @@ ospf_rt_sum_tr(struct ospf_area *oa)
   struct ospf_area *bb = p->backbone;
   struct top_hash_entry *en;
   ort *re, *abr;
-  ip_addr ip, abrip;
-  u32 dst_rid, metric, options;
-  int pxlen;
-  u8 pxopts;
-
+  u32 metric;
 
   if (!bb)
     return;
@@ -869,26 +857,31 @@ ospf_rt_sum_tr(struct ospf_area *oa)
 
     if (en->lsa_type == LSA_T_SUM_NET)
     {
-      lsa_parse_sum_net(en, ospf_is_v2(p), &ip, &pxlen, &pxopts, &metric);
+      net_addr net;
+      u8 pxopts;
+
+      lsa_parse_sum_net(en, ospf_is_v2(p), &net, &pxopts, &metric);
 
       if (pxopts & OPT_PX_NU)
        continue;
 
-      if (pxlen < 0 || pxlen > MAX_PREFIX_LENGTH)
+      if (net.pxlen > MAX_PREFIX_LENGTH)
       {
        log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
            p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
        continue;
       }
 
-      re = fib_find(&p->rtf, &ip, pxlen);
+      re = fib_find(&p->rtf, &net);
     }
     else // en->lsa_type == LSA_T_SUM_RT
     {
+      u32 dst_rid, options;
+
       lsa_parse_sum_rt(en, ospf_is_v2(p), &dst_rid, &metric, &options);
 
-      ip = ipa_from_rid(dst_rid);
-      re = fib_find(&bb->rtr, &ip, MAX_PREFIX_LENGTH);
+      net_addr_ip4 nrid = net_from_rid(dst_rid);
+      re = fib_find(&bb->rtr, (net_addr *) &nrid);
     }
 
     /* 16.3 (1b) */
@@ -906,8 +899,8 @@ ospf_rt_sum_tr(struct ospf_area *oa)
       continue;
 
     /* 16.3. (4) */
-    abrip = ipa_from_rid(en->lsa.rt);
-    abr = fib_find(&oa->rtr, &abrip, MAX_PREFIX_LENGTH);
+    net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
+    abr = fib_find(&oa->rtr, (net_addr *) &nrid);
     if (!abr || !abr->n.type)
       continue;
 
@@ -998,7 +991,7 @@ decide_sum_lsa(struct ospf_area *oa, ort *nf, int dest)
     return 1;
 
   struct area_net *anet = (struct area_net *)
-    fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen);
+    fib_route(&nf->n.oa->net_fib, nf->fn.addr);
 
   /* Condensed area network found */
   if (anet)
@@ -1017,13 +1010,13 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf)
   if (nf->area_net)
   {
     /* It is a default route for stub areas, handled entirely in ospf_rt_abr() */
-    if (nf->fn.pxlen == 0)
+    if (nf->fn.addr->pxlen == 0)
       return;
 
     /* Find that area network */
     WALK_LIST(anet_oa, p->area_list)
     {
-      anet = (struct area_net *) fib_find(&anet_oa->net_fib, &nf->fn.prefix, nf->fn.pxlen);
+      anet = fib_find(&anet_oa->net_fib, nf->fn.addr);
       if (anet)
        break;
     }
@@ -1042,10 +1035,12 @@ check_sum_net_lsa(struct ospf_proto *p, ort *nf)
 static inline void
 check_sum_rt_lsa(struct ospf_proto *p, ort *nf)
 {
+  u32 rid = rid_from_net(nf->fn.addr);
+
   struct ospf_area *oa;
   WALK_LIST(oa, p->area_list)
     if (decide_sum_lsa(oa, nf, ORT_ROUTER))
-      ospf_originate_sum_rt_lsa(p, oa, nf, nf->n.metric1, nf->n.options);
+      ospf_originate_sum_rt_lsa(p, oa, rid, nf->n.metric1, nf->n.options);
 }
 
 static inline int
@@ -1058,7 +1053,7 @@ decide_nssa_lsa(struct ospf_proto *p, ort *nf, struct ospf_lsa_ext_local *rt)
     return 0;
 
   /* Condensed area network found */
-  if (fib_route(&oa->enet_fib, nf->fn.prefix, nf->fn.pxlen))
+  if (fib_route(&oa->enet_fib, nf->fn.addr))
     return 0;
 
   if (!en || (en->lsa_type != LSA_T_NSSA))
@@ -1093,7 +1088,7 @@ check_nssa_lsa(struct ospf_proto *p, ort *nf)
     /* Find that area network */
     WALK_LIST(oa, p->area_list)
     {
-      anet = (struct area_net *) fib_find(&oa->enet_fib, &nf->fn.prefix, nf->fn.pxlen);
+      anet = fib_find(&oa->enet_fib, nf->fn.addr);
       if (anet)
        break;
     }
@@ -1164,6 +1159,7 @@ ospf_rt_abr1(struct ospf_proto *p)
 {
   struct area_net *anet;
   ort *nf, *default_nf;
+  net_addr default_net;
 
   /* RFC 2328 G.3 - incomplete resolution of virtual next hops - routers */
   FIB_WALK(&p->backbone->rtr, nftmp)
@@ -1189,7 +1185,7 @@ ospf_rt_abr1(struct ospf_proto *p)
     /* Compute condensed area networks */
     if (nf->n.type == RTS_OSPF)
     {
-      anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.prefix, nf->fn.pxlen);
+      anet = (struct area_net *) fib_route(&nf->n.oa->net_fib, nf->fn.addr);
       if (anet)
       {
        if (!anet->active)
@@ -1197,7 +1193,7 @@ ospf_rt_abr1(struct ospf_proto *p)
          anet->active = 1;
 
          /* Get a RT entry and mark it to know that it is an area network */
-         ort *nfi = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen);
+         ort *nfi = fib_get(&p->rtf, anet->fn.addr);
          nfi->area_net = 1;
 
          /* 16.2. (3) */
@@ -1212,8 +1208,13 @@ ospf_rt_abr1(struct ospf_proto *p)
   }
   FIB_WALK_END;
 
-  ip_addr addr = IPA_NONE;
-  default_nf = (ort *) fib_get(&p->rtf, &addr, 0);
+
+  if (ospf_is_v2(p))
+    net_fill_ip4(&default_net, IP4_NONE, 0);
+  else
+    net_fill_ip6(&default_net, IP6_NONE, 0);
+
+  default_nf = fib_get(&p->rtf, &default_net);
   default_nf->area_net = 1;
 
   struct ospf_area *oa;
@@ -1244,7 +1245,7 @@ ospf_rt_abr1(struct ospf_proto *p)
       {
        nf = (ort *) nftmp;
        if (nf->n.options & ORTA_ASBR)
-         ri_install_asbr(p, &nf->fn.prefix, &nf->n);
+         ri_install_asbr(p, rid_from_net(nf->fn.addr), &nf->n);
       }
       FIB_WALK_END;
     }
@@ -1300,7 +1301,7 @@ ospf_rt_abr2(struct ospf_proto *p)
        if (!nf->n.type || !(nf->n.options & ORTA_ABR))
          continue;
 
-       nf2 = fib_find(&bb->rtr, &nf->fn.prefix, MAX_PREFIX_LENGTH);
+       nf2 = fib_find(&bb->rtr, nf->fn.addr);
        if (!nf2 || !nf2->n.type || !(nf2->n.options & ORTA_ABR))
          continue;
 
@@ -1346,7 +1347,7 @@ ospf_rt_abr2(struct ospf_proto *p)
     if (rt_is_nssa(nf) && (nf->n.options & ORTA_PROP))
     {
       struct area_net *anet = (struct area_net *)
-       fib_route(&nf->n.oa->enet_fib, nf->fn.prefix, nf->fn.pxlen);
+       fib_route(&nf->n.oa->enet_fib, nf->fn.addr);
 
       if (anet)
       {
@@ -1355,7 +1356,7 @@ ospf_rt_abr2(struct ospf_proto *p)
          anet->active = 1;
 
          /* Get a RT entry and mark it to know that it is an area network */
-         nf2 = (ort *) fib_get(&p->rtf, &anet->fn.prefix, anet->fn.pxlen);
+         nf2 = fib_get(&p->rtf, anet->fn.addr);
          nf2->area_net = 1;
        }
 
@@ -1383,22 +1384,57 @@ ospf_rt_abr2(struct ospf_proto *p)
 
 /* Like fib_route(), but ignores dummy rt entries */
 static void *
-ospf_fib_route(struct fib *f, ip_addr a, int len)
+ospf_fib_route_ip4(struct fib *f, ip4_addr a, int len)
+{
+  net_addr_ip4 net = NET_ADDR_IP4(a, len);
+  ort *nf;
+
+loop:
+  nf = fib_find(f, (net_addr *) &net);
+  if (nf && nf->n.type)
+    return nf;
+
+  if (net.pxlen > 0)
+  {
+    net.pxlen--;
+    ip4_clrbit(&net.prefix, net.pxlen);
+    goto loop;
+  }
+
+  return NULL;
+}
+
+static void *
+ospf_fib_route_ip6(struct fib *f, ip6_addr a, int len)
 {
-  ip_addr a0;
+  net_addr_ip6 net = NET_ADDR_IP6(a, len);
   ort *nf;
 
-  while (len >= 0)
+loop:
+  nf = fib_find(f, (net_addr *) &net);
+  if (nf && nf->n.type)
+    return nf;
+
+  if (net.pxlen > 0)
   {
-    a0 = ipa_and(a, ipa_mkmask(len));
-    nf = fib_find(f, &a0, len);
-    if (nf && nf->n.type)
-      return nf;
-    len--;
+    net.pxlen--;
+    ip6_clrbit(&net.prefix, net.pxlen);
+    goto loop;
   }
+
   return NULL;
 }
 
+static void *
+ospf_fib_route(struct fib *f, ip_addr a)
+{
+  if (ospf_is_v2(p))
+    return ospf_fib_route_ip4(f, ipa_to_ip4(a), IP4_MAX_PREFIX_LENGTH);
+  else
+    return ospf_fib_route_ip6(f, ipa_to_ip6(a), IP6_MAX_PREFIX_LENGTH);
+}
+
+
 /* RFC 2328 16.4. calculating external routes */
 static void
 ospf_ext_spf(struct ospf_proto *p)
@@ -1407,7 +1443,6 @@ ospf_ext_spf(struct ospf_proto *p)
   struct ospf_lsa_ext_local rt;
   ort *nf1, *nf2;
   orta nfa = {};
-  ip_addr rtid;
   u32 br_metric;
   struct ospf_area *atmp;
 
@@ -1437,7 +1472,7 @@ ospf_ext_spf(struct ospf_proto *p)
     if (rt.pxopts & OPT_PX_NU)
       continue;
 
-    if (rt.pxlen < 0 || rt.pxlen > MAX_PREFIX_LENGTH)
+    if (rt.net.pxlen > MAX_PREFIX_LENGTH)
     {
       log(L_WARN "%s: Invalid prefix in LSA (Type: %04x, Id: %R, Rt: %R)",
          p->p.name, en->lsa_type, en->lsa.id, en->lsa.rt);
@@ -1457,8 +1492,8 @@ ospf_ext_spf(struct ospf_proto *p)
     if (!atmp)
       continue;                        /* Should not happen */
 
-    rtid = ipa_from_rid(en->lsa.rt);
-    nf1 = fib_find(&atmp->rtr, &rtid, MAX_PREFIX_LENGTH);
+    net_addr_ip4 nrid = net_from_rid(en->lsa.rt);
+    nf1 = fib_find(&atmp->rtr, (net_addr *) &nrid);
 
     if (!nf1 || !nf1->n.type)
       continue;                        /* No AS boundary router found */
@@ -1468,7 +1503,7 @@ ospf_ext_spf(struct ospf_proto *p)
 
     /* 16.4. (3) NSSA - special rule for default routes */
     /* ABR should use default only if P-bit is set and summaries are active */
-    if ((en->lsa_type == LSA_T_NSSA) && ipa_zero(rt.ip) && (rt.pxlen == 0) &&
+    if ((en->lsa_type == LSA_T_NSSA) && (rt.net.pxlen == 0) &&
        (p->areano > 1) && !(rt.propagate && atmp->ac->summary))
       continue;
 
@@ -1480,7 +1515,7 @@ ospf_ext_spf(struct ospf_proto *p)
     }
     else
     {
-      nf2 = ospf_fib_route(&p->rtf, rt.fwaddr, MAX_PREFIX_LENGTH);
+      nf2 = ospf_fib_route(&p->rtf, rt.fwaddr);
       if (!nf2)
        continue;
 
@@ -1542,7 +1577,7 @@ ospf_ext_spf(struct ospf_proto *p)
     nfa.oa = atmp; /* undefined in RFC 2328 */
     nfa.en = en; /* store LSA for later (NSSA processing) */
 
-    ri_install_ext(p, rt.ip, rt.pxlen, &nfa);
+    ri_install_ext(p, &rt.net, &nfa);
   }
 }
 
@@ -1961,7 +1996,7 @@ again1:
 
       if (reload || ort_changed(nf, &a0))
       {
-       net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen);
+       net *ne = net_get(p->p.table, nf->fn.addr);
        rta *a = rta_lookup(&a0);
        rte *e = rte_get_temp(a);
 
@@ -1975,8 +2010,8 @@ again1:
        e->net = ne;
        e->pref = p->p.preference;
 
-       DBG("Mod rte type %d - %I/%d via %I on iface %s, met %d\n",
-           a0.source, nf->fn.prefix, nf->fn.pxlen, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
+       DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
+           a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
        rte_update(&p->p, ne, e);
       }
     }
@@ -1986,7 +2021,7 @@ again1:
       rta_free(nf->old_rta);
       nf->old_rta = NULL;
 
-      net *ne = net_get(p->p.table, nf->fn.prefix, nf->fn.pxlen);
+      net *ne = net_get(p->p.table, nf->fn.addr);
       rte_update(&p->p, ne, NULL);
     }
 
index 30332f3b4f9ca05cb39d7babd50d2949e4b8d589..80243c9a0054853c3f8ddc13a474ad7275a080c9 100644 (file)
@@ -78,12 +78,13 @@ typedef struct ort
    * route was not in the last update, in that case other old_* values are not
    * valid.
    */
-  struct fib_node fn;
   orta n;
   u32 old_metric1, old_metric2, old_tag, old_rid;
   rta *old_rta;
   u8 external_rte;
   u8 area_net;
+
+  struct fib_node fn;
 }
 ort;
 
index 8119cfa6db49d51a9b76fee580a13c85d5d7f597..4783277102ac181aba758339a92693527c84f6ff 100644 (file)
@@ -283,8 +283,8 @@ ospf_originate_lsa(struct ospf_proto *p, struct ospf_new_lsa *lsa)
 
   if (en->nf != lsa->nf)
   {
-    log(L_ERR "%s: LSA ID collision for %I/%d",
-       p->p.name, lsa->nf->fn.prefix, lsa->nf->fn.pxlen);
+    log(L_ERR "%s: LSA ID collision for %N",
+       p->p.name, lsa->nf->fn.addr);
 
     en = NULL;
     goto drop;
@@ -520,8 +520,8 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
   /*
    * 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.
+   * prefix has to be mapped on itself.  All received prefixes have to be mapped
+   * on different u32s.
    *
    * We have an assumption that if there is nontrivial (non-/32) network prefix,
    * then there is not /32 prefix for the first and the last IP address of the
@@ -551,8 +551,9 @@ ort_to_lsaid(struct ospf_proto *p, ort *nf)
   if (ospf_is_v3(p))
     return nf->fn.uid;
 
-  u32 id = ipa_to_u32(nf->fn.prefix);
-  int pxlen = nf->fn.pxlen;
+  net_addr_ip4 *net = (void *) nf->fn.addr;
+  u32 id = ip4_to_u32(net->prefix);
+  int pxlen = net->pxlen;
 
   if ((pxlen == 0) || (pxlen == 32))
     return id;
@@ -999,9 +1000,10 @@ prepare_sum3_net_lsa_body(struct ospf_proto *p, ort *nf, u32 metric)
 {
   struct ospf_lsa_sum3_net *sum;
 
-  sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) + IPV6_PREFIX_SPACE(nf->fn.pxlen));
+  sum = lsab_allocz(p, sizeof(struct ospf_lsa_sum3_net) +
+                   IPV6_PREFIX_SPACE(nf->fn.addr->pxlen));
   sum->metric = metric;
-  put_ipv6_prefix(sum->prefix, nf->fn.prefix, nf->fn.pxlen, 0, 0);
+  ospf_put_ipv6_prefix(sum->prefix, nf->fn.addr, 0, 0);
 }
 
 static inline void
@@ -1028,7 +1030,7 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf,
   };
 
   if (ospf_is_v2(p))
-    prepare_sum2_lsa_body(p, nf->fn.pxlen, metric);
+    prepare_sum2_lsa_body(p, nf->fn.addr->pxlen, metric);
   else
     prepare_sum3_net_lsa_body(p, nf, metric);
 
@@ -1036,20 +1038,20 @@ ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf,
 }
 
 void
-ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options)
+ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options)
 {
   struct ospf_new_lsa lsa = {
     .type = LSA_T_SUM_RT,
     .mode = LSA_M_RTCALC,
     .dom  = oa->areaid,
-    .id   = ipa_to_rid(nf->fn.prefix), /* Router ID of ASBR, irrelevant for OSPFv3 */
+    .id   = drid,      /* Router ID of ASBR, irrelevant for OSPFv3 */
     .opts = oa->options
   };
 
   if (ospf_is_v2(p))
     prepare_sum2_lsa_body(p, 0, metric);
   else
-    prepare_sum3_rt_lsa_body(p, lsa.id, metric, options & LSA_OPTIONS_MASK);
+    prepare_sum3_rt_lsa_body(p, drid, metric, options & LSA_OPTIONS_MASK);
 
   ospf_originate_lsa(p, &lsa);
 }
@@ -1082,7 +1084,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
 {
   struct ospf_lsa_ext3 *ext;
   int bsize = sizeof(struct ospf_lsa_ext3)
-    + IPV6_PREFIX_SPACE(nf->fn.pxlen)
+    + IPV6_PREFIX_SPACE(nf->fn.addr->pxlen)
     + (ipa_nonzero(fwaddr) ? 16 : 0)
     + (tag ? 4 : 0);
 
@@ -1090,7 +1092,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
   ext->metric = metric & LSA_METRIC_MASK;
   u32 *buf = ext->rest;
 
-  buf = put_ipv6_prefix(buf, nf->fn.prefix, nf->fn.pxlen, pbit ? OPT_PX_P : 0, 0);
+  buf = ospf_put_ipv6_prefix(buf, nf->fn.addr, pbit ? OPT_PX_P : 0, 0);
 
   if (ebit)
     ext->metric |= LSA_EXT3_EBIT;
@@ -1098,7 +1100,7 @@ prepare_ext3_lsa_body(struct ospf_proto *p, ort *nf,
   if (ipa_nonzero(fwaddr))
   {
     ext->metric |= LSA_EXT3_FBIT;
-    buf = put_ipv6_addr(buf, fwaddr);
+    buf = ospf_put_ipv6_addr(buf, fwaddr);
   }
 
   if (tag)
@@ -1140,7 +1142,7 @@ ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 m
   };
 
   if (ospf_is_v2(p))
-    prepare_ext2_lsa_body(p, nf->fn.pxlen, metric, ebit, fwaddr, tag);
+    prepare_ext2_lsa_body(p, nf->fn.addr->pxlen, metric, ebit, fwaddr, tag);
   else
     prepare_ext3_lsa_body(p, nf, metric, ebit, fwaddr, tag, oa && pbit);
 
@@ -1253,7 +1255,7 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
 
   if (!new)
   {
-    nf = (ort *) fib_find(&p->rtf, &n->n.prefix, n->n.pxlen);
+    nf = fib_find(&p->rtf, n->n.addr);
 
     if (!nf || !nf->external_rte)
       return;
@@ -1290,13 +1292,13 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
 
     if (ipa_zero(fwd))
     {
-      log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %I/%d",
-         p->p.name, n->n.prefix, n->n.pxlen);
+      log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
+         p->p.name, n->n.addr);
       return;
     }
   }
 
-  nf = (ort *) fib_get(&p->rtf, &n->n.prefix, n->n.pxlen);
+  nf = fib_get(&p->rtf, n->n.addr);
   ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1);
   nf->external_rte = 1;
 }
@@ -1308,11 +1310,12 @@ ospf_rt_notify(struct proto *P, rtable *tbl UNUSED, net *n, rte *new, rte *old U
  */
 
 static inline void
-lsab_put_prefix(struct ospf_proto *p, ip_addr prefix, u32 pxlen, u32 cost)
+lsab_put_prefix(struct ospf_proto *p, ip6_addr prefix, u32 pxlen, u32 cost)
 {
+  net_addr_ip6 net = NET_ADDR_IP6(prefix, pxlen);
   void *buf = lsab_alloc(p, IPV6_PREFIX_SPACE(pxlen));
-  u8 flags = (pxlen < MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
-  put_ipv6_prefix(buf, prefix, pxlen, flags, cost);
+  u8 flags = (pxlen < IP6_MAX_PREFIX_LENGTH) ? 0 : OPT_PX_LA;
+  ospf_put_ipv6_prefix(buf, (net_addr *) &net, flags, cost);
 }
 
 static void
@@ -1406,7 +1409,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
          (a->scope <= SCOPE_LINK))
        continue;
 
-      if (((a->pxlen < MAX_PREFIX_LENGTH) && net_lsa) ||
+      if (((a->pxlen < IP6_MAX_PREFIX_LENGTH) && net_lsa) ||
          configured_stubnet(oa, a))
        continue;
 
@@ -1414,7 +1417,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
          (ifa->state == OSPF_IS_LOOP) ||
          (ifa->type == OSPF_IT_PTMP))
       {
-       lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0);
+       lsab_put_prefix(p, a->ip, IP6_MAX_PREFIX_LENGTH, 0);
        host_addr = 1;
       }
       else
@@ -1430,7 +1433,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
     if (!sn->hidden)
     {
       lsab_put_prefix(p, sn->px.addr, sn->px.len, sn->cost);
-      if (sn->px.len == MAX_PREFIX_LENGTH)
+      if (sn->px.len == IP6_MAX_PREFIX_LENGTH)
        host_addr = 1;
       i++;
     }
@@ -1451,7 +1454,7 @@ prepare_prefix_rt_lsa_body(struct ospf_proto *p, struct ospf_area *oa)
          continue;
 
        /* Found some IP */
-       lsab_put_prefix(p, a->ip, MAX_PREFIX_LENGTH, 0);
+       lsab_put_prefix(p, a->ip, IP6_MAX_PREFIX_LENGTH, 0);
        i++;
        goto done;
       }
index 5652ced0e2243697f48d87e71dd0ad692a7b8cca..1dbee070b81939801ab6941d92e2be07ce790af5 100644 (file)
@@ -185,7 +185,7 @@ static inline void ospf_flush2_lsa(struct ospf_proto *p, struct top_hash_entry *
 { if (*en) { ospf_flush_lsa(p, *en); *en = NULL; } }
 
 void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric);
-void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, int metric, u32 options);
+void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options);
 void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit);
 
 void ospf_rt_notify(struct proto *P, rtable *tbl, net *n, rte *new, rte *old, ea_list *attrs);
index 6ef803222329d82854d37777609891e70eaa4bcb..422858808662a588a5e894ccc5f43957cb885fa7 100644 (file)
@@ -60,12 +60,12 @@ pipe_rt_notify(struct proto *P, rtable *src_table, net *n, rte *new, rte *old, e
 
   if (dst_table->pipe_busy)
     {
-      log(L_ERR "Pipe loop detected when sending %I/%d to table %s",
-         n->n.prefix, n->n.pxlen, dst_table->name);
+      log(L_ERR "Pipe loop detected when sending %N to table %s",
+         n->n.addr, dst_table->name);
       return;
     }
 
-  nn = net_get(dst_table, n->n.prefix, n->n.pxlen);
+  nn = net_get(dst_table, n->n.addr);
   if (new)
     {
       memcpy(&a, new->attrs, sizeof(rta));
index 6370e006f29f20bc5178a8a86f636b462e37b966..2de8999123fc2e85a9490c422bfd756e8e8be2f3 100644 (file)
@@ -258,9 +258,7 @@ radv_ifa_notify(struct proto *p, unsigned flags, struct ifa *a)
 
 static inline int radv_net_match_trigger(struct radv_config *cf, net *n)
 {
-  return cf->trigger_valid &&
-    (n->n.pxlen == cf->trigger_pxlen) &&
-    ipa_equal(n->n.prefix, cf->trigger_prefix);
+  return cf->trigger_valid && net_equal(n->n.addr, cf->trigger);
 }
 
 int
@@ -306,8 +304,7 @@ radv_check_active(struct proto_radv *ra)
   if (! cf->trigger_valid)
     return 1;
 
-  return rt_examine(ra->p.table, cf->trigger_prefix, cf->trigger_pxlen,
-                   &(ra->p), ra->p.cf->out_filter);
+  return rt_examine(ra->p.table, cf->trigger, &ra->p, ra->p.cf->out_filter);
 }
 
 static struct proto *
index 48ba9c1a308df119b3953fd9a745faa5c85dd4ec..aede6a671c7f2ac9083aae05bc6ac2b7e57ef877 100644 (file)
@@ -50,8 +50,7 @@ struct radv_config
   list rdnss_list;             /* Global list of RDNSS configs (struct radv_rdnss_config) */
   list dnssl_list;             /* Global list of DNSSL configs (struct radv_dnssl_config) */
 
-  ip_addr trigger_prefix;      /* Prefix of a trigger route, if defined */
-  u8 trigger_pxlen;            /* Pxlen of a trigger route, if defined */
+  net_addr *trigger;           /* Prefix of a trigger route, if defined */
   u8 trigger_valid;            /* Whether a trigger route is defined */
 };
 
index be20734fc00f22b36bf065a28a688901ff7cff3b..e2a2390b5e52b46ca67d9b95733eba3ffb30c360 100644 (file)
@@ -78,8 +78,7 @@ struct rip_auth_tail
 /* Internal representation of RTE block data */
 struct rip_block
 {
-  ip_addr prefix;
-  int pxlen;
+  net_addr net;
   u32 metric;
   u16 tag;
   u16 no_af;
@@ -115,17 +114,17 @@ rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
     struct rip_block_v2 *block = (void *) pos;
     block->family = rte->no_af ? 0 : htons(RIP_AF_IPV4);
     block->tag = htons(rte->tag);
-    block->network = ip4_hton(ipa_to_ip4(rte->prefix));
-    block->netmask = ip4_hton(ip4_mkmask(rte->pxlen));
+    block->network = ip4_hton(net4_prefix(&rte->net));
+    block->netmask = ip4_hton(ip4_mkmask(net4_pxlen(&rte->net)));
     block->next_hop = ip4_hton(ipa_to_ip4(rte->next_hop));
     block->metric = htonl(rte->metric);
   }
   else /* RIPng */
   {
     struct rip_block_ng *block = (void *) pos;
-    block->prefix = ip6_hton(ipa_to_ip6(rte->prefix));
+    block->prefix = ip6_hton(net6_prefix(&rte->net));
     block->tag = htons(rte->tag);
-    block->pxlen = rte->pxlen;
+    block->pxlen = net6_pxlen(&rte->net);
     block->metric = rte->metric;
   }
 }
@@ -151,8 +150,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
     if (block->family != (rte->no_af ? 0 : htons(RIP_AF_IPV4)))
       return 0;
 
-    rte->prefix = ipa_from_ip4(ip4_ntoh(block->network));
-    rte->pxlen = ip4_masklen(ip4_ntoh(block->netmask));
+    uint pxlen = ip4_masklen(ip4_ntoh(block->netmask));
+    net_fill_ip4(&rte->net, ip4_ntoh(block->network), pxlen);
     rte->metric = ntohl(block->metric);
     rte->tag = ntohs(block->tag);
     rte->next_hop = ipa_from_ip4(ip4_ntoh(block->next_hop));
@@ -171,8 +170,8 @@ rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
       return 0;
     }
 
-    rte->prefix = ipa_from_ip6(ip6_ntoh(block->prefix));
-    rte->pxlen = block->pxlen;
+    uint pxlen = (block->pxlen < IP6_MAX_PREFIX_LENGTH) ? block->pxlen : 255;
+    net_fill_ip6(&rte->net, ip6_ntoh(block->prefix), pxlen);
     rte->metric = block->metric;
     rte->tag = ntohs(block->tag);
     /* rte->next_hop is deliberately kept unmodified */;
@@ -385,8 +384,9 @@ rip_receive_request(struct rip_proto *p, struct rip_iface *ifa, struct rip_packe
   if (!rip_get_block(p, pos, &b))
     return;
 
-  /* Special case - zero prefix, infinity metric */
-  if (ipa_nonzero(b.prefix) || b.pxlen || (b.metric != p->infinity))
+  /* Special case - infinity metric, for RIPng also zero prefix */
+  if ((b.metric != p->infinity) ||
+      (rip_is_ng(p) && !net_zero_ip6((net_addr_ip6 *) &b.net)))
     return;
 
   /* We do nothing if TX is already active */
@@ -444,23 +444,23 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
     }
 
     struct rip_block rte = {
-      .prefix = en->n.prefix,
-      .pxlen = en->n.pxlen,
       .metric = en->metric,
       .tag = en->tag
     };
 
+    net_copy(&rte.net, en->n.addr);
+
     if (en->iface == ifa->iface)
       rte.next_hop = en->next_hop;
 
     if (rip_is_v2(p) && (ifa->cf->version == RIP_V1))
     {
       /* Skipping subnets (i.e. not hosts, classful networks or default route) */
-      if (ip4_masklen(ip4_class_mask(ipa_to_ip4(en->n.prefix))) != en->n.pxlen)
+      if (ip4_masklen(ip4_class_mask(net4_prefix(&rte.net))) != rte.net.pxlen)
        goto next_entry;
 
       rte.tag = 0;
-      rte.pxlen = 0;
+      rte.net.pxlen = 0;
       rte.next_hop = IPA_NONE;
     }
 
@@ -476,7 +476,7 @@ rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
        goto next_entry;
     }
 
-    // TRACE(D_PACKETS, "    %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric);
+    // TRACE(D_PACKETS, "    %N -> %I metric %d", &rte.net, rte.next_hop, rte.metric);
 
     /* RIPng next hop entry */
     if (rip_is_ng(p) && !ipa_equal(rte.next_hop, last_next_hop))
@@ -577,23 +577,25 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
     if (!rip_get_block(p, pos, &rte))
       continue;
 
-    int c = ipa_classify_net(rte.prefix);
-    if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
-      SKIP("invalid prefix");
-
     if (rip_is_v2(p) && (pkt->version == RIP_V1))
     {
-      if (ifa->cf->check_zero && (rte.tag || rte.pxlen || ipa_nonzero(rte.next_hop)))
+      if (ifa->cf->check_zero && (rte.tag || rte.net.pxlen || ipa_nonzero(rte.next_hop)))
        SKIP("RIPv1 reserved field is nonzero");
 
       rte.tag = 0;
-      rte.pxlen = ip4_masklen(ip4_class_mask(ipa_to_ip4(rte.prefix)));
+      rte.net.pxlen = ip4_masklen(ip4_class_mask(net4_prefix(&rte.net)));
       rte.next_hop = IPA_NONE;
     }
 
-    if ((rte.pxlen < 0) || (rte.pxlen > MAX_PREFIX_LENGTH))
+    if (rte.net.pxlen == 255)
       SKIP("invalid prefix length");
 
+    net_normalize(&rte.net);
+
+    int c = net_classify(&rte.net);
+    if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
+      SKIP("invalid prefix");
+
     if (rte.metric > p->infinity)
       SKIP("invalid metric");
 
@@ -604,7 +606,7 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
        rte.next_hop = IPA_NONE;
     }
 
-    // TRACE(D_PACKETS, "    %I/%d -> %I metric %d", rte.prefix, rte.pxlen, rte.next_hop, rte.metric);
+    // TRACE(D_PACKETS, "    %N -> %I metric %d", &rte.net.n, rte.next_hop, rte.metric);
 
     rte.metric += ifa->cf->metric;
 
@@ -618,16 +620,16 @@ rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_pack
        .expires = now + ifa->cf->timeout_time
       };
 
-      rip_update_rte(p, &rte.prefix, rte.pxlen, &new);
+      rip_update_rte(p, &rte.net, &new);
     }
     else
-      rip_withdraw_rte(p, &rte.prefix, rte.pxlen, from);
+      rip_withdraw_rte(p, &rte.net, from);
 
     continue;
 
   skip:
-    LOG_RTE("Ignoring route %I/%d received from %I - %s",
-           rte.prefix, rte.pxlen, from->nbr->addr, err_dsc);
+    LOG_RTE("Ignoring route %N received from %I - %s",
+           &rte.net, from->nbr->addr, err_dsc);
   }
 }
 
index c85fd69b92f421e3f813eec04cb1ad09c0ac09c1..d8c3b6a843e8256ba260d87ff89e251418d26b15 100644 (file)
@@ -92,15 +92,6 @@ static void rip_trigger_update(struct rip_proto *p);
  *     RIP routes
  */
 
-static void
-rip_init_entry(struct fib_node *fn)
-{
-  // struct rip_entry *en = (void) *fn;
-
-  const uint offset = OFFSETOF(struct rip_entry, routes);
-  memset((byte *)fn + offset, 0, sizeof(struct rip_entry) - offset);
-}
-
 static struct rip_rte *
 rip_add_rte(struct rip_proto *p, struct rip_rte **rp, struct rip_rte *src)
 {
@@ -152,7 +143,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
   if (rt)
   {
     /* Update */
-    net *n = net_get(p->p.table, en->n.prefix, en->n.pxlen);
+    net *n = net_get(p->p.table, en->n.addr);
 
     rta a0 = {
       .src = p->p.main_source,
@@ -221,7 +212,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
   else
   {
     /* Withdraw */
-    net *n = net_find(p->p.table, en->n.prefix, en->n.pxlen);
+    net *n = net_find(p->p.table, en->n.addr);
     rte_update(&p->p, n, NULL);
   }
 }
@@ -229,8 +220,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
 /**
  * rip_update_rte - enter a route update to RIP routing table
  * @p: RIP instance
- * @prefix: network prefix
- * @pxlen: network prefix length
+ * @addr: network address
  * @new: a &rip_rte representing the new route
  *
  * The function is called by the RIP packet processing code whenever it receives
@@ -240,9 +230,9 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
  * rip_withdraw_rte() should be called instead of rip_update_rte().
  */
 void
-rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new)
+rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new)
 {
-  struct rip_entry *en = fib_get(&p->rtable, prefix, pxlen);
+  struct rip_entry *en = fib_get(&p->rtable, n);
   struct rip_rte *rt, **rp;
   int changed = 0;
 
@@ -282,8 +272,7 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
 /**
  * rip_withdraw_rte - enter a route withdraw to RIP routing table
  * @p: RIP instance
- * @prefix: network prefix
- * @pxlen: network prefix length
+ * @addr: network address
  * @from: a &rip_neighbor propagating the withdraw
  *
  * The function is called by the RIP packet processing code whenever it receives
@@ -291,9 +280,9 @@ rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *
  * removed. Eventually, the change is also propagated by rip_announce_rte().
  */
 void
-rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from)
+rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
 {
-  struct rip_entry *en = fib_find(&p->rtable, prefix, pxlen);
+  struct rip_entry *en = fib_find(&p->rtable, n);
   struct rip_rte *rt, **rp;
 
   if (!en)
@@ -335,15 +324,15 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
 
     if (rt_metric > p->infinity)
     {
-      log(L_WARN "%s: Invalid rip_metric value %u for route %I/%d",
-         p->p.name, rt_metric, net->n.prefix, net->n.pxlen);
+      log(L_WARN "%s: Invalid rip_metric value %u for route %N",
+         p->p.name, rt_metric, net->n.addr);
       rt_metric = p->infinity;
     }
 
     if (rt_tag > 0xffff)
     {
-      log(L_WARN "%s: Invalid rip_tag value %u for route %I/%d",
-         p->p.name, rt_tag, net->n.prefix, net->n.pxlen);
+      log(L_WARN "%s: Invalid rip_tag value %u for route %N",
+         p->p.name, rt_tag, net->n.addr);
       rt_metric = p->infinity;
       rt_tag = 0;
     }
@@ -355,7 +344,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
      * collection.
      */
 
-    en = fib_get(&p->rtable, &net->n.prefix, net->n.pxlen);
+    en = fib_get(&p->rtable, net->n.addr);
 
     old_metric = en->valid ? en->metric : -1;
 
@@ -369,7 +358,7 @@ rip_rt_notify(struct proto *P, struct rtable *table UNUSED, struct network *net,
   else
   {
     /* Withdraw */
-    en = fib_find(&p->rtable, &net->n.prefix, net->n.pxlen);
+    en = fib_find(&p->rtable, net->n.addr);
 
     if (!en || en->valid != RIP_ENTRY_VALID)
       return;
@@ -875,7 +864,7 @@ rip_timer(timer *t)
 
       if (expires <= now)
       {
-       // TRACE(D_EVENTS, "entry is too old: %I/%d", en->n.prefix, en->n.pxlen);
+       // TRACE(D_EVENTS, "entry is too old: %N", en->n.addr);
        en->valid = 0;
       }
       else
@@ -1108,7 +1097,8 @@ rip_start(struct proto *P)
   struct rip_config *cf = (void *) (P->cf);
 
   init_list(&p->iface_list);
-  fib_init(&p->rtable, P->pool, sizeof(struct rip_entry), 0, rip_init_entry);
+  fib_init(&p->rtable, P->pool, rip_is_v2(p) ? NET_IP4 : NET_IP6,
+          sizeof(struct rip_entry), OFFSETOF(struct rip_entry, n), 0, NULL);
   p->rte_slab = sl_new(P->pool, sizeof(struct rip_rte));
   p->timer = tm_new_set(P->pool, rip_timer, p, 0, 0);
 
@@ -1257,8 +1247,8 @@ rip_dump(struct proto *P)
   FIB_WALK(&p->rtable, e)
   {
     struct rip_entry *en = (struct rip_entry *) e;
-    debug("RIP: entry #%d: %I/%d via %I dev %s valid %d metric %d age %d s\n",
-         i++, en->n.prefix, en->n.pxlen, en->next_hop, en->iface->name,
+    debug("RIP: entry #%d: %N via %I dev %s valid %d metric %d age %d s\n",
+         i++, en->n.addr, en->next_hop, en->iface->name,
          en->valid, en->metric, now - en->changed);
   }
   FIB_WALK_END;
index f245e61260d4792c9e16e662ee8bf4fd3bba4d59..97c5ab3f3267442701c7162892936b33f401060e 100644 (file)
@@ -149,7 +149,6 @@ struct rip_neighbor
 
 struct rip_entry
 {
-  struct fib_node n;
   struct rip_rte *routes;              /* List of incoming routes */
 
   u8 valid;                            /* Entry validity state (RIP_ENTRY_*) */
@@ -160,6 +159,8 @@ struct rip_entry
   ip_addr next_hop;                    /* Outgoing route next hop */
 
   bird_clock_t changed;                        /* Last time when the outgoing route metric changed */
+
+  struct fib_node n;
 };
 
 struct rip_rte
@@ -211,8 +212,8 @@ rip_reset_tx_session(struct rip_proto *p, struct rip_iface *ifa)
 }
 
 /* rip.c */
-void rip_update_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_rte *new);
-void rip_withdraw_rte(struct rip_proto *p, ip_addr *prefix, int pxlen, struct rip_neighbor *from);
+void rip_update_rte(struct rip_proto *p, net_addr *n, struct rip_rte *new);
+void rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from);
 struct rip_neighbor * rip_get_neighbor(struct rip_proto *p, ip_addr *a, struct rip_iface *ifa);
 void rip_update_bfd(struct rip_proto *p, struct rip_neighbor *n);
 void rip_show_interfaces(struct proto *P, char *iff);
index be808593c622a5581527cb48c54bdd58096b3102..a11a9b6eddfb0dff0759b8c771323e76c1284c39 100644 (file)
@@ -112,7 +112,7 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
 
   /* We skip rta_lookup() here */
 
-  n = net_get(p->table, r->net, r->masklen);
+  n = net_get_ipa(p->table, r->net, r->masklen);
   e = rte_get_temp(&a);
   e->net = n;
   e->pflags = 0;
@@ -136,7 +136,7 @@ static_remove(struct proto *p, struct static_route *r)
     return;
 
   DBG("Removing static route %I/%d via %I\n", r->net, r->masklen, r->via);
-  n = net_find(p->table, r->net, r->masklen);
+  n = net_find_ipa(p->table, r->net, r->masklen);
   rte_update(p, n, NULL);
   r->installed = 0;
 }
index 674d338b0221fb8c76572cf7c7809fc6760e7bde..6d99b0e8af7cb8701ed255826b0b2a8fa324163f 100644 (file)
@@ -911,8 +911,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
          ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
          if (!ra.nexthops)
            {
-             log(L_ERR "KRT: Received strange multipath route %I/%d",
-                 net->n.prefix, net->n.pxlen);
+             log(L_ERR "KRT: Received strange multipath route %N", net->n.addr);
              return;
            }
 
@@ -922,8 +921,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
       ra.iface = if_find_by_index(oif);
       if (!ra.iface)
        {
-         log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
-             net->n.prefix, net->n.pxlen, oif);
+         log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif);
          return;
        }
 
@@ -944,8 +942,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
                           (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
          if (!ng || (ng->scope == SCOPE_HOST))
            {
-             log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
-                 net->n.prefix, net->n.pxlen, ra.gw);
+             log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr, ra.gw);
              return;
            }
        }
@@ -1020,8 +1017,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
 
       if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
         {
-         log(L_ERR "KRT: Received route %I/%d with strange RTA_METRICS attribute",
-             net->n.prefix, net->n.pxlen);
+         log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
          return;
        }
 
index 2eab5cb2e46c260fdae6eb63a9acbea2fc959015..5db682ca96aa301230b30b52109e93199e4e0257 100644 (file)
@@ -297,14 +297,14 @@ static inline void
 krt_trace_in(struct krt_proto *p, rte *e, char *msg)
 {
   if (p->p.debug & D_PACKETS)
-    log(L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
+    log(L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
 }
 
 static inline void
 krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
 {
   if (p->p.debug & D_PACKETS)
-    log_rl(f, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
+    log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
 }
 
 /*
@@ -347,7 +347,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
   net *n = e->net;
   rta *aa = rta_clone(e->attrs);
   rte *ee = rte_get_temp(aa);
-  net *nn = net_get(p->p.table, n->n.prefix, n->n.pxlen);
+  net *nn = net_get(p->p.table, n->n.addr);
   ee->net = nn;
   ee->pflags = 0;
   ee->pref = p->p.preference;
@@ -358,7 +358,7 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
 static void
 krt_learn_announce_delete(struct krt_proto *p, net *n)
 {
-  n = net_find(p->p.table, n->n.prefix, n->n.pxlen);
+  n = net_find(p->p.table, n->n.addr);
   rte_update(&p->p, n, NULL);
 }
 
@@ -367,7 +367,7 @@ static void
 krt_learn_scan(struct krt_proto *p, rte *e)
 {
   net *n0 = e->net;
-  net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
+  net *n = net_get(&p->krt_table, n0->n.addr);
   rte *m, **mm;
 
   e->attrs = rta_lookup(e->attrs);
@@ -469,7 +469,7 @@ static void
 krt_learn_async(struct krt_proto *p, rte *e, int new)
 {
   net *n0 = e->net;
-  net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
+  net *n = net_get(&p->krt_table, n0->n.addr);
   rte *g, **gg, *best, **bestp, *old_best;
 
   e->attrs = rta_lookup(e->attrs);