]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Basic support for IPv6. The system-dependent part doesn't work yet,
authorMartin Mares <mj@ucw.cz>
Tue, 3 Aug 1999 19:36:06 +0000 (19:36 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 3 Aug 1999 19:36:06 +0000 (19:36 +0000)
but the core routines are there and seem to be working.

   o  lib/ipv6.[ch] written
   o  Lexical analyser recognizes IPv6 addresses and when in IPv6
      mode, treats pure IPv4 addresses as router IDs.
   o  Router ID must be configured manually on IPv6 systems.
   o  Added SCOPE_ORGANIZATION for org-scoped IPv6 multicasts.
   o  Fixed few places where ipa_(hton|ntoh) was called as a function
      returning converted address.

13 files changed:
TODO
conf/cf-lex.l
conf/conf.c
conf/confbase.Y
lib/Modules
lib/ip.h
lib/ipv6.c
lib/ipv6.h
nest/config.Y
nest/iface.c
sysdep/cf/linux-v6.h
sysdep/linux/netlink/netlink.c
sysdep/unix/io.c

diff --git a/TODO b/TODO
index d4f55e5876ad91fc0deb8a1a86078ebae3b169d0..802c2d07060d19a066fbda2082fc09c6f3306ce9 100644 (file)
--- a/TODO
+++ b/TODO
@@ -14,8 +14,7 @@ Core
 - default preferences of protocols: prefer BGP over OSPF/RIP external routes?
 
 - static: check validity of route destination?
-
-- device: configuration of interface patterns
+- static: allow specifying a per-route filter program for setting route attributes?
 
 - rte_update: check whether all bits not covered by masklen are zero
 - rte_update: debug mode
@@ -31,6 +30,7 @@ Core
 - config: executable config files
 - config: when parsing prefix, check zero bits
 - config: reconfiguration
+- config: useless rules when protocols disabled
 
 - krt: rescan interfaces when route addition fails?
 - krt: does PERSIST mode have any sense if kernel syncer is shut down as last?
@@ -53,47 +53,41 @@ Cleanup
 - replace all NUM, IPA and expr tokens by constant filter expressions
 - try compiling with -Wunused
 - does everybody test return value of sk_open?
+- add references to RFC's we did follow
 
 Various ideas
 ~~~~~~~~~~~~~
 - real multipath (doesn't seem to be simple at all :()
 - fake multipath (even less simple)
 - route recalculation timing and flap dampening [see RFC2439 for algorithms]
-- aggregate engine: standard route aggregation and summarization
+- aggregate engine: standard route aggregation and summarization [RFC2519]
 - aggregate engine: injection of manually configured pseudo-static routes
 - generate default route if any working BGP connection exists (aggregate engine again?)
 - generate default route to IGP's (aggregate engine yet another time?)
+- look at RFC 2386 (QoS-based routing)
 
 
 RIP
 ~~~
-       - RIP: export-only and import-only mode?
+       - export-only and import-only mode?
        - drop RIPv1 (Historic protocol)?
        - Route Tag
        - limit routing table xfer (frequency, only to neighbors)
-       - multicast on/off (per interface)
 
 OSPF
 ~~~~
        - importing of device routes for networks where we don't run OSPF
        - check incoming packets using neighbor cache
-       - stub area: either no external routes or only default route
        - RFC2328 appendix E: Use a better algorithm
        - automatic generation of external route tags (RFC1403)
        - RFC1587 NSSA areas
        - RFC2370 opaque LSA's
-       - RFC1793 Demand Circuit Support ??
        - respect interface MTU and try not to create larger packets unless unavoidable
 
-
 BGP
 ~~~
-       - in, local, out RIB
-       - maxsize=4096
-       - detection of loops
        - aggregation, ATOMIC_AGGREGATE
        - communities
-       - confederations
        - attributes must be sorted!
        - re-export of NEXT_HOP attribute
        - BGP session over currently down interface
@@ -104,7 +98,6 @@ BGP
        - inter-advertisement delay???!
        - normalize (sort) incoming AS-SET's
        - maximum length of AS paths
-
        - expected neighbor AS
        - hold time
        - idle timer after error: initial value, exponential growth, maximum value
index 94c2b2ab0d44722a36d9bc6e1549937030fa5f40..21727a9de74b33085de83d7cb3e77a60c2668579 100644 (file)
@@ -65,9 +65,25 @@ WHITE [ \t]
 %%
 
 {DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+ {
+#ifdef IPV6
+  if (ipv4_pton_u32(yytext, &cf_lval.i32))
+    return RTRID;
+  cf_error("Invalid IPv4 address %s", yytext);
+#else
   if (ip_pton(yytext, &cf_lval.a))
     return IPA;
-  cf_error("Invalid IP address");
+  cf_error("Invalid IP address %s", yytext);
+#endif
+}
+
+({XIGIT}*::|({XIGIT}*:){3,})({XIGIT}*|{DIGIT}+\.{DIGIT}+\.{DIGIT}+\.{DIGIT}+) {
+#ifdef IPV6
+  if (ip_pton(yytext, &cf_lval.a))
+    return IPA;
+  cf_error("Invalid IP address %s", yytext);
+#else
+  cf_error("This is an IPv4 router, therefore IPv6 addresses are not supported");
+#endif
 }
 
 0x{DIGIT}+ {
index 0ce593c76215cdc5cbc1326b876fac3f0d7a8499..d9bf9d889a99f0574a27108163c69e09645856e2 100644 (file)
@@ -54,6 +54,10 @@ config_parse(struct config *c)
   cf_parse();
   filters_postconfig();                        /* FIXME: Do we really need this? */
   protos_postconfig(c);
+#ifdef IPV6
+  if (!c->router_id)
+    cf_error("Router ID must be configured manually on IPv6 routers");
+#endif
   return 1;
 }
 
index f9293a4035f39063ee79f4ebf4f7a27d18c2e67b..a6eb87649ac9d3a0c1cbd9816bea72eff1db743a 100644 (file)
@@ -22,6 +22,7 @@ CF_DECLS
 
 %union {
   int i;
+  u32 i32;
   ip_addr a;
   struct symbol *s;
   char *t;
@@ -35,6 +36,7 @@ CF_DECLS
 
 %token END
 %token <i> NUM
+%token <i32> RTRID
 %token <a> IPA
 %token <s> SYM
 %token <t> TEXT
index 1597b9afa3d2cf1b99f79aa2596ed9f71b12f17e..cf654127a2eaf1b26177970fcd9718008d9f865a 100644 (file)
@@ -2,7 +2,7 @@ birdlib.h
 bitops.c
 bitops.h
 ip.h
-#ifdef CONFIG_IPV6
+#ifdef IPV6
 ipv6.c
 ipv6.h
 #else
index 1bce89f8fe011f7d0f0652a9e27617cffadf5770..9b247d5725f90fe02e6537b984685a9759b299b1 100644 (file)
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -35,7 +35,8 @@
 #define SCOPE_HOST 0
 #define SCOPE_LINK 1
 #define SCOPE_SITE 2
-#define SCOPE_UNIVERSE 3
+#define SCOPE_ORGANIZATION 3
+#define SCOPE_UNIVERSE 4
 
 /*
  *     Is it a valid network prefix?
index e612af72480ec2aaa5a203b163cd8899cedc1143..c1b07637c4ca0cc831971577f117c52d8824b863 100644 (file)
 /*
  *     BIRD Library -- IPv6 Address Manipulation Functions
  *
- *     (c) 1998 Martin Mares <mj@ucw.cz>
+ *     (c) 1999 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
+ *
  */
 
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
 #include "nest/bird.h"
 #include "lib/ip.h"
+#include "lib/bitops.h"
+#include "lib/endian.h"
+
+/*
+ *  See RFC 2373 for explanation of IPv6 addressing issues.
+ */
+
+ip_addr
+ipv6_mkmask(unsigned n)
+{
+  ip_addr a;
+  int i;
+
+  for(i=0; i<4; i++)
+    {
+      if (!n)
+       a.addr[i] = 0;
+      else if (n >= 32)
+       {
+         a.addr[i] = ~0;
+         n -= 32;
+       }
+      else
+       {
+         a.addr[i] = u32_mkmask(n);
+         n = 0;
+       }
+    }
+  return a;
+}
+
+unsigned
+ipv6_mklen(ip_addr *a)
+{
+  int i, j, n;
+
+  for(i=0, n=0; i<4; i++, n+=32)
+    if (a->addr[i] != ~0U)
+      {
+       j = u32_masklen(a->addr[i]);
+       if (j < 0)
+         return j;
+       n += j;
+       while (++i < 4)
+         if (a->addr[i])
+           return -1;
+       break;
+      }
+  return n;
+}
+
+int
+ipv6_classify(ip_addr *a)
+{
+  u32 x = a->addr[0];
+
+  /* FIXME: Relax these requirements? */
+  if ((x & 0xe0000000) == 0x20000000)          /* Aggregatable Global Unicast Address */
+    return IADDR_HOST | SCOPE_UNIVERSE;
+  if ((x & 0xfc000000) == 0xe8000000)          /* Link-Local Address */
+    return IADDR_HOST | SCOPE_LINK;
+  if ((x & 0xfc000000) == 0xec000000)          /* Site-Local Address */
+    return IADDR_HOST | SCOPE_SITE;
+  if ((x & 0xff000000) == 0xff000000)          /* Multicast Address */
+    {
+      unsigned int scope = (x >> 16) & 0x0f;
+      switch (scope)
+       {
+       case 1:  return IADDR_MULTICAST | SCOPE_HOST;
+       case 2:  return IADDR_MULTICAST | SCOPE_LINK;
+       case 5:  return IADDR_MULTICAST | SCOPE_SITE;
+       case 8:  return IADDR_MULTICAST | SCOPE_ORGANIZATION;
+       case 14: return IADDR_MULTICAST | SCOPE_UNIVERSE;
+       }
+    }
+  return IADDR_INVALID;
+}
+
+void
+ipv6_hton(ip_addr *a)
+{
+  int i;
+
+  for(i=0; i<4; i++)
+    a->addr[i] = htonl(a->addr[i]);
+}
+
+void
+ipv6_ntoh(ip_addr *a)
+{
+  int i;
+
+  for(i=0; i<4; i++)
+    a->addr[i] = ntohl(a->addr[i]);
+}
+
+int
+ipv6_compare(ip_addr *x, ip_addr *y)
+{
+  int i;
+
+  for(i=0; i<4; i++)
+    if (x->addr[i] > y->addr[i])
+      return 1;
+    else if (x->addr[i] < y->addr[i])
+      return -1;
+  return 0;
+}
+
+/*
+ *  Conversion of IPv6 address to presentation format and vice versa.
+ *  Heavily inspired by routines written by Paul Vixie for the BIND project
+ *  and of course by RFC 2373.
+ */
+
+char *
+ip_ntop(ip_addr a, char *b)
+{
+  u16 words[8];
+  int bestpos, bestlen, curpos, curlen, i;
+  char *c;
+
+  /* First of all, preprocess the address and find the longest run of zeros */
+  bestlen = bestpos = curpos = curlen = 0;
+  for(i=0; i<8; i++)
+    {
+      u32 x = a.addr[i/2];
+      words[i] = ((i%2) ? x : (x >> 16)) & 0xffff;
+      if (words[i])
+       curlen = 0;
+      else
+       {
+         if (!curlen)
+           curpos = i;
+         curlen++;
+         if (curlen > bestlen)
+           {
+             bestpos = curpos;
+             bestlen = curlen;
+           }
+       }
+    }
+  if (bestlen < 2)
+    bestpos = -1;
+
+  /* Is it an encapsulated IPv4 address? */
+  if (!bestpos &&
+      (bestlen == 5 && a.addr[2] == 0xffff ||
+       bestlen == 6))
+    {
+      u32 x = a.addr[3];
+      b += sprintf(b, "::%s%d.%d.%d.%d",
+                  a.addr[2] ? "ffff:" : "",
+                  ((x >> 24) & 0xff),
+                  ((x >> 16) & 0xff),
+                  ((x >> 8) & 0xff),
+                  (x & 0xff));
+      return b;
+    }
+
+  /* Normal IPv6 formatting, compress the largest sequence of zeros */
+  for(i=0; i<8; i++)
+    {
+      if (i == bestpos)
+       {
+         i += bestlen - 1;
+         *b++ = ':';
+         if (i == 7)
+           *b++ = ':';
+       }
+      else
+       {
+         if (i)
+           *b++ = ':';
+         b += sprintf(b, "%x", words[i]);
+       }
+    }
+  *b = 0;
+  return b;
+}
+
+char *
+ip_ntox(ip_addr a, char *b)
+{
+  int i;
+
+  for(i=0; i<4; i++)
+    {
+      if (i)
+       *b++ = '.';
+      b += sprintf(b, "%08x", a.addr[i]);
+    }
+  return b;
+}
+
+int
+ipv4_pton_u32(char *a, u32 *o)
+{
+  int i,j;
+  unsigned long int l;
+  u32 ia = 0;
+
+  i=4;
+  while (i--)
+    {
+      char *d, *c = strchr(a, '.');
+      if (!c != !i)
+       return 0;
+      l = strtoul(a, &d, 10);
+      if (d != c && *d || l > 255)
+       return 0;
+      ia = (ia << 8) | l;
+      if (c)
+       c++;
+      a = c;
+    }
+  *o = ia;
+  return 1;
+}
+
+int
+ip_pton(char *a, ip_addr *o)
+{
+  u16 words[8];
+  int i, j, k, l, hfil;
+  char *start;
+
+  if (a[0] == ':')                     /* Leading :: */
+    {
+      if (a[1] != ':')
+       return 0;
+      a++;
+    }
+  hfil = -1;
+  i = 0;
+  while (*a)
+    {
+      if (*a == ':')                   /* :: */
+       {
+         if (hfil >= 0)
+           return 0;
+         hfil = i;
+         a++;
+         continue;
+       }
+      j = 0;
+      l = 0;
+      start = a;
+      for(;;)
+       {
+         if (*a >= '0' && *a <= '9')
+           k = *a++ - '0';
+         else if (*a >= 'A' && *a <= 'F')
+           k = *a++ - 'A' + 10;
+         else if (*a >= 'a' && *a <= 'f')
+           k = *a++ - 'a' + 10;
+         else
+           break;
+         j = (j << 4) + k;
+         if (j >= 0x10000 || ++l > 4)
+           return 0;
+       }
+      if (*a == ':' && a[1])
+       a++;
+      else if (*a == '.' && (i == 6 || i < 6 && hfil >= 0))
+       {                               /* Embedded IPv4 address */
+         u32 x;
+         if (!ipv4_pton_u32(start, &x))
+           return 0;
+         words[i++] = x >> 16;
+         words[i++] = x;
+         break;
+       }
+      else if (*a)
+       return 0;
+      if (i >= 8)
+       return 0;
+      words[i++] = j;
+    }
+
+  /* Replace :: with an appropriate number of zeros */
+  if (hfil >= 0)
+    {
+      j = 8 - i;
+      for(i=7; i-j >= hfil; i--)
+       words[i] = words[i-j];
+      for(; i>=hfil; i--)
+       words[i] = 0;
+    }
+
+  /* Convert the address to ip_addr format */
+  for(i=0; i<4; i++)
+    o->addr[i] = (words[2*i] << 16) | words[2*i+1];
+  return 1;
+}
+
+#ifdef TEST
+
+#include "bitops.c"
+
+static void test(char *x)
+{
+  ip_addr a;
+  char c[STD_ADDRESS_P_LENGTH+1];
+
+  printf("%-40s ", x);
+  if (!ip_pton(x, &a))
+    {
+      puts("BAD");
+      return;
+    }
+  ip_ntop(a, c);
+  printf("%-40s %04x\n", c, ipv6_classify(&a));
+}
+
+int main(void)
+{
+  puts("Positive tests:");
+  test("1:2:3:4:5:6:7:8");
+  test("dead:beef:DEAD:BEEF::f00d");
+  test("::");
+  test("::1");
+  test("1::");
+  test("::1.234.5.6");
+  test("::ffff:1.234.5.6");
+  test("::fffe:1.234.5.6");
+  test("1:2:3:4:5:6:7::8");
+  test("2080::8:800:200c:417a");
+  test("ff01::101");
+
+  puts("Negative tests:");
+  test(":::");
+  test("1:2:3:4:5:6:7:8:");
+  test("1::2::3");
+  test("::12345");
+  test("::1.2.3.4:5");
+  test(":1:2:3:4:5:6:7:8");
+  test("g:1:2:3:4:5:6:7");
+  return 0;
+}
 
-#error "Ought to implement these."
+#endif
index 35d8e29d5922dd089d3e89644445e64cb498d905..59005f949d103ffd17cf83072e33c2be5adac664 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     BIRD -- IP Addresses et Cetera for IPv6
  *
- *     (c) 1998 Martin Mares <mj@ucw.cz>
+ *     (c) 1999 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 #include <netinet/in.h>
 #include <string.h>
 
-typedef struct ipv4_addr {
+typedef struct ipv6_addr {
   u32 addr[4];
 } ip_addr;
 
-#define _MI(a,b,c,d) ((struct ip_addr) { a, b, c, d })
+#define _MI(a,b,c,d) ((struct ipv6_addr) {{ a, b, c, d }})
 #define _I0(a) ((a).addr[0])
 #define _I1(a) ((a).addr[1])
 #define _I2(a) ((a).addr[2])
@@ -28,38 +28,50 @@ typedef struct ipv4_addr {
 #define IPA_NONE _MI(0,0,0,0)
 
 #define ipa_equal(x,y) (!memcmp(&(x),&(y),sizeof(ip_addr)))
-#define ipa_nonzero(x) (_I0(a) || _I1(a) || _I2(a) || _I3(a))
-#define ipa_and(a,b) _MI(_I0(a) & _I0(b), \
-                        _I1(a) & _I1(b), \
-                        _I2(a) & _I2(b), \
-                        _I3(a) & _I3(b))
-#define ipa_or(a,b) _MI(_I0(a) | _I0(b), \
-                       _I1(a) | _I1(b), \
-                       _I2(a) | _I2(b), \
-                       _I3(a) | _I3(b))
-#define ipa_xor(a,b) _MI(_I0(a) ^ _I0(b), \
-                        _I1(a) ^ _I1(b), \
-                        _I2(a) ^ _I2(b), \
-                        _I3(a) ^ _I3(b))
-#define ipa_not(a) _MI(~_I0(a),~_I1(a),~_I2(a),~_I3(a))
+#define ipa_nonzero(x) ({ ip_addr _a=(x); (_I0(_a) || _I1(_a) || _I2(_a) || _I3(_a)); })
+#define ipa_and(x,y) ({ ip_addr _a=(x), _b=(y); \
+                    _MI(_I0(_a) & _I0(_b), \
+                        _I1(_a) & _I1(_b), \
+                        _I2(_a) & _I2(_b), \
+                        _I3(_a) & _I3(_b)); })
+#define ipa_or(x,y)  ({ ip_addr _a=(x), _b=(y); \
+                    _MI(_I0(_a) | _I0(_b), \
+                        _I1(_a) | _I1(_b), \
+                        _I2(_a) | _I2(_b), \
+                        _I3(_a) | _I3(_b)); })
+#define ipa_xor(x,y) ({ ip_addr _a=(x), _b=(y); \
+                    _MI(_I0(_a) ^ _I0(_b), \
+                        _I1(_a) ^ _I1(_b), \
+                        _I2(_a) ^ _I2(_b), \
+                        _I3(_a) ^ _I3(_b)); })
+#define ipa_not(x) ({ ip_addr _a=(x); _MI(~_I0(_a),~_I1(_a),~_I2(_a),~_I3(_a)); })
 #define ipa_mkmask(x) ipv6_mkmask(x)
 #define ipa_mklen(x) ipv6_mklen(&(x))
 #define ipa_hash(x) ipv6_hash(&(x))
 #define ipa_hton(x) ipv6_hton(&(x))
 #define ipa_ntoh(x) ipv6_ntoh(&(x))
 #define ipa_classify(x) ipv6_classify(&(x))
