xref: /csrg-svn/sys/netiso/clnp_input.c (revision 37469)
136370Ssklower /***********************************************************
236370Ssklower 		Copyright IBM Corporation 1987
336370Ssklower 
436370Ssklower                       All Rights Reserved
536370Ssklower 
636370Ssklower Permission to use, copy, modify, and distribute this software and its
736370Ssklower documentation for any purpose and without fee is hereby granted,
836370Ssklower provided that the above copyright notice appear in all copies and that
936370Ssklower both that copyright notice and this permission notice appear in
1036370Ssklower supporting documentation, and that the name of IBM not be
1136370Ssklower used in advertising or publicity pertaining to distribution of the
1236370Ssklower software without specific, written prior permission.
1336370Ssklower 
1436370Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536370Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636370Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736370Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836370Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936370Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036370Ssklower SOFTWARE.
2136370Ssklower 
2236370Ssklower ******************************************************************/
2336370Ssklower 
2436370Ssklower /*
2536370Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636370Ssklower  */
2736766Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */
2836766Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */
29*37469Ssklower /*	@(#)clnp_input.c	7.4 (Berkeley) 04/22/89 */
3036370Ssklower 
3136370Ssklower #ifndef lint
3236766Ssklower static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $";
3336370Ssklower #endif lint
3436370Ssklower 
3536370Ssklower #include "../h/types.h"
3636370Ssklower #include "../h/param.h"
3736370Ssklower #include "../h/mbuf.h"
3836370Ssklower #include "../h/domain.h"
3936370Ssklower #include "../h/protosw.h"
4036370Ssklower #include "../h/socket.h"
4136370Ssklower #include "../h/socketvar.h"
4236370Ssklower #include "../h/errno.h"
4336370Ssklower #include "../h/time.h"
4436370Ssklower 
4536370Ssklower #include "../net/if.h"
46*37469Ssklower #include "../net/iftypes.h"
4736370Ssklower #include "../net/route.h"
4836370Ssklower 
49*37469Ssklower #include "iso.h"
50*37469Ssklower #include "iso_var.h"
51*37469Ssklower #include "iso_snpac.h"
52*37469Ssklower #include "clnp.h"
53*37469Ssklower #include "clnl.h"
54*37469Ssklower #include "../netinet/in_systm.h"
55*37469Ssklower #include "../netinet/ip.h"
56*37469Ssklower #include "eonvar.h"
57*37469Ssklower #include "esis.h"
58*37469Ssklower #include "clnp_stat.h"
59*37469Ssklower #include "argo_debug.h"
6036370Ssklower 
6136370Ssklower #ifdef ISO
6236370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
6336370Ssklower struct clnl_protosw clnl_protox[256];
6436370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
6536370Ssklower struct mbuf	*clnp_data_ck();
6636370Ssklower 
6736370Ssklower int	clnp_input();
6836370Ssklower 
6936370Ssklower int	esis_input();
7036370Ssklower 
7136370Ssklower #ifdef	ISO_X25ESIS
7236370Ssklower int	x25esis_input();
7336370Ssklower #endif	ISO_X25ESIS
7436370Ssklower 
7536370Ssklower /*
7636370Ssklower  * FUNCTION:		clnp_init
7736370Ssklower  *
7836370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
7936370Ssklower  *
8036370Ssklower  * RETURNS:			none
8136370Ssklower  *
8236370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
8336370Ssklower  *					the isosw table.
8436370Ssklower  *
8536370Ssklower  * NOTES:
8636370Ssklower  */
8736370Ssklower clnp_init()
8836370Ssklower {
8936370Ssklower 	register struct protosw *pr;
9036370Ssklower 
9136370Ssklower 	/*
9236370Ssklower 	 *	CLNP protox initialization
9336370Ssklower 	 */
9436370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
9536370Ssklower 		printf("clnl_init: no raw CLNP\n");
9636370Ssklower 	else
9736370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
9836370Ssklower 
9936370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
10036370Ssklower 		printf("clnl_init: no tp/clnp\n");
10136370Ssklower 	else
10236370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
10336370Ssklower 
10436370Ssklower 	/*
10536370Ssklower 	 *	CLNL protox initialization
10636370Ssklower 	 */
10736370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
10836370Ssklower 
10936370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
11036370Ssklower }
11136370Ssklower 
11236370Ssklower /*
11336370Ssklower  * FUNCTION:		clnlintr
11436370Ssklower  *
11536370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
11636370Ssklower  *
11736370Ssklower  * RETURNS:			nothing.
11836370Ssklower  *
11936370Ssklower  * SIDE EFFECTS:
12036370Ssklower  *
12136370Ssklower  * NOTES:
12236370Ssklower  */
12336370Ssklower clnlintr()
12436370Ssklower {
12536370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
12636370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
12736370Ssklower 	int							s;		/* save and restore priority */
12836370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
12936370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
13036370Ssklower 
13136370Ssklower 	/*
13236370Ssklower 	 *	Get next datagram off clnl input queue
13336370Ssklower 	 */
13436370Ssklower next:
13536370Ssklower 	s = splimp();
13636765Ssklower 	/* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
13736765Ssklower 	IF_DEQUEUE(&clnlintrq, m);
138*37469Ssklower 	splx(s);
13936370Ssklower 
14036765Ssklower 
14136765Ssklower 	if (m == 0)		/* nothing to do */
14236765Ssklower 		return;
143*37469Ssklower 	if ((m->m_flags & M_PKTHDR) == 0) {
14436765Ssklower 		m_freem(m);
14536765Ssklower 		goto next;
14636765Ssklower 	}
147*37469Ssklower 	bzero((caddr_t)&sh, sizeof(sh));
148*37469Ssklower 	sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
149*37469Ssklower 	switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
150*37469Ssklower 		extern int ether_output();
151*37469Ssklower 	case IFT_EON:
152*37469Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
153*37469Ssklower 		bcopy(sizeof(u_long) + mtod(m, caddr_t),
154*37469Ssklower 					(caddr_t)sh.snh_shost, sizeof(u_long));
155*37469Ssklower 		sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
156*37469Ssklower 								_offsetof(struct eon_hdr, eonh_class)];
157*37469Ssklower 		m->m_data += EONIPLEN;
158*37469Ssklower 		m->m_len -= EONIPLEN;
159*37469Ssklower 		m->m_pkthdr.len -= EONIPLEN;
160*37469Ssklower 		break;
161*37469Ssklower 
162*37469Ssklower 	default:
163*37469Ssklower 		if (sh.snh_ifp->if_output == ether_output) {
164*37469Ssklower 			bcopy((caddr_t)(mtod(m, struct llc_etherhdr *)->dst),
165*37469Ssklower 				(caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
166*37469Ssklower 			m->m_data += sizeof (struct llc_etherhdr);
167*37469Ssklower 			m->m_len -= sizeof (struct llc_etherhdr);
168*37469Ssklower 			m->m_pkthdr.len -= sizeof (struct llc_etherhdr);
169*37469Ssklower 		}
170*37469Ssklower 	}
17136370Ssklower 	IFDEBUG(D_INPUT)
17236370Ssklower 		int i;
17336370Ssklower 		printf("clnlintr: src:");
17436370Ssklower 		for (i=0; i<6; i++)
17536370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
17636370Ssklower 		printf(" dst:");
17736370Ssklower 		for (i=0; i<6; i++)
17836370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
17936370Ssklower 		printf("\n");
18036370Ssklower 	ENDDEBUG
18136370Ssklower 
18236370Ssklower 	/*
18336370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
18436370Ssklower 	 *	Drop the packet if this fails.
18536370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
18636370Ssklower 	 *	data is not there.
18736370Ssklower 	 */
18836370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
18936370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
19036370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
19136370Ssklower 		goto next;				/* m_pullup discards mbuf */
19236370Ssklower 	}
19336370Ssklower 
19436370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
19536370Ssklower 
19636370Ssklower 	/*
19736370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
19836370Ssklower 	 */
19936370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
20036370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
20136370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
20236370Ssklower 		m_freem(m);
20336370Ssklower 		goto next;
20436370Ssklower 	}
20536370Ssklower 
20636370Ssklower 	/*
20736370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
20836370Ssklower 	 *	Drop packet if this fails.
20936370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
21036370Ssklower 	 */
21136370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
212*37469Ssklower 		if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
21336370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
21436370Ssklower 			goto next;	/* m_pullup discards mbuf */
21536370Ssklower 		}
21636370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
21736370Ssklower 	}
21836370Ssklower 
21936370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
22036370Ssklower 
22136370Ssklower 
22236370Ssklower 	if (clnlsw->clnl_input)
22336370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
22436370Ssklower 	else
22536370Ssklower 		m_freem(m);
22636370Ssklower 
22736370Ssklower 	goto next;
22836370Ssklower }
22936370Ssklower 
23036370Ssklower /*
23136370Ssklower  * FUNCTION:		clnp_input
23236370Ssklower  *
23336370Ssklower  * PURPOSE:			process an incoming clnp packet
23436370Ssklower  *
23536370Ssklower  * RETURNS:			nothing
23636370Ssklower  *
23736370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
23836370Ssklower  *
23936370Ssklower  * NOTES:
24036370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
24136370Ssklower  *	will it be correctly aligned?
24236370Ssklower  */
243*37469Ssklower clnp_input(m, shp)
24436370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
24536370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
24636370Ssklower {
24736370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
24836370Ssklower 	struct iso_addr				src;	/* source address of pkt */
24936370Ssklower 	struct iso_addr				dst;	/* destination address of pkt */
25036370Ssklower 	caddr_t						hoff;	/* current offset in packet */
25136370Ssklower 	caddr_t						hend;	/* address of end of header info */
25236370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
25336370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
25436370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
25536370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
25636370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
25736766Ssklower 	int							need_afrin = 0;
25836766Ssklower 										/* true if congestion experienced */
25936766Ssklower 										/* which means you need afrin nose */
26036766Ssklower 										/* spray. How clever! */
26136370Ssklower 
26236370Ssklower 	IFDEBUG(D_INPUT)
26336370Ssklower 		printf(
26436766Ssklower 		   "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
26536766Ssklower 			m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
26636370Ssklower 	ENDDEBUG
26736766Ssklower 	need_afrin = 0;
26836370Ssklower 
26936370Ssklower 	/*
27036370Ssklower 	 *	If no iso addresses have been set, there is nothing
27136370Ssklower 	 *	to do with the packet.
27236370Ssklower 	 */
27336370Ssklower 	if (iso_ifaddr == NULL) {
27436370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
27536370Ssklower 		return;
27636370Ssklower 	}
27736370Ssklower 
27836370Ssklower 	INCSTAT(cns_total);
27936370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
28036370Ssklower 
28136766Ssklower 	IFDEBUG(D_DUMPIN)
28236766Ssklower 		struct mbuf *mhead;
28336766Ssklower 		int			total_len = 0;
28436766Ssklower 		printf("clnp_input: clnp header:\n");
28536766Ssklower 		dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
28636766Ssklower 		printf("clnp_input: mbuf chain:\n");
28736766Ssklower 		for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
28836766Ssklower 			printf("m x%x, len %d\n", mhead, mhead->m_len);
28936766Ssklower 			total_len += mhead->m_len;
29036766Ssklower 		}
29136766Ssklower 		printf("clnp_input: total length of mbuf chain %d:\n", total_len);
29236766Ssklower 	ENDDEBUG
29336766Ssklower 
29436370Ssklower 	/*
29536370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
29636370Ssklower 	 *	checksum does not match
29736370Ssklower 	 */
298*37469Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
29936370Ssklower 		INCSTAT(cns_badcsum);
30036370Ssklower 		clnp_discard(m, GEN_BADCSUM);
301*37469Ssklower 		return;
30236370Ssklower 	}
30336370Ssklower 
30436370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
30536370Ssklower 		INCSTAT(cns_badvers);
30636370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
307*37469Ssklower 		return;
30836370Ssklower 	}
30936370Ssklower 
31036370Ssklower 
31136370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
31236370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
31336370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
314*37469Ssklower 		return;
31536370Ssklower 
31636370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
31736370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
31836370Ssklower 
31936370Ssklower 	/*
32036370Ssklower 	 *	extract the source and destination address
32136370Ssklower 	 *	drop packet on failure
32236370Ssklower 	 */
32336370Ssklower 	bzero((caddr_t)&src, sizeof(src));
32436370Ssklower 	bzero((caddr_t)&dst, sizeof(dst));
32536370Ssklower 
32636370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
32736370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
32836370Ssklower 	if (hoff == (caddr_t)0) {
32936370Ssklower 		INCSTAT(cns_badaddr);
33036370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
331*37469Ssklower 		return;
33236370Ssklower 	}
33336370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
33436370Ssklower 	if (hoff == (caddr_t)0) {
33536370Ssklower 		INCSTAT(cns_badaddr);
33636370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
337*37469Ssklower 		return;
33836370Ssklower 	}
33936370Ssklower 
34036370Ssklower 	IFDEBUG(D_INPUT)
34136370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
34236370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
34336370Ssklower 	ENDDEBUG
34436370Ssklower 
34536370Ssklower 	/*
34636370Ssklower 	 *	extract the segmentation information, if it is present.
34736370Ssklower 	 *	drop packet on failure
34836370Ssklower 	 */
349*37469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
350*37469Ssklower 		(clnp->cnf_type & CNF_SEG_OK)) {
35136370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
35236370Ssklower 			INCSTAT(cns_noseg);
35336370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
354*37469Ssklower 			return;
35536370Ssklower 		} else {
35636370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
35736370Ssklower 			/* make sure segmentation fields are in host order */
35836370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
35936370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
36036370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
36136370Ssklower 			seg_off = hoff - (caddr_t)clnp;
36236370Ssklower 			hoff += sizeof(struct clnp_segment);
36336370Ssklower 		}
36436370Ssklower 	}
36536370Ssklower 
36636370Ssklower 	/*
36736370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
36836370Ssklower 	 *	false (indicating an error was found in the options) or
36936370Ssklower 	 *	an unsupported option was found
37036370Ssklower 	 *	then drop packet and emit an ER.
37136370Ssklower 	 */
37236370Ssklower 	if (hoff < hend) {
37336370Ssklower 		int		errcode;
37436370Ssklower 
37536370Ssklower 		oidxp = &oidx;
37636370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
37736370Ssklower 
37836370Ssklower 		/* we do not support security */
37936370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
38036370Ssklower 			errcode = DISC_UNSUPPSECURE;
38136370Ssklower 
38236370Ssklower 		/* the er option is valid with ER pdus only */
38336370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
384*37469Ssklower 			((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
38536370Ssklower 			errcode = DISC_UNSUPPOPT;
38636370Ssklower 
38736766Ssklower #ifdef	DECBIT
38836766Ssklower 		/* check if the congestion experienced bit is set */
38936766Ssklower 		if (oidxp->cni_qos_formatp) {
39036766Ssklower 			caddr_t	qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
39136766Ssklower 			u_char	qos = *qosp;
39236766Ssklower 
39336766Ssklower 			need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
39436766Ssklower 				(CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
39536766Ssklower 			if (need_afrin)
39636766Ssklower 				INCSTAT(cns_congest_rcvd);
39736766Ssklower 		}
39836766Ssklower #endif	DECBIT
39936766Ssklower 
40036370Ssklower 		if (errcode != 0) {
40136370Ssklower 			clnp_discard(m, (char)errcode);
40236370Ssklower 			IFDEBUG(D_INPUT)
40336370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
40436370Ssklower 					errcode);
40536370Ssklower 			ENDDEBUG
406*37469Ssklower 			return;
40736370Ssklower 		}
40836370Ssklower 	}
40936370Ssklower 
41036370Ssklower 	/*
41136370Ssklower 	 *	check if this packet is for us. if not, then forward
41236370Ssklower 	 */
41336370Ssklower 	if (clnp_ours(&dst) == 0) {
41436370Ssklower 		IFDEBUG(D_INPUT)
41536370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
41636370Ssklower 		ENDDEBUG
41736370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
418*37469Ssklower 		return;
41936370Ssklower 	}
42036370Ssklower 
42136370Ssklower 	/*
42236370Ssklower 	 *	ESIS Configuration Response Function
42336370Ssklower 	 *
42436370Ssklower 	 *	If the packet received was sent to the multicast address
42536370Ssklower 	 *	all end systems, then send an esh to the source
42636370Ssklower 	 */
427*37469Ssklower 	if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
42836370Ssklower 		extern short esis_holding_time;
42936370Ssklower 
43036370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
43136370Ssklower 			shp->snh_shost, 6);
43236370Ssklower 	}
43336370Ssklower 
43436370Ssklower 	/*
43536370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
43636370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
43736370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
43836370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
43936370Ssklower 	 *	we should have nothing more to do with it.
44036370Ssklower 	 */
441*37469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
442*37469Ssklower 		(clnp->cnf_type & CNF_SEG_OK) &&
44336370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
44436370Ssklower 		struct mbuf	*m0;
44536370Ssklower 
44636370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
44736370Ssklower 			m = m0;
44836370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
44936370Ssklower 		} else {
450*37469Ssklower 			return;
45136370Ssklower 		}
45236370Ssklower 	}
45336370Ssklower 
45436370Ssklower 	/*
45536370Ssklower 	 *	give the packet to the higher layer
45636370Ssklower 	 *
45736370Ssklower 	 *	Note: the total length of packet
45836370Ssklower 	 *	is the total length field of the segmentation part,
45936370Ssklower 	 *	or, if absent, the segment length field of the
46036370Ssklower 	 *	header.
46136370Ssklower 	 */
462*37469Ssklower 	switch (clnp->cnf_type & CNF_TYPE) {
46336370Ssklower 	case CLNP_ER:
46436370Ssklower 		/*
46536370Ssklower 		 *	This ER must have the er option.
46636370Ssklower 		 *	If the option is not present, discard datagram.
46736370Ssklower 		 */
46836370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
46936370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
47036370Ssklower 		} else {
47136370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
47236370Ssklower 		}
47336370Ssklower 		break;
47436370Ssklower 
47536370Ssklower 	case CLNP_DT:
47636766Ssklower  		if (need_afrin) {
47736766Ssklower  			/* NOTE: do this before TP gets the packet so tp ack can use info*/
47836766Ssklower  			IFDEBUG(D_INPUT)
47936766Ssklower  				printf("clnp_input: Calling tpclnp_ctlinput(%s)\n",
48036766Ssklower  					clnp_iso_addrp(&src));
48136766Ssklower  			ENDDEBUG
48236766Ssklower  			tpclnp_ctlinput1(PRC_QUENCH2, &src);
48336766Ssklower  		}
48436370Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst,
48536370Ssklower 			clnp->cnf_hdr_len);
48636370Ssklower 		break;
48736370Ssklower 
48836370Ssklower  	case CLNP_RAW:
48936370Ssklower 	case CLNP_ECR:
49036370Ssklower 		IFDEBUG(D_INPUT)
49136370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
492*37469Ssklower 				clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
49336370Ssklower 		ENDDEBUG
49436370Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst,
49536370Ssklower 					clnp->cnf_hdr_len);
49636370Ssklower 		break;
49736370Ssklower 
49836370Ssklower 	case CLNP_EC:
49936370Ssklower 		IFDEBUG(D_INPUT)
50036370Ssklower 			printf("clnp_input: echoing packet\n");
50136370Ssklower 		ENDDEBUG
50236370Ssklower 		/*
50336370Ssklower 		 *	Switch the source and destination address,
50436370Ssklower 		 */
50536370Ssklower 		hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
506*37469Ssklower 		CLNP_INSERT_ADDR(hoff, src);
507*37469Ssklower 		CLNP_INSERT_ADDR(hoff, dst);
508*37469Ssklower 		clnp->cnf_type &= ~CNF_TYPE;
509*37469Ssklower 		clnp->cnf_type |= CLNP_ECR;
51036370Ssklower 
51136370Ssklower 		/*
51236370Ssklower 		 *	Forward back to sender
51336370Ssklower 		 */
514*37469Ssklower  		clnp_forward(m, (int)(clnp->cnf_type & CNF_SEG_OK?seg_part.cng_tot_len : seg_len),
51536370Ssklower 			&src, oidxp, seg_off, shp);
51636370Ssklower 		break;
51736370Ssklower 
51836370Ssklower 	default:
519*37469Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n",
520*37469Ssklower 			clnp->cnf_type & CNF_TYPE);
52136370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
52236370Ssklower  		break;
52336370Ssklower 	}
52436370Ssklower }
52536370Ssklower #endif ISO
526