2  * Copyright (c) 2000-2007 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) 1982, 1986, 1988, 1993 
  30  *      The Regents of the University of California.  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. All advertising materials mentioning features or use of this software 
  41  *    must display the following acknowledgement: 
  42  *      This product includes software developed by the University of 
  43  *      California, Berkeley and its contributors. 
  44  * 4. Neither the name of the University nor the names of its contributors 
  45  *    may be used to endorse or promote products derived from this software 
  46  *    without specific prior written permission. 
  48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 
  49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
  50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
  51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 
  52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
  53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
  54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
  56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
  57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
  60  *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95 
  63  * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 
  64  * support for mandatory and extensible security protections.  This notice 
  65  * is included in support of clause 2.2 (b) of the Apple Public License, 
  69 #include <sys/param.h> 
  70 #include <sys/systm.h> 
  71 #include <sys/kernel.h> 
  72 #include <sys/malloc.h> 
  75 #include <sys/domain.h> 
  76 #include <sys/protosw.h> 
  77 #include <sys/socket.h> 
  78 #include <sys/socketvar.h> 
  79 #include <sys/sysctl.h> 
  80 #include <libkern/OSAtomic.h> 
  81 #include <kern/zalloc.h> 
  83 #include <pexpert/pexpert.h> 
  86 #include <net/route.h> 
  89 #include <netinet/in.h> 
  90 #include <netinet/in_systm.h> 
  91 #include <netinet/ip.h> 
  92 #include <netinet/in_pcb.h> 
  93 #include <netinet/in_var.h> 
  94 #include <netinet/ip_var.h> 
  95 #include <netinet/ip_mroute.h> 
  97 #include <netinet/ip_fw.h> 
 100 #include <netinet6/ipsec.h> 
 104 #include <netinet/ip_dummynet.h> 
 108 #include <security/mac_framework.h> 
 112 int rip_detach(struct socket 
*); 
 113 int rip_abort(struct socket 
*); 
 114 int rip_disconnect(struct socket 
*); 
 115 int rip_bind(struct socket 
*, struct sockaddr 
*, struct proc 
*); 
 116 int rip_connect(struct socket 
*, struct sockaddr 
*, struct proc 
*); 
 117 int rip_shutdown(struct socket 
*); 
 120 extern int ipsec_bypass
; 
 123 extern u_long  route_generation
; 
 124 struct  inpcbhead ripcb
; 
 125 struct  inpcbinfo ripcbinfo
; 
 127 /* control hooks for ipfw and dummynet */ 
 129 ip_fw_ctl_t 
*ip_fw_ctl_ptr
; 
 131 ip_dn_ctl_t 
*ip_dn_ctl_ptr
; 
 132 #endif /* DUMMYNET */ 
 133 #endif /* IPFIREWALL */ 
 136  * Nominal space allocated to a raw ip socket. 
 142  * Raw interface to IP protocol. 
 146  * Initialize raw connection block q. 
 151         struct inpcbinfo 
*pcbinfo
; 
 154         ripcbinfo
.listhead 
= &ripcb
; 
 156          * XXX We don't use the hash list for raw IP, but it's easier 
 157          * to allocate a one entry hash list than it is to check all 
 158          * over the place for hashbase == NULL. 
 160         ripcbinfo
.hashbase 
= hashinit(1, M_PCB
, &ripcbinfo
.hashmask
); 
 161         ripcbinfo
.porthashbase 
= hashinit(1, M_PCB
, &ripcbinfo
.porthashmask
); 
 163         ripcbinfo
