]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Temporary integrated commit (RIP).
authorOndrej Zajicek <santiago@crfreenet.org>
Mon, 25 Jun 2012 00:56:09 +0000 (02:56 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Mon, 25 Jun 2012 00:56:09 +0000 (02:56 +0200)
conf/confbase.Y
lib/ip.c
lib/ip.h
nest/proto.c
nest/protocol.h
nest/rt-table.c
proto/rip/auth.c
proto/rip/config.Y
proto/rip/rip.c
proto/rip/rip.h
proto/static/static.c

index 088c1e4f4ca19b79b650dc791af8e82e5ead201f..bcee76d54572ead91e2a589dde09cf335aa67480 100644 (file)
@@ -162,6 +162,8 @@ ipa_scope:
 
 prefix:
    ipa pxlen {
+     if (ipa_is_ip4($1))
+       $2 += 96;       // XXXX make it better
      if (!ip_is_prefix($1, $2)) cf_error("Invalid prefix");
      $$.addr = $1; $$.len = $2;
    }
index 95a01f915509f2efb841b820e9a019fcc3d11ffa..e4cb8d4d30ccb1ffc32420b14130e0b56b9b13d6 100644 (file)
--- a/lib/ip.c
+++ b/lib/ip.c
@@ -349,6 +349,24 @@ ip_scope_text(unsigned scope)
     return scope_table[scope];
 }
 
+ip4_addr
+ip4_class_mask(ip4_addr ad)
+{
+  u32 m, a = _I(ad);
+  
+  if (a < 0x80000000)
+    m = 0xff000000;
+  else if (a < 0xc0000000)
+    m = 0xffff0000;
+  else
+    m = 0xffffff00;
+  if (a & ~m)
+    m = 0xffffffff;
+
+  return _MI4(m);
+}
+
+
 #include "nest/route.h"
 
 void
@@ -484,8 +502,8 @@ void ipa_ntoh(ip_addr x) { DUMMY }
 int ipa_classify(ip_addr x) { DUMMY }
 
 /**
- * ipa_class_mask - guess netmask according to address class
- * @x: IP address
+ * ip4_class_mask - guess netmask according to address class
+ * @x: IPv4 address
  *
  * This function (available in IPv4 version only) returns a
  * network mask according to the address class of @x. Although
@@ -493,7 +511,7 @@ int ipa_classify(ip_addr x) { DUMMY }
  * routing protocols transferring no prefix lengths nor netmasks
  * and this function could be useful to them.
  */
-ip_addr ipa_class_mask(ip_addr x) { DUMMY }
+ip_addr ip4_class_mask(ip_addr x) { DUMMY }
 
 /**
  * ipa_from_u32 - convert IPv4 address to an integer
index 6ddd16208fe9c327b6af121eb6a2f049a1e880a2..b62937ef43868433a6380858acdc9ab5c623c5c1 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -338,7 +338,7 @@ int ip6_pton(char *a, ip6_addr *o);
 
 
 
-
+ip4_addr ip4_class_mask(ip4_addr a);
 
 
 
@@ -401,7 +401,7 @@ static inline int ipa_classify_net(ip_addr a)
 #define IP_PREC_INTERNET_CONTROL 0xc0
 */
 
-u32 ipv4_class_mask(u32);
+
 byte *ipv4_skip_header(byte *, int *);
 
 struct fib_node;
index 887d3e5e97962a8010f6d5eba2484911331283a6..80e2292de526de64e856e469409cb9d8c65744fc 100644 (file)
@@ -692,6 +692,7 @@ protos_build(void)
 #endif
 #ifdef CONFIG_RIP
   proto_build(&proto_rip);
+  proto_build(&proto_ripng);
 #endif
 #ifdef CONFIG_STATIC
   proto_build(&proto_static);
index 8bbcf8d390a286f9009111bd1d9208d11fdbc948..a37fa1293c696adcc754785eb3ba8f45be2154ad 100644 (file)
@@ -75,7 +75,7 @@ void protos_dump_all(void);
  */
 
 extern struct protocol
