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

Cache object: 71feec2001d9ff81715efaf2bdc2eed0


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