LCOV - code coverage report
Current view: top level - netinet - raw_ip.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 228 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 7 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: raw_ip.c,v 1.112 2018/09/13 19:53:58 bluhm Exp $      */
       2             : /*      $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $     */
       3             : 
       4             : /*
       5             :  * Copyright (c) 1982, 1986, 1988, 1993
       6             :  *      The Regents of the University of California.  All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      11             :  * 1. Redistributions of source code must retain the above copyright
      12             :  *    notice, this list of conditions and the following disclaimer.
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  * 3. Neither the name of the University nor the names of its contributors
      17             :  *    may be used to endorse or promote products derived from this software
      18             :  *    without specific prior written permission.
      19             :  *
      20             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      21             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      22             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      23             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      24             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      25             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      26             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      27             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      28             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      29             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      30             :  * SUCH DAMAGE.
      31             :  *
      32             :  *      @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
      33             :  *
      34             :  * NRL grants permission for redistribution and use in source and binary
      35             :  * forms, with or without modification, of the software and documentation
      36             :  * created at NRL provided that the following conditions are met:
      37             :  *
      38             :  * 1. Redistributions of source code must retain the above copyright
      39             :  *    notice, this list of conditions and the following disclaimer.
      40             :  * 2. Redistributions in binary form must reproduce the above copyright
      41             :  *    notice, this list of conditions and the following disclaimer in the
      42             :  *    documentation and/or other materials provided with the distribution.
      43             :  * 3. All advertising materials mentioning features or use of this software
      44             :  *    must display the following acknowledgements:
      45             :  *      This product includes software developed by the University of
      46             :  *      California, Berkeley and its contributors.
      47             :  *      This product includes software developed at the Information
      48             :  *      Technology Division, US Naval Research Laboratory.
      49             :  * 4. Neither the name of the NRL nor the names of its contributors
      50             :  *    may be used to endorse or promote products derived from this software
      51             :  *    without specific prior written permission.
      52             :  *
      53             :  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
      54             :  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
      55             :  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
      56             :  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
      57             :  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
      58             :  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      59             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
      60             :  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
      61             :  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      62             :  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      63             :  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      64             :  *
      65             :  * The views and conclusions contained in the software and documentation
      66             :  * are those of the authors and should not be interpreted as representing
      67             :  * official policies, either expressed or implied, of the US Naval
      68             :  * Research Laboratory (NRL).
      69             :  */
      70             : 
      71             : #include <sys/param.h>
      72             : #include <sys/systm.h>
      73             : #include <sys/mbuf.h>
      74             : #include <sys/socket.h>
      75             : #include <sys/protosw.h>
      76             : #include <sys/socketvar.h>
      77             : 
      78             : #include <net/if.h>
      79             : #include <net/if_var.h>
      80             : #include <net/route.h>
      81             : 
      82             : #include <netinet/in.h>
      83             : #include <netinet/ip.h>
      84             : #include <netinet/ip_mroute.h>
      85             : #include <netinet/ip_var.h>
      86             : #include <netinet/in_pcb.h>
      87             : #include <netinet/in_var.h>
      88             : #include <netinet/ip_icmp.h>
      89             : 
      90             : #include <net/pfvar.h>
      91             : 
      92             : #include "pf.h"
      93             : 
      94             : struct inpcbtable rawcbtable;
      95             : 
      96             : /*
      97             :  * Nominal space allocated to a raw ip socket.
      98             :  */
      99             : #define RIPSNDQ         8192
     100             : #define RIPRCVQ         8192
     101             : 
     102             : /*
     103             :  * Raw interface to IP protocol.
     104             :  */
     105             : 
     106             : /*
     107             :  * Initialize raw connection block q.
     108             :  */
     109             : void
     110           0 : rip_init(void)
     111             : {
     112             : 
     113           0 :         in_pcbinit(&rawcbtable, 1);
     114           0 : }
     115             : 
     116             : struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET };
     117             : 
     118             : int
     119           0 : rip_input(struct mbuf **mp, int *offp, int proto, int af)
     120             : {
     121           0 :         struct mbuf *m = *mp;
     122           0 :         struct ip *ip = mtod(m, struct ip *);
     123             :         struct inpcb *inp, *last = NULL;
     124             :         struct in_addr *key;
     125           0 :         struct mbuf *opts = NULL;
     126           0 :         struct counters_ref ref;
     127             :         uint64_t *counters;
     128             : 
     129           0 :         KASSERT(af == AF_INET);
     130             : 
     131           0 :         ripsrc.sin_addr = ip->ip_src;
     132           0 :         key = &ip->ip_dst;
     133             : #if NPF > 0
     134           0 :         if (m->m_pkthdr.pf.flags & PF_TAG_DIVERTED) {
     135             :                 struct pf_divert *divert;
     136             : 
     137           0 :                 divert = pf_find_divert(m);
     138           0 :                 KASSERT(divert != NULL);
     139           0 :                 switch (divert->type) {
     140             :                 case PF_DIVERT_TO:
     141           0 :                         key = &divert->addr.v4;
     142           0 :                         break;
     143             :                 case PF_DIVERT_REPLY:
     144             :                         break;
     145             :                 default:
     146           0 :                         panic("%s: unknown divert type %d, mbuf %p, divert %p",
     147             :                             __func__, divert->type, m, divert);
     148             :                 }
     149           0 :         }
     150             : #endif
     151           0 :         NET_ASSERT_LOCKED();
     152           0 :         TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
     153           0 :                 if (inp->inp_socket->so_state & SS_CANTRCVMORE)
     154             :                         continue;
     155             : #ifdef INET6
     156           0 :                 if (inp->inp_flags & INP_IPV6)
     157             :                         continue;
     158             : #endif
     159           0 :                 if (rtable_l2(inp->inp_rtableid) !=
     160           0 :                     rtable_l2(m->m_pkthdr.ph_rtableid))
     161             :                         continue;
     162             : 
     163           0 :                 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p)
     164             :                         continue;
     165           0 :                 if (inp->inp_laddr.s_addr &&
     166           0 :                     inp->inp_laddr.s_addr != key->s_addr)
     167             :                         continue;
     168           0 :                 if (inp->inp_faddr.s_addr &&
     169           0 :                     inp->inp_faddr.s_addr != ip->ip_src.s_addr)
     170             :                         continue;
     171           0 :                 if (last) {
     172             :                         struct mbuf *n;
     173             : 
     174           0 :                         if ((n = m_copym(m, 0, M_COPYALL, M_NOWAIT)) != NULL) {
     175           0 :                                 if (last->inp_flags & INP_CONTROLOPTS ||
     176           0 :                                     last->inp_socket->so_options & SO_TIMESTAMP)
     177           0 :                                         ip_savecontrol(last, &opts, ip, n);
     178           0 :                                 if (sbappendaddr(last->inp_socket,
     179           0 :                                     &last->inp_socket->so_rcv,
     180           0 :                                     sintosa(&ripsrc), n, opts) == 0) {
     181             :                                         /* should notify about lost packet */
     182           0 :                                         m_freem(n);
     183           0 :                                         m_freem(opts);
     184           0 :                                 } else
     185           0 :                                         sorwakeup(last->inp_socket);
     186           0 :                                 opts = NULL;
     187           0 :                         }
     188           0 :                 }
     189             :                 last = inp;
     190           0 :         }
     191           0 :         if (last) {
     192           0 :                 if (last->inp_flags & INP_CONTROLOPTS ||
     193           0 :                     last->inp_socket->so_options & SO_TIMESTAMP)
     194           0 :                         ip_savecontrol(last, &opts, ip, m);
     195           0 :                 if (sbappendaddr(last->inp_socket, &last->inp_socket->so_rcv,
     196           0 :                     sintosa(&ripsrc), m, opts) == 0) {
     197           0 :                         m_freem(m);
     198           0 :                         m_freem(opts);
     199           0 :                 } else
     200           0 :                         sorwakeup(last->inp_socket);
     201             :         } else {
     202           0 :                 if (ip->ip_p != IPPROTO_ICMP)
     203           0 :                         icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
     204             :                 else
     205           0 :                         m_freem(m);
     206             : 
     207           0 :                 counters = counters_enter(&ref, ipcounters);
     208           0 :                 counters[ips_noproto]++;
     209           0 :                 counters[ips_delivered]--;
     210           0 :                 counters_leave(&ref, ipcounters);
     211             :         }
     212           0 :         return IPPROTO_DONE;
     213           0 : }
     214             : 
     215             : /*
     216             :  * Generate IP header and pass packet to ip_output.
     217             :  * Tack on options user may have setup with control call.
     218             :  */
     219             : int
     220           0 : rip_output(struct mbuf *m, struct socket *so, struct sockaddr *dstaddr,
     221             :     struct mbuf *control)
     222             : {
     223             :         struct ip *ip;
     224             :         struct inpcb *inp;
     225             :         int flags, error;
     226             : 
     227           0 :         inp = sotoinpcb(so);
     228             :         flags = IP_ALLOWBROADCAST;
     229             : 
     230             :         /*
     231             :          * If the user handed us a complete IP packet, use it.
     232             :          * Otherwise, allocate an mbuf for a header and fill it in.
     233             :          */
     234           0 :         if ((inp->inp_flags & INP_HDRINCL) == 0) {
     235           0 :                 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
     236           0 :                         m_freem(m);
     237           0 :                         return (EMSGSIZE);
     238             :                 }
     239           0 :                 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
     240           0 :                 if (!m)
     241           0 :                         return (ENOBUFS);
     242           0 :                 ip = mtod(m, struct ip *);
     243           0 :                 ip->ip_tos = inp->inp_ip.ip_tos;
     244           0 :                 ip->ip_off = htons(0);
     245           0 :                 ip->ip_p = inp->inp_ip.ip_p;
     246           0 :                 ip->ip_len = htons(m->m_pkthdr.len);
     247           0 :                 ip->ip_src = inp->inp_laddr;
     248           0 :                 ip->ip_dst = satosin(dstaddr)->sin_addr;
     249           0 :                 ip->ip_ttl = inp->inp_ip.ip_ttl ? inp->inp_ip.ip_ttl : MAXTTL;
     250           0 :         } else {
     251           0 :                 if (m->m_pkthdr.len > IP_MAXPACKET) {
     252           0 :                         m_freem(m);
     253           0 :                         return (EMSGSIZE);
     254             :                 }
     255           0 :                 if (m->m_pkthdr.len < sizeof(struct ip)) {
     256           0 :                         m_freem(m);
     257           0 :                         return (EINVAL);
     258             :                 }
     259           0 :                 ip = mtod(m, struct ip *);
     260             :                 /*
     261             :                  * don't allow both user specified and setsockopt options,
     262             :                  * and don't allow packet length sizes that will crash
     263             :                  */
     264           0 :                 if ((ip->ip_hl != (sizeof (*ip) >> 2) && inp->inp_options) ||
     265           0 :                     ntohs(ip->ip_len) > m->m_pkthdr.len ||
     266           0 :                     ntohs(ip->ip_len) < ip->ip_hl << 2) {
     267           0 :                         m_freem(m);
     268           0 :                         return (EINVAL);
     269             :                 }
     270           0 :                 if (ip->ip_id == 0) {
     271           0 :                         ip->ip_id = htons(ip_randomid());
     272           0 :                 }
     273             :                 /* XXX prevent ip_output from overwriting header fields */
     274             :                 flags |= IP_RAWOUTPUT;
     275           0 :                 ipstat_inc(ips_rawout);
     276             :         }
     277             : #ifdef INET6
     278             :         /*
     279             :          * A thought:  Even though raw IP shouldn't be able to set IPv6
     280             :          *             multicast options, if it does, the last parameter to
     281             :          *             ip_output should be guarded against v6/v4 problems.
     282             :          */
     283             : #endif
     284             :         /* force routing table */
     285           0 :         m->m_pkthdr.ph_rtableid = inp->inp_rtableid;
     286             : 
     287             : #if NPF > 0
     288           0 :         if (inp->inp_socket->so_state & SS_ISCONNECTED &&
     289           0 :             ip->ip_p != IPPROTO_ICMP)
     290           0 :                 pf_mbuf_link_inpcb(m, inp);
     291             : #endif
     292             : 
     293           0 :         error = ip_output(m, inp->inp_options, &inp->inp_route, flags,
     294           0 :             inp->inp_moptions, inp, 0);
     295           0 :         if (error == EACCES)    /* translate pf(4) error for userland */
     296             :                 error = EHOSTUNREACH;
     297           0 :         return (error);
     298           0 : }
     299             : 
     300             : /*
     301             :  * Raw IP socket option processing.
     302             :  */
     303             : int
     304           0 : rip_ctloutput(int op, struct socket *so, int level, int optname,
     305             :     struct mbuf *m)
     306             : {
     307           0 :         struct inpcb *inp = sotoinpcb(so);
     308             :         int error;
     309             : 
     310           0 :         if (level != IPPROTO_IP)
     311           0 :                 return (EINVAL);
     312             : 
     313           0 :         switch (optname) {
     314             : 
     315             :         case IP_HDRINCL:
     316             :                 error = 0;
     317           0 :                 if (op == PRCO_SETOPT) {
     318           0 :                         if (m == NULL || m->m_len < sizeof (int))
     319           0 :                                 error = EINVAL;
     320           0 :                         else if (*mtod(m, int *))
     321           0 :                                 inp->inp_flags |= INP_HDRINCL;
     322             :                         else
     323           0 :                                 inp->inp_flags &= ~INP_HDRINCL;
     324             :                 } else {
     325           0 :                         m->m_len = sizeof(int);
     326           0 :                         *mtod(m, int *) = inp->inp_flags & INP_HDRINCL;
     327             :                 }
     328           0 :                 return (error);
     329             : 
     330             :         case MRT_INIT:
     331             :         case MRT_DONE:
     332             :         case MRT_ADD_VIF:
     333             :         case MRT_DEL_VIF:
     334             :         case MRT_ADD_MFC:
     335             :         case MRT_DEL_MFC:
     336             :         case MRT_VERSION:
     337             :         case MRT_ASSERT:
     338             :         case MRT_API_SUPPORT:
     339             :         case MRT_API_CONFIG:
     340             : #ifdef MROUTING
     341           0 :                 switch (op) {
     342             :                 case PRCO_SETOPT:
     343           0 :                         error = ip_mrouter_set(so, optname, m);
     344           0 :                         break;
     345             :                 case PRCO_GETOPT:
     346           0 :                         error = ip_mrouter_get(so, optname, m);
     347           0 :                         break;
     348             :                 default:
     349             :                         error = EINVAL;
     350           0 :                         break;
     351             :                 }
     352           0 :                 return (error);
     353             : #else
     354             :                 return (EOPNOTSUPP);
     355             : #endif
     356             :         }
     357           0 :         return (ip_ctloutput(op, so, level, optname, m));
     358           0 : }
     359             : 
     360             : u_long  rip_sendspace = RIPSNDQ;
     361             : u_long  rip_recvspace = RIPRCVQ;
     362             : 
     363             : /*ARGSUSED*/
     364             : int
     365           0 : rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
     366             :     struct mbuf *control, struct proc *p)
     367             : {
     368             :         struct inpcb *inp;
     369             :         int error = 0;
     370             : 
     371           0 :         if (req == PRU_CONTROL)
     372           0 :                 return (in_control(so, (u_long)m, (caddr_t)nam,
     373           0 :                     (struct ifnet *)control));
     374             : 
     375           0 :         soassertlocked(so);
     376             : 
     377           0 :         inp = sotoinpcb(so);
     378           0 :         if (inp == NULL) {
     379             :                 error = EINVAL;
     380           0 :                 goto release;
     381             :         }
     382             : 
     383           0 :         switch (req) {
     384             : 
     385             :         case PRU_DISCONNECT:
     386           0 :                 if ((so->so_state & SS_ISCONNECTED) == 0) {
     387             :                         error = ENOTCONN;
     388           0 :                         break;
     389             :                 }
     390             :                 /* FALLTHROUGH */
     391             :         case PRU_ABORT:
     392           0 :                 soisdisconnected(so);
     393           0 :                 if (inp == NULL)
     394           0 :                         panic("rip_abort");
     395             : #ifdef MROUTING
     396           0 :                 if (so == ip_mrouter[inp->inp_rtableid])
     397           0 :                         ip_mrouter_done(so);
     398             : #endif
     399           0 :                 in_pcbdetach(inp);
     400           0 :                 break;
     401             : 
     402             :         case PRU_BIND:
     403             :             {
     404           0 :                 struct sockaddr_in *addr;
     405             : 
     406           0 :                 if ((error = in_nam2sin(nam, &addr)))
     407           0 :                         break;
     408           0 :                 if (!((so->so_options & SO_BINDANY) ||
     409           0 :                     addr->sin_addr.s_addr == INADDR_ANY ||
     410           0 :                     addr->sin_addr.s_addr == INADDR_BROADCAST ||
     411           0 :                     in_broadcast(addr->sin_addr, inp->inp_rtableid) ||
     412           0 :                     ifa_ifwithaddr(sintosa(addr), inp->inp_rtableid))) {
     413             :                         error = EADDRNOTAVAIL;
     414           0 :                         break;
     415             :                 }
     416           0 :                 inp->inp_laddr = addr->sin_addr;
     417           0 :                 break;
     418           0 :             }
     419             :         case PRU_CONNECT:
     420             :             {
     421           0 :                 struct sockaddr_in *addr;
     422             : 
     423           0 :                 if ((error = in_nam2sin(nam, &addr)))
     424           0 :                         break;
     425           0 :                 inp->inp_faddr = addr->sin_addr;
     426           0 :                 soisconnected(so);
     427           0 :                 break;
     428           0 :             }
     429             : 
     430             :         case PRU_CONNECT2:
     431             :                 error = EOPNOTSUPP;
     432           0 :                 break;
     433             : 
     434             :         /*
     435             :          * Mark the connection as being incapable of further input.
     436             :          */
     437             :         case PRU_SHUTDOWN:
     438           0 :                 socantsendmore(so);
     439           0 :                 break;
     440             : 
     441             :         /*
     442             :          * Ship a packet out.  The appropriate raw output
     443             :          * routine handles any massaging necessary.
     444             :          */
     445             :         case PRU_SEND:
     446             :             {
     447           0 :                 struct sockaddr_in dst;
     448             : 
     449           0 :                 memset(&dst, 0, sizeof(dst));
     450           0 :                 dst.sin_family = AF_INET;
     451           0 :                 dst.sin_len = sizeof(dst);
     452           0 :                 if (so->so_state & SS_ISCONNECTED) {
     453           0 :                         if (nam) {
     454             :                                 error = EISCONN;
     455           0 :                                 break;
     456             :                         }
     457           0 :                         dst.sin_addr = inp->inp_faddr;
     458           0 :                 } else {
     459           0 :                         struct sockaddr_in *addr;
     460             : 
     461           0 :                         if (nam == NULL) {
     462             :                                 error = ENOTCONN;
     463           0 :                                 break;
     464             :                         }
     465           0 :                         if ((error = in_nam2sin(nam, &addr)))
     466           0 :                                 break;
     467           0 :                         dst.sin_addr = addr->sin_addr;
     468           0 :                 }
     469             : #ifdef IPSEC
     470             :                 /* XXX Find an IPsec TDB */
     471             : #endif
     472           0 :                 error = rip_output(m, so, sintosa(&dst), NULL);
     473             :                 m = NULL;
     474           0 :                 break;
     475           0 :             }
     476             : 
     477             :         case PRU_SENSE:
     478             :                 /*
     479             :                  * stat: don't bother with a blocksize.
     480             :                  */
     481           0 :                 return (0);
     482             : 
     483             :         /*
     484             :          * Not supported.
     485             :          */
     486             :         case PRU_LISTEN:
     487             :         case PRU_ACCEPT:
     488             :         case PRU_SENDOOB:
     489             :                 error = EOPNOTSUPP;
     490           0 :                 break;
     491             : 
     492             :         case PRU_RCVD:
     493             :         case PRU_RCVOOB:
     494           0 :                 return (EOPNOTSUPP);    /* do not free mbuf's */
     495             : 
     496             :         case PRU_SOCKADDR:
     497           0 :                 in_setsockaddr(inp, nam);
     498           0 :                 break;
     499             : 
     500             :         case PRU_PEERADDR:
     501           0 :                 in_setpeeraddr(inp, nam);
     502           0 :                 break;
     503             : 
     504             :         default:
     505           0 :                 panic("rip_usrreq");
     506             :         }
     507             : release:
     508           0 :         m_freem(control);
     509           0 :         m_freem(m);
     510           0 :         return (error);
     511           0 : }
     512             : 
     513             : int
     514           0 : rip_attach(struct socket *so, int proto)
     515             : {
     516             :         struct inpcb *inp;
     517             :         int error;
     518             : 
     519           0 :         if (so->so_pcb)
     520           0 :                 panic("rip_attach");
     521           0 :         if ((so->so_state & SS_PRIV) == 0)
     522           0 :                 return EACCES;
     523           0 :         if (proto < 0 || proto >= IPPROTO_MAX)
     524           0 :                 return EPROTONOSUPPORT;
     525             : 
     526           0 :         if ((error = soreserve(so, rip_sendspace, rip_recvspace)))
     527           0 :                 return error;
     528           0 :         NET_ASSERT_LOCKED();
     529           0 :         if ((error = in_pcballoc(so, &rawcbtable)))
     530           0 :                 return error;
     531           0 :         inp = sotoinpcb(so);
     532           0 :         inp->inp_ip.ip_p = proto;
     533           0 :         return 0;
     534           0 : }
     535             : 
     536             : int
     537           0 : rip_detach(struct socket *so)
     538             : {
     539           0 :         struct inpcb *inp = sotoinpcb(so);
     540             : 
     541           0 :         soassertlocked(so);
     542             : 
     543           0 :         if (inp == NULL)
     544           0 :                 return (EINVAL);
     545             : 
     546             : #ifdef MROUTING
     547           0 :         if (so == ip_mrouter[inp->inp_rtableid])
     548           0 :                 ip_mrouter_done(so);
     549             : #endif
     550           0 :         in_pcbdetach(inp);
     551             : 
     552           0 :         return (0);
     553           0 : }

Generated by: LCOV version 1.13