iof-bird-daemon / lib / net.h @ 04632fd7
History | View | Annotate | Download (7.13 KB)
1 |
/*
|
---|---|
2 |
* BIRD Internet Routing Daemon -- Network addresses
|
3 |
*
|
4 |
* (c) 2015 Ondrej Zajicek <santiago@crfreenet.org>
|
5 |
* (c) 2015 CZ.NIC z.s.p.o.
|
6 |
*
|
7 |
* Can be freely distributed and used under the terms of the GNU GPL.
|
8 |
*/
|
9 |
|
10 |
#ifndef _BIRD_NET_H_
|
11 |
#define _BIRD_NET_H_
|
12 |
|
13 |
#include "lib/ip.h" |
14 |
|
15 |
|
16 |
#define NET_IP4 1 |
17 |
#define NET_IP6 2 |
18 |
#define NET_VPN4 3 |
19 |
#define NET_VPN6 4 |
20 |
#define NET_MAX 5 |
21 |
|
22 |
typedef struct net_addr { |
23 |
u8 type; |
24 |
u8 pxlen; |
25 |
u16 length; |
26 |
u8 data[16];
|
27 |
u64 align[0];
|
28 |
} net_addr; |
29 |
|
30 |
typedef struct net_addr_ip4 { |
31 |
u8 type; |
32 |
u8 pxlen; |
33 |
u16 length; |
34 |
ip4_addr prefix; |
35 |
} net_addr_ip4; |
36 |
|
37 |
typedef struct net_addr_ip6 { |
38 |
u8 type; |
39 |
u8 pxlen; |
40 |
u16 length; |
41 |
ip6_addr prefix; |
42 |
} net_addr_ip6; |
43 |
|
44 |
typedef struct net_addr_vpn4 { |
45 |
u8 type; |
46 |
u8 pxlen; |
47 |
u16 length; |
48 |
ip4_addr prefix; |
49 |
u64 rd; |
50 |
} net_addr_vpn4; |
51 |
|
52 |
typedef struct net_addr_vpn6 { |
53 |
u8 type; |
54 |
u8 pxlen; |
55 |
u16 length; |
56 |
ip6_addr prefix; |
57 |
u64 rd; |
58 |
} net_addr_vpn6; |
59 |
|
60 |
|
61 |
typedef union net_addr_union { |
62 |
net_addr n; |
63 |
net_addr_ip4 ip4; |
64 |
net_addr_ip6 ip6; |
65 |
net_addr_vpn4 vpn4; |
66 |
net_addr_vpn6 vpn6; |
67 |
} net_addr_union; |
68 |
|
69 |
|
70 |
extern const u16 net_addr_length[]; |
71 |
extern const u8 net_max_prefix_length[]; |
72 |
extern const u16 net_max_text_length[]; |
73 |
|
74 |
#define NET_MAX_TEXT_LENGTH 65 |
75 |
|
76 |
|
77 |
#define NET_ADDR_IP4(prefix,pxlen) \
|
78 |
((net_addr_ip4) { NET_IP4, pxlen, sizeof(net_addr_ip4), prefix })
|
79 |
|
80 |
#define NET_ADDR_IP6(prefix,pxlen) \
|
81 |
((net_addr_ip6) { NET_IP6, pxlen, sizeof(net_addr_ip6), prefix })
|
82 |
|
83 |
#define NET_ADDR_VPN4(prefix,pxlen,rd) \
|
84 |
((net_addr_vpn4) { NET_VPN4, pxlen, sizeof(net_addr_vpn4), prefix, rd })
|
85 |
|
86 |
#define NET_ADDR_VPN6(prefix,pxlen,rd) \
|
87 |
((net_addr_vpn6) { NET_VPN6, pxlen, sizeof(net_addr_vpn6), prefix, rd })
|
88 |
|
89 |
|
90 |
static inline void net_fill_ip4(net_addr *a, ip4_addr prefix, uint pxlen) |
91 |
{ *(net_addr_ip4 *)a = NET_ADDR_IP4(prefix, pxlen); } |
92 |
|
93 |
static inline void net_fill_ip6(net_addr *a, ip6_addr prefix, uint pxlen) |
94 |
{ *(net_addr_ip6 *)a = NET_ADDR_IP6(prefix, pxlen); } |
95 |
|
96 |
static inline void net_fill_vpn4(net_addr *a, ip4_addr prefix, uint pxlen, u64 rd) |
97 |
{ *(net_addr_vpn4 *)a = NET_ADDR_VPN4(prefix, pxlen, rd); } |
98 |
|
99 |
static inline void net_fill_vpn6(net_addr *a, ip6_addr prefix, uint pxlen, u64 rd) |
100 |
{ *(net_addr_vpn6 *)a = NET_ADDR_VPN6(prefix, pxlen, rd); } |
101 |
|
102 |
static inline void net_fill_ipa(net_addr *a, ip_addr prefix, uint pxlen) |
103 |
{ |
104 |
if (ipa_is_ip4(prefix))
|
105 |
net_fill_ip4(a, ipa_to_ip4(prefix), pxlen); |
106 |
else
|
107 |
net_fill_ip6(a, ipa_to_ip6(prefix), pxlen); |
108 |
} |
109 |
|
110 |
static inline void net_fill_ip_host(net_addr *a, ip_addr prefix) |
111 |
{ |
112 |
if (ipa_is_ip4(prefix))
|
113 |
net_fill_ip4(a, ipa_to_ip4(prefix), IP4_MAX_PREFIX_LENGTH); |
114 |
else
|
115 |
net_fill_ip6(a, ipa_to_ip6(prefix), IP6_MAX_PREFIX_LENGTH); |
116 |
} |
117 |
|
118 |
static inline int net_is_ip(const net_addr *a) |
119 |
{ return (a->type == NET_IP4) || (a->type == NET_IP6); }
|
120 |
|
121 |
|
122 |
static inline ip4_addr net4_prefix(const net_addr *a) |
123 |
{ return ((net_addr_ip4 *) a)->prefix; }
|
124 |
|
125 |
static inline ip6_addr net6_prefix(const net_addr *a) |
126 |
{ return ((net_addr_ip6 *) a)->prefix; }
|
127 |
|
128 |
static inline ip_addr net_prefix(const net_addr *a) |
129 |
{ |
130 |
switch (a->type)
|
131 |
{ |
132 |
case NET_IP4:
|
133 |
case NET_VPN4: return ipa_from_ip4(net4_prefix(a)); |
134 |
case NET_IP6:
|
135 |
case NET_VPN6: return ipa_from_ip6(net6_prefix(a)); |
136 |
default: return IPA_NONE; |
137 |
} |
138 |
} |
139 |
|
140 |
static inline uint net4_pxlen(const net_addr *a) |
141 |
{ return a->pxlen; }
|
142 |
|
143 |
static inline uint net6_pxlen(const net_addr *a) |
144 |
{ return a->pxlen; }
|
145 |
|
146 |
static inline uint net_pxlen(const net_addr *a) |
147 |
{ return a->pxlen; }
|
148 |
|
149 |
ip_addr net_pxmask(const net_addr *a);
|
150 |
|
151 |
|
152 |
static inline int net_equal(const net_addr *a, const net_addr *b) |
153 |
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
|
154 |
|
155 |
static inline int net_equal_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) |
156 |
{ return !memcmp(a, b, sizeof(net_addr_ip4)); } |
157 |
|
158 |
static inline int net_equal_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) |
159 |
{ return !memcmp(a, b, sizeof(net_addr_ip6)); } |
160 |
|
161 |
static inline int net_equal_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b) |
162 |
{ return !memcmp(a, b, sizeof(net_addr_vpn4)); } |
163 |
|
164 |
static inline int net_equal_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b) |
165 |
{ return !memcmp(a, b, sizeof(net_addr_vpn6)); } |
166 |
|
167 |
|
168 |
static inline int net_zero_ip4(const net_addr_ip4 *a) |
169 |
{ return !a->pxlen && ip4_zero(a->prefix); }
|
170 |
|
171 |
static inline int net_zero_ip6(const net_addr_ip6 *a) |
172 |
{ return !a->pxlen && ip6_zero(a->prefix); }
|
173 |
|
174 |
static inline int net_zero_vpn4(const net_addr_vpn4 *a) |
175 |
{ return !a->pxlen && ip4_zero(a->prefix) && !a->rd; }
|
176 |
|
177 |
static inline int net_zero_vpn6(const net_addr_vpn6 *a) |
178 |
{ return !a->pxlen && ip6_zero(a->prefix) && !a->rd; }
|
179 |
|
180 |
|
181 |
static inline int net_compare_ip4(const net_addr_ip4 *a, const net_addr_ip4 *b) |
182 |
{ return ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
183 |
|
184 |
static inline int net_compare_ip6(const net_addr_ip6 *a, const net_addr_ip6 *b) |
185 |
{ return ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
186 |
|
187 |
static inline int net_compare_vpn4(const net_addr_vpn4 *a, const net_addr_vpn4 *b) |
188 |
{ return u64_cmp(a->rd, b->rd) ?: ip4_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
189 |
|
190 |
static inline int net_compare_vpn6(const net_addr_vpn6 *a, const net_addr_vpn6 *b) |
191 |
{ return u64_cmp(a->rd, b->rd) ?: ip6_compare(a->prefix, b->prefix) ?: uint_cmp(a->pxlen, b->pxlen); }
|
192 |
|
193 |
int net_compare(const net_addr *a, const net_addr *b); |
194 |
|
195 |
|
196 |
static inline void net_copy(net_addr *dst, const net_addr *src) |
197 |
{ memcpy(dst, src, src->length); } |
198 |
|
199 |
static inline void net_copy_ip4(net_addr_ip4 *dst, const net_addr_ip4 *src) |
200 |
{ memcpy(dst, src, sizeof(net_addr_ip4)); }
|
201 |
|
202 |
static inline void net_copy_ip6(net_addr_ip6 *dst, const net_addr_ip6 *src) |
203 |
{ memcpy(dst, src, sizeof(net_addr_ip6)); }
|
204 |
|
205 |
static inline void net_copy_vpn4(net_addr_vpn4 *dst, const net_addr_vpn4 *src) |
206 |
{ memcpy(dst, src, sizeof(net_addr_vpn4)); }
|
207 |
|
208 |
static inline void net_copy_vpn6(net_addr_vpn6 *dst, const net_addr_vpn6 *src) |
209 |
{ memcpy(dst, src, sizeof(net_addr_vpn6)); }
|
210 |
|
211 |
|
212 |
static inline u32 net_hash_ip4(const net_addr_ip4 *n) |
213 |
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
214 |
|
215 |
static inline u32 net_hash_ip6(const net_addr_ip6 *n) |
216 |
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26); } |
217 |
|
218 |
/* XXXX */
|
219 |
static inline u32 u64_hash(u64 a) |
220 |
{ return u32_hash(a); }
|
221 |
|
222 |
static inline u32 net_hash_vpn4(const net_addr_vpn4 *n) |
223 |
{ return ip4_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } |
224 |
|
225 |
static inline u32 net_hash_vpn6(const net_addr_vpn6 *n) |
226 |
{ return ip6_hash(n->prefix) ^ ((u32) n->pxlen << 26) ^ u64_hash(n->rd); } |
227 |
|
228 |
|
229 |
static inline int net_validate_ip4(const net_addr_ip4 *n) |
230 |
{ |
231 |
return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) &&
|
232 |
ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen)))); |
233 |
} |
234 |
|
235 |
static inline int net_validate_ip6(const net_addr_ip6 *n) |
236 |
{ |
237 |
return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) &&
|
238 |
ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen)))); |
239 |
} |
240 |
|
241 |
int net_validate(const net_addr *N); |
242 |
|
243 |
|
244 |
static inline void net_normalize_ip4(net_addr_ip4 *n) |
245 |
{ n->prefix = ip4_and(n->prefix, ip4_mkmask(n->pxlen)); } |
246 |
|
247 |
static inline void net_normalize_ip6(net_addr_ip6 *n) |
248 |
{ n->prefix = ip6_and(n->prefix, ip6_mkmask(n->pxlen)); } |
249 |
|
250 |
void net_normalize(net_addr *N);
|
251 |
|
252 |
|
253 |
int net_classify(const net_addr *N); |
254 |
int net_format(const net_addr *N, char *buf, int buflen); |
255 |
|
256 |
|
257 |
int ipa_in_netX(const ip_addr A, const net_addr *N); |
258 |
int net_in_netX(const net_addr *A, const net_addr *N); |
259 |
|
260 |
|
261 |
#endif
|