1*36400Ssklower /*********************************************************** 2*36400Ssklower Copyright IBM Corporation 1987 3*36400Ssklower 4*36400Ssklower All Rights Reserved 5*36400Ssklower 6*36400Ssklower Permission to use, copy, modify, and distribute this software and its 7*36400Ssklower documentation for any purpose and without fee is hereby granted, 8*36400Ssklower provided that the above copyright notice appear in all copies and that 9*36400Ssklower both that copyright notice and this permission notice appear in 10*36400Ssklower supporting documentation, and that the name of IBM not be 11*36400Ssklower used in advertising or publicity pertaining to distribution of the 12*36400Ssklower software without specific, written prior permission. 13*36400Ssklower 14*36400Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36400Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36400Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36400Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36400Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36400Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36400Ssklower SOFTWARE. 21*36400Ssklower 22*36400Ssklower ******************************************************************/ 23*36400Ssklower 24*36400Ssklower /* 25*36400Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36400Ssklower */ 27*36400Ssklower /* 28*36400Ssklower * ARGO TP 29*36400Ssklower * $Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $ 30*36400Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_inet.c,v $ 31*36400Ssklower * 32*36400Ssklower * Here is where you find the inet-dependent code. We've tried 33*36400Ssklower * keep all net-level and (primarily) address-family-dependent stuff 34*36400Ssklower * out of the tp source, and everthing here is reached indirectly 35*36400Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 36*36400Ssklower * (see tp_pcb.c). 37*36400Ssklower * The routines here are: 38*36400Ssklower * in_getsufx: gets transport suffix out of an inpcb structure. 39*36400Ssklower * in_putsufx: put transport suffix into an inpcb structure. 40*36400Ssklower * in_putnetaddr: put a whole net addr into an inpcb. 41*36400Ssklower * in_getnetaddr: get a whole net addr from an inpcb. 42*36400Ssklower * in_recycle_suffix: clear suffix for reuse in inpcb 43*36400Ssklower * tpip_mtu: figure out what size tpdu to use 44*36400Ssklower * tpip_input: take a pkt from ip, strip off its ip header, give to tp 45*36400Ssklower * tpip_output_dg: package a pkt for ip given 2 addresses & some data 46*36400Ssklower * tpip_output: package a pkt for ip given an inpcb & some data 47*36400Ssklower */ 48*36400Ssklower 49*36400Ssklower #ifndef lint 50*36400Ssklower static char *rcsid = "$Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $"; 51*36400Ssklower #endif lint 52*36400Ssklower 53*36400Ssklower #ifdef INET 54*36400Ssklower 55*36400Ssklower #include "types.h" 56*36400Ssklower #include "socket.h" 57*36400Ssklower #include "socketvar.h" 58*36400Ssklower #include "mbuf.h" 59*36400Ssklower #include "errno.h" 60*36400Ssklower #include "time.h" 61*36400Ssklower #include "../net/if.h" 62*36400Ssklower #include "../netiso/tp_param.h" 63*36400Ssklower #include "../netiso/argo_debug.h" 64*36400Ssklower #include "../netiso/tp_stat.h" 65*36400Ssklower #include "../netiso/tp_ip.h" 66*36400Ssklower #include "../netiso/tp_pcb.h" 67*36400Ssklower #include "../netiso/tp_trace.h" 68*36400Ssklower #include "../netiso/tp_stat.h" 69*36400Ssklower #include "../netiso/tp_tpdu.h" 70*36400Ssklower #include "../netinet/in_var.h" 71*36400Ssklower 72*36400Ssklower 73*36400Ssklower /* 74*36400Ssklower * NAME: in_getsufx() 75*36400Ssklower 76*36400Ssklower * CALLED FROM: pr_usrreq() on PRU_BIND, 77*36400Ssklower * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 78*36400Ssklower * 79*36400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 80*36400Ssklower * Get a transport suffix from an inpcb structure (inp). 81*36400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 82*36400Ssklower * 83*36400Ssklower * RETURNS: internet port / transport suffix 84*36400Ssklower * (CAST TO AN INT) 85*36400Ssklower * 86*36400Ssklower * SIDE EFFECTS: 87*36400Ssklower * 88*36400Ssklower * NOTES: 89*36400Ssklower */ 90*36400Ssklower 91*36400Ssklower int 92*36400Ssklower in_getsufx(inp, which) 93*36400Ssklower struct inpcb *inp; 94*36400Ssklower int which; 95*36400Ssklower { 96*36400Ssklower switch (which) { 97*36400Ssklower case TP_LOCAL: 98*36400Ssklower return (int) inp->inp_lport; 99*36400Ssklower 100*36400Ssklower case TP_FOREIGN: 101*36400Ssklower return (int) inp->inp_fport; 102*36400Ssklower } 103*36400Ssklower } 104*36400Ssklower 105*36400Ssklower /* 106*36400Ssklower * NAME: in_putsufx() 107*36400Ssklower * 108*36400Ssklower * CALLED FROM: tp_newsocket(); i.e., when a connection 109*36400Ssklower * is being established by an incoming CR_TPDU. 110*36400Ssklower * 111*36400Ssklower * FUNCTION, ARGUMENTS: 112*36400Ssklower * Put a transport suffix (found in name) into an inpcb structure (inp). 113*36400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 114*36400Ssklower * 115*36400Ssklower * RETURNS: Nada 116*36400Ssklower * 117*36400Ssklower * SIDE EFFECTS: 118*36400Ssklower * 119*36400Ssklower * NOTES: 120*36400Ssklower */ 121*36400Ssklower void 122*36400Ssklower in_putsufx(inp, name, which) 123*36400Ssklower struct inpcb *inp; 124*36400Ssklower struct sockaddr_in *name; 125*36400Ssklower int which; 126*36400Ssklower { 127*36400Ssklower switch (which) { 128*36400Ssklower case TP_LOCAL: 129*36400Ssklower inp->inp_lport = name->sin_port; 130*36400Ssklower break; 131*36400Ssklower case TP_FOREIGN: 132*36400Ssklower inp->inp_fport = name->sin_port; 133*36400Ssklower break; 134*36400Ssklower } 135*36400Ssklower } 136*36400Ssklower 137*36400Ssklower /* 138*36400Ssklower * NAME: in_recycle_tsuffix() 139*36400Ssklower * 140*36400Ssklower * CALLED FROM: tp.trans whenever we go into REFWAIT state. 141*36400Ssklower * 142*36400Ssklower * FUNCTION and ARGUMENT: 143*36400Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 144*36400Ssklower * (inp) is the net level pcb. 145*36400Ssklower * 146*36400Ssklower * RETURNS: Nada 147*36400Ssklower * 148*36400Ssklower * SIDE EFFECTS: 149*36400Ssklower * 150*36400Ssklower * NOTES: This really shouldn't have to be done in a NET level pcb 151*36400Ssklower * but... for the internet world that just the way it is done in BSD... 152*36400Ssklower * The alternative is to have the port unusable until the reference 153*36400Ssklower * timer goes off. 154*36400Ssklower */ 155*36400Ssklower void 156*36400Ssklower in_recycle_tsuffix(inp) 157*36400Ssklower struct inpcb *inp; 158*36400Ssklower { 159*36400Ssklower inp->inp_fport = inp->inp_lport = 0; 160*36400Ssklower } 161*36400Ssklower 162*36400Ssklower /* 163*36400Ssklower * NAME: in_putnetaddr() 164*36400Ssklower * 165*36400Ssklower * CALLED FROM: 166*36400Ssklower * tp_newsocket(); i.e., when a connection is being established by an 167*36400Ssklower * incoming CR_TPDU. 168*36400Ssklower * 169*36400Ssklower * FUNCTION and ARGUMENTS: 170*36400Ssklower * Copy a whole net addr from a struct sockaddr (name). 171*36400Ssklower * into an inpcb (inp). 172*36400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 173*36400Ssklower * 174*36400Ssklower * RETURNS: Nada 175*36400Ssklower * 176*36400Ssklower * SIDE EFFECTS: 177*36400Ssklower * 178*36400Ssklower * NOTES: 179*36400Ssklower */ 180*36400Ssklower void 181*36400Ssklower in_putnetaddr(inp, name, which) 182*36400Ssklower register struct inpcb *inp; 183*36400Ssklower struct sockaddr_in *name; 184*36400Ssklower int which; 185*36400Ssklower { 186*36400Ssklower switch (which) { 187*36400Ssklower case TP_LOCAL: 188*36400Ssklower bcopy((caddr_t)&name->sin_addr, 189*36400Ssklower (caddr_t)&inp->inp_laddr, sizeof(struct in_addr)); 190*36400Ssklower /* won't work if the dst address (name) is INADDR_ANY */ 191*36400Ssklower 192*36400Ssklower break; 193*36400Ssklower case TP_FOREIGN: 194*36400Ssklower if( name != (struct sockaddr_in *)0 ) { 195*36400Ssklower bcopy((caddr_t)&name->sin_addr, 196*36400Ssklower (caddr_t)&inp->inp_faddr, sizeof(struct in_addr)); 197*36400Ssklower } 198*36400Ssklower } 199*36400Ssklower } 200*36400Ssklower 201*36400Ssklower /* 202*36400Ssklower * NAME: in_getnetaddr() 203*36400Ssklower * 204*36400Ssklower * CALLED FROM: 205*36400Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 206*36400Ssklower * FUNCTION and ARGUMENTS: 207*36400Ssklower * Copy a whole net addr from an inpcb (inp) into 208*36400Ssklower * a struct sockaddr (name). 209*36400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 210*36400Ssklower * 211*36400Ssklower * RETURNS: Nada 212*36400Ssklower * 213*36400Ssklower * SIDE EFFECTS: 214*36400Ssklower * 215*36400Ssklower * NOTES: 216*36400Ssklower */ 217*36400Ssklower 218*36400Ssklower void 219*36400Ssklower in_getnetaddr( inp, name, which) 220*36400Ssklower struct inpcb *inp; 221*36400Ssklower struct sockaddr_in *name; 222*36400Ssklower int which; 223*36400Ssklower { 224*36400Ssklower switch (which) { 225*36400Ssklower case TP_LOCAL: 226*36400Ssklower bcopy( (caddr_t)&inp->inp_laddr, (caddr_t)&name->sin_addr, 227*36400Ssklower sizeof(struct in_addr)); 228*36400Ssklower /* won't work if the dst address (name) is INADDR_ANY */ 229*36400Ssklower break; 230*36400Ssklower 231*36400Ssklower case TP_FOREIGN: 232*36400Ssklower bcopy( (caddr_t)&inp->inp_faddr, (caddr_t)&name->sin_addr, 233*36400Ssklower sizeof(struct in_addr)); 234*36400Ssklower /* won't work if the dst address (name) is INADDR_ANY */ 235*36400Ssklower break; 236*36400Ssklower } 237*36400Ssklower } 238*36400Ssklower 239*36400Ssklower /* 240*36400Ssklower * NAME: tpip_mtu() 241*36400Ssklower * 242*36400Ssklower * CALLED FROM: 243*36400Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 244*36400Ssklower * 245*36400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 246*36400Ssklower * 247*36400Ssklower * Determine the proper maximum transmission unit, i.e., MTU, to use, given 248*36400Ssklower * a) the header size for the network protocol and the max transmission 249*36400Ssklower * unit on the subnet interface, determined from the information in (inp), 250*36400Ssklower * b) the max size negotiated so far (negot) 251*36400Ssklower * c) the window size used by the tp connection (found in so), 252*36400Ssklower * 253*36400Ssklower * The result is put in the integer *size in its integer form and in 254*36400Ssklower * *negot in its logarithmic form. 255*36400Ssklower * 256*36400Ssklower * The rules are: 257*36400Ssklower * a) can only negotiate down from the value found in *negot. 258*36400Ssklower * b) the MTU must be < the windowsize, 259*36400Ssklower * c) If src and dest are on the same net, 260*36400Ssklower * we will negotiate the closest size larger than MTU but really USE 261*36400Ssklower * the actual device mtu - ll hdr sizes. 262*36400Ssklower * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. 263*36400Ssklower * 264*36400Ssklower * SIDE EFFECTS: 265*36400Ssklower * changes the values addressed by the arguments (size) and (negot) 266*36400Ssklower * and 267*36400Ssklower * when the peer is not on one of our directly connected subnets, it 268*36400Ssklower * looks up a route, leaving the route in the inpcb addressed by (inp) 269*36400Ssklower * 270*36400Ssklower * NOTES: 271*36400Ssklower */ 272*36400Ssklower 273*36400Ssklower void 274*36400Ssklower tpip_mtu(so, inp, size, negot) 275*36400Ssklower struct socket *so; 276*36400Ssklower struct inpcb *inp; 277*36400Ssklower int *size; 278*36400Ssklower u_char *negot; 279*36400Ssklower { 280*36400Ssklower register struct ifnet *ifp; 281*36400Ssklower struct ifnet *tpip_route(); 282*36400Ssklower struct in_ifaddr *ia; 283*36400Ssklower register int i; 284*36400Ssklower int windowsize = so->so_rcv.sb_hiwat; 285*36400Ssklower 286*36400Ssklower IFDEBUG(D_CONN) 287*36400Ssklower printf("tpip_mtu(0x%x,0x%x,0x%x,0x%x)\n", 288*36400Ssklower so, inp, size, negot); 289*36400Ssklower printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr); 290*36400Ssklower ENDDEBUG 291*36400Ssklower IFTRACE(D_CONN) 292*36400Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); 293*36400Ssklower ENDTRACE 294*36400Ssklower 295*36400Ssklower *size = 1 << *negot; 296*36400Ssklower 297*36400Ssklower if( *size > windowsize ) { 298*36400Ssklower *size = windowsize; 299*36400Ssklower } 300*36400Ssklower 301*36400Ssklower ia = in_iaonnetof(in_netof(inp->inp_faddr)); 302*36400Ssklower if ( ia == (struct in_ifaddr *)0 ) { 303*36400Ssklower ifp = tpip_route(&inp->inp_faddr); 304*36400Ssklower if( ifp == (struct ifnet *)0 ) 305*36400Ssklower return ; 306*36400Ssklower } else 307*36400Ssklower ifp = ia->ia_ifp; 308*36400Ssklower 309*36400Ssklower 310*36400Ssklower /**************************************************************** 311*36400Ssklower * TODO - make this indirect off the socket structure to the 312*36400Ssklower * network layer to get headersize 313*36400Ssklower * After all, who knows what lies below the IP layer? 314*36400Ssklower * Who knows how big the NL header will be? 315*36400Ssklower ***************************************************************/ 316*36400Ssklower 317*36400Ssklower if( *size > ifp->if_mtu - sizeof(struct ip)) { 318*36400Ssklower *size = ifp->if_mtu - sizeof(struct ip); 319*36400Ssklower } 320*36400Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++) 321*36400Ssklower ; 322*36400Ssklower i--; 323*36400Ssklower 324*36400Ssklower if (in_netof(inp->inp_laddr) != in_netof(inp->inp_faddr)) { 325*36400Ssklower i++; 326*36400Ssklower } else { 327*36400Ssklower *size = 1<<i; 328*36400Ssklower } 329*36400Ssklower *negot = i; 330*36400Ssklower 331*36400Ssklower IFDEBUG(D_CONN) 332*36400Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 333*36400Ssklower ifp->if_name, *size, *negot); 334*36400Ssklower ENDDEBUG 335*36400Ssklower IFTRACE(D_CONN) 336*36400Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", 337*36400Ssklower *size, *negot, 0, 0); 338*36400Ssklower ENDTRACE 339*36400Ssklower 340*36400Ssklower } 341*36400Ssklower 342*36400Ssklower /* 343*36400Ssklower * NAME: tpip_output() 344*36400Ssklower * 345*36400Ssklower * CALLED FROM: tp_emit() 346*36400Ssklower * 347*36400Ssklower * FUNCTION and ARGUMENTS: 348*36400Ssklower * Take a packet(m0) from tp and package it so that ip will accept it. 349*36400Ssklower * This means prepending space for the ip header and filling in a few 350*36400Ssklower * of the fields. 351*36400Ssklower * inp is the inpcb structure; datalen is the length of the data in the 352*36400Ssklower * mbuf string m0. 353*36400Ssklower * RETURNS: 354*36400Ssklower * whatever (E*) is returned form the net layer output routine. 355*36400Ssklower * 356*36400Ssklower * SIDE EFFECTS: 357*36400Ssklower * 358*36400Ssklower * NOTES: 359*36400Ssklower */ 360*36400Ssklower 361*36400Ssklower int 362*36400Ssklower tpip_output(inp, m0, datalen, nochksum) 363*36400Ssklower struct inpcb *inp; 364*36400Ssklower struct mbuf *m0; 365*36400Ssklower int datalen; 366*36400Ssklower int nochksum; 367*36400Ssklower { 368*36400Ssklower return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, 369*36400Ssklower &inp->inp_route, nochksum); 370*36400Ssklower } 371*36400Ssklower 372*36400Ssklower /* 373*36400Ssklower * NAME: tpip_output_dg() 374*36400Ssklower * 375*36400Ssklower * CALLED FROM: tp_error_emit() 376*36400Ssklower * 377*36400Ssklower * FUNCTION and ARGUMENTS: 378*36400Ssklower * This is a copy of tpip_output that takes the addresses 379*36400Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 380*36400Ssklower * don't have an in_pcb with which to call the normal output rtn. 381*36400Ssklower * 382*36400Ssklower * RETURNS: ENOBUFS or whatever (E*) is 383*36400Ssklower * returned form the net layer output routine. 384*36400Ssklower * 385*36400Ssklower * SIDE EFFECTS: 386*36400Ssklower * 387*36400Ssklower * NOTES: 388*36400Ssklower */ 389*36400Ssklower 390*36400Ssklower int 391*36400Ssklower tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 392*36400Ssklower struct in_addr *laddr, *faddr; 393*36400Ssklower struct mbuf *m0; 394*36400Ssklower int datalen; 395*36400Ssklower struct route *ro; 396*36400Ssklower int nochksum; 397*36400Ssklower { 398*36400Ssklower register struct mbuf *m; 399*36400Ssklower register struct ip *ip; 400*36400Ssklower int error; 401*36400Ssklower 402*36400Ssklower IFDEBUG(D_EMIT) 403*36400Ssklower printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 404*36400Ssklower ENDDEBUG 405*36400Ssklower 406*36400Ssklower 407*36400Ssklower MGET(m, M_DONTWAIT, TPMT_IPHDR); 408*36400Ssklower if (m == 0) { 409*36400Ssklower error = ENOBUFS; 410*36400Ssklower goto bad; 411*36400Ssklower } 412*36400Ssklower bzero(mtod(m, caddr_t), MLEN); 413*36400Ssklower m->m_next = m0; 414*36400Ssklower m->m_off = MMAXOFF - sizeof(struct ip); 415*36400Ssklower m->m_len = sizeof(struct ip); 416*36400Ssklower m->m_act = MNULL; 417*36400Ssklower 418*36400Ssklower ip = mtod(m, struct ip *); 419*36400Ssklower 420*36400Ssklower ip->ip_p = IPPROTO_TP; 421*36400Ssklower ip->ip_len = sizeof(struct ip) + datalen; 422*36400Ssklower ip->ip_ttl = MAXTTL; 423*36400Ssklower /* don't know why you need to set ttl; 424*36400Ssklower * overlay doesn't even make this available 425*36400Ssklower */ 426*36400Ssklower 427*36400Ssklower ip->ip_src = *laddr; 428*36400Ssklower ip->ip_dst = *faddr; 429*36400Ssklower 430*36400Ssklower IncStat(ts_tpdu_sent); 431*36400Ssklower IFDEBUG(D_EMIT) 432*36400Ssklower dump_mbuf(m, "tpip_output_dg before ip_output\n"); 433*36400Ssklower ENDDEBUG 434*36400Ssklower 435*36400Ssklower error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST); 436*36400Ssklower 437*36400Ssklower IFDEBUG(D_EMIT) 438*36400Ssklower printf("tpip_output_dg after ip_output\n"); 439*36400Ssklower ENDDEBUG 440*36400Ssklower 441*36400Ssklower return error; 442*36400Ssklower 443*36400Ssklower bad: 444*36400Ssklower m_freem(m); 445*36400Ssklower IncStat(ts_send_drop); 446*36400Ssklower return error; 447*36400Ssklower } 448*36400Ssklower 449*36400Ssklower /* 450*36400Ssklower * NAME: tpip_input() 451*36400Ssklower * 452*36400Ssklower * CALLED FROM: 453*36400Ssklower * ip's input routine, indirectly through the protosw. 454*36400Ssklower * 455*36400Ssklower * FUNCTION and ARGUMENTS: 456*36400Ssklower * Take a packet (m) from ip, strip off the ip header and give it to tp 457*36400Ssklower * 458*36400Ssklower * RETURNS: No return value. 459*36400Ssklower * 460*36400Ssklower * SIDE EFFECTS: 461*36400Ssklower * 462*36400Ssklower * NOTES: 463*36400Ssklower */ 464*36400Ssklower ProtoHook 465*36400Ssklower tpip_input(m) 466*36400Ssklower struct mbuf *m; 467*36400Ssklower { 468*36400Ssklower typedef struct { 469*36400Ssklower struct ip tpip_i; 470*36400Ssklower struct tpdu tpip_d; 471*36400Ssklower } tpiphdr; 472*36400Ssklower register struct tpdu *hdr = mtod(m, struct tpdu *); 473*36400Ssklower struct sockaddr_in src, dst; 474*36400Ssklower register struct ip *ip; 475*36400Ssklower int s = splnet(); 476*36400Ssklower 477*36400Ssklower IncStat(ts_pkt_rcvd); 478*36400Ssklower 479*36400Ssklower /* IP layer has already pulled up the IP header */ 480*36400Ssklower 481*36400Ssklower while( m->m_len < 1 ) { 482*36400Ssklower struct mbuf *n; 483*36400Ssklower n = m_free(m); 484*36400Ssklower if( n == MNULL ) { 485*36400Ssklower splx(s); 486*36400Ssklower return 0; 487*36400Ssklower } 488*36400Ssklower } 489*36400Ssklower CHANGE_MTYPE(m, TPMT_DATA); 490*36400Ssklower 491*36400Ssklower /* 492*36400Ssklower * now pull up the whole tp header : we stripped all leading mbufs 493*36400Ssklower * w/o at least one byte, so we know we can read the tpdu_li field. 494*36400Ssklower */ 495*36400Ssklower hdr = &(mtod(m, tpiphdr *))->tpip_d; 496*36400Ssklower 497*36400Ssklower if( m->m_len < hdr->tpdu_li + 1 + sizeof(struct ip) ) { 498*36400Ssklower if((m = m_pullup(m, sizeof(struct ip) + (int)(hdr->tpdu_li)+1))==MNULL){ 499*36400Ssklower IFDEBUG(D_TPINPUT) 500*36400Ssklower printf("tp_input, pullup 2!\n"); 501*36400Ssklower ENDDEBUG 502*36400Ssklower goto discard; 503*36400Ssklower } 504*36400Ssklower } 505*36400Ssklower /* 506*36400Ssklower * cannot use tp_inputprep() here 'cause you don't 507*36400Ssklower * have quite the same situation 508*36400Ssklower */ 509*36400Ssklower 510*36400Ssklower IFDEBUG(D_TPINPUT) 511*36400Ssklower dump_mbuf(m, "after tpip_input both pullups"); 512*36400Ssklower ENDDEBUG 513*36400Ssklower /* 514*36400Ssklower * m_pullup may have returned a different mbuf 515*36400Ssklower */ 516*36400Ssklower ip = &(mtod(m, tpiphdr *))->tpip_i; 517*36400Ssklower 518*36400Ssklower /* 519*36400Ssklower * drop the ip header from the front of the mbuf 520*36400Ssklower * this is necessary for the tp checksum 521*36400Ssklower */ 522*36400Ssklower m->m_len -= sizeof(struct ip); 523*36400Ssklower m->m_off += sizeof(struct ip); 524*36400Ssklower 525*36400Ssklower src.sin_addr = *(struct in_addr *)&(ip->ip_src); 526*36400Ssklower src.sin_family = AF_INET; 527*36400Ssklower dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); 528*36400Ssklower dst.sin_family = AF_INET; 529*36400Ssklower 530*36400Ssklower (void) tp_input(m, &src, &dst, 0, tpip_output_dg); 531*36400Ssklower splx(s); 532*36400Ssklower return 0; 533*36400Ssklower 534*36400Ssklower discard: 535*36400Ssklower IFDEBUG(D_TPINPUT) 536*36400Ssklower printf("tpip_input DISCARD\n"); 537*36400Ssklower ENDDEBUG 538*36400Ssklower IFTRACE(D_TPINPUT) 539*36400Ssklower tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); 540*36400Ssklower ENDTRACE 541*36400Ssklower m_freem(m); 542*36400Ssklower IncStat(ts_recv_drop); 543*36400Ssklower 544*36400Ssklower return 0; 545*36400Ssklower } 546*36400Ssklower 547*36400Ssklower 548*36400Ssklower #include "../h/protosw.h" 549*36400Ssklower #include "../netinet/ip_icmp.h" 550*36400Ssklower 551*36400Ssklower /* 552*36400Ssklower * NAME: tpin_quench() 553*36400Ssklower * 554*36400Ssklower * CALLED FROM: tpip_ctlinput() 555*36400Ssklower * 556*36400Ssklower * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench 557*36400Ssklower * 558*36400Ssklower * RETURNS: Nada 559*36400Ssklower * 560*36400Ssklower * SIDE EFFECTS: 561*36400Ssklower * 562*36400Ssklower * NOTES: 563*36400Ssklower */ 564*36400Ssklower 565*36400Ssklower void 566*36400Ssklower tpin_quench(inp) 567*36400Ssklower struct inpcb *inp; 568*36400Ssklower { 569*36400Ssklower tp_quench( inp->inp_socket->so_tpcb ); 570*36400Ssklower } 571*36400Ssklower 572*36400Ssklower /* 573*36400Ssklower * NAME: tpip_ctlinput() 574*36400Ssklower * 575*36400Ssklower * CALLED FROM: 576*36400Ssklower * The network layer through the protosw table. 577*36400Ssklower * 578*36400Ssklower * FUNCTION and ARGUMENTS: 579*36400Ssklower * When clnp gets an ICMP msg this gets called. 580*36400Ssklower * It either returns an error status to the user or 581*36400Ssklower * causes all connections on this address to be aborted 582*36400Ssklower * by calling the appropriate xx_notify() routine. 583*36400Ssklower * (cmd) is the type of ICMP error. 584*36400Ssklower * (sa) the address of the sender 585*36400Ssklower * 586*36400Ssklower * RETURNS: Nothing 587*36400Ssklower * 588*36400Ssklower * SIDE EFFECTS: 589*36400Ssklower * 590*36400Ssklower * NOTES: 591*36400Ssklower */ 592*36400Ssklower ProtoHook 593*36400Ssklower tpip_ctlinput(cmd, sin) 594*36400Ssklower int cmd; 595*36400Ssklower struct sockaddr_in *sin; 596*36400Ssklower { 597*36400Ssklower extern u_char inetctlerrmap[]; 598*36400Ssklower extern ProtoHook tpin_abort(); 599*36400Ssklower extern ProtoHook in_rtchange(); 600*36400Ssklower 601*36400Ssklower if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) 602*36400Ssklower return 0; 603*36400Ssklower if (sin->sin_addr.s_addr == INADDR_ANY) 604*36400Ssklower return 0; 605*36400Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 606*36400Ssklower return 0; 607*36400Ssklower switch (cmd) { 608*36400Ssklower 609*36400Ssklower case PRC_QUENCH: 610*36400Ssklower in_pcbnotify(&tp_inpcb, &sin->sin_addr, 0, tp_quench); 611*36400Ssklower break; 612*36400Ssklower 613*36400Ssklower case PRC_ROUTEDEAD: 614*36400Ssklower case PRC_HOSTUNREACH: 615*36400Ssklower case PRC_UNREACH_NET: 616*36400Ssklower case PRC_IFDOWN: 617*36400Ssklower case PRC_HOSTDEAD: 618*36400Ssklower in_pcbnotify(&tp_inpcb, &sin->sin_addr, 619*36400Ssklower (int)inetctlerrmap[cmd], in_rtchange); 620*36400Ssklower break; 621*36400Ssklower 622*36400Ssklower default: 623*36400Ssklower /* 624*36400Ssklower case PRC_MSGSIZE: 625*36400Ssklower case PRC_UNREACH_HOST: 626*36400Ssklower case PRC_UNREACH_PROTOCOL: 627*36400Ssklower case PRC_UNREACH_PORT: 628*36400Ssklower case PRC_UNREACH_NEEDFRAG: 629*36400Ssklower case PRC_UNREACH_SRCFAIL: 630*36400Ssklower case PRC_REDIRECT_NET: 631*36400Ssklower case PRC_REDIRECT_HOST: 632*36400Ssklower case PRC_REDIRECT_TOSNET: 633*36400Ssklower case PRC_REDIRECT_TOSHOST: 634*36400Ssklower case PRC_TIMXCEED_INTRANS: 635*36400Ssklower case PRC_TIMXCEED_REASS: 636*36400Ssklower case PRC_PARAMPROB: 637*36400Ssklower */ 638*36400Ssklower in_pcbnotify(&tp_inpcb, sin, (int)inetctlerrmap[cmd], tpin_abort); 639*36400Ssklower } 640*36400Ssklower return 0; 641*36400Ssklower } 642*36400Ssklower 643*36400Ssklower /* 644*36400Ssklower * NAME: tpin_abort() 645*36400Ssklower * 646*36400Ssklower * CALLED FROM: 647*36400Ssklower * xxx_notify() from tp_ctlinput() when 648*36400Ssklower * net level gets some ICMP-equiv. type event. 649*36400Ssklower * 650*36400Ssklower * FUNCTION and ARGUMENTS: 651*36400Ssklower * Cause the connection to be aborted with some sort of error 652*36400Ssklower * reason indicating that the network layer caused the abort. 653*36400Ssklower * Fakes an ER TPDU so we can go through the driver. 654*36400Ssklower * 655*36400Ssklower * RETURNS: Nothing 656*36400Ssklower * 657*36400Ssklower * SIDE EFFECTS: 658*36400Ssklower * 659*36400Ssklower * NOTES: 660*36400Ssklower */ 661*36400Ssklower 662*36400Ssklower ProtoHook 663*36400Ssklower tpin_abort(inp) 664*36400Ssklower struct inpcb *inp; 665*36400Ssklower { 666*36400Ssklower struct tp_event e; 667*36400Ssklower 668*36400Ssklower e.ev_number = ER_TPDU; 669*36400Ssklower e.ATTR(ER_TPDU).e_reason = ENETRESET; 670*36400Ssklower (void) tp_driver(inp->inp_ppcb, &e); 671*36400Ssklower return 0; 672*36400Ssklower } 673*36400Ssklower 674*36400Ssklower #ifdef ARGO_DEBUG 675*36400Ssklower dump_inaddr(addr) 676*36400Ssklower register struct sockaddr_in *addr; 677*36400Ssklower { 678*36400Ssklower printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr); 679*36400Ssklower } 680*36400Ssklower #endif ARGO_DEBUG 681*36400Ssklower 682*36400Ssklower /* 683*36400Ssklower * NAME: tpip_route() 684*36400Ssklower * 685*36400Ssklower * CALLED FROM: tpip_mtu() 686*36400Ssklower * 687*36400Ssklower * FUNCTION and ARGUMENTS: given a destination addresss, 688*36400Ssklower * find the interface that would be used to send something to this address. 689*36400Ssklower * 690*36400Ssklower * RETURNS: pointer to an ifnet structure 691*36400Ssklower * 692*36400Ssklower * SIDE EFFECTS: 693*36400Ssklower * 694*36400Ssklower * NOTES: 695*36400Ssklower */ 696*36400Ssklower struct ifnet * 697*36400Ssklower tpip_route(dst) 698*36400Ssklower struct in_addr *dst; 699*36400Ssklower { 700*36400Ssklower struct ifnet *ifp = (struct ifnet *)0; 701*36400Ssklower struct sockaddr_in *dst_in; 702*36400Ssklower struct route iproute; 703*36400Ssklower struct route *ro = (struct route *)0; 704*36400Ssklower struct in_ifaddr *ia; 705*36400Ssklower 706*36400Ssklower IFDEBUG(D_CONN) 707*36400Ssklower printf("tpip_route: dst is x%x\n", *dst); 708*36400Ssklower ENDDEBUG 709*36400Ssklower 710*36400Ssklower ro = &iproute; 711*36400Ssklower bzero((caddr_t)ro, sizeof (*ro)); 712*36400Ssklower dst_in = (struct sockaddr_in *)&ro->ro_dst; 713*36400Ssklower dst_in->sin_family = AF_INET; 714*36400Ssklower dst_in->sin_addr = *dst; 715*36400Ssklower 716*36400Ssklower ia = (struct in_ifaddr *)ifa_ifwithdstaddr(dst_in); 717*36400Ssklower if (ia == 0) 718*36400Ssklower ia = in_iaonnetof(in_netof(dst_in)); 719*36400Ssklower if (ia != 0) { 720*36400Ssklower ifp = ia->ia_ifp; 721*36400Ssklower IFDEBUG(D_CONN) 722*36400Ssklower printf("tpip_route: ifp from ia:0x%x\n", ia); 723*36400Ssklower ENDDEBUG 724*36400Ssklower } else { 725*36400Ssklower rtalloc(ro); 726*36400Ssklower if (ro->ro_rt != 0) { 727*36400Ssklower ifp = ro->ro_rt->rt_ifp; 728*36400Ssklower IFDEBUG(D_CONN) 729*36400Ssklower printf("tpip_route: ifp from route:0x%x ro_rt 0x%x\n", ro, 730*36400Ssklower ro->ro_rt); 731*36400Ssklower ENDDEBUG 732*36400Ssklower rtfree(ro->ro_rt); 733*36400Ssklower } 734*36400Ssklower } 735*36400Ssklower IFDEBUG(D_CONN) 736*36400Ssklower printf("tpip_route: returning 0x%x\n", ifp); 737*36400Ssklower if (ifp) 738*36400Ssklower printf("tpip_route: if name %s unit 0x%x, mtu 0x%x\n", 739*36400Ssklower ifp->if_name, ifp->if_unit, ifp->if_mtu); 740*36400Ssklower ENDDEBUG 741*36400Ssklower return ifp; 742*36400Ssklower } 743*36400Ssklower 744*36400Ssklower #endif INET 745