summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Modules7
-rw-r--r--lib/birdlib.h6
-rw-r--r--lib/event.c2
-rw-r--r--lib/event.h7
-rw-r--r--lib/ip.c376
-rw-r--r--lib/ip.h471
-rw-r--r--lib/ipv4.c110
-rw-r--r--lib/ipv4.h116
-rw-r--r--lib/ipv6.c384
-rw-r--r--lib/ipv6.h141
-rw-r--r--lib/printf.c4
-rw-r--r--lib/slists.h8
-rw-r--r--lib/socket.h2
13 files changed, 819 insertions, 815 deletions
diff --git a/lib/Modules b/lib/Modules
index 7131f0b2..7254df2d 100644
--- a/lib/Modules
+++ b/lib/Modules
@@ -3,13 +3,6 @@ bitops.c
bitops.h
ip.h
ip.c
-#ifdef IPV6
-ipv6.c
-ipv6.h
-#else
-ipv4.c
-ipv4.h
-#endif
lists.c
lists.h
md5.c
diff --git a/lib/birdlib.h b/lib/birdlib.h
index c489c45f..84a6c1b4 100644
--- a/lib/birdlib.h
+++ b/lib/birdlib.h
@@ -33,6 +33,12 @@
#define ABS(a) ((a)>=0 ? (a) : -(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
+#define BIT32_VAL(p) (((u32) 1) << ((p) % 32))
+#define BIT32_TEST(b,p) ((b)[(p)/32] & BIT32_VAL(p))
+#define BIT32_SET(b,p) ((b)[(p)/32] |= BIT32_VAL(p))
+#define BIT32_CLR(b,p) ((b)[(p)/32] &= ~BIT32_VAL(p))
+#define BIT32_ZERO(b,l) memset((b), 0, (l)/8)
+
#ifndef NULL
#define NULL ((void *) 0)
#endif
diff --git a/lib/event.c b/lib/event.c
index 916cf55c..b429c205 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -27,7 +27,7 @@ event_list global_event_list;
inline void
ev_postpone(event *e)
{
- if (e->n.next)
+ if (ev_active(e))
{
rem_node(&e->n);
e->n.next = NULL;
diff --git a/lib/event.h b/lib/event.h
index d8500413..d5975222 100644
--- a/lib/event.h
+++ b/lib/event.h
@@ -30,4 +30,11 @@ void ev_schedule(event *);
void ev_postpone(event *);
int ev_run_list(event_list *);
+static inline int
+ev_active(event *e)
+{
+ return e->n.next != NULL;
+}
+
+
#endif
diff --git a/lib/ip.c b/lib/ip.c
index aa61553e..01edf0d5 100644
--- a/lib/ip.c
+++ b/lib/ip.c
@@ -1,14 +1,11 @@
/*
- * BIRD Library -- IP address routines common for IPv4 and IPv6
+ * BIRD Library -- IP address functions
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
-#include "nest/bird.h"
-#include "lib/ip.h"
-
/**
* DOC: IP addresses
*
@@ -18,6 +15,333 @@
* they must be manipulated using the following functions and macros.
*/
+#include <stdlib.h>
+
+#include "nest/bird.h"
+#include "lib/ip.h"
+
+
+int
+ip6_compare(ip6_addr a, ip6_addr b)
+{
+ int i;
+ for (i=0; i<4; i++)
+ if (a.addr[i] > b.addr[i])
+ return 1;
+ else if (a.addr[i] < b.addr[i])
+ return -1;
+ return 0;
+}
+
+ip6_addr
+ip6_mkmask(uint n)
+{
+ ip6_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;
+}
+
+int
+ip6_masklen(ip6_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
+ip4_classify(ip4_addr ad)
+{
+ u32 a = _I(ad);
+ u32 b = a >> 24U;
+
+ if (b && b <= 0xdf)
+ {
+ if (b == 0x7f)
+ return IADDR_HOST | SCOPE_HOST;
+ else if ((b == 0x0a) ||
+ ((a & 0xffff0000) == 0xc0a80000) ||
+ ((a & 0xfff00000) == 0xac100000))
+ return IADDR_HOST | SCOPE_SITE;
+ else
+ return IADDR_HOST | SCOPE_UNIVERSE;
+ }
+
+ if (b >= 0xe0 && b <= 0xef)
+ return IADDR_MULTICAST | SCOPE_UNIVERSE;
+
+ if (a == 0xffffffff)
+ return IADDR_BROADCAST | SCOPE_LINK;
+
+ return IADDR_INVALID;
+}
+
+int
+ip6_classify(ip6_addr *a)
+{
+ u32 x = a->addr[0];
+
+ if ((x & 0xe0000000) == 0x20000000) /* 2000::/3 Aggregatable Global Unicast Address */
+ return IADDR_HOST | SCOPE_UNIVERSE;
+ if ((x & 0xffc00000) == 0xfe800000) /* fe80::/10 Link-Local Address */
+ return IADDR_HOST | SCOPE_LINK;
+ if ((x & 0xffc00000) == 0xfec00000) /* fec0::/10 Site-Local Address */
+ return IADDR_HOST | SCOPE_SITE;
+ if ((x & 0xfe000000) == 0xfc000000) /* fc00::/7 Unique Local Unicast Address (RFC 4193) */
+ return IADDR_HOST | SCOPE_SITE;
+ if ((x & 0xff000000) == 0xff000000) /* ff00::/8 Multicast Address */
+ {
+ uint 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;
+ default: return IADDR_MULTICAST | SCOPE_UNDEFINED;
+ }
+ }
+
+ if (!x && !a->addr[1])
+ {
+ u32 a2 = a->addr[2];
+ u32 a3 = a->addr[3];
+
+ if (a2 == 0 && a3 == 1)
+ return IADDR_HOST | SCOPE_HOST; /* Loopback address */
+ if (a2 == 0)
+ return ip4_classify(_MI4(a3)); /* IPv4 compatible addresses */
+ if (a2 == 0xffff)
+ return ip4_classify(_MI4(a3)); /* IPv4 mapped addresses */
+
+ return IADDR_INVALID;
+ }
+
+ return IADDR_HOST | SCOPE_UNDEFINED;
+}
+
+
+
+/*
+ * 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 *
+ip4_ntop(ip4_addr a, char *b)
+{
+ u32 x = _I(a);
+ return b + bsprintf(b, "%d.%d.%d.%d", (x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff);
+}
+
+
+char *
+ip6_ntop(ip6_addr a, char *b)
+{
+ u16 words[8];
+ int bestpos, bestlen, curpos, curlen, i;
+
+ /* 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 += bsprintf(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 += bsprintf(b, "%x", words[i]);
+ }
+ }
+ *b = 0;
+ return b;
+}
+
+int
+ip4_pton(char *a, ip4_addr *o)
+{
+ int i;
+ 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 = ip4_from_u32(ia);
+ return 1;
+}
+
+int
+ip6_pton(char *a, ip6_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 */
+ ip4_addr x;
+ if (!ip4_pton(start, &x))
+ return 0;
+ words[i++] = _I(x) >> 16;
+ words[i++] = _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 ip6_addr format */
+ for (i=0; i<4; i++)
+ o->addr[i] = (words[2*i] << 16) | words[2*i+1];
+
+ return 1;
+}
+
+
/**
* ip_scope_text - get textual representation of address scope
* @scope: scope (%SCOPE_xxx)
@@ -25,7 +349,7 @@
* Returns a pointer to a textual name of the scope given.
*/
char *
-ip_scope_text(unsigned scope)
+ip_scope_text(uint scope)
{
static char *scope_table[] = { "host", "link", "site", "org", "univ", "undef" };
@@ -35,6 +359,23 @@ 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);
+}
+
#if 0
/**
* ipa_equal - compare two IP addresses for equality
@@ -102,14 +443,14 @@ ip_addr ipa_not(ip_addr x) { DUMMY }
ip_addr ipa_mkmask(int x) { DUMMY }
/**
- * ipa_mkmask - calculate netmask length
+ * ipa_masklen - calculate netmask length
* @x: IP address
*
* This function checks whether @x represents a valid netmask and
* returns the size of the associate network prefix or -1 for invalid
* mask.
*/
-int ipa_mklen(ip_addr x) { DUMMY }
+int ipa_masklen(ip_addr x) { DUMMY }
/**
* ipa_hash - hash IP addresses
@@ -151,8 +492,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
@@ -160,7 +501,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 }
+ip4_addr ip4_class_mask(ip4_addr x) { DUMMY }
/**
* ipa_from_u32 - convert IPv4 address to an integer
@@ -193,7 +534,7 @@ ip_addr ipa_to_u32(u32 x) { DUMMY }
int ipa_compare(ip_addr x, ip_addr y) { DUMMY }
/**
- * ipa_build - build an IPv6 address from parts
+ * ipa_build6 - build an IPv6 address from parts
* @a1: part #1
* @a2: part #2
* @a3: part #3
@@ -203,18 +544,7 @@ int ipa_compare(ip_addr x, ip_addr y) { DUMMY }
* address. It's used for example when a protocol wants to bind its
* socket to a hard-wired multicast address.
*/
-ip_addr ipa_build(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY }
-
-/**
- * ipa_absolutize - convert link scope IPv6 address to universe scope
- * @x: link scope IPv6 address
- * @y: universe scope IPv6 prefix of the interface
- *
- * This function combines a link-scope IPv6 address @x with the universe
- * scope prefix @x of the network assigned to an interface to get a
- * universe scope form of @x.
- */
-ip_addr ipa_absolutize(ip_addr x, ip_addr y) { DUMMY }
+ip_addr ipa_build6(u32 a1, u32 a2, u32 a3, u32 a4) { DUMMY }
/**
* ip_ntop - convert IP address to textual representation
diff --git a/lib/ip.h b/lib/ip.h
index 023c1064..45e073d9 100644
--- a/lib/ip.h
+++ b/lib/ip.h
@@ -9,59 +9,474 @@
#ifndef _BIRD_IP_H_
#define _BIRD_IP_H_
-#ifndef IPV6
-#include "ipv4.h"
+#include "lib/endian.h"
+#include "lib/string.h"
+#include "lib/bitops.h"
+#include "lib/unaligned.h"
+
+
+#define IP4_OSPF_ALL_ROUTERS ipa_build4(224, 0, 0, 5)
+#define IP4_OSPF_DES_ROUTERS ipa_build4(224, 0, 0, 6)
+
+#define IP6_ALL_NODES ipa_build6(0xFF020000, 0, 0, 1)
+#define IP6_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 2)
+#define IP6_OSPF_ALL_ROUTERS ipa_build6(0xFF020000, 0, 0, 5)
+#define IP6_OSPF_DES_ROUTERS ipa_build6(0xFF020000, 0, 0, 6)
+#define IP6_RIP_ROUTERS ipa_build6(0xFF020000, 0, 0, 9)
+
+#define IP4_NONE _MI4(0)
+#define IP6_NONE _MI6(0,0,0,0)
+
+#define IP4_MIN_MTU 576
+#define IP6_MIN_MTU 1280
+
+#define IP_PREC_INTERNET_CONTROL 0xc0
+
+
+#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
-#include "ipv6.h"
+#define MAX_PREFIX_LENGTH 32
+#define BITS_PER_IP_ADDRESS 32
+#define STD_ADDRESS_P_LENGTH 15
+#define SIZE_OF_IP_HEADER 24
+#endif
+
+
+#ifdef DEBUGGING
+
+typedef struct ip4_addr {
+ u32 addr;
+} ip4_addr;
+
+#define _MI4(x) ((struct ip4_addr) { x })
+#define _I(x) (x).addr
+
+#else
+
+typedef u32 ip4_addr;
+
+#define _MI4(x) (x)
+#define _I(x) (x)
+
+#endif
+
+
+typedef struct ip6_addr {
+ u32 addr[4];
+} ip6_addr;
+
+#define _MI6(a,b,c,d) ((struct ip6_addr) {{ a, b, c, d }})
+#define _I0(a) ((a).addr[0])
+#define _I1(a) ((a).addr[1])
+#define _I2(a) ((a).addr[2])
+#define _I3(a) ((a).addr[3])
+
+
+#ifdef IPV6
+
+/* Structure ip_addr may contain both IPv4 and IPv6 addresses */
+typedef ip6_addr ip_addr;
+#define IPA_NONE IP6_NONE
+
+#define ipa_from_ip4(x) _MI6(0,0,0xffff,_I(x))
+#define ipa_from_ip6(x) x
+#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
+
+#define ipa_to_ip4(x) _MI4(_I3(x))
+#define ipa_to_ip6(x) x
+#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
+
+#define ipa_is_ip4(a) ip6_is_v4mapped(a)
+
+#else
+
+/* Provisionary ip_addr definition same as ip4_addr */
+typedef ip4_addr ip_addr;
+#define IPA_NONE IP4_NONE
+
+#define ipa_from_ip4(x) x
+#define ipa_from_ip6(x) IPA_NONE
+#define ipa_from_u32(x) ipa_from_ip4(ip4_from_u32(x))
+
+#define ipa_to_ip4(x) x
+#define ipa_to_ip6(x) IP6_NONE
+#define ipa_to_u32(x) ip4_to_u32(ipa_to_ip4(x))
+
+#define ipa_is_ip4(a) 1
+
+#endif
+
+
+/*
+ * Public constructors
+ */
+
+#define ip4_from_u32(x) _MI4(x)
+#define ip4_to_u32(x) _I(x)
+
+#define ip4_build(a,b,c,d) _MI4(((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
+#define ip6_build(a,b,c,d) _MI6(a,b,c,d)
+
+#define ipa_build4(a,b,c,d) ipa_from_ip4(ip4_build(a,b,c,d))
+#define ipa_build6(a,b,c,d) ipa_from_ip6(ip6_build(a,b,c,d))
+
+
+/*
+ * Basic algebraic functions
+ */
+
+static inline int ip4_equal(ip4_addr a, ip4_addr b)
+{ return _I(a) == _I(b); }
+
+static inline int ip4_zero(ip4_addr a)
+{ return _I(a) == 0; }
+
+static inline int ip4_nonzero(ip4_addr a)
+{ return _I(a) != 0; }
+
+static inline ip4_addr ip4_and(ip4_addr a, ip4_addr b)
+{ return _MI4(_I(a) & _I(b)); }
+
+static inline ip4_addr ip4_or(ip4_addr a, ip4_addr b)
+{ return _MI4(_I(a) | _I(b)); }
+
+static inline ip4_addr ip4_xor(ip4_addr a, ip4_addr b)
+{ return _MI4(_I(a) ^ _I(b)); }
+
+static inline ip4_addr ip4_not(ip4_addr a)
+{ return _MI4(~_I(a)); }
+
+
+static inline int ip6_equal(ip6_addr a, ip6_addr b)
+{ return _I0(a) == _I0(b) && _I1(a) == _I1(b) && _I2(a) == _I2(b) && _I3(a) == _I3(b); }
+
+static inline int ip6_zero(ip6_addr a)
+{ return !_I0(a) && !_I1(a) && !_I2(a) && !_I3(a); }
+
+static inline int ip6_nonzero(ip6_addr a)
+{ return _I0(a) || _I1(a) || _I2(a) || _I3(a); }
+
+static inline ip6_addr ip6_and(ip6_addr a, ip6_addr b)
+{ return _MI6(_I0(a) & _I0(b), _I1(a) & _I1(b), _I2(a) & _I2(b), _I3(a) & _I3(b)); }
+
+static inline ip6_addr ip6_or(ip6_addr a, ip6_addr b)
+{ return _MI6(_I0(a) | _I0(b), _I1(a) | _I1(b), _I2(a) | _I2(b), _I3(a) | _I3(b)); }
+
+static inline ip6_addr ip6_xor(ip6_addr a, ip6_addr b)
+{ return _MI6(_I0(a) ^ _I0(b), _I1(a) ^ _I1(b), _I2(a) ^ _I2(b), _I3(a) ^ _I3(b)); }
+
+static inline ip6_addr ip6_not(ip6_addr a)
+{ return _MI6(~_I0(a), ~_I1(a), ~_I2(a), ~_I3(a)); }
+
+
+#ifdef IPV6
+#define ipa_equal(x,y) ip6_equal(x,y)
+#define ipa_zero(x) ip6_zero(x)
+#define ipa_nonzero(x) ip6_nonzero(x)
+#define ipa_and(x,y) ip6_and(x,y)
+#define ipa_or(x,y) ip6_or(x,y)
+#define ipa_xor(x,y) ip6_xor(x,y)
+#define ipa_not(x) ip6_not(x)
+#else
+#define ipa_equal(x,y) ip4_equal(x,y)
+#define ipa_zero(x) ip4_zero(x)
+#define ipa_nonzero(x) ip4_nonzero(x)
+#define ipa_and(x,y) ip4_and(x,y)
+#define ipa_or(x,y) ip4_or(x,y)
+#define ipa_xor(x,y) ip4_xor(x,y)
+#define ipa_not(x) ip4_not(x)
+#endif
+
+
+
+#ifdef IPV6
+/*
+ * A zero address is either a token for invalid/unused, or the prefix of default
+ * routes. These functions should be used in the second case, where both IPv4
+ * and IPv6 zero addresses should be checked.
+ */
+
+static inline int ipa_zero2(ip_addr a)
+{ return !_I0(a) && !_I1(a) && ((_I2(a) == 0) || (_I2(a) == 0xffff)) && !_I3(a); }
+
+static inline int ipa_nonzero2(ip_addr a)
+{ return _I0(a) || _I1(a) || ((_I2(a) != 0) && (_I2(a) != 0xffff)) || _I3(a); }
+
+#else
+#define ipa_zero2(x) ip4_zero(x)
+#define ipa_nonzero2(x) ip4_nonzero(x)
+#endif
+
+
+/*
+ * Hash and compare functions
+ */
+
+static inline uint ip4_hash(ip4_addr a)
+{
+ /* Returns a 16-bit value */
+ u32 x = _I(a);
+ x ^= x >> 16;
+ x ^= x << 10;
+ return x & 0xffff;
+}
+
+static inline u32 ip4_hash32(ip4_addr a)
+{
+ /* Returns a 32-bit value, although low-order bits are not mixed */
+ u32 x = _I(a);
+ x ^= x << 16;
+ x ^= x << 12;
+ return x;
+}
+
+static inline uint ip6_hash(ip6_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;
+}
+
+static inline u32 ip6_hash32(ip6_addr a)
+{
+ /* Returns a 32-bit hash key, although low-order bits are not mixed */
+ u32 x = _I0(a) ^ _I1(a) ^ _I2(a) ^ _I3(a);
+ return x ^ (x << 16) ^ (x << 24);
+}
+
+static inline int ip4_compare(ip4_addr a, ip4_addr b)
+{ return (_I(a) > _I(b)) - (_I(a) < _I(b)); }
+
+int ip6_compare(ip6_addr a, ip6_addr b);
+
+
+#ifdef IPV6
+#define ipa_hash(x) ip6_hash(x)
+#define ipa_hash32(x) ip6_hash32(x)
+#define ipa_compare(x,y) ip6_compare(x,y)
+#else
+#define ipa_hash(x) ip4_hash(x)
+#define ipa_hash32(x) ip4_hash32(x)
+#define ipa_compare(x,y) ip4_compare(x,y)
#endif
-#define ipa_zero(x) (!ipa_nonzero(x))
-#define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
-#define ipa_in_net(x,n,p) (ipa_zero(ipa_and(ipa_xor((n),(x)),ipa_mkmask(p))))
-#define net_in_net(n1,l1,n2,l2) (((l1) >= (l2)) && (ipa_zero(ipa_and(ipa_xor((n1),(n2)),ipa_mkmask(l2)))))
/*
- * ip_classify() returns either a negative number for invalid addresses
- * or scope OR'ed together with address type.
+ * IP address classification
*/
+/* Address class */
#define IADDR_INVALID -1
#define IADDR_SCOPE_MASK 0xfff
#define IADDR_HOST 0x1000
#define IADDR_BROADCAST 0x2000
#define IADDR_MULTICAST 0x4000
+/* Address scope */
+#define SCOPE_HOST 0
+#define SCOPE_LINK 1
+#define SCOPE_SITE 2
+#define SCOPE_ORGANIZATION 3
+#define SCOPE_UNIVERSE 4
+#define SCOPE_UNDEFINED 5
+
+int ip4_classify(ip4_addr ad);
+int ip6_classify(ip6_addr *a);
+
+static inline int ip6_is_link_local(ip6_addr a)
+{ return (_I0(a) & 0xffc00000) == 0xfe800000; }
+
+static inline int ip6_is_v4mapped(ip6_addr a)
+{ return _I0(a) == 0 && _I1(a) == 0 && _I2(a) == 0xffff; }
+
+#ifdef IPV6
+#define ipa_classify(x) ip6_classify(&(x))
+#define ipa_is_link_local(x) ip6_is_link_local(x)
+#else
+#define ipa_classify(x) ip4_classify(x)
+#define ipa_is_link_local(x) 0
+#endif
+
+static inline int ipa_classify_net(ip_addr a)
+{ return ipa_zero2(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); }
+
+
/*
- * Address scope
+ * Miscellaneous IP prefix manipulation
*/
-#define SCOPE_HOST 0
-#define SCOPE_LINK 1
-#define SCOPE_SITE 2
-#define SCOPE_ORGANIZATION 3
-#define SCOPE_UNIVERSE 4
-#define SCOPE_UNDEFINED 5
+static inline ip4_addr ip4_mkmask(uint n)
+{ return _MI4(u32_mkmask(n)); }
+
+static inline int ip4_masklen(ip4_addr a)
+{ return u32_masklen(_I(a)); }
+
+ip6_addr ip6_mkmask(uint n);
+int ip6_masklen(ip6_addr *a);
+
+/* ipX_pxlen() requires that x != y */
+static inline uint ip4_pxlen(ip4_addr a, ip4_addr b)
+{ return 31 - u32_log2(_I(a) ^ _I(b)); }
+
+static inline uint ip6_pxlen(ip6_addr a, ip6_addr b)
+{
+ int i = 0;
+ i += (a.addr[i] == b.addr[i]);
+ i += (a.addr[i] == b.addr[i]);
+ i += (a.addr[i] == b.addr[i]);
+ i += (a.addr[i] == b.addr[i]);
+ return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
+}
+
+static inline u32 ip4_getbit(ip4_addr a, uint pos)
+{ return _I(a) & (0x80000000 >> pos); }
+
+static inline u32 ip6_getbit(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); }
+
+static inline ip4_addr ip4_opposite_m2(ip4_addr a)
+{ return _MI4(_I(a) ^ 3); }
+
+static inline ip6_addr ip6_opposite_m1(ip6_addr a)
+{ return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 1); }
+
+static inline ip6_addr ip6_opposite_m2(ip6_addr a)
+{ return _MI6(_I0(a), _I1(a), _I2(a), _I3(a) ^ 3); }
+
+ip4_addr ip4_class_mask(ip4_addr ad);
+
+#ifdef IPV6
+#define ipa_mkmask(x) ip6_mkmask(x)
+#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_opposite_m1(x) ip6_opposite_m1(x)
+#define ipa_opposite_m2(x) ip6_opposite_m2(x)
+#else
+#define ipa_mkmask(x) ip4_mkmask(x)
+#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_opposite_m1(x) ip4_opposite_m1(x)
+#define ipa_opposite_m2(x) ip4_opposite_m2(x)
+#endif
-char *ip_scope_text(unsigned);
/*
- * Network prefixes
+ * Host/network order conversions
*/
-struct prefix {
- ip_addr addr;
- unsigned int len;
-};
+static inline ip4_addr ip4_hton(ip4_addr a)
+{ return _MI4(htonl(_I(a))); }
+
+static inline ip4_addr ip4_ntoh(ip4_addr a)
+{ return _MI4(ntohl(_I(a))); }
+
+static inline ip6_addr ip6_hton(ip6_addr a)
+{ return _MI6(htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a))); }
+
+static inline ip6_addr ip6_ntoh(ip6_addr a)
+{ return _MI6(ntohl(_I0(a)), ntohl(_I1(a)), ntohl(_I2(a)), ntohl(_I3(a))); }
+
+#ifdef IPV6
+#define ipa_hton(x) x = ip6_hton(x)
+#define ipa_ntoh(x) x = ip6_ntoh(x)
+#else
+#define ipa_hton(x) x = ip4_hton(x)
+#define ipa_ntoh(x) x = ip4_ntoh(x)
+#endif
+
+
+/*
+ * Unaligned data access (in network order)
+ */
+
+static inline ip4_addr get_ip4(void *buf)
+{
+ return _MI4(get_u32(buf));
+}
+
+static inline ip6_addr get_ip6(void *buf)
+{
+ ip6_addr a;
+ memcpy(&a, buf, 16);
+ return ip6_ntoh(a);
+}
+
+static inline void * put_ip4(void *buf, ip4_addr a)
+{
+ put_u32(buf, _I(a));
+ return buf+4;
+}
+
+static inline void * put_ip6(void *buf, ip6_addr a)
+{
+ a = ip6_hton(a);
+ memcpy(buf, &a, 16);
+ return buf+16;
+}
+
+// XXXX these functions must be redesigned or removed
+#ifdef IPV6
+#define get_ipa(x) get_ip6(x)
+#define put_ipa(x,y) put_ip6(x,y)
+#else
+#define get_ipa(x) get_ip4(x)
+#define put_ipa(x,y) put_ip4(x,y)
+#endif
+
+
+/*
+ * Binary/text form conversions
+ */
+
+char *ip4_ntop(ip4_addr a, char *b);
+char *ip6_ntop(ip6_addr a, char *b);
+
+static inline char * ip4_ntox(ip4_addr a, char *b)
+{ return b + bsprintf(b, "%08x", _I(a)); }
+
+static inline char * ip6_ntox(ip6_addr a, char *b)
+{ return b + bsprintf(b, "%08x.%08x.%08x.%08x", _I0(a), _I1(a), _I2(a), _I3(a)); }
+
+int ip4_pton(char *a, ip4_addr *o);
+int ip6_pton(char *a, ip6_addr *o);
+
+// XXXX these functions must be redesigned or removed
+#ifdef IPV6
+#define ipa_ntop(x,y) ip6_ntop(x,y)
+#define ipa_ntox(x,y) ip6_ntox(x,y)
+#define ipa_pton(x,y) ip6_pton(x,y)
+#else
+#define ipa_ntop(x,y) ip4_ntop(x,y)
+#define ipa_ntox(x,y) ip4_ntox(x,y)
+#define ipa_pton(x,y) ip4_pton(x,y)
+#endif
-static inline int ipa_classify_net(ip_addr a)
-{ return ipa_zero(a) ? (IADDR_HOST | SCOPE_UNIVERSE) : ipa_classify(a); }
/*
- * Conversions between internal and string representation
+ * Miscellaneous
*/
-char *ip_ntop(ip_addr a, char *);
-char *ip_ntox(ip_addr a, char *);
-int ip_pton(char *a, ip_addr *o);
+// XXXX review this
+
+#define ip_is_prefix(a,l) (!ipa_nonzero(ipa_and(a, ipa_not(ipa_mkmask(l)))))
+#define ipa_in_net(x,n,p) (ipa_zero(ipa_and(ipa_xor((n),(x)),ipa_mkmask(p))))
+#define net_in_net(n1,l1,n2,l2) (((l1) >= (l2)) && (ipa_zero(ipa_and(ipa_xor((n1),(n2)),ipa_mkmask(l2)))))
+
+char *ip_scope_text(unsigned);
+
+struct prefix {
+ ip_addr addr;
+ unsigned int len;
+};
+
#endif
diff --git a/lib/ipv4.c b/lib/ipv4.c
deleted file mode 100644
index 751351ca..00000000
--- a/lib/ipv4.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * BIRD Library -- IPv4 Address Manipulation Functions
- *
- * (c) 1998 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <stdlib.h>
-
-#include "nest/bird.h"
-#include "lib/ip.h"
-#include "lib/string.h"
-
-int
-ipv4_classify(u32 a)
-{
- u32 b = a >> 24U;
-
- if (b && b <= 0xdf)
- {
- if (b == 0x7f)
- return IADDR_HOST | SCOPE_HOST;
- else if (b == 0x0a ||
- (a & 0xffff0000) == 0xc0a80000 ||
- (a & 0xfff00000) == 0xac100000)
- return IADDR_HOST | SCOPE_SITE;
- else
- return IADDR_HOST | SCOPE_UNIVERSE;
- }
- if (b >= 0xe0 && b <= 0xef)
- return IADDR_MULTICAST | SCOPE_UNIVERSE;
- if (a == 0xffffffff)
- return IADDR_BROADCAST | SCOPE_LINK;
- return IADDR_INVALID;
-}
-
-char *
-ip_ntop(ip_addr a, char *b)
-{
- u32 x = _I(a);
-
- return b + bsprintf(b, "%d.%d.%d.%d",
- ((x >> 24) & 0xff),
- ((x >> 16) & 0xff),
- ((x >> 8) & 0xff),
- (x & 0xff));
-}
-
-char *
-ip_ntox(ip_addr a, char *b)
-{
- return b + bsprintf(b, "%08x", _I(a));
-}
-
-u32
-ipv4_class_mask(u32 a)
-{
- u32 m;
-
- if (a < 0x80000000)
- m = 0xff000000;
- else if (a < 0xc0000000)
- m = 0xffff0000;
- else
- m = 0xffffff00;
- while (a & ~m)
- m |= m >> 1;
- return m;
-}
-
-int
-ip_pton(char *a, ip_addr *o)
-{
- int i;
- 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 = ipa_from_u32(ia);
- return 1;
-}
-
-byte *
-ipv4_skip_header(byte *pkt, int *len)
-{
- int l = *len;
- int q;
-
- if (l < 20 || (*pkt & 0xf0) != 0x40)
- return NULL;
- q = (*pkt & 0x0f) * 4;
- if (q > l)
- return NULL;
- *len -= q;
- return pkt + q;
-}
diff --git a/lib/ipv4.h b/lib/ipv4.h
deleted file mode 100644
index 7fbdf2eb..00000000
--- a/lib/ipv4.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * BIRD -- IP Addresses et Cetera for IPv4
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_IPV4_H_
-#define _BIRD_IPV4_H_
-
-#include "lib/endian.h"
-#include "lib/bitops.h"
-#include "lib/unaligned.h"
-
-#ifdef DEBUGGING
-
-/*
- * Use the structural representation when you want to make sure
- * nobody unauthorized attempts to handle ip_addr as number.
- */
-
-typedef struct ipv4_addr {
- u32 addr;
-} ip_addr;
-
-#define _I(x) (x).addr
-#define _MI(x) ((struct ipv4_addr) { x })
-
-#else
-
-typedef u32 ip_addr;
-
-#define _I(x) (x)
-#define _MI(x) (x)
-
-#endif
-
-#define MAX_PREFIX_LENGTH 32
-#define BITS_PER_IP_ADDRESS 32
-#define STD_ADDRESS_P_LENGTH 15
-#define SIZE_OF_IP_HEADER 24
-
-#define IPA_NONE (_MI(0))
-
-#define ipa_equal(x,y) (_I(x) == _I(y))
-#define ipa_nonzero(x) _I(x)
-#define ipa_and(x,y) _MI(_I(x) & _I(y))
-#define ipa_or(x,y) _MI(_I(x) | _I(y))
-#define ipa_xor(x,y) _MI(_I(x) ^ _I(y))
-#define ipa_not(x) _MI(~_I(x))
-#define ipa_mkmask(x) _MI(u32_mkmask(x))
-#define ipa_mklen(x) u32_masklen(_I(x))
-#define ipa_hash(x) ipv4_hash(_I(x))
-#define ipa_hash32(x) ipv4_hash32(_I(x))
-#define ipa_hton(x) x = _MI(htonl(_I(x)))
-#define ipa_ntoh(x) x = _MI(ntohl(_I(x)))
-#define ipa_classify(x) ipv4_classify(_I(x))
-#define ipa_has_link_scope(x) ipv4_has_link_scope(_I(x))
-#define ipa_opposite_m1(x) _MI(_I(x) ^ 1)
-#define ipa_opposite_m2(x) _MI(_I(x) ^ 3)
-#define ipa_class_mask(x) _MI(ipv4_class_mask(_I(x)))
-#define ipa_from_u32(x) _MI(x)
-#define ipa_to_u32(x) _I(x)
-#define ipa_compare(x,y) ipv4_compare(_I(x),_I(y))
-/* ipa_pxlen() requires that x != y */
-#define ipa_pxlen(x, y) ipv4_pxlen(_I(x), _I(y))
-#define ipa_getbit(x, y) (_I(x) & (0x80000000 >> (y)))
-#define ipa_put_addr(x, y) ipv4_put_addr(x, y)
-
-#define ip_skip_header(x, y) ipv4_skip_header(x, y)
-
-int ipv4_classify(u32);
-u32 ipv4_class_mask(u32);
-byte *ipv4_skip_header(byte *, int *);
-
-static inline int ipv4_has_link_scope(u32 a UNUSED)
-{
- return 0;
-}
-
-static inline unsigned ipv4_hash(u32 a)
-{
- /* Returns a 16-bit value */
- a ^= a >> 16;
- a ^= a << 10;
- return a & 0xffff;
-}
-
-static inline u32 ipv4_hash32(u32 a)
-{
- /* Returns a 32-bit value, although low-order bits are not mixed */
- a ^= a << 16;
- a ^= a << 12;
- return a;
-}
-
-static inline int ipv4_compare(u32 x, u32 y)
-{
- return (x > y) - (x < y);
-}
-
-static inline u32 ipv4_pxlen(u32 a, u32 b)
-{
- return 31 - u32_log2(a ^ b);
-}
-
-static inline byte * ipv4_put_addr(byte *buf, ip_addr a)
-{
- put_u32(buf, _I(a));
- return buf+4;
-}
-
-#define IP_PREC_INTERNET_CONTROL 0xc0
-
-#endif
diff --git a/lib/ipv6.c b/lib/ipv6.c
deleted file mode 100644
index 623f6328..00000000
--- a/lib/ipv6.c
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * BIRD Library -- IPv6 Address Manipulation Functions
- *
- * (c) 1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include <stdlib.h>
-
-#include "nest/bird.h"
-#include "lib/ip.h"
-#include "lib/bitops.h"
-#include "lib/endian.h"
-#include "lib/string.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];
-
- if ((x & 0xe0000000) == 0x20000000) /* 2000::/3 Aggregatable Global Unicast Address */
- return IADDR_HOST | SCOPE_UNIVERSE;
- if ((x & 0xffc00000) == 0xfe800000) /* fe80::/10 Link-Local Address */
- return IADDR_HOST | SCOPE_LINK;
- if ((x & 0xffc00000) == 0xfec00000) /* fec0::/10 Site-Local Address */
- return IADDR_HOST | SCOPE_SITE;
- if ((x & 0xfe000000) == 0xfc000000) /* fc00::/7 Unique Local Unicast Address (RFC 4193) */
- return IADDR_HOST | SCOPE_SITE;
- if ((x & 0xff000000) == 0xff000000) /* ff00::/8 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;
- default: return IADDR_MULTICAST | SCOPE_UNDEFINED;
- }
- }
- if (!x && !a->addr[1] && !a->addr[2])
- {
- u32 y = a->addr[3];
- if (y == 1)
- return IADDR_HOST | SCOPE_HOST; /* Loopback address */
- /* IPv4 compatible addresses */
- if (y >= 0x7f000000 && y < 0x80000000)
- return IADDR_HOST | SCOPE_HOST;
- if ((y & 0xff000000) == 0x0a000000 ||
- (y & 0xffff0000) == 0xc0a80000 ||
- (y & 0xfff00000) == 0xac100000)
- return IADDR_HOST | SCOPE_SITE;
- if (y >= 0x01000000 && y < 0xe0000000)
- return IADDR_HOST | SCOPE_UNIVERSE;
- }
- return IADDR_HOST | SCOPE_UNDEFINED;
-}
-
-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;
- ip_addr *x = &X;
- ip_addr *y = &Y;
-
- 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;
-
- /* 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 += bsprintf(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 += bsprintf(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 += bsprintf(b, "%08x", a.addr[i]);
- }
- return b;
-}
-
-int
-ipv4_pton_u32(char *a, u32 *o)
-{
- int i;
- 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;
-}
-
-void ipv6_absolutize(ip_addr *a, ip_addr *ifa)
-{
- if ((a->addr[0] & 0xffc00000) == 0xfe800000 && /* a is link-scope */
- ((ifa->addr[0] & 0xe0000000) == 0x20000000 | /* ifa is AGU ... */
- (ifa->addr[0] & 0xffc00000) == 0xfec00000)) /* ... or site-scope */
- {
- a->addr[0] = ifa->addr[0]; /* Copy the prefix, leave interface ID */
- a->addr[1] = ifa->addr[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;
-}
-
-#endif
diff --git a/lib/ipv6.h b/lib/ipv6.h
deleted file mode 100644
index b935a6ef..00000000
--- a/lib/ipv6.h
+++ /dev/null
@@ -1,141 +0,0 @@
-
-/*
- * BIRD -- IP Addresses et Cetera for IPv6
- *
- * (c) 1999--2000 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#ifndef _BIRD_IPV6_H_
-#define _BIRD_IPV6_H_
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include "lib/string.h"
-#include "lib/bitops.h"
-#include "lib/unaligned.h"
-
-typedef struct ipv6_addr {
- u32 addr[4];
-} ip_addr;
-
-#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])
-#define _I3(a) ((a).addr[3])
-
-#define MAX_PREFIX_LENGTH 128
-#define BITS_PER_IP_ADDRESS 128
-#define STD_ADDRESS_P_LENGTH 39
-#define SIZE_OF_IP_HEADER 40
-
-#define IPA_NONE _MI(0,0,0,0)
-
-#define ipa_equal(x,y) ({ ip_addr _a=(x), _b=(y); \
- _I0(_a) == _I0(_b) && \
- _I1(_a) == _I1(_b) && \
- _I2(_a) == _I2(_b) && \
- _I3(_a) == _I3(_b); })
-#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_hash32(x) ipv6_hash32(&(x))
-#define ipa_hton(x) ipv6_hton(&(x))
-#define ipa_ntoh(x) ipv6_ntoh(&(x))
-#define ipa_classify(x) ipv6_classify(&(x))
-#define ipa_has_link_scope(x) ipv6_has_link_scope(&(x))
-#define ipa_opposite_m1(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 1); })
-#define ipa_opposite_m2(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 3); })
-/* 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)
-/* ipa_pxlen() requires that x != y */
-#define ipa_pxlen(x, y) ipv6_pxlen(x, y)
-#define ipa_getbit(x, y) ipv6_getbit(x, y)
-#define ipa_put_addr(x, y) ipv6_put_addr(x, y)
-#define ipa_absolutize(x,y) ipv6_absolutize(x,y)
-
-/* In IPv6, SOCK_RAW does not return packet header */
-#define ip_skip_header(x, y) x
-
-ip_addr ipv6_mkmask(unsigned);
-unsigned ipv6_mklen(ip_addr *);
-int ipv6_classify(ip_addr *);
-void ipv6_hton(ip_addr *);
-void ipv6_ntoh(ip_addr *);
-int ipv6_compare(ip_addr, ip_addr);
-int ipv4_pton_u32(char *, u32 *);
-void ipv6_absolutize(ip_addr *, ip_addr *);
-
-static inline int ipv6_has_link_scope(ip_addr *a)
-{
- return ((a->addr[0] & 0xffc00000) == 0xfe800000);
-}
-
-/*
- * This hash function looks well, but once IPv6 enters
- * mainstream use, we need to check that it has good
- * distribution properties on real 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;
-}
-
-static inline u32 ipv6_hash32(ip_addr *a)
-{
- /* Returns a 32-bit hash key, although low-order bits are not ixed */
- u32 x = _I0(*a) ^ _I1(*a) ^ _I2(*a) ^ _I3(*a);
- return x ^ (x << 16) ^ (x << 24);
-}
-
-static inline u32 ipv6_getbit(ip_addr a, u32 y)
-{
- return a.addr[y / 32] & (0x80000000 >> (y % 32));
-}
-
-static inline u32 ipv6_pxlen(ip_addr a, ip_addr b)
-{
- int i = 0;
- i+= (a.addr[i] == b.addr[i]);
- i+= (a.addr[i] == b.addr[i]);
- i+= (a.addr[i] == b.addr[i]);
- i+= (a.addr[i] == b.addr[i]);
- return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]);
-}
-
-static inline byte * ipv6_put_addr(byte *buf, ip_addr a)
-{
- put_u32(buf+0, _I0(a));
- put_u32(buf+4, _I1(a));
- put_u32(buf+8, _I2(a));
- put_u32(buf+12, _I3(a));
- return buf+16;
-}
-
-#define IP_PREC_INTERNET_CONTROL 0xc0
-
-#endif
diff --git a/lib/printf.c b/lib/printf.c
index ebecc140..3eb988fa 100644
--- a/lib/printf.c
+++ b/lib/printf.c
@@ -283,9 +283,9 @@ int bvsnprintf(char *buf, int size, const char *fmt, va_list args)
/* IP address */
case 'I':
if (flags & SPECIAL)
- ip_ntox(va_arg(args, ip_addr), ipbuf);
+ ipa_ntox(va_arg(args, ip_addr), ipbuf);
else {
- ip_ntop(va_arg(args, ip_addr), ipbuf);
+ ipa_ntop(va_arg(args, ip_addr), ipbuf);
if (field_width == 1)
field_width = STD_ADDRESS_P_LENGTH;
}
diff --git a/lib/slists.h b/lib/slists.h
index 2334e36a..d98d02d2 100644
--- a/lib/slists.h
+++ b/lib/slists.h
@@ -68,10 +68,12 @@ typedef struct siterator {
#define SNODE (snode *)
#define SHEAD(list) ((void *)((list).head))
#define STAIL(list) ((void *)((list).tail))
-#define WALK_SLIST(n,list) for(n=SHEAD(list);(SNODE (n))->next; \
- n=(void *)((SNODE (n))->next))
+#define SNODE_NEXT(n) ((void *)((SNODE (n))->next))
+#define SNODE_VALID(n) ((SNODE (n))->next)
+
+#define WALK_SLIST(n,list) for(n=SHEAD(list); SNODE_VALID(n); n=SNODE_NEXT(n))
#define WALK_SLIST_DELSAFE(n,nxt,list) \
- for(n=SHEAD(list); nxt=(void *)((SNODE (n))->next); n=(void *) nxt)
+ for(n=SHEAD(list); nxt=SNODE_NEXT(n); n=(void *) nxt)
#define EMPTY_SLIST(list) (!(list).head->next)
void s_add_tail(slist *, snode *);
diff --git a/lib/socket.h b/lib/socket.h
index f1fffa94..a5b85aa2 100644
--- a/lib/socket.h
+++ b/lib/socket.h
@@ -91,6 +91,8 @@ int sk_set_ipv6_checksum(sock *s, int offset);
int sk_set_icmp6_filter(sock *s, int p1, int p2);
void sk_log_error(sock *s, const char *p);
+byte * sk_rx_buffer(sock *s, int *len); /* Temporary */
+
extern int sk_priority_control; /* Suggested priority for control traffic, should be sysdep define */