+/* ipa_opposite and ipa_class_mask don't make sense with IPv6 */
+/* ipa_from_u32 and ipa_to_u32 replaced by ipa_build */
+#define ipa_build(a,b,c,d) _MI(a,b,c,d)
+#define ipa_compare(x,y) ipv6_compare(&x,&y)
 
 ip_addr ipv6_mkmask(unsigned);
 unsigned ipv6_mklen(ip_addr *);
 int ipv6_classify(ip_addr *);
 void ipv6_hton(ip_addr *);
 void ipv6_ntoh(ip_addr *);
+int ipv6_compare(ip_addr *, ip_addr *);
+int ipv4_pton_u32(char *, u32 *);
 
 /* FIXME: Is this hash function uniformly distributed over standard routing tables? */
 static inline unsigned ipv6_hash(ip_addr *a)
 {
+  /* Returns a 16-bit hash key */
   u32 x = _I0(*a) ^ _I1(*a) ^ _I2(*a) ^ _I3(*a);
   return (x ^ (x >> 16) ^ (x >> 8)) & 0xffff;
 }
 
+#define IP_PREC_INTERNET_CONTROL 0             /* FIXME: What's the right value? */
+
 #endif
index 0c6532117f024cf86270a16606a7a9af8e04aaac..dfef4e273794a48c1fe72c05a95beaf56743a0dc 100644 (file)
@@ -20,7 +20,7 @@ CF_KEYWORDS(ROUTER, ID, PROTOCOL, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
 CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, TABLE)
 CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID)
 
