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_tty.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 /*
    3  * ng_tty.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: Archie Cobbs <archie@freebsd.org>
   38  *
   39  * $FreeBSD: releng/5.3/sys/netgraph/ng_tty.c 136588 2004-10-16 08:43:07Z cvs2svn $
   40  * $Whistle: ng_tty.c,v 1.21 1999/11/01 09:24:52 julian Exp $
   41  */
   42 
   43 /*
   44  * This file implements a terminal line discipline that is also a
   45  * netgraph node. Installing this line discipline on a terminal device
   46  * instantiates a new netgraph node of this type, which allows access
   47  * to the device via the "hook" hook of the node.
   48  *
   49  * Once the line discipline is installed, you can find out the name
   50  * of the corresponding netgraph node via a NGIOCGINFO ioctl().
   51  *
   52  * Incoming characters are delievered to the hook one at a time, each
   53  * in its own mbuf. You may optionally define a ``hotchar,'' which causes
   54  * incoming characters to be buffered up until either the hotchar is
   55  * seen or the mbuf is full (MHLEN bytes). Then all buffered characters
   56  * are immediately delivered.
   57  *
   58  * NOTE: This node operates at spltty().
   59  */
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/conf.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/malloc.h>
   67 #include <sys/fcntl.h>
   68 #include <sys/tty.h>
   69 #include <sys/ttycom.h>
   70 #include <sys/syslog.h>
   71 #include <sys/errno.h>
   72 #include <sys/ioccom.h>
   73 
   74 #include <netgraph/ng_message.h>
   75 #include <netgraph/netgraph.h>
   76 #include <netgraph/ng_tty.h>
   77 
   78 NET_NEEDS_GIANT("ng_tty");
   79 
   80 /* Misc defs */
   81 #define MAX_MBUFQ               3       /* Max number of queued mbufs */
   82 #define NGT_HIWATER             400     /* High water mark on output */
   83 
   84 /* Per-node private info */
   85 struct ngt_sc {
   86         struct  tty *tp;                /* Terminal device */
   87         node_p  node;                   /* Netgraph node */
   88         hook_p  hook;                   /* Netgraph hook */
   89         struct  mbuf *m;                /* Incoming data buffer */
   90         struct  mbuf *qhead, **qtail;   /* Queue of outgoing mbuf's */
   91         short   qlen;                   /* Length of queue */
   92         short   hotchar;                /* Hotchar, or -1 if none */
   93         u_int   flags;                  /* Flags */
   94         struct  callout_handle chand;   /* See man timeout(9) */
   95 };
   96 typedef struct ngt_sc *sc_p;
   97 
   98 /* Flags */
   99 #define FLG_TIMEOUT             0x0001  /* A timeout is pending */
  100 #define FLG_DEBUG               0x0002
  101 
  102 /* Debugging */
  103 #ifdef INVARIANTS
  104 #define QUEUECHECK(sc)                                                  \
  105     do {                                                                \
  106       struct mbuf       **mp;                                           \
  107       int               k;                                              \
  108                                                                         \
  109       for (k = 0, mp = &sc->qhead;                                      \
  110         k <= MAX_MBUFQ && *mp;                                          \
  111         k++, mp = &(*mp)->m_nextpkt);                                   \
  112       if (k != sc->qlen || k > MAX_MBUFQ || *mp || mp != sc->qtail)     \
  113         panic("%s: queue", __func__);                                   \
  114     } while (0)
  115 #else
  116 #define QUEUECHECK(sc)  do {} while (0)
  117 #endif
  118 
  119 /* Line discipline methods */
  120 static int      ngt_open(struct cdev *dev, struct tty *tp);
  121 static int      ngt_close(struct tty *tp, int flag);
  122 static int      ngt_read(struct tty *tp, struct uio *uio, int flag);
  123 static int      ngt_write(struct tty *tp, struct uio *uio, int flag);
  124 static int      ngt_tioctl(struct tty *tp,
  125                     u_long cmd, caddr_t data, int flag, struct thread *);
  126 static int      ngt_input(int c, struct tty *tp);
  127 static int      ngt_start(struct tty *tp);
  128 
  129 /* Netgraph methods */
  130 static ng_constructor_t ngt_constructor;
  131 static ng_rcvmsg_t      ngt_rcvmsg;
  132 static ng_shutdown_t    ngt_shutdown;
  133 static ng_newhook_t     ngt_newhook;
  134 static ng_connect_t     ngt_connect;
  135 static ng_rcvdata_t     ngt_rcvdata;
  136 static ng_disconnect_t  ngt_disconnect;
  137 static int      ngt_mod_event(module_t mod, int event, void *data);
  138 
  139 /* Other stuff */
  140 static void     ngt_timeout(void *arg);
  141 
  142 #define ERROUT(x)               do { error = (x); goto done; } while (0)
  143 
  144 /* Line discipline descriptor */
  145 static struct linesw ngt_disc = {
  146         ngt_open,
  147         ngt_close,
  148         ngt_read,
  149         ngt_write,
  150         ngt_tioctl,
  151         ngt_input,
  152         ngt_start,
  153         ttymodem
  154 };
  155 
  156 /* Netgraph node type descriptor */
  157 static struct ng_type typestruct = {
  158         .version =      NG_ABI_VERSION,
  159         .name =         NG_TTY_NODE_TYPE,
  160         .mod_event =    ngt_mod_event,
  161         .constructor =  ngt_constructor,
  162         .rcvmsg =       ngt_rcvmsg,
  163         .shutdown =     ngt_shutdown,
  164         .newhook =      ngt_newhook,
  165         .connect =      ngt_connect,
  166         .rcvdata =      ngt_rcvdata,
  167         .disconnect =   ngt_disconnect,
  168 };
  169 NETGRAPH_INIT(tty, &typestruct);
  170 
  171 /*
  172  * XXXRW: ngt_unit is protected by ng_tty_mtx.  ngt_ldisc is constant once
  173  * ng_tty is initialized.  ngt_nodeop_ok is untouched, and might want to be a
  174  * sleep lock in the future?
  175  */
  176 static int ngt_unit;
  177 static int ngt_nodeop_ok;       /* OK to create/remove node */
  178 static int ngt_ldisc;
  179 
  180 static struct mtx       ng_tty_mtx;
  181 MTX_SYSINIT(ng_tty, &ng_tty_mtx, "ng_tty", MTX_DEF);
  182 
  183 /******************************************************************
  184                     LINE DISCIPLINE METHODS
  185 ******************************************************************/
  186 
  187 /*
  188  * Set our line discipline on the tty.
  189  * Called from device open routine or ttioctl() at >= splsofttty()
  190  */
  191 static int
  192 ngt_open(struct cdev *dev, struct tty *tp)
  193 {
  194         struct thread *const td = curthread;    /* XXX */
  195         char name[sizeof(NG_TTY_NODE_TYPE) + 8];
  196         sc_p sc;
  197         int s, error;
  198 
  199         /* Super-user only */
  200         if ((error = suser(td)))
  201                 return (error);
  202         s = splnet();
  203         (void) spltty();        /* XXX is this necessary? */
  204 
  205         tp->t_hotchar = NG_TTY_DFL_HOTCHAR;
  206 
  207         /* Initialize private struct */
  208         MALLOC(sc, sc_p, sizeof(*sc), M_NETGRAPH, M_WAITOK | M_ZERO);
  209         if (sc == NULL) {
  210                 error = ENOMEM;
  211                 goto done;
  212         }
  213         sc->tp = tp;
  214         sc->hotchar = NG_TTY_DFL_HOTCHAR;
  215         sc->qtail = &sc->qhead;
  216         QUEUECHECK(sc);
  217         callout_handle_init(&sc->chand);
  218 
  219         /* Setup netgraph node */
  220         ngt_nodeop_ok = 1;
  221         error = ng_make_node_common(&typestruct, &sc->node);
  222         ngt_nodeop_ok = 0;
  223         if (error) {
  224                 FREE(sc, M_NETGRAPH);
  225                 goto done;
  226         }
  227         mtx_lock(&ng_tty_mtx);
  228         snprintf(name, sizeof(name), "%s%d", typestruct.name, ngt_unit++);
  229         mtx_unlock(&ng_tty_mtx);
  230 
  231         /* Assign node its name */
  232         if ((error = ng_name_node(sc->node, name))) {
  233                 log(LOG_ERR, "%s: node name exists?\n", name);
  234                 ngt_nodeop_ok = 1;
  235                 NG_NODE_UNREF(sc->node);
  236                 ngt_nodeop_ok = 0;
  237                 goto done;
  238         }
  239 
  240         /* Set back pointers */
  241         NG_NODE_SET_PRIVATE(sc->node, sc);
  242         tp->t_sc = (caddr_t) sc;
  243 
  244         /*
  245          * Pre-allocate cblocks to the an appropriate amount.
  246          * I'm not sure what is appropriate.
  247          */
  248         ttyflush(tp, FREAD | FWRITE);
  249         clist_alloc_cblocks(&tp->t_canq, 0, 0);
  250         clist_alloc_cblocks(&tp->t_rawq, 0, 0);
  251         clist_alloc_cblocks(&tp->t_outq,
  252             MLEN + NGT_HIWATER, MLEN + NGT_HIWATER);
  253 
  254 done:
  255         /* Done */
  256         splx(s);
  257         return (error);
  258 }
  259 
  260 /*
  261  * Line specific close routine, called from device close routine
  262  * and from ttioctl at >= splsofttty(). This causes the node to
  263  * be destroyed as well.
  264  */
  265 static int
  266 ngt_close(struct tty *tp, int flag)
  267 {
  268         const sc_p sc = (sc_p) tp->t_sc;
  269         int s;
  270 
  271         s = spltty();
  272         ttyflush(tp, FREAD | FWRITE);
  273         clist_free_cblocks(&tp->t_outq);
  274         if (sc != NULL) {
  275                 if (sc->flags & FLG_TIMEOUT) {
  276                         untimeout(ngt_timeout, sc, sc->chand);
  277                         sc->flags &= ~FLG_TIMEOUT;
  278                 }
  279                 ngt_nodeop_ok = 1;
  280                 ng_rmnode_self(sc->node);
  281                 ngt_nodeop_ok = 0;
  282                 tp->t_sc = NULL;
  283         }
  284         splx(s);
  285         return (0);
  286 }
  287 
  288 /*
  289  * Once the device has been turned into a node, we don't allow reading.
  290  */
  291 static int
  292 ngt_read(struct tty *tp, struct uio *uio, int flag)
  293 {
  294         return (EIO);
  295 }
  296 
  297 /*
  298  * Once the device has been turned into a node, we don't allow writing.
  299  */
  300 static int
  301 ngt_write(struct tty *tp, struct uio *uio, int flag)
  302 {
  303         return (EIO);
  304 }
  305 
  306 /*
  307  * We implement the NGIOCGINFO ioctl() defined in ng_message.h.
  308  */
  309 static int
  310 ngt_tioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td)
  311 {
  312         const sc_p sc = (sc_p) tp->t_sc;
  313         int s, error = 0;
  314 
  315         s = spltty();
  316         switch (cmd) {
  317         case NGIOCGINFO:
  318             {
  319                 struct nodeinfo *const ni = (struct nodeinfo *) data;
  320                 const node_p node = sc->node;
  321 
  322                 bzero(ni, sizeof(*ni));
  323                 if (NG_NODE_HAS_NAME(node))
  324                         strncpy(ni->name, NG_NODE_NAME(node), sizeof(ni->name) - 1);
  325                 strncpy(ni->type, node->nd_type->name, sizeof(ni->type) - 1);
  326                 ni->id = (u_int32_t) ng_node2ID(node);
  327                 ni->hooks = NG_NODE_NUMHOOKS(node);
  328                 break;
  329             }
  330         default:
  331                 ERROUT(ENOIOCTL);
  332         }
  333 done:
  334         splx(s);
  335         return (error);
  336 }
  337 
  338 /*
  339  * Receive data coming from the device. We get one character at
  340  * a time, which is kindof silly.
  341  * Only guaranteed to be at splsofttty() or spltty().
  342  */
  343 static int
  344 ngt_input(int c, struct tty *tp)
  345 {
  346         const sc_p sc = (sc_p) tp->t_sc;
  347         const node_p node = sc->node;
  348         struct mbuf *m;
  349         int s, error = 0;
  350 
  351         if (!sc || tp != sc->tp)
  352                 return (0);
  353         s = spltty();
  354         if (!sc->hook)
  355                 ERROUT(0);
  356 
  357         /* Check for error conditions */
  358         if ((tp->t_state & TS_CONNECTED) == 0) {
  359                 if (sc->flags & FLG_DEBUG)
  360                         log(LOG_DEBUG, "%s: no carrier\n", NG_NODE_NAME(node));
  361                 ERROUT(0);
  362         }
  363         if (c & TTY_ERRORMASK) {
  364                 /* framing error or overrun on this char */
  365                 if (sc->flags & FLG_DEBUG)
  366                         log(LOG_DEBUG, "%s: line error %x\n",
  367                             NG_NODE_NAME(node), c & TTY_ERRORMASK);
  368                 ERROUT(0);
  369         }
  370         c &= TTY_CHARMASK;
  371 
  372         /* Get a new header mbuf if we need one */
  373         if (!(m = sc->m)) {
  374                 MGETHDR(m, M_DONTWAIT, MT_DATA);
  375                 if (!m) {
  376                         if (sc->flags & FLG_DEBUG)
  377                                 log(LOG_ERR,
  378                                     "%s: can't get mbuf\n", NG_NODE_NAME(node));
  379                         ERROUT(ENOBUFS);
  380                 }
  381                 m->m_len = m->m_pkthdr.len = 0;
  382                 m->m_pkthdr.rcvif = NULL;
  383                 sc->m = m;
  384         }
  385 
  386         /* Add char to mbuf */
  387         *mtod(m, u_char *) = c;
  388         m->m_data++;
  389         m->m_len++;
  390         m->m_pkthdr.len++;
  391 
  392         /* Ship off mbuf if it's time */
  393         if (sc->hotchar == -1 || c == sc->hotchar || m->m_len >= MHLEN) {
  394                 m->m_data = m->m_pktdat;
  395                 NG_SEND_DATA_ONLY(error, sc->hook, m);
  396                 sc->m = NULL;
  397         }
  398 done:
  399         splx(s);
  400         return (error);
  401 }
  402 
  403 /*
  404  * This is called when the device driver is ready for more output.
  405  * Called from tty system at splsofttty() or spltty().
  406  * Also call from ngt_rcv_data() when a new mbuf is available for output.
  407  */
  408 static int
  409 ngt_start(struct tty *tp)
  410 {
  411         const sc_p sc = (sc_p) tp->t_sc;
  412         int s;
  413 
  414         s = spltty();
  415         while (tp->t_outq.c_cc < NGT_HIWATER) { /* XXX 2.2 specific ? */
  416                 struct mbuf *m = sc->qhead;
  417 
  418                 /* Remove first mbuf from queue */
  419                 if (!m)
  420                         break;
  421                 if ((sc->qhead = m->m_nextpkt) == NULL)
  422                         sc->qtail = &sc->qhead;
  423                 sc->qlen--;
  424                 QUEUECHECK(sc);
  425 
  426                 /* Send as much of it as possible */
  427                 while (m) {
  428                         int     sent;
  429 
  430                         sent = m->m_len
  431                             - b_to_q(mtod(m, u_char *), m->m_len, &tp->t_outq);
  432                         m->m_data += sent;
  433                         m->m_len -= sent;
  434                         if (m->m_len > 0)
  435                                 break;  /* device can't take no more */
  436                         m = m_free(m);
  437                 }
  438 
  439                 /* Put remainder of mbuf chain (if any) back on queue */
  440                 if (m) {
  441                         m->m_nextpkt = sc->qhead;
  442                         sc->qhead = m;
  443                         if (sc->qtail == &sc->qhead)
  444                                 sc->qtail = &m->m_nextpkt;
  445                         sc->qlen++;
  446                         QUEUECHECK(sc);
  447                         break;
  448                 }
  449         }
  450 
  451         /* Call output process whether or not there is any output. We are
  452          * being called in lieu of ttstart and must do what it would. */
  453         if (tp->t_oproc != NULL)
  454                 (*tp->t_oproc) (tp);
  455 
  456         /* This timeout is needed for operation on a pseudo-tty, because the
  457          * pty code doesn't call pppstart after it has drained the t_outq. */
  458         if (sc->qhead && (sc->flags & FLG_TIMEOUT) == 0) {
  459                 sc->chand = timeout(ngt_timeout, sc, 1);
  460                 sc->flags |= FLG_TIMEOUT;
  461         }
  462         splx(s);
  463         return (0);
  464 }
  465 
  466 /*
  467  * We still have data to output to the device, so try sending more.
  468  */
  469 static void
  470 ngt_timeout(void *arg)
  471 {
  472         const sc_p sc = (sc_p) arg;
  473         int s;
  474 
  475         s = spltty();
  476         sc->flags &= ~FLG_TIMEOUT;
  477         ngt_start(sc->tp);
  478         splx(s);
  479 }
  480 
  481 /******************************************************************
  482                     NETGRAPH NODE METHODS
  483 ******************************************************************/
  484 
  485 /*
  486  * Initialize a new node of this type.
  487  *
  488  * We only allow nodes to be created as a result of setting
  489  * the line discipline on a tty, so always return an error if not.
  490  */
  491 static int
  492 ngt_constructor(node_p node)
  493 {
  494         return (EOPNOTSUPP);
  495 }
  496 
  497 /*
  498  * Add a new hook. There can only be one.
  499  */
  500 static int
  501 ngt_newhook(node_p node, hook_p hook, const char *name)
  502 {
  503         const sc_p sc = NG_NODE_PRIVATE(node);
  504         int s, error = 0;
  505 
  506         if (strcmp(name, NG_TTY_HOOK))
  507                 return (EINVAL);
  508         s = spltty();
  509         if (sc->hook)
  510                 ERROUT(EISCONN);
  511         sc->hook = hook;
  512 done:
  513         splx(s);
  514         return (error);
  515 }
  516 
  517 /*
  518  * Set the hooks into queueing mode (for outgoing packets)
  519  * Force single client at a time.
  520  */
  521 static int
  522 ngt_connect(hook_p hook)
  523 {
  524         /*NG_HOOK_FORCE_WRITER(hook);
  525         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));*/
  526         return (0);
  527 }
  528 
  529 /*
  530  * Disconnect the hook
  531  */
  532 static int
  533 ngt_disconnect(hook_p hook)
  534 {
  535         const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  536         int s;
  537 
  538         s = spltty();
  539         if (hook != sc->hook)
  540                 panic(__func__);
  541         sc->hook = NULL;
  542         m_freem(sc->m);
  543         sc->m = NULL;
  544         splx(s);
  545         return (0);
  546 }
  547 
  548 /*
  549  * Remove this node. The does the netgraph portion of the shutdown.
  550  * This should only be called indirectly from ngt_close().
  551  */
  552 static int
  553 ngt_shutdown(node_p node)
  554 {
  555         const sc_p sc = NG_NODE_PRIVATE(node);
  556 
  557         if (!ngt_nodeop_ok)
  558                 return (EOPNOTSUPP);
  559         NG_NODE_SET_PRIVATE(node, NULL);
  560         NG_NODE_UNREF(sc->node);
  561         m_freem(sc->qhead);
  562         m_freem(sc->m);
  563         bzero(sc, sizeof(*sc));
  564         FREE(sc, M_NETGRAPH);
  565         return (0);
  566 }
  567 
  568 /*
  569  * Receive incoming data from netgraph system. Put it on our
  570  * output queue and start output if necessary.
  571  */
  572 static int
  573 ngt_rcvdata(hook_p hook, item_p item)
  574 {
  575         const sc_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
  576         int s, error = 0;
  577         struct mbuf *m;
  578 
  579         if (hook != sc->hook)
  580                 panic(__func__);
  581 
  582         NGI_GET_M(item, m);
  583         NG_FREE_ITEM(item);
  584         s = spltty();
  585         if (sc->qlen >= MAX_MBUFQ)
  586                 ERROUT(ENOBUFS);
  587         m->m_nextpkt = NULL;
  588         *sc->qtail = m;
  589         sc->qtail = &m->m_nextpkt;
  590         sc->qlen++;
  591         QUEUECHECK(sc);
  592         m = NULL;
  593         if (sc->qlen == 1)
  594                 ngt_start(sc->tp);
  595 done:
  596         splx(s);
  597         if (m)
  598                 m_freem(m);
  599         return (error);
  600 }
  601 
  602 /*
  603  * Receive control message
  604  */
  605 static int
  606 ngt_rcvmsg(node_p node, item_p item, hook_p lasthook)
  607 {
  608         const sc_p sc = NG_NODE_PRIVATE(node);
  609         struct ng_mesg *resp = NULL;
  610         int error = 0;
  611         struct ng_mesg *msg;
  612 
  613         NGI_GET_MSG(item, msg);
  614         switch (msg->header.typecookie) {
  615         case NGM_TTY_COOKIE:
  616                 switch (msg->header.cmd) {
  617                 case NGM_TTY_SET_HOTCHAR:
  618                     {
  619                         int     hotchar;
  620 
  621                         if (msg->header.arglen != sizeof(int))
  622                                 ERROUT(EINVAL);
  623                         hotchar = *((int *) msg->data);
  624                         if (hotchar != (u_char) hotchar && hotchar != -1)
  625                                 ERROUT(EINVAL);
  626                         sc->hotchar = hotchar;  /* race condition is OK */
  627                         break;
  628                     }
  629                 case NGM_TTY_GET_HOTCHAR:
  630                         NG_MKRESPONSE(resp, msg, sizeof(int), M_NOWAIT);
  631                         if (!resp)
  632                                 ERROUT(ENOMEM);
  633                         /* Race condition here is OK */
  634                         *((int *) resp->data) = sc->hotchar;
  635                         break;
  636                 default:
  637                         ERROUT(EINVAL);
  638                 }
  639                 break;
  640         default:
  641                 ERROUT(EINVAL);
  642         }
  643 done:
  644         NG_RESPOND_MSG(error, node, item, resp);
  645         NG_FREE_MSG(msg);
  646         return (error);
  647 }
  648 
  649 /******************************************************************
  650                         INITIALIZATION
  651 ******************************************************************/
  652 
  653 /*
  654  * Handle loading and unloading for this node type
  655  */
  656 static int
  657 ngt_mod_event(module_t mod, int event, void *data)
  658 {
  659         /* struct ng_type *const type = data;*/
  660         int s, error = 0;
  661 
  662         switch (event) {
  663         case MOD_LOAD:
  664 
  665                 /* Register line discipline */
  666                 s = spltty();
  667                 if ((ngt_ldisc = ldisc_register(NETGRAPHDISC, &ngt_disc)) < 0) {
  668                         splx(s);
  669                         log(LOG_ERR, "%s: can't register line discipline",
  670                             __func__);
  671                         return (EIO);
  672                 }
  673                 splx(s);
  674                 break;
  675 
  676         case MOD_UNLOAD:
  677 
  678                 /* Unregister line discipline */
  679                 s = spltty();
  680                 ldisc_deregister(ngt_ldisc);
  681                 splx(s);
  682                 break;
  683 
  684         default:
  685                 error = EOPNOTSUPP;
  686                 break;
  687         }
  688         return (error);
  689 }
  690 

Cache object: 2b2b77f1d926a6a5649b631775ecd8ff


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