136400Ssklower /*********************************************************** 236400Ssklower Copyright IBM Corporation 1987 336400Ssklower 436400Ssklower All Rights Reserved 536400Ssklower 636400Ssklower Permission to use, copy, modify, and distribute this software and its 736400Ssklower documentation for any purpose and without fee is hereby granted, 836400Ssklower provided that the above copyright notice appear in all copies and that 936400Ssklower both that copyright notice and this permission notice appear in 1036400Ssklower supporting documentation, and that the name of IBM not be 1136400Ssklower used in advertising or publicity pertaining to distribution of the 1236400Ssklower software without specific, written prior permission. 1336400Ssklower 1436400Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536400Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636400Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736400Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836400Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936400Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036400Ssklower SOFTWARE. 2136400Ssklower 2236400Ssklower ******************************************************************/ 2336400Ssklower 2436400Ssklower /* 2536400Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636400Ssklower */ 2736400Ssklower /* 2836400Ssklower * ARGO TP 2936400Ssklower * $Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $ 3036400Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_inet.c,v $ 31*39928Ssklower * @(#)tp_inet.c 7.5 (Berkeley) 01/16/90 * 3236400Ssklower * 3336400Ssklower * Here is where you find the inet-dependent code. We've tried 3436400Ssklower * keep all net-level and (primarily) address-family-dependent stuff 3536400Ssklower * out of the tp source, and everthing here is reached indirectly 3636400Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 3736400Ssklower * (see tp_pcb.c). 3836400Ssklower * The routines here are: 3936400Ssklower * in_getsufx: gets transport suffix out of an inpcb structure. 4036400Ssklower * in_putsufx: put transport suffix into an inpcb structure. 4136400Ssklower * in_putnetaddr: put a whole net addr into an inpcb. 4236400Ssklower * in_getnetaddr: get a whole net addr from an inpcb. 4336400Ssklower * in_recycle_suffix: clear suffix for reuse in inpcb 4436400Ssklower * tpip_mtu: figure out what size tpdu to use 4536400Ssklower * tpip_input: take a pkt from ip, strip off its ip header, give to tp 4636400Ssklower * tpip_output_dg: package a pkt for ip given 2 addresses & some data 4736400Ssklower * tpip_output: package a pkt for ip given an inpcb & some data 4836400Ssklower */ 4936400Ssklower 5036400Ssklower #ifndef lint 5136400Ssklower static char *rcsid = "$Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $"; 5236400Ssklower #endif lint 5336400Ssklower 5436400Ssklower #ifdef INET 5536400Ssklower 5637469Ssklower #include "param.h" 5736400Ssklower #include "socket.h" 5836400Ssklower #include "socketvar.h" 5936400Ssklower #include "mbuf.h" 6036400Ssklower #include "errno.h" 6136400Ssklower #include "time.h" 6236400Ssklower #include "../net/if.h" 6337469Ssklower #include "tp_param.h" 6437469Ssklower #include "argo_debug.h" 6537469Ssklower #include "tp_stat.h" 6637469Ssklower #include "tp_ip.h" 6737469Ssklower #include "tp_pcb.h" 6837469Ssklower #include "tp_trace.h" 6937469Ssklower #include "tp_stat.h" 7037469Ssklower #include "tp_tpdu.h" 7136400Ssklower #include "../netinet/in_var.h" 7236400Ssklower 7337469Ssklower #ifndef ISO 7437469Ssklower #include "iso_chksum.c" 7537469Ssklower #endif 7636400Ssklower 7736400Ssklower /* 7836400Ssklower * NAME: in_getsufx() 7936400Ssklower 8036400Ssklower * CALLED FROM: pr_usrreq() on PRU_BIND, 8136400Ssklower * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 8236400Ssklower * 8336400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 8436400Ssklower * Get a transport suffix from an inpcb structure (inp). 8536400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 8636400Ssklower * 8736400Ssklower * RETURNS: internet port / transport suffix 8836400Ssklower * (CAST TO AN INT) 8936400Ssklower * 9036400Ssklower * SIDE EFFECTS: 9136400Ssklower * 9236400Ssklower * NOTES: 9336400Ssklower */ 9437469Ssklower in_getsufx(inp, lenp, data_out, which) 9536400Ssklower struct inpcb *inp; 9637469Ssklower u_short *lenp; 9737469Ssklower caddr_t data_out; 9836400Ssklower int which; 9936400Ssklower { 10037469Ssklower *lenp = sizeof(u_short); 10136400Ssklower switch (which) { 10236400Ssklower case TP_LOCAL: 10337469Ssklower *(u_short *)data_out = inp->inp_lport; 10437469Ssklower return; 10536400Ssklower 10636400Ssklower case TP_FOREIGN: 10737469Ssklower *(u_short *)data_out = inp->inp_fport; 10836400Ssklower } 10937469Ssklower 11036400Ssklower } 11136400Ssklower 11236400Ssklower /* 11336400Ssklower * NAME: in_putsufx() 11436400Ssklower * 11536400Ssklower * CALLED FROM: tp_newsocket(); i.e., when a connection 11636400Ssklower * is being established by an incoming CR_TPDU. 11736400Ssklower * 11836400Ssklower * FUNCTION, ARGUMENTS: 11936400Ssklower * Put a transport suffix (found in name) into an inpcb structure (inp). 12036400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 12136400Ssklower * 12236400Ssklower * RETURNS: Nada 12336400Ssklower * 12436400Ssklower * SIDE EFFECTS: 12536400Ssklower * 12636400Ssklower * NOTES: 12736400Ssklower */ 12837469Ssklower /*ARGSUSED*/ 12936400Ssklower void 13037469Ssklower in_putsufx(inp, sufxloc, sufxlen, which) 13136400Ssklower struct inpcb *inp; 13237469Ssklower caddr_t sufxloc; 13336400Ssklower int which; 13436400Ssklower { 13537469Ssklower if (which == TP_FOREIGN) { 13637469Ssklower bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport)); 13736400Ssklower } 13836400Ssklower } 13936400Ssklower 14036400Ssklower /* 14136400Ssklower * NAME: in_recycle_tsuffix() 14236400Ssklower * 14336400Ssklower * CALLED FROM: tp.trans whenever we go into REFWAIT state. 14436400Ssklower * 14536400Ssklower * FUNCTION and ARGUMENT: 14636400Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 14736400Ssklower * (inp) is the net level pcb. 14836400Ssklower * 14936400Ssklower * RETURNS: Nada 15036400Ssklower * 15136400Ssklower * SIDE EFFECTS: 15236400Ssklower * 15336400Ssklower * NOTES: This really shouldn't have to be done in a NET level pcb 15436400Ssklower * but... for the internet world that just the way it is done in BSD... 15536400Ssklower * The alternative is to have the port unusable until the reference 15636400Ssklower * timer goes off. 15736400Ssklower */ 15836400Ssklower void 15936400Ssklower in_recycle_tsuffix(inp) 16036400Ssklower struct inpcb *inp; 16136400Ssklower { 16236400Ssklower inp->inp_fport = inp->inp_lport = 0; 16336400Ssklower } 16436400Ssklower 16536400Ssklower /* 16636400Ssklower * NAME: in_putnetaddr() 16736400Ssklower * 16836400Ssklower * CALLED FROM: 16936400Ssklower * tp_newsocket(); i.e., when a connection is being established by an 17036400Ssklower * incoming CR_TPDU. 17136400Ssklower * 17236400Ssklower * FUNCTION and ARGUMENTS: 17336400Ssklower * Copy a whole net addr from a struct sockaddr (name). 17436400Ssklower * into an inpcb (inp). 17536400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 17636400Ssklower * 17736400Ssklower * RETURNS: Nada 17836400Ssklower * 17936400Ssklower * SIDE EFFECTS: 18036400Ssklower * 18136400Ssklower * NOTES: 18236400Ssklower */ 18336400Ssklower void 18436400Ssklower in_putnetaddr(inp, name, which) 18536400Ssklower register struct inpcb *inp; 18636400Ssklower struct sockaddr_in *name; 18736400Ssklower int which; 18836400Ssklower { 18936400Ssklower switch (which) { 19036400Ssklower case TP_LOCAL: 19136400Ssklower bcopy((caddr_t)&name->sin_addr, 19236400Ssklower (caddr_t)&inp->inp_laddr, sizeof(struct in_addr)); 19336400Ssklower /* won't work if the dst address (name) is INADDR_ANY */ 19436400Ssklower 19536400Ssklower break; 19636400Ssklower case TP_FOREIGN: 19736400Ssklower if( name != (struct sockaddr_in *)0 ) { 19836400Ssklower bcopy((caddr_t)&name->sin_addr, 19936400Ssklower (caddr_t)&inp->inp_faddr, sizeof(struct in_addr)); 20036400Ssklower } 20136400Ssklower } 20236400Ssklower } 20336400Ssklower 20436400Ssklower /* 20536400Ssklower * NAME: in_getnetaddr() 20636400Ssklower * 20736400Ssklower * CALLED FROM: 20836400Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 20936400Ssklower * FUNCTION and ARGUMENTS: 21036400Ssklower * Copy a whole net addr from an inpcb (inp) into 21137469Ssklower * an mbuf (name); 21236400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 21336400Ssklower * 21436400Ssklower * RETURNS: Nada 21536400Ssklower * 21636400Ssklower * SIDE EFFECTS: 21736400Ssklower * 21836400Ssklower * NOTES: 21936400Ssklower */ 22036400Ssklower 22136400Ssklower void 22236400Ssklower in_getnetaddr( inp, name, which) 22337469Ssklower register struct mbuf *name; 22436400Ssklower struct inpcb *inp; 22536400Ssklower int which; 22636400Ssklower { 22737469Ssklower register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *); 22837469Ssklower bzero((caddr_t)sin, sizeof(*sin)); 22936400Ssklower switch (which) { 23036400Ssklower case TP_LOCAL: 23137469Ssklower sin->sin_addr = inp->inp_laddr; 23237469Ssklower sin->sin_port = inp->inp_lport; 23336400Ssklower break; 23436400Ssklower case TP_FOREIGN: 23537469Ssklower sin->sin_addr = inp->inp_faddr; 23637469Ssklower sin->sin_port = inp->inp_fport; 23736400Ssklower break; 23837469Ssklower default: 23937469Ssklower return; 24036400Ssklower } 24137469Ssklower name->m_len = sin->sin_len = sizeof (*sin); 24237469Ssklower sin->sin_family = AF_INET; 24336400Ssklower } 24436400Ssklower 24536400Ssklower /* 24636400Ssklower * NAME: tpip_mtu() 24736400Ssklower * 24836400Ssklower * CALLED FROM: 24936400Ssklower * tp_input() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 25036400Ssklower * 25136400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 25236400Ssklower * 25336400Ssklower * Determine the proper maximum transmission unit, i.e., MTU, to use, given 25436400Ssklower * a) the header size for the network protocol and the max transmission 25536400Ssklower * unit on the subnet interface, determined from the information in (inp), 25636400Ssklower * b) the max size negotiated so far (negot) 25736400Ssklower * c) the window size used by the tp connection (found in so), 25836400Ssklower * 25936400Ssklower * The result is put in the integer *size in its integer form and in 26036400Ssklower * *negot in its logarithmic form. 26136400Ssklower * 26236400Ssklower * The rules are: 26336400Ssklower * a) can only negotiate down from the value found in *negot. 26436400Ssklower * b) the MTU must be < the windowsize, 26536400Ssklower * c) If src and dest are on the same net, 26636400Ssklower * we will negotiate the closest size larger than MTU but really USE 26736400Ssklower * the actual device mtu - ll hdr sizes. 26836400Ssklower * otherwise we negotiate the closest size smaller than MTU - ll hdr sizes. 26936400Ssklower * 27036400Ssklower * SIDE EFFECTS: 27136400Ssklower * changes the values addressed by the arguments (size) and (negot) 27236400Ssklower * and 27336400Ssklower * when the peer is not on one of our directly connected subnets, it 27436400Ssklower * looks up a route, leaving the route in the inpcb addressed by (inp) 27536400Ssklower * 27636400Ssklower * NOTES: 27736400Ssklower */ 27836400Ssklower 27936400Ssklower void 28036400Ssklower tpip_mtu(so, inp, size, negot) 28136400Ssklower struct socket *so; 28236400Ssklower struct inpcb *inp; 28336400Ssklower int *size; 28436400Ssklower u_char *negot; 28536400Ssklower { 28636400Ssklower register struct ifnet *ifp; 28736400Ssklower struct ifnet *tpip_route(); 28836400Ssklower struct in_ifaddr *ia; 28936400Ssklower register int i; 29036400Ssklower int windowsize = so->so_rcv.sb_hiwat; 29136400Ssklower 29236400Ssklower IFDEBUG(D_CONN) 29336400Ssklower printf("tpip_mtu(0x%x,0x%x,0x%x,0x%x)\n", 29436400Ssklower so, inp, size, negot); 29536400Ssklower printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr); 29636400Ssklower ENDDEBUG 29736400Ssklower IFTRACE(D_CONN) 29836400Ssklower tptrace(TPPTmisc, "ENTER GET MTU: size negot \n",*size, *negot, 0, 0); 29936400Ssklower ENDTRACE 30036400Ssklower 30136400Ssklower *size = 1 << *negot; 30236400Ssklower 30336400Ssklower if( *size > windowsize ) { 30436400Ssklower *size = windowsize; 30536400Ssklower } 30636400Ssklower 30736400Ssklower ia = in_iaonnetof(in_netof(inp->inp_faddr)); 30836400Ssklower if ( ia == (struct in_ifaddr *)0 ) { 30936400Ssklower ifp = tpip_route(&inp->inp_faddr); 31036400Ssklower if( ifp == (struct ifnet *)0 ) 31136400Ssklower return ; 31236400Ssklower } else 31336400Ssklower ifp = ia->ia_ifp; 31436400Ssklower 31536400Ssklower 31636400Ssklower /**************************************************************** 31736400Ssklower * TODO - make this indirect off the socket structure to the 31836400Ssklower * network layer to get headersize 31936400Ssklower * After all, who knows what lies below the IP layer? 32036400Ssklower * Who knows how big the NL header will be? 32136400Ssklower ***************************************************************/ 32236400Ssklower 32336400Ssklower if( *size > ifp->if_mtu - sizeof(struct ip)) { 32436400Ssklower *size = ifp->if_mtu - sizeof(struct ip); 32536400Ssklower } 32636400Ssklower for(i=TP_MIN_TPDUSIZE; (i<TP_MAX_TPDUSIZE && ((1<<i)<*size)) ; i++) 32736400Ssklower ; 32836400Ssklower i--; 32936400Ssklower 33036400Ssklower if (in_netof(inp->inp_laddr) != in_netof(inp->inp_faddr)) { 33136400Ssklower i++; 33236400Ssklower } else { 33336400Ssklower *size = 1<<i; 33436400Ssklower } 33536400Ssklower *negot = i; 33636400Ssklower 33736400Ssklower IFDEBUG(D_CONN) 33836400Ssklower printf("GET MTU RETURNS: ifp %s size 0x%x negot 0x%x\n", 33936400Ssklower ifp->if_name, *size, *negot); 34036400Ssklower ENDDEBUG 34136400Ssklower IFTRACE(D_CONN) 34236400Ssklower tptrace(TPPTmisc, "EXIT GET MTU: tpcb size negot \n", 34336400Ssklower *size, *negot, 0, 0); 34436400Ssklower ENDTRACE 34536400Ssklower 34636400Ssklower } 34736400Ssklower 34836400Ssklower /* 34936400Ssklower * NAME: tpip_output() 35036400Ssklower * 35136400Ssklower * CALLED FROM: tp_emit() 35236400Ssklower * 35336400Ssklower * FUNCTION and ARGUMENTS: 35436400Ssklower * Take a packet(m0) from tp and package it so that ip will accept it. 35536400Ssklower * This means prepending space for the ip header and filling in a few 35636400Ssklower * of the fields. 35736400Ssklower * inp is the inpcb structure; datalen is the length of the data in the 35836400Ssklower * mbuf string m0. 35936400Ssklower * RETURNS: 36036400Ssklower * whatever (E*) is returned form the net layer output routine. 36136400Ssklower * 36236400Ssklower * SIDE EFFECTS: 36336400Ssklower * 36436400Ssklower * NOTES: 36536400Ssklower */ 36636400Ssklower 36736400Ssklower int 36836400Ssklower tpip_output(inp, m0, datalen, nochksum) 36936400Ssklower struct inpcb *inp; 37036400Ssklower struct mbuf *m0; 37136400Ssklower int datalen; 37236400Ssklower int nochksum; 37336400Ssklower { 37436400Ssklower return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, 37536400Ssklower &inp->inp_route, nochksum); 37636400Ssklower } 37736400Ssklower 37836400Ssklower /* 37936400Ssklower * NAME: tpip_output_dg() 38036400Ssklower * 38136400Ssklower * CALLED FROM: tp_error_emit() 38236400Ssklower * 38336400Ssklower * FUNCTION and ARGUMENTS: 38436400Ssklower * This is a copy of tpip_output that takes the addresses 38536400Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 38636400Ssklower * don't have an in_pcb with which to call the normal output rtn. 38736400Ssklower * 38836400Ssklower * RETURNS: ENOBUFS or whatever (E*) is 38936400Ssklower * returned form the net layer output routine. 39036400Ssklower * 39136400Ssklower * SIDE EFFECTS: 39236400Ssklower * 39336400Ssklower * NOTES: 39436400Ssklower */ 39536400Ssklower 39637469Ssklower /*ARGSUSED*/ 39736400Ssklower int 39836400Ssklower tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 39936400Ssklower struct in_addr *laddr, *faddr; 40036400Ssklower struct mbuf *m0; 40136400Ssklower int datalen; 40236400Ssklower struct route *ro; 40336400Ssklower int nochksum; 40436400Ssklower { 40536400Ssklower register struct mbuf *m; 40636400Ssklower register struct ip *ip; 40736400Ssklower int error; 40836400Ssklower 40936400Ssklower IFDEBUG(D_EMIT) 41036400Ssklower printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 41136400Ssklower ENDDEBUG 41236400Ssklower 41336400Ssklower 41437469Ssklower MGETHDR(m, M_DONTWAIT, TPMT_IPHDR); 41536400Ssklower if (m == 0) { 41636400Ssklower error = ENOBUFS; 41736400Ssklower goto bad; 41836400Ssklower } 41936400Ssklower m->m_next = m0; 42037469Ssklower MH_ALIGN(m, sizeof(struct ip)); 42136400Ssklower m->m_len = sizeof(struct ip); 42236400Ssklower 42336400Ssklower ip = mtod(m, struct ip *); 42437469Ssklower bzero((caddr_t)ip, sizeof *ip); 42536400Ssklower 42636400Ssklower ip->ip_p = IPPROTO_TP; 42737469Ssklower m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen; 42836400Ssklower ip->ip_ttl = MAXTTL; 42936400Ssklower /* don't know why you need to set ttl; 43036400Ssklower * overlay doesn't even make this available 43136400Ssklower */ 43236400Ssklower 43336400Ssklower ip->ip_src = *laddr; 43436400Ssklower ip->ip_dst = *faddr; 43536400Ssklower 43636400Ssklower IncStat(ts_tpdu_sent); 43736400Ssklower IFDEBUG(D_EMIT) 43836400Ssklower dump_mbuf(m, "tpip_output_dg before ip_output\n"); 43936400Ssklower ENDDEBUG 44036400Ssklower 44136400Ssklower error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST); 44236400Ssklower 44336400Ssklower IFDEBUG(D_EMIT) 44436400Ssklower printf("tpip_output_dg after ip_output\n"); 44536400Ssklower ENDDEBUG 44636400Ssklower 44736400Ssklower return error; 44836400Ssklower 44936400Ssklower bad: 45036400Ssklower m_freem(m); 45136400Ssklower IncStat(ts_send_drop); 45236400Ssklower return error; 45336400Ssklower } 45436400Ssklower 45536400Ssklower /* 45636400Ssklower * NAME: tpip_input() 45736400Ssklower * 45836400Ssklower * CALLED FROM: 45936400Ssklower * ip's input routine, indirectly through the protosw. 46036400Ssklower * 46136400Ssklower * FUNCTION and ARGUMENTS: 46236400Ssklower * Take a packet (m) from ip, strip off the ip header and give it to tp 46336400Ssklower * 46436400Ssklower * RETURNS: No return value. 46536400Ssklower * 46636400Ssklower * SIDE EFFECTS: 46736400Ssklower * 46836400Ssklower * NOTES: 46936400Ssklower */ 47036400Ssklower ProtoHook 47137469Ssklower tpip_input(m, iplen) 47236400Ssklower struct mbuf *m; 47337469Ssklower int iplen; 47436400Ssklower { 47536400Ssklower struct sockaddr_in src, dst; 47636400Ssklower register struct ip *ip; 47737469Ssklower int s = splnet(), hdrlen; 47836400Ssklower 47936400Ssklower IncStat(ts_pkt_rcvd); 48036400Ssklower 48137469Ssklower /* 48237469Ssklower * IP layer has already pulled up the IP header, 48337469Ssklower * but the first byte after the IP header may not be there, 48437469Ssklower * e.g. if you came in via loopback, so you have to do an 48537469Ssklower * m_pullup to before you can even look to see how much you 48637469Ssklower * really need. The good news is that m_pullup will round 48737469Ssklower * up to almost the next mbuf's worth. 48837469Ssklower */ 48936400Ssklower 49037469Ssklower 49137469Ssklower if((m = m_pullup(m, iplen + 1)) == MNULL) 49237469Ssklower goto discard; 49336400Ssklower CHANGE_MTYPE(m, TPMT_DATA); 49436400Ssklower 49536400Ssklower /* 49637469Ssklower * Now pull up the whole tp header: 49737469Ssklower * Unfortunately, there may be IP options to skip past so we 49837469Ssklower * just fetch it as an unsigned char. 49936400Ssklower */ 50037469Ssklower hdrlen = iplen + 1 + mtod(m, u_char *)[iplen]; 50136400Ssklower 50237469Ssklower if( m->m_len < hdrlen ) { 50337469Ssklower if((m = m_pullup(m, hdrlen)) == MNULL){ 50436400Ssklower IFDEBUG(D_TPINPUT) 50536400Ssklower printf("tp_input, pullup 2!\n"); 50636400Ssklower ENDDEBUG 50736400Ssklower goto discard; 50836400Ssklower } 50936400Ssklower } 51036400Ssklower /* 51136400Ssklower * cannot use tp_inputprep() here 'cause you don't 51236400Ssklower * have quite the same situation 51336400Ssklower */ 51436400Ssklower 51536400Ssklower IFDEBUG(D_TPINPUT) 51636400Ssklower dump_mbuf(m, "after tpip_input both pullups"); 51736400Ssklower ENDDEBUG 51836400Ssklower /* 51936400Ssklower * m_pullup may have returned a different mbuf 52036400Ssklower */ 52137469Ssklower ip = mtod(m, struct ip *); 52236400Ssklower 52336400Ssklower /* 52436400Ssklower * drop the ip header from the front of the mbuf 52536400Ssklower * this is necessary for the tp checksum 52636400Ssklower */ 52737469Ssklower m->m_len -= iplen; 52837469Ssklower m->m_data += iplen; 52936400Ssklower 53036400Ssklower src.sin_addr = *(struct in_addr *)&(ip->ip_src); 53136400Ssklower src.sin_family = AF_INET; 53237469Ssklower src.sin_len = sizeof(src); 53336400Ssklower dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); 53436400Ssklower dst.sin_family = AF_INET; 53537469Ssklower dst.sin_len = sizeof(dst); 53636400Ssklower 53737469Ssklower (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, 538*39928Ssklower 0, tpip_output_dg, 0); 53936400Ssklower return 0; 54036400Ssklower 54136400Ssklower discard: 54236400Ssklower IFDEBUG(D_TPINPUT) 54336400Ssklower printf("tpip_input DISCARD\n"); 54436400Ssklower ENDDEBUG 54536400Ssklower IFTRACE(D_TPINPUT) 54636400Ssklower tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); 54736400Ssklower ENDTRACE 54836400Ssklower m_freem(m); 54936400Ssklower IncStat(ts_recv_drop); 55037469Ssklower splx(s); 55136400Ssklower return 0; 55236400Ssklower } 55336400Ssklower 55436400Ssklower 55537536Smckusick #include "protosw.h" 55636400Ssklower #include "../netinet/ip_icmp.h" 55736400Ssklower 55837469Ssklower extern void tp_quench(); 55936400Ssklower /* 56036400Ssklower * NAME: tpin_quench() 56136400Ssklower * 56236400Ssklower * CALLED FROM: tpip_ctlinput() 56336400Ssklower * 56436400Ssklower * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench 56536400Ssklower * 56636400Ssklower * RETURNS: Nada 56736400Ssklower * 56836400Ssklower * SIDE EFFECTS: 56936400Ssklower * 57036400Ssklower * NOTES: 57136400Ssklower */ 57236400Ssklower 57336400Ssklower void 57436400Ssklower tpin_quench(inp) 57536400Ssklower struct inpcb *inp; 57636400Ssklower { 57737469Ssklower tp_quench((struct tp_pcb *)inp->inp_socket->so_tpcb, PRC_QUENCH); 57836400Ssklower } 57936400Ssklower 58036400Ssklower /* 58136400Ssklower * NAME: tpip_ctlinput() 58236400Ssklower * 58336400Ssklower * CALLED FROM: 58436400Ssklower * The network layer through the protosw table. 58536400Ssklower * 58636400Ssklower * FUNCTION and ARGUMENTS: 58736400Ssklower * When clnp gets an ICMP msg this gets called. 58836400Ssklower * It either returns an error status to the user or 58936400Ssklower * causes all connections on this address to be aborted 59036400Ssklower * by calling the appropriate xx_notify() routine. 59136400Ssklower * (cmd) is the type of ICMP error. 59236400Ssklower * (sa) the address of the sender 59336400Ssklower * 59436400Ssklower * RETURNS: Nothing 59536400Ssklower * 59636400Ssklower * SIDE EFFECTS: 59736400Ssklower * 59836400Ssklower * NOTES: 59936400Ssklower */ 60036400Ssklower ProtoHook 60136400Ssklower tpip_ctlinput(cmd, sin) 60236400Ssklower int cmd; 60336400Ssklower struct sockaddr_in *sin; 60436400Ssklower { 60536400Ssklower extern u_char inetctlerrmap[]; 60636400Ssklower extern ProtoHook tpin_abort(); 60736400Ssklower extern ProtoHook in_rtchange(); 60836400Ssklower 60936400Ssklower if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) 61036400Ssklower return 0; 61136400Ssklower if (sin->sin_addr.s_addr == INADDR_ANY) 61236400Ssklower return 0; 61336400Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 61436400Ssklower return 0; 61536400Ssklower switch (cmd) { 61636400Ssklower 61736400Ssklower case PRC_QUENCH: 618*39928Ssklower in_pcbnotify(&tp_inpcb, sin, 61937469Ssklower 0, (int (*)())tp_quench); 62036400Ssklower break; 62136400Ssklower 62236400Ssklower case PRC_ROUTEDEAD: 62336400Ssklower case PRC_HOSTUNREACH: 62436400Ssklower case PRC_UNREACH_NET: 62536400Ssklower case PRC_IFDOWN: 62636400Ssklower case PRC_HOSTDEAD: 627*39928Ssklower in_pcbnotify(&tp_inpcb, sin, 62836400Ssklower (int)inetctlerrmap[cmd], in_rtchange); 62936400Ssklower break; 63036400Ssklower 63136400Ssklower default: 63236400Ssklower /* 63336400Ssklower case PRC_MSGSIZE: 63436400Ssklower case PRC_UNREACH_HOST: 63536400Ssklower case PRC_UNREACH_PROTOCOL: 63636400Ssklower case PRC_UNREACH_PORT: 63736400Ssklower case PRC_UNREACH_NEEDFRAG: 63836400Ssklower case PRC_UNREACH_SRCFAIL: 63936400Ssklower case PRC_REDIRECT_NET: 64036400Ssklower case PRC_REDIRECT_HOST: 64136400Ssklower case PRC_REDIRECT_TOSNET: 64236400Ssklower case PRC_REDIRECT_TOSHOST: 64336400Ssklower case PRC_TIMXCEED_INTRANS: 64436400Ssklower case PRC_TIMXCEED_REASS: 64536400Ssklower case PRC_PARAMPROB: 64636400Ssklower */ 647*39928Ssklower in_pcbnotify(&tp_inpcb, sin, 64837469Ssklower (int)inetctlerrmap[cmd], tpin_abort); 64936400Ssklower } 65036400Ssklower return 0; 65136400Ssklower } 65236400Ssklower 65336400Ssklower /* 65436400Ssklower * NAME: tpin_abort() 65536400Ssklower * 65636400Ssklower * CALLED FROM: 65736400Ssklower * xxx_notify() from tp_ctlinput() when 65836400Ssklower * net level gets some ICMP-equiv. type event. 65936400Ssklower * 66036400Ssklower * FUNCTION and ARGUMENTS: 66136400Ssklower * Cause the connection to be aborted with some sort of error 66236400Ssklower * reason indicating that the network layer caused the abort. 66336400Ssklower * Fakes an ER TPDU so we can go through the driver. 66436400Ssklower * 66536400Ssklower * RETURNS: Nothing 66636400Ssklower * 66736400Ssklower * SIDE EFFECTS: 66836400Ssklower * 66936400Ssklower * NOTES: 67036400Ssklower */ 67136400Ssklower 67236400Ssklower ProtoHook 67336400Ssklower tpin_abort(inp) 67436400Ssklower struct inpcb *inp; 67536400Ssklower { 67636400Ssklower struct tp_event e; 67736400Ssklower 67836400Ssklower e.ev_number = ER_TPDU; 67936400Ssklower e.ATTR(ER_TPDU).e_reason = ENETRESET; 68037469Ssklower (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e); 68136400Ssklower return 0; 68236400Ssklower } 68336400Ssklower 68436400Ssklower #ifdef ARGO_DEBUG 68536400Ssklower dump_inaddr(addr) 68636400Ssklower register struct sockaddr_in *addr; 68736400Ssklower { 68836400Ssklower printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr); 68936400Ssklower } 69036400Ssklower #endif ARGO_DEBUG 69136400Ssklower 69236400Ssklower /* 69336400Ssklower * NAME: tpip_route() 69436400Ssklower * 69536400Ssklower * CALLED FROM: tpip_mtu() 69636400Ssklower * 69736400Ssklower * FUNCTION and ARGUMENTS: given a destination addresss, 69836400Ssklower * find the interface that would be used to send something to this address. 69936400Ssklower * 70036400Ssklower * RETURNS: pointer to an ifnet structure 70136400Ssklower * 70236400Ssklower * SIDE EFFECTS: 70336400Ssklower * 70436400Ssklower * NOTES: 70536400Ssklower */ 70636400Ssklower struct ifnet * 70736400Ssklower tpip_route(dst) 70836400Ssklower struct in_addr *dst; 70936400Ssklower { 71037469Ssklower struct ifnet *ifp = (struct ifnet *)0; 71137469Ssklower struct sockaddr_in insock; 71237469Ssklower struct sockaddr_in *sin = &insock; 71337469Ssklower struct rtentry *rt; 71437469Ssklower struct ifaddr *ia; 71536400Ssklower 71636400Ssklower IFDEBUG(D_CONN) 71736400Ssklower printf("tpip_route: dst is x%x\n", *dst); 71836400Ssklower ENDDEBUG 71936400Ssklower 72037469Ssklower bzero((caddr_t)sin, sizeof (*sin)); 72137469Ssklower sin->sin_family = AF_INET; 72237469Ssklower sin->sin_len = sizeof(*sin); 72337469Ssklower sin->sin_addr = *dst; 72436400Ssklower 72537469Ssklower ia = ifa_ifwithdstaddr((struct sockaddr *)sin); 72636400Ssklower if (ia == 0) 72737469Ssklower ia = ifa_ifwithnet((struct sockaddr *)sin); 72836400Ssklower if (ia != 0) { 72937469Ssklower ifp = ia->ifa_ifp; 73036400Ssklower IFDEBUG(D_CONN) 73136400Ssklower printf("tpip_route: ifp from ia:0x%x\n", ia); 73236400Ssklower ENDDEBUG 73336400Ssklower } else { 73437469Ssklower rt = rtalloc1((struct sockaddr *)sin, 0); 73537469Ssklower if (rt != 0) { 73637469Ssklower ifp = rt->rt_ifp; 73736400Ssklower IFDEBUG(D_CONN) 73837469Ssklower printf("tpip_route: ifp from rentry: 0x%x\n", rt); 73936400Ssklower ENDDEBUG 74037469Ssklower rtfree(rt); 74136400Ssklower } 74236400Ssklower } 74336400Ssklower IFDEBUG(D_CONN) 74436400Ssklower printf("tpip_route: returning 0x%x\n", ifp); 74536400Ssklower if (ifp) 74636400Ssklower printf("tpip_route: if name %s unit 0x%x, mtu 0x%x\n", 74736400Ssklower ifp->if_name, ifp->if_unit, ifp->if_mtu); 74836400Ssklower ENDDEBUG 74936400Ssklower return ifp; 75036400Ssklower } 75136400Ssklower 75236400Ssklower #endif INET 753