-%type <i> idval
+%type <i32> idval
 %type <f> imexport
 %type <r> rtable
 %type <p> password_list password_begin
@@ -37,8 +37,15 @@ rtrid: ROUTER ID idval ';' {
  ;
 
 idval:
-   NUM
- | IPA { $$ = ipa_to_u32($1); }
+   NUM { $$ = $1; }
+ | RTRID
+ | IPA {
+#ifndef IPV6
+     $$ = ipa_to_u32($1);
+#else
+     cf_error("Router IDs must be entered as hexadecimal numbers in IPv6 version");
+#endif
+   }
  ;
 
 /* Creation of routing tables */
index 3a5d9c6bda4ad591a8e1b58fa3c74241f3b0922e..debec45d859b58b87225acf85a2398800f76c5b1 100644 (file)
@@ -549,8 +549,9 @@ ifa_delete(struct ifa *a)
 }
 
 static void
-auto_router_id(void)                   /* FIXME: What if we run IPv6??? */
+auto_router_id(void)
 {
+#ifndef IPV6
   struct iface *i, *j;
 
   j = NULL;
@@ -564,6 +565,7 @@ auto_router_id(void)                        /* FIXME: What if we run IPv6??? */
     die("Cannot determine router ID (no suitable network interface found), please configure it manually");
   debug("Guessed router ID %I (%s)\n", j->addr->ip, j->name);
   config->router_id = ipa_to_u32(j->addr->ip);
+#endif
 }
 
 void
