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

Cache object: 6d97142aa8f066896d4a2fd923baf331


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