in6_proto.c revision 53541
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the project nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netinet6/in6_proto.c 53541 1999-11-22 02:45:11Z shin $
30 */
31
32/*
33 * Copyright (c) 1982, 1986, 1993
34 *	The Regents of the University of California.  All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 *    notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 *    notice, this list of conditions and the following disclaimer in the
43 *    documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 *    must display the following acknowledgement:
46 *	This product includes software developed by the University of
47 *	California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 *    may be used to endorse or promote products derived from this software
50 *    without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 *	@(#)in_proto.c	8.1 (Berkeley) 6/10/93
65 */
66
67#include "opt_inet.h"
68#include "opt_ipsec.h"
69
70#include <sys/param.h>
71#include <sys/socket.h>
72#include <sys/socketvar.h>
73#include <sys/protosw.h>
74#include <sys/kernel.h>
75#include <sys/domain.h>
76#include <sys/mbuf.h>
77#include <sys/systm.h>
78#include <sys/sysctl.h>
79
80#include <net/if.h>
81#include <net/radix.h>
82#include <net/route.h>
83
84#include <netinet/in.h>
85#include <netinet/in_systm.h>
86#include <netinet/in_var.h>
87#include <netinet/ip.h>
88#include <netinet/ip_var.h>
89#include <netinet6/ip6.h>
90#include <netinet6/ip6_var.h>
91#include <netinet6/icmp6.h>
92
93#include <netinet/tcp.h>
94#include <netinet/tcp_timer.h>
95#include <netinet/tcp_var.h>
96#include <netinet/udp.h>
97#include <netinet/udp_var.h>
98#include <netinet6/tcp6_var.h>
99#include <netinet6/udp6_var.h>
100
101#include <netinet6/pim6_var.h>
102
103#include <netinet6/nd6.h>
104#include <netinet6/in6_prefix.h>
105
106#ifdef IPSEC
107#include <netinet6/ipsec.h>
108#ifdef INET6
109#include <netinet6/ipsec6.h>
110#endif /* INET6 */
111#include <netinet6/ah.h>
112#ifdef IPSEC_ESP
113#include <netinet6/esp.h>
114#endif
115#include <netinet6/ipcomp.h>
116#endif /*IPSEC*/
117
118#include <netinet6/ip6protosw.h>
119
120/* #include "gif.h" */
121#if NGIF > 0
122#include <netinet6/in6_gif.h>
123#endif
124
125#include <net/net_osdep.h>
126
127#define	offsetof(type, member)	((size_t)(&((type *)0)->member))
128
129/*
130 * TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
131 */
132
133extern struct	domain inet6domain;
134static struct	pr_usrreqs nousrreqs;
135
136struct ip6protosw inet6sw[] = {
137{ 0,		&inet6domain,	IPPROTO_IPV6,	0,
138  0,		0,		0,		0,
139  0,
140  ip6_init,	0,		frag6_slowtimo,	frag6_drain,
141  &nousrreqs,
142},
143{ SOCK_RAW,	&inet6domain,	IPPROTO_RAW,	PR_ATOMIC | PR_ADDR,
144  rip6_input,	rip6_output,	0,		rip6_ctloutput,
145  0,
146  0,		0,		0,		0,
147  &rip6_usrreqs
148},
149{ SOCK_RAW,	&inet6domain,	IPPROTO_ICMPV6,	PR_ATOMIC | PR_ADDR,
150  icmp6_input,	rip6_output,	0,		rip6_ctloutput,
151  0,
152  icmp6_init,	icmp6_fasttimo,	0,		0,
153  &rip6_usrreqs
154},
155{ SOCK_RAW,	&inet6domain,	IPPROTO_DSTOPTS,PR_ATOMIC|PR_ADDR,
156  dest6_input,	0,	 	0,		0,
157  0,
158  0,		0,		0,		0,
159  &nousrreqs
160},
161{ SOCK_RAW,	&inet6domain,	IPPROTO_ROUTING,PR_ATOMIC|PR_ADDR,
162  route6_input,	0,	 	0,		0,
163  0,
164  0,		0,		0,		0,
165  &nousrreqs
166},
167{ SOCK_RAW,	&inet6domain,	IPPROTO_FRAGMENT,PR_ATOMIC|PR_ADDR,
168  frag6_input,	0,	 	0,		0,
169  0,
170  0,		0,		0,		0,
171  &nousrreqs
172},
173#ifdef IPSEC
174{ SOCK_RAW,	&inet6domain,	IPPROTO_AH,	PR_ATOMIC|PR_ADDR,
175  ah6_input,	0,	 	0,		0,
176  0,
177  0,		0,		0,		0,
178  &nousrreqs,
179},
180#ifdef IPSEC_ESP
181{ SOCK_RAW,	&inet6domain,	IPPROTO_ESP,	PR_ATOMIC|PR_ADDR,
182  esp6_input,	0,	 	0,		0,
183  0,
184  0,		0,		0,		0,
185  &nousrreqs,
186},
187#endif
188{ SOCK_RAW,	&inet6domain,	IPPROTO_IPCOMP,	PR_ATOMIC|PR_ADDR,
189  ipcomp6_input, 0,	 	0,		0,
190  0,
191  0,		0,		0,		0,
192  &nousrreqs,
193},
194#endif /* IPSEC */
195#if NGIF > 0
196{ SOCK_RAW,	&inet6domain,	IPPROTO_IPV4,	PR_ATOMIC|PR_ADDR,
197  in6_gif_input,0,	 	0,		0,
198  0,
199  0,		0,		0,		0,
200  &nousrreqs
201},
202#ifdef INET6
203{ SOCK_RAW,	&inet6domain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR,
204  in6_gif_input,0,	 	0,		0,
205  0,
206  0,		0,		0,		0,
207  &nousrreqs
208},
209#endif /* INET6 */
210#endif /* GIF */
211/* raw wildcard */
212{ SOCK_RAW,	&inet6domain,	0,		PR_ATOMIC | PR_ADDR,
213  rip6_input,	rip6_output,	0,		rip6_ctloutput,
214  0,
215  0,		0,		0,		0,
216  &rip6_usrreqs
217},
218};
219
220extern int	in6_inithead __P((void **, int));
221
222struct domain inet6domain =
223    { AF_INET6, "internet6", 0, 0, 0,
224      (struct protosw *)inet6sw,
225      (struct protosw *)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])], 0,
226      in6_inithead,
227      offsetof(struct sockaddr_in6, sin6_addr) << 3,
228      sizeof(struct sockaddr_in6) };
229
230DOMAIN_SET(inet6);
231
232/*
233 * Internet configuration info
234 */
235#ifndef	IPV6FORWARDING
236#ifdef GATEWAY6
237#define	IPV6FORWARDING	1	/* forward IP6 packets not for us */
238#else
239#define	IPV6FORWARDING	0	/* don't forward IP6 packets not for us */
240#endif /* GATEWAY6 */
241#endif /* !IPV6FORWARDING */
242
243#ifndef	IPV6_SENDREDIRECTS
244#define	IPV6_SENDREDIRECTS	1
245#endif
246
247int	ip6_forwarding = IPV6FORWARDING;	/* act as router? */
248int	ip6_sendredirects = IPV6_SENDREDIRECTS;
249int	ip6_defhlim = IPV6_DEFHLIM;
250int	ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
251int	ip6_accept_rtadv = 0;	/* "IPV6FORWARDING ? 0 : 1" is dangerous */
252int	ip6_maxfragpackets = 200;
253int	ip6_log_interval = 5;
254int	ip6_hdrnestlimit = 50;	/* appropriate? */
255int	ip6_dad_count = 1;	/* DupAddrDetectionTransmits */
256u_int32_t	ip6_flow_seq;
257int	ip6_auto_flowlabel = 1;
258#if NGIF > 0
259int	ip6_gif_hlim = GIF_HLIM;
260#else
261int	ip6_gif_hlim = 0;
262#endif
263int	ip6_use_deprecated = 1;	/* allow deprecated addr (RFC2462 5.5.4) */
264int	ip6_rr_prune = 5;	/* router renumbering prefix
265				 * walk list every 5 sec.    */
266int	ip6_mapped_addr_on = 1;
267
268u_int32_t ip6_id = 0UL;
269int	ip6_keepfaith = 0;
270time_t	ip6_log_time = (time_t)0L;
271
272/* icmp6 */
273/*
274 * BSDI4 defines these variables in in_proto.c...
275 * XXX: what if we don't define INET? Should we define pmtu6_expire
276 * or so? (jinmei@kame.net 19990310)
277 */
278int	pmtu_expire = 60*10;
279int	pmtu_probe = 60*2;
280
281/* raw IP6 parameters */
282/*
283 * Nominal space allocated to a raw ip socket.
284 */
285#define	RIPV6SNDQ	8192
286#define	RIPV6RCVQ	8192
287
288u_long	rip6_sendspace = RIPV6SNDQ;
289u_long	rip6_recvspace = RIPV6RCVQ;
290
291/* ICMPV6 parameters */
292int	icmp6_rediraccept = 1;		/* accept and process redirects */
293int	icmp6_redirtimeout = 10 * 60;	/* 10 minutes */
294u_int	icmp6errratelim = 1000;		/* 1000usec = 1msec */
295
296/* UDP on IP6 parameters */
297int	udp6_sendspace = 9216;		/* really max datagram size */
298int	udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
299					/* 40 1K datagrams */
300
301/*
302 * sysctl related items.
303 */
304SYSCTL_NODE(_net,	PF_INET6,	inet6,	CTLFLAG_RW,	0,
305	"Internet6 Family");
306
307/* net.inet6 */
308SYSCTL_NODE(_net_inet6,	IPPROTO_IPV6,	ip6,	CTLFLAG_RW, 0,	"IP6");
309SYSCTL_NODE(_net_inet6,	IPPROTO_ICMPV6,	icmp6,	CTLFLAG_RW, 0,	"ICMP6");
310SYSCTL_NODE(_net_inet6,	IPPROTO_UDP,	udp6,	CTLFLAG_RW, 0,	"UDP6");
311SYSCTL_NODE(_net_inet6,	IPPROTO_TCP,	tcp6,	CTLFLAG_RW, 0,	"TCP6");
312#ifdef IPSEC
313SYSCTL_NODE(_net_inet6,	IPPROTO_ESP,	ipsec6,	CTLFLAG_RW, 0,	"IPSEC6");
314#endif /* IPSEC */
315
316/* net.inet6.ip6 */
317static int
318sysctl_ip6_forwarding SYSCTL_HANDLER_ARGS
319{
320	int error = 0;
321	int old_ip6_forwarding;
322	int changed;
323
324	error = SYSCTL_OUT(req, arg1, sizeof(int));
325	if (error || !req->newptr)
326		return (error);
327	old_ip6_forwarding = ip6_forwarding;
328	error = SYSCTL_IN(req, arg1, sizeof(int));
329	if (error != 0)
330		return (error);
331	changed = (ip6_forwarding ? 1 : 0) ^ (old_ip6_forwarding ? 1 : 0);
332	if (changed == 0)
333		return (error);
334	if (ip6_forwarding != 0) {	/* host becomes router */
335		int s = splnet();
336		struct nd_prefix *pr, *next;
337
338		for (pr = nd_prefix.lh_first; pr; pr = next) {
339			next = pr->ndpr_next;
340			if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
341				in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
342			prelist_remove(pr);
343		}
344		splx(s);
345	} else {			/* router becomes host */
346		struct socket so;
347
348		/* XXX: init dummy so */
349		bzero(&so, sizeof(so));
350		while(!LIST_EMPTY(&rr_prefix))
351			delete_each_prefix(&so, LIST_FIRST(&rr_prefix),
352					   PR_ORIG_KERNEL);
353	}
354
355	return (error);
356}
357
358SYSCTL_OID(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding,
359	   CTLTYPE_INT|CTLFLAG_RW, &ip6_forwarding, 0, sysctl_ip6_forwarding,
360	   "I", "");
361SYSCTL_INT(_net_inet6_ip6, IPV6CTL_SENDREDIRECTS,
362	redirect, CTLFLAG_RW,		&ip6_sendredirects,	0, "");
363SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM,
364	hlim, CTLFLAG_RW,		&ip6_defhlim,	0, "");
365SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS,
366	maxfragpackets, CTLFLAG_RW,	&ip6_maxfragpackets,	0, "");
367SYSCTL_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV,
368	accept_rtadv, CTLFLAG_RW,	&ip6_accept_rtadv,	0, "");
369SYSCTL_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH,
370	keepfaith, CTLFLAG_RW,		&ip6_keepfaith,	0, "");
371SYSCTL_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL,
372	log_interval, CTLFLAG_RW,	&ip6_log_interval,	0, "");
373SYSCTL_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT,
374	hdrnestlimit, CTLFLAG_RW,	&ip6_hdrnestlimit,	0, "");
375SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DAD_COUNT,
376	dad_count, CTLFLAG_RW,	&ip6_dad_count,	0, "");
377SYSCTL_INT(_net_inet6_ip6, IPV6CTL_AUTO_FLOWLABEL,
378	auto_flowlabel, CTLFLAG_RW,	&ip6_auto_flowlabel,	0, "");
379SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM,
380	defmcasthlim, CTLFLAG_RW,	&ip6_defmcasthlim,	0, "");
381SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM,
382	gifhlim, CTLFLAG_RW,	&ip6_gif_hlim,			0, "");
383SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED,
384	use_deprecated, CTLFLAG_RW,	&ip6_use_deprecated,	0, "");
385SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE,
386	rr_prune, CTLFLAG_RW,	&ip6_rr_prune,			0, "");
387SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAPPED_ADDR,
388	mapped_addr, CTLFLAG_RW,	&ip6_mapped_addr_on,	0, "");
389
390/* net.inet6.icmp6 */
391SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT,
392	rediraccept, CTLFLAG_RW,	&icmp6_rediraccept,	0, "");
393SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT,
394	redirtimeout, CTLFLAG_RW,	&icmp6_redirtimeout,	0, "");
395SYSCTL_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD,
396	&icmp6stat, icmp6stat, "");
397SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ERRRATELIMIT,
398	errratelimit, CTLFLAG_RW,	&icmp6errratelim,	0, "");
399SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE,
400	nd6_prune, CTLFLAG_RW,		&nd6_prune,	0, "");
401SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY,
402	nd6_delay, CTLFLAG_RW,		&nd6_delay,	0, "");
403SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_UMAXTRIES,
404	nd6_umaxtries, CTLFLAG_RW,	&nd6_umaxtries,	0, "");
405SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MMAXTRIES,
406	nd6_mmaxtries, CTLFLAG_RW,	&nd6_mmaxtries,	0, "");
407SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK,
408	nd6_useloopback, CTLFLAG_RW,	&nd6_useloopback, 0, "");
409SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PROXYALL,
410	nd6_proxyall, CTLFLAG_RW,	&nd6_proxyall, 0, "");
411