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.108 2008/08/06 15:01:23 plunky 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.108 2008/08/06 15:01:23 plunky 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_private.h>
   90 #include <netinet/ip_mroute.h>
   91 #include <netinet/ip_icmp.h>
   92 #include <netinet/in_pcb.h>
   93 #include <netinet/in_proto.h>
   94 #include <netinet/in_var.h>
   95 
   96 #include <machine/stdarg.h>
   97 
   98 #ifdef IPSEC
   99 #include <netinet6/ipsec.h>
  100 #include <netinet6/ipsec_private.h>
  101 #endif /* IPSEC */
  102 
  103 #ifdef FAST_IPSEC
  104 #include <netipsec/ipsec.h>
  105 #include <netipsec/ipsec_var.h>
  106 #include <netipsec/ipsec_private.h>
  107 #endif  /* FAST_IPSEC */
  108 
  109 struct inpcbtable rawcbtable;
  110 
  111 int      rip_pcbnotify(struct inpcbtable *, struct in_addr,
  112     struct in_addr, int, int, void (*)(struct inpcb *, int));
  113 int      rip_bind(struct inpcb *, struct mbuf *);
  114 int      rip_connect(struct inpcb *, struct mbuf *);
  115 void     rip_disconnect(struct inpcb *);
  116 
  117 /*
  118  * Nominal space allocated to a raw ip socket.
  119  */
  120 #define RIPSNDQ         8192
  121 #define RIPRCVQ         8192
  122 
  123 /*
  124  * Raw interface to IP protocol.
  125  */
  126 
  127 /*
  128  * Initialize raw connection block q.
  129  */
  130 void
  131 rip_init(void)
  132 {
  133 
  134         in_pcbinit(&rawcbtable, 1, 1);
  135 }
  136 
  137 static void
  138 rip_sbappendaddr(struct inpcb *last, struct ip *ip, const struct sockaddr *sa,
  139     int hlen, struct mbuf *opts, struct mbuf *n)
  140 {
  141         if (last->inp_flags & INP_NOHEADER)
  142                 m_adj(n, hlen);
  143         if (last->inp_flags & INP_CONTROLOPTS ||
  144             last->inp_socket->so_options & SO_TIMESTAMP)
  145                 ip_savecontrol(last, &opts, ip, n);
  146         if (sbappendaddr(&last->inp_socket->so_rcv, sa, n, opts) == 0) {
  147                 /* should notify about lost packet */
  148                 m_freem(n);
  149                 if (opts)
  150                         m_freem(opts);
  151         } else
  152                 sorwakeup(last->inp_socket);
  153 }
  154 
  155 /*
  156  * Setup generic address and protocol structures
  157  * for raw_input routine, then pass them along with
  158  * mbuf chain.
  159  */
  160 void
  161 rip_input(struct mbuf *m, ...)
  162 {
  163         int hlen, proto;
  164         struct ip *ip = mtod(m, struct ip *);
  165         struct inpcb_hdr *inph;
  166         struct inpcb *inp;
  167         struct inpcb *last = NULL;
  168         struct mbuf *n, *opts = NULL;
  169         struct sockaddr_in ripsrc;
  170         va_list ap;
  171 
  172         va_start(ap, m);
  173         (void)va_arg(ap, int);          /* ignore value, advance ap */
  174         proto = va_arg(ap, int);
  175         va_end(ap);
  176 
  177         sockaddr_in_init(&ripsrc, &ip->ip_src, 0);
  178 
  179         /*
  180          * XXX Compatibility: programs using raw IP expect ip_len
  181          * XXX to have the header length subtracted, and in host order.
  182          * XXX ip_off is also expected to be host order.
  183          */
  184         hlen = ip->ip_hl << 2;
  185         ip->ip_len = ntohs(ip->ip_len) - hlen;
  186         NTOHS(ip->ip_off);
  187 
  188         CIRCLEQ_FOREACH(inph, &rawcbtable.inpt_queue, inph_queue) {
  189                 inp = (struct inpcb *)inph;
  190                 if (inp->inp_af != AF_INET)
  191                         continue;
  192                 if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != proto)
  193                         continue;
  194                 if (!in_nullhost(inp->inp_laddr) &&
  195                     !in_hosteq(inp->inp_laddr, ip->ip_dst))
  196                         continue;
  197                 if (!in_nullhost(inp->inp_faddr) &&
  198                     !in_hosteq(inp->inp_faddr, ip->ip_src))
  199                         continue;
  200                 if (last == NULL)
  201                         ;
  202 #if defined(IPSEC) || defined(FAST_IPSEC)
  203                 /* check AH/ESP integrity. */
  204                 else if (ipsec4_in_reject_so(m, last->inp_socket)) {
  205                         IPSEC_STATINC(IPSEC_STAT_IN_POLVIO);
  206                         /* do not inject data to pcb */
  207                 }
  208 #endif /*IPSEC*/
  209                 else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
  210                         rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, opts,
  211                             n);
  212                         opts = NULL;
  213                 }
  214                 last = inp;
  215         }
  216 #if defined(IPSEC) || defined(FAST_IPSEC)
  217         /* check AH/ESP integrity. */
  218         if (last != NULL && ipsec4_in_reject_so(m, last->inp_socket)) {
  219                 m_freem(m);
  220                 IPSEC_STATINC(IPSEC_STAT_IN_POLVIO);
  221                 IP_STATDEC(IP_STAT_DELIVERED);
  222                 /* do not inject data to pcb */
  223         } else
  224 #endif /*IPSEC*/
  225         if (last != NULL)
  226                 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, opts, m);
  227         else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
  228                 uint64_t *ips;
  229 
  230                 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
  231                     0, 0);
  232                 ips = IP_STAT_GETREF();
  233                 ips[IP_STAT_NOPROTO]++;
  234                 ips[IP_STAT_DELIVERED]--;
  235                 IP_STAT_PUTREF();
  236         } else
  237                 m_freem(m);
  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, const 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, satocsin(sa)->sin_addr,
  289                     ip->ip_src, ip->ip_p, errno, notify);
  290 
  291                 /* XXX mapped address case */
  292         } else
  293                 in_pcbnotifyall(&rawcbtable, satocsin(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 || m->m_pkthdr.len < IP_MINFRAGSIZE)
  369                         flags |= IP_NOIPNEWID;
  370                 opts = NULL;
  371                 /* XXX prevent ip_output from overwriting header fields */
  372                 flags |= IP_RAWOUTPUT;
  373                 IP_STATINC(IP_STAT_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, struct sockopt *sopt)
  384 {
  385         struct inpcb *inp = sotoinpcb(so);
  386         int error = 0;
  387         int optval;
  388 
  389         if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) {
  390                 if (op == PRCO_GETOPT) {
  391                         optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0;
  392                         error = sockopt_set(sopt, &optval, sizeof(optval));
  393                 } else if (op == PRCO_SETOPT) {
  394                         error = sockopt_getint(sopt, &optval);
  395                         if (error)
  396                                 goto out;
  397                         if (optval) {
  398                                 inp->inp_flags &= ~INP_HDRINCL;
  399                                 inp->inp_flags |= INP_NOHEADER;
  400                         } else
  401                                 inp->inp_flags &= ~INP_NOHEADER;
  402                 }
  403                 goto out;
  404         } else if (sopt->sopt_level != IPPROTO_IP)
  405                 return ip_ctloutput(op, so, sopt);
  406 
  407         switch (op) {
  408 
  409         case PRCO_SETOPT:
  410                 switch (sopt->sopt_name) {
  411                 case IP_HDRINCL:
  412                         error = sockopt_getint(sopt, &optval);
  413                         if (error)
  414                                 break;
  415                         if (optval)
  416                                 inp->inp_flags |= INP_HDRINCL;
  417                         else
  418                                 inp->inp_flags &= ~INP_HDRINCL;
  419                         break;
  420 
  421 #ifdef MROUTING
  422                 case MRT_INIT:
  423                 case MRT_DONE:
  424                 case MRT_ADD_VIF:
  425                 case MRT_DEL_VIF:
  426                 case MRT_ADD_MFC:
  427                 case MRT_DEL_MFC:
  428                 case MRT_ASSERT:
  429                 case MRT_API_CONFIG:
  430                 case MRT_ADD_BW_UPCALL:
  431                 case MRT_DEL_BW_UPCALL:
  432                         error = ip_mrouter_set(so, sopt);
  433                         break;
  434 #endif
  435 
  436                 default:
  437                         error = ip_ctloutput(op, so, sopt);
  438                         break;
  439                 }
  440                 break;
  441 
  442         case PRCO_GETOPT:
  443                 switch (sopt->sopt_name) {
  444                 case IP_HDRINCL:
  445                         optval = inp->inp_flags & INP_HDRINCL;
  446                         error = sockopt_set(sopt, &optval, sizeof(optval));
  447                         break;
  448 
  449 #ifdef MROUTING
  450                 case MRT_VERSION:
  451                 case MRT_ASSERT:
  452                 case MRT_API_SUPPORT:
  453                 case MRT_API_CONFIG:
  454                         error = ip_mrouter_get(so, sopt);
  455                         break;
  456 #endif
  457 
  458                 default:
  459                         error = ip_ctloutput(op, so, sopt);
  460                         break;
  461                 }
  462                 break;
  463         }
  464  out:
  465         return error;
  466 }
  467 
  468 int
  469 rip_bind(struct inpcb *inp, struct mbuf *nam)
  470 {
  471         struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  472 
  473         if (nam->m_len != sizeof(*addr))
  474                 return (EINVAL);
  475         if (TAILQ_FIRST(&ifnet) == 0)
  476                 return (EADDRNOTAVAIL);
  477         if (addr->sin_family != AF_INET &&
  478             addr->sin_family != AF_IMPLINK)
  479                 return (EAFNOSUPPORT);
  480         if (!in_nullhost(addr->sin_addr) &&
  481             ifa_ifwithaddr(sintosa(addr)) == 0)
  482                 return (EADDRNOTAVAIL);
  483         inp->inp_laddr = addr->sin_addr;
  484         return (0);
  485 }
  486 
  487 int
  488 rip_connect(struct inpcb *inp, struct mbuf *nam)
  489 {
  490         struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *);
  491 
  492         if (nam->m_len != sizeof(*addr))
  493                 return (EINVAL);
  494         if (TAILQ_FIRST(&ifnet) == 0)
  495                 return (EADDRNOTAVAIL);
  496         if (addr->sin_family != AF_INET &&
  497             addr->sin_family != AF_IMPLINK)
  498                 return (EAFNOSUPPORT);
  499         inp->inp_faddr = addr->sin_addr;
  500         return (0);
  501 }
  502 
  503 void
  504 rip_disconnect(struct inpcb *inp)
  505 {
  506 
  507         inp->inp_faddr = zeroin_addr;
  508 }
  509 
  510 u_long  rip_sendspace = RIPSNDQ;
  511 u_long  rip_recvspace = RIPRCVQ;
  512 
  513 /*ARGSUSED*/
  514 int
  515 rip_usrreq(struct socket *so, int req,
  516     struct mbuf *m, struct mbuf *nam, struct mbuf *control, struct lwp *l)
  517 {
  518         struct inpcb *inp;
  519         int s;
  520         int error = 0;
  521 #ifdef MROUTING
  522         extern struct socket *ip_mrouter;
  523 #endif
  524 
  525         if (req == PRU_CONTROL)
  526                 return (in_control(so, (long)m, (void *)nam,
  527                     (struct ifnet *)control, l));
  528 
  529         s = splsoftnet();
  530 
  531         if (req == PRU_PURGEIF) {
  532                 mutex_enter(softnet_lock);
  533                 in_pcbpurgeif0(&rawcbtable, (struct ifnet *)control);
  534                 in_purgeif((struct ifnet *)control);
  535                 in_pcbpurgeif(&rawcbtable, (struct ifnet *)control);
  536                 mutex_exit(softnet_lock);
  537                 splx(s);
  538                 return (0);
  539         }
  540 
  541         inp = sotoinpcb(so);
  542 #ifdef DIAGNOSTIC
  543         if (req != PRU_SEND && req != PRU_SENDOOB && control)
  544                 panic("rip_usrreq: unexpected control mbuf");
  545 #endif
  546         if (inp == 0 && req != PRU_ATTACH) {
  547                 error = EINVAL;
  548                 goto release;
  549         }
  550 
  551         switch (req) {
  552 
  553         case PRU_ATTACH:
  554                 sosetlock(so);
  555                 if (inp != 0) {
  556                         error = EISCONN;
  557                         break;
  558                 }
  559 
  560                 if (l == NULL) {
  561                         error = EACCES;
  562                         break;
  563                 }
  564 
  565                 /* XXX: raw socket permissions are checked in socreate() */
  566 
  567                 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  568                         error = soreserve(so, rip_sendspace, rip_recvspace);
  569                         if (error)
  570                                 break;
  571                 }
  572                 error = in_pcballoc(so, &rawcbtable);
  573                 if (error)
  574                         break;
  575                 inp = sotoinpcb(so);
  576                 inp->inp_ip.ip_p = (long)nam;
  577                 break;
  578 
  579         case PRU_DETACH:
  580 #ifdef MROUTING
  581                 if (so == ip_mrouter)
  582                         ip_mrouter_done();
  583 #endif
  584                 in_pcbdetach(inp);
  585                 break;
  586 
  587         case PRU_BIND:
  588                 error = rip_bind(inp, nam);
  589                 break;
  590 
  591         case PRU_LISTEN:
  592                 error = EOPNOTSUPP;
  593                 break;
  594 
  595         case PRU_CONNECT:
  596                 error = rip_connect(inp, nam);
  597                 if (error)
  598                         break;
  599                 soisconnected(so);
  600                 break;
  601 
  602         case PRU_CONNECT2:
  603                 error = EOPNOTSUPP;
  604                 break;
  605 
  606         case PRU_DISCONNECT:
  607                 soisdisconnected(so);
  608                 rip_disconnect(inp);
  609                 break;
  610 
  611         /*
  612          * Mark the connection as being incapable of further input.
  613          */
  614         case PRU_SHUTDOWN:
  615                 socantsendmore(so);
  616                 break;
  617 
  618         case PRU_RCVD:
  619                 error = EOPNOTSUPP;
  620                 break;
  621 
  622         /*
  623          * Ship a packet out.  The appropriate raw output
  624          * routine handles any massaging necessary.
  625          */
  626         case PRU_SEND:
  627                 if (control && control->m_len) {
  628                         m_freem(control);
  629                         m_freem(m);
  630                         error = EINVAL;
  631                         break;
  632                 }
  633         {
  634                 if (nam) {
  635                         if ((so->so_state & SS_ISCONNECTED) != 0) {
  636                                 error = EISCONN;
  637                                 goto die;
  638                         }
  639                         error = rip_connect(inp, nam);
  640                         if (error) {
  641                         die:
  642                                 m_freem(m);
  643                                 break;
  644                         }
  645                 } else {
  646                         if ((so->so_state & SS_ISCONNECTED) == 0) {
  647                                 error = ENOTCONN;
  648                                 goto die;
  649                         }
  650                 }
  651                 error = rip_output(m, inp);
  652                 if (nam)
  653                         rip_disconnect(inp);
  654         }
  655                 break;
  656 
  657         case PRU_SENSE:
  658                 /*
  659                  * stat: don't bother with a blocksize.
  660                  */
  661                 splx(s);
  662                 return (0);
  663 
  664         case PRU_RCVOOB:
  665                 error = EOPNOTSUPP;
  666                 break;
  667 
  668         case PRU_SENDOOB:
  669                 m_freem(control);
  670                 m_freem(m);
  671                 error = EOPNOTSUPP;
  672                 break;
  673 
  674         case PRU_SOCKADDR:
  675                 in_setsockaddr(inp, nam);
  676                 break;
  677 
  678         case PRU_PEERADDR:
  679                 in_setpeeraddr(inp, nam);
  680                 break;
  681 
  682         default:
  683                 panic("rip_usrreq");
  684         }
  685 
  686 release:
  687         splx(s);
  688         return (error);
  689 }
  690 
  691 SYSCTL_SETUP(sysctl_net_inet_raw_setup, "sysctl net.inet.raw subtree setup")
  692 {
  693 
  694         sysctl_createv(clog, 0, NULL, NULL,
  695                        CTLFLAG_PERMANENT,
  696                        CTLTYPE_NODE, "net", NULL,
  697                        NULL, 0, NULL, 0,
  698                        CTL_NET, CTL_EOL);
  699         sysctl_createv(clog, 0, NULL, NULL,
  700                        CTLFLAG_PERMANENT,
  701                        CTLTYPE_NODE, "inet", NULL,
  702                        NULL, 0, NULL, 0,
  703                        CTL_NET, PF_INET, CTL_EOL);
  704         sysctl_createv(clog, 0, NULL, NULL,
  705                        CTLFLAG_PERMANENT,
  706                        CTLTYPE_NODE, "raw",
  707                        SYSCTL_DESCR("Raw IPv4 settings"),
  708                        NULL, 0, NULL, 0,
  709                        CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL);
  710 
  711         sysctl_createv(clog, 0, NULL, NULL,
  712                        CTLFLAG_PERMANENT,
  713                        CTLTYPE_STRUCT, "pcblist",
  714                        SYSCTL_DESCR("Raw IPv4 control block list"),
  715                        sysctl_inpcblist, 0, &rawcbtable, 0,
  716                        CTL_NET, PF_INET, IPPROTO_RAW,
  717                        CTL_CREATE, CTL_EOL);
  718 }

Cache object: 05f7c265d4b0f9c2a7bc11c053e0e927


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