1/*
2 * Copyright (c) 2000-2014 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 *    notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 *    notice, this list of conditions and the following disclaimer in the
39 *    documentation and/or other materials provided with the distribution.
40 * 3. Neither the name of the project nor the names of its contributors
41 *    may be used to endorse or promote products derived from this software
42 *    without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.4 2001/07/29 19:32:40 ume Exp $
57 */
58
59/*
60 * Copyright (c) 1982, 1986, 1988, 1993
61 *	The Regents of the University of California.  All rights reserved.
62 *
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
65 * are met:
66 * 1. Redistributions of source code must retain the above copyright
67 *    notice, this list of conditions and the following disclaimer.
68 * 2. Redistributions in binary form must reproduce the above copyright
69 *    notice, this list of conditions and the following disclaimer in the
70 *    documentation and/or other materials provided with the distribution.
71 * 3. All advertising materials mentioning features or use of this software
72 *    must display the following acknowledgement:
73 *	This product includes software developed by the University of
74 *	California, Berkeley and its contributors.
75 * 4. Neither the name of the University nor the names of its contributors
76 *    may be used to endorse or promote products derived from this software
77 *    without specific prior written permission.
78 *
79 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
80 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
81 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
82 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
83 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
84 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
85 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
86 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
87 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
88 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
89 * SUCH DAMAGE.
90 *
91 *	@(#)raw_ip.c	8.2 (Berkeley) 1/4/94
92 */
93#include <sys/param.h>
94#include <sys/malloc.h>
95#include <sys/proc.h>
96#include <sys/mcache.h>
97#include <sys/mbuf.h>
98#include <sys/socket.h>
99#include <sys/protosw.h>
100#include <sys/socketvar.h>
101#include <sys/errno.h>
102#include <sys/systm.h>
103
104#include <net/if.h>
105#include <net/route.h>
106#include <net/if_types.h>
107
108#include <netinet/in.h>
109#include <netinet/in_var.h>
110#include <netinet/in_systm.h>
111#include <netinet/ip6.h>
112#include <netinet6/ip6_var.h>
113#include <netinet/icmp6.h>
114#include <netinet/in_pcb.h>
115#include <netinet6/in6_pcb.h>
116#include <netinet6/nd6.h>
117#include <netinet6/ip6protosw.h>
118#include <netinet6/scope6_var.h>
119#include <netinet6/raw_ip6.h>
120#include <netinet6/ip6_fw.h>
121
122#if IPSEC
123#include <netinet6/ipsec.h>
124#include <netinet6/ipsec6.h>
125#endif /*IPSEC*/
126
127#if NECP
128#include <net/necp.h>
129#endif
130
131/*
132 * Raw interface to IP6 protocol.
133 */
134
135extern struct	inpcbhead ripcb;
136extern struct	inpcbinfo ripcbinfo;
137extern u_int32_t	rip_sendspace;
138extern u_int32_t	rip_recvspace;
139
140struct rip6stat rip6stat;
141
142/*
143 * Setup generic address and protocol structures
144 * for raw_input routine, then pass them along with
145 * mbuf chain.
146 */
147int
148rip6_input(
149	struct	mbuf **mp,
150	int	*offp,
151	int	proto)
152{
153	struct mbuf *m = *mp;
154	struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *);
155	struct inpcb *in6p;
156	struct inpcb *last = 0;
157	struct mbuf *opts = NULL;
158	struct sockaddr_in6 rip6src;
159	int ret;
160	struct ifnet *ifp = m->m_pkthdr.rcvif;
161
162	/* Expect 32-bit aligned data pointer on strict-align platforms */
163	MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m);
164
165	rip6stat.rip6s_ipackets++;
166
167	init_sin6(&rip6src, m); /* general init */
168
169	lck_rw_lock_shared(ripcbinfo.ipi_lock);
170	LIST_FOREACH(in6p, &ripcb, inp_list) {
171		if ((in6p->in6p_vflag & INP_IPV6) == 0)
172			continue;
173		if (in6p->in6p_ip6_nxt &&
174		    in6p->in6p_ip6_nxt != proto)
175			continue;
176		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr) &&
177		    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, &ip6->ip6_dst))
178			continue;
179		if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr) &&
180		    !IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, &ip6->ip6_src))
181			continue;
182
183		if (inp_restricted_recv(in6p, ifp))
184			continue;
185
186		if (proto == IPPROTO_ICMPV6 || in6p->in6p_cksum != -1) {
187			rip6stat.rip6s_isum++;
188			if (in6_cksum(m, ip6->ip6_nxt, *offp,
189			    m->m_pkthdr.len - *offp)) {
190				rip6stat.rip6s_badsum++;
191				continue;
192			}
193		}
194		if (last) {
195			struct mbuf *n = m_copy(m, 0, (int)M_COPYALL);
196
197#if NECP
198			if (n && !necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_dst, &ip6->ip6_src, ifp, NULL)) {
199				m_freem(n);
200				/* do not inject data into pcb */
201			} else
202#endif /* NECP */
203			if (n) {
204				if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
205				    (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
206				    (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) {
207					ret = ip6_savecontrol(last, n, &opts);
208					if (ret != 0) {
209						m_freem(n);
210						m_freem(opts);
211						last = in6p;
212						continue;
213					}
214				}
215				/* strip intermediate headers */
216				m_adj(n, *offp);
217				so_recv_data_stat(last->in6p_socket, m, 0);
218				if (sbappendaddr(&last->in6p_socket->so_rcv,
219						(struct sockaddr *)&rip6src,
220						 n, opts, NULL) == 0) {
221					rip6stat.rip6s_fullsock++;
222				} else
223					sorwakeup(last->in6p_socket);
224				opts = NULL;
225			}
226		}
227		last = in6p;
228	}
229
230#if NECP
231	if (last && !necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_dst, &ip6->ip6_src, ifp, NULL)) {
232		m_freem(m);
233		ip6stat.ip6s_delivered--;
234		/* do not inject data into pcb */
235	} else
236#endif /* NECP */
237	if (last) {
238		if ((last->in6p_flags & INP_CONTROLOPTS) != 0 ||
239		    (last->in6p_socket->so_options & SO_TIMESTAMP) != 0 ||
240		    (last->in6p_socket->so_options & SO_TIMESTAMP_MONOTONIC) != 0) {
241			ret = ip6_savecontrol(last, m, &opts);
242			if (ret != 0) {
243				m_freem(m);
244				m_freem(opts);
245				ip6stat.ip6s_delivered--;
246				goto unlock;
247			}
248
249		}
250		/* strip intermediate headers */
251		m_adj(m, *offp);
252		so_recv_data_stat(last->in6p_socket, m, 0);
253		if (sbappendaddr(&last->in6p_socket->so_rcv,
254				(struct sockaddr *)&rip6src, m, opts, NULL) == 0) {
255			rip6stat.rip6s_fullsock++;
256		} else
257			sorwakeup(last->in6p_socket);
258	} else {
259		rip6stat.rip6s_nosock++;
260		if (m->m_flags & M_MCAST)
261			rip6stat.rip6s_nosockmcast++;
262		if (proto == IPPROTO_NONE)
263			m_freem(m);
264		else {
265			char *prvnxtp = ip6_get_prevhdr(m, *offp); /* XXX */
266			icmp6_error(m, ICMP6_PARAM_PROB,
267				    ICMP6_PARAMPROB_NEXTHEADER,
268				    prvnxtp - mtod(m, char *));
269		}
270		ip6stat.ip6s_delivered--;
271	}
272
273unlock:
274	lck_rw_done(ripcbinfo.ipi_lock);
275
276	return IPPROTO_DONE;
277}
278
279void
280rip6_ctlinput(
281	int cmd,
282	struct sockaddr *sa,
283	void *d)
284{
285	struct ip6_hdr *ip6;
286	struct mbuf *m;
287	void *cmdarg = NULL;
288	int off = 0;
289	struct ip6ctlparam *ip6cp = NULL;
290	const struct sockaddr_in6 *sa6_src = NULL;
291	void (*notify)(struct inpcb *, int) = in6_rtchange;
292
293	if (sa->sa_family != AF_INET6 ||
294	    sa->sa_len != sizeof(struct sockaddr_in6))
295		return;
296
297	if ((unsigned)cmd >= PRC_NCMDS)
298		return;
299	if (PRC_IS_REDIRECT(cmd))
300		notify = in6_rtchange, d = NULL;
301	else if (cmd == PRC_HOSTDEAD)
302		d = NULL;
303	else if (inet6ctlerrmap[cmd] == 0)
304		return;
305
306	/* if the parameter is from icmp6, decode it. */
307	if (d != NULL) {
308		ip6cp = (struct ip6ctlparam *)d;
309		m = ip6cp->ip6c_m;
310		ip6 = ip6cp->ip6c_ip6;
311		off = ip6cp->ip6c_off;
312		cmdarg = ip6cp->ip6c_cmdarg;
313		sa6_src = ip6cp->ip6c_src;
314	} else {
315		m = NULL;
316		ip6 = NULL;
317		sa6_src = &sa6_any;
318	}
319
320	(void) in6_pcbnotify(&ripcbinfo, sa, 0, (const struct sockaddr *)sa6_src,
321			     0, cmd, cmdarg, notify);
322}
323
324/*
325 * Generate IPv6 header and pass packet to ip6_output.
326 * Tack on options user may have setup with control call.
327 */
328int
329rip6_output(
330	struct mbuf *m,
331	struct socket *so,
332	struct sockaddr_in6 *dstsock,
333	struct mbuf *control,
334	int israw)
335{
336	struct in6_addr *dst;
337	struct ip6_hdr *ip6;
338	struct inpcb *in6p;
339	u_int	plen = m->m_pkthdr.len;
340	int error = 0;
341	struct ip6_pktopts opt, *optp = NULL;
342	struct ip6_moptions *im6o = NULL;
343	struct ifnet *oifp = NULL;
344	int type = 0, code = 0;		/* for ICMPv6 output statistics only */
345	mbuf_svc_class_t msc = MBUF_SC_UNSPEC;
346	struct ip6_out_args ip6oa =
347	    { IFSCOPE_NONE, { 0 }, IP6OAF_SELECT_SRCIF, 0 };
348	int flags = IPV6_OUTARGS;
349
350	in6p = sotoin6pcb(so);
351
352	if (in6p == NULL
353#if NECP
354		|| (necp_socket_should_use_flow_divert(in6p))
355#endif /* NECP */
356		) {
357		if (in6p == NULL)
358			error = EINVAL;
359		else
360			error = EPROTOTYPE;
361		goto bad;
362	}
363	if (dstsock != NULL && IN6_IS_ADDR_V4MAPPED(&dstsock->sin6_addr)) {
364		error = EINVAL;
365		goto bad;
366	}
367
368	if (in6p->inp_flags & INP_BOUND_IF) {
369		ip6oa.ip6oa_boundif = in6p->inp_boundifp->if_index;
370		ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
371	}
372	if (INP_NO_CELLULAR(in6p))
373		ip6oa.ip6oa_flags |= IP6OAF_NO_CELLULAR;
374	if (INP_NO_EXPENSIVE(in6p))
375		ip6oa.ip6oa_flags |= IP6OAF_NO_EXPENSIVE;
376	if (INP_AWDL_UNRESTRICTED(in6p))
377		ip6oa.ip6oa_flags |= IP6OAF_AWDL_UNRESTRICTED;
378
379	dst = &dstsock->sin6_addr;
380	if (control) {
381		msc = mbuf_service_class_from_control(control);
382
383		if ((error = ip6_setpktopts(control, &opt, NULL,
384		    SOCK_PROTO(so))) != 0)
385			goto bad;
386		optp = &opt;
387	} else
388		optp = in6p->in6p_outputopts;
389
390	/*
391	 * For an ICMPv6 packet, we should know its type and code
392	 * to update statistics.
393	 */
394	if (SOCK_PROTO(so) == IPPROTO_ICMPV6) {
395		struct icmp6_hdr *icmp6;
396		if (m->m_len < sizeof(struct icmp6_hdr) &&
397		    (m = m_pullup(m, sizeof(struct icmp6_hdr))) == NULL) {
398			error = ENOBUFS;
399			goto bad;
400		}
401		icmp6 = mtod(m, struct icmp6_hdr *);
402		type = icmp6->icmp6_type;
403		code = icmp6->icmp6_code;
404	}
405
406	if (in6p->inp_flowhash == 0)
407		in6p->inp_flowhash = inp_calc_flowhash(in6p);
408	/* update flowinfo - RFC 6437 */
409	if (in6p->inp_flow == 0 && in6p->in6p_flags & IN6P_AUTOFLOWLABEL) {
410		in6p->inp_flow &= ~IPV6_FLOWLABEL_MASK;
411		in6p->inp_flow |=
412		    (htonl(in6p->inp_flowhash) & IPV6_FLOWLABEL_MASK);
413	}
414
415	M_PREPEND(m, sizeof(*ip6), M_WAIT);
416	if (m == NULL) {
417		error = ENOBUFS;
418		goto bad;
419	}
420	ip6 = mtod(m, struct ip6_hdr *);
421
422	/*
423	 * Next header might not be ICMP6 but use its pseudo header anyway.
424	 */
425	ip6->ip6_dst = *dst;
426
427	im6o = in6p->in6p_moptions;
428
429	/*
430	 * If the scope of the destination is link-local, embed the interface
431	 * index in the address.
432	 *
433	 * XXX advanced-api value overrides sin6_scope_id
434	 */
435	if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) {
436		struct in6_pktinfo *pi;
437		struct ifnet *im6o_multicast_ifp = NULL;
438
439		if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) && im6o != NULL) {
440			IM6O_LOCK(im6o);
441			im6o_multicast_ifp = im6o->im6o_multicast_ifp;
442			IM6O_UNLOCK(im6o);
443		}
444		/*
445		 * XXX Boundary check is assumed to be already done in
446		 * ip6_setpktoptions().
447		 */
448		ifnet_head_lock_shared();
449		if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) {
450			ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex);
451			oifp = ifindex2ifnet[pi->ipi6_ifindex];
452			if (oifp != NULL)
453				ifnet_reference(oifp);
454		} else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
455		    im6o != NULL && im6o_multicast_ifp != NULL) {
456			oifp = im6o_multicast_ifp;
457			ifnet_reference(oifp);
458			ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index);
459		} else if (dstsock->sin6_scope_id) {
460			/*
461			 * boundary check
462			 *
463			 * Sinced stsock->sin6_scope_id is unsigned, we don't
464			 * need to check if it's < 0
465			 */
466			if (if_index < dstsock->sin6_scope_id) {
467				error = ENXIO;  /* XXX EINVAL? */
468				ifnet_head_done();
469				goto bad;
470			}
471			ip6->ip6_dst.s6_addr16[1]
472				= htons(dstsock->sin6_scope_id & 0xffff);/*XXX*/
473		}
474		ifnet_head_done();
475	}
476
477	/*
478	 * Source address selection.
479	 */
480	{
481		struct in6_addr *in6a;
482		struct in6_addr	storage;
483		u_short index = 0;
484
485		if (israw != 0 && optp && optp->ip6po_pktinfo && !IN6_IS_ADDR_UNSPECIFIED(&optp->ip6po_pktinfo->ipi6_addr)) {
486			in6a = &optp->ip6po_pktinfo->ipi6_addr;
487			flags |= IPV6_FLAG_NOSRCIFSEL;
488		} else if ((in6a = in6_selectsrc(dstsock, optp, in6p,
489		    &in6p->in6p_route, NULL, &storage, ip6oa.ip6oa_boundif,
490		    &error)) == 0) {
491			if (error == 0)
492				error = EADDRNOTAVAIL;
493			goto bad;
494		} else {
495			ip6oa.ip6oa_flags |= IP6OAF_BOUND_SRCADDR;
496		}
497		ip6->ip6_src = *in6a;
498		if (in6p->in6p_route.ro_rt != NULL) {
499			RT_LOCK(in6p->in6p_route.ro_rt);
500			if (in6p->in6p_route.ro_rt->rt_ifp != NULL)
501				index = in6p->in6p_route.ro_rt->rt_ifp->if_index;
502			RT_UNLOCK(in6p->in6p_route.ro_rt);
503			if (oifp != NULL)
504				ifnet_release(oifp);
505			ifnet_head_lock_shared();
506			if (index == 0 || if_index < index) {
507				panic("bad if_index on interface from route");
508			}
509			oifp = ifindex2ifnet[index];
510			if (oifp != NULL)
511				ifnet_reference(oifp);
512			ifnet_head_done();
513		}
514	}
515	ip6->ip6_flow = (ip6->ip6_flow & ~IPV6_FLOWINFO_MASK) |
516		(in6p->inp_flow & IPV6_FLOWINFO_MASK);
517	ip6->ip6_vfc = (ip6->ip6_vfc & ~IPV6_VERSION_MASK) |
518		(IPV6_VERSION & IPV6_VERSION_MASK);
519	/* ip6_plen will be filled in ip6_output, so not fill it here. */
520	ip6->ip6_nxt = in6p->in6p_ip6_nxt;
521	ip6->ip6_hlim = in6_selecthlim(in6p, oifp);
522
523	if (SOCK_PROTO(so) == IPPROTO_ICMPV6 || in6p->in6p_cksum != -1) {
524		struct mbuf *n;
525		int off;
526		u_int16_t *p;
527
528		/* compute checksum */
529		if (SOCK_PROTO(so) == IPPROTO_ICMPV6)
530			off = offsetof(struct icmp6_hdr, icmp6_cksum);
531		else
532			off = in6p->in6p_cksum;
533		if (plen < (unsigned int)(off + 1)) {
534			error = EINVAL;
535			goto bad;
536		}
537		off += sizeof(struct ip6_hdr);
538
539		n = m;
540		while (n && n->m_len <= off) {
541			off -= n->m_len;
542			n = n->m_next;
543		}
544		if (!n)
545			goto bad;
546		p = (u_int16_t *)(void *)(mtod(n, caddr_t) + off);
547		*p = 0;
548		*p = in6_cksum(m, ip6->ip6_nxt, sizeof(*ip6), plen);
549	}
550
551#if NECP
552	{
553		necp_kernel_policy_id policy_id;
554		if (!necp_socket_is_allowed_to_send_recv_v6(in6p, 0, 0, &ip6->ip6_src, &ip6->ip6_dst, NULL, &policy_id)) {
555			error = EHOSTUNREACH;
556			goto bad;
557		}
558
559		necp_mark_packet_from_socket(m, in6p, policy_id);
560	}
561#endif /* NECP */
562
563#if IPSEC
564	if (in6p->in6p_sp != NULL && ipsec_setsocket(m, so) != 0) {
565		error = ENOBUFS;
566		goto bad;
567	}
568#endif /*IPSEC*/
569
570	if (ROUTE_UNUSABLE(&in6p->in6p_route))
571		ROUTE_RELEASE(&in6p->in6p_route);
572
573	if (oifp != NULL) {
574		ifnet_release(oifp);
575		oifp = NULL;
576	}
577
578	set_packet_service_class(m, so, msc, PKT_SCF_IPV6);
579	m->m_pkthdr.pkt_flowsrc = FLOWSRC_INPCB;
580	m->m_pkthdr.pkt_flowid = in6p->inp_flowhash;
581	m->m_pkthdr.pkt_flags |= (PKTF_FLOW_ID | PKTF_FLOW_LOCALSRC |
582	    PKTF_FLOW_RAWSOCK);
583	m->m_pkthdr.pkt_proto = in6p->in6p_ip6_nxt;
584
585	if (im6o != NULL)
586		IM6O_ADDREF(im6o);
587
588	error = ip6_output(m, optp, &in6p->in6p_route, flags, im6o,
589	    &oifp, &ip6oa);
590
591	if (im6o != NULL)
592		IM6O_REMREF(im6o);
593
594	if (in6p->in6p_route.ro_rt != NULL) {
595		struct rtentry *rt = in6p->in6p_route.ro_rt;
596		struct ifnet *outif;
597
598		if ((rt->rt_flags & RTF_MULTICAST) ||
599		    in6p->in6p_socket == NULL ||
600		    !(in6p->in6p_socket->so_state & SS_ISCONNECTED)) {
601			rt = NULL;	/* unusable */
602		}
603		/*
604		 * Always discard the cached route for unconnected
605		 * socket or if it is a multicast route.
606		 */
607		if (rt == NULL)
608			ROUTE_RELEASE(&in6p->in6p_route);
609
610		/*
611		 * If this is a connected socket and the destination
612		 * route is not multicast, update outif with that of
613		 * the route interface index used by IP.
614		 */
615		if (rt != NULL &&
616		    (outif = rt->rt_ifp) != in6p->in6p_last_outifp)
617			in6p->in6p_last_outifp = outif;
618	} else {
619		ROUTE_RELEASE(&in6p->in6p_route);
620	}
621
622	/*
623	 * If output interface was cellular/expensive, and this socket is
624	 * denied access to it, generate an event.
625	 */
626	if (error != 0 && (ip6oa.ip6oa_retflags & IP6OARF_IFDENIED) &&
627	    (INP_NO_CELLULAR(in6p) || INP_NO_EXPENSIVE(in6p)))
628		soevent(in6p->inp_socket, (SO_FILT_HINT_LOCKED|
629		    SO_FILT_HINT_IFDENIED));
630
631	if (SOCK_PROTO(so) == IPPROTO_ICMPV6) {
632		if (oifp)
633			icmp6_ifoutstat_inc(oifp, type, code);
634		icmp6stat.icp6s_outhist[type]++;
635	} else
636		rip6stat.rip6s_opackets++;
637
638	goto freectl;
639
640bad:
641	if (m != NULL)
642		m_freem(m);
643
644freectl:
645	if (optp == &opt && optp->ip6po_rthdr)
646		ROUTE_RELEASE(&optp->ip6po_route);
647
648	if (control != NULL) {
649		if (optp == &opt)
650			ip6_clearpktopts(optp, -1);
651		m_freem(control);
652	}
653	if (oifp != NULL)
654		ifnet_release(oifp);
655	return(error);
656}
657
658#if IPFW2
659__private_extern__ void
660load_ip6fw(void)
661{
662	ip6_fw_init();
663}
664#endif
665
666/*
667 * Raw IPv6 socket option processing.
668 */
669int
670rip6_ctloutput(
671	struct socket *so,
672	struct sockopt *sopt)
673{
674	int error, optval;
675
676	/* Allow <SOL_SOCKET,SO_FLUSH> at this level */
677	if (sopt->sopt_level == IPPROTO_ICMPV6)
678		/*
679		 * XXX: is it better to call icmp6_ctloutput() directly
680		 * from protosw?
681		 */
682		return(icmp6_ctloutput(so, sopt));
683	else if (sopt->sopt_level != IPPROTO_IPV6 &&
684	    !(sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_FLUSH))
685		return (EINVAL);
686
687	error = 0;
688
689	switch (sopt->sopt_dir) {
690	case SOPT_GET:
691		switch (sopt->sopt_name) {
692#if IPFW2
693		case IPV6_FW_ADD:
694		case IPV6_FW_GET:
695			if (ip6_fw_ctl_ptr == 0)
696				load_ip6fw();
697			if (ip6_fw_ctl_ptr)
698				error = ip6_fw_ctl_ptr(sopt);
699			else
700				error = ENOPROTOOPT;
701			break;
702#endif
703		case IPV6_CHECKSUM:
704			error = ip6_raw_ctloutput(so, sopt);
705			break;
706		default:
707			error = ip6_ctloutput(so, sopt);
708			break;
709		}
710		break;
711
712	case SOPT_SET:
713		switch (sopt->sopt_name) {
714#if IPFW2
715		case IPV6_FW_ADD:
716		case IPV6_FW_DEL:
717		case IPV6_FW_FLUSH:
718		case IPV6_FW_ZERO:
719			if (ip6_fw_ctl_ptr == 0)
720				load_ip6fw();
721			if (ip6_fw_ctl_ptr)
722				error = ip6_fw_ctl_ptr(sopt);
723			else
724				error = ENOPROTOOPT;
725			break;
726#endif
727
728		case IPV6_CHECKSUM:
729			error = ip6_raw_ctloutput(so, sopt);
730			break;
731
732		case SO_FLUSH:
733			if ((error = sooptcopyin(sopt, &optval, sizeof (optval),
734			    sizeof (optval))) != 0)
735				break;
736
737			error = inp_flush(sotoinpcb(so), optval);
738			break;
739
740		default:
741			error = ip6_ctloutput(so, sopt);
742			break;
743		}
744		break;
745	}
746
747	return (error);
748}
749
750static int
751rip6_attach(struct socket *so, int proto, struct proc *p)
752{
753	struct inpcb *inp;
754	int error;
755
756	inp = sotoinpcb(so);
757	if (inp)
758		panic("rip6_attach");
759	if ((error = proc_suser(p)) != 0)
760		return error;
761
762	error = soreserve(so, rip_sendspace, rip_recvspace);
763	if (error)
764		return error;
765	error = in_pcballoc(so, &ripcbinfo, p);
766	if (error)
767		return error;
768	inp = (struct inpcb *)so->so_pcb;
769	inp->inp_vflag |= INP_IPV6;
770	inp->in6p_ip6_nxt = (char)proto;
771	inp->in6p_hops = -1;	/* use kernel default */
772	inp->in6p_cksum = -1;
773	MALLOC(inp->in6p_icmp6filt, struct icmp6_filter *,
774	       sizeof(struct icmp6_filter), M_PCB, M_WAITOK);
775	if (inp->in6p_icmp6filt == NULL)
776		return (ENOMEM);
777	ICMP6_FILTER_SETPASSALL(inp->in6p_icmp6filt);
778	return 0;
779}
780
781static int
782rip6_detach(struct socket *so)
783{
784	struct inpcb *inp;
785
786	inp = sotoinpcb(so);
787	if (inp == 0)
788		panic("rip6_detach");
789	/* xxx: RSVP */
790	if (inp->in6p_icmp6filt) {
791		FREE(inp->in6p_icmp6filt, M_PCB);
792		inp->in6p_icmp6filt = NULL;
793	}
794	in6_pcbdetach(inp);
795	return 0;
796}
797
798static int
799rip6_abort(struct socket *so)
800{
801	soisdisconnected(so);
802	return rip6_detach(so);
803}
804
805static int
806rip6_disconnect(struct socket *so)
807{
808	struct inpcb *inp = sotoinpcb(so);
809
810	if ((so->so_state & SS_ISCONNECTED) == 0)
811		return ENOTCONN;
812	inp->in6p_faddr = in6addr_any;
813	return rip6_abort(so);
814}
815
816static int
817rip6_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
818{
819#pragma unused(p)
820	struct inpcb *inp = sotoinpcb(so);
821	struct sockaddr_in6 sin6;
822	struct ifaddr *ifa = NULL;
823	struct ifnet *outif = NULL;
824	int error;
825
826	if (inp == NULL
827#if NECP
828		|| (necp_socket_should_use_flow_divert(inp))
829#endif /* NECP */
830		)
831		return (inp == NULL ? EINVAL : EPROTOTYPE);
832
833	if (nam->sa_len != sizeof (struct sockaddr_in6))
834		return (EINVAL);
835
836	if (TAILQ_EMPTY(&ifnet_head) || SIN6(nam)->sin6_family != AF_INET6)
837		return (EADDRNOTAVAIL);
838
839	bzero(&sin6, sizeof (sin6));
840	*(&sin6) = *SIN6(nam);
841
842	if ((error = sa6_embedscope(&sin6, ip6_use_defzone)) != 0)
843		return (error);
844
845	/* Sanitize local copy for address searches */
846	sin6.sin6_flowinfo = 0;
847	sin6.sin6_scope_id = 0;
848	sin6.sin6_port = 0;
849
850	if (!IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr) &&
851	    (ifa = ifa_ifwithaddr(SA(&sin6))) == 0)
852		return (EADDRNOTAVAIL);
853	if (ifa != NULL) {
854		IFA_LOCK(ifa);
855		if (((struct in6_ifaddr *)ifa)->ia6_flags &
856		    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
857		     IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
858			IFA_UNLOCK(ifa);
859			IFA_REMREF(ifa);
860			return (EADDRNOTAVAIL);
861		}
862		outif = ifa->ifa_ifp;
863		IFA_UNLOCK(ifa);
864		IFA_REMREF(ifa);
865	}
866	inp->in6p_laddr = sin6.sin6_addr;
867	inp->in6p_last_outifp = outif;
868	return (0);
869}
870
871static int
872rip6_connect(struct socket *so, struct sockaddr *nam, __unused struct proc *p)
873{
874	struct inpcb *inp = sotoinpcb(so);
875	struct sockaddr_in6 *addr = (struct sockaddr_in6 *)(void *)nam;
876	struct in6_addr *in6a = NULL;
877	struct in6_addr storage;
878	int error = 0;
879#if ENABLE_DEFAULT_SCOPE
880	struct sockaddr_in6 tmp;
881#endif
882	unsigned int ifscope;
883	struct ifnet *outif = NULL;
884
885	if (inp == NULL
886#if NECP
887		|| (necp_socket_should_use_flow_divert(inp))
888#endif /* NECP */
889		)
890		return (inp == NULL ? EINVAL : EPROTOTYPE);
891	if (nam->sa_len != sizeof(*addr))
892		return EINVAL;
893	if (TAILQ_EMPTY(&ifnet_head))
894		return EADDRNOTAVAIL;
895	if (addr->sin6_family != AF_INET6)
896		return EAFNOSUPPORT;
897#if ENABLE_DEFAULT_SCOPE
898	if (addr->sin6_scope_id == 0) {	/* not change if specified  */
899		/* avoid overwrites */
900		tmp = *addr;
901		addr = &tmp;
902		addr->sin6_scope_id = scope6_addr2default(&addr->sin6_addr);
903	}
904#endif
905
906	ifscope = (inp->inp_flags & INP_BOUND_IF) ?
907	    inp->inp_boundifp->if_index : IFSCOPE_NONE;
908
909	/* Source address selection. XXX: need pcblookup? */
910	in6a = in6_selectsrc(addr, inp->in6p_outputopts, inp, &inp->in6p_route,
911	    NULL, &storage, ifscope, &error);
912	if (in6a == NULL)
913		return (error ? error : EADDRNOTAVAIL);
914	inp->in6p_laddr = *in6a;
915	inp->in6p_faddr = addr->sin6_addr;
916	if (inp->in6p_route.ro_rt != NULL)
917		outif = inp->in6p_route.ro_rt->rt_ifp;
918	inp->in6p_last_outifp = outif;
919	soisconnected(so);
920	return 0;
921}
922
923static int
924rip6_shutdown(struct socket *so)
925{
926	socantsendmore(so);
927	return 0;
928}
929
930static int
931rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
932    struct mbuf *control, struct proc *p)
933{
934#pragma unused(flags, p)
935	struct inpcb *inp = sotoinpcb(so);
936	struct sockaddr_in6 tmp;
937	struct sockaddr_in6 *dst = (struct sockaddr_in6 *)(void *)nam;
938	int error = 0;
939
940	if (inp == NULL
941#if NECP
942		|| (necp_socket_should_use_flow_divert(inp))
943#endif /* NECP */
944		) {
945		if (inp == NULL)
946			error = EINVAL;
947		else
948			error = EPROTOTYPE;
949		goto bad;
950	}
951
952	/* always copy sockaddr to avoid overwrites */
953	if (so->so_state & SS_ISCONNECTED) {
954		if (nam != NULL) {
955			error = EISCONN;
956			goto bad;
957		}
958		/* XXX */
959		bzero(&tmp, sizeof(tmp));
960		tmp.sin6_family = AF_INET6;
961		tmp.sin6_len = sizeof(struct sockaddr_in6);
962		bcopy(&inp->in6p_faddr, &tmp.sin6_addr,
963		      sizeof(struct in6_addr));
964		dst = &tmp;
965	} else {
966		if (nam == NULL) {
967			error = ENOTCONN;
968			goto bad;
969		}
970		tmp = *(struct sockaddr_in6 *)(void *)nam;
971		dst = &tmp;
972	}
973#if ENABLE_DEFAULT_SCOPE
974	if (dst->sin6_scope_id == 0) {	/* not change if specified  */
975		dst->sin6_scope_id = scope6_addr2default(&dst->sin6_addr);
976	}
977#endif
978	return (rip6_output(m, so, dst, control, 1));
979
980bad:
981	VERIFY(error != 0);
982
983	if (m != NULL)
984		m_freem(m);
985	if (control != NULL)
986		m_freem(control);
987
988	return (error);
989}
990
991struct pr_usrreqs rip6_usrreqs = {
992	.pru_abort =		rip6_abort,
993	.pru_attach =		rip6_attach,
994	.pru_bind =		rip6_bind,
995	.pru_connect =		rip6_connect,
996	.pru_control =		in6_control,
997	.pru_detach =		rip6_detach,
998	.pru_disconnect =	rip6_disconnect,
999	.pru_peeraddr =		in6_getpeeraddr,
1000	.pru_send =		rip6_send,
1001	.pru_shutdown =		rip6_shutdown,
1002	.pru_sockaddr =		in6_getsockaddr,
1003	.pru_sosend =		sosend,
1004	.pru_soreceive =	soreceive,
1005};
1006
1007__private_extern__ struct pr_usrreqs icmp6_dgram_usrreqs = {
1008	.pru_abort =		rip6_abort,
1009	.pru_attach =		icmp6_dgram_attach,
1010	.pru_bind =		rip6_bind,
1011	.pru_connect =		rip6_connect,
1012	.pru_control =		in6_control,
1013	.pru_detach =		rip6_detach,
1014	.pru_disconnect =	rip6_disconnect,
1015	.pru_peeraddr =		in6_getpeeraddr,
1016	.pru_send =		icmp6_dgram_send,
1017	.pru_shutdown =		rip6_shutdown,
1018	.pru_sockaddr =		in6_getsockaddr,
1019	.pru_sosend =		sosend,
1020	.pru_soreceive =	soreceive,
1021};
1022