]>
Commit | Line | Data |
---|---|---|
b49e6f5a | 1 | |
c40e05a0 MM |
2 | /* |
3 | * BIRD -- IP Addresses et Cetera for IPv6 | |
4 | * | |
4ebbbd40 | 5 | * (c) 1999--2000 Martin Mares <mj@ucw.cz> |
c40e05a0 MM |
6 | * |
7 | * Can be freely distributed and used under the terms of the GNU GPL. | |
8 | */ | |
9 | ||
294c182e MM |
10 | #ifndef _BIRD_IPV6_H_ |
11 | #define _BIRD_IPV6_H_ | |
c40e05a0 | 12 | |
012279f3 | 13 | #include <sys/types.h> |
c40e05a0 | 14 | #include <netinet/in.h> |
221135d6 | 15 | #include "lib/string.h" |
b1a597e0 | 16 | #include "lib/bitops.h" |
cf31112f | 17 | #include "lib/unaligned.h" |
c40e05a0 | 18 | |
dce26783 | 19 | typedef struct ipv6_addr { |
c40e05a0 MM |
20 | u32 addr[4]; |
21 | } ip_addr; | |
22 | ||
dce26783 | 23 | #define _MI(a,b,c,d) ((struct ipv6_addr) {{ a, b, c, d }}) |
c40e05a0 MM |
24 | #define _I0(a) ((a).addr[0]) |
25 | #define _I1(a) ((a).addr[1]) | |
26 | #define _I2(a) ((a).addr[2]) | |
27 | #define _I3(a) ((a).addr[3]) | |
28 | ||
b1a597e0 | 29 | #define MAX_PREFIX_LENGTH 128 |
25697773 | 30 | #define BITS_PER_IP_ADDRESS 128 |
6b5e06ab | 31 | #define STD_ADDRESS_P_LENGTH 39 |
3df89cef | 32 | #define SIZE_OF_IP_HEADER 40 |
25697773 | 33 | |
c40e05a0 MM |
34 | #define IPA_NONE _MI(0,0,0,0) |
35 | ||
1b3b3e34 OZ |
36 | #define ipa_equal(x,y) ({ ip_addr _a=(x), _b=(y); \ |
37 | _I0(_a) == _I0(_b) && \ | |
38 | _I1(_a) == _I1(_b) && \ | |
39 | _I2(_a) == _I2(_b) && \ | |
40 | _I3(_a) == _I3(_b); }) | |
dce26783 MM |
41 | #define ipa_nonzero(x) ({ ip_addr _a=(x); (_I0(_a) || _I1(_a) || _I2(_a) || _I3(_a)); }) |
42 | #define ipa_and(x,y) ({ ip_addr _a=(x), _b=(y); \ | |
43 | _MI(_I0(_a) & _I0(_b), \ | |
44 | _I1(_a) & _I1(_b), \ | |
45 | _I2(_a) & _I2(_b), \ | |
46 | _I3(_a) & _I3(_b)); }) | |
47 | #define ipa_or(x,y) ({ ip_addr _a=(x), _b=(y); \ | |
48 | _MI(_I0(_a) | _I0(_b), \ | |
49 | _I1(_a) | _I1(_b), \ | |
50 | _I2(_a) | _I2(_b), \ | |
51 | _I3(_a) | _I3(_b)); }) | |
52 | #define ipa_xor(x,y) ({ ip_addr _a=(x), _b=(y); \ | |
53 | _MI(_I0(_a) ^ _I0(_b), \ | |
54 | _I1(_a) ^ _I1(_b), \ | |
55 | _I2(_a) ^ _I2(_b), \ | |
56 | _I3(_a) ^ _I3(_b)); }) | |
57 | #define ipa_not(x) ({ ip_addr _a=(x); _MI(~_I0(_a),~_I1(_a),~_I2(_a),~_I3(_a)); }) | |
c40e05a0 | 58 | #define ipa_mkmask(x) ipv6_mkmask(x) |
18c8241a MM |
59 | #define ipa_mklen(x) ipv6_mklen(&(x)) |
60 | #define ipa_hash(x) ipv6_hash(&(x)) | |
e7d2ac44 | 61 | #define ipa_hash32(x) ipv6_hash32(&(x)) |
18c8241a MM |
62 | #define ipa_hton(x) ipv6_hton(&(x)) |
63 | #define ipa_ntoh(x) ipv6_ntoh(&(x)) | |
64 | #define ipa_classify(x) ipv6_classify(&(x)) | |
be862406 | 65 | #define ipa_has_link_scope(x) ipv6_has_link_scope(&(x)) |
ba321706 OZ |
66 | #define ipa_opposite_m1(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 1); }) |
67 | #define ipa_opposite_m2(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 3); }) | |
68 | /* ipa_class_mask don't make sense with IPv6 */ | |
dce26783 MM |
69 | /* ipa_from_u32 and ipa_to_u32 replaced by ipa_build */ |
70 | #define ipa_build(a,b,c,d) _MI(a,b,c,d) | |
12a9d139 | 71 | #define ipa_compare(x,y) ipv6_compare(x,y) |
b1a597e0 OZ |
72 | /* ipa_pxlen() requires that x != y */ |
73 | #define ipa_pxlen(x, y) ipv6_pxlen(x, y) | |
74 | #define ipa_getbit(x, y) ipv6_getbit(x, y) | |
cf31112f | 75 | #define ipa_put_addr(x, y) ipv6_put_addr(x, y) |
cfa6ab05 | 76 | #define ipa_absolutize(x,y) ipv6_absolutize(x,y) |
c40e05a0 | 77 | |
061ab802 OZ |
78 | /* In IPv6, SOCK_RAW does not return packet header */ |
79 | #define ip_skip_header(x, y) x | |
80 | ||
c40e05a0 | 81 | ip_addr ipv6_mkmask(unsigned); |
18c8241a MM |
82 | unsigned ipv6_mklen(ip_addr *); |
83 | int ipv6_classify(ip_addr *); | |
84 | void ipv6_hton(ip_addr *); | |
85 | void ipv6_ntoh(ip_addr *); | |
12a9d139 | 86 | int ipv6_compare(ip_addr, ip_addr); |
dce26783 | 87 | int ipv4_pton_u32(char *, u32 *); |
cfa6ab05 | 88 | void ipv6_absolutize(ip_addr *, ip_addr *); |
18c8241a | 89 | |
be862406 OZ |
90 | static inline int ipv6_has_link_scope(ip_addr *a) |
91 | { | |
92 | return ((a->addr[0] & 0xffc00000) == 0xfe800000); | |
93 | } | |
94 | ||
4ebbbd40 MM |
95 | /* |
96 | * This hash function looks well, but once IPv6 enters | |
97 | * mainstream use, we need to check that it has good | |
98 | * distribution properties on real routing tables. | |
99 | */ | |
100 | ||
18c8241a MM |
101 | static inline unsigned ipv6_hash(ip_addr *a) |
102 | { | |
dce26783 | 103 | /* Returns a 16-bit hash key */ |
18c8241a | 104 | u32 x = _I0(*a) ^ _I1(*a) ^ _I2(*a) ^ _I3(*a); |
a6f250f5 | 105 | return (x ^ (x >> 16) ^ (x >> 8)) & 0xffff; |
18c8241a | 106 | } |
c40e05a0 | 107 | |
e7d2ac44 OZ |
108 | static inline u32 ipv6_hash32(ip_addr *a) |
109 | { | |
110 | /* Returns a 32-bit hash key, although low-order bits are not ixed */ | |
111 | u32 x = _I0(*a) ^ _I1(*a) ^ _I2(*a) ^ _I3(*a); | |
112 | return x ^ (x << 16) ^ (x << 24); | |
113 | } | |
114 | ||
b1a597e0 OZ |
115 | static inline u32 ipv6_getbit(ip_addr a, u32 y) |
116 | { | |
117 | return a.addr[y / 32] & (0x80000000 >> (y % 32)); | |
118 | } | |
119 | ||
120 | static inline u32 ipv6_pxlen(ip_addr a, ip_addr b) | |
121 | { | |
122 | int i = 0; | |
123 | i+= (a.addr[i] == b.addr[i]); | |
124 | i+= (a.addr[i] == b.addr[i]); | |
125 | i+= (a.addr[i] == b.addr[i]); | |
126 | i+= (a.addr[i] == b.addr[i]); | |
127 | return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]); | |
128 | } | |
129 | ||
cf31112f OZ |
130 | static inline byte * ipv6_put_addr(byte *buf, ip_addr a) |
131 | { | |
132 | put_u32(buf+0, _I0(a)); | |
133 | put_u32(buf+4, _I1(a)); | |
134 | put_u32(buf+8, _I2(a)); | |
135 | put_u32(buf+12, _I3(a)); | |
136 | return buf+16; | |
137 | } | |
138 | ||
ef4a50be | 139 | #define IP_PREC_INTERNET_CONTROL 0xc0 |
dce26783 | 140 | |
c40e05a0 | 141 | #endif |