2  * Copyright (c) 2000-2014 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> 
  96 #include <sys/mcache.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> 
 105 #include <net/route.h> 
 106 #include <net/if_types.h> 
 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> 
 123 #include <netinet6/ipsec.h> 
 124 #include <netinet6/ipsec6.h> 
 128 #include <net/necp.h> 
 132  * Raw interface to IP6 protocol. 
 135 extern struct   inpcbhead ripcb
; 
 136 extern struct   inpcbinfo ripcbinfo
; 
 137 extern u_int32_t        rip_sendspace
; 
 138 extern u_int32_t        rip_recvspace
; 
 140 struct rip6stat rip6stat
; 
 143  * Setup generic address and protocol structures 
 144  * for raw_input routine, then pass them along with 
 153         struct mbuf 
*m 
= *mp
; 
 154         struct ip6_hdr 
*ip6 
= mtod(m
, struct ip6_hdr 
*); 
 156         struct inpcb 
*last 
= 0; 
 157         struct mbuf 
*opts 
= NULL
; 
 158         struct sockaddr_in6 rip6src
; 
 160         struct ifnet 
*ifp 
= m
->m_pkthdr
.rcvif
; 
 162         /* Expect 32-bit aligned data pointer on strict-align platforms */ 
 163         MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m
); 
 165         rip6stat
.rip6s_ipackets
++; 
 167         init_sin6(&rip6src
, m
); /* general init */ 
 169         lck_rw_lock_shared(ripcbinfo
.ipi_lock
); 
 170         LIST_FOREACH(in6p
, &ripcb
, inp_list
) { 
 171                 if ((in6p
->in6p_vflag 
& INP_IPV6
) == 0) 
 173                 if (in6p
->in6p_ip6_nxt 
&& 
 174                     in6p
->in6p_ip6_nxt 
!= proto
) 
 176                 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_laddr
) && 
 177                     !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_laddr
, &ip6
->ip6_dst
)) 
 179                 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p
->in6p_faddr
) && 
 180                     !IN6_ARE_ADDR_EQUAL(&in6p
->in6p_faddr
, &ip6
->ip6_src
)) 
 183                 if (inp_restricted_recv(in6p
, ifp
)) 
 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
++; 
 195                         struct mbuf 
*n 
= m_copy(m
, 0, (int)M_COPYALL
); 
 198                         if (n 
&& !necp_socket_is_allowed_to_send_recv_v6(in6p
, 0, 0, &ip6
->ip6_dst
, &ip6
->ip6_src
, ifp
, NULL
)) { 
 200                                 /* do not inject data into pcb */ 
 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
); 
 215                                 /* strip intermediate headers */ 
 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
++; 
 223                                         sorwakeup(last
->in6p_socket
); 
 231         if (last 
&& !necp_socket_is_allowed_to_send_recv_v6(in6p
, 0, 0, &ip6
->ip6_dst
, &ip6
->ip6_src
, ifp
, NULL
)) { 
 233                 ip6stat
.ip6s_delivered
--; 
 234                 /* do not inject data into pcb */ 
 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
); 
 245                                 ip6stat
.ip6s_delivered
--; 
 250                 /* strip intermediate headers */ 
 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
++; 
 257                         sorwakeup(last
->in6p_socket
); 
 259                 rip6stat
.rip6s_nosock
++; 
 260                 if (m
->m_flags 
& M_MCAST
) 
 261                         rip6stat
.rip6s_nosockmcast
++; 
 262                 if (proto 
== IPPROTO_NONE
) 
 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 *)); 
 270                 ip6stat
.ip6s_delivered
--; 
 274         lck_rw_done(ripcbinfo
.ipi_lock
); 
 289         struct ip6ctlparam 
*ip6cp 
= NULL
; 
 290         const struct sockaddr_in6 
*sa6_src 
= NULL
; 
 291         void (*notify
)(struct inpcb 
*, int) = in6_rtchange
; 
 293         if (sa
->sa_family 
!= AF_INET6 
|| 
 294             sa
->sa_len 
!= sizeof(struct sockaddr_in6
)) 
 297         if ((unsigned)cmd 
>= PRC_NCMDS
) 
 299         if (PRC_IS_REDIRECT(cmd
)) 
 300                 notify 
= in6_rtchange
, d 
= NULL
; 
 301         else if (cmd 
== PRC_HOSTDEAD
) 
 303         else if (inet6ctlerrmap
[cmd
] == 0) 
 306         /* if the parameter is from icmp6, decode it. */ 
 308                 ip6cp 
= (struct ip6ctlparam 
*)d
; 
 310                 ip6 
= ip6cp
->ip6c_ip6
; 
 311                 off 
= ip6cp
->ip6c_off
; 
 312                 cmdarg 
