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 $ 31*45900Ssklower * @(#)tp_cons.c 7.4 (Berkeley) 01/09/91 * 3236398Ssklower * 33*45900Ssklower * Here is where you find the iso- and cons-dependent code. We've tried 3436398Ssklower * keep all net-level and (primarily) address-family-dependent stuff 3536398Ssklower * out of the tp source, and everthing here is reached indirectly 3636398Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 3736398Ssklower * (see tp_pcb.c). 3836398Ssklower * The routines here are: 3936398Ssklower * tpcons_mtu: figure out what size tpdu to use 4036398Ssklower * tpcons_input: pullup and call tp_input w/ correct arguments 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 5036398Ssklower #ifdef ISO 51*45900Ssklower #ifdef TPCONS 5236398Ssklower 5337469Ssklower #include "param.h" 5436398Ssklower #include "socket.h" 5536398Ssklower #include "domain.h" 5636398Ssklower #include "mbuf.h" 5736398Ssklower #include "errno.h" 5836398Ssklower #include "time.h" 59*45900Ssklower 6036398Ssklower #include "../net/if.h" 61*45900Ssklower #include "../net/route.h" 6236398Ssklower 6337469Ssklower #include "tp_param.h" 6437469Ssklower #include "argo_debug.h" 6537469Ssklower #include "tp_stat.h" 6637469Ssklower #include "tp_pcb.h" 6737469Ssklower #include "tp_trace.h" 6837469Ssklower #include "tp_stat.h" 6937469Ssklower #include "tp_tpdu.h" 7037469Ssklower #include "iso.h" 71*45900Ssklower #include "iso_errno.h" 7237469Ssklower #include "iso_pcb.h" 7337469Ssklower #include "cons.h" 7437469Ssklower #include "tp_seq.h" 7536398Ssklower 76*45900Ssklower #undef FALSE 77*45900Ssklower #undef TRUE 78*45900Ssklower #include "../netccitt/x25.h" 79*45900Ssklower #include "../netccitt/pk.h" 80*45900Ssklower #include "../netccitt/pk_var.h" 81*45900Ssklower 82*45900Ssklower #include "if_cons.c" 8336398Ssklower int tpcons_output(); 8436398Ssklower 8536398Ssklower /* 8636398Ssklower * CALLED FROM: 87*45900Ssklower * tp_route_to() for PRU_CONNECT 88*45900Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 89*45900Ssklower * version of the previous procedure for X.25 90*45900Ssklower */ 91*45900Ssklower 92*45900Ssklower tpcons_pcbconnect(isop, nam) 93*45900Ssklower struct isopcb *isop; 94*45900Ssklower register struct mbuf *nam; 95*45900Ssklower { 96*45900Ssklower int error; 97*45900Ssklower if (error = iso_pcbconnect(isop, nam)) 98*45900Ssklower return error; 99*45900Ssklower if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) { 100*45900Ssklower IFDEBUG(D_CCONS) 101*45900Ssklower printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error); 102*45900Ssklower ENDDEBUG 103*45900Ssklower return ENOBUFS; 104*45900Ssklower } 105*45900Ssklower if (error = cons_connect(isop)) { /* if it doesn't work */ 106*45900Ssklower /* oh, dear, throw packet away */ 107*45900Ssklower pk_disconnect((struct pklcd *)isop->isop_chan); 108*45900Ssklower isop->isop_chan = 0; 109*45900Ssklower return error; 110*45900Ssklower } 111*45900Ssklower } 112*45900Ssklower 113*45900Ssklower 114*45900Ssklower /* 115*45900Ssklower * CALLED FROM: 11636398Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 11736398Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 11836398Ssklower * version of the previous procedure for X.25 11936398Ssklower */ 12036398Ssklower 12136398Ssklower void 12236398Ssklower tpcons_mtu(so, isop, size, negot) 12336398Ssklower struct socket *so; 12436398Ssklower struct isopcb *isop; 12536398Ssklower int *size; 12636398Ssklower u_char *negot; 12736398Ssklower { 12836398Ssklower register struct ifnet *ifp; 129*45900Ssklower register int i=0, isize; 13036398Ssklower int windowsize = so->so_rcv.sb_hiwat; 13136398Ssklower 13236398Ssklower IFTRACE(D_CONN) 13336398Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0); 13436398Ssklower ENDTRACE 13536398Ssklower 136*45900Ssklower isize = *size = 1 << *negot; 137*45900Ssklower #ifdef ancient_history 13836398Ssklower if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0) 13936398Ssklower return; 140*45900Ssklower #endif 14136398Ssklower 142*45900Ssklower if (isize > windowsize) { 143*45900Ssklower isize = windowsize; 14436398Ssklower i++; 14536398Ssklower } 146*45900Ssklower if (isize > ifp->if_mtu) { 147*45900Ssklower isize = ifp->if_mtu; 14836398Ssklower i++; 14936398Ssklower } 150*45900Ssklower if (i) { 15136398Ssklower /* size was changed by this routine - have to transform it to 15236398Ssklower * the log2 of size 15336398Ssklower */ 154*45900Ssklower for (i = TP_MIN_TPDUSIZE; i < TP_MAX_TPDUSIZE; i++) { 155*45900Ssklower if (isize < (1 << (1 + i))) 156*45900Ssklower break; 15736398Ssklower } 15836398Ssklower *negot = i; 159*45900Ssklower *size = 1 << i; 16036398Ssklower } 16136398Ssklower 16236398Ssklower IFDEBUG(D_CONN) 16336398Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 16436398Ssklower ifp->if_name, *size, *negot); 16536398Ssklower ENDDEBUG 16636398Ssklower IFTRACE(D_CONN) 16736398Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ", 16836398Ssklower *size, *negot, 0, 0); 16936398Ssklower ENDTRACE 17036398Ssklower } 17136398Ssklower 17236398Ssklower /* 17336398Ssklower * CALLED FROM: 17436398Ssklower * cons 17536398Ssklower * FUNCTION and ARGUMENTS: 17636398Ssklower * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not - 17736398Ssklower */ 17836398Ssklower ProtoHook 17936398Ssklower tpcons_ctlinput(cmd, siso, isop) 18036398Ssklower int cmd; 18136398Ssklower struct sockaddr_iso *siso; 18236398Ssklower struct isopcb *isop; 18336398Ssklower { 18436398Ssklower switch (cmd) { 18536398Ssklower 18636398Ssklower case PRC_CONS_SEND_DONE: 18736398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 18836398Ssklower register struct tp_pcb *tpcb = 18936398Ssklower (struct tp_pcb *)isop->isop_socket->so_tpcb; 19036398Ssklower struct tp_event E; 19136398Ssklower int error = 0; 19236398Ssklower 19336398Ssklower if( tpcb->tp_class == TP_CLASS_0 ) { 19436398Ssklower /* only if class is exactly class zero, not 19536398Ssklower * still in class negotiation 19636398Ssklower */ 19736398Ssklower /* fake an ack */ 19836398Ssklower register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1); 19936398Ssklower 20036398Ssklower IFTRACE(D_DATA) 20136398Ssklower tptrace(TPPTmisc, "FAKE ACK seq cdt 1", 20236398Ssklower seq, 0,0,0); 20336398Ssklower ENDTRACE 20436398Ssklower IFDEBUG(D_DATA) 20536398Ssklower printf("FAKE ACK seq 0x%x cdt 1\n", seq ); 20636398Ssklower ENDDEBUG 20736398Ssklower E.ATTR(AK_TPDU).e_cdt = 1; 20836398Ssklower E.ATTR(AK_TPDU).e_seq = seq; 20936398Ssklower E.ATTR(AK_TPDU).e_subseq = 0; 21036398Ssklower E.ATTR(AK_TPDU).e_fcc_present = 0; 21136398Ssklower error = DoEvent(AK_TPDU); 21236398Ssklower if( error ) { 21336398Ssklower tpcb->tp_sock->so_error = error; 21436398Ssklower } 21536398Ssklower } /* else ignore it */ 21636398Ssklower } 21736398Ssklower break; 21836398Ssklower case PRC_ROUTEDEAD: 21936398Ssklower if( isop->isop_socket ) { /* tp 0 only */ 22036398Ssklower tpiso_reset(isop); 22136398Ssklower break; 22236398Ssklower } /* else drop through */ 22336398Ssklower default: 22436398Ssklower (void) tpclnp_ctlinput(cmd, siso); 22536398Ssklower break; 22636398Ssklower } 22736398Ssklower return 0; 22836398Ssklower } 22936398Ssklower 23036398Ssklower /* 23136398Ssklower * CALLED FROM: 23236398Ssklower * cons's intr routine 23336398Ssklower * FUNCTION and ARGUMENTS: 23436398Ssklower * Take a packet (m) from cons, pullup m as required by tp, 23536398Ssklower * ignore the socket argument, and call tp_input. 23636398Ssklower * No return value. 23736398Ssklower */ 23836398Ssklower ProtoHook 239*45900Ssklower tpcons_input(m, faddr, laddr, channel) 24036398Ssklower struct mbuf *m; 24136398Ssklower struct sockaddr_iso *faddr, *laddr; 242*45900Ssklower caddr_t channel; 24336398Ssklower { 24436398Ssklower if( m == MNULL) 24536398Ssklower return 0; 24636398Ssklower 24736398Ssklower m = (struct mbuf *)tp_inputprep(m); 24836398Ssklower 24936398Ssklower IFDEBUG(D_TPINPUT) 25036398Ssklower printf("tpcons_input before tp_input(m 0x%x)\n", m); 25136398Ssklower dump_buf( m, 12+ m->m_len); 25236398Ssklower ENDDEBUG 25336398Ssklower tp_input(m, faddr, laddr, channel, tpcons_output); 25436398Ssklower return 0; 25536398Ssklower } 25636398Ssklower 25736398Ssklower 25836398Ssklower /* 25936398Ssklower * CALLED FROM: 26036398Ssklower * tp_emit() 26136398Ssklower * FUNCTION and ARGUMENTS: 26236398Ssklower * Take a packet(m0) from tp and package it so that cons will accept it. 26336398Ssklower * This means filling in a few of the fields. 26436398Ssklower * inp is the isopcb structure; datalen is the length of the data in the 26536398Ssklower * mbuf string m0. 26636398Ssklower * RETURN VALUE: 26736398Ssklower * whatever (E*) is returned form the net layer output routine. 26836398Ssklower */ 26936398Ssklower 27036398Ssklower int 27136398Ssklower tpcons_output(isop, m0, datalen, nochksum) 27236398Ssklower struct isopcb *isop; 27336398Ssklower struct mbuf *m0; 27436398Ssklower int datalen; 27536398Ssklower int nochksum; 27636398Ssklower { 277*45900Ssklower register struct mbuf *m = m0; 27836398Ssklower int error; 27936398Ssklower 28036398Ssklower IFDEBUG(D_EMIT) 28136398Ssklower printf( 28236398Ssklower "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n", 28336398Ssklower isop, m0, datalen, isop->isop_socket); 28436398Ssklower ENDDEBUG 285*45900Ssklower if (m == MNULL) 28636398Ssklower return 0; 287*45900Ssklower if (m->m_flags & M_PKTHDR == 0) { 288*45900Ssklower MGETHDR(m, M_DONTWAIT, MT_DATA); 289*45900Ssklower if (m == 0) 290*45900Ssklower return ENOBUFS; 291*45900Ssklower m->m_next = m0; 292*45900Ssklower } 293*45900Ssklower m->m_pkthdr.len = datalen; 294*45900Ssklower error = pk_send(isop->isop_chan, m); 29536398Ssklower IncStat(ts_tpdu_sent); 29636398Ssklower 29736398Ssklower return error; 29836398Ssklower } 29936398Ssklower /* 30036398Ssklower * CALLED FROM: 30136398Ssklower * tp_error_emit() 30236398Ssklower * FUNCTION and ARGUMENTS: 303*45900Ssklower * Take a packet(m0) from tp and package it so that cons will accept it. 304*45900Ssklower * chan is the cons channel to use; datalen is the length of the data in the 305*45900Ssklower * mbuf string m0. 30636398Ssklower * RETURN VALUE: 30736398Ssklower * whatever (E*) is returned form the net layer output routine. 30836398Ssklower */ 30936398Ssklower 31036398Ssklower int 311*45900Ssklower tpcons_dg_output(chan, m0, datalen) 312*45900Ssklower caddr_t chan; 31336398Ssklower struct mbuf *m0; 31436398Ssklower int datalen; 31536398Ssklower { 316*45900Ssklower return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0); 31736398Ssklower } 318*45900Ssklower #endif TPCONS 31936398Ssklower #endif ISO 320