149268Sbostic /*-
2*63222Sbostic * Copyright (c) 1991, 1993
3*63222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*63222Sbostic * @(#)tp_inet.c 8.1 (Berkeley) 06/10/93
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
6156533Sbostic #include <sys/param.h>
6256533Sbostic #include <sys/socket.h>
6356533Sbostic #include <sys/socketvar.h>
6456533Sbostic #include <sys/mbuf.h>
6556533Sbostic #include <sys/errno.h>
6656533Sbostic #include <sys/time.h>
6736400Ssklower
6856533Sbostic #include <net/if.h>
6956533Sbostic
7056533Sbostic #include <netiso/tp_param.h>
7156533Sbostic #include <netiso/argo_debug.h>
7256533Sbostic #include <netiso/tp_stat.h>
7356533Sbostic #include <netiso/tp_ip.h>
7456533Sbostic #include <netiso/tp_pcb.h>
7556533Sbostic #include <netiso/tp_trace.h>
7656533Sbostic #include <netiso/tp_stat.h>
7756533Sbostic #include <netiso/tp_tpdu.h>
7856533Sbostic #include <netinet/in_var.h>
7956533Sbostic
8037469Ssklower #ifndef ISO
8156533Sbostic #include <netiso/iso_chksum.c>
8237469Ssklower #endif
8336400Ssklower
8436400Ssklower /*
8536400Ssklower * NAME: in_getsufx()
8636400Ssklower
8736400Ssklower * CALLED FROM: pr_usrreq() on PRU_BIND,
8836400Ssklower * PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
8936400Ssklower *
9036400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE:
9136400Ssklower * Get a transport suffix from an inpcb structure (inp).
9236400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
9336400Ssklower *
9436400Ssklower * RETURNS: internet port / transport suffix
9536400Ssklower * (CAST TO AN INT)
9636400Ssklower *
9736400Ssklower * SIDE EFFECTS:
9836400Ssklower *
9936400Ssklower * NOTES:
10036400Ssklower */
10137469Ssklower in_getsufx(inp, lenp, data_out, which)
10236400Ssklower struct inpcb *inp;
10337469Ssklower u_short *lenp;
10437469Ssklower caddr_t data_out;
10536400Ssklower int which;
10636400Ssklower {
10737469Ssklower *lenp = sizeof(u_short);
10836400Ssklower switch (which) {
10936400Ssklower case TP_LOCAL:
11037469Ssklower *(u_short *)data_out = inp->inp_lport;
11137469Ssklower return;
11236400Ssklower
11336400Ssklower case TP_FOREIGN:
11437469Ssklower *(u_short *)data_out = inp->inp_fport;
11536400Ssklower }
11637469Ssklower
11736400Ssklower }
11836400Ssklower
11936400Ssklower /*
12036400Ssklower * NAME: in_putsufx()
12136400Ssklower *
12236400Ssklower * CALLED FROM: tp_newsocket(); i.e., when a connection
12336400Ssklower * is being established by an incoming CR_TPDU.
12436400Ssklower *
12536400Ssklower * FUNCTION, ARGUMENTS:
12636400Ssklower * Put a transport suffix (found in name) into an inpcb structure (inp).
12736400Ssklower * The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
12836400Ssklower *
12936400Ssklower * RETURNS: Nada
13036400Ssklower *
13136400Ssklower * SIDE EFFECTS:
13236400Ssklower *
13336400Ssklower * NOTES:
13436400Ssklower */
13537469Ssklower /*ARGSUSED*/
13636400Ssklower void
in_putsufx(inp,sufxloc,sufxlen,which)13737469Ssklower in_putsufx(inp, sufxloc, sufxlen, which)
13836400Ssklower struct inpcb *inp;
13937469Ssklower caddr_t sufxloc;
14036400Ssklower int which;
14136400Ssklower {
14237469Ssklower if (which == TP_FOREIGN) {
14337469Ssklower bcopy(sufxloc, (caddr_t)&inp->inp_fport, sizeof(inp->inp_fport));
14436400Ssklower }
14536400Ssklower }
14636400Ssklower
14736400Ssklower /*
14836400Ssklower * NAME: in_recycle_tsuffix()
14936400Ssklower *
15036400Ssklower * CALLED FROM: tp.trans whenever we go into REFWAIT state.
15136400Ssklower *
15236400Ssklower * FUNCTION and ARGUMENT:
15336400Ssklower * Called when a ref is frozen, to allow the suffix to be reused.
15436400Ssklower * (inp) is the net level pcb.
15536400Ssklower *
15636400Ssklower * RETURNS: Nada
15736400Ssklower *
15836400Ssklower * SIDE EFFECTS:
15936400Ssklower *
16036400Ssklower * NOTES: This really shouldn't have to be done in a NET level pcb
16136400Ssklower * but... for the internet world that just the way it is done in BSD...
16236400Ssklower * The alternative is to have the port unusable until the reference
16336400Ssklower * timer goes off.
16436400Ssklower */
16536400Ssklower void
in_recycle_tsuffix(inp)16636400Ssklower in_recycle_tsuffix(inp)
16736400Ssklower struct inpcb *inp;
16836400Ssklower {
16936400Ssklower inp->inp_fport = inp->inp_lport = 0;
17036400Ssklower }
17136400Ssklower
17236400Ssklower /*
17336400Ssklower * NAME: in_putnetaddr()
17436400Ssklower *
17536400Ssklower * CALLED FROM:
17636400Ssklower * tp_newsocket(); i.e., when a connection is being established by an
17736400Ssklower * incoming CR_TPDU.
17836400Ssklower *
17936400Ssklower * FUNCTION and ARGUMENTS:
18036400Ssklower * Copy a whole net addr from a struct sockaddr (name).
18136400Ssklower * into an inpcb (inp).
18236400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN
18336400Ssklower *
18436400Ssklower * RETURNS: Nada
18536400Ssklower *
18636400Ssklower * SIDE EFFECTS:
18736400Ssklower *
18836400Ssklower * NOTES:
18936400Ssklower */
19036400Ssklower void
in_putnetaddr(inp,name,which)19136400Ssklower in_putnetaddr(inp, name, which)
19236400Ssklower register struct inpcb *inp;
19336400Ssklower struct sockaddr_in *name;
19436400Ssklower int which;
19536400Ssklower {
19636400Ssklower switch (which) {
19736400Ssklower case TP_LOCAL:
19836400Ssklower bcopy((caddr_t)&name->sin_addr,
19936400Ssklower (caddr_t)&inp->inp_laddr, sizeof(struct in_addr));
20036400Ssklower /* won't work if the dst address (name) is INADDR_ANY */
20136400Ssklower
20236400Ssklower break;
20336400Ssklower case TP_FOREIGN:
20436400Ssklower if( name != (struct sockaddr_in *)0 ) {
20536400Ssklower bcopy((caddr_t)&name->sin_addr,
20636400Ssklower (caddr_t)&inp->inp_faddr, sizeof(struct in_addr));
20736400Ssklower }
20836400Ssklower }
20936400Ssklower }
21036400Ssklower
21136400Ssklower /*
21244422Ssklower * NAME: in_putnetaddr()
21344422Ssklower *
21444422Ssklower * CALLED FROM:
21544422Ssklower * tp_input() when a connection is being established by an
21644422Ssklower * incoming CR_TPDU, and considered for interception.
21744422Ssklower *
21844422Ssklower * FUNCTION and ARGUMENTS:
21944422Ssklower * Compare a whole net addr from a struct sockaddr (name),
22044422Ssklower * with that implicitly stored in an inpcb (inp).
22144422Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN
22244422Ssklower *
22344422Ssklower * RETURNS: Nada
22444422Ssklower *
22544422Ssklower * SIDE EFFECTS:
22644422Ssklower *
22744422Ssklower * NOTES:
22844422Ssklower */
in_cmpnetaddr(inp,name,which)22944422Ssklower in_cmpnetaddr(inp, name, which)
23044422Ssklower register struct inpcb *inp;
23144422Ssklower register struct sockaddr_in *name;
23244422Ssklower int which;
23344422Ssklower {
23444422Ssklower if (which == TP_LOCAL) {
23544422Ssklower if (name->sin_port && name->sin_port != inp->inp_lport)
23644422Ssklower return 0;
23744422Ssklower return (name->sin_addr.s_addr == inp->inp_laddr.s_addr);
23844422Ssklower }
23944422Ssklower if (name->sin_port && name->sin_port != inp->inp_fport)
24044422Ssklower return 0;
24144422Ssklower return (name->sin_addr.s_addr == inp->inp_faddr.s_addr);
24244422Ssklower }
24344422Ssklower
24444422Ssklower /*
24536400Ssklower * NAME: in_getnetaddr()
24636400Ssklower *
24736400Ssklower * CALLED FROM:
24836400Ssklower * pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
24936400Ssklower * FUNCTION and ARGUMENTS:
25036400Ssklower * Copy a whole net addr from an inpcb (inp) into
25137469Ssklower * an mbuf (name);
25236400Ssklower * The argument (which) takes values TP_LOCAL or TP_FOREIGN.
25336400Ssklower *
25436400Ssklower * RETURNS: Nada
25536400Ssklower *
25636400Ssklower * SIDE EFFECTS:
25736400Ssklower *
25836400Ssklower * NOTES:
25936400Ssklower */
26036400Ssklower
26136400Ssklower void
in_getnetaddr(inp,name,which)26236400Ssklower in_getnetaddr( inp, name, which)
26337469Ssklower register struct mbuf *name;
26436400Ssklower struct inpcb *inp;
26536400Ssklower int which;
26636400Ssklower {
26737469Ssklower register struct sockaddr_in *sin = mtod(name, struct sockaddr_in *);
26837469Ssklower bzero((caddr_t)sin, sizeof(*sin));
26936400Ssklower switch (which) {
27036400Ssklower case TP_LOCAL:
27137469Ssklower sin->sin_addr = inp->inp_laddr;
27237469Ssklower sin->sin_port = inp->inp_lport;
27336400Ssklower break;
27436400Ssklower case TP_FOREIGN:
27537469Ssklower sin->sin_addr = inp->inp_faddr;
27637469Ssklower sin->sin_port = inp->inp_fport;
27736400Ssklower break;
27837469Ssklower default:
27937469Ssklower return;
28036400Ssklower }
28137469Ssklower name->m_len = sin->sin_len = sizeof (*sin);
28237469Ssklower sin->sin_family = AF_INET;
28336400Ssklower }
28436400Ssklower
28536400Ssklower /*
28636400Ssklower * NAME: tpip_mtu()
28736400Ssklower *
28836400Ssklower * CALLED FROM:
28951246Ssklower * tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
29036400Ssklower *
29136400Ssklower * FUNCTION, ARGUMENTS, and RETURN VALUE:
29236400Ssklower *
29351246Ssklower * Perform subnetwork dependent part of determining MTU information.
29451246Ssklower * It appears that setting a double pointer to the rtentry associated with
29551246Ssklower * the destination, and returning the header size for the network protocol
29651246Ssklower * suffices.
29736400Ssklower *
29836400Ssklower * SIDE EFFECTS:
29951246Ssklower * Sets tp_routep pointer in pcb.
30036400Ssklower *
30136400Ssklower * NOTES:
30236400Ssklower */
30336400Ssklower
tpip_mtu(tpcb)30451246Ssklower tpip_mtu(tpcb)
30551246Ssklower register struct tp_pcb *tpcb;
30636400Ssklower {
30751246Ssklower struct inpcb *inp = (struct inpcb *)tpcb->tp_npcb;
30836400Ssklower
30936400Ssklower IFDEBUG(D_CONN)
31051246Ssklower printf("tpip_mtu(tpcb)\n", tpcb);
31151246Ssklower printf("tpip_mtu routing to addr 0x%x\n", inp->inp_faddr.s_addr);
31236400Ssklower ENDDEBUG
31351246Ssklower tpcb->tp_routep = &(inp->inp_route.ro_rt);
31451246Ssklower return (sizeof (struct ip));
31536400Ssklower
31636400Ssklower }
31736400Ssklower
31836400Ssklower /*
31936400Ssklower * NAME: tpip_output()
32036400Ssklower *
32136400Ssklower * CALLED FROM: tp_emit()
32236400Ssklower *
32336400Ssklower * FUNCTION and ARGUMENTS:
32436400Ssklower * Take a packet(m0) from tp and package it so that ip will accept it.
32536400Ssklower * This means prepending space for the ip header and filling in a few
32636400Ssklower * of the fields.
32736400Ssklower * inp is the inpcb structure; datalen is the length of the data in the
32836400Ssklower * mbuf string m0.
32936400Ssklower * RETURNS:
33036400Ssklower * whatever (E*) is returned form the net layer output routine.
33136400Ssklower *
33236400Ssklower * SIDE EFFECTS:
33336400Ssklower *
33436400Ssklower * NOTES:
33536400Ssklower */
33636400Ssklower
33736400Ssklower int
tpip_output(inp,m0,datalen,nochksum)33836400Ssklower tpip_output(inp, m0, datalen, nochksum)
33936400Ssklower struct inpcb *inp;
34036400Ssklower struct mbuf *m0;
34136400Ssklower int datalen;
34236400Ssklower int nochksum;
34336400Ssklower {
34436400Ssklower return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen,
34536400Ssklower &inp->inp_route, nochksum);
34636400Ssklower }
34736400Ssklower
34836400Ssklower /*
34936400Ssklower * NAME: tpip_output_dg()
35036400Ssklower *
35136400Ssklower * CALLED FROM: tp_error_emit()
35236400Ssklower *
35336400Ssklower * FUNCTION and ARGUMENTS:
35436400Ssklower * This is a copy of tpip_output that takes the addresses
35536400Ssklower * instead of a pcb. It's used by the tp_error_emit, when we
35636400Ssklower * don't have an in_pcb with which to call the normal output rtn.
35736400Ssklower *
35836400Ssklower * RETURNS: ENOBUFS or whatever (E*) is
35936400Ssklower * returned form the net layer output routine.
36036400Ssklower *
36136400Ssklower * SIDE EFFECTS:
36236400Ssklower *
36336400Ssklower * NOTES:
36436400Ssklower */
36536400Ssklower
36637469Ssklower /*ARGSUSED*/
36736400Ssklower int
tpip_output_dg(laddr,faddr,m0,datalen,ro,nochksum)36836400Ssklower tpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
36936400Ssklower struct in_addr *laddr, *faddr;
37036400Ssklower struct mbuf *m0;
37136400Ssklower int datalen;
37236400Ssklower struct route *ro;
37336400Ssklower int nochksum;
37436400Ssklower {
37536400Ssklower register struct mbuf *m;
37636400Ssklower register struct ip *ip;
37736400Ssklower int error;
37836400Ssklower
37936400Ssklower IFDEBUG(D_EMIT)
38036400Ssklower printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0);
38136400Ssklower ENDDEBUG
38236400Ssklower
38336400Ssklower
38437469Ssklower MGETHDR(m, M_DONTWAIT, TPMT_IPHDR);
38536400Ssklower if (m == 0) {
38636400Ssklower error = ENOBUFS;
38736400Ssklower goto bad;
38836400Ssklower }
38936400Ssklower m->m_next = m0;
39037469Ssklower MH_ALIGN(m, sizeof(struct ip));
39136400Ssklower m->m_len = sizeof(struct ip);
39236400Ssklower
39336400Ssklower ip = mtod(m, struct ip *);
39437469Ssklower bzero((caddr_t)ip, sizeof *ip);
39536400Ssklower
39636400Ssklower ip->ip_p = IPPROTO_TP;
39737469Ssklower m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen;
39836400Ssklower ip->ip_ttl = MAXTTL;
39936400Ssklower /* don't know why you need to set ttl;
40036400Ssklower * overlay doesn't even make this available
40136400Ssklower */
40236400Ssklower
40336400Ssklower ip->ip_src = *laddr;
40436400Ssklower ip->ip_dst = *faddr;
40536400Ssklower
40636400Ssklower IncStat(ts_tpdu_sent);
40736400Ssklower IFDEBUG(D_EMIT)
40836400Ssklower dump_mbuf(m, "tpip_output_dg before ip_output\n");
40936400Ssklower ENDDEBUG
41036400Ssklower
41161657Ssklower error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST, NULL);
41236400Ssklower
41336400Ssklower IFDEBUG(D_EMIT)
41436400Ssklower printf("tpip_output_dg after ip_output\n");
41536400Ssklower ENDDEBUG
41636400Ssklower
41736400Ssklower return error;
41836400Ssklower
41936400Ssklower bad:
42036400Ssklower m_freem(m);
42136400Ssklower IncStat(ts_send_drop);
42236400Ssklower return error;
42336400Ssklower }
42436400Ssklower
42536400Ssklower /*
42636400Ssklower * NAME: tpip_input()
42736400Ssklower *
42836400Ssklower * CALLED FROM:
42936400Ssklower * ip's input routine, indirectly through the protosw.
43036400Ssklower *
43136400Ssklower * FUNCTION and ARGUMENTS:
43236400Ssklower * Take a packet (m) from ip, strip off the ip header and give it to tp
43336400Ssklower *
43436400Ssklower * RETURNS: No return value.
43536400Ssklower *
43636400Ssklower * SIDE EFFECTS:
43736400Ssklower *
43836400Ssklower * NOTES:
43936400Ssklower */
44036400Ssklower ProtoHook
tpip_input(m,iplen)44137469Ssklower tpip_input(m, iplen)
44236400Ssklower struct mbuf *m;
44337469Ssklower int iplen;
44436400Ssklower {
44536400Ssklower struct sockaddr_in src, dst;
44636400Ssklower register struct ip *ip;
44737469Ssklower int s = splnet(), hdrlen;
44836400Ssklower
44936400Ssklower IncStat(ts_pkt_rcvd);
45036400Ssklower
45137469Ssklower /*
45237469Ssklower * IP layer has already pulled up the IP header,
45337469Ssklower * but the first byte after the IP header may not be there,
45437469Ssklower * e.g. if you came in via loopback, so you have to do an
45537469Ssklower * m_pullup to before you can even look to see how much you
45637469Ssklower * really need. The good news is that m_pullup will round
45737469Ssklower * up to almost the next mbuf's worth.
45837469Ssklower */
45936400Ssklower
46037469Ssklower
46137469Ssklower if((m = m_pullup(m, iplen + 1)) == MNULL)
46237469Ssklower goto discard;
46336400Ssklower CHANGE_MTYPE(m, TPMT_DATA);
46436400Ssklower
46536400Ssklower /*
46637469Ssklower * Now pull up the whole tp header:
46737469Ssklower * Unfortunately, there may be IP options to skip past so we
46837469Ssklower * just fetch it as an unsigned char.
46936400Ssklower */
47037469Ssklower hdrlen = iplen + 1 + mtod(m, u_char *)[iplen];
47136400Ssklower
47237469Ssklower if( m->m_len < hdrlen ) {
47337469Ssklower if((m = m_pullup(m, hdrlen)) == MNULL){
47436400Ssklower IFDEBUG(D_TPINPUT)
47536400Ssklower printf("tp_input, pullup 2!\n");
47636400Ssklower ENDDEBUG
47736400Ssklower goto discard;
47836400Ssklower }
47936400Ssklower }
48036400Ssklower /*
48136400Ssklower * cannot use tp_inputprep() here 'cause you don't
48236400Ssklower * have quite the same situation
48336400Ssklower */
48436400Ssklower
48536400Ssklower IFDEBUG(D_TPINPUT)
48636400Ssklower dump_mbuf(m, "after tpip_input both pullups");
48736400Ssklower ENDDEBUG
48836400Ssklower /*
48936400Ssklower * m_pullup may have returned a different mbuf
49036400Ssklower */
49137469Ssklower ip = mtod(m, struct ip *);
49236400Ssklower
49336400Ssklower /*
49436400Ssklower * drop the ip header from the front of the mbuf
49536400Ssklower * this is necessary for the tp checksum
49636400Ssklower */
49737469Ssklower m->m_len -= iplen;
49837469Ssklower m->m_data += iplen;
49936400Ssklower
50036400Ssklower src.sin_addr = *(struct in_addr *)&(ip->ip_src);
50136400Ssklower src.sin_family = AF_INET;
50237469Ssklower src.sin_len = sizeof(src);
50336400Ssklower dst.sin_addr = *(struct in_addr *)&(ip->ip_dst);
50436400Ssklower dst.sin_family = AF_INET;
50537469Ssklower dst.sin_len = sizeof(dst);
50636400Ssklower
50737469Ssklower (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst,
50839928Ssklower 0, tpip_output_dg, 0);
50936400Ssklower return 0;
51036400Ssklower
51136400Ssklower discard:
51236400Ssklower IFDEBUG(D_TPINPUT)
51336400Ssklower printf("tpip_input DISCARD\n");
51436400Ssklower ENDDEBUG
51536400Ssklower IFTRACE(D_TPINPUT)
51636400Ssklower tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0);
51736400Ssklower ENDTRACE
51836400Ssklower m_freem(m);
51936400Ssklower IncStat(ts_recv_drop);
52037469Ssklower splx(s);
52136400Ssklower return 0;
52236400Ssklower }
52336400Ssklower
52436400Ssklower
52556533Sbostic #include <sys/protosw.h>
52656533Sbostic #include <netinet/ip_icmp.h>
52736400Ssklower
52837469Ssklower extern void tp_quench();
52936400Ssklower /*
53036400Ssklower * NAME: tpin_quench()
53136400Ssklower *
53236400Ssklower * CALLED FROM: tpip_ctlinput()
53336400Ssklower *
53436400Ssklower * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench
53536400Ssklower *
53636400Ssklower * RETURNS: Nada
53736400Ssklower *
53836400Ssklower * SIDE EFFECTS:
53936400Ssklower *
54036400Ssklower * NOTES:
54136400Ssklower */
54236400Ssklower
54336400Ssklower void
tpin_quench(inp)54436400Ssklower tpin_quench(inp)
54536400Ssklower struct inpcb *inp;
54636400Ssklower {
54750435Ssklower tp_quench((struct tp_pcb *)inp->inp_socket->so_pcb, PRC_QUENCH);
54836400Ssklower }
54936400Ssklower
55036400Ssklower /*
55136400Ssklower * NAME: tpip_ctlinput()
55236400Ssklower *
55336400Ssklower * CALLED FROM:
55436400Ssklower * The network layer through the protosw table.
55536400Ssklower *
55636400Ssklower * FUNCTION and ARGUMENTS:
55736400Ssklower * When clnp gets an ICMP msg this gets called.
55836400Ssklower * It either returns an error status to the user or
55936400Ssklower * causes all connections on this address to be aborted
56036400Ssklower * by calling the appropriate xx_notify() routine.
56136400Ssklower * (cmd) is the type of ICMP error.
56236400Ssklower * (sa) the address of the sender
56336400Ssklower *
56436400Ssklower * RETURNS: Nothing
56536400Ssklower *
56636400Ssklower * SIDE EFFECTS:
56736400Ssklower *
56836400Ssklower * NOTES:
56936400Ssklower */
57036400Ssklower ProtoHook
tpip_ctlinput(cmd,sin)57136400Ssklower tpip_ctlinput(cmd, sin)
57236400Ssklower int cmd;
57336400Ssklower struct sockaddr_in *sin;
57436400Ssklower {
57536400Ssklower extern u_char inetctlerrmap[];
57645630Ssklower extern struct in_addr zeroin_addr;
57761657Ssklower void tp_quench __P((struct inpcb *,int));
57861657Ssklower void tpin_abort __P((struct inpcb *,int));
57936400Ssklower
58036400Ssklower if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK)
58136400Ssklower return 0;
58236400Ssklower if (sin->sin_addr.s_addr == INADDR_ANY)
58336400Ssklower return 0;
58436400Ssklower if (cmd < 0 || cmd > PRC_NCMDS)
58536400Ssklower return 0;
58636400Ssklower switch (cmd) {
58736400Ssklower
58836400Ssklower case PRC_QUENCH:
58961657Ssklower in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0,
59061657Ssklower zeroin_addr, 0, cmd, tp_quench);
59136400Ssklower break;
59236400Ssklower
59336400Ssklower case PRC_ROUTEDEAD:
59436400Ssklower case PRC_HOSTUNREACH:
59536400Ssklower case PRC_UNREACH_NET:
59636400Ssklower case PRC_IFDOWN:
59736400Ssklower case PRC_HOSTDEAD:
59861657Ssklower in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0,
59945630Ssklower zeroin_addr, 0, cmd, in_rtchange);
60036400Ssklower break;
60136400Ssklower
60236400Ssklower default:
60336400Ssklower /*
60436400Ssklower case PRC_MSGSIZE:
60536400Ssklower case PRC_UNREACH_HOST:
60636400Ssklower case PRC_UNREACH_PROTOCOL:
60736400Ssklower case PRC_UNREACH_PORT:
60836400Ssklower case PRC_UNREACH_NEEDFRAG:
60936400Ssklower case PRC_UNREACH_SRCFAIL:
61036400Ssklower case PRC_REDIRECT_NET:
61136400Ssklower case PRC_REDIRECT_HOST:
61236400Ssklower case PRC_REDIRECT_TOSNET:
61336400Ssklower case PRC_REDIRECT_TOSHOST:
61436400Ssklower case PRC_TIMXCEED_INTRANS:
61536400Ssklower case PRC_TIMXCEED_REASS:
61636400Ssklower case PRC_PARAMPROB:
61736400Ssklower */
61861657Ssklower in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0,
61961657Ssklower zeroin_addr, 0, cmd, tpin_abort);
62036400Ssklower }
62136400Ssklower return 0;
62236400Ssklower }
62336400Ssklower
62436400Ssklower /*
62536400Ssklower * NAME: tpin_abort()
62636400Ssklower *
62736400Ssklower * CALLED FROM:
62836400Ssklower * xxx_notify() from tp_ctlinput() when
62936400Ssklower * net level gets some ICMP-equiv. type event.
63036400Ssklower *
63136400Ssklower * FUNCTION and ARGUMENTS:
63236400Ssklower * Cause the connection to be aborted with some sort of error
63336400Ssklower * reason indicating that the network layer caused the abort.
63436400Ssklower * Fakes an ER TPDU so we can go through the driver.
63536400Ssklower *
63636400Ssklower * RETURNS: Nothing
63736400Ssklower *
63836400Ssklower * SIDE EFFECTS:
63936400Ssklower *
64036400Ssklower * NOTES:
64136400Ssklower */
64236400Ssklower
64336400Ssklower ProtoHook
tpin_abort(inp)64436400Ssklower tpin_abort(inp)
64536400Ssklower struct inpcb *inp;
64636400Ssklower {
64736400Ssklower struct tp_event e;
64836400Ssklower
64936400Ssklower e.ev_number = ER_TPDU;
65036400Ssklower e.ATTR(ER_TPDU).e_reason = ENETRESET;
65137469Ssklower (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e);
65236400Ssklower return 0;
65336400Ssklower }
65436400Ssklower
65536400Ssklower #ifdef ARGO_DEBUG
dump_inaddr(addr)65636400Ssklower dump_inaddr(addr)
65736400Ssklower register struct sockaddr_in *addr;
65836400Ssklower {
65936400Ssklower printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr);
66036400Ssklower }
66160359Sbostic #endif /* ARGO_DEBUG */
66260359Sbostic #endif /* INET */
663