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

Cache object: 9179f529f9020c64332177557b0e8f1f


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