index 69ab0f8ff8aa90c8dd76d85122fc639ab6fe97d6..ef52ee460eb758672271a42f244eab39df39760a 100644 (file)
@@ -8,9 +8,16 @@
 
 #define IPV6
 
-#define CONFIG_TOS
 #define CONFIG_AUTO_ROUTES
 #define CONFIG_ALL_MULTICAST
+#define CONFIG_SELF_CONSCIOUS
+
+/*
+ *  Netlink supports multiple tables, but kernel IPv6 code doesn't, so we
+ *  treat it as a multiple table system with number of tables set to 1.
+ */
+#define CONFIG_MULTIPLE_TABLES
+#define CONFIG_ALL_TABLES_AT_ONCE
 
 /*
 Link: sysdep/linux/netlink
index 6682dbc2b8a86307c09a199ab82293695e322f22..f71f1f5e4239a0c4de5418b91e43c6484d5323ea 100644 (file)
@@ -242,7 +242,7 @@ nl_add_attr_ipa(struct nlmsghdr *h, unsigned maxsize, int code, ip_addr ipa)
   a = (struct rtattr *)((char *)h + NLMSG_ALIGN(h->nlmsg_len));
   a->rta_type = code;
   a->rta_len = len;
-  ipa = ipa_hton(ipa);
+  ipa_hton(ipa);
   memcpy(RTA_DATA(a), &ipa, sizeof(ipa));
   h->nlmsg_len = NLMSG_ALIGN(h->nlmsg_len) + len;
 }
@@ -351,17 +351,18 @@ nl_parse_addr(struct nlmsghdr *h)
   if (i->ifa_flags & IFA_F_SECONDARY)
     ifa.flags |= IA_SECONDARY;
   memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL]), sizeof(ifa.ip));
-  ifa.ip = ipa_ntoh(ifa.ip);
+  ipa_ntoh(ifa.ip);
   ifa.pxlen = i->ifa_prefixlen;
   if (ifi->flags & IF_UNNUMBERED)
     {
       memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite));
-      ifa.opposite = ifa.brd = ipa_ntoh(ifa.opposite);
+      ipa_ntoh(ifa.opposite);
+      ifa.brd = ifa.opposite;
     }
   else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
     {
       memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd));
-      ifa.brd = ipa_ntoh(ifa.brd);
+      ipa_ntoh(ifa.brd);
     }
   /* else a NBMA link */
   ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen));
