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.4 (Berkeley) 01/09/91 * 32 * 33 * Here is where you find the iso- and cons-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: 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 50 #ifdef ISO 51 #ifdef TPCONS 52 53 #include "param.h" 54 #include "socket.h" 55 #include "domain.h" 56 #include "mbuf.h" 57 #include "errno.h" 58 #include "time.h" 59 60 #include "../net/if.h" 61 #include "../net/route.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 "iso.h" 71 #include "iso_errno.h" 72 #include "iso_pcb.h" 73 #include "cons.h" 74 #include "tp_seq.h" 75 76 #undef FALSE 77 #undef TRUE 78 #include "../netccitt/x25.h" 79 #include "../netccitt/pk.h" 80 #include "../netccitt/pk_var.h" 81 82 #include "if_cons.c" 83 int tpcons_output(); 84 85 /* 86 * CALLED FROM: 87 * tp_route_to() for PRU_CONNECT 88 * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 89 * version of the previous procedure for X.25 90 */ 91 92 tpcons_pcbconnect(isop, nam) 93 struct isopcb *isop; 94 register struct mbuf *nam; 95 { 96 int error; 97 if (error = iso_pcbconnect(isop, nam)) 98 return error; 99 if ((isop->isop_chan = (caddr_t) pk_attach((struct socket *)0)) == 0) { 100 IFDEBUG(D_CCONS) 101 printf("tpcons_pcbconnect: no pklcd; returns 0x%x\n", error); 102 ENDDEBUG 103 return ENOBUFS; 104 } 105 if (error = cons_connect(isop)) { /* if it doesn't work */ 106 /* oh, dear, throw packet away */ 107 pk_disconnect((struct pklcd *)isop->isop_chan); 108 isop->isop_chan = 0; 109 return error; 110 } 111 } 112 113 114 /* 115 * CALLED FROM: 116 * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 117 * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 118 * version of the previous procedure for X.25 119 */ 120 121 void 122 tpcons_mtu(so, isop, size, negot) 123 struct socket *so; 124 struct isopcb *isop; 125 int *size; 126 u_char *negot; 127 { 128 register struct ifnet *ifp; 129 register int i=0, isize; 130 int windowsize = so->so_rcv.sb_hiwat; 131 132 IFTRACE(D_CONN) 133 tptrace(TPPTmisc, "ENTER GET MTU: size negot ",*size, *negot, 0, 0); 134 ENDTRACE 135 136 isize = *size = 1 << *negot; 137 #ifdef ancient_history 138 if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0) 139 return; 140 #endif 141 142 if (isize > windowsize) { 143 isize = windowsize; 144 i++; 145 } 146 if (isize > ifp->if_mtu) { 147 isize = ifp->if_mtu; 148 i++; 149 } 150 if (i) { 151 /* size was changed by this routine - have to transform it to 152 * the log2 of size 153 */ 154 for (i = TP_MIN_TPDUSIZE; i < TP_MAX_TPDUSIZE; i++) { 155 if (isize < (1 << (1 + i))) 156 break; 157 } 158 *negot = i; 159 *size = 1 << i; 160 } 161 162 IFDEBUG(D_CONN) 163 printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 164 ifp->if_name, *size, *negot); 165 ENDDEBUG 166 IFTRACE(D_CONN) 167 tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot ", 168 *size, *negot, 0, 0); 169 ENDTRACE 170 } 171 172 /* 173 * CALLED FROM: 174 * cons 175 * FUNCTION and ARGUMENTS: 176 * THIS MAYBE BELONGS IN SOME OTHER PLACE??? but i think not - 177 */ 178 ProtoHook 179 tpcons_ctlinput(cmd, siso, isop) 180 int cmd; 181 struct sockaddr_iso *siso; 182 struct isopcb *isop; 183 { 184 switch (cmd) { 185 186 case PRC_CONS_SEND_DONE: 187 if( isop->isop_socket ) { /* tp 0 only */ 188 register struct tp_pcb *tpcb = 189 (struct tp_pcb *)isop->isop_socket->so_tpcb; 190 struct tp_event E; 191 int error = 0; 192 193 if( tpcb->tp_class == TP_CLASS_0 ) { 194 /* only if class is exactly class zero, not 195 * still in class negotiation 196 */ 197 /* fake an ack */ 198 register SeqNum seq = SEQ_ADD(tpcb, tpcb->tp_snduna, 1); 199 200 IFTRACE(D_DATA) 201 tptrace(TPPTmisc, "FAKE ACK seq cdt 1", 202 seq, 0,0,0); 203 ENDTRACE 204 IFDEBUG(D_DATA) 205 printf("FAKE ACK seq 0x%x cdt 1\n", seq ); 206 ENDDEBUG 207 E.ATTR(AK_TPDU).e_cdt = 1; 208 E.ATTR(AK_TPDU).e_seq = seq; 209 E.ATTR(AK_TPDU).e_subseq = 0; 210 E.ATTR(AK_TPDU).e_fcc_present = 0; 211 error = DoEvent(AK_TPDU); 212 if( error ) { 213 tpcb->tp_sock->so_error = error; 214 } 215 } /* else ignore it */ 216 } 217 break; 218 case PRC_ROUTEDEAD: 219 if( isop->isop_socket ) { /* tp 0 only */ 220 tpiso_reset(isop); 221 break; 222 } /* else drop through */ 223 default: 224 (void) tpclnp_ctlinput(cmd, siso); 225 break; 226 } 227 return 0; 228 } 229 230 /* 231 * CALLED FROM: 232 * cons's intr routine 233 * FUNCTION and ARGUMENTS: 234 * Take a packet (m) from cons, pullup m as required by tp, 235 * ignore the socket argument, and call tp_input. 236 * No return value. 237 */ 238 ProtoHook 239 tpcons_input(m, faddr, laddr, channel) 240 struct mbuf *m; 241 struct sockaddr_iso *faddr, *laddr; 242 caddr_t channel; 243 { 244 if( m == MNULL) 245 return 0; 246 247 m = (struct mbuf *)tp_inputprep(m); 248 249 IFDEBUG(D_TPINPUT) 250 printf("tpcons_input before tp_input(m 0x%x)\n", m); 251 dump_buf( m, 12+ m->m_len); 252 ENDDEBUG 253 tp_input(m, faddr, laddr, channel, tpcons_output); 254 return 0; 255 } 256 257 258 /* 259 * CALLED FROM: 260 * tp_emit() 261 * FUNCTION and ARGUMENTS: 262 * Take a packet(m0) from tp and package it so that cons will accept it. 263 * This means filling in a few of the fields. 264 * inp is the isopcb structure; datalen is the length of the data in the 265 * mbuf string m0. 266 * RETURN VALUE: 267 * whatever (E*) is returned form the net layer output routine. 268 */ 269 270 int 271 tpcons_output(isop, m0, datalen, nochksum) 272 struct isopcb *isop; 273 struct mbuf *m0; 274 int datalen; 275 int nochksum; 276 { 277 register struct mbuf *m = m0; 278 int error; 279 280 IFDEBUG(D_EMIT) 281 printf( 282 "tpcons_output(isop 0x%x, m 0x%x, len 0x%x socket 0x%x\n", 283 isop, m0, datalen, isop->isop_socket); 284 ENDDEBUG 285 if (m == MNULL) 286 return 0; 287 if (m->m_flags & M_PKTHDR == 0) { 288 MGETHDR(m, M_DONTWAIT, MT_DATA); 289 if (m == 0) 290 return ENOBUFS; 291 m->m_next = m0; 292 } 293 m->m_pkthdr.len = datalen; 294 error = pk_send(isop->isop_chan, m); 295 IncStat(ts_tpdu_sent); 296 297 return error; 298 } 299 /* 300 * CALLED FROM: 301 * tp_error_emit() 302 * FUNCTION and ARGUMENTS: 303 * Take a packet(m0) from tp and package it so that cons will accept it. 304 * chan is the cons channel to use; datalen is the length of the data in the 305 * mbuf string m0. 306 * RETURN VALUE: 307 * whatever (E*) is returned form the net layer output routine. 308 */ 309 310 int 311 tpcons_dg_output(chan, m0, datalen) 312 caddr_t chan; 313 struct mbuf *m0; 314 int datalen; 315 { 316 return tpcons_output(((struct pklcd *)chan)->lcd_upnext, m0, datalen, 0); 317 } 318 #endif TPCONS 319 #endif ISO 320