ipv6.h 11.3 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#ifndef _IPV6_H
#define _IPV6_H

#include <linux/in6.h>
#include <asm/byteorder.h>

/* The latest drafts declared increase in minimal mtu up to 1280. */

#define IPV6_MIN_MTU	1280

/*
 *	Advanced API
 *	source interface/address selection, source routing, etc...
 *	*under construction*
 */


struct in6_pktinfo {
	struct in6_addr	ipi6_addr;
	int		ipi6_ifindex;
};


struct in6_ifreq {
	struct in6_addr	ifr6_addr;
	__u32		ifr6_prefixlen;
	int		ifr6_ifindex; 
};

30 31
#define IPV6_SRCRT_STRICT	0x01	/* Deprecated; will be removed */
#define IPV6_SRCRT_TYPE_0	0	/* Deprecated; will be removed */
32
#define IPV6_SRCRT_TYPE_2	2	/* IPv6 type 2 Routing Header	*/
Linus Torvalds's avatar
Linus Torvalds committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/*
 *	routing header
 */
struct ipv6_rt_hdr {
	__u8		nexthdr;
	__u8		hdrlen;
	__u8		type;
	__u8		segments_left;

	/*
	 *	type specific data
	 *	variable length field
	 */
};


struct ipv6_opt_hdr {
	__u8 		nexthdr;
	__u8 		hdrlen;
	/* 
	 * TLV encoded option data follows.
	 */
56
} __attribute__ ((packed));	/* required for some archs */
Linus Torvalds's avatar
Linus Torvalds committed
57 58 59 60 61 62 63 64 65 66 67 68 69 70

#define ipv6_destopt_hdr ipv6_opt_hdr
#define ipv6_hopopt_hdr  ipv6_opt_hdr

#ifdef __KERNEL__
#define ipv6_optlen(p)  (((p)->hdrlen+1) << 3)
#endif

/*
 *	routing header type 0 (used in cmsghdr struct)
 */

struct rt0_hdr {
	struct ipv6_rt_hdr	rt_hdr;
71
	__u32			reserved;
Linus Torvalds's avatar
Linus Torvalds committed
72 73 74 75 76
	struct in6_addr		addr[0];

#define rt0_type		rt_hdr.type
};

77 78 79 80 81 82 83 84 85 86 87 88
/*
 *	routing header type 2
 */

struct rt2_hdr {
	struct ipv6_rt_hdr	rt_hdr;
	__u32			reserved;
	struct in6_addr		addr;

#define rt2_type		rt_hdr.type
};

89 90 91 92 93 94 95 96 97 98
/*
 *	home address option in destination options header
 */

struct ipv6_destopt_hao {
	__u8			type;
	__u8			length;
	struct in6_addr		addr;
} __attribute__ ((__packed__));

Linus Torvalds's avatar
Linus Torvalds committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/*
 *	IPv6 fixed header
 *
 *	BEWARE, it is incorrect. The first 4 bits of flow_lbl
 *	are glued to priority now, forming "class".
 */

struct ipv6hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
	__u8			priority:4,
				version:4;
#elif defined(__BIG_ENDIAN_BITFIELD)
	__u8			version:4,
				priority:4;
#else
#error	"Please fix <asm/byteorder.h>"
#endif
	__u8			flow_lbl[3];

Al Viro's avatar
Al Viro committed
118
	__be16			payload_len;
Linus Torvalds's avatar
Linus Torvalds committed
119 120 121 122 123 124 125
	__u8			nexthdr;
	__u8			hop_limit;

	struct	in6_addr	saddr;
	struct	in6_addr	daddr;
};

126
#ifdef __KERNEL__
Linus Torvalds's avatar
Linus Torvalds committed
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
/*
 * This structure contains configuration options per IPv6 link.
 */
struct ipv6_devconf {
	__s32		forwarding;
	__s32		hop_limit;
	__s32		mtu6;
	__s32		accept_ra;
	__s32		accept_redirects;
	__s32		autoconf;
	__s32		dad_transmits;
	__s32		rtr_solicits;
	__s32		rtr_solicit_interval;
	__s32		rtr_solicit_delay;
	__s32		force_mld_version;
#ifdef CONFIG_IPV6_PRIVACY
	__s32		use_tempaddr;
	__s32		temp_valid_lft;
	__s32		temp_prefered_lft;
	__s32		regen_max_retry;
	__s32		max_desync_factor;
#endif
	__s32		max_addresses;
150
	__s32		accept_ra_defrtr;
151
	__s32		accept_ra_pinfo;
152 153
#ifdef CONFIG_IPV6_ROUTER_PREF
	__s32		accept_ra_rtr_pref;
154
	__s32		rtr_probe_interval;
155 156 157
#ifdef CONFIG_IPV6_ROUTE_INFO
	__s32		accept_ra_rt_info_max_plen;
#endif
158
#endif
159
	__s32		proxy_ndp;
160
	__s32		accept_source_route;
161 162
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
	__s32		optimistic_dad;
163 164 165
#endif
#ifdef CONFIG_IPV6_MROUTE
	__s32		mc_forwarding;
166
#endif
167
	__s32		disable_ipv6;
168
	__s32		accept_dad;
Linus Torvalds's avatar
Linus Torvalds committed
169 170
	void		*sysctl;
};
171
#endif
Linus Torvalds's avatar
Linus Torvalds committed
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