.ipi_zone 
= (void *) zinit(sizeof(struct inpcb
), 
 164                                             (4096 * sizeof(struct inpcb
)),  
 167         pcbinfo 
= &ripcbinfo
; 
 169          * allocate lock group attribute and group for udp pcb mutexes 
 171         pcbinfo
->mtx_grp_attr 
= lck_grp_attr_alloc_init(); 
 173         pcbinfo
->mtx_grp 
= lck_grp_alloc_init("ripcb", pcbinfo
->mtx_grp_attr
); 
 176          * allocate the lock attribute for udp pcb mutexes 
 178         pcbinfo
->mtx_attr 
= lck_attr_alloc_init(); 
 180         if ((pcbinfo
->mtx 
= lck_rw_alloc_init(pcbinfo
->mtx_grp
, pcbinfo
->mtx_attr
)) == NULL
) 
 181                 return; /* pretty much dead if this fails... */ 
 185 static struct   sockaddr_in ripsrc 
= { sizeof(ripsrc
), AF_INET 
, 0, {0}, {0,0,0,0,0,0,0,0,} }; 
 187  * Setup generic address and protocol structures 
 188  * for raw_input routine, then pass them along with 
 196         register struct ip 
*ip 
= mtod(m
, struct ip 
*); 
 197         register struct inpcb 
*inp
; 
 198         struct inpcb 
*last 
= 0; 
 199         struct mbuf 
*opts 
= 0; 
 202         ripsrc
.sin_addr 
= ip
->ip_src
; 
 203         lck_rw_lock_shared(ripcbinfo
.mtx
); 
 204         LIST_FOREACH(inp
, &ripcb
, inp_list
) { 
 206                 if ((inp
->inp_vflag 
& INP_IPV4
) == 0) 
 209                 if (inp
->inp_ip_p 
&& (inp
->inp_ip_p 
!= ip
->ip_p
)) 
 211                 if (inp
->inp_laddr
.s_addr 
&& 
 212                   inp
->inp_laddr
.s_addr 
!= ip
->ip_dst
.s_addr
) 
 214                 if (inp
->inp_faddr
.s_addr 
&& 
 215                   inp
->inp_faddr
.s_addr 
!= ip
->ip_src
.s_addr
) 
 218                         struct mbuf 
*n 
= m_copy(m
, 0, (int)M_COPYALL
); 
 221                         /* check AH/ESP integrity. */ 
 223                         if (ipsec_bypass 
== 0 && n
) { 
 224                                 if (ipsec4_in_reject_so(n
, last
->inp_socket
)) { 
 226                                         IPSEC_STAT_INCREMENT(ipsecstat
.in_polvio
); 
 227                                         /* do not inject data to pcb */ 
 233                         if (n 
&& skipit 
== 0) { 
 234                                 if (mac_inpcb_check_deliver(last
, n
, AF_INET
, 
 239                         if (n 
&& skipit 
== 0) { 
 241                                 if (last
->inp_flags 
& INP_CONTROLOPTS 
|| 
 242                                     last
->inp_socket
->so_options 
& SO_TIMESTAMP
) 
 243                                     ip_savecontrol(last
, &opts
, ip
, n
); 
 244                                 if (last
->inp_flags 
& INP_STRIPHDR
) { 
 246                                         n
->m_pkthdr
.len 
-= iphlen
; 
 249 // ###LOCK need to lock that socket? 
 250                                 if (sbappendaddr(&last
->inp_socket
->so_rcv
, 
 251                                     (struct sockaddr 
*)&ripsrc
, n
, 
 252                                     opts
, &error
) != 0) { 
 253                                         sorwakeup(last
->inp_socket
); 
 257                                                 /* should notify about lost packet */ 
 258                                                 kprintf("rip_input can't append to socket\n"); 
 266         lck_rw_done(ripcbinfo
.mtx
); 
 268         /* check AH/ESP integrity. */ 
 270         if (ipsec_bypass 
== 0 && last
) { 
 271                 if (ipsec4_in_reject_so(m
, last
->inp_socket
)) { 
 273                         IPSEC_STAT_INCREMENT(ipsecstat
.in_polvio
); 
 274                         OSAddAtomic(1, (SInt32
*)&ipstat
.ips_delivered
); 
 275                         /* do not inject data to pcb */ 
 281         if (last 
&& skipit 
== 0) { 
 282                 if (mac_inpcb_check_deliver(last
, m
, AF_INET
, SOCK_RAW
) != 0) 
 288                         if (last
->inp_flags 
& INP_CONTROLOPTS 
|| 
 289                                 last
->inp_socket
->so_options 
& SO_TIMESTAMP
) 
 290                                 ip_savecontrol(last
, &opts
, ip
, m
); 
 291                         if (last
->inp_flags 
& INP_STRIPHDR
) { 
 293                                 m
->m_pkthdr
.len 
-= iphlen
; 
 296                         if (sbappendaddr(&last
->inp_socket
->so_rcv
, 
 297                                 (struct sockaddr 
*)&ripsrc
, m
, opts
, NULL
) != 0) { 
 298                                 sorwakeup(last
->inp_socket
); 
 300                                 kprintf("rip_input(2) can't append to socket\n"); 
 304                         OSAddAtomic(1, (SInt32
*)&ipstat
.ips_noproto
); 
 305                         OSAddAtomic(-1, (SInt32
*)&ipstat
.ips_delivered
); 
 311  * Generate IP header and pass packet to ip_output. 
 312  * Tack on options user may have setup with control call. 
 315 rip_output(m
, so
, dst
) 
 316         register struct mbuf 
*m
; 
 320         register struct ip 
*ip
; 
 321         register struct inpcb 
*inp 
= sotoinpcb(so
); 
 322         int flags 
= (so
->so_options 
& SO_DONTROUTE
) | IP_ALLOWBROADCAST
; 
 325          * If the user handed us a complete IP packet, use it. 
 326          * Otherwise, allocate an mbuf for a header and fill it in. 
 328         if ((inp
->inp_flags 
& INP_HDRINCL
) == 0) { 
 329                 if (m
->m_pkthdr
.len 
+ sizeof(struct ip
) > IP_MAXPACKET
) { 
 333                 M_PREPEND(m
, sizeof(struct ip
), M_WAIT
); 
 334                 ip 
= mtod(m
, struct ip 
*); 
 335                 ip
->ip_tos 
= inp
->inp_ip_tos
; 
 337                 ip
->ip_p 
= inp
->inp_ip_p
; 
 338                 ip
->ip_len 
= m
->m_pkthdr
.len
; 
 339                 ip
->ip_src 
= inp
->inp_laddr
; 
 340                 ip
->ip_dst
.s_addr 
= dst
; 
 341                 ip
->ip_ttl 
= inp
->inp_ip_ttl
; 
 343                 if (m
->m_pkthdr
.len 
> IP_MAXPACKET
) { 
 347                 ip 
= mtod(m
, struct ip 
*); 
 348                 /* don't allow both user specified and setsockopt options, 
 349                    and don't allow packet length sizes that will crash */ 
 350                 if (((IP_VHL_HL(ip
->ip_vhl
) != (sizeof (*ip
) >> 2)) 
 352                     || (ip
->ip_len 
> m
->m_pkthdr
.len
) 
 353                     || (ip
->ip_len 
< (IP_VHL_HL(ip
->ip_vhl
) << 2))) { 
 359                         ip
->ip_id 
= ip_randomid(); 
 361                         ip
->ip_id 
= htons(ip_id
++); 
 363                 /* XXX prevent ip_output from overwriting header fields */ 
 364                 flags 
|= IP_RAWOUTPUT
; 
 365                 OSAddAtomic(1, (SInt32
*)&ipstat
.ips_rawout
); 
 369         if (ipsec_bypass 
== 0 && ipsec_setsocket(m
, so
) != 0) { 
 375         if (inp
->inp_route
.ro_rt 
&& inp
->inp_route
.ro_rt
->generation_id 
!= route_generation
) { 
 376                 rtfree(inp
->inp_route
.ro_rt
); 
 377                 inp
->inp_route
.ro_rt 
= (struct rtentry 
*)0; 
 381         mac_mbuf_label_associate_inpcb(inp
, m
); 
 384 #if CONFIG_FORCE_OUT_IFP 
 385         return (ip_output_list(m
, 0, inp
->inp_options
, &inp
->inp_route
, flags
, 
 386                           inp
->inp_moptions
, inp
->pdp_ifp
)); 
 388         return (ip_output_list(m
, 0, inp
->inp_options
, &inp
->inp_route
, flags
, 
 389                           inp
->inp_moptions
, NULL
)); 
 402         if (!DUMMYNET_LOADED
) 
 404 #endif /* DUMMYNET */ 
 407         return err 
== 0 && ip_fw_ctl_ptr 
== NULL 
? -1 : err
; 
 409 #endif /* IPFIREWALL */ 
 412  * Raw IP socket option processing. 
 415 rip_ctloutput(so
, sopt
) 
 417         struct sockopt 
*sopt
; 
 419         struct  inpcb 
*inp 
= sotoinpcb(so
); 
 422         if (sopt
->sopt_level 
!= IPPROTO_IP
) 
 427         switch (sopt
->sopt_dir
) { 
 429                 switch (sopt
->sopt_name
) { 
 431                         optval 
= inp
->inp_flags 
& INP_HDRINCL
; 
 432                         error 
= sooptcopyout(sopt
, &optval
, sizeof optval
); 
 436             optval 
= inp
->inp_flags 
& INP_STRIPHDR
; 
 437             error 
= sooptcopyout(sopt
, &optval
, sizeof optval
); 
 445                         if (ip_fw_ctl_ptr 
== 0) 
 447                         if (ip_fw_ctl_ptr 
&& error 
== 0) 
 448                                 error 
= ip_fw_ctl_ptr(sopt
); 
 455                 case IP_DUMMYNET_GET
: 
 457                                 error 
= ip_dn_ctl_ptr(sopt
); 
 461 #endif /* DUMMYNET */ 
 472                         error 
= ip_mrouter_get(so
, sopt
); 
 474 #endif /* MROUTING */ 
 477                         error 
= ip_ctloutput(so
, sopt
); 
 483                 switch (sopt
->sopt_name
) { 
 485                         error 
= sooptcopyin(sopt
, &optval
, sizeof optval
, 
 490                                 inp
->inp_flags 
|= INP_HDRINCL
; 
 492                                 inp
->inp_flags 
&= ~INP_HDRINCL
; 
 496             error 
= sooptcopyin(sopt
, &optval
, sizeof optval
, 
 501                 inp
->inp_flags 
|= INP_STRIPHDR
; 
 503                 inp
->inp_flags 
&= ~INP_STRIPHDR
; 
 515                 case IP_OLD_FW_FLUSH
: 
 517                 case IP_OLD_FW_RESETLOG
: 
 518                         if (ip_fw_ctl_ptr 
== 0) 
 520                         if (ip_fw_ctl_ptr 
&& error 
== 0) 
 521                                 error 
= ip_fw_ctl_ptr(sopt
); 
 525 #endif /* IPFIREWALL */ 
 528                 case IP_DUMMYNET_CONFIGURE
: 
 529                 case IP_DUMMYNET_DEL
: 
 530                 case IP_DUMMYNET_FLUSH
: 
 532                                 error 
= ip_dn_ctl_ptr(sopt
); 
 534                                 error 
= ENOPROTOOPT 
; 
 540                         error 
= ip_rsvp_init(so
); 
 544                         error 
= ip_rsvp_done(); 
 547                         /* XXX - should be combined */ 
 549                         error 
= ip_rsvp_vif_init(so
, sopt
); 
 552                 case IP_RSVP_VIF_OFF
: 
 553                         error 
= ip_rsvp_vif_done(so
, sopt
); 
 564                         error 
= ip_mrouter_set(so
, sopt
); 
 566 #endif /* MROUTING */ 
 569                         error 
= ip_ctloutput(so
, sopt
); 
 579  * This function exists solely to receive the PRC_IFDOWN messages which 
 580  * are sent by if_down().  It looks for an ifaddr whose ifa_addr is sa, 
 581  * and calls in_ifadown() to remove all routes corresponding to that address. 
 582  * It also receives the PRC_IFUP messages from if_up() and reinstalls the 
 591         struct in_ifaddr 
*ia
; 
 598                 lck_mtx_lock(rt_mtx
); 
 599                 for (ia 
= in_ifaddrhead
.tqh_first
; ia
; 
 600                      ia 
= ia
->ia_link
.tqe_next
) { 
 601                         if (ia
->ia_ifa
.ifa_addr 
== sa
 
 602                             && (ia
->ia_flags 
& IFA_ROUTE
)) { 
 604                                  * in_ifscrub kills the interface route. 
 606                                 in_ifscrub(ia
->ia_ifp
, ia
, 1); 
 608                                  * in_ifadown gets rid of all the rest of 
 609                                  * the routes.  This is not quite the right 
 610                                  * thing to do, but at least if we are running 
 611                                  * a routing process they will come back. 
 613                                 in_ifadown(&ia
->ia_ifa
, 1); 
 617                 lck_mtx_unlock(rt_mtx
); 
 621                 lck_mtx_lock(rt_mtx
); 
 622                 for (ia 
= in_ifaddrhead
.tqh_first
; ia
; 
 623                      ia 
= ia
->ia_link
.tqe_next
) { 
 624                         if (ia
->ia_ifa
.ifa_addr 
== sa
) 
 627                 if (ia 
== 0 || (ia
->ia_flags 
& IFA_ROUTE
)) { 
 628                         lck_mtx_unlock(rt_mtx
); 
 632                 ifp 
= ia
->ia_ifa
.ifa_ifp
; 
 634                 if ((ifp
->if_flags 
& IFF_LOOPBACK
) 
 635                     || (ifp
->if_flags 
& IFF_POINTOPOINT
)) 
 638                 err 
= rtinit_locked(&ia
->ia_ifa
, RTM_ADD
, flags
); 
 639                 lck_mtx_unlock(rt_mtx
); 
 641                         ia
->ia_flags 
|= IFA_ROUTE
; 
 646 u_long  rip_sendspace 
= RIPSNDQ
; 
 647 u_long  rip_recvspace 
= RIPRCVQ
; 
 649 SYSCTL_INT(_net_inet_raw
, OID_AUTO
, maxdgram
, CTLFLAG_RW
, 
 650     &rip_sendspace
, 0, "Maximum outgoing raw IP datagram size"); 
 651 SYSCTL_INT(_net_inet_raw
, OID_AUTO
, recvspace
, CTLFLAG_RW
, 
 652     &rip_recvspace
, 0, "Maximum incoming raw IP datagram size"); 
 655 rip_attach(struct socket 
*so
, int proto
, struct proc 
*p
) 
 663         if ((so
->so_state 
& SS_PRIV
) == 0) 
 666         error 
= soreserve(so
, rip_sendspace
, rip_recvspace
); 
 669         error 
= in_pcballoc(so
, &ripcbinfo
, p
); 
 672         inp 
= (struct inpcb 
*)so
->so_pcb
; 
 673         inp
->inp_vflag 
|= INP_IPV4
; 
 674         inp
->inp_ip_p 
= proto
; 
 675         inp
->inp_ip_ttl 
= ip_defttl
; 
 679 __private_extern__ 
int 
 680 rip_detach(struct socket 
*so
) 
 688         if (so 
== ip_mrouter
) 
 690         ip_rsvp_force_done(so
); 
 693 #endif /* MROUTING */ 
 698 __private_extern__ 
int 
 699 rip_abort(struct socket 
*so
) 
 701         soisdisconnected(so
); 
 702         return rip_detach(so
); 
 705 __private_extern__ 
int 
 706 rip_disconnect(struct socket 
*so
) 
 708         if ((so
->so_state 
& SS_ISCONNECTED
) == 0) 
 710         return rip_abort(so
); 
 713 __private_extern__ 
int 
 714 rip_bind(struct socket 
*so
, struct sockaddr 
*nam
, __unused 
struct proc 
*p
) 
 716         struct inpcb 
*inp 
= sotoinpcb(so
); 
 717         struct sockaddr_in 
*addr 
= (struct sockaddr_in 
*)nam
; 
 718         struct ifaddr 
*ifa 
= NULL
; 
 720         if (nam
->sa_len 
!= sizeof(*addr
)) 
 723         if (TAILQ_EMPTY(&ifnet_head
) || ((addr
->sin_family 
!= AF_INET
) && 
 724                                     (addr
->sin_family 
!= AF_IMPLINK
)) || 
 725             (addr
->sin_addr
.s_addr 
&& 
 726              (ifa 
= ifa_ifwithaddr((struct sockaddr 
*)addr
)) == 0)) { 
 727                 return EADDRNOTAVAIL
; 
 733         inp
->inp_laddr 
= addr
->sin_addr
; 
 737 __private_extern__ 
int 
 738 rip_connect(struct socket 
*so
, struct sockaddr 
*nam
, __unused  
struct proc 
*p
) 
 740         struct inpcb 
*inp 
= sotoinpcb(so
); 
 741         struct sockaddr_in 
*addr 
= (struct sockaddr_in 
*)nam
; 
 743         if (nam
->sa_len 
!= sizeof(*addr
)) 
 745         if (TAILQ_EMPTY(&ifnet_head
)) 
 746                 return EADDRNOTAVAIL
; 
 747         if ((addr
->sin_family 
!= AF_INET
) && 
 748             (addr
->sin_family 
!= AF_IMPLINK
)) 
 750         inp
->inp_faddr 
= addr
->sin_addr
; 
 755 __private_extern__ 
int 
 756 rip_shutdown(struct socket 
*so
) 
 762 __private_extern__ 
int 
 763 rip_send(struct socket 
*so
, __unused 
int flags
, struct mbuf 
*m
, struct sockaddr 
*nam
, 
 764          __unused 
struct mbuf 
*control
, __unused 
struct proc 
*p
) 
 766         struct inpcb 
*inp 
= sotoinpcb(so
); 
 769         if (so
->so_state 
& SS_ISCONNECTED
) { 
 774                 dst 
= inp
->inp_faddr
.s_addr
; 
 780                 dst 
= ((struct sockaddr_in 
*)nam
)->sin_addr
.s_addr
; 
 782         return rip_output(m
, so
, dst
); 
 785 /* note: rip_unlock is called from different protos  instead of the generic socket_unlock, 
 786  * it will handle the socket dealloc on last reference  
 789 rip_unlock(struct socket 
*so
, int refcount
, int debug
) 
 792         struct inpcb 
*inp 
= sotoinpcb(so
); 
 795                 lr_saved 
= (unsigned int) __builtin_return_address(0); 
 796         else lr_saved 
= debug
; 
 799                 if (so
->so_usecount 
<= 0) 
 800                         panic("rip_unlock: bad refoucnt so=%p val=%x\n", so
, so
->so_usecount
); 
 802                 if (so
->so_usecount 
== 0 && (inp
->inp_wantcnt 
== WNT_STOPUSING
)) { 
 803                         /* cleanup after last reference */ 
 804                         lck_mtx_unlock(so
->so_proto
->pr_domain
->dom_mtx
); 
 805                         lck_rw_lock_exclusive(ripcbinfo
.mtx
); 
 807                         lck_rw_done(ripcbinfo
.mtx
); 
 811         so
->unlock_lr
[so
->next_unlock_lr
] = (u_int32_t
)lr_saved
; 
 812         so
->next_unlock_lr 
= (so
->next_unlock_lr
+1) % SO_LCKDBG_MAX
; 
 813         lck_mtx_unlock(so
->so_proto
->pr_domain
->dom_mtx
); 
 818 rip_pcblist SYSCTL_HANDLER_ARGS
 
 820 #pragma unused(oidp, arg1, arg2) 
 822         struct inpcb 
*inp
, **inp_list
; 
 827          * The process of preparing the TCB list is too time-consuming and 
 828          * resource-intensive to repeat twice on every request. 
 830         lck_rw_lock_exclusive(ripcbinfo
.mtx
); 
 831         if (req
->oldptr 
== USER_ADDR_NULL
) { 
 832                 n 
= ripcbinfo
.ipi_count
; 
 833                 req
->oldidx 
= 2 * (sizeof xig
) 
 834                         + (n 
+ n
/8) * sizeof(struct xinpcb
); 
 835                 lck_rw_done(ripcbinfo
.mtx
); 
 839         if (req
->newptr 
!= USER_ADDR_NULL
) { 
 840                 lck_rw_done(ripcbinfo
.mtx
); 
 845          * OK, now we're committed to doing something. 
 847         gencnt 
= ripcbinfo
.ipi_gencnt
; 
 848         n 
= ripcbinfo
.ipi_count
; 
 850         bzero(&xig
, sizeof(xig
)); 
 851         xig
.xig_len 
= sizeof xig
; 
 853         xig
.xig_gen 
= gencnt
; 
 854         xig
.xig_sogen 
= so_gencnt
; 
 855         error 
= SYSCTL_OUT(req
, &xig
, sizeof xig
); 
 857                 lck_rw_done(ripcbinfo
.mtx
); 
 861      * We are done if there is no pcb 
 864         lck_rw_done(ripcbinfo
.mtx
); 
 868         inp_list 
= _MALLOC(n 
* sizeof *inp_list
, M_TEMP
, M_WAITOK
); 
 870                 lck_rw_done(ripcbinfo
.mtx
); 
 874         for (inp 
= ripcbinfo
.listhead
->lh_first
, i 
= 0; inp 
&& i 
< n
; 
 875              inp 
= inp
->inp_list
.le_next
) { 
 876                 if (inp
->inp_gencnt 
<= gencnt 
&& inp
->inp_state 
!= INPCB_STATE_DEAD
) 
 882         for (i 
= 0; i 
< n
; i
++) { 
 884                 if (inp
->inp_gencnt 
<= gencnt 
&& inp
->inp_state 
!= INPCB_STATE_DEAD
) { 
 887                         bzero(&xi
, sizeof(xi
)); 
 888                         xi
.xi_len 
= sizeof xi
; 
 889                         /* XXX should avoid extra copy */ 
 890                         inpcb_to_compat(inp
, &xi
.xi_inp
); 
 892                                 sotoxsocket(inp
->inp_socket
, &xi
.xi_socket
); 
 893                         error 
= SYSCTL_OUT(req
, &xi
, sizeof xi
); 
 898                  * Give the user an updated idea of our state. 
 899                  * If the generation differs from what we told 
 900                  * her before, she knows that something happened 
 901                  * while we were processing this request, and it 
 902                  * might be necessary to retry. 
 904                 bzero(&xig
, sizeof(xig
)); 
 905                 xig
.xig_len 
= sizeof xig
; 
 906                 xig
.xig_gen 
= ripcbinfo
.ipi_gencnt
; 
 907                 xig
.xig_sogen 
= so_gencnt
; 
 908                 xig
.xig_count 
= ripcbinfo
.ipi_count
; 
 909                 error 
= SYSCTL_OUT(req
, &xig
, sizeof xig
); 
 911         FREE(inp_list
, M_TEMP
); 
 912         lck_rw_done(ripcbinfo
.mtx
); 
 916 SYSCTL_PROC(_net_inet_raw
, OID_AUTO
/*XXX*/, pcblist
, CTLFLAG_RD
, 0, 0, 
 917             rip_pcblist
, "S,xinpcb", "List of active raw IP sockets"); 
 919 struct pr_usrreqs rip_usrreqs 
= { 
 920         rip_abort
, pru_accept_notsupp
, rip_attach
, rip_bind
, rip_connect
, 
 921         pru_connect2_notsupp
, in_control
, rip_detach
, rip_disconnect
, 
 922         pru_listen_notsupp
, in_setpeeraddr
, pru_rcvd_notsupp
, 
 923         pru_rcvoob_notsupp
, rip_send
, pru_sense_null
, rip_shutdown
, 
 924         in_setsockaddr
, sosend
, soreceive
, pru_sopoll_notsupp
 
 926 /* DSEP Review Done pl-20051213-v02 @3253 */