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/netgraph/ng_socket.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 
    2 /*
    3  * ng_socket.c
    4  *
    5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
    6  * All rights reserved.
    7  * 
    8  * Subject to the following obligations and disclaimer of warranty, use and
    9  * redistribution of this software, in source or object code forms, with or
   10  * without modifications are expressly permitted by Whistle Communications;
   11  * provided, however, that:
   12  * 1. Any and all reproductions of the source or object code must include the
   13  *    copyright notice above and the following disclaimer of warranties; and
   14  * 2. No rights are granted, in any manner or form, to use Whistle
   15  *    Communications, Inc. trademarks, including the mark "WHISTLE
   16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
   17  *    such appears in the above copyright notice or in the software.
   18  * 
   19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
   20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
   21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
   22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
   23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
   24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
   25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
   26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
   27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
   28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
   29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
   30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
   31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
   32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
   35  * OF SUCH DAMAGE.
   36  *
   37  * Author: Julian Elischer <julian@freebsd.org>
   38  *
   39  * $FreeBSD: stable/4/sys/netgraph/ng_socket.c 126159 2004-02-23 10:17:33Z ru $
   40  * $Whistle: ng_socket.c,v 1.28 1999/11/01 09:24:52 julian Exp $
   41  */
   42 
   43 /*
   44  * Netgraph socket nodes
   45  *
   46  * There are two types of netgraph sockets, control and data.
   47  * Control sockets have a netgraph node, but data sockets are
   48  * parasitic on control sockets, and have no node of their own.
   49  */
   50 
   51 #include <sys/param.h>
   52 #include <sys/systm.h>
   53 #include <sys/proc.h>
   54 #include <sys/domain.h>
   55 #include <sys/errno.h>
   56 #include <sys/kernel.h>
   57 #include <sys/filedesc.h>
   58 #include <sys/malloc.h>
   59 #include <sys/queue.h>
   60 #include <sys/mbuf.h>
   61 #include <sys/protosw.h>
   62 #include <sys/socket.h>
   63 #include <sys/socketvar.h>
   64 #include <sys/sysctl.h>
   65 #ifdef NOTYET
   66 #include <sys/vnode.h>
   67 #endif
   68 #include <netgraph/ng_message.h>
   69 #include <netgraph/netgraph.h>
   70 #include <netgraph/ng_socketvar.h>
   71 #include <netgraph/ng_socket.h>
   72 
   73 /*
   74  * It's Ascii-art time!
   75  *   +-------------+   +-------------+
   76  *   |socket  (ctl)|   |socket (data)|
   77  *   +-------------+   +-------------+
   78  *          ^                 ^
   79  *          |                 |
   80  *          v                 v
   81  *    +-----------+     +-----------+
   82  *    |pcb   (ctl)|     |pcb  (data)|
   83  *    +-----------+     +-----------+
   84  *          ^                 ^
   85  *          |                 |
   86  *          v                 v
   87  *      +--------------------------+
   88  *      |   Socket type private    |
   89  *      |       data               |
   90  *      +--------------------------+
   91  *                   ^
   92  *                   |
   93  *                   v
   94  *           +----------------+
   95  *           | struct ng_node |
   96  *           +----------------+
   97  */
   98 
   99 /* Netgraph node methods */
  100 static ng_constructor_t ngs_constructor;
  101 static ng_rcvmsg_t      ngs_rcvmsg;
  102 static ng_shutdown_t    ngs_rmnode;
  103 static ng_newhook_t     ngs_newhook;
  104 static ng_rcvdata_t     ngs_rcvdata;
  105 static ng_disconnect_t  ngs_disconnect;
  106 
  107 /* Internal methods */
  108 static int      ng_attach_data(struct socket *so);
  109 static int      ng_attach_cntl(struct socket *so);
  110 static int      ng_attach_common(struct socket *so, int type);
  111 static void     ng_detach_common(struct ngpcb *pcbp, int type);
  112 /*static int    ng_internalize(struct mbuf *m, struct proc *p); */
  113 
  114 static int      ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp);
  115 static int      ng_connect_cntl(struct sockaddr *nam, struct ngpcb *pcbp);
  116 static int      ng_bind(struct sockaddr *nam, struct ngpcb *pcbp);
  117 
  118 static int      ngs_mod_event(module_t mod, int event, void *data);
  119 static int      ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg,
  120                         struct sockaddr_ng *addr);
  121 
  122 /* Netgraph type descriptor */
  123 static struct ng_type typestruct = {
  124         NG_VERSION,
  125         NG_SOCKET_NODE_TYPE,
  126         ngs_mod_event,
  127         ngs_constructor,
  128         ngs_rcvmsg,
  129         ngs_rmnode,
  130         ngs_newhook,
  131         NULL,
  132         NULL,
  133         ngs_rcvdata,
  134         ngs_rcvdata,
  135         ngs_disconnect,
  136         NULL
  137 };
  138 NETGRAPH_INIT(socket, &typestruct);
  139 
  140 /* Buffer space */
  141 static u_long ngpdg_sendspace = 20 * 1024;      /* really max datagram size */
  142 SYSCTL_INT(_net_graph, OID_AUTO, maxdgram, CTLFLAG_RW,
  143     &ngpdg_sendspace , 0, "Maximum outgoing Netgraph datagram size");
  144 static u_long ngpdg_recvspace = 20 * 1024;
  145 SYSCTL_INT(_net_graph, OID_AUTO, recvspace, CTLFLAG_RW,
  146     &ngpdg_recvspace , 0, "Maximum space for incoming Netgraph datagrams");
  147 
  148 /* List of all sockets */
  149 LIST_HEAD(, ngpcb) ngsocklist;
  150 
  151 #define sotongpcb(so) ((struct ngpcb *)(so)->so_pcb)
  152 
  153 /* If getting unexplained errors returned, set this to "Debugger("X"); */
  154 #ifndef TRAP_ERROR
  155 #define TRAP_ERROR
  156 #endif
  157 
  158 /***************************************************************
  159         Control sockets
  160 ***************************************************************/
  161 
  162 static int
  163 ngc_attach(struct socket *so, int proto, struct proc *p)
  164 {
  165         struct ngpcb *const pcbp = sotongpcb(so);
  166 
  167         if (suser(p))
  168                 return (EPERM);
  169         if (pcbp != NULL)
  170                 return (EISCONN);
  171         return (ng_attach_cntl(so));
  172 }
  173 
  174 static int
  175 ngc_detach(struct socket *so)
  176 {
  177         struct ngpcb *const pcbp = sotongpcb(so);
  178 
  179         if (pcbp == NULL)
  180                 return (EINVAL);
  181         ng_detach_common(pcbp, NG_CONTROL);
  182         return (0);
  183 }
  184 
  185 static int
  186 ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
  187          struct mbuf *control, struct proc *p)
  188 {
  189         struct ngpcb *const pcbp = sotongpcb(so);
  190         struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
  191         struct ng_mesg *resp;
  192         struct mbuf *m0;
  193         char *msg, *path = NULL;
  194         int len, error = 0;
  195 
  196         if (pcbp == NULL) {
  197                 error = EINVAL;
  198                 goto release;
  199         }
  200 #ifdef  NOTYET
  201         if (control && (error = ng_internalize(control, p))) {
  202                 if (pcbp->sockdata == NULL) {
  203                         error = ENOTCONN;
  204                         goto release;
  205                 }
  206         }
  207 #else   /* NOTYET */
  208         if (control) {
  209                 error = EINVAL;
  210                 goto release;
  211         }
  212 #endif  /* NOTYET */
  213 
  214         /* Require destination as there may be >= 1 hooks on this node */
  215         if (addr == NULL) {
  216                 error = EDESTADDRREQ;
  217                 goto release;
  218         }
  219 
  220         /* Allocate an expendable buffer for the path, chop off
  221          * the sockaddr header, and make sure it's NUL terminated */
  222         len = sap->sg_len - 2;
  223         MALLOC(path, char *, len + 1, M_NETGRAPH, M_WAITOK);
  224         if (path == NULL) {
  225                 error = ENOMEM;
  226                 goto release;
  227         }
  228         bcopy(sap->sg_data, path, len);
  229         path[len] = '\0';
  230 
  231         /* Move the actual message out of mbufs into a linear buffer.
  232          * Start by adding up the size of the data. (could use mh_len?) */
  233         for (len = 0, m0 = m; m0 != NULL; m0 = m0->m_next)
  234                 len += m0->m_len;
  235 
  236         /* Move the data into a linear buffer as well. Messages are not
  237          * delivered in mbufs. */
  238         MALLOC(msg, char *, len + 1, M_NETGRAPH, M_WAITOK);
  239         if (msg == NULL) {
  240                 error = ENOMEM;
  241                 goto release;
  242         }
  243         m_copydata(m, 0, len, msg);
  244 
  245         /* The callee will free the msg when done. The addr is our business. */
  246         error = ng_send_msg(pcbp->sockdata->node,
  247                             (struct ng_mesg *) msg, path, &resp);
  248 
  249         /* If the callee responded with a synchronous response, then put it
  250          * back on the receive side of the socket; sap is source address. */
  251         if (error == 0 && resp != NULL)
  252                 error = ship_msg(pcbp, resp, sap);
  253 
  254 release:
  255         if (path != NULL)
  256                 FREE(path, M_NETGRAPH);
  257         if (control != NULL)
  258                 m_freem(control);
  259         if (m != NULL)
  260                 m_freem(m);
  261         return (error);
  262 }
  263 
  264 static int
  265 ngc_bind(struct socket *so, struct sockaddr *nam, struct proc *p)
  266 {
  267         struct ngpcb *const pcbp = sotongpcb(so);
  268 
  269         if (pcbp == 0)
  270                 return (EINVAL);
  271         return (ng_bind(nam, pcbp));
  272 }
  273 
  274 static int
  275 ngc_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
  276 {
  277         struct ngpcb *const pcbp = sotongpcb(so);
  278 
  279         if (pcbp == 0)
  280                 return (EINVAL);
  281         return (ng_connect_cntl(nam, pcbp));
  282 }
  283 
  284 /***************************************************************
  285         Data sockets
  286 ***************************************************************/
  287 
  288 static int
  289 ngd_attach(struct socket *so, int proto, struct proc *p)
  290 {
  291         struct ngpcb *const pcbp = sotongpcb(so);
  292 
  293         if (pcbp != NULL)
  294                 return (EISCONN);
  295         return (ng_attach_data(so));
  296 }
  297 
  298 static int
  299 ngd_detach(struct socket *so)
  300 {
  301         struct ngpcb *const pcbp = sotongpcb(so);
  302 
  303         if (pcbp == NULL)
  304                 return (EINVAL);
  305         ng_detach_common(pcbp, NG_DATA);
  306         return (0);
  307 }
  308 
  309 static int
  310 ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
  311          struct mbuf *control, struct proc *p)
  312 {
  313         struct ngpcb *const pcbp = sotongpcb(so);
  314         struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
  315         meta_p  mp = NULL;
  316         int     len, error;
  317         hook_p  hook = NULL;
  318         char    hookname[NG_HOOKLEN + 1];
  319 
  320         if ((pcbp == NULL) || (control != NULL)) {
  321                 error = EINVAL;
  322                 goto release;
  323         }
  324         if (pcbp->sockdata == NULL) {
  325                 error = ENOTCONN;
  326                 goto release;
  327         }
  328         /*
  329          * If the user used any of these ways to not specify an address
  330          * then handle specially.
  331          */
  332         if ((sap == NULL)
  333             || ((len = sap->sg_len - 2) <= 0)
  334             || (*sap->sg_data == '\0')) {
  335                 if (pcbp->sockdata->node->numhooks != 1) {
  336                         error = EDESTADDRREQ;
  337                         goto release;
  338                 }
  339                 /*
  340                  * if exactly one hook exists, just use it.
  341                  * Special case to allow write(2) to work on an ng_socket.
  342                  */
  343                 hook = LIST_FIRST(&pcbp->sockdata->node->hooks);
  344         } else {
  345                 if (len > NG_HOOKLEN) {
  346                         error = EINVAL;
  347                         goto release;
  348                 }
  349 
  350                 /*
  351                  * chop off the sockaddr header, and make sure it's NUL
  352                  * terminated
  353                  */
  354                 bcopy(sap->sg_data, hookname, len);
  355                 hookname[len] = '\0';
  356 
  357                 /* Find the correct hook from 'hookname' */
  358                 LIST_FOREACH(hook, &pcbp->sockdata->node->hooks, hooks) {
  359                         if (strcmp(hookname, hook->name) == 0)
  360                                 break;
  361                 }
  362                 if (hook == NULL)
  363                         error = EHOSTUNREACH;
  364         }
  365 
  366         /* Send data (OK if hook is NULL) */
  367         NG_SEND_DATA(error, hook, m, mp);       /* makes m NULL */
  368 
  369 release:
  370         if (control != NULL)
  371                 m_freem(control);
  372         if (m != NULL)
  373                 m_freem(m);
  374         return (error);
  375 }
  376 
  377 static int
  378 ngd_connect(struct socket *so, struct sockaddr *nam, struct proc *p)
  379 {
  380         struct ngpcb *const pcbp = sotongpcb(so);
  381 
  382         if (pcbp == 0)
  383                 return (EINVAL);
  384         return (ng_connect_data(nam, pcbp));
  385 }
  386 
  387 /*
  388  * Used for both data and control sockets
  389  */
  390 static int
  391 ng_setsockaddr(struct socket *so, struct sockaddr **addr)
  392 {
  393         struct ngpcb *pcbp;
  394         struct sockaddr_ng *sg;
  395         int sg_len, namelen, s;
  396 
  397         /* Why isn't sg_data a `char[1]' ? :-( */
  398         sg_len = sizeof(struct sockaddr_ng) - sizeof(sg->sg_data) + 1;
  399 
  400         s = splnet();
  401         pcbp = sotongpcb(so);
  402         if ((pcbp == 0) || (pcbp->sockdata == NULL)) {
  403                 splx(s);
  404                 return (EINVAL);
  405         }
  406 
  407         namelen = 0;            /* silence compiler ! */
  408 
  409         if (pcbp->sockdata->node->name != NULL)
  410                 sg_len += namelen = strlen(pcbp->sockdata->node->name);
  411 
  412         MALLOC(sg, struct sockaddr_ng *, sg_len, M_SONAME, M_WAITOK);
  413         bzero(sg, sg_len);
  414 
  415         if (pcbp->sockdata->node->name != NULL)
  416                 bcopy(pcbp->sockdata->node->name, sg->sg_data, namelen);
  417         splx(s);
  418 
  419         sg->sg_len = sg_len;
  420         sg->sg_family = AF_NETGRAPH;
  421         *addr = (struct sockaddr *)sg;
  422 
  423         return (0);
  424 }
  425 
  426 /*
  427  * Attach a socket to it's protocol specific partner.
  428  * For a control socket, actually create a netgraph node and attach
  429  * to it as well.
  430  */
  431 
  432 static int
  433 ng_attach_cntl(struct socket *so)
  434 {
  435         struct ngsock *privdata;
  436         struct ngpcb *pcbp;
  437         int error;
  438 
  439         /* Setup protocol control block */
  440         if ((error = ng_attach_common(so, NG_CONTROL)) != 0)
  441                 return (error);
  442         pcbp = sotongpcb(so);
  443 
  444         /* Allocate node private info */
  445         MALLOC(privdata, struct ngsock *,
  446             sizeof(*privdata), M_NETGRAPH, M_WAITOK);
  447         if (privdata == NULL) {
  448                 ng_detach_common(pcbp, NG_CONTROL);
  449                 return (ENOMEM);
  450         }
  451         bzero(privdata, sizeof(*privdata));
  452 
  453         /* Make the generic node components */
  454         if ((error = ng_make_node_common(&typestruct, &privdata->node)) != 0) {
  455                 FREE(privdata, M_NETGRAPH);
  456                 ng_detach_common(pcbp, NG_CONTROL);
  457                 return (error);
  458         }
  459         privdata->node->private = privdata;
  460 
  461         /* Link the pcb and the node private data */
  462         privdata->ctlsock = pcbp;
  463         pcbp->sockdata = privdata;
  464         privdata->refs++;
  465         return (0);
  466 }
  467 
  468 static int
  469 ng_attach_data(struct socket *so)
  470 {
  471         return(ng_attach_common(so, NG_DATA));
  472 }
  473 
  474 /*
  475  * Set up a socket protocol control block.
  476  * This code is shared between control and data sockets.
  477  */
  478 static int
  479 ng_attach_common(struct socket *so, int type)
  480 {
  481         struct ngpcb *pcbp;
  482         int error;
  483 
  484         /* Standard socket setup stuff */
  485         error = soreserve(so, ngpdg_sendspace, ngpdg_recvspace);
  486         if (error)
  487                 return (error);
  488 
  489         /* Allocate the pcb */
  490         MALLOC(pcbp, struct ngpcb *, sizeof(*pcbp), M_PCB, M_WAITOK);
  491         if (pcbp == NULL)
  492                 return (ENOMEM);
  493         bzero(pcbp, sizeof(*pcbp));
  494         pcbp->type = type;
  495 
  496         /* Link the pcb and the socket */
  497         so->so_pcb = (caddr_t) pcbp;
  498         pcbp->ng_socket = so;
  499 
  500         /* Add the socket to linked list */
  501         LIST_INSERT_HEAD(&ngsocklist, pcbp, socks);
  502         return (0);
  503 }
  504 
  505 /*
  506  * Disassociate the socket from it's protocol specific
  507  * partner. If it's attached to a node's private data structure,
  508  * then unlink from that too. If we were the last socket attached to it,
  509  * then shut down the entire node. Shared code for control and data sockets.
  510  */
  511 static void
  512 ng_detach_common(struct ngpcb *pcbp, int which)
  513 {
  514         struct ngsock *sockdata;
  515 
  516         if (pcbp->sockdata) {
  517                 sockdata = pcbp->sockdata;
  518                 pcbp->sockdata = NULL;
  519                 switch (which) {
  520                 case NG_CONTROL:
  521                         sockdata->ctlsock = NULL;
  522                         break;
  523                 case NG_DATA:
  524                         sockdata->datasock = NULL;
  525                         break;
  526                 default:
  527                         panic(__FUNCTION__);
  528                 }
  529                 if ((--sockdata->refs == 0) && (sockdata->node != NULL))
  530                         ng_rmnode(sockdata->node);
  531         }
  532         pcbp->ng_socket->so_pcb = NULL;
  533         pcbp->ng_socket = NULL;
  534         LIST_REMOVE(pcbp, socks);
  535         FREE(pcbp, M_PCB);
  536 }
  537 
  538 #ifdef NOTYET
  539 /*
  540  * File descriptors can be passed into a AF_NETGRAPH socket.
  541  * Note, that file descriptors cannot be passed OUT.
  542  * Only character device descriptors are accepted.
  543  * Character devices are useful to connect a graph to a device,
  544  * which after all is the purpose of this whole system.
  545  */
  546 static int
  547 ng_internalize(struct mbuf *control, struct proc *p)
  548 {
  549         struct filedesc *fdp = p->p_fd;
  550         const struct cmsghdr *cm = mtod(control, const struct cmsghdr *);
  551         struct file *fp;
  552         struct vnode *vn;
  553         int oldfds;
  554         int fd;
  555 
  556         if (cm->cmsg_type != SCM_RIGHTS || cm->cmsg_level != SOL_SOCKET ||
  557             cm->cmsg_len != control->m_len) {
  558                 TRAP_ERROR;
  559                 return (EINVAL);
  560         }
  561 
  562         /* Check there is only one FD. XXX what would more than one signify? */
  563         oldfds = (cm->cmsg_len - sizeof(*cm)) / sizeof(int);
  564         if (oldfds != 1) {
  565                 TRAP_ERROR;
  566                 return (EINVAL);
  567         }
  568 
  569         /* Check that the FD given is legit. and change it to a pointer to a
  570          * struct file. */
  571         fd = *(int *) (cm + 1);
  572         if ((unsigned) fd >= fdp->fd_nfiles
  573             || (fp = fdp->fd_ofiles[fd]) == NULL) {
  574                 return (EBADF);
  575         }
  576 
  577         /* Depending on what kind of resource it is, act differently. For
  578          * devices, we treat it as a file. For a AF_NETGRAPH socket,
  579          * shortcut straight to the node. */
  580         switch (fp->f_type) {
  581         case DTYPE_VNODE:
  582                 vn = (struct vnode *) fp->f_data;
  583                 if (vn && (vn->v_type == VCHR)) {
  584                         /* for a VCHR, actually reference the FILE */
  585                         fp->f_count++;
  586                         /* XXX then what :) */
  587                         /* how to pass on to other modules? */
  588                 } else {
  589                         TRAP_ERROR;
  590                         return (EINVAL);
  591                 }
  592                 break;
  593         default:
  594                 TRAP_ERROR;
  595                 return (EINVAL);
  596         }
  597         return (0);
  598 }
  599 #endif  /* NOTYET */
  600 
  601 /*
  602  * Connect the data socket to a named control socket node.
  603  */
  604 static int
  605 ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
  606 {
  607         struct sockaddr_ng *sap;
  608         node_p farnode;
  609         struct ngsock *sockdata;
  610         int error;
  611 
  612         /* If we are already connected, don't do it again */
  613         if (pcbp->sockdata != NULL)
  614                 return (EISCONN);
  615 
  616         /* Find the target (victim) and check it doesn't already have a data
  617          * socket. Also check it is a 'socket' type node. */
  618         sap = (struct sockaddr_ng *) nam;
  619         if ((error = ng_path2node(NULL, sap->sg_data, &farnode, NULL)))
  620                 return (error);
  621 
  622         if (strcmp(farnode->type->name, NG_SOCKET_NODE_TYPE) != 0)
  623                 return (EINVAL);
  624         sockdata = farnode->private;
  625         if (sockdata->datasock != NULL)
  626                 return (EADDRINUSE);
  627 
  628         /* Link the PCB and the private data struct. and note the extra
  629          * reference */
  630         sockdata->datasock = pcbp;
  631         pcbp->sockdata = sockdata;
  632         sockdata->refs++;
  633         return (0);
  634 }
  635 
  636 /*
  637  * Connect the existing control socket node to a named node:hook.
  638  * The hook we use on this end is the same name as the remote node name.
  639  */
  640 static int
  641 ng_connect_cntl(struct sockaddr *nam, struct ngpcb *pcbp)
  642 {
  643         struct ngsock *const sockdata = pcbp->sockdata;
  644         struct sockaddr_ng *sap;
  645         char *node, *hook;
  646         node_p farnode;
  647         int rtn, error;
  648 
  649         sap = (struct sockaddr_ng *) nam;
  650         rtn = ng_path_parse(sap->sg_data, &node, NULL, &hook);
  651         if (rtn < 0 || node == NULL || hook == NULL) {
  652                 TRAP_ERROR;
  653                 return (EINVAL);
  654         }
  655         farnode = ng_findname(sockdata->node, node);
  656         if (farnode == NULL) {
  657                 TRAP_ERROR;
  658                 return (EADDRNOTAVAIL);
  659         }
  660 
  661         /* Connect, using a hook name the same as the far node name. */
  662         error = ng_con_nodes(sockdata->node, node, farnode, hook);
  663         return error;
  664 }
  665 
  666 /*
  667  * Binding a socket means giving the corresponding node a name
  668  */
  669 static int
  670 ng_bind(struct sockaddr *nam, struct ngpcb *pcbp)
  671 {
  672         struct ngsock *const sockdata = pcbp->sockdata;
  673         struct sockaddr_ng *const sap = (struct sockaddr_ng *) nam;
  674 
  675         if (sockdata == NULL) {
  676                 TRAP_ERROR;
  677                 return (EINVAL);
  678         }
  679         if (sap->sg_len < 3 || sap->sg_data[sap->sg_len - 3] != '\0') {
  680                 TRAP_ERROR;
  681                 return (EINVAL);
  682         }
  683         return (ng_name_node(sockdata->node, sap->sg_data));
  684 }
  685 
  686 /*
  687  * Take a message and pass it up to the control socket associated
  688  * with the node.
  689  */
  690 static int
  691 ship_msg(struct ngpcb *pcbp, struct ng_mesg *msg, struct sockaddr_ng *addr)
  692 {
  693         struct socket *const so = pcbp->ng_socket;
  694         struct mbuf *mdata;
  695         int msglen;
  696 
  697         /* Copy the message itself into an mbuf chain */
  698         msglen = sizeof(struct ng_mesg) + msg->header.arglen;
  699         mdata = m_devget((caddr_t) msg, msglen, 0, NULL, NULL);
  700 
  701         /* Here we free the message, as we are the end of the line.
  702          * We need to do that regardless of whether we got mbufs. */
  703         FREE(msg, M_NETGRAPH);
  704 
  705         if (mdata == NULL) {
  706                 TRAP_ERROR;
  707                 return (ENOBUFS);
  708         }
  709 
  710         /* Send it up to the socket */
  711         if (sbappendaddr(&so->so_rcv,
  712             (struct sockaddr *) addr, mdata, NULL) == 0) {
  713                 TRAP_ERROR;
  714                 m_freem(mdata);
  715                 return (ENOBUFS);
  716         }
  717         sorwakeup(so);
  718         return (0);
  719 }
  720 
  721 /*
  722  * You can only create new nodes from the socket end of things.
  723  */
  724 static int
  725 ngs_constructor(node_p *nodep)
  726 {
  727         return (EINVAL);
  728 }
  729 
  730 /*
  731  * We allow any hook to be connected to the node.
  732  * There is no per-hook private information though.
  733  */
  734 static int
  735 ngs_newhook(node_p node, hook_p hook, const char *name)
  736 {
  737         hook->private = node->private;
  738         return (0);
  739 }
  740 
  741 /*
  742  * Incoming messages get passed up to the control socket.
  743  * Unless they are for us specifically (socket_type)
  744  */
  745 static int
  746 ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
  747            struct ng_mesg **resp)
  748 {
  749         struct ngsock *const sockdata = node->private;
  750         struct ngpcb *const pcbp = sockdata->ctlsock;
  751         struct sockaddr_ng *addr;
  752         int addrlen;
  753         int error = 0;
  754 
  755         /* Only allow mesgs to be passed if we have the control socket.
  756          * Data sockets can only support the generic messages. */
  757         if (pcbp == NULL) {
  758                 TRAP_ERROR;
  759                 return (EINVAL);
  760         }
  761 
  762         if (msg->header.typecookie == NGM_SOCKET_COOKIE) {
  763                 switch (msg->header.cmd) {
  764                 case NGM_SOCK_CMD_NOLINGER:
  765                         sockdata->flags |= NGS_FLAG_NOLINGER;
  766                         break;
  767                 case NGM_SOCK_CMD_LINGER:
  768                         sockdata->flags &= ~NGS_FLAG_NOLINGER;
  769                         break;
  770                 default:
  771                         error = EINVAL;         /* unknown command */
  772                 }
  773                 /* Free the message and return */
  774                 FREE(msg, M_NETGRAPH);
  775                 return(error);
  776 
  777         }
  778         /* Get the return address into a sockaddr */
  779         if ((retaddr == NULL) || (*retaddr == '\0'))
  780                 retaddr = "";
  781         addrlen = strlen(retaddr);
  782         MALLOC(addr, struct sockaddr_ng *, addrlen + 4, M_NETGRAPH, M_NOWAIT);
  783         if (addr == NULL) {
  784                 TRAP_ERROR;
  785                 return (ENOMEM);
  786         }
  787         addr->sg_len = addrlen + 3;
  788         addr->sg_family = AF_NETGRAPH;
  789         bcopy(retaddr, addr->sg_data, addrlen);
  790         addr->sg_data[addrlen] = '\0';
  791 
  792         /* Send it up */
  793         error = ship_msg(pcbp, msg, addr);
  794         FREE(addr, M_NETGRAPH);
  795         return (error);
  796 }
  797 
  798 /*
  799  * Receive data on a hook
  800  */
  801 static int
  802 ngs_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
  803 {
  804         struct ngsock *const sockdata = hook->node->private;
  805         struct ngpcb *const pcbp = sockdata->datasock;
  806         struct socket *so;
  807         struct sockaddr_ng *addr;
  808         char *addrbuf[NG_HOOKLEN + 1 + 4];
  809         int addrlen;
  810 
  811         /* If there is no data socket, black-hole it */
  812         if (pcbp == NULL) {
  813                 NG_FREE_DATA(m, meta);
  814                 return (0);
  815         }
  816         so = pcbp->ng_socket;
  817 
  818         /* Get the return address into a sockaddr. */
  819         addrlen = strlen(hook->name);   /* <= NG_HOOKLEN */
  820         addr = (struct sockaddr_ng *) addrbuf;
  821         addr->sg_len = addrlen + 3;
  822         addr->sg_family = AF_NETGRAPH;
  823         bcopy(hook->name, addr->sg_data, addrlen);
  824         addr->sg_data[addrlen] = '\0';
  825 
  826         /* We have no use for the meta data, free/clear it now. */
  827         NG_FREE_META(meta);
  828 
  829         /* Try to tell the socket which hook it came in on */
  830         if (sbappendaddr(&so->so_rcv, (struct sockaddr *) addr, m, NULL) == 0) {
  831                 m_freem(m);
  832                 TRAP_ERROR;
  833                 return (ENOBUFS);
  834         }
  835         sorwakeup(so);
  836         return (0);
  837 }
  838 
  839 /*
  840  * Hook disconnection
  841  *
  842  * For this type, removal of the last link destroys the node
  843  * if the NOLINGER flag is set.
  844  */
  845 static int
  846 ngs_disconnect(hook_p hook)
  847 {
  848         struct ngsock *const sockdata = hook->node->private;
  849 
  850         if ((sockdata->flags & NGS_FLAG_NOLINGER )
  851         && (hook->node->numhooks == 0)) {
  852                 ng_rmnode(hook->node);
  853         }
  854         return (0);
  855 }
  856 
  857 /*
  858  * Do local shutdown processing.
  859  * In this case, that involves making sure the socket
  860  * knows we should be shutting down.
  861  */
  862 static int
  863 ngs_rmnode(node_p node)
  864 {
  865         struct ngsock *const sockdata = node->private;
  866         struct ngpcb *const dpcbp = sockdata->datasock;
  867         struct ngpcb *const pcbp = sockdata->ctlsock;
  868 
  869         ng_cutlinks(node);
  870         ng_unname(node);
  871 
  872         if (dpcbp != NULL) {
  873                 soisdisconnected(dpcbp->ng_socket);
  874                 dpcbp->sockdata = NULL;
  875                 sockdata->datasock = NULL;
  876                 sockdata->refs--;
  877         }
  878         if (pcbp != NULL) {
  879                 soisdisconnected(pcbp->ng_socket);
  880                 pcbp->sockdata = NULL;
  881                 sockdata->ctlsock = NULL;
  882                 sockdata->refs--;
  883         }
  884         node->private = NULL;
  885         ng_unref(node);
  886         FREE(sockdata, M_NETGRAPH);
  887         return (0);
  888 }
  889 
  890 /*
  891  * Control and data socket type descriptors
  892  */
  893 
  894 static struct pr_usrreqs ngc_usrreqs = {
  895         NULL,                   /* abort */
  896         pru_accept_notsupp,
  897         ngc_attach,
  898         ngc_bind,
  899         ngc_connect,
  900         pru_connect2_notsupp,
  901         pru_control_notsupp,
  902         ngc_detach,
  903         NULL,                   /* disconnect */
  904         pru_listen_notsupp,
  905         NULL,                   /* setpeeraddr */
  906         pru_rcvd_notsupp,
  907         pru_rcvoob_notsupp,
  908         ngc_send,
  909         pru_sense_null,
  910         NULL,                   /* shutdown */
  911         ng_setsockaddr,
  912         sosend,
  913         soreceive,
  914         sopoll
  915 };
  916 
  917 static struct pr_usrreqs ngd_usrreqs = {
  918         NULL,                   /* abort */
  919         pru_accept_notsupp,
  920         ngd_attach,
  921         NULL,                   /* bind */
  922         ngd_connect,
  923         pru_connect2_notsupp,
  924         pru_control_notsupp,
  925         ngd_detach,
  926         NULL,                   /* disconnect */
  927         pru_listen_notsupp,
  928         NULL,                   /* setpeeraddr */
  929         pru_rcvd_notsupp,
  930         pru_rcvoob_notsupp,
  931         ngd_send,
  932         pru_sense_null,
  933         NULL,                   /* shutdown */
  934         ng_setsockaddr,
  935         sosend,
  936         soreceive,
  937         sopoll
  938 };
  939 
  940 /*
  941  * Definitions of protocols supported in the NETGRAPH domain.
  942  */
  943 
  944 extern struct domain ngdomain;          /* stop compiler warnings */
  945 
  946 static struct protosw ngsw[] = {
  947         {
  948                 SOCK_DGRAM,
  949                 &ngdomain,
  950                 NG_CONTROL,
  951                 PR_ATOMIC | PR_ADDR /* | PR_RIGHTS */,
  952                 0, 0, 0, 0,
  953                 NULL,
  954                 0, 0, 0, 0,
  955                 &ngc_usrreqs
  956         },
  957         {
  958                 SOCK_DGRAM,
  959                 &ngdomain,
  960                 NG_DATA,
  961                 PR_ATOMIC | PR_ADDR,
  962                 0, 0, 0, 0,
  963                 NULL,
  964                 0, 0, 0, 0,
  965                 &ngd_usrreqs
  966         }
  967 };
  968 
  969 struct domain ngdomain = {
  970         AF_NETGRAPH,
  971         "netgraph",
  972         0,
  973         NULL,
  974         NULL,
  975         ngsw,
  976         &ngsw[sizeof(ngsw) / sizeof(ngsw[0])],
  977         0,
  978         NULL,
  979         0,
  980         0
  981 };
  982 
  983 /*
  984  * Handle loading and unloading for this node type
  985  * This is to handle auxiliary linkages (e.g protocol domain addition).
  986  */
  987 static int
  988 ngs_mod_event(module_t mod, int event, void *data)
  989 {
  990         int error = 0;
  991 
  992         switch (event) {
  993         case MOD_LOAD:
  994                 /* Register protocol domain */
  995                 net_add_domain(&ngdomain);
  996                 break;
  997         case MOD_UNLOAD:
  998                 /* Insure there are no open netgraph sockets */
  999                 if (!LIST_EMPTY(&ngsocklist)) {
 1000                         error = EBUSY;
 1001                         break;
 1002                 }
 1003 
 1004 #ifdef NOTYET
 1005                 /* Unregister protocol domain XXX can't do this yet.. */
 1006                 if ((error = net_rm_domain(&ngdomain)) != 0)
 1007                         break;
 1008 #else
 1009                 error = EBUSY;
 1010 #endif
 1011                 break;
 1012         default:
 1013                 error = EOPNOTSUPP;
 1014                 break;
 1015         }
 1016         return (error);
 1017 }
 1018 
 1019 SYSCTL_INT(_net_graph, OID_AUTO, family, CTLFLAG_RD, 0, AF_NETGRAPH, "");
 1020 SYSCTL_NODE(_net_graph, OID_AUTO, data, CTLFLAG_RW, 0, "DATA");
 1021 SYSCTL_INT(_net_graph_data, OID_AUTO, proto, CTLFLAG_RD, 0, NG_DATA, "");
 1022 SYSCTL_NODE(_net_graph, OID_AUTO, control, CTLFLAG_RW, 0, "CONTROL");
 1023 SYSCTL_INT(_net_graph_control, OID_AUTO, proto, CTLFLAG_RD, 0, NG_CONTROL, "");
 1024 

Cache object: 719ea7ce4e23a16b21e2bb5f0aa8af38


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