in6_proto.c revision 55679
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 55679 2000-01-09 19:17:30Z 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#include <netinet6/ah.h>
109#include <netinet6/ipsec6.h>
110#include <netinet6/ah6.h>
111#ifdef IPSEC_ESP
112#include <netinet6/esp.h>
113#include <netinet6/esp6.h>
114#endif
115#endif /*IPSEC*/
116
117#include <netinet6/ip6protosw.h>
118
119#include "gif.h"
120#if NGIF > 0
121#include <netinet6/in6_gif.h>
122#endif
123
124#include <net/net_osdep.h>
125
126#define	offsetof(type, member)	((size_t)(&((type *)0)->member))
127
128/*
129 * TCP/IP protocol family: IP6, ICMP6, UDP, TCP.
130 */
131
132extern struct	domain inet6domain;
133static struct	pr_usrreqs nousrreqs;
134
135struct ip6protosw inet6sw[] = {
136{ 0,		&inet6domain,	IPPROTO_IPV6,	0,
137  0,		0,		0,		0,
138  0,
139  ip6_init,	0,		frag6_slowtimo,	frag6_drain,
140  &nousrreqs,
141},
142{ SOCK_DGRAM,	&inet6domain,	IPPROTO_UDP,	PR_ATOMIC | PR_ADDR,
143  udp6_input,	0,		udp6_ctlinput,	ip6_ctloutput,
144  0,
145  0,		0,		0,		0,
146  &udp6_usrreqs,
147},
148{ SOCK_STREAM,	&inet6domain,	IPPROTO_TCP,	PR_CONNREQUIRED | PR_WANTRCVD,
149  tcp6_input,	0,		tcp6_ctlinput,	tcp_ctloutput,
150  0,
151#ifdef INET	/* don't call timeout routines twice */
152  tcp_init,	0,		0,		tcp_drain,
153#else
154  tcp_init,	0,		tcp_slowtimo,	tcp_drain,
155#endif
156  &tcp6_usrreqs,
157},
158{ SOCK_RAW,	&inet6domain,	IPPROTO_RAW,	PR_ATOMIC | PR_ADDR,
159  rip6_input,	rip6_output,	0,		rip6_ctloutput,
160  0,
161  0,		0,		0,		0,
162  &rip6_usrreqs
163},
164{ SOCK_RAW,	&inet6domain,	IPPROTO_ICMPV6,	PR_ATOMIC | PR_ADDR,
165  icmp6_input,	rip6_output,	0,		rip6_ctloutput,
166  0,
167  icmp6_init,	icmp6_fasttimo,	0,		0,
168  &rip6_usrreqs
169},
170{ SOCK_RAW,	&inet6domain,	IPPROTO_DSTOPTS,PR_ATOMIC|PR_ADDR,
171  dest6_input,	0,	 	0,		0,
172  0,
173  0,		0,		0,		0,
174  &nousrreqs
175},
176{ SOCK_RAW,	&inet6domain,	IPPROTO_ROUTING,PR_ATOMIC|PR_ADDR,
177  route6_input,	0,	 	0,		0,
178  0,
179  0,		0,		0,		0,
180  &nousrreqs
181},
182{ SOCK_RAW,	&inet6domain,	IPPROTO_FRAGMENT,PR_ATOMIC|PR_ADDR,
183  frag6_input,	0,	 	0,		0,
184  0,
185  0,		0,		0,		0,
186  &nousrreqs
187},
188#ifdef IPSEC
189{ SOCK_RAW,	&inet6domain,	IPPROTO_AH,	PR_ATOMIC|PR_ADDR,
190  ah6_input,	0,	 	0,		0,
191  0,
192  0,		0,		0,		0,
193  &nousrreqs,
194},
195#ifdef IPSEC_ESP
196{ SOCK_RAW,	&inet6domain,	IPPROTO_ESP,	PR_ATOMIC|PR_ADDR,
197  esp6_input,	0,	 	0,		0,
198  0,
199  0,		0,		0,		0,
200  &nousrreqs,
201},
202#endif
203#endif /* IPSEC */
204#if NGIF > 0
205{ SOCK_RAW,	&inet6domain,	IPPROTO_IPV4,	PR_ATOMIC|PR_ADDR,
206  in6_gif_input,0,	 	0,		0,
207  0,
208  0,		0,		0,		0,
209  &nousrreqs
210},
211{ SOCK_RAW,	&inet6domain,	IPPROTO_IPV6,	PR_ATOMIC|PR_ADDR,
212  in6_gif_input,0,	 	0,		0,
213  0,
214  0,		0,		0,		0,
215  &nousrreqs
216},
217#endif /* GIF */
218/* raw wildcard */
219{ SOCK_RAW,	&inet6domain,	0,		PR_ATOMIC | PR_ADDR,
220  rip6_input,	rip6_output,	0,		rip6_ctloutput,
221  0,
222  0,		0,		0,		0,
223  &rip6_usrreqs
224},
225};
226
227extern int	in6_inithead __P((void **, int));
228
229struct domain inet6domain =
230    { AF_INET6, "internet6", 0, 0, 0,
231      (struct protosw *)inet6sw,
232      (struct protosw *)&inet6sw[sizeof(inet6sw)/sizeof(inet6sw[0])], 0,
233      in6_inithead,
234      offsetof(struct sockaddr_in6, sin6_addr) << 3,
235      sizeof(struct sockaddr_in6) };
236
237DOMAIN_SET(inet6);
238
239/*
240 * Internet configuration info
241 */
242#ifndef	IPV6FORWARDING
243#ifdef GATEWAY6
244#define	IPV6FORWARDING	1	/* forward IP6 packets not for us */
245#else
246#define	IPV6FORWARDING	0	/* don't forward IP6 packets not for us */
247#endif /* GATEWAY6 */
248#endif /* !IPV6FORWARDING */
249
250#ifndef	IPV6_SENDREDIRECTS
251#define	IPV6_SENDREDIRECTS	1
252#endif
253
254int	ip6_forwarding = IPV6FORWARDING;	/* act as router? */
255int	ip6_sendredirects = IPV6_SENDREDIRECTS;
256int	ip6_defhlim = IPV6_DEFHLIM;
257int	ip6_defmcasthlim = IPV6_DEFAULT_MULTICAST_HOPS;
258int	ip6_accept_rtadv = 0;	/* "IPV6FORWARDING ? 0 : 1" is dangerous */
259int	ip6_maxfragpackets = 200;
260int	ip6_log_interval = 5;
261int	ip6_hdrnestlimit = 50;	/* appropriate? */
262int	ip6_dad_count = 1;	/* DupAddrDetectionTransmits */
263u_int32_t	ip6_flow_seq;
264int	ip6_auto_flowlabel = 1;
265#if NGIF > 0
266int	ip6_gif_hlim = GIF_HLIM;
267#else
268int	ip6_gif_hlim = 0;
269#endif
270int	ip6_use_deprecated = 1;	/* allow deprecated addr (RFC2462 5.5.4) */
271int	ip6_rr_prune = 5;	/* router renumbering prefix
272				 * walk list every 5 sec.    */
273int	ip6_mapped_addr_on = 1;
274
275u_int32_t ip6_id = 0UL;
276int	ip6_keepfaith = 0;
277time_t	ip6_log_time = (time_t)0L;
278
279/* icmp6 */
280/*
281 * BSDI4 defines these variables in in_proto.c...
282 * XXX: what if we don't define INET? Should we define pmtu6_expire
283 * or so? (jinmei@kame.net 19990310)
284 */
285int	pmtu_expire = 60*10;
286int	pmtu_probe = 60*2;
287
288/* raw IP6 parameters */
289/*
290 * Nominal space allocated to a raw ip socket.
291 */
292#define	RIPV6SNDQ	8192
293#define	RIPV6RCVQ	8192
294
295u_long	rip6_sendspace = RIPV6SNDQ;
296u_long	rip6_recvspace = RIPV6RCVQ;
297
298/* ICMPV6 parameters */
299int	icmp6_rediraccept = 1;		/* accept and process redirects */
300int	icmp6_redirtimeout = 10 * 60;	/* 10 minutes */
301u_int	icmp6errratelim = 1000;		/* 1000usec = 1msec */
302
303/* UDP on IP6 parameters */
304int	udp6_sendspace = 9216;		/* really max datagram size */
305int	udp6_recvspace = 40 * (1024 + sizeof(struct sockaddr_in6));
306					/* 40 1K datagrams */
307
308/*
309 * sysctl related items.
310 */
311SYSCTL_NODE(_net,	PF_INET6,	inet6,	CTLFLAG_RW,	0,
312	"Internet6 Family");
313
314/* net.inet6 */
315SYSCTL_NODE(_net_inet6,	IPPROTO_IPV6,	ip6,	CTLFLAG_RW, 0,	"IP6");
316SYSCTL_NODE(_net_inet6,	IPPROTO_ICMPV6,	icmp6,	CTLFLAG_RW, 0,	"ICMP6");
317SYSCTL_NODE(_net_inet6,	IPPROTO_UDP,	udp6,	CTLFLAG_RW, 0,	"UDP6");
318SYSCTL_NODE(_net_inet6,	IPPROTO_TCP,	tcp6,	CTLFLAG_RW, 0,	"TCP6");
319#ifdef IPSEC
320SYSCTL_NODE(_net_inet6,	IPPROTO_ESP,	ipsec6,	CTLFLAG_RW, 0,	"IPSEC6");
321#endif /* IPSEC */
322
323/* net.inet6.ip6 */
324static int
325sysctl_ip6_forwarding SYSCTL_HANDLER_ARGS
326{
327	int error = 0;
328	int old_ip6_forwarding;
329	int changed;
330
331	error = SYSCTL_OUT(req, arg1, sizeof(int));
332	if (error || !req->newptr)
333		return (error);
334	old_ip6_forwarding = ip6_forwarding;
335	error = SYSCTL_IN(req, arg1, sizeof(int));
336	if (error != 0)
337		return (error);
338	changed = (ip6_forwarding ? 1 : 0) ^ (old_ip6_forwarding ? 1 : 0);
339	if (changed == 0)
340		return (error);
341	if (ip6_forwarding != 0) {	/* host becomes router */
342		int s = splnet();
343		struct nd_prefix *pr, *next;
344
345		for (pr = LIST_FIRST(&nd_prefix); pr; pr = next) {
346			next = LIST_NEXT(pr, ndpr_entry);
347			if (!IN6_IS_ADDR_UNSPECIFIED(&pr->ndpr_addr))
348				in6_ifdel(pr->ndpr_ifp, &pr->ndpr_addr);
349			prelist_remove(pr);
350		}
351		splx(s);
352	} else {			/* router becomes host */
353		struct socket so;
354
355		/* XXX: init dummy so */
356		bzero(&so, sizeof(so));
357		while(!LIST_EMPTY(&rr_prefix))
358			delete_each_prefix(&so, LIST_FIRST(&rr_prefix),
359					   PR_ORIG_KERNEL);
360	}
361
362	return (error);
363}
364
365SYSCTL_OID(_net_inet6_ip6, IPV6CTL_FORWARDING, forwarding,
366	   CTLTYPE_INT|CTLFLAG_RW, &ip6_forwarding, 0, sysctl_ip6_forwarding,
367	   "I", "");
368SYSCTL_INT(_net_inet6_ip6, IPV6CTL_SENDREDIRECTS,
369	redirect, CTLFLAG_RW,		&ip6_sendredirects,	0, "");
370SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFHLIM,
371	hlim, CTLFLAG_RW,		&ip6_defhlim,	0, "");
372SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAXFRAGPACKETS,
373	maxfragpackets, CTLFLAG_RW,	&ip6_maxfragpackets,	0, "");
374SYSCTL_INT(_net_inet6_ip6, IPV6CTL_ACCEPT_RTADV,
375	accept_rtadv, CTLFLAG_RW,	&ip6_accept_rtadv,	0, "");
376SYSCTL_INT(_net_inet6_ip6, IPV6CTL_KEEPFAITH,
377	keepfaith, CTLFLAG_RW,		&ip6_keepfaith,	0, "");
378SYSCTL_INT(_net_inet6_ip6, IPV6CTL_LOG_INTERVAL,
379	log_interval, CTLFLAG_RW,	&ip6_log_interval,	0, "");
380SYSCTL_INT(_net_inet6_ip6, IPV6CTL_HDRNESTLIMIT,
381	hdrnestlimit, CTLFLAG_RW,	&ip6_hdrnestlimit,	0, "");
382SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DAD_COUNT,
383	dad_count, CTLFLAG_RW,	&ip6_dad_count,	0, "");
384SYSCTL_INT(_net_inet6_ip6, IPV6CTL_AUTO_FLOWLABEL,
385	auto_flowlabel, CTLFLAG_RW,	&ip6_auto_flowlabel,	0, "");
386SYSCTL_INT(_net_inet6_ip6, IPV6CTL_DEFMCASTHLIM,
387	defmcasthlim, CTLFLAG_RW,	&ip6_defmcasthlim,	0, "");
388SYSCTL_INT(_net_inet6_ip6, IPV6CTL_GIF_HLIM,
389	gifhlim, CTLFLAG_RW,	&ip6_gif_hlim,			0, "");
390SYSCTL_STRING(_net_inet6_ip6, IPV6CTL_KAME_VERSION,
391	kame_version, CTLFLAG_RD,	__KAME_VERSION,		0, "");
392SYSCTL_INT(_net_inet6_ip6, IPV6CTL_USE_DEPRECATED,
393	use_deprecated, CTLFLAG_RW,	&ip6_use_deprecated,	0, "");
394SYSCTL_INT(_net_inet6_ip6, IPV6CTL_RR_PRUNE,
395	rr_prune, CTLFLAG_RW,	&ip6_rr_prune,			0, "");
396SYSCTL_INT(_net_inet6_ip6, IPV6CTL_MAPPED_ADDR,
397	mapped_addr, CTLFLAG_RW,	&ip6_mapped_addr_on,	0, "");
398
399/* net.inet6.icmp6 */
400SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRACCEPT,
401	rediraccept, CTLFLAG_RW,	&icmp6_rediraccept,	0, "");
402SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_REDIRTIMEOUT,
403	redirtimeout, CTLFLAG_RW,	&icmp6_redirtimeout,	0, "");
404SYSCTL_STRUCT(_net_inet6_icmp6, ICMPV6CTL_STATS, stats, CTLFLAG_RD,
405	&icmp6stat, icmp6stat, "");
406SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ERRRATELIMIT,
407	errratelimit, CTLFLAG_RW,	&icmp6errratelim,	0, "");
408SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PRUNE,
409	nd6_prune, CTLFLAG_RW,		&nd6_prune,	0, "");
410SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_DELAY,
411	nd6_delay, CTLFLAG_RW,		&nd6_delay,	0, "");
412SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_UMAXTRIES,
413	nd6_umaxtries, CTLFLAG_RW,	&nd6_umaxtries,	0, "");
414SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MMAXTRIES,
415	nd6_mmaxtries, CTLFLAG_RW,	&nd6_mmaxtries,	0, "");
416SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK,
417	nd6_useloopback, CTLFLAG_RW,	&nd6_useloopback, 0, "");
418SYSCTL_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_PROXYALL,
419	nd6_proxyall, CTLFLAG_RW,	&nd6_proxyall, 0, "");
420