1*36381Ssklower /*********************************************************** 2*36381Ssklower Copyright IBM Corporation 1987 3*36381Ssklower 4*36381Ssklower All Rights Reserved 5*36381Ssklower 6*36381Ssklower Permission to use, copy, modify, and distribute this software and its 7*36381Ssklower documentation for any purpose and without fee is hereby granted, 8*36381Ssklower provided that the above copyright notice appear in all copies and that 9*36381Ssklower both that copyright notice and this permission notice appear in 10*36381Ssklower supporting documentation, and that the name of IBM not be 11*36381Ssklower used in advertising or publicity pertaining to distribution of the 12*36381Ssklower software without specific, written prior permission. 13*36381Ssklower 14*36381Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36381Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36381Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36381Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36381Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36381Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36381Ssklower SOFTWARE. 21*36381Ssklower 22*36381Ssklower ******************************************************************/ 23*36381Ssklower 24*36381Ssklower /* 25*36381Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36381Ssklower */ 27*36381Ssklower /* 28*36381Ssklower * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $ 29*36381Ssklower * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $ 30*36381Ssklower * 31*36381Ssklower * cons.c - Connection Oriented Network Service: 32*36381Ssklower * including support for a) user transport-level service, 33*36381Ssklower * b) COSNS below CLNP, and c) CONS below TP. 34*36381Ssklower */ 35*36381Ssklower 36*36381Ssklower #ifndef lint 37*36381Ssklower static char *rcsid = "$Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $"; 38*36381Ssklower #endif lint 39*36381Ssklower 40*36381Ssklower #ifdef ARGO_DEBUG 41*36381Ssklower #define Static 42*36381Ssklower unsigned LAST_CALL_PCB; 43*36381Ssklower #else ARGO_DEBUG 44*36381Ssklower #define Static static 45*36381Ssklower #endif ARGO_DEBUG 46*36381Ssklower 47*36381Ssklower #include "ecn.h" 48*36381Ssklower #include "argoxtwentyfive.h" 49*36381Ssklower 50*36381Ssklower #if NARGOXTWENTYFIVE > 0 51*36381Ssklower 52*36381Ssklower #ifdef KERNEL 53*36381Ssklower 54*36381Ssklower #include "param.h" 55*36381Ssklower #include "systm.h" 56*36381Ssklower #include "mbuf.h" 57*36381Ssklower #include "protosw.h" 58*36381Ssklower #include "socket.h" 59*36381Ssklower #include "socketvar.h" 60*36381Ssklower #include "errno.h" 61*36381Ssklower #include "ioctl.h" 62*36381Ssklower 63*36381Ssklower #include "../net/if.h" 64*36381Ssklower #include "../net/netisr.h" 65*36381Ssklower #include "../net/route.h" 66*36381Ssklower 67*36381Ssklower #include "../netiso/iso_errno.h" 68*36381Ssklower #include "../netiso/argo_debug.h" 69*36381Ssklower #include "../netiso/tp_trace.h" 70*36381Ssklower #include "../netiso/iso.h" 71*36381Ssklower #include "../netiso/cons.h" 72*36381Ssklower #include "../netiso/iso_pcb.h" 73*36381Ssklower #include "../netiso/cons_pcb.h" 74*36381Ssklower #include "../caif/eicon.h" 75*36381Ssklower 76*36381Ssklower #ifdef ARGO_DEBUG 77*36381Ssklower #define MT_XCONN 0x50 78*36381Ssklower #define MT_XCLOSE 0x51 79*36381Ssklower #define MT_XCONFIRM 0x52 80*36381Ssklower #define MT_XDATA 0x53 81*36381Ssklower #define MT_XHEADER 0x54 82*36381Ssklower #else 83*36381Ssklower #define MT_XCONN MT_DATA 84*36381Ssklower #define MT_XCLOSE MT_DATA 85*36381Ssklower #define MT_XCONFIRM MT_DATA 86*36381Ssklower #define MT_XDATA MT_DATA 87*36381Ssklower #define MT_XHEADER MT_HEADER 88*36381Ssklower #endif ARGO_DEBUG 89*36381Ssklower 90*36381Ssklower #define DONTCLEAR -1 91*36381Ssklower 92*36381Ssklower /********************************************************************* 93*36381Ssklower * cons.c - CONS interface to the eicon adapter 94*36381Ssklower * Includes connection manager - for (TP, CLNP)/x.25 95*36381Ssklower * 96*36381Ssklower * TODO: figure out what resources we might run out of besides mbufs. 97*36381Ssklower * If we run out of any of them (including mbufs) close and recycle 98*36381Ssklower * lru x% of the connections, for some parameter x. 99*36381Ssklower * 100*36381Ssklower * There are 4 interfaces from above: 101*36381Ssklower * 0) from CLNP: 102*36381Ssklower * cons is an interface driver - CLNP calls 103*36381Ssklower * cosns_output(ifp, m, dst), a device-type interface output routine 104*36381Ssklower * that does some connection management stuff and queues a 105*36381Ssklower * request on the eicon driver queue by calling ifp->if_output. 106*36381Ssklower * The eicon's ifp structure contains cosns_output as its output routine 107*36381Ssklower * rather than ifp_>if_output! Kludge, but we don't have much choice... 108*36381Ssklower * X25 connections created in this manner may always be multiplexed 109*36381Ssklower * but only with their own kind (not with connections servicing TP 110*36381Ssklower * directly.) 111*36381Ssklower * co_flags & CONSF_DGM 112*36381Ssklower * 1) from TP0: 113*36381Ssklower * cons CO network service 114*36381Ssklower * TP associates a transport connection with a network connection. 115*36381Ssklower * cons_output( isop, m, len, isdgm==0 ) 116*36381Ssklower * co_flags == 0 117*36381Ssklower * 2) from TP 4: 118*36381Ssklower * It's a datagram service, like clnp is. - even though it calls 119*36381Ssklower * cons_output( isop, m, len, isdgm==1 ) 120*36381Ssklower * it eventually goes through 121*36381Ssklower * cosns_output(ifp, m, dst). 122*36381Ssklower * TP4 permits multiplexing (reuse, possibly simultaneously) of the 123*36381Ssklower * network connections. 124*36381Ssklower * This means that many sockets (many tpcbs) may be associated with 125*36381Ssklower * this cons_pcb, hence cannot have a back ptr from cons_pcb to a tpcb. 126*36381Ssklower * co_flags & CONSF_DGM 127*36381Ssklower * co_socket is null since there may be many sockets that use this copcb. 128*36381Ssklower * 3) from user: cons_usrreq(), cons_ctloutput() 129*36381Ssklower * cons is a standard transport service interface. 130*36381Ssklower * There is a 1-1 correspondence between net connections and sockets. 131*36381Ssklower * co_socket points to a socket. 132*36381Ssklower * 133*36381Ssklower NOTE: 134*36381Ssklower streams would really be nice. sigh. 135*36381Ssklower NOTE: 136*36381Ssklower eicon <--> cons interface: the first mbuf (the ecn_request structure) 137*36381Ssklower had better NOT be a cluster. 138*36381Ssklower NOTE: 139*36381Ssklower PVCs could be handled by config-ing a cons with an address and with the 140*36381Ssklower IFF_POINTTOPOINT flag on. This code would then have to skip the 141*36381Ssklower connection setup stuff for pt-to-pt links. 142*36381Ssklower NOTE: 143*36381Ssklower We keep track of the ifp for each connection. Right now this is 144*36381Ssklower unnecessary, but just in case someone comes up with some kind 145*36381Ssklower of a kludge to allow > 1 eicon to be attached at a time, 146*36381Ssklower (i.e., some meaningful netof( a type 37 address ) ), 147*36381Ssklower we do keep track of this. 148*36381Ssklower 149*36381Ssklower 150*36381Ssklower *********************************************************************/ 151*36381Ssklower 152*36381Ssklower #define touch(copcb) copcb->co_ttl = copcb->co_init_ttl 153*36381Ssklower 154*36381Ssklower #define CONS_IFQMAXLEN 5 155*36381Ssklower 156*36381Ssklower #define SET_CHANMASK( isop, chan )\ 157*36381Ssklower if( (u_int)(chan) < 32 ) \ 158*36381Ssklower (isop)->isop_chanmask = (1<<((chan)-1));\ 159*36381Ssklower else \ 160*36381Ssklower (isop)->isop_negchanmask = (1<<((256-(chan))-1)) 161*36381Ssklower 162*36381Ssklower #define ADD_CHANMASK( isop, chan )\ 163*36381Ssklower if( (u_int)(chan) < 32 ) \ 164*36381Ssklower (isop)->isop_chanmask |= (1<<((chan)-1));\ 165*36381Ssklower else \ 166*36381Ssklower (isop)->isop_negchanmask |= (1<<((256-(chan))-1)) 167*36381Ssklower 168*36381Ssklower struct ifnet *consif; /* TO BE REMOVED */ 169*36381Ssklower Static int consinit(), consioctl(), consattach(); 170*36381Ssklower 171*36381Ssklower /* protosw pointers for getting to higher layer */ 172*36381Ssklower Static struct protosw *CLNP_proto; 173*36381Ssklower Static struct protosw *TP_proto; 174*36381Ssklower Static struct protosw *X25_proto; 175*36381Ssklower Static int issue_clear_req(); 176*36381Ssklower 177*36381Ssklower #ifndef PHASEONE 178*36381Ssklower extern struct ifaddr *ifa_ifwithnet(); 179*36381Ssklower #endif PHASEONE 180*36381Ssklower 181*36381Ssklower extern struct ifaddr *ifa_ifwithaddr(); 182*36381Ssklower 183*36381Ssklower Static struct socket dummysocket; /* for use by cosns */ 184*36381Ssklower 185*36381Ssklower extern struct isopcb tp_isopcb; /* chain of all TP pcbs */ 186*36381Ssklower struct isopcb cons_isopcb; /* chain of all cons pcbs */ 187*36381Ssklower struct isopcb tp_incoming_pending; /* incoming connections 188*36381Ssklower for TP, pending */ 189*36381Ssklower 190*36381Ssklower struct isopcb *Xpcblist[] = { 191*36381Ssklower &cons_isopcb, 192*36381Ssklower &tp_incoming_pending, 193*36381Ssklower &tp_isopcb, 194*36381Ssklower (struct isopcb *)0 195*36381Ssklower }; 196*36381Ssklower 197*36381Ssklower Static int parse_facil(), NSAPtoDTE(), make_partial_x25_packet(); 198*36381Ssklower Static int FACILtoNSAP(), DTEtoNSAP(); 199*36381Ssklower Static struct cons_pcb *cons_chan_to_pcb(); 200*36381Ssklower 201*36381Ssklower #define HIGH_NIBBLE 1 202*36381Ssklower #define LOW_NIBBLE 0 203*36381Ssklower 204*36381Ssklower /* 205*36381Ssklower * NAME: nibble_copy() 206*36381Ssklower * FUNCTION and ARGUMENTS: 207*36381Ssklower * copies (len) nibbles from (src_octet), high or low nibble 208*36381Ssklower * to (dst_octet), high or low nibble, 209*36381Ssklower * src_nibble & dst_nibble should be: 210*36381Ssklower * HIGH_NIBBLE (1) if leftmost 4 bits/ most significant nibble 211*36381Ssklower * LOW_NIBBLE (0) if rightmost 4 bits/ least significant nibble 212*36381Ssklower * RETURNS: VOID 213*36381Ssklower */ 214*36381Ssklower void 215*36381Ssklower nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, len) 216*36381Ssklower register char *src_octet; 217*36381Ssklower register char *dst_octet; 218*36381Ssklower register unsigned src_nibble; 219*36381Ssklower register unsigned dst_nibble; 220*36381Ssklower int len; 221*36381Ssklower { 222*36381Ssklower 223*36381Ssklower register i; 224*36381Ssklower register unsigned dshift, sshift; 225*36381Ssklower 226*36381Ssklower IFDEBUG(D_CADDR) 227*36381Ssklower printf("nibble_copy ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 228*36381Ssklower src_octet, src_nibble, dst_octet, dst_nibble, len); 229*36381Ssklower ENDDEBUG 230*36381Ssklower #define SHIFT 0x4 231*36381Ssklower 232*36381Ssklower dshift = dst_nibble << 2; 233*36381Ssklower sshift = src_nibble << 2; 234*36381Ssklower 235*36381Ssklower for (i=0; i<len; i++) { 236*36381Ssklower /* clear dst_nibble */ 237*36381Ssklower *dst_octet &= ~(0xf<< dshift); 238*36381Ssklower 239*36381Ssklower /* set dst nibble */ 240*36381Ssklower *dst_octet |= ( 0xf & (*src_octet >> sshift))<< dshift; 241*36381Ssklower 242*36381Ssklower dshift ^= SHIFT; 243*36381Ssklower sshift ^= SHIFT; 244*36381Ssklower src_nibble = 1-src_nibble; 245*36381Ssklower dst_nibble = 1-dst_nibble; 246*36381Ssklower src_octet += src_nibble; 247*36381Ssklower dst_octet += dst_nibble; 248*36381Ssklower } 249*36381Ssklower IFDEBUG(D_CADDR) 250*36381Ssklower printf("nibble_copy DONE\n"); 251*36381Ssklower ENDDEBUG 252*36381Ssklower } 253*36381Ssklower 254*36381Ssklower /* 255*36381Ssklower * NAME: nibble_match() 256*36381Ssklower * FUNCTION and ARGUMENTS: 257*36381Ssklower * compares src_octet/src_nibble and dst_octet/dst_nibble for len nibbles. 258*36381Ssklower * RETURNS: 0 if they differ, 1 if they are the same. 259*36381Ssklower */ 260*36381Ssklower int 261*36381Ssklower nibble_match( src_octet, src_nibble, dst_octet, dst_nibble, len) 262*36381Ssklower register char *src_octet; 263*36381Ssklower register char *dst_octet; 264*36381Ssklower register unsigned src_nibble; 265*36381Ssklower register unsigned dst_nibble; 266*36381Ssklower int len; 267*36381Ssklower { 268*36381Ssklower 269*36381Ssklower register i; 270*36381Ssklower register unsigned dshift, sshift; 271*36381Ssklower u_char nibble_a, nibble_b; 272*36381Ssklower 273*36381Ssklower IFDEBUG(D_CADDR) 274*36381Ssklower printf("nibble_match ( 0x%x, 0x%x, 0x%x, 0x%x 0x%x)\n", 275*36381Ssklower src_octet, src_nibble, dst_octet, dst_nibble, len); 276*36381Ssklower ENDDEBUG 277*36381Ssklower #define SHIFT 0x4 278*36381Ssklower 279*36381Ssklower dshift = dst_nibble << 2; 280*36381Ssklower sshift = src_nibble << 2; 281*36381Ssklower 282*36381Ssklower for (i=0; i<len; i++) { 283*36381Ssklower nibble_b = ((*dst_octet)>>dshift) & 0xf; 284*36381Ssklower nibble_a = ( 0xf & (*src_octet >> sshift)); 285*36381Ssklower if( nibble_b != nibble_a ) 286*36381Ssklower return 0; 287*36381Ssklower 288*36381Ssklower dshift ^= SHIFT; 289*36381Ssklower sshift ^= SHIFT; 290*36381Ssklower src_nibble = 1-src_nibble; 291*36381Ssklower dst_nibble = 1-dst_nibble; 292*36381Ssklower src_octet += src_nibble; 293*36381Ssklower dst_octet += dst_nibble; 294*36381Ssklower } 295*36381Ssklower IFDEBUG(D_CADDR) 296*36381Ssklower printf("nibble_match DONE\n"); 297*36381Ssklower ENDDEBUG 298*36381Ssklower return 1; 299*36381Ssklower } 300*36381Ssklower 301*36381Ssklower #ifdef ARGO_DEBUG 302*36381Ssklower 303*36381Ssklower Static 304*36381Ssklower dump_copcb(copcb, str) 305*36381Ssklower char * str; 306*36381Ssklower register struct cons_pcb *copcb; 307*36381Ssklower { 308*36381Ssklower printf("XPCB DUMP %s\n", str); 309*36381Ssklower if (copcb) { 310*36381Ssklower printf("\t copcb 0x%x next 0x%x head 0x%x socket 0x%x ifp 0x%x\n", 311*36381Ssklower copcb, copcb->co_next, copcb->co_head, copcb->co_socket, copcb->co_ifp); 312*36381Ssklower printf("\t channel 0x%x state 0x%x flags 0x%x proto 0x%x\n", 313*36381Ssklower copcb->co_channel, copcb->co_state, copcb->co_flags, copcb->co_proto); 314*36381Ssklower printf("\t laddr :\n"); 315*36381Ssklower dump_isoaddr(&copcb->co_laddr); 316*36381Ssklower printf("\t faddr :\n"); 317*36381Ssklower dump_isoaddr(&copcb->co_faddr); 318*36381Ssklower printf("\tttl 0x%x init_ttl 0x%x pending: %d\n", 319*36381Ssklower copcb->co_ttl, copcb->co_init_ttl, copcb->co_pending.ifq_len); 320*36381Ssklower } 321*36381Ssklower printf("END DUMP\n"); 322*36381Ssklower } 323*36381Ssklower #endif ARGO_DEBUG 324*36381Ssklower 325*36381Ssklower /* 326*36381Ssklower * FUNCTION : choose_output - chooses between the eicon and loopback. 327*36381Ssklower * This MUST be here because the ifp->if_output routine is cosns_output 328*36381Ssklower * -- due to our need to look like a device driver for CLNP. sigh. 329*36381Ssklower * ARGUMENTS & PURPOSE: (copcb) ptr to a protocol control block for 330*36381Ssklower * x.25, (m) is an mbuf ptr. *m is a request destined either 331*36381Ssklower * for the eicon driver or for the loopback driver. 332*36381Ssklower * RETURNS : whatever error value the 2I or loopback returns. 333*36381Ssklower */ 334*36381Ssklower Static int 335*36381Ssklower choose_output( ifp, m, loop) 336*36381Ssklower struct ifnet *ifp; 337*36381Ssklower struct mbuf *m; 338*36381Ssklower int loop; 339*36381Ssklower { 340*36381Ssklower int error; 341*36381Ssklower 342*36381Ssklower if( !m ) 343*36381Ssklower return 0; 344*36381Ssklower ASSERT(m->m_len != 0); 345*36381Ssklower if( loop != 0) 346*36381Ssklower error = lpboutput( ifp, m ); 347*36381Ssklower else 348*36381Ssklower error = ecnoutput( ifp, m ); 349*36381Ssklower 350*36381Ssklower if (error == 0) 351*36381Ssklower ifp->if_opackets ++; 352*36381Ssklower else { 353*36381Ssklower ifp->if_oerrors ++; 354*36381Ssklower IFTRACE(D_CDATA) 355*36381Ssklower tptrace( TPPTmisc, 356*36381Ssklower "choose_output: ifp m error loop\n", 357*36381Ssklower ifp, m, error, loop); 358*36381Ssklower ENDTRACE 359*36381Ssklower } 360*36381Ssklower IFDEBUG(D_CCONS) 361*36381Ssklower printf("choose_output returns 0x%x\n", error ); 362*36381Ssklower ENDDEBUG 363*36381Ssklower return error; 364*36381Ssklower } 365*36381Ssklower 366*36381Ssklower /* 367*36381Ssklower **************************** NET PROTOCOL cons *************************** 368*36381Ssklower */ 369*36381Ssklower 370*36381Ssklower /* 371*36381Ssklower * NAME: cons_init() 372*36381Ssklower * CALLED FROM: 373*36381Ssklower * autoconf 374*36381Ssklower * FUNCTION: 375*36381Ssklower * initialize the protocol 376*36381Ssklower */ 377*36381Ssklower cons_init() 378*36381Ssklower { 379*36381Ssklower init_lpb(); 380*36381Ssklower consattach(); 381*36381Ssklower 382*36381Ssklower /* protocol init stuff */ 383*36381Ssklower 384*36381Ssklower consintrq.ifq_maxlen = IFQ_MAXLEN; 385*36381Ssklower consintrq.ifq_head = consintrq.ifq_tail = (struct mbuf *)0; 386*36381Ssklower 387*36381Ssklower CLNP_proto = pffindproto(AF_ISO, ISOPROTO_CLNP, SOCK_DGRAM); 388*36381Ssklower X25_proto = pffindproto(AF_ISO, ISOPROTO_X25, SOCK_STREAM); 389*36381Ssklower TP_proto = pffindproto(AF_ISO, ISOPROTO_TP0, SOCK_SEQPACKET); 390*36381Ssklower IFDEBUG(D_CCONS) 391*36381Ssklower printf("cons_init end : cnlp_proto 0x%x cons proto 0x%x tp proto 0x%x\n", 392*36381Ssklower CLNP_proto, X25_proto, TP_proto); 393*36381Ssklower ENDDEBUG 394*36381Ssklower 395*36381Ssklower cons_isopcb.isop_next = cons_isopcb.isop_prev = &cons_isopcb; 396*36381Ssklower tp_incoming_pending.isop_next = tp_incoming_pending.isop_prev = 397*36381Ssklower &tp_incoming_pending; 398*36381Ssklower } 399*36381Ssklower 400*36381Ssklower #ifdef notdef 401*36381Ssklower 402*36381Ssklower /* 403*36381Ssklower * NAME: cons_free_lru() 404*36381Ssklower * some day CALLED FROM: 405*36381Ssklower * wherever we run out of mbufs (not used right yet) 406*36381Ssklower * FUNCTION: 407*36381Ssklower * get rid of the num least recently used connections and 408*36381Ssklower * recycle their mbufs. 409*36381Ssklower * NOTE: GROTESQUELY INEFFICIENT needs to be written nicely 410*36381Ssklower */ 411*36381Ssklower 412*36381Ssklower Static 413*36381Ssklower cons_free_lru(qty) 414*36381Ssklower int qty; 415*36381Ssklower { 416*36381Ssklower register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist; 417*36381Ssklower register struct cons_pcb *copcb; 418*36381Ssklower struct cons_pcb Lru; 419*36381Ssklower struct cons_pcb *lru; 420*36381Ssklower 421*36381Ssklower IFDEBUG(D_CCONS) 422*36381Ssklower printf("cons_free_lru( 0x%x )\n", qty); 423*36381Ssklower ENDDEBUG 424*36381Ssklower 425*36381Ssklower Lru.co_ttl = X25_TTL; 426*36381Ssklower lru = &Lru; 427*36381Ssklower 428*36381Ssklower while (qty > 1) { /* GROT */ 429*36381Ssklower cons_free_lru( 1 ); 430*36381Ssklower qty -- ; 431*36381Ssklower } 432*36381Ssklower 433*36381Ssklower for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) { 434*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 435*36381Ssklower while (copcb != *copcblist) { 436*36381Ssklower if( copcb->co_ttl < lru->co_ttl ) 437*36381Ssklower lru = copcb; 438*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 439*36381Ssklower } 440*36381Ssklower } 441*36381Ssklower 442*36381Ssklower if(lru->co_socket) { 443*36381Ssklower soisdisconnected(lru->co_socket); 444*36381Ssklower sohasoutofband(lru->co_socket); /* signal */ 445*36381Ssklower } 446*36381Ssklower 447*36381Ssklower cons_clear_and_detach( lru, E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS); 448*36381Ssklower } 449*36381Ssklower #endif notdef 450*36381Ssklower 451*36381Ssklower /* 452*36381Ssklower * NAME: cons_slowtimo() 453*36381Ssklower * CALLED FROM: 454*36381Ssklower * the clock 455*36381Ssklower * FUNCTION: 456*36381Ssklower * get rid of any timed-out cons connections 457*36381Ssklower * cons connections get "touched" with every use, meaning the 458*36381Ssklower * time-to-live gets reset to its max value w/ every use. 459*36381Ssklower * The slowtimo() rtn decrements the time-to-live for each 460*36381Ssklower * cons connection. If one of them hits zero ---> zap the connection. 461*36381Ssklower * This really only applies to those used for CLNP and TP4. 462*36381Ssklower * TP4 keeps the connections open with keepalive. 463*36381Ssklower * TODO: 464*36381Ssklower * Have this happen ONLY for international connections since 465*36381Ssklower * there's no connect time charge for domestic calls. 466*36381Ssklower * Make default 5 min; make a user option to change it. 467*36381Ssklower * TODO: 468*36381Ssklower * Maybe if the ttl gets lower than a certain threshold, move this 469*36381Ssklower * copcb to the END of its queue so it doesn't slow down the others. 470*36381Ssklower */ 471*36381Ssklower 472*36381Ssklower cons_slowtimo() 473*36381Ssklower { 474*36381Ssklower register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist; 475*36381Ssklower register struct cons_pcb *copcb; 476*36381Ssklower int s = splnet(); 477*36381Ssklower int qlen = 0; 478*36381Ssklower int qdrops = 0; 479*36381Ssklower int nvisited = 0; 480*36381Ssklower 481*36381Ssklower #ifdef ARGO_DEBUG 482*36381Ssklower Static int count; 483*36381Ssklower 484*36381Ssklower count = 0; 485*36381Ssklower #endif ARGO_DEBUG 486*36381Ssklower 487*36381Ssklower IncStat(co_slowtimo); 488*36381Ssklower for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) { 489*36381Ssklower #ifdef ARGO_DEBUG 490*36381Ssklower if( copcb == (struct cons_pcb *)0 ) { 491*36381Ssklower ASSERT( 0 ); 492*36381Ssklower panic("TURNING OFF cons_slowtimo()!!! \n"); 493*36381Ssklower } 494*36381Ssklower #endif ARGO_DEBUG 495*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 496*36381Ssklower while (copcb != *copcblist) { 497*36381Ssklower #ifdef ARGO_DEBUG 498*36381Ssklower if(++count >50 ) { 499*36381Ssklower printf("cons PANIC: slowtimo LOOP\n"); 500*36381Ssklower splx(s); 501*36381Ssklower return; 502*36381Ssklower } 503*36381Ssklower #endif ARGO_DEBUG 504*36381Ssklower #ifdef notdef 505*36381Ssklower if( copcb->co_init_ttl == 0 ) { 506*36381Ssklower ASSERT( (struct isopcb *)(*copcblist)==(struct isopcb *)&tp_isopcb ); 507*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 508*36381Ssklower continue; 509*36381Ssklower } 510*36381Ssklower #endif notdef 511*36381Ssklower nvisited ++; 512*36381Ssklower ASSERT( copcb != (struct cons_pcb *)0 ); 513*36381Ssklower qlen += copcb->co_pending.ifq_len; 514*36381Ssklower qdrops += copcb->co_pending.ifq_drops; 515*36381Ssklower 516*36381Ssklower if( copcb->co_socket) { 517*36381Ssklower /* don't want XTS, TP0 connections to be subject to time out */ 518*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 519*36381Ssklower continue; 520*36381Ssklower } 521*36381Ssklower 522*36381Ssklower if( -- (copcb->co_ttl) > 0 ) { 523*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 524*36381Ssklower continue; 525*36381Ssklower } 526*36381Ssklower 527*36381Ssklower IncStat(co_timedout); 528*36381Ssklower 529*36381Ssklower IFDEBUG(D_CCONN) 530*36381Ssklower printf("TIMING OUT chan 0x%x copcb 0x%x flags 0x%x\n", 531*36381Ssklower copcb->co_channel, copcb, copcb->co_flags ); 532*36381Ssklower ENDDEBUG 533*36381Ssklower 534*36381Ssklower { 535*36381Ssklower register struct cons_pcb * next = 536*36381Ssklower (struct cons_pcb *)copcb->co_next; 537*36381Ssklower cons_clear_and_detach(copcb, 538*36381Ssklower E_CO_HLI_RESYNC, PRC_TIMXCEED_REASS); 539*36381Ssklower copcb = next; 540*36381Ssklower } 541*36381Ssklower } 542*36381Ssklower } 543*36381Ssklower if(nvisited) { 544*36381Ssklower cons_stat.co_avg_qlen = qlen / nvisited; 545*36381Ssklower cons_stat.co_avg_qdrop = qdrops / nvisited; 546*36381Ssklower cons_stat.co_active = nvisited; 547*36381Ssklower } 548*36381Ssklower done: 549*36381Ssklower splx(s); 550*36381Ssklower } 551*36381Ssklower 552*36381Ssklower DUMP_PCBLIST() 553*36381Ssklower { 554*36381Ssklower register int i=0; 555*36381Ssklower register struct cons_pcb *copcb; 556*36381Ssklower register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist; 557*36381Ssklower 558*36381Ssklower for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) { 559*36381Ssklower printf("FOR %d: 0x%x ", ++i, copcb); 560*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 561*36381Ssklower printf(" next 0x%x, *copcblist 0x%x\n", copcb, *copcblist); 562*36381Ssklower while (copcb != *copcblist) { 563*36381Ssklower ASSERT( copcb != (struct cons_pcb *)0 ); 564*36381Ssklower printf("\tCOPCB 0x%x\n", copcb); 565*36381Ssklower if( copcb ) 566*36381Ssklower dump_buf(copcb, sizeof( *copcb)); 567*36381Ssklower else 568*36381Ssklower break; 569*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 570*36381Ssklower } 571*36381Ssklower } 572*36381Ssklower } 573*36381Ssklower 574*36381Ssklower /* 575*36381Ssklower * NAME: cons_pcballoc() 576*36381Ssklower * CALLED FROM: 577*36381Ssklower * cons_usrreq() when doing PRU_ATTACH, 578*36381Ssklower * cons_incoming() when opening a new connection. 579*36381Ssklower * FUNCTION and ARGUMENTS: 580*36381Ssklower * Allocates a new pcb. 581*36381Ssklower * The flags and proto arguments are stashed into the new pcb. 582*36381Ssklower * RETURN VALUE: 583*36381Ssklower * E* if error, 0 if ok 584*36381Ssklower */ 585*36381Ssklower Static int 586*36381Ssklower cons_pcballoc(so, head, flags, proto, dest) 587*36381Ssklower struct socket *so; 588*36381Ssklower struct isopcb *head; 589*36381Ssklower u_short flags; 590*36381Ssklower struct protosw *proto; 591*36381Ssklower struct cons_pcb **dest; 592*36381Ssklower { 593*36381Ssklower int error; 594*36381Ssklower register struct cons_pcb *copcb; 595*36381Ssklower 596*36381Ssklower IFDEBUG(D_CCONN) 597*36381Ssklower printf("cons_pcballoc (0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", 598*36381Ssklower so, head, flags, proto, dest); 599*36381Ssklower ENDDEBUG 600*36381Ssklower if(proto == (struct protosw *)0) 601*36381Ssklower return EPROTONOSUPPORT; 602*36381Ssklower 603*36381Ssklower if( ( error = iso_pcballoc(so, head) ) == EOK ) { 604*36381Ssklower /* Have allocated a cleared mbuf */ 605*36381Ssklower 606*36381Ssklower copcb = (struct cons_pcb *)so->so_pcb; 607*36381Ssklower copcb->co_ttl = copcb->co_init_ttl = X25_TTL; 608*36381Ssklower copcb->co_flags = flags; 609*36381Ssklower copcb->co_proto = proto; 610*36381Ssklower copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN; 611*36381Ssklower copcb->co_myself = copcb; 612*36381Ssklower 613*36381Ssklower if (so == &dummysocket) 614*36381Ssklower copcb->co_socket = (struct socket *)0; 615*36381Ssklower 616*36381Ssklower *dest = copcb; 617*36381Ssklower } 618*36381Ssklower done: 619*36381Ssklower IFDEBUG(D_CCONN) 620*36381Ssklower printf("cons_pcballoc returns 0x%x: DUMP\n", copcb); 621*36381Ssklower dump_buf( copcb, sizeof(*copcb)); 622*36381Ssklower ENDDEBUG 623*36381Ssklower if( (flags & CONSF_ICRE) == 0) { 624*36381Ssklower struct dte_addr *dtea = &(*dest)->co_peer_dte; 625*36381Ssklower int len; 626*36381Ssklower 627*36381Ssklower error = iso_8208snparesolve(&(*dest)->co_faddr, dtea, &len); 628*36381Ssklower ASSERT(error == 0); 629*36381Ssklower ASSERT(len == sizeof(struct dte_addr)); 630*36381Ssklower } 631*36381Ssklower 632*36381Ssklower return error; 633*36381Ssklower } 634*36381Ssklower 635*36381Ssklower /* 636*36381Ssklower * NAME: cons_connect() 637*36381Ssklower * CALLED FROM: 638*36381Ssklower * cons_usrreq() when opening a new connection. 639*36381Ssklower * FUNCTION anD ARGUMENTS: 640*36381Ssklower * Figures out which device to use, finding a route if one doesn't 641*36381Ssklower * already exist. 642*36381Ssklower * Builds an eicon connection request and gives it to the device. 643*36381Ssklower * RETURN VALUE: 644*36381Ssklower * returns E* 645*36381Ssklower */ 646*36381Ssklower Static int 647*36381Ssklower cons_connect( copcb ) 648*36381Ssklower register struct cons_pcb *copcb; 649*36381Ssklower { 650*36381Ssklower register struct eicon_request *ecnrq; 651*36381Ssklower register struct mbuf *m; 652*36381Ssklower int error = 0; 653*36381Ssklower struct ifaddr *ifa; 654*36381Ssklower 655*36381Ssklower IFDEBUG(D_CCONN) 656*36381Ssklower printf("cons_connect( 0x%x ) : ifp 0x%x\npeer: ", copcb, copcb->co_ifp); 657*36381Ssklower dump_isoaddr(&copcb->co_faddr); 658*36381Ssklower printf("\nmyaddr: "); 659*36381Ssklower dump_isoaddr(&copcb->co_laddr); 660*36381Ssklower printf("\n" ); 661*36381Ssklower ENDDEBUG 662*36381Ssklower 663*36381Ssklower /* PHASE 2: this call is OK */ 664*36381Ssklower if( ifa = ifa_ifwithaddr(&copcb->co_faddr ) ) { 665*36381Ssklower /* foreign address is me */ 666*36381Ssklower copcb->co_ifp = ifa->ifa_ifp; 667*36381Ssklower IFDEBUG(D_CCONN) 668*36381Ssklower printf("cons_connect: after if_withaddr copcb->co_ifp 0x%x\n", 669*36381Ssklower copcb->co_ifp); 670*36381Ssklower ENDDEBUG 671*36381Ssklower 672*36381Ssklower if( (ifa->ifa_ifp->if_flags&(IFF_LOOPBACK|IFF_UP)) == 673*36381Ssklower (IFF_LOOPBACK|IFF_UP)) { 674*36381Ssklower copcb->co_flags |= CONSF_LOOPBACK; 675*36381Ssklower } 676*36381Ssklower bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 677*36381Ssklower sizeof(struct sockaddr)); 678*36381Ssklower } 679*36381Ssklower IFDEBUG(D_CCONN) 680*36381Ssklower printf("cons_connect: co_flags 0x%x\n", copcb->co_flags); 681*36381Ssklower if( ifa ) { 682*36381Ssklower printf(" cons_connect withaddr returns %s\n", 683*36381Ssklower copcb->co_ifp->if_name); 684*36381Ssklower } 685*36381Ssklower ENDDEBUG 686*36381Ssklower else if ( copcb->co_ifp == (struct ifnet *)0 ) { 687*36381Ssklower #ifdef PHASEONE 688*36381Ssklower /* 689*36381Ssklower * We need to get the local nsap address. 690*36381Ssklower * First, route to the destination. This will provide us with 691*36381Ssklower * an ifp. Second, determine which local address linked on 692*36381Ssklower * that ifp is appropriate 693*36381Ssklower */ 694*36381Ssklower struct sockaddr_iso *first_hop; /* filled by clnp_route */ 695*36381Ssklower struct iso_addr *localaddr, *clnp_srcaddr(); 696*36381Ssklower 697*36381Ssklower if (error = clnp_route(&copcb->co_faddr, 698*36381Ssklower &((struct isopcb *)copcb)->isop_route, /* flags */0, 699*36381Ssklower &first_hop, &copcb->co_ifp)) 700*36381Ssklower goto bad; 701*36381Ssklower 702*36381Ssklower /* determine local address based upon ifp */ 703*36381Ssklower if ((localaddr = clnp_srcaddr(copcb->co_ifp, 704*36381Ssklower &first_hop->siso_addr)) == NULL) { 705*36381Ssklower error = ENETUNREACH; 706*36381Ssklower goto bad; 707*36381Ssklower } 708*36381Ssklower copcb->co_laddr.siso_family = AF_ISO; 709*36381Ssklower copcb->co_laddr.siso_addr = *localaddr; 710*36381Ssklower #else 711*36381Ssklower /* Foreign addr isn't me (lpb). If still don't have an ifp or have 712*36381Ssklower * an ifp but don't know its address, look for a route 713*36381Ssklower */ 714*36381Ssklower if( ifa = ifa_ifwithnet(&copcb->co_faddr) ) { 715*36381Ssklower copcb->co_ifp = ifa->ifa_ifp; 716*36381Ssklower IFDEBUG(D_CCONN) 717*36381Ssklower printf(" cons_connect withnet returns %s\n", 718*36381Ssklower copcb->co_ifp->if_name); 719*36381Ssklower ENDDEBUG 720*36381Ssklower } else { 721*36381Ssklower printf("cons PANIC: connect: can't find SNPA \n"); 722*36381Ssklower error = ENETUNREACH; 723*36381Ssklower goto bad; 724*36381Ssklower } 725*36381Ssklower #endif PHASEONE 726*36381Ssklower } 727*36381Ssklower #ifndef PHASEONE 728*36381Ssklower if( ifa == (struct ifaddr *)0 ) { 729*36381Ssklower struct ifaddr * iso_ifwithidi(); 730*36381Ssklower 731*36381Ssklower if( ifa = iso_ifwithidi(&copcb->co_faddr) ) { 732*36381Ssklower copcb->co_ifp = ifa->ifa_ifp; 733*36381Ssklower IFDEBUG(D_CCONN) 734*36381Ssklower printf(" cons_connect withnet returns %s\n", 735*36381Ssklower copcb->co_ifp->if_name); 736*36381Ssklower ENDDEBUG 737*36381Ssklower } else { 738*36381Ssklower printf("cons PANIC: connect: can't find SNPA \n"); 739*36381Ssklower error = ENETUNREACH; 740*36381Ssklower goto bad; 741*36381Ssklower } 742*36381Ssklower } 743*36381Ssklower bcopy((caddr_t)&ifa->ifa_addr, (caddr_t)&copcb->co_laddr, 744*36381Ssklower sizeof(struct sockaddr)); 745*36381Ssklower #endif PHASEONE 746*36381Ssklower 747*36381Ssklower copcb->co_state = CONNECTING; 748*36381Ssklower 749*36381Ssklower ASSERT( copcb->co_ifp != (struct ifnet *) 0); 750*36381Ssklower if ( copcb->co_ifp == (struct ifnet *)0 ) { 751*36381Ssklower error = ENETUNREACH; 752*36381Ssklower goto bad; 753*36381Ssklower } 754*36381Ssklower 755*36381Ssklower m = m_getclr(M_DONTWAIT, MT_XCONN); 756*36381Ssklower if( !m ) { 757*36381Ssklower copcb->co_ifp->if_oerrors ++; 758*36381Ssklower error = ENOBUFS; 759*36381Ssklower goto bad; 760*36381Ssklower } 761*36381Ssklower m->m_len = sizeof(struct eicon_request); 762*36381Ssklower 763*36381Ssklower ecnrq = mtod(m, struct eicon_request *); 764*36381Ssklower 765*36381Ssklower copcb->co_myself = copcb; 766*36381Ssklower ecnrq->e_pcb = (caddr_t)copcb; 767*36381Ssklower #ifdef ARGO_DEBUG 768*36381Ssklower LAST_CALL_PCB = (unsigned) ecnrq->e_pcb; 769*36381Ssklower #endif ARGO_DEBUG 770*36381Ssklower ecnrq->e_cmd = ECN_CALL; 771*36381Ssklower ecnrq->e_vc = 0; /* mbz ? */ 772*36381Ssklower ecnrq->e_info = 0; /* mbz */ 773*36381Ssklower 774*36381Ssklower /* get data buffer */ 775*36381Ssklower { struct mbuf *n; 776*36381Ssklower 777*36381Ssklower MGET(n, M_DONTWAIT, MT_XCONN); 778*36381Ssklower if( n==MNULL ) { 779*36381Ssklower copcb->co_ifp->if_oerrors ++; 780*36381Ssklower error = ENOBUFS; 781*36381Ssklower goto bad; 782*36381Ssklower } 783*36381Ssklower e_data(ecnrq) = n; /* e_data is really dtom(ecnrq)->m_next */ 784*36381Ssklower } 785*36381Ssklower 786*36381Ssklower IFDEBUG(D_CCONN) 787*36381Ssklower printf( 788*36381Ssklower "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", 789*36381Ssklower &copcb->co_laddr, &copcb->co_faddr, 790*36381Ssklower copcb->co_proto->pr_protocol, 791*36381Ssklower e_data(ecnrq), 792*36381Ssklower copcb->co_flags & CONSF_XTS); 793*36381Ssklower ENDDEBUG 794*36381Ssklower if( error = make_partial_x25_packet( copcb, e_data(ecnrq)) ) { 795*36381Ssklower copcb->co_ifp->if_oerrors ++; 796*36381Ssklower m_freem(m); 797*36381Ssklower goto bad; 798*36381Ssklower } 799*36381Ssklower 800*36381Ssklower IncStat(co_call); 801*36381Ssklower 802*36381Ssklower IFDEBUG(D_CDUMP_REQ) 803*36381Ssklower printf("cons_connect ecnrq:\n"); 804*36381Ssklower dump_buf(ecnrq, sizeof(*ecnrq)); 805*36381Ssklower ENDDEBUG 806*36381Ssklower 807*36381Ssklower ASSERT( copcb->co_channel == 0); 808*36381Ssklower if( copcb->co_channel != 0) { 809*36381Ssklower printf("cons_connect PANIC: channel is 0x%x\n", copcb->co_channel); 810*36381Ssklower } 811*36381Ssklower 812*36381Ssklower error = choose_output(copcb->co_ifp, m, copcb->co_flags & CONSF_LOOPBACK); 813*36381Ssklower 814*36381Ssklower switch( error ) { 815*36381Ssklower case 0: /* ok */ 816*36381Ssklower break; 817*36381Ssklower default: /* problem */ 818*36381Ssklower printf("cons: PANIC: if_output returns 0x%x\n", error); 819*36381Ssklower cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD); 820*36381Ssklower } 821*36381Ssklower 822*36381Ssklower bad: 823*36381Ssklower IFTRACE(D_CDATA) 824*36381Ssklower tptrace( TPPTmisc, 825*36381Ssklower "cons_connect: choose (copcb m) returned error\n", 826*36381Ssklower copcb, m, error, 0); 827*36381Ssklower ENDTRACE 828*36381Ssklower return error; 829*36381Ssklower } 830*36381Ssklower 831*36381Ssklower /* 832*36381Ssklower * NAME: cons_find() 833*36381Ssklower * CALLED FROM: 834*36381Ssklower * cosns_output1() thus: 835*36381Ssklower * cons_find( CONSF_DGM, dst, proto, 0, 0) where 836*36381Ssklower * proto is one of { TP_proto, CLNP_proto } 837*36381Ssklower * FUNCTION and ARGUMENTS: 838*36381Ssklower * Looks through list of connections for the destination, 839*36381Ssklower * for one marked for the use indicated by flags. 840*36381Ssklower * If none found, opens up a new connection. 841*36381Ssklower * These connections will be eliminated by : 842*36381Ssklower * a) slowtimo timer, or 843*36381Ssklower * b) the need for a new connection, when we've run out of resources. 844*36381Ssklower * The argument flags describes the type of pcb we want - may 845*36381Ssklower * specify multiplexing-ok, datagram use, etc. 846*36381Ssklower * The argument proto points the the higher layer protocol that 847*36381Ssklower * will be using this connection. 848*36381Ssklower * RETURN VALUE: 849*36381Ssklower * returns a ptr to a pcb whose characteristics match those 850*36381Ssklower * described by (flags, proto) 851*36381Ssklower */ 852*36381Ssklower 853*36381Ssklower Static struct cons_pcb * 854*36381Ssklower cons_find(flags, dst, proto, addl_criteria, mask) 855*36381Ssklower u_int flags, mask; 856*36381Ssklower struct sockaddr_iso *dst; 857*36381Ssklower struct protosw *proto; 858*36381Ssklower int (*addl_criteria)(); 859*36381Ssklower { 860*36381Ssklower register struct cons_pcb *copcb; 861*36381Ssklower register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist; 862*36381Ssklower int s = splnet(); /* or whatever, for the device! */ 863*36381Ssklower struct dte_addr dest_dte; 864*36381Ssklower int dummy; 865*36381Ssklower 866*36381Ssklower struct copcb_descriptor { 867*36381Ssklower int xd_qlen; 868*36381Ssklower struct cons_pcb *xd_pcb; 869*36381Ssklower } next_best = { 870*36381Ssklower 0, (struct cons_pcb *)0 871*36381Ssklower }; 872*36381Ssklower 873*36381Ssklower IFDEBUG(D_CFIND) 874*36381Ssklower printf("cons_find( flags 0x%x proto 0x%x) ", flags, proto); 875*36381Ssklower ENDDEBUG 876*36381Ssklower 877*36381Ssklower if ( iso_8208snparesolve(dst, &dest_dte, &dummy)) { 878*36381Ssklower ASSERT(0); 879*36381Ssklower return (struct cons_pcb *)0; /* error */ 880*36381Ssklower } 881*36381Ssklower ASSERT(dummy == sizeof(struct dte_addr)); 882*36381Ssklower 883*36381Ssklower for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) { 884*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 885*36381Ssklower while (copcb != *copcblist) { 886*36381Ssklower IFDEBUG(D_CFIND) 887*36381Ssklower printf( 888*36381Ssklower "cons_find: chan 0x%x flags 0x%x proto 0x%x state 0x%x \n", 889*36381Ssklower copcb->co_channel, copcb->co_flags, copcb->co_proto, 890*36381Ssklower copcb->co_state); 891*36381Ssklower ENDDEBUG 892*36381Ssklower /* 893*36381Ssklower * if flags is a subset of the bits in co_flags, it will suffice 894*36381Ssklower */ 895*36381Ssklower if( ((copcb->co_flags & flags) == flags ) && 896*36381Ssklower /* PHASE2: where do we get the mask if we use nsaps ???? 897*36381Ssklower * If dte addresses are used, then use 898*36381Ssklower * nibble compare otherwise...??? 899*36381Ssklower */ 900*36381Ssklower #ifdef notdef 901*36381Ssklower iso_addrmatch1(&(copcb->co_faddr.siso_addr), &(dst->siso_addr)) 902*36381Ssklower #else 903*36381Ssklower dest_dte.dtea_niblen == copcb->co_peer_dte.dtea_niblen && 904*36381Ssklower nibble_match( (char *)&(copcb->co_peer_dte.dtea_addr), 905*36381Ssklower HIGH_NIBBLE, (char *)dest_dte.dtea_addr, 906*36381Ssklower HIGH_NIBBLE, dest_dte.dtea_niblen) 907*36381Ssklower #endif notdef 908*36381Ssklower && 909*36381Ssklower (copcb->co_proto == proto) && 910*36381Ssklower (copcb->co_state >= MIN_USABLE_STATE)) { 911*36381Ssklower IFDEBUG(D_CFIND) 912*36381Ssklower printf( 913*36381Ssklower "cons_find: add'l criteria...\n" ); 914*36381Ssklower ENDDEBUG 915*36381Ssklower if((copcb->co_state != OPEN) && 916*36381Ssklower (next_best.xd_qlen > copcb->co_pending.ifq_len)) { 917*36381Ssklower next_best.xd_pcb = copcb; 918*36381Ssklower next_best.xd_qlen = copcb->co_pending.ifq_len; 919*36381Ssklower } 920*36381Ssklower if( !addl_criteria || (*addl_criteria)(copcb, mask) ) { 921*36381Ssklower goto found; /* have to break out of 2 loops */ 922*36381Ssklower } 923*36381Ssklower } 924*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next ; 925*36381Ssklower } 926*36381Ssklower } 927*36381Ssklower #ifdef notdef 928*36381Ssklower /* TODO: 929*36381Ssklower * have a limit of the number of calls per desitination. 930*36381Ssklower * If we didn't find one already open AND our limit for this 931*36381Ssklower * destination hasn't been reached, return 0 'cause 932*36381Ssklower * then the caller will open a new one. 933*36381Ssklower * Otherwise return next_best. 934*36381Ssklower * To do this we need some sort of per-destination info. 935*36381Ssklower * Could go into the directory service. Oh, grotesque. 936*36381Ssklower */ 937*36381Ssklower #endif notdef 938*36381Ssklower if( copcb == (struct cons_pcb *)0 ) { 939*36381Ssklower copcb = next_best.xd_pcb; /* may be zero too */ 940*36381Ssklower IFDEBUG(D_CFIND) 941*36381Ssklower printf("NEXT_BEST! \n"); 942*36381Ssklower dump_copcb(copcb, "find: next_best"); 943*36381Ssklower ENDDEBUG 944*36381Ssklower } 945*36381Ssklower found: 946*36381Ssklower 947*36381Ssklower splx(s); 948*36381Ssklower 949*36381Ssklower IFDEBUG(D_CFIND) 950*36381Ssklower printf("returns 0x%x \n", copcb); 951*36381Ssklower ENDDEBUG 952*36381Ssklower return copcb; 953*36381Ssklower } 954*36381Ssklower 955*36381Ssklower 956*36381Ssklower /* 957*36381Ssklower * NAME: issue_clear_req() 958*36381Ssklower * CALLED FROM: 959*36381Ssklower * cons_clear() and wherever we get an error from x.25 that makes us 960*36381Ssklower * want to close the vc on which it came, but don't have 961*36381Ssklower * a copcb assoc. with that vc. 962*36381Ssklower * FUNCTION and ARGUMENTS: 963*36381Ssklower * Creates an eicon_request for a clear request, returns it in an mbuf. 964*36381Ssklower * (chan) is the channel on which to do the clear, (reason) is the 965*36381Ssklower * clear reason(diagnostic). 966*36381Ssklower * RETURN VALUE: 967*36381Ssklower * returns E* 968*36381Ssklower */ 969*36381Ssklower Static int 970*36381Ssklower issue_clear_req(chan, reason, ifp, loop) 971*36381Ssklower u_char chan, reason; 972*36381Ssklower struct ifnet *ifp; 973*36381Ssklower int loop; 974*36381Ssklower { 975*36381Ssklower register struct mbuf *m; 976*36381Ssklower register struct mbuf *cdm; 977*36381Ssklower register struct eicon_request *ecnrq; 978*36381Ssklower struct e_clear_data *ecd; 979*36381Ssklower 980*36381Ssklower IFDEBUG(D_CCONN) 981*36381Ssklower printf("issue_clear_req(0x%x, 0x%x, 0x%x, 0x%x)\n", 982*36381Ssklower chan, reason, ifp, loop); 983*36381Ssklower ENDDEBUG 984*36381Ssklower m = m_getclr(M_DONTWAIT, MT_XCLOSE); 985*36381Ssklower if( !m ) { 986*36381Ssklower return ENOBUFS; 987*36381Ssklower } 988*36381Ssklower m->m_len = sizeof(struct eicon_request); 989*36381Ssklower ecnrq = mtod(m, struct eicon_request *); 990*36381Ssklower ecnrq->e_cmd = ECN_CLEAR; 991*36381Ssklower ecnrq->e_vc = chan & 0xff; 992*36381Ssklower /* 993*36381Ssklower * see p. 149 of 8208 for reasons (diagnostic codes) 994*36381Ssklower */ 995*36381Ssklower MGET(cdm, M_DONTWAIT, MT_XCLOSE); 996*36381Ssklower if( !cdm ) { 997*36381Ssklower m_freem(m); 998*36381Ssklower return ENOBUFS; 999*36381Ssklower } 1000*36381Ssklower cdm->m_len = sizeof(struct e_clear_data); /* cause, diagnostic */ 1001*36381Ssklower e_data(ecnrq) = cdm; 1002*36381Ssklower 1003*36381Ssklower ecd = mtod(cdm, struct e_clear_data *); 1004*36381Ssklower ecd->ecd_cause = 0x0; /* DTE initiated, diagnostic tells more */ 1005*36381Ssklower ecd->ecd_diagnostic = (u_char)reason; 1006*36381Ssklower 1007*36381Ssklower IncStat(co_clear_out); 1008*36381Ssklower return choose_output(ifp, m, loop); 1009*36381Ssklower } 1010*36381Ssklower 1011*36381Ssklower 1012*36381Ssklower /* 1013*36381Ssklower * NAME: cons_clear() 1014*36381Ssklower * CALLED FROM: 1015*36381Ssklower * cons_usrreq(), PRU_DISCONNECT, 1016*36381Ssklower * cons_slowtimo(), cons_free_lru() 1017*36381Ssklower * FUNCTION and ARGUMENTS: 1018*36381Ssklower * Builds a clear request for the connection represented by copcb, 1019*36381Ssklower * gives it to the device. 1020*36381Ssklower * ECN_CLEAR(request) takes e_vc only, returns adr_status. 1021*36381Ssklower * RETURN VALUE: 1022*36381Ssklower */ 1023*36381Ssklower 1024*36381Ssklower Static int 1025*36381Ssklower cons_clear( copcb, reason) 1026*36381Ssklower register struct cons_pcb *copcb; 1027*36381Ssklower u_char reason; 1028*36381Ssklower { 1029*36381Ssklower register struct mbuf *m; 1030*36381Ssklower int error; 1031*36381Ssklower 1032*36381Ssklower IFDEBUG(D_CCONN) 1033*36381Ssklower printf("cons_clear(0x%x, 0x%x)\n", copcb, reason); 1034*36381Ssklower ENDDEBUG 1035*36381Ssklower if( !copcb) { 1036*36381Ssklower printf("cons PANIC: clear: No copcb\n"); 1037*36381Ssklower return 0; 1038*36381Ssklower } 1039*36381Ssklower while( copcb->co_pending.ifq_len > 0 ) { 1040*36381Ssklower register int s = splimp(); 1041*36381Ssklower 1042*36381Ssklower IF_DEQUEUE( &copcb->co_pending, m ); 1043*36381Ssklower splx(s); 1044*36381Ssklower m_freem(m); 1045*36381Ssklower } 1046*36381Ssklower if( (copcb->co_state == CLOSED) || (copcb->co_state == CLOSING) ) 1047*36381Ssklower return 0; 1048*36381Ssklower 1049*36381Ssklower #ifdef ARGO_DEBUG 1050*36381Ssklower if( copcb->co_state == CONNECTING) { 1051*36381Ssklower IFDEBUG(D_CCONN) 1052*36381Ssklower dump_copcb(copcb, "clear"); 1053*36381Ssklower ENDDEBUG 1054*36381Ssklower } else if( (copcb->co_channel == 0) || (copcb->co_channel == X_NOCHANNEL) ) { 1055*36381Ssklower IFDEBUG(D_CCONN) 1056*36381Ssklower dump_copcb(copcb, "clear"); 1057*36381Ssklower ENDDEBUG 1058*36381Ssklower } 1059*36381Ssklower #endif ARGO_DEBUG 1060*36381Ssklower 1061*36381Ssklower copcb->co_state = CLOSING; 1062*36381Ssklower 1063*36381Ssklower IFDEBUG(D_CCONN) 1064*36381Ssklower printf("cons_clear: channel 0x%x copcb 0x%x dst: ", 1065*36381Ssklower copcb->co_channel, copcb); 1066*36381Ssklower dump_isoaddr(&copcb->co_faddr); 1067*36381Ssklower dump_copcb(copcb, "clear"); 1068*36381Ssklower ENDDEBUG 1069*36381Ssklower 1070*36381Ssklower error = issue_clear_req(copcb->co_channel, reason, copcb->co_ifp, 1071*36381Ssklower copcb->co_flags & CONSF_LOOPBACK); 1072*36381Ssklower copcb->co_channel = X_NOCHANNEL; 1073*36381Ssklower copcb->co_state = CLOSED; 1074*36381Ssklower return error; 1075*36381Ssklower } 1076*36381Ssklower 1077*36381Ssklower 1078*36381Ssklower /* 1079*36381Ssklower * NAME: cons_senddata() 1080*36381Ssklower * CALLED FROM: 1081*36381Ssklower * cons_output(), consoutput(), consintr() 1082*36381Ssklower * FUNCTION and ARGUMENTS: 1083*36381Ssklower * issued a data (write) command - if the device isn't ready, 1084*36381Ssklower * it enqueues the command on a per-connection queue. 1085*36381Ssklower * RETURN VALUE: 1086*36381Ssklower * ENOBUFS 1087*36381Ssklower * Is responsible for freeing m0! 1088*36381Ssklower * 1089*36381Ssklower * ECN_SEND (write) 1090*36381Ssklower */ 1091*36381Ssklower 1092*36381Ssklower Static int 1093*36381Ssklower cons_senddata(copcb, m0) 1094*36381Ssklower register struct cons_pcb *copcb; 1095*36381Ssklower struct mbuf *m0; 1096*36381Ssklower { 1097*36381Ssklower register struct mbuf *m; 1098*36381Ssklower register struct eicon_request *ecnrq; 1099*36381Ssklower int s; 1100*36381Ssklower 1101*36381Ssklower IFDEBUG(D_CDATA) 1102*36381Ssklower printf("cons_senddata( 0x%x, m 0x%x ) chan 0x%x", 1103*36381Ssklower copcb, m0, copcb->co_channel ); 1104*36381Ssklower printf(" co_lport 0x%x\n", copcb->co_lport); 1105*36381Ssklower ENDDEBUG 1106*36381Ssklower if( m0 == MNULL ) 1107*36381Ssklower return; 1108*36381Ssklower ASSERT( m0->m_len > 0); 1109*36381Ssklower if( m0->m_len <= 0) { 1110*36381Ssklower printf("cons_senddata : BAD MLEN? 0x%x", m0->m_len); 1111*36381Ssklower } 1112*36381Ssklower 1113*36381Ssklower touch(copcb); 1114*36381Ssklower 1115*36381Ssklower if( (copcb->co_state == CONNECTING) || (copcb->co_state == ACKWAIT) ) { 1116*36381Ssklower IFDEBUG(D_CDATA) 1117*36381Ssklower printf("senddata PUTTING ON PENDING Q copcb 0x%x state 0x%x\n", 1118*36381Ssklower copcb, copcb->co_state); 1119*36381Ssklower ENDDEBUG 1120*36381Ssklower s = splimp(); 1121*36381Ssklower if (IF_QFULL(&copcb->co_pending)) { 1122*36381Ssklower IFDEBUG(D_CDATA) 1123*36381Ssklower printf("senddata DROPPING m0 0x%x\n", m0); 1124*36381Ssklower ENDDEBUG 1125*36381Ssklower IF_DROP(&copcb->co_pending); 1126*36381Ssklower if(copcb->co_ifp) { 1127*36381Ssklower copcb->co_ifp->if_snd.ifq_drops ++; 1128*36381Ssklower } 1129*36381Ssklower IncStat(co_Xdrops); 1130*36381Ssklower copcb->co_ifp->if_oerrors ++; 1131*36381Ssklower splx(s); 1132*36381Ssklower m_freem (m0); 1133*36381Ssklower 1134*36381Ssklower if( copcb->co_proto && copcb->co_proto->pr_ctlinput ) { 1135*36381Ssklower (*copcb->co_proto->pr_ctlinput)(PRC_QUENCH, 1136*36381Ssklower (struct sockaddr_iso *)&copcb->co_faddr, 1137*36381Ssklower (caddr_t)copcb); 1138*36381Ssklower 1139*36381Ssklower return 0; 1140*36381Ssklower } else 1141*36381Ssklower return E_CO_QFULL; 1142*36381Ssklower } 1143*36381Ssklower IFDEBUG(D_CDATA) 1144*36381Ssklower printf("Putting 0x%x on 0x%x->pending Q\n", m0, copcb); 1145*36381Ssklower ENDDEBUG 1146*36381Ssklower IF_ENQUEUE( &copcb->co_pending, m0 ); 1147*36381Ssklower splx(s); 1148*36381Ssklower return 0; 1149*36381Ssklower } 1150*36381Ssklower if(copcb->co_channel == 0 ) { 1151*36381Ssklower return E_CO_CHAN; 1152*36381Ssklower } 1153*36381Ssklower ASSERT( copcb->co_state == OPEN); 1154*36381Ssklower 1155*36381Ssklower m = m_getclr(M_DONTWAIT, MT_XDATA); 1156*36381Ssklower if( !m ) { 1157*36381Ssklower copcb->co_ifp->if_oerrors ++; 1158*36381Ssklower m_freem (m0); 1159*36381Ssklower return ENOBUFS; 1160*36381Ssklower } 1161*36381Ssklower m->m_len = sizeof(struct eicon_request); 1162*36381Ssklower ecnrq = mtod(m, struct eicon_request *); 1163*36381Ssklower ecnrq->e_pcb = (caddr_t)copcb; 1164*36381Ssklower if( copcb->co_myself != copcb ) { 1165*36381Ssklower struct mbuf *mm; 1166*36381Ssklower /* TODO: REMOVE THIS DEBUGGING HACK */ 1167*36381Ssklower ASSERT(0); 1168*36381Ssklower printf("BAD e_pcb from HL (0x%x,0x%x)\n", copcb, copcb->co_myself); 1169*36381Ssklower mm = dtom( copcb ); 1170*36381Ssklower if(mm->m_type == MT_FREE) 1171*36381Ssklower printf("FREED MBUF!\n"); 1172*36381Ssklower return ENETDOWN; 1173*36381Ssklower } 1174*36381Ssklower ASSERT( copcb->co_channel != 0); 1175*36381Ssklower ASSERT( copcb->co_channel != X_NOCHANNEL); 1176*36381Ssklower ecnrq->e_vc = (copcb->co_channel & 0xff); 1177*36381Ssklower ecnrq->e_cmd = ECN_SEND; 1178*36381Ssklower e_data(ecnrq) = m0; 1179*36381Ssklower { 1180*36381Ssklower /* TODO: REMOVE THIS DEBUGGING HACK */ 1181*36381Ssklower struct mbuf *thedata = e_data(ecnrq); 1182*36381Ssklower u_int *firstint = mtod( thedata, u_int *); 1183*36381Ssklower 1184*36381Ssklower if( (*firstint & 0xff000000) != 0x81000000 ) { 1185*36381Ssklower /* not clnp */ 1186*36381Ssklower switch( ((*firstint) & 0x00ff0000) >> 20 ) { 1187*36381Ssklower case 0x1: 1188*36381Ssklower case 0x2: 1189*36381Ssklower case 0x3: 1190*36381Ssklower case 0x6: 1191*36381Ssklower case 0x7: 1192*36381Ssklower case 0x8: 1193*36381Ssklower case 0xc: 1194*36381Ssklower case 0xd: 1195*36381Ssklower case 0xe: 1196*36381Ssklower case 0xf: 1197*36381Ssklower break; 1198*36381Ssklower default: 1199*36381Ssklower printf(" ECN_SEND! BAD DATA\n" ); 1200*36381Ssklower dump_buf( thedata, 20 + 12 ); 1201*36381Ssklower m_freem( m0 ); 1202*36381Ssklower return ENETDOWN; 1203*36381Ssklower } 1204*36381Ssklower } 1205*36381Ssklower } 1206*36381Ssklower 1207*36381Ssklower ecnrq->e_info = 0; 1208*36381Ssklower 1209*36381Ssklower IFDEBUG(D_CDUMP_REQ) 1210*36381Ssklower printf("senddata ecnrq\n"); 1211*36381Ssklower ENDDEBUG 1212*36381Ssklower IncStat(co_send); 1213*36381Ssklower 1214*36381Ssklower ASSERT( copcb->co_state == OPEN ); 1215*36381Ssklower copcb->co_state = ACKWAIT; 1216*36381Ssklower 1217*36381Ssklower if( copcb->co_myself != copcb ) { 1218*36381Ssklower struct mbuf *mm; 1219*36381Ssklower /* TODO: REMOVE this and all mention of co_myself */ 1220*36381Ssklower ASSERT(0); 1221*36381Ssklower printf("BAD e_pcb TO THE BOARD ecn (0x%x) cmd 0x%x\n", 1222*36381Ssklower ecnrq->e_pcb, ecnrq->e_cmd); 1223*36381Ssklower mm = dtom( copcb ); 1224*36381Ssklower if(mm->m_type == MT_FREE) 1225*36381Ssklower printf("FREED MBUF!\n"); 1226*36381Ssklower dump_buf (ecnrq, sizeof (*ecnrq)); 1227*36381Ssklower return ENETDOWN; 1228*36381Ssklower } 1229*36381Ssklower 1230*36381Ssklower return 1231*36381Ssklower choose_output(copcb->co_ifp, dtom(ecnrq), copcb->co_flags&CONSF_LOOPBACK); 1232*36381Ssklower } 1233*36381Ssklower 1234*36381Ssklower /* 1235*36381Ssklower * NAME: cons_send_on_vc() 1236*36381Ssklower * CALLED FROM: 1237*36381Ssklower * tp_error_emit() 1238*36381Ssklower * FUNCTION and ARGUMENTS: 1239*36381Ssklower * Take a packet(m0), of length (datalen) from tp and 1240*36381Ssklower * send it on the channel (chan). 1241*36381Ssklower * 1242*36381Ssklower * RETURN VALUE: 1243*36381Ssklower * whatever (E*) is returned form the net layer output routine. 1244*36381Ssklower */ 1245*36381Ssklower int 1246*36381Ssklower cons_send_on_vc(chan, m, datalen) 1247*36381Ssklower int chan; 1248*36381Ssklower struct mbuf *m; 1249*36381Ssklower int datalen; 1250*36381Ssklower { 1251*36381Ssklower struct cons_pcb *copcb = (struct cons_pcb *)0; 1252*36381Ssklower 1253*36381Ssklower if(m == MNULL) 1254*36381Ssklower return; 1255*36381Ssklower 1256*36381Ssklower if((copcb = 1257*36381Ssklower #ifdef ARGO_DEBUG 1258*36381Ssklower cons_chan_to_pcb( chan, __LINE__ ) 1259*36381Ssklower #else ARGO_DEBUG 1260*36381Ssklower cons_chan_to_pcb( chan ) 1261*36381Ssklower #endif ARGO_DEBUG 1262*36381Ssklower ) == (struct cons_pcb *)0 ) 1263*36381Ssklower return E_CO_CHAN; 1264*36381Ssklower IFDEBUG(D_CCONS) 1265*36381Ssklower printf("cons_send_on_vc m 0x%x m_len 0x%x\n", m, m->m_len); 1266*36381Ssklower ENDDEBUG 1267*36381Ssklower return cons_senddata( copcb, m); 1268*36381Ssklower } 1269*36381Ssklower 1270*36381Ssklower /* 1271*36381Ssklower * NAME: cons_output() 1272*36381Ssklower * CALLED FROM: 1273*36381Ssklower * tpiso_output(), can have whatever interface we want it to... 1274*36381Ssklower * tpiso_output() decides whether to give a packet to CLNP or to 1275*36381Ssklower * cons; if the latter, it calls this routine. 1276*36381Ssklower * FUNCTION and ARGUMENTS: 1277*36381Ssklower * tp has alloc-ed a pcb - but it may not be open. 1278*36381Ssklower * some classes of tp may allow multiplexing, in which 1279*36381Ssklower * case, you may choose to send the data on ANOTHER cons connection. 1280*36381Ssklower * This decides which net connection to use, opens one if necessary. 1281*36381Ssklower * Then it sends the data. 1282*36381Ssklower */ 1283*36381Ssklower 1284*36381Ssklower cons_output(isop, m, len, isdgm) 1285*36381Ssklower struct isopcb *isop; 1286*36381Ssklower struct mbuf *m; 1287*36381Ssklower int len; 1288*36381Ssklower int isdgm; 1289*36381Ssklower { 1290*36381Ssklower struct cons_pcb *copcb = (struct cons_pcb *)0; 1291*36381Ssklower int error; 1292*36381Ssklower int s = splnet(); 1293*36381Ssklower 1294*36381Ssklower IFDEBUG(D_CCONS) 1295*36381Ssklower printf("cons_output( isop 0x%x, m 0x%x, len 0x%x, dgm 0x%x )\n", 1296*36381Ssklower isop,m,len, isdgm); 1297*36381Ssklower ENDDEBUG 1298*36381Ssklower 1299*36381Ssklower if( m == MNULL ) 1300*36381Ssklower return 0; 1301*36381Ssklower ASSERT(m->m_len > 0); 1302*36381Ssklower if( isdgm ) { 1303*36381Ssklower error = cosns_output1(0, m, &isop->isop_faddr, TP_proto, isop); 1304*36381Ssklower IFDEBUG(D_CDATA) 1305*36381Ssklower if(error) 1306*36381Ssklower printf("cosns_output1 RETURNS ERROR 0x%x\n", error); 1307*36381Ssklower ENDDEBUG 1308*36381Ssklower return error; 1309*36381Ssklower } 1310*36381Ssklower 1311*36381Ssklower if( isop->isop_chanmask || isop->isop_negchanmask) { 1312*36381Ssklower register int mask = isop->isop_chanmask; 1313*36381Ssklower register int chan = 1; 1314*36381Ssklower 1315*36381Ssklower if( mask == 0) 1316*36381Ssklower mask = isop->isop_negchanmask; 1317*36381Ssklower 1318*36381Ssklower for ( chan=1; (mask & 1)==0; chan++,mask>>=1 ) ; 1319*36381Ssklower 1320*36381Ssklower if( isop->isop_chanmask == 0 ) 1321*36381Ssklower chan = -chan; 1322*36381Ssklower 1323*36381Ssklower IFDEBUG(D_CCONS) 1324*36381Ssklower printf( 1325*36381Ssklower "cons_output: isop 0x%x cmask 0x%x negmask 0x%x, chan 0x%x\n", 1326*36381Ssklower isop, isop->isop_chanmask, isop->isop_negchanmask, chan); 1327*36381Ssklower ENDDEBUG 1328*36381Ssklower ASSERT( chan != 0); 1329*36381Ssklower #ifdef ARGO_DEBUG 1330*36381Ssklower copcb = cons_chan_to_pcb( chan, __LINE__ ); 1331*36381Ssklower #else ARGO_DEBUG 1332*36381Ssklower copcb = cons_chan_to_pcb( chan ); 1333*36381Ssklower #endif ARGO_DEBUG 1334*36381Ssklower } 1335*36381Ssklower if( copcb == (struct cons_pcb *)0 ) { 1336*36381Ssklower /* get a new one */ 1337*36381Ssklower 1338*36381Ssklower if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, CONSF_OCRE, 1339*36381Ssklower TP_proto, &copcb)) != EOK ) { 1340*36381Ssklower IFDEBUG(D_CCONS) 1341*36381Ssklower printf("cosns_output: no copcb; returns 0x%x\n", error); 1342*36381Ssklower ENDDEBUG 1343*36381Ssklower (void) m_freem (m); 1344*36381Ssklower splx(s); 1345*36381Ssklower return error ; 1346*36381Ssklower } 1347*36381Ssklower 1348*36381Ssklower /* abbreviated form of iso_pcbconnect(): */ 1349*36381Ssklower bcopy((caddr_t)&isop->isop_faddr, (caddr_t)&copcb->co_faddr, 1350*36381Ssklower sizeof(struct sockaddr_iso)); 1351*36381Ssklower 1352*36381Ssklower if ( error = cons_connect( copcb ) ) { /* if it doesn't work */ 1353*36381Ssklower /* oh, dear, throw packet away */ 1354*36381Ssklower remque((struct isopcb *)copcb); 1355*36381Ssklower (void) m_free(dtom(copcb)); 1356*36381Ssklower (void) m_freem( m ); 1357*36381Ssklower splx(s); 1358*36381Ssklower return error; 1359*36381Ssklower } 1360*36381Ssklower 1361*36381Ssklower if( copcb->co_socket ) { 1362*36381Ssklower while( (copcb->co_state != OPEN) && 1363*36381Ssklower !(error = copcb->co_socket->so_error) ) { 1364*36381Ssklower IFDEBUG(D_CCONS) 1365*36381Ssklower printf( 1366*36381Ssklower "SLEEP1 copcb 0x%x isop 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n", 1367*36381Ssklower copcb, isop, copcb->co_state, copcb->co_channel, 1368*36381Ssklower ((struct isopcb *)isop)->isop_chanmask, 1369*36381Ssklower ((struct isopcb *)isop)->isop_negchanmask 1370*36381Ssklower ); 1371*36381Ssklower ENDDEBUG 1372*36381Ssklower sleep( (caddr_t)&copcb->co_state, PZERO+1 ); 1373*36381Ssklower IFDEBUG(D_CCONS) 1374*36381Ssklower printf("AFTER SLEEP 1 chan 0x%x chanmask 0x%x negchanmask 0x%x\n", 1375*36381Ssklower copcb->co_channel, isop->isop_chanmask, 1376*36381Ssklower isop->isop_negchanmask); 1377*36381Ssklower ENDDEBUG 1378*36381Ssklower } 1379*36381Ssklower if( !error ) 1380*36381Ssklower SET_CHANMASK( isop, copcb->co_channel); 1381*36381Ssklower } 1382*36381Ssklower 1383*36381Ssklower } 1384*36381Ssklower 1385*36381Ssklower IFDEBUG(D_CDATA) 1386*36381Ssklower printf("cons_output calling senddata(0x%x 0x%x)\n", copcb, m); 1387*36381Ssklower ASSERT(m != MNULL); 1388*36381Ssklower ASSERT(m->m_len != 0); 1389*36381Ssklower ENDDEBUG 1390*36381Ssklower 1391*36381Ssklower if( !error ) 1392*36381Ssklower error = cons_senddata( copcb, m); 1393*36381Ssklower splx(s); 1394*36381Ssklower return error; 1395*36381Ssklower } 1396*36381Ssklower 1397*36381Ssklower /* 1398*36381Ssklower * NAME: cons_openvc() 1399*36381Ssklower * CALLED FROM: 1400*36381Ssklower * TP when it decides to open a VC for TP 0 1401*36381Ssklower * FUNCTION: 1402*36381Ssklower * opens a connection and stashes the pcb info in the socket 1403*36381Ssklower * substitute for iso_pcbconnect/ in_pcbconnect for the class 0 case 1404*36381Ssklower * only. 1405*36381Ssklower */ 1406*36381Ssklower int 1407*36381Ssklower cons_openvc(copcb, faddr, so) 1408*36381Ssklower struct cons_pcb *copcb; 1409*36381Ssklower struct sockaddr_iso *faddr; 1410*36381Ssklower struct socket *so; 1411*36381Ssklower { 1412*36381Ssklower int error = 0; 1413*36381Ssklower int s = splnet(); 1414*36381Ssklower struct cons_pcb *cons_chan_to_pcb(); 1415*36381Ssklower 1416*36381Ssklower 1417*36381Ssklower ASSERT( copcb->co_socket == so ); 1418*36381Ssklower IFTRACE(D_CCONN) 1419*36381Ssklower tptrace(TPPTmisc, "cons_openvc( copcb so )\n", copcb, so, 0, 0); 1420*36381Ssklower ENDTRACE 1421*36381Ssklower IFDEBUG(D_CCONN) 1422*36381Ssklower printf("cons_openvc( copcb 0x%x, so 0x%x )\n", copcb,so); 1423*36381Ssklower ENDDEBUG 1424*36381Ssklower /* 1425*36381Ssklower * initialize the copcb part of the isopcb 1426*36381Ssklower */ 1427*36381Ssklower copcb->co_ttl = copcb->co_init_ttl = X25_TTL; 1428*36381Ssklower copcb->co_flags = CONSF_OCRE; 1429*36381Ssklower copcb->co_proto = TP_proto; 1430*36381Ssklower copcb->co_pending.ifq_maxlen = CONS_IFQMAXLEN; 1431*36381Ssklower 1432*36381Ssklower /* abbreviated form of iso_pcbconnect(): */ 1433*36381Ssklower bcopy((caddr_t)faddr, (caddr_t)&copcb->co_faddr, 1434*36381Ssklower sizeof(struct sockaddr_iso)); 1435*36381Ssklower 1436*36381Ssklower ASSERT( copcb->co_socket == so ); 1437*36381Ssklower if( error = cons_connect( copcb ) ) 1438*36381Ssklower goto done; 1439*36381Ssklower while( (copcb->co_state != OPEN) && !(error = so->so_error) ) { 1440*36381Ssklower IFDEBUG(D_CCONS) 1441*36381Ssklower printf( 1442*36381Ssklower "SLEEP2 copcb 0x%x state 0x%x chan 0x%x mask 0x%x neg 0x%x\n", 1443*36381Ssklower copcb, copcb->co_state, copcb->co_channel, 1444*36381Ssklower copcb->co_chanmask, 1445*36381Ssklower copcb->co_negchanmask 1446*36381Ssklower ); 1447*36381Ssklower ENDDEBUG 1448*36381Ssklower sleep( (caddr_t)&copcb->co_state, PZERO+2 ); 1449*36381Ssklower IFDEBUG(D_CCONS) 1450*36381Ssklower printf("AFTER SLEEP2 chan 0x%x chanmask 0x%x negchanmask 0x%x\n", 1451*36381Ssklower copcb->co_channel, copcb->co_chanmask, 1452*36381Ssklower copcb->co_negchanmask); 1453*36381Ssklower ENDDEBUG 1454*36381Ssklower } 1455*36381Ssklower if( !error ) 1456*36381Ssklower SET_CHANMASK( (struct isopcb *)copcb, copcb->co_channel); 1457*36381Ssklower done: 1458*36381Ssklower ASSERT( copcb->co_socket == so ); 1459*36381Ssklower splx(s); 1460*36381Ssklower 1461*36381Ssklower IFDEBUG(D_CCONN) 1462*36381Ssklower printf("cons_openvc: copcb 0x%x error 0x%x\n", copcb, error ); 1463*36381Ssklower ENDDEBUG 1464*36381Ssklower return error; 1465*36381Ssklower } 1466*36381Ssklower 1467*36381Ssklower /* 1468*36381Ssklower * NAME: cons_netcmd() 1469*36381Ssklower * CALLED FROM: 1470*36381Ssklower * tp_route_to() when it decides to accept or reject an incoming 1471*36381Ssklower * connection it calls this. 1472*36381Ssklower * FUNCTION: 1473*36381Ssklower * either closes the cons connection named by (channel) 1474*36381Ssklower * or associates the copcb with the channel #. 1475*36381Ssklower * and removes the old copcb from the tp_incoming_pending list. 1476*36381Ssklower */ 1477*36381Ssklower int 1478*36381Ssklower cons_netcmd(cmd, isop, channel, isdgm) 1479*36381Ssklower int cmd; 1480*36381Ssklower struct isopcb *isop; 1481*36381Ssklower int channel; 1482*36381Ssklower { 1483*36381Ssklower int s = splnet(); 1484*36381Ssklower int error = 0; 1485*36381Ssklower struct cons_pcb *copcb = (struct cons_pcb *)0; 1486*36381Ssklower struct cons_pcb *cons_chan_to_pcb(); 1487*36381Ssklower 1488*36381Ssklower IFTRACE(D_CCONN) 1489*36381Ssklower tptrace(TPPTmisc, "cons_netcmd( cmd isopcb channel isdgm)\n", 1490*36381Ssklower cmd,isop,channel, isdgm); 1491*36381Ssklower ENDTRACE 1492*36381Ssklower IFDEBUG(D_CCONN) 1493*36381Ssklower printf("cons_netcmd( cmd 0x%x, isop 0x%x, channel 0x%x, isdgm 0x%x)\n", 1494*36381Ssklower cmd,isop,channel, isdgm); 1495*36381Ssklower if( isop ) 1496*36381Ssklower printf("cons_netcmd: isop->socket 0x%x\n", 1497*36381Ssklower isop->isop_socket); 1498*36381Ssklower ENDDEBUG 1499*36381Ssklower ASSERT(cmd != CONN_OPEN); 1500*36381Ssklower 1501*36381Ssklower /* Can we find a cons-level pcb based on channel? */ 1502*36381Ssklower if(channel) { 1503*36381Ssklower if((copcb = 1504*36381Ssklower #ifdef ARGO_DEBUG 1505*36381Ssklower cons_chan_to_pcb( channel, __LINE__ ) 1506*36381Ssklower #else ARGO_DEBUG 1507*36381Ssklower cons_chan_to_pcb( channel) 1508*36381Ssklower #endif ARGO_DEBUG 1509*36381Ssklower ) == (struct cons_pcb *)0) { 1510*36381Ssklower error = ECONNABORTED; 1511*36381Ssklower splx(s); 1512*36381Ssklower return error; 1513*36381Ssklower } 1514*36381Ssklower if( copcb == (struct cons_pcb *) isop ) { 1515*36381Ssklower copcb = (struct cons_pcb *)0; 1516*36381Ssklower /* avoid operating on a pcb twice */ 1517*36381Ssklower } else { 1518*36381Ssklower /* if isop is null (close/refuse): 1519*36381Ssklower * this would remove from the TP list, which is NOT what we want 1520*36381Ssklower * so only remove if there is an isop (gag) 1521*36381Ssklower */ 1522*36381Ssklower if( isop ) { 1523*36381Ssklower remque((struct cons_pcb *)copcb); /* take it off pending list */ 1524*36381Ssklower } else { 1525*36381Ssklower ASSERT( (cmd == CONN_CLOSE) || (cmd == CONN_REFUSE) ); 1526*36381Ssklower } 1527*36381Ssklower } 1528*36381Ssklower } 1529*36381Ssklower /* now we have one of these cases: 1530*36381Ssklower * 1) isop is non-null and copcb is null 1531*36381Ssklower * 2) isop is non-null and copcb is non-null and they are different 1532*36381Ssklower * 3) isop is null and copcb is non-null 1533*36381Ssklower */ 1534*36381Ssklower ASSERT( (isop != (struct isopcb *)0) || (copcb != (struct cons_pcb *)0)); 1535*36381Ssklower 1536*36381Ssklower switch(cmd) { 1537*36381Ssklower 1538*36381Ssklower case CONN_CONFIRM: 1539*36381Ssklower if( isdgm ) { 1540*36381Ssklower /* we want two separate pcbs */ 1541*36381Ssklower /* if we don't have a copcb, get one */ 1542*36381Ssklower 1543*36381Ssklower if( copcb == (struct cons_pcb *)0 ) { 1544*36381Ssklower if(( error = cons_pcballoc(&dummysocket, &cons_isopcb, 1545*36381Ssklower ((struct cons_pcb *)isop)->co_flags, 1546*36381Ssklower TP_proto, &copcb)) != EOK ) 1547*36381Ssklower return error; 1548*36381Ssklower /* copy missing info from isop */ 1549*36381Ssklower copcb->co_laddr = isop->isop_laddr; 1550*36381Ssklower copcb->co_faddr = isop->isop_faddr; 1551*36381Ssklower /* don't care about tsuffices */ 1552*36381Ssklower ((struct cons_pcb *)isop)->co_channel = 0; 1553*36381Ssklower /* no longer used */ 1554*36381Ssklower 1555*36381Ssklower copcb->co_ifp = ((struct cons_pcb *)isop)->co_ifp ; 1556*36381Ssklower ASSERT( copcb->co_pending.ifq_len == 0 ); 1557*36381Ssklower 1558*36381Ssklower } else { 1559*36381Ssklower insque((struct isopcb *)copcb, 1560*36381Ssklower (struct isopcb *)&cons_isopcb); 1561*36381Ssklower } 1562*36381Ssklower copcb->co_state = OPEN; 1563*36381Ssklower copcb->co_flags |= CONSF_DGM; 1564*36381Ssklower copcb->co_channel = channel; 1565*36381Ssklower ASSERT(copcb->co_channel != 0); 1566*36381Ssklower 1567*36381Ssklower IFDEBUG(D_CCONN) 1568*36381Ssklower printf("cons_netcmd: put 0x%x on regular list \n", copcb); 1569*36381Ssklower ENDDEBUG 1570*36381Ssklower } else { 1571*36381Ssklower /* must be TP 0, since this is never called from XTS code */ 1572*36381Ssklower /* we want ONE pcb, namely isop. 1573*36381Ssklower * If this TPE were the active side, 1574*36381Ssklower * there ought not to be a copcb, since TP should 1575*36381Ssklower * know that you can't send a CR with dgm and negot down 1576*36381Ssklower * to non-dgm. 1577*36381Ssklower * If this TPE were the passive side, we want to copy from 1578*36381Ssklower * the copcb that was on the pending list, and delete the 1579*36381Ssklower * pending copcb. 1580*36381Ssklower */ 1581*36381Ssklower if( copcb ) { 1582*36381Ssklower IFDEBUG(D_CCONN) 1583*36381Ssklower printf("cons_netcmd: copied info from 0x%x to 0x%x\n", 1584*36381Ssklower copcb, isop); 1585*36381Ssklower ENDDEBUG 1586*36381Ssklower isop->isop_laddr = copcb->co_laddr; 1587*36381Ssklower isop->isop_faddr = copcb->co_faddr; 1588*36381Ssklower /* tsuffices, socket should be there already */ 1589*36381Ssklower ((struct cons_pcb *)isop)->co_flags = 1590*36381Ssklower copcb->co_flags & ~CONSF_DGM; 1591*36381Ssklower ((struct cons_pcb *)isop)->co_init_ttl = copcb->co_init_ttl; 1592*36381Ssklower touch(((struct cons_pcb *)isop)); 1593*36381Ssklower ((struct cons_pcb *)isop)->co_channel = channel; 1594*36381Ssklower ((struct cons_pcb *)isop)->co_ifp = copcb->co_ifp; 1595*36381Ssklower ((struct cons_pcb *)isop)->co_proto = copcb->co_proto; 1596*36381Ssklower ((struct cons_pcb *)isop)->co_myself = 1597*36381Ssklower (struct cons_pcb *)isop; 1598*36381Ssklower SET_CHANMASK( isop, ((struct cons_pcb *)isop)->co_channel ); 1599*36381Ssklower ASSERT( copcb->co_pending.ifq_len == 0 ); 1600*36381Ssklower 1601*36381Ssklower /* get rid of the copcb that was on the pending list */ 1602*36381Ssklower (void) m_free(dtom(copcb)); 1603*36381Ssklower } 1604*36381Ssklower ((struct cons_pcb *)isop)->co_state = OPEN; 1605*36381Ssklower } 1606*36381Ssklower break; 1607*36381Ssklower 1608*36381Ssklower case CONN_CLOSE: 1609*36381Ssklower case CONN_REFUSE: 1610*36381Ssklower /* if dgm then ignore; the connections will 1611*36381Ssklower * be re-used or will time out 1612*36381Ssklower */ 1613*36381Ssklower if( isdgm ) 1614*36381Ssklower break; 1615*36381Ssklower 1616*36381Ssklower /* we should never come in here with both isop and copcb 1617*36381Ssklower * unless is dgm, hence the following assertion: 1618*36381Ssklower */ 1619*36381Ssklower ASSERT( (copcb == (struct cons_pcb *)0) || 1620*36381Ssklower (isop == (struct isopcb *)0) ); 1621*36381Ssklower 1622*36381Ssklower /* close whichever pcb we have */ 1623*36381Ssklower if( copcb ) 1624*36381Ssklower error = cons_clear(copcb, (cmd == CONN_CLOSE)? 1625*36381Ssklower E_CO_HLI_DISCN:E_CO_HLI_REJT); 1626*36381Ssklower if( isop ) 1627*36381Ssklower error = cons_clear((struct cons_pcb *)isop, (cmd == CONN_CLOSE)? 1628*36381Ssklower E_CO_HLI_DISCN:E_CO_HLI_REJT); 1629*36381Ssklower 1630*36381Ssklower if(copcb && (copcb->co_socket == (struct socket *)0) ) { 1631*36381Ssklower ASSERT( copcb->co_flags & (CONSF_DGM | CONSF_ICRE) ); 1632*36381Ssklower (void) m_free(dtom(copcb)); /* detached */ 1633*36381Ssklower } 1634*36381Ssklower /* isop will always be detached by the higher layer */ 1635*36381Ssklower break; 1636*36381Ssklower default: 1637*36381Ssklower error = EOPNOTSUPP; 1638*36381Ssklower break; 1639*36381Ssklower } 1640*36381Ssklower splx(s); 1641*36381Ssklower 1642*36381Ssklower IFDEBUG(D_CCONN) 1643*36381Ssklower printf("cons_netcmd returns 0x%x: isop 0x%x\n", isop, error ); 1644*36381Ssklower ENDDEBUG 1645*36381Ssklower return error; 1646*36381Ssklower } 1647*36381Ssklower 1648*36381Ssklower 1649*36381Ssklower /* 1650*36381Ssklower * NAME: addr_proto_consistency_check() 1651*36381Ssklower * CALLED FROM: cons_incoming() 1652*36381Ssklower * FUNCTION and ARGUMENTS: 1653*36381Ssklower * Enforces a set of rules regarding what addresses will serve 1654*36381Ssklower * what protocol stack. This is a kludge forced upon us by the 1655*36381Ssklower * fact that there's no way to tell which NET layer you want to 1656*36381Ssklower * run when opening a socket. Besides, no doubt, OSI directory 1657*36381Ssklower * services won't advertise any kind of a protocol stack with the 1658*36381Ssklower * NSAPs. sigh. 1659*36381Ssklower * RETURNS 1660*36381Ssklower * EAFNOSUPPORT or EOK. 1661*36381Ssklower */ 1662*36381Ssklower Static int 1663*36381Ssklower addr_proto_consistency_check(proto, addr) 1664*36381Ssklower int proto; 1665*36381Ssklower struct sockaddr_iso *addr; 1666*36381Ssklower { 1667*36381Ssklower switch( proto ) { 1668*36381Ssklower case ISOPROTO_CLNP: 1669*36381Ssklower break; 1670*36381Ssklower 1671*36381Ssklower case ISOPROTO_INACT_NL: 1672*36381Ssklower case ISOPROTO_CLTP: 1673*36381Ssklower return E_CO_HLI_PROTOID; 1674*36381Ssklower 1675*36381Ssklower case ISOPROTO_TP: 1676*36381Ssklower case ISOPROTO_X25: 1677*36381Ssklower /* hl is TP or X.25 */ 1678*36381Ssklower if (addr->siso_addr.isoa_afi != AFI_37) 1679*36381Ssklower return E_CO_AIWP; 1680*36381Ssklower /* kludge - necessary because this is the only type of 1681*36381Ssklower * NSAP we build for an incoming NC 1682*36381Ssklower */ 1683*36381Ssklower break; 1684*36381Ssklower default: /* unsupported */ 1685*36381Ssklower return E_CO_HLI_PROTOID; 1686*36381Ssklower } 1687*36381Ssklower return EOK; 1688*36381Ssklower } 1689*36381Ssklower /* 1690*36381Ssklower * NAME: cons_incoming() 1691*36381Ssklower * CALLED FROM: 1692*36381Ssklower * consintr() for incoming OPEN 1693*36381Ssklower * FUNCTION and ARGUMENTS: 1694*36381Ssklower * Determines which higher layer gets this call, and 1695*36381Ssklower * thus whether to immediately accept, reject, or to let the 1696*36381Ssklower * higher layer determine this question. 1697*36381Ssklower */ 1698*36381Ssklower Static 1699*36381Ssklower cons_incoming(ifp, ecnrq) 1700*36381Ssklower struct ifnet *ifp; 1701*36381Ssklower register struct eicon_request *ecnrq; 1702*36381Ssklower { 1703*36381Ssklower struct sockaddr_iso me; 1704*36381Ssklower struct sockaddr_iso peer; 1705*36381Ssklower struct cons_pcb *copcb; 1706*36381Ssklower int loop = 0; 1707*36381Ssklower int proto =0; 1708*36381Ssklower int error = 0; 1709*36381Ssklower struct dte_addr peer_dte; 1710*36381Ssklower 1711*36381Ssklower IFDEBUG(D_INCOMING) 1712*36381Ssklower printf("consincoming enter: ifp 0x%x ecnrq 0x%x\n", ifp, ecnrq); 1713*36381Ssklower ENDDEBUG 1714*36381Ssklower bzero( &me, sizeof(me)); 1715*36381Ssklower error = parse_facil( mtod(e_data(ecnrq), caddr_t), 1716*36381Ssklower (e_data(ecnrq))->m_len, &me, &peer, &proto, 1717*36381Ssklower &peer_dte); 1718*36381Ssklower loop = is_me( &peer ); /* <-- THIS may be a problem : 1719*36381Ssklower * peer may be nonsense. 1720*36381Ssklower * We can only expect that WE will do it right 1721*36381Ssklower * and never will we get an error return from 1722*36381Ssklower * parse_facil on a facil that WE generated, 1723*36381Ssklower * so if garbage comes in, peer will be garbage, 1724*36381Ssklower * and loop will be false. 1725*36381Ssklower */ 1726*36381Ssklower if( error != EOK ) { 1727*36381Ssklower (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop); 1728*36381Ssklower IncStat(co_parse_facil_err); 1729*36381Ssklower IncStat(co_Rdrops); 1730*36381Ssklower return; 1731*36381Ssklower } 1732*36381Ssklower 1733*36381Ssklower if( (error = addr_proto_consistency_check(proto, &me)) != EOK ) { 1734*36381Ssklower /* problem with consistency */ 1735*36381Ssklower (void) issue_clear_req(ecnrq->e_vc, error, ifp, loop); 1736*36381Ssklower IncStat(co_addr_proto_consist_err); 1737*36381Ssklower IncStat(co_Rdrops); 1738*36381Ssklower return; 1739*36381Ssklower } else { 1740*36381Ssklower switch( proto ) { 1741*36381Ssklower case ISOPROTO_X25: 1742*36381Ssklower copcb = (struct cons_pcb *) 1743*36381Ssklower ((struct cons_pcb *)(&cons_isopcb))->co_next; 1744*36381Ssklower 1745*36381Ssklower while (copcb != (struct cons_pcb *)&cons_isopcb) { 1746*36381Ssklower if( copcb->co_lport == me.siso_tsuffix ) { 1747*36381Ssklower /* for cons "transport service", 1748*36381Ssklower * multiplexing is not allowed 1749*36381Ssklower */ 1750*36381Ssklower if( !copcb->co_socket ) { 1751*36381Ssklower printf( 1752*36381Ssklower "PANIC cons_incoming NOT TP but no sock\n"); 1753*36381Ssklower copcb = (struct cons_pcb *)0; 1754*36381Ssklower break; 1755*36381Ssklower } 1756*36381Ssklower if( copcb->co_socket->so_options & SO_ACCEPTCONN ) { 1757*36381Ssklower struct cons_pcb *newx; 1758*36381Ssklower 1759*36381Ssklower newx = (struct cons_pcb *) 1760*36381Ssklower sonewconn(copcb->co_socket)->so_pcb; 1761*36381Ssklower newx->co_laddr = copcb->co_laddr; 1762*36381Ssklower newx->co_peer_dte = peer_dte; 1763*36381Ssklower newx->co_proto = copcb->co_proto; 1764*36381Ssklower newx->co_myself = newx; 1765*36381Ssklower touch(copcb); 1766*36381Ssklower copcb = newx; 1767*36381Ssklower soisconnected(copcb->co_socket); 1768*36381Ssklower break; 1769*36381Ssklower } /* else keep looking */ 1770*36381Ssklower } 1771*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 1772*36381Ssklower } 1773*36381Ssklower if (copcb == (struct cons_pcb *)&cons_isopcb) 1774*36381Ssklower copcb = (struct cons_pcb *) 0; 1775*36381Ssklower break; 1776*36381Ssklower 1777*36381Ssklower case ISOPROTO_TP: 1778*36381Ssklower ASSERT( me.siso_tsuffix == 0 ); 1779*36381Ssklower /* 1780*36381Ssklower * We treat this rather like we do for CLNP. 1781*36381Ssklower * TP can't tell which socket 1782*36381Ssklower * wants this until the TP header comes in, so there's no way 1783*36381Ssklower * to associate this channel with a tpcb/isopcb. 1784*36381Ssklower * We assume data will arrive (a CR TPDU) and be given to TP along with 1785*36381Ssklower * the channel number. We can then expect TP to call us with 1786*36381Ssklower * the channel number and pcb ptr, telling us to keep this connection 1787*36381Ssklower * or clear it. 1788*36381Ssklower * Now, tp will have created an isopcb in the tp_isopcb list. 1789*36381Ssklower * We will have to keep another copcb though, because there is no 1790*36381Ssklower * 1-1 correspondence between socket and copcb when multiplexing 1791*36381Ssklower * is allowed. 1792*36381Ssklower * But we want to save the peer address, ifp, and state, proto. 1793*36381Ssklower * If the channel should clear before TP responds, we need 1794*36381Ssklower * to know that also, so we create a tp-pending list... 1795*36381Ssklower */ 1796*36381Ssklower if( cons_pcballoc(&dummysocket, &tp_incoming_pending, 1797*36381Ssklower CONSF_ICRE, TP_proto, &copcb) != EOK ) { 1798*36381Ssklower copcb = (struct cons_pcb *)0; 1799*36381Ssklower } else { 1800*36381Ssklower copcb->co_peer_dte = peer_dte; 1801*36381Ssklower } 1802*36381Ssklower break; 1803*36381Ssklower 1804*36381Ssklower 1805*36381Ssklower case ISOPROTO_CLNP: 1806*36381Ssklower if( cons_pcballoc(&dummysocket, &cons_isopcb, 1807*36381Ssklower CONSF_ICRE | CONSF_DGM, CLNP_proto, &copcb ) != EOK ) { 1808*36381Ssklower /* choke */ 1809*36381Ssklower copcb = (struct cons_pcb *)0; 1810*36381Ssklower } else { 1811*36381Ssklower copcb->co_peer_dte = peer_dte; 1812*36381Ssklower } 1813*36381Ssklower break; 1814*36381Ssklower 1815*36381Ssklower default: 1816*36381Ssklower panic("cons_incoming"); 1817*36381Ssklower } /* end switch */ 1818*36381Ssklower 1819*36381Ssklower if(copcb) { 1820*36381Ssklower touch(copcb); 1821*36381Ssklower copcb->co_channel = (int)ecnrq->e_vc; 1822*36381Ssklower ASSERT( copcb->co_channel != 0); 1823*36381Ssklower copcb->co_state = OPEN; 1824*36381Ssklower copcb->co_ifp = ifp; 1825*36381Ssklower copcb->co_laddr = me; 1826*36381Ssklower copcb->co_faddr = peer; 1827*36381Ssklower if(loop) 1828*36381Ssklower copcb->co_flags |= CONSF_LOOPBACK; 1829*36381Ssklower IFDEBUG(D_CADDR) 1830*36381Ssklower printf("cons_incoming found XPCB 0x%x, loop 0x%x\n", 1831*36381Ssklower copcb, loop); 1832*36381Ssklower printf("\nco_laddr: "); 1833*36381Ssklower dump_buf(&copcb->co_laddr, sizeof(copcb->co_laddr)); 1834*36381Ssklower printf("\nco_faddr: "); 1835*36381Ssklower dump_buf(&copcb->co_faddr, sizeof(copcb->co_faddr)); 1836*36381Ssklower printf("\n"); 1837*36381Ssklower ENDDEBUG 1838*36381Ssklower } else { 1839*36381Ssklower ifp->if_ierrors ++; 1840*36381Ssklower (void) issue_clear_req(ecnrq->e_vc, E_CO_OSI_UNSAP, ifp, loop); 1841*36381Ssklower IncStat(co_no_copcb); 1842*36381Ssklower IncStat(co_Rdrops); 1843*36381Ssklower } 1844*36381Ssklower } 1845*36381Ssklower /* caller frees the mbuf so we don't have to do any such thing */ 1846*36381Ssklower } 1847*36381Ssklower 1848*36381Ssklower /* 1849*36381Ssklower **************************** DEVICE cons *************************** 1850*36381Ssklower */ 1851*36381Ssklower 1852*36381Ssklower /* 1853*36381Ssklower * NAME: cosns_output() 1854*36381Ssklower * CALLED FROM: 1855*36381Ssklower * clnp - this routine is given as the device-output routine 1856*36381Ssklower * for the adcom driver. 1857*36381Ssklower * FUNCTION and ARGUMENTS: 1858*36381Ssklower * (ifp) is the cons/adcom, found by routing function. 1859*36381Ssklower * (m0) is the clnp datagram. 1860*36381Ssklower * (dst) is the destination address 1861*36381Ssklower * This routine finds an x.25 connection for datagram use and 1862*36381Ssklower * sends the packet. 1863*36381Ssklower */ 1864*36381Ssklower int 1865*36381Ssklower cosns_output(ifp, m0, dst) 1866*36381Ssklower { 1867*36381Ssklower return cosns_output1(ifp, m0, dst, CLNP_proto, NULL); 1868*36381Ssklower } 1869*36381Ssklower 1870*36381Ssklower /* DEBUGGING ONLY? */ 1871*36381Ssklower int total_cosns_len = 0; 1872*36381Ssklower int total_cosns_cnt = 0; 1873*36381Ssklower int total_pkts_to_clnp = 0; 1874*36381Ssklower 1875*36381Ssklower /* 1876*36381Ssklower * The isop is passed here so that if we have set x25crud in the 1877*36381Ssklower * pcb, it can be passed down to cons_connect. It could be null 1878*36381Ssklower * however, in the case of tp4/x25/clnp 1879*36381Ssklower */ 1880*36381Ssklower Static int 1881*36381Ssklower cosns_output1(ifp, m0, dst, proto, isop) 1882*36381Ssklower struct ifnet *ifp; 1883*36381Ssklower register struct mbuf *m0; 1884*36381Ssklower struct sockaddr_iso *dst; 1885*36381Ssklower struct protosw *proto; 1886*36381Ssklower struct isopcb *isop; /* NULL if coming from clnp */ 1887*36381Ssklower { 1888*36381Ssklower register struct cons_pcb *copcb; 1889*36381Ssklower int s = splnet(); 1890*36381Ssklower int error = 0; 1891*36381Ssklower 1892*36381Ssklower { register struct mbuf *n=m0; 1893*36381Ssklower register int len = 0; 1894*36381Ssklower 1895*36381Ssklower for(;;) { 1896*36381Ssklower len += n->m_len; 1897*36381Ssklower if (n->m_next == MNULL ) { 1898*36381Ssklower break; 1899*36381Ssklower } 1900*36381Ssklower n = n->m_next; 1901*36381Ssklower } 1902*36381Ssklower total_cosns_len += len; 1903*36381Ssklower total_cosns_cnt ++; 1904*36381Ssklower 1905*36381Ssklower } 1906*36381Ssklower 1907*36381Ssklower IFDEBUG(D_CCONS) 1908*36381Ssklower printf("cosns_output1( ifp 0x%x, m 0x%x, dst 0x%x )\n", ifp, m0, dst ); 1909*36381Ssklower ENDDEBUG 1910*36381Ssklower if ( ! (copcb = cons_find( CONSF_DGM, dst, proto, 0, 0) )) { 1911*36381Ssklower struct cons_pcb *newcopcb; /* so we can pass addr of this to pcballoc */ 1912*36381Ssklower 1913*36381Ssklower if( (error = cons_pcballoc(&dummysocket, &cons_isopcb, 1914*36381Ssklower CONSF_DGM | CONSF_OCRE, proto, &newcopcb) ) != EOK ) { 1915*36381Ssklower IFDEBUG(D_CCONS) 1916*36381Ssklower printf("cosns_output: no copcb; returns \n"); 1917*36381Ssklower ENDDEBUG 1918*36381Ssklower (void) m_freem(m0); 1919*36381Ssklower goto done; 1920*36381Ssklower } 1921*36381Ssklower copcb = newcopcb; 1922*36381Ssklower 1923*36381Ssklower /* abbreviated form of iso_pcbconnect(): */ 1924*36381Ssklower bcopy((caddr_t)dst, (caddr_t)&copcb->co_faddr, 1925*36381Ssklower sizeof(struct sockaddr_iso)); 1926*36381Ssklower 1927*36381Ssklower /* copy x25crud into copcb if necessary */ 1928*36381Ssklower if ((isop != NULL) && (isop->isop_x25crud_len > 0)) { 1929*36381Ssklower bcopy(isop->isop_x25crud, copcb->co_x25crud, 1930*36381Ssklower isop->isop_x25crud_len); 1931*36381Ssklower copcb->co_x25crud_len = isop->isop_x25crud_len; 1932*36381Ssklower } 1933*36381Ssklower 1934*36381Ssklower copcb->co_ifp = ifp; /* NULL IF COMING FROM TP4! */ 1935*36381Ssklower 1936*36381Ssklower if ( error = cons_connect( copcb ) ) { /* if it doesn't work */ 1937*36381Ssklower /* oh, dear, throw packet away */ 1938*36381Ssklower remque((struct isopcb *)copcb); 1939*36381Ssklower (void) m_free(dtom(copcb)); 1940*36381Ssklower (void) m_freem(m0); 1941*36381Ssklower goto done; 1942*36381Ssklower } 1943*36381Ssklower } 1944*36381Ssklower IFDEBUG(D_CDATA) 1945*36381Ssklower printf("cosns_output1 @ senddata: state 0x%x flags 0x%x channel 0x%x\n", 1946*36381Ssklower copcb->co_state, copcb->co_flags, copcb->co_channel); 1947*36381Ssklower ENDDEBUG 1948*36381Ssklower ASSERT(copcb->co_channel != X_NOCHANNEL); 1949*36381Ssklower error = cons_senddata(copcb, m0); 1950*36381Ssklower done: 1951*36381Ssklower splx(s); 1952*36381Ssklower return error; 1953*36381Ssklower } 1954*36381Ssklower 1955*36381Ssklower 1956*36381Ssklower /* 1957*36381Ssklower **************************** TRANSPORT cons *************************** 1958*36381Ssklower */ 1959*36381Ssklower 1960*36381Ssklower 1961*36381Ssklower /* 1962*36381Ssklower * NAME: cons_detach() 1963*36381Ssklower * CALLED FROM: 1964*36381Ssklower * cons_usrreq() on PRU_DETACH 1965*36381Ssklower * cons_netcmd() when TP releases a net connection 1966*36381Ssklower * cons_slowtimo() when timeout releases a net connection 1967*36381Ssklower * FUNCTION and ARGUMENT: 1968*36381Ssklower * removes the copcb from the list of copcbs in use, and frees the mbufs. 1969*36381Ssklower * detaches the pcb from the socket, where a socket exists. 1970*36381Ssklower * RETURN VALUE: 1971*36381Ssklower * ENOTCONN if it couldn't find the copcb in the list of connections. 1972*36381Ssklower */ 1973*36381Ssklower 1974*36381Ssklower Static int 1975*36381Ssklower cons_detach( copcb ) 1976*36381Ssklower register struct cons_pcb *copcb; 1977*36381Ssklower { 1978*36381Ssklower struct socket *so = copcb->co_socket; 1979*36381Ssklower 1980*36381Ssklower IFDEBUG(D_CCONN) 1981*36381Ssklower printf("cons_detach( copcb 0x%x )\n", copcb); 1982*36381Ssklower ENDDEBUG 1983*36381Ssklower if(so) { 1984*36381Ssklower if (so->so_head) { 1985*36381Ssklower if (!soqremque(so, 0) && !soqremque(so, 1)) 1986*36381Ssklower panic("sofree dq"); 1987*36381Ssklower so->so_head = 0; 1988*36381Ssklower } 1989*36381Ssklower ((struct isopcb *)copcb)->isop_options = 0; /* kludge */ 1990*36381Ssklower iso_pcbdetach(copcb); /* detaches from so */ 1991*36381Ssklower } else { 1992*36381Ssklower remque((struct isopcb *)copcb); 1993*36381Ssklower (void) m_free(dtom(copcb)); 1994*36381Ssklower } 1995*36381Ssklower } 1996*36381Ssklower 1997*36381Ssklower Static int 1998*36381Ssklower cons_clear_and_detach(copcb, clearreason, ctlcmd) 1999*36381Ssklower register struct cons_pcb *copcb; 2000*36381Ssklower int clearreason; 2001*36381Ssklower int ctlcmd; 2002*36381Ssklower { 2003*36381Ssklower IFDEBUG(D_CCONN) 2004*36381Ssklower printf("Clear and Detach (0x%x, 0x%x, 0x%x)\n", 2005*36381Ssklower copcb, clearreason, ctlcmd); 2006*36381Ssklower ENDDEBUG 2007*36381Ssklower if( clearreason != DONTCLEAR ) { 2008*36381Ssklower (void) cons_clear( copcb , clearreason ); 2009*36381Ssklower } 2010*36381Ssklower if( copcb->co_proto && copcb->co_proto->pr_ctlinput ) 2011*36381Ssklower (*copcb->co_proto->pr_ctlinput)(ctlcmd, 2012*36381Ssklower (struct sockaddr_iso *)&copcb->co_faddr, (caddr_t)copcb); 2013*36381Ssklower 2014*36381Ssklower if( copcb->co_socket == (struct socket *)0 ) { 2015*36381Ssklower /* tp4, clnp users only */ 2016*36381Ssklower (void) cons_detach( copcb ); 2017*36381Ssklower } /* else detach will be called by the socket's closing */ 2018*36381Ssklower else { 2019*36381Ssklower ASSERT( copcb->co_socket != &dummysocket ); 2020*36381Ssklower ASSERT( (copcb->co_flags & CONSF_DGM) == 0 ); 2021*36381Ssklower } 2022*36381Ssklower IFDEBUG(D_CCONN) 2023*36381Ssklower printf("END OF Clear and Detach (0x%x, 0x%x, 0x%x)\n", 2024*36381Ssklower copcb, clearreason, ctlcmd); 2025*36381Ssklower ENDDEBUG 2026*36381Ssklower } 2027*36381Ssklower 2028*36381Ssklower Static int 2029*36381Ssklower cons_pcbbind( copcb, nam ) 2030*36381Ssklower register struct cons_pcb *copcb; 2031*36381Ssklower struct mbuf *nam; 2032*36381Ssklower { 2033*36381Ssklower int error; 2034*36381Ssklower 2035*36381Ssklower if( error = iso_pcbbind( copcb, nam) ) 2036*36381Ssklower return error; 2037*36381Ssklower 2038*36381Ssklower /* iso_pcbbind already ensured that if port < 1024 it's superuser */ 2039*36381Ssklower /* Now we check: must be in range 0 .. 23 or in range 1024 .. 99 */ 2040*36381Ssklower 2041*36381Ssklower if( (copcb->co_lport < X25_PORT_RESERVED) || 2042*36381Ssklower ((copcb->co_lport >= ISO_PORT_RESERVED) && 2043*36381Ssklower (copcb->co_lport <= X25_PORT_USERMAX))) { 2044*36381Ssklower munge( copcb->co_lport, (&copcb->co_laddr)->siso_addr.t37_idi + 2045*36381Ssklower ADDR37_IDI_LEN, 1 /* nibble */); 2046*36381Ssklower munge( copcb->co_fport, (&copcb->co_faddr)->siso_addr.t37_idi + 2047*36381Ssklower ADDR37_IDI_LEN, 1 /* nibble */); 2048*36381Ssklower return 0; 2049*36381Ssklower } else 2050*36381Ssklower return EADDRNOTAVAIL; 2051*36381Ssklower } 2052*36381Ssklower /* 2053*36381Ssklower * NAME: cons_usrreq() 2054*36381Ssklower * CALLED FROM: 2055*36381Ssklower * user level via proto switch 2056*36381Ssklower * FUNCTION and ARGUMENTS: 2057*36381Ssklower * so : socket 2058*36381Ssklower * req: which PRU* request 2059*36381Ssklower * m : data or mbuf ptr into which to stash data 2060*36381Ssklower * nam: mbuf ptr which is really a sockaddr_iso 2061*36381Ssklower * ifq: in PRU_CONTROL case, an ifnet structure 2062*36381Ssklower * RETURN VALUE: 2063*36381Ssklower * ENOTCONN if trying to do something which requires a connection 2064*36381Ssklower * and it's not yet connected 2065*36381Ssklower * EISCONN if trying to do something which cannot be done to a connection 2066*36381Ssklower * but it's connected 2067*36381Ssklower * ENOBUFS if ran out of mbufs 2068*36381Ssklower * EWOULDBLOCK if in nonblocking mode & can't send right away 2069*36381Ssklower * EOPNOSUPP if req isn't supported 2070*36381Ssklower * E* other passed up from lower layers or from other routines 2071*36381Ssklower */ 2072*36381Ssklower 2073*36381Ssklower cons_usrreq(so, req, m, nam, ifp) 2074*36381Ssklower struct socket *so; 2075*36381Ssklower u_int req; 2076*36381Ssklower struct mbuf *m, *nam; 2077*36381Ssklower int *ifp; 2078*36381Ssklower { 2079*36381Ssklower struct cons_pcb *copcb = (struct cons_pcb *)so->so_pcb; 2080*36381Ssklower int s = splnet(); 2081*36381Ssklower int error = 0; 2082*36381Ssklower 2083*36381Ssklower IFDEBUG(D_CCONS) 2084*36381Ssklower printf("cons_usrreq 0x%x so 0x%x copcb 0x%x\n", req, so, copcb); 2085*36381Ssklower ENDDEBUG 2086*36381Ssklower if (req == PRU_CONTROL) { 2087*36381Ssklower error = iso_control(so, (int)m, (caddr_t)nam, (struct ifnet *)ifp); 2088*36381Ssklower splx(s); 2089*36381Ssklower return error; 2090*36381Ssklower } 2091*36381Ssklower if (copcb == (struct cons_pcb *)0 && req != PRU_ATTACH) { 2092*36381Ssklower splx(s); 2093*36381Ssklower return ENOTCONN; 2094*36381Ssklower } 2095*36381Ssklower 2096*36381Ssklower switch (req) { 2097*36381Ssklower 2098*36381Ssklower case PRU_ATTACH: 2099*36381Ssklower if (copcb) { 2100*36381Ssklower error = EISCONN; 2101*36381Ssklower break; 2102*36381Ssklower } 2103*36381Ssklower soreserve(so, X25_SBSIZE, X25_SBSIZE); /* CONS size */ 2104*36381Ssklower error = cons_pcballoc(so, &cons_isopcb, CONSF_XTS, X25_proto, &copcb ); 2105*36381Ssklower break; 2106*36381Ssklower 2107*36381Ssklower case PRU_ABORT: /* called from close() */ 2108*36381Ssklower /* called for each incoming connect queued on the parent (accepting) 2109*36381Ssklower * socket (SO_ACCEPTCONN); 2110*36381Ssklower */ 2111*36381Ssklower error = cons_detach ( copcb ); 2112*36381Ssklower break; 2113*36381Ssklower 2114*36381Ssklower case PRU_DETACH: /* called from close() */ 2115*36381Ssklower /* called after disconnect was called iff was connected at the time 2116*36381Ssklower * of the close, or directly if socket never got connected */ 2117*36381Ssklower error = cons_detach ( copcb ); 2118*36381Ssklower break; 2119*36381Ssklower 2120*36381Ssklower case PRU_SHUTDOWN: 2121*36381Ssklower /* recv end may have been released; local credit might be zero */ 2122*36381Ssklower case PRU_DISCONNECT: 2123*36381Ssklower soisdisconnected(so); 2124*36381Ssklower error = cons_clear(copcb, E_CO_HLI_DISCN); 2125*36381Ssklower break; 2126*36381Ssklower 2127*36381Ssklower case PRU_BIND: 2128*36381Ssklower error = cons_pcbbind( copcb, nam); 2129*36381Ssklower break; 2130*36381Ssklower 2131*36381Ssklower case PRU_LISTEN: 2132*36381Ssklower if (copcb->co_lport == 0) 2133*36381Ssklower error = cons_pcbbind( copcb, 0 ); 2134*36381Ssklower break; 2135*36381Ssklower 2136*36381Ssklower 2137*36381Ssklower case PRU_SOCKADDR: { 2138*36381Ssklower struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 2139*36381Ssklower 2140*36381Ssklower nam->m_len = sizeof (struct sockaddr_iso); 2141*36381Ssklower if(copcb->co_ifp) 2142*36381Ssklower bcopy( (caddr_t)&copcb->co_laddr, 2143*36381Ssklower (caddr_t)siso, sizeof(struct sockaddr_iso) ); 2144*36381Ssklower 2145*36381Ssklower ((struct sockaddr_iso *)siso)->siso_tsuffix = copcb->co_lport; 2146*36381Ssklower } 2147*36381Ssklower break; 2148*36381Ssklower 2149*36381Ssklower case PRU_PEERADDR: 2150*36381Ssklower if( (so->so_state & SS_ISCONNECTED) && 2151*36381Ssklower (so->so_state & SS_ISDISCONNECTING) == 0) { 2152*36381Ssklower struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 2153*36381Ssklower 2154*36381Ssklower nam->m_len = sizeof (struct sockaddr_iso); 2155*36381Ssklower bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 2156*36381Ssklower sizeof(struct sockaddr_iso) ); 2157*36381Ssklower } else 2158*36381Ssklower error = ENOTCONN; 2159*36381Ssklower break; 2160*36381Ssklower 2161*36381Ssklower case PRU_CONNECT: 2162*36381Ssklower /* TODO: We need to bind to the RIGHT interface. 2163*36381Ssklower * The only way to have the right interface is to have 2164*36381Ssklower * the right route. 2165*36381Ssklower */ 2166*36381Ssklower IFDEBUG(D_CCONN) 2167*36381Ssklower printf("PRU_CONNECT 1: local tsuffix 0x%x so->so_head 0x%x nam:\n", 2168*36381Ssklower copcb->co_lport, so->so_head); 2169*36381Ssklower dump_isoaddr( mtod(nam, struct sockaddr_iso *) ); 2170*36381Ssklower ENDDEBUG 2171*36381Ssklower if (copcb->co_lport == 0) { 2172*36381Ssklower if( error = cons_pcbbind( copcb, 0 )) 2173*36381Ssklower break; 2174*36381Ssklower } 2175*36381Ssklower IFDEBUG(D_CCONN) 2176*36381Ssklower printf("PRU_CONNECT 2: local tsuffix 0x%x so->so_head 0x%x nam:\n", 2177*36381Ssklower copcb->co_lport, so->so_head); 2178*36381Ssklower dump_isoaddr( mtod(nam, struct sockaddr_iso *) ); 2179*36381Ssklower ENDDEBUG 2180*36381Ssklower 2181*36381Ssklower { /* change the destination address so the last 2 digits 2182*36381Ssklower * are the port/suffix/selector (whatever you want to call it) 2183*36381Ssklower */ 2184*36381Ssklower register struct sockaddr_iso *siso = 2185*36381Ssklower mtod(nam, struct sockaddr_iso *); 2186*36381Ssklower if( (siso->siso_tsuffix < X25_PORT_RESERVED) || 2187*36381Ssklower ((siso->siso_tsuffix >= ISO_PORT_RESERVED) && 2188*36381Ssklower (siso->siso_tsuffix <= X25_PORT_USERMAX))) 2189*36381Ssklower munge( siso->siso_tsuffix, 2190*36381Ssklower siso->siso_addr.t37_idi + ADDR37_IDI_LEN, 2191*36381Ssklower 1 /* nibble */); 2192*36381Ssklower } 2193*36381Ssklower 2194*36381Ssklower soisconnecting(so); 2195*36381Ssklower if (error = iso_pcbconnect(copcb, nam)) 2196*36381Ssklower break; 2197*36381Ssklower error = cons_connect( copcb ); 2198*36381Ssklower if ( error ) { 2199*36381Ssklower /* 2200*36381Ssklower remque((struct isopcb *)copcb); 2201*36381Ssklower (void) m_free(dtom(copcb)); 2202*36381Ssklower */ 2203*36381Ssklower break; 2204*36381Ssklower } 2205*36381Ssklower while( (copcb->co_state != OPEN)&&(copcb->co_socket->so_error == 0) ) { 2206*36381Ssklower IFDEBUG(D_CCONN) 2207*36381Ssklower printf("PRU_CONNECT: error 0x%x sleeping on 0x%x\n", 2208*36381Ssklower copcb->co_socket->so_error, 2209*36381Ssklower (caddr_t)&copcb->co_state ); 2210*36381Ssklower ENDDEBUG 2211*36381Ssklower sleep( (caddr_t)&copcb->co_state, PZERO+3 ); 2212*36381Ssklower } 2213*36381Ssklower 2214*36381Ssklower ASSERT( copcb->co_channel != 0); 2215*36381Ssklower 2216*36381Ssklower SET_CHANMASK ( (struct isopcb *)copcb, copcb->co_channel); 2217*36381Ssklower break; 2218*36381Ssklower 2219*36381Ssklower case PRU_ACCEPT: 2220*36381Ssklower /* so here is the NEW socket */ 2221*36381Ssklower so->so_error = 0; 2222*36381Ssklower if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTED)== 0) { 2223*36381Ssklower error = EWOULDBLOCK; 2224*36381Ssklower break; 2225*36381Ssklower } 2226*36381Ssklower { 2227*36381Ssklower struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 2228*36381Ssklower 2229*36381Ssklower /* copy the peer's address into the return argument */ 2230*36381Ssklower nam->m_len = sizeof (struct sockaddr_iso); 2231*36381Ssklower bcopy( (caddr_t)&copcb->co_faddr, (caddr_t)siso, 2232*36381Ssklower sizeof(struct sockaddr_iso)); 2233*36381Ssklower } 2234*36381Ssklower break; 2235*36381Ssklower 2236*36381Ssklower case PRU_SEND: 2237*36381Ssklower case PRU_SENDEOT: 2238*36381Ssklower /* 2239*36381Ssklower * sosend calls this until sbspace goes negative. 2240*36381Ssklower * Sbspace may be made negative by appending this mbuf chain, 2241*36381Ssklower * possibly by a whole cluster. 2242*36381Ssklower */ 2243*36381Ssklower { 2244*36381Ssklower /* no need to actually queue this stuff and dequeue it, 2245*36381Ssklower * just bump the pointers in so_snd so that higher 2246*36381Ssklower * layer of socket code will cause it to sleep when 2247*36381Ssklower * we've run out of socket space 2248*36381Ssklower * TODO: 2249*36381Ssklower * Unfortunately that makes sbflush vomit so we have 2250*36381Ssklower * to allocate a single real mbuf (say size 240) 2251*36381Ssklower * and sballoc it and sbfree it upon CONS_SEND_DONE. 2252*36381Ssklower * Oh, my, is this sickening or what? 2253*36381Ssklower */ 2254*36381Ssklower { 2255*36381Ssklower struct mbuf *mx; 2256*36381Ssklower 2257*36381Ssklower MGET(mx, M_DONTWAIT, MT_DATA); 2258*36381Ssklower mx->m_len = MLEN; 2259*36381Ssklower sbappend((caddr_t)&copcb->co_socket->so_snd, mx); 2260*36381Ssklower } 2261*36381Ssklower if( m ) { 2262*36381Ssklower IFDEBUG(D_CDATA) 2263*36381Ssklower printf("X.25 Usrreq calling cons_senddata(0x%x, 0x%x)\n", 2264*36381Ssklower copcb, m); 2265*36381Ssklower ENDDEBUG 2266*36381Ssklower error = cons_senddata(copcb, m); 2267*36381Ssklower } 2268*36381Ssklower IFDEBUG(D_CCONS) 2269*36381Ssklower printf("PRU_SEND sent tsuffix 0x%x, m 0x%x error 0x%x\n", 2270*36381Ssklower copcb->co_lport, m, error); 2271*36381Ssklower ENDDEBUG 2272*36381Ssklower 2273*36381Ssklower if( req == PRU_SENDEOT ) { 2274*36381Ssklower while(copcb->co_socket->so_snd.sb_cc > 0) 2275*36381Ssklower sbwait(&copcb->co_socket->so_snd); 2276*36381Ssklower } 2277*36381Ssklower } 2278*36381Ssklower break; 2279*36381Ssklower 2280*36381Ssklower case PRU_CONTROL: 2281*36381Ssklower error = cons_ioctl(so, m, (caddr_t)nam); 2282*36381Ssklower break; 2283*36381Ssklower 2284*36381Ssklower 2285*36381Ssklower case PRU_RCVD: 2286*36381Ssklower case PRU_RCVOOB: 2287*36381Ssklower case PRU_SENDOOB: 2288*36381Ssklower /* COULD support INTERRUPT packets as oob */ 2289*36381Ssklower case PRU_PROTOSEND: 2290*36381Ssklower case PRU_PROTORCV: 2291*36381Ssklower case PRU_SENSE: 2292*36381Ssklower case PRU_SLOWTIMO: 2293*36381Ssklower case PRU_CONNECT2: 2294*36381Ssklower case PRU_FASTTIMO: 2295*36381Ssklower default: 2296*36381Ssklower error = EOPNOTSUPP; 2297*36381Ssklower } 2298*36381Ssklower 2299*36381Ssklower IFDEBUG(D_CCONS) 2300*36381Ssklower printf("cons_usrreq cmd 0x%x copcb 0x%x returned error 0x%x\n", 2301*36381Ssklower req, copcb, error); 2302*36381Ssklower ENDDEBUG 2303*36381Ssklower splx(s); 2304*36381Ssklower return error; 2305*36381Ssklower } 2306*36381Ssklower 2307*36381Ssklower /* 2308*36381Ssklower * NAME: cons_input() 2309*36381Ssklower * CALLED FROM: 2310*36381Ssklower * consintr() through the isosw protosw for "transport" version of X25 2311*36381Ssklower * FUNCTION & ARGUMENTS: 2312*36381Ssklower * process incoming data 2313*36381Ssklower */ 2314*36381Ssklower cons_input(m, faddr, laddr, so) 2315*36381Ssklower register struct mbuf *m; 2316*36381Ssklower struct sockaddr_iso *faddr, *laddr; /* not used */ 2317*36381Ssklower register struct socket *so; 2318*36381Ssklower { 2319*36381Ssklower IFDEBUG(D_CCONS) 2320*36381Ssklower printf("cons_input( m 0x%x, so 0x%x)\n", m,so); 2321*36381Ssklower ENDDEBUG 2322*36381Ssklower sbappend(&so->so_rcv, m); 2323*36381Ssklower sbwakeup(&so->so_rcv); 2324*36381Ssklower } 2325*36381Ssklower 2326*36381Ssklower #ifdef notdef 2327*36381Ssklower /* 2328*36381Ssklower * NAME: cons_ctloutput() 2329*36381Ssklower * CALLED FROM: 2330*36381Ssklower * set/get sockopts() 2331*36381Ssklower * Presently the protosw has 0 in the ctloutput spot 2332*36381Ssklower * because we haven't inplemented anything yet. 2333*36381Ssklower * If there's reason to put some options in here, 2334*36381Ssklower * be sure to stick this routine name in the protosw in iso_proto.c 2335*36381Ssklower */ 2336*36381Ssklower cons_ctloutput(cmd, so, level, optname, mp) 2337*36381Ssklower int cmd, level, optname; 2338*36381Ssklower struct socket *so; 2339*36381Ssklower struct mbuf **mp; 2340*36381Ssklower { 2341*36381Ssklower int s = splnet(); 2342*36381Ssklower 2343*36381Ssklower splx(s); 2344*36381Ssklower return EOPNOTSUPP; 2345*36381Ssklower } 2346*36381Ssklower #endif notdef 2347*36381Ssklower 2348*36381Ssklower 2349*36381Ssklower /* 2350*36381Ssklower * NAME: cons_ctlinput() 2351*36381Ssklower * CALLED FROM: 2352*36381Ssklower * lower layer when ECN_CLEAR occurs : this routine is here 2353*36381Ssklower * for consistency - cons subnet service calls its higher layer 2354*36381Ssklower * through the protosw entry. 2355*36381Ssklower * FUNCTION & ARGUMENTS: 2356*36381Ssklower * cmd is a PRC_* command, list found in ../h/protosw.h 2357*36381Ssklower * copcb is the obvious. 2358*36381Ssklower * This serves the higher-layer cons service. 2359*36381Ssklower * NOTE: this takes 3rd arg. because cons uses it to inform itself 2360*36381Ssklower * of things (timeouts, etc) but has a pcb instead of an address. 2361*36381Ssklower */ 2362*36381Ssklower cons_ctlinput(cmd, sa, copcb) 2363*36381Ssklower int cmd; 2364*36381Ssklower struct sockaddr *sa; 2365*36381Ssklower register struct cons_pcb *copcb; 2366*36381Ssklower { 2367*36381Ssklower int error = 0; 2368*36381Ssklower int s = splnet(); 2369*36381Ssklower extern u_char inetctlerrmap[]; 2370*36381Ssklower extern int iso_rtchange(); 2371*36381Ssklower 2372*36381Ssklower IFDEBUG(D_CCONS) 2373*36381Ssklower printf("cons_ctlinput( cmd 0x%x, copcb 0x%x)\n", cmd, copcb); 2374*36381Ssklower ENDDEBUG 2375*36381Ssklower /* co_socket had better exist */ 2376*36381Ssklower switch (cmd) { 2377*36381Ssklower case PRC_CONS_SEND_DONE: 2378*36381Ssklower ASSERT( copcb->co_socket ); 2379*36381Ssklower ASSERT( copcb->co_flags & CONSF_XTS ); 2380*36381Ssklower sbdrop((caddr_t)&copcb->co_socket->so_snd, MLEN); 2381*36381Ssklower sbwakeup((caddr_t)&copcb->co_socket->so_snd); 2382*36381Ssklower break; 2383*36381Ssklower 2384*36381Ssklower case PRC_ROUTEDEAD: 2385*36381Ssklower error = ENETUNREACH; 2386*36381Ssklower break; 2387*36381Ssklower 2388*36381Ssklower case PRC_TIMXCEED_REASS: 2389*36381Ssklower error = ETIMEDOUT; 2390*36381Ssklower break; 2391*36381Ssklower 2392*36381Ssklower /* 2393*36381Ssklower case PRC_QUENCH: 2394*36381Ssklower iso_pcbnotify(&cons_pcb, sa, 2395*36381Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 2396*36381Ssklower iso_pcbnotify(&tp_incoming_pending, sa, 2397*36381Ssklower (int)inetctlerrmap[cmd], tpiso_quench); 2398*36381Ssklower iso_pcbnotify(&tp_isopcb, sa, 2399*36381Ssklower (int)inetctlerrmap[cmd], tpiso_quench); 2400*36381Ssklower */ 2401*36381Ssklower 2402*36381Ssklower case PRC_IFDOWN: 2403*36381Ssklower iso_pcbnotify(&cons_isopcb, sa, 2404*36381Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 2405*36381Ssklower iso_pcbnotify(&tp_incoming_pending, sa, 2406*36381Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 2407*36381Ssklower iso_pcbnotify(&tp_isopcb, sa, 2408*36381Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 2409*36381Ssklower break; 2410*36381Ssklower 2411*36381Ssklower 2412*36381Ssklower default: 2413*36381Ssklower printf("cons_ctlinput: unknown cmd 0x%x\n", cmd); 2414*36381Ssklower } 2415*36381Ssklower if(error) { 2416*36381Ssklower soisdisconnected(copcb->co_socket); 2417*36381Ssklower sohasoutofband(copcb->co_socket); 2418*36381Ssklower } 2419*36381Ssklower splx(s); 2420*36381Ssklower } 2421*36381Ssklower 2422*36381Ssklower /* 2423*36381Ssklower *********************** SERVES ALL cons embodiments ******************* 2424*36381Ssklower */ 2425*36381Ssklower 2426*36381Ssklower /* 2427*36381Ssklower * NAME: cons_chan_to_pcb() 2428*36381Ssklower * CALLED FROM: 2429*36381Ssklower * cons_chan_to_tpcb() in tp_cons.c 2430*36381Ssklower * and in this file: incoming requests that give only a channel number, i.e., 2431*36381Ssklower * ECN_ACCEPT, ECN_RECEIVE, ECN_CLEAR 2432*36381Ssklower * FUNCTION: 2433*36381Ssklower * identify the pcb assoc with that channel 2434*36381Ssklower * RETURN: 2435*36381Ssklower * ptr to the pcb 2436*36381Ssklower */ 2437*36381Ssklower struct cons_pcb * 2438*36381Ssklower #ifdef ARGO_DEBUG 2439*36381Ssklower cons_chan_to_pcb( channel, linenumber ) 2440*36381Ssklower int linenumber; 2441*36381Ssklower #else ARGO_DEBUG 2442*36381Ssklower cons_chan_to_pcb( channel) 2443*36381Ssklower #endif ARGO_DEBUG 2444*36381Ssklower register int channel; 2445*36381Ssklower { 2446*36381Ssklower register struct cons_pcb **copcblist = (struct cons_pcb **)Xpcblist; 2447*36381Ssklower register struct cons_pcb *copcb; 2448*36381Ssklower 2449*36381Ssklower /* just to be sure */ 2450*36381Ssklower channel = channel & 0xff; 2451*36381Ssklower 2452*36381Ssklower for( copcb = *copcblist; copcb; copcb = *(++copcblist) ) { 2453*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 2454*36381Ssklower while (copcb != *copcblist) { 2455*36381Ssklower if ( copcb->co_channel == channel ) 2456*36381Ssklower goto found; /* want to break out of both loops */ 2457*36381Ssklower 2458*36381Ssklower copcb = (struct cons_pcb *)copcb->co_next; 2459*36381Ssklower } 2460*36381Ssklower } 2461*36381Ssklower found: /* or maybe not... */ 2462*36381Ssklower IFDEBUG(D_CCONS) 2463*36381Ssklower printf("cons_chan_to_pcb( 0x%x, %d ) %s 0x%x\n", channel, linenumber, 2464*36381Ssklower copcb?"FOUND":"FAILED", copcb); 2465*36381Ssklower ENDDEBUG 2466*36381Ssklower 2467*36381Ssklower return copcb; 2468*36381Ssklower } 2469*36381Ssklower 2470*36381Ssklower 2471*36381Ssklower /* 2472*36381Ssklower * NAME: is_me() 2473*36381Ssklower * CALLED FROM: 2474*36381Ssklower * cons_incoming(). Perhaps could just expand in line. 2475*36381Ssklower * FUNCTION and ARGUMENTS: 2476*36381Ssklower * for the given remote address (remadr) if it exactly matches 2477*36381Ssklower * one of the addresses of ME, and I am up as loopback, 2478*36381Ssklower * return TRUE, else return FALSE. 2479*36381Ssklower * RETURNS: 2480*36381Ssklower * Boolean 2481*36381Ssklower */ 2482*36381Ssklower Static int 2483*36381Ssklower is_me(remaddr) 2484*36381Ssklower struct sockaddr_iso *remaddr; 2485*36381Ssklower { 2486*36381Ssklower struct ifnet *ifp = consif; 2487*36381Ssklower /* PHASE2: this is ok */ 2488*36381Ssklower struct ifaddr *ifa = ifa_ifwithaddr(remaddr); 2489*36381Ssklower 2490*36381Ssklower IFDEBUG(D_CADDR) 2491*36381Ssklower printf("is_me: withaddr returns %s\n", 2492*36381Ssklower ifa?ifa->ifa_ifp->if_name:"NONE"); 2493*36381Ssklower ENDDEBUG 2494*36381Ssklower if( ifa ) { 2495*36381Ssklower /* remaddr matches one of my interfaces exactly */ 2496*36381Ssklower if( ifa->ifa_ifp->if_flags & IFF_LOOPBACK ) { 2497*36381Ssklower ASSERT( ifp == ifa->ifa_ifp ); 2498*36381Ssklower return 1; 2499*36381Ssklower } 2500*36381Ssklower } 2501*36381Ssklower return 0; 2502*36381Ssklower } 2503*36381Ssklower 2504*36381Ssklower find_error_reason( ecnrq ) 2505*36381Ssklower register struct eicon_request *ecnrq; 2506*36381Ssklower { 2507*36381Ssklower extern u_char x25_error_stats[]; 2508*36381Ssklower int error; 2509*36381Ssklower struct mbuf *cdm; 2510*36381Ssklower struct e_clear_data *ecd; 2511*36381Ssklower 2512*36381Ssklower cdm = e_data(ecnrq); 2513*36381Ssklower if( cdm && cdm->m_len > 0 ) { 2514*36381Ssklower ecd = mtod(cdm, struct e_clear_data *); 2515*36381Ssklower switch( ecd->ecd_cause ) { 2516*36381Ssklower case 0x00: 2517*36381Ssklower case 0x80: 2518*36381Ssklower /* DTE originated; look at the diagnostic */ 2519*36381Ssklower error = (CONL_ERROR_MASK | ecd->ecd_diagnostic); 2520*36381Ssklower goto done; 2521*36381Ssklower 2522*36381Ssklower case 0x01: /* number busy */ 2523*36381Ssklower case 0x81: 2524*36381Ssklower case 0x09: /* Out of order */ 2525*36381Ssklower case 0x89: 2526*36381Ssklower case 0x11: /* Remot Procedure Error */ 2527*36381Ssklower case 0x91: 2528*36381Ssklower case 0x19: /* reverse charging accept not subscribed */ 2529*36381Ssklower case 0x99: 2530*36381Ssklower case 0x21: /* Incampat destination */ 2531*36381Ssklower case 0xa1: 2532*36381Ssklower case 0x29: /* fast select accept not subscribed */ 2533*36381Ssklower case 0xa9: 2534*36381Ssklower case 0x39: /* ship absent */ 2535*36381Ssklower case 0xb9: 2536*36381Ssklower case 0x03: /* invalid facil request */ 2537*36381Ssklower case 0x83: 2538*36381Ssklower case 0x0b: /* access barred */ 2539*36381Ssklower case 0x8b: 2540*36381Ssklower case 0x13: /* local procedure error */ 2541*36381Ssklower case 0x93: 2542*36381Ssklower case 0x05: /* network congestion */ 2543*36381Ssklower case 0x85: 2544*36381Ssklower case 0x8d: /* not obtainable */ 2545*36381Ssklower case 0x0d: 2546*36381Ssklower case 0x95: /* RPOA out of order */ 2547*36381Ssklower case 0x15: 2548*36381Ssklower /* take out bit 8 2549*36381Ssklower * so we don't have to have so many perror entries 2550*36381Ssklower */ 2551*36381Ssklower error = (CONL_ERROR_MASK | 0x100 | (ecd->ecd_cause & ~0x80)); 2552*36381Ssklower goto done; 2553*36381Ssklower 2554*36381Ssklower case 0xc1: /* gateway-detected proc error */ 2555*36381Ssklower case 0xc3: /* gateway congestion */ 2556*36381Ssklower 2557*36381Ssklower error = (CONL_ERROR_MASK | 0x100 | ecd->ecd_cause); 2558*36381Ssklower goto done; 2559*36381Ssklower } 2560*36381Ssklower } 2561*36381Ssklower /* otherwise, a *hopefully* valid perror exists in the e_reason field */ 2562*36381Ssklower error = ecnrq->e_reason; 2563*36381Ssklower if (error = 0) { 2564*36381Ssklower printf("Incoming PKT TYPE 0x%x with reason 0x%x\n", 2565*36381Ssklower ecnrq->e_cmd, 2566*36381Ssklower ecnrq->e_reason); 2567*36381Ssklower error = E_CO_HLI_DISCA; 2568*36381Ssklower } 2569*36381Ssklower 2570*36381Ssklower done: 2571*36381Ssklower if(error & 0x1ff == 0) { 2572*36381Ssklower error = 0; 2573*36381Ssklower } else if( error & 0x1ff > sizeof(x25_error_stats)) { 2574*36381Ssklower ASSERT(0); 2575*36381Ssklower } else { 2576*36381Ssklower x25_error_stats[error& 0x1ff] ++; 2577*36381Ssklower } 2578*36381Ssklower return error; 2579*36381Ssklower } 2580*36381Ssklower 2581*36381Ssklower /* 2582*36381Ssklower * NAME: consintr() 2583*36381Ssklower * CALLED FROM: 2584*36381Ssklower * the eicon driver via software interrupt 2585*36381Ssklower * FUNCTION and ARGUMENTS: 2586*36381Ssklower * processes incoming indications, passing them 2587*36381Ssklower * along to clnp, tp, or x.25-transport as appropriate. 2588*36381Ssklower */ 2589*36381Ssklower consintr() 2590*36381Ssklower { 2591*36381Ssklower struct ifnet *ifp = consif; 2592*36381Ssklower register struct eicon_request *ecnrq; 2593*36381Ssklower register struct cons_pcb *copcb = (struct cons_pcb *)0; 2594*36381Ssklower register struct mbuf *m; 2595*36381Ssklower int s, s0 = splnet(); 2596*36381Ssklower 2597*36381Ssklower IncStat(co_intr); 2598*36381Ssklower ifp->if_ipackets ++; 2599*36381Ssklower 2600*36381Ssklower for(;;) { 2601*36381Ssklower /* 2602*36381Ssklower * Get next request off input queue 2603*36381Ssklower */ 2604*36381Ssklower s = splimp(); 2605*36381Ssklower IF_DEQUEUE(&consintrq, m); 2606*36381Ssklower splx(s); 2607*36381Ssklower IFDEBUG(D_INCOMING) 2608*36381Ssklower printf("cons intr() 0x%x m_off 0x%x m_len 0x%x dequeued\n", 2609*36381Ssklower m, m?m->m_off:0, m?m->m_len:0); 2610*36381Ssklower ENDDEBUG 2611*36381Ssklower 2612*36381Ssklower if (m == 0) { 2613*36381Ssklower splx(s0); 2614*36381Ssklower return; 2615*36381Ssklower } 2616*36381Ssklower 2617*36381Ssklower if((m->m_off != MMINOFF)||(m->m_len != sizeof (struct eicon_request))){ 2618*36381Ssklower ifp->if_ierrors ++; 2619*36381Ssklower IncStat(co_Rdrops); 2620*36381Ssklower printf("Cons R DROP! BAD MBUF FROM LL 0x%x sizeof(...) 0x%x\n", 2621*36381Ssklower m, sizeof(struct eicon_request)); 2622*36381Ssklower continue; 2623*36381Ssklower } 2624*36381Ssklower 2625*36381Ssklower ecnrq = mtod(m, struct eicon_request *); 2626*36381Ssklower 2627*36381Ssklower 2628*36381Ssklower IFDEBUG(D_INCOMING) 2629*36381Ssklower printf("INTR: e_cmd 0x%x, e_data 0x%x\n", ecnrq->e_cmd, 2630*36381Ssklower e_data(ecnrq)); 2631*36381Ssklower if( e_data(ecnrq) != 0 ) { 2632*36381Ssklower /* let's just look at the first few bytes */ 2633*36381Ssklower /* 2634*36381Ssklower dump_buf( e_data(ecnrq), (e_data(ecnrq))->m_len + 12); 2635*36381Ssklower */ 2636*36381Ssklower dump_buf( e_data(ecnrq), 20 + 12); 2637*36381Ssklower } 2638*36381Ssklower ENDDEBUG 2639*36381Ssklower IFTRACE(D_CDATA) 2640*36381Ssklower tptrace( TPPTmisc, "INTR: req_type m lun\n", 2641*36381Ssklower ecnrq->e_cmd, m, ecnrq->e_vc, 0); 2642*36381Ssklower ENDTRACE 2643*36381Ssklower 2644*36381Ssklower switch( ecnrq->e_cmd ) { 2645*36381Ssklower 2646*36381Ssklower case ECN_ACK: /* data put on the board */ 2647*36381Ssklower IncStat(co_ack); 2648*36381Ssklower ASSERT( ecnrq->e_vc != 0); 2649*36381Ssklower /* from ACKWAIT to OPEN */ 2650*36381Ssklower if ( (copcb = 2651*36381Ssklower #ifdef ARGO_DEBUG 2652*36381Ssklower cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ ) 2653*36381Ssklower #else ARGO_DEBUG 2654*36381Ssklower cons_chan_to_pcb( (int)ecnrq->e_vc ) 2655*36381Ssklower #endif ARGO_DEBUG 2656*36381Ssklower ) == (struct cons_pcb *)0 ) 2657*36381Ssklower break; 2658*36381Ssklower copcb->co_state = OPEN; 2659*36381Ssklower /* 2660*36381Ssklower * Anything on the pending queue for this connection? 2661*36381Ssklower */ 2662*36381Ssklower if( copcb->co_pending.ifq_len == 0 ) { 2663*36381Ssklower if( copcb->co_proto->pr_ctlinput ) 2664*36381Ssklower /* for the sake of higher layer protocol (tp) */ 2665*36381Ssklower (*copcb->co_proto->pr_ctlinput) 2666*36381Ssklower (PRC_CONS_SEND_DONE, 2667*36381Ssklower (struct sockaddr_iso *)&copcb->co_faddr, 2668*36381Ssklower (caddr_t)copcb); 2669*36381Ssklower } else { 2670*36381Ssklower register struct mbuf *m0; 2671*36381Ssklower 2672*36381Ssklower s = splimp(); 2673*36381Ssklower IF_DEQUEUE( &copcb->co_pending, m0 ); 2674*36381Ssklower splx(s); 2675*36381Ssklower /* CAN ONLY DO 1 item here 2676*36381Ssklower * if you change this if to while, HA HA 2677*36381Ssklower * it'll go right back onto 2678*36381Ssklower * the pending queue (which means things will 2679*36381Ssklower * be reordered on the queue!) 2680*36381Ssklower */ 2681*36381Ssklower if( m0 ) { 2682*36381Ssklower IFDEBUG(D_CDATA) 2683*36381Ssklower printf("ACK sending pending queue 0x%x len 0x%x\n", 2684*36381Ssklower m0, m0->m_len); 2685*36381Ssklower ENDDEBUG 2686*36381Ssklower ASSERT( m0->m_len != 0); 2687*36381Ssklower (void) cons_senddata(copcb, m0); 2688*36381Ssklower } 2689*36381Ssklower } 2690*36381Ssklower 2691*36381Ssklower /* send more? */ 2692*36381Ssklower break; 2693*36381Ssklower 2694*36381Ssklower case ECN_ACCEPT: /* call accepted at other end */ 2695*36381Ssklower /* adr_src, adr_dst are as given in the ECN_CALL 2696*36381Ssklower * pcb field is copied from our ECN_CALL 2697*36381Ssklower * request, confirm gives me a channel number 2698*36381Ssklower */ 2699*36381Ssklower ASSERT( ecnrq->e_vc != 0); 2700*36381Ssklower 2701*36381Ssklower IncStat(co_accept); 2702*36381Ssklower if(copcb = 2703*36381Ssklower #ifdef ARGO_DEBUG 2704*36381Ssklower cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__ ) 2705*36381Ssklower #else ARGO_DEBUG 2706*36381Ssklower cons_chan_to_pcb((int)ecnrq->e_vc) 2707*36381Ssklower #endif ARGO_DEBUG 2708*36381Ssklower ) { 2709*36381Ssklower /* error: already exists */ 2710*36381Ssklower printf("cons PANIC: dbl confirm for channel 0x%x\n", 2711*36381Ssklower ecnrq->e_vc); 2712*36381Ssklower break; 2713*36381Ssklower } 2714*36381Ssklower copcb = (struct cons_pcb *)ecnrq->e_pcb; 2715*36381Ssklower if( copcb->co_myself != copcb ) { 2716*36381Ssklower struct mbuf *mm; 2717*36381Ssklower /* TODO: REMOVE */ 2718*36381Ssklower ASSERT(0); 2719*36381Ssklower printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 2720*36381Ssklower ecnrq->e_pcb, ecnrq->e_cmd); 2721*36381Ssklower mm = dtom( copcb ); 2722*36381Ssklower if(mm->m_type == MT_FREE) 2723*36381Ssklower printf("FREED MBUF!\n"); 2724*36381Ssklower dump_buf (ecnrq, sizeof (*ecnrq)); 2725*36381Ssklower panic("BAD ecnrq"); 2726*36381Ssklower break; 2727*36381Ssklower } 2728*36381Ssklower touch(copcb); 2729*36381Ssklower copcb->co_state = OPEN; 2730*36381Ssklower copcb->co_channel = (int)ecnrq->e_vc; 2731*36381Ssklower if(copcb->co_socket) { 2732*36381Ssklower /* tp0 will take care of itself */ 2733*36381Ssklower if( copcb->co_flags & CONSF_XTS) 2734*36381Ssklower soisconnected(copcb->co_socket); /* wake 'em up */ 2735*36381Ssklower } 2736*36381Ssklower wakeup( (caddr_t)&copcb->co_state ); 2737*36381Ssklower 2738*36381Ssklower /* 2739*36381Ssklower * Anything on the pending queue for this connection? 2740*36381Ssklower */ 2741*36381Ssklower if( copcb->co_pending.ifq_len > 0 ) { 2742*36381Ssklower register struct mbuf *m0; 2743*36381Ssklower 2744*36381Ssklower s = splimp(); 2745*36381Ssklower IF_DEQUEUE( &copcb->co_pending, m0 ); 2746*36381Ssklower splx(s); 2747*36381Ssklower /* CAN ONLY DO 1 item here 2748*36381Ssklower * if you change this if to while, HA HA 2749*36381Ssklower * it'll go right back onto 2750*36381Ssklower * the pending queue (which means things will 2751*36381Ssklower * be reordered on the queue!) 2752*36381Ssklower */ 2753*36381Ssklower if( m0 ) { 2754*36381Ssklower IFDEBUG(D_CDATA) 2755*36381Ssklower printf("ACPT sending pending queue 0x%x len 0x%x\n", 2756*36381Ssklower m0, m0->m_len); 2757*36381Ssklower ENDDEBUG 2758*36381Ssklower ASSERT( m0->m_len != 0); 2759*36381Ssklower (void) cons_senddata(copcb, m0); 2760*36381Ssklower } 2761*36381Ssklower } 2762*36381Ssklower break; 2763*36381Ssklower 2764*36381Ssklower case ECN_REFUSE: 2765*36381Ssklower /* other end refused our connect request */ 2766*36381Ssklower /* src, dst are as given in the ECN_CALL */ 2767*36381Ssklower 2768*36381Ssklower IncStat(co_refuse); 2769*36381Ssklower copcb = (struct cons_pcb *)ecnrq->e_pcb; 2770*36381Ssklower if( copcb->co_myself != copcb ) { 2771*36381Ssklower struct mbuf *mm; 2772*36381Ssklower /* TODO: REMOVE */ 2773*36381Ssklower ASSERT(0); 2774*36381Ssklower printf("BAD e_pcb from ecn (0x%x) cmd 0x%x\n", 2775*36381Ssklower ecnrq->e_pcb, ecnrq->e_cmd); 2776*36381Ssklower mm = dtom( copcb ); 2777*36381Ssklower if(mm->m_type == MT_FREE) 2778*36381Ssklower printf("FREED MBUF!\n"); 2779*36381Ssklower dump_buf (ecnrq, sizeof (*ecnrq)); 2780*36381Ssklower dump_buf (copcb, sizeof (*copcb)); 2781*36381Ssklower panic("BAD ecnrq"); 2782*36381Ssklower break; 2783*36381Ssklower } 2784*36381Ssklower touch(copcb); 2785*36381Ssklower copcb->co_state = CLOSED; /* do we have to do a clear?? */ 2786*36381Ssklower copcb->co_channel = X_NOCHANNEL; 2787*36381Ssklower if(copcb->co_socket) { 2788*36381Ssklower copcb->co_socket->so_error = ECONNREFUSED; 2789*36381Ssklower /* TODO: if there's diagnostic info in the 2790*36381Ssklower * packet, and it's more useful than this E*, 2791*36381Ssklower * get it 2792*36381Ssklower */ 2793*36381Ssklower soisdisconnected(copcb->co_socket); /* wake 'em up */ 2794*36381Ssklower IFDEBUG(D_INCOMING) 2795*36381Ssklower printf("ECN_REFUSE: waking up 0x%x\n", 2796*36381Ssklower (caddr_t)&copcb->co_state ); 2797*36381Ssklower ENDDEBUG 2798*36381Ssklower wakeup( (caddr_t)&copcb->co_state ); 2799*36381Ssklower } 2800*36381Ssklower /* 2801*36381Ssklower * Anything on the pending queue for this connection? 2802*36381Ssklower */ 2803*36381Ssklower while( copcb->co_pending.ifq_len > 0 ) { 2804*36381Ssklower register struct mbuf *m0; 2805*36381Ssklower 2806*36381Ssklower s = splimp(); 2807*36381Ssklower IF_DEQUEUE( &copcb->co_pending, m0 ); 2808*36381Ssklower splx(s); 2809*36381Ssklower m_freem(m0); 2810*36381Ssklower } 2811*36381Ssklower if ( ecnrq->e_reason == E_CO_NORESOURCES ) { 2812*36381Ssklower IncStat(co_noresources); 2813*36381Ssklower cons_clear_and_detach( copcb, DONTCLEAR, PRC_QUENCH ); 2814*36381Ssklower } else if(copcb->co_socket ) { 2815*36381Ssklower copcb->co_socket->so_error = find_error_reason( ecnrq ); 2816*36381Ssklower } 2817*36381Ssklower break; 2818*36381Ssklower 2819*36381Ssklower case ECN_CONNECT: /* incoming call */ 2820*36381Ssklower /* 2821*36381Ssklower * ECN_CONNECT indication gives adc_src, adc_dst and channel 2822*36381Ssklower */ 2823*36381Ssklower ASSERT( ecnrq->e_vc != 0); 2824*36381Ssklower 2825*36381Ssklower IncStat(co_connect); 2826*36381Ssklower cons_incoming(ifp, ecnrq); 2827*36381Ssklower break; 2828*36381Ssklower 2829*36381Ssklower case ECN_RESET: 2830*36381Ssklower case ECN_CLEAR: 2831*36381Ssklower /* 2832*36381Ssklower * ECN_CLEAR(indication) (if we can construct such a beast) 2833*36381Ssklower * gives e_vc, 2834*36381Ssklower * Throw away anything queued pending on this connection 2835*36381Ssklower * give a reset indication to the upper layer if TP 2836*36381Ssklower * free the mbufs 2837*36381Ssklower */ 2838*36381Ssklower ASSERT( ecnrq->e_vc != 0); 2839*36381Ssklower if( ecnrq->e_cmd == ECN_CLEAR ) 2840*36381Ssklower IncStat(co_clear_in); 2841*36381Ssklower else 2842*36381Ssklower IncStat(co_reset_in); 2843*36381Ssklower #ifdef ARGO_DEBUG 2844*36381Ssklower if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc, __LINE__)) ) 2845*36381Ssklower #else ARGO_DEBUG 2846*36381Ssklower if( ! (copcb=cons_chan_to_pcb((int)ecnrq->e_vc)) ) 2847*36381Ssklower #endif ARGO_DEBUG 2848*36381Ssklower 2849*36381Ssklower break; 2850*36381Ssklower while( copcb->co_pending.ifq_len ) { 2851*36381Ssklower register struct mbuf *m0; 2852*36381Ssklower 2853*36381Ssklower s = splimp(); 2854*36381Ssklower IF_DEQUEUE( &copcb->co_pending, m0 ); 2855*36381Ssklower splx(s); 2856*36381Ssklower m_freem(m0); 2857*36381Ssklower } 2858*36381Ssklower copcb->co_state = CLOSED; /* do we have to do a clear? */ 2859*36381Ssklower copcb->co_channel = X_NOCHANNEL; 2860*36381Ssklower 2861*36381Ssklower cons_clear_and_detach( copcb, DONTCLEAR, PRC_ROUTEDEAD ); 2862*36381Ssklower if (copcb->co_socket ) { 2863*36381Ssklower copcb->co_socket->so_error = find_error_reason( ecnrq ); 2864*36381Ssklower } 2865*36381Ssklower break; 2866*36381Ssklower 2867*36381Ssklower case ECN_RECEIVE: 2868*36381Ssklower /* 2869*36381Ssklower * ECN_RECEIVE (read) 2870*36381Ssklower */ 2871*36381Ssklower ASSERT( ecnrq->e_vc != 0); 2872*36381Ssklower IncStat(co_receive); 2873*36381Ssklower { 2874*36381Ssklower /* TODO: REMOVE */ 2875*36381Ssklower struct mbuf *thedata = e_data(ecnrq); 2876*36381Ssklower u_int *firstint = mtod( thedata, u_int *); 2877*36381Ssklower 2878*36381Ssklower if( (*firstint & 0xff000000) != 0x81000000 ) { 2879*36381Ssklower /* not clnp */ 2880*36381Ssklower switch( ((*firstint) & 0x00ff0000) >> 20 ) { 2881*36381Ssklower case 0x1: 2882*36381Ssklower case 0x2: 2883*36381Ssklower case 0x3: 2884*36381Ssklower case 0x6: 2885*36381Ssklower case 0x7: 2886*36381Ssklower case 0x8: 2887*36381Ssklower case 0xc: 2888*36381Ssklower case 0xd: 2889*36381Ssklower case 0xe: 2890*36381Ssklower case 0xf: 2891*36381Ssklower break; 2892*36381Ssklower default: 2893*36381Ssklower printf(" ECN_RECEIVE! BAD DATA\n" ); 2894*36381Ssklower dump_buf( thedata, 20 + 12 ); 2895*36381Ssklower m_freem( m ); 2896*36381Ssklower splx(s0); 2897*36381Ssklower } 2898*36381Ssklower } 2899*36381Ssklower } 2900*36381Ssklower if ( (copcb = 2901*36381Ssklower #ifdef ARGO_DEBUG 2902*36381Ssklower cons_chan_to_pcb( (int)ecnrq->e_vc, __LINE__ ) 2903*36381Ssklower #else ARGO_DEBUG 2904*36381Ssklower cons_chan_to_pcb( (int)ecnrq->e_vc ) 2905*36381Ssklower #endif ARGO_DEBUG 2906*36381Ssklower ) == (struct cons_pcb *)0 ) { 2907*36381Ssklower ifp->if_ierrors ++; 2908*36381Ssklower IFTRACE(D_CDATA) 2909*36381Ssklower tptrace(TPPTmisc, "ECN_RECEIVE DROPPED chan \n", 2910*36381Ssklower ecnrq->e_vc, 0, 0, 0); 2911*36381Ssklower ENDTRACE 2912*36381Ssklower break; 2913*36381Ssklower } 2914*36381Ssklower 2915*36381Ssklower touch(copcb); 2916*36381Ssklower if( ecnrq->e_info & ECN_INFO_RCVD_INT ) { 2917*36381Ssklower /* interrupt packet */ 2918*36381Ssklower printf("consintr: interrupt pkttype : DROPPED\n"); 2919*36381Ssklower IncStat(co_intrpt_pkts_in); 2920*36381Ssklower IncStat(co_Rdrops); 2921*36381Ssklower break; 2922*36381Ssklower } 2923*36381Ssklower /* new way */ 2924*36381Ssklower if( copcb->co_proto == CLNP_proto ) 2925*36381Ssklower { 2926*36381Ssklower /* IP: put it on the queue and set soft interrupt */ 2927*36381Ssklower struct ifqueue *ifq; 2928*36381Ssklower extern struct ifqueue clnlintrq; 2929*36381Ssklower register struct mbuf *ifpp; /* for ptr to ifp */ 2930*36381Ssklower register struct mbuf *data = e_data(ecnrq); 2931*36381Ssklower 2932*36381Ssklower total_pkts_to_clnp ++; 2933*36381Ssklower 2934*36381Ssklower /* when acting as a subnet service, have to prepend a 2935*36381Ssklower * pointer to the ifnet before handing this to clnp 2936*36381Ssklower * GAG 2937*36381Ssklower */ 2938*36381Ssklower if( ( data->m_off > MMINOFF + sizeof(struct snpa_hdr)) && 2939*36381Ssklower ( data->m_off <= MMAXOFF )) { 2940*36381Ssklower data->m_off -= sizeof(struct snpa_hdr); 2941*36381Ssklower data->m_len += sizeof(struct snpa_hdr); 2942*36381Ssklower } else { 2943*36381Ssklower MGET(ifpp, M_DONTWAIT, MT_XHEADER); 2944*36381Ssklower if( !ifpp ) { 2945*36381Ssklower ifp->if_ierrors ++; 2946*36381Ssklower splx(s0); 2947*36381Ssklower m_freem(m); /* frees everything */ 2948*36381Ssklower return; 2949*36381Ssklower } 2950*36381Ssklower ifpp->m_len = sizeof(struct snpa_hdr); 2951*36381Ssklower ifpp->m_act = 0; 2952*36381Ssklower ifpp->m_next = data; 2953*36381Ssklower data = ifpp; 2954*36381Ssklower } 2955*36381Ssklower IFTRACE(D_CDATA) 2956*36381Ssklower tptrace(TPPTmisc, "-->CLNP copcb\n", copcb, 0, 0, 0); 2957*36381Ssklower ENDTRACE 2958*36381Ssklower { 2959*36381Ssklower /* 2960*36381Ssklower * TODO: if we ever use esis/cons we have to 2961*36381Ssklower * think of something reasonable to stick in the 2962*36381Ssklower * snh_shost,snh_dhost fields. I guess 2963*36381Ssklower * the x.121 address is what we want. 2964*36381Ssklower * 2965*36381Ssklower * That would also require length fields in the 2966*36381Ssklower * snpa_hdr structure. 2967*36381Ssklower */ 2968*36381Ssklower struct snpa_hdr *snh = 2969*36381Ssklower mtod(data, struct snpa_hdr *); 2970*36381Ssklower bzero((caddr_t)&snh, sizeof(struct snpa_hdr)); 2971*36381Ssklower bcopy((caddr_t)&ifp, (caddr_t)&snh->snh_ifp, 2972*36381Ssklower sizeof(struct ifnet *)); 2973*36381Ssklower } 2974*36381Ssklower *( mtod(data, struct ifnet **) ) = ifp; /* KLUDGE */ 2975*36381Ssklower 2976*36381Ssklower ifq = &clnlintrq; 2977*36381Ssklower splimp(); 2978*36381Ssklower if (IF_QFULL(ifq)) { 2979*36381Ssklower IF_DROP(ifq); 2980*36381Ssklower m_freem(m); 2981*36381Ssklower IFDEBUG(D_INCOMING) 2982*36381Ssklower printf("DROPPED! ecnrq 0x%x, data 0x%x\n", m,data); 2983*36381Ssklower ENDDEBUG 2984*36381Ssklower splx(s0); 2985*36381Ssklower ifp->if_ierrors ++; 2986*36381Ssklower return; 2987*36381Ssklower } 2988*36381Ssklower IF_ENQUEUE(ifq, data); 2989*36381Ssklower IFDEBUG(D_INCOMING) 2990*36381Ssklower printf( 2991*36381Ssklower "0x%x enqueued on ip Q: m_len 0x%x m_type 0x%x m_off 0x%x\n", 2992*36381Ssklower data, data->m_len, data->m_type, data->m_off); 2993*36381Ssklower dump_buf(mtod(data, caddr_t), data->m_len); 2994*36381Ssklower ENDDEBUG 2995*36381Ssklower e_data(ecnrq) = (struct mbuf *)0; 2996*36381Ssklower schednetisr(NETISR_CLNP); 2997*36381Ssklower } else { 2998*36381Ssklower /* HL is NOT clnp */ 2999*36381Ssklower IFTRACE(D_CDATA) 3000*36381Ssklower tptrace(TPPTmisc, 3001*36381Ssklower "-->HL pr_input so copcb channel\n", 3002*36381Ssklower copcb->co_proto->pr_input, 3003*36381Ssklower copcb->co_socket, copcb, 3004*36381Ssklower copcb->co_channel); 3005*36381Ssklower ENDTRACE 3006*36381Ssklower IFDEBUG(D_INCOMING) 3007*36381Ssklower printf( "0x%x --> HL proto 0x%x chan 0x%x\n", 3008*36381Ssklower e_data(ecnrq), copcb->co_proto, copcb->co_channel ); 3009*36381Ssklower ENDDEBUG 3010*36381Ssklower 3011*36381Ssklower (*copcb->co_proto->pr_input)(e_data(ecnrq), 3012*36381Ssklower &copcb->co_faddr, 3013*36381Ssklower &copcb->co_laddr, 3014*36381Ssklower copcb->co_socket, /* used by cons-transport interface */ 3015*36381Ssklower (copcb->co_flags & CONSF_DGM)?0: 3016*36381Ssklower copcb->co_channel);/* used by tp-cons interface */ 3017*36381Ssklower 3018*36381Ssklower /* 3019*36381Ssklower * the pr_input will free the data chain, so we must 3020*36381Ssklower * zero the ptr to is so that m_free doesn't panic 3021*36381Ssklower */ 3022*36381Ssklower e_data(ecnrq) = (struct mbuf *)0; 3023*36381Ssklower } 3024*36381Ssklower break; 3025*36381Ssklower 3026*36381Ssklower default: 3027*36381Ssklower /* error */ 3028*36381Ssklower ifp->if_ierrors ++; 3029*36381Ssklower printf("consintr: unknown request\n"); 3030*36381Ssklower } 3031*36381Ssklower IFDEBUG(D_INCOMING) 3032*36381Ssklower printf("consintr: m_freem( 0x%x )\n", m); 3033*36381Ssklower ENDDEBUG 3034*36381Ssklower m_freem( m ); 3035*36381Ssklower } 3036*36381Ssklower splx(s0); 3037*36381Ssklower } 3038*36381Ssklower 3039*36381Ssklower /* 3040*36381Ssklower * Process an ioctl request. 3041*36381Ssklower * also set-time-limit, extend-time-limit 3042*36381Ssklower * for ALL channels, the time-limit ioctls will be done by open-a-dummy-socket, 3043*36381Ssklower * do ioctl with the channel number, close the socket (dumb!). 3044*36381Ssklower */ 3045*36381Ssklower /* ARGSUSED */ 3046*36381Ssklower cons_ioctl(so, cmd, data) 3047*36381Ssklower struct socket *so; 3048*36381Ssklower int cmd; 3049*36381Ssklower caddr_t data; 3050*36381Ssklower { 3051*36381Ssklower int s = splnet(); 3052*36381Ssklower int error = 0; 3053*36381Ssklower 3054*36381Ssklower IFDEBUG(D_CCONS) 3055*36381Ssklower printf("cons_ioctl( cmd 0x%x )\n", cmd); 3056*36381Ssklower ENDDEBUG 3057*36381Ssklower 3058*36381Ssklower #ifdef notdef 3059*36381Ssklower switch (cmd) { 3060*36381Ssklower 3061*36381Ssklower default: 3062*36381Ssklower #endif notdef 3063*36381Ssklower error = EOPNOTSUPP; 3064*36381Ssklower #ifdef notdef 3065*36381Ssklower } 3066*36381Ssklower #endif notdef 3067*36381Ssklower 3068*36381Ssklower splx(s); 3069*36381Ssklower return (error); 3070*36381Ssklower } 3071*36381Ssklower 3072*36381Ssklower 3073*36381Ssklower /* 3074*36381Ssklower ************************************************************* 3075*36381Ssklower * * 3076*36381Ssklower * * 3077*36381Ssklower * Interface to CO Subnetwork service from CLNP * 3078*36381Ssklower * Must be a device interface. ***** 3079*36381Ssklower * *** 3080*36381Ssklower * * 3081*36381Ssklower * Poof! 3082*36381Ssklower */ 3083*36381Ssklower 3084*36381Ssklower /* 3085*36381Ssklower * NAME: consioctl() 3086*36381Ssklower * CALLED FROM: 3087*36381Ssklower * called through the ifnet structure. 3088*36381Ssklower * FUNCTION and ARGUMENTS: 3089*36381Ssklower * the usual ioctl stuff 3090*36381Ssklower * RETURNS: 3091*36381Ssklower * E* 3092*36381Ssklower * SIDE EFFECTS: 3093*36381Ssklower * NOTES: 3094*36381Ssklower */ 3095*36381Ssklower consioctl(ifp, cmd, data) 3096*36381Ssklower register struct ifnet *ifp; 3097*36381Ssklower register int cmd; 3098*36381Ssklower register caddr_t data; 3099*36381Ssklower { 3100*36381Ssklower register struct ifaddr *ifa = (struct ifaddr *)data; 3101*36381Ssklower register int s = splimp(); 3102*36381Ssklower register struct ifreq *ifr = (struct ifreq *)data; 3103*36381Ssklower register int error = 0; 3104*36381Ssklower void consshutdown(); 3105*36381Ssklower 3106*36381Ssklower switch (cmd) { 3107*36381Ssklower case SIOCSIFADDR: 3108*36381Ssklower switch (ifa->ifa_addr.sa_family) { 3109*36381Ssklower case AF_ISO: 3110*36381Ssklower if( (ifp->if_flags & IFF_UP ) == 0) 3111*36381Ssklower consinit(ifp->if_unit); 3112*36381Ssklower break; 3113*36381Ssklower default: 3114*36381Ssklower printf("CANNOT config cons with address family %d\n", 3115*36381Ssklower ifa->ifa_addr.sa_family); 3116*36381Ssklower break; 3117*36381Ssklower } 3118*36381Ssklower break; 3119*36381Ssklower case SIOCSIFFLAGS: 3120*36381Ssklower IFDEBUG(D_CCONS) 3121*36381Ssklower printf("consioctl: set flags to x%x\n", ifr->ifr_flags); 3122*36381Ssklower printf("consioctl: ifp flags are x%x\n", ifp->if_flags); 3123*36381Ssklower ENDDEBUG 3124*36381Ssklower if( ifr->ifr_flags & IFF_LOOPBACK ) 3125*36381Ssklower ifp->if_flags |= IFF_LOOPBACK; 3126*36381Ssklower else 3127*36381Ssklower ifp->if_flags &= ~IFF_LOOPBACK; 3128*36381Ssklower 3129*36381Ssklower /* if board is down but request takes it up, init the board */ 3130*36381Ssklower if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) 3131*36381Ssklower consinit(ifp->if_unit); 3132*36381Ssklower 3133*36381Ssklower /* if board is up but request takes it down, shut the board down */ 3134*36381Ssklower if (((ifr->ifr_flags & IFF_UP) == 0) && (ifp->if_flags & IFF_UP)) { 3135*36381Ssklower consshutdown(ifp->if_unit); 3136*36381Ssklower } 3137*36381Ssklower IFDEBUG(D_CCONS) 3138*36381Ssklower printf("consioctl: flags are x%x\n", ifp->if_flags); 3139*36381Ssklower ENDDEBUG 3140*36381Ssklower break; 3141*36381Ssklower case SIOCGSTATUS: 3142*36381Ssklower /* warning: must coerse ifp to (struct ifstatus *) in order to use */ 3143*36381Ssklower IFDEBUG(D_CCONS) 3144*36381Ssklower printf("consioctl: EICON status request\n"); 3145*36381Ssklower ENDDEBUG 3146*36381Ssklower #if NECN>0 3147*36381Ssklower ecnioctl(ifp, cmd, data); 3148*36381Ssklower #else 3149*36381Ssklower error = ENODEV; 3150*36381Ssklower #endif NECN>0 3151*36381Ssklower break; 3152*36381Ssklower default: 3153*36381Ssklower error = EINVAL; 3154*36381Ssklower } 3155*36381Ssklower splx(s); 3156*36381Ssklower return error; 3157*36381Ssklower } 3158*36381Ssklower 3159*36381Ssklower /* 3160*36381Ssklower * NAME: consattach() 3161*36381Ssklower * CALLED FROM: 3162*36381Ssklower * cons_init() (which comes from autoconf) 3163*36381Ssklower * FUNCTION and ARGUMENTS: 3164*36381Ssklower * creates an ifp and fills it in; calls ifattach() on it. 3165*36381Ssklower * RETURNS: 3166*36381Ssklower * no return value 3167*36381Ssklower * SIDE EFFECTS: 3168*36381Ssklower * NOTES: 3169*36381Ssklower */ 3170*36381Ssklower consattach() 3171*36381Ssklower { 3172*36381Ssklower register struct ifnet *ifp; 3173*36381Ssklower register struct mbuf *m; 3174*36381Ssklower 3175*36381Ssklower if(sizeof(struct ifnet) > MLEN) { 3176*36381Ssklower printf("Can't attach cons! sizeof(struct ifnet) > MLEN\n"); 3177*36381Ssklower return; 3178*36381Ssklower } 3179*36381Ssklower MGET(m, M_DONTWAIT, MT_IFADDR); 3180*36381Ssklower if( !m ) { 3181*36381Ssklower printf("Can't attach cons! NO MBUFS!\n"); 3182*36381Ssklower return; 3183*36381Ssklower } 3184*36381Ssklower m->m_len = sizeof(struct ifnet); 3185*36381Ssklower ifp = consif = mtod(m, struct ifnet *); 3186*36381Ssklower ifp->if_unit = 0; 3187*36381Ssklower ifp->if_name = "cons"; 3188*36381Ssklower ifp->if_mtu = ECN_MTU; 3189*36381Ssklower ifp->if_init = consinit; 3190*36381Ssklower ifp->if_ioctl = consioctl; 3191*36381Ssklower ifp->if_output = cosns_output; /* called by clnp */ 3192*36381Ssklower ifp->if_flags = IFF_LOOPBACK; /* default */ 3193*36381Ssklower if_attach(ifp); 3194*36381Ssklower printf("cons%d: pseudo device attached \n", ifp->if_unit); 3195*36381Ssklower } 3196*36381Ssklower 3197*36381Ssklower /* 3198*36381Ssklower * NAME: consinit() 3199*36381Ssklower * CALLED FROM: 3200*36381Ssklower * consioctl() 3201*36381Ssklower * FUNCTION and ARGUMENTS: 3202*36381Ssklower * Initializes apropos data structures, etc. 3203*36381Ssklower * Marks the device as up. 3204*36381Ssklower * Zaps the address list. 3205*36381Ssklower * Calls device layer restart on the device if necessary. 3206*36381Ssklower */ 3207*36381Ssklower Static 3208*36381Ssklower consinit(_unit) 3209*36381Ssklower register int _unit; /* unit to initialize */ 3210*36381Ssklower { 3211*36381Ssklower struct ifnet *ecnifp(); 3212*36381Ssklower struct ifnet *ifp; 3213*36381Ssklower int s; 3214*36381Ssklower 3215*36381Ssklower if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) { 3216*36381Ssklower ecnrestart(ifp); 3217*36381Ssklower IncStat(co_restart); 3218*36381Ssklower } 3219*36381Ssklower if (consif->if_addrlist == (struct ifaddr *)0) 3220*36381Ssklower return; 3221*36381Ssklower if ((consif->if_flags & IFF_UP) == 0) { 3222*36381Ssklower s = splimp(); 3223*36381Ssklower consif->if_flags |= IFF_UP; 3224*36381Ssklower splx(s); 3225*36381Ssklower } 3226*36381Ssklower 3227*36381Ssklower } 3228*36381Ssklower 3229*36381Ssklower /* 3230*36381Ssklower * NAME: consshutdown() 3231*36381Ssklower * CALLED FROM: 3232*36381Ssklower * cons_ioctl() when user takes down an interface w/ SIOCSIFFLAGS 3233*36381Ssklower * FUNCTION and ARGUMENTS: 3234*36381Ssklower * calls lower layer shutdown routine on the device. 3235*36381Ssklower * and marks the if as down if the if is the sw loopback pseudodevice. 3236*36381Ssklower * RETURNS: 3237*36381Ssklower * no return value 3238*36381Ssklower */ 3239*36381Ssklower void 3240*36381Ssklower consshutdown(_unit) 3241*36381Ssklower register int _unit; /* unit to shutdown */ 3242*36381Ssklower { 3243*36381Ssklower extern struct ifnet *ecnifp(); 3244*36381Ssklower struct ifnet *ifp; 3245*36381Ssklower int s; 3246*36381Ssklower 3247*36381Ssklower if ((ifp = ecnifp(_unit)) != (struct ifnet *)0 ) { 3248*36381Ssklower ecnshutdown(ifp); 3249*36381Ssklower } 3250*36381Ssklower if ((consif->if_flags & IFF_UP) ) { 3251*36381Ssklower s = splimp(); 3252*36381Ssklower consif->if_flags &= ~IFF_UP; 3253*36381Ssklower splx(s); 3254*36381Ssklower } 3255*36381Ssklower } 3256*36381Ssklower #endif KERNEL 3257*36381Ssklower 3258*36381Ssklower /* 3259*36381Ssklower * NAME: munge() 3260*36381Ssklower * CALLED FROM: 3261*36381Ssklower * cons_pcbbind(), cons_usrreq() 3262*36381Ssklower * FUNCTION and ARGUMENTS: 3263*36381Ssklower * Takes the argument (value) and stashes it into the last two 3264*36381Ssklower * nibbles of an X.121 address. Does this in the two nibbles beginning 3265*36381Ssklower * at the location defined by the character pointer (dst_octet) and the 3266*36381Ssklower * integer (dst_nibble). Nibble 0 is the lower nibble (high 3267*36381Ssklower * order 4 bits); nibble 1 is the low order 4 bits of *(dst_octet). 3268*36381Ssklower * 3269*36381Ssklower * RETURNS: 3270*36381Ssklower * no return value 3271*36381Ssklower */ 3272*36381Ssklower Static 3273*36381Ssklower munge( value, dst_octet, dst_nibble) 3274*36381Ssklower int value; 3275*36381Ssklower caddr_t dst_octet; 3276*36381Ssklower int dst_nibble; 3277*36381Ssklower { 3278*36381Ssklower IFDEBUG(D_CCONN) 3279*36381Ssklower printf("MUNGE: value 0x%x dst_octet 0x%x, nibble 0x%x)\n", 3280*36381Ssklower value, dst_octet, dst_nibble); 3281*36381Ssklower ENDDEBUG 3282*36381Ssklower if (value >= ISO_PORT_RESERVED) 3283*36381Ssklower value -= 1000; 3284*36381Ssklower 3285*36381Ssklower { 3286*36381Ssklower /* convert so it looks like a decimal number */ 3287*36381Ssklower register int tens, ones; 3288*36381Ssklower 3289*36381Ssklower tens = value/10; 3290*36381Ssklower ASSERT( tens <= 9 ); 3291*36381Ssklower ones = value - (tens * 10); 3292*36381Ssklower 3293*36381Ssklower value = tens * 16 + ones; 3294*36381Ssklower } 3295*36381Ssklower 3296*36381Ssklower dst_octet --; 3297*36381Ssklower /* leave nibble same 'cause it's one after the last set nibble */ 3298*36381Ssklower 3299*36381Ssklower *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */ 3300*36381Ssklower *dst_octet |= ((value>>4) << (dst_nibble<<2)); 3301*36381Ssklower dst_nibble = 1-dst_nibble; 3302*36381Ssklower dst_octet += dst_nibble; 3303*36381Ssklower 3304*36381Ssklower *dst_octet &= ~(0xff<<(dst_nibble << 2)); /* zero it */ 3305*36381Ssklower *dst_octet |= ((value&0xff) << (dst_nibble<<2)); 3306*36381Ssklower } 3307*36381Ssklower 3308*36381Ssklower /* 3309*36381Ssklower * NAME: unmunge() 3310*36381Ssklower * CALLED FROM: 3311*36381Ssklower * DTEtoNSAP(), FACILtoNSAP() 3312*36381Ssklower * FUNCTION and ARGUMENTS: 3313*36381Ssklower * return the port/tsuffix represented by the two digits found in a 3314*36381Ssklower * bcd string beginning at the (dst_nibble)th nibble of the 3315*36381Ssklower * octet BEFORE (dst_octet). 3316*36381Ssklower * 3317*36381Ssklower * dst_octet,dst_nibble is the nibble after the one we'll look at 3318*36381Ssklower * RETURNS: 3319*36381Ssklower * an integer, the port/tsuffix 3320*36381Ssklower * Note- converts to a port > 1000 if necessary. 3321*36381Ssklower */ 3322*36381Ssklower Static int 3323*36381Ssklower unmunge( dst_octet, dst_nibble ) 3324*36381Ssklower caddr_t dst_octet; 3325*36381Ssklower int dst_nibble; 3326*36381Ssklower { 3327*36381Ssklower register u_short last = 0; 3328*36381Ssklower 3329*36381Ssklower dst_octet --; 3330*36381Ssklower /* leave nibble same 'cause it's one after the last set nibble */ 3331*36381Ssklower IFDEBUG(D_CADDR) 3332*36381Ssklower printf("unmunge: *octet 0x%x, nibble 0x%x\n", *dst_octet, 3333*36381Ssklower dst_nibble); 3334*36381Ssklower ENDDEBUG 3335*36381Ssklower 3336*36381Ssklower last = ((*dst_octet) & (0xff<<(dst_nibble<<2))); 3337*36381Ssklower dst_nibble = 1-dst_nibble; 3338*36381Ssklower dst_octet += dst_nibble; 3339*36381Ssklower 3340*36381Ssklower last |= ((*dst_octet) & (0xff<<(dst_nibble << 2))); 3341*36381Ssklower { 3342*36381Ssklower /* convert to a decimal number */ 3343*36381Ssklower register int tens, ones; 3344*36381Ssklower 3345*36381Ssklower tens = (last&0xf0)>>4; 3346*36381Ssklower ones = last&0xf; 3347*36381Ssklower 3348*36381Ssklower last = tens * 10 + ones; 3349*36381Ssklower } 3350*36381Ssklower 3351*36381Ssklower IFDEBUG(D_CADDR) 3352*36381Ssklower printf("unmunge computes 0x%x\n", last); 3353*36381Ssklower ENDDEBUG 3354*36381Ssklower if((int)last+1000 >= ISO_PORT_RESERVED) 3355*36381Ssklower last += 1000; 3356*36381Ssklower IFDEBUG(D_CADDR) 3357*36381Ssklower printf("unmunge returns 0x%x\n", last); 3358*36381Ssklower ENDDEBUG 3359*36381Ssklower return last; 3360*36381Ssklower } 3361*36381Ssklower 3362*36381Ssklower /* 3363*36381Ssklower * NAME: make_partial_x25_packet() 3364*36381Ssklower * 3365*36381Ssklower * FUNCTION and ARGUMENTS: 3366*36381Ssklower * Makes part of an X.25 call packet, for use by the eicon board. 3367*36381Ssklower * (src) and (dst) are the NSAP-addresses of source and destination. 3368*36381Ssklower * (proto) is the higher-layer protocol number (in iso.h) 3369*36381Ssklower * (buf) is a ptr to a buffer into which to write this partial header. 3370*36381Ssklower * 3371*36381Ssklower * The partial header looks like (choke): 3372*36381Ssklower * octet meaning 3373*36381Ssklower * 1 calling DTE len | called DTE len (lengths in nibbles) 3374*36381Ssklower * 2..n-1 called DTE addr | (<-- boundary may be middle of an octet) 3375*36381Ssklower * calling DTE addr | zero nibble to round to octet boundary. 3376*36381Ssklower * n Facility length (in octets) 3377*36381Ssklower * n+1 Facility field, which is a set of: 3378*36381Ssklower * m facil code 3379*36381Ssklower * m+1 facil param len (for >2-byte facilities) in octets 3380*36381Ssklower * m+2..p facil param field 3381*36381Ssklower * q user data (protocol identification octet) 3382*36381Ssklower * 3383*36381Ssklower * 3384*36381Ssklower * RETURNS: 3385*36381Ssklower * 0 if OK 3386*36381Ssklower * E* if failed. 3387*36381Ssklower */ 3388*36381Ssklower 3389*36381Ssklower #ifdef X25_1984 3390*36381Ssklower int cons_use_facils = 1; 3391*36381Ssklower #else X25_1984 3392*36381Ssklower int cons_use_facils = 0; 3393*36381Ssklower #endif X25_1984 3394*36381Ssklower 3395*36381Ssklower int cons_use_udata = 1; /* KLUDGE FOR DEBUGGING */ 3396*36381Ssklower 3397*36381Ssklower Static int 3398*36381Ssklower make_partial_x25_packet(copcb, m) 3399*36381Ssklower struct cons_pcb *copcb; 3400*36381Ssklower struct mbuf *m; 3401*36381Ssklower { 3402*36381Ssklower struct sockaddr_iso *src, *dst; 3403*36381Ssklower u_int proto; 3404*36381Ssklower int flag; 3405*36381Ssklower caddr_t buf = mtod(m, caddr_t); 3406*36381Ssklower register caddr_t ptr = buf + 1; /* make room for 2 length nibbles */ 3407*36381Ssklower register int len = 0; 3408*36381Ssklower int buflen =0; 3409*36381Ssklower caddr_t facil_len; 3410*36381Ssklower int oddness = 0; 3411*36381Ssklower 3412*36381Ssklower src = &copcb->co_laddr; 3413*36381Ssklower dst = &copcb->co_faddr; 3414*36381Ssklower proto = copcb->co_proto->pr_protocol, 3415*36381Ssklower flag = copcb->co_flags & CONSF_XTS; 3416*36381Ssklower 3417*36381Ssklower 3418*36381Ssklower IFDEBUG(D_CCONN) 3419*36381Ssklower printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", 3420*36381Ssklower src, dst, proto, m, flag); 3421*36381Ssklower ENDDEBUG 3422*36381Ssklower 3423*36381Ssklower /* 3424*36381Ssklower * Note - order of addrs in x25 pkt hdr is wierd: 3425*36381Ssklower * calling len/called len/called addr/calling addr (p.40 ISO 8202) 3426*36381Ssklower */ 3427*36381Ssklower if( (len = copcb->co_peer_dte.dtea_niblen) > 0 ) { 3428*36381Ssklower nibble_copy( (char *)(copcb->co_peer_dte.dtea_addr), HIGH_NIBBLE, 3429*36381Ssklower ptr, HIGH_NIBBLE, len); 3430*36381Ssklower } else { 3431*36381Ssklower if ((len = NSAPtoDTE( ptr, HIGH_NIBBLE, dst)) <=0 ) { 3432*36381Ssklower return E_CO_OSI_UNSAP; 3433*36381Ssklower } 3434*36381Ssklower } 3435*36381Ssklower *buf = len; /* fill in called dte addr length */ 3436*36381Ssklower ptr += len>>1; /* len is in nibbles */ 3437*36381Ssklower oddness += len&0x1; 3438*36381Ssklower 3439*36381Ssklower if ((len = NSAPtoDTE( ptr, 1-(len&0x1), src)) <=0 ) { 3440*36381Ssklower return E_CO_OSI_UNSAP; 3441*36381Ssklower } 3442*36381Ssklower ptr += len>>1; /* len is in nibbles */ 3443*36381Ssklower *buf |= len << 4; /* fill in calling dte addr length */ 3444*36381Ssklower oddness += len&0x1; 3445*36381Ssklower 3446*36381Ssklower IFDEBUG(D_CADDR) 3447*36381Ssklower printf("make_partial 2: ptr 0x%x, len 0x%x oddness 0x%x\n", 3448*36381Ssklower ptr, len, oddness ); 3449*36381Ssklower ENDDEBUG 3450*36381Ssklower /* if either of the addresses were an odd length, the count is off by 1 */ 3451*36381Ssklower if( oddness ) { 3452*36381Ssklower ptr ++; 3453*36381Ssklower } 3454*36381Ssklower 3455*36381Ssklower /* ptr now points to facil length (len of whole facil field in OCTETS */ 3456*36381Ssklower facil_len = ptr ++; 3457*36381Ssklower 3458*36381Ssklower IFDEBUG(D_CADDR) 3459*36381Ssklower printf("make_partial calling: ptr 0x%x, len 0x%x\n", ptr, 3460*36381Ssklower src->siso_addr.isoa_len); 3461*36381Ssklower ENDDEBUG 3462*36381Ssklower if( cons_use_facils ) { 3463*36381Ssklower *ptr = 0xcb; /* calling facility code */ 3464*36381Ssklower ptr ++; 3465*36381Ssklower ptr ++; /* leave room for facil param len (in OCTETS + 1) */ 3466*36381Ssklower ptr ++; /* leave room for the facil param len (in nibbles), 3467*36381Ssklower * high two bits of which indicate full/partial NSAP 3468*36381Ssklower */ 3469*36381Ssklower len = src->siso_addr.isoa_len; 3470*36381Ssklower bcopy( &src->siso_addr.isoa_afi, ptr, len); 3471*36381Ssklower *(ptr-2) = len+2; /* facil param len in octets */ 3472*36381Ssklower *(ptr-1) = len<<1; /* facil param len in nibbles */ 3473*36381Ssklower ptr += len; 3474*36381Ssklower 3475*36381Ssklower IFDEBUG(D_CADDR) 3476*36381Ssklower printf("make_partial called: ptr 0x%x, len 0x%x\n", ptr, 3477*36381Ssklower dst->siso_addr.isoa_len); 3478*36381Ssklower ENDDEBUG 3479*36381Ssklower *ptr = 0xc9; /* called facility code */ 3480*36381Ssklower ptr ++; 3481*36381Ssklower ptr ++; /* leave room for facil param len (in OCTETS + 1) */ 3482*36381Ssklower ptr ++; /* leave room for the facil param len (in nibbles), 3483*36381Ssklower * high two bits of which indicate full/partial NSAP 3484*36381Ssklower */ 3485*36381Ssklower len = dst->siso_addr.isoa_len; 3486*36381Ssklower bcopy( &dst->siso_addr.isoa_afi, ptr, len); 3487*36381Ssklower *(ptr-2) = len+2; /* facil param len = addr len + 1 for each of these 3488*36381Ssklower * two length fields, in octets */ 3489*36381Ssklower *(ptr-1) = len<<1; /* facil param len in nibbles */ 3490*36381Ssklower ptr += len; 3491*36381Ssklower 3492*36381Ssklower } 3493*36381Ssklower *facil_len = ptr - facil_len - 1; 3494*36381Ssklower if(*facil_len > X25_FACIL_LEN_MAX ) 3495*36381Ssklower return E_CO_PNA_LONG; 3496*36381Ssklower 3497*36381Ssklower if( cons_use_udata ) { 3498*36381Ssklower if (copcb->co_x25crud_len > 0) { 3499*36381Ssklower /* 3500*36381Ssklower * The user specified something. Stick it in 3501*36381Ssklower */ 3502*36381Ssklower bcopy(copcb->co_x25crud, ptr, copcb->co_x25crud_len); 3503*36381Ssklower ptr += copcb->co_x25crud_len; 3504*36381Ssklower } else { 3505*36381Ssklower /* protocol identifier */ 3506*36381Ssklower switch (proto) { 3507*36381Ssklower /* unfortunately all are considered 1 protocol */ 3508*36381Ssklower case ISOPROTO_TP0: 3509*36381Ssklower case ISOPROTO_TP1: 3510*36381Ssklower case ISOPROTO_TP2: 3511*36381Ssklower case ISOPROTO_TP3: 3512*36381Ssklower case ISOPROTO_TP4: 3513*36381Ssklower case ISOPROTO_CLTP: 3514*36381Ssklower /* no user data for TP */ 3515*36381Ssklower break; 3516*36381Ssklower 3517*36381Ssklower case ISOPROTO_CLNP: 3518*36381Ssklower *ptr = 0x81; 3519*36381Ssklower ptr++; /* count the proto id byte! */ 3520*36381Ssklower break; 3521*36381Ssklower case ISOPROTO_INACT_NL: 3522*36381Ssklower *ptr = 0x0; 3523*36381Ssklower ptr++; /* count the proto id byte! */ 3524*36381Ssklower break; 3525*36381Ssklower case ISOPROTO_X25: 3526*36381Ssklower *ptr = 0xff; /* reserved for future extensions */ 3527*36381Ssklower /* we're stealing this value for local use */ 3528*36381Ssklower ptr++; /* count the proto id byte! */ 3529*36381Ssklower break; 3530*36381Ssklower default: 3531*36381Ssklower return EPROTONOSUPPORT; 3532*36381Ssklower } 3533*36381Ssklower } 3534*36381Ssklower } 3535*36381Ssklower 3536*36381Ssklower buflen = (int)(ptr - buf); 3537*36381Ssklower 3538*36381Ssklower IFDEBUG(D_CDUMP_REQ) 3539*36381Ssklower register int i; 3540*36381Ssklower 3541*36381Ssklower printf("ECN_CONNECT DATA buf 0x%x len %d (0x%x)\n", 3542*36381Ssklower buf, buflen, buflen); 3543*36381Ssklower for( i=0; i < buflen; ) { 3544*36381Ssklower printf("+%d: %x %x %x %x %x %x %x %x\n", 3545*36381Ssklower i, 3546*36381Ssklower *(buf+i), *(buf+i+1), *(buf+i+2), *(buf+i+3), 3547*36381Ssklower *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7)); 3548*36381Ssklower i+=8; 3549*36381Ssklower } 3550*36381Ssklower ENDDEBUG 3551*36381Ssklower IFDEBUG(D_CADDR) 3552*36381Ssklower printf("make_partial returns buf 0x%x size 0x%x bytes\n", 3553*36381Ssklower mtod(m, caddr_t), buflen); 3554*36381Ssklower ENDDEBUG 3555*36381Ssklower 3556*36381Ssklower ASSERT( X25_PARTIAL_PKT_LEN_MAX < MLEN ); 3557*36381Ssklower 3558*36381Ssklower if(buflen > X25_PARTIAL_PKT_LEN_MAX) 3559*36381Ssklower return E_CO_PNA_LONG; 3560*36381Ssklower 3561*36381Ssklower m->m_len = buflen; 3562*36381Ssklower return 0; 3563*36381Ssklower } 3564*36381Ssklower 3565*36381Ssklower /* 3566*36381Ssklower * NAME: NSAPtoDTE() 3567*36381Ssklower * CALLED FROM: 3568*36381Ssklower * make_partial_x25_packet() 3569*36381Ssklower * FUNCTION and ARGUMENTS: 3570*36381Ssklower * get a DTE address from an NSAP-address (struct sockaddr_iso) 3571*36381Ssklower * (dst_octet) is the octet into which to begin stashing the DTE addr 3572*36381Ssklower * (dst_nibble) takes 0 or 1. 1 means begin filling in the DTE addr 3573*36381Ssklower * in the high-order nibble of dst_octet. 0 means low-order nibble. 3574*36381Ssklower * (addr) is the NSAP-address 3575*36381Ssklower * (flag) is true if the transport suffix is to become the 3576*36381Ssklower * last two digits of the DTE address 3577*36381Ssklower * A DTE address is a series of BCD digits 3578*36381Ssklower * 3579*36381Ssklower * A DTE address may have leading zeros. The are significant. 3580*36381Ssklower * 1 digit per nibble, may be an odd number of nibbles. 3581*36381Ssklower * 3582*36381Ssklower * An NSAP-address has the DTE address in the IDI. Leading zeros are 3583*36381Ssklower * significant. Trailing hex f indicates the end of the DTE address. 3584*36381Ssklower * Also is a series of BCD digits, one per nibble. 3585*36381Ssklower * 3586*36381Ssklower * RETURNS 3587*36381Ssklower * # significant digits in the DTE address, -1 if error. 3588*36381Ssklower */ 3589*36381Ssklower 3590*36381Ssklower Static int 3591*36381Ssklower NSAPtoDTE( dst_octet, dst_nibble, addr) 3592*36381Ssklower caddr_t dst_octet; 3593*36381Ssklower int dst_nibble; 3594*36381Ssklower register struct sockaddr_iso *addr; 3595*36381Ssklower { 3596*36381Ssklower int error; 3597*36381Ssklower u_char x121string[7]; /* maximum is 14 digits */ 3598*36381Ssklower int x121strlen; 3599*36381Ssklower struct dte_addr *dtea; 3600*36381Ssklower 3601*36381Ssklower IFDEBUG(D_CADDR) 3602*36381Ssklower printf("NSAPtoDTE: nsap: %s\n", clnp_iso_addrp(&addr->siso_addr)); 3603*36381Ssklower ENDDEBUG 3604*36381Ssklower 3605*36381Ssklower error = iso_8208snparesolve(addr, x121string, &x121strlen); 3606*36381Ssklower ASSERT(error == 0); 3607*36381Ssklower if( error != 0 ) { 3608*36381Ssklower /* no snpa - cannot send */ 3609*36381Ssklower IFDEBUG(D_CADDR) 3610*36381Ssklower printf("NSAPtoDTE: 8208resolve: %d\n", error ); 3611*36381Ssklower ENDDEBUG 3612*36381Ssklower return 0; 3613*36381Ssklower } 3614*36381Ssklower ASSERT(x121strlen == sizeof(struct dte_addr)); 3615*36381Ssklower dtea = (struct dte_addr *)x121string; 3616*36381Ssklower x121strlen = dtea->dtea_niblen; 3617*36381Ssklower 3618*36381Ssklower nibble_copy((char *)x121string, HIGH_NIBBLE, 3619*36381Ssklower dst_octet, dst_nibble, x121strlen); 3620*36381Ssklower return x121strlen; 3621*36381Ssklower } 3622*36381Ssklower 3623*36381Ssklower /* 3624*36381Ssklower * NAME: FACILtoNSAP() 3625*36381Ssklower * CALLED FROM: 3626*36381Ssklower * parse_facil() 3627*36381Ssklower * FUNCTION and ARGUMENTS: 3628*36381Ssklower * Creates and NSAP in the sockaddr_iso (addr) from the 3629*36381Ssklower * x.25 facility found at (buf), of length (buf_len). 3630*36381Ssklower * RETURNS: 3631*36381Ssklower * 0 if ok, non-zero if error; 3632*36381Ssklower */ 3633*36381Ssklower 3634*36381Ssklower Static int 3635*36381Ssklower FACILtoNSAP( buf, buf_len, addr) 3636*36381Ssklower caddr_t buf; 3637*36381Ssklower u_char buf_len; /* in bytes */ 3638*36381Ssklower register struct sockaddr_iso *addr; 3639*36381Ssklower { 3640*36381Ssklower int len_in_nibbles; 3641*36381Ssklower 3642*36381Ssklower IFDEBUG(D_CADDR) 3643*36381Ssklower printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 3644*36381Ssklower buf, buf_len, addr ); 3645*36381Ssklower ENDDEBUG 3646*36381Ssklower 3647*36381Ssklower len_in_nibbles = *buf; 3648*36381Ssklower /* despite the fact that X.25 makes us put a length in nibbles 3649*36381Ssklower * here, the NSAP-addrs are always in full octets 3650*36381Ssklower */ 3651*36381Ssklower buf ++; 3652*36381Ssklower 3653*36381Ssklower bzero( addr, sizeof (struct sockaddr_iso) ); 3654*36381Ssklower 3655*36381Ssklower ASSERT(buf_len <= 1+sizeof (struct iso_addr)); 3656*36381Ssklower if(buf_len > 1+sizeof (struct iso_addr)) { 3657*36381Ssklower return -1; /* error */ 3658*36381Ssklower } 3659*36381Ssklower ASSERT(len_in_nibbles == (buf_len - 1)<<1); 3660*36381Ssklower if(len_in_nibbles != (buf_len - 1)<<1) { 3661*36381Ssklower return -2; /* error */ 3662*36381Ssklower } 3663*36381Ssklower bcopy(buf, &addr->siso_addr.isoa_afi, buf_len-1); 3664*36381Ssklower addr->siso_addr.isoa_len = buf_len-1; 3665*36381Ssklower IFDEBUG(D_CADDR) 3666*36381Ssklower printf("FACILtoNSAP: isoa_len 0x%x\n", 3667*36381Ssklower addr->siso_addr.isoa_len); 3668*36381Ssklower ENDDEBUG 3669*36381Ssklower addr->siso_family = AF_ISO; 3670*36381Ssklower 3671*36381Ssklower addr->siso_tsuffix = 3672*36381Ssklower unmunge( ((caddr_t)&addr->siso_addr.t37_idi) + ADDR37_IDI_LEN , 1 ); 3673*36381Ssklower return 0; 3674*36381Ssklower } 3675*36381Ssklower 3676*36381Ssklower /* 3677*36381Ssklower * NAME: DTEtoNSAP() 3678*36381Ssklower * CALLED FROM: 3679*36381Ssklower * parse_facil() 3680*36381Ssklower * FUNCTION and ARGUMENTS: 3681*36381Ssklower * Creates a type 37 NSAP in the sockaddr_iso (addr) 3682*36381Ssklower * from a DTE address found at the (src_nibble)th nibble of 3683*36381Ssklower * the octet (src_octet), of length (src_nib_len). 3684*36381Ssklower * 3685*36381Ssklower * RETURNS: 3686*36381Ssklower * 0 if ok; E* otherwise. 3687*36381Ssklower */ 3688*36381Ssklower 3689*36381Ssklower Static int 3690*36381Ssklower DTEtoNSAP(addr, src_octet, src_nibble, src_nib_len) 3691*36381Ssklower struct sockaddr_iso *addr; 3692*36381Ssklower caddr_t src_octet; 3693*36381Ssklower int src_nibble, src_nib_len; 3694*36381Ssklower { 3695*36381Ssklower caddr_t dst_octet; 3696*36381Ssklower int pad_len; 3697*36381Ssklower int dst_nibble; 3698*36381Ssklower char first_nib; 3699*36381Ssklower static char *z_pad = "\0\0\0\0\0\0\0"; 3700*36381Ssklower static char *f_pad = "\021\021\021\021\021\021\021"; 3701*36381Ssklower 3702*36381Ssklower IFDEBUG(D_CADDR) 3703*36381Ssklower printf("DTEtoNSAP( 0x%x, 0x%x, 0x%x, 0x%x )\n", 3704*36381Ssklower src_octet, src_nibble, src_nib_len, addr ); 3705*36381Ssklower ENDDEBUG 3706*36381Ssklower 3707*36381Ssklower bzero( addr, sizeof(*addr)); 3708*36381Ssklower addr->siso_family = AF_ISO; 3709*36381Ssklower /* 3710*36381Ssklower * Coming from a DTE addr it's always type 37. 3711*36381Ssklower * src_octet <-- starting place in the NSAP-address of 3712*36381Ssklower * the embedded SNPA-address (x.121 addr or DTE addr). 3713*36381Ssklower */ 3714*36381Ssklower addr->siso_addr.isoa_afi = 0x37; 3715*36381Ssklower 3716*36381Ssklower /* first, figure out what pad to use and pad */ 3717*36381Ssklower 3718*36381Ssklower first_nib = (*src_octet) >> (SHIFT*(1-src_nibble)); 3719*36381Ssklower pad_len = (ADDR37_IDI_LEN<<1 - src_nib_len); 3720*36381Ssklower nibble_copy(first_nib? z_pad : f_pad, HIGH_NIBBLE, 3721*36381Ssklower (caddr_t) addr->siso_addr.t37_idi, HIGH_NIBBLE, pad_len); 3722*36381Ssklower 3723*36381Ssklower dst_octet += (pad_len>>1); 3724*36381Ssklower dst_nibble = 1-(pad_len & 0x1); 3725*36381Ssklower IFDEBUG(D_CADDR) 3726*36381Ssklower printf("DTEtoNSAP 2( 0x%x, 0x%x, 0x%x, 0x%x )\n", 3727*36381Ssklower dst_octet, dst_nibble, pad_len, src_nib_len ); 3728*36381Ssklower ENDDEBUG 3729*36381Ssklower 3730*36381Ssklower /* now copy the dte address */ 3731*36381Ssklower nibble_copy( src_octet, src_nibble, dst_octet, dst_nibble, src_nib_len); 3732*36381Ssklower 3733*36381Ssklower addr->siso_addr.isoa_len = ADDR37_IDI_LEN + ADDR37_DSP_LEN +1 /* for afi */; 3734*36381Ssklower /* kludge */ 3735*36381Ssklower 3736*36381Ssklower addr->siso_tsuffix = unmunge( 3737*36381Ssklower (caddr_t) &(addr->siso_addr.t37_idi[ADDR37_IDI_LEN]), HIGH_NIBBLE); 3738*36381Ssklower 3739*36381Ssklower IFDEBUG(D_CADDR) 3740*36381Ssklower printf("DTEtoNSAP 3 returning 0 tsuffix 0x%x\n", addr->siso_tsuffix); 3741*36381Ssklower ENDDEBUG 3742*36381Ssklower 3743*36381Ssklower return 0; /* ok */ 3744*36381Ssklower } 3745*36381Ssklower 3746*36381Ssklower /* 3747*36381Ssklower * FUNCTION and ARGUMENTS: 3748*36381Ssklower * parses (buf_len) bytes beginning at (buf) and finds 3749*36381Ssklower * a called nsap, a calling nsap, and protocol identifier. 3750*36381Ssklower * RETURNS: 3751*36381Ssklower * 0 if ok, E* otherwise. 3752*36381Ssklower */ 3753*36381Ssklower 3754*36381Ssklower Static int 3755*36381Ssklower parse_facil( buf, buf_len, called, calling, proto, peer_dte) 3756*36381Ssklower caddr_t buf; 3757*36381Ssklower u_char buf_len; /* in bytes */ 3758*36381Ssklower register struct sockaddr_iso *called, *calling; 3759*36381Ssklower int *proto; 3760*36381Ssklower struct dte_addr *peer_dte; 3761*36381Ssklower { 3762*36381Ssklower register int i; 3763*36381Ssklower caddr_t ptr; 3764*36381Ssklower caddr_t facil_len; 3765*36381Ssklower int facil_param_len; 3766*36381Ssklower struct sockaddr_iso *addr; 3767*36381Ssklower int addrs_not_parsed = (int)0xcb + (int)0xc9; 3768*36381Ssklower 3769*36381Ssklower IFDEBUG(D_CADDR) 3770*36381Ssklower printf("parse_facil( 0x%x, 0x%x, 0x%x, 0x%x, 0x%x )\n", 3771*36381Ssklower buf, buf_len, called, calling, *proto); 3772*36381Ssklower dump_buf(buf, buf_len); 3773*36381Ssklower ENDDEBUG 3774*36381Ssklower 3775*36381Ssklower /* find the beginnings of the facility fields in buf 3776*36381Ssklower * by skipping over the called & calling DTE addresses 3777*36381Ssklower * i <- # nibbles in called + # nibbles in calling 3778*36381Ssklower * i += 1 so that an odd nibble gets rounded up to even 3779*36381Ssklower * before dividing by 2, then divide by two to get # octets 3780*36381Ssklower */ 3781*36381Ssklower i = (int)(*buf >> 4) + (int)(*buf&0xf); 3782*36381Ssklower i++; 3783*36381Ssklower ptr = (caddr_t) (buf + (i>>1)); 3784*36381Ssklower /* now i is number of octets */ 3785*36381Ssklower 3786*36381Ssklower ptr ++; /* plus one for the DTE lengths byte */ 3787*36381Ssklower 3788*36381Ssklower /* ptr now is at facil_length field */ 3789*36381Ssklower facil_len = ptr++; 3790*36381Ssklower IFDEBUG(D_CADDR) 3791*36381Ssklower printf("parse_facils: facil length is 0x%x\n", (int) *facil_len); 3792*36381Ssklower ENDDEBUG 3793*36381Ssklower 3794*36381Ssklower while( ptr <= (caddr_t)(facil_len + (int)*facil_len) ) { 3795*36381Ssklower /* get NSAP addresses from facilities */ 3796*36381Ssklower switch (*ptr) { 3797*36381Ssklower case 0xcb: 3798*36381Ssklower facil_param_len = 0; 3799*36381Ssklower addr = calling; 3800*36381Ssklower addrs_not_parsed -= 0xcb; 3801*36381Ssklower break; 3802*36381Ssklower case 0xc9: 3803*36381Ssklower facil_param_len = 0; 3804*36381Ssklower addr = called; 3805*36381Ssklower addrs_not_parsed -= 0xc9; 3806*36381Ssklower break; 3807*36381Ssklower 3808*36381Ssklower /* from here to default are legit cases that I ignore */ 3809*36381Ssklower 3810*36381Ssklower /* variable length */ 3811*36381Ssklower case 0xca: /* end-to-end transit delay negot */ 3812*36381Ssklower case 0xc6: /* network user id */ 3813*36381Ssklower case 0xc5: /* charging info : indicating monetary unit */ 3814*36381Ssklower case 0xc2: /* charging info : indicating segment count */ 3815*36381Ssklower case 0xc1: /* charging info : indicating call duration */ 3816*36381Ssklower case 0xc4: /* RPOA extended format */ 3817*36381Ssklower case 0xc3: /* call redirection notification */ 3818*36381Ssklower facil_param_len = 0; 3819*36381Ssklower addr = (struct sockaddr_iso *)0; 3820*36381Ssklower break; 3821*36381Ssklower 3822*36381Ssklower /* 1 octet */ 3823*36381Ssklower case 0x0a: /* min. throughput class negot */ 3824*36381Ssklower case 0x02: /* throughput class */ 3825*36381Ssklower case 0x03: case 0x47: /* CUG shit */ 3826*36381Ssklower case 0x0b: /* expedited data negot */ 3827*36381Ssklower case 0x01: /* Fast select or reverse charging 3828*36381Ssklower (example of intelligent protocol design) */ 3829*36381Ssklower case 0x04: /* charging info : requesting service */ 3830*36381Ssklower case 0x08: /* called line addr modified notification */ 3831*36381Ssklower facil_param_len = 1; 3832*36381Ssklower addr = (struct sockaddr_iso *)0; 3833*36381Ssklower break; 3834*36381Ssklower 3835*36381Ssklower /* any 2 octets */ 3836*36381Ssklower case 0x42: /* pkt size */ 3837*36381Ssklower case 0x43: /* win size */ 3838*36381Ssklower case 0x44: /* RPOA basic format */ 3839*36381Ssklower case 0x41: /* bilateral CUG shit */ 3840*36381Ssklower case 0x49: /* transit delay selection and indication */ 3841*36381Ssklower facil_param_len = 2; 3842*36381Ssklower addr = (struct sockaddr_iso *)0; 3843*36381Ssklower break; 3844*36381Ssklower 3845*36381Ssklower /* don't have any 3 octets */ 3846*36381Ssklower /* 3847*36381Ssklower facil_param_len = 3; 3848*36381Ssklower */ 3849*36381Ssklower default: 3850*36381Ssklower ASSERT(0); 3851*36381Ssklower printf( 3852*36381Ssklower "BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n", 3853*36381Ssklower facil_len, *facil_len, 3854*36381Ssklower ptr, *ptr); 3855*36381Ssklower addr = (struct sockaddr_iso *)0; 3856*36381Ssklower /* facil that we don't handle */ 3857*36381Ssklower return E_CO_HLI_REJI; 3858*36381Ssklower } 3859*36381Ssklower ptr++; /* one for facil code */ 3860*36381Ssklower if(facil_param_len == 0) /* variable length */ 3861*36381Ssklower facil_param_len = (int)*ptr; /* 1 + the real facil param */ 3862*36381Ssklower if( addr && FACILtoNSAP(ptr+1, facil_param_len-1, addr) ) { 3863*36381Ssklower return E_CO_OSI_UNSAP; 3864*36381Ssklower } 3865*36381Ssklower ptr += facil_param_len; 3866*36381Ssklower } 3867*36381Ssklower if( addrs_not_parsed ) { 3868*36381Ssklower /* no facilities, get NSAP addresses from DTE addresses */ 3869*36381Ssklower register int ed, ing; 3870*36381Ssklower 3871*36381Ssklower ed = (int)(*buf&0xf); 3872*36381Ssklower if( ed == 0 ) { 3873*36381Ssklower panic("Called DTE address absent"); 3874*36381Ssklower } 3875*36381Ssklower DTEtoNSAP(called, (buf + 1)/*octet*/, 3876*36381Ssklower 1/*nibble*/, ed); 3877*36381Ssklower 3878*36381Ssklower ing = (int)(*buf >> 4); 3879*36381Ssklower if( ing == 0 ) { 3880*36381Ssklower printf("cons: panic: Calling DTE address absent"); 3881*36381Ssklower return E_CO_HLI_REJI; 3882*36381Ssklower } 3883*36381Ssklower nibble_copy((buf + (ed>>1)+1)/*octet*/, 1-(ed&0x1)/*nibble*/, 3884*36381Ssklower peer_dte->dtea_addr, HIGH_NIBBLE, ing); 3885*36381Ssklower DTEtoNSAP(calling, (buf + (ed>>1)+1)/*octet*/, 3886*36381Ssklower 1-(ed&0x1)/*nibble*/, ing); 3887*36381Ssklower 3888*36381Ssklower } 3889*36381Ssklower 3890*36381Ssklower ASSERT( ptr == (caddr_t)(facil_len + 1 + (int)*facil_len) ); 3891*36381Ssklower 3892*36381Ssklower /* 3893*36381Ssklower * now look for user data to find protocol identifier 3894*36381Ssklower */ 3895*36381Ssklower if( ptr == buf + buf_len ) { 3896*36381Ssklower /* no user data */ 3897*36381Ssklower *proto = ISOPROTO_TP; /* to proto id --> use TP */ 3898*36381Ssklower IFDEBUG(D_CADDR) 3899*36381Ssklower printf("NO USER DATA: use TP\n"); 3900*36381Ssklower ENDDEBUG 3901*36381Ssklower } else { 3902*36381Ssklower ASSERT ( ptr < buf + buf_len ); 3903*36381Ssklower if ( ptr >= buf + buf_len ) { 3904*36381Ssklower printf("ptr 0x%x buf 0x%x buf_len 0x%x buf+buf_len 0x%x\n", 3905*36381Ssklower ptr, buf, buf_len, buf+buf_len); 3906*36381Ssklower } 3907*36381Ssklower IFDEBUG(D_CADDR) 3908*36381Ssklower printf("proto byte 0x%x, value 0x%x\n", ptr, *ptr); 3909*36381Ssklower ENDDEBUG 3910*36381Ssklower switch(*ptr) { 3911*36381Ssklower case 0x81: 3912*36381Ssklower *proto = ISOPROTO_CLNP; 3913*36381Ssklower break; 3914*36381Ssklower case 0x0: 3915*36381Ssklower *proto = ISOPROTO_INACT_NL; 3916*36381Ssklower break; 3917*36381Ssklower case 'e': /* for EAN */ 3918*36381Ssklower *proto = ISOPROTO_TP; 3919*36381Ssklower /* can check for "an2" or can ignore the rest of the u data */ 3920*36381Ssklower break; 3921*36381Ssklower case 0xff: /* reserved for future extensions */ 3922*36381Ssklower *proto = ISOPROTO_X25; 3923*36381Ssklower break; 3924*36381Ssklower case 0x82: /* 9542 not implemented */ 3925*36381Ssklower case 0x84: /* 8878/A SNDCP not implemented */ 3926*36381Ssklower default: 3927*36381Ssklower *proto = -1; 3928*36381Ssklower return E_CO_HLI_PROTOID; 3929*36381Ssklower } 3930*36381Ssklower } 3931*36381Ssklower return 0; 3932*36381Ssklower } 3933*36381Ssklower 3934*36381Ssklower #endif NARGOXTWENTYFIVE > 0 3935