home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / sysVr4386slip / part01 / driver / io / slip.c
Encoding:
C/C++ Source or Header  |  1991-03-21  |  21.2 KB  |  939 lines

  1. /*
  2.  *            Copyright 1991, Intel Corporation
  3.  *                  All rights reserved.
  4.  *
  5.  * Permission to use, copy, modify, and distribute this software and
  6.  * its documentation for any purpose and without fee is hereby granted,
  7.  * provided that the above copyright notice appear in all copies and
  8.  * that both the copyright notice appear in all copies and that both
  9.  * the copyright notice and this permission notice appear in
  10.  * supporting documentation, and that the name of Intel Corporation
  11.  * not be used in advertising or publicity pertaining to distribution
  12.  * of the software without specific, written prior premission.
  13.  * 
  14.  * COMPANY AND/OR INTEL DISCLAIM ALL WARRANTIES WITH REGARD TO
  15.  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
  16.  * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
  17.  * EVENT SHALL COMPANY NOR INTEL BE LIABLE FOR ANY SPECIAL,
  18.  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  19.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  21.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  22.  * OF THIS SOFTWARE.
  23.  */
  24.  
  25. /*
  26.  * Serial Line Internet Protocol (SLIP) streams multiplexor driver for
  27.  * Intel Unix System V/386 Release 4.0.
  28.  *
  29.  * The upper streams is supposed to be linked to the ip driver (/dev/ip)
  30.  * and optionally linked to the slip hangup daemon. The lower streams can
  31.  * linked to any number of serial driver.
  32.  *
  33.  * The slattach command builds the ip to slip to serial device links and
  34.  * The slhangupd command is a daemon for receiving M_HANGUP message from
  35.  * the serial driver.
  36.  *
  37.  * The packet framing protocol code, in the upper write and the lower
  38.  * read service routine (slip_uwsrv and slip_lrsrv) is based from
  39.  * tty_slip.c written by Rayan Zachariassen <rayan@ai.toronto.edu> and
  40.  * Doug Kingston <dpk@morgan.com>.
  41.  *
  42.  * Author:
  43.  *     Sudji Husodo <sudji@indo.intel.com> 1/9/91
  44.  */
  45.  
  46. #include <sys/types.h>
  47. #include <sys/kmem.h>
  48. #include <sys/stream.h>
  49. #include <sys/stropts.h>
  50. #include <sys/dlpi.h>
  51. #include <sys/syslog.h>
  52. #include <sys/strlog.h>
  53. #include <sys/socket.h>
  54. #include <sys/sockio.h>
  55. #include <sys/log.h>
  56. #include <sys/errno.h>
  57. #include <sys/ioctl.h>
  58. #include <sys/param.h>
  59. #include <sys/ddi.h>
  60.  
  61. #include <net/if.h>
  62. #include <netinet/in.h>
  63. #include <netinet/in_systm.h>
  64. #include <netinet/ip.h>
  65. #include <sys/slip.h>
  66.  
  67. #define DL_PRIM_SIZE    sizeof (union DL_primitives)
  68.  
  69. int slip_devflag = 0;        /* V4.0 style driver */
  70.  
  71. #ifndef DEBUG
  72. static
  73. #endif
  74. int slip_open(),  slip_close(), slip_uwput(), slip_uwsrv(),
  75.     slip_lwput(), slip_lwsrv(), slip_lrput(), slip_lrsrv();
  76.  
  77. static struct module_info minfo[5] = {
  78.     SLIPM_ID, "slip", 0, 8192, 16384, 4096,
  79.     SLIPM_ID, "slip", 0, 8192, 16384, 4096,
  80.     SLIPM_ID, "slip", 0, 8192, 16384, 4096,
  81.     SLIPM_ID, "slip", 0, 8192, 16384, 4096,
  82.     SLIPM_ID, "slip", 0, 8192, 16384, 4096,
  83. };
  84.  
  85. static struct qinit urinit = {
  86.     NULL,       NULL,       slip_open, slip_close, NULL, &minfo[0], NULL };
  87.  
  88. static struct qinit uwinit = {
  89.     slip_uwput, slip_uwsrv, slip_open, slip_close, NULL, &minfo[1], NULL };
  90.  
  91. static struct qinit lrinit = {
  92.     slip_lrput, slip_lrsrv, slip_open, slip_close, NULL, &minfo[3], NULL };
  93.  
  94. static struct qinit lwinit = {
  95.     slip_lwput, slip_lwsrv, slip_open, slip_close, NULL, &minfo[4], NULL };
  96.  
  97. struct streamtab slip_info = {
  98.     &urinit, &uwinit, &lrinit, &lwinit };
  99.  
  100. slip_t *slip_hup = (slip_t *) 0;
  101.  
  102. extern    struct    ifstats    *ifstats;
  103. extern    u_int    slip_num;
  104. extern    slip_t    slip_data[];
  105.  
  106. /*
  107.  * slip_open
  108.  */
  109.  
  110. #ifndef DEBUG
  111. static
  112. #endif
  113. slip_open (q, devp, flag, sflag, credp)
  114. queue_t    *q;
  115. dev_t    *devp;
  116. int        flag;
  117. int        sflag;
  118. struct    cred    *credp;
  119. {
  120.     register slip_t *p_slip;
  121.     dev_t     dev;
  122.     int         oldpri;
  123.     mblk_t     *bp;
  124.     major_t  major = getmajor (*devp);
  125.     minor_t  minor = getminor (*devp);
  126.  
  127.     STRLOG (SLIPM_ID,0,0,SL_TRACE,"slip_open: major %d minor %d",major,minor);
  128.  
  129.     /* find an unused entry in slip_data */
  130.  
  131.     if (sflag == CLONEOPEN) {
  132.         for (dev=0, p_slip=&slip_data[0]; dev<slip_num; dev++, p_slip++)
  133.             if (!p_slip->buf)
  134.                 break;
  135.         minor = (minor_t) dev;
  136.     }
  137.  
  138.     /* if there's no more free entry, return No Space error code */
  139.  
  140.     if (minor >= slip_num) {
  141.         STRLOG (SLIPM_ID, 1, 0, SL_TRACE, "slip open: can't allocate device");
  142.         return ENXIO;
  143.     }
  144.  
  145.     /* initialized slip information */
  146.  
  147.     oldpri = splstr ();
  148.     p_slip->state    = DL_UNBOUND;
  149.     p_slip->qtop     = q;
  150.     p_slip->qbot     = NULL;
  151.     p_slip->buf      = (u_char *) kmem_alloc (SLIPMTU, KM_SLEEP);
  152.     p_slip->qt_blocked = 0;
  153.     drv_getparm (PPID, &p_slip->pid);        /* keep process id */
  154.  
  155.     p_slip->escape   = p_slip->overrun = p_slip->inlen = 0;
  156.     p_slip->flags    = IFF_UP | IFF_POINTOPOINT;
  157.     p_slip->uname[0] = '\0';
  158.  
  159.     /* initialized interface and its statistics */
  160.  
  161.     p_slip->stats.ifs_name       = (char *) p_slip->uname;
  162.     p_slip->stats.ifs_unit       = 0;
  163.     p_slip->stats.ifs_active     = 0;
  164.     p_slip->stats.ifs_mtu        = SLIPMTU;
  165.     p_slip->stats.ifs_ipackets   = p_slip->stats.ifs_opackets = 0;
  166.     p_slip->stats.ifs_ierrors    = p_slip->stats.ifs_oerrors  = 0;
  167.     p_slip->stats.ifs_collisions = 0;
  168.     splx (oldpri);
  169.  
  170.     /* initialize read and write queue pointers to private data */
  171.  
  172.     q->q_ptr = (caddr_t) p_slip;
  173.     WR(q)->q_ptr = (caddr_t) p_slip;
  174.  
  175.     /* set up the correct stream head flow control parameters */
  176.  
  177.     if (bp = allocb (sizeof (struct stroptions), BPRI_MED)) {
  178.         struct stroptions *sop = (struct stroptions *) bp->b_rptr;
  179.         bp->b_datap->db_type = M_SETOPTS;
  180.         bp->b_wptr += sizeof (struct stroptions);
  181.         sop->so_flags = SO_HIWAT | SO_LOWAT;
  182.         sop->so_hiwat = minfo [2].mi_hiwat;
  183.         sop->so_lowat = minfo [2].mi_lowat;
  184.         putnext (q, bp);
  185.     }
  186.     *devp = makedevice (major, minor);
  187.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip open: device %d coming up", minor);
  188.     return (0);
  189. }
  190.  
  191. /*
  192.  * slip_close ()
  193.  */
  194.  
  195. #ifndef DEBUG
  196. static
  197. #endif
  198. slip_close (q)
  199. queue_t    *q;
  200. {
  201.     slip_t    *p_slip;
  202.     dev_t     dev;
  203.     int        oldpri;
  204.  
  205.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_close: going down ...");
  206.     p_slip = (slip_t *) q->q_ptr;
  207.     oldpri = splstr ();
  208.  
  209.     if (p_slip->buf)
  210.         kmem_free (p_slip->buf, SLIPMTU);
  211.  
  212.     p_slip->state = DL_UNATTACHED;
  213.     p_slip->buf   = 0;
  214.     p_slip->inlen = 0;
  215.     p_slip->qtop  = 0;
  216.     p_slip->pid   = 0;
  217.  
  218.     ifstats = p_slip->stats.ifs_next;         /* reset ifstats pointers */
  219.     splx (oldpri);
  220. }
  221.  
  222. /*
  223.  *    slip_ioctl ()
  224.  */
  225.  
  226. #ifndef DEBUG
  227. static
  228. #endif
  229. slip_ioctl (q, mp)
  230. queue_t    *q;
  231. mblk_t    *mp;
  232. {
  233.     struct iocblk *iocp;
  234.     struct ifreq  *ifr;
  235.     slip_t *p_slip;
  236.     int        oldpri;
  237.     struct    linkblk    *lp;
  238.     slip_t *pp;
  239.     u_char *p;
  240.     int n;
  241.  
  242.     p_slip  = (slip_t *) q->q_ptr;
  243.     iocp = (struct iocblk *) mp->b_rptr;
  244.  
  245.     STRLOG (SLIPM_ID, 1, 0, SL_TRACE, "slip_ioctl: enter: case ('%c',%d)", 0x00FF&(iocp->ioc_cmd>>8), 0x00FF&iocp->ioc_cmd);
  246.     oldpri = splstr ();
  247.  
  248.     switch (iocp->ioc_cmd) {
  249.  
  250.     case REG_SLHUP:
  251.         STRLOG (SLIPM_ID, 1, 0, SL_TRACE, "slip_ioctl: REG_SLHUP");
  252.         if (slip_hup) {
  253.             splx (oldpri);
  254.             mp->b_datap->db_type = M_IOCNAK;
  255.             qreply (q, mp);
  256.             return (0);
  257.         }
  258.         else
  259.             slip_hup = p_slip;
  260.         break;
  261.  
  262.     case UNREG_SLHUP:
  263.         STRLOG (SLIPM_ID, 1, 0, SL_TRACE, "slip_ioctl: UNREG_SLHUP");
  264.         slip_hup = 0;
  265.         break;
  266.  
  267.     case I_LINK:
  268.         iocp->ioc_error = iocp->ioc_rval = iocp->ioc_count = 0;
  269.  
  270.         lp = (struct linkblk *) mp->b_cont->b_rptr;
  271.         p_slip->qbot = lp->l_qbot;
  272.         p_slip->qbot->q_ptr = (char *) p_slip;
  273.         OTHERQ (p_slip->qbot)->q_ptr = (char *) p_slip;
  274.         break;
  275.  
  276.     case I_UNLINK:
  277.         iocp->ioc_error = iocp->ioc_rval = iocp->ioc_count = 0;
  278.         p_slip->qbot = NULL;
  279.         break;
  280.  
  281.     case SIOCSIFNAME:
  282.         ifr = (struct ifreq *) mp->b_cont->b_rptr;
  283.  
  284.         /* copy interface name to local slip structure */
  285.  
  286.         /*
  287.          * interface name (ifr->ifr_name) contains the name and unit, e.g.
  288.          * "sl0", "sl12", "emd0", "wd1", etc. Store the name in slip->uname
  289.          * and unit in slip->unit. If unit is not supplied, e.g. "slip",
  290.          * then unit number is assumed to be zero.
  291.          */
  292.  
  293.         strncpy (p_slip->uname, ifr->ifr_name, IFNAMSIZ);    /* copy name */
  294.         n = 0;
  295.  
  296.         /* starting from the last char, find the first non-digit char */
  297.  
  298.         p = p_slip->uname + strlen(p_slip->uname) - 1;
  299.         while ('0' <= *p && *p <= '9')
  300.             p--;
  301.  
  302.         /* calculate integer, replace them with nulls */
  303.  
  304.         while (*++p) {
  305.             n = 10*n + (*p-'0');
  306.             *p = '\0';
  307.         }
  308.         p_slip->stats.ifs_unit = n;                /* set ifs unit number  */
  309.  
  310.         /* search for matching interface name and unit */
  311.  
  312.         for (n=0, pp=&slip_data[0]; n<slip_num; n++, pp++)
  313.             if (pp != p_slip && pp->buf && !strcmp (pp->uname,p_slip->uname) &&
  314.                 pp->stats.ifs_unit == p_slip->stats.ifs_unit)
  315.                 break;
  316.  
  317.         if (n < slip_num) {                            /* found matching ifname */
  318.             splx (oldpri);
  319.             mp->b_datap->db_type = M_IOCNAK;        /* Negative Ack reply */
  320.             qreply (q, mp);
  321.             return (0);
  322.         }
  323.         else {                                        /* ifname is unique */
  324.             p_slip->stats.ifs_next = ifstats;        /* set ifstats pointers */
  325.             ifstats = &p_slip->stats;                /* used for statistics */
  326.         }                                            /* by netstat command */
  327.         break;
  328.  
  329.     case SIOCGIFFLAGS:
  330.         ((struct iocblk_in *)iocp)->ioc_ifflags = p_slip->flags;
  331.         break;
  332.  
  333.     case SIOCSIFFLAGS:
  334.         p_slip->flags = ((struct iocblk_in *)iocp)->ioc_ifflags;
  335.         break;
  336.  
  337.     case SIOCSIFADDR:
  338.         p_slip->flags |= IFF_RUNNING;
  339.         ((struct iocblk_in *)iocp)->ioc_ifflags |= IFF_RUNNING;
  340.         break;
  341.  
  342.     default:
  343.         break;
  344.     }
  345.     splx (oldpri);
  346.     mp->b_datap->db_type = M_IOCACK;
  347.     qreply (q, mp);
  348. }
  349.  
  350. /*
  351.  * slip_uwput ()
  352.  */
  353.  
  354. #ifndef DEBUG
  355. static
  356. #endif
  357. slip_uwput (q, mp)
  358. queue_t    *q;
  359. mblk_t    *mp;
  360. {
  361.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_uwput: case 0x%2.2x", mp->b_datap->db_type);
  362.  
  363.     switch (mp->b_datap->db_type) {
  364.  
  365.     case M_FLUSH:
  366.         if (*mp->b_rptr & FLUSHW) {
  367.             flushq(q, FLUSHALL);
  368.             *mp->b_rptr &= ~FLUSHW;
  369.         }
  370.         if (*mp->b_rptr & FLUSHR)
  371.             qreply(q, mp);
  372.         else
  373.             freemsg(mp);
  374.         break;
  375.  
  376.     case M_IOCTL:
  377.         slip_ioctl (q, mp);
  378.         break;
  379.  
  380.     case M_PROTO:
  381.     case M_PCPROTO:
  382.         slip_dl_cmds (q, mp);
  383.         break;
  384.  
  385.     default:
  386.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_uwput: unknown message type, passing message to the next queue");
  387.         putnext (((slip_t *)q->q_ptr)->qbot, mp);
  388.         break;
  389.     } 
  390. }
  391.  
  392. /*
  393.  * slip_uwsrv ()
  394.  */
  395.  
  396. #ifndef DEBUG
  397. static
  398. #endif
  399. slip_uwsrv (q)
  400. register queue_t *q;
  401. {
  402.     register mblk_t    *mp, *mpd, *mp2;
  403.     register u_char    *cp;
  404.     register int    pktlen, num;
  405.     register slip_t *p_slip;
  406.  
  407.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_uwsrv: enter");
  408.  
  409.     while ((mp = getq(q)) != NULL) {
  410.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_uwsrv: got message from q");
  411.         p_slip = (slip_t *) q->q_ptr;
  412.  
  413.  
  414.         if (!canput (p_slip->qbot)) {
  415.             STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_uwsrv: can't put message to qbot");
  416.             putbq (q, mp);
  417.             p_slip->qt_blocked = 1;
  418.             return;
  419.         }
  420.         pktlen = 0;
  421.  
  422.         /*
  423.          * count the number of special characters (END & ESC)
  424.          */
  425.  
  426.         num = 2;        /* END char is put at the start and end of packet */
  427.  
  428.         for (mpd = mp->b_cont; mpd != 0; mpd = mpd->b_cont) {
  429.             pktlen += (mpd->b_wptr - mpd->b_rptr);
  430.  
  431.             for (cp = mpd->b_rptr; cp < mpd->b_wptr; cp++) {
  432.                 if (*cp == END || *cp == ESC)
  433.                     num++;
  434.             }
  435.         }
  436.         STRLOG (SLIPM_ID, 1, 0, SL_TRACE, "slip_uwsrv: # of bytes in packet = %d; # of special character in packet: %d", pktlen, num);
  437.  
  438.         /*
  439.          * allocate message block to be sent down stream
  440.          */
  441.  
  442.         if ((mp2 = allocb (pktlen + num, BPRI_MED)) == NULL) {
  443.             STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_uwsrv: can't allocate message block - dropping outgoing message");
  444.             p_slip->stats.ifs_oerrors++;
  445.             freemsg (mp);
  446.             return;
  447.         }
  448.         /*
  449.          * frame packet, escape special characters ESC and END
  450.          */
  451.  
  452.         *mp2->b_wptr++ = END;
  453.  
  454.         for (mpd = mp->b_cont; mpd != 0; mpd = mpd->b_cont) {
  455.             for (cp = mpd->b_rptr; cp < mpd->b_wptr; cp++) {
  456.                 if (*cp == END) {
  457.                     *mp2->b_wptr++ = ESC;
  458.                     *mp2->b_wptr++ = ESC_END;
  459.                 }
  460.                 else if (*cp == ESC) {
  461.                     *mp2->b_wptr++ = ESC;
  462.                     *mp2->b_wptr++ = ESC_ESC;
  463.                 }
  464.                 else
  465.                     *mp2->b_wptr++ = *cp;
  466.             }
  467.         }
  468.         *mp2->b_wptr++ = END;
  469.  
  470.         mp2->b_datap->db_type = M_DATA;
  471.         p_slip->stats.ifs_opackets++;
  472.         freemsg (mp);
  473.         slip_lwput (p_slip->qbot, mp2);
  474.     }
  475. }
  476.  
  477. /*
  478.  * slip_lwput
  479.  */
  480.  
  481. #ifndef DEBUG
  482. static
  483. #endif
  484. slip_lwput (q, mp)
  485. queue_t *q;
  486. mblk_t  *mp;
  487. {
  488.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lwput: enter %x, %x",q , mp);
  489.  
  490.     if (canput(q->q_next)) {
  491.         STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lwput: putnext");
  492.         putnext(q, mp);
  493.     }
  494.     else {
  495.         STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lwput: putq");
  496.         putq(q, mp);
  497.     }
  498. }
  499.  
  500. /*
  501.  * slip_lwsrv (q)
  502.  */
  503.  
  504. #ifndef DEBUG
  505. static
  506. #endif
  507. slip_lwsrv (q)
  508. queue_t *q;
  509. {
  510.     mblk_t  *mp;
  511.     slip_t *p_slip;
  512.  
  513.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE,"slip_lwsrv: enter");
  514.  
  515.     while (mp = getq(q)) {
  516.         STRLOG (SLIPM_ID, 0, 0, SL_TRACE,"slip_lwsrv: getq (%x) = %x",q, mp);
  517.         if (canput(q->q_next)) {
  518.             STRLOG (SLIPM_ID, 0, 0, SL_TRACE,"slip_lwsrv: putnext");
  519.             putnext(q, mp);
  520.         }
  521.         else {
  522.             STRLOG (SLIPM_ID, 0, 0, SL_TRACE,"slip_lwsrv: putbq");
  523.             putbq(q, mp);
  524.             return;
  525.         }
  526.     }
  527.     p_slip = (slip_t *) q->q_ptr;
  528.  
  529.     if (p_slip->qt_blocked) {
  530.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_lwsrv: slip_uwsrv is blocked, enable it");
  531.         /*
  532.          * qtop is the upper read q and
  533.          * we want to enable the upper write q
  534.          */
  535.         qenable (WR(p_slip->qtop));
  536.         p_slip->qt_blocked = 0;
  537.     }
  538. }
  539.  
  540. /*
  541.  * slip_lrput ()
  542.  */
  543.  
  544. #ifndef DEBUG
  545. static
  546. #endif
  547. slip_lrput (q, mp)
  548. queue_t    *q;
  549. mblk_t    *mp;
  550. {
  551.     slip_t     *p_slip;
  552.     mblk_t    *resp;
  553.     int        device;
  554.     int        oldpri;
  555.  
  556.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lrput: enter: case 0x%2.2x", mp->b_datap->db_type);
  557.     p_slip = (slip_t *) q->q_ptr;
  558.  
  559.     switch (mp->b_datap->db_type) {
  560.  
  561.     case M_DATA:
  562.         STRLOG (SLIPM_ID,2,0,SL_TRACE,"slip_lrput: putq (%x, %x)", q, mp);
  563.         putq (q, mp);
  564.         break;
  565.  
  566.     case M_FLUSH:
  567.         STRLOG (SLIPM_ID,2,0,SL_TRACE,"slip_lrput: M_FLUSH type = %x",*mp->b_rptr);
  568.         if (*mp->b_rptr & FLUSHR)
  569.             flushq(q, FLUSHALL);
  570.         if (*mp->b_rptr & FLUSHW) {
  571.             *mp->b_rptr &= ~FLUSHR;
  572.             flushq(WR(q), FLUSHALL);
  573.             qreply(q, mp);
  574.         } else
  575.             freemsg(mp);
  576.         return;
  577.  
  578.     case M_HANGUP:
  579.         oldpri = splstr ();
  580.         /*
  581.          * if pid is set, ignore message
  582.          */
  583.         if (p_slip->pid == 0)
  584.             freemsg (mp);
  585.         /*
  586.          * else if slip hangup daemon exists send pid to the daemon
  587.          */
  588.         else if (slip_hup && (resp = allocb (sizeof(pid_t),BPRI_MED))) {
  589.             STRLOG (SLIPM_ID,1,0,SL_TRACE,
  590.                 "slip_lrput: sending pid %d to hangup daemon", p_slip->pid);
  591.             *(pid_t *) resp->b_wptr = p_slip->pid;
  592.             resp->b_wptr += sizeof (pid_t);
  593.             resp->b_datap->db_type = M_PCPROTO;
  594.             putnext (slip_hup->qtop, resp);
  595.             freemsg (mp);
  596.         }
  597.         /*
  598.          * else pass the message upstream
  599.          */
  600.         else
  601.             putnext (p_slip->qtop, mp);
  602.  
  603.         splx (oldpri);
  604.         break;
  605.             
  606.     default:
  607.         putnext (p_slip->qtop, mp);
  608.         break;
  609.     }
  610. }
  611.  
  612. /*
  613.  * slip_lrsrv ()
  614.  */
  615.  
  616. #ifndef DEBUG
  617. static
  618. #endif
  619. slip_lrsrv (q)
  620. queue_t    *q;
  621. {
  622.     register    u_char     *cp;
  623.     register    slip_t     *p_slip;
  624.     mblk_t        *bp, *mp, *mp1, *mp2;
  625.  
  626.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lrsrv: enter");
  627.  
  628.     while ((mp = getq(q)) != NULL) {
  629.         p_slip = (slip_t *) q->q_ptr;
  630.  
  631. STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_lrsrv: q=%x, mp=%x;", q, mp);
  632.         if (!canput (p_slip->qtop->q_next)) {
  633.             putbq (q, mp);
  634.             return;
  635.         }
  636.         p_slip = (slip_t *) q->q_ptr;
  637.  
  638.         for (bp = mp; bp != 0; bp = bp->b_cont) {
  639.             for (cp = bp->b_rptr; cp < bp->b_wptr; cp++) {
  640.                 if (*cp == END) {
  641.                     if (p_slip->inlen < sizeof (struct ip))
  642.                         ;                        /* ignore packet */
  643.  
  644.                     else if (p_slip->overrun)
  645.                         p_slip->stats.ifs_ierrors++;
  646.  
  647.                     else if ((mp1=allocb (DL_UNITDATA_IND_SIZE,BPRI_MED))==NULL)
  648.                         p_slip->stats.ifs_ierrors++;
  649.  
  650.                     else if ((mp2 = allocb (p_slip->inlen, BPRI_MED)) == NULL) {
  651.                         p_slip->stats.ifs_ierrors++;
  652.                         freemsg (mp1);
  653.                     }
  654.                     else {
  655.                         p_slip->stats.ifs_ipackets++;    /* send unit data */
  656.                         linkb (mp1, mp2);                /* indication up */
  657.                         slip_dl_unitdata_ind (q, mp1);    /* stream */
  658.                         putnext (p_slip->qtop, mp1);
  659.                     }
  660.                     p_slip->inlen = 0;                    /* reset info for */
  661.                     p_slip->overrun = 0;                /* receiving data */
  662.                     p_slip->escape = 0;
  663.                 }
  664.                 else if (p_slip->inlen >= SLIPMTU)
  665.                     p_slip->overrun = 1;
  666.  
  667.                 else if (*cp == ESC)                    /* if data is ESC */
  668.                     p_slip->escape = 1;
  669.  
  670.                 else if (p_slip->escape) {
  671.                     p_slip->escape = 0;
  672.  
  673.                     if (*cp == ESC_END)
  674.                         *(p_slip->buf + p_slip->inlen++) = END;
  675.                     else if (*cp == ESC_ESC)
  676.                         *(p_slip->buf + p_slip->inlen++) = ESC;
  677.                     else
  678.                         *(p_slip->buf + p_slip->inlen++) = *cp;
  679.                 }
  680.                 else
  681.                     *(p_slip->buf + p_slip->inlen++) = *cp;
  682.             }
  683.             bp->b_rptr = cp;
  684.         }
  685.         freemsg (mp);
  686.     }
  687. }
  688.  
  689. /*
  690.  * slip_dl_cmds ()
  691.  */
  692.  
  693. #ifndef DEBUG
  694. static
  695. #endif
  696. slip_dl_cmds (q, mp)
  697. queue_t    *q;
  698. mblk_t    *mp;
  699. {
  700.     union DL_primitives    *p_dl;
  701.     mblk_t                *response;
  702.     slip_t                *p_slip;
  703.     int        oldpri;
  704.  
  705.     if ((response = allocb (DL_PRIM_SIZE, BPRI_MED)) == NULL) {
  706.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: can't allocate response buffer");
  707.         freemsg (mp);
  708.         return;
  709.     }
  710.  
  711.     p_slip = (slip_t *) q->q_ptr;
  712.     p_dl = (union DL_primitives *) mp->b_datap->db_base;
  713.  
  714.     switch (p_dl->dl_primitive) {
  715.  
  716.     case DL_INFO_REQ:
  717.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: DL_INFO_REQ");
  718.         slip_dl_info_ack (q, mp, response);
  719.         break;
  720.  
  721.     case DL_BIND_REQ:
  722.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: DL_BIND_REQ");
  723.         if (p_slip->state == DL_UNBOUND) {
  724.             oldpri = splstr ();
  725.             p_slip->sap   = ((dl_bind_req_t *)p_dl)->dl_sap;
  726.             p_slip->state = DL_IDLE;
  727.             p_slip->stats.ifs_active = 1;
  728.             splx (oldpri);
  729.  
  730.             slip_dl_bind_ack (q, mp, response);
  731.         }
  732.         else
  733.             slip_dl_error_ack (q, mp, response, DL_OUTSTATE);
  734.         break;
  735.  
  736.     case DL_UNBIND_REQ:
  737.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: DL_UNBIND_REQ");
  738.         if (p_slip->state == DL_IDLE) {
  739.             oldpri = splstr ();
  740.             p_slip->state = DL_UNBOUND;
  741.             p_slip->stats.ifs_active = 0;
  742.             splx (oldpri);
  743.  
  744.             flushq (q, FLUSHDATA);                        /* Flush both q's */
  745.             flushq (RD(q), FLUSHDATA);
  746.  
  747.             slip_dl_ok_ack (q, mp, response);
  748.         }
  749.         else
  750.             slip_dl_error_ack (q, mp, response, DL_OUTSTATE);
  751.  
  752.         break;
  753.  
  754.     case DL_UNITDATA_REQ:
  755.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: DL_UNITDATA_REQ");
  756.         if (p_slip->state == DL_IDLE) {
  757.             STRLOG (SLIPM_ID,2,0,SL_TRACE,"slip_dl_cmd: putq (%x, %x)", q, mp);
  758.             putq (q, mp);
  759.             return;
  760.         }
  761.         else
  762.             slip_dl_error_ack (q, mp, response, DL_OUTSTATE);
  763.  
  764.         break;
  765.  
  766.     default:
  767.         STRLOG (SLIPM_ID,1,0,SL_TRACE,"slip_dl_cmd: default 0x%2.2x",p_dl->dl_primitive);
  768.         slip_dl_error_ack (q, mp, response, DL_UNSUPPORTED);
  769.         break;
  770.     }
  771.     freemsg (mp);
  772.     putnext (RD(q), response);
  773. }
  774.  
  775. /*
  776.  *  slip_dl_info_ack ()
  777.  */
  778.  
  779. #ifndef DEBUG
  780. static
  781. #endif
  782. slip_dl_info_ack (q, mp, response)
  783. queue_t *q;
  784. mblk_t    *mp;
  785. mblk_t    *response;
  786. {
  787.     dl_info_ack_t    *p_info_ack;
  788.     slip_t            *p_slip;
  789.  
  790.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_dl_info_ack: enter");
  791.  
  792.     p_slip = (slip_t *) q->q_ptr;
  793.  
  794.     p_info_ack = (dl_info_ack_t *) response->b_wptr;
  795.     p_info_ack->dl_primitive     = DL_INFO_ACK;
  796.     p_info_ack->dl_max_sdu       = SLIPMTU;
  797.  
  798.     p_info_ack->dl_min_sdu       = 46;                  /* ????? */
  799.     p_info_ack->dl_addr_length   = 0;                    /* ????? MAC_ADD_SIZE*/
  800.     p_info_ack->dl_mac_type      = DL_CHAR;                /* ????? */
  801.  
  802.     p_info_ack->dl_current_state = p_slip->state;
  803.     p_info_ack->dl_service_mode  = DL_CLDLS;            /* connecionless DL */
  804.  
  805.     p_info_ack->dl_qos_length       = 0;                /* ???? */
  806.     p_info_ack->dl_qos_offset       = 0;                /* ???? */
  807.     p_info_ack->dl_qos_range_length = 0;                /* ???? */
  808.     p_info_ack->dl_qos_range_offset = 0;                /* ???? */
  809.  
  810.     p_info_ack->dl_provider_style = DL_STYLE1;
  811.  
  812.     p_info_ack->dl_addr_offset = 0;                        /* ???? */
  813.     p_info_ack->dl_growth = 0;
  814.  
  815.     response->b_datap->db_type = M_PCPROTO;
  816.     response->b_wptr           += DL_INFO_ACK_SIZE;
  817. }
  818.  
  819. /*
  820.  *  slip_dl_bind_ack ()
  821.  */
  822.  
  823. #ifndef DEBUG
  824. static
  825. #endif
  826. slip_dl_bind_ack (q, mp, response)
  827. queue_t *q;
  828. mblk_t    *mp;
  829. mblk_t    *response;
  830. {
  831.     dl_bind_req_t    *p_dl;
  832.     dl_bind_ack_t    *p_bind;
  833.  
  834.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_dl_bind_ack: enter");
  835.  
  836.     p_dl = (dl_bind_req_t *) mp->b_datap->db_base;
  837.  
  838.     p_bind = (dl_bind_ack_t *) response->b_wptr;
  839.     p_bind->dl_primitive   = DL_BIND_ACK;
  840.     p_bind->dl_sap         = p_dl->dl_sap;
  841.     p_bind->dl_addr_length = 0;
  842.     p_bind->dl_addr_offset = 0;
  843.  
  844.     response->b_wptr           += DL_BIND_ACK_SIZE;
  845.     response->b_datap->db_type = M_PCPROTO;
  846. }
  847.  
  848. /*
  849.  *  slip_dl_ok_ack ()
  850.  */
  851.  
  852. #ifndef DEBUG
  853. static
  854. #endif
  855. slip_dl_ok_ack (q, mp, response)
  856. queue_t *q;
  857. mblk_t    *mp;
  858. mblk_t    *response;
  859. {
  860.     union DL_primitives    *p_dl;
  861.     dl_ok_ack_t            *p_ok_ack;
  862.  
  863.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_dl_ok_ack: enter");
  864.  
  865.     p_dl = (union DL_primitives *) mp->b_datap->db_base;
  866.  
  867.     p_ok_ack = (dl_ok_ack_t *)(response->b_wptr);
  868.     p_ok_ack->dl_primitive         = DL_OK_ACK;
  869.     p_ok_ack->dl_correct_primitive = p_dl->dl_primitive;
  870.  
  871.     response->b_wptr           += DL_OK_ACK_SIZE;
  872.     response->b_datap->db_type = M_PCPROTO;
  873. }
  874.  
  875. /*
  876.  * slip_dl_error_ack
  877.  */
  878.  
  879. #ifndef DEBUG
  880. static
  881. #endif
  882. slip_dl_error_ack (q, mp, response, dl_errno)
  883. queue_t *q;
  884. mblk_t    *mp;
  885. mblk_t    *response;
  886. ulong    dl_errno;
  887. {
  888.     union DL_primitives    *p_dl;
  889.     dl_error_ack_t        *p_error;
  890.  
  891.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_dl_error_ack: enter");
  892.  
  893.     p_dl = (union DL_primitives *) mp->b_datap->db_base;
  894.  
  895.     p_error = (dl_error_ack_t *) response->b_wptr;
  896.     p_error->dl_primitive       = DL_ERROR_ACK;
  897.     p_error->dl_error_primitive = p_dl->dl_primitive;
  898.     p_error->dl_errno           = dl_errno;
  899.     p_error->dl_unix_errno      = 0;
  900.  
  901.     response->b_wptr           += DL_ERROR_ACK_SIZE;
  902.     response->b_datap->db_type = M_PCPROTO;
  903. }
  904.  
  905. /*
  906.  * slip_dl_unitdata_ind ()
  907.  */
  908.  
  909. #ifndef DEBUG
  910. static
  911. #endif
  912. slip_dl_unitdata_ind (q, mp)
  913. queue_t *q;
  914. mblk_t    *mp;
  915. {
  916.     dl_unitdata_ind_t    *p_dl;
  917.     slip_t                *p_slip;
  918.  
  919.     STRLOG (SLIPM_ID, 0, 0, SL_TRACE, "slip_dl_unitdata_ind: enter");
  920.  
  921.     p_dl = (dl_unitdata_ind_t *) mp->b_wptr;
  922.     p_dl->dl_primitive = DL_UNITDATA_IND;
  923.     p_dl->dl_dest_addr_length = 0;
  924.     p_dl->dl_dest_addr_offset = DL_UNITDATA_IND_SIZE;
  925.     p_dl->dl_src_addr_length = 0;
  926.     p_dl->dl_src_addr_offset = p_dl->dl_dest_addr_offset + p_dl->dl_dest_addr_length;
  927.  
  928.     mp->b_wptr += DL_UNITDATA_IND_SIZE;
  929.     mp->b_datap->db_type = M_PROTO;
  930.  
  931.     /* copy packet received to the next message block */
  932.  
  933.     p_slip = (slip_t *) q->q_ptr;
  934.  
  935.     bcopy ((caddr_t)p_slip->buf, (caddr_t)mp->b_cont->b_wptr, p_slip->inlen);
  936.  
  937.     mp->b_cont->b_wptr += p_slip->inlen;
  938. }
  939.