]>
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)) | |
61 | #define ipa_hton(x) ipv6_hton(&(x)) | |
62 | #define ipa_ntoh(x) ipv6_ntoh(&(x)) | |
63 | #define ipa_classify(x) ipv6_classify(&(x)) | |
be862406 | 64 | #define ipa_has_link_scope(x) ipv6_has_link_scope(&(x)) |
ba321706 OZ |
65 | #define ipa_opposite_m1(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 1); }) |
66 | #define ipa_opposite_m2(x) ({ ip_addr _a=(x); _MI(_I0(_a),_I1(_a),_I2(_a),_I3(_a) ^ 3); }) | |
67 | /* ipa_class_mask don't make sense with IPv6 */ | |
dce26783 MM |
68 | /* ipa_from_u32 and ipa_to_u32 replaced by ipa_build */ |
69 | #define ipa_build(a,b,c,d) _MI(a,b,c,d) | |
12a9d139 | 70 | #define ipa_compare(x,y) ipv6_compare(x,y) |
b1a597e0 OZ |
71 | /* ipa_pxlen() requires that x != y */ |
72 | #define ipa_pxlen(x, y) ipv6_pxlen(x, y) | |
73 | #define ipa_getbit(x, y) ipv6_getbit(x, y) | |
cf31112f | 74 | #define ipa_put_addr(x, y) ipv6_put_addr(x, y) |
cfa6ab05 | 75 | #define ipa_absolutize(x,y) ipv6_absolutize(x,y) |
c40e05a0 | 76 | |
061ab802 OZ |
77 | /* In IPv6, SOCK_RAW does not return packet header */ |
78 | #define ip_skip_header(x, y) x | |
79 | ||
c40e05a0 | 80 | ip_addr ipv6_mkmask(unsigned); |
18c8241a MM |
81 | unsigned ipv6_mklen(ip_addr *); |
82 | int ipv6_classify(ip_addr *); | |
83 | void ipv6_hton(ip_addr *); | |
84 | void ipv6_ntoh(ip_addr *); | |
12a9d139 | 85 | int ipv6_compare(ip_addr, ip_addr); |
dce26783 | 86 | int ipv4_pton_u32(char *, u32 *); |
cfa6ab05 | 87 | void ipv6_absolutize(ip_addr *, ip_addr *); |
18c8241a | 88 | |
be862406 OZ |
89 | static inline int ipv6_has_link_scope(ip_addr *a) |
90 | { | |
91 | return ((a->addr[0] & 0xffc00000) == 0xfe800000); | |
92 | } | |
93 | ||
4ebbbd40 MM |
94 | /* |
95 | * This hash function looks well, but once IPv6 enters | |
96 | * mainstream use, we need to check that it has good | |
97 | * distribution properties on real routing tables. | |
98 | */ | |
99 | ||
18c8241a MM |
100 | static inline unsigned ipv6_hash(ip_addr *a) |
101 | { | |
dce26783 | 102 | /* Returns a 16-bit hash key */ |
18c8241a | 103 | u32 x = _I0(*a) ^ _I1(*a) ^ _I2(*a) ^ _I3(*a); |
a6f250f5 | 104 | return (x ^ (x >> 16) ^ (x >> 8)) & 0xffff; |
18c8241a | 105 | } |
c40e05a0 | 106 | |
b1a597e0 OZ |
107 | static inline u32 ipv6_getbit(ip_addr a, u32 y) |
108 | { | |
109 | return a.addr[y / 32] & (0x80000000 >> (y % 32)); | |
110 | } | |
111 | ||
112 | static inline u32 ipv6_pxlen(ip_addr a, ip_addr b) | |
113 | { | |
114 | int i = 0; | |
115 | i+= (a.addr[i] == b.addr[i]); | |
116 | i+= (a.addr[i] == b.addr[i]); | |
117 | i+= (a.addr[i] == b.addr[i]); | |
118 | i+= (a.addr[i] == b.addr[i]); | |
119 | return 32 * i + 31 - u32_log2(a.addr[i] ^ b.addr[i]); | |
120 | } | |
121 | ||
cf31112f OZ |
122 | static inline byte * ipv6_put_addr(byte *buf, ip_addr a) |
123 | { | |
124 | put_u32(buf+0, _I0(a)); | |
125 | put_u32(buf+4, _I1(a)); | |
126 | put_u32(buf+8, _I2(a)); | |
127 | put_u32(buf+12, _I3(a)); | |
128 | return buf+16; | |
129 | } | |
130 | ||
ef4a50be | 131 | #define IP_PREC_INTERNET_CONTROL 0xc0 |
dce26783 | 132 | |
c40e05a0 | 133 | #endif |