149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50648Ssklower * @(#)if_cons.c 7.11 (Berkeley) 07/29/91 849268Sbostic */ 949268Sbostic 1036381Ssklower /*********************************************************** 1136381Ssklower Copyright IBM Corporation 1987 1236381Ssklower 1336381Ssklower All Rights Reserved 1436381Ssklower 1536381Ssklower Permission to use, copy, modify, and distribute this software and its 1636381Ssklower documentation for any purpose and without fee is hereby granted, 1736381Ssklower provided that the above copyright notice appear in all copies and that 1836381Ssklower both that copyright notice and this permission notice appear in 1936381Ssklower supporting documentation, and that the name of IBM not be 2036381Ssklower used in advertising or publicity pertaining to distribution of the 2136381Ssklower software without specific, written prior permission. 2236381Ssklower 2336381Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436381Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536381Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636381Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736381Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836381Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936381Ssklower SOFTWARE. 3036381Ssklower 3136381Ssklower ******************************************************************/ 3236381Ssklower 3336381Ssklower /* 3436381Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536381Ssklower */ 3636381Ssklower /* 3736381Ssklower * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $ 3836381Ssklower * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $ 3936381Ssklower * 4036381Ssklower * cons.c - Connection Oriented Network Service: 4136381Ssklower * including support for a) user transport-level service, 4236381Ssklower * b) COSNS below CLNP, and c) CONS below TP. 4345899Ssklower */ 4436381Ssklower 4545899Ssklower #ifdef TPCONS 4645899Ssklower #ifdef KERNEL 4736381Ssklower #ifdef ARGO_DEBUG 4836381Ssklower #define Static 4936381Ssklower unsigned LAST_CALL_PCB; 5036381Ssklower #else ARGO_DEBUG 5136381Ssklower #define Static static 5236381Ssklower #endif ARGO_DEBUG 5336381Ssklower 5436381Ssklower 5536381Ssklower 5645899Ssklower #ifndef SOCK_STREAM 5736381Ssklower #include "param.h" 5836381Ssklower #include "systm.h" 5936381Ssklower #include "mbuf.h" 6036381Ssklower #include "protosw.h" 6136381Ssklower #include "socket.h" 6236381Ssklower #include "socketvar.h" 6336381Ssklower #include "errno.h" 6436381Ssklower #include "ioctl.h" 6540783Smarc #include "tsleep.h" 6636381Ssklower 6736381Ssklower #include "../net/if.h" 6836381Ssklower #include "../net/netisr.h" 6936381Ssklower #include "../net/route.h" 7036381Ssklower 7145899Ssklower #include "iso_errno.h" 7245899Ssklower #include "argo_debug.h" 7345899Ssklower #include "tp_trace.h" 7445899Ssklower #include "iso.h" 7545899Ssklower #include "cons.h" 7645899Ssklower #include "iso_pcb.h" 7736381Ssklower 7845899Ssklower #include "../netccitt/x25.h" 7945899Ssklower #include "../netccitt/pk.h" 8045899Ssklower #include "../netccitt/pk_var.h" 8145899Ssklower #endif 8245899Ssklower 8336381Ssklower #ifdef ARGO_DEBUG 8436381Ssklower #define MT_XCONN 0x50 8536381Ssklower #define MT_XCLOSE 0x51 8636381Ssklower #define MT_XCONFIRM 0x52 8736381Ssklower #define MT_XDATA 0x53 8836381Ssklower #define MT_XHEADER 0x54 8936381Ssklower #else 9036381Ssklower #define MT_XCONN MT_DATA 9136381Ssklower #define MT_XCLOSE MT_DATA 9236381Ssklower #define MT_XCONFIRM MT_DATA 9336381Ssklower #define MT_XDATA MT_DATA 9436381Ssklower #define MT_XHEADER MT_HEADER 9536381Ssklower #endif ARGO_DEBUG 9636381Ssklower 9736381Ssklower #define DONTCLEAR -1 9836381Ssklower 9936381Ssklower /********************************************************************* 10045899Ssklower * cons.c - CONS interface to the x.25 layer 10136381Ssklower * 10236381Ssklower * TODO: figure out what resources we might run out of besides mbufs. 10336381Ssklower * If we run out of any of them (including mbufs) close and recycle 10436381Ssklower * lru x% of the connections, for some parameter x. 10536381Ssklower * 10645899Ssklower * There are 2 interfaces from above: 10736381Ssklower * 1) from TP0: 10836381Ssklower * cons CO network service 10936381Ssklower * TP associates a transport connection with a network connection. 11036381Ssklower * cons_output( isop, m, len, isdgm==0 ) 11136381Ssklower * co_flags == 0 11245899Ssklower * 2) from TP4: 11336381Ssklower * It's a datagram service, like clnp is. - even though it calls 11436381Ssklower * cons_output( isop, m, len, isdgm==1 ) 11536381Ssklower * it eventually goes through 11636381Ssklower * cosns_output(ifp, m, dst). 11736381Ssklower * TP4 permits multiplexing (reuse, possibly simultaneously) of the 11836381Ssklower * network connections. 11936381Ssklower * This means that many sockets (many tpcbs) may be associated with 12045899Ssklower * this pklcd, hence cannot have a back ptr from pklcd to a tpcb. 12136381Ssklower * co_flags & CONSF_DGM 12245899Ssklower * co_socket is null since there may be many sockets that use this pklcd. 12336381Ssklower * 12436381Ssklower NOTE: 12536381Ssklower streams would really be nice. sigh. 12636381Ssklower NOTE: 12736381Ssklower PVCs could be handled by config-ing a cons with an address and with the 12836381Ssklower IFF_POINTTOPOINT flag on. This code would then have to skip the 12936381Ssklower connection setup stuff for pt-to-pt links. 13036381Ssklower 13136381Ssklower 13236381Ssklower *********************************************************************/ 13336381Ssklower 13436381Ssklower 13536381Ssklower #define CONS_IFQMAXLEN 5 13636381Ssklower 13736381Ssklower 13836381Ssklower /* protosw pointers for getting to higher layer */ 13936381Ssklower Static struct protosw *CLNP_proto; 14036381Ssklower Static struct protosw *TP_proto; 14136381Ssklower Static struct protosw *X25_proto; 14236381Ssklower Static int issue_clear_req(); 14336381Ssklower 14436381Ssklower #ifndef PHASEONE 14536381Ssklower extern struct ifaddr *ifa_ifwithnet(); 14636381Ssklower #endif PHASEONE 14736381Ssklower 14836381Ssklower extern struct ifaddr *ifa_ifwithaddr(); 14936381Ssklower 15036381Ssklower extern struct isopcb tp_isopcb; /* chain of all TP pcbs */ 15136381Ssklower 15236381Ssklower 15336381Ssklower Static int parse_facil(), NSAPtoDTE(), make_partial_x25_packet(); 15436381Ssklower Static int FACILtoNSAP(), DTEtoNSAP(); 15545899Ssklower Static struct pklcd *cons_chan_to_pcb(); 15636381Ssklower 15736381Ssklower #define HIGH_NIBBLE 1 15836381Ssklower #define LOW_NIBBLE 0 15936381Ssklower 16036381Ssklower /* 16136381Ssklower * NAME: nibble_copy() 16236381Ssklower * FUNCTION and ARGUMENTS: 16336381Ssklower * copies (len) nibbles from (src_octet), high or low nibble 16436381Ssklower * to (dst_octet), high or low nibble, 16536381Ssklower * src_nibble & dst_nibble should be: 16636381Ssklower * HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble 16736381Ssklower * LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble 16836381Ssklower * RETURNS: VOID 16936381Ssklower */ 17036381Ssklower void 17145899Ssklower nibble_copy(src_octet, src_nibble, dst_octet, dst_nibble, len) 17236381Ssklower register char *src_octet; 17336381Ssklower register char *dst_octet; 17436381Ssklower register unsigned src_nibble; 17536381Ssklower register unsigned dst_nibble; 17636381Ssklower int len; 17736381Ssklower { 17836381Ssklower 17936381Ssklower register i; 18036381Ssklower register unsigned dshift, sshift; 18136381Ssklower 18236381Ssklower IFDEBUG(D_CADDR) 18336381Ssklower printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 18436381Ssklower src_octet, src_nibble, dst_octet, dst_nibble, len); 18536381Ssklower ENDDEBUG 18636381Ssklower #define SHIFT 0x4 18736381Ssklower 18836381Ssklower dshift = dst_nibble << 2; 18936381Ssklower sshift = src_nibble << 2; 19036381Ssklower 19136381Ssklower for (i=0; i<len; i++) { 19236381Ssklower /* clear dst_nibble */ 19336381Ssklower *dst_octet &= ~(0xf<< dshift); 19436381Ssklower 19536381Ssklower /* set dst nibble */ 19636381Ssklower *dst_octet |= ( 0xf & (*src_octet >> sshift))<< dshift; 19736381Ssklower 19836381Ssklower dshift ^= SHIFT; 19936381Ssklower sshift ^= SHIFT; 20036381Ssklower src_nibble = 1-src_nibble; 20136381Ssklower dst_nibble = 1-dst_nibble; 20236381Ssklower src_octet += src_nibble; 20336381Ssklower dst_octet += dst_nibble; 20436381Ssklower } 20536381Ssklower IFDEBUG(D_CADDR) 20636381Ssklower printf("nibble_copy DONE\n"); 20736381Ssklower ENDDEBUG 20836381Ssklower } 20936381Ssklower 21036381Ssklower /* 21136381Ssklower * NAME: nibble_match() 21236381Ssklower * FUNCTION and ARGUMENTS: 21336381Ssklower * compares src_octet/src_nibble and dst_octet/dst_nibble for len nibbles. 21436381Ssklower * RETURNS: 0 if they differ, 1 if they are the same. 21536381Ssklower */ 21636381Ssklower int 21736381Ssklower nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len) 21836381Ssklower register char *src_octet; 21936381Ssklower register char *dst_octet; 22036381Ssklower register unsigned src_nibble; 22136381Ssklower register unsigned dst_nibble; 22236381Ssklower int len; 22336381Ssklower { 22436381Ssklower 22536381Ssklower register i; 22636381Ssklower register unsigned dshift, sshift; 22736381Ssklower u_char nibble_a, nibble_b; 22836381Ssklower 22936381Ssklower IFDEBUG(D_CADDR) 23036381Ssklower printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 23136381Ssklower src_octet, src_nibble, dst_octet, dst_nibble, len); 23236381Ssklower ENDDEBUG 23336381Ssklower #define SHIFT 0x4 23436381Ssklower 23536381Ssklower dshift = dst_nibble << 2; 23636381Ssklower sshift = src_nibble << 2; 23736381Ssklower 23836381Ssklower for (i=0; i<len; i++) { 23936381Ssklower nibble_b = ((*dst_octet)>>dshift) & 0xf; 24036381Ssklower nibble_a = ( 0xf & (*src_octet >> sshift)); 24145899Ssklower if (nibble_b != nibble_a) 24236381Ssklower return 0; 24336381Ssklower 24436381Ssklower dshift ^= SHIFT; 24536381Ssklower sshift ^= SHIFT; 24636381Ssklower src_nibble = 1-src_nibble; 24736381Ssklower dst_nibble = 1-dst_nibble; 24836381Ssklower src_octet += src_nibble; 24936381Ssklower dst_octet += dst_nibble; 25036381Ssklower } 25136381Ssklower IFDEBUG(D_CADDR) 25236381Ssklower printf("nibble_match DONE\n"); 25336381Ssklower ENDDEBUG 25436381Ssklower return 1; 25536381Ssklower } 25636381Ssklower 25736381Ssklower /* 25836381Ssklower **************************** NET PROTOCOL cons *************************** 25936381Ssklower */ 26036381Ssklower /* 26136381Ssklower * NAME: cons_init() 26236381Ssklower * CALLED FROM: 26336381Ssklower * autoconf 26436381Ssklower * FUNCTION: 26536381Ssklower * initialize the protocol 26636381Ssklower */ 26736381Ssklower cons_init() 26836381Ssklower { 26945899Ssklower int tp_incoming(), clnp_incoming(); 27036381Ssklower 27136381Ssklower 27236381Ssklower CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 27336381Ssklower X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM); 27436381Ssklower TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET); 27536381Ssklower IFDEBUG(D_CCONS) 27636381Ssklower printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n", 27736381Ssklower CLNP_proto, X25_proto, TP_proto); 27836381Ssklower ENDDEBUG 27945899Ssklower #ifdef notdef 28045899Ssklower pk_protolisten(0x81, 0, clnp_incoming); 28145899Ssklower pk_protolisten(0x82, 0, esis_incoming); 28245899Ssklower pk_protolisten(0x84, 0, tp8878_A_incoming); 28349041Ssklower pk_protolisten(0, 0, tp_incoming); 28445899Ssklower #endif 28536381Ssklower } 28636381Ssklower 28749937Ssklower tp_incoming(lcp, m) 28845899Ssklower struct pklcd *lcp; 28949937Ssklower register struct mbuf *m; 29036381Ssklower { 29145899Ssklower register struct isopcb *isop; 29245899Ssklower int cons_tpinput(); 29336381Ssklower 294*50648Ssklower if (iso_pcballoc((struct socket *)0, &tp_isopcb)) { 29549937Ssklower pk_close(lcp); 29645899Ssklower return; 29736381Ssklower } 298*50648Ssklower isop = tp_isopcb.isop_next; 29945899Ssklower lcp->lcd_upper = cons_tpinput; 30045899Ssklower lcp->lcd_upnext = (caddr_t)isop; 30149937Ssklower lcp->lcd_send(lcp); /* Confirms call */ 30245899Ssklower isop->isop_chan = (caddr_t)lcp; 30345899Ssklower isop->isop_laddr = &isop->isop_sladdr; 30445899Ssklower isop->isop_faddr = &isop->isop_sfaddr; 30545899Ssklower DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr); 30645899Ssklower DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr); 307*50648Ssklower parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data), 30845899Ssklower m->m_pkthdr.len - PKHEADERLN); 30936381Ssklower } 31036381Ssklower 31145899Ssklower cons_tpinput(lcp, m0) 31245899Ssklower struct mbuf *m0; 31345899Ssklower struct pklcd *lcp; 31436381Ssklower { 31545899Ssklower register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext; 31645899Ssklower register struct x25_packet *xp; 317*50648Ssklower int cmd, ptype = CLEAR; 31836381Ssklower 31949265Ssklower if (isop == 0) 32049265Ssklower return; 321*50648Ssklower if (m0 == 0) 32249041Ssklower goto dead; 32345899Ssklower switch(m0->m_type) { 32445899Ssklower case MT_DATA: 32545899Ssklower case MT_OOBDATA: 326*50648Ssklower tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, (caddr_t)lcp); 32749584Ssklower return; 32836381Ssklower 32945899Ssklower case MT_CONTROL: 330*50648Ssklower switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) { 33136381Ssklower 33245899Ssklower case RR: 33345899Ssklower cmd = PRC_CONS_SEND_DONE; 33445899Ssklower break; 33536381Ssklower 33649265Ssklower case CALL_ACCEPTED: 33749265Ssklower if (lcp->lcd_sb.sb_mb) 33849265Ssklower lcp->lcd_send(lcp); /* XXX - fix this */ 33949584Ssklower /*FALLTHROUGH*/ 34049584Ssklower default: 34149584Ssklower return; 34249265Ssklower 34349041Ssklower dead: 34449041Ssklower case CLEAR: 34549041Ssklower case CLEAR_CONF: 346*50648Ssklower lcp->lcd_upper = 0; 347*50648Ssklower lcp->lcd_upnext = 0; 348*50648Ssklower isop->isop_chan = 0; 349*50648Ssklower case RESET: 35045899Ssklower cmd = PRC_ROUTEDEAD; 35136381Ssklower } 35245899Ssklower tpcons_ctlinput(cmd, isop->isop_faddr, isop); 353*50648Ssklower if (cmd = PRC_ROUTEDEAD && isop->isop_refcnt == 0) 354*50648Ssklower iso_pcbdetach(isop); 35536381Ssklower } 35636381Ssklower } 35736381Ssklower 35836381Ssklower /* 35936381Ssklower * NAME: cons_connect() 36036381Ssklower * CALLED FROM: 36145899Ssklower * tpcons_pcbconnect() when opening a new connection. 36236381Ssklower * FUNCTION anD ARGUMENTS: 36336381Ssklower * Figures out which device to use, finding a route if one doesn't 36436381Ssklower * already exist. 36536381Ssklower * RETURN VALUE: 36636381Ssklower * returns E* 36736381Ssklower */ 36845899Ssklower cons_connect(isop) 36945899Ssklower register struct isopcb *isop; 37036381Ssklower { 37145899Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 37236381Ssklower register struct mbuf *m; 37336381Ssklower struct ifaddr *ifa; 37449937Ssklower int error; 37536381Ssklower 37636381Ssklower IFDEBUG(D_CCONN) 37745899Ssklower printf("cons_connect(0x%x): ", isop); 37845899Ssklower dump_isoaddr(isop->isop_faddr); 37945899Ssklower printf("myaddr: "); 38045899Ssklower dump_isoaddr(isop->isop_laddr); 38136381Ssklower printf("\n" ); 38236381Ssklower ENDDEBUG 38345899Ssklower NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr); 38449265Ssklower lcp->lcd_upper = cons_tpinput; 38549265Ssklower lcp->lcd_upnext = (caddr_t)isop; 38636381Ssklower IFDEBUG(D_CCONN) 38736381Ssklower printf( 38845899Ssklower "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n", 38945899Ssklower &lcp->lcd_faddr, &lcp->lcd_laddr, 39045899Ssklower isop->isop_socket->so_proto->pr_protocol); 39136381Ssklower ENDDEBUG 39249937Ssklower if ((error = make_partial_x25_packet(isop, lcp, m)) == 0) 39349937Ssklower error = pk_connect(lcp, &lcp->lcd_faddr); 39449937Ssklower return error; 39536381Ssklower } 39636381Ssklower 39736381Ssklower /* 39836381Ssklower **************************** DEVICE cons *************************** 39936381Ssklower */ 40036381Ssklower 40136381Ssklower 40236381Ssklower /* 40336381Ssklower * NAME: cons_ctlinput() 40436381Ssklower * CALLED FROM: 40536381Ssklower * lower layer when ECN_CLEAR occurs : this routine is here 40636381Ssklower * for consistency - cons subnet service calls its higher layer 40736381Ssklower * through the protosw entry. 40836381Ssklower * FUNCTION & ARGUMENTS: 40937536Smckusick * cmd is a PRC_* command, list found in ../sys/protosw.h 41036381Ssklower * copcb is the obvious. 41136381Ssklower * This serves the higher-layer cons service. 41236381Ssklower * NOTE: this takes 3rd arg. because cons uses it to inform itself 41336381Ssklower * of things (timeouts, etc) but has a pcb instead of an address. 41436381Ssklower */ 41536381Ssklower cons_ctlinput(cmd, sa, copcb) 41636381Ssklower int cmd; 41736381Ssklower struct sockaddr *sa; 41845899Ssklower register struct pklcd *copcb; 41936381Ssklower { 42036381Ssklower } 42136381Ssklower 42236381Ssklower 42345899Ssklower find_error_reason( xp ) 42445899Ssklower register struct x25_packet *xp; 42536381Ssklower { 42636381Ssklower extern u_char x25_error_stats[]; 42745899Ssklower int error, cause; 42836381Ssklower 42945899Ssklower if (xp) { 43045899Ssklower cause = 4[(char *)xp]; 43145899Ssklower switch (cause) { 43236381Ssklower case 0x00: 43336381Ssklower case 0x80: 43436381Ssklower /* DTE originated; look at the diagnostic */ 43545899Ssklower error = (CONL_ERROR_MASK | cause); 43636381Ssklower goto done; 43736381Ssklower 43836381Ssklower case 0x01: /* number busy */ 43936381Ssklower case 0x81: 44036381Ssklower case 0x09: /* Out of order */ 44136381Ssklower case 0x89: 44236381Ssklower case 0x11: /* Remot Procedure Error */ 44336381Ssklower case 0x91: 44436381Ssklower case 0x19: /* reverse charging accept not subscribed */ 44536381Ssklower case 0x99: 44636381Ssklower case 0x21: /* Incampat destination */ 44736381Ssklower case 0xa1: 44836381Ssklower case 0x29: /* fast select accept not subscribed */ 44936381Ssklower case 0xa9: 45036381Ssklower case 0x39: /* ship absent */ 45136381Ssklower case 0xb9: 45236381Ssklower case 0x03: /* invalid facil request */ 45336381Ssklower case 0x83: 45436381Ssklower case 0x0b: /* access barred */ 45536381Ssklower case 0x8b: 45636381Ssklower case 0x13: /* local procedure error */ 45736381Ssklower case 0x93: 45836381Ssklower case 0x05: /* network congestion */ 45936381Ssklower case 0x85: 46036381Ssklower case 0x8d: /* not obtainable */ 46136381Ssklower case 0x0d: 46236381Ssklower case 0x95: /* RPOA out of order */ 46336381Ssklower case 0x15: 46436381Ssklower /* take out bit 8 46536381Ssklower * so we don't have to have so many perror entries 46636381Ssklower */ 46745899Ssklower error = (CONL_ERROR_MASK | 0x100 | (cause & ~0x80)); 46836381Ssklower goto done; 46936381Ssklower 47036381Ssklower case 0xc1: /* gateway-detected proc error */ 47136381Ssklower case 0xc3: /* gateway congestion */ 47236381Ssklower 47345899Ssklower error = (CONL_ERROR_MASK | 0x100 | cause); 47436381Ssklower goto done; 47536381Ssklower } 47636381Ssklower } 47736381Ssklower /* otherwise, a *hopefully* valid perror exists in the e_reason field */ 47845899Ssklower error = xp->packet_data; 47936381Ssklower if (error = 0) { 48036381Ssklower printf("Incoming PKT TYPE 0x%x with reason 0x%x\n", 48145899Ssklower pk_decode(xp), 48245899Ssklower cause); 48336381Ssklower error = E_CO_HLI_DISCA; 48436381Ssklower } 48536381Ssklower 48636381Ssklower done: 48736381Ssklower return error; 48836381Ssklower } 48936381Ssklower 49036381Ssklower 49136381Ssklower 49236381Ssklower #endif KERNEL 49336381Ssklower 49436381Ssklower /* 49536381Ssklower * NAME: make_partial_x25_packet() 49636381Ssklower * 49736381Ssklower * FUNCTION and ARGUMENTS: 49845899Ssklower * Makes part of an X.25 call packet, for use by x25. 49936381Ssklower * (src) and (dst) are the NSAP-addresses of source and destination. 50036381Ssklower * (buf) is a ptr to a buffer into which to write this partial header. 50136381Ssklower * 50245899Ssklower * 0 Facility length (in octets) 50345899Ssklower * 1 Facility field, which is a set of: 50436381Ssklower * m facil code 50536381Ssklower * m+1 facil param len (for >2-byte facilities) in octets 50636381Ssklower * m+2..p facil param field 50736381Ssklower * q user data (protocol identification octet) 50836381Ssklower * 50936381Ssklower * 51036381Ssklower * RETURNS: 51136381Ssklower * 0 if OK 51236381Ssklower * E* if failed. 51345899Ssklower * 51445899Ssklower * SIDE EFFECTS: 51545899Ssklower * Stores facilites mbuf in X.25 control block, where the connect 51645899Ssklower * routine knows where to look for it. 51736381Ssklower */ 51836381Ssklower 51936381Ssklower #ifdef X25_1984 52036381Ssklower int cons_use_facils = 1; 52136381Ssklower #else X25_1984 52236381Ssklower int cons_use_facils = 0; 52336381Ssklower #endif X25_1984 52436381Ssklower 52536381Ssklower int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */ 52636381Ssklower 52736381Ssklower Static int 52845899Ssklower make_partial_x25_packet(isop, lcp) 52945899Ssklower struct isopcb *isop; 53045899Ssklower struct pklcd *lcp; 53136381Ssklower { 53236381Ssklower u_int proto; 53336381Ssklower int flag; 53445899Ssklower caddr_t buf; 53549041Ssklower register caddr_t ptr; 53636381Ssklower register int len = 0; 53736381Ssklower int buflen =0; 53836381Ssklower caddr_t facil_len; 53936381Ssklower int oddness = 0; 54045899Ssklower struct mbuf *m; 54136381Ssklower 54236381Ssklower 54349584Ssklower IFDEBUG(D_CCONN) 54449584Ssklower printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", 54549584Ssklower isop->isop_laddr, isop->isop_faddr, proto, m, flag); 54649584Ssklower ENDDEBUG 54749584Ssklower if (cons_use_udata) { 54849584Ssklower if (isop->isop_x25crud_len > 0) { 54949584Ssklower /* 55049584Ssklower * The user specified something. Stick it in 55149584Ssklower */ 55249584Ssklower bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata, 55349584Ssklower isop->isop_x25crud_len); 55449584Ssklower lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len; 55549584Ssklower } 55649584Ssklower } 55749584Ssklower 55849584Ssklower if (cons_use_facils == 0) { 55949584Ssklower lcp->lcd_facilities = 0; 56049584Ssklower return 0; 56149584Ssklower } 56249937Ssklower MGETHDR(m, MT_DATA, M_WAITOK); 56345899Ssklower if (m == 0) 56445899Ssklower return ENOBUFS; 56545899Ssklower buf = mtod(m, caddr_t); 56649041Ssklower ptr = buf; 56736381Ssklower 56836381Ssklower /* ptr now points to facil length (len of whole facil field in OCTETS */ 56936381Ssklower facil_len = ptr ++; 57049937Ssklower m->m_len = 0; 57149937Ssklower pk_build_facilities(m, &lcp->lcd_faddr, 0); 57236381Ssklower 57336381Ssklower IFDEBUG(D_CADDR) 57436381Ssklower printf("make_partial calling: ptr 0x%x, len 0x%x\n", ptr, 57545899Ssklower isop->isop_laddr->siso_addr.isoa_len); 57636381Ssklower ENDDEBUG 57745899Ssklower if (cons_use_facils) { 57849937Ssklower *ptr++ = 0; /* Marker to separate X.25 facitilies from CCITT ones */ 57949937Ssklower *ptr++ = 0x0f; 58036381Ssklower *ptr = 0xcb; /* calling facility code */ 58136381Ssklower ptr ++; 58236381Ssklower ptr ++; /* leave room for facil param len (in OCTETS + 1) */ 58336381Ssklower ptr ++; /* leave room for the facil param len (in nibbles), 58449937Ssklower * high two bits of which indicate full/partial NSAP 58549937Ssklower */ 58645899Ssklower len = isop->isop_laddr->siso_addr.isoa_len; 58745899Ssklower bcopy( isop->isop_laddr->siso_data, ptr, len); 58849584Ssklower *(ptr-2) = len+1; /* facil param len in octets */ 58936381Ssklower *(ptr-1) = len<<1; /* facil param len in nibbles */ 59036381Ssklower ptr += len; 59136381Ssklower 59236381Ssklower IFDEBUG(D_CADDR) 59336381Ssklower printf("make_partial called: ptr 0x%x, len 0x%x\n", ptr, 59445899Ssklower isop->isop_faddr->siso_addr.isoa_len); 59536381Ssklower ENDDEBUG 59636381Ssklower *ptr = 0xc9; /* called facility code */ 59736381Ssklower ptr ++; 59836381Ssklower ptr ++; /* leave room for facil param len (in OCTETS + 1) */ 59936381Ssklower ptr ++; /* leave room for the facil param len (in nibbles), 60049937Ssklower * high two bits of which indicate full/partial NSAP 60149937Ssklower */ 60245899Ssklower len = isop->isop_faddr->siso_nlen; 60345899Ssklower bcopy(isop->isop_faddr->siso_data, ptr, len); 60449584Ssklower *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these 60536381Ssklower * two length fields, in octets */ 60636381Ssklower *(ptr-1) = len<<1; /* facil param len in nibbles */ 60736381Ssklower ptr += len; 60836381Ssklower 60936381Ssklower } 61036381Ssklower *facil_len = ptr - facil_len - 1; 61145899Ssklower if (*facil_len > MAX_FACILITIES) 61236381Ssklower return E_CO_PNA_LONG; 61336381Ssklower 61436381Ssklower buflen = (int)(ptr - buf); 61536381Ssklower 61636381Ssklower IFDEBUG(D_CDUMP_REQ) 61736381Ssklower register int i; 61836381Ssklower 61936381Ssklower printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n", 62036381Ssklower buf, buflen, buflen); 62136381Ssklower for( i=0; i < buflen; ) { 62236381Ssklower printf("+%d: %x %x %x %x %x %x %x %x\n", 62336381Ssklower i, 62436381Ssklower *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3), 62536381Ssklower *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7)); 62636381Ssklower i+=8; 62736381Ssklower } 62836381Ssklower ENDDEBUG 62936381Ssklower IFDEBUG(D_CADDR) 63036381Ssklower printf("make_partial returns buf 0x%x size 0x%x bytes\n", 63136381Ssklower mtod(m, caddr_t), buflen); 63236381Ssklower ENDDEBUG 63336381Ssklower 63445899Ssklower if (buflen > MHLEN) 63536381Ssklower return E_CO_PNA_LONG; 63636381Ssklower 63749937Ssklower m->m_pkthdr.len = m->m_len = buflen; 63845899Ssklower lcp->lcd_facilities = m; 63936381Ssklower return 0; 64036381Ssklower } 64136381Ssklower 64236381Ssklower /* 64336381Ssklower * NAME: NSAPtoDTE() 64436381Ssklower * CALLED FROM: 64536381Ssklower * make_partial_x25_packet() 64636381Ssklower * FUNCTION and ARGUMENTS: 64736381Ssklower * get a DTE address from an NSAP-address (struct sockaddr_iso) 64836381Ssklower * (dst_octet) is the octet into which to begin stashing the DTE addr 64936381Ssklower * (dst_nibble) takes 0 or 1. 1 means begin filling in the DTE addr 65036381Ssklower * in the high-order nibble of dst_octet. 0 means low-order nibble. 65136381Ssklower * (addr) is the NSAP-address 65236381Ssklower * (flag) is true if the transport suffix is to become the 65336381Ssklower * last two digits of the DTE address 65445899Ssklower * A DTE address is a series of ASCII digits 65536381Ssklower * 65636381Ssklower * A DTE address may have leading zeros. The are significant. 65736381Ssklower * 1 digit per nibble, may be an odd number of nibbles. 65836381Ssklower * 65936381Ssklower * An NSAP-address has the DTE address in the IDI. Leading zeros are 66036381Ssklower * significant. Trailing hex f indicates the end of the DTE address. 66145899Ssklower * The IDI is a series of BCD digits, one per nibble. 66236381Ssklower * 66336381Ssklower * RETURNS 66436381Ssklower * # significant digits in the DTE address, -1 if error. 66536381Ssklower */ 66636381Ssklower 66736381Ssklower Static int 66845899Ssklower NSAPtoDTE(siso, sx25) 66945899Ssklower register struct sockaddr_iso *siso; 67045899Ssklower register struct sockaddr_x25 *sx25; 67136381Ssklower { 67245899Ssklower int dtelen = -1; 67336381Ssklower 67436381Ssklower IFDEBUG(D_CADDR) 67545899Ssklower printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&siso->siso_addr)); 67636381Ssklower ENDDEBUG 67736381Ssklower 67845899Ssklower if (siso->siso_data[0] == AFI_37) { 67945899Ssklower register char *out = sx25->x25_addr; 68045899Ssklower register char *in = siso->siso_data + 1; 68145899Ssklower register int nibble; 68249041Ssklower char *lim = siso->siso_data + siso->siso_nlen; 68349041Ssklower char *olim = out+15; 68445899Ssklower int lowNibble = 0; 68545899Ssklower 68645899Ssklower while (in < lim) { 68745899Ssklower nibble = ((lowNibble ? *in++ : (*in >> 4)) & 0xf) | 0x30; 68845899Ssklower lowNibble ^= 1; 68949041Ssklower if (nibble != 0x3f && out < olim) 69045899Ssklower *out++ = nibble; 69145899Ssklower } 69245899Ssklower dtelen = out - sx25->x25_addr; 69345899Ssklower *out++ = 0; 69445899Ssklower } else { 69545899Ssklower /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/ 696*50648Ssklower register struct rtentry *rt; 697*50648Ssklower extern struct sockaddr_iso blank_siso; 698*50648Ssklower struct sockaddr_iso nsiso; 69945899Ssklower 700*50648Ssklower nsiso = blank_siso; 701*50648Ssklower bcopy(nsiso.siso_data, siso->siso_data, 702*50648Ssklower nsiso.siso_nlen = siso->siso_nlen); 703*50648Ssklower if (rt = rtalloc1(&nsiso, 1)) { 70445899Ssklower register struct sockaddr_x25 *sxx = 70545899Ssklower (struct sockaddr_x25 *)rt->rt_gateway; 70645899Ssklower register char *in = sxx->x25_addr; 70745899Ssklower 70845899Ssklower rt->rt_use--; 70945899Ssklower if (sxx && sxx->x25_family == AF_CCITT) { 71045899Ssklower bcopy(sx25->x25_addr, sxx->x25_addr, sizeof(sx25->x25_addr)); 71145899Ssklower while (*in++) {} 71245899Ssklower dtelen = in - sxx->x25_addr; 71345899Ssklower } 71445899Ssklower } 71536381Ssklower } 71645899Ssklower return dtelen; 71736381Ssklower } 71836381Ssklower 71936381Ssklower /* 72036381Ssklower * NAME: FACILtoNSAP() 72136381Ssklower * CALLED FROM: 72236381Ssklower * parse_facil() 72336381Ssklower * FUNCTION and ARGUMENTS: 72436381Ssklower * Creates and NSAP in the sockaddr_iso (addr) from the 72545899Ssklower * x.25 facility found at buf - 1. 72636381Ssklower * RETURNS: 727*50648Ssklower * 0 if ok, -1 if error. 72836381Ssklower */ 72936381Ssklower 73036381Ssklower Static int 73145899Ssklower FACILtoNSAP(addr, buf) 732*50648Ssklower register u_char *buf; 73336381Ssklower register struct sockaddr_iso *addr; 73436381Ssklower { 735*50648Ssklower int len_in_nibbles = *++buf & 0x3f; 736*50648Ssklower u_char buf_len = (len_in_nibbles + 1) >> 1;; /* in bytes */ 73736381Ssklower 73836381Ssklower IFDEBUG(D_CADDR) 73936381Ssklower printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 74036381Ssklower buf, buf_len, addr ); 74136381Ssklower ENDDEBUG 74236381Ssklower 74345899Ssklower len_in_nibbles = *buf & 0x3f; 74436381Ssklower /* despite the fact that X.25 makes us put a length in nibbles 74536381Ssklower * here, the NSAP-addrs are always in full octets 74636381Ssklower */ 74745899Ssklower switch (*buf++ & 0xc0) { 74845899Ssklower case 0: 74945899Ssklower /* Entire OSI NSAP address */ 75045899Ssklower bcopy((caddr_t)buf, addr->siso_data, addr->siso_nlen = buf_len); 75145899Ssklower break; 75236381Ssklower 75345899Ssklower case 40: 75445899Ssklower /* Partial OSI NSAP address, assume trailing */ 75545899Ssklower if (buf_len + addr->siso_nlen > sizeof(addr->siso_addr)) 75645899Ssklower return -1; 75745899Ssklower bcopy((caddr_t)buf, TSEL(addr), buf_len); 75845899Ssklower addr->siso_nlen += buf_len; 75945899Ssklower break; 76036381Ssklower 76145899Ssklower default: 76245899Ssklower /* Rather than blow away the connection, just ignore and use 76345899Ssklower NSAP from DTE */; 76436381Ssklower } 765*50648Ssklower return 0; 76645899Ssklower } 76736381Ssklower 768*50648Ssklower Static 76945899Ssklower init_siso(siso) 77045899Ssklower register struct sockaddr_iso *siso; 77145899Ssklower { 77245899Ssklower siso->siso_len = sizeof (*siso); 77345899Ssklower siso->siso_family = AF_ISO; 77445899Ssklower siso->siso_data[0] = AFI_37; 77545899Ssklower siso->siso_nlen = 8; 77636381Ssklower } 77736381Ssklower 77836381Ssklower /* 77936381Ssklower * NAME: DTEtoNSAP() 78036381Ssklower * CALLED FROM: 78136381Ssklower * parse_facil() 78236381Ssklower * FUNCTION and ARGUMENTS: 78336381Ssklower * Creates a type 37 NSAP in the sockaddr_iso (addr) 78445899Ssklower * from a DTE address found in a sockaddr_x25. 78536381Ssklower * 78636381Ssklower * RETURNS: 78736381Ssklower * 0 if ok; E* otherwise. 78836381Ssklower */ 78936381Ssklower 79036381Ssklower Static int 79145899Ssklower DTEtoNSAP(addr, sx) 79236381Ssklower struct sockaddr_iso *addr; 79345899Ssklower struct sockaddr_x25 *sx; 79436381Ssklower { 79545899Ssklower register char *in, *out; 79645899Ssklower register int first; 79745899Ssklower int pad_tail = 0; 79845899Ssklower int src_len; 79936381Ssklower 80036381Ssklower 80145899Ssklower init_siso(addr); 80245899Ssklower in = sx->x25_addr; 803*50648Ssklower src_len = strlen(in); 804*50648Ssklower addr->siso_nlen = (src_len + 3) / 2; 805*50648Ssklower out = addr->siso_data; 806*50648Ssklower *out++ = 0x37; 807*50648Ssklower if (src_len & 1) { 80845899Ssklower pad_tail = 0xf; 80945899Ssklower src_len++; 81045899Ssklower } 811*50648Ssklower for (first = 0; src_len > 0; src_len--) { 812*50648Ssklower first |= 0xf & *in++; 81345899Ssklower if (src_len & 1) { 81445899Ssklower *out++ = first; 81545899Ssklower first = 0; 81645899Ssklower } 81745899Ssklower else first <<= 4; 81845899Ssklower } 81945899Ssklower if (pad_tail) 82045899Ssklower out[-1] |= 0xf; 82136381Ssklower return 0; /* ok */ 82236381Ssklower } 82336381Ssklower 82436381Ssklower /* 82536381Ssklower * FUNCTION and ARGUMENTS: 82636381Ssklower * parses (buf_len) bytes beginning at (buf) and finds 82736381Ssklower * a called nsap, a calling nsap, and protocol identifier. 82836381Ssklower * RETURNS: 82936381Ssklower * 0 if ok, E* otherwise. 83036381Ssklower */ 83136381Ssklower 832*50648Ssklower Static int 83345899Ssklower parse_facil(lcp, isop, buf, buf_len) 83436381Ssklower caddr_t buf; 83536381Ssklower u_char buf_len; /* in bytes */ 83645899Ssklower struct isopcb *isop; 83745899Ssklower struct pklcd *lcp; 83836381Ssklower { 83936381Ssklower register int i; 84045899Ssklower register u_char *ptr = (u_char *)buf; 84145899Ssklower u_char *ptr_lim, *facil_lim; 84245899Ssklower int facil_param_len, facil_len; 84336381Ssklower 84436381Ssklower IFDEBUG(D_CADDR) 84545899Ssklower printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", 846*50648Ssklower lcp, isop, buf, buf_len); 84736381Ssklower dump_buf(buf, buf_len); 84836381Ssklower ENDDEBUG 84936381Ssklower 85036381Ssklower /* find the beginnings of the facility fields in buf 85136381Ssklower * by skipping over the called & calling DTE addresses 85236381Ssklower * i <- # nibbles in called + # nibbles in calling 85336381Ssklower * i += 1 so that an odd nibble gets rounded up to even 85436381Ssklower * before dividing by 2, then divide by two to get # octets 85536381Ssklower */ 85645899Ssklower i = (int)(*ptr >> 4) + (int)(*ptr&0xf); 85736381Ssklower i++; 85845899Ssklower ptr += i >> 1; 85936381Ssklower ptr ++; /* plus one for the DTE lengths byte */ 86036381Ssklower 86136381Ssklower /* ptr now is at facil_length field */ 86245899Ssklower facil_len = *ptr++; 86345899Ssklower facil_lim = ptr + facil_len; 86436381Ssklower IFDEBUG(D_CADDR) 86545899Ssklower printf("parse_facils: facil length is 0x%x\n", (int) facil_len); 86636381Ssklower ENDDEBUG 86736381Ssklower 868*50648Ssklower while (ptr < facil_lim) { 86936381Ssklower /* get NSAP addresses from facilities */ 87045899Ssklower switch (*ptr++) { 87136381Ssklower case 0xcb: 87245899Ssklower /* calling NSAP */ 87345899Ssklower facil_param_len = FACILtoNSAP(isop->isop_faddr, ptr); 87436381Ssklower break; 87536381Ssklower case 0xc9: 87645899Ssklower /* called NSAP */ 87745899Ssklower facil_param_len = FACILtoNSAP(isop->isop_laddr, ptr); 87836381Ssklower break; 87936381Ssklower 88036381Ssklower /* from here to default are legit cases that I ignore */ 88136381Ssklower /* variable length */ 88236381Ssklower case 0xca: /* end-to-end transit delay negot */ 88336381Ssklower case 0xc6: /* network user id */ 88436381Ssklower case 0xc5: /* charging info : indicating monetary unit */ 88536381Ssklower case 0xc2: /* charging info : indicating segment count */ 88636381Ssklower case 0xc1: /* charging info : indicating call duration */ 88736381Ssklower case 0xc4: /* RPOA extended format */ 88836381Ssklower case 0xc3: /* call redirection notification */ 88936381Ssklower facil_param_len = 0; 89036381Ssklower break; 89136381Ssklower 89236381Ssklower /* 1 octet */ 89336381Ssklower case 0x0a: /* min. throughput class negot */ 89436381Ssklower case 0x02: /* throughput class */ 89536381Ssklower case 0x03: case 0x47: /* CUG shit */ 89636381Ssklower case 0x0b: /* expedited data negot */ 89736381Ssklower case 0x01: /* Fast select or reverse charging 89836381Ssklower (example of intelligent protocol design) */ 89936381Ssklower case 0x04: /* charging info : requesting service */ 90036381Ssklower case 0x08: /* called line addr modified notification */ 901*50648Ssklower case 0x00: /* marker to indicate beginning of CCITT facils */ 90236381Ssklower facil_param_len = 1; 90336381Ssklower break; 90436381Ssklower 90536381Ssklower /* any 2 octets */ 90636381Ssklower case 0x42: /* pkt size */ 90736381Ssklower case 0x43: /* win size */ 90836381Ssklower case 0x44: /* RPOA basic format */ 90936381Ssklower case 0x41: /* bilateral CUG shit */ 91036381Ssklower case 0x49: /* transit delay selection and indication */ 91136381Ssklower facil_param_len = 2; 91236381Ssklower break; 91336381Ssklower 91436381Ssklower default: 91536381Ssklower printf( 916*50648Ssklower "BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n", 917*50648Ssklower facil_lim, facil_len, ptr - 1, ptr[-1]); 918*50648Ssklower /* facil that we don't handle 919*50648Ssklower return E_CO_HLI_REJI; */ 920*50648Ssklower switch (ptr[-1] & 0xc0) { 921*50648Ssklower case 0x00: facil_param_len = 1; break; 922*50648Ssklower case 0x40: facil_param_len = 2; break; 923*50648Ssklower case 0x80: facil_param_len = 3; break; 924*50648Ssklower case 0xc0: facil_param_len = 0; break; 925*50648Ssklower } 92636381Ssklower } 92745899Ssklower if (facil_param_len == -1) 92845899Ssklower return E_CO_REG_ICDA; 92945899Ssklower if (facil_param_len == 0) /* variable length */ 930*50648Ssklower facil_param_len = (int)*ptr++; /* 1 + the real facil param */ 93136381Ssklower ptr += facil_param_len; 93236381Ssklower } 93336381Ssklower return 0; 93436381Ssklower } 93536381Ssklower 93645899Ssklower #endif TPCONS 937