-  proto_device, proto_radv, proto_rip, proto_static,
+  proto_device, proto_radv, proto_rip, proto_ripng, proto_static,
   proto_ospf, proto_pipe, proto_bgp;
 
 /*
index 03238afc480cd28316e41b865f46b687c491ce23..1c17146e00e2bce11d0d976fef1ff5d3add165da 100644 (file)
@@ -517,7 +517,8 @@ rte_recalculate(struct announce_hook *ah, net *net, rte *new, ea_list *tmpa, str
 #ifdef CONFIG_RIP
              /* lastmod is used internally by RIP as the last time
                 when the route was received. */
-             if (src->proto == &proto_rip)
+             if ((src->proto == &proto_rip) ||
+                 (src->proto == &proto_ripng))
                old->lastmod = now;
 #endif
              return;
index b7b0611ee887de8c7a183d33c183af51a1930183..b9ce75e61b33d0b238486e06f937dc93cdcfe7f5 100644 (file)
@@ -30,7 +30,7 @@
 #define PACKETLEN(num) (num * sizeof(struct rip_block) + sizeof(struct rip_packet_heading))
 
 /*
- * rip_incoming_authentication - check authentication of incomming packet and return 1 if there's problem.
+ * rip_incoming_authentication - check authentication of incoming packet and return 1 if there's problem.
  */
 int
 rip_incoming_authentication( struct proto *p, struct rip_block_auth *block, struct rip_packet *packet, int num, ip_addr whotoldme )
index cd4f30e7c0abd202acfa7fbf89d6bf7a09606f95..ad41ffab01c08b1ec845d7d3728f7b60f689a0e0 100644 (file)
@@ -24,7 +24,7 @@ CF_DEFINES
 
 CF_DECLS
 
