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