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/net/raw_usrreq.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 /*
    2  * Copyright (c) 1980, 1986, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)raw_usrreq.c        8.1 (Berkeley) 6/10/93
   30  * $FreeBSD: src/sys/net/raw_usrreq.c,v 1.18 1999/08/28 00:48:28 peter Exp $
   31  * $DragonFly: src/sys/net/raw_usrreq.c,v 1.14 2007/06/24 20:00:00 dillon Exp $
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/mbuf.h>
   37 #include <sys/proc.h>
   38 #include <sys/priv.h>
   39 #include <sys/protosw.h>
   40 #include <sys/socket.h>
   41 #include <sys/socketvar.h>
   42 
   43 #include <sys/socketvar2.h>
   44 #include <sys/msgport2.h>
   45 
   46 #include <net/raw_cb.h>
   47 
   48 
   49 static struct lwkt_token raw_token = LWKT_TOKEN_INITIALIZER(raw_token);
   50 
   51 /*
   52  * Initialize raw connection block q.
   53  */
   54 void
   55 raw_init(void)
   56 {
   57         LIST_INIT(&rawcb_list);
   58 }
   59 
   60 /************************************************************************
   61  *                       RAW PROTOCOL INTERFACE                         *
   62  ************************************************************************/
   63 
   64 /*
   65  * Raw protocol input routine.  Find the socket associated with the packet(s)
   66  * and move them over.  If nothing exists for this packet, drop it.  This
   67  * routine is indirect called via rts_input() and will be serialized on
   68  * cpu 0.
   69  *
   70  * Most other raw protocol interface functions are also serialized XXX.
   71  */
   72 void
   73 raw_input(struct mbuf *m0, const struct sockproto *proto,
   74           const struct sockaddr *src, const struct sockaddr *dst,
   75           const struct rawcb *skip)
   76 {
   77         struct rawcb *rp;
   78         struct mbuf *m = m0;
   79         struct socket *last;
   80 
   81         lwkt_gettoken(&raw_token);
   82 
   83         last = NULL;
   84         LIST_FOREACH(rp, &rawcb_list, list) {
   85                 if (rp == skip)
   86                         continue;
   87                 if (rp->rcb_proto.sp_family != proto->sp_family)
   88                         continue;
   89                 if (rp->rcb_proto.sp_protocol  &&
   90                     rp->rcb_proto.sp_protocol != proto->sp_protocol)
   91                         continue;
   92                 /*
   93                  * We assume the lower level routines have
   94                  * placed the address in a canonical format
   95                  * suitable for a structure comparison.
   96                  *
   97                  * Note that if the lengths are not the same
   98                  * the comparison will fail at the first byte.
   99                  */
  100                 if (rp->rcb_laddr && !sa_equal(rp->rcb_laddr, dst))
  101                         continue;
  102                 if (rp->rcb_faddr && !sa_equal(rp->rcb_faddr, src))
  103                         continue;
  104                 if (last) {
  105                         struct mbuf *n;
  106 
  107                         n = m_copypacket(m, MB_DONTWAIT);
  108                         if (n != NULL) {
  109                                 lwkt_gettoken(&last->so_rcv.ssb_token);
  110                                 if (ssb_appendaddr(&last->so_rcv, src, n,
  111                                                  NULL) == 0) {
  112                                         /* should notify about lost packet */
  113                                         m_freem(n);
  114                                 } else {
  115                                         sorwakeup(last);
  116                                 }
  117                                 lwkt_reltoken(&last->so_rcv.ssb_token);
  118                         }
  119                 }
  120                 last = rp->rcb_socket;
  121         }
  122         if (last) {
  123                 lwkt_gettoken(&last->so_rcv.ssb_token);
  124                 if (ssb_appendaddr(&last->so_rcv, src, m, NULL) == 0)
  125                         m_freem(m);
  126                 else
  127                         sorwakeup(last);
  128                 lwkt_reltoken(&last->so_rcv.ssb_token);
  129         } else {
  130                 m_freem(m);
  131         }
  132         lwkt_reltoken(&raw_token);
  133 }
  134 
  135 /*
  136  * nm_cmd, nm_arg, nm_extra
  137  */
  138 void
  139 raw_ctlinput(netmsg_t msg)
  140 {
  141         int error = 0;
  142 
  143         if (msg->ctlinput.nm_cmd < 0 || msg->ctlinput.nm_cmd > PRC_NCMDS)
  144                 ;
  145         lwkt_replymsg(&msg->lmsg, error);
  146 }
  147 
  148 /*
  149  * NOTE: (so) is referenced from soabort*() and netmsg_pru_abort()
  150  *       will sofree() it when we return.
  151  */
  152 static void
  153 raw_uabort(netmsg_t msg)
  154 {
  155         struct rawcb *rp = sotorawcb(msg->base.nm_so);
  156         int error;
  157 
  158         if (rp) {
  159                 raw_disconnect(rp);
  160                 soisdisconnected(msg->base.nm_so);
  161                 error = 0;
  162         } else {
  163                 error = EINVAL;
  164         }
  165         lwkt_replymsg(&msg->lmsg, error);
  166 }
  167 
  168 /* pru_accept is EOPNOTSUPP */
  169 
  170 static void
  171 raw_uattach(netmsg_t msg)
  172 {
  173         struct socket *so = msg->base.nm_so;
  174         int proto = msg->attach.nm_proto;
  175         struct pru_attach_info *ai = msg->attach.nm_ai;
  176         struct rawcb *rp;
  177         int error;
  178 
  179         rp = sotorawcb(so);
  180         if (rp) {
  181                 error = priv_check_cred(ai->p_ucred, PRIV_ROOT, NULL_CRED_OKAY);
  182                 if (error == 0)
  183                         error = raw_attach(so, proto, ai->sb_rlimit);
  184         } else {
  185                 error = EINVAL;
  186         }
  187         lwkt_replymsg(&msg->lmsg, error);
  188 }
  189 
  190 static void
  191 raw_ubind(netmsg_t msg)
  192 {
  193         lwkt_replymsg(&msg->lmsg, EINVAL);
  194 }
  195 
  196 static void
  197 raw_uconnect(netmsg_t msg)
  198 {
  199         lwkt_replymsg(&msg->lmsg, EINVAL);
  200 }
  201 
  202 /* pru_connect2 is EOPNOTSUPP */
  203 /* pru_control is EOPNOTSUPP */
  204 
  205 static void
  206 raw_udetach(netmsg_t msg)
  207 {
  208         struct rawcb *rp = sotorawcb(msg->base.nm_so);
  209         int error;
  210 
  211         if (rp) {
  212                 raw_detach(rp);
  213                 error = 0;
  214         } else {
  215                 error = EINVAL;
  216         }
  217         lwkt_replymsg(&msg->lmsg, error);
  218 }
  219 
  220 static void
  221 raw_udisconnect(netmsg_t msg)
  222 {
  223         struct socket *so = msg->base.nm_so;
  224         struct rawcb *rp;
  225         int error;
  226 
  227         rp = sotorawcb(so);
  228         if (rp == NULL) {
  229                 error = EINVAL;
  230         } else if (rp->rcb_faddr == NULL) {
  231                 error = ENOTCONN;
  232         } else {
  233                 soreference(so);
  234                 raw_disconnect(rp);
  235                 soisdisconnected(so);
  236                 sofree(so);
  237                 error = 0;
  238         }
  239         lwkt_replymsg(&msg->lmsg, error);
  240 }
  241 
  242 /* pru_listen is EOPNOTSUPP */
  243 
  244 static void
  245 raw_upeeraddr(netmsg_t msg)
  246 {
  247         struct rawcb *rp = sotorawcb(msg->base.nm_so);
  248         int error;
  249 
  250         if (rp == NULL) {
  251                 error = EINVAL;
  252         } else if (rp->rcb_faddr == NULL) {
  253                 error = ENOTCONN;
  254         } else {
  255                 *msg->peeraddr.nm_nam = dup_sockaddr(rp->rcb_faddr);
  256                 error = 0;
  257         }
  258         lwkt_replymsg(&msg->lmsg, error);
  259 }
  260 
  261 /* pru_rcvd is EOPNOTSUPP */
  262 /* pru_rcvoob is EOPNOTSUPP */
  263 
  264 static void
  265 raw_usend(netmsg_t msg)
  266 {
  267         struct socket *so = msg->base.nm_so;
  268         struct mbuf *m = msg->send.nm_m;
  269         struct mbuf *control = msg->send.nm_control;
  270         struct rawcb *rp = sotorawcb(so);
  271         struct pr_output_info oi;
  272         int flags = msg->send.nm_flags;
  273         int error;
  274 
  275         if (rp == NULL) {
  276                 error = EINVAL;
  277                 goto release;
  278         }
  279 
  280         if (flags & PRUS_OOB) {
  281                 error = EOPNOTSUPP;
  282                 goto release;
  283         }
  284 
  285         if (control && control->m_len) {
  286                 error = EOPNOTSUPP;
  287                 goto release;
  288         }
  289         if (msg->send.nm_addr) {
  290                 if (rp->rcb_faddr) {
  291                         error = EISCONN;
  292                         goto release;
  293                 }
  294                 rp->rcb_faddr = msg->send.nm_addr;
  295         } else if (rp->rcb_faddr == NULL) {
  296                 error = ENOTCONN;
  297                 goto release;
  298         }
  299         oi.p_pid = msg->send.nm_td->td_proc->p_pid;
  300         error = (*so->so_proto->pr_output)(m, so, &oi);
  301         m = NULL;
  302         if (msg->send.nm_addr)
  303                 rp->rcb_faddr = NULL;
  304 release:
  305         if (m != NULL)
  306                 m_freem(m);
  307         lwkt_replymsg(&msg->lmsg, error);
  308 }
  309 
  310 /* pru_sense is null */
  311 
  312 static void
  313 raw_ushutdown(netmsg_t msg)
  314 {
  315         struct rawcb *rp = sotorawcb(msg->base.nm_so);
  316         int error;
  317 
  318         if (rp) {
  319                 socantsendmore(msg->base.nm_so);
  320                 error = 0;
  321         } else {
  322                 error = EINVAL;
  323         }
  324         lwkt_replymsg(&msg->lmsg, error);
  325 }
  326 
  327 static void
  328 raw_usockaddr(netmsg_t msg)
  329 {
  330         struct rawcb *rp = sotorawcb(msg->base.nm_so);
  331         int error;
  332 
  333         if (rp == NULL) {
  334                 error = EINVAL;
  335         } else if (rp->rcb_laddr == NULL) {
  336                 error = EINVAL;
  337         } else {
  338                 *msg->sockaddr.nm_nam = dup_sockaddr(rp->rcb_laddr);
  339                 error = 0;
  340         }
  341         lwkt_replymsg(&msg->lmsg, error);
  342 }
  343 
  344 struct pr_usrreqs raw_usrreqs = {
  345         .pru_abort = raw_uabort,
  346         .pru_accept = pr_generic_notsupp,
  347         .pru_attach = raw_uattach,
  348         .pru_bind = raw_ubind,
  349         .pru_connect = raw_uconnect,
  350         .pru_connect2 = pr_generic_notsupp,
  351         .pru_control = pr_generic_notsupp,
  352         .pru_detach = raw_udetach, 
  353         .pru_disconnect = raw_udisconnect,
  354         .pru_listen = pr_generic_notsupp,
  355         .pru_peeraddr = raw_upeeraddr,
  356         .pru_rcvd = pr_generic_notsupp,
  357         .pru_rcvoob = pr_generic_notsupp,
  358         .pru_send = raw_usend,
  359         .pru_sense = pru_sense_null,
  360         .pru_shutdown = raw_ushutdown,
  361         .pru_sockaddr = raw_usockaddr,
  362         .pru_sosend = sosend,
  363         .pru_soreceive = soreceive
  364 };

Cache object: 33b2d1a3a513d219de87926a2a7514d3


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