= ip6cp
->ip6c_cmdarg
; 
 313                 sa6_src 
= ip6cp
->ip6c_src
; 
 320         (void) in6_pcbnotify(&ripcbinfo
, sa
, 0, (const struct sockaddr 
*)sa6_src
, 
 321                              0, cmd
, cmdarg
, notify
); 
 325  * Generate IPv6 header and pass packet to ip6_output. 
 326  * Tack on options user may have setup with control call. 
 332         struct sockaddr_in6 
*dstsock
, 
 333         struct mbuf 
*control
, 
 336         struct in6_addr 
*dst
; 
 339         u_int   plen 
= m
->m_pkthdr
.len
; 
 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
; 
 350         in6p 
= sotoin6pcb(so
); 
 354                 || (necp_socket_should_use_flow_divert(in6p
)) 
 363         if (dstsock 
!= NULL 
&& IN6_IS_ADDR_V4MAPPED(&dstsock
->sin6_addr
)) { 
 368         if (in6p
->inp_flags 
& INP_BOUND_IF
) { 
 369                 ip6oa
.ip6oa_boundif 
= in6p
->inp_boundifp
->if_index
; 
 370                 ip6oa
.ip6oa_flags 
|= IP6OAF_BOUND_IF
; 
 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
; 
 379         dst 
= &dstsock
->sin6_addr
; 
 381                 msc 
= mbuf_service_class_from_control(control
); 
 383                 if ((error 
= ip6_setpktopts(control
, &opt
, NULL
, 
 384                     SOCK_PROTO(so
))) != 0) 
 388                 optp 
= in6p
->in6p_outputopts
; 
 391          * For an ICMPv6 packet, we should know its type and code 
 392          * to update statistics. 
 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
) { 
 401                 icmp6 
= mtod(m
, struct icmp6_hdr 
*); 
 402                 type 
= icmp6
->icmp6_type
; 
 403                 code 
= icmp6
->icmp6_code
; 
 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
; 
 412                     (htonl(in6p
->inp_flowhash
) & IPV6_FLOWLABEL_MASK
); 
 415         M_PREPEND(m
, sizeof(*ip6
), M_WAIT
); 
 420         ip6 
= mtod(m
, struct ip6_hdr 
*); 
 423          * Next header might not be ICMP6 but use its pseudo header anyway. 
 427         im6o 
= in6p
->in6p_moptions
; 
 430          * If the scope of the destination is link-local, embed the interface 
 431          * index in the address. 
 433          * XXX advanced-api value overrides sin6_scope_id 
 435         if (IN6_IS_SCOPE_LINKLOCAL(&ip6
->ip6_dst
)) { 
 436                 struct in6_pktinfo 
*pi
; 
 437                 struct ifnet 
*im6o_multicast_ifp 
= NULL
; 
 439                 if (IN6_IS_ADDR_MULTICAST(&ip6
->ip6_dst
) && im6o 
!= NULL
) { 
 441                         im6o_multicast_ifp 
= im6o
->im6o_multicast_ifp
; 
 445                  * XXX Boundary check is assumed to be already done in 
 446                  * ip6_setpktoptions(). 
 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
]; 
 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
) { 
 463                          * Sinced stsock->sin6_scope_id is unsigned, we don't 
 464                          * need to check if it's < 0 
 466                         if (if_index 
< dstsock
->sin6_scope_id
) { 
 467                                 error 
= ENXIO
;  /* XXX EINVAL? */ 
 471                         ip6
->ip6_dst
.s6_addr16
[1] 
 472                                 = htons(dstsock
->sin6_scope_id 
& 0xffff);/*XXX*/ 
 478          * Source address selection. 
 481                 struct in6_addr 
*in6a
; 
 482                 struct in6_addr storage
; 
 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
, 
 492                                 error 
= EADDRNOTAVAIL
; 
 495                         ip6oa
.ip6oa_flags 
|= IP6OAF_BOUND_SRCADDR
; 
 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
); 
 505                         ifnet_head_lock_shared(); 
 506                         if (index 
== 0 || if_index 
< index
) { 
 507                                 panic("bad if_index on interface from route"); 
 509                         oifp 
= ifindex2ifnet
[index
]; 
 511                                 ifnet_reference(oifp
); 
 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
); 
 523         if (SOCK_PROTO(so
) == IPPROTO_ICMPV6 
|| in6p
->in6p_cksum 
!= -1) { 
 528                 /* compute checksum */ 
 529                 if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
) 
 530                         off 
= offsetof(struct icmp6_hdr
, icmp6_cksum
); 
 532                         off 
= in6p
->in6p_cksum
; 
 533                 if (plen 
< (unsigned int)(off 
+ 1)) { 
 537                 off 
+= sizeof(struct ip6_hdr
); 
 540                 while (n 
&& n
->m_len 
<= off
) { 
 546                 p 
= (u_int16_t 
*)(void *)(mtod(n
, caddr_t
) + off
); 
 548                 *p 
= in6_cksum(m
, ip6
->ip6_nxt
, sizeof(*ip6
), plen
); 
 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
; 
 559                 necp_mark_packet_from_socket(m
, in6p
, policy_id
); 
 564         if (in6p
->in6p_sp 
!= NULL 
&& ipsec_setsocket(m
, so
) != 0) { 
 570         if (ROUTE_UNUSABLE(&in6p
->in6p_route
)) 
 571                 ROUTE_RELEASE(&in6p
->in6p_route
); 
 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 
| 
 583         m
->m_pkthdr
.pkt_proto 
= in6p
->in6p_ip6_nxt
; 
 588         error 
= ip6_output(m
, optp
, &in6p
->in6p_route
, flags
, im6o
, 
 594         if (in6p
->in6p_route
.ro_rt 
!= NULL
) { 
 595                 struct rtentry 
*rt 
= in6p
->in6p_route
.ro_rt
; 
 598                 if ((rt
->rt_flags 
& RTF_MULTICAST
) || 
 599                     in6p
->in6p_socket 
== NULL 
|| 
 600                     !(in6p
->in6p_socket
->so_state 
& SS_ISCONNECTED
)) { 
 601                         rt 
= NULL
;      /* unusable */ 
 604                  * Always discard the cached route for unconnected 
 605                  * socket or if it is a multicast route. 
 608                         ROUTE_RELEASE(&in6p
->in6p_route
); 
 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. 
 616                     (outif 
= rt
->rt_ifp
) != in6p
->in6p_last_outifp
) 
 617                         in6p
->in6p_last_outifp 
= outif
; 
 619                 ROUTE_RELEASE(&in6p
->in6p_route
); 
 623          * If output interface was cellular/expensive, and this socket is 
 624          * denied access to it, generate an event. 
 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
)); 
 631         if (SOCK_PROTO(so
) == IPPROTO_ICMPV6
) { 
 633                         icmp6_ifoutstat_inc(oifp
, type
, code
); 
 634                 icmp6stat
.icp6s_outhist
[type
]++; 
 636                 rip6stat
.rip6s_opackets
++; 
 645         if (optp 
== &opt 
&& optp
->ip6po_rthdr
) 
 646                 ROUTE_RELEASE(&optp
->ip6po_route
); 
 648         if (control 
!= NULL
) { 
 650                         ip6_clearpktopts(optp
, -1); 
 659 __private_extern__ 
void 
 667  * Raw IPv6 socket option processing. 
 672         struct sockopt 
*sopt
) 
 676         /* Allow <SOL_SOCKET,SO_FLUSH> at this level */ 
 677         if (sopt
->sopt_level 
== IPPROTO_ICMPV6
) 
 679                  * XXX: is it better to call icmp6_ctloutput() directly 
 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
)) 
 689         switch (sopt
->sopt_dir
) { 
 691                 switch (sopt
->sopt_name
) { 
 695                         if (ip6_fw_ctl_ptr 
== 0) 
 698                                 error 
= ip6_fw_ctl_ptr(sopt
); 
 704                         error 
= ip6_raw_ctloutput(so
, sopt
); 
 707                         error 
= ip6_ctloutput(so
, sopt
); 
 713                 switch (sopt
->sopt_name
) { 
 719                         if (ip6_fw_ctl_ptr 
== 0) 
 722                                 error 
= ip6_fw_ctl_ptr(sopt
); 
 729                         error 
= ip6_raw_ctloutput(so
, sopt
); 
 733                         if ((error 
= sooptcopyin(sopt
, &optval
, sizeof (optval
), 
 734                             sizeof (optval
))) != 0) 
 737                         error 
= inp_flush(sotoinpcb(so
), optval
); 
 741                         error 
= ip6_ctloutput(so
, sopt
); 
 751 rip6_attach(struct socket 
*so
, int proto
, struct proc 
*p
) 
 758                 panic("rip6_attach"); 
 759         if ((error 
= proc_suser(p
)) != 0) 
 762         error 
= soreserve(so
, rip_sendspace
, rip_recvspace
); 
 765         error 
= in_pcballoc(so
, &ripcbinfo
, p
); 
 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
) 
 777         ICMP6_FILTER_SETPASSALL(inp
->in6p_icmp6filt
); 
 782 rip6_detach(struct socket 
*so
) 
 788                 panic("rip6_detach"); 
 790         if (inp
->in6p_icmp6filt
) { 
 791                 FREE(inp
->in6p_icmp6filt
, M_PCB
); 
 792                 inp
->in6p_icmp6filt 
= NULL
; 
 799 rip6_abort(struct socket 
*so
) 
 801         soisdisconnected(so
); 
 802         return rip6_detach(so
); 
 806 rip6_disconnect(struct socket 
*so
) 
 808         struct inpcb 
*inp 
= sotoinpcb(so
); 
 810         if ((so
->so_state 
& SS_ISCONNECTED
) == 0) 
 812         inp
->in6p_faddr 
= in6addr_any
; 
 813         return rip6_abort(so
); 
 817 rip6_bind(struct socket 
*so
, struct sockaddr 
*nam
, struct proc 
*p
) 
 820         struct inpcb 
*inp 
= sotoinpcb(so
); 
 821         struct sockaddr_in6 sin6
; 
 822         struct ifaddr 
*ifa 
= NULL
; 
 823         struct ifnet 
*outif 
= NULL
; 
 828                 || (necp_socket_should_use_flow_divert(inp
)) 
 831                 return (inp 
== NULL 
? EINVAL 
: EPROTOTYPE
); 
 833         if (nam
->sa_len 
!= sizeof (struct sockaddr_in6
)) 
 836         if (TAILQ_EMPTY(&ifnet_head
) || SIN6(nam
)->sin6_family 
!= AF_INET6
) 
 837                 return (EADDRNOTAVAIL
); 
 839         bzero(&sin6
, sizeof (sin6
)); 
 840         *(&sin6
) = *SIN6(nam
); 
 842         if ((error 
= sa6_embedscope(&sin6
, ip6_use_defzone
)) != 0) 
 845         /* Sanitize local copy for address searches */ 
 846         sin6
.sin6_flowinfo 
= 0; 
 847         sin6
.sin6_scope_id 
= 0; 
 850         if (!IN6_IS_ADDR_UNSPECIFIED(&sin6
.sin6_addr
) && 
 851             (ifa 
= ifa_ifwithaddr(SA(&sin6
))) == 0) 
 852                 return (EADDRNOTAVAIL
); 
 855                 if (((struct in6_ifaddr 
*)ifa
)->ia6_flags 
& 
 856                     (IN6_IFF_ANYCAST
|IN6_IFF_NOTREADY
| 
 857                      IN6_IFF_DETACHED
|IN6_IFF_DEPRECATED
)) { 
 860                         return (EADDRNOTAVAIL
); 
 862                 outif 
= ifa
->ifa_ifp
; 
 866         inp
->in6p_laddr 
= sin6
.sin6_addr
; 
 867         inp
->in6p_last_outifp 
= outif
; 
 872 rip6_connect(struct socket 
*so
, struct sockaddr 
*nam
, __unused 
struct proc 
*p
) 
 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
; 
 879 #if ENABLE_DEFAULT_SCOPE 
 880         struct sockaddr_in6 tmp
; 
 882         unsigned int ifscope
; 
 883         struct ifnet 
*outif 
= NULL
; 
 887                 || (necp_socket_should_use_flow_divert(inp
)) 
 890                 return (inp 
== NULL 
? EINVAL 
: EPROTOTYPE
); 
 891         if (nam
->sa_len 
!= sizeof(*addr
)) 
 893         if (TAILQ_EMPTY(&ifnet_head
)) 
 894                 return EADDRNOTAVAIL
; 
 895         if (addr
->sin6_family 
!= AF_INET6
) 
 897 #if ENABLE_DEFAULT_SCOPE 
 898         if (addr
->sin6_scope_id 
== 0) { /* not change if specified  */ 
 899                 /* avoid overwrites */ 
 902                 addr
->sin6_scope_id 
= scope6_addr2default(&addr
->sin6_addr
); 
 906         ifscope 
= (inp
->inp_flags 
& INP_BOUND_IF
) ? 
 907             inp
->inp_boundifp
->if_index 
: IFSCOPE_NONE
; 
 909         /* Source address selection. XXX: need pcblookup? */ 
 910         in6a 
= in6_selectsrc(addr
, inp
->in6p_outputopts
, inp
, &inp
->in6p_route
, 
 911             NULL
, &storage
, ifscope
, &error
); 
 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
; 
 924 rip6_shutdown(struct socket 
*so
) 
 931 rip6_send(struct socket 
*so
, int flags
, struct mbuf 
*m
, struct sockaddr 
*nam
, 
 932     struct mbuf 
*control
, struct proc 
*p
) 
 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
; 
 942                 || (necp_socket_should_use_flow_divert(inp
)) 
 952         /* always copy sockaddr to avoid overwrites */ 
 953         if (so
->so_state 
& SS_ISCONNECTED
) { 
 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
)); 
 970                 tmp 
= *(struct sockaddr_in6 
*)(void *)nam
; 
 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
); 
 978         return (rip6_output(m
, so
, dst
, control
, 1)); 
 991 struct 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
, 
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
,