-CF_KEYWORDS(RIP, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
+CF_KEYWORDS(RIP, RIPNG, INFINITY, METRIC, PORT, PERIOD, GARBAGE, TIMEOUT,
            MODE, BROADCAST, MULTICAST, QUIET, NOLISTEN, VERSION1, 
            AUTHENTICATION, NONE, PLAINTEXT, MD5,
            HONOR, NEVER, NEIGHBOR, ALWAYS,
@@ -39,11 +39,20 @@ CF_ADDTO(proto, rip_cfg '}' { RIP_CFG->passwords = get_passwords(); } )
 rip_cfg_start: proto_start RIP {
      this_proto = proto_config_new(&proto_rip, sizeof(struct rip_proto_config), $1);
      rip_init_config(RIP_CFG);
+     RIP_CFG->port = RIP_PORT_V2;
+   }
+ ;
+
+ripng_cfg_start: proto_start RIPNG {
+     this_proto = proto_config_new(&proto_ripng, sizeof(struct rip_proto_config), $1);
+     rip_init_config(RIP_CFG);
+     RIP_CFG->port = RIP_PORT_NG;
    }
  ;
 
 rip_cfg:
    rip_cfg_start proto_name '{'
+ | ripng_cfg_start proto_name '{'
  | rip_cfg proto_item ';'
  | rip_cfg INFINITY expr ';'   { RIP_CFG->infinity = $3; }
  | rip_cfg PORT expr ';'       { RIP_CFG->port = $3; }
index 9ec4ac749e8c7c2c02bbc2265921f5217921590b..bcd44ed442715defaead4f49b00819e898452306 100644 (file)
 
 static struct rip_interface *new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_patt *patt);
 
+static inline int rip_is_old(struct proto *p)
+{ return p->proto == &proto_rip; }
+
+static inline int rip_is_ng(struct proto *p)
+{ return p->proto == &proto_ripng; }
+
 /*
  * Output processing
  *
@@ -92,34 +98,30 @@ rip_tx_err( sock *s, int err )
  * that could be fixed but it is not real problem).
  */
 static int
-rip_tx_prepare(struct proto *p, struct rip_block *b, struct rip_entry *e, struct rip_interface *rif, int pos )
+rip_tx_prepare(struct proto *p, struct rip_block *block, struct rip_entry *e, struct rip_interface *rif, int pos )
 {
-  int metric;
-  DBG( "." );
-  b->tag     = htons( e->tag );
-  b->network = e->n.prefix;
-  metric = e->metric;
-  if (neigh_connected_to(p, &e->whotoldme, rif->iface)) {
-    DBG( "(split horizon)" );
-    metric = P_CF->infinity;
-  }
-#ifndef IPV6
-  b->family  = htons( 2 ); /* AF_INET */
-  b->netmask = ipa_mkmask( e->n.pxlen );
-  ipa_hton( b->netmask );
-
-  if (neigh_connected_to(p, &e->nexthop, rif->iface))
-    b->nexthop = e->nexthop;
-  else
-    b->nexthop = IPA_NONE;
-  ipa_hton( b->nexthop );  
-  b->metric  = htonl( metric );
-#else
-  b->pxlen = e->n.pxlen;
-  b->metric  = metric; /* it is u8 */
-#endif
+  int split = neigh_connected_to(p, &e->whotoldme, rif->iface);
+  int nh_ok = neigh_connected_to(p, &e->nexthop, rif->iface);
+  int metric = split ? P_CF->infinity : e->metric;
+
+  if (rip_is_old(p)) {
+    /* RIPv2 */
+    struct rip_block_v2 *b = (void *) block;
+    b->afi = htons(AF_INET);
+    b->tag = htons(e->tag);
+    b->network = ip4_hton(ipa_to_ip4(e->n.prefix));
+    b->netmask = ip4_hton(ip4_mkmask(e->n.pxlen));
+    b->nexthop = nh_ok ? ip4_hton(ipa_to_ip4(e->nexthop)) : IP4_NONE;
+    b->metric = htonl(metric);
 
-  ipa_hton( b->network );
+  } else {
+    /* RIPng */
+    struct rip_block_ng *b = (void *) block;
+    b->network = ip6_hton(e->n.prefix);
+    b->tag = htons(e->tag);
+    b->pxlen = e->n.pxlen;
+    b->metric = metric;
+  }
 
   return pos+1;
 }
@@ -146,19 +148,18 @@ rip_tx( sock *s )
     DBG( "Preparing packet to send: " );
 
     packet->heading.command = RIPCMD_RESPONSE;
-#ifndef IPV6
-    packet->heading.version = RIP_V2;
-#else
-    packet->heading.version = RIP_NG;
-#endif
     packet->heading.unused  = 0;
 
     i = !!P_CF->authtype;
-#ifndef IPV6
-    maxi = ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX);
-#else
-    maxi = 5; /* We need to have at least reserve of one at end of packet */
-#endif
+
+    if (rip_is_old(p)) {
+      packet->heading.version = 2; 
+      maxi = ((P_CF->authtype == AT_MD5) ? PACKET_MD5_MAX : PACKET_MAX);
+    } else {
+      /* RIPng has independent version numbering */
+      packet->heading.version = 1;
+      maxi = 5;        /* FIXME: This is some nonsense? */
+    }
     
     FIB_ITERATE_START(&P->rtable, &c->iter, z) {
       struct rip_entry *e = (struct rip_entry *) z;
@@ -278,116 +279,122 @@ rip_rte_update_if_better(rtable *tab, net *net, struct proto *p, rte *new)
 }
 
 /*
- * advertise_entry - let main routing table know about our new entry
+ * process_block - let main routing table know about our new entry
  * @b: entry in network format
  *
- * This basically translates @b to format used by bird core and feeds
- * bird core with this route.
+ * This does some basic checking and then translates @b to format
+ * used by bird core and feeds bird core with this route.
  */
 static void
