xref: /csrg-svn/sys/netiso/clnp_input.c (revision 43332)
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*43332Ssklower /*	@(#)clnp_input.c	7.12 (Berkeley) 06/20/90 */
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 
3537536Smckusick #include "types.h"
3637536Smckusick #include "param.h"
3737536Smckusick #include "mbuf.h"
3837536Smckusick #include "domain.h"
3937536Smckusick #include "protosw.h"
4037536Smckusick #include "socket.h"
4137536Smckusick #include "socketvar.h"
4237536Smckusick #include "errno.h"
4337536Smckusick #include "time.h"
4436370Ssklower 
4536370Ssklower #include "../net/if.h"
4639195Ssklower #include "../net/if_types.h"
4736370Ssklower #include "../net/route.h"
4836370Ssklower 
4937469Ssklower #include "iso.h"
5037469Ssklower #include "iso_var.h"
5137469Ssklower #include "iso_snpac.h"
5237469Ssklower #include "clnp.h"
5337469Ssklower #include "clnl.h"
5438841Ssklower #include "esis.h"
5537469Ssklower #include "../netinet/in_systm.h"
5637469Ssklower #include "../netinet/ip.h"
5738841Ssklower #include "../netinet/if_ether.h"
5837469Ssklower #include "eonvar.h"
5937469Ssklower #include "clnp_stat.h"
6037469Ssklower #include "argo_debug.h"
6136370Ssklower 
6236370Ssklower #ifdef ISO
6336370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
6436370Ssklower struct clnl_protosw clnl_protox[256];
6536370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
6636370Ssklower struct mbuf	*clnp_data_ck();
6736370Ssklower 
6836370Ssklower int	clnp_input();
6936370Ssklower 
7036370Ssklower int	esis_input();
7136370Ssklower 
7236370Ssklower #ifdef	ISO_X25ESIS
7336370Ssklower int	x25esis_input();
7436370Ssklower #endif	ISO_X25ESIS
7536370Ssklower 
7636370Ssklower /*
7736370Ssklower  * FUNCTION:		clnp_init
7836370Ssklower  *
7936370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
8036370Ssklower  *
8136370Ssklower  * RETURNS:			none
8236370Ssklower  *
8336370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
8436370Ssklower  *					the isosw table.
8536370Ssklower  *
8636370Ssklower  * NOTES:
8736370Ssklower  */
8836370Ssklower clnp_init()
8936370Ssklower {
9036370Ssklower 	register struct protosw *pr;
9136370Ssklower 
9236370Ssklower 	/*
9336370Ssklower 	 *	CLNP protox initialization
9436370Ssklower 	 */
9536370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
9636370Ssklower 		printf("clnl_init: no raw CLNP\n");
9736370Ssklower 	else
9836370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
9936370Ssklower 
10036370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
10136370Ssklower 		printf("clnl_init: no tp/clnp\n");
10236370Ssklower 	else
10336370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
10436370Ssklower 
10536370Ssklower 	/*
10636370Ssklower 	 *	CLNL protox initialization
10736370Ssklower 	 */
10836370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
10936370Ssklower 
11036370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
11136370Ssklower }
11236370Ssklower 
11336370Ssklower /*
11436370Ssklower  * FUNCTION:		clnlintr
11536370Ssklower  *
11636370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
11736370Ssklower  *
11836370Ssklower  * RETURNS:			nothing.
11936370Ssklower  *
12036370Ssklower  * SIDE EFFECTS:
12136370Ssklower  *
12236370Ssklower  * NOTES:
12336370Ssklower  */
12436370Ssklower clnlintr()
12536370Ssklower {
12636370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
12736370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
12836370Ssklower 	int							s;		/* save and restore priority */
12936370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
13036370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
13136370Ssklower 
13236370Ssklower 	/*
13336370Ssklower 	 *	Get next datagram off clnl input queue
13436370Ssklower 	 */
13536370Ssklower next:
13636370Ssklower 	s = splimp();
13736765Ssklower 	/* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
13836765Ssklower 	IF_DEQUEUE(&clnlintrq, m);
13937469Ssklower 	splx(s);
14036370Ssklower 
14136765Ssklower 
14236765Ssklower 	if (m == 0)		/* nothing to do */
14336765Ssklower 		return;
144*43332Ssklower 	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) {
14536765Ssklower 		m_freem(m);
14636765Ssklower 		goto next;
147*43332Ssklower 	} else {
148*43332Ssklower 		register struct ifaddr *ifa;
149*43332Ssklower 		for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next)
150*43332Ssklower 			if (ifa->ifa_addr->sa_family == AF_ISO)
151*43332Ssklower 				break;
152*43332Ssklower 		if (ifa == 0) {
153*43332Ssklower 			m_freem(m);
154*43332Ssklower 			goto next;
155*43332Ssklower 		}
15636765Ssklower 	}
15737469Ssklower 	bzero((caddr_t)&sh, sizeof(sh));
15837469Ssklower 	sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
15937469Ssklower 	switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
16037469Ssklower 		extern int ether_output();
16137469Ssklower 	case IFT_EON:
16237469Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
16337469Ssklower 		bcopy(sizeof(u_long) + mtod(m, caddr_t),
16437469Ssklower 					(caddr_t)sh.snh_shost, sizeof(u_long));
16537469Ssklower 		sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
16637469Ssklower 								_offsetof(struct eon_hdr, eonh_class)];
16737469Ssklower 		m->m_data += EONIPLEN;
16837469Ssklower 		m->m_len -= EONIPLEN;
16937469Ssklower 		m->m_pkthdr.len -= EONIPLEN;
17037469Ssklower 		break;
17137469Ssklower 
17237469Ssklower 	default:
17337469Ssklower 		if (sh.snh_ifp->if_output == ether_output) {
17438841Ssklower 			bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost),
17537469Ssklower 				(caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
17638841Ssklower 			m->m_data += sizeof (struct ether_header);
17738841Ssklower 			m->m_len -= sizeof (struct ether_header);
17838841Ssklower 			m->m_pkthdr.len -= sizeof (struct ether_header);
17937469Ssklower 		}
18037469Ssklower 	}
18136370Ssklower 	IFDEBUG(D_INPUT)
18236370Ssklower 		int i;
18336370Ssklower 		printf("clnlintr: src:");
18436370Ssklower 		for (i=0; i<6; i++)
18536370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
18636370Ssklower 		printf(" dst:");
18736370Ssklower 		for (i=0; i<6; i++)
18836370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
18936370Ssklower 		printf("\n");
19036370Ssklower 	ENDDEBUG
19136370Ssklower 
19236370Ssklower 	/*
19336370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
19436370Ssklower 	 *	Drop the packet if this fails.
19536370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
19636370Ssklower 	 *	data is not there.
19736370Ssklower 	 */
19836370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
19936370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
20036370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
20136370Ssklower 		goto next;				/* m_pullup discards mbuf */
20236370Ssklower 	}
20336370Ssklower 
20436370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
20536370Ssklower 
20636370Ssklower 	/*
20736370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
20836370Ssklower 	 */
20936370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
21036370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
21136370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
21236370Ssklower 		m_freem(m);
21336370Ssklower 		goto next;
21436370Ssklower 	}
21536370Ssklower 
21636370Ssklower 	/*
21736370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
21836370Ssklower 	 *	Drop packet if this fails.
21936370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
22036370Ssklower 	 */
22136370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
22237469Ssklower 		if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
22336370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
22436370Ssklower 			goto next;	/* m_pullup discards mbuf */
22536370Ssklower 		}
22636370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
22736370Ssklower 	}
22836370Ssklower 
22936370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
23036370Ssklower 
23136370Ssklower 
23236370Ssklower 	if (clnlsw->clnl_input)
23336370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
23436370Ssklower 	else
23536370Ssklower 		m_freem(m);
23636370Ssklower 
23736370Ssklower 	goto next;
23836370Ssklower }
23936370Ssklower 
24036370Ssklower /*
24136370Ssklower  * FUNCTION:		clnp_input
24236370Ssklower  *
24336370Ssklower  * PURPOSE:			process an incoming clnp packet
24436370Ssklower  *
24536370Ssklower  * RETURNS:			nothing
24636370Ssklower  *
24736370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
24836370Ssklower  *
24936370Ssklower  * NOTES:
25036370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
25136370Ssklower  *	will it be correctly aligned?
25236370Ssklower  */
25337469Ssklower clnp_input(m, shp)
25436370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
25536370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
25636370Ssklower {
25736370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
25839930Ssklower 	struct sockaddr_iso			source; /* source address of pkt */
25939930Ssklower 	struct sockaddr_iso			target; /* destination address of pkt */
26039930Ssklower #define src	source.siso_addr
26139930Ssklower #define dst	target.siso_addr
26236370Ssklower 	caddr_t						hoff;	/* current offset in packet */
26336370Ssklower 	caddr_t						hend;	/* address of end of header info */
26436370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
26536370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
26636370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
26736370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
26836370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
26939930Ssklower 	extern struct sockaddr_iso	blank_siso;		/* used for initializing */
27036766Ssklower 	int							need_afrin = 0;
27136766Ssklower 										/* true if congestion experienced */
27236766Ssklower 										/* which means you need afrin nose */
27336766Ssklower 										/* spray. How clever! */
27436370Ssklower 
27536370Ssklower 	IFDEBUG(D_INPUT)
27636370Ssklower 		printf(
27736766Ssklower 		   "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
27836766Ssklower 			m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
27936370Ssklower 	ENDDEBUG
28036766Ssklower 	need_afrin = 0;
28136370Ssklower 
28236370Ssklower 	/*
28336370Ssklower 	 *	If no iso addresses have been set, there is nothing
28436370Ssklower 	 *	to do with the packet.
28536370Ssklower 	 */
28636370Ssklower 	if (iso_ifaddr == NULL) {
28736370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
28836370Ssklower 		return;
28936370Ssklower 	}
29036370Ssklower 
29136370Ssklower 	INCSTAT(cns_total);
29236370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
29336370Ssklower 
29436766Ssklower 	IFDEBUG(D_DUMPIN)
29536766Ssklower 		struct mbuf *mhead;
29636766Ssklower 		int			total_len = 0;
29736766Ssklower 		printf("clnp_input: clnp header:\n");
29836766Ssklower 		dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
29936766Ssklower 		printf("clnp_input: mbuf chain:\n");
30036766Ssklower 		for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
30136766Ssklower 			printf("m x%x, len %d\n", mhead, mhead->m_len);
30236766Ssklower 			total_len += mhead->m_len;
30336766Ssklower 		}
30436766Ssklower 		printf("clnp_input: total length of mbuf chain %d:\n", total_len);
30536766Ssklower 	ENDDEBUG
30636766Ssklower 
30736370Ssklower 	/*
30836370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
30936370Ssklower 	 *	checksum does not match
31036370Ssklower 	 */
31137469Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
31236370Ssklower 		INCSTAT(cns_badcsum);
31336370Ssklower 		clnp_discard(m, GEN_BADCSUM);
31437469Ssklower 		return;
31536370Ssklower 	}
31636370Ssklower 
31736370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
31836370Ssklower 		INCSTAT(cns_badvers);
31936370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
32037469Ssklower 		return;
32136370Ssklower 	}
32236370Ssklower 
32336370Ssklower 
32436370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
32536370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
32636370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
32737469Ssklower 		return;
32836370Ssklower 
32936370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
33036370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
33136370Ssklower 
33236370Ssklower 	/*
33336370Ssklower 	 *	extract the source and destination address
33436370Ssklower 	 *	drop packet on failure
33536370Ssklower 	 */
33639930Ssklower 	source = target = blank_siso;
33736370Ssklower 
33836370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
33936370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
34036370Ssklower 	if (hoff == (caddr_t)0) {
34136370Ssklower 		INCSTAT(cns_badaddr);
34236370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
34337469Ssklower 		return;
34436370Ssklower 	}
34536370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
34636370Ssklower 	if (hoff == (caddr_t)0) {
34736370Ssklower 		INCSTAT(cns_badaddr);
34836370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
34937469Ssklower 		return;
35036370Ssklower 	}
35136370Ssklower 
35236370Ssklower 	IFDEBUG(D_INPUT)
35336370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
35436370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
35536370Ssklower 	ENDDEBUG
35636370Ssklower 
35736370Ssklower 	/*
35836370Ssklower 	 *	extract the segmentation information, if it is present.
35936370Ssklower 	 *	drop packet on failure
36036370Ssklower 	 */
36137469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
36237469Ssklower 		(clnp->cnf_type & CNF_SEG_OK)) {
36336370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
36436370Ssklower 			INCSTAT(cns_noseg);
36536370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
36637469Ssklower 			return;
36736370Ssklower 		} else {
36836370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
36936370Ssklower 			/* make sure segmentation fields are in host order */
37036370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
37136370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
37236370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
37336370Ssklower 			seg_off = hoff - (caddr_t)clnp;
37436370Ssklower 			hoff += sizeof(struct clnp_segment);
37536370Ssklower 		}
37636370Ssklower 	}
37736370Ssklower 
37836370Ssklower 	/*
37936370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
38036370Ssklower 	 *	false (indicating an error was found in the options) or
38136370Ssklower 	 *	an unsupported option was found
38236370Ssklower 	 *	then drop packet and emit an ER.
38336370Ssklower 	 */
38436370Ssklower 	if (hoff < hend) {
38536370Ssklower 		int		errcode;
38636370Ssklower 
38736370Ssklower 		oidxp = &oidx;
38836370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
38936370Ssklower 
39036370Ssklower 		/* we do not support security */
39136370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
39236370Ssklower 			errcode = DISC_UNSUPPSECURE;
39336370Ssklower 
39436370Ssklower 		/* the er option is valid with ER pdus only */
39536370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
39637469Ssklower 			((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
39736370Ssklower 			errcode = DISC_UNSUPPOPT;
39836370Ssklower 
39936766Ssklower #ifdef	DECBIT
40036766Ssklower 		/* check if the congestion experienced bit is set */
40136766Ssklower 		if (oidxp->cni_qos_formatp) {
40236766Ssklower 			caddr_t	qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
40336766Ssklower 			u_char	qos = *qosp;
40436766Ssklower 
40536766Ssklower 			need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
40636766Ssklower 				(CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
40736766Ssklower 			if (need_afrin)
40836766Ssklower 				INCSTAT(cns_congest_rcvd);
40936766Ssklower 		}
41036766Ssklower #endif	DECBIT
41136766Ssklower 
41236370Ssklower 		if (errcode != 0) {
41336370Ssklower 			clnp_discard(m, (char)errcode);
41436370Ssklower 			IFDEBUG(D_INPUT)
41536370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
41636370Ssklower 					errcode);
41736370Ssklower 			ENDDEBUG
41837469Ssklower 			return;
41936370Ssklower 		}
42036370Ssklower 	}
42136370Ssklower 
42236370Ssklower 	/*
42336370Ssklower 	 *	check if this packet is for us. if not, then forward
42436370Ssklower 	 */
42536370Ssklower 	if (clnp_ours(&dst) == 0) {
42636370Ssklower 		IFDEBUG(D_INPUT)
42736370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
42836370Ssklower 		ENDDEBUG
42936370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
43037469Ssklower 		return;
43136370Ssklower 	}
43236370Ssklower 
43336370Ssklower 	/*
43436370Ssklower 	 *	ESIS Configuration Response Function
43536370Ssklower 	 *
43636370Ssklower 	 *	If the packet received was sent to the multicast address
43736370Ssklower 	 *	all end systems, then send an esh to the source
43836370Ssklower 	 */
43937469Ssklower 	if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
44036370Ssklower 		extern short esis_holding_time;
44136370Ssklower 
44236370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
443*43332Ssklower 			shp->snh_shost, 6, &dst);
44436370Ssklower 	}
44536370Ssklower 
44636370Ssklower 	/*
44736370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
44836370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
44936370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
45036370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
45136370Ssklower 	 *	we should have nothing more to do with it.
45236370Ssklower 	 */
45337469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
45437469Ssklower 		(clnp->cnf_type & CNF_SEG_OK) &&
45536370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
45636370Ssklower 		struct mbuf	*m0;
45736370Ssklower 
45836370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
45936370Ssklower 			m = m0;
46036370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
46139195Ssklower 			INCSTAT(cns_reassembled);
46236370Ssklower 		} else {
46337469Ssklower 			return;
46436370Ssklower 		}
46536370Ssklower 	}
46636370Ssklower 
46736370Ssklower 	/*
46836370Ssklower 	 *	give the packet to the higher layer
46936370Ssklower 	 *
47036370Ssklower 	 *	Note: the total length of packet
47136370Ssklower 	 *	is the total length field of the segmentation part,
47236370Ssklower 	 *	or, if absent, the segment length field of the
47336370Ssklower 	 *	header.
47436370Ssklower 	 */
47539195Ssklower 	INCSTAT(cns_delivered);
47637469Ssklower 	switch (clnp->cnf_type & CNF_TYPE) {
47736370Ssklower 	case CLNP_ER:
47836370Ssklower 		/*
47936370Ssklower 		 *	This ER must have the er option.
48036370Ssklower 		 *	If the option is not present, discard datagram.
48136370Ssklower 		 */
48236370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
48336370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
48436370Ssklower 		} else {
48536370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
48636370Ssklower 		}
48736370Ssklower 		break;
48836370Ssklower 
48936370Ssklower 	case CLNP_DT:
49039930Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target,
49139931Ssklower 			clnp->cnf_hdr_len, need_afrin);
49236370Ssklower 		break;
49336370Ssklower 
49436370Ssklower  	case CLNP_RAW:
49536370Ssklower 	case CLNP_ECR:
49636370Ssklower 		IFDEBUG(D_INPUT)
49736370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
49837469Ssklower 				clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
49936370Ssklower 		ENDDEBUG
50041338Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target,
50136370Ssklower 					clnp->cnf_hdr_len);
50236370Ssklower 		break;
50336370Ssklower 
50436370Ssklower 	case CLNP_EC:
50536370Ssklower 		IFDEBUG(D_INPUT)
50636370Ssklower 			printf("clnp_input: echoing packet\n");
50736370Ssklower 		ENDDEBUG
50836370Ssklower 		/*
50936370Ssklower 		 *	Switch the source and destination address,
51036370Ssklower 		 */
51136370Ssklower 		hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
51237469Ssklower 		CLNP_INSERT_ADDR(hoff, src);
51337469Ssklower 		CLNP_INSERT_ADDR(hoff, dst);
51437469Ssklower 		clnp->cnf_type &= ~CNF_TYPE;
51537469Ssklower 		clnp->cnf_type |= CLNP_ECR;
51636370Ssklower 
51736370Ssklower 		/*
51836370Ssklower 		 *	Forward back to sender
51936370Ssklower 		 */
52039232Ssklower 		clnp_forward(m, (int)
52139232Ssklower 			(clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len),
52239232Ssklower 			&src, oidxp, seg_off, 0);
52336370Ssklower 		break;
52436370Ssklower 
52536370Ssklower 	default:
52637469Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n",
52737469Ssklower 			clnp->cnf_type & CNF_TYPE);
52839195Ssklower 		clnp_stat.cns_delivered--;
52939195Ssklower 		clnp_stat.cns_noproto++;
53036370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
53136370Ssklower  		break;
53236370Ssklower 	}
53336370Ssklower }
53436370Ssklower #endif ISO
535