diff options
Diffstat (limited to 'include/net/ipv6.h')
-rw-r--r-- | include/net/ipv6.h | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h new file mode 100644 index 000000000000..87c45cbfbaf6 --- /dev/null +++ b/include/net/ipv6.h | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * Linux INET6 implementation | ||
3 | * | ||
4 | * Authors: | ||
5 | * Pedro Roque <roque@di.fc.ul.pt> | ||
6 | * | ||
7 | * $Id: ipv6.h,v 1.1 2002/05/20 15:13:07 jgrimm Exp $ | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #ifndef _NET_IPV6_H | ||
16 | #define _NET_IPV6_H | ||
17 | |||
18 | #include <linux/ipv6.h> | ||
19 | #include <linux/hardirq.h> | ||
20 | #include <net/ndisc.h> | ||
21 | #include <net/flow.h> | ||
22 | #include <net/snmp.h> | ||
23 | |||
24 | #define SIN6_LEN_RFC2133 24 | ||
25 | |||
26 | #define IPV6_MAXPLEN 65535 | ||
27 | |||
28 | /* | ||
29 | * NextHeader field of IPv6 header | ||
30 | */ | ||
31 | |||
32 | #define NEXTHDR_HOP 0 /* Hop-by-hop option header. */ | ||
33 | #define NEXTHDR_TCP 6 /* TCP segment. */ | ||
34 | #define NEXTHDR_UDP 17 /* UDP message. */ | ||
35 | #define NEXTHDR_IPV6 41 /* IPv6 in IPv6 */ | ||
36 | #define NEXTHDR_ROUTING 43 /* Routing header. */ | ||
37 | #define NEXTHDR_FRAGMENT 44 /* Fragmentation/reassembly header. */ | ||
38 | #define NEXTHDR_ESP 50 /* Encapsulating security payload. */ | ||
39 | #define NEXTHDR_AUTH 51 /* Authentication header. */ | ||
40 | #define NEXTHDR_ICMP 58 /* ICMP for IPv6. */ | ||
41 | #define NEXTHDR_NONE 59 /* No next header */ | ||
42 | #define NEXTHDR_DEST 60 /* Destination options header. */ | ||
43 | |||
44 | #define NEXTHDR_MAX 255 | ||
45 | |||
46 | |||
47 | |||
48 | #define IPV6_DEFAULT_HOPLIMIT 64 | ||
49 | #define IPV6_DEFAULT_MCASTHOPS 1 | ||
50 | |||
51 | /* | ||
52 | * Addr type | ||
53 | * | ||
54 | * type - unicast | multicast | ||
55 | * scope - local | site | global | ||
56 | * v4 - compat | ||
57 | * v4mapped | ||
58 | * any | ||
59 | * loopback | ||
60 | */ | ||
61 | |||
62 | #define IPV6_ADDR_ANY 0x0000U | ||
63 | |||
64 | #define IPV6_ADDR_UNICAST 0x0001U | ||
65 | #define IPV6_ADDR_MULTICAST 0x0002U | ||
66 | |||
67 | #define IPV6_ADDR_LOOPBACK 0x0010U | ||
68 | #define IPV6_ADDR_LINKLOCAL 0x0020U | ||
69 | #define IPV6_ADDR_SITELOCAL 0x0040U | ||
70 | |||
71 | #define IPV6_ADDR_COMPATv4 0x0080U | ||
72 | |||
73 | #define IPV6_ADDR_SCOPE_MASK 0x00f0U | ||
74 | |||
75 | #define IPV6_ADDR_MAPPED 0x1000U | ||
76 | #define IPV6_ADDR_RESERVED 0x2000U /* reserved address space */ | ||
77 | |||
78 | /* | ||
79 | * Addr scopes | ||
80 | */ | ||
81 | #ifdef __KERNEL__ | ||
82 | #define IPV6_ADDR_MC_SCOPE(a) \ | ||
83 | ((a)->s6_addr[1] & 0x0f) /* nonstandard */ | ||
84 | #define __IPV6_ADDR_SCOPE_INVALID -1 | ||
85 | #endif | ||
86 | #define IPV6_ADDR_SCOPE_NODELOCAL 0x01 | ||
87 | #define IPV6_ADDR_SCOPE_LINKLOCAL 0x02 | ||
88 | #define IPV6_ADDR_SCOPE_SITELOCAL 0x05 | ||
89 | #define IPV6_ADDR_SCOPE_ORGLOCAL 0x08 | ||
90 | #define IPV6_ADDR_SCOPE_GLOBAL 0x0e | ||
91 | |||
92 | /* | ||
93 | * fragmentation header | ||
94 | */ | ||
95 | |||
96 | struct frag_hdr { | ||
97 | unsigned char nexthdr; | ||
98 | unsigned char reserved; | ||
99 | unsigned short frag_off; | ||
100 | __u32 identification; | ||
101 | }; | ||
102 | |||
103 | #define IP6_MF 0x0001 | ||
104 | |||
105 | #ifdef __KERNEL__ | ||
106 | |||
107 | #include <net/sock.h> | ||
108 | |||
109 | /* sysctls */ | ||
110 | extern int sysctl_ipv6_bindv6only; | ||
111 | extern int sysctl_mld_max_msf; | ||
112 | |||
113 | /* MIBs */ | ||
114 | DECLARE_SNMP_STAT(struct ipstats_mib, ipv6_statistics); | ||
115 | #define IP6_INC_STATS(field) SNMP_INC_STATS(ipv6_statistics, field) | ||
116 | #define IP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(ipv6_statistics, field) | ||
117 | #define IP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(ipv6_statistics, field) | ||
118 | DECLARE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics); | ||
119 | #define ICMP6_INC_STATS(idev, field) ({ \ | ||
120 | struct inet6_dev *_idev = (idev); \ | ||
121 | if (likely(_idev != NULL)) \ | ||
122 | SNMP_INC_STATS(idev->stats.icmpv6, field); \ | ||
123 | SNMP_INC_STATS(icmpv6_statistics, field); \ | ||
124 | }) | ||
125 | #define ICMP6_INC_STATS_BH(idev, field) ({ \ | ||
126 | struct inet6_dev *_idev = (idev); \ | ||
127 | if (likely(_idev != NULL)) \ | ||
128 | SNMP_INC_STATS_BH((_idev)->stats.icmpv6, field); \ | ||
129 | SNMP_INC_STATS_BH(icmpv6_statistics, field); \ | ||
130 | }) | ||
131 | #define ICMP6_INC_STATS_USER(idev, field) ({ \ | ||
132 | struct inet6_dev *_idev = (idev); \ | ||
133 | if (likely(_idev != NULL)) \ | ||
134 | SNMP_INC_STATS_USER(_idev->stats.icmpv6, field); \ | ||
135 | SNMP_INC_STATS_USER(icmpv6_statistics, field); \ | ||
136 | }) | ||
137 | #define ICMP6_INC_STATS_OFFSET_BH(idev, field, offset) ({ \ | ||
138 | struct inet6_dev *_idev = idev; \ | ||
139 | __typeof__(offset) _offset = (offset); \ | ||
140 | if (likely(_idev != NULL)) \ | ||
141 | SNMP_INC_STATS_OFFSET_BH(_idev->stats.icmpv6, field, _offset); \ | ||
142 | SNMP_INC_STATS_OFFSET_BH(icmpv6_statistics, field, _offset); \ | ||
143 | }) | ||
144 | DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6); | ||
145 | #define UDP6_INC_STATS(field) SNMP_INC_STATS(udp_stats_in6, field) | ||
146 | #define UDP6_INC_STATS_BH(field) SNMP_INC_STATS_BH(udp_stats_in6, field) | ||
147 | #define UDP6_INC_STATS_USER(field) SNMP_INC_STATS_USER(udp_stats_in6, field) | ||
148 | extern atomic_t inet6_sock_nr; | ||
149 | |||
150 | int snmp6_register_dev(struct inet6_dev *idev); | ||
151 | int snmp6_unregister_dev(struct inet6_dev *idev); | ||
152 | int snmp6_alloc_dev(struct inet6_dev *idev); | ||
153 | int snmp6_free_dev(struct inet6_dev *idev); | ||
154 | int snmp6_mib_init(void *ptr[2], size_t mibsize, size_t mibalign); | ||
155 | void snmp6_mib_free(void *ptr[2]); | ||
156 | |||
157 | struct ip6_ra_chain | ||
158 | { | ||
159 | struct ip6_ra_chain *next; | ||
160 | struct sock *sk; | ||
161 | int sel; | ||
162 | void (*destructor)(struct sock *); | ||
163 | }; | ||
164 | |||
165 | extern struct ip6_ra_chain *ip6_ra_chain; | ||
166 | extern rwlock_t ip6_ra_lock; | ||
167 | |||
168 | /* | ||
169 | This structure is prepared by protocol, when parsing | ||
170 | ancillary data and passed to IPv6. | ||
171 | */ | ||
172 | |||
173 | struct ipv6_txoptions | ||
174 | { | ||
175 | /* Length of this structure */ | ||
176 | int tot_len; | ||
177 | |||
178 | /* length of extension headers */ | ||
179 | |||
180 | __u16 opt_flen; /* after fragment hdr */ | ||
181 | __u16 opt_nflen; /* before fragment hdr */ | ||
182 | |||
183 | struct ipv6_opt_hdr *hopopt; | ||
184 | struct ipv6_opt_hdr *dst0opt; | ||
185 | struct ipv6_rt_hdr *srcrt; /* Routing Header */ | ||
186 | struct ipv6_opt_hdr *auth; | ||
187 | struct ipv6_opt_hdr *dst1opt; | ||
188 | |||
189 | /* Option buffer, as read by IPV6_PKTOPTIONS, starts here. */ | ||
190 | }; | ||
191 | |||
192 | struct ip6_flowlabel | ||
193 | { | ||
194 | struct ip6_flowlabel *next; | ||
195 | u32 label; | ||
196 | struct in6_addr dst; | ||
197 | struct ipv6_txoptions *opt; | ||
198 | atomic_t users; | ||
199 | unsigned long linger; | ||
200 | u8 share; | ||
201 | u32 owner; | ||
202 | unsigned long lastuse; | ||
203 | unsigned long expires; | ||
204 | }; | ||
205 | |||
206 | #define IPV6_FLOWINFO_MASK __constant_htonl(0x0FFFFFFF) | ||
207 | #define IPV6_FLOWLABEL_MASK __constant_htonl(0x000FFFFF) | ||
208 | |||
209 | struct ipv6_fl_socklist | ||
210 | { | ||
211 | struct ipv6_fl_socklist *next; | ||
212 | struct ip6_flowlabel *fl; | ||
213 | }; | ||
214 | |||
215 | extern struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, u32 label); | ||
216 | extern struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, | ||
217 | struct ip6_flowlabel * fl, | ||
218 | struct ipv6_txoptions * fopt); | ||
219 | extern void fl6_free_socklist(struct sock *sk); | ||
220 | extern int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen); | ||
221 | extern void ip6_flowlabel_init(void); | ||
222 | extern void ip6_flowlabel_cleanup(void); | ||
223 | |||
224 | static inline void fl6_sock_release(struct ip6_flowlabel *fl) | ||
225 | { | ||
226 | if (fl) | ||
227 | atomic_dec(&fl->users); | ||
228 | } | ||
229 | |||
230 | extern int ip6_ra_control(struct sock *sk, int sel, | ||
231 | void (*destructor)(struct sock *)); | ||
232 | |||
233 | |||
234 | extern int ipv6_parse_hopopts(struct sk_buff *skb, int); | ||
235 | |||
236 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); | ||
237 | |||
238 | extern int ip6_frag_nqueues; | ||
239 | extern atomic_t ip6_frag_mem; | ||
240 | |||
241 | #define IPV6_FRAG_TIMEOUT (60*HZ) /* 60 seconds */ | ||
242 | |||
243 | /* | ||
244 | * Function prototype for build_xmit | ||
245 | */ | ||
246 | |||
247 | typedef int (*inet_getfrag_t) (const void *data, | ||
248 | struct in6_addr *addr, | ||
249 | char *, | ||
250 | unsigned int, unsigned int); | ||
251 | |||
252 | |||
253 | extern int ipv6_addr_type(const struct in6_addr *addr); | ||
254 | |||
255 | static inline int ipv6_addr_scope(const struct in6_addr *addr) | ||
256 | { | ||
257 | return ipv6_addr_type(addr) & IPV6_ADDR_SCOPE_MASK; | ||
258 | } | ||
259 | |||
260 | static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) | ||
261 | { | ||
262 | return memcmp((const void *) a1, (const void *) a2, sizeof(struct in6_addr)); | ||
263 | } | ||
264 | |||
265 | static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2) | ||
266 | { | ||
267 | memcpy((void *) a1, (const void *) a2, sizeof(struct in6_addr)); | ||
268 | } | ||
269 | |||
270 | static inline void ipv6_addr_prefix(struct in6_addr *pfx, | ||
271 | const struct in6_addr *addr, | ||
272 | int plen) | ||
273 | { | ||
274 | /* caller must guarantee 0 <= plen <= 128 */ | ||
275 | int o = plen >> 3, | ||
276 | b = plen & 0x7; | ||
277 | |||
278 | memcpy(pfx->s6_addr, addr, o); | ||
279 | if (b != 0) { | ||
280 | pfx->s6_addr[o] = addr->s6_addr[o] & (0xff00 >> b); | ||
281 | o++; | ||
282 | } | ||
283 | if (o < 16) | ||
284 | memset(pfx->s6_addr + o, 0, 16 - o); | ||
285 | } | ||
286 | |||
287 | #ifndef __HAVE_ARCH_ADDR_SET | ||
288 | static inline void ipv6_addr_set(struct in6_addr *addr, | ||
289 | __u32 w1, __u32 w2, | ||
290 | __u32 w3, __u32 w4) | ||
291 | { | ||
292 | addr->s6_addr32[0] = w1; | ||
293 | addr->s6_addr32[1] = w2; | ||
294 | addr->s6_addr32[2] = w3; | ||
295 | addr->s6_addr32[3] = w4; | ||
296 | } | ||
297 | #endif | ||
298 | |||
299 | static inline int ipv6_addr_equal(const struct in6_addr *a1, | ||
300 | const struct in6_addr *a2) | ||
301 | { | ||
302 | return (a1->s6_addr32[0] == a2->s6_addr32[0] && | ||
303 | a1->s6_addr32[1] == a2->s6_addr32[1] && | ||
304 | a1->s6_addr32[2] == a2->s6_addr32[2] && | ||
305 | a1->s6_addr32[3] == a2->s6_addr32[3]); | ||
306 | } | ||
307 | |||
308 | static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2, | ||
309 | unsigned int prefixlen) | ||
310 | { | ||
311 | unsigned pdw, pbi; | ||
312 | |||
313 | /* check complete u32 in prefix */ | ||
314 | pdw = prefixlen >> 5; | ||
315 | if (pdw && memcmp(a1, a2, pdw << 2)) | ||
316 | return 0; | ||
317 | |||
318 | /* check incomplete u32 in prefix */ | ||
319 | pbi = prefixlen & 0x1f; | ||
320 | if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) | ||
321 | return 0; | ||
322 | |||
323 | return 1; | ||
324 | } | ||
325 | |||
326 | static inline int ipv6_prefix_equal(const struct in6_addr *a1, | ||
327 | const struct in6_addr *a2, | ||
328 | unsigned int prefixlen) | ||
329 | { | ||
330 | return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32, | ||
331 | prefixlen); | ||
332 | } | ||
333 | |||
334 | static inline int ipv6_addr_any(const struct in6_addr *a) | ||
335 | { | ||
336 | return ((a->s6_addr32[0] | a->s6_addr32[1] | | ||
337 | a->s6_addr32[2] | a->s6_addr32[3] ) == 0); | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * Prototypes exported by ipv6 | ||
342 | */ | ||
343 | |||
344 | /* | ||
345 | * rcv function (called from netdevice level) | ||
346 | */ | ||
347 | |||
348 | extern int ipv6_rcv(struct sk_buff *skb, | ||
349 | struct net_device *dev, | ||
350 | struct packet_type *pt); | ||
351 | |||
352 | /* | ||
353 | * upper-layer output functions | ||
354 | */ | ||
355 | extern int ip6_xmit(struct sock *sk, | ||
356 | struct sk_buff *skb, | ||
357 | struct flowi *fl, | ||
358 | struct ipv6_txoptions *opt, | ||
359 | int ipfragok); | ||
360 | |||
361 | extern int ip6_nd_hdr(struct sock *sk, | ||
362 | struct sk_buff *skb, | ||
363 | struct net_device *dev, | ||
364 | struct in6_addr *saddr, | ||
365 | struct in6_addr *daddr, | ||
366 | int proto, int len); | ||
367 | |||
368 | extern int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr); | ||
369 | |||
370 | extern int ip6_append_data(struct sock *sk, | ||
371 | int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), | ||
372 | void *from, | ||
373 | int length, | ||
374 | int transhdrlen, | ||
375 | int hlimit, | ||
376 | struct ipv6_txoptions *opt, | ||
377 | struct flowi *fl, | ||
378 | struct rt6_info *rt, | ||
379 | unsigned int flags); | ||
380 | |||
381 | extern int ip6_push_pending_frames(struct sock *sk); | ||
382 | |||
383 | extern void ip6_flush_pending_frames(struct sock *sk); | ||
384 | |||
385 | extern int ip6_dst_lookup(struct sock *sk, | ||
386 | struct dst_entry **dst, | ||
387 | struct flowi *fl); | ||
388 | |||
389 | /* | ||
390 | * skb processing functions | ||
391 | */ | ||
392 | |||
393 | extern int ip6_output(struct sk_buff *skb); | ||
394 | extern int ip6_forward(struct sk_buff *skb); | ||
395 | extern int ip6_input(struct sk_buff *skb); | ||
396 | extern int ip6_mc_input(struct sk_buff *skb); | ||
397 | |||
398 | /* | ||
399 | * Extension header (options) processing | ||
400 | */ | ||
401 | |||
402 | extern u8 * ipv6_build_nfrag_opts(struct sk_buff *skb, | ||
403 | u8 *prev_hdr, | ||
404 | struct ipv6_txoptions *opt, | ||
405 | struct in6_addr *daddr, | ||
406 | u32 jumbolen); | ||
407 | extern u8 * ipv6_build_frag_opts(struct sk_buff *skb, | ||
408 | u8 *prev_hdr, | ||
409 | struct ipv6_txoptions *opt); | ||
410 | extern void ipv6_push_nfrag_opts(struct sk_buff *skb, | ||
411 | struct ipv6_txoptions *opt, | ||
412 | u8 *proto, | ||
413 | struct in6_addr **daddr_p); | ||
414 | extern void ipv6_push_frag_opts(struct sk_buff *skb, | ||
415 | struct ipv6_txoptions *opt, | ||
416 | u8 *proto); | ||
417 | |||
418 | extern int ipv6_skip_exthdr(const struct sk_buff *, int start, | ||
419 | u8 *nexthdrp, int len); | ||
420 | |||
421 | extern int ipv6_ext_hdr(u8 nexthdr); | ||
422 | |||
423 | extern struct ipv6_txoptions * ipv6_invert_rthdr(struct sock *sk, | ||
424 | struct ipv6_rt_hdr *hdr); | ||
425 | |||
426 | |||
427 | /* | ||
428 | * socket options (ipv6_sockglue.c) | ||
429 | */ | ||
430 | |||
431 | extern int ipv6_setsockopt(struct sock *sk, int level, | ||
432 | int optname, | ||
433 | char __user *optval, | ||
434 | int optlen); | ||
435 | extern int ipv6_getsockopt(struct sock *sk, int level, | ||
436 | int optname, | ||
437 | char __user *optval, | ||
438 | int __user *optlen); | ||
439 | |||
440 | extern void ipv6_packet_init(void); | ||
441 | |||
442 | extern void ipv6_packet_cleanup(void); | ||
443 | |||
444 | extern int ip6_datagram_connect(struct sock *sk, | ||
445 | struct sockaddr *addr, int addr_len); | ||
446 | |||
447 | extern int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len); | ||
448 | extern void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, u16 port, | ||
449 | u32 info, u8 *payload); | ||
450 | extern void ipv6_local_error(struct sock *sk, int err, struct flowi *fl, u32 info); | ||
451 | |||
452 | extern int inet6_release(struct socket *sock); | ||
453 | extern int inet6_bind(struct socket *sock, struct sockaddr *uaddr, | ||
454 | int addr_len); | ||
455 | extern int inet6_getname(struct socket *sock, struct sockaddr *uaddr, | ||
456 | int *uaddr_len, int peer); | ||
457 | extern int inet6_ioctl(struct socket *sock, unsigned int cmd, | ||
458 | unsigned long arg); | ||
459 | |||
460 | /* | ||
461 | * reassembly.c | ||
462 | */ | ||
463 | extern int sysctl_ip6frag_high_thresh; | ||
464 | extern int sysctl_ip6frag_low_thresh; | ||
465 | extern int sysctl_ip6frag_time; | ||
466 | extern int sysctl_ip6frag_secret_interval; | ||
467 | |||
468 | #endif /* __KERNEL__ */ | ||
469 | #endif /* _NET_IPV6_H */ | ||
470 | |||
471 | |||
472 | |||