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