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/netiso/if_cons.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: if_cons.c,v 1.15 2003/08/07 16:33:35 agc Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 1991, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the University nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  *
   31  *      @(#)if_cons.c   8.1 (Berkeley) 6/10/93
   32  */
   33 
   34 /***********************************************************
   35                 Copyright IBM Corporation 1987
   36 
   37                       All Rights Reserved
   38 
   39 Permission to use, copy, modify, and distribute this software and its
   40 documentation for any purpose and without fee is hereby granted,
   41 provided that the above copyright notice appear in all copies and that
   42 both that copyright notice and this permission notice appear in
   43 supporting documentation, and that the name of IBM not be
   44 used in advertising or publicity pertaining to distribution of the
   45 software without specific, written prior permission.
   46 
   47 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
   48 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
   49 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
   50 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
   51 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
   52 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
   53 SOFTWARE.
   54 
   55 ******************************************************************/
   56 
   57 /*
   58  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
   59  */
   60 /*
   61  * cons.c - Connection Oriented Network Service:
   62  * including support for a) user transport-level service,
   63  *      b) COSNS below CLNP, and c) CONS below TP.
   64  */
   65 
   66 #include <sys/cdefs.h>
   67 __KERNEL_RCSID(1, "$NetBSD: if_cons.c,v 1.15 2003/08/07 16:33:35 agc Exp $");
   68 
   69 #ifdef TPCONS
   70 #ifdef _KERNEL
   71 #ifdef ARGO_DEBUG
   72 #define Static
   73 unsigned        LAST_CALL_PCB;
   74 #else                           /* ARGO_DEBUG */
   75 #define Static static
   76 #endif                          /* ARGO_DEBUG */
   77 
   78 #ifndef SOCK_STREAM
   79 #include <sys/param.h>
   80 #include <sys/systm.h>
   81 #include <sys/mbuf.h>
   82 #include <sys/protosw.h>
   83 #include <sys/socket.h>
   84 #include <sys/socketvar.h>
   85 #include <sys/errno.h>
   86 #include <sys/ioctl.h>
   87 
   88 #include <net/if.h>
   89 #include <net/netisr.h>
   90 #include <net/route.h>
   91 
   92 #include <netiso/iso_errno.h>
   93 #include <netiso/argo_debug.h>
   94 #include <netiso/tp_trace.h>
   95 #include <netiso/iso.h>
   96 #include <netiso/cons.h>
   97 #include <netiso/iso_pcb.h>
   98 #include <netiso/iso_var.h>
   99 #include <netiso/tp_var.h>
  100 #include <netiso/clnp.h>
  101 
  102 #include <netccitt/x25.h>
  103 #include <netccitt/pk.h>
  104 #include <netccitt/pk_var.h>
  105 #include <netccitt/pk_extern.h>
  106 #endif
  107 
  108 #ifdef ARGO_DEBUG
  109 #define MT_XCONN        0x50
  110 #define MT_XCLOSE       0x51
  111 #define MT_XCONFIRM     0x52
  112 #define MT_XDATA        0x53
  113 #define MT_XHEADER      0x54
  114 #else
  115 #define MT_XCONN        MT_DATA
  116 #define MT_XCLOSE       MT_DATA
  117 #define MT_XCONFIRM     MT_DATA
  118 #define MT_XDATA        MT_DATA
  119 #define MT_XHEADER      MT_HEADER
  120 #endif  /* ARGO_DEBUG */
  121 
  122 #define DONTCLEAR        -1
  123 
  124 /*********************************************************************
  125  * cons.c - CONS interface to the x.25 layer
  126  *
  127  * TODO: figure out what resources we might run out of besides mbufs.
  128  *  If we run out of any of them (including mbufs) close and recycle
  129  *  lru x% of the connections, for some parameter x.
  130  *
  131  * There are 2 interfaces from above:
  132  * 1) from TP0:
  133  *    cons CO network service
  134  *    TP associates a transport connection with a network connection.
  135  *        cons_output( isop, m, len, isdgm==0 )
  136  *        co_flags == 0
  137  * 2) from TP4:
  138  *        It's a datagram service, like clnp is. - even though it calls
  139  *                      cons_output( isop, m, len, isdgm==1 )
  140  *        it eventually goes through
  141  *                      cosns_output(ifp, m, dst).
  142  *    TP4 permits multiplexing (reuse, possibly simultaneously) of the
  143  *        network connections.
  144  *    This means that many sockets (many tpcbs) may be associated with
  145  *    this pklcd, hence cannot have a back ptr from pklcd to a tpcb.
  146  *        co_flags & CONSF_DGM
  147  *    co_socket is null since there may be many sockets that use this pklcd.
  148  * NOTE:
  149  *      streams would really be nice. sigh.
  150  * NOTE:
  151  *      PVCs could be handled by config-ing a cons with an address and with the
  152  *      IFF_POINTTOPOINT flag on.  This code would then have to skip the
  153  *      connection setup stuff for pt-to-pt links.
  154  *
  155  *********************************************************************/
  156 
  157 
  158 #define CONS_IFQMAXLEN 5
  159 
  160 Static int make_partial_x25_packet __P((struct isopcb *, struct pklcd *));
  161 Static int NSAPtoDTE __P((struct sockaddr_iso *, struct sockaddr_x25 *));
  162 Static int FACILtoNSAP __P((struct sockaddr_iso *, u_char *));
  163 Static void init_siso __P((struct sockaddr_iso *));
  164 Static int DTEtoNSAP __P((struct sockaddr_iso *, struct sockaddr_x25 *));
  165 Static int parse_facil __P((struct pklcd *, struct isopcb *, caddr_t, u_char));
  166 
  167 /* protosw pointers for getting to higher layer */
  168 Static struct protosw *CLNP_proto;
  169 Static struct protosw *TP_proto;
  170 Static struct protosw *X25_proto;
  171 
  172 extern struct isopcb tp_isopcb; /* chain of all TP pcbs */
  173 
  174 
  175 #define HIGH_NIBBLE 1
  176 #define LOW_NIBBLE 0
  177 
  178 /*
  179  * NAME:        nibble_copy()
  180  * FUNCTION and ARGUMENTS:
  181  *      copies (len) nibbles from (src_octet), high or low nibble
  182  *  to (dst_octet), high or low nibble,
  183  * src_nibble & dst_nibble should be:
  184  *      HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble
  185  *      LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble
  186  * RETURNS: VOID
  187  */
  188 void
  189 nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len)
  190         char  *src_octet;
  191         char  *dst_octet;
  192         unsigned src_nibble;
  193         unsigned dst_nibble;
  194         int             len;
  195 {
  196 
  197         int i;
  198         unsigned dshift, sshift;
  199 
  200 #ifdef ARGO_DEBUG
  201         if (argo_debug[D_CADDR]) {
  202                 printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
  203                     src_octet, src_nibble, dst_octet, dst_nibble, len);
  204         }
  205 #endif
  206 #define SHIFT 0x4
  207 
  208         dshift = dst_nibble << 2;
  209         sshift = src_nibble << 2;
  210 
  211         for (i = 0; i < len; i++) {
  212                 /* clear dst_nibble  */
  213                 *dst_octet &= ~(0xf << dshift);
  214 
  215                 /* set dst nibble */
  216                 *dst_octet |= (0xf & (*src_octet >> sshift)) << dshift;
  217 
  218                 dshift ^= SHIFT;
  219                 sshift ^= SHIFT;
  220                 src_nibble = 1 - src_nibble;
  221                 dst_nibble = 1 - dst_nibble;
  222                 src_octet += src_nibble;
  223                 dst_octet += dst_nibble;
  224         }
  225 #ifdef ARGO_DEBUG
  226         if (argo_debug[D_CADDR]) {
  227                 printf("nibble_copy DONE\n");
  228         }
  229 #endif
  230 }
  231 
  232 /*
  233  * NAME:        nibble_match()
  234  * FUNCTION and ARGUMENTS:
  235  *      compares src_octet/src_nibble and dst_octet/dst_nibble  for len nibbles.
  236  * RETURNS: 0 if they differ, 1 if they are the same.
  237  */
  238 int
  239 nibble_match(src_octet, src_nibble, dst_octet, dst_nibble, len)
  240         char  *src_octet;
  241         char  *dst_octet;
  242         unsigned src_nibble;
  243         unsigned dst_nibble;
  244         int             len;
  245 {
  246 
  247         int i;
  248         unsigned dshift, sshift;
  249         u_char          nibble_a, nibble_b;
  250 
  251 #ifdef ARGO_DEBUG
  252         if (argo_debug[D_CADDR]) {
  253                 printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n",
  254                        src_octet, src_nibble, dst_octet, dst_nibble, len);
  255         }
  256 #endif
  257 #define SHIFT 0x4
  258 
  259         dshift = dst_nibble << 2;
  260         sshift = src_nibble << 2;
  261 
  262         for (i = 0; i < len; i++) {
  263                 nibble_b = ((*dst_octet) >> dshift) & 0xf;
  264                 nibble_a = (0xf & (*src_octet >> sshift));
  265                 if (nibble_b != nibble_a)
  266                         return 0;
  267 
  268                 dshift ^= SHIFT;
  269                 sshift ^= SHIFT;
  270                 src_nibble = 1 - src_nibble;
  271                 dst_nibble = 1 - dst_nibble;
  272                 src_octet += src_nibble;
  273                 dst_octet += dst_nibble;
  274         }
  275 #ifdef ARGO_DEBUG
  276         if (argo_debug[D_CADDR]) {
  277                 printf("nibble_match DONE\n");
  278         }
  279 #endif
  280         return 1;
  281 }
  282 
  283 /*
  284  **************************** NET PROTOCOL cons ***************************
  285  */
  286 /*
  287  * NAME:        cons_init()
  288  * CALLED FROM:
  289  *      autoconf
  290  * FUNCTION:
  291  *      initialize the protocol
  292  */
  293 void
  294 cons_init()
  295 {
  296         CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM);
  297         X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM);
  298         TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET);
  299 #ifdef ARGO_DEBUG
  300         if (argo_debug[D_CCONS]) {
  301                 printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n",
  302                        CLNP_proto, X25_proto, TP_proto);
  303         }
  304 #endif
  305 #ifdef notdef
  306         pk_protolisten(0x81, 0, clnp_incoming);
  307         pk_protolisten(0x82, 0, esis_incoming);
  308         pk_protolisten(0x84, 0, tp8878_A_incoming);
  309         pk_protolisten(0, 0, tp_incoming);
  310 #endif
  311 }
  312 
  313 int
  314 tp_incoming(m, v)
  315         struct mbuf *m;
  316         void *v;
  317 {
  318         struct pklcd   *lcp = v;
  319         struct isopcb *isop;
  320 
  321         if (iso_pcballoc(NULL, &tp_isopcb)) {
  322                 pk_close(lcp);
  323                 return 0;
  324         }
  325         isop = tp_isopcb.isop_next;
  326         lcp->lcd_upper = cons_tpinput;
  327         lcp->lcd_upnext = (caddr_t) isop;
  328         lcp->lcd_send(lcp);     /* Confirms call */
  329         isop->isop_chan = (caddr_t) lcp;
  330         isop->isop_laddr = &isop->isop_sladdr;
  331         isop->isop_faddr = &isop->isop_sfaddr;
  332         DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
  333         DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
  334         parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data),
  335                     m->m_pkthdr.len - PKHEADERLN);
  336         return 0;
  337 }
  338 
  339 int
  340 cons_tpinput(m0, v)
  341         struct mbuf    *m0;
  342         void *v;
  343 {
  344         struct pklcd   *lcp = v;
  345         struct isopcb *isop = (struct isopcb *) lcp->lcd_upnext;
  346         int             cmd, ptype = PK_CLEAR;
  347 
  348         if (isop == 0)
  349                 return 0;
  350         if (m0 == 0)
  351                 goto dead;
  352         switch (m0->m_type) {
  353         case MT_DATA:
  354         case MT_OOBDATA:
  355                 tpcons_input(m0, isop->isop_faddr, isop->isop_laddr,
  356                              (caddr_t) lcp);
  357                 return 0;
  358 
  359         case MT_CONTROL:
  360                 switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) {
  361 
  362                 case PK_RR:
  363                         cmd = PRC_CONS_SEND_DONE;
  364                         break;
  365 
  366                 case PK_CALL_ACCEPTED:
  367                         if (lcp->lcd_sb.sb_mb)
  368                                 lcp->lcd_send(lcp);     /* XXX - fix this */
  369                         /* FALLTHROUGH */
  370                 default:
  371                         return 0;
  372 
  373         dead:
  374                 case PK_CLEAR:
  375                 case PK_CLEAR_CONF:
  376                         lcp->lcd_upper = 0;
  377                         lcp->lcd_upnext = 0;
  378                         isop->isop_chan = 0;
  379                 case PK_RESET:
  380                         cmd = PRC_ROUTEDEAD;
  381                 }
  382                 tpcons_ctlinput(cmd, (struct sockaddr *) isop->isop_faddr,
  383                                 isop);
  384                 if (cmd == PRC_ROUTEDEAD && isop->isop_refcnt == 0)
  385                         iso_pcbdetach(isop);
  386         }
  387         return 0;
  388 }
  389 
  390 /*
  391  * NAME:        cons_connect()
  392  * CALLED FROM:
  393  *      tpcons_pcbconnect() when opening a new connection.
  394  * FUNCTION anD ARGUMENTS:
  395  *  Figures out which device to use, finding a route if one doesn't
  396  *  already exist.
  397  * RETURN VALUE:
  398  *  returns E*
  399  */
  400 int
  401 cons_connect(isop)
  402         struct isopcb *isop;
  403 {
  404         struct pklcd *lcp = (struct pklcd *) isop->isop_chan;
  405         int             error;
  406 
  407 #ifdef ARGO_DEBUG
  408         if (argo_debug[D_CCONN]) {
  409                 printf("cons_connect(0x%x): ", isop);
  410                 dump_isoaddr(isop->isop_faddr);
  411                 printf("myaddr: ");
  412                 dump_isoaddr(isop->isop_laddr);
  413                 printf("\n");
  414         }
  415 #endif
  416         NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
  417         lcp->lcd_upper = cons_tpinput;
  418         lcp->lcd_upnext = (caddr_t) isop;
  419 #ifdef ARGO_DEBUG
  420         if (argo_debug[D_CCONN]) {
  421                 printf(
  422                     "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
  423                     &lcp->lcd_faddr, &lcp->lcd_laddr,
  424                     isop->isop_socket->so_proto->pr_protocol);
  425         }
  426 #endif
  427         if ((error = make_partial_x25_packet(isop, lcp)) == 0)
  428                 error = pk_connect(lcp, &lcp->lcd_faddr);
  429         return error;
  430 }
  431 
  432 /*
  433  **************************** DEVICE cons ***************************
  434  */
  435 
  436 
  437 /*
  438  * NAME:        cons_ctlinput() CALLED FROM: lower layer when ECN_CLEAR
  439  * occurs : this routine is here for consistency - cons subnet service calls
  440  * its higher layer through the protosw entry. FUNCTION & ARGUMENTS: cmd is a
  441  * PRC_* command, list found in ../sys/protosw.h copcb is the obvious. This
  442  * serves the higher-layer cons service. NOTE: this takes 3rd arg. because
  443  * cons uses it to inform itself of things (timeouts, etc) but has a pcb
  444  * instead of an address.
  445  */
  446 void *
  447 cons_ctlinput(cmd, sa, v)
  448         int             cmd;
  449         struct sockaddr *sa;
  450         void *v;
  451 {
  452         return NULL;
  453 }
  454 
  455 
  456 int
  457 find_error_reason(xp)
  458         struct x25_packet *xp;
  459 {
  460         int             error, cause = 0;
  461 
  462         if (xp) {
  463                 cause = 4[(char *) xp];
  464                 switch (cause) {
  465                 case 0x00:
  466                 case 0x80:
  467                         /* DTE originated; look at the diagnostic */
  468                         error = (CONL_ERROR_MASK | cause);
  469                         goto done;
  470 
  471                 case 0x01:      /* number busy */
  472                 case 0x81:
  473                 case 0x09:      /* Out of order */
  474                 case 0x89:
  475                 case 0x11:      /* Remot Procedure Error */
  476                 case 0x91:
  477                 case 0x19:      /* reverse charging accept not subscribed */
  478                 case 0x99:
  479                 case 0x21:      /* Incampat destination */
  480                 case 0xa1:
  481                 case 0x29:      /* fast select accept not subscribed */
  482                 case 0xa9:
  483                 case 0x39:      /* ship absent */
  484                 case 0xb9:
  485                 case 0x03:      /* invalid facil request */
  486                 case 0x83:
  487                 case 0x0b:      /* access barred */
  488                 case 0x8b:
  489                 case 0x13:      /* local procedure error */
  490                 case 0x93:
  491                 case 0x05:      /* network congestion */
  492                 case 0x85:
  493                 case 0x8d:      /* not obtainable */
  494                 case 0x0d:
  495                 case 0x95:      /* RPOA out of order */
  496                 case 0x15:
  497                         /*
  498                          * take out bit 8 so we don't have to have so many
  499                          * perror entries
  500                          */
  501                         error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80));
  502                         goto done;
  503 
  504                 case 0xc1:      /* gateway-detected proc error */
  505                 case 0xc3:      /* gateway congestion */
  506 
  507                         error = (CONL_ERROR_MASK | 0x100 | cause);
  508                         goto done;
  509                 }
  510         }
  511         /* otherwise, a *hopefully* valid perror exists in the e_reason field */
  512         error = xp->packet_data;
  513         if (error == 0) {
  514                 printf("Incoming PKT TYPE 0x%x with reason 0x%x\n",
  515                     pk_decode(xp), cause);
  516                 error = E_CO_HLI_DISCA;
  517         }
  518 done:
  519         return error;
  520 }
  521 
  522 
  523 
  524 #endif                          /* _KERNEL */
  525 
  526 /*
  527  * NAME:        make_partial_x25_packet()
  528  *
  529  * FUNCTION and ARGUMENTS:
  530  *      Makes part of an X.25 call packet, for use by x25.
  531  *  (src) and (dst) are the NSAP-addresses of source and destination.
  532  *      (buf) is a ptr to a buffer into which to write this partial header.
  533  *
  534  *       0                      Facility length (in octets)
  535  *       1                      Facility field, which is a set of:
  536  *        m                     facil code
  537  *        m+1           facil param len (for >2-byte facilities) in octets
  538  *        m+2..p        facil param field
  539  *  q                   user data (protocol identification octet)
  540  *
  541  *
  542  * RETURNS:
  543  *  0 if OK
  544  *  E* if failed.
  545  *
  546  * SIDE EFFECTS:
  547  * Stores facilites mbuf in X.25 control block, where the connect
  548  * routine knows where to look for it.
  549  */
  550 
  551 #ifdef X25_1984
  552 int             cons_use_facils = 1;
  553 #else /* X25_1984  */
  554 int             cons_use_facils = 0;
  555 #endif /* X25_1984  */
  556 
  557 int  cons_use_udata = 1;        /* KLUDGE FOR DEBUGGING */
  558 
  559 Static int
  560 make_partial_x25_packet(isop, lcp)
  561         struct isopcb  *isop;
  562         struct pklcd   *lcp;
  563 {
  564         u_int           proto = 0;
  565         int             flag = 0;
  566         caddr_t         buf;
  567         caddr_t ptr;
  568         int    len = 0;
  569         int             buflen = 0;
  570         caddr_t         facil_len;
  571         struct mbuf    *m = NULL;
  572 
  573 
  574 #ifdef ARGO_DEBUG
  575         if (argo_debug[D_CCONN]) {
  576                 printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  577                     isop->isop_laddr, isop->isop_faddr, proto, m, flag);
  578         }
  579 #endif
  580         if (cons_use_udata) {
  581                 if (isop->isop_x25crud_len > 0) {
  582                         /*
  583                          *      The user specified something. Stick it in
  584                          */
  585                         bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
  586                               isop->isop_x25crud_len);
  587                         lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
  588                 }
  589         }
  590         if (cons_use_facils == 0) {
  591                 lcp->lcd_facilities = 0;
  592                 return 0;
  593         }
  594         m = m_gethdr(M_WAIT, MT_DATA);
  595         buf = mtod(m, caddr_t);
  596         ptr = buf;
  597 
  598         /* ptr now points to facil length (len of whole facil field in OCTETS */
  599         facil_len = ptr++;
  600         m->m_len = 0;
  601         pk_build_facilities(m, &lcp->lcd_faddr, 0);
  602 
  603 #ifdef ARGO_DEBUG
  604         if (argo_debug[D_CADDR]) {
  605                 printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr,
  606                     isop->isop_laddr->siso_addr.isoa_len);
  607         }
  608 #endif
  609         if (cons_use_facils) {
  610                 *ptr++ = 0;     /* Marker to separate X.25 facitilies from
  611                                  * CCITT ones */
  612                 *ptr++ = 0x0f;
  613                 *ptr = 0xcb;    /* calling facility code */
  614                 ptr++;
  615                 ptr++;          /* leave room for facil param len (in OCTETS
  616                                  * + 1) */
  617                 ptr++;          /* leave room for the facil param len (in
  618                                  * nibbles), high two bits of which indicate
  619                                  * full/partial NSAP */
  620                 len = isop->isop_laddr->siso_addr.isoa_len;
  621                 bcopy(isop->isop_laddr->siso_data, ptr, len);
  622                 *(ptr - 2) = len + 1;   /* facil param len in octets */
  623                 *(ptr - 1) = len << 1;  /* facil param len in nibbles */
  624                 ptr += len;
  625 
  626 #ifdef ARGO_DEBUG
  627                 if (argo_debug[D_CADDR]) {
  628                         printf("make_partial  called: ptr 0x%x, len 0x%x\n", ptr,
  629                             isop->isop_faddr->siso_addr.isoa_len);
  630                 }
  631 #endif
  632                 *ptr = 0xc9;    /* called facility code */
  633                 ptr++;
  634                 ptr++;          /* leave room for facil param len (in OCTETS
  635                                  * + 1) */
  636                 ptr++;          /* leave room for the facil param len (in
  637                                  * nibbles), high two bits of which indicate
  638                                  * full/partial NSAP */
  639                 len = isop->isop_faddr->siso_nlen;
  640                 bcopy(isop->isop_faddr->siso_data, ptr, len);
  641                 *(ptr - 2) = len + 1;   /* facil param len = addr len + 1 for
  642                                          * each of these two length fields,
  643                                          * in octets */
  644                 *(ptr - 1) = len << 1;  /* facil param len in nibbles */
  645                 ptr += len;
  646 
  647         }
  648         *facil_len = ptr - facil_len - 1;
  649         if (*facil_len > MAX_FACILITIES)
  650                 return E_CO_PNA_LONG;
  651 
  652         buflen = (int) (ptr - buf);
  653 
  654 #ifdef ARGO_DEBUG
  655         if (argo_debug[D_CDUMP_REQ]) {
  656                 int    i;
  657 
  658                 printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n",
  659                     buf, buflen, buflen);
  660                 for (i = 0; i < buflen;) {
  661                         printf("+%d: %x %x %x %x    %x %x %x %x\n",
  662                             i,
  663                             *(buf + i), *(buf + i + 1), *(buf + i + 2), *(buf + i + 3),
  664                             *(buf + i + 4), *(buf + i + 5), *(buf + i + 6), *(buf + i + 7));
  665                         i += 8;
  666                 }
  667         }
  668 #endif
  669 #ifdef ARGO_DEBUG
  670         if (argo_debug[D_CADDR]) {
  671                 printf("make_partial returns buf 0x%x size 0x%x bytes\n",
  672                        mtod(m, caddr_t), buflen);
  673         }
  674 #endif
  675 
  676         if (buflen > MHLEN)
  677                 return E_CO_PNA_LONG;
  678 
  679         m->m_pkthdr.len = m->m_len = buflen;
  680         lcp->lcd_facilities = m;
  681         return 0;
  682 }
  683 
  684 /*
  685  * NAME:        NSAPtoDTE()
  686  * CALLED FROM:
  687  *  make_partial_x25_packet()
  688  * FUNCTION and ARGUMENTS:
  689  *  get a DTE address from an NSAP-address (struct sockaddr_iso)
  690  *  (dst_octet) is the octet into which to begin stashing the DTE addr
  691  *  (dst_nibble) takes 0 or 1.  1 means begin filling in the DTE addr
  692  *              in the high-order nibble of dst_octet.  0 means low-order nibble.
  693  *  (addr) is the NSAP-address
  694  *  (flag) is true if the transport suffix is to become the
  695  *              last two digits of the DTE address
  696  *  A DTE address is a series of ASCII digits
  697  *
  698  *      A DTE address may have leading zeros. The are significant.
  699  *              1 digit per nibble, may be an odd number of nibbles.
  700  *
  701  *  An NSAP-address has the DTE address in the IDI. Leading zeros are
  702  *              significant. Trailing hex f indicates the end of the DTE address.
  703  *      The IDI is a series of BCD digits, one per nibble.
  704  *
  705  * RETURNS
  706  *  # significant digits in the DTE address, -1 if error.
  707  */
  708 
  709 Static int
  710 NSAPtoDTE(siso, sx25)
  711         struct sockaddr_iso *siso;
  712         struct sockaddr_x25 *sx25;
  713 {
  714         int             dtelen = -1;
  715 
  716 #ifdef ARGO_DEBUG
  717         if (argo_debug[D_CADDR]) {
  718                 printf("NSAPtoDTE: nsap: %s\n",
  719                     clnp_iso_addrp(&siso->siso_addr));
  720         }
  721 #endif
  722 
  723         if (siso->siso_data[0] == AFI_37) {
  724                 char  *out = sx25->x25_addr;
  725                 char  *in = siso->siso_data + 1;
  726                 int    nibble;
  727                 char           *lim = siso->siso_data + siso->siso_nlen;
  728                 char           *olim = out + 15;
  729                 int             lowNibble = 0;
  730 
  731                 while (in < lim) {
  732                         nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30;
  733                         lowNibble ^= 1;
  734                         if (nibble != 0x3f && out < olim)
  735                                 *out++ = nibble;
  736                 }
  737                 dtelen = out - sx25->x25_addr;
  738                 *out++ = 0;
  739         } else {
  740                 /*
  741                  * error = iso_8208snparesolve(addr, x121string,
  742                  * &x121strlen);
  743                  */
  744                 struct rtentry *rt;
  745                 extern struct sockaddr_iso blank_siso;
  746                 struct sockaddr_iso nsiso;
  747 
  748                 nsiso = blank_siso;
  749                 bcopy(nsiso.siso_data, siso->siso_data,
  750                       nsiso.siso_nlen = siso->siso_nlen);
  751                 if ((rt = rtalloc1((struct sockaddr *) &nsiso, 1)) != NULL) {
  752                         struct sockaddr_x25 *sxx =
  753                         (struct sockaddr_x25 *) rt->rt_gateway;
  754                         char  *in = sxx->x25_addr;
  755 
  756                         rt->rt_use--;
  757                         if (sxx && sxx->x25_family == AF_CCITT) {
  758                                 bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr));
  759                                 while (*in++) {
  760                                 }
  761                                 dtelen = in - sxx->x25_addr;
  762                         }
  763                 }
  764         }
  765         return dtelen;
  766 }
  767 
  768 /*
  769  * NAME:        FACILtoNSAP()
  770  * CALLED FROM:
  771  *  parse_facil()
  772  * FUNCTION and ARGUMENTS:
  773  *      Creates and NSAP in the sockaddr_iso (addr) from the
  774  *  x.25 facility found at buf - 1.
  775  * RETURNS:
  776  *  0 if ok, -1 if error.
  777  */
  778 
  779 Static int
  780 FACILtoNSAP(addr, buf)
  781         u_char *buf;
  782         struct sockaddr_iso *addr;
  783 {
  784         int             len_in_nibbles = *++buf & 0x3f;
  785         u_char          buf_len = (len_in_nibbles + 1) >> 1;;   /* in bytes */
  786 
  787 #ifdef ARGO_DEBUG
  788         if (argo_debug[D_CADDR]) {
  789                 printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n",
  790                     buf, buf_len, addr);
  791         }
  792 #endif
  793 
  794         len_in_nibbles = *buf & 0x3f;
  795         /*
  796          * despite the fact that X.25 makes us put a length in nibbles here,
  797          * the NSAP-addrs are always in full octets
  798          */
  799         switch (*buf++ & 0xc0) {
  800         case 0:
  801                 /* Entire OSI NSAP address */
  802                 bcopy((caddr_t) buf, addr->siso_data, addr->siso_nlen = buf_len);
  803                 break;
  804 
  805         case 40:
  806                 /* Partial OSI NSAP address, assume trailing */
  807                 if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr))
  808                         return -1;
  809                 bcopy((caddr_t) buf, TSEL(addr), buf_len);
  810                 addr->siso_nlen += buf_len;
  811                 break;
  812 
  813         default:
  814                 /*
  815                  * Rather than blow away the connection, just ignore and use
  816                  * NSAP from DTE
  817                                  */ ;
  818         }
  819         return 0;
  820 }
  821 
  822 Static void
  823 init_siso(siso)
  824         struct sockaddr_iso *siso;
  825 {
  826         siso->siso_len = sizeof(*siso);
  827         siso->siso_family = AF_ISO;
  828         siso->siso_data[0] = AFI_37;
  829         siso->siso_nlen = 8;
  830 }
  831 
  832 /*
  833  * NAME:        DTEtoNSAP()
  834  * CALLED FROM:
  835  *  parse_facil()
  836  * FUNCTION and ARGUMENTS:
  837  *  Creates a type 37 NSAP in the sockaddr_iso (addr)
  838  *      from a DTE address found in a sockaddr_x25.
  839  *
  840  * RETURNS:
  841  *  0 if ok; E* otherwise.
  842  */
  843 
  844 Static int
  845 DTEtoNSAP(addr, sx)
  846         struct sockaddr_iso *addr;
  847         struct sockaddr_x25 *sx;
  848 {
  849         char  *in, *out;
  850         int    first;
  851         int             pad_tail = 0;
  852         int             src_len;
  853 
  854 
  855         init_siso(addr);
  856         in = sx->x25_addr;
  857         src_len = strlen(in);
  858         addr->siso_nlen = (src_len + 3) / 2;
  859         out = addr->siso_data;
  860         *out++ = 0x37;
  861         if (src_len & 1) {
  862                 pad_tail = 0xf;
  863                 src_len++;
  864         }
  865         for (first = 0; src_len > 0; src_len--) {
  866                 first |= 0xf & *in++;
  867                 if (src_len & 1) {
  868                         *out++ = first;
  869                         first = 0;
  870                 } else
  871                         first <<= 4;
  872         }
  873         if (pad_tail)
  874                 out[-1] |= 0xf;
  875         return 0;               /* ok */
  876 }
  877 
  878 /*
  879  * FUNCTION and ARGUMENTS:
  880  *      parses (buf_len) bytes beginning at (buf) and finds
  881  *  a called nsap, a calling nsap, and protocol identifier.
  882  * RETURNS:
  883  *  0 if ok, E* otherwise.
  884  */
  885 
  886 Static int
  887 parse_facil(lcp, isop, buf, buf_len)
  888         caddr_t         buf;
  889         u_char          buf_len;/* in bytes */
  890         struct isopcb  *isop;
  891         struct pklcd   *lcp;
  892 {
  893         int    i;
  894         u_char *ptr = (u_char *) buf;
  895         u_char         *facil_lim;
  896         int             facil_param_len = 0, facil_len;
  897 
  898 #ifdef ARGO_DEBUG
  899         if (argo_debug[D_CADDR]) {
  900                 printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n",
  901                     lcp, isop, buf, buf_len);
  902                 dump_buf(buf, buf_len);
  903         }
  904 #endif
  905 
  906         /*
  907          * find the beginnings of the facility fields in buf by skipping over
  908          * the called & calling DTE addresses i <- # nibbles in called + #
  909          * nibbles in calling i += 1 so that an odd nibble gets rounded up to
  910          * even  before dividing by 2, then divide by two to get # octets
  911          */
  912         i = (int) (*ptr >> 4) + (int) (*ptr & 0xf);
  913         i++;
  914         ptr += i >> 1;
  915         ptr++;                  /* plus one for the DTE lengths byte */
  916 
  917         /* ptr now is at facil_length field */
  918         facil_len = *ptr++;
  919         facil_lim = ptr + facil_len;
  920 #ifdef ARGO_DEBUG
  921         if (argo_debug[D_CADDR]) {
  922                 printf("parse_facils: facil length is  0x%x\n", (int) facil_len);
  923         }
  924 #endif
  925 
  926         while (ptr < facil_lim) {
  927                 /* get NSAP addresses from facilities */
  928                 switch (*ptr++) {
  929                 case 0xcb:
  930                         /* calling NSAP */
  931                         facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr);
  932                         break;
  933                 case 0xc9:
  934                         /* called NSAP */
  935                         facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr);
  936                         break;
  937 
  938                         /* from here to default are legit cases that I ignore */
  939                         /* variable length */
  940                 case 0xca:      /* end-to-end transit delay negot */
  941                 case 0xc6:      /* network user id */
  942                 case 0xc5:      /* charging info : indicating monetary unit */
  943                 case 0xc2:      /* charging info : indicating segment count */
  944                 case 0xc1:      /* charging info : indicating call duration */
  945                 case 0xc4:      /* RPOA extended format */
  946                 case 0xc3:      /* call redirection notification */
  947                         facil_param_len = 0;
  948                         break;
  949 
  950                         /* 1 octet */
  951                 case 0x0a:      /* min. throughput class negot */
  952                 case 0x02:      /* throughput class */
  953                 case 0x03:
  954                 case 0x47:      /* CUG shit */
  955                 case 0x0b:      /* expedited data negot */
  956                 case 0x01:      /* Fast select or reverse charging (example
  957                                  * of intelligent protocol design) */
  958                 case 0x04:      /* charging info : requesting service */
  959                 case 0x08:      /* called line addr modified notification */
  960                 case 0x00:      /* marker to indicate beginning of CCITT
  961                                  * facils */
  962                         facil_param_len = 1;
  963                         break;
  964 
  965                         /* any 2 octets */
  966                 case 0x42:      /* pkt size */
  967                 case 0x43:      /* win size */
  968                 case 0x44:      /* RPOA basic format */
  969                 case 0x41:      /* bilateral CUG shit */
  970                 case 0x49:      /* transit delay selection and indication */
  971                         facil_param_len = 2;
  972                         break;
  973 
  974                 default:
  975                         printf(
  976                             "BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n",
  977                             facil_lim, facil_len, ptr - 1, ptr[-1]);
  978                         /*
  979                          * facil that we don't handle return E_CO_HLI_REJI;
  980                          */
  981                         switch (ptr[-1] & 0xc0) {
  982                         case 0x00:
  983                                 facil_param_len = 1;
  984                                 break;
  985                         case 0x40:
  986                                 facil_param_len = 2;
  987                                 break;
  988                         case 0x80:
  989                                 facil_param_len = 3;
  990                                 break;
  991                         case 0xc0:
  992                                 facil_param_len = 0;
  993                                 break;
  994                         }
  995                 }
  996                 if (facil_param_len == -1)
  997                         return E_CO_REG_ICDA;
  998                 if (facil_param_len == 0)       /* variable length */
  999                         facil_param_len = (int) *ptr++; /* 1 + the real facil
 1000                                                          * param */
 1001                 ptr += facil_param_len;
 1002         }
 1003         return 0;
 1004 }
 1005 
 1006 #endif                          /* TPCONS */

Cache object: fd52d8826d761a3f39b29030b97b02b4


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