2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
30 * All rights reserved.
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
56 * $FreeBSD: src/sys/netinet6/raw_ip6.c,v 1.7.2.4 2001/07/29 19:32:40 ume Exp $
60 * Copyright (c) 1982, 1986, 1988, 1993
61 * The Regents of the University of California. All rights reserved.
63 * Redistribution and use in source and binary forms, with or without
64 * modification, are permitted provided that the following conditions
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.
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
91 * @(#)raw_ip.c 8.2 (Berkeley) 1/4/94
93 #include <sys/param.h>
94 #include <sys/malloc.h>
97 #include <sys/socket.h>
98 #include <sys/protosw.h>
99 #include <sys/socketvar.h>
100 #include <sys/errno.h>
101 #include <sys/systm.h>
104 #include <net/route.h>
105 #include <net/if_types.h>
107 #include <netinet/in.h>
108 #include <netinet/in_var.h>
109 #include <netinet/in_systm.h>
110 #include <netinet/ip6.h>
111 #include <netinet6/ip6_var.h>
112 #include <netinet6/ip6_mroute.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 #if ENABLE_DEFAULT_SCOPE
119 #include <netinet6/scope6_var.h>
121 #include <netinet6/raw_ip6.h>
122 #include <netinet6/ip6_fw.h>
125 #include <netinet6/ipsec.h>
126 #include <netinet6/ipsec6.h>
127 extern int ipsec_bypass
;
130 #define satosin6(sa) ((struct sockaddr_in6 *)(sa))
131 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
134 * Raw interface to IP6 protocol.
137 extern struct inpcbhead ripcb
;
138 extern struct inpcbinfo ripcbinfo
;
139 extern u_int32_t rip_sendspace
;
140 extern u_int32_t rip_recvspace
;
142 struct rip6stat rip6stat
;
145 * Setup generic address and protocol structures
146 * for raw_input routine, then pass them along with
154 struct mbuf
*m
= *mp
;
155 register struct ip6_hdr
*ip6
= mtod(m
, struct ip6_hdr
*);
156 register struct inpcb
*in6p
;
157 struct inpcb
*last
= 0;
158 struct mbuf
*opts
= NULL
;
159 struct sockaddr_in6 rip6src
;
160 int proto
= ip6
->ip6_nxt
;
162 rip6stat
.rip6s_ipackets
++;
164 #if defined(NFAITH) && 0 < NFAITH
165 if (faithprefix(&ip6
->ip6_dst
)) {
166 /* XXX send icmp6 host/port unreach? */
172 init_sin6(&rip6src
, m
); /* general init */
174 lck_rw_lock_shared(ripcbinfo
.mtx
);
175 LIST_FOREACH(in6p
, &ripcb
, inp_list
) {
176 if ((in6p
->in6p_vflag
& INP_IPV6
) == 0)
178 if (in6p
->in6p_ip6_nxt
&&
179 in6p
->in6p_ip6_nxt
!= proto
)
181 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) &&
182 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
))
184 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) &&
185 !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
))
187 if (in6p
->in6p_cksum
!= -1) {
188 rip6stat
.rip6s_isum
++;
189 if (in6_cksum(m
, ip6
->ip6_nxt
, *offp
,
190 m
->m_pkthdr
.len
- *offp
)) {
191 rip6stat
.rip6s_badsum
++;
196 struct mbuf
*n
= m_copy(m
, 0, (int)M_COPYALL
);
200 * Check AH/ESP integrity.
202 if (ipsec_bypass
== 0 && n
&& ipsec6_in_reject_so(n
, last
->inp_socket
)) {
204 IPSEC_STAT_INCREMENT(ipsec6stat
.in_polvio
);
205 /* do not inject data into pcb */
209 if (last
->in6p_flags
& IN6P_CONTROLOPTS
||
210 last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
211 ip6_savecontrol(last
, &opts
, ip6
, n
);
212 /* strip intermediate headers */
214 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
215 (struct sockaddr
*)&rip6src
,
216 n
, opts
, NULL
) == 0) {
217 rip6stat
.rip6s_fullsock
++;
219 sorwakeup(last
->in6p_socket
);
225 lck_rw_done(ripcbinfo
.mtx
);
228 * Check AH/ESP integrity.
230 if (ipsec_bypass
== 0 && last
&& ipsec6_in_reject_so(m
, last
->inp_socket
)) {
232 IPSEC_STAT_INCREMENT(ipsec6stat
.in_polvio
);
233 ip6stat
.ip6s_delivered
--;
234 /* do not inject data into pcb */
238 if (last
->in6p_flags
& IN6P_CONTROLOPTS
||
239 last
->in6p_socket
->so_options
& SO_TIMESTAMP
)
240 ip6_savecontrol(last
, &opts
, ip6
, m
);
241 /* strip intermediate headers */
243 if (sbappendaddr(&last
->in6p_socket
->so_rcv
,
244 (struct sockaddr
*)&rip6src
, m
, opts
, NULL
) == 0) {
245 rip6stat
.rip6s_fullsock
++;
247 sorwakeup(last
->in6p_socket
);
249 rip6stat
.rip6s_nosock
++;
250 if (m
->m_flags
& M_MCAST
)
251 rip6stat
.rip6s_nosockmcast
++;
252 if (proto
== IPPROTO_NONE
)
255 char *prvnxtp
= ip6_get_prevhdr(m
, *offp
); /* XXX */
256 icmp6_error(m
, ICMP6_PARAM_PROB
,
257 ICMP6_PARAMPROB_NEXTHEADER
,
258 prvnxtp
- mtod(m
, char *));
260 ip6stat
.ip6s_delivered
--;
274 struct ip6ctlparam
*ip6cp
= NULL
;
275 const struct sockaddr_in6
*sa6_src
= NULL
;
276 void (*notify
)(struct inpcb
*, int) = in6_rtchange
;
278 if (sa
->sa_family
!= AF_INET6
||
279 sa
->sa_len
!= sizeof(struct sockaddr_in6
))
282 if ((unsigned)cmd
>= PRC_NCMDS
)
284 if (PRC_IS_REDIRECT(cmd
))
285 notify
= in6_rtchange
, d
= NULL
;
286 else if (cmd
== PRC_HOSTDEAD
)
288 else if (inet6ctlerrmap
[cmd
] == 0)
291 /* if the parameter is from icmp6, decode it. */
293 ip6cp
= (struct ip6ctlparam
*)d
;
295 ip6
= ip6cp
->ip6c_ip6
;
296 off
= ip6cp
->ip6c_off
;
297 sa6_src
= ip6cp
->ip6c_src
;
304 (void) in6_pcbnotify(&ripcbinfo
, sa
, 0, (const struct sockaddr
*)sa6_src
,
309 * Generate IPv6 header and pass packet to ip6_output.
310 * Tack on options user may have setup with control call.
314 register struct mbuf
*m
,
316 struct sockaddr_in6
*dstsock
,
317 struct mbuf
*control
)
319 struct in6_addr
*dst
;
322 u_int plen
= m
->m_pkthdr
.len
;
324 struct ip6_pktopts opt
, *optp
= 0;
325 struct ifnet
*oifp
= NULL
;
326 int type
= 0, code
= 0; /* for ICMPv6 output statistics only */
329 mbuf_traffic_class_t mtc
= MBUF_TC_NONE
;
330 #endif /* PKT_PRIORITY */
332 in6p
= sotoin6pcb(so
);
337 dst
= &dstsock
->sin6_addr
;
340 mtc
= mbuf_traffic_class_from_control(control
);
341 #endif /* PKT_PRIORITY */
343 if ((error
= ip6_setpktoptions(control
, &opt
, priv
, 0)) != 0)
347 optp
= in6p
->in6p_outputopts
;
350 * For an ICMPv6 packet, we should know its type and code
351 * to update statistics.
353 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
354 struct icmp6_hdr
*icmp6
;
355 if (m
->m_len
< sizeof(struct icmp6_hdr
) &&
356 (m
= m_pullup(m
, sizeof(struct icmp6_hdr
))) == NULL
) {
360 icmp6
= mtod(m
, struct icmp6_hdr
*);
361 type
= icmp6
->icmp6_type
;
362 code
= icmp6
->icmp6_code
;
365 M_PREPEND(m
, sizeof(*ip6
), M_WAIT
);
370 ip6
= mtod(m
, struct ip6_hdr
*);
373 * Next header might not be ICMP6 but use its pseudo header anyway.
378 * If the scope of the destination is link-local, embed the interface
379 * index in the address.
381 * XXX advanced-api value overrides sin6_scope_id
383 if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) {
384 struct in6_pktinfo
*pi
;
387 * XXX Boundary check is assumed to be already done in
388 * ip6_setpktoptions().
390 ifnet_head_lock_shared();
391 if (optp
&& (pi
= optp
->ip6po_pktinfo
) && pi
->ipi6_ifindex
) {
392 ip6
->ip6_dst
.s6_addr16
[1] = htons(pi
->ipi6_ifindex
);
393 oifp
= ifindex2ifnet
[pi
->ipi6_ifindex
];
394 } else if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) &&
395 in6p
->in6p_moptions
&&
396 in6p
->in6p_moptions
->im6o_multicast_ifp
) {
397 oifp
= in6p
->in6p_moptions
->im6o_multicast_ifp
;
398 ip6
->ip6_dst
.s6_addr16
[1] = htons(oifp
->if_index
);
399 } else if (dstsock
->sin6_scope_id
) {
403 * Sinced stsock->sin6_scope_id is unsigned, we don't
404 * need to check if it's < 0
406 if (if_index
< dstsock
->sin6_scope_id
) {
407 error
= ENXIO
; /* XXX EINVAL? */
411 ip6
->ip6_dst
.s6_addr16
[1]
412 = htons(dstsock
->sin6_scope_id
& 0xffff);/*XXX*/
418 * Source address selection.
421 struct in6_addr
*in6a
;
422 struct in6_addr storage
;
424 if ((in6a
= in6_selectsrc(dstsock
, optp
,
428 &storage
, &error
)) == 0) {
430 error
= EADDRNOTAVAIL
;
433 ip6
->ip6_src
= *in6a
;
434 if (in6p
->in6p_route
.ro_rt
!= NULL
) {
435 RT_LOCK(in6p
->in6p_route
.ro_rt
);
436 if (in6p
->in6p_route
.ro_rt
->rt_ifp
!= NULL
)
437 index
= in6p
->in6p_route
.ro_rt
->rt_ifp
->if_index
;
438 RT_UNLOCK(in6p
->in6p_route
.ro_rt
);
439 ifnet_head_lock_shared();
440 if (index
== 0 || if_index
< index
) {
441 panic("bad if_index on interface from route");
443 oifp
= ifindex2ifnet
[index
];
447 ip6
->ip6_flow
= (ip6
->ip6_flow
& ~IPV6_FLOWINFO_MASK
) |
448 (in6p
->in6p_flowinfo
& IPV6_FLOWINFO_MASK
);
449 ip6
->ip6_vfc
= (ip6
->ip6_vfc
& ~IPV6_VERSION_MASK
) |
450 (IPV6_VERSION
& IPV6_VERSION_MASK
);
451 /* ip6_plen will be filled in ip6_output, so not fill it here. */
452 ip6
->ip6_nxt
= in6p
->in6p_ip6_nxt
;
453 ip6
->ip6_hlim
= in6_selecthlim(in6p
, oifp
);
455 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
||
456 in6p
->in6p_cksum
!= -1) {
461 /* compute checksum */
462 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
)
463 off
= offsetof(struct icmp6_hdr
, icmp6_cksum
);
465 off
= in6p
->in6p_cksum
;
466 if (plen
< off
+ 1) {
470 off
+= sizeof(struct ip6_hdr
);
473 while (n
&& n
->m_len
<= off
) {
479 p
= (u_int16_t
*)(mtod(n
, caddr_t
) + off
);
481 *p
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
);
485 if (ipsec_bypass
== 0 && ipsec_setsocket(m
, so
) != 0) {
491 if (in6p
->in6p_route
.ro_rt
!= NULL
&&
492 in6p
->in6p_route
.ro_rt
->generation_id
!= route_generation
) {
493 rtfree(in6p
->in6p_route
.ro_rt
);
494 in6p
->in6p_route
.ro_rt
= NULL
;
498 set_traffic_class(m
, so
, mtc
);
499 #endif /* PKT_PRIORITY */
501 error
= ip6_output(m
, optp
, &in6p
->in6p_route
, 0,
502 in6p
->in6p_moptions
, &oifp
, 0);
504 #if IFNET_ROUTE_REFCNT
506 * Always discard the cached route for unconnected socket
507 * or if it is a multicast route.
509 if (in6p
->in6p_route
.ro_rt
!= NULL
&&
510 ((in6p
->in6p_route
.ro_rt
->rt_flags
& RTF_MULTICAST
) ||
511 in6p
->in6p_socket
== NULL
||
512 in6p
->in6p_socket
->so_state
!= SS_ISCONNECTED
)) {
513 rtfree(in6p
->in6p_route
.ro_rt
);
514 in6p
->in6p_route
.ro_rt
= NULL
;
516 #endif /* IFNET_ROUTE_REFCNT */
518 if (so
->so_proto
->pr_protocol
== IPPROTO_ICMPV6
) {
520 icmp6_ifoutstat_inc(oifp
, type
, code
);
521 icmp6stat
.icp6s_outhist
[type
]++;
523 rip6stat
.rip6s_opackets
++;
532 if (optp
== &opt
&& optp
->ip6po_rthdr
&& optp
->ip6po_route
.ro_rt
) {
533 rtfree(optp
->ip6po_route
.ro_rt
);
534 optp
->ip6po_route
.ro_rt
= NULL
;
538 ip6_clearpktopts(optp
, 0, -1);
545 __private_extern__
void
553 * Raw IPv6 socket option processing.
558 struct sockopt
*sopt
)
562 if (sopt
->sopt_level
== IPPROTO_ICMPV6
)
564 * XXX: is it better to call icmp6_ctloutput() directly
567 return(icmp6_ctloutput(so
, sopt
));
568 else if (sopt
->sopt_level
!= IPPROTO_IPV6
)
573 switch (sopt
->sopt_dir
) {
575 switch (sopt
->sopt_name
) {
579 if (ip6_fw_ctl_ptr
== 0)
582 error
= ip6_fw_ctl_ptr(sopt
);
596 error
= ip6_mrouter_get(so
, sopt
);
600 error
= ip6_ctloutput(so
, sopt
);
606 switch (sopt
->sopt_name
) {
612 if (ip6_fw_ctl_ptr
== 0)
615 error
= ip6_fw_ctl_ptr(sopt
);
629 error
= ip6_mrouter_set(so
, sopt
);
633 error
= ip6_ctloutput(so
, sopt
);
643 rip6_attach(struct socket
*so
, int proto
, struct proc
*p
)
650 panic("rip6_attach");
651 if ((error
= proc_suser(p
)) != 0)
654 error
= soreserve(so
, rip_sendspace
, rip_recvspace
);
657 error
= in_pcballoc(so
, &ripcbinfo
, p
);
660 inp
= (struct inpcb
*)so
->so_pcb
;
661 inp
->inp_vflag
|= INP_IPV6
;
662 inp
->in6p_ip6_nxt
= (char)proto
;
663 inp
->in6p_hops
= -1; /* use kernel default */
664 inp
->in6p_cksum
= -1;
665 MALLOC(inp
->in6p_icmp6filt
, struct icmp6_filter
*,
666 sizeof(struct icmp6_filter
), M_PCB
, M_WAITOK
);
667 if (inp
->in6p_icmp6filt
== NULL
)
669 ICMP6_FILTER_SETPASSALL(inp
->in6p_icmp6filt
);
674 rip6_detach(struct socket
*so
)
680 panic("rip6_detach");
683 if (so
== ip6_mrouter
)
686 if (inp
->in6p_icmp6filt
) {
687 FREE(inp
->in6p_icmp6filt
, M_PCB
);
688 inp
->in6p_icmp6filt
= NULL
;
695 rip6_abort(struct socket
*so
)
697 soisdisconnected(so
);
698 return rip6_detach(so
);
702 rip6_disconnect(struct socket
*so
)
704 struct inpcb
*inp
= sotoinpcb(so
);
706 if ((so
->so_state
& SS_ISCONNECTED
) == 0)
708 inp
->in6p_faddr
= in6addr_any
;
709 return rip6_abort(so
);
713 rip6_bind(struct socket
*so
, struct sockaddr
*nam
, __unused
struct proc
*p
)
715 struct inpcb
*inp
= sotoinpcb(so
);
716 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
717 struct ifaddr
*ia
= NULL
;
719 if (nam
->sa_len
!= sizeof(*addr
))
722 if (TAILQ_EMPTY(&ifnet_head
) || addr
->sin6_family
!= AF_INET6
)
723 return EADDRNOTAVAIL
;
724 #if ENABLE_DEFAULT_SCOPE
725 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
726 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
729 if (!IN6_IS_ADDR_UNSPECIFIED(&addr
->sin6_addr
) &&
730 (ia
= ifa_ifwithaddr((struct sockaddr
*)addr
)) == 0)
731 return EADDRNOTAVAIL
;
733 ((struct in6_ifaddr
*)ia
)->ia6_flags
&
734 (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
|
735 IN6_IFF_DETACHED
|IN6_IFF_DEPRECATED
)) {
737 return(EADDRNOTAVAIL
);
741 inp
->in6p_laddr
= addr
->sin6_addr
;
746 rip6_connect(struct socket
*so
, struct sockaddr
*nam
, __unused
struct proc
*p
)
748 struct inpcb
*inp
= sotoinpcb(so
);
749 struct sockaddr_in6
*addr
= (struct sockaddr_in6
*)nam
;
750 struct in6_addr
*in6a
= NULL
;
751 struct in6_addr storage
;
753 #if ENABLE_DEFAULT_SCOPE
754 struct sockaddr_in6 tmp
;
757 if (nam
->sa_len
!= sizeof(*addr
))
759 if (TAILQ_EMPTY(&ifnet_head
))
760 return EADDRNOTAVAIL
;
761 if (addr
->sin6_family
!= AF_INET6
)
763 #if ENABLE_DEFAULT_SCOPE
764 if (addr
->sin6_scope_id
== 0) { /* not change if specified */
765 /* avoid overwrites */
768 addr
->sin6_scope_id
= scope6_addr2default(&addr
->sin6_addr
);
771 /* Source address selection. XXX: need pcblookup? */
772 in6a
= in6_selectsrc(addr
, inp
->in6p_outputopts
,
773 inp
->in6p_moptions
, &inp
->in6p_route
,
774 &inp
->in6p_laddr
, &storage
, &error
);
776 return (error
? error
: EADDRNOTAVAIL
);
777 inp
->in6p_laddr
= *in6a
;
778 inp
->in6p_faddr
= addr
->sin6_addr
;
784 rip6_shutdown(struct socket
*so
)
791 rip6_send(struct socket
*so
, __unused
int flags
, struct mbuf
*m
, struct sockaddr
*nam
,
792 struct mbuf
*control
, __unused
struct proc
*p
)
794 struct inpcb
*inp
= sotoinpcb(so
);
795 struct sockaddr_in6 tmp
;
796 struct sockaddr_in6
*dst
;
798 /* always copy sockaddr to avoid overwrites */
799 if (so
->so_state
& SS_ISCONNECTED
) {
805 bzero(&tmp
, sizeof(tmp
));
806 tmp
.sin6_family
= AF_INET6
;
807 tmp
.sin6_len
= sizeof(struct sockaddr_in6
);
808 bcopy(&inp
->in6p_faddr
, &tmp
.sin6_addr
,
809 sizeof(struct in6_addr
));
816 tmp
= *(struct sockaddr_in6
*)nam
;
819 #if ENABLE_DEFAULT_SCOPE
820 if (dst
->sin6_scope_id
== 0) { /* not change if specified */
821 dst
->sin6_scope_id
= scope6_addr2default(&dst
->sin6_addr
);
824 return rip6_output(m
, so
, dst
, control
);
827 struct pr_usrreqs rip6_usrreqs
= {
828 rip6_abort
, pru_accept_notsupp
, rip6_attach
, rip6_bind
, rip6_connect
,
829 pru_connect2_notsupp
, in6_control
, rip6_detach
, rip6_disconnect
,
830 pru_listen_notsupp
, in6_setpeeraddr
, pru_rcvd_notsupp
,
831 pru_rcvoob_notsupp
, rip6_send
, pru_sense_null
, rip6_shutdown
,
832 in6_setsockaddr
, sosend
, soreceive
, pru_sopoll_notsupp
835 __private_extern__
struct pr_usrreqs icmp6_dgram_usrreqs
= {
836 rip6_abort
, pru_accept_notsupp
, icmp6_dgram_attach
, rip6_bind
, rip6_connect
,
837 pru_connect2_notsupp
, in6_control
, rip6_detach
, rip6_disconnect
,
838 pru_listen_notsupp
, in6_setpeeraddr
, pru_rcvd_notsupp
,
839 pru_rcvoob_notsupp
, icmp6_dgram_send
, pru_sense_null
, rip6_shutdown
,
840 in6_setsockaddr
, sosend
, soreceive
, pru_sopoll_notsupp