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

Cache object: 74527edb55c5b12f7097df4f10673395


[ 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.