-advertise_entry( struct proto *p, struct rip_block *b, ip_addr whotoldme, struct iface *iface )
+process_block( struct proto *p, struct rip_block *block, ip_addr from, struct iface *iface, int version )
 {
-  rta *a, A;
-  rte *r;
-  net *n;
-  neighbor *neighbor;
   struct rip_interface *rif;
-  int pxlen;
-
-  bzero(&A, sizeof(A));
-  A.proto = p;
-  A.source = RTS_RIP;
-  A.scope = SCOPE_UNIVERSE;
-  A.cast = RTC_UNICAST;
-  A.dest = RTD_ROUTER;
-  A.flags = 0;
-#ifndef IPV6
-  A.gw = ipa_nonzero(b->nexthop) ? b->nexthop : whotoldme;
-  pxlen = ipa_mklen(b->netmask);
-#else
-  /* FIXME: next hop is in other packet for v6 */
-  A.gw = whotoldme; 
-  pxlen = b->pxlen;
-#endif
-  A.from = whotoldme;
+  ip_addr prefix, gw;
+  int pxlen, metric, tag;
+
+  CHK_MAGIC;
+
+  if (rip_is_old(p)) {
+    /* RIPv2 */
+    struct rip_block_v2 *b = (void *) block;
+
+    if (ntohs(b->afi) != AF_INET)
+      return;
+
+    prefix = ipa_from_ip4(ip4_ntoh(b->network));
+    gw = ip4_nonzero(b->nexthop) ? ipa_from_ip4(ip4_ntoh(b->nexthop)) : from;
+    metric = ntohl(b->metric);
+    tag = ntohs(b->tag);
+
+    /* FIXME (nonurgent): better handling of RIPv1? */
+    if (version == 1)
+      pxlen = ip4_masklen(ip4_class_mask(ipa_to_ip4(prefix)));
+    else
+      pxlen = ip4_masklen(ip4_ntoh(b->netmask));
+
+    if (pxlen < 0) {
+      log(L_REMOTE "%s: Received invalid netmask for %I from %I",
+         p->name, prefix, from);
+      return;
+    }
 
-  /* No need to look if destination looks valid - ie not net 0 or 127 -- core will do for us. */
+  } else {
+    /* RIPng */
+    struct rip_block_ng *b = (void *) block;
+    prefix = ip6_ntoh(b->network);
+    gw = from;
+    pxlen = b->pxlen;
+    metric = b->metric;
+    tag = ntohs(b->tag);
+
+    /* Ignore nexthop block */
+    if (metric == 0xff)
+      return;
 
-  neighbor = neigh_find2( p, &A.gw, iface, 0 );
-  if (!neighbor) {
-    log( L_REMOTE "%s: %I asked me to route %I/%d using not-neighbor %I.", p->name, A.from, b->network, pxlen, A.gw );
+    if (pxlen > MAX_PREFIX_LENGTH) {
+      log(L_REMOTE "%s: Received invalid pxlen %d for %I from %I",
+         p->name, pxlen, prefix, from);
+      return;
+    }
+  }
+
+
+  if ((!metric) || (metric > P_CF->infinity)) {
+    log(L_REMOTE "%s: Received route %I/%d with invalid metric %d from %I",
+       p->name, prefix, pxlen, metric, from);
     return;
   }
-  if (neighbor->scope == SCOPE_HOST) {
+
+  neighbor *neigh = neigh_find2( p, &gw, iface, 0 );
+  if (!neigh) {
+    log( L_REMOTE "%s: Received route %I/%d with strange nexthop %I from %I",
+        p->name, prefix, pxlen, gw, from );
+    return;
+  }
+  if (neigh->scope == SCOPE_HOST) {
     DBG("Self-destined route, ignoring.\n");
     return;
   }
 
-  A.iface = neighbor->iface;
-  if (!(rif = neighbor->data)) {
-    rif = neighbor->data = find_interface(p, A.iface);
+
+  TRACE(D_PACKETS, "Received %I/%d metric %d from %I",
+       prefix, pxlen, metric, from);
+
+  rta A = {
+    .proto = p,
+    .source = RTS_RIP,
+    .scope = SCOPE_UNIVERSE,
+    .cast = RTC_UNICAST,
+    .dest = RTD_ROUTER,
+    .gw = gw,
+    .from = from,
+    .iface = neigh->iface
+  };
+
+  if (rip_is_old(p)) pxlen += 96;  // XXXX: Hack
+  net *n = net_get(p->table, prefix, pxlen);
+  rta *a = rta_lookup(&A);
+  rte *r = rte_get_temp(a);
+
+  if (!(rif = neigh->data)) {
+    rif = neigh->data = find_interface(p, A.iface);
   }
   if (!rif)
     bug("Route packet using unknown interface? No.");
-    
-  /* set to: interface of nexthop */
-  a = rta_lookup(&A);
-  if (pxlen==-1)  {
-    log( L_REMOTE "%s: %I gave me invalid pxlen/netmask for %I.", p->name, A.from, b->network );
-    return;
-  }
-  n = net_get( p->table, b->network, pxlen );
-  r = rte_get_temp(a);
-#ifndef IPV6
-  r->u.rip.metric = ntohl(b->metric) + rif->metric;
-#else  
-  r->u.rip.metric = b->metric + rif->metric;
-#endif
 
+  r->u.rip.metric = metric + rif->metric;
+  if (r->u.rip.metric > P_CF->infinity)
+    r->u.rip.metric = P_CF->infinity;
+  r->u.rip.tag = tag;
   r->u.rip.entry = NULL;
-  if (r->u.rip.metric > P_CF->infinity) r->u.rip.metric = P_CF->infinity;
-  r->u.rip.tag = ntohl(b->tag);
+
   r->net = n;
   r->pflags = 0; /* Here go my flags */
   rip_rte_update_if_better( p->table, n, p, r );
   DBG( "done\n" );
 }
 
-/*
- * process_block - do some basic check and pass block to advertise_entry
- */
-static void
-process_block( struct proto *p, struct rip_block *block, ip_addr whotoldme, struct iface *iface )
-{
-#ifndef IPV6
-  int metric = ntohl( block->metric );
-#else
-  int metric = block->metric;
-#endif
-  ip_addr network = block->network;
-
-  CHK_MAGIC;
-#ifdef IPV6
-  TRACE(D_ROUTES, "block: %I tells me: %I/%d available, metric %d... ",
-      whotoldme, network, block->pxlen, metric );
-#else
-  TRACE(D_ROUTES, "block: %I tells me: %I/%d available, metric %d... ",
-      whotoldme, network, ipa_mklen(block->netmask), metric );
-#endif
-
-  if ((!metric) || (metric > P_CF->infinity)) {
-#ifdef IPV6 /* Someone is sedning us nexthop and we are ignoring it */
-    if (metric == 0xff)
-      { DBG( "IpV6 nexthop ignored" ); return; }
-#endif
-    log( L_WARN "%s: Got metric %d from %I", p->name, metric, whotoldme );
-    return;
-  }
-
-  advertise_entry( p, block, whotoldme, iface );
-}
-
-#define BAD( x ) { log( L_REMOTE "%s: " x, p->name ); return 1; }
+#define BAD( x ) do { log( L_REMOTE "%s: " x, p->name ); return 1; } while(0)
 
 /*
  * rip_process_packet - this is main routine for incoming packets.
@@ -396,12 +403,12 @@ static int
 rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr whotoldme, int port, struct iface *iface )
 {
   int i;
-  int authenticated = 0;
+  int auth = 0;
   neighbor *neighbor;
 
   switch( packet->heading.version ) {
-  case RIP_V1: DBG( "Rip1: " ); break;
-  case RIP_V2: DBG( "Rip2: " ); break;
+  case 1: DBG( "Rip1: " ); break;
+  case 2: DBG( "Rip2: " ); break;
   default: BAD( "Unknown version" );
   }
 
@@ -414,6 +421,7 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr
            BAD( "They asked me to send routing table, but he is not my neighbor" );
          rip_sendto( p, whotoldme, port, HEAD(P->interfaces) ); /* no broadcast */
           break;
+
   case RIPCMD_RESPONSE: DBG( "*** Rtable from %I\n", whotoldme ); 
           if (port != P_CF->port) {
            log( L_REMOTE "%s: %I send me routing info from port %d", p->name, whotoldme, port );
@@ -425,31 +433,25 @@ rip_process_packet( struct proto *p, struct rip_packet *packet, int num, ip_addr
            return 0;
          }
 
-          for (i=0; i<num; i++) {
-           struct rip_block *block = &packet->block[i];
-#ifndef IPV6
-           /* Authentication is not defined for v6 */
-           if (block->family == 0xffff) {
-             if (i)
-               continue;       /* md5 tail has this family */
-             if (rip_incoming_authentication(p, (void *) block, packet, num, whotoldme))
-               BAD( "Authentication failed" );
-             authenticated = 1;
-             continue;
-           }
-#endif
-           if ((!authenticated) && (P_CF->authtype != AT_NONE))
-             BAD( "Packet is not authenticated and it should be" );
-           ipa_ntoh( block->network );
-#ifndef IPV6
-           ipa_ntoh( block->netmask );
-           ipa_ntoh( block->nexthop );
-           if (packet->heading.version == RIP_V1)      /* FIXME (nonurgent): switch to disable this? */
-             block->netmask = ipa_class_mask(block->network);
-#endif
-           process_block( p, block, whotoldme, iface );
+         /* Authentication is not defined for RIPng */
+         if (rip_is_old(p)) {
+             struct rip_block_auth *b = (void *) &packet->block[0];
+
+             if (b->mustbeFFFF == 0xffff) {
+               if (rip_incoming_authentication(p, b, packet, num, whotoldme))
+                 BAD( "Authentication failed" );
+               else
+                 auth = 1;
+             }
          }
+
+         if ((!auth) && (P_CF->authtype != AT_NONE))
+           BAD( "Packet is not authenticated and it should be" );
+
+          for (i=auth; i<num; i++)
+           process_block( p, &packet->block[i], whotoldme, iface, packet->heading.version);
           break;
+
   case RIPCMD_TRACEON:
   case RIPCMD_TRACEOFF: BAD( "I was asked for traceon/traceoff" );
   case 5: BAD( "Some Sun extension around here" );
@@ -474,22 +476,21 @@ rip_rx(sock *s, int size)
   if (i->mode & IM_NOLISTEN)
     return 1;
 
-#ifdef IPV6
   if (! i->iface || s->lifindex != i->iface->index)
     return 1;
 
   iface = i->iface;
-#endif
+
 
   CHK_MAGIC;
-  DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, i->iface ? i->iface->name : "(dummy)" );
+  DBG( "RIP: message came: %d bytes from %I via %s\n", size, s->faddr, iface ? iface->name : "(dummy)" );
   size -= sizeof( struct rip_packet_heading );
   if (size < 0) BAD( "Too small packet" );
   if (size % sizeof( struct rip_block )) BAD( "Odd sized packet" );
   num = size / sizeof( struct rip_block );
   if (num>PACKET_MAX) BAD( "Too many blocks" );
 
-  if (ipa_equal(i->iface->addr->ip, s->faddr)) {
+  if (ipa_equal(iface->addr->ip, s->faddr)) {
     DBG("My own packet\n");
     return 1;
   }
@@ -703,11 +704,12 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
   rif->sock->err_hook = rip_tx_err;
   rif->sock->daddr = IPA_NONE;
   rif->sock->dport = P_CF->port;
+  rif->sock->flags = rip_is_old(p) ? SKF_V4ONLY : SKF_V6ONLY;
   if (new)
     {
       rif->sock->ttl = 1;
       rif->sock->tos = IP_PREC_INTERNET_CONTROL;
-      rif->sock->flags = SKF_LADDR_RX;
+      rif->sock->flags |= SKF_LADDR_RX;
     }
 
   if (new) {
@@ -715,11 +717,7 @@ new_iface(struct proto *p, struct iface *new, unsigned long flags, struct iface_
       log( L_WARN "%s: rip is not defined over unnumbered links", p->name );
     rif->sock->saddr = IPA_NONE;
     if (rif->multicast) {
-#ifndef IPV6
-      rif->sock->daddr = ipa_from_u32(0xe0000009);
-#else
-      rif->sock->daddr = ipa_build6(0xff020000, 0, 0, 9);
-#endif
+      rif->sock->daddr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
     } else {
       rif->sock->daddr = new->addr->brd;
     }
@@ -805,11 +803,7 @@ rip_if_notify(struct proto *p, unsigned c, struct iface *iface)
 
     lock = olock_new( p->pool );
     if (!(PATT->mode & IM_BROADCAST) && (iface->flags & IF_MULTICAST))
-#ifndef IPV6
-      lock->addr = ipa_from_u32(0xe0000009);
-#else
-      lock->addr = ipa_build6(0xff020000, 0, 0, 9);
-#endif
+      lock->addr = rip_is_old(p) ? IP4_ALL_RIP_ROUTERS : IP6_ALL_RIP_ROUTERS;
     else
       lock->addr = iface->addr->brd;
     lock->port = P_CF->port;
@@ -982,7 +976,6 @@ rip_init_config(struct rip_proto_config *c)
 {
   init_list(&c->iface_list);
   c->infinity  = 16;
-  c->port      = RIP_PORT;
   c->period    = 30;
   c->garbage_time = 120+180;
   c->timeout_time = 120;
@@ -1036,6 +1029,7 @@ rip_copy_config(struct proto_config *dest, struct proto_config *src)
 struct protocol proto_rip = {
   name: "RIP",
   template: "rip%d",
+  tables: RTB_IPV4,
   attr_class: EAP_RIP,
   preference: DEF_PREF_RIP,
   get_route_info: rip_get_route_info,
@@ -1047,3 +1041,20 @@ struct protocol proto_rip = {
   reconfigure: rip_reconfigure,
   copy_config: rip_copy_config
 };
+
+struct protocol proto_ripng = {
+  name: "RIPng",
+  template: "ripng%d",
+  tables: RTB_IPV6,
+  attr_class: EAP_RIP,
+  preference: DEF_PREF_RIP,
+  get_route_info: rip_get_route_info,
+  get_attr: rip_get_attr,
+
+  init: rip_init,
+  dump: rip_dump,
+  start: rip_start,
+  reconfigure: rip_reconfigure,
+  copy_config: rip_copy_config
+};
+
index 896fab649995b5114545a867e871826582625abd..0b04f6b279641acb347bfdc77d3eb76f007adaa8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Structures for RIP protocol
  *
  FIXME: in V6, they insert additional entry whenever next hop differs. Such entry is identified by 0xff in metric.
* FIXME: in V6, they insert additional entry whenever next hop differs. Such entry is identified by 0xff in metric.
  */
 
 #include "nest/route.h"
 #define PACKET_MAX     25
 #define PACKET_MD5_MAX 18      /* FIXME */
 
+#define RIP_PORT_V2    520     /* RIPv2 (for IPv4) */
+#define RIP_PORT_NG    521     /* RIPng (for IPv6 */
 
-#define RIP_V1         1
-#define RIP_V2         2
-#define RIP_NG         1       /* A new version numbering */
+#define IP4_ALL_RIP_ROUTERS    ipa_build4(224, 0, 0, 9)
+#define IP6_ALL_RIP_ROUTERS    ipa_build6(0xff020000, 0, 0, 9)
 
-#ifndef IPV6
-#define RIP_PORT       520     /* RIP for IPv4 */
-#else
-#define RIP_PORT       521     /* RIPng */
-#endif
 
 struct rip_connection {
   node n;
@@ -48,31 +44,30 @@ struct rip_packet_heading {         /* 4 bytes */
 #define RIPCMD_TRACEOFF         4       /* turn it off */
 #define RIPCMD_MAX              5
   u8 version;
-#define RIP_V1                 1
-#define RIP_V2                 2
-#define RIP_NG                         1       /* this is verion 1 of RIPng */
   u16 unused;
 };
 
-#ifndef IPV6
-struct rip_block {     /* 20 bytes */
-  u16 family;  /* 0xffff on first message means this is authentication */
+struct rip_block {     /* 20 bytes, for both RIPv2 and RIPng */
+  u32 data[5];
+};
+
+struct rip_block_v2 {
+  u16 afi;             /* 0xffff on first message means this is authentication */
   u16 tag;
-  ip_addr network;
-  ip_addr netmask;
-  ip_addr nexthop;
+  ip4_addr network;
+  ip4_addr netmask;
+  ip4_addr nexthop;
   u32 metric;
 };
-#else
-struct rip_block { /* IPv6 version!, 20 bytes, too */
-  ip_addr network;
+
+struct rip_block_ng {
+  ip6_addr network;
   u16 tag;
   u8 pxlen;
   u8 metric;
 };
-#endif
 
-struct rip_block_auth { /* 20 bytes */
+struct rip_block_auth {
   u16 mustbeFFFF;
   u16 authtype;
   u16 packetlen;
index 6a027f503c87ef20b7f710bbe8241ece51c712f5..290854766c12456da2e41a897b282a373b4955f3 100644 (file)
@@ -58,22 +58,20 @@ p_igp_table(struct proto *p)
 static void
 static_install(struct proto *p, struct static_route *r, struct iface *ifa)
 {
-  net *n;
-  rta a, *aa;
-  rte *e;
-
   if (r->installed)
     return;
 
   DBG("Installing static route %I/%d, rtd=%d\n", r->net, r->masklen, r->dest);
-  bzero(&a, sizeof(a));
-  a.proto = p;
-  a.source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC;
-  a.scope = SCOPE_UNIVERSE;
-  a.cast = RTC_UNICAST;
-  a.dest = r->dest;
-  a.gw = r->via;
-  a.iface = ifa;
+
+  rta a = {
+    .proto = p,
+    .source = (r->dest == RTD_DEVICE) ? RTS_STATIC_DEVICE : RTS_STATIC,
+    .scope = SCOPE_UNIVERSE,
+    .cast = RTC_UNICAST,
+    .dest = r->dest,
+    .gw = r->via,
+    .iface = ifa
+  };
 
   if (r->dest == RTD_MULTIPATH)
     {
@@ -108,9 +106,10 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
   if (r->dest == RTDX_RECURSIVE)
     rta_set_recursive_next_hop(p->table, &a, p_igp_table(p), &r->via, &r->via);
 
-  aa = rta_lookup(&a);
-  n = net_get(p->table, r->net, r->masklen);
-  e = rte_get_temp(aa);
+  // int pxlen = r->masklen + (ipa_is_ip4(r->net) ? 96 : 0);  // XXXX: Hack
+  net *n = net_get(p->table, r->net, r->masklen);
+  rta *aa = rta_lookup(&a);
+  rte *e = rte_get_temp(aa);
   e->net = n;
   e->pflags = 0;
   rte_update(p->table, n, p, p, e);
@@ -120,13 +119,13 @@ static_install(struct proto *p, struct static_route *r, struct iface *ifa)
 static void
 static_remove(struct proto *p, struct static_route *r)
 {
-  net *n;
-
   if (!r->installed)
     return;
 
   DBG("Removing static route %I/%d\n", r->net, r->masklen);
-  n = net_find(p->table, r->net, r->masklen);
+
+  // int pxlen = r->masklen + (ipa_is_ip4(r->net) ? 96 : 0);  // XXXX: Hack
+  net *n = net_find(p->table, r->net, r->masklen);
   if (n)
     rte_update(p->table, n, p, p, NULL);
   r->installed = 0;