/* index values for the variables in ipv6_devconf */
enum {
	DEVCONF_FORWARDING = 0,
	DEVCONF_HOPLIMIT,
	DEVCONF_MTU6,
	DEVCONF_ACCEPT_RA,
	DEVCONF_ACCEPT_REDIRECTS,
	DEVCONF_AUTOCONF,
	DEVCONF_DAD_TRANSMITS,
	DEVCONF_RTR_SOLICITS,
	DEVCONF_RTR_SOLICIT_INTERVAL,
	DEVCONF_RTR_SOLICIT_DELAY,
	DEVCONF_USE_TEMPADDR,
	DEVCONF_TEMP_VALID_LFT,
	DEVCONF_TEMP_PREFERED_LFT,
	DEVCONF_REGEN_MAX_RETRY,
	DEVCONF_MAX_DESYNC_FACTOR,
	DEVCONF_MAX_ADDRESSES,
	DEVCONF_FORCE_MLD_VERSION,
192
	DEVCONF_ACCEPT_RA_DEFRTR,
193
	DEVCONF_ACCEPT_RA_PINFO,
194
	DEVCONF_ACCEPT_RA_RTR_PREF,
195
	DEVCONF_RTR_PROBE_INTERVAL,
196
	DEVCONF_ACCEPT_RA_RT_INFO_MAX_PLEN,
197
	DEVCONF_PROXY_NDP,
198
	DEVCONF_OPTIMISTIC_DAD,
199
	DEVCONF_ACCEPT_SOURCE_ROUTE,
200
	DEVCONF_MC_FORWARDING,
201
	DEVCONF_DISABLE_IPV6,
202
	DEVCONF_ACCEPT_DAD,
Linus Torvalds's avatar
Linus Torvalds committed
203 204 205 206 207 208 209 210
	DEVCONF_MAX
};

#ifdef __KERNEL__
#include <linux/icmpv6.h>
#include <linux/tcp.h>
#include <linux/udp.h>

211 212
#include <net/inet_sock.h>

213 214 215 216 217
static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
{
	return (struct ipv6hdr *)skb_network_header(skb);
}

218 219
static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb)
{
220
	return (struct ipv6hdr *)skb_transport_header(skb);
221 222
}

Linus Torvalds's avatar
Linus Torvalds committed
223 224 225 226 227 228 229 230 231 232 233 234
/* 
   This structure contains results of exthdrs parsing
   as offsets from skb->nh.
 */

struct inet6_skb_parm {
	int			iif;
	__u16			ra;
	__u16			hop;
	__u16			dst0;
	__u16			srcrt;
	__u16			dst1;
235
	__u16			lastopt;
236
	__u32			nhoff;
237
	__u16			flags;
238
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
239 240
	__u16			dsthao;
#endif
241 242

#define IP6SKB_XFRM_TRANSFORMED	1
243
#define IP6SKB_FORWARDED	2
Linus Torvalds's avatar
Linus Torvalds committed
244 245 246 247
};

#define IP6CB(skb)	((struct inet6_skb_parm*)((skb)->cb))

248 249 250 251 252
static inline int inet6_iif(const struct sk_buff *skb)
{
	return IP6CB(skb)->iif;
}

253
struct inet6_request_sock {
254 255 256 257 258 259
	struct in6_addr		loc_addr;
	struct in6_addr		rmt_addr;
	struct sk_buff		*pktopts;
	int			iif;
};

260 261 262 263
struct tcp6_request_sock {
	struct tcp_request_sock	  tcp6rsk_tcp;
	struct inet6_request_sock tcp6rsk_inet6;
};
264

265 266 267 268
struct ipv6_mc_socklist;
struct ipv6_ac_socklist;
struct ipv6_fl_socklist;

Linus Torvalds's avatar
Linus Torvalds committed
269 270 271 272 273 274 275 276 277 278 279 280
/**
 * struct ipv6_pinfo - ipv6 private area
 *
 * In the struct sock hierarchy (tcp6_sock, upd6_sock, etc)
 * this _must_ be the last member, so that inet6_sk_generic
 * is able to calculate its offset from the base struct sock
 * by using the struct proto->slab_obj_size member. -acme
 */
