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/netccitt/pk_input.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 /*      $NetBSD: pk_input.c,v 1.25 2005/02/26 22:45:10 perry Exp $      */
    2 
    3 /*
    4  * Copyright (c) 1991, 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by the
    8  * Laboratory for Computation Vision and the Computer Science Department
    9  * of the University of British Columbia and the Computer Science
   10  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      @(#)pk_input.c  8.1 (Berkeley) 6/10/93
   37  */
   38 
   39 /*
   40  * Copyright (c) 1984 University of British Columbia.
   41  * Copyright (c) 1992 Computer Science Department IV,
   42  *              University of Erlangen-Nuremberg, Germany.
   43  *
   44  * This code is derived from software contributed to Berkeley by the
   45  * Laboratory for Computation Vision and the Computer Science Department
   46  * of the University of British Columbia and the Computer Science
   47  * Department (IV) of the University of Erlangen-Nuremberg, Germany.
   48  *
   49  * Redistribution and use in source and binary forms, with or without
   50  * modification, are permitted provided that the following conditions
   51  * are met:
   52  * 1. Redistributions of source code must retain the above copyright
   53  *    notice, this list of conditions and the following disclaimer.
   54  * 2. Redistributions in binary form must reproduce the above copyright
   55  *    notice, this list of conditions and the following disclaimer in the
   56  *    documentation and/or other materials provided with the distribution.
   57  * 3. All advertising materials mentioning features or use of this software
   58  *    must display the following acknowledgement:
   59  *      This product includes software developed by the University of
   60  *      California, Berkeley and its contributors.
   61  * 4. Neither the name of the University nor the names of its contributors
   62  *    may be used to endorse or promote products derived from this software
   63  *    without specific prior written permission.
   64  *
   65  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   66  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   67  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   68  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   69  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   70  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   71  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   72  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   73  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   74  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   75  * SUCH DAMAGE.
   76  *
   77  *      @(#)pk_input.c  8.1 (Berkeley) 6/10/93
   78  */
   79 
   80 #include <sys/cdefs.h>
   81 __KERNEL_RCSID(0, "$NetBSD: pk_input.c,v 1.25 2005/02/26 22:45:10 perry Exp $");
   82 
   83 #include "opt_hdlc.h"
   84 #include "opt_llc.h"
   85 
   86 #include <sys/param.h>
   87 #include <sys/systm.h>
   88 #include <sys/mbuf.h>
   89 #include <sys/socket.h>
   90 #include <sys/protosw.h>
   91 #include <sys/socketvar.h>
   92 #include <sys/proc.h>
   93 #include <sys/errno.h>
   94 
   95 #include <net/if.h>
   96 #include <net/if_dl.h>
   97 #include <net/if_llc.h>
   98 #include <net/route.h>
   99 
  100 #include <netccitt/dll.h>
  101 #include <netccitt/x25.h>
  102 #include <netccitt/pk.h>
  103 #include <netccitt/pk_var.h>
  104 #include <netccitt/pk_extern.h>
  105 #include <netccitt/llc_var.h>
  106 #ifdef HDLC
  107 #include <netccitt/hdlc.h>
  108 #include <netccitt/hd_var.h>
  109 #endif
  110 
  111 #include <machine/stdarg.h>
  112 
  113 struct pkcb_q   pkcb_q = {&pkcb_q, &pkcb_q};
  114 
  115 static void prune_dnic __P((char *, char *, char *, struct x25config *));
  116 static void save_extra __P((struct mbuf *, octet *, struct socket *));
  117 
  118 /*
  119  * ccittintr() is the generic interrupt handler for HDLC, LLC2, and X.25. This
  120  * allows to have kernel running X.25 but no HDLC or LLC2 or both (in case we
  121  * employ boards that do all the stuff themselves, e.g. ADAX X.25 or TPS ISDN.)
  122  */
  123 void
  124 ccittintr()
  125 {
  126         extern struct ifqueue pkintrq;
  127         extern struct ifqueue hdintrq;
  128         extern struct ifqueue llcintrq;
  129 
  130 #ifdef HDLC
  131         if (hdintrq.ifq_len)
  132                 hdintr();
  133 #endif
  134 #ifdef LLC
  135         if (llcintrq.ifq_len)
  136                 llcintr();
  137 #endif
  138         if (pkintrq.ifq_len)
  139                 pkintr();
  140 }
  141 
  142 struct pkcb    *
  143 pk_newlink(ia, llnext)
  144         struct x25_ifaddr *ia;
  145         caddr_t         llnext;
  146 {
  147         struct x25config *xcp = &ia->ia_xc;
  148         struct pkcb *pkp;
  149         const struct protosw *pp;
  150         unsigned        size;
  151 
  152         pp = pffindproto(AF_CCITT, (int) xcp->xc_lproto, 0);
  153         if (pp == 0 || pp->pr_output == 0) {
  154                 pk_message(0, xcp, "link level protosw error");
  155                 return ((struct pkcb *) 0);
  156         }
  157         /*
  158          * Allocate a network control block structure
  159          */
  160         size = sizeof(struct pkcb);
  161         pkp = (struct pkcb *) malloc(size, M_PCB, M_WAITOK|M_ZERO);
  162         if (pkp == 0)
  163                 return ((struct pkcb *) 0);
  164         pkp->pk_lloutput = pp->pr_output;
  165         pkp->pk_llctlinput = pp->pr_ctlinput;
  166         pkp->pk_xcp = xcp;
  167         IFAREF(&ia->ia_ifa);
  168         pkp->pk_ia = ia;
  169         pkp->pk_state = DTE_WAITING;
  170         pkp->pk_llnext = llnext;
  171         insque(pkp, &pkcb_q);
  172 
  173         /*
  174          * set defaults
  175          */
  176 
  177         if (xcp->xc_pwsize == 0)
  178                 xcp->xc_pwsize = DEFAULT_WINDOW_SIZE;
  179         if (xcp->xc_psize == 0)
  180                 xcp->xc_psize = X25_PS128;
  181         /*
  182          * Allocate logical channel descriptor vector
  183          */
  184 
  185         (void) pk_resize(pkp);
  186         return (pkp);
  187 }
  188 
  189 
  190 int
  191 pk_dellink(pkp)
  192         struct pkcb *pkp;
  193 {
  194         int    i;
  195         const struct protosw *pp;
  196 
  197         /*
  198          * Essentially we have the choice to
  199          * (a) go ahead and let the route be deleted and
  200          *     leave the pkcb associated with that route
  201          *     as it is, i.e. the connections stay open
  202          * (b) do a pk_disconnect() on all channels associated
  203          *     with the route via the pkcb and then proceed.
  204          *
  205          * For the time being we stick with (b)
  206          */
  207 
  208         for (i = 1; i < pkp->pk_maxlcn; ++i)
  209                 if (pkp->pk_chan[i])
  210                         pk_disconnect(pkp->pk_chan[i]);
  211 
  212         /*
  213          * Free the pkcb
  214          */
  215 
  216         /*
  217          * First find the protoswitch to get hold of the link level
  218          * protocol to be notified that the packet level entity is
  219          * dissolving ...
  220          */
  221         pp = pffindproto(AF_CCITT, (int) pkp->pk_xcp->xc_lproto, 0);
  222         if (pp == 0 || pp->pr_output == 0) {
  223                 pk_message(0, pkp->pk_xcp, "link level protosw error");
  224                 return (EPROTONOSUPPORT);
  225         }
  226         pkp->pk_refcount--;
  227         if (!pkp->pk_refcount) {
  228                 struct dll_ctlinfo ctlinfo;
  229 
  230                 remque(pkp);
  231                 if (pkp->pk_rt->rt_llinfo == (caddr_t) pkp)
  232                         pkp->pk_rt->rt_llinfo = (caddr_t) NULL;
  233 
  234                 /*
  235                  * Tell the link level that the pkcb is dissolving
  236                  */
  237                 if (pp->pr_ctlinput && pkp->pk_llnext) {
  238                         ctlinfo.dlcti_pcb = pkp->pk_llnext;
  239                         ctlinfo.dlcti_rt = pkp->pk_rt;
  240                         (*pp->pr_ctlinput) (PRC_DISCONNECT_REQUEST,
  241                                             (struct sockaddr *)pkp->pk_xcp,
  242                                             &ctlinfo);
  243                 }
  244                 if (pkp->pk_ia != NULL)
  245                         IFAFREE(&pkp->pk_ia->ia_ifa);
  246 
  247                 free((caddr_t) pkp->pk_chan, M_IFADDR);
  248                 free((caddr_t) pkp, M_PCB);
  249         }
  250         return (0);
  251 }
  252 
  253 
  254 int
  255 pk_resize(pkp)
  256         struct pkcb *pkp;
  257 {
  258         struct pklcd   *dev_lcp = 0;
  259         struct x25config *xcp = pkp->pk_xcp;
  260         if (pkp->pk_chan &&
  261             (pkp->pk_maxlcn != xcp->xc_maxlcn)) {
  262                 pk_restart(pkp, X25_RESTART_NETWORK_CONGESTION);
  263                 dev_lcp = pkp->pk_chan[0];
  264                 free((caddr_t) pkp->pk_chan, M_IFADDR);
  265                 pkp->pk_chan = 0;
  266         }
  267         if (pkp->pk_chan == 0) {
  268                 unsigned        size;
  269                 pkp->pk_maxlcn = xcp->xc_maxlcn;
  270                 size = (pkp->pk_maxlcn + 1) * sizeof(struct pklcd *);
  271                 pkp->pk_chan = malloc(size, M_IFADDR, M_WAITOK|M_ZERO);
  272                 if (pkp->pk_chan) {
  273                         /*
  274                          * Allocate a logical channel descriptor for lcn 0
  275                          */
  276                         if (dev_lcp == 0 &&
  277                             (dev_lcp = pk_attach((struct socket *) 0)) == 0)
  278                                 return (ENOBUFS);
  279                         dev_lcp->lcd_state = READY;
  280                         dev_lcp->lcd_pkp = pkp;
  281                         pkp->pk_chan[0] = dev_lcp;
  282                 } else {
  283                         if (dev_lcp)
  284                                 pk_close(dev_lcp);
  285                         return (ENOBUFS);
  286                 }
  287         }
  288         return 0;
  289 }
  290 
  291 /*
  292  * This procedure is called by the link level whenever the link becomes
  293  * operational, is reset, or when the link goes down.
  294  */
  295 /* VARARGS */
  296 void *
  297 pk_ctlinput(code, src, addr)
  298         int             code;
  299         struct sockaddr *src;
  300         void            *addr;
  301 {
  302         struct pkcb *pkp = (struct pkcb *) addr;
  303         struct rtentry *llrt;
  304 
  305         /*XXX correct?*/
  306         if (src->sa_family != AF_CCITT)
  307                 return 0;
  308 
  309         switch (code) {
  310         case PRC_LINKUP:
  311                 if (pkp->pk_state == DTE_WAITING)
  312                         pk_restart(pkp, X25_RESTART_NETWORK_CONGESTION);
  313                 break;
  314 
  315         case PRC_LINKDOWN:
  316                 pk_restart(pkp, -1);    /* Clear all active circuits */
  317                 pkp->pk_state = DTE_WAITING;
  318                 break;
  319 
  320         case PRC_LINKRESET:
  321                 pk_restart(pkp, X25_RESTART_NETWORK_CONGESTION);
  322                 break;
  323 
  324         case PRC_CONNECT_INDICATION:
  325 
  326                 if ((llrt = rtalloc1(src, 0)) == 0)
  327                         return 0;
  328                 else
  329                         llrt->rt_refcnt--;
  330 
  331                 pkp = (((struct npaidbentry *) llrt->rt_llinfo)->np_rt) ?
  332                         (struct pkcb *) (((struct npaidbentry *) llrt->rt_llinfo)->np_rt->rt_llinfo) : (struct pkcb *) 0;
  333                 if (pkp == (struct pkcb *) 0)
  334                         return 0;
  335                 pkp->pk_llnext = addr;
  336 
  337                 return ((caddr_t) pkp);
  338 
  339         case PRC_DISCONNECT_INDICATION:
  340                 pk_restart(pkp, -1);    /* Clear all active circuits */
  341                 pkp->pk_state = DTE_WAITING;
  342                 pkp->pk_llnext = (caddr_t) 0;
  343                 break;
  344         }
  345         return (0);
  346 }
  347 struct ifqueue  pkintrq;
  348 /*
  349  * This routine is called if there are semi-smart devices that do HDLC
  350  * in hardware and want to queue the packet and call level 3 directly
  351  */
  352 void
  353 pkintr()
  354 {
  355         struct mbuf *m;
  356         int    s;
  357 
  358         for (;;) {
  359                 s = splnet();
  360                 IF_DEQUEUE(&pkintrq, m);
  361                 splx(s);
  362                 if (m == 0)
  363                         break;
  364                 if (m->m_len < PKHEADERLN) {
  365                         printf("pkintr: packet too short (len=%d)\n",
  366                             m->m_len);
  367                         m_freem(m);
  368                         continue;
  369                 }
  370                 pk_input(m);
  371         }
  372 }
  373 
  374 struct mbuf    *pk_bad_packet;
  375 struct mbuf_cache pk_input_cache = {0};
  376 /*
  377  * X.25 PACKET INPUT
  378  *
  379  * This procedure is called by a link level procedure whenever an information
  380  * frame is received. It decodes the packet and demultiplexes based on the
  381  * logical channel number.
  382  *
  383  * We change the original conventions of the UBC code here -- since there may be
  384  * multiple pkcb's for a given interface of type 802.2 class 2, we retrieve
  385  * which one it is from m_pkthdr.rcvif (which has been overwritten by lower
  386  * layers); That field is then restored for the benefit of upper layers which
  387  * may make use of it, such as CLNP.
  388  *
  389  */
  390 
  391 #define RESTART_DTE_ORIGINATED(xp) \
  392         (((xp)->packet_cause == X25_RESTART_DTE_ORIGINATED) || \
  393          ((xp)->packet_cause >= X25_RESTART_DTE_ORIGINATED2))
  394 
  395 void
  396 pk_input(struct mbuf *m, ...)
  397 {
  398         struct x25_packet *xp;
  399         struct pklcd *lcp;
  400         struct socket *so = 0;
  401         struct pkcb *pkp;
  402         int             ptype, lcn, lcdstate = LISTEN;
  403 
  404         if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize)
  405                 mbuf_cache(&pk_input_cache, m);
  406         if ((m->m_flags & M_PKTHDR) == 0)
  407                 panic("pkintr");
  408 
  409         if ((pkp = (struct pkcb *) m->m_pkthdr.rcvif) == 0)
  410                 return;
  411         xp = mtod(m, struct x25_packet *);
  412         ptype = pk_decode(xp);
  413         lcn = LCN(xp);
  414         lcp = pkp->pk_chan[lcn];
  415 
  416         /*
  417          * If the DTE is in Restart  state, then it will ignore data,
  418          * interrupt, call setup and clearing, flow control and reset
  419          * packets.
  420          */
  421         if (lcn < 0 || lcn > pkp->pk_maxlcn) {
  422                 pk_message(lcn, pkp->pk_xcp, "illegal lcn");
  423                 m_freem(m);
  424                 return;
  425         }
  426         pk_trace(pkp->pk_xcp, m, "P-In");
  427 
  428         if (pkp->pk_state != DTE_READY && ptype != PK_RESTART &&
  429             ptype != PK_RESTART_CONF) {
  430                 m_freem(m);
  431                 return;
  432         }
  433         if (lcp) {
  434                 so = lcp->lcd_so;
  435                 lcdstate = lcp->lcd_state;
  436         } else {
  437                 if (ptype == PK_CLEAR) {/* idle line probe (Datapac specific) */
  438                         /* send response on lcd 0's output queue */
  439                         lcp = pkp->pk_chan[0];
  440                         lcp->lcd_template = pk_template(lcn, X25_CLEAR_CONFIRM);
  441                         pk_output(lcp);
  442                         m_freem(m);
  443                         return;
  444                 }
  445                 if (ptype != PK_CALL)
  446                         ptype = PK_INVALID_PACKET;
  447         }
  448 
  449         if (lcn == 0 && ptype != PK_RESTART && ptype != PK_RESTART_CONF) {
  450                 pk_message(0, pkp->pk_xcp, "illegal ptype (%d, %s) on lcn 0",
  451                            ptype, pk_name[ptype / MAXSTATES]);
  452                 if (pk_bad_packet)
  453                         m_freem(pk_bad_packet);
  454                 pk_bad_packet = m;
  455                 return;
  456         }
  457         m->m_pkthdr.rcvif = pkp->pk_ia->ia_ifp;
  458 
  459         switch (ptype + lcdstate) {
  460                 /*
  461                  * Incoming Call packet received.
  462                  */
  463         case PK_CALL + LISTEN:
  464                 pk_incoming_call(pkp, m);
  465                 break;
  466 
  467                 /*
  468                  * Call collision: Just throw this "incoming call" away since
  469                  * the DCE will ignore it anyway.
  470                  */
  471         case PK_CALL + SENT_CALL:
  472                 pk_message((int) lcn, pkp->pk_xcp,
  473                            "incoming call collision");
  474                 break;
  475 
  476                 /*
  477                  * Call confirmation packet received. This usually means our
  478                  * previous connect request is now complete.
  479                  */
  480         case PK_CALL_ACCEPTED + SENT_CALL:
  481                 MCHTYPE(m, MT_CONTROL);
  482                 pk_call_accepted(lcp, m);
  483                 break;
  484 
  485                 /*
  486                  * This condition can only happen if the previous state was
  487                  * SENT_CALL. Just ignore the packet, eventually a clear
  488                  * confirmation should arrive.
  489                  */
  490         case PK_CALL_ACCEPTED + SENT_CLEAR:
  491                 break;
  492 
  493                 /*
  494                  * Clear packet received. This requires a complete tear down
  495                  * of the virtual circuit.  Free buffers and control blocks.
  496                  * and send a clear confirmation.
  497                  */
  498         case PK_CLEAR + READY:
  499         case PK_CLEAR + RECEIVED_CALL:
  500         case PK_CLEAR + SENT_CALL:
  501         case PK_CLEAR + DATA_TRANSFER:
  502                 lcp->lcd_state = RECEIVED_CLEAR;
  503                 lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_CLEAR_CONFIRM);
  504                 pk_output(lcp);
  505                 pk_clearcause(pkp, xp);
  506                 if (lcp->lcd_upper) {
  507                         MCHTYPE(m, MT_CONTROL);
  508                         (*lcp->lcd_upper)(m, lcp);
  509                 }
  510                 pk_close(lcp);
  511                 lcp = 0;
  512                 break;
  513 
  514                 /*
  515                  * Clear collision: Treat this clear packet as a
  516                  * confirmation.
  517                  */
  518         case PK_CLEAR + SENT_CLEAR:
  519                 pk_close(lcp);
  520                 break;
  521 
  522                 /*
  523                  * Clear confirmation received. This usually means the
  524                  * virtual circuit is now completely removed.
  525                  */
  526         case PK_CLEAR_CONF + SENT_CLEAR:
  527                 pk_close(lcp);
  528                 break;
  529 
  530                 /*
  531                  * A clear confirmation on an unassigned logical channel -
  532                  * just ignore it. Note: All other packets on an unassigned
  533                  * channel results in a clear.
  534                  */
  535         case PK_CLEAR_CONF + READY:
  536         case PK_CLEAR_CONF + LISTEN:
  537                 break;
  538 
  539                 /*
  540                  * Data packet received. Pass on to next level. Move the Q
  541                  * and M bits into the data portion for the next level.
  542                  */
  543         case PK_DATA + DATA_TRANSFER:
  544                 if (lcp->lcd_reset_condition) {
  545                         ptype = PK_DELETE_PACKET;
  546                         break;
  547                 }
  548                 /*
  549                  * Process the P(S) flow control information in this Data
  550                  * packet. Check that the packets arrive in the correct
  551                  * sequence and that they are within the "lcd_input_window".
  552                  * Input window rotation is initiated by the receive
  553                  * interface.
  554                  */
  555 
  556                 if (PS(xp) != ((lcp->lcd_rsn + 1) % MODULUS) ||
  557                     PS(xp) == ((lcp->lcd_input_window + lcp->lcd_windowsize) % MODULUS)) {
  558                         m_freem(m);
  559                         pk_procerror(PK_RESET, lcp,
  560                                      "p(s) flow control error", 1);
  561                         break;
  562                 }
  563                 lcp->lcd_rsn = PS(xp);
  564 
  565                 if (pk_ack(lcp, PR(xp)) != PACKET_OK) {
  566                         m_freem(m);
  567                         break;
  568                 }
  569                 m->m_data += PKHEADERLN;
  570                 m->m_len -= PKHEADERLN;
  571                 m->m_pkthdr.len -= PKHEADERLN;
  572 
  573                 lcp->lcd_rxcnt++;
  574                 if (lcp->lcd_flags & X25_MBS_HOLD) {
  575                         struct mbuf *n = lcp->lcd_cps;
  576                         int             mbit = MBIT(xp);
  577                         octet           q_and_d_bits;
  578 
  579                         if (n) {
  580                                 n->m_pkthdr.len += m->m_pkthdr.len;
  581                                 while (n->m_next)
  582                                         n = n->m_next;
  583                                 n->m_next = m;
  584                                 m = lcp->lcd_cps;
  585 
  586                                 if (lcp->lcd_cpsmax &&
  587                                     n->m_pkthdr.len > lcp->lcd_cpsmax) {
  588                                         pk_procerror(PK_RESET, lcp,
  589                                                      "C.P.S. overflow", 128);
  590                                         return;
  591                                 }
  592                                 q_and_d_bits = 0xc0 & *(octet *) xp;
  593                                 xp = (struct x25_packet *)
  594                                         (mtod(m, octet *) - PKHEADERLN);
  595                                 *(octet *) xp |= q_and_d_bits;
  596                         }
  597                         if (mbit) {
  598                                 lcp->lcd_cps = m;
  599                                 pk_flowcontrol(lcp, 0, 1);
  600                                 return;
  601                         }
  602                         lcp->lcd_cps = 0;
  603                 }
  604                 if (so == 0)
  605                         break;
  606                 if (lcp->lcd_flags & X25_MQBIT) {
  607                         octet t = (X25GBITS(xp->bits, q_bit)) ? t = 0x80 : 0;
  608 
  609                         if (MBIT(xp))
  610                                 t |= 0x40;
  611                         m->m_data -= 1;
  612                         m->m_len += 1;
  613                         m->m_pkthdr.len += 1;
  614                         *mtod(m, octet *) = t;
  615                 }
  616                 /*
  617                  * Discard Q-BIT packets if the application
  618                  * doesn't want to be informed of M and Q bit status
  619                  */
  620                 if (X25GBITS(xp->bits, q_bit)
  621                     && (lcp->lcd_flags & X25_MQBIT) == 0) {
  622                         m_freem(m);
  623                         /*
  624                          * NB.  This is dangerous: sending a RR here can
  625                          * cause sequence number errors if a previous data
  626                          * packet has not yet been passed up to the application
  627                          * (RR's are normally generated via PRU_RCVD).
  628                          */
  629                         pk_flowcontrol(lcp, 0, 1);
  630                 } else {
  631                         sbappendrecord(&so->so_rcv, m);
  632                         sorwakeup(so);
  633                 }
  634                 break;
  635 
  636                 /*
  637                  * Interrupt packet received.
  638                  */
  639         case PK_INTERRUPT + DATA_TRANSFER:
  640                 if (lcp->lcd_reset_condition)
  641                         break;
  642                 lcp->lcd_intrdata = xp->packet_data;
  643                 lcp->lcd_template = pk_template(lcp->lcd_lcn,
  644                                                 X25_INTERRUPT_CONFIRM);
  645                 pk_output(lcp);
  646                 m->m_data += PKHEADERLN;
  647                 m->m_len -= PKHEADERLN;
  648                 m->m_pkthdr.len -= PKHEADERLN;
  649                 MCHTYPE(m, MT_OOBDATA);
  650                 if (so) {
  651                         if (so->so_options & SO_OOBINLINE)
  652                                 sbinsertoob(&so->so_rcv, m);
  653                         else
  654                                 m_freem(m);
  655                         sohasoutofband(so);
  656                 }
  657                 break;
  658 
  659                 /*
  660                  * Interrupt confirmation packet received.
  661                  */
  662         case PK_INTERRUPT_CONF + DATA_TRANSFER:
  663                 if (lcp->lcd_reset_condition)
  664                         break;
  665                 if (lcp->lcd_intrconf_pending == TRUE)
  666                         lcp->lcd_intrconf_pending = FALSE;
  667                 else
  668                         pk_procerror(PK_RESET, lcp, "unexpected packet", 43);
  669                 break;
  670 
  671                 /*
  672                  * Receiver ready received. Rotate the output window and
  673                  * output any data packets waiting transmission.
  674                  */
  675         case PK_RR + DATA_TRANSFER:
  676                 if (lcp->lcd_reset_condition ||
  677                     pk_ack(lcp, PR(xp)) != PACKET_OK) {
  678                         ptype = PK_DELETE_PACKET;
  679                         break;
  680                 }
  681                 if (lcp->lcd_rnr_condition == TRUE)
  682                         lcp->lcd_rnr_condition = FALSE;
  683                 pk_output(lcp);
  684                 break;
  685 
  686                 /*
  687                  * Receiver Not Ready received. Packets up to the P(R) can be
  688                  * be sent. Condition is cleared with a RR.
  689                  */
  690         case PK_RNR + DATA_TRANSFER:
  691                 if (lcp->lcd_reset_condition ||
  692                     pk_ack(lcp, PR(xp)) != PACKET_OK) {
  693                         ptype = PK_DELETE_PACKET;
  694                         break;
  695                 }
  696                 lcp->lcd_rnr_condition = TRUE;
  697                 break;
  698 
  699                 /*
  700                  * Reset packet received. Set state to FLOW_OPEN.  The Input
  701                  * and Output window edges ar set to zero. Both the send and
  702                  * receive numbers are reset. A confirmation is returned.
  703                  */
  704         case PK_RESET + DATA_TRANSFER:
  705                 if (lcp->lcd_reset_condition)
  706                         /* Reset collision. Just ignore packet. */
  707                         break;
  708 
  709                 pk_resetcause(pkp, xp);
  710                 lcp->lcd_window_condition = lcp->lcd_rnr_condition =
  711                         lcp->lcd_intrconf_pending = FALSE;
  712                 lcp->lcd_output_window = lcp->lcd_input_window =
  713                         lcp->lcd_last_transmitted_pr = 0;
  714                 lcp->lcd_ssn = 0;
  715                 lcp->lcd_rsn = MODULUS - 1;
  716 
  717                 lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_RESET_CONFIRM);
  718                 pk_output(lcp);
  719 
  720                 pk_flush(lcp);
  721                 if (so == 0)
  722                         break;
  723                 wakeup((caddr_t) & so->so_timeo);
  724                 sorwakeup(so);
  725                 sowwakeup(so);
  726                 break;
  727 
  728                 /*
  729                  * Reset confirmation received.
  730                  */
  731         case PK_RESET_CONF + DATA_TRANSFER:
  732                 if (lcp->lcd_reset_condition) {
  733                         lcp->lcd_reset_condition = FALSE;
  734                         pk_output(lcp);
  735                 } else
  736                         pk_procerror(PK_RESET, lcp, "unexpected packet", 32);
  737                 break;
  738 
  739         case PK_DATA + SENT_CLEAR:
  740                 ptype = PK_DELETE_PACKET;
  741         case PK_RR + SENT_CLEAR:
  742         case PK_RNR + SENT_CLEAR:
  743         case PK_INTERRUPT + SENT_CLEAR:
  744         case PK_INTERRUPT_CONF + SENT_CLEAR:
  745         case PK_RESET + SENT_CLEAR:
  746         case PK_RESET_CONF + SENT_CLEAR:
  747                 /*
  748                  * Just ignore p if we have sent a CLEAR already.
  749                  */
  750                 break;
  751 
  752                 /*
  753                  * Restart sets all the permanent virtual circuits to the
  754                  * "Data Transfer" stae and  all the switched virtual
  755                  * circuits to the "Ready" state.
  756                  */
  757         case PK_RESTART + READY:
  758                 switch (pkp->pk_state) {
  759                 case DTE_SENT_RESTART:
  760                         /*
  761                          * Restart collision. If case the restart cause is
  762                          * "DTE originated" we have a DTE-DTE situation and
  763                          * are trying to resolve who is going to play DTE/DCE
  764                          * [ISO 8208:4.2-4.5]
  765                          */
  766                         if (RESTART_DTE_ORIGINATED(xp)) {
  767                                 pk_restart(pkp, X25_RESTART_DTE_ORIGINATED);
  768                                 pk_message(0, pkp->pk_xcp,
  769                                            "RESTART collision");
  770                                 if ((pkp->pk_restartcolls++) > MAXRESTARTCOLLISIONS) {
  771                                         pk_message(0, pkp->pk_xcp,
  772                                             "excessive RESTART collisions");
  773                                         pkp->pk_restartcolls = 0;
  774                                 }
  775                                 break;
  776                         }
  777                         pkp->pk_state = DTE_READY;
  778                         pkp->pk_dxerole |= DTE_PLAYDTE;
  779                         pkp->pk_dxerole &= ~DTE_PLAYDCE;
  780                         pk_message(0, pkp->pk_xcp,
  781                                    "Packet level operational");
  782                         pk_message(0, pkp->pk_xcp,
  783                                    "Assuming DTE role");
  784                         if (pkp->pk_dxerole & DTE_CONNECTPENDING)
  785                                 pk_callcomplete(pkp);
  786                         break;
  787 
  788                 default:
  789                         pk_restart(pkp, -1);
  790                         pk_restartcause(pkp, xp);
  791                         pkp->pk_chan[0]->lcd_template = pk_template(0,
  792                                                        X25_RESTART_CONFIRM);
  793                         pk_output(pkp->pk_chan[0]);
  794                         pkp->pk_state = DTE_READY;
  795                         pkp->pk_dxerole |= RESTART_DTE_ORIGINATED(xp) ? DTE_PLAYDCE :
  796                                 DTE_PLAYDTE;
  797                         if (pkp->pk_dxerole & DTE_PLAYDTE) {
  798                                 pkp->pk_dxerole &= ~DTE_PLAYDCE;
  799                                 pk_message(0, pkp->pk_xcp,
  800                                            "Assuming DTE role");
  801                         } else {
  802                                 pkp->pk_dxerole &= ~DTE_PLAYDTE;
  803                                 pk_message(0, pkp->pk_xcp,
  804                                            "Assuming DCE role");
  805                         }
  806                         if (pkp->pk_dxerole & DTE_CONNECTPENDING)
  807                                 pk_callcomplete(pkp);
  808                 }
  809                 break;
  810 
  811                 /*
  812                  * Restart confirmation received. All logical channels are
  813                  * set to READY.
  814                  */
  815         case PK_RESTART_CONF + READY:
  816                 switch (pkp->pk_state) {
  817                 case DTE_SENT_RESTART:
  818                         pkp->pk_state = DTE_READY;
  819                         pkp->pk_dxerole |= DTE_PLAYDTE;
  820                         pkp->pk_dxerole &= ~DTE_PLAYDCE;
  821                         pk_message(0, pkp->pk_xcp,
  822                                    "Packet level operational");
  823                         pk_message(0, pkp->pk_xcp,
  824                                    "Assuming DTE role");
  825                         if (pkp->pk_dxerole & DTE_CONNECTPENDING)
  826                                 pk_callcomplete(pkp);
  827                         break;
  828 
  829                 default:
  830                         /* Restart local procedure error. */
  831                         pk_restart(pkp, X25_RESTART_LOCAL_PROCEDURE_ERROR);
  832                         pkp->pk_state = DTE_SENT_RESTART;
  833                         pkp->pk_dxerole &= ~(DTE_PLAYDTE | DTE_PLAYDCE);
  834                 }
  835                 break;
  836 
  837         default:
  838                 if (lcp) {
  839                         pk_procerror(PK_CLEAR, lcp, "unknown packet error", 33);
  840                         pk_message(lcn, pkp->pk_xcp,
  841                                    "\"%s\" unexpected in \"%s\" state",
  842                             pk_name[ptype / MAXSTATES], pk_state[lcdstate]);
  843                 } else
  844                         pk_message(lcn, pkp->pk_xcp,
  845                                    "packet arrived on unassigned lcn");
  846                 break;
  847         }
  848         if (so == 0 && lcp && lcp->lcd_upper && lcdstate == DATA_TRANSFER) {
  849                 if (ptype != PK_DATA && ptype != PK_INTERRUPT)
  850                         MCHTYPE(m, MT_CONTROL);
  851                 lcp->lcd_upper(m, lcp);
  852         } else if (ptype != PK_DATA && ptype != PK_INTERRUPT)
  853                 m_freem(m);
  854 }
  855 
  856 static void
  857 prune_dnic(from, to, dnicname, xcp)
  858         char           *from, *to, *dnicname;
  859         struct x25config *xcp;
  860 {
  861         char  *cp1 = from, *cp2 = from;
  862         if (xcp->xc_prepnd0 && *cp1 == '') {
  863                 from = ++cp1;
  864                 goto copyrest;
  865         }
  866         if (xcp->xc_nodnic) {
  867                 for (cp1 = dnicname; (*cp2 = *cp1++) != '\0';)
  868                         cp2++;
  869                 cp1 = from;
  870         }
  871 copyrest:
  872         for (cp1 = dnicname; (*cp2 = *cp1++) != '\0';)
  873                 cp2++;
  874 }
  875 
  876 void
  877 pk_simple_bsd(from, to, lower, len)
  878         octet *from, *to;
  879         int    len, lower;
  880 {
  881         int    c;
  882         while (--len >= 0) {
  883                 c = *from;
  884                 if (lower & 0x01)
  885                         from++;
  886                 else
  887                         c >>= 4;
  888                 c &= 0x0f;
  889                 c |= 0x30;
  890                 *to++ = c;
  891                 lower++;
  892         }
  893         *to = 0;
  894 }
  895 
  896 void
  897 pk_from_bcd(a, iscalling, sa, xcp)
  898         struct x25_calladdr *a;
  899         int             iscalling;
  900         struct sockaddr_x25 *sa;
  901         struct x25config *xcp;
  902 {
  903         octet           buf[MAXADDRLN + 1];
  904         octet          *cp;
  905         unsigned        count;
  906 
  907         bzero((caddr_t) sa, sizeof(*sa));
  908         sa->x25_len = sizeof(*sa);
  909         sa->x25_family = AF_CCITT;
  910         if (iscalling) {
  911                 cp = a->address_field + (X25GBITS(a->addrlens, called_addrlen) / 2);
  912                 count = X25GBITS(a->addrlens, calling_addrlen);
  913                 pk_simple_bsd(cp, buf, X25GBITS(a->addrlens, called_addrlen), count);
  914         } else {
  915                 count = X25GBITS(a->addrlens, called_addrlen);
  916                 pk_simple_bsd(a->address_field, buf, 0, count);
  917         }
  918         if (xcp->xc_addr.x25_net && (xcp->xc_nodnic || xcp->xc_prepnd0)) {
  919                 octet           dnicname[sizeof(long) * NBBY / 3 + 2];
  920 
  921                 snprintf((char *) dnicname, sizeof(dnicname), "%d",
  922                     xcp->xc_addr.x25_net);
  923                 prune_dnic((char *) buf, sa->x25_addr, dnicname, xcp);
  924         } else
  925                 bcopy((caddr_t) buf, (caddr_t) sa->x25_addr, count + 1);
  926 }
  927 
  928 static void
  929 save_extra(m0, fp, so)
  930         struct mbuf    *m0;
  931         octet          *fp;
  932         struct socket  *so;
  933 {
  934         struct mbuf *m;
  935         struct cmsghdr  cmsghdr;
  936         /* XXX: christos:
  937          * used to be m_copy(m, 0, ...)
  938          * I think it is supposed to be m_copy(m0,
  939          */
  940         if ((m = m_copy(m0, 0, (int) M_COPYALL)) != NULL) {
  941                 int             off = fp - mtod(m0, octet *);
  942                 int             len = m->m_pkthdr.len - off + sizeof(cmsghdr);
  943                 cmsghdr.cmsg_len = len;
  944                 cmsghdr.cmsg_level = AF_CCITT;
  945                 cmsghdr.cmsg_type = PK_FACILITIES;
  946                 m_adj(m, off);
  947                 M_PREPEND(m, sizeof(cmsghdr), M_DONTWAIT);
  948                 if (m == 0)
  949                         return;
  950                 bcopy((caddr_t) & cmsghdr, mtod(m, caddr_t), sizeof(cmsghdr));
  951                 MCHTYPE(m, MT_CONTROL);
  952                 sbappendrecord(&so->so_rcv, m);
  953         }
  954 }
  955 
  956 /*
  957  * This routine handles incoming call packets. It matches the protocol field
  958  * on the Call User Data field (usually the first four bytes) with sockets
  959  * awaiting connections.
  960  */
  961 
  962 void
  963 pk_incoming_call(pkp, m0)
  964         struct pkcb    *pkp;
  965         struct mbuf    *m0;
  966 {
  967         struct pklcd *lcp = 0, *l;
  968         struct sockaddr_x25 *sa;
  969         struct x25_calladdr *a;
  970         struct socket *so = 0;
  971         struct x25_packet *xp = mtod(m0, struct x25_packet *);
  972         struct mbuf    *m;
  973         struct x25config *xcp = pkp->pk_xcp;
  974         int             len = m0->m_pkthdr.len;
  975         unsigned        udlen;
  976         char           *errstr = "server unavailable";
  977         octet          *u, *facp;
  978         int             lcn = LCN(xp);
  979 
  980         /*
  981          * First, copy the data from the incoming call packet to a X25
  982          * address descriptor. It is to be regretted that you have to parse
  983          * the facilities into a sockaddr to determine if reverse charging is
  984          * being requested
  985          */
  986         if ((m = m_get(M_DONTWAIT, MT_SONAME)) == 0)
  987                 return;
  988         sa = mtod(m, struct sockaddr_x25 *);
  989         a = (struct x25_calladdr *) & xp->packet_data;
  990         facp = u = (octet *) (a->address_field +
  991                               ((X25GBITS(a->addrlens, called_addrlen) + X25GBITS(a->addrlens, calling_addrlen) + 1) / 2));
  992         u += *u + 1;
  993         udlen = min(16, ((octet *) xp) + len - u);
  994 #if 0
  995         /* Cannot happen; udlen is unsigned */
  996         if (udlen < 0)
  997                 udlen = 0;
  998 #endif
  999         pk_from_bcd(a, 1, sa, pkp->pk_xcp);     /* get calling address */
 1000         pk_parse_facilities(facp, sa);
 1001         bcopy((caddr_t) u, sa->x25_udata, udlen);
 1002         sa->x25_udlen = udlen;
 1003 
 1004         /*
 1005          * Now, loop through the listen sockets looking for a match on the
 1006          * PID. That is the first few octets of the user data field.
 1007          * This is the closest thing to a port number for X.25 packets.
 1008          * It does provide a way of multiplexing services at the user level.
 1009          */
 1010 
 1011         for (l = pk_listenhead.tqh_first; l; l = l->lcd_listen.tqe_next) {
 1012                 struct sockaddr_x25 *sxp = l->lcd_ceaddr;
 1013 
 1014                 if (bcmp(sxp->x25_udata, u, sxp->x25_udlen))
 1015                         continue;
 1016                 if (sxp->x25_net &&
 1017                     sxp->x25_net != xcp->xc_addr.x25_net)
 1018                         continue;
 1019                 /*
 1020                  * don't accept incoming calls with the D-Bit on
 1021                  * unless the server agrees
 1022                  */
 1023                 if (X25GBITS(xp->bits, d_bit) && !(sxp->x25_opts.op_flags & X25_DBIT)) {
 1024                         errstr = "incoming D-Bit mismatch";
 1025                         break;
 1026                 }
 1027                 /*
 1028                  * don't accept incoming collect calls unless
 1029                  * the server sets the reverse charging option.
 1030                  */
 1031                 if ((sxp->x25_opts.op_flags & (X25_OLDSOCKADDR | X25_REVERSE_CHARGE)) == 0 &&
 1032                     sa->x25_opts.op_flags & X25_REVERSE_CHARGE) {
 1033                         errstr = "incoming collect call refused";
 1034                         break;
 1035                 }
 1036                 if (l->lcd_so) {
 1037                         so = sonewconn(l->lcd_so, SS_ISCONNECTED);
 1038                         if (so)
 1039                                 lcp = (struct pklcd *) so->so_pcb;
 1040                 } else
 1041                         lcp = pk_attach((struct socket *) 0);
 1042                 if (lcp == 0) {
 1043                         /*
 1044                          * Insufficient space or too many unaccepted
 1045                          * connections.  Just throw the call away.
 1046                          */
 1047                         errstr = "server malfunction";
 1048                         break;
 1049                 }
 1050                 lcp->lcd_upper = l->lcd_upper;
 1051                 lcp->lcd_upnext = l->lcd_upnext;
 1052                 lcp->lcd_lcn = lcn;
 1053                 lcp->lcd_state = RECEIVED_CALL;
 1054                 sa->x25_opts.op_flags |= (sxp->x25_opts.op_flags &
 1055                                         ~X25_REVERSE_CHARGE) | l->lcd_flags;
 1056                 pk_assoc(pkp, lcp, sa);
 1057                 lcp->lcd_faddr = *sa;
 1058                 lcp->lcd_laddr.x25_udlen = sxp->x25_udlen;
 1059                 lcp->lcd_craddr = &lcp->lcd_faddr;
 1060                 lcp->lcd_template = pk_template(lcp->lcd_lcn, X25_CALL_ACCEPTED);
 1061                 if (lcp->lcd_flags & X25_DBIT) {
 1062                         if (X25GBITS(xp->bits, d_bit))
 1063                                 X25SBITS(mtod(lcp->lcd_template,
 1064                                       struct x25_packet *)->bits, d_bit, 1);
 1065                         else
 1066                                 lcp->lcd_flags &= ~X25_DBIT;
 1067                 }
 1068                 if (so) {
 1069                         pk_output(lcp);
 1070                         soisconnected(so);
 1071                         if (so->so_options & SO_OOBINLINE)
 1072                                 save_extra(m0, facp, so);
 1073                 } else if (lcp->lcd_upper) {
 1074                         (*lcp->lcd_upper) (m0, lcp);
 1075                 }
 1076                 (void) m_free(m);
 1077                 return;
 1078         }
 1079 
 1080         /*
 1081          * If the call fails for whatever reason, we still need to build a
 1082          * skeleton LCD in order to be able to properly  receive the CLEAR
 1083          * CONFIRMATION.
 1084          */
 1085 #ifdef WATERLOO                 /* be explicit */
 1086         if (l == 0 && bcmp(sa->x25_udata, "ean", 3) == 0)
 1087                 pk_message(lcn, pkp->pk_xcp, "host=%s ean%c: %s",
 1088                            sa->x25_addr, sa->x25_udata[3] & 0xff, errstr);
 1089         else if (l == 0 && bcmp(sa->x25_udata, "\1\0\0\0", 4) == 0)
 1090                 pk_message(lcn, pkp->pk_xcp, "host=%s x29d: %s",
 1091                            sa->x25_addr, errstr);
 1092         else
 1093 #endif
 1094                 pk_message(lcn, pkp->pk_xcp, "host=%s pid=%x %x %x %x: %s",
 1095                            sa->x25_addr, sa->x25_udata[0] & 0xff,
 1096                            sa->x25_udata[1] & 0xff, sa->x25_udata[2] & 0xff,
 1097                            sa->x25_udata[3] & 0xff, errstr);
 1098         if ((lcp = pk_attach((struct socket *) 0)) == 0) {
 1099                 (void) m_free(m);
 1100                 return;
 1101         }
 1102         lcp->lcd_lcn = lcn;
 1103         lcp->lcd_state = RECEIVED_CALL;
 1104         pk_assoc(pkp, lcp, sa);
 1105         (void) m_free(m);
 1106         pk_clear(lcp, 0, 1);
 1107 }
 1108 
 1109 void
 1110 pk_call_accepted(lcp, m)
 1111         struct pklcd   *lcp;
 1112         struct mbuf    *m;
 1113 {
 1114         struct x25_calladdr *ap;
 1115         octet *fcp;
 1116         struct x25_packet *xp = mtod(m, struct x25_packet *);
 1117         int             len = m->m_len;
 1118 
 1119         lcp->lcd_state = DATA_TRANSFER;
 1120         if (lcp->lcd_so)
 1121                 soisconnected(lcp->lcd_so);
 1122         if ((lcp->lcd_flags & X25_DBIT) && (X25GBITS(xp->bits, d_bit) == 0))
 1123                 lcp->lcd_flags &= ~X25_DBIT;
 1124         if (len > 3) {
 1125                 ap = (struct x25_calladdr *) & xp->packet_data;
 1126                 fcp = (octet *) ap->address_field + (X25GBITS(ap->addrlens, calling_addrlen) +
 1127                             X25GBITS(ap->addrlens, called_addrlen) + 1) / 2;
 1128                 if (fcp + *fcp <= ((octet *) xp) + len)
 1129                         pk_parse_facilities(fcp, lcp->lcd_ceaddr);
 1130         }
 1131         pk_assoc(lcp->lcd_pkp, lcp, lcp->lcd_ceaddr);
 1132         if (lcp->lcd_so == 0 && lcp->lcd_upper)
 1133                 (*lcp->lcd_upper)(m, lcp);
 1134 }
 1135 
 1136 void
 1137 pk_parse_facilities(fcp, sa)
 1138         octet *fcp;
 1139         struct sockaddr_x25 *sa;
 1140 {
 1141         octet *maxfcp;
 1142 
 1143         maxfcp = fcp + *fcp;
 1144         fcp++;
 1145         while (fcp < maxfcp) {
 1146                 /*
 1147                  * Ignore national DCE or DTE facilities
 1148                  */
 1149                 if (*fcp == 0 || *fcp == 0xff)
 1150                         break;
 1151                 switch (*fcp) {
 1152                 case FACILITIES_WINDOWSIZE:
 1153                         sa->x25_opts.op_wsize = fcp[1];
 1154                         fcp += 3;
 1155                         break;
 1156 
 1157                 case FACILITIES_PACKETSIZE:
 1158                         sa->x25_opts.op_psize = fcp[1];
 1159                         fcp += 3;
 1160                         break;
 1161 
 1162                 case FACILITIES_THROUGHPUT:
 1163                         sa->x25_opts.op_speed = fcp[1];
 1164                         fcp += 2;
 1165                         break;
 1166 
 1167                 case FACILITIES_REVERSE_CHARGE:
 1168                         if (fcp[1] & 01)
 1169                                 sa->x25_opts.op_flags |= X25_REVERSE_CHARGE;
 1170                         /*
 1171                          * Datapac specific: for a X.25(1976) DTE, bit 2
 1172                          * indicates a "hi priority" (eg. international) call.
 1173                          */
 1174                         if (fcp[1] & 02 && sa->x25_opts.op_psize == 0)
 1175                                 sa->x25_opts.op_psize = X25_PS128;
 1176                         fcp += 2;
 1177                         break;
 1178 
 1179                 default:
 1180 #if 0
 1181                          printf("unknown facility %x, class=%d\n", *fcp,
 1182                              (*fcp & 0xc0) >> 6);
 1183 #endif
 1184                         switch ((*fcp & 0xc0) >> 6) {
 1185                         case 0:/* class A */
 1186                                 fcp += 2;
 1187                                 break;
 1188 
 1189                         case 1:
 1190                                 fcp += 3;
 1191                                 break;
 1192 
 1193                         case 2:
 1194                                 fcp += 4;
 1195                                 break;
 1196 
 1197                         case 3:
 1198                                 fcp++;
 1199                                 fcp += *fcp;
 1200                         }
 1201                 }
 1202         }
 1203 }

Cache object: 513c58dcfd05613e4ca441eed674a420


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