1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)tp_cons.c 7.8 (Berkeley) 05/09/91 8 */ 9 10 /*********************************************************** 11 Copyright IBM Corporation 1987 12 13 All Rights Reserved 14 15 Permission to use, copy, modify, and distribute this software and its 16 documentation for any purpose and without fee is hereby granted, 17 provided that the above copyright notice appear in all copies and that 18 both that copyright notice and this permission notice appear in 19 supporting documentation, and that the name of IBM not be 20 used in advertising or publicity pertaining to distribution of the 21 software without specific, written prior permission. 22 23 IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 24 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 25 IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 26 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 27 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 28 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 29 SOFTWARE. 30 31 ******************************************************************/ 32 33 /* 34 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 35 */ 36 /* 37 * ARGO TP 38 * $Header: tp_cons.c,v 5.6 88/11/18 17:27:13 nhall Exp $ 39 * $Source: /usr/argo/sys/netiso/RCS/tp_cons.c,v $ 40 * 41 * Here is where you find the iso- and cons-dependent code. We've tried 42 * keep all net-level and (primarily) address-family-dependent stuff 43 * out of the tp source, and everthing here is reached indirectly 44 * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 45 * (see tp_pcb.c). 46 * The routines here are: 47 * tpcons_input: pullup and call tp_input w/ correct arguments 48 * tpcons_output: package a pkt for cons given an isopcb & some data 49 * cons_chan_to_tpcb: find a tpcb based on the channel # 50 */ 51 52 #ifdef ISO 53 #ifdef TPCONS 54 55 #include "param.h" 56 #include "socket.h" 57 #include "domain.h" 58 #include "mbuf.h" 59 #include "errno.h" 60 #include "time.h" 61 62 #include "../net/if.h" 63 #include "../net/route.h" 64 65 #include "tp_param.h" 66 #include "argo_debug.h" 67 #include "tp_stat.h" 68 #include "tp_pcb.h" 69 #include "tp_trace.h" 70 #include "tp_stat.h" 71 #include "tp_tpdu.h" 72 #include "iso.h" 73 #include "iso_errno.h" 74 #include "iso_pcb.h" 75 #include "cons.h" 76 #include "tp_seq.h" 77 78 #undef FALSE 79 #undef TRUE 80 #include "../netccitt/x25.h" 81 #include "../netccitt/pk.h" 82 #include "../netccitt/pk_var.h" 83 84 #include "if_cons.c" 85 int tpcons_output(); 86 87 /* 88 * CALLED FROM: 89 * tp_route_to() for PRU_CONNECT 90 * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 91 * version of the previous procedure for X.25 92 */ 93 94 tpcons_pcbconnect(isop, nam) 95 struct isopcb *isop; 96 register struct mbuf *nam; 97 { 98 int error; 99 if (error = iso_pcbconnect(isop, nam)) 100 return error; 101 if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) { 102 IFDEBUG(D_CCONS) 103 printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error); 104 ENDDEBUG 105 return ENOBUFS; 106 } 107 if (error = cons_connect(isop)) { /* if it doesn't work */ 108 /* oh, dear, throw packet away */ 109 pk_disconnect((struct pklcd *)isop->isop_chan); 110 isop->isop_chan = 0; 111 } else 112 isop->isop_refcnt = 1; 113 return error; 114 } 115 116 117 /* 118 * CALLED FROM: 119 * cons 120 * FUNCTION and ARGUMENTS: 121 * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not - 122 */ 123 ProtoHook 124 tpcons_ctlinput(cmd, siso, isop) 125 int cmd; 126 struct sockaddr_iso *siso; 127 struct isopcb *isop; 128 { 129 switch (cmd) { 130 131 case PRC_CONS_SEND_DONE: 132 if( isop->isop_socket ) { /* tp 0 only */ 133 register struct tp_pcb *tpcb = 134 (struct tp_pcb *)isop->isop_socket->so_tpcb; 135 struct tp_event E; 136 int error = 0; 137 138 if( tpcb->tp_class == TP_CLASS_0 ) { 139 /* only if class is exactly class zero, not 140 * still in class negotiation 141 */ 142 /* fake an ack */ 143 register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1); 144 145 IFTRACE(D_DATA) 146 tptrace(TPPTmisc, "FAKE ACK seq cdt 1", 147 seq, 0,0,0); 148 ENDTRACE 149 IFDEBUG(D_DATA) 150 printf("FAKE ACK seq 0x%x cdt 1\n", seq ); 151 ENDDEBUG 152 E.ATTR(AK_TPDU).e_cdt = 1; 153 E.ATTR(AK_TPDU).e_seq = seq; 154 E.ATTR(AK_TPDU).e_subseq = 0; 155 E.ATTR(AK_TPDU).e_fcc_present = 0; 156 error = DoEvent(AK_TPDU); 157 if( error ) { 158 tpcb->tp_sock->so_error = error; 159 } 160 } /* else ignore it */ 161 } 162 break; 163 case PRC_ROUTEDEAD: 164 if( isop->isop_socket ) { /* tp 0 only */ 165 tpiso_reset(isop); 166 break; 167 } /* else drop through */ 168 default: 169 (void) tpclnp_ctlinput(cmd, siso); 170 break; 171 } 172 return 0; 173 } 174 175 /* 176 * CALLED FROM: 177 * cons's intr routine 178 * FUNCTION and ARGUMENTS: 179 * Take a packet (m) from cons, pullup m as required by tp, 180 * ignore the socket argument, and call tp_input. 181 * No return value. 182 */ 183 ProtoHook 184 tpcons_input(m, faddr, laddr, channel) 185 struct mbuf *m; 186 struct sockaddr_iso *faddr, *laddr; 187 caddr_t channel; 188 { 189 if( m == MNULL) 190 return 0; 191 192 m = (struct mbuf *)tp_inputprep(m); 193 194 IFDEBUG(D_TPINPUT) 195 printf("tpcons_input before tp_input(m 0x%x)\n", m); 196 dump_buf( m, 12+ m->m_len); 197 ENDDEBUG 198 tp_input(m, faddr, laddr, channel, tpcons_output, 0); 199 return 0; 200 } 201 202 203 /* 204 * CALLED FROM: 205 * tp_emit() 206 * FUNCTION and ARGUMENTS: 207 * Take a packet(m0) from tp and package it so that cons will accept it. 208 * This means filling in a few of the fields. 209 * inp is the isopcb structure; datalen is the length of the data in the 210 * mbuf string m0. 211 * RETURN VALUE: 212 * whatever (E*) is returned form the net layer output routine. 213 */ 214 215 int 216 tpcons_output(isop, m0, datalen, nochksum) 217 struct isopcb *isop; 218 struct mbuf *m0; 219 int datalen; 220 int nochksum; 221 { 222 register struct mbuf *m = m0; 223 int error; 224 225 IFDEBUG(D_EMIT) 226 printf( 227 "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n", 228 isop, m0, datalen, isop->isop_socket); 229 ENDDEBUG 230 if (m == MNULL) 231 return 0; 232 if ((m->m_flags & M_PKTHDR) == 0) { 233 MGETHDR(m, M_DONTWAIT, MT_DATA); 234 if (m == 0) 235 return ENOBUFS; 236 m->m_next = m0; 237 } 238 m->m_pkthdr.len = datalen; 239 error = pk_send(isop->isop_chan, m); 240 IncStat(ts_tpdu_sent); 241 242 return error; 243 } 244 /* 245 * CALLED FROM: 246 * tp_error_emit() 247 * FUNCTION and ARGUMENTS: 248 * Take a packet(m0) from tp and package it so that cons will accept it. 249 * chan is the cons channel to use; datalen is the length of the data in the 250 * mbuf string m0. 251 * RETURN VALUE: 252 * whatever (E*) is returned form the net layer output routine. 253 */ 254 255 int 256 tpcons_dg_output(chan, m0, datalen) 257 caddr_t chan; 258 struct mbuf *m0; 259 int datalen; 260 { 261 return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0); 262 } 263 #endif TPCONS 264 #endif ISO 265