xref: /csrg-svn/sys/netiso/clnp_input.c (revision 52487)
149267Sbostic /*-
249267Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349267Sbostic  * All rights reserved.
449267Sbostic  *
549267Sbostic  * %sccs.include.redist.c%
649267Sbostic  *
7*52487Ssklower  *	@(#)clnp_input.c	7.14 (Berkeley) 02/14/92
849267Sbostic  */
949267Sbostic 
1036370Ssklower /***********************************************************
1136370Ssklower 		Copyright IBM Corporation 1987
1236370Ssklower 
1336370Ssklower                       All Rights Reserved
1436370Ssklower 
1536370Ssklower Permission to use, copy, modify, and distribute this software and its
1636370Ssklower documentation for any purpose and without fee is hereby granted,
1736370Ssklower provided that the above copyright notice appear in all copies and that
1836370Ssklower both that copyright notice and this permission notice appear in
1936370Ssklower supporting documentation, and that the name of IBM not be
2036370Ssklower used in advertising or publicity pertaining to distribution of the
2136370Ssklower software without specific, written prior permission.
2236370Ssklower 
2336370Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436370Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536370Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636370Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736370Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836370Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936370Ssklower SOFTWARE.
3036370Ssklower 
3136370Ssklower ******************************************************************/
3236370Ssklower 
3336370Ssklower /*
3436370Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536370Ssklower  */
3636766Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */
3736766Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */
3836370Ssklower 
3937536Smckusick #include "types.h"
4037536Smckusick #include "param.h"
4137536Smckusick #include "mbuf.h"
4237536Smckusick #include "domain.h"
4337536Smckusick #include "protosw.h"
4437536Smckusick #include "socket.h"
4537536Smckusick #include "socketvar.h"
4637536Smckusick #include "errno.h"
4737536Smckusick #include "time.h"
4836370Ssklower 
4936370Ssklower #include "../net/if.h"
5039195Ssklower #include "../net/if_types.h"
5136370Ssklower #include "../net/route.h"
5236370Ssklower 
5337469Ssklower #include "iso.h"
5437469Ssklower #include "iso_var.h"
5537469Ssklower #include "iso_snpac.h"
5637469Ssklower #include "clnp.h"
5737469Ssklower #include "clnl.h"
5838841Ssklower #include "esis.h"
5937469Ssklower #include "../netinet/in_systm.h"
6037469Ssklower #include "../netinet/ip.h"
6138841Ssklower #include "../netinet/if_ether.h"
6237469Ssklower #include "eonvar.h"
6337469Ssklower #include "clnp_stat.h"
6437469Ssklower #include "argo_debug.h"
6536370Ssklower 
6636370Ssklower #ifdef ISO
6736370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
6836370Ssklower struct clnl_protosw clnl_protox[256];
6936370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
7036370Ssklower struct mbuf	*clnp_data_ck();
7136370Ssklower 
7236370Ssklower int	clnp_input();
7336370Ssklower 
7436370Ssklower int	esis_input();
7536370Ssklower 
7636370Ssklower #ifdef	ISO_X25ESIS
7736370Ssklower int	x25esis_input();
7836370Ssklower #endif	ISO_X25ESIS
7936370Ssklower 
8036370Ssklower /*
8136370Ssklower  * FUNCTION:		clnp_init
8236370Ssklower  *
8336370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
8436370Ssklower  *
8536370Ssklower  * RETURNS:			none
8636370Ssklower  *
8736370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
8836370Ssklower  *					the isosw table.
8936370Ssklower  *
9036370Ssklower  * NOTES:
9136370Ssklower  */
9236370Ssklower clnp_init()
9336370Ssklower {
9436370Ssklower 	register struct protosw *pr;
9536370Ssklower 
9636370Ssklower 	/*
9736370Ssklower 	 *	CLNP protox initialization
9836370Ssklower 	 */
9936370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
10036370Ssklower 		printf("clnl_init: no raw CLNP\n");
10136370Ssklower 	else
10236370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
10336370Ssklower 
10436370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
10536370Ssklower 		printf("clnl_init: no tp/clnp\n");
10636370Ssklower 	else
10736370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
10836370Ssklower 
10936370Ssklower 	/*
11036370Ssklower 	 *	CLNL protox initialization
11136370Ssklower 	 */
11236370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
11336370Ssklower 
11436370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
11536370Ssklower }
11636370Ssklower 
11736370Ssklower /*
11836370Ssklower  * FUNCTION:		clnlintr
11936370Ssklower  *
12036370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
12136370Ssklower  *
12236370Ssklower  * RETURNS:			nothing.
12336370Ssklower  *
12436370Ssklower  * SIDE EFFECTS:
12536370Ssklower  *
12636370Ssklower  * NOTES:
12736370Ssklower  */
12836370Ssklower clnlintr()
12936370Ssklower {
13036370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
13136370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
13236370Ssklower 	int							s;		/* save and restore priority */
13336370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
13436370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
13536370Ssklower 
13636370Ssklower 	/*
13736370Ssklower 	 *	Get next datagram off clnl input queue
13836370Ssklower 	 */
13936370Ssklower next:
14036370Ssklower 	s = splimp();
14136765Ssklower 	/* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
14236765Ssklower 	IF_DEQUEUE(&clnlintrq, m);
14337469Ssklower 	splx(s);
14436370Ssklower 
14536765Ssklower 
14636765Ssklower 	if (m == 0)		/* nothing to do */
14736765Ssklower 		return;
14843332Ssklower 	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) {
14936765Ssklower 		m_freem(m);
15036765Ssklower 		goto next;
15143332Ssklower 	} else {
15243332Ssklower 		register struct ifaddr *ifa;
15343332Ssklower 		for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next)
15443332Ssklower 			if (ifa->ifa_addr->sa_family == AF_ISO)
15543332Ssklower 				break;
15643332Ssklower 		if (ifa == 0) {
15743332Ssklower 			m_freem(m);
15843332Ssklower 			goto next;
15943332Ssklower 		}
16036765Ssklower 	}
16137469Ssklower 	bzero((caddr_t)&sh, sizeof(sh));
16237469Ssklower 	sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
16337469Ssklower 	switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
16437469Ssklower 		extern int ether_output();
16537469Ssklower 	case IFT_EON:
16637469Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
16737469Ssklower 		bcopy(sizeof(u_long) + mtod(m, caddr_t),
16837469Ssklower 					(caddr_t)sh.snh_shost, sizeof(u_long));
16937469Ssklower 		sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
17037469Ssklower 								_offsetof(struct eon_hdr, eonh_class)];
17137469Ssklower 		m->m_data += EONIPLEN;
17237469Ssklower 		m->m_len -= EONIPLEN;
17337469Ssklower 		m->m_pkthdr.len -= EONIPLEN;
17437469Ssklower 		break;
17537469Ssklower 
17637469Ssklower 	default:
17737469Ssklower 		if (sh.snh_ifp->if_output == ether_output) {
17838841Ssklower 			bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost),
17937469Ssklower 				(caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
18038841Ssklower 			m->m_data += sizeof (struct ether_header);
18138841Ssklower 			m->m_len -= sizeof (struct ether_header);
18238841Ssklower 			m->m_pkthdr.len -= sizeof (struct ether_header);
18337469Ssklower 		}
18437469Ssklower 	}
18536370Ssklower 	IFDEBUG(D_INPUT)
18636370Ssklower 		int i;
18736370Ssklower 		printf("clnlintr: src:");
18836370Ssklower 		for (i=0; i<6; i++)
18936370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
19036370Ssklower 		printf(" dst:");
19136370Ssklower 		for (i=0; i<6; i++)
19236370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
19336370Ssklower 		printf("\n");
19436370Ssklower 	ENDDEBUG
19536370Ssklower 
19636370Ssklower 	/*
19736370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
19836370Ssklower 	 *	Drop the packet if this fails.
19936370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
20036370Ssklower 	 *	data is not there.
20136370Ssklower 	 */
20236370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
20336370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
20436370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
20536370Ssklower 		goto next;				/* m_pullup discards mbuf */
20636370Ssklower 	}
20736370Ssklower 
20836370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
20936370Ssklower 
21036370Ssklower 	/*
21136370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
21236370Ssklower 	 */
21336370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
21436370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
21536370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
21636370Ssklower 		m_freem(m);
21736370Ssklower 		goto next;
21836370Ssklower 	}
21936370Ssklower 
22036370Ssklower 	/*
22136370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
22236370Ssklower 	 *	Drop packet if this fails.
22336370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
22436370Ssklower 	 */
22536370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
22637469Ssklower 		if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
22736370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
22836370Ssklower 			goto next;	/* m_pullup discards mbuf */
22936370Ssklower 		}
23036370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
23136370Ssklower 	}
23236370Ssklower 
23336370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
23436370Ssklower 
23536370Ssklower 
23636370Ssklower 	if (clnlsw->clnl_input)
23736370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
23836370Ssklower 	else
23936370Ssklower 		m_freem(m);
24036370Ssklower 
24136370Ssklower 	goto next;
24236370Ssklower }
24336370Ssklower 
24436370Ssklower /*
24536370Ssklower  * FUNCTION:		clnp_input
24636370Ssklower  *
24736370Ssklower  * PURPOSE:			process an incoming clnp packet
24836370Ssklower  *
24936370Ssklower  * RETURNS:			nothing
25036370Ssklower  *
25136370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
25236370Ssklower  *
25336370Ssklower  * NOTES:
25436370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
25536370Ssklower  *	will it be correctly aligned?
25636370Ssklower  */
25737469Ssklower clnp_input(m, shp)
25836370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
25936370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
26036370Ssklower {
26136370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
26239930Ssklower 	struct sockaddr_iso			source; /* source address of pkt */
26339930Ssklower 	struct sockaddr_iso			target; /* destination address of pkt */
26439930Ssklower #define src	source.siso_addr
26539930Ssklower #define dst	target.siso_addr
26636370Ssklower 	caddr_t						hoff;	/* current offset in packet */
26736370Ssklower 	caddr_t						hend;	/* address of end of header info */
26836370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
26936370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
27036370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
27136370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
27236370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
27339930Ssklower 	extern struct sockaddr_iso	blank_siso;		/* used for initializing */
27436766Ssklower 	int							need_afrin = 0;
27536766Ssklower 										/* true if congestion experienced */
27636766Ssklower 										/* which means you need afrin nose */
27736766Ssklower 										/* spray. How clever! */
27836370Ssklower 
27936370Ssklower 	IFDEBUG(D_INPUT)
28036370Ssklower 		printf(
28136766Ssklower 		   "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
28236766Ssklower 			m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
28336370Ssklower 	ENDDEBUG
28436766Ssklower 	need_afrin = 0;
28536370Ssklower 
28636370Ssklower 	/*
28736370Ssklower 	 *	If no iso addresses have been set, there is nothing
28836370Ssklower 	 *	to do with the packet.
28936370Ssklower 	 */
29036370Ssklower 	if (iso_ifaddr == NULL) {
29136370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
29236370Ssklower 		return;
29336370Ssklower 	}
29436370Ssklower 
29536370Ssklower 	INCSTAT(cns_total);
29636370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
29736370Ssklower 
29836766Ssklower 	IFDEBUG(D_DUMPIN)
29936766Ssklower 		struct mbuf *mhead;
30036766Ssklower 		int			total_len = 0;
30136766Ssklower 		printf("clnp_input: clnp header:\n");
30236766Ssklower 		dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
30336766Ssklower 		printf("clnp_input: mbuf chain:\n");
30436766Ssklower 		for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
30536766Ssklower 			printf("m x%x, len %d\n", mhead, mhead->m_len);
30636766Ssklower 			total_len += mhead->m_len;
30736766Ssklower 		}
30836766Ssklower 		printf("clnp_input: total length of mbuf chain %d:\n", total_len);
30936766Ssklower 	ENDDEBUG
31036766Ssklower 
31136370Ssklower 	/*
31236370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
31336370Ssklower 	 *	checksum does not match
31436370Ssklower 	 */
31537469Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
31636370Ssklower 		INCSTAT(cns_badcsum);
31736370Ssklower 		clnp_discard(m, GEN_BADCSUM);
31837469Ssklower 		return;
31936370Ssklower 	}
32036370Ssklower 
32136370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
32236370Ssklower 		INCSTAT(cns_badvers);
32336370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
32437469Ssklower 		return;
32536370Ssklower 	}
32636370Ssklower 
32736370Ssklower 
32836370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
32936370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
33036370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
33137469Ssklower 		return;
33236370Ssklower 
33336370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
33436370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
33536370Ssklower 
33636370Ssklower 	/*
33736370Ssklower 	 *	extract the source and destination address
33836370Ssklower 	 *	drop packet on failure
33936370Ssklower 	 */
34039930Ssklower 	source = target = blank_siso;
34136370Ssklower 
34236370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
34336370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
34436370Ssklower 	if (hoff == (caddr_t)0) {
34536370Ssklower 		INCSTAT(cns_badaddr);
34636370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
34737469Ssklower 		return;
34836370Ssklower 	}
34936370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
35036370Ssklower 	if (hoff == (caddr_t)0) {
35136370Ssklower 		INCSTAT(cns_badaddr);
35236370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
35337469Ssklower 		return;
35436370Ssklower 	}
35536370Ssklower 
35636370Ssklower 	IFDEBUG(D_INPUT)
35736370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
35836370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
35936370Ssklower 	ENDDEBUG
36036370Ssklower 
36136370Ssklower 	/*
36236370Ssklower 	 *	extract the segmentation information, if it is present.
36336370Ssklower 	 *	drop packet on failure
36436370Ssklower 	 */
36537469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
36637469Ssklower 		(clnp->cnf_type & CNF_SEG_OK)) {
36736370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
36836370Ssklower 			INCSTAT(cns_noseg);
36936370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
37037469Ssklower 			return;
37136370Ssklower 		} else {
37236370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
37336370Ssklower 			/* make sure segmentation fields are in host order */
37436370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
37536370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
37636370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
37736370Ssklower 			seg_off = hoff - (caddr_t)clnp;
37836370Ssklower 			hoff += sizeof(struct clnp_segment);
37936370Ssklower 		}
38036370Ssklower 	}
38136370Ssklower 
38236370Ssklower 	/*
38336370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
38436370Ssklower 	 *	false (indicating an error was found in the options) or
38536370Ssklower 	 *	an unsupported option was found
38636370Ssklower 	 *	then drop packet and emit an ER.
38736370Ssklower 	 */
38836370Ssklower 	if (hoff < hend) {
38936370Ssklower 		int		errcode;
39036370Ssklower 
39136370Ssklower 		oidxp = &oidx;
39236370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
39336370Ssklower 
39436370Ssklower 		/* we do not support security */
39536370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
39636370Ssklower 			errcode = DISC_UNSUPPSECURE;
39736370Ssklower 
39836370Ssklower 		/* the er option is valid with ER pdus only */
39936370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
40037469Ssklower 			((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
40136370Ssklower 			errcode = DISC_UNSUPPOPT;
40236370Ssklower 
40336766Ssklower #ifdef	DECBIT
40436766Ssklower 		/* check if the congestion experienced bit is set */
40536766Ssklower 		if (oidxp->cni_qos_formatp) {
40636766Ssklower 			caddr_t	qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
40736766Ssklower 			u_char	qos = *qosp;
40836766Ssklower 
40936766Ssklower 			need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
41036766Ssklower 				(CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
41136766Ssklower 			if (need_afrin)
41236766Ssklower 				INCSTAT(cns_congest_rcvd);
41336766Ssklower 		}
41436766Ssklower #endif	DECBIT
41536766Ssklower 
41636370Ssklower 		if (errcode != 0) {
41736370Ssklower 			clnp_discard(m, (char)errcode);
41836370Ssklower 			IFDEBUG(D_INPUT)
41936370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
42036370Ssklower 					errcode);
42136370Ssklower 			ENDDEBUG
42237469Ssklower 			return;
42336370Ssklower 		}
42436370Ssklower 	}
42536370Ssklower 
42636370Ssklower 	/*
42736370Ssklower 	 *	check if this packet is for us. if not, then forward
42836370Ssklower 	 */
42936370Ssklower 	if (clnp_ours(&dst) == 0) {
43036370Ssklower 		IFDEBUG(D_INPUT)
43136370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
43236370Ssklower 		ENDDEBUG
43336370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
43437469Ssklower 		return;
43536370Ssklower 	}
43636370Ssklower 
43736370Ssklower 	/*
43836370Ssklower 	 *	ESIS Configuration Response Function
43936370Ssklower 	 *
44036370Ssklower 	 *	If the packet received was sent to the multicast address
44136370Ssklower 	 *	all end systems, then send an esh to the source
44236370Ssklower 	 */
44337469Ssklower 	if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
44436370Ssklower 		extern short esis_holding_time;
44536370Ssklower 
44636370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
44743332Ssklower 			shp->snh_shost, 6, &dst);
44836370Ssklower 	}
44936370Ssklower 
45036370Ssklower 	/*
45136370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
45236370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
45336370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
45436370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
45536370Ssklower 	 *	we should have nothing more to do with it.
45636370Ssklower 	 */
45737469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
45837469Ssklower 		(clnp->cnf_type & CNF_SEG_OK) &&
45936370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
46036370Ssklower 		struct mbuf	*m0;
46136370Ssklower 
46236370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
46336370Ssklower 			m = m0;
46436370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
46539195Ssklower 			INCSTAT(cns_reassembled);
46636370Ssklower 		} else {
46737469Ssklower 			return;
46836370Ssklower 		}
46936370Ssklower 	}
47036370Ssklower 
47136370Ssklower 	/*
47236370Ssklower 	 *	give the packet to the higher layer
47336370Ssklower 	 *
47436370Ssklower 	 *	Note: the total length of packet
47536370Ssklower 	 *	is the total length field of the segmentation part,
47636370Ssklower 	 *	or, if absent, the segment length field of the
47736370Ssklower 	 *	header.
47836370Ssklower 	 */
47939195Ssklower 	INCSTAT(cns_delivered);
48037469Ssklower 	switch (clnp->cnf_type & CNF_TYPE) {
48136370Ssklower 	case CLNP_ER:
48236370Ssklower 		/*
48336370Ssklower 		 *	This ER must have the er option.
48436370Ssklower 		 *	If the option is not present, discard datagram.
48536370Ssklower 		 */
48636370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
48736370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
48836370Ssklower 		} else {
48936370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
49036370Ssklower 		}
49136370Ssklower 		break;
49236370Ssklower 
49336370Ssklower 	case CLNP_DT:
49439930Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target,
49539931Ssklower 			clnp->cnf_hdr_len, need_afrin);
49636370Ssklower 		break;
49736370Ssklower 
49836370Ssklower  	case CLNP_RAW:
49936370Ssklower 	case CLNP_ECR:
50036370Ssklower 		IFDEBUG(D_INPUT)
50136370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
50237469Ssklower 				clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
50336370Ssklower 		ENDDEBUG
50441338Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target,
50536370Ssklower 					clnp->cnf_hdr_len);
50636370Ssklower 		break;
50736370Ssklower 
50836370Ssklower 	case CLNP_EC:
50936370Ssklower 		IFDEBUG(D_INPUT)
51036370Ssklower 			printf("clnp_input: echoing packet\n");
51136370Ssklower 		ENDDEBUG
512*52487Ssklower 		(void)clnp_echoreply(m,
513*52487Ssklower 			(clnp->cnf_type & CNF_SEG_OK ? (int)seg_part.cng_tot_len : seg_len),
514*52487Ssklower 			&source, &target, oidxp);
51536370Ssklower 		break;
51636370Ssklower 
51736370Ssklower 	default:
51837469Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n",
51937469Ssklower 			clnp->cnf_type & CNF_TYPE);
52039195Ssklower 		clnp_stat.cns_delivered--;
52139195Ssklower 		clnp_stat.cns_noproto++;
52236370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
52336370Ssklower  		break;
52436370Ssklower 	}
52536370Ssklower }
52636370Ssklower #endif ISO
527