1*36403Ssklower /*********************************************************** 2*36403Ssklower Copyright IBM Corporation 1987 3*36403Ssklower 4*36403Ssklower All Rights Reserved 5*36403Ssklower 6*36403Ssklower Permission to use, copy, modify, and distribute this software and its 7*36403Ssklower documentation for any purpose and without fee is hereby granted, 8*36403Ssklower provided that the above copyright notice appear in all copies and that 9*36403Ssklower both that copyright notice and this permission notice appear in 10*36403Ssklower supporting documentation, and that the name of IBM not be 11*36403Ssklower used in advertising or publicity pertaining to distribution of the 12*36403Ssklower software without specific, written prior permission. 13*36403Ssklower 14*36403Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36403Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36403Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36403Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36403Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36403Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36403Ssklower SOFTWARE. 21*36403Ssklower 22*36403Ssklower ******************************************************************/ 23*36403Ssklower 24*36403Ssklower /* 25*36403Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36403Ssklower */ 27*36403Ssklower /* 28*36403Ssklower * ARGO TP 29*36403Ssklower * $Header: tp_iso.c,v 5.3 88/11/18 17:27:57 nhall Exp $ 30*36403Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_iso.c,v $ 31*36403Ssklower * 32*36403Ssklower * Here is where you find the iso-dependent code. We've tried 33*36403Ssklower * keep all net-level and (primarily) address-family-dependent stuff 34*36403Ssklower * out of the tp source, and everthing here is reached indirectly 35*36403Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 36*36403Ssklower * (see tp_pcb.c). 37*36403Ssklower * The routines here are: 38*36403Ssklower * iso_getsufx: gets transport suffix out of an isopcb structure. 39*36403Ssklower * iso_putsufx: put transport suffix into an isopcb structure. 40*36403Ssklower * iso_putnetaddr: put a whole net addr into an isopcb. 41*36403Ssklower * iso_getnetaddr: get a whole net addr from an isopcb. 42*36403Ssklower * iso_recycle_suffix: clear suffix for reuse in isopcb 43*36403Ssklower * tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff 44*36403Ssklower * tpclnp_mtu: figure out what size tpdu to use 45*36403Ssklower * tpclnp_input: take a pkt from clnp, strip off its clnp header, 46*36403Ssklower * give to tp 47*36403Ssklower * tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data 48*36403Ssklower * tpclnp_output: package a pkt for clnp given an isopcb & some data 49*36403Ssklower */ 50*36403Ssklower 51*36403Ssklower #ifndef lint 52*36403Ssklower static char *rcsid = "$Header: tp_iso.c,v 5.3 88/11/18 17:27:57 nhall Exp $"; 53*36403Ssklower #endif lint 54*36403Ssklower 55*36403Ssklower #ifdef ISO 56*36403Ssklower 57*36403Ssklower #include "../h/types.h" 58*36403Ssklower #include "../h/socket.h" 59*36403Ssklower #include "../h/socketvar.h" 60*36403Ssklower #include "../h/domain.h" 61*36403Ssklower #include "../h/mbuf.h" 62*36403Ssklower #include "../h/errno.h" 63*36403Ssklower #include "../h/time.h" 64*36403Ssklower #include "../net/if.h" 65*36403Ssklower #include "../net/route.h" 66*36403Ssklower #include "../h/protosw.h" 67*36403Ssklower 68*36403Ssklower #include "../netiso/tp_param.h" 69*36403Ssklower #include "../netiso/argo_debug.h" 70*36403Ssklower #include "../netiso/tp_stat.h" 71*36403Ssklower #include "../netiso/tp_pcb.h" 72*36403Ssklower #include "../netiso/tp_trace.h" 73*36403Ssklower #include "../netiso/tp_stat.h" 74*36403Ssklower #include "../netiso/tp_tpdu.h" 75*36403Ssklower #include "../netiso/tp_clnp.h" 76*36403Ssklower 77*36403Ssklower /* 78*36403Ssklower * CALLED FROM: 79*36403Ssklower * pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 80*36403Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 81*36403Ssklower * Return a transport suffix from an isopcb structure (inp). 82*36403Ssklower * (CAST TO AN INT) 83*36403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 84*36403Ssklower */ 85*36403Ssklower 86*36403Ssklower short 87*36403Ssklower iso_getsufx(isop, which) 88*36403Ssklower struct isopcb *isop; 89*36403Ssklower int which; 90*36403Ssklower { 91*36403Ssklower switch (which) { 92*36403Ssklower case TP_LOCAL: 93*36403Ssklower return htons(isop->isop_laddr.siso_tsuffix); 94*36403Ssklower 95*36403Ssklower case TP_FOREIGN: 96*36403Ssklower return htons(isop->isop_faddr.siso_tsuffix); 97*36403Ssklower } 98*36403Ssklower } 99*36403Ssklower 100*36403Ssklower /* CALLED FROM: 101*36403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 102*36403Ssklower * incoming CR_TPDU. 103*36403Ssklower * 104*36403Ssklower * FUNCTION, ARGUMENTS: 105*36403Ssklower * Put a transport suffix (found in name) into an isopcb structure (isop). 106*36403Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 107*36403Ssklower */ 108*36403Ssklower void 109*36403Ssklower iso_putsufx(isop, name, which) 110*36403Ssklower struct isopcb *isop; 111*36403Ssklower struct sockaddr_iso *name; 112*36403Ssklower int which; 113*36403Ssklower { 114*36403Ssklower switch (which) { 115*36403Ssklower case TP_LOCAL: 116*36403Ssklower isop->isop_lport = ntohs(name->siso_tsuffix); 117*36403Ssklower break; 118*36403Ssklower case TP_FOREIGN: 119*36403Ssklower isop->isop_fport = ntohs(name->siso_tsuffix); 120*36403Ssklower break; 121*36403Ssklower } 122*36403Ssklower } 123*36403Ssklower 124*36403Ssklower /* 125*36403Ssklower * CALLED FROM: 126*36403Ssklower * tp.trans whenever we go into REFWAIT state. 127*36403Ssklower * FUNCTION and ARGUMENT: 128*36403Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 129*36403Ssklower * (isop) is the net level pcb. This really shouldn't have to be 130*36403Ssklower * done in a NET level pcb but... for the internet world that just 131*36403Ssklower * the way it is done in BSD... 132*36403Ssklower * The alternative is to have the port unusable until the reference 133*36403Ssklower * timer goes off. 134*36403Ssklower */ 135*36403Ssklower void 136*36403Ssklower iso_recycle_tsuffix(isop) 137*36403Ssklower struct isopcb *isop; 138*36403Ssklower { 139*36403Ssklower isop->isop_laddr.siso_tsuffix = isop->isop_faddr.siso_tsuffix = 0; 140*36403Ssklower } 141*36403Ssklower 142*36403Ssklower /* 143*36403Ssklower * CALLED FROM: 144*36403Ssklower * tp_newsocket(); i.e., when a connection is being established by an 145*36403Ssklower * incoming CR_TPDU. 146*36403Ssklower * 147*36403Ssklower * FUNCTION and ARGUMENTS: 148*36403Ssklower * Copy a whole net addr from a struct sockaddr (name). 149*36403Ssklower * into an isopcb (isop). 150*36403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 151*36403Ssklower */ 152*36403Ssklower void 153*36403Ssklower iso_putnetaddr(isop, name, which) 154*36403Ssklower register struct isopcb *isop; 155*36403Ssklower struct sockaddr_iso *name; 156*36403Ssklower int which; 157*36403Ssklower { 158*36403Ssklower switch (which) { 159*36403Ssklower case TP_LOCAL: 160*36403Ssklower isop->isop_laddr.siso_family = AF_ISO; 161*36403Ssklower bcopy((caddr_t)&name->siso_addr, 162*36403Ssklower (caddr_t)&isop->isop_laddr.siso_addr, sizeof(struct iso_addr)); 163*36403Ssklower IFDEBUG(D_TPISO) 164*36403Ssklower printf("PUT TP_LOCAL addr\n"); 165*36403Ssklower dump_isoaddr(&isop->isop_laddr); 166*36403Ssklower ENDDEBUG 167*36403Ssklower break; 168*36403Ssklower case TP_FOREIGN: 169*36403Ssklower isop->isop_faddr.siso_family = AF_ISO; 170*36403Ssklower if( name != (struct sockaddr_iso *)0 ) { 171*36403Ssklower bcopy((caddr_t)&name->siso_addr, 172*36403Ssklower (caddr_t)&isop->isop_faddr.siso_addr, sizeof(struct iso_addr)); 173*36403Ssklower } 174*36403Ssklower IFDEBUG(D_TPISO) 175*36403Ssklower printf("PUT TP_FOREIGN addr\n"); 176*36403Ssklower dump_isoaddr(&isop->isop_faddr); 177*36403Ssklower ENDDEBUG 178*36403Ssklower } 179*36403Ssklower } 180*36403Ssklower 181*36403Ssklower /* 182*36403Ssklower * CALLED FROM: 183*36403Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 184*36403Ssklower * FUNCTION and ARGUMENTS: 185*36403Ssklower * Copy a whole net addr from an isopcb (isop) into 186*36403Ssklower * a struct sockaddr (name). 187*36403Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 188*36403Ssklower */ 189*36403Ssklower 190*36403Ssklower void 191*36403Ssklower iso_getnetaddr( isop, name, which) 192*36403Ssklower struct isopcb *isop; 193*36403Ssklower struct sockaddr_iso *name; 194*36403Ssklower int which; 195*36403Ssklower { 196*36403Ssklower switch (which) { 197*36403Ssklower case TP_LOCAL: 198*36403Ssklower bcopy( (caddr_t)&isop->isop_laddr.siso_addr, 199*36403Ssklower (caddr_t)&name->siso_addr, sizeof(struct iso_addr)); 200*36403Ssklower break; 201*36403Ssklower 202*36403Ssklower case TP_FOREIGN: 203*36403Ssklower bcopy( (caddr_t)&isop->isop_faddr.siso_addr, 204*36403Ssklower (caddr_t)&name->siso_addr, sizeof(struct iso_addr)); 205*36403Ssklower break; 206*36403Ssklower } 207*36403Ssklower } 208*36403Ssklower 209*36403Ssklower /* 210*36403Ssklower * CALLED FROM: 211*36403Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 212*36403Ssklower * FUNCTION, ARGUMENTS, SIDE EFFECTS and RETURN VALUE: 213*36403Ssklower * Determine the proper maximum transmission unit, i.e., MTU, to use, given 214*36403Ssklower * a) the header size for the network protocol and the max transmission 215*36403Ssklower * unit on the subnet interface, determined from the information in (isop), 216*36403Ssklower * b) the max size negotiated so far (negot) 217*36403Ssklower * c) the window size used by the tp connection (found in so), 218*36403Ssklower * 219*36403Ssklower * The result is put in the integer *size in its integer form and in 220*36403Ssklower * *negot in its logarithmic form. 221*36403Ssklower * 222*36403Ssklower * The rules are: 223*36403Ssklower * a) can only negotiate down from the value found in *negot. 224*36403Ssklower * b) the MTU must be < the windowsize, 225*36403Ssklower * c) If src and dest are on the same net, 226*36403Ssklower * we will negotiate the closest size larger than MTU but really USE 227*36403Ssklower * the actual device mtu - ll hdr sizes. 228*36403Ssklower * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. 229*36403Ssklower */ 230*36403Ssklower 231*36403Ssklower void 232*36403Ssklower tpclnp_mtu(so, isop, size, negot ) 233*36403Ssklower struct socket *so; 234*36403Ssklower struct isopcb *isop; 235*36403Ssklower int *size; 236*36403Ssklower u_char *negot; 237*36403Ssklower { 238*36403Ssklower struct ifnet *ifp; 239*36403Ssklower register int i; 240*36403Ssklower int windowsize = so->so_rcv.sb_hiwat; 241*36403Ssklower int clnp_size; 242*36403Ssklower int sizeismtu = 0; 243*36403Ssklower 244*36403Ssklower struct ifnet *iso_routeifp(); 245*36403Ssklower 246*36403Ssklower IFDEBUG(D_CONN) 247*36403Ssklower printf("tpclnp_mtu(0x%x,0x%x,0x%x,0x%x)\n", so, isop, size, negot); 248*36403Ssklower ENDDEBUG 249*36403Ssklower IFTRACE(D_CONN) 250*36403Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); 251*36403Ssklower ENDTRACE 252*36403Ssklower 253*36403Ssklower *size = 1 << *negot; 254*36403Ssklower 255*36403Ssklower if( *size > windowsize ) { 256*36403Ssklower *size = windowsize; 257*36403Ssklower } 258*36403Ssklower 259*36403Ssklower if ((ifp = iso_routeifp(&isop->isop_faddr)) == (struct ifnet *)0) 260*36403Ssklower return; 261*36403Ssklower 262*36403Ssklower /* TODO - make this indirect off the socket structure to the 263*36403Ssklower * network layer to get headersize 264*36403Ssklower */ 265*36403Ssklower clnp_size = clnp_hdrsize(isop->isop_laddr.siso_addr.isoa_len); 266*36403Ssklower 267*36403Ssklower if(*size > ifp->if_mtu - clnp_size) { 268*36403Ssklower *size = ifp->if_mtu - clnp_size; 269*36403Ssklower sizeismtu = 1; 270*36403Ssklower } 271*36403Ssklower IFTRACE(D_CONN) 272*36403Ssklower tptrace(TPPTmisc, "GET MTU MID: tpcb size negot i \n", 273*36403Ssklower *size, *negot, i, 0); 274*36403Ssklower ENDTRACE 275*36403Ssklower 276*36403Ssklower /* have to transform size to the log2 of size */ 277*36403Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i) <= *size)) ; i++) 278*36403Ssklower ; 279*36403Ssklower i--; 280*36403Ssklower 281*36403Ssklower /* are we on the same LAN? if so, negotiate one tpdu size larger, 282*36403Ssklower * and actually send the real mtu size 283*36403Ssklower */ 284*36403Ssklower /* PHASE2: replace with iso_on_localnet(&isop->isop_faddr); 285*36403Ssklower * or something along those lines 286*36403Ssklower */ 287*36403Ssklower if ( iso_netmatch(&isop->isop_laddr, &isop->isop_faddr) && sizeismtu ) { 288*36403Ssklower i++; 289*36403Ssklower } else { 290*36403Ssklower *size = 1<<i; 291*36403Ssklower } 292*36403Ssklower *negot = i; 293*36403Ssklower 294*36403Ssklower IFDEBUG(D_CONN) 295*36403Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 296*36403Ssklower ifp->if_name, *size, *negot); 297*36403Ssklower ENDDEBUG 298*36403Ssklower IFTRACE(D_CONN) 299*36403Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", 300*36403Ssklower *size, *negot, 0, 0); 301*36403Ssklower ENDTRACE 302*36403Ssklower } 303*36403Ssklower 304*36403Ssklower 305*36403Ssklower /* 306*36403Ssklower * CALLED FROM: 307*36403Ssklower * tp_emit() 308*36403Ssklower * FUNCTION and ARGUMENTS: 309*36403Ssklower * Take a packet(m0) from tp and package it so that clnp will accept it. 310*36403Ssklower * This means prepending space for the clnp header and filling in a few 311*36403Ssklower * of the fields. 312*36403Ssklower * inp is the isopcb structure; datalen is the length of the data in the 313*36403Ssklower * mbuf string m0. 314*36403Ssklower * RETURN VALUE: 315*36403Ssklower * whatever (E*) is returned form the net layer output routine. 316*36403Ssklower */ 317*36403Ssklower 318*36403Ssklower int 319*36403Ssklower tpclnp_output(isop, m0, datalen, nochksum) 320*36403Ssklower struct isopcb *isop; 321*36403Ssklower struct mbuf *m0; 322*36403Ssklower int datalen; 323*36403Ssklower int nochksum; 324*36403Ssklower { 325*36403Ssklower IncStat(ts_tpdu_sent); 326*36403Ssklower 327*36403Ssklower IFDEBUG(D_TPISO) 328*36403Ssklower struct tpdu *hdr = mtod(m0, struct tpdu *); 329*36403Ssklower 330*36403Ssklower printf( 331*36403Ssklower "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n", 332*36403Ssklower datalen, 333*36403Ssklower (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum); 334*36403Ssklower dump_isoaddr(&isop->isop_faddr); 335*36403Ssklower printf("\nsrc addr:\n"); 336*36403Ssklower dump_isoaddr(&isop->isop_laddr); 337*36403Ssklower dump_mbuf(m0, "at tpclnp_output"); 338*36403Ssklower ENDDEBUG 339*36403Ssklower 340*36403Ssklower return 341*36403Ssklower clnp_output(m0, isop, datalen, nochksum?CLNP_NO_CKSUM:0 /* flags */); 342*36403Ssklower } 343*36403Ssklower 344*36403Ssklower /* 345*36403Ssklower * CALLED FROM: 346*36403Ssklower * tp_error_emit() 347*36403Ssklower * FUNCTION and ARGUMENTS: 348*36403Ssklower * This is a copy of tpclnp_output that takes the addresses 349*36403Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 350*36403Ssklower * don't have an iso_pcb with which to call the normal output rtn. 351*36403Ssklower * RETURN VALUE: 352*36403Ssklower * ENOBUFS or 353*36403Ssklower * whatever (E*) is returned form the net layer output routine. 354*36403Ssklower */ 355*36403Ssklower 356*36403Ssklower int 357*36403Ssklower tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 358*36403Ssklower struct iso_addr *laddr, *faddr; 359*36403Ssklower struct mbuf *m0; 360*36403Ssklower int datalen; 361*36403Ssklower struct route *ro; 362*36403Ssklower int nochksum; 363*36403Ssklower { 364*36403Ssklower struct isopcb tmppcb; 365*36403Ssklower struct iso_addr *isoa; 366*36403Ssklower int err; 367*36403Ssklower int flags; 368*36403Ssklower 369*36403Ssklower IFDEBUG(D_TPISO) 370*36403Ssklower printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 371*36403Ssklower ENDDEBUG 372*36403Ssklower 373*36403Ssklower /* 374*36403Ssklower * Fill in minimal portion of isopcb so that clnp can send the 375*36403Ssklower * packet. 376*36403Ssklower */ 377*36403Ssklower bzero((caddr_t)&tmppcb, sizeof(tmppcb)); 378*36403Ssklower isoa = &(tmppcb.isop_laddr.siso_addr); 379*36403Ssklower bcopy((caddr_t)laddr, (caddr_t)isoa, sizeof (struct iso_addr)); 380*36403Ssklower isoa = &(tmppcb.isop_faddr.siso_addr); 381*36403Ssklower bcopy((caddr_t)faddr, (caddr_t)isoa, sizeof (struct iso_addr)); 382*36403Ssklower 383*36403Ssklower IFDEBUG(D_TPISO) 384*36403Ssklower printf("tpclnp_output_dg faddr: \n"); 385*36403Ssklower dump_isoaddr(&tmppcb.isop_faddr); 386*36403Ssklower printf("\ntpclnp_output_dg laddr: \n"); 387*36403Ssklower dump_isoaddr(&tmppcb.isop_laddr); 388*36403Ssklower printf("\n"); 389*36403Ssklower ENDDEBUG 390*36403Ssklower 391*36403Ssklower /* 392*36403Ssklower * Do not use packet cache since this is a one shot error packet 393*36403Ssklower */ 394*36403Ssklower flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0)); 395*36403Ssklower 396*36403Ssklower IncStat(ts_tpdu_sent); 397*36403Ssklower 398*36403Ssklower err = clnp_output(m0, &tmppcb, datalen, flags); 399*36403Ssklower 400*36403Ssklower /* 401*36403Ssklower * Free route allocated by clnp (if the route was indeed allocated) 402*36403Ssklower */ 403*36403Ssklower if (tmppcb.isop_route.ro_rt) 404*36403Ssklower RTFREE(tmppcb.isop_route.ro_rt); 405*36403Ssklower 406*36403Ssklower return(err); 407*36403Ssklower } 408*36403Ssklower 409*36403Ssklower /* 410*36403Ssklower * CALLED FROM: 411*36403Ssklower * clnp's input routine, indirectly through the protosw. 412*36403Ssklower * FUNCTION and ARGUMENTS: 413*36403Ssklower * Take a packet (m) from clnp, strip off the clnp header and give it to tp 414*36403Ssklower * No return value. 415*36403Ssklower */ 416*36403Ssklower ProtoHook 417*36403Ssklower tpclnp_input(m, faddr, laddr, clnp_len) 418*36403Ssklower struct mbuf *m; 419*36403Ssklower struct iso_addr *faddr, *laddr; 420*36403Ssklower int clnp_len; 421*36403Ssklower { 422*36403Ssklower struct sockaddr_iso src, dst; 423*36403Ssklower int s = splnet(); 424*36403Ssklower 425*36403Ssklower IncStat(ts_pkt_rcvd); 426*36403Ssklower 427*36403Ssklower IFDEBUG(D_TPINPUT) 428*36403Ssklower printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); 429*36403Ssklower dump_mbuf(m, "at tpclnp_input"); 430*36403Ssklower ENDDEBUG 431*36403Ssklower /* 432*36403Ssklower * CLNP gives us an mbuf chain WITH the clnp header pulled up, 433*36403Ssklower * and the length of the clnp header. 434*36403Ssklower * First, strip off the Clnp header. leave the mbuf there for the 435*36403Ssklower * pullup that follows. 436*36403Ssklower */ 437*36403Ssklower 438*36403Ssklower m->m_len -= clnp_len; 439*36403Ssklower m->m_off += clnp_len; 440*36403Ssklower 441*36403Ssklower m = (struct mbuf *)tp_inputprep(m); 442*36403Ssklower 443*36403Ssklower IFDEBUG(D_TPINPUT) 444*36403Ssklower dump_mbuf(m, "after tpclnp_input both pullups"); 445*36403Ssklower ENDDEBUG 446*36403Ssklower 447*36403Ssklower src.siso_family = dst.siso_family = AF_ISO; 448*36403Ssklower bcopy(faddr, &src.siso_addr, sizeof(struct iso_addr)); 449*36403Ssklower bcopy(laddr, &dst.siso_addr, sizeof(struct iso_addr)); 450*36403Ssklower 451*36403Ssklower IFDEBUG(D_TPISO) 452*36403Ssklower printf("calling tp_input: &src 0x%x &dst 0x%x, src addr:\n", 453*36403Ssklower &src, &dst); 454*36403Ssklower printf(" dst addr:\n"); 455*36403Ssklower dump_isoaddr(&src); 456*36403Ssklower dump_isoaddr(&dst); 457*36403Ssklower ENDDEBUG 458*36403Ssklower 459*36403Ssklower (void) tp_input(m, &src, &dst, 0, tpclnp_output_dg); 460*36403Ssklower 461*36403Ssklower IFDEBUG(D_QUENCH) 462*36403Ssklower { 463*36403Ssklower if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { 464*36403Ssklower printf("tpclnp_input: FAKING %s\n", 465*36403Ssklower tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); 466*36403Ssklower if(tp_stat.ts_pkt_rcvd & 0x1) { 467*36403Ssklower tpclnp_ctlinput(PRC_QUENCH, &src); 468*36403Ssklower } else { 469*36403Ssklower tpclnp_ctlinput(PRC_QUENCH2, &src); 470*36403Ssklower } 471*36403Ssklower } 472*36403Ssklower } 473*36403Ssklower ENDDEBUG 474*36403Ssklower 475*36403Ssklower splx(s); 476*36403Ssklower return 0; 477*36403Ssklower 478*36403Ssklower discard: 479*36403Ssklower IFDEBUG(D_TPINPUT) 480*36403Ssklower printf("tpclnp_input DISCARD\n"); 481*36403Ssklower ENDDEBUG 482*36403Ssklower IFTRACE(D_TPINPUT) 483*36403Ssklower tptrace(TPPTmisc, "tpclnp_input DISCARD m", m,0,0,0); 484*36403Ssklower ENDTRACE 485*36403Ssklower m_freem(m); 486*36403Ssklower IncStat(ts_recv_drop); 487*36403Ssklower splx(s); 488*36403Ssklower 489*36403Ssklower return 0; 490*36403Ssklower } 491*36403Ssklower 492*36403Ssklower ProtoHook 493*36403Ssklower iso_rtchange() 494*36403Ssklower { 495*36403Ssklower return 0; 496*36403Ssklower } 497*36403Ssklower 498*36403Ssklower /* 499*36403Ssklower * CALLED FROM: 500*36403Ssklower * tpclnp_ctlinput() 501*36403Ssklower * FUNCTION and ARGUMENTS: 502*36403Ssklower * find the tpcb pointer and pass it to tp_quench 503*36403Ssklower */ 504*36403Ssklower void 505*36403Ssklower tpiso_decbit(isop) 506*36403Ssklower struct isopcb *isop; 507*36403Ssklower { 508*36403Ssklower tp_quench( isop->isop_socket->so_tpcb, PRC_QUENCH2 ); 509*36403Ssklower } 510*36403Ssklower /* 511*36403Ssklower * CALLED FROM: 512*36403Ssklower * tpclnp_ctlinput() 513*36403Ssklower * FUNCTION and ARGUMENTS: 514*36403Ssklower * find the tpcb pointer and pass it to tp_quench 515*36403Ssklower */ 516*36403Ssklower void 517*36403Ssklower tpiso_quench(isop) 518*36403Ssklower struct isopcb *isop; 519*36403Ssklower { 520*36403Ssklower tp_quench( isop->isop_socket->so_tpcb, PRC_QUENCH ); 521*36403Ssklower } 522*36403Ssklower 523*36403Ssklower /* 524*36403Ssklower * CALLED FROM: 525*36403Ssklower * The network layer through the protosw table. 526*36403Ssklower * FUNCTION and ARGUMENTS: 527*36403Ssklower * When clnp an ICMP-like msg this gets called. 528*36403Ssklower * It either returns an error status to the user or 529*36403Ssklower * it causes all connections on this address to be aborted 530*36403Ssklower * by calling the appropriate xx_notify() routine. 531*36403Ssklower * (cmd) is the type of ICMP error. 532*36403Ssklower * (siso) is the address of the guy who sent the ER CLNPDU 533*36403Ssklower */ 534*36403Ssklower ProtoHook 535*36403Ssklower tpclnp_ctlinput(cmd, siso) 536*36403Ssklower int cmd; 537*36403Ssklower struct sockaddr_iso *siso; 538*36403Ssklower { 539*36403Ssklower extern u_char inetctlerrmap[]; 540*36403Ssklower extern ProtoHook tpiso_abort(); 541*36403Ssklower extern ProtoHook iso_rtchange(); 542*36403Ssklower extern ProtoHook tpiso_reset(); 543*36403Ssklower 544*36403Ssklower IFDEBUG(D_TPINPUT) 545*36403Ssklower printf("tpclnp_ctlinput: cmd 0x%x addr: ", cmd); 546*36403Ssklower dump_isoaddr(siso); 547*36403Ssklower printf("\n"); 548*36403Ssklower ENDDEBUG 549*36403Ssklower 550*36403Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 551*36403Ssklower return 0; 552*36403Ssklower switch (cmd) { 553*36403Ssklower 554*36403Ssklower case PRC_QUENCH2: 555*36403Ssklower iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_decbit); 556*36403Ssklower break; 557*36403Ssklower 558*36403Ssklower case PRC_QUENCH: 559*36403Ssklower iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_quench); 560*36403Ssklower break; 561*36403Ssklower 562*36403Ssklower case PRC_TIMXCEED_REASS: 563*36403Ssklower case PRC_ROUTEDEAD: 564*36403Ssklower iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 0, tpiso_reset); 565*36403Ssklower break; 566*36403Ssklower 567*36403Ssklower case PRC_HOSTUNREACH: 568*36403Ssklower case PRC_UNREACH_NET: 569*36403Ssklower case PRC_IFDOWN: 570*36403Ssklower case PRC_HOSTDEAD: 571*36403Ssklower iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 572*36403Ssklower (int)inetctlerrmap[cmd], iso_rtchange); 573*36403Ssklower break; 574*36403Ssklower 575*36403Ssklower default: 576*36403Ssklower /* 577*36403Ssklower case PRC_MSGSIZE: 578*36403Ssklower case PRC_UNREACH_HOST: 579*36403Ssklower case PRC_UNREACH_PROTOCOL: 580*36403Ssklower case PRC_UNREACH_PORT: 581*36403Ssklower case PRC_UNREACH_NEEDFRAG: 582*36403Ssklower case PRC_UNREACH_SRCFAIL: 583*36403Ssklower case PRC_REDIRECT_NET: 584*36403Ssklower case PRC_REDIRECT_HOST: 585*36403Ssklower case PRC_REDIRECT_TOSNET: 586*36403Ssklower case PRC_REDIRECT_TOSHOST: 587*36403Ssklower case PRC_TIMXCEED_INTRANS: 588*36403Ssklower case PRC_PARAMPROB: 589*36403Ssklower */ 590*36403Ssklower iso_pcbnotify(&tp_isopcb, &siso->siso_addr, 591*36403Ssklower (int)inetctlerrmap[cmd], tpiso_abort); 592*36403Ssklower break; 593*36403Ssklower } 594*36403Ssklower return 0; 595*36403Ssklower } 596*36403Ssklower 597*36403Ssklower /* 598*36403Ssklower * These next 2 routines are 599*36403Ssklower * CALLED FROM: 600*36403Ssklower * xxx_notify() from tp_ctlinput() when 601*36403Ssklower * net level gets some ICMP-equiv. type event. 602*36403Ssklower * FUNCTION and ARGUMENTS: 603*36403Ssklower * Cause the connection to be aborted with some sort of error 604*36403Ssklower * reason indicating that the network layer caused the abort. 605*36403Ssklower * Fakes an ER TPDU so we can go through the driver. 606*36403Ssklower * abort always aborts the TP connection. 607*36403Ssklower * reset may or may not, depending on the TP class that's in use. 608*36403Ssklower */ 609*36403Ssklower ProtoHook 610*36403Ssklower tpiso_abort(isop) 611*36403Ssklower struct isopcb *isop; 612*36403Ssklower { 613*36403Ssklower struct tp_event e; 614*36403Ssklower 615*36403Ssklower IFDEBUG(D_CONN) 616*36403Ssklower printf("tpiso_abort 0x%x\n", isop); 617*36403Ssklower ENDDEBUG 618*36403Ssklower e.ev_number = ER_TPDU; 619*36403Ssklower e.ATTR(ER_TPDU).e_reason = ECONNABORTED; 620*36403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 621*36403Ssklower } 622*36403Ssklower 623*36403Ssklower ProtoHook 624*36403Ssklower tpiso_reset(isop) 625*36403Ssklower struct isopcb *isop; 626*36403Ssklower { 627*36403Ssklower struct tp_event e; 628*36403Ssklower 629*36403Ssklower e.ev_number = T_NETRESET; 630*36403Ssklower return tp_driver((struct tp_pcb *)isop->isop_socket->so_tpcb, &e); 631*36403Ssklower 632*36403Ssklower } 633*36403Ssklower 634*36403Ssklower #endif ISO 635