1*36398Ssklower /*********************************************************** 2*36398Ssklower Copyright IBM Corporation 1987 3*36398Ssklower 4*36398Ssklower All Rights Reserved 5*36398Ssklower 6*36398Ssklower Permission to use, copy, modify, and distribute this software and its 7*36398Ssklower documentation for any purpose and without fee is hereby granted, 8*36398Ssklower provided that the above copyright notice appear in all copies and that 9*36398Ssklower both that copyright notice and this permission notice appear in 10*36398Ssklower supporting documentation, and that the name of IBM not be 11*36398Ssklower used in advertising or publicity pertaining to distribution of the 12*36398Ssklower software without specific, written prior permission. 13*36398Ssklower 14*36398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36398Ssklower SOFTWARE. 21*36398Ssklower 22*36398Ssklower ******************************************************************/ 23*36398Ssklower 24*36398Ssklower /* 25*36398Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36398Ssklower */ 27*36398Ssklower /* 28*36398Ssklower * ARGO TP 29*36398Ssklower * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $ 30*36398Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $ 31*36398Ssklower * 32*36398Ssklower * Here is where you find the iso-dependent code. We've tried 33*36398Ssklower * keep all net-level and (primarily) address-family-dependent stuff 34*36398Ssklower * out of the tp source, and everthing here is reached indirectly 35*36398Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 36*36398Ssklower * (see tp_pcb.c). 37*36398Ssklower * The routines here are: 38*36398Ssklower * tpcons_mtu: figure out what size tpdu to use 39*36398Ssklower * tpcons_input: pullup and call tp_input w/ correct arguments 40*36398Ssklower * tpcons_output_dg: package a pkt for cons given 2 addresses & some data 41*36398Ssklower * tpcons_output: package a pkt for cons given an isopcb & some data 42*36398Ssklower * cons_chan_to_tpcb: find a tpcb based on the channel # 43*36398Ssklower */ 44*36398Ssklower 45*36398Ssklower #ifndef lint 46*36398Ssklower static char *rcsid = "$Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $"; 47*36398Ssklower #endif lint 48*36398Ssklower 49*36398Ssklower #include "argoxtwentyfive.h" 50*36398Ssklower 51*36398Ssklower #ifdef ISO 52*36398Ssklower #if NARGOXTWENTYFIVE > 0 53*36398Ssklower 54*36398Ssklower #include "types.h" 55*36398Ssklower #include "socket.h" 56*36398Ssklower #include "domain.h" 57*36398Ssklower #include "mbuf.h" 58*36398Ssklower #include "errno.h" 59*36398Ssklower #include "time.h" 60*36398Ssklower #include "../net/if.h" 61*36398Ssklower 62*36398Ssklower #include "../netiso/tp_param.h" 63*36398Ssklower #include "../netiso/argo_debug.h" 64*36398Ssklower #include "../netiso/tp_stat.h" 65*36398Ssklower #include "../netiso/tp_pcb.h" 66*36398Ssklower #include "../netiso/tp_trace.h" 67*36398Ssklower #include "../netiso/tp_stat.h" 68*36398Ssklower #include "../netiso/tp_tpdu.h" 69*36398Ssklower #include "../net/route.h" 70*36398Ssklower #include "../netiso/iso.h" 71*36398Ssklower #include "../netiso/iso_pcb.h" 72*36398Ssklower #include "../netiso/cons.h" 73*36398Ssklower #include "../netiso/tp_seq.h" 74*36398Ssklower 75*36398Ssklower int tpcons_output(); 76*36398Ssklower 77*36398Ssklower /* 78*36398Ssklower * CALLED FROM: 79*36398Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 80*36398Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 81*36398Ssklower * version of the previous procedure for X.25 82*36398Ssklower */ 83*36398Ssklower 84*36398Ssklower void 85*36398Ssklower tpcons_mtu(so, isop, size, negot) 86*36398Ssklower struct socket *so; 87*36398Ssklower struct isopcb *isop; 88*36398Ssklower int *size; 89*36398Ssklower u_char *negot; 90*36398Ssklower { 91*36398Ssklower register struct ifnet *ifp; 92*36398Ssklower register int i=0; 93*36398Ssklower int windowsize = so->so_rcv.sb_hiwat; 94*36398Ssklower struct ifnet *iso_routeifp(); 95*36398Ssklower 96*36398Ssklower IFTRACE(D_CONN) 97*36398Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0); 98*36398Ssklower ENDTRACE 99*36398Ssklower 100*36398Ssklower 101*36398Ssklower *size = 1 << *negot; 102*36398Ssklower if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0) 103*36398Ssklower return; 104*36398Ssklower 105*36398Ssklower if( *size > windowsize ) { 106*36398Ssklower *size = windowsize; 107*36398Ssklower i++; 108*36398Ssklower } 109*36398Ssklower 110*36398Ssklower if(*size > ifp->if_mtu) { 111*36398Ssklower *size = ifp->if_mtu ; 112*36398Ssklower i++; 113*36398Ssklower } 114*36398Ssklower if(i) { 115*36398Ssklower /* size was changed by this routine - have to transform it to 116*36398Ssklower * the log2 of size 117*36398Ssklower */ 118*36398Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++) 119*36398Ssklower ; 120*36398Ssklower /* are we on the same LAN? if so, negotiate one tpdu size larger, 121*36398Ssklower * and actually send the real mtu size 122*36398Ssklower */ 123*36398Ssklower /* PHASE2: replace with iso_on_localnet(&isop->isop_faddr); 124*36398Ssklower */ 125*36398Ssklower if ( !iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) ) { 126*36398Ssklower i--; 127*36398Ssklower *size = 1<<i; 128*36398Ssklower } 129*36398Ssklower *negot = i; 130*36398Ssklower } 131*36398Ssklower 132*36398Ssklower IFDEBUG(D_CONN) 133*36398Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 134*36398Ssklower ifp->if_name, *size, *negot); 135*36398Ssklower ENDDEBUG 136*36398Ssklower IFTRACE(D_CONN) 137*36398Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ", 138*36398Ssklower *size, *negot, 0, 0); 139*36398Ssklower ENDTRACE 140*36398Ssklower } 141*36398Ssklower 142*36398Ssklower /* 143*36398Ssklower * CALLED FROM: 144*36398Ssklower * cons 145*36398Ssklower * FUNCTION and ARGUMENTS: 146*36398Ssklower * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not - 147*36398Ssklower */ 148*36398Ssklower ProtoHook 149*36398Ssklower tpcons_ctlinput(cmd, siso, isop) 150*36398Ssklower int cmd; 151*36398Ssklower struct sockaddr_iso *siso; 152*36398Ssklower struct isopcb *isop; 153*36398Ssklower { 154*36398Ssklower switch (cmd) { 155*36398Ssklower 156*36398Ssklower case PRC_CONS_SEND_DONE: 157*36398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 158*36398Ssklower register struct tp_pcb *tpcb = 159*36398Ssklower (struct tp_pcb *)isop->isop_socket->so_tpcb; 160*36398Ssklower struct tp_event E; 161*36398Ssklower int error = 0; 162*36398Ssklower 163*36398Ssklower if( tpcb->tp_class == TP_CLASS_0 ) { 164*36398Ssklower /* only if class is exactly class zero, not 165*36398Ssklower * still in class negotiation 166*36398Ssklower */ 167*36398Ssklower /* fake an ack */ 168*36398Ssklower register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1); 169*36398Ssklower 170*36398Ssklower IFTRACE(D_DATA) 171*36398Ssklower tptrace(TPPTmisc, "FAKE ACK seq cdt 1", 172*36398Ssklower seq, 0,0,0); 173*36398Ssklower ENDTRACE 174*36398Ssklower IFDEBUG(D_DATA) 175*36398Ssklower printf("FAKE ACK seq 0x%x cdt 1\n", seq ); 176*36398Ssklower ENDDEBUG 177*36398Ssklower E.ATTR(AK_TPDU).e_cdt = 1; 178*36398Ssklower E.ATTR(AK_TPDU).e_seq = seq; 179*36398Ssklower E.ATTR(AK_TPDU).e_subseq = 0; 180*36398Ssklower E.ATTR(AK_TPDU).e_fcc_present = 0; 181*36398Ssklower error = DoEvent(AK_TPDU); 182*36398Ssklower if( error ) { 183*36398Ssklower tpcb->tp_sock->so_error = error; 184*36398Ssklower } 185*36398Ssklower } /* else ignore it */ 186*36398Ssklower } 187*36398Ssklower break; 188*36398Ssklower case PRC_ROUTEDEAD: 189*36398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 190*36398Ssklower tpiso_reset(isop); 191*36398Ssklower break; 192*36398Ssklower } /* else drop through */ 193*36398Ssklower default: 194*36398Ssklower (void) tpclnp_ctlinput(cmd, siso); 195*36398Ssklower break; 196*36398Ssklower } 197*36398Ssklower return 0; 198*36398Ssklower } 199*36398Ssklower 200*36398Ssklower /* 201*36398Ssklower * CALLED FROM: 202*36398Ssklower * cons's intr routine 203*36398Ssklower * FUNCTION and ARGUMENTS: 204*36398Ssklower * Take a packet (m) from cons, pullup m as required by tp, 205*36398Ssklower * ignore the socket argument, and call tp_input. 206*36398Ssklower * No return value. 207*36398Ssklower */ 208*36398Ssklower ProtoHook 209*36398Ssklower tpcons_input(m, faddr, laddr, so, channel) 210*36398Ssklower struct mbuf *m; 211*36398Ssklower struct sockaddr_iso *faddr, *laddr; 212*36398Ssklower struct socket *so; /* not used */ 213*36398Ssklower int channel; 214*36398Ssklower { 215*36398Ssklower if( m == MNULL) 216*36398Ssklower return 0; 217*36398Ssklower 218*36398Ssklower m = (struct mbuf *)tp_inputprep(m); 219*36398Ssklower 220*36398Ssklower IFDEBUG(D_TPINPUT) 221*36398Ssklower printf("tpcons_input before tp_input(m 0x%x)\n", m); 222*36398Ssklower dump_buf( m, 12+ m->m_len); 223*36398Ssklower ENDDEBUG 224*36398Ssklower tp_input(m, faddr, laddr, channel, tpcons_output); 225*36398Ssklower return 0; 226*36398Ssklower } 227*36398Ssklower 228*36398Ssklower 229*36398Ssklower /* 230*36398Ssklower * CALLED FROM: 231*36398Ssklower * tp_emit() 232*36398Ssklower * FUNCTION and ARGUMENTS: 233*36398Ssklower * Take a packet(m0) from tp and package it so that cons will accept it. 234*36398Ssklower * This means filling in a few of the fields. 235*36398Ssklower * inp is the isopcb structure; datalen is the length of the data in the 236*36398Ssklower * mbuf string m0. 237*36398Ssklower * RETURN VALUE: 238*36398Ssklower * whatever (E*) is returned form the net layer output routine. 239*36398Ssklower */ 240*36398Ssklower 241*36398Ssklower int 242*36398Ssklower tpcons_output(isop, m0, datalen, nochksum) 243*36398Ssklower struct isopcb *isop; 244*36398Ssklower struct mbuf *m0; 245*36398Ssklower int datalen; 246*36398Ssklower int nochksum; 247*36398Ssklower { 248*36398Ssklower struct tp_pcb *tpcb; 249*36398Ssklower int error; 250*36398Ssklower 251*36398Ssklower IFDEBUG(D_EMIT) 252*36398Ssklower printf( 253*36398Ssklower "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n", 254*36398Ssklower isop, m0, datalen, isop->isop_socket); 255*36398Ssklower ENDDEBUG 256*36398Ssklower if(m0 == MNULL) 257*36398Ssklower return 0; 258*36398Ssklower ASSERT(m0->m_len > 0); 259*36398Ssklower tpcb = (struct tp_pcb *)isop->isop_socket->so_tpcb; 260*36398Ssklower 261*36398Ssklower /* check is for class EQUAL to 4: if still in negotiation stage, 262*36398Ssklower * cannot send as dgm 263*36398Ssklower */ 264*36398Ssklower error = cons_output(isop, m0, datalen, (tpcb->tp_class == TP_CLASS_4)); 265*36398Ssklower IncStat(ts_tpdu_sent); 266*36398Ssklower 267*36398Ssklower IFTRACE(D_EMIT) 268*36398Ssklower tptrace( TPPTmisc, 269*36398Ssklower "tpcons_output( isop m isdgm cons_output returns", 270*36398Ssklower isop, m0, (tpcb->tp_class == TP_CLASS_4), error ); 271*36398Ssklower ENDTRACE 272*36398Ssklower return error; 273*36398Ssklower } 274*36398Ssklower 275*36398Ssklower /* 276*36398Ssklower * CALLED FROM: 277*36398Ssklower * tp_error_emit() 278*36398Ssklower * FUNCTION and ARGUMENTS: 279*36398Ssklower * This is a copy of tpcons_output that takes the addresses 280*36398Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 281*36398Ssklower * don't have an iso_pcb with which to call the normal output rtn. 282*36398Ssklower * RETURN VALUE: 283*36398Ssklower * ENOBUFS or 284*36398Ssklower * whatever (E*) is returned form the net layer output routine. 285*36398Ssklower */ 286*36398Ssklower 287*36398Ssklower int 288*36398Ssklower tpcons_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 289*36398Ssklower struct iso_addr *laddr, *faddr; 290*36398Ssklower struct mbuf *m0; 291*36398Ssklower int datalen; 292*36398Ssklower struct route *ro; 293*36398Ssklower int nochksum; 294*36398Ssklower { 295*36398Ssklower IFDEBUG(D_TPISO) 296*36398Ssklower printf("PANIC: tpcons_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 297*36398Ssklower ENDDEBUG 298*36398Ssklower 299*36398Ssklower return 0; 300*36398Ssklower } 301*36398Ssklower 302*36398Ssklower struct tp_pcb * 303*36398Ssklower cons_chan_to_tpcb(chan) 304*36398Ssklower int chan; 305*36398Ssklower { 306*36398Ssklower extern struct isopcb *cons_chan_to_pcb (); 307*36398Ssklower #ifdef ARGO_DEBUG 308*36398Ssklower struct isopcb *isop = cons_chan_to_pcb (chan, -1); 309*36398Ssklower #else ARGO_DEBUG 310*36398Ssklower struct isopcb *isop = cons_chan_to_pcb (chan); 311*36398Ssklower #endif ARGO_DEBUG 312*36398Ssklower 313*36398Ssklower IFTRACE(D_CONN) 314*36398Ssklower tptrace(TPPTmisc, "vc->tpcb(chan) socket", 315*36398Ssklower chan, isop->isop_socket, 0, 0); 316*36398Ssklower ENDTRACE 317*36398Ssklower IFDEBUG(D_CONN) 318*36398Ssklower printf("vc->tpcb(0x%x) socket 0x%x, *ISOP dump:", 319*36398Ssklower chan, isop->isop_socket); 320*36398Ssklower dump_buf( isop, 32); 321*36398Ssklower ENDDEBUG 322*36398Ssklower if( isop->isop_socket == (struct socket *)0 ) 323*36398Ssklower return (struct tp_pcb *) 0; 324*36398Ssklower else { 325*36398Ssklower return (struct tp_pcb *)(isop->isop_socket->so_tpcb); 326*36398Ssklower } 327*36398Ssklower } 328*36398Ssklower #endif NARGOXTWENTYFIVE 329*36398Ssklower #endif ISO 330