149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*51246Ssklower * @(#)tp_inet.c 7.10 (Berkeley) 10/02/91 849268Sbostic */ 949268Sbostic 1036400Ssklower /*********************************************************** 1136400Ssklower Copyright IBM Corporation 1987 1236400Ssklower 1336400Ssklower All Rights Reserved 1436400Ssklower 1536400Ssklower Permission to use, copy, modify, and distribute this software and its 1636400Ssklower documentation for any purpose and without fee is hereby granted, 1736400Ssklower provided that the above copyright notice appear in all copies and that 1836400Ssklower both that copyright notice and this permission notice appear in 1936400Ssklower supporting documentation, and that the name of IBM not be 2036400Ssklower used in advertising or publicity pertaining to distribution of the 2136400Ssklower software without specific, written prior permission. 2236400Ssklower 2336400Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436400Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536400Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636400Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736400Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836400Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936400Ssklower SOFTWARE. 3036400Ssklower 3136400Ssklower ******************************************************************/ 3236400Ssklower 3336400Ssklower /* 3436400Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536400Ssklower */ 3636400Ssklower /* 3736400Ssklower * ARGO TP 3836400Ssklower * $Header: tp_inet.c,v 5.3 88/11/18 17:27:29 nhall Exp $ 3936400Ssklower * $Source: /usr/argo/sys/netiso/RCS/tp_inet.c,v $ 4036400Ssklower * 4136400Ssklower * Here is where you find the inet-dependent code. We've tried 4236400Ssklower * keep all net-level and (primarily) address-family-dependent stuff 4336400Ssklower * out of the tp source, and everthing here is reached indirectly 4436400Ssklower * through a switch table (struct nl_protosw *) tpcb->tp_nlproto 4536400Ssklower * (see tp_pcb.c). 4636400Ssklower * The routines here are: 4749268Sbostic * in_getsufx: gets transport suffix out of an inpcb structure. 4849268Sbostic * in_putsufx: put transport suffix into an inpcb structure. 4949268Sbostic * in_putnetaddr: put a whole net addr into an inpcb. 5049268Sbostic * in_getnetaddr: get a whole net addr from an inpcb. 5149268Sbostic * in_cmpnetaddr: compare a whole net addr from an isopcb. 5249268Sbostic * in_recycle_suffix: clear suffix for reuse in inpcb 5349268Sbostic * tpip_mtu: figure out what size tpdu to use 5449268Sbostic * tpip_input: take a pkt from ip, strip off its ip header, give to tp 5549268Sbostic * tpip_output_dg: package a pkt for ip given 2 addresses & some data 5649268Sbostic * tpip_output: package a pkt for ip given an inpcb & some data 5736400Ssklower */ 5836400Ssklower 5936400Ssklower #ifdef INET 6036400Ssklower 6137469Ssklower #include "param.h" 6236400Ssklower #include "socket.h" 6336400Ssklower #include "socketvar.h" 6436400Ssklower #include "mbuf.h" 6536400Ssklower #include "errno.h" 6636400Ssklower #include "time.h" 6736400Ssklower #include "../net/if.h" 6837469Ssklower #include "tp_param.h" 6937469Ssklower #include "argo_debug.h" 7037469Ssklower #include "tp_stat.h" 7137469Ssklower #include "tp_ip.h" 7237469Ssklower #include "tp_pcb.h" 7337469Ssklower #include "tp_trace.h" 7437469Ssklower #include "tp_stat.h" 7537469Ssklower #include "tp_tpdu.h" 7636400Ssklower #include "../netinet/in_var.h" 7736400Ssklower 7837469Ssklower #ifndef ISO 7937469Ssklower #include "iso_chksum.c" 8037469Ssklower #endif 8136400Ssklower 8236400Ssklower /* 8336400Ssklower * NAME: in_getsufx() 8436400Ssklower 8536400Ssklower * CALLED FROM: pr_usrreq() on PRU_BIND, 8636400Ssklower * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR 8736400Ssklower * 8836400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 8936400Ssklower * Get a transport suffix from an inpcb structure (inp). 9036400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 9136400Ssklower * 9236400Ssklower * RETURNS: internet port / transport suffix 9336400Ssklower * (CAST TO AN INT) 9436400Ssklower * 9536400Ssklower * SIDE EFFECTS: 9636400Ssklower * 9736400Ssklower * NOTES: 9836400Ssklower */ 9937469Ssklower in_getsufx(inp, lenp, data_out, which) 10036400Ssklower struct inpcb *inp; 10137469Ssklower u_short *lenp; 10237469Ssklower caddr_t data_out; 10336400Ssklower int which; 10436400Ssklower { 10537469Ssklower *lenp = sizeof(u_short); 10636400Ssklower switch (which) { 10736400Ssklower case TP_LOCAL: 10837469Ssklower *(u_short *)data_out = inp->inp_lport; 10937469Ssklower return; 11036400Ssklower 11136400Ssklower case TP_FOREIGN: 11237469Ssklower *(u_short *)data_out = inp->inp_fport; 11336400Ssklower } 11437469Ssklower 11536400Ssklower } 11636400Ssklower 11736400Ssklower /* 11836400Ssklower * NAME: in_putsufx() 11936400Ssklower * 12036400Ssklower * CALLED FROM: tp_newsocket(); i.e., when a connection 12136400Ssklower * is being established by an incoming CR_TPDU. 12236400Ssklower * 12336400Ssklower * FUNCTION, ARGUMENTS: 12436400Ssklower * Put a transport suffix (found in name) into an inpcb structure (inp). 12536400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN. 12636400Ssklower * 12736400Ssklower * RETURNS: Nada 12836400Ssklower * 12936400Ssklower * SIDE EFFECTS: 13036400Ssklower * 13136400Ssklower * NOTES: 13236400Ssklower */ 13337469Ssklower /*ARGSUSED*/ 13436400Ssklower void 13537469Ssklower in_putsufx(inp, sufxloc, sufxlen, which) 13636400Ssklower struct inpcb *inp; 13737469Ssklower caddr_t sufxloc; 13836400Ssklower int which; 13936400Ssklower { 14037469Ssklower if (which == TP_FOREIGN) { 14137469Ssklower bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport)); 14236400Ssklower } 14336400Ssklower } 14436400Ssklower 14536400Ssklower /* 14636400Ssklower * NAME: in_recycle_tsuffix() 14736400Ssklower * 14836400Ssklower * CALLED FROM: tp.trans whenever we go into REFWAIT state. 14936400Ssklower * 15036400Ssklower * FUNCTION and ARGUMENT: 15136400Ssklower * Called when a ref is frozen, to allow the suffix to be reused. 15236400Ssklower * (inp) is the net level pcb. 15336400Ssklower * 15436400Ssklower * RETURNS: Nada 15536400Ssklower * 15636400Ssklower * SIDE EFFECTS: 15736400Ssklower * 15836400Ssklower * NOTES: This really shouldn't have to be done in a NET level pcb 15936400Ssklower * but... for the internet world that just the way it is done in BSD... 16036400Ssklower * The alternative is to have the port unusable until the reference 16136400Ssklower * timer goes off. 16236400Ssklower */ 16336400Ssklower void 16436400Ssklower in_recycle_tsuffix(inp) 16536400Ssklower struct inpcb *inp; 16636400Ssklower { 16736400Ssklower inp->inp_fport = inp->inp_lport = 0; 16836400Ssklower } 16936400Ssklower 17036400Ssklower /* 17136400Ssklower * NAME: in_putnetaddr() 17236400Ssklower * 17336400Ssklower * CALLED FROM: 17436400Ssklower * tp_newsocket(); i.e., when a connection is being established by an 17536400Ssklower * incoming CR_TPDU. 17636400Ssklower * 17736400Ssklower * FUNCTION and ARGUMENTS: 17836400Ssklower * Copy a whole net addr from a struct sockaddr (name). 17936400Ssklower * into an inpcb (inp). 18036400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 18136400Ssklower * 18236400Ssklower * RETURNS: Nada 18336400Ssklower * 18436400Ssklower * SIDE EFFECTS: 18536400Ssklower * 18636400Ssklower * NOTES: 18736400Ssklower */ 18836400Ssklower void 18936400Ssklower in_putnetaddr(inp, name, which) 19036400Ssklower register struct inpcb *inp; 19136400Ssklower struct sockaddr_in *name; 19236400Ssklower int which; 19336400Ssklower { 19436400Ssklower switch (which) { 19536400Ssklower case TP_LOCAL: 19636400Ssklower bcopy((caddr_t)&name->sin_addr, 19736400Ssklower (caddr_t)&inp->inp_laddr, sizeof(struct in_addr)); 19836400Ssklower /* won't work if the dst address (name) is INADDR_ANY */ 19936400Ssklower 20036400Ssklower break; 20136400Ssklower case TP_FOREIGN: 20236400Ssklower if( name != (struct sockaddr_in *)0 ) { 20336400Ssklower bcopy((caddr_t)&name->sin_addr, 20436400Ssklower (caddr_t)&inp->inp_faddr, sizeof(struct in_addr)); 20536400Ssklower } 20636400Ssklower } 20736400Ssklower } 20836400Ssklower 20936400Ssklower /* 21044422Ssklower * NAME: in_putnetaddr() 21144422Ssklower * 21244422Ssklower * CALLED FROM: 21344422Ssklower * tp_input() when a connection is being established by an 21444422Ssklower * incoming CR_TPDU, and considered for interception. 21544422Ssklower * 21644422Ssklower * FUNCTION and ARGUMENTS: 21744422Ssklower * Compare a whole net addr from a struct sockaddr (name), 21844422Ssklower * with that implicitly stored in an inpcb (inp). 21944422Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN 22044422Ssklower * 22144422Ssklower * RETURNS: Nada 22244422Ssklower * 22344422Ssklower * SIDE EFFECTS: 22444422Ssklower * 22544422Ssklower * NOTES: 22644422Ssklower */ 22744422Ssklower in_cmpnetaddr(inp, name, which) 22844422Ssklower register struct inpcb *inp; 22944422Ssklower register struct sockaddr_in *name; 23044422Ssklower int which; 23144422Ssklower { 23244422Ssklower if (which == TP_LOCAL) { 23344422Ssklower if (name->sin_port && name->sin_port != inp->inp_lport) 23444422Ssklower return 0; 23544422Ssklower return (name->sin_addr.s_addr == inp->inp_laddr.s_addr); 23644422Ssklower } 23744422Ssklower if (name->sin_port && name->sin_port != inp->inp_fport) 23844422Ssklower return 0; 23944422Ssklower return (name->sin_addr.s_addr == inp->inp_faddr.s_addr); 24044422Ssklower } 24144422Ssklower 24244422Ssklower /* 24336400Ssklower * NAME: in_getnetaddr() 24436400Ssklower * 24536400Ssklower * CALLED FROM: 24636400Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR 24736400Ssklower * FUNCTION and ARGUMENTS: 24836400Ssklower * Copy a whole net addr from an inpcb (inp) into 24937469Ssklower * an mbuf (name); 25036400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN. 25136400Ssklower * 25236400Ssklower * RETURNS: Nada 25336400Ssklower * 25436400Ssklower * SIDE EFFECTS: 25536400Ssklower * 25636400Ssklower * NOTES: 25736400Ssklower */ 25836400Ssklower 25936400Ssklower void 26036400Ssklower in_getnetaddr( inp, name, which) 26137469Ssklower register struct mbuf *name; 26236400Ssklower struct inpcb *inp; 26336400Ssklower int which; 26436400Ssklower { 26537469Ssklower register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *); 26637469Ssklower bzero((caddr_t)sin, sizeof(*sin)); 26736400Ssklower switch (which) { 26836400Ssklower case TP_LOCAL: 26937469Ssklower sin->sin_addr = inp->inp_laddr; 27037469Ssklower sin->sin_port = inp->inp_lport; 27136400Ssklower break; 27236400Ssklower case TP_FOREIGN: 27337469Ssklower sin->sin_addr = inp->inp_faddr; 27437469Ssklower sin->sin_port = inp->inp_fport; 27536400Ssklower break; 27637469Ssklower default: 27737469Ssklower return; 27836400Ssklower } 27937469Ssklower name->m_len = sin->sin_len = sizeof (*sin); 28037469Ssklower sin->sin_family = AF_INET; 28136400Ssklower } 28236400Ssklower 28336400Ssklower /* 28436400Ssklower * NAME: tpip_mtu() 28536400Ssklower * 28636400Ssklower * CALLED FROM: 287*51246Ssklower * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT 28836400Ssklower * 28936400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE: 29036400Ssklower * 291*51246Ssklower * Perform subnetwork dependent part of determining MTU information. 292*51246Ssklower * It appears that setting a double pointer to the rtentry associated with 293*51246Ssklower * the destination, and returning the header size for the network protocol 294*51246Ssklower * suffices. 29536400Ssklower * 29636400Ssklower * SIDE EFFECTS: 297*51246Ssklower * Sets tp_routep pointer in pcb. 29836400Ssklower * 29936400Ssklower * NOTES: 30036400Ssklower */ 30136400Ssklower 302*51246Ssklower tpip_mtu(tpcb) 303*51246Ssklower register struct tp_pcb *tpcb; 30436400Ssklower { 305*51246Ssklower struct inpcb *inp = (struct inpcb *)tpcb->tp_npcb; 30636400Ssklower 30736400Ssklower IFDEBUG(D_CONN) 308*51246Ssklower printf("tpip_mtu(tpcb)\n", tpcb); 309*51246Ssklower printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr.s_addr); 31036400Ssklower ENDDEBUG 311*51246Ssklower tpcb->tp_routep = &(inp->inp_route.ro_rt); 312*51246Ssklower return (sizeof (struct ip)); 31336400Ssklower 31436400Ssklower } 31536400Ssklower 31636400Ssklower /* 31736400Ssklower * NAME: tpip_output() 31836400Ssklower * 31936400Ssklower * CALLED FROM: tp_emit() 32036400Ssklower * 32136400Ssklower * FUNCTION and ARGUMENTS: 32236400Ssklower * Take a packet(m0) from tp and package it so that ip will accept it. 32336400Ssklower * This means prepending space for the ip header and filling in a few 32436400Ssklower * of the fields. 32536400Ssklower * inp is the inpcb structure; datalen is the length of the data in the 32636400Ssklower * mbuf string m0. 32736400Ssklower * RETURNS: 32836400Ssklower * whatever (E*) is returned form the net layer output routine. 32936400Ssklower * 33036400Ssklower * SIDE EFFECTS: 33136400Ssklower * 33236400Ssklower * NOTES: 33336400Ssklower */ 33436400Ssklower 33536400Ssklower int 33636400Ssklower tpip_output(inp, m0, datalen, nochksum) 33736400Ssklower struct inpcb *inp; 33836400Ssklower struct mbuf *m0; 33936400Ssklower int datalen; 34036400Ssklower int nochksum; 34136400Ssklower { 34236400Ssklower return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, 34336400Ssklower &inp->inp_route, nochksum); 34436400Ssklower } 34536400Ssklower 34636400Ssklower /* 34736400Ssklower * NAME: tpip_output_dg() 34836400Ssklower * 34936400Ssklower * CALLED FROM: tp_error_emit() 35036400Ssklower * 35136400Ssklower * FUNCTION and ARGUMENTS: 35236400Ssklower * This is a copy of tpip_output that takes the addresses 35336400Ssklower * instead of a pcb. It's used by the tp_error_emit, when we 35436400Ssklower * don't have an in_pcb with which to call the normal output rtn. 35536400Ssklower * 35636400Ssklower * RETURNS: ENOBUFS or whatever (E*) is 35736400Ssklower * returned form the net layer output routine. 35836400Ssklower * 35936400Ssklower * SIDE EFFECTS: 36036400Ssklower * 36136400Ssklower * NOTES: 36236400Ssklower */ 36336400Ssklower 36437469Ssklower /*ARGSUSED*/ 36536400Ssklower int 36636400Ssklower tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) 36736400Ssklower struct in_addr *laddr, *faddr; 36836400Ssklower struct mbuf *m0; 36936400Ssklower int datalen; 37036400Ssklower struct route *ro; 37136400Ssklower int nochksum; 37236400Ssklower { 37336400Ssklower register struct mbuf *m; 37436400Ssklower register struct ip *ip; 37536400Ssklower int error; 37636400Ssklower 37736400Ssklower IFDEBUG(D_EMIT) 37836400Ssklower printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); 37936400Ssklower ENDDEBUG 38036400Ssklower 38136400Ssklower 38237469Ssklower MGETHDR(m, M_DONTWAIT, TPMT_IPHDR); 38336400Ssklower if (m == 0) { 38436400Ssklower error = ENOBUFS; 38536400Ssklower goto bad; 38636400Ssklower } 38736400Ssklower m->m_next = m0; 38837469Ssklower MH_ALIGN(m, sizeof(struct ip)); 38936400Ssklower m->m_len = sizeof(struct ip); 39036400Ssklower 39136400Ssklower ip = mtod(m, struct ip *); 39237469Ssklower bzero((caddr_t)ip, sizeof *ip); 39336400Ssklower 39436400Ssklower ip->ip_p = IPPROTO_TP; 39537469Ssklower m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen; 39636400Ssklower ip->ip_ttl = MAXTTL; 39736400Ssklower /* don't know why you need to set ttl; 39836400Ssklower * overlay doesn't even make this available 39936400Ssklower */ 40036400Ssklower 40136400Ssklower ip->ip_src = *laddr; 40236400Ssklower ip->ip_dst = *faddr; 40336400Ssklower 40436400Ssklower IncStat(ts_tpdu_sent); 40536400Ssklower IFDEBUG(D_EMIT) 40636400Ssklower dump_mbuf(m, "tpip_output_dg before ip_output\n"); 40736400Ssklower ENDDEBUG 40836400Ssklower 40936400Ssklower error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST); 41036400Ssklower 41136400Ssklower IFDEBUG(D_EMIT) 41236400Ssklower printf("tpip_output_dg after ip_output\n"); 41336400Ssklower ENDDEBUG 41436400Ssklower 41536400Ssklower return error; 41636400Ssklower 41736400Ssklower bad: 41836400Ssklower m_freem(m); 41936400Ssklower IncStat(ts_send_drop); 42036400Ssklower return error; 42136400Ssklower } 42236400Ssklower 42336400Ssklower /* 42436400Ssklower * NAME: tpip_input() 42536400Ssklower * 42636400Ssklower * CALLED FROM: 42736400Ssklower * ip's input routine, indirectly through the protosw. 42836400Ssklower * 42936400Ssklower * FUNCTION and ARGUMENTS: 43036400Ssklower * Take a packet (m) from ip, strip off the ip header and give it to tp 43136400Ssklower * 43236400Ssklower * RETURNS: No return value. 43336400Ssklower * 43436400Ssklower * SIDE EFFECTS: 43536400Ssklower * 43636400Ssklower * NOTES: 43736400Ssklower */ 43836400Ssklower ProtoHook 43937469Ssklower tpip_input(m, iplen) 44036400Ssklower struct mbuf *m; 44137469Ssklower int iplen; 44236400Ssklower { 44336400Ssklower struct sockaddr_in src, dst; 44436400Ssklower register struct ip *ip; 44537469Ssklower int s = splnet(), hdrlen; 44636400Ssklower 44736400Ssklower IncStat(ts_pkt_rcvd); 44836400Ssklower 44937469Ssklower /* 45037469Ssklower * IP layer has already pulled up the IP header, 45137469Ssklower * but the first byte after the IP header may not be there, 45237469Ssklower * e.g. if you came in via loopback, so you have to do an 45337469Ssklower * m_pullup to before you can even look to see how much you 45437469Ssklower * really need. The good news is that m_pullup will round 45537469Ssklower * up to almost the next mbuf's worth. 45637469Ssklower */ 45736400Ssklower 45837469Ssklower 45937469Ssklower if((m = m_pullup(m, iplen + 1)) == MNULL) 46037469Ssklower goto discard; 46136400Ssklower CHANGE_MTYPE(m, TPMT_DATA); 46236400Ssklower 46336400Ssklower /* 46437469Ssklower * Now pull up the whole tp header: 46537469Ssklower * Unfortunately, there may be IP options to skip past so we 46637469Ssklower * just fetch it as an unsigned char. 46736400Ssklower */ 46837469Ssklower hdrlen = iplen + 1 + mtod(m, u_char *)[iplen]; 46936400Ssklower 47037469Ssklower if( m->m_len < hdrlen ) { 47137469Ssklower if((m = m_pullup(m, hdrlen)) == MNULL){ 47236400Ssklower IFDEBUG(D_TPINPUT) 47336400Ssklower printf("tp_input, pullup 2!\n"); 47436400Ssklower ENDDEBUG 47536400Ssklower goto discard; 47636400Ssklower } 47736400Ssklower } 47836400Ssklower /* 47936400Ssklower * cannot use tp_inputprep() here 'cause you don't 48036400Ssklower * have quite the same situation 48136400Ssklower */ 48236400Ssklower 48336400Ssklower IFDEBUG(D_TPINPUT) 48436400Ssklower dump_mbuf(m, "after tpip_input both pullups"); 48536400Ssklower ENDDEBUG 48636400Ssklower /* 48736400Ssklower * m_pullup may have returned a different mbuf 48836400Ssklower */ 48937469Ssklower ip = mtod(m, struct ip *); 49036400Ssklower 49136400Ssklower /* 49236400Ssklower * drop the ip header from the front of the mbuf 49336400Ssklower * this is necessary for the tp checksum 49436400Ssklower */ 49537469Ssklower m->m_len -= iplen; 49637469Ssklower m->m_data += iplen; 49736400Ssklower 49836400Ssklower src.sin_addr = *(struct in_addr *)&(ip->ip_src); 49936400Ssklower src.sin_family = AF_INET; 50037469Ssklower src.sin_len = sizeof(src); 50136400Ssklower dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); 50236400Ssklower dst.sin_family = AF_INET; 50337469Ssklower dst.sin_len = sizeof(dst); 50436400Ssklower 50537469Ssklower (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, 50639928Ssklower 0, tpip_output_dg, 0); 50736400Ssklower return 0; 50836400Ssklower 50936400Ssklower discard: 51036400Ssklower IFDEBUG(D_TPINPUT) 51136400Ssklower printf("tpip_input DISCARD\n"); 51236400Ssklower ENDDEBUG 51336400Ssklower IFTRACE(D_TPINPUT) 51436400Ssklower tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); 51536400Ssklower ENDTRACE 51636400Ssklower m_freem(m); 51736400Ssklower IncStat(ts_recv_drop); 51837469Ssklower splx(s); 51936400Ssklower return 0; 52036400Ssklower } 52136400Ssklower 52236400Ssklower 52337536Smckusick #include "protosw.h" 52436400Ssklower #include "../netinet/ip_icmp.h" 52536400Ssklower 52637469Ssklower extern void tp_quench(); 52736400Ssklower /* 52836400Ssklower * NAME: tpin_quench() 52936400Ssklower * 53036400Ssklower * CALLED FROM: tpip_ctlinput() 53136400Ssklower * 53236400Ssklower * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench 53336400Ssklower * 53436400Ssklower * RETURNS: Nada 53536400Ssklower * 53636400Ssklower * SIDE EFFECTS: 53736400Ssklower * 53836400Ssklower * NOTES: 53936400Ssklower */ 54036400Ssklower 54136400Ssklower void 54236400Ssklower tpin_quench(inp) 54336400Ssklower struct inpcb *inp; 54436400Ssklower { 54550435Ssklower tp_quench((struct tp_pcb *)inp->inp_socket->so_pcb, PRC_QUENCH); 54636400Ssklower } 54736400Ssklower 54836400Ssklower /* 54936400Ssklower * NAME: tpip_ctlinput() 55036400Ssklower * 55136400Ssklower * CALLED FROM: 55236400Ssklower * The network layer through the protosw table. 55336400Ssklower * 55436400Ssklower * FUNCTION and ARGUMENTS: 55536400Ssklower * When clnp gets an ICMP msg this gets called. 55636400Ssklower * It either returns an error status to the user or 55736400Ssklower * causes all connections on this address to be aborted 55836400Ssklower * by calling the appropriate xx_notify() routine. 55936400Ssklower * (cmd) is the type of ICMP error. 56036400Ssklower * (sa) the address of the sender 56136400Ssklower * 56236400Ssklower * RETURNS: Nothing 56336400Ssklower * 56436400Ssklower * SIDE EFFECTS: 56536400Ssklower * 56636400Ssklower * NOTES: 56736400Ssklower */ 56836400Ssklower ProtoHook 56936400Ssklower tpip_ctlinput(cmd, sin) 57036400Ssklower int cmd; 57136400Ssklower struct sockaddr_in *sin; 57236400Ssklower { 57336400Ssklower extern u_char inetctlerrmap[]; 57436400Ssklower extern ProtoHook tpin_abort(); 57536400Ssklower extern ProtoHook in_rtchange(); 57645630Ssklower extern struct in_addr zeroin_addr; 57736400Ssklower 57836400Ssklower if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) 57936400Ssklower return 0; 58036400Ssklower if (sin->sin_addr.s_addr == INADDR_ANY) 58136400Ssklower return 0; 58236400Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 58336400Ssklower return 0; 58436400Ssklower switch (cmd) { 58536400Ssklower 58636400Ssklower case PRC_QUENCH: 58745630Ssklower in_pcbnotify(&tp_inpcb, sin, 0, 58845630Ssklower zeroin_addr, 0, cmd, (int (*)())tp_quench); 58936400Ssklower break; 59036400Ssklower 59136400Ssklower case PRC_ROUTEDEAD: 59236400Ssklower case PRC_HOSTUNREACH: 59336400Ssklower case PRC_UNREACH_NET: 59436400Ssklower case PRC_IFDOWN: 59536400Ssklower case PRC_HOSTDEAD: 59645630Ssklower in_pcbnotify(&tp_inpcb, sin, 0, 59745630Ssklower zeroin_addr, 0, cmd, in_rtchange); 59836400Ssklower break; 59936400Ssklower 60036400Ssklower default: 60136400Ssklower /* 60236400Ssklower case PRC_MSGSIZE: 60336400Ssklower case PRC_UNREACH_HOST: 60436400Ssklower case PRC_UNREACH_PROTOCOL: 60536400Ssklower case PRC_UNREACH_PORT: 60636400Ssklower case PRC_UNREACH_NEEDFRAG: 60736400Ssklower case PRC_UNREACH_SRCFAIL: 60836400Ssklower case PRC_REDIRECT_NET: 60936400Ssklower case PRC_REDIRECT_HOST: 61036400Ssklower case PRC_REDIRECT_TOSNET: 61136400Ssklower case PRC_REDIRECT_TOSHOST: 61236400Ssklower case PRC_TIMXCEED_INTRANS: 61336400Ssklower case PRC_TIMXCEED_REASS: 61436400Ssklower case PRC_PARAMPROB: 61536400Ssklower */ 61645630Ssklower in_pcbnotify(&tp_inpcb, sin, 0, zeroin_addr, 0, 61745630Ssklower cmd, tpin_abort); 61836400Ssklower } 61936400Ssklower return 0; 62036400Ssklower } 62136400Ssklower 62236400Ssklower /* 62336400Ssklower * NAME: tpin_abort() 62436400Ssklower * 62536400Ssklower * CALLED FROM: 62636400Ssklower * xxx_notify() from tp_ctlinput() when 62736400Ssklower * net level gets some ICMP-equiv. type event. 62836400Ssklower * 62936400Ssklower * FUNCTION and ARGUMENTS: 63036400Ssklower * Cause the connection to be aborted with some sort of error 63136400Ssklower * reason indicating that the network layer caused the abort. 63236400Ssklower * Fakes an ER TPDU so we can go through the driver. 63336400Ssklower * 63436400Ssklower * RETURNS: Nothing 63536400Ssklower * 63636400Ssklower * SIDE EFFECTS: 63736400Ssklower * 63836400Ssklower * NOTES: 63936400Ssklower */ 64036400Ssklower 64136400Ssklower ProtoHook 64236400Ssklower tpin_abort(inp) 64336400Ssklower struct inpcb *inp; 64436400Ssklower { 64536400Ssklower struct tp_event e; 64636400Ssklower 64736400Ssklower e.ev_number = ER_TPDU; 64836400Ssklower e.ATTR(ER_TPDU).e_reason = ENETRESET; 64937469Ssklower (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e); 65036400Ssklower return 0; 65136400Ssklower } 65236400Ssklower 65336400Ssklower #ifdef ARGO_DEBUG 65436400Ssklower dump_inaddr(addr) 65536400Ssklower register struct sockaddr_in *addr; 65636400Ssklower { 65736400Ssklower printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr); 65836400Ssklower } 65936400Ssklower #endif ARGO_DEBUG 66036400Ssklower #endif INET 661