xref: /freebsd/sys/netinet6/raw_ip6.c (revision 195ebc7e9e4b129de810833791a19dfb4349d6a9)
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 
30 /*-
31  * Copyright (c) 1982, 1986, 1988, 1993
32  *	The Regents of the University of California.
33  * All rights reserved.
34  *
35  * Redistribution and use in source and binary forms, with or without
36  * modification, are permitted provided that the following conditions
37  * are met:
38  * 1. Redistributions of source code must retain the above copyright
39  *    notice, this list of conditions and the following disclaimer.
40  * 2. Redistributions in binary form must reproduce the above copyright
41  *    notice, this list of conditions and the following disclaimer in the
42  *    documentation and/or other materials provided with the distribution.
43  * 4. Neither the name of the University nor the names of its contributors
44  *    may be used to endorse or promote products derived from this software
45  *    without specific prior written permission.
46  *
47  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57  * SUCH DAMAGE.
58  *
59  *	@(#)raw_ip.c	8.2 (Berkeley) 1/4/94
60  */
61 
62 #include <sys/cdefs.h>
63 __FBSDID("$FreeBSD$");
64 
65 #include "opt_ipsec.h"
66 #include "opt_inet6.h"
67 #include "opt_route.h"
68 
69 #include <sys/param.h>
70 #include <sys/errno.h>
71 #include <sys/jail.h>
72 #include <sys/lock.h>
73 #include <sys/malloc.h>
74 #include <sys/mbuf.h>
75 #include <sys/priv.h>
76 #include <sys/proc.h>
77 #include <sys/protosw.h>
78 #include <sys/signalvar.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/sx.h>
82 #include <sys/syslog.h>
83 #include <sys/vimage.h>
84 
85 #include <net/if.h>
86 #include <net/if_types.h>
87 #include <net/route.h>
88 #include <net/vnet.h>
89 
90 #include <netinet/in.h>
91 #include <netinet/in_var.h>
92 #include <netinet/in_systm.h>
93 #include <netinet/in_pcb.h>
94 #include <netinet/vinet.h>
95 
96 #include <netinet/icmp6.h>
97 #include <netinet/ip6.h>
98 #include <netinet6/ip6protosw.h>
99 #include <netinet6/ip6_mroute.h>
100 #include <netinet6/in6_pcb.h>
101 #include <netinet6/ip6_var.h>
102 #include <netinet6/nd6.h>
103 #include <netinet6/raw_ip6.h>
104 #include <netinet6/scope6_var.h>
105 #include <netinet6/vinet6.h>
106 
107 #ifdef IPSEC
108 #include <netipsec/ipsec.h>
109 #include <netipsec/ipsec6.h>
110 #endif /* IPSEC */
111 
112 #include <machine/stdarg.h>
113 
114 #define	satosin6(sa)	((struct sockaddr_in6 *)(sa))
115 #define	ifatoia6(ifa)	((struct in6_ifaddr *)(ifa))
116 
117 /*
118  * Raw interface to IP6 protocol.
119  */
120 
121 #ifdef VIMAGE_GLOBALS
122 extern struct	inpcbhead ripcb;
123 extern struct	inpcbinfo ripcbinfo;
124 struct rip6stat rip6stat;
125 #endif
126 
127 extern u_long	rip_sendspace;
128 extern u_long	rip_recvspace;
129 
130 /*
131  * Hooks for multicast routing. They all default to NULL, so leave them not
132  * initialized and rely on BSS being set to 0.
133  */
134 
135 /*
136  * The socket used to communicate with the multicast routing daemon.
137  */
138 #ifdef VIMAGE_GLOBALS
139 struct socket *ip6_mrouter;
140 #endif
141 
142 /*
143  * The various mrouter functions.
144  */
145 int (*ip6_mrouter_set)(struct socket *, struct sockopt *);
146 int (*ip6_mrouter_get)(struct socket *, struct sockopt *);
147 int (*ip6_mrouter_done)(void);
148 int (*ip6_mforward)(struct ip6_hdr *, struct ifnet *, struct mbuf *);
149 int (*mrt6_ioctl)(int, caddr_t);
150 
151 /*
152  * Setup generic address and protocol structures for raw_input routine, then
153  * pass them along with mbuf chain.
154  */
155 int
156 rip6_input(struct mbuf **mp, int *offp, int proto)
157 {
158 	INIT_VNET_INET(curvnet);
159 	INIT_VNET_INET6(curvnet);
160 #ifdef IPSEC
161 	INIT_VNET_IPSEC(curvnet);
162 #endif
163 	struct ifnet *ifp;
164 	struct mbuf *m = *mp;
165 	register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
166 	register struct inpcb *in6p;
167 	struct inpcb *last = 0;
168 	struct mbuf *opts = NULL;
169 	struct sockaddr_in6 fromsa;
170 
171 	V_rip6stat.rip6s_ipackets++;
172 
173 	if (faithprefix_p != NULL && (*faithprefix_p)(&ip6->ip6_dst)) {
174 		/* XXX Send icmp6 host/port unreach? */
175 		m_freem(m);
176 		return (IPPROTO_DONE);
177 	}
178 
179 	init_sin6(&fromsa, m); /* general init */
180 
181 	ifp = m->m_pkthdr.rcvif;
182 
183 	INP_INFO_RLOCK(&V_ripcbinfo);
184 	LIST_FOREACH(in6p, &V_ripcb, inp_list) {
185 		/* XXX inp locking */
186 		if ((in6p->inp_vflag & INP_IPV6) == 0)
187 			continue;
188 		if (in6p->inp_ip_p &&
189 		    in6p->inp_ip_p != proto)
190 			continue;
191 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
192 		    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
193 			continue;
194 		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
195 		    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
196 			continue;
197 		if (jailed(in6p->inp_cred)) {
198 			/*
199 			 * Allow raw socket in jail to receive multicast;
200 			 * assume process had PRIV_NETINET_RAW at attach,
201 			 * and fall through into normal filter path if so.
202 			 */
203 			if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
204 			    prison_check_ip6(in6p->inp_cred,
205 			    &ip6->ip6_dst) != 0)
206 				continue;
207 		}
208 		if (in6p->in6p_cksum != -1) {
209 			V_rip6stat.rip6s_isum++;
210 			if (in6_cksum(m, proto, *offp,
211 			    m->m_pkthdr.len - *offp)) {
212 				INP_RUNLOCK(in6p);
213 				V_rip6stat.rip6s_badsum++;
214 				continue;
215 			}
216 		}
217 		INP_RLOCK(in6p);
218 		/*
219 		 * If this raw socket has multicast state, and we
220 		 * have received a multicast, check if this socket
221 		 * should receive it, as multicast filtering is now
222 		 * the responsibility of the transport layer.
223 		 */
224 		if (in6p->in6p_moptions &&
225 		    IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
226 			struct sockaddr_in6 mcaddr;
227 			int blocked;
228 
229 			bzero(&mcaddr, sizeof(struct sockaddr_in6));
230 			mcaddr.sin6_len = sizeof(struct sockaddr_in6);
231 			mcaddr.sin6_family = AF_INET6;
232 			mcaddr.sin6_addr = ip6->ip6_dst;
233 
234 			blocked = im6o_mc_filter(in6p->in6p_moptions, ifp,
235 			    (struct sockaddr *)&mcaddr,
236 			    (struct sockaddr *)&fromsa);
237 			if (blocked != MCAST_PASS) {
238 				IP6STAT_INC(ip6s_notmember);
239 				continue;
240 			}
241 		}
242 		if (last != NULL) {
243 			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
244 
245 #ifdef IPSEC
246 			/*
247 			 * Check AH/ESP integrity.
248 			 */
249 			if (n && ipsec6_in_reject(n, last)) {
250 				m_freem(n);
251 				V_ipsec6stat.in_polvio++;
252 				/* Do not inject data into pcb. */
253 			} else
254 #endif /* IPSEC */
255 			if (n) {
256 				if (last->inp_flags & INP_CONTROLOPTS ||
257 				    last->inp_socket->so_options & SO_TIMESTAMP)
258 					ip6_savecontrol(last, n, &opts);
259 				/* strip intermediate headers */
260 				m_adj(n, *offp);
261 				if (sbappendaddr(&last->inp_socket->so_rcv,
262 						(struct sockaddr *)&fromsa,
263 						 n, opts) == 0) {
264 					m_freem(n);
265 					if (opts)
266 						m_freem(opts);
267 					V_rip6stat.rip6s_fullsock++;
268 				} else
269 					sorwakeup(last->inp_socket);
270 				opts = NULL;
271 			}
272 			INP_RUNLOCK(last);
273 		}
274 		last = in6p;
275 	}
276 	INP_INFO_RUNLOCK(&V_ripcbinfo);
277 #ifdef IPSEC
278 	/*
279 	 * Check AH/ESP integrity.
280 	 */
281 	if ((last != NULL) && ipsec6_in_reject(m, last)) {
282 		m_freem(m);
283 		V_ipsec6stat.in_polvio++;
284 		V_ip6stat.ip6s_delivered--;
285 		/* Do not inject data into pcb. */
286 		INP_RUNLOCK(last);
287 	} else
288 #endif /* IPSEC */
289 	if (last != NULL) {
290 		if (last->inp_flags & INP_CONTROLOPTS ||
291 		    last->inp_socket->so_options & SO_TIMESTAMP)
292 			ip6_savecontrol(last, m, &opts);
293 		/* Strip intermediate headers. */
294 		m_adj(m, *offp);
295 		if (sbappendaddr(&last->inp_socket->so_rcv,
296 		    (struct sockaddr *)&fromsa, m, opts) == 0) {
297 			m_freem(m);
298 			if (opts)
299 				m_freem(opts);
300 			V_rip6stat.rip6s_fullsock++;
301 		} else
302 			sorwakeup(last->inp_socket);
303 		INP_RUNLOCK(last);
304 	} else {
305 		V_rip6stat.rip6s_nosock++;
306 		if (m->m_flags & M_MCAST)
307 			V_rip6stat.rip6s_nosockmcast++;
308 		if (proto == IPPROTO_NONE)
309 			m_freem(m);
310 		else {
311 			char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
312 			icmp6_error(m, ICMP6_PARAM_PROB,
313 			    ICMP6_PARAMPROB_NEXTHEADER,
314 			    prvnxtp - mtod(m, char *));
315 		}
316 		V_ip6stat.ip6s_delivered--;
317 	}
318 	return (IPPROTO_DONE);
319 }
320 
321 void
322 rip6_ctlinput(int cmd, struct sockaddr *sa, void *d)
323 {
324 	INIT_VNET_INET(curvnet);
325 	struct ip6_hdr *ip6;
326 	struct mbuf *m;
327 	int off = 0;
328 	struct ip6ctlparam *ip6cp = NULL;
329 	const struct sockaddr_in6 *sa6_src = NULL;
330 	void *cmdarg;
331 	struct inpcb *(*notify)(struct inpcb *, int) = in6_rtchange;
332 
333 	if (sa->sa_family != AF_INET6 ||
334 	    sa->sa_len != sizeof(struct sockaddr_in6))
335 		return;
336 
337 	if ((unsigned)cmd >= PRC_NCMDS)
338 		return;
339 	if (PRC_IS_REDIRECT(cmd))
340 		notify = in6_rtchange, d = NULL;
341 	else if (cmd == PRC_HOSTDEAD)
342 		d = NULL;
343 	else if (inet6ctlerrmap[cmd] == 0)
344 		return;
345 
346 	/*
347 	 * If the parameter is from icmp6, decode it.
348 	 */
349 	if (d != NULL) {
350 		ip6cp = (struct ip6ctlparam *)d;
351 		m = ip6cp->ip6c_m;
352 		ip6 = ip6cp->ip6c_ip6;
353 		off = ip6cp->ip6c_off;
354 		cmdarg = ip6cp->ip6c_cmdarg;
355 		sa6_src = ip6cp->ip6c_src;
356 	} else {
357 		m = NULL;
358 		ip6 = NULL;
359 		cmdarg = NULL;
360 		sa6_src = &sa6_any;
361 	}
362 
363 	(void) in6_pcbnotify(&V_ripcbinfo, sa, 0,
364 	    (const struct sockaddr *)sa6_src, 0, cmd, cmdarg, notify);
365 }
366 
367 /*
368  * Generate IPv6 header and pass packet to ip6_output.  Tack on options user
369  * may have setup with control call.
370  */
371 int
372 #if __STDC__
373 rip6_output(struct mbuf *m, ...)
374 #else
375 rip6_output(m, va_alist)
376 	struct mbuf *m;
377 	va_dcl
378 #endif
379 {
380 	INIT_VNET_INET6(curvnet);
381 	struct mbuf *control;
382 	struct socket *so;
383 	struct sockaddr_in6 *dstsock;
384 	struct in6_addr *dst;
385 	struct ip6_hdr *ip6;
386 	struct inpcb *in6p;
387 	u_int	plen = m->m_pkthdr.len;
388 	int error = 0;
389 	struct ip6_pktopts opt, *optp;
390 	struct ifnet *oifp = NULL;
391 	int type = 0, code = 0;		/* for ICMPv6 output statistics only */
392 	int scope_ambiguous = 0;
393 	struct in6_addr *in6a;
394 	va_list ap;
395 
396 	va_start(ap, m);
397 	so = va_arg(ap, struct socket *);
398 	dstsock = va_arg(ap, struct sockaddr_in6 *);
399 	control = va_arg(ap, struct mbuf *);
400 	va_end(ap);
401 
402 	in6p = sotoinpcb(so);
403 	INP_WLOCK(in6p);
404 
405 	dst = &dstsock->sin6_addr;
406 	if (control != NULL) {
407 		if ((error = ip6_setpktopts(control, &opt,
408 		    in6p->in6p_outputopts, so->so_cred,
409 		    so->so_proto->pr_protocol)) != 0) {
410 			goto bad;
411 		}
412 		optp = &opt;
413 	} else
414 		optp = in6p->in6p_outputopts;
415 
416 	/*
417 	 * Check and convert scope zone ID into internal form.
418 	 *
419 	 * XXX: we may still need to determine the zone later.
420 	 */
421 	if (!(so->so_state & SS_ISCONNECTED)) {
422 		if (dstsock->sin6_scope_id == 0 && !V_ip6_use_defzone)
423 			scope_ambiguous = 1;
424 		if ((error = sa6_embedscope(dstsock, V_ip6_use_defzone)) != 0)
425 			goto bad;
426 	}
427 
428 	/*
429 	 * For an ICMPv6 packet, we should know its type and code to update
430 	 * statistics.
431 	 */
432 	if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
433 		struct icmp6_hdr *icmp6;
434 		if (m->m_len < sizeof(struct icmp6_hdr) &&
435 		    (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
436 			error = ENOBUFS;
437 			goto bad;
438 		}
439 		icmp6 = mtod(m, struct icmp6_hdr *);
440 		type = icmp6->icmp6_type;
441 		code = icmp6->icmp6_code;
442 	}
443 
444 	M_PREPEND(m, sizeof(*ip6), M_DONTWAIT);
445 	if (m == NULL) {
446 		error = ENOBUFS;
447 		goto bad;
448 	}
449 	ip6 = mtod(m, struct ip6_hdr *);
450 
451 	/*
452 	 * Source address selection.
453 	 */
454 	if ((in6a = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
455 	    &oifp, &error)) == NULL) {
456 		if (error == 0)
457 			error = EADDRNOTAVAIL;
458 		goto bad;
459 	}
460 	error = prison_get_ip6(in6p->inp_cred, in6a);
461 	if (error != 0)
462 		goto bad;
463 	ip6->ip6_src = *in6a;
464 
465 	if (oifp && scope_ambiguous) {
466 		/*
467 		 * Application should provide a proper zone ID or the use of
468 		 * default zone IDs should be enabled.  Unfortunately, some
469 		 * applications do not behave as it should, so we need a
470 		 * workaround.  Even if an appropriate ID is not determined
471 		 * (when it's required), if we can determine the outgoing
472 		 * interface. determine the zone ID based on the interface.
473 		 */
474 		error = in6_setscope(&dstsock->sin6_addr, oifp, NULL);
475 		if (error != 0)
476 			goto bad;
477 	}
478 	ip6->ip6_dst = dstsock->sin6_addr;
479 
480 	/*
481 	 * Fill in the rest of the IPv6 header fields.
482 	 */
483 	ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
484 	    (in6p->inp_flow & IPV6_FLOWINFO_MASK);
485 	ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
486 	    (IPV6_VERSION & IPV6_VERSION_MASK);
487 
488 	/*
489 	 * ip6_plen will be filled in ip6_output, so not fill it here.
490 	 */
491 	ip6->ip6_nxt = in6p->inp_ip_p;
492 	ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
493 
494 	if (so->so_proto->pr_protocol == IPPROTO_ICMPV6 ||
495 	    in6p->in6p_cksum != -1) {
496 		struct mbuf *n;
497 		int off;
498 		u_int16_t *p;
499 
500 		/* Compute checksum. */
501 		if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
502 			off = offsetof(struct icmp6_hdr, icmp6_cksum);
503 		else
504 			off = in6p->in6p_cksum;
505 		if (plen < off + 1) {
506 			error = EINVAL;
507 			goto bad;
508 		}
509 		off += sizeof(struct ip6_hdr);
510 
511 		n = m;
512 		while (n && n->m_len <= off) {
513 			off -= n->m_len;
514 			n = n->m_next;
515 		}
516 		if (!n)
517 			goto bad;
518 		p = (u_int16_t *)(mtod(n, caddr_t) + off);
519 		*p = 0;
520 		*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
521 	}
522 
523 	error = ip6_output(m, optp, NULL, 0, in6p->in6p_moptions, &oifp, in6p);
524 	if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
525 		if (oifp)
526 			icmp6_ifoutstat_inc(oifp, type, code);
527 		ICMP6STAT_INC(icp6s_outhist[type]);
528 	} else
529 		V_rip6stat.rip6s_opackets++;
530 
531 	goto freectl;
532 
533  bad:
534 	if (m)
535 		m_freem(m);
536 
537  freectl:
538 	if (control != NULL) {
539 		ip6_clearpktopts(&opt, -1);
540 		m_freem(control);
541 	}
542 	INP_WUNLOCK(in6p);
543 	return (error);
544 }
545 
546 /*
547  * Raw IPv6 socket option processing.
548  */
549 int
550 rip6_ctloutput(struct socket *so, struct sockopt *sopt)
551 {
552 	int error;
553 
554 	if (sopt->sopt_level == IPPROTO_ICMPV6)
555 		/*
556 		 * XXX: is it better to call icmp6_ctloutput() directly
557 		 * from protosw?
558 		 */
559 		return (icmp6_ctloutput(so, sopt));
560 	else if (sopt->sopt_level != IPPROTO_IPV6)
561 		return (EINVAL);
562 
563 	error = 0;
564 
565 	switch (sopt->sopt_dir) {
566 	case SOPT_GET:
567 		switch (sopt->sopt_name) {
568 		case MRT6_INIT:
569 		case MRT6_DONE:
570 		case MRT6_ADD_MIF:
571 		case MRT6_DEL_MIF:
572 		case MRT6_ADD_MFC:
573 		case MRT6_DEL_MFC:
574 		case MRT6_PIM:
575 			error = ip6_mrouter_get ?  ip6_mrouter_get(so, sopt) :
576 			    EOPNOTSUPP;
577 			break;
578 		case IPV6_CHECKSUM:
579 			error = ip6_raw_ctloutput(so, sopt);
580 			break;
581 		default:
582 			error = ip6_ctloutput(so, sopt);
583 			break;
584 		}
585 		break;
586 
587 	case SOPT_SET:
588 		switch (sopt->sopt_name) {
589 		case MRT6_INIT:
590 		case MRT6_DONE:
591 		case MRT6_ADD_MIF:
592 		case MRT6_DEL_MIF:
593 		case MRT6_ADD_MFC:
594 		case MRT6_DEL_MFC:
595 		case MRT6_PIM:
596 			error = ip6_mrouter_set ?  ip6_mrouter_set(so, sopt) :
597 			    EOPNOTSUPP;
598 			break;
599 		case IPV6_CHECKSUM:
600 			error = ip6_raw_ctloutput(so, sopt);
601 			break;
602 		default:
603 			error = ip6_ctloutput(so, sopt);
604 			break;
605 		}
606 		break;
607 	}
608 
609 	return (error);
610 }
611 
612 static int
613 rip6_attach(struct socket *so, int proto, struct thread *td)
614 {
615 	INIT_VNET_INET(so->so_vnet);
616 	struct inpcb *inp;
617 	struct icmp6_filter *filter;
618 	int error;
619 
620 	inp = sotoinpcb(so);
621 	KASSERT(inp == NULL, ("rip6_attach: inp != NULL"));
622 
623 	error = priv_check(td, PRIV_NETINET_RAW);
624 	if (error)
625 		return (error);
626 	error = soreserve(so, rip_sendspace, rip_recvspace);
627 	if (error)
628 		return (error);
629 	filter = malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
630 	if (filter == NULL)
631 		return (ENOMEM);
632 	INP_INFO_WLOCK(&V_ripcbinfo);
633 	error = in_pcballoc(so, &V_ripcbinfo);
634 	if (error) {
635 		INP_INFO_WUNLOCK(&V_ripcbinfo);
636 		free(filter, M_PCB);
637 		return (error);
638 	}
639 	inp = (struct inpcb *)so->so_pcb;
640 	INP_INFO_WUNLOCK(&V_ripcbinfo);
641 	inp->inp_vflag |= INP_IPV6;
642 	inp->inp_ip_p = (long)proto;
643 	inp->in6p_hops = -1;	/* use kernel default */
644 	inp->in6p_cksum = -1;
645 	inp->in6p_icmp6filt = filter;
646 	ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
647 	INP_WUNLOCK(inp);
648 	return (0);
649 }
650 
651 static void
652 rip6_detach(struct socket *so)
653 {
654 	INIT_VNET_INET(so->so_vnet);
655 	INIT_VNET_INET6(so->so_vnet);
656 	struct inpcb *inp;
657 
658 	inp = sotoinpcb(so);
659 	KASSERT(inp != NULL, ("rip6_detach: inp == NULL"));
660 
661 	if (so == V_ip6_mrouter && ip6_mrouter_done)
662 		ip6_mrouter_done();
663 	/* xxx: RSVP */
664 	INP_INFO_WLOCK(&V_ripcbinfo);
665 	INP_WLOCK(inp);
666 	free(inp->in6p_icmp6filt, M_PCB);
667 	in_pcbdetach(inp);
668 	in_pcbfree(inp);
669 	INP_INFO_WUNLOCK(&V_ripcbinfo);
670 }
671 
672 /* XXXRW: This can't ever be called. */
673 static void
674 rip6_abort(struct socket *so)
675 {
676 	struct inpcb *inp;
677 
678 	inp = sotoinpcb(so);
679 	KASSERT(inp != NULL, ("rip6_abort: inp == NULL"));
680 
681 	soisdisconnected(so);
682 }
683 
684 static void
685 rip6_close(struct socket *so)
686 {
687 	struct inpcb *inp;
688 
689 	inp = sotoinpcb(so);
690 	KASSERT(inp != NULL, ("rip6_close: inp == NULL"));
691 
692 	soisdisconnected(so);
693 }
694 
695 static int
696 rip6_disconnect(struct socket *so)
697 {
698 	struct inpcb *inp;
699 
700 	inp = sotoinpcb(so);
701 	KASSERT(inp != NULL, ("rip6_disconnect: inp == NULL"));
702 
703 	if ((so->so_state & SS_ISCONNECTED) == 0)
704 		return (ENOTCONN);
705 	inp->in6p_faddr = in6addr_any;
706 	rip6_abort(so);
707 	return (0);
708 }
709 
710 static int
711 rip6_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
712 {
713 	INIT_VNET_NET(so->so_vnet);
714 	INIT_VNET_INET(so->so_vnet);
715 	INIT_VNET_INET6(so->so_vnet);
716 	struct inpcb *inp;
717 	struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
718 	struct ifaddr *ia = NULL;
719 	int error = 0;
720 
721 	inp = sotoinpcb(so);
722 	KASSERT(inp != NULL, ("rip6_bind: inp == NULL"));
723 
724 	if (nam->sa_len != sizeof(*addr))
725 		return (EINVAL);
726 	if ((error = prison_check_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
727 		return (error);
728 	if (TAILQ_EMPTY(&V_ifnet) || addr->sin6_family != AF_INET6)
729 		return (EADDRNOTAVAIL);
730 	if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
731 		return (error);
732 
733 	if (!IN6_IS_ADDR_UNSPECIFIED(&addr->sin6_addr) &&
734 	    (ia = ifa_ifwithaddr((struct sockaddr *)addr)) == 0)
735 		return (EADDRNOTAVAIL);
736 	if (ia &&
737 	    ((struct in6_ifaddr *)ia)->ia6_flags &
738 	    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
739 	     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
740 		return (EADDRNOTAVAIL);
741 	}
742 	INP_INFO_WLOCK(&V_ripcbinfo);
743 	INP_WLOCK(inp);
744 	inp->in6p_laddr = addr->sin6_addr;
745 	INP_WUNLOCK(inp);
746 	INP_INFO_WUNLOCK(&V_ripcbinfo);
747 	return (0);
748 }
749 
750 static int
751 rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
752 {
753 	INIT_VNET_NET(so->so_vnet);
754 	INIT_VNET_INET(so->so_vnet);
755 	INIT_VNET_INET6(so->so_vnet);
756 	struct inpcb *inp;
757 	struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
758 	struct in6_addr *in6a = NULL;
759 	struct ifnet *ifp = NULL;
760 	int error = 0, scope_ambiguous = 0;
761 
762 	inp = sotoinpcb(so);
763 	KASSERT(inp != NULL, ("rip6_connect: inp == NULL"));
764 
765 	if (nam->sa_len != sizeof(*addr))
766 		return (EINVAL);
767 	if (TAILQ_EMPTY(&V_ifnet))
768 		return (EADDRNOTAVAIL);
769 	if (addr->sin6_family != AF_INET6)
770 		return (EAFNOSUPPORT);
771 
772 	/*
773 	 * Application should provide a proper zone ID or the use of default
774 	 * zone IDs should be enabled.  Unfortunately, some applications do
775 	 * not behave as it should, so we need a workaround.  Even if an
776 	 * appropriate ID is not determined, we'll see if we can determine
777 	 * the outgoing interface.  If we can, determine the zone ID based on
778 	 * the interface below.
779 	 */
780 	if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone)
781 		scope_ambiguous = 1;
782 	if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0)
783 		return (error);
784 
785 	INP_INFO_WLOCK(&V_ripcbinfo);
786 	INP_WLOCK(inp);
787 	/* Source address selection. XXX: need pcblookup? */
788 	in6a = in6_selectsrc(addr, inp->in6p_outputopts,
789 			     inp, NULL, so->so_cred,
790 			     &ifp, &error);
791 	if (in6a == NULL) {
792 		INP_WUNLOCK(inp);
793 		INP_INFO_WUNLOCK(&V_ripcbinfo);
794 		return (error ? error : EADDRNOTAVAIL);
795 	}
796 
797 	/* XXX: see above */
798 	if (ifp && scope_ambiguous &&
799 	    (error = in6_setscope(&addr->sin6_addr, ifp, NULL)) != 0) {
800 		INP_WUNLOCK(inp);
801 		INP_INFO_WUNLOCK(&V_ripcbinfo);
802 		return (error);
803 	}
804 	inp->in6p_faddr = addr->sin6_addr;
805 	inp->in6p_laddr = *in6a;
806 	soisconnected(so);
807 	INP_WUNLOCK(inp);
808 	INP_INFO_WUNLOCK(&V_ripcbinfo);
809 	return (0);
810 }
811 
812 static int
813 rip6_shutdown(struct socket *so)
814 {
815 	struct inpcb *inp;
816 
817 	inp = sotoinpcb(so);
818 	KASSERT(inp != NULL, ("rip6_shutdown: inp == NULL"));
819 
820 	INP_WLOCK(inp);
821 	socantsendmore(so);
822 	INP_WUNLOCK(inp);
823 	return (0);
824 }
825 
826 static int
827 rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
828     struct mbuf *control, struct thread *td)
829 {
830 	struct inpcb *inp;
831 	struct sockaddr_in6 tmp;
832 	struct sockaddr_in6 *dst;
833 	int ret;
834 
835 	inp = sotoinpcb(so);
836 	KASSERT(inp != NULL, ("rip6_send: inp == NULL"));
837 
838 	/* Always copy sockaddr to avoid overwrites. */
839 	/* Unlocked read. */
840 	if (so->so_state & SS_ISCONNECTED) {
841 		if (nam) {
842 			m_freem(m);
843 			return (EISCONN);
844 		}
845 		/* XXX */
846 		bzero(&tmp, sizeof(tmp));
847 		tmp.sin6_family = AF_INET6;
848 		tmp.sin6_len = sizeof(struct sockaddr_in6);
849 		INP_RLOCK(inp);
850 		bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
851 		    sizeof(struct in6_addr));
852 		INP_RUNLOCK(inp);
853 		dst = &tmp;
854 	} else {
855 		if (nam == NULL) {
856 			m_freem(m);
857 			return (ENOTCONN);
858 		}
859 		if (nam->sa_len != sizeof(struct sockaddr_in6)) {
860 			m_freem(m);
861 			return (EINVAL);
862 		}
863 		tmp = *(struct sockaddr_in6 *)nam;
864 		dst = &tmp;
865 
866 		if (dst->sin6_family == AF_UNSPEC) {
867 			/*
868 			 * XXX: we allow this case for backward
869 			 * compatibility to buggy applications that
870 			 * rely on old (and wrong) kernel behavior.
871 			 */
872 			log(LOG_INFO, "rip6 SEND: address family is "
873 			    "unspec. Assume AF_INET6\n");
874 			dst->sin6_family = AF_INET6;
875 		} else if (dst->sin6_family != AF_INET6) {
876 			m_freem(m);
877 			return(EAFNOSUPPORT);
878 		}
879 	}
880 	ret = rip6_output(m, so, dst, control);
881 	return (ret);
882 }
883 
884 struct pr_usrreqs rip6_usrreqs = {
885 	.pru_abort =		rip6_abort,
886 	.pru_attach =		rip6_attach,
887 	.pru_bind =		rip6_bind,
888 	.pru_connect =		rip6_connect,
889 	.pru_control =		in6_control,
890 	.pru_detach =		rip6_detach,
891 	.pru_disconnect =	rip6_disconnect,
892 	.pru_peeraddr =		in6_getpeeraddr,
893 	.pru_send =		rip6_send,
894 	.pru_shutdown =		rip6_shutdown,
895 	.pru_sockaddr =		in6_getsockaddr,
896 	.pru_close =		rip6_close,
897 };
898