xref: /csrg-svn/sys/netiso/tp_iso.c (revision 67779)
149268Sbostic /*-
263222Sbostic  * Copyright (c) 1991, 1993
363222Sbostic  *	The Regents of the University of California.  All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*67779Ssklower  *	@(#)tp_iso.c	8.2 (Berkeley) 09/22/94
849268Sbostic  */
949268Sbostic 
1036403Ssklower /***********************************************************
1136403Ssklower 		Copyright IBM Corporation 1987
1236403Ssklower 
1336403Ssklower                       All Rights Reserved
1436403Ssklower 
1536403Ssklower Permission to use, copy, modify, and distribute this software and its
1636403Ssklower documentation for any purpose and without fee is hereby granted,
1736403Ssklower provided that the above copyright notice appear in all copies and that
1836403Ssklower both that copyright notice and this permission notice appear in
1936403Ssklower supporting documentation, and that the name of IBM not be
2036403Ssklower used in advertising or publicity pertaining to distribution of the
2136403Ssklower software without specific, written prior permission.
2236403Ssklower 
2336403Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436403Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536403Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636403Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736403Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836403Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936403Ssklower SOFTWARE.
3036403Ssklower 
3136403Ssklower ******************************************************************/
3236403Ssklower 
3336403Ssklower /*
3436403Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536403Ssklower  */
3636403Ssklower /*
3736403Ssklower  * ARGO TP
3837469Ssklower  * $Header: /var/src/sys/netiso/RCS/tp_iso.c,v 5.1 89/02/09 16:20:51 hagens Exp $
3937469Ssklower  * $Source: /var/src/sys/netiso/RCS/tp_iso.c,v $
4036403Ssklower  *
4136403Ssklower  * Here is where you find the iso-dependent code.  We've tried
4236403Ssklower  * keep all net-level and (primarily) address-family-dependent stuff
4336403Ssklower  * out of the tp source, and everthing here is reached indirectly
4436403Ssklower  * through a switch table (struct nl_protosw *) tpcb->tp_nlproto
4536403Ssklower  * (see tp_pcb.c).
4636403Ssklower  * The routines here are:
4736403Ssklower  * 		iso_getsufx: gets transport suffix out of an isopcb structure.
4836403Ssklower  * 		iso_putsufx: put transport suffix into an isopcb structure.
4936403Ssklower  *		iso_putnetaddr: put a whole net addr into an isopcb.
5036403Ssklower  *		iso_getnetaddr: get a whole net addr from an isopcb.
5144422Ssklower  *		iso_cmpnetaddr: compare a whole net addr from an isopcb.
5236403Ssklower  *		iso_recycle_suffix: clear suffix for reuse in isopcb
5336403Ssklower  * 		tpclnp_ctlinput: handle ER CNLPdu : icmp-like stuff
5436403Ssklower  * 		tpclnp_mtu: figure out what size tpdu to use
5536403Ssklower  *		tpclnp_input: take a pkt from clnp, strip off its clnp header,
5636403Ssklower  *				give to tp
5736403Ssklower  *		tpclnp_output_dg: package a pkt for clnp given 2 addresses & some data
5836403Ssklower  *		tpclnp_output: package a pkt for clnp given an isopcb & some data
5936403Ssklower  */
6036403Ssklower 
6136403Ssklower #ifdef ISO
6236403Ssklower 
6356533Sbostic #include <sys/param.h>
6456533Sbostic #include <sys/socket.h>
6556533Sbostic #include <sys/socketvar.h>
6656533Sbostic #include <sys/domain.h>
6756533Sbostic #include <sys/malloc.h>
6856533Sbostic #include <sys/mbuf.h>
6956533Sbostic #include <sys/errno.h>
7056533Sbostic #include <sys/time.h>
7156533Sbostic #include <sys/protosw.h>
72*67779Ssklower #include <sys/kernel.h>
7337469Ssklower 
7456533Sbostic #include <net/if.h>
7556533Sbostic #include <net/route.h>
7636403Ssklower 
7756533Sbostic #include <netiso/argo_debug.h>
7856533Sbostic #include <netiso/tp_param.h>
7956533Sbostic #include <netiso/tp_stat.h>
8056533Sbostic #include <netiso/tp_pcb.h>
8156533Sbostic #include <netiso/tp_trace.h>
8256533Sbostic #include <netiso/tp_stat.h>
8356533Sbostic #include <netiso/tp_tpdu.h>
8456533Sbostic #include <netiso/tp_clnp.h>
8556533Sbostic #include <netiso/cltp_var.h>
8636403Ssklower 
8736403Ssklower /*
8836403Ssklower  * CALLED FROM:
8936403Ssklower  * 	pr_usrreq() on PRU_BIND, PRU_CONNECT, PRU_ACCEPT, and PRU_PEERADDR
9037469Ssklower  * FUNCTION, ARGUMENTS:
9136403Ssklower  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
9236403Ssklower  */
9336403Ssklower 
9437469Ssklower iso_getsufx(isop, lenp, data_out, which)
9536403Ssklower 	struct isopcb *isop;
9637469Ssklower 	u_short *lenp;
9737469Ssklower 	caddr_t data_out;
9836403Ssklower 	int which;
9936403Ssklower {
10037469Ssklower 	register struct sockaddr_iso *addr = 0;
10137469Ssklower 
10236403Ssklower 	switch (which) {
10336403Ssklower 	case TP_LOCAL:
10437469Ssklower 		addr = isop->isop_laddr;
10537469Ssklower 		break;
10636403Ssklower 
10736403Ssklower 	case TP_FOREIGN:
10837469Ssklower 		addr = isop->isop_faddr;
10936403Ssklower 	}
11037469Ssklower 	if (addr)
11138841Ssklower 		bcopy(TSEL(addr), data_out, (*lenp = addr->siso_tlen));
11236403Ssklower }
11336403Ssklower 
11436403Ssklower /* CALLED FROM:
11536403Ssklower  * 	tp_newsocket(); i.e., when a connection is being established by an
11636403Ssklower  * 	incoming CR_TPDU.
11736403Ssklower  *
11836403Ssklower  * FUNCTION, ARGUMENTS:
11936403Ssklower  * 	Put a transport suffix (found in name) into an isopcb structure (isop).
12036403Ssklower  * 	The argument (which) takes the value TP_LOCAL or TP_FOREIGN.
12136403Ssklower  */
12236403Ssklower void
iso_putsufx(isop,sufxloc,sufxlen,which)12337469Ssklower iso_putsufx(isop, sufxloc, sufxlen, which)
12436403Ssklower 	struct isopcb *isop;
12537469Ssklower 	caddr_t sufxloc;
12637469Ssklower 	int sufxlen, which;
12736403Ssklower {
12837469Ssklower 	struct sockaddr_iso **dst, *backup;
12937469Ssklower 	register struct sockaddr_iso *addr;
13037469Ssklower 	struct mbuf *m;
13137469Ssklower 	int len;
13237469Ssklower 
13336403Ssklower 	switch (which) {
13437469Ssklower 	default:
13537469Ssklower 		return;
13637469Ssklower 
13736403Ssklower 	case TP_LOCAL:
13837469Ssklower 		dst = &isop->isop_laddr;
13937469Ssklower 		backup = &isop->isop_sladdr;
14036403Ssklower 		break;
14137469Ssklower 
14236403Ssklower 	case TP_FOREIGN:
14337469Ssklower 		dst = &isop->isop_faddr;
14437469Ssklower 		backup = &isop->isop_sfaddr;
14536403Ssklower 	}
14637469Ssklower 	if ((addr = *dst) == 0) {
14737469Ssklower 		addr = *dst = backup;
14837469Ssklower 		addr->siso_nlen = 0;
14938841Ssklower 		addr->siso_slen = 0;
15038841Ssklower 		addr->siso_plen = 0;
15137469Ssklower 		printf("iso_putsufx on un-initialized isopcb\n");
15237469Ssklower 	}
15337469Ssklower 	len = sufxlen + addr->siso_nlen +
15438841Ssklower 			(sizeof(*addr) - sizeof(addr->siso_data));
15537469Ssklower 	if (addr == backup) {
15638841Ssklower 		if (len > sizeof(*addr)) {
15737469Ssklower 				m = m_getclr(M_DONTWAIT, MT_SONAME);
15837469Ssklower 				if (m == 0)
15937469Ssklower 					return;
16037469Ssklower 				addr = *dst = mtod(m, struct sockaddr_iso *);
16137469Ssklower 				*addr = *backup;
16237469Ssklower 				m->m_len = len;
16337469Ssklower 		}
16438841Ssklower 	}
16537469Ssklower 	bcopy(sufxloc, TSEL(addr), sufxlen);
16638841Ssklower 	addr->siso_tlen = sufxlen;
16737469Ssklower 	addr->siso_len = len;
16836403Ssklower }
16936403Ssklower 
17036403Ssklower /*
17136403Ssklower  * CALLED FROM:
17236403Ssklower  * 	tp.trans whenever we go into REFWAIT state.
17336403Ssklower  * FUNCTION and ARGUMENT:
17436403Ssklower  *	 Called when a ref is frozen, to allow the suffix to be reused.
17536403Ssklower  * 	(isop) is the net level pcb.  This really shouldn't have to be
17636403Ssklower  * 	done in a NET level pcb but... for the internet world that just
17736403Ssklower  * 	the way it is done in BSD...
17836403Ssklower  * 	The alternative is to have the port unusable until the reference
17936403Ssklower  * 	timer goes off.
18036403Ssklower  */
18136403Ssklower void
iso_recycle_tsuffix(isop)18236403Ssklower iso_recycle_tsuffix(isop)
18336403Ssklower 	struct isopcb	*isop;
18436403Ssklower {
18538841Ssklower 	isop->isop_laddr->siso_tlen = isop->isop_faddr->siso_tlen = 0;
18636403Ssklower }
18736403Ssklower 
18836403Ssklower /*
18936403Ssklower  * CALLED FROM:
19036403Ssklower  * 	tp_newsocket(); i.e., when a connection is being established by an
19136403Ssklower  * 	incoming CR_TPDU.
19236403Ssklower  *
19336403Ssklower  * FUNCTION and ARGUMENTS:
19436403Ssklower  * 	Copy a whole net addr from a struct sockaddr (name).
19536403Ssklower  * 	into an isopcb (isop).
19636403Ssklower  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN
19736403Ssklower  */
19836403Ssklower void
iso_putnetaddr(isop,name,which)19936403Ssklower iso_putnetaddr(isop, name, which)
20036403Ssklower 	register struct isopcb	*isop;
20136403Ssklower 	struct sockaddr_iso	*name;
20236403Ssklower 	int which;
20336403Ssklower {
20437469Ssklower 	struct sockaddr_iso **sisop, *backup;
20537469Ssklower 	register struct sockaddr_iso *siso;
20637469Ssklower 
20736403Ssklower 	switch (which) {
20844422Ssklower 	default:
20944422Ssklower 		printf("iso_putnetaddr: should panic\n");
21044422Ssklower 		return;
21136403Ssklower 	case TP_LOCAL:
21237469Ssklower 		sisop = &isop->isop_laddr;
21337469Ssklower 		backup = &isop->isop_sladdr;
21436403Ssklower 		break;
21536403Ssklower 	case TP_FOREIGN:
21637469Ssklower 		sisop = &isop->isop_faddr;
21737469Ssklower 		backup = &isop->isop_sfaddr;
21836403Ssklower 	}
21937469Ssklower 	siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
22037469Ssklower 	IFDEBUG(D_TPISO)
22137469Ssklower 		printf("ISO_PUTNETADDR\n");
22237469Ssklower 		dump_isoaddr(isop->isop_faddr);
22337469Ssklower 	ENDDEBUG
22437469Ssklower 	siso->siso_addr = name->siso_addr;
22536403Ssklower }
22636403Ssklower 
22736403Ssklower /*
22836403Ssklower  * CALLED FROM:
22944422Ssklower  * 	tp_input() when a connection is being established by an
23044422Ssklower  * 	incoming CR_TPDU, and considered for interception.
23144422Ssklower  *
23244422Ssklower  * FUNCTION and ARGUMENTS:
23344422Ssklower  * 	compare a whole net addr from a struct sockaddr (name),
23444422Ssklower  * 	with that implicitly stored in an isopcb (isop).
23544422Ssklower  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN.
23644422Ssklower  */
iso_cmpnetaddr(isop,name,which)23744422Ssklower iso_cmpnetaddr(isop, name, which)
23844422Ssklower 	register struct isopcb	*isop;
23944422Ssklower 	register struct sockaddr_iso	*name;
24044422Ssklower 	int which;
24144422Ssklower {
24244422Ssklower 	struct sockaddr_iso **sisop, *backup;
24344422Ssklower 	register struct sockaddr_iso *siso;
24444422Ssklower 
24544422Ssklower 	switch (which) {
24644422Ssklower 	default:
24744422Ssklower 		printf("iso_cmpnetaddr: should panic\n");
24844422Ssklower 		return 0;
24944422Ssklower 	case TP_LOCAL:
25044422Ssklower 		sisop = &isop->isop_laddr;
25144422Ssklower 		backup = &isop->isop_sladdr;
25244422Ssklower 		break;
25344422Ssklower 	case TP_FOREIGN:
25444422Ssklower 		sisop = &isop->isop_faddr;
25544422Ssklower 		backup = &isop->isop_sfaddr;
25644422Ssklower 	}
25744422Ssklower 	siso = ((*sisop == 0) ? (*sisop = backup) : *sisop);
25844422Ssklower 	IFDEBUG(D_TPISO)
25944422Ssklower 		printf("ISO_CMPNETADDR\n");
26044422Ssklower 		dump_isoaddr(siso);
26144422Ssklower 	ENDDEBUG
26244422Ssklower 	if (name->siso_tlen && bcmp(TSEL(name), TSEL(siso), name->siso_tlen))
26344422Ssklower 		return (0);
26444422Ssklower 	return (bcmp((caddr_t)name->siso_data,
26544422Ssklower 			 (caddr_t)siso->siso_data, name->siso_nlen) == 0);
26644422Ssklower }
26744422Ssklower 
26844422Ssklower /*
26944422Ssklower  * CALLED FROM:
27036403Ssklower  *  pr_usrreq() PRU_SOCKADDR, PRU_ACCEPT, PRU_PEERADDR
27136403Ssklower  * FUNCTION and ARGUMENTS:
27236403Ssklower  * 	Copy a whole net addr from an isopcb (isop) into
27336403Ssklower  * 	a struct sockaddr (name).
27436403Ssklower  * 	The argument (which) takes values TP_LOCAL or TP_FOREIGN.
27536403Ssklower  */
27636403Ssklower 
27736403Ssklower void
iso_getnetaddr(isop,name,which)27836403Ssklower iso_getnetaddr( isop, name, which)
27936403Ssklower 	struct isopcb *isop;
28037469Ssklower 	struct mbuf *name;
28136403Ssklower 	int which;
28236403Ssklower {
28337469Ssklower 	struct sockaddr_iso *siso =
28437469Ssklower 		(which == TP_LOCAL ? isop->isop_laddr : isop->isop_faddr);
28537469Ssklower 	if (siso)
28637469Ssklower 		bcopy((caddr_t)siso, mtod(name, caddr_t),
28737469Ssklower 				(unsigned)(name->m_len = siso->siso_len));
28837469Ssklower 	else
28937469Ssklower 		name->m_len = 0;
29036403Ssklower }
29136403Ssklower /*
29251246Ssklower  * NAME: 	tpclnp_mtu()
29351246Ssklower  *
29436403Ssklower  * CALLED FROM:
29551246Ssklower  *  tp_route_to() on incoming CR, CC, and pr_usrreq() for PRU_CONNECT
29636403Ssklower  *
29751246Ssklower  * FUNCTION, ARGUMENTS, and RETURN VALUE:
29851246Ssklower  *
29951246Ssklower  * Perform subnetwork dependent part of determining MTU information.
30051246Ssklower  * It appears that setting a double pointer to the rtentry associated with
30151246Ssklower  * the destination, and returning the header size for the network protocol
30251246Ssklower  * suffices.
30336403Ssklower  *
30451246Ssklower  * SIDE EFFECTS:
30551246Ssklower  * Sets tp_routep pointer in pcb.
30651246Ssklower  *
30751246Ssklower  * NOTES:
30836403Ssklower  */
tpclnp_mtu(tpcb)30951246Ssklower tpclnp_mtu(tpcb)
31051246Ssklower register struct tp_pcb *tpcb;
31136403Ssklower {
31251246Ssklower 	struct isopcb			*isop = (struct isopcb *)tpcb->tp_npcb;
31336403Ssklower 
31436403Ssklower 	IFDEBUG(D_CONN)
31551246Ssklower 		printf("tpclnp_mtu(tpcb)\n", tpcb);
31636403Ssklower 	ENDDEBUG
31751246Ssklower 	tpcb->tp_routep = &(isop->isop_route.ro_rt);
31851246Ssklower 	if (tpcb->tp_netservice == ISO_CONS)
31951246Ssklower 		return 0;
32051246Ssklower 	else
32151246Ssklower 		return (sizeof(struct clnp_fixed) + sizeof(struct clnp_segment) +
32251246Ssklower 			2 * sizeof(struct iso_addr));
32336403Ssklower 
32436403Ssklower }
32536403Ssklower 
32636403Ssklower /*
32736403Ssklower  * CALLED FROM:
32836403Ssklower  *  tp_emit()
32936403Ssklower  * FUNCTION and ARGUMENTS:
33036403Ssklower  *  Take a packet(m0) from tp and package it so that clnp will accept it.
33136403Ssklower  *  This means prepending space for the clnp header and filling in a few
33236403Ssklower  *  of the fields.
33351246Ssklower  *  isop is the isopcb structure; datalen is the length of the data in the
33436403Ssklower  *  mbuf string m0.
33536403Ssklower  * RETURN VALUE:
33636403Ssklower  *  whatever (E*) is returned form the net layer output routine.
33736403Ssklower  */
33836403Ssklower 
33936403Ssklower int
tpclnp_output(isop,m0,datalen,nochksum)34036403Ssklower tpclnp_output(isop, m0, datalen, nochksum)
34136403Ssklower 	struct isopcb		*isop;
34236403Ssklower 	struct mbuf 		*m0;
34336403Ssklower 	int 				datalen;
34436403Ssklower 	int					nochksum;
34536403Ssklower {
34637469Ssklower 	register struct mbuf *m = m0;
34736403Ssklower 	IncStat(ts_tpdu_sent);
34836403Ssklower 
34936403Ssklower 	IFDEBUG(D_TPISO)
35036403Ssklower 		struct tpdu *hdr = mtod(m0, struct tpdu *);
35136403Ssklower 
35236403Ssklower 		printf(
35336403Ssklower "abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n",
35436403Ssklower 			datalen,
35536403Ssklower 			(int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum);
35637469Ssklower 		dump_isoaddr(isop->isop_faddr);
35736403Ssklower 		printf("\nsrc addr:\n");
35837469Ssklower 		dump_isoaddr(isop->isop_laddr);
35936403Ssklower 		dump_mbuf(m0, "at tpclnp_output");
36036403Ssklower 	ENDDEBUG
36136403Ssklower 
36236403Ssklower 	return
36338841Ssklower 		clnp_output(m0, isop, datalen,  /* flags */nochksum ? CLNP_NO_CKSUM : 0);
36436403Ssklower }
36536403Ssklower 
36636403Ssklower /*
36736403Ssklower  * CALLED FROM:
36836403Ssklower  *  tp_error_emit()
36936403Ssklower  * FUNCTION and ARGUMENTS:
37036403Ssklower  *  This is a copy of tpclnp_output that takes the addresses
37136403Ssklower  *  instead of a pcb.  It's used by the tp_error_emit, when we
37236403Ssklower  *  don't have an iso_pcb with which to call the normal output rtn.
37336403Ssklower  * RETURN VALUE:
37436403Ssklower  *  ENOBUFS or
37536403Ssklower  *  whatever (E*) is returned form the net layer output routine.
37636403Ssklower  */
37736403Ssklower 
37836403Ssklower int
tpclnp_output_dg(laddr,faddr,m0,datalen,ro,nochksum)37936403Ssklower tpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum)
38036403Ssklower 	struct iso_addr		*laddr, *faddr;
38136403Ssklower 	struct mbuf 		*m0;
38236403Ssklower 	int 				datalen;
38336403Ssklower 	struct route 		*ro;
38436403Ssklower 	int					nochksum;
38536403Ssklower {
38636403Ssklower 	struct isopcb		tmppcb;
38736403Ssklower 	int					err;
38836403Ssklower 	int					flags;
38937469Ssklower 	register struct mbuf *m = m0;
39036403Ssklower 
39136403Ssklower 	IFDEBUG(D_TPISO)
39236403Ssklower 		printf("tpclnp_output_dg  datalen 0x%x m0 0x%x\n", datalen, m0);
39336403Ssklower 	ENDDEBUG
39436403Ssklower 
39536403Ssklower 	/*
39636403Ssklower 	 *	Fill in minimal portion of isopcb so that clnp can send the
39736403Ssklower 	 *	packet.
39836403Ssklower 	 */
39936403Ssklower 	bzero((caddr_t)&tmppcb, sizeof(tmppcb));
40037469Ssklower 	tmppcb.isop_laddr = &tmppcb.isop_sladdr;
40137469Ssklower 	tmppcb.isop_laddr->siso_addr = *laddr;
40237469Ssklower 	tmppcb.isop_faddr = &tmppcb.isop_sfaddr;
40337469Ssklower 	tmppcb.isop_faddr->siso_addr = *faddr;
40436403Ssklower 
40536403Ssklower 	IFDEBUG(D_TPISO)
40636403Ssklower 		printf("tpclnp_output_dg  faddr: \n");
40737469Ssklower 		dump_isoaddr(&tmppcb.isop_sfaddr);
40836403Ssklower 		printf("\ntpclnp_output_dg  laddr: \n");
40937469Ssklower 		dump_isoaddr(&tmppcb.isop_sladdr);
41036403Ssklower 		printf("\n");
41136403Ssklower 	ENDDEBUG
41236403Ssklower 
41336403Ssklower 	/*
41436403Ssklower 	 *	Do not use packet cache since this is a one shot error packet
41536403Ssklower 	 */
41636403Ssklower 	flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0));
41736403Ssklower 
41836403Ssklower 	IncStat(ts_tpdu_sent);
41936403Ssklower 
42038841Ssklower 	err = clnp_output(m0, &tmppcb, datalen,  flags);
42136403Ssklower 
42236403Ssklower 	/*
42336403Ssklower 	 *	Free route allocated by clnp (if the route was indeed allocated)
42436403Ssklower 	 */
42536403Ssklower 	if (tmppcb.isop_route.ro_rt)
42636403Ssklower 		RTFREE(tmppcb.isop_route.ro_rt);
42736403Ssklower 
42836403Ssklower 	return(err);
42936403Ssklower }
43036403Ssklower /*
43136403Ssklower  * CALLED FROM:
43236403Ssklower  * 	clnp's input routine, indirectly through the protosw.
43336403Ssklower  * FUNCTION and ARGUMENTS:
43436403Ssklower  * Take a packet (m) from clnp, strip off the clnp header and give it to tp
43536403Ssklower  * No return value.
43636403Ssklower  */
43736403Ssklower ProtoHook
tpclnp_input(m,src,dst,clnp_len,ce_bit)43839927Ssklower tpclnp_input(m, src, dst, clnp_len, ce_bit)
43939926Ssklower 	register struct mbuf *m;
44039926Ssklower 	struct sockaddr_iso *src, *dst;
44139927Ssklower 	int clnp_len, ce_bit;
44236403Ssklower {
44337469Ssklower 	struct mbuf *tp_inputprep();
44439926Ssklower 	int tp_input(), cltp_input(), (*input)() = tp_input;
44536403Ssklower 
44636403Ssklower 	IncStat(ts_pkt_rcvd);
44736403Ssklower 
44836403Ssklower 	IFDEBUG(D_TPINPUT)
44936403Ssklower 		printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len);
45036403Ssklower 		dump_mbuf(m, "at tpclnp_input");
45136403Ssklower 	ENDDEBUG
45236403Ssklower 	/*
45336403Ssklower 	 * CLNP gives us an mbuf chain WITH the clnp header pulled up,
45436403Ssklower 	 * and the length of the clnp header.
45536403Ssklower 	 * First, strip off the Clnp header. leave the mbuf there for the
45636403Ssklower 	 * pullup that follows.
45736403Ssklower 	 */
45836403Ssklower 	m->m_len -= clnp_len;
45937469Ssklower 	m->m_data += clnp_len;
46056911Ssklower 	m->m_pkthdr.len -= clnp_len;
46156911Ssklower 	/* XXXX: should probably be in clnp_input */
46256911Ssklower 	switch (dst->siso_data[dst->siso_nlen - 1]) {
46356911Ssklower #ifdef TUBA
46456911Ssklower 	case ISOPROTO_TCP:
46556911Ssklower 		return (tuba_tcpinput(m, src, dst));
46656911Ssklower #endif
46756911Ssklower 	case 0:
46856911Ssklower 		if (m->m_len == 0 && (m = m_pullup(m, 1)) == 0)
46956911Ssklower 			return 0;
47056911Ssklower 		if (*(mtod(m, u_char *)) == ISO10747_IDRP)
47156911Ssklower 			return (idrp_input(m, src, dst));
47256911Ssklower 	}
47337469Ssklower 	m = tp_inputprep(m);
47439926Ssklower 	if (m == 0)
47539926Ssklower 		return 0;
47639926Ssklower 	if (mtod(m, u_char *)[1] == UD_TPDU_type)
47739926Ssklower 		input = cltp_input;
47836403Ssklower 
47936403Ssklower 	IFDEBUG(D_TPINPUT)
48036403Ssklower 		dump_mbuf(m, "after tpclnp_input both pullups");
48136403Ssklower 	ENDDEBUG
48236403Ssklower 
48336403Ssklower 	IFDEBUG(D_TPISO)
48439926Ssklower 		printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n",
48539926Ssklower 			(input == tp_input ? "tp_" : "clts_"), src, dst);
48639926Ssklower 		dump_isoaddr(src);
48736403Ssklower 		printf(" dst addr:\n");
48839926Ssklower 		dump_isoaddr(dst);
48936403Ssklower 	ENDDEBUG
49036403Ssklower 
49139926Ssklower 	(void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst,
49239927Ssklower 				0, tpclnp_output_dg, ce_bit);
49336403Ssklower 
49436403Ssklower 	IFDEBUG(D_QUENCH)
49536403Ssklower 		{
49636403Ssklower 			if(time.tv_usec & 0x4 && time.tv_usec & 0x40) {
49736403Ssklower 				printf("tpclnp_input: FAKING %s\n",
49836403Ssklower 					tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2");
49936403Ssklower 				if(tp_stat.ts_pkt_rcvd & 0x1) {
50036403Ssklower 					tpclnp_ctlinput(PRC_QUENCH, &src);
50136403Ssklower 				} else {
50236403Ssklower 					tpclnp_ctlinput(PRC_QUENCH2, &src);
50336403Ssklower 				}
50436403Ssklower 			}
50536403Ssklower 		}
50636403Ssklower 	ENDDEBUG
50736403Ssklower 
50836403Ssklower 	return 0;
50936403Ssklower }
51036403Ssklower 
51136403Ssklower ProtoHook
iso_rtchange()51236403Ssklower iso_rtchange()
51336403Ssklower {
51436403Ssklower 	return 0;
51536403Ssklower }
51636403Ssklower 
51736403Ssklower /*
51836403Ssklower  * CALLED FROM:
51936403Ssklower  *  tpclnp_ctlinput()
52036403Ssklower  * FUNCTION and ARGUMENTS:
52136403Ssklower  *  find the tpcb pointer and pass it to tp_quench
52236403Ssklower  */
52336403Ssklower void
tpiso_decbit(isop)52436403Ssklower tpiso_decbit(isop)
52536403Ssklower 	struct isopcb *isop;
52636403Ssklower {
52750435Ssklower 	tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH2);
52836403Ssklower }
52936403Ssklower /*
53036403Ssklower  * CALLED FROM:
53136403Ssklower  *  tpclnp_ctlinput()
53236403Ssklower  * FUNCTION and ARGUMENTS:
53336403Ssklower  *  find the tpcb pointer and pass it to tp_quench
53436403Ssklower  */
53536403Ssklower void
tpiso_quench(isop)53636403Ssklower tpiso_quench(isop)
53736403Ssklower 	struct isopcb *isop;
53836403Ssklower {
53950435Ssklower 	tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH);
54036403Ssklower }
54136403Ssklower 
54236403Ssklower /*
54336403Ssklower  * CALLED FROM:
54436403Ssklower  *  The network layer through the protosw table.
54536403Ssklower  * FUNCTION and ARGUMENTS:
54636403Ssklower  *	When clnp an ICMP-like msg this gets called.
54736403Ssklower  *	It either returns an error status to the user or
54836403Ssklower  *	it causes all connections on this address to be aborted
54936403Ssklower  *	by calling the appropriate xx_notify() routine.
55036403Ssklower  *	(cmd) is the type of ICMP error.
55136403Ssklower  * 	(siso) is the address of the guy who sent the ER CLNPDU
55236403Ssklower  */
55336403Ssklower ProtoHook
tpclnp_ctlinput(cmd,siso)55436403Ssklower tpclnp_ctlinput(cmd, siso)
55536403Ssklower 	int cmd;
55636403Ssklower 	struct sockaddr_iso *siso;
55736403Ssklower {
55836403Ssklower 	extern u_char inetctlerrmap[];
55936403Ssklower 	extern ProtoHook tpiso_abort();
56036403Ssklower 	extern ProtoHook iso_rtchange();
56136403Ssklower 	extern ProtoHook tpiso_reset();
56237469Ssklower 	void iso_pcbnotify();
56336403Ssklower 
56436403Ssklower 	IFDEBUG(D_TPINPUT)
56539926Ssklower 		printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd);
56639926Ssklower 		dump_isoaddr(siso);
56736403Ssklower 	ENDDEBUG
56836403Ssklower 
56936403Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
57036403Ssklower 		return 0;
57139926Ssklower 	if (siso->siso_family != AF_ISO)
57239926Ssklower 		return 0;
57336403Ssklower 	switch (cmd) {
57436403Ssklower 
57536403Ssklower 		case	PRC_QUENCH2:
57639926Ssklower 			iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit);
57736403Ssklower 			break;
57836403Ssklower 
57936403Ssklower 		case	PRC_QUENCH:
58039926Ssklower 			iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench);
58136403Ssklower 			break;
58236403Ssklower 
58336403Ssklower 		case	PRC_TIMXCEED_REASS:
58436403Ssklower 		case	PRC_ROUTEDEAD:
58539926Ssklower 			iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset);
58636403Ssklower 			break;
58736403Ssklower 
58836403Ssklower 		case	PRC_HOSTUNREACH:
58936403Ssklower 		case	PRC_UNREACH_NET:
59036403Ssklower 		case	PRC_IFDOWN:
59136403Ssklower 		case	PRC_HOSTDEAD:
59239926Ssklower 			iso_pcbnotify(&tp_isopcb, siso,
59336403Ssklower 					(int)inetctlerrmap[cmd], iso_rtchange);
59436403Ssklower 			break;
59536403Ssklower 
59636403Ssklower 		default:
59736403Ssklower 		/*
59836403Ssklower 		case	PRC_MSGSIZE:
59936403Ssklower 		case	PRC_UNREACH_HOST:
60036403Ssklower 		case	PRC_UNREACH_PROTOCOL:
60136403Ssklower 		case	PRC_UNREACH_PORT:
60236403Ssklower 		case	PRC_UNREACH_NEEDFRAG:
60336403Ssklower 		case	PRC_UNREACH_SRCFAIL:
60436403Ssklower 		case	PRC_REDIRECT_NET:
60536403Ssklower 		case	PRC_REDIRECT_HOST:
60636403Ssklower 		case	PRC_REDIRECT_TOSNET:
60736403Ssklower 		case	PRC_REDIRECT_TOSHOST:
60836403Ssklower 		case	PRC_TIMXCEED_INTRANS:
60936403Ssklower 		case	PRC_PARAMPROB:
61036403Ssklower 		*/
61139926Ssklower 		iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort);
61236403Ssklower 		break;
61336403Ssklower 	}
61436403Ssklower 	return 0;
61536403Ssklower }
61639926Ssklower /*
61739926Ssklower  * XXX - Variant which is called by clnp_er.c with an isoaddr rather
61839926Ssklower  * than a sockaddr_iso.
61939926Ssklower  */
62036403Ssklower 
62139926Ssklower static struct sockaddr_iso siso = {sizeof(siso), AF_ISO};
tpclnp_ctlinput1(cmd,isoa)62239926Ssklower tpclnp_ctlinput1(cmd, isoa)
62339926Ssklower 	int cmd;
62439926Ssklower 	struct iso_addr *isoa;
62539926Ssklower {
62639926Ssklower 	bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr));
62739926Ssklower 	bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len);
62839926Ssklower 	tpclnp_ctlinput(cmd, &siso);
62939926Ssklower }
63039926Ssklower 
63136403Ssklower /*
63236403Ssklower  * These next 2 routines are
63336403Ssklower  * CALLED FROM:
63436403Ssklower  *	xxx_notify() from tp_ctlinput() when
63536403Ssklower  *  net level gets some ICMP-equiv. type event.
63636403Ssklower  * FUNCTION and ARGUMENTS:
63736403Ssklower  *  Cause the connection to be aborted with some sort of error
63836403Ssklower  *  reason indicating that the network layer caused the abort.
63936403Ssklower  *  Fakes an ER TPDU so we can go through the driver.
64036403Ssklower  *  abort always aborts the TP connection.
64136403Ssklower  *  reset may or may not, depending on the TP class that's in use.
64236403Ssklower  */
64336403Ssklower ProtoHook
tpiso_abort(isop)64436403Ssklower tpiso_abort(isop)
64536403Ssklower 	struct isopcb *isop;
64636403Ssklower {
64736403Ssklower 	struct tp_event e;
64836403Ssklower 
64936403Ssklower 	IFDEBUG(D_CONN)
65036403Ssklower 		printf("tpiso_abort 0x%x\n", isop);
65136403Ssklower 	ENDDEBUG
65236403Ssklower 	e.ev_number = ER_TPDU;
65336403Ssklower 	e.ATTR(ER_TPDU).e_reason = ECONNABORTED;
65450435Ssklower 	return  tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);
65536403Ssklower }
65636403Ssklower 
65736403Ssklower ProtoHook
tpiso_reset(isop)65836403Ssklower tpiso_reset(isop)
65936403Ssklower 	struct isopcb *isop;
66036403Ssklower {
66136403Ssklower 	struct tp_event e;
66236403Ssklower 
66336403Ssklower 	e.ev_number = T_NETRESET;
66450435Ssklower 	return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);
66536403Ssklower 
66636403Ssklower }
66736403Ssklower 
66860359Sbostic #endif /* ISO */
669