@@ -575,7 +576,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
   if (a[RTA_DST])
     {
       memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
-      dst = ipa_ntoh(dst);
+      ipa_ntoh(dst);
     }
   else
     dst = IPA_NONE;
@@ -630,7 +631,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
          neighbor *ng;
          ra.dest = RTD_ROUTER;
          memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
-         ra.gw = ipa_ntoh(ra.gw);
+         ipa_ntoh(ra.gw);
          ng = neigh_find(&p->p, &ra.gw, 0);
          if (ng)
            ra.iface = ng->iface;
index 39cf200f86f98d4a3e4a1a0f9b7e58c00a74fe16..3e070fa13cfdf2f7fabdfdccdae35552c781f6fb 100644 (file)
@@ -314,7 +314,7 @@ sk_new(pool *p)
 static inline void
 set_inaddr(struct in_addr *ia, ip_addr a)
 {
-  a = ipa_hton(a);
+  ipa_hton(a);
   memcpy(&ia->s_addr, &a, sizeof(a));
 }
 
@@ -334,7 +334,7 @@ get_sockaddr(struct sockaddr_in *sa, ip_addr *a, unsigned *port)
   if (port)
     *port = ntohs(sa->sin_port);
   memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
-  *a = ipa_ntoh(*a);
+  ipa_ntoh(*a);
 }
 
 static char *