136398Ssklower /*********************************************************** 236398Ssklower Copyright IBM Corporation 1987 336398Ssklower 436398Ssklower All Rights Reserved 536398Ssklower 636398Ssklower Permission to use, copy, modify, and distribute this software and its 736398Ssklower documentation for any purpose and without fee is hereby granted, 836398Ssklower provided that the above copyright notice appear in all copies and that 936398Ssklower both that copyright notice and this permission notice appear in 1036398Ssklower supporting documentation, and that the name of IBM not be 1136398Ssklower used in advertising or publicity pertaining to distribution of the 1236398Ssklower software without specific, written prior permission. 1336398Ssklower 1436398Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536398Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636398Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736398Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836398Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936398Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036398Ssklower SOFTWARE. 2136398Ssklower 2236398Ssklower ******************************************************************/ 2336398Ssklower 2436398Ssklower /* 2536398Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636398Ssklower */ 2736398Ssklower /* 2836398Ssklower * ARGO TP 2936398Ssklower * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $ 3036398Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $ 3136398Ssklower * 3236398Ssklower * Here is where you find the iso-dependent code. We've tried 3336398Ssklower * keep all net-level and (primarily) address-family-dependent stuff 3436398Ssklower * out of the tp source, and everthing here is reached indirectly 3536398Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 3636398Ssklower * (see tp_pcb.c). 3736398Ssklower * The routines here are: 3836398Ssklower * tpcons_mtu: figure out what size tpdu to use 3936398Ssklower * tpcons_input: pullup and call tp_input w/ correct arguments 4036398Ssklower * tpcons_output_dg: package a pkt for cons given 2 addresses & some data 4136398Ssklower * tpcons_output: package a pkt for cons given an isopcb & some data 4236398Ssklower * cons_chan_to_tpcb: find a tpcb based on the channel # 4336398Ssklower */ 4436398Ssklower 4536398Ssklower #ifndef lint 4636398Ssklower static char *rcsid = "$Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $"; 4736398Ssklower #endif lint 4836398Ssklower 4936398Ssklower #include "argoxtwentyfive.h" 5036398Ssklower 5136398Ssklower #ifdef ISO 5236398Ssklower #if NARGOXTWENTYFIVE > 0 5336398Ssklower 54*37469Ssklower #include "param.h" 5536398Ssklower #include "socket.h" 5636398Ssklower #include "domain.h" 5736398Ssklower #include "mbuf.h" 5836398Ssklower #include "errno.h" 5936398Ssklower #include "time.h" 6036398Ssklower #include "../net/if.h" 6136398Ssklower 62*37469Ssklower #include "tp_param.h" 63*37469Ssklower #include "argo_debug.h" 64*37469Ssklower #include "tp_stat.h" 65*37469Ssklower #include "tp_pcb.h" 66*37469Ssklower #include "tp_trace.h" 67*37469Ssklower #include "tp_stat.h" 68*37469Ssklower #include "tp_tpdu.h" 6936398Ssklower #include "../net/route.h" 70*37469Ssklower #include "iso.h" 71*37469Ssklower #include "iso_pcb.h" 72*37469Ssklower #include "cons.h" 73*37469Ssklower #include "tp_seq.h" 7436398Ssklower 7536398Ssklower int tpcons_output(); 7636398Ssklower 7736398Ssklower /* 7836398Ssklower * CALLED FROM: 7936398Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 8036398Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 8136398Ssklower * version of the previous procedure for X.25 8236398Ssklower */ 8336398Ssklower 8436398Ssklower void 8536398Ssklower tpcons_mtu(so, isop, size, negot) 8636398Ssklower struct socket *so; 8736398Ssklower struct isopcb *isop; 8836398Ssklower int *size; 8936398Ssklower u_char *negot; 9036398Ssklower { 9136398Ssklower register struct ifnet *ifp; 9236398Ssklower register int i=0; 9336398Ssklower int windowsize = so->so_rcv.sb_hiwat; 9436398Ssklower struct ifnet *iso_routeifp(); 9536398Ssklower 9636398Ssklower IFTRACE(D_CONN) 9736398Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0); 9836398Ssklower ENDTRACE 9936398Ssklower 10036398Ssklower 10136398Ssklower *size = 1 << *negot; 10236398Ssklower if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0) 10336398Ssklower return; 10436398Ssklower 10536398Ssklower if( *size > windowsize ) { 10636398Ssklower *size = windowsize; 10736398Ssklower i++; 10836398Ssklower } 10936398Ssklower 11036398Ssklower if(*size > ifp->if_mtu) { 11136398Ssklower *size = ifp->if_mtu ; 11236398Ssklower i++; 11336398Ssklower } 11436398Ssklower if(i) { 11536398Ssklower /* size was changed by this routine - have to transform it to 11636398Ssklower * the log2 of size 11736398Ssklower */ 11836398Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++) 11936398Ssklower ; 12036398Ssklower /* are we on the same LAN? if so, negotiate one tpdu size larger, 12136398Ssklower * and actually send the real mtu size 12236398Ssklower */ 12336398Ssklower /* PHASE2: replace with iso_on_localnet(&isop->isop_faddr); 12436398Ssklower */ 12536398Ssklower if ( !iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) ) { 12636398Ssklower i--; 12736398Ssklower *size = 1<<i; 12836398Ssklower } 12936398Ssklower *negot = i; 13036398Ssklower } 13136398Ssklower 13236398Ssklower IFDEBUG(D_CONN) 13336398Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 13436398Ssklower ifp->if_name, *size, *negot); 13536398Ssklower ENDDEBUG 13636398Ssklower IFTRACE(D_CONN) 13736398Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ", 13836398Ssklower *size, *negot, 0, 0); 13936398Ssklower ENDTRACE 14036398Ssklower } 14136398Ssklower 14236398Ssklower /* 14336398Ssklower * CALLED FROM: 14436398Ssklower * cons 14536398Ssklower * FUNCTION and ARGUMENTS: 14636398Ssklower * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not - 14736398Ssklower */ 14836398Ssklower ProtoHook 14936398Ssklower tpcons_ctlinput(cmd, siso, isop) 15036398Ssklower int cmd; 15136398Ssklower struct sockaddr_iso *siso; 15236398Ssklower struct isopcb *isop; 15336398Ssklower { 15436398Ssklower switch (cmd) { 15536398Ssklower 15636398Ssklower case PRC_CONS_SEND_DONE: 15736398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 15836398Ssklower register struct tp_pcb *tpcb = 15936398Ssklower (struct tp_pcb *)isop->isop_socket->so_tpcb; 16036398Ssklower struct tp_event E; 16136398Ssklower int error = 0; 16236398Ssklower 16336398Ssklower if( tpcb->tp_class == TP_CLASS_0 ) { 16436398Ssklower /* only if class is exactly class zero, not 16536398Ssklower * still in class negotiation 16636398Ssklower */ 16736398Ssklower /* fake an ack */ 16836398Ssklower register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1); 16936398Ssklower 17036398Ssklower IFTRACE(D_DATA) 17136398Ssklower tptrace(TPPTmisc, "FAKE ACK seq cdt 1", 17236398Ssklower seq, 0,0,0); 17336398Ssklower ENDTRACE 17436398Ssklower IFDEBUG(D_DATA) 17536398Ssklower printf("FAKE ACK seq 0x%x cdt 1\n", seq ); 17636398Ssklower ENDDEBUG 17736398Ssklower E.ATTR(AK_TPDU).e_cdt = 1; 17836398Ssklower E.ATTR(AK_TPDU).e_seq = seq; 17936398Ssklower E.ATTR(AK_TPDU).e_subseq = 0; 18036398Ssklower E.ATTR(AK_TPDU).e_fcc_present = 0; 18136398Ssklower error = DoEvent(AK_TPDU); 18236398Ssklower if( error ) { 18336398Ssklower tpcb->tp_sock->so_error = error; 18436398Ssklower } 18536398Ssklower } /* else ignore it */ 18636398Ssklower } 18736398Ssklower break; 18836398Ssklower case PRC_ROUTEDEAD: 18936398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 19036398Ssklower tpiso_reset(isop); 19136398Ssklower break; 19236398Ssklower } /* else drop through */ 19336398Ssklower default: 19436398Ssklower (void) tpclnp_ctlinput(cmd, siso); 19536398Ssklower break; 19636398Ssklower } 19736398Ssklower return 0; 19836398Ssklower } 19936398Ssklower 20036398Ssklower /* 20136398Ssklower * CALLED FROM: 20236398Ssklower * cons's intr routine 20336398Ssklower * FUNCTION and ARGUMENTS: 20436398Ssklower * Take a packet (m) from cons, pullup m as required by tp, 20536398Ssklower * ignore the socket argument, and call tp_input. 20636398Ssklower * No return value. 20736398Ssklower */ 20836398Ssklower ProtoHook 20936398Ssklower tpcons_input(m, faddr, laddr, so, channel) 21036398Ssklower struct mbuf *m; 21136398Ssklower struct sockaddr_iso *faddr, *laddr; 21236398Ssklower struct socket *so; /* not used */ 21336398Ssklower int channel; 21436398Ssklower { 21536398Ssklower if( m == MNULL) 21636398Ssklower return 0; 21736398Ssklower 21836398Ssklower m = (struct mbuf *)tp_inputprep(m); 21936398Ssklower 22036398Ssklower IFDEBUG(D_TPINPUT) 22136398Ssklower printf("tpcons_input before tp_input(m 0x%x)\n", m); 22236398Ssklower dump_buf( m, 12+ m->m_len); 22336398Ssklower ENDDEBUG 22436398Ssklower tp_input(m, faddr, laddr, channel, tpcons_output); 22536398Ssklower return 0; 22636398Ssklower } 22736398Ssklower 22836398Ssklower 22936398Ssklower /* 23036398Ssklower * CALLED FROM: 23136398Ssklower * tp_emit() 23236398Ssklower * FUNCTION and ARGUMENTS: 23336398Ssklower * Take a packet(m0) from tp and package it so that cons will accept it. 23436398Ssklower * This means filling in a few of the fields. 23536398Ssklower * inp is the isopcb structure; datalen is the length of the data in the 23636398Ssklower * mbuf string m0. 23736398Ssklower * RETURN VALUE: 23836398Ssklower * whatever (E*) is returned form the net layer output routine. 23936398Ssklower */ 24036398Ssklower 24136398Ssklower int 24236398Ssklower tpcons_output(isop, m0, datalen, nochksum) 24336398Ssklower struct isopcb *isop; 24436398Ssklower struct mbuf *m0; 24536398Ssklower int datalen; 24636398Ssklower int nochksum; 24736398Ssklower { 24836398Ssklower struct tp_pcb *tpcb; 24936398Ssklower int error; 25036398Ssklower 25136398Ssklower IFDEBUG(D_EMIT) 25236398Ssklower printf( 25336398Ssklower "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n", 25436398Ssklower isop, m0, datalen, isop->isop_socket); 25536398Ssklower ENDDEBUG 25636398Ssklower if(m0 == MNULL) 25736398Ssklower return 0; 25836398Ssklower ASSERT(m0->m_len > 0); 25936398Ssklower tpcb = (struct tp_pcb *)isop->isop_socket->so_tpcb; 26036398Ssklower 26136398Ssklower /* check is for class EQUAL to 4: if still in negotiation stage, 26236398Ssklower * cannot send as dgm 26336398Ssklower */ 26436398Ssklower error = cons_output(isop, m0, datalen, (tpcb->tp_class == TP_CLASS_4)); 26536398Ssklower IncStat(ts_tpdu_sent); 26636398Ssklower 26736398Ssklower IFTRACE(D_EMIT) 26836398Ssklower tptrace( TPPTmisc, 26936398Ssklower "tpcons_output( isop m isdgm cons_output returns", 27036398Ssklower isop, m0, (tpcb->tp_class == TP_CLASS_4), error ); 27136398Ssklower ENDTRACE 27236398Ssklower return error; 27336398Ssklower } 27436398Ssklower 27536398Ssklower /* 27636398Ssklower * CALLED FROM: 27736398Ssklower * tp_error_emit() 27836398Ssklower * FUNCTION and ARGUMENTS: 27936398Ssklower * This is a copy of tpcons_output that takes the addresses 28036398Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 28136398Ssklower * don't have an iso_pcb with which to call the normal output rtn. 28236398Ssklower * RETURN VALUE: 28336398Ssklower * ENOBUFS or 28436398Ssklower * whatever (E*) is returned form the net layer output routine. 28536398Ssklower */ 28636398Ssklower 28736398Ssklower int 28836398Ssklower tpcons_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 28936398Ssklower struct iso_addr *laddr, *faddr; 29036398Ssklower struct mbuf *m0; 29136398Ssklower int datalen; 29236398Ssklower struct route *ro; 29336398Ssklower int nochksum; 29436398Ssklower { 29536398Ssklower IFDEBUG(D_TPISO) 29636398Ssklower printf("PANIC: tpcons_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 29736398Ssklower ENDDEBUG 29836398Ssklower 29936398Ssklower return 0; 30036398Ssklower } 30136398Ssklower 30236398Ssklower struct tp_pcb * 30336398Ssklower cons_chan_to_tpcb(chan) 30436398Ssklower int chan; 30536398Ssklower { 30636398Ssklower extern struct isopcb *cons_chan_to_pcb (); 30736398Ssklower #ifdef ARGO_DEBUG 30836398Ssklower struct isopcb *isop = cons_chan_to_pcb (chan, -1); 30936398Ssklower #else ARGO_DEBUG 31036398Ssklower struct isopcb *isop = cons_chan_to_pcb (chan); 31136398Ssklower #endif ARGO_DEBUG 31236398Ssklower 31336398Ssklower IFTRACE(D_CONN) 31436398Ssklower tptrace(TPPTmisc, "vc->tpcb(chan) socket", 31536398Ssklower chan, isop->isop_socket, 0, 0); 31636398Ssklower ENDTRACE 31736398Ssklower IFDEBUG(D_CONN) 31836398Ssklower printf("vc->tpcb(0x%x) socket 0x%x, *ISOP dump:", 31936398Ssklower chan, isop->isop_socket); 32036398Ssklower dump_buf( isop, 32); 32136398Ssklower ENDDEBUG 32236398Ssklower if( isop->isop_socket == (struct socket *)0 ) 32336398Ssklower return (struct tp_pcb *) 0; 32436398Ssklower else { 32536398Ssklower return (struct tp_pcb *)(isop->isop_socket->so_tpcb); 32636398Ssklower } 32736398Ssklower } 32836398Ssklower #endif NARGOXTWENTYFIVE 32936398Ssklower #endif ISO 330