struct ipv6_pinfo {
	struct in6_addr 	saddr;
	struct in6_addr 	rcv_saddr;
	struct in6_addr		daddr;
281
	struct in6_pktinfo	sticky_pktinfo;
Linus Torvalds's avatar
Linus Torvalds committed
282
	struct in6_addr		*daddr_cache;
283 284 285
#ifdef CONFIG_IPV6_SUBTREES
	struct in6_addr		*saddr_cache;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
286

Al Viro's avatar
Al Viro committed
287
	__be32			flow_label;
Linus Torvalds's avatar
Linus Torvalds committed
288
	__u32			frag_size;
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311

	/*
	 * Packed in 16bits.
	 * Omit one shift by by putting the signed field at MSB.
	 */
#if defined(__BIG_ENDIAN_BITFIELD)
	__s16			hop_limit:9;
	__u16			__unused_1:7;
#else
	__u16			__unused_1:7;
	__s16			hop_limit:9;
#endif

#if defined(__BIG_ENDIAN_BITFIELD)
	/* Packed in 16bits. */
	__s16			mcast_hops:9;
	__u16			__unused_2:6,
				mc_loop:1;
#else
	__u16			mc_loop:1,
				__unused_2:6;
	__s16			mcast_hops:9;
#endif
Linus Torvalds's avatar
Linus Torvalds committed
312 313 314 315 316
	int			mcast_oif;

	/* pktoption flags */
	union {
		struct {
317 318
			__u16	srcrt:1,
				osrcrt:1,
Linus Torvalds's avatar
Linus Torvalds committed
319
			        rxinfo:1,
320
			        rxoinfo:1,
Linus Torvalds's avatar
Linus Torvalds committed
321
				rxhlim:1,
322
				rxohlim:1,
Linus Torvalds's avatar
Linus Torvalds committed
323
				hopopts:1,
324
				ohopopts:1,
Linus Torvalds's avatar
Linus Torvalds committed
325
				dstopts:1,
326
				odstopts:1,
327 328
                                rxflow:1,
				rxtclass:1;
Linus Torvalds's avatar
Linus Torvalds committed
329
		} bits;
330
		__u16		all;
Linus Torvalds's avatar
Linus Torvalds committed
331 332 333
	} rxopt;

	/* sockopt flags */
334
	__u8			recverr:1,
Linus Torvalds's avatar
Linus Torvalds committed
335 336
	                        sndflow:1,
				pmtudisc:2,
337 338 339 340 341
				ipv6only:1,
				srcprefs:3;	/* 001: prefer temporary address
						 * 010: prefer public address
						 * 100: prefer care-of address
						 */
342
	__u8			tclass;
Linus Torvalds's avatar
Linus Torvalds committed
343 344 345 346 347 348 349 350 351 352 353

	__u32			dst_cookie;

	struct ipv6_mc_socklist	*ipv6_mc_list;
	struct ipv6_ac_socklist	*ipv6_ac_list;
	struct ipv6_fl_socklist *ipv6_fl_list;

	struct ipv6_txoptions	*opt;
	struct sk_buff		*pktoptions;
	struct {
		struct ipv6_txoptions *opt;
354 355
		u8 hop_limit;
		u8 tclass;
Linus Torvalds's avatar
Linus Torvalds committed
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
	} cork;
};

/* WARNING: don't change the layout of the members in {raw,udp,tcp}6_sock! */
struct raw6_sock {
	/* inet_sock has to be the first member of raw6_sock */
	struct inet_sock	inet;
	__u32			checksum;	/* perform checksum */
	__u32			offset;		/* checksum offset  */
	struct icmp6_filter	filter;
	/* ipv6_pinfo has to be the last member of raw6_sock, see inet6_sk_generic */
	struct ipv6_pinfo	inet6;
};

struct udp6_sock {
	struct udp_sock	  udp;
	/* ipv6_pinfo has to be the last member of udp6_sock, see inet6_sk_generic */
	struct ipv6_pinfo inet6;
};

struct tcp6_sock {
	struct tcp_sock	  tcp;
	/* ipv6_pinfo has to be the last member of tcp6_sock, see inet6_sk_generic */
	struct ipv6_pinfo inet6;
};

382 383
extern int inet6_sk_rebuild_header(struct sock *sk);

Linus Torvalds's avatar
Linus Torvalds committed
384 385 386 387 388 389
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
{
	return inet_sk(__sk)->pinet6;
}

390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
static inline struct inet6_request_sock *
			inet6_rsk(const struct request_sock *rsk)
{
	return (struct inet6_request_sock *)(((u8 *)rsk) +
					     inet_rsk(rsk)->inet6_rsk_offset);
}

static inline u32 inet6_rsk_offset(struct request_sock *rsk)
{
	return rsk->rsk_ops->obj_size - sizeof(struct inet6_request_sock);
}

static inline struct request_sock *inet6_reqsk_alloc(struct request_sock_ops *ops)
{
	struct request_sock *req = reqsk_alloc(ops);

406
	if (req != NULL) {
407
		inet_rsk(req)->inet6_rsk_offset = inet6_rsk_offset(req);
408 409
		inet6_rsk(req)->pktopts = NULL;
	}
410 411 412 413

	return req;
}

Linus Torvalds's avatar
Linus Torvalds committed
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
{
	return (struct raw6_sock *)sk;
}

static inline void inet_sk_copy_descendant(struct sock *sk_to,
					   const struct sock *sk_from)
{
	int ancestor_size = sizeof(struct inet_sock);

	if (sk_from->sk_family == PF_INET6)
		ancestor_size += sizeof(struct ipv6_pinfo);

	__inet_sk_copy_descendant(sk_to, sk_from, ancestor_size);
}

#define __ipv6_only_sock(sk)	(inet6_sk(sk)->ipv6only)
#define ipv6_only_sock(sk)	((sk)->sk_family == PF_INET6 && __ipv6_only_sock(sk))
432

433 434 435 436 437
struct inet6_timewait_sock {
	struct in6_addr tw_v6_daddr;
	struct in6_addr	tw_v6_rcv_saddr;
};

438
struct tcp6_timewait_sock {
439 440
	struct tcp_timewait_sock   tcp6tw_tcp;
	struct inet6_timewait_sock tcp6tw_inet6;
441 442
};

443 444
static inline u16 inet6_tw_offset(const struct proto *prot)
{
445 446
	return prot->twsk_prot->twsk_obj_size -
			sizeof(struct inet6_timewait_sock);
447 448 449
}

static inline struct inet6_timewait_sock *inet6_twsk(const struct sock *sk)
450
{
451 452
	return (struct inet6_timewait_sock *)(((u8 *)sk) +
					      inet_twsk(sk)->tw_ipv6_offset);
453 454
}

455
static inline struct in6_addr *__inet6_rcv_saddr(const struct sock *sk)
456 457
{
	return likely(sk->sk_state != TCP_TIME_WAIT) ?
458
		&inet6_sk(sk)->rcv_saddr : &inet6_twsk(sk)->tw_v6_rcv_saddr;
459 460
}

461
static inline struct in6_addr *inet6_rcv_saddr(const struct sock *sk)
462
{
463
	return sk->sk_family == AF_INET6 ? __inet6_rcv_saddr(sk) : NULL;
464 465
}

466
static inline int inet_v6_ipv6only(const struct sock *sk)
467 468
{
	return likely(sk->sk_state != TCP_TIME_WAIT) ?
469
		ipv6_only_sock(sk) : inet_twsk(sk)->tw_ipv6only;
470
}
Linus Torvalds's avatar
Linus Torvalds committed
471 472 473 474 475 476 477 478 479
#else
#define __ipv6_only_sock(sk)	0
#define ipv6_only_sock(sk)	0

static inline struct ipv6_pinfo * inet6_sk(const struct sock *__sk)
{
	return NULL;
}

480 481 482 483 484 485
static inline struct inet6_request_sock *
			inet6_rsk(const struct request_sock *rsk)
{
	return NULL;
}

Linus Torvalds's avatar
Linus Torvalds committed
486 487 488 489 490
static inline struct raw6_sock *raw6_sk(const struct sock *sk)
{
	return NULL;
}

491 492
#define __inet6_rcv_saddr(__sk)	NULL
#define inet6_rcv_saddr(__sk)	NULL
493
#define tcp_twsk_ipv6only(__sk)		0
494
#define inet_v6_ipv6only(__sk)		0
495
#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
Linus Torvalds's avatar
Linus Torvalds committed
496

497
#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
498
	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&& \
Al Viro's avatar
Al Viro committed
499
	 ((*((__portpair *)&(inet_sk(__sk)->dport))) == (__ports))  	&& \
500 501 502 503
	 ((__sk)->sk_family		== AF_INET6)		&& \
	 ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))	&& \
	 ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr))	&& \
	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
Linus Torvalds's avatar
Linus Torvalds committed
504

505
#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
506
	(((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)	&& \
507 508 509 510 511 512
	 (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports))	&& \
	 ((__sk)->sk_family	       == PF_INET6)			&& \
	 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)))	&& \
	 (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \
	 (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))

513 514 515
#endif /* __KERNEL__ */

#endif /* _IPV6_H */