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