home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netccitt / pk_subr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-26  |  24.7 KB  |  1,073 lines

  1. /*
  2.  * Copyright (c) University of British Columbia, 1984
  3.  * Copyright (c) 1990 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * the Laboratory for Computation Vision and the Computer Science Department
  8.  * of the University of British Columbia.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  *    @(#)pk_subr.c    7.16 (Berkeley) 6/6/91
  39.  */
  40.  
  41. #include "param.h"
  42. #include "systm.h"
  43. #include "mbuf.h"
  44. #include "socket.h"
  45. #include "protosw.h"
  46. #include "socketvar.h"
  47. #include "errno.h"
  48. #include "time.h"
  49. #include "kernel.h"
  50.  
  51. #include "../net/if.h"
  52.  
  53. #include "x25.h"
  54. #include "pk.h"
  55. #include "pk_var.h"
  56. #include "x25err.h"
  57.  
  58. int     pk_sendspace = 1024 * 2 + 8;
  59. int     pk_recvspace = 1024 * 2 + 8;
  60.  
  61. struct pklcd_q pklcd_q = {&pklcd_q, &pklcd_q};
  62.  
  63. /* 
  64.  *  Attach X.25 protocol to socket, allocate logical channel descripter
  65.  *  and buffer space, and enter LISTEN state if we are to accept
  66.  *  IN-COMMING CALL packets.  
  67.  *
  68.  */
  69.  
  70. struct pklcd *
  71. pk_attach (so)
  72. struct socket *so;
  73. {
  74.     register struct pklcd *lcp;
  75.     register int error = ENOBUFS;
  76.     int pk_output();
  77.  
  78.     MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
  79.     if (lcp) {
  80.         bzero ((caddr_t)lcp, sizeof (*lcp));
  81.         insque (&lcp -> lcd_q, &pklcd_q);
  82.         lcp -> lcd_state = READY;
  83.         lcp -> lcd_send = pk_output;
  84.         if (so) {
  85.             error = soreserve (so, pk_sendspace, pk_recvspace);
  86.             lcp -> lcd_so = so;
  87.             if (so -> so_options & SO_ACCEPTCONN)
  88.                 lcp -> lcd_state = LISTEN;
  89.         } else
  90.             sbreserve (&lcp -> lcd_sb, pk_sendspace);
  91.     }
  92.     if (so) {
  93.         so -> so_pcb = (caddr_t) lcp;
  94.         so -> so_error = error;
  95.     }
  96.     return (lcp);
  97. }
  98.  
  99. /* 
  100.  *  Disconnect X.25 protocol from socket.
  101.  */
  102.  
  103. pk_disconnect (lcp)
  104. register struct pklcd *lcp;
  105. {
  106.     register struct socket *so = lcp -> lcd_so;
  107.     register struct pklcd *l, *p;
  108.  
  109.     switch (lcp -> lcd_state) {
  110.     case LISTEN: 
  111.         for (p = 0, l = pk_listenhead; l && l != lcp; p = l, l = l -> lcd_listen);
  112.         if (p == 0) {
  113.             if (l != 0)
  114.                 pk_listenhead = l -> lcd_listen;
  115.         }
  116.         else
  117.         if (l != 0)
  118.             p -> lcd_listen = l -> lcd_listen;
  119.         pk_close (lcp);
  120.         break;
  121.  
  122.     case READY: 
  123.         pk_acct (lcp);
  124.         pk_close (lcp);
  125.         break;
  126.  
  127.     case SENT_CLEAR: 
  128.     case RECEIVED_CLEAR: 
  129.         break;
  130.  
  131.     default: 
  132.         pk_acct (lcp);
  133.         if (so) {
  134.             soisdisconnecting (so);
  135.             sbflush (&so -> so_rcv);
  136.         }
  137.         pk_clear (lcp, 241, 0); /* Normal Disconnect */
  138.  
  139.     }
  140. }
  141.  
  142. /* 
  143.  *  Close an X.25 Logical Channel. Discard all space held by the
  144.  *  connection and internal descriptors. Wake up any sleepers.
  145.  */
  146.  
  147. pk_close (lcp)
  148. struct pklcd *lcp;
  149. {
  150.     register struct socket *so = lcp -> lcd_so;
  151.  
  152.     pk_freelcd (lcp);
  153.  
  154.     if (so == NULL)
  155.         return;
  156.  
  157.     so -> so_pcb = 0;
  158.     soisdisconnected (so);
  159.     /* sofree (so);    /* gak!!! you can't do that here */
  160. }
  161.  
  162. /* 
  163.  *  Create a template to be used to send X.25 packets on a logical
  164.  *  channel. It allocates an mbuf and fills in a skeletal packet
  165.  *  depending on its type. This packet is passed to pk_output where
  166.  *  the remainer of the packet is filled in.
  167. */
  168.  
  169. struct mbuf *
  170. pk_template (lcn, type)
  171. int lcn, type;
  172. {
  173.     register struct mbuf *m;
  174.     register struct x25_packet *xp;
  175.  
  176.     MGETHDR (m, M_DONTWAIT, MT_HEADER);
  177.     if (m == 0)
  178.         panic ("pk_template");
  179.     m -> m_act = 0;
  180.  
  181.     /*
  182.      * Efficiency hack: leave a four byte gap at the beginning
  183.      * of the packet level header with the hope that this will
  184.      * be enough room for the link level to insert its header.
  185.      */
  186.     m -> m_data += max_linkhdr;
  187.     m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
  188.  
  189.     xp = mtod (m, struct x25_packet *);
  190.     *(long *)xp = 0;        /* ugly, but fast */
  191. /*    xp -> q_bit = 0;*/
  192.     xp -> fmt_identifier = 1;
  193. /*    xp -> lc_group_number = 0;*/
  194.  
  195.     SET_LCN(xp, lcn);
  196.     xp -> packet_type = type;
  197.  
  198.     return (m);
  199. }
  200.  
  201. /* 
  202.  *  This routine restarts all the virtual circuits. Actually,
  203.  *  the virtual circuits are not "restarted" as such. Instead,
  204.  *  any active switched circuit is simply returned to READY
  205.  *  state.
  206.  */
  207.  
  208. pk_restart (pkp, restart_cause)
  209. register struct pkcb *pkp;
  210. int restart_cause;
  211. {
  212.     register struct mbuf *m;
  213.     register struct pklcd *lcp;
  214.     register int i;
  215.  
  216.     /* Restart all logical channels. */
  217.     if (pkp -> pk_chan == 0)
  218.         return;
  219.     for (i = 1; i <= pkp -> pk_maxlcn; ++i)
  220.         if ((lcp = pkp -> pk_chan[i]) != NULL) {
  221.             if (lcp -> lcd_so) {
  222.                 lcp -> lcd_so -> so_error = ENETRESET;
  223.                 pk_close (lcp);
  224.             } else {
  225.                 pk_flush (lcp);
  226.                 lcp -> lcd_state = READY;
  227.                 if (lcp -> lcd_upper)
  228.                     lcp -> lcd_upper (lcp, 0);
  229.             }
  230.         }
  231.  
  232.     if (restart_cause < 0)
  233.         return;
  234.  
  235.     pkp -> pk_state = DTE_SENT_RESTART;
  236.     lcp = pkp -> pk_chan[0];
  237.     m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
  238.     m -> m_pkthdr.len = m -> m_len += 2;
  239.     mtod (m, struct x25_packet *) -> packet_data = 0;    /* DTE only */
  240.     mtod (m, octet *)[4]  = restart_cause;
  241.     pk_output (lcp);
  242. }
  243.  
  244.  
  245. /* 
  246.  *  This procedure frees up the Logical Channel Descripter.
  247.  */
  248.  
  249. pk_freelcd (lcp)
  250. register struct pklcd *lcp;
  251. {
  252.     if (lcp == NULL)
  253.         return;
  254.  
  255.     if (lcp -> lcd_lcn > 0)
  256.         lcp -> lcd_pkp -> pk_chan[lcp -> lcd_lcn] = NULL;
  257.  
  258.     pk_flush (lcp);
  259.     remque (&lcp -> lcd_q);
  260.     free ((caddr_t)lcp, M_PCB);
  261. }
  262.  
  263.  
  264. /* 
  265.  *  Bind a address and protocol value to a socket.  The important
  266.  *  part is the protocol value - the first four characters of the 
  267.  *  Call User Data field.
  268.  */
  269.  
  270. pk_bind (lcp, nam)
  271. struct pklcd *lcp;
  272. struct mbuf *nam;
  273. {
  274.     register struct pkcb *pkp;
  275.     register struct pklcd *pp;
  276.     register struct sockaddr_x25 *sa;
  277.  
  278.     if (nam == NULL)
  279.         return (EADDRNOTAVAIL);
  280.     if (lcp -> lcd_ceaddr)                /* XXX */
  281.         return (EADDRINUSE);
  282.     if (pk_checksockaddr (nam))
  283.         return (EINVAL);
  284.     sa = mtod (nam, struct sockaddr_x25 *);
  285.  
  286.     /*
  287.      * If the user wishes to accept calls only from a particular
  288.      * net (net != 0), make sure the net is known
  289.      */
  290.  
  291.     if (sa -> x25_net)
  292.         for (pkp = pkcbhead; ; pkp = pkp -> pk_next) {
  293.             if (pkp == 0)
  294.                 return (ENETUNREACH);
  295.             if (pkp -> pk_xcp -> xc_addr.x25_net == sa -> x25_net)
  296.                 break;
  297.         }
  298.  
  299.     /*
  300.      * For ISO's sake permit default listeners, but only one such . . .
  301.      */
  302.     for (pp = pk_listenhead; pp; pp = pp -> lcd_listen) {
  303.         register struct sockaddr_x25 *sa2 = pp -> lcd_ceaddr;
  304.         if ((sa2 -> x25_udlen == sa -> x25_udlen) &&
  305.             (sa2 -> x25_udlen == 0 ||
  306.              (bcmp (sa2 -> x25_udata, sa -> x25_udata,
  307.                 min (sa2 -> x25_udlen, sa -> x25_udlen)) == 0)))
  308.                 return (EADDRINUSE);
  309.     }
  310.     lcp -> lcd_laddr = *sa;
  311.     lcp -> lcd_ceaddr = &lcp -> lcd_laddr;
  312.     return (0);
  313. }
  314.  
  315. /*
  316.  * Include a bound control block in the list of listeners.
  317.  */
  318. pk_listen (lcp)
  319. register struct pklcd *lcp;
  320. {
  321.     register struct pklcd **pp;
  322.  
  323.     if (lcp -> lcd_ceaddr == 0)
  324.         return (EDESTADDRREQ);
  325.  
  326.     lcp -> lcd_state = LISTEN;
  327.     /*
  328.      * Add default listener at end, any others at start.
  329.      */
  330.     if (lcp -> lcd_ceaddr -> x25_udlen == 0) {
  331.         for (pp = &pk_listenhead; *pp; )
  332.             pp = &((*pp) -> lcd_listen);
  333.         *pp = lcp;
  334.     } else {
  335.         lcp -> lcd_listen = pk_listenhead;
  336.         pk_listenhead = lcp;
  337.     }
  338.     return (0);
  339. }
  340. /*
  341.  * Include a listening control block for the benefit of other protocols.
  342.  */
  343. pk_protolisten (spi, spilen, callee)
  344. int (*callee) ();
  345. {
  346.     register struct pklcd *lcp = pk_attach ((struct socket *)0);
  347.     register struct mbuf *nam;
  348.     register struct sockaddr_x25 *sa;
  349.     int error = ENOBUFS;
  350.  
  351.     if (lcp) {
  352.         if (nam = m_getclr (MT_SONAME, M_DONTWAIT)) {
  353.             sa = mtod (nam, struct sockaddr_x25 *);
  354.             sa -> x25_family = AF_CCITT;
  355.             sa -> x25_len = nam -> m_len = sizeof (*sa);
  356.             sa -> x25_udlen = spilen;
  357.             sa -> x25_udata[0] = spi;
  358.             lcp -> lcd_upper = callee;
  359.             lcp -> lcd_flags = X25_MBS_HOLD;
  360.             if ((error = pk_bind (lcp, nam)) == 0)
  361.                 error = pk_listen (lcp);
  362.             (void) m_free (nam);
  363.         }
  364.         if (error)
  365.             pk_freelcd (lcp);
  366.     }
  367.     return error; /* Hopefully Zero !*/
  368. }
  369.  
  370. /*
  371.  * Associate a logical channel descriptor with a network.
  372.  * Fill in the default network specific parameters and then
  373.  * set any parameters explicitly specified by the user or
  374.  * by the remote DTE.
  375.  */
  376.  
  377. pk_assoc (pkp, lcp, sa)
  378. register struct pkcb *pkp;
  379. register struct pklcd *lcp;
  380. register struct sockaddr_x25 *sa;
  381. {
  382.  
  383.     lcp -> lcd_pkp = pkp;
  384.     lcp -> lcd_packetsize = pkp -> pk_xcp -> xc_psize;
  385.     lcp -> lcd_windowsize = pkp -> pk_xcp -> xc_pwsize;
  386.     lcp -> lcd_rsn = MODULUS - 1;
  387.     pkp -> pk_chan[lcp -> lcd_lcn] = lcp;
  388.  
  389.     if (sa -> x25_opts.op_psize)
  390.         lcp -> lcd_packetsize = sa -> x25_opts.op_psize;
  391.     else
  392.         sa -> x25_opts.op_psize = lcp -> lcd_packetsize;
  393.     if (sa -> x25_opts.op_wsize)
  394.         lcp -> lcd_windowsize = sa -> x25_opts.op_wsize;
  395.     else
  396.         sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
  397.     sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
  398.     lcp -> lcd_flags |= sa -> x25_opts.op_flags;
  399.     lcp -> lcd_stime = time.tv_sec;
  400. }
  401.  
  402. pk_connect (lcp, sa)
  403. register struct pklcd *lcp;
  404. register struct sockaddr_x25 *sa;
  405. {
  406.     register struct pkcb *pkp;
  407.  
  408.     if (sa -> x25_addr[0] == '\0')
  409.         return (EDESTADDRREQ);
  410.     if (lcp -> lcd_pkp == 0)
  411.         for (pkp = pkcbhead; ; pkp = pkp -> pk_next) {
  412.         if (pkp == 0)
  413.             return (ENETUNREACH);
  414.         /*
  415.          * use first net configured (last in list
  416.          * headed by pkcbhead) if net is zero
  417.          *
  418.          * This is clearly bogus for many llc2's sharing
  419.          * the same xcp; we will replace this with a
  420.          * routing lookup.
  421.          */
  422.         if (sa -> x25_net == 0 && pkp -> pk_next == 0)
  423.             break;
  424.         if (sa -> x25_net == pkp -> pk_xcp -> xc_addr.x25_net)
  425.             break;
  426.     }
  427.  
  428.     if (pkp -> pk_state != DTE_READY)
  429.         return (ENETDOWN);
  430.     if ((lcp -> lcd_lcn = pk_getlcn (pkp)) == 0)
  431.         return (EMFILE);
  432.     lcp -> lcd_faddr = *sa;
  433.     lcp -> lcd_ceaddr = & lcp -> lcd_faddr;
  434.     pk_assoc (pkp, lcp, lcp -> lcd_ceaddr);
  435.     if (lcp -> lcd_so)
  436.         soisconnecting (lcp -> lcd_so);
  437.     lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
  438.     pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
  439.     return (*pkp -> pk_ia -> ia_start) (lcp);
  440. }
  441.  
  442. struct bcdinfo {
  443.     octet *cp;
  444.     unsigned posn;
  445. };
  446. /* 
  447.  *  Build the rest of the CALL REQUEST packet. Fill in calling
  448.  *  address, facilities fields and the user data field.
  449.  */
  450.  
  451. pk_callrequest (lcp, sa, xcp)
  452. struct pklcd *lcp;
  453. register struct sockaddr_x25 *sa;
  454. register struct x25config *xcp;
  455. {
  456.     register struct x25_calladdr *a;
  457.     register struct mbuf *m = lcp -> lcd_template;
  458.     register struct x25_packet *xp = mtod (m, struct x25_packet *);
  459.     struct bcdinfo b;
  460.  
  461.     if (lcp -> lcd_flags & X25_DBIT)
  462.         xp -> d_bit = 1;
  463.     a = (struct x25_calladdr *) &xp -> packet_data;
  464.     b.cp = (octet *) a -> address_field;
  465.     b.posn = 0;
  466.     a -> called_addrlen = to_bcd (&b, sa, xcp);
  467.     a -> calling_addrlen = to_bcd (&b, &xcp -> xc_addr, xcp);
  468.     if (b.posn & 0x01)
  469.         *b.cp++ &= 0xf0;
  470.     m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
  471.  
  472.     if (lcp -> lcd_facilities) {
  473.         m -> m_pkthdr.len += 
  474.             (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
  475.         lcp -> lcd_facilities = 0;
  476.     } else
  477.         pk_build_facilities (m, sa, (int)xcp -> xc_type);
  478.  
  479.     m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
  480. }
  481.  
  482. pk_build_facilities (m, sa, type)
  483. register struct mbuf *m;
  484. struct sockaddr_x25 *sa;
  485. {
  486.     register octet *cp;
  487.     register octet *fcp;
  488.     register int revcharge;
  489.  
  490.     cp = mtod (m, octet *) + m -> m_len;
  491.     fcp = cp + 1;
  492.     revcharge = sa -> x25_opts.op_flags & X25_REVERSE_CHARGE ? 1 : 0;
  493.     /*
  494.      * This is specific to Datapac X.25(1976) DTEs.  International
  495.      * calls must have the "hi priority" bit on.
  496.      */
  497.     if (type == X25_1976 && sa -> x25_opts.op_psize == X25_PS128)
  498.         revcharge |= 02;
  499.     if (revcharge) {
  500.         *fcp++ = FACILITIES_REVERSE_CHARGE;
  501.         *fcp++ = revcharge;
  502.     }
  503.     switch (type) {
  504.     case X25_1980:
  505.     case X25_1984:
  506.         *fcp++ = FACILITIES_PACKETSIZE;
  507.         *fcp++ = sa -> x25_opts.op_psize;
  508.         *fcp++ = sa -> x25_opts.op_psize;
  509.  
  510.         *fcp++ = FACILITIES_WINDOWSIZE;
  511.         *fcp++ = sa -> x25_opts.op_wsize;
  512.         *fcp++ = sa -> x25_opts.op_wsize;
  513.     }
  514.     *cp = fcp - cp - 1;
  515.     m -> m_pkthdr.len = (m -> m_len += *cp + 1);
  516. }
  517.  
  518. to_bcd (b, sa, xcp)
  519. register struct bcdinfo *b;
  520. struct sockaddr_x25 *sa;
  521. register struct x25config *xcp;
  522. {
  523.     register char *x = sa -> x25_addr;
  524.     unsigned start = b -> posn;
  525.     /*
  526.      * The nodnic and prepnd0 stuff looks tedious,
  527.      * but it does allow full X.121 addresses to be used,
  528.      * which is handy for routing info (& OSI type 37 addresses).
  529.      */
  530.     if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
  531.         char dnicname[sizeof(long) * NBBY/3 + 2];
  532.         register char *p = dnicname;
  533.  
  534.         sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
  535.         for (; *p; p++) /* *p == 0 means dnic matched */
  536.             if ((*p ^ *x++) & 0x0f)
  537.                 break;
  538.         if (*p || xcp -> xc_nodnic == 0)
  539.             x = sa -> x25_addr;
  540.         if (*p && xcp -> xc_prepnd0) {
  541.             if ((b -> posn)++ & 0x01)
  542.                 *(b -> cp)++;
  543.             else
  544.                 *(b -> cp) = 0;
  545.         }
  546.     }
  547.     while (*x)
  548.         if ((b -> posn)++ & 0x01)
  549.             *(b -> cp)++ |= *x++ & 0x0F;
  550.         else
  551.             *(b -> cp) = *x++ << 4;
  552.     return ((b -> posn) - start);
  553. }
  554.  
  555. /* 
  556.  *  This routine gets the  first available logical channel number.  The
  557.  *  search is from the highest number to lowest number (DTE).
  558.  */
  559.  
  560. pk_getlcn (pkp)
  561. register struct pkcb *pkp;
  562. {
  563.     register int i;
  564.  
  565.     if (pkp -> pk_chan == 0)
  566.         return (0);
  567.     for (i = pkp -> pk_maxlcn; i > 0; --i)
  568.         if (pkp -> pk_chan[i] == NULL)
  569.             break;
  570.     return (i);
  571.  
  572. }
  573.  
  574. /* 
  575.  *  This procedure sends a CLEAR request packet. The lc state is
  576.  *  set to "SENT_CLEAR". 
  577.  */
  578.  
  579. pk_clear (lcp, diagnostic, abortive)
  580. register struct pklcd *lcp;
  581. {
  582.     register struct mbuf *m = pk_template (lcp -> lcd_lcn, X25_CLEAR);
  583.  
  584.     m -> m_len += 2;
  585.     mtod (m, struct x25_packet *) -> packet_data = 0;
  586.     mtod (m, octet *)[4] = diagnostic;
  587.     if (lcp -> lcd_facilities) {
  588.         m -> m_next = lcp -> lcd_facilities;
  589.         m -> m_pkthdr.len += m -> m_next -> m_len;
  590.         lcp -> lcd_facilities = 0;
  591.     }
  592.     if (abortive)
  593.         lcp -> lcd_template = m;
  594.     else {
  595.         struct socket *so = lcp -> lcd_so;
  596.         struct sockbuf *sb = so ? & so -> so_snd : & lcp -> lcd_sb;
  597.         sbappendrecord (sb, m);
  598.     }
  599.     pk_output (lcp);
  600.  
  601. }
  602.  
  603. /*
  604.  * This procedure generates RNR's or RR's to inhibit or enable
  605.  * inward data flow, if the current state changes (blocked ==> open or
  606.  * vice versa), or if forced to generate one.  One forces RNR's to ack data.  
  607.  */
  608. pk_flowcontrol (lcp, inhibit, forced)
  609. register struct pklcd *lcp;
  610. {
  611.     inhibit = (inhibit != 0);
  612.     if (lcp == 0 || lcp -> lcd_state != DATA_TRANSFER ||
  613.         (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
  614.         return;
  615.     lcp -> lcd_rxrnr_condition = inhibit;
  616.     lcp -> lcd_template =
  617.         pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
  618.     pk_output (lcp);
  619. }
  620.  
  621. /* 
  622.  *  This procedure sends a RESET request packet. It re-intializes
  623.  *  virtual circuit.
  624.  */
  625.  
  626. static
  627. pk_reset (lcp, diagnostic)
  628. register struct pklcd *lcp;
  629. {
  630.     register struct mbuf *m;
  631.     register struct socket *so = lcp -> lcd_so;
  632.  
  633.     if (lcp -> lcd_state != DATA_TRANSFER)
  634.         return;
  635.  
  636.     if (so)
  637.         so -> so_error = ECONNRESET;
  638.     lcp -> lcd_reset_condition = TRUE;
  639.  
  640.     /* Reset all the control variables for the channel. */
  641.     pk_flush (lcp);
  642.     lcp -> lcd_window_condition = lcp -> lcd_rnr_condition =
  643.         lcp -> lcd_intrconf_pending = FALSE;
  644.     lcp -> lcd_rsn = MODULUS - 1;
  645.     lcp -> lcd_ssn = 0;
  646.     lcp -> lcd_output_window = lcp -> lcd_input_window =
  647.         lcp -> lcd_last_transmitted_pr = 0;
  648.     m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
  649.     m -> m_pkthdr.len = m -> m_len += 2;
  650.     mtod (m, struct x25_packet *) -> packet_data = 0;
  651.     mtod (m, octet *)[4] = diagnostic;
  652.     pk_output (lcp);
  653.  
  654. }
  655.  
  656. /*
  657.  * This procedure frees all data queued for output or delivery on a
  658.  *  virtual circuit.
  659.  */
  660.  
  661. pk_flush (lcp)
  662. register struct pklcd *lcp;
  663. {
  664.     register struct socket *so;
  665.  
  666.     if (lcp -> lcd_template)
  667.         m_freem (lcp -> lcd_template);
  668.  
  669.     if (lcp -> lcd_cps) {
  670.         m_freem (lcp -> lcd_cps);
  671.         lcp -> lcd_cps = 0;
  672.     }
  673.     if (lcp -> lcd_facilities) {
  674.         m_freem (lcp -> lcd_facilities);
  675.         lcp -> lcd_facilities = 0;
  676.     }
  677.     if (so = lcp -> lcd_so) {
  678.         sbflush (&so -> so_rcv);
  679.         sbflush (&so -> so_snd);
  680.     } else 
  681.         sbflush (&lcp -> lcd_sb);
  682. }
  683.  
  684. /* 
  685.  *  This procedure handles all local protocol procedure errors.
  686.  */
  687.  
  688. pk_procerror (error, lcp, errstr, diagnostic)
  689. register struct pklcd *lcp;
  690. char *errstr;
  691. {
  692.  
  693.     pk_message (lcp -> lcd_lcn, lcp -> lcd_pkp -> pk_xcp, errstr);
  694.  
  695.     switch (error) {
  696.     case CLEAR: 
  697.         if (lcp -> lcd_so) {
  698.             lcp -> lcd_so -> so_error = ECONNABORTED;
  699.             soisdisconnecting (lcp -> lcd_so);
  700.         }
  701.         pk_clear (lcp, diagnostic, 1);
  702.         break;
  703.  
  704.     case RESET: 
  705.         pk_reset (lcp, diagnostic);
  706.     }
  707. }
  708.  
  709. /* 
  710.  *  This procedure is called during the DATA TRANSFER state to check 
  711.  *  and  process  the P(R) values  received  in the DATA,  RR OR RNR
  712.  *  packets.
  713.  */
  714.  
  715. pk_ack (lcp, pr)
  716. struct pklcd *lcp;
  717. unsigned pr;
  718. {
  719.     register struct socket *so = lcp -> lcd_so;
  720.  
  721.     if (lcp -> lcd_output_window == pr)
  722.         return (PACKET_OK);
  723.     if (lcp -> lcd_output_window < lcp -> lcd_ssn) {
  724.         if (pr < lcp -> lcd_output_window || pr > lcp -> lcd_ssn) {
  725.             pk_procerror (RESET, lcp,
  726.                 "p(r) flow control error", 2);
  727.             return (ERROR_PACKET);
  728.         }
  729.     }
  730.     else {
  731.         if (pr < lcp -> lcd_output_window && pr > lcp -> lcd_ssn) {
  732.             pk_procerror (RESET, lcp,
  733.                 "p(r) flow control error #2", 2);
  734.             return (ERROR_PACKET);
  735.         }
  736.     }
  737.  
  738.     lcp -> lcd_output_window = pr;        /* Rotate window. */
  739.     if (lcp -> lcd_window_condition == TRUE)
  740.         lcp -> lcd_window_condition = FALSE;
  741.  
  742.     if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel))
  743.         sowwakeup (so);
  744.  
  745.     return (PACKET_OK);
  746. }
  747.  
  748. /* 
  749.  *  This procedure decodes the X.25 level 3 packet returning a 
  750.  *  code to be used in switchs or arrays.
  751.  */
  752.  
  753. pk_decode (xp)
  754. register struct x25_packet *xp;
  755. {
  756.     register int type;
  757.  
  758.     if (xp -> fmt_identifier != 1)
  759.         return (INVALID_PACKET);
  760. #ifdef ancient_history
  761.     /* 
  762.      *  Make sure that the logical channel group number is 0.
  763.      *  This restriction may be removed at some later date.
  764.      */
  765.     if (xp -> lc_group_number != 0)
  766.         return (INVALID_PACKET);
  767. #endif
  768.     /* 
  769.      *  Test for data packet first.
  770.      */
  771.     if (!(xp -> packet_type & DATA_PACKET_DESIGNATOR))
  772.         return (DATA);
  773.  
  774.     /* 
  775.      *  Test if flow control packet (RR or RNR).
  776.      */
  777.     if (!(xp -> packet_type & RR_OR_RNR_PACKET_DESIGNATOR))
  778.         switch (xp -> packet_type & 0x1f) {
  779.         case X25_RR:
  780.             return (RR);
  781.         case X25_RNR:
  782.             return (RNR);
  783.         case X25_REJECT:
  784.             return (REJECT);
  785.         }
  786.  
  787.     /* 
  788.      *  Determine the rest of the packet types.
  789.      */
  790.     switch (xp -> packet_type) {
  791.     case X25_CALL: 
  792.         type = CALL;
  793.         break;
  794.  
  795.     case X25_CALL_ACCEPTED: 
  796.         type = CALL_ACCEPTED;
  797.         break;
  798.  
  799.     case X25_CLEAR: 
  800.         type = CLEAR;
  801.         break;
  802.  
  803.     case X25_CLEAR_CONFIRM: 
  804.         type = CLEAR_CONF;
  805.         break;
  806.  
  807.     case X25_INTERRUPT: 
  808.         type = INTERRUPT;
  809.         break;
  810.  
  811.     case X25_INTERRUPT_CONFIRM: 
  812.         type = INTERRUPT_CONF;
  813.         break;
  814.  
  815.     case X25_RESET: 
  816.         type = RESET;
  817.         break;
  818.  
  819.     case X25_RESET_CONFIRM: 
  820.         type = RESET_CONF;
  821.         break;
  822.  
  823.     case X25_RESTART: 
  824.         type = RESTART;
  825.         break;
  826.  
  827.     case X25_RESTART_CONFIRM: 
  828.         type = RESTART_CONF;
  829.         break;
  830.  
  831.     case X25_DIAGNOSTIC:
  832.         type = DIAG_TYPE;
  833.         break;
  834.  
  835.     default: 
  836.         type = INVALID_PACKET;
  837.     }
  838.     return (type);
  839. }
  840.  
  841. /* 
  842.  *  A restart packet has been received. Print out the reason
  843.  *  for the restart.
  844.  */
  845.  
  846. pk_restartcause (pkp, xp)
  847. struct pkcb *pkp;
  848. register struct x25_packet *xp;
  849. {
  850.     register struct x25config *xcp = pkp -> pk_xcp;
  851.     register int lcn = LCN(xp);
  852.  
  853.     switch (xp -> packet_data) {
  854.     case X25_RESTART_LOCAL_PROCEDURE_ERROR: 
  855.         pk_message (lcn, xcp, "restart: local procedure error");
  856.         break;
  857.  
  858.     case X25_RESTART_NETWORK_CONGESTION: 
  859.         pk_message (lcn, xcp, "restart: network congestion");
  860.         break;
  861.  
  862.     case X25_RESTART_NETWORK_OPERATIONAL: 
  863.         pk_message (lcn, xcp, "restart: network operational");
  864.         break;
  865.  
  866.     default: 
  867.         pk_message (lcn, xcp, "restart: unknown cause");
  868.     }
  869. }
  870.  
  871. #define MAXRESETCAUSE    7
  872.  
  873. int     Reset_cause[] = {
  874.     EXRESET, EXROUT, 0, EXRRPE, 0, EXRLPE, 0, EXRNCG
  875. };
  876.  
  877. /* 
  878.  *  A reset packet has arrived. Return the cause to the user.
  879.  */
  880.  
  881. pk_resetcause (pkp, xp)
  882. struct pkcb *pkp;
  883. register struct x25_packet *xp;
  884. {
  885.     register struct pklcd *lcp =
  886.                 pkp -> pk_chan[LCN(xp)];
  887.     register int code = xp -> packet_data;
  888.  
  889.     if (code > MAXRESETCAUSE)
  890.         code = 7;    /* EXRNCG */
  891.  
  892.     pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
  893.             xp -> packet_data, 4[(u_char *)xp]);
  894.             
  895.     if (lcp -> lcd_so)
  896.         lcp -> lcd_so -> so_error = Reset_cause[code];
  897. }
  898.  
  899. #define MAXCLEARCAUSE    25
  900.  
  901. int     Clear_cause[] = {
  902.     EXCLEAR, EXCBUSY, 0, EXCINV, 0, EXCNCG, 0,
  903.     0, 0, EXCOUT, 0, EXCAB, 0, EXCNOB, 0, 0, 0, EXCRPE,
  904.     0, EXCLPE, 0, 0, 0, 0, 0, EXCRRC
  905. };
  906.  
  907. /* 
  908.  *  A clear packet has arrived. Return the cause to the user.
  909.  */
  910.  
  911. pk_clearcause (pkp, xp)
  912. struct pkcb *pkp;
  913. register struct x25_packet *xp;
  914. {
  915.     register struct pklcd *lcp =
  916.         pkp -> pk_chan[LCN(xp)];
  917.     register int code = xp -> packet_data;
  918.  
  919.     if (code > MAXCLEARCAUSE)
  920.         code = 5;    /* EXRNCG */
  921.     if (lcp -> lcd_so)
  922.         lcp -> lcd_so -> so_error = Clear_cause[code];
  923. }
  924.  
  925. char *
  926. format_ntn (xcp)
  927. register struct x25config *xcp;
  928. {
  929.  
  930.     return (xcp -> xc_addr.x25_addr);
  931. }
  932.  
  933. /* VARARGS1 */
  934. pk_message (lcn, xcp, fmt, a1, a2, a3, a4, a5, a6)
  935. struct x25config *xcp;
  936. char *fmt;
  937. {
  938.  
  939.     if (lcn)
  940.         if (pkcbhead -> pk_next)
  941.             printf ("X.25(%s): lcn %d: ", format_ntn (xcp), lcn);
  942.         else
  943.             printf ("X.25: lcn %d: ", lcn);
  944.     else
  945.         if (pkcbhead -> pk_next)
  946.             printf ("X.25(%s): ", format_ntn (xcp));
  947.         else
  948.             printf ("X.25: ");
  949.  
  950.     printf (fmt, a1, a2, a3, a4, a5, a6);
  951.     printf ("\n");
  952. }
  953.  
  954. pk_fragment (lcp, m0, qbit, mbit, wait)
  955. struct mbuf *m0;
  956. register struct pklcd *lcp;
  957. {
  958.     register struct mbuf *m = m0;
  959.     register struct x25_packet *xp;
  960.     register struct sockbuf *sb;
  961.     struct mbuf *head = 0, *next, **mp = &head, *m_split ();
  962.     int totlen, psize = 1 << (lcp -> lcd_packetsize);
  963.  
  964.     if (m == 0)
  965.         return 0;
  966.     if (m -> m_flags & M_PKTHDR == 0)
  967.         panic ("pk_fragment");
  968.     totlen = m -> m_pkthdr.len;
  969.     m -> m_act = 0;
  970.     sb = lcp -> lcd_so ? &lcp -> lcd_so -> so_snd : & lcp -> lcd_sb;
  971.     do {
  972.         if (totlen > psize) {
  973.             if ((next = m_split (m, psize, wait)) == 0)
  974.                 goto abort;
  975.             totlen -= psize;
  976.         } else
  977.             next = 0;
  978.         M_PREPEND(m, PKHEADERLN, wait);
  979.         if (m == 0)
  980.             goto abort;
  981.         *mp = m;
  982.         mp = & m -> m_act;
  983.         *mp = 0;
  984.         xp = mtod (m, struct x25_packet *);
  985.         0[(char *)xp] = 0;
  986.         if (qbit)
  987.             xp -> q_bit = 1;
  988.         if (lcp -> lcd_flags & X25_DBIT)
  989.             xp -> d_bit = 1;
  990.         xp -> fmt_identifier = 1;
  991.         xp -> packet_type = X25_DATA;
  992.         SET_LCN(xp, lcp -> lcd_lcn);
  993.         if (next || (mbit && (totlen == psize ||
  994.                       (lcp -> lcd_flags & X25_DBIT))))
  995.             MBIT(xp) = 1;
  996.     } while (m = next);
  997.     for (m = head; m; m = next) {
  998.         next = m -> m_act;
  999.         m -> m_act = 0;
  1000.         sbappendrecord (sb, m);
  1001.     }
  1002.     return 0;
  1003. abort:
  1004.     if (wait)
  1005.         panic ("pk_fragment null mbuf after wait");
  1006.     if (next)
  1007.         m_freem (next);
  1008.     for (m = head; m; m = next) {
  1009.         next = m -> m_act;
  1010.         m_freem (m);
  1011.     }
  1012.     return ENOBUFS;
  1013. }
  1014.  
  1015. struct mbuf *
  1016. m_split (m0, len0, wait)
  1017. register struct mbuf *m0;
  1018. int len0;
  1019. {
  1020.     register struct mbuf *m, *n;
  1021.     unsigned len = len0, remain;
  1022.  
  1023.     for (m = m0; m && len > m -> m_len; m = m -> m_next)
  1024.         len -= m -> m_len;
  1025.     if (m == 0)
  1026.         return (0);
  1027.     remain = m -> m_len - len;
  1028.     if (m0 -> m_flags & M_PKTHDR) {
  1029.         MGETHDR(n, wait, m0 -> m_type);
  1030.         if (n == 0)
  1031.             return (0);
  1032.         n -> m_pkthdr.rcvif = m0 -> m_pkthdr.rcvif;
  1033.         n -> m_pkthdr.len = m0 -> m_pkthdr.len - len0;
  1034.         m0 -> m_pkthdr.len = len0;
  1035.         if (m -> m_flags & M_EXT)
  1036.             goto extpacket;
  1037.         if (remain > MHLEN) {
  1038.             /* m can't be the lead packet */
  1039.             MH_ALIGN(n, 0);
  1040.             n -> m_next = m_split (m, len, wait);
  1041.             if (n -> m_next == 0) {
  1042.                 (void) m_free (n);
  1043.                 return (0);
  1044.             } else
  1045.                 return (n);
  1046.         } else
  1047.             MH_ALIGN(n, remain);
  1048.     } else if (remain == 0) {
  1049.         n = m -> m_next;
  1050.         m -> m_next = 0;
  1051.         return (n);
  1052.     } else {
  1053.         MGET(n, wait, m -> m_type);
  1054.         if (n == 0)
  1055.             return (0);
  1056.         M_ALIGN(n, remain);
  1057.     }
  1058. extpacket:
  1059.     if (m -> m_flags & M_EXT) {
  1060.         n -> m_flags |= M_EXT;
  1061.         n -> m_ext = m -> m_ext;
  1062.         mclrefcnt[mtocl (m -> m_ext.ext_buf)]++;
  1063.         n -> m_data = m -> m_data + len;
  1064.     } else {
  1065.         bcopy (mtod (m, caddr_t) + len, mtod (n, caddr_t), remain);
  1066.     }
  1067.     n -> m_len = remain;
  1068.     m -> m_len = len;
  1069.     n -> m_next = m -> m_next;
  1070.     m -> m_next = 0;
  1071.     return (n);
  1072. }
  1073.