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.184 2022/11/04 09:00:58 ozaki-r 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 /*
   64  * Raw interface to IP protocol.
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __KERNEL_RCSID(0, "$NetBSD: raw_ip.c,v 1.184 2022/11/04 09:00:58 ozaki-r Exp $");
   69 
   70 #ifdef _KERNEL_OPT
   71 #include "opt_inet.h"
   72 #include "opt_ipsec.h"
   73 #include "opt_mrouting.h"
   74 #include "opt_net_mpsafe.h"
   75 #endif
   76 
   77 #include <sys/param.h>
   78 #include <sys/sysctl.h>
   79 #include <sys/mbuf.h>
   80 #include <sys/socket.h>
   81 #include <sys/protosw.h>
   82 #include <sys/socketvar.h>
   83 #include <sys/errno.h>
   84 #include <sys/systm.h>
   85 #include <sys/proc.h>
   86 #include <sys/kauth.h>
   87 
   88 #include <net/if.h>
   89 
   90 #include <netinet/in.h>
   91 #include <netinet/in_systm.h>
   92 #include <netinet/ip.h>
   93 #include <netinet/ip_var.h>
   94 #include <netinet/ip_private.h>
   95 #include <netinet/ip_mroute.h>
   96 #include <netinet/ip_icmp.h>
   97 #include <netinet/in_pcb.h>
   98 #include <netinet/in_proto.h>
   99 #include <netinet/in_var.h>
  100 
  101 #ifdef IPSEC
  102 #include <netipsec/ipsec.h>
  103 #endif
  104 
  105 struct inpcbtable rawcbtable;
  106 
  107 int      rip_pcbnotify(struct inpcbtable *, struct in_addr,
  108     struct in_addr, int, int, void (*)(struct inpcb *, int));
  109 static int       rip_connect_pcb(struct inpcb *, struct sockaddr_in *);
  110 static void      rip_disconnect1(struct inpcb *);
  111 
  112 static void sysctl_net_inet_raw_setup(struct sysctllog **);
  113 
  114 /*
  115  * Nominal space allocated to a raw ip socket.
  116  */
  117 #define RIPSNDQ         8192
  118 #define RIPRCVQ         8192
  119 
  120 static u_long           rip_sendspace = RIPSNDQ;
  121 static u_long           rip_recvspace = RIPRCVQ;
  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         sysctl_net_inet_raw_setup(NULL);
  135         inpcb_init(&rawcbtable, 1, 1);
  136 }
  137 
  138 static void
  139 rip_sbappendaddr(struct inpcb *last, struct ip *ip, const struct sockaddr *sa,
  140     int hlen, struct mbuf *n)
  141 {
  142         struct mbuf *opts = NULL;
  143 
  144         if (last->inp_flags & INP_NOHEADER)
  145                 m_adj(n, hlen);
  146         if (last->inp_flags & INP_CONTROLOPTS ||
  147             SOOPT_TIMESTAMP(last->inp_socket->so_options))
  148                 ip_savecontrol(last, &opts, ip, n);
  149         if (sbappendaddr(&last->inp_socket->so_rcv, sa, n, opts) == 0) {
  150                 soroverflow(last->inp_socket);
  151                 m_freem(n);
  152                 if (opts)
  153                         m_freem(opts);
  154         } else {
  155                 sorwakeup(last->inp_socket);
  156         }
  157 }
  158 
  159 /*
  160  * Setup generic address and protocol structures
  161  * for raw_input routine, then pass them along with
  162  * mbuf chain.
  163  */
  164 void
  165 rip_input(struct mbuf *m, int off, int proto)
  166 {
  167         struct ip *ip = mtod(m, struct ip *);
  168         struct inpcb *inp;
  169         struct inpcb *last = NULL;
  170         struct mbuf *n;
  171         struct sockaddr_in ripsrc;
  172         int hlen;
  173 
  174         sockaddr_in_init(&ripsrc, &ip->ip_src, 0);
  175 
  176         /*
  177          * XXX Compatibility: programs using raw IP expect ip_len
  178          * XXX to have the header length subtracted, and in host order.
  179          * XXX ip_off is also expected to be host order.
  180          */
  181         hlen = ip->ip_hl << 2;
  182         ip->ip_len = ntohs(ip->ip_len) - hlen;
  183         NTOHS(ip->ip_off);
  184 
  185         TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
  186                 if (inp->inp_af != AF_INET)
  187                         continue;
  188                 if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
  189                         continue;
  190                 if (!in_nullhost(in4p_laddr(inp)) &&
  191                     !in_hosteq(in4p_laddr(inp), ip->ip_dst))
  192                         continue;
  193                 if (!in_nullhost(in4p_faddr(inp)) &&
  194                     !in_hosteq(in4p_faddr(inp), ip->ip_src))
  195                         continue;
  196 
  197                 if (last == NULL) {
  198                         ;
  199                 }
  200 #if defined(IPSEC)
  201                 else if (ipsec_used && ipsec_in_reject(m, last)) {
  202                         /* do not inject data into pcb */
  203                 }
  204 #endif
  205                 else if ((n = m_copypacket(m, M_DONTWAIT)) != NULL) {
  206                         rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, n);
  207                 }
  208 
  209                 last = inp;
  210         }
  211 
  212 #if defined(IPSEC)
  213         if (ipsec_used && last != NULL && ipsec_in_reject(m, last)) {
  214                 m_freem(m);
  215                 IP_STATDEC(IP_STAT_DELIVERED);
  216                 /* do not inject data into pcb */
  217         } else
  218 #endif
  219         if (last != NULL) {
  220                 rip_sbappendaddr(last, ip, sintosa(&ripsrc), hlen, m);
  221         } else if (inetsw[ip_protox[ip->ip_p]].pr_input == rip_input) {
  222                 uint64_t *ips;
  223 
  224                 icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL,
  225                     0, 0);
  226                 ips = IP_STAT_GETREF();
  227                 ips[IP_STAT_NOPROTO]++;
  228                 ips[IP_STAT_DELIVERED]--;
  229                 IP_STAT_PUTREF();
  230         } else {
  231                 m_freem(m);
  232         }
  233 
  234         return;
  235 }
  236 
  237 int
  238 rip_pcbnotify(struct inpcbtable *table,
  239     struct in_addr faddr, struct in_addr laddr, int proto, int errno,
  240     void (*notify)(struct inpcb *, int))
  241 {
  242         struct inpcb *inp;
  243         int nmatch;
  244 
  245         nmatch = 0;
  246         TAILQ_FOREACH(inp, &table->inpt_queue, inp_queue) {
  247                 if (inp->inp_af != AF_INET)
  248                         continue;
  249                 if (in4p_ip(inp).ip_p && in4p_ip(inp).ip_p != proto)
  250                         continue;
  251                 if (in_hosteq(in4p_faddr(inp), faddr) &&
  252                     in_hosteq(in4p_laddr(inp), laddr)) {
  253                         (*notify)(inp, errno);
  254                         nmatch++;
  255                 }
  256         }
  257 
  258         return nmatch;
  259 }
  260 
  261 void *
  262 rip_ctlinput(int cmd, const struct sockaddr *sa, void *v)
  263 {
  264         struct ip *ip = v;
  265         void (*notify)(struct inpcb *, int) = inpcb_rtchange;
  266         int errno;
  267 
  268         if (sa->sa_family != AF_INET ||
  269             sa->sa_len != sizeof(struct sockaddr_in))
  270                 return NULL;
  271         if ((unsigned)cmd >= PRC_NCMDS)
  272                 return NULL;
  273         errno = inetctlerrmap[cmd];
  274         if (PRC_IS_REDIRECT(cmd))
  275                 notify = inpcb_rtchange, ip = 0;
  276         else if (cmd == PRC_HOSTDEAD)
  277                 ip = 0;
  278         else if (errno == 0)
  279                 return NULL;
  280         if (ip) {
  281                 rip_pcbnotify(&rawcbtable, satocsin(sa)->sin_addr,
  282                     ip->ip_src, ip->ip_p, errno, notify);
  283 
  284                 /* XXX mapped address case */
  285         } else
  286                 inpcb_notifyall(&rawcbtable, satocsin(sa)->sin_addr, errno,
  287                     notify);
  288         return NULL;
  289 }
  290 
  291 /*
  292  * Generate IP header and pass packet to ip_output.
  293  * Tack on options user may have setup with control call.
  294  */
  295 int
  296 rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control,
  297     struct lwp *l)
  298 {
  299         struct ip *ip;
  300         struct mbuf *opts;
  301         struct ip_pktopts pktopts;
  302         kauth_cred_t cred;
  303         int error, flags;
  304 
  305         flags = (inp->inp_socket->so_options & SO_DONTROUTE) |
  306             IP_ALLOWBROADCAST | IP_RETURNMTU;
  307 
  308         if (l == NULL)
  309                 cred = NULL;
  310         else
  311                 cred = l->l_cred;
  312 
  313         /* Setup IP outgoing packet options */
  314         memset(&pktopts, 0, sizeof(pktopts));
  315         error = ip_setpktopts(control, &pktopts, &flags, inp, cred);
  316         if (control != NULL)
  317                 m_freem(control);
  318         if (error != 0)
  319                 goto release;
  320 
  321         /*
  322          * If the user handed us a complete IP packet, use it.
  323          * Otherwise, allocate an mbuf for a header and fill it in.
  324          */
  325         if ((inp->inp_flags & INP_HDRINCL) == 0) {
  326                 if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) {
  327                         error = EMSGSIZE;
  328                         goto release;
  329                 }
  330                 M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
  331                 if (!m) {
  332                         error = ENOBUFS;
  333                         goto release;
  334                 }
  335                 ip = mtod(m, struct ip *);
  336                 ip->ip_tos = 0;
  337                 ip->ip_off = htons(0);
  338                 ip->ip_p = in4p_ip(inp).ip_p;
  339                 ip->ip_len = htons(m->m_pkthdr.len);
  340                 ip->ip_src = pktopts.ippo_laddr.sin_addr;
  341                 ip->ip_dst = in4p_faddr(inp);
  342                 ip->ip_ttl = MAXTTL;
  343                 opts = inp->inp_options;
  344         } else {
  345                 if (m->m_pkthdr.len > IP_MAXPACKET) {
  346                         error = EMSGSIZE;
  347                         goto release;
  348                 }
  349                 if (m->m_pkthdr.len < sizeof(struct ip)) {
  350                         error = EINVAL;
  351                         goto release;
  352                 }
  353                 ip = mtod(m, struct ip *);
  354 
  355                 /*
  356                  * If the mbuf is read-only, we need to allocate
  357                  * a new mbuf for the header, since we need to
  358                  * modify the header.
  359                  */
  360                 if (M_READONLY(m)) {
  361                         int hlen = ip->ip_hl << 2;
  362 
  363                         m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3);
  364                         if (m == NULL) {
  365                                 error = ENOMEM;
  366                                 goto release;
  367                         }
  368                         ip = mtod(m, struct ip *);
  369                 }
  370 
  371                 /* XXX userland passes ip_len and ip_off in host order */
  372                 if (m->m_pkthdr.len != ip->ip_len) {
  373                         error = EINVAL;
  374                         goto release;
  375                 }
  376                 HTONS(ip->ip_len);
  377                 HTONS(ip->ip_off);
  378 
  379                 if (ip->ip_id != 0 || m->m_pkthdr.len < IP_MINFRAGSIZE)
  380                         flags |= IP_NOIPNEWID;
  381                 opts = NULL;
  382 
  383                 /* Prevent ip_output from overwriting header fields. */
  384                 flags |= IP_RAWOUTPUT;
  385 
  386                 IP_STATINC(IP_STAT_RAWOUT);
  387         }
  388 
  389         /*
  390          * IP output.  Note: if IP_RETURNMTU flag is set, the MTU size
  391          * will be stored in inp_errormtu.
  392          */
  393         return ip_output(m, opts, &inp->inp_route, flags, pktopts.ippo_imo,
  394             inp);
  395 
  396  release:
  397         if (m != NULL)
  398                 m_freem(m);
  399         return error;
  400 }
  401 
  402 /*
  403  * Raw IP socket option processing.
  404  */
  405 int
  406 rip_ctloutput(int op, struct socket *so, struct sockopt *sopt)
  407 {
  408         struct inpcb *inp = sotoinpcb(so);
  409         int error = 0;
  410         int optval;
  411 
  412         if (sopt->sopt_level == SOL_SOCKET && sopt->sopt_name == SO_NOHEADER) {
  413                 if (op == PRCO_GETOPT) {
  414                         optval = (inp->inp_flags & INP_NOHEADER) ? 1 : 0;
  415                         error = sockopt_set(sopt, &optval, sizeof(optval));
  416                 } else if (op == PRCO_SETOPT) {
  417                         error = sockopt_getint(sopt, &optval);
  418                         if (error)
  419                                 goto out;
  420                         if (optval) {
  421                                 inp->inp_flags &= ~INP_HDRINCL;
  422                                 inp->inp_flags |= INP_NOHEADER;
  423                         } else
  424                                 inp->inp_flags &= ~INP_NOHEADER;
  425                 }
  426                 goto out;
  427         } else if (sopt->sopt_level != IPPROTO_IP)
  428                 return ip_ctloutput(op, so, sopt);
  429 
  430         switch (op) {
  431 
  432         case PRCO_SETOPT:
  433                 switch (sopt->sopt_name) {
  434                 case IP_HDRINCL:
  435                         error = sockopt_getint(sopt, &optval);
  436                         if (error)
  437                                 break;
  438                         if (optval)
  439                                 inp->inp_flags |= INP_HDRINCL;
  440                         else
  441                                 inp->inp_flags &= ~INP_HDRINCL;
  442                         break;
  443 
  444 #ifdef MROUTING
  445                 case MRT_INIT:
  446                 case MRT_DONE:
  447                 case MRT_ADD_VIF:
  448                 case MRT_DEL_VIF:
  449                 case MRT_ADD_MFC:
  450                 case MRT_DEL_MFC:
  451                 case MRT_ASSERT:
  452                 case MRT_API_CONFIG:
  453                 case MRT_ADD_BW_UPCALL:
  454                 case MRT_DEL_BW_UPCALL:
  455                         error = ip_mrouter_set(so, sopt);
  456                         break;
  457 #endif
  458 
  459                 default:
  460                         error = ip_ctloutput(op, so, sopt);
  461                         break;
  462                 }
  463                 break;
  464 
  465         case PRCO_GETOPT:
  466                 switch (sopt->sopt_name) {
  467                 case IP_HDRINCL:
  468                         optval = inp->inp_flags & INP_HDRINCL;
  469                         error = sockopt_set(sopt, &optval, sizeof(optval));
  470                         break;
  471 
  472 #ifdef MROUTING
  473                 case MRT_VERSION:
  474                 case MRT_ASSERT:
  475                 case MRT_API_SUPPORT:
  476                 case MRT_API_CONFIG:
  477                         error = ip_mrouter_get(so, sopt);
  478                         break;
  479 #endif
  480 
  481                 default:
  482                         error = ip_ctloutput(op, so, sopt);
  483                         break;
  484                 }
  485                 break;
  486         }
  487  out:
  488         return error;
  489 }
  490 
  491 int
  492 rip_connect_pcb(struct inpcb *inp, struct sockaddr_in *addr)
  493 {
  494 
  495         if (IFNET_READER_EMPTY())
  496                 return (EADDRNOTAVAIL);
  497         if (addr->sin_family != AF_INET)
  498                 return (EAFNOSUPPORT);
  499         if (addr->sin_len != sizeof(*addr))
  500                 return EINVAL;
  501         in4p_faddr(inp) = addr->sin_addr;
  502         return (0);
  503 }
  504 
  505 static void
  506 rip_disconnect1(struct inpcb *inp)
  507 {
  508 
  509         in4p_faddr(inp) = zeroin_addr;
  510 }
  511 
  512 static int
  513 rip_attach(struct socket *so, int proto)
  514 {
  515         struct inpcb *inp;
  516         int error;
  517 
  518         KASSERT(sotoinpcb(so) == NULL);
  519         sosetlock(so);
  520 
  521         if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
  522                 error = soreserve(so, rip_sendspace, rip_recvspace);
  523                 if (error) {
  524                         return error;
  525                 }
  526         }
  527 
  528         error = inpcb_create(so, &rawcbtable);
  529         if (error) {
  530                 return error;
  531         }
  532         inp = sotoinpcb(so);
  533         in4p_ip(inp).ip_p = proto;
  534         KASSERT(solocked(so));
  535 
  536         return 0;
  537 }
  538 
  539 static void
  540 rip_detach(struct socket *so)
  541 {
  542         struct inpcb *inp;
  543 
  544         KASSERT(solocked(so));
  545         inp = sotoinpcb(so);
  546         KASSERT(inp != NULL);
  547 
  548 #ifdef MROUTING
  549         extern struct socket *ip_mrouter;
  550         if (so == ip_mrouter) {
  551                 ip_mrouter_done();
  552         }
  553 #endif
  554         inpcb_destroy(inp);
  555 }
  556 
  557 static int
  558 rip_accept(struct socket *so, struct sockaddr *nam)
  559 {
  560         KASSERT(solocked(so));
  561 
  562         panic("rip_accept");
  563 
  564         return EOPNOTSUPP;
  565 }
  566 
  567 static int
  568 rip_bind(struct socket *so, struct sockaddr *nam, struct lwp *l)
  569 {
  570         struct inpcb *inp = sotoinpcb(so);
  571         struct sockaddr_in *addr = (struct sockaddr_in *)nam;
  572         int error = 0;
  573         int s, ss;
  574         struct ifaddr *ifa;
  575 
  576         KASSERT(solocked(so));
  577         KASSERT(inp != NULL);
  578         KASSERT(nam != NULL);
  579 
  580         if (addr->sin_len != sizeof(*addr))
  581                 return EINVAL;
  582 
  583         s = splsoftnet();
  584         if (IFNET_READER_EMPTY()) {
  585                 error = EADDRNOTAVAIL;
  586                 goto release;
  587         }
  588         if (addr->sin_family != AF_INET) {
  589                 error = EAFNOSUPPORT;
  590                 goto release;
  591         }
  592         ss = pserialize_read_enter();
  593         if ((ifa = ifa_ifwithaddr(sintosa(addr))) == NULL &&
  594             (inp->inp_flags & INP_BINDANY) == 0 &&
  595             !in_nullhost(addr->sin_addr))
  596         {
  597                 pserialize_read_exit(ss);
  598                 error = EADDRNOTAVAIL;
  599                 goto release;
  600         }
  601         if (ifa && (ifatoia(ifa))->ia4_flags & IN6_IFF_DUPLICATED) {
  602                 pserialize_read_exit(ss);
  603                 error = EADDRNOTAVAIL;
  604                 goto release;
  605         }
  606         pserialize_read_exit(ss);
  607 
  608         in4p_laddr(inp) = addr->sin_addr;
  609 
  610 release:
  611         splx(s);
  612         return error;
  613 }
  614 
  615 static int
  616 rip_listen(struct socket *so, struct lwp *l)
  617 {
  618         KASSERT(solocked(so));
  619 
  620         return EOPNOTSUPP;
  621 }
  622 
  623 static int
  624 rip_connect(struct socket *so, struct sockaddr *nam, struct lwp *l)
  625 {
  626         struct inpcb *inp = sotoinpcb(so);
  627         int error = 0;
  628         int s;
  629 
  630         KASSERT(solocked(so));
  631         KASSERT(inp != NULL);
  632         KASSERT(nam != NULL);
  633 
  634         s = splsoftnet();
  635         error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
  636         if (! error)
  637                 soisconnected(so);
  638         splx(s);
  639 
  640         return error;
  641 }
  642 
  643 static int
  644 rip_connect2(struct socket *so, struct socket *so2)
  645 {
  646         KASSERT(solocked(so));
  647 
  648         return EOPNOTSUPP;
  649 }
  650 
  651 static int
  652 rip_disconnect(struct socket *so)
  653 {
  654         struct inpcb *inp = sotoinpcb(so);
  655         int s;
  656 
  657         KASSERT(solocked(so));
  658         KASSERT(inp != NULL);
  659 
  660         s = splsoftnet();
  661         soisdisconnected(so);
  662         rip_disconnect1(inp);
  663         splx(s);
  664 
  665         return 0;
  666 }
  667 
  668 static int
  669 rip_shutdown(struct socket *so)
  670 {
  671         int s;
  672 
  673         KASSERT(solocked(so));
  674 
  675         /*
  676          * Mark the connection as being incapable of further input.
  677          */
  678         s = splsoftnet();
  679         socantsendmore(so);
  680         splx(s);
  681 
  682         return 0;
  683 }
  684 
  685 static int
  686 rip_abort(struct socket *so)
  687 {
  688         KASSERT(solocked(so));
  689 
  690         panic("rip_abort");
  691 
  692         return EOPNOTSUPP;
  693 }
  694 
  695 static int
  696 rip_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp)
  697 {
  698         return in_control(so, cmd, nam, ifp);
  699 }
  700 
  701 static int
  702 rip_stat(struct socket *so, struct stat *ub)
  703 {
  704         KASSERT(solocked(so));
  705 
  706         /* stat: don't bother with a blocksize. */
  707         return 0;
  708 }
  709 
  710 static int
  711 rip_peeraddr(struct socket *so, struct sockaddr *nam)
  712 {
  713         int s;
  714 
  715         KASSERT(solocked(so));
  716         KASSERT(sotoinpcb(so) != NULL);
  717         KASSERT(nam != NULL);
  718 
  719         s = splsoftnet();
  720         inpcb_fetch_peeraddr(sotoinpcb(so), (struct sockaddr_in *)nam);
  721         splx(s);
  722 
  723         return 0;
  724 }
  725 
  726 static int
  727 rip_sockaddr(struct socket *so, struct sockaddr *nam)
  728 {
  729         int s;
  730 
  731         KASSERT(solocked(so));
  732         KASSERT(sotoinpcb(so) != NULL);
  733         KASSERT(nam != NULL);
  734 
  735         s = splsoftnet();
  736         inpcb_fetch_sockaddr(sotoinpcb(so), (struct sockaddr_in *)nam);
  737         splx(s);
  738 
  739         return 0;
  740 }
  741 
  742 static int
  743 rip_rcvd(struct socket *so, int flags, struct lwp *l)
  744 {
  745         KASSERT(solocked(so));
  746 
  747         return EOPNOTSUPP;
  748 }
  749 
  750 static int
  751 rip_recvoob(struct socket *so, struct mbuf *m, int flags)
  752 {
  753         KASSERT(solocked(so));
  754 
  755         return EOPNOTSUPP;
  756 }
  757 
  758 static int
  759 rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam,
  760     struct mbuf *control, struct lwp *l)
  761 {
  762         struct inpcb *inp = sotoinpcb(so);
  763         int error = 0;
  764         int s;
  765 
  766         KASSERT(solocked(so));
  767         KASSERT(inp != NULL);
  768         KASSERT(m != NULL);
  769 
  770         /*
  771          * Ship a packet out.  The appropriate raw output
  772          * routine handles any massaging necessary.
  773          */
  774         s = splsoftnet();
  775         if (nam) {
  776                 if ((so->so_state & SS_ISCONNECTED) != 0) {
  777                         error = EISCONN;
  778                         goto die;
  779                 }
  780                 error = rip_connect_pcb(inp, (struct sockaddr_in *)nam);
  781                 if (error)
  782                         goto die;
  783         } else {
  784                 if ((so->so_state & SS_ISCONNECTED) == 0) {
  785                         error = ENOTCONN;
  786                         goto die;
  787                 }
  788         }
  789         error = rip_output(m, inp, control, l);
  790         m = NULL;
  791         control = NULL;
  792         if (nam)
  793                 rip_disconnect1(inp);
  794  die:
  795         if (m != NULL)
  796                 m_freem(m);
  797         if (control != NULL)
  798                 m_freem(control);
  799 
  800         splx(s);
  801         return error;
  802 }
  803 
  804 static int
  805 rip_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control)
  806 {
  807         KASSERT(solocked(so));
  808 
  809         m_freem(m);
  810         m_freem(control);
  811 
  812         return EOPNOTSUPP;
  813 }
  814 
  815 static int
  816 rip_purgeif(struct socket *so, struct ifnet *ifp)
  817 {
  818         int s;
  819 
  820         s = splsoftnet();
  821         mutex_enter(softnet_lock);
  822         inpcb_purgeif0(&rawcbtable, ifp);
  823 #ifdef NET_MPSAFE
  824         mutex_exit(softnet_lock);
  825 #endif
  826         in_purgeif(ifp);
  827 #ifdef NET_MPSAFE
  828         mutex_enter(softnet_lock);
  829 #endif
  830         inpcb_purgeif(&rawcbtable, ifp);
  831         mutex_exit(softnet_lock);
  832         splx(s);
  833 
  834         return 0;
  835 }
  836 
  837 PR_WRAP_USRREQS(rip)
  838 #define rip_attach      rip_attach_wrapper
  839 #define rip_detach      rip_detach_wrapper
  840 #define rip_accept      rip_accept_wrapper
  841 #define rip_bind        rip_bind_wrapper
  842 #define rip_listen      rip_listen_wrapper
  843 #define rip_connect     rip_connect_wrapper
  844 #define rip_connect2    rip_connect2_wrapper
  845 #define rip_disconnect  rip_disconnect_wrapper
  846 #define rip_shutdown    rip_shutdown_wrapper
  847 #define rip_abort       rip_abort_wrapper
  848 #define rip_ioctl       rip_ioctl_wrapper
  849 #define rip_stat        rip_stat_wrapper
  850 #define rip_peeraddr    rip_peeraddr_wrapper
  851 #define rip_sockaddr    rip_sockaddr_wrapper
  852 #define rip_rcvd        rip_rcvd_wrapper
  853 #define rip_recvoob     rip_recvoob_wrapper
  854 #define rip_send        rip_send_wrapper
  855 #define rip_sendoob     rip_sendoob_wrapper
  856 #define rip_purgeif     rip_purgeif_wrapper
  857 
  858 const struct pr_usrreqs rip_usrreqs = {
  859         .pr_attach      = rip_attach,
  860         .pr_detach      = rip_detach,
  861         .pr_accept      = rip_accept,
  862         .pr_bind        = rip_bind,
  863         .pr_listen      = rip_listen,
  864         .pr_connect     = rip_connect,
  865         .pr_connect2    = rip_connect2,
  866         .pr_disconnect  = rip_disconnect,
  867         .pr_shutdown    = rip_shutdown,
  868         .pr_abort       = rip_abort,
  869         .pr_ioctl       = rip_ioctl,
  870         .pr_stat        = rip_stat,
  871         .pr_peeraddr    = rip_peeraddr,
  872         .pr_sockaddr    = rip_sockaddr,
  873         .pr_rcvd        = rip_rcvd,
  874         .pr_recvoob     = rip_recvoob,
  875         .pr_send        = rip_send,
  876         .pr_sendoob     = rip_sendoob,
  877         .pr_purgeif     = rip_purgeif,
  878 };
  879 
  880 static void
  881 sysctl_net_inet_raw_setup(struct sysctllog **clog)
  882 {
  883 
  884         sysctl_createv(clog, 0, NULL, NULL,
  885                        CTLFLAG_PERMANENT,
  886                        CTLTYPE_NODE, "inet", NULL,
  887                        NULL, 0, NULL, 0,
  888                        CTL_NET, PF_INET, CTL_EOL);
  889         sysctl_createv(clog, 0, NULL, NULL,
  890                        CTLFLAG_PERMANENT,
  891                        CTLTYPE_NODE, "raw",
  892                        SYSCTL_DESCR("Raw IPv4 settings"),
  893                        NULL, 0, NULL, 0,
  894                        CTL_NET, PF_INET, IPPROTO_RAW, CTL_EOL);
  895 
  896         sysctl_createv(clog, 0, NULL, NULL,
  897                        CTLFLAG_PERMANENT,
  898                        CTLTYPE_STRUCT, "pcblist",
  899                        SYSCTL_DESCR("Raw IPv4 control block list"),
  900                        sysctl_inpcblist, 0, &rawcbtable, 0,
  901                        CTL_NET, PF_INET, IPPROTO_RAW,
  902                        CTL_CREATE, CTL_EOL);
  903 }

Cache object: 1d5f5c6de7cbdc907681776f0efbc86f


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