The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netinet/raw_ip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: raw_ip.c,v 1.94 2006/10/25 22:49:23 elad Exp $ */
    2 
    3 /*
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 /*
   33  * Copyright (c) 1982, 1986, 1988, 1993
   34  *      The Regents of the University of California.  All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. 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.
   47  *
   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
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)raw_ip.c    8.7 (Berkeley) 5/15/95
   61  */
   62 
   63 #include <sys/cdefs.h>
   64 __KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.94 2006/10/25 22:49:23 elad Exp $");
   65 
   66 #include "opt_inet.h"
   67 #include "opt_ipsec.h"
   68 #include "opt_mrouting.h"
   69 
   70 #include <sys/param.h>
   71 #include <sys/sysctl.h>
   72 #include <sys/malloc.h>
   73 #include <sys/mbuf.h>
   74 #include <sys/socket.h>
   75 #include <sys/protosw.h>
   76 #include <sys/socketvar.h>
   77 #include <sys/errno.h>
   78 #include <sys/systm.h>
   79 #include <sys/proc.h>
   80 #include <sys/kauth.h>
   81 
   82 #include <net/if.h>
   83 #include <net/route.h>
   84 
   85 #include <netinet/in.h>
   86 #include <netinet/in_systm.h>
   87 #include <netinet/ip.h>
   88 #include <netinet/ip_var.h>
   89 #include <netinet/ip_mroute.h>
   90 #include <netinet/ip_icmp.h>
   91 #include <netinet/in_pcb.h>
   92 #include <netinet/in_proto.h>
   93 #include <netinet/in_var.h>
   94 
   95 #include <machine/stdarg.h>
   96 
   97 #ifdef IPSEC
   98 #include <netinet6/ipsec.h>
   99 #endif /*IPSEC*/
  100 
  101 #ifdef FAST_IPSEC
  102 #include <netipsec/ipsec.h>
  103 #include <netipsec/ipsec_var.h>                 /* XXX ipsecstat namespace */
  104 #endif  /* FAST_IPSEC*/
  105 
  106 struct inpcbtable rawcbtable;
  107 
  108 int      rip_pcbnotify(struct inpcbtable *, struct in_addr,
  109     struct in_addr, int, int, void (*)(struct inpcb *, int));
  110 int      rip_bind(struct inpcb *, struct mbuf *);
  111 int      rip_connect(struct inpcb *, struct mbuf *);
  112 void     rip_disconnect(struct inpcb *);
  113 
  114 /*
  115  * Nominal space allocated to a raw ip socket.
  116  */
  117 #define RIPSNDQ         8192
  118 #define RIPRCVQ         8192
  119 
  120 /*
  121  * Raw interface to IP protocol.
  122  */
  123 
  124 /*
  125  * Initialize raw connection block q.
  126  */
  127 void
  128 rip_init(void)
  129 {
  130 
  131         in_pcbinit(&rawcbtable, 1, 1);
  132 }
  133 
  134 /*
  135  * Setup generic address and protocol structures
  136  * for raw_input routine, then pass them along with
  137  * mbuf chain.
  138  */
  139 void
  140 rip_input(struct mbuf *m, ...)
  141 {
  142         int proto;
  143         struct ip *ip = mtod(m, struct ip *);
  144         struct inpcb_hdr *inph;
  145         struct inpcb *inp;
  146         struct inpcb *last = 0;
  147         struct mbuf *opts = 0;
  148         struct sockaddr_in ripsrc;
  149         va_list ap;
  150 
  151         va_start(ap, m);
  152         (void)va_arg(ap, int);          /* ignore value, advance ap */
  153         proto = va_arg(ap, int);
  154         va_end(ap);
  155 
  156         ripsrc.sin_family = AF_INET;
  157         ripsrc.sin_len = sizeof(struct sockaddr_in);
  158         ripsrc.sin_addr = ip->ip_src;
  159         ripsrc.sin_port = 0;
  160         bzero((caddr_t)ripsrc.sin_zero, sizeof(ripsrc.sin_zero));
  161 
  162         /*
  163          * XXX Compatibility: programs using raw IP expect ip_len
  164          * XXX to have the header length subtracted, and in host order.
  165          * XXX ip_off is also expected to be host order.
  166          */
  167         ip->ip_len = ntohs(ip->ip_len) - (ip->ip_hl << 2);
  168         NTOHS(ip->ip_off);
  169 
  170         CIRCLEQ_FOREACH(inph, &rawcbtable.inpt_queue, inph_queue) {
  171                 inp = (struct inpcb *)inph;
  172                 if (inp->inp_af != AF_INET)
  173                         continue;
  174                 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
  175                         continue;
  176                 if (!in_nullhost(inp->inp_laddr) &&
  177                     !in_hosteq(inp->inp_laddr, ip->ip_dst))
  178                         continue;
  179                 if (!in_nullhost(inp->inp_faddr) &&
  180                     !in_hosteq(inp->inp_faddr, ip->ip_src))
  181                         continue;
  182                 if (last) {
  183                         struct mbuf *n;
  184 
  185 #if defined(IPSEC) || defined(FAST_IPSEC)
  186                         /* check AH/ESP integrity. */
  187                         if (ipsec4_in_reject_so(m, last->inp_socket)) {
  188                                 ipsecstat.in_polvio++;
  189                                 /* do not inject data to pcb */
  190                         } else
  191 #endif /*IPSEC*/
  192                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  193                                 if (last->inp_flags & INP_CONTROLOPTS ||
  194                                     last->inp_socket->so_options & SO_TIMESTAMP)
  195                                         ip_savecontrol(last, &opts, ip, n);
  196                                 if (sbappendaddr(&last->inp_socket->so_rcv,
  197                                     sintosa(&ripsrc), n, opts) == 0) {
  198                                         /* should notify about lost packet */
  199                                         m_freem(n);
  200                                         if (opts)
  201                                                 m_freem(opts);
  202                                 } else
  203                                         sorwakeup(last->inp_socket);
  204                                 opts = NULL;
  205                         }
  206                 }
  207                 last = inp;
  208         }
  209 #if defined(IPSEC) || defined(FAST_IPSEC)
  210         /* check AH/ESP integrity. */
  211         if (last && ipsec4_in_reject_so(m, last->inp_socket)) {
  212                 m_freem(m);
  213                 ipsecstat.in_polvio++;
  214                 ipstat.ips_delivered--;
  215                 /* do not inject data to pcb */
  216         } else
  217 #endif /*IPSEC*/
  218         if (last) {
  219                 if (last->inp_flags & INP_CONTROLOPTS ||
  220                     last->inp_socket->so_options & SO_TIMESTAMP)
  221                         ip_savecontrol(last, &opts, ip, m);
  222                 if (sbappendaddr(&last->inp_socket->so_rcv,
  223                     sintosa(&ripsrc), m, opts) == 0) {
  224                         m_freem(m);
  225                         if (opts)
  226                                 m_freem(opts);
  227                 } else
  228                         sorwakeup(last->inp_socket);
  229         } else {
  230                 if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
  231                         icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
  232                             0, 0);
  233                         ipstat.ips_noproto++;
  234                         ipstat.ips_delivered--;
  235                 } else
  236                         m_freem(m);
  237         }
  238         return;
  239 }
  240 
  241 int
  242 rip_pcbnotify(struct inpcbtable *table,
  243     struct in_addr faddr, struct in_addr laddr, int proto, int errno,
  244     void (*notify)(struct inpcb *, int))
  245 {
  246         struct inpcb *inp, *ninp;
  247         int nmatch;
  248 
  249         nmatch = 0;
  250         for (inp = (struct inpcb *)CIRCLEQ_FIRST(&table->inpt_queue);
  251             inp != (struct inpcb *)&table->inpt_queue;
  252             inp = ninp) {
  253                 ninp = (struct inpcb *)inp->inp_queue.cqe_next;
  254                 if (inp->inp_af != AF_INET)
  255                         continue;
  256                 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
  257                         continue;
  258                 if (in_hosteq(inp->inp_faddr, faddr) &&
  259                     in_hosteq(inp->inp_laddr, laddr)) {
  260                         (*notify)(inp, errno);
  261                         nmatch++;
  262                 }
  263         }
  264 
  265         return nmatch;
  266 }
  267 
  268 void *
  269 rip_ctlinput(int cmd, struct sockaddr *sa, void *v)
  270 {
  271         struct ip *ip = v;
  272         void (*notify)(struct inpcb *, int) = in_rtchange;
  273         int errno;
  274 
  275         if (sa->sa_family != AF_INET ||
  276             sa->sa_len != sizeof(struct sockaddr_in))
  277                 return NULL;
  278         if ((unsigned)cmd >= PRC_NCMDS)
  279                 return NULL;
  280         errno = inetctlerrmap[cmd];
  281         if (PRC_IS_REDIRECT(cmd))
  282                 notify = in_rtchange, ip = 0;
  283         else if (cmd == PRC_HOSTDEAD)
  284                 ip = 0;
  285         else if (errno == 0)
  286                 return NULL;
  287         if (ip) {
  288                 rip_pcbnotify(&rawcbtable, satosin(sa)->sin_addr,
  289                     ip->ip_src, ip->ip_p, errno, notify);
  290 
  291                 /* XXX mapped address case */
  292         } else
  293                 in_pcbnotifyall(&rawcbtable, satosin(sa)->sin_addr, errno,
  294                     notify);
  295         return NULL;
  296 }
  297 
  298 /*
  299  * Generate IP header and pass packet to ip_output.
  300  * Tack on options user may have setup with control call.
  301  */
  302 int
  303 rip_output(struct mbuf *m, ...)
  304 {
  305         struct inpcb *inp;
  306         struct ip *ip;
  307         struct mbuf *opts;
  308         int flags;
  309         va_list ap;
  310 
  311         va_start(ap, m);
  312         inp = va_arg(ap, struct inpcb *);
  313         va_end(ap);
  314 
  315         flags =
  316             (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST
  317             | IP_RETURNMTU;
  318 
  319         /*
  320          * If the user handed us a complete IP packet, use it.
  321          * Otherwise, allocate an mbuf for a header and fill it in.
  322          */
  323         if ((inp->inp_flags & INP_HDRINCL) == 0) {
  324                 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
  325                         m_freem(m);
  326                         return (EMSGSIZE);
  327                 }
  328                 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
  329                 if (!m)
  330                         return (ENOBUFS);
  331                 ip = mtod(m, struct ip *);
  332                 ip->ip_tos = 0;
  333                 ip->ip_off = htons(0);
  334                 ip->ip_p = inp->inp_ip.ip_p;
  335                 ip->ip_len = htons(m->m_pkthdr.len);
  336                 ip->ip_src = inp->inp_laddr;
  337                 ip->ip_dst = inp->inp_faddr;
  338                 ip->ip_ttl = MAXTTL;
  339                 opts = inp->inp_options;
  340         } else {
  341                 if (m->m_pkthdr.len > IP_MAXPACKET) {
  342                         m_freem(m);
  343                         return (EMSGSIZE);
  344                 }
  345                 ip = mtod(m, struct ip *);
  346 
  347                 /*
  348                  * If the mbuf is read-only, we need to allocate
  349                  * a new mbuf for the header, since we need to
  350                  * modify the header.
  351                  */
  352                 if (M_READONLY(m)) {
  353                         int hlen = ip->ip_hl << 2;
  354 
  355                         m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3);
  356                         if (m == NULL)
  357                                 return (ENOMEM);        /* XXX */
  358                         ip = mtod(m, struct ip *);
  359                 }
  360 
  361                 /* XXX userland passes ip_len and ip_off in host order */
  362                 if (m->m_pkthdr.len != ip->ip_len) {
  363                         m_freem(m);
  364                         return (EINVAL);
  365                 }
  366                 HTONS(ip->ip_len);
  367                 HTONS(ip->ip_off);
  368                 if (ip->ip_id == 0)
  369                         ip->ip_id = ip_newid();
  370                 opts = NULL;
  371                 /* XXX prevent ip_output from overwriting header fields */
  372                 flags |= IP_RAWOUTPUT;
  373                 ipstat.ips_rawout++;
  374         }
  375         return (ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions,
  376              inp->inp_socket, &inp->inp_errormtu));
  377 }
  378 
  379 /*
  380  * Raw IP socket option processing.
  381  */
  382 int
  383 rip_ctloutput(int op, struct socket *so, int level, int optname,
  384     struct mbuf **m)
  385 {
  386         struct inpcb *inp = sotoinpcb(so);
  387         int error = 0;
  388 
  389         if (level != IPPROTO_IP) {
  390                 error = ENOPROTOOPT;
  391                 if (op == PRCO_SETOPT && *m != 0)
  392                         (void) m_free(*m);
  393         } else switch (op) {
  394 
  395         case PRCO_SETOPT:
  396                 switch (optname) {
  397                 case IP_HDRINCL:
  398                         if (*m == 0 || (*m)->m_len < sizeof (int))
  399                                 error = EINVAL;
  400                         else {
  401                                 if (*mtod(*m, int *))
  402                                         inp->inp_flags |= INP_HDRINCL;
  403                                 else
  404                                         inp->inp_flags &= ~INP_HDRINCL;
  405                         }
  406                         if (*m != 0)
  407                                 (void) m_free(*m);
  408                         break;
  409 
  410 #ifdef MROUTING
  411                 case MRT_INIT:
  412                 case MRT_DONE:
  413                 case MRT_ADD_VIF:
  414                 case MRT_DEL_VIF:
  415                 case MRT_ADD_MFC:
  416                 case MRT_DEL_MFC:
  417                 case MRT_ASSERT:
  418                 case MRT_API_CONFIG:
  419                 case MRT_ADD_BW_UPCALL:
  420                 case MRT_DEL_BW_UPCALL:
  421                         error = ip_mrouter_set(so, optname, m);
  422                         break;
  423 #endif
  424 
  425                 default:
  426                         error = ip_ctloutput(op, so, level, optname, m);
  427                         break;
  428                 }
  429                 break;
  430 
  431         case PRCO_GETOPT:
  432                 switch (optname) {
  433                 case IP_HDRINCL:
  434                         *m = m_get(M_WAIT, MT_SOOPTS);
  435                         MCLAIM((*m), so->so_mowner);
  436                         (*m)->m_len = sizeof (int);
  437                         *mtod(*m, int *) = inp->inp_flags & INP_HDRINCL ? 1 : 0;
  438                         break;
  439 
  440 #ifdef MROUTING
  441                 case MRT_VERSION:
  442                 case MRT_ASSERT:
  443                 case MRT_API_SUPPORT:
  444                 case MRT_API_CONFIG:
  445                         error = ip_mrouter_get(so, optname, m);
  446                         break;
  447 #endif
  448 
  449                 default:
  450                         error = ip_ctloutput(op, so, level, optname, m);
  451                         break;
  452                 }
  453                 break;
  454         }
  455         return (error);
  456 }
  457 
  458 int
  459 rip_bind(struct inpcb *inp, struct mbuf *nam)
  460 {
  461         struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  462 
  463         if (nam->m_len != sizeof(*addr))
  464                 return (EINVAL);
  465         if (TAILQ_FIRST(&ifnet) == 0)
  466                 return (EADDRNOTAVAIL);
  467         if (addr->sin_family != AF_INET &&
  468             addr->sin_family != AF_IMPLINK)
  469                 return (EAFNOSUPPORT);
  470         if (!in_nullhost(addr->sin_addr) &&
  471             ifa_ifwithaddr(sintosa(addr)) == 0)
  472                 return (EADDRNOTAVAIL);
  473         inp->inp_laddr = addr->sin_addr;
  474         return (0);
  475 }
  476 
  477 int
  478 rip_connect(struct inpcb *inp, struct mbuf *nam)
  479 {
  480         struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  481 
  482         if (nam->m_len != sizeof(*addr))
  483                 return (EINVAL);
  484         if (TAILQ_FIRST(&ifnet) == 0)
  485                 return (EADDRNOTAVAIL);
  486         if (addr->sin_family != AF_INET &&
  487             addr->sin_family != AF_IMPLINK)
  488                 return (EAFNOSUPPORT);
  489         inp->inp_faddr = addr->sin_addr;
  490         return (0);
  491 }
  492 
  493 void
  494 rip_disconnect(struct inpcb *inp)
  495 {
  496 
  497         inp->inp_faddr = zeroin_addr;
  498 }
  499 
  500 u_long  rip_sendspace = RIPSNDQ;
  501 u_long  rip_recvspace = RIPRCVQ;
  502 
  503 /*ARGSUSED*/
  504 int
  505 rip_usrreq(struct socket *so, int req,
  506     struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l)
  507 {
  508         struct inpcb *inp;
  509         int s;
  510         int error = 0;
  511 #ifdef MROUTING
  512         extern struct socket *ip_mrouter;
  513 #endif
  514 
  515         if (req == PRU_CONTROL)
  516                 return (in_control(so, (long)m, (caddr_t)nam,
  517                     (struct ifnet *)control, l));
  518 
  519         s = splsoftnet();
  520 
  521         if (req == PRU_PURGEIF) {
  522                 in_pcbpurgeif0(&rawcbtable, (struct ifnet *)control);
  523                 in_purgeif((struct ifnet *)control);
  524                 in_pcbpurgeif(&rawcbtable, (struct ifnet *)control);
  525                 splx(s);
  526                 return (0);
  527         }
  528 
  529         inp = sotoinpcb(so);
  530 #ifdef DIAGNOSTIC
  531         if (req != PRU_SEND && req != PRU_SENDOOB && control)
  532                 panic("rip_usrreq: unexpected control mbuf");
  533 #endif
  534         if (inp == 0 && req != PRU_ATTACH) {
  535                 error = EINVAL;
  536                 goto release;
  537         }
  538 
  539         switch (req) {
  540 
  541         case PRU_ATTACH:
  542                 if (inp != 0) {
  543                         error = EISCONN;
  544                         break;
  545                 }
  546 
  547                 if (l == NULL) {
  548                         error = EACCES;
  549                         break;
  550                 }
  551 
  552                 /* XXX: raw socket permissions are checked in socreate() */
  553 
  554                 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  555                         error = soreserve(so, rip_sendspace, rip_recvspace);
  556                         if (error)
  557                                 break;
  558                 }
  559                 error = in_pcballoc(so, &rawcbtable);
  560                 if (error)
  561                         break;
  562                 inp = sotoinpcb(so);
  563                 inp->inp_ip.ip_p = (long)nam;
  564                 break;
  565 
  566         case PRU_DETACH:
  567 #ifdef MROUTING
  568                 if (so == ip_mrouter)
  569                         ip_mrouter_done();
  570 #endif
  571                 in_pcbdetach(inp);
  572                 break;
  573 
  574         case PRU_BIND:
  575                 error = rip_bind(inp, nam);
  576                 break;
  577 
  578         case PRU_LISTEN:
  579                 error = EOPNOTSUPP;
  580                 break;
  581 
  582         case PRU_CONNECT:
  583                 error = rip_connect(inp, nam);
  584                 if (error)
  585                         break;
  586                 soisconnected(so);
  587                 break;
  588 
  589         case PRU_CONNECT2:
  590                 error = EOPNOTSUPP;
  591                 break;
  592 
  593         case PRU_DISCONNECT:
  594                 soisdisconnected(so);
  595                 rip_disconnect(inp);
  596                 break;
  597 
  598         /*
  599          * Mark the connection as being incapable of further input.
  600          */
  601         case PRU_SHUTDOWN:
  602                 socantsendmore(so);
  603                 break;
  604 
  605         case PRU_RCVD:
  606                 error = EOPNOTSUPP;
  607                 break;
  608 
  609         /*
  610          * Ship a packet out.  The appropriate raw output
  611          * routine handles any massaging necessary.
  612          */
  613         case PRU_SEND:
  614                 if (control && control->m_len) {
  615                         m_freem(control);
  616                         m_freem(m);
  617                         error = EINVAL;
  618                         break;
  619                 }
  620         {
  621                 if (nam) {
  622                         if ((so->so_state & SS_ISCONNECTED) != 0) {
  623                                 error = EISCONN;
  624                                 goto die;
  625                         }
  626                         error = rip_connect(inp, nam);
  627                         if (error) {
  628                         die:
  629                                 m_freem(m);
  630                                 break;
  631                         }
  632                 } else {
  633                         if ((so->so_state & SS_ISCONNECTED) == 0) {
  634                                 error = ENOTCONN;
  635                                 goto die;
  636                         }
  637                 }
  638                 error = rip_output(m, inp);
  639                 if (nam)
  640                         rip_disconnect(inp);
  641         }
  642                 break;
  643 
  644         case PRU_SENSE:
  645                 /*
  646                  * stat: don't bother with a blocksize.
  647                  */
  648                 splx(s);
  649                 return (0);
  650 
  651         case PRU_RCVOOB:
  652                 error = EOPNOTSUPP;
  653                 break;
  654 
  655         case PRU_SENDOOB:
  656                 m_freem(control);
  657                 m_freem(m);
  658                 error = EOPNOTSUPP;
  659                 break;
  660 
  661         case PRU_SOCKADDR:
  662                 in_setsockaddr(inp, nam);
  663                 break;
  664 
  665         case PRU_PEERADDR:
  666                 in_setpeeraddr(inp, nam);
  667                 break;
  668 
  669         default:
  670                 panic("rip_usrreq");
  671         }
  672 
  673 release:
  674         splx(s);
  675         return (error);
  676 }
  677 
  678 SYSCTL_SETUP(sysctl_net_inet_raw_setup, "sysctl net.inet.raw subtree setup")
  679 {
  680 
  681         sysctl_createv(clog, 0, NULL, NULL,
  682                        CTLFLAG_PERMANENT,
  683                        CTLTYPE_NODE, "net", NULL,
  684                        NULL, 0, NULL, 0,
  685                        CTL_NET, CTL_EOL);
  686         sysctl_createv(clog, 0, NULL, NULL,
  687                        CTLFLAG_PERMANENT,
  688                        CTLTYPE_NODE, "inet", NULL,
  689                        NULL, 0, NULL, 0,
  690                        CTL_NET, PF_INET, CTL_EOL);
  691         sysctl_createv(clog, 0, NULL, NULL,
  692                        CTLFLAG_PERMANENT,
  693                        CTLTYPE_NODE, "raw",
  694                        SYSCTL_DESCR("Raw IPv4 settings"),
  695                        NULL, 0, NULL, 0,
  696                        CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL);
  697 
  698         sysctl_createv(clog, 0, NULL, NULL,
  699                        CTLFLAG_PERMANENT,
  700                        CTLTYPE_STRUCT, "pcblist",
  701                        SYSCTL_DESCR("Raw IPv4 control block list"),
  702                        sysctl_inpcblist, 0, &rawcbtable, 0,
  703                        CTL_NET, PF_INET, IPPROTO_RAW,
  704                        CTL_CREATE, CTL_EOL);
  705 }

Cache object: 8bed940e0ba6eb8760ebe541aafa428e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.