xref: /csrg-svn/sys/netiso/clnp_input.c (revision 63222)
149267Sbostic /*-
2*63222Sbostic  * Copyright (c) 1991, 1993
3*63222Sbostic  *	The Regents of the University of California.  All rights reserved.
449267Sbostic  *
549267Sbostic  * %sccs.include.redist.c%
649267Sbostic  *
7*63222Sbostic  *	@(#)clnp_input.c	8.1 (Berkeley) 06/10/93
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 
3956533Sbostic #include <sys/param.h>
4056533Sbostic #include <sys/mbuf.h>
4156533Sbostic #include <sys/domain.h>
4256533Sbostic #include <sys/protosw.h>
4356533Sbostic #include <sys/socket.h>
4456533Sbostic #include <sys/socketvar.h>
4556533Sbostic #include <sys/errno.h>
4656533Sbostic #include <sys/time.h>
4736370Ssklower 
4856533Sbostic #include <net/if.h>
4956533Sbostic #include <net/if_types.h>
5056533Sbostic #include <net/route.h>
5136370Ssklower 
5256533Sbostic #include <netiso/iso.h>
5356533Sbostic #include <netiso/iso_var.h>
5456533Sbostic #include <netiso/iso_snpac.h>
5556533Sbostic #include <netiso/clnp.h>
5656533Sbostic #include <netiso/clnl.h>
5756533Sbostic #include <netiso/esis.h>
5856533Sbostic #include <netinet/in_systm.h>
5956533Sbostic #include <netinet/ip.h>
6056533Sbostic #include <netinet/if_ether.h>
6156533Sbostic #include <netiso/eonvar.h>
6256533Sbostic #include <netiso/clnp_stat.h>
6356533Sbostic #include <netiso/argo_debug.h>
6436370Ssklower 
6536370Ssklower #ifdef ISO
6636370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
6736370Ssklower struct clnl_protosw clnl_protox[256];
6836370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
6936370Ssklower struct mbuf	*clnp_data_ck();
7036370Ssklower 
7136370Ssklower int	clnp_input();
7236370Ssklower 
7336370Ssklower int	esis_input();
7436370Ssklower 
7536370Ssklower #ifdef	ISO_X25ESIS
7636370Ssklower int	x25esis_input();
7760359Sbostic #endif	/* ISO_X25ESIS */
7836370Ssklower 
7936370Ssklower /*
8036370Ssklower  * FUNCTION:		clnp_init
8136370Ssklower  *
8236370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
8336370Ssklower  *
8436370Ssklower  * RETURNS:			none
8536370Ssklower  *
8636370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
8736370Ssklower  *					the isosw table.
8836370Ssklower  *
8936370Ssklower  * NOTES:
9036370Ssklower  */
clnp_init()9136370Ssklower clnp_init()
9236370Ssklower {
9336370Ssklower 	register struct protosw *pr;
9436370Ssklower 
9536370Ssklower 	/*
9636370Ssklower 	 *	CLNP protox initialization
9736370Ssklower 	 */
9836370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
9936370Ssklower 		printf("clnl_init: no raw CLNP\n");
10036370Ssklower 	else
10136370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
10236370Ssklower 
10336370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
10436370Ssklower 		printf("clnl_init: no tp/clnp\n");
10536370Ssklower 	else
10636370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
10736370Ssklower 
10836370Ssklower 	/*
10936370Ssklower 	 *	CLNL protox initialization
11036370Ssklower 	 */
11136370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
11236370Ssklower 
11336370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
11436370Ssklower }
11536370Ssklower 
11636370Ssklower /*
11736370Ssklower  * FUNCTION:		clnlintr
11836370Ssklower  *
11936370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
12036370Ssklower  *
12136370Ssklower  * RETURNS:			nothing.
12236370Ssklower  *
12336370Ssklower  * SIDE EFFECTS:
12436370Ssklower  *
12536370Ssklower  * NOTES:
12636370Ssklower  */
clnlintr()12736370Ssklower clnlintr()
12836370Ssklower {
12936370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
13036370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
13136370Ssklower 	int							s;		/* save and restore priority */
13236370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
13336370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
13436370Ssklower 
13536370Ssklower 	/*
13636370Ssklower 	 *	Get next datagram off clnl input queue
13736370Ssklower 	 */
13836370Ssklower next:
13936370Ssklower 	s = splimp();
14036765Ssklower 	/* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
14136765Ssklower 	IF_DEQUEUE(&clnlintrq, m);
14237469Ssklower 	splx(s);
14336370Ssklower 
14436765Ssklower 
14536765Ssklower 	if (m == 0)		/* nothing to do */
14636765Ssklower 		return;
14743332Ssklower 	if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) {
14836765Ssklower 		m_freem(m);
14936765Ssklower 		goto next;
15043332Ssklower 	} else {
15143332Ssklower 		register struct ifaddr *ifa;
15243332Ssklower 		for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next)
15343332Ssklower 			if (ifa->ifa_addr->sa_family == AF_ISO)
15443332Ssklower 				break;
15543332Ssklower 		if (ifa == 0) {
15643332Ssklower 			m_freem(m);
15743332Ssklower 			goto next;
15843332Ssklower 		}
15936765Ssklower 	}
16037469Ssklower 	bzero((caddr_t)&sh, sizeof(sh));
16137469Ssklower 	sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST);
16237469Ssklower 	switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) {
16337469Ssklower 		extern int ether_output();
16437469Ssklower 	case IFT_EON:
16537469Ssklower 		bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long));
16637469Ssklower 		bcopy(sizeof(u_long) + mtod(m, caddr_t),
16737469Ssklower 					(caddr_t)sh.snh_shost, sizeof(u_long));
16837469Ssklower 		sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) +
16937469Ssklower 								_offsetof(struct eon_hdr, eonh_class)];
17037469Ssklower 		m->m_data += EONIPLEN;
17137469Ssklower 		m->m_len -= EONIPLEN;
17237469Ssklower 		m->m_pkthdr.len -= EONIPLEN;
17337469Ssklower 		break;
17437469Ssklower 
17537469Ssklower 	default:
17637469Ssklower 		if (sh.snh_ifp->if_output == ether_output) {
17738841Ssklower 			bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost),
17837469Ssklower 				(caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
17938841Ssklower 			m->m_data += sizeof (struct ether_header);
18038841Ssklower 			m->m_len -= sizeof (struct ether_header);
18138841Ssklower 			m->m_pkthdr.len -= sizeof (struct ether_header);
18237469Ssklower 		}
18337469Ssklower 	}
18436370Ssklower 	IFDEBUG(D_INPUT)
18536370Ssklower 		int i;
18636370Ssklower 		printf("clnlintr: src:");
18736370Ssklower 		for (i=0; i<6; i++)
18836370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
18936370Ssklower 		printf(" dst:");
19036370Ssklower 		for (i=0; i<6; i++)
19136370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
19236370Ssklower 		printf("\n");
19336370Ssklower 	ENDDEBUG
19436370Ssklower 
19536370Ssklower 	/*
19636370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
19736370Ssklower 	 *	Drop the packet if this fails.
19836370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
19936370Ssklower 	 *	data is not there.
20036370Ssklower 	 */
20136370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
20236370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
20336370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
20436370Ssklower 		goto next;				/* m_pullup discards mbuf */
20536370Ssklower 	}
20636370Ssklower 
20736370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
20836370Ssklower 
20936370Ssklower 	/*
21036370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
21136370Ssklower 	 */
21236370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
21336370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
21436370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
21536370Ssklower 		m_freem(m);
21636370Ssklower 		goto next;
21736370Ssklower 	}
21836370Ssklower 
21936370Ssklower 	/*
22036370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
22136370Ssklower 	 *	Drop packet if this fails.
22236370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
22336370Ssklower 	 */
22436370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
22537469Ssklower 		if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) {
22636370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
22736370Ssklower 			goto next;	/* m_pullup discards mbuf */
22836370Ssklower 		}
22936370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
23036370Ssklower 	}
23136370Ssklower 
23236370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
23336370Ssklower 
23436370Ssklower 
23536370Ssklower 	if (clnlsw->clnl_input)
23636370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
23736370Ssklower 	else
23836370Ssklower 		m_freem(m);
23936370Ssklower 
24036370Ssklower 	goto next;
24136370Ssklower }
24236370Ssklower 
24336370Ssklower /*
24436370Ssklower  * FUNCTION:		clnp_input
24536370Ssklower  *
24636370Ssklower  * PURPOSE:			process an incoming clnp packet
24736370Ssklower  *
24836370Ssklower  * RETURNS:			nothing
24936370Ssklower  *
25036370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
25136370Ssklower  *
25236370Ssklower  * NOTES:
25336370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
25436370Ssklower  *	will it be correctly aligned?
25536370Ssklower  */
25637469Ssklower clnp_input(m, shp)
25736370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
25836370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
25936370Ssklower {
26036370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
26139930Ssklower 	struct sockaddr_iso			source; /* source address of pkt */
26239930Ssklower 	struct sockaddr_iso			target; /* destination address of pkt */
26339930Ssklower #define src	source.siso_addr
26439930Ssklower #define dst	target.siso_addr
26536370Ssklower 	caddr_t						hoff;	/* current offset in packet */
26636370Ssklower 	caddr_t						hend;	/* address of end of header info */
26736370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
26836370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
26936370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
27036370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
27136370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
27239930Ssklower 	extern struct sockaddr_iso	blank_siso;		/* used for initializing */
27336766Ssklower 	int							need_afrin = 0;
27436766Ssklower 										/* true if congestion experienced */
27536766Ssklower 										/* which means you need afrin nose */
27636766Ssklower 										/* spray. How clever! */
27736370Ssklower 
27836370Ssklower 	IFDEBUG(D_INPUT)
27936370Ssklower 		printf(
28036766Ssklower 		   "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
28136766Ssklower 			m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
28236370Ssklower 	ENDDEBUG
28336766Ssklower 	need_afrin = 0;
28436370Ssklower 
28536370Ssklower 	/*
28636370Ssklower 	 *	If no iso addresses have been set, there is nothing
28736370Ssklower 	 *	to do with the packet.
28836370Ssklower 	 */
28936370Ssklower 	if (iso_ifaddr == NULL) {
29036370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
29136370Ssklower 		return;
29236370Ssklower 	}
29336370Ssklower 
29436370Ssklower 	INCSTAT(cns_total);
29536370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
29636370Ssklower 
29736766Ssklower 	IFDEBUG(D_DUMPIN)
29836766Ssklower 		struct mbuf *mhead;
29936766Ssklower 		int			total_len = 0;
30036766Ssklower 		printf("clnp_input: clnp header:\n");
30136766Ssklower 		dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
30236766Ssklower 		printf("clnp_input: mbuf chain:\n");
30336766Ssklower 		for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
30436766Ssklower 			printf("m x%x, len %d\n", mhead, mhead->m_len);
30536766Ssklower 			total_len += mhead->m_len;
30636766Ssklower 		}
30736766Ssklower 		printf("clnp_input: total length of mbuf chain %d:\n", total_len);
30836766Ssklower 	ENDDEBUG
30936766Ssklower 
31036370Ssklower 	/*
31136370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
31236370Ssklower 	 *	checksum does not match
31336370Ssklower 	 */
31437469Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) {
31536370Ssklower 		INCSTAT(cns_badcsum);
31636370Ssklower 		clnp_discard(m, GEN_BADCSUM);
31737469Ssklower 		return;
31836370Ssklower 	}
31936370Ssklower 
32036370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
32136370Ssklower 		INCSTAT(cns_badvers);
32236370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
32337469Ssklower 		return;
32436370Ssklower 	}
32536370Ssklower 
32636370Ssklower 
32736370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
32836370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
32936370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
33037469Ssklower 		return;
33136370Ssklower 
33236370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
33336370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
33436370Ssklower 
33536370Ssklower 	/*
33636370Ssklower 	 *	extract the source and destination address
33736370Ssklower 	 *	drop packet on failure
33836370Ssklower 	 */
33939930Ssklower 	source = target = blank_siso;
34036370Ssklower 
34136370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
34236370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
34336370Ssklower 	if (hoff == (caddr_t)0) {
34436370Ssklower 		INCSTAT(cns_badaddr);
34536370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
34637469Ssklower 		return;
34736370Ssklower 	}
34836370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
34936370Ssklower 	if (hoff == (caddr_t)0) {
35036370Ssklower 		INCSTAT(cns_badaddr);
35136370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
35237469Ssklower 		return;
35336370Ssklower 	}
35436370Ssklower 
35536370Ssklower 	IFDEBUG(D_INPUT)
35636370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
35736370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
35836370Ssklower 	ENDDEBUG
35936370Ssklower 
36036370Ssklower 	/*
36136370Ssklower 	 *	extract the segmentation information, if it is present.
36236370Ssklower 	 *	drop packet on failure
36336370Ssklower 	 */
36437469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
36537469Ssklower 		(clnp->cnf_type & CNF_SEG_OK)) {
36636370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
36736370Ssklower 			INCSTAT(cns_noseg);
36836370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
36937469Ssklower 			return;
37036370Ssklower 		} else {
37136370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
37236370Ssklower 			/* make sure segmentation fields are in host order */
37336370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
37436370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
37536370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
37636370Ssklower 			seg_off = hoff - (caddr_t)clnp;
37736370Ssklower 			hoff += sizeof(struct clnp_segment);
37836370Ssklower 		}
37936370Ssklower 	}
38036370Ssklower 
38136370Ssklower 	/*
38236370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
38336370Ssklower 	 *	false (indicating an error was found in the options) or
38436370Ssklower 	 *	an unsupported option was found
38536370Ssklower 	 *	then drop packet and emit an ER.
38636370Ssklower 	 */
38736370Ssklower 	if (hoff < hend) {
38836370Ssklower 		int		errcode;
38936370Ssklower 
39036370Ssklower 		oidxp = &oidx;
39136370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
39236370Ssklower 
39336370Ssklower 		/* we do not support security */
39436370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
39536370Ssklower 			errcode = DISC_UNSUPPSECURE;
39636370Ssklower 
39736370Ssklower 		/* the er option is valid with ER pdus only */
39836370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
39937469Ssklower 			((clnp->cnf_type & CNF_TYPE) != CLNP_ER))
40036370Ssklower 			errcode = DISC_UNSUPPOPT;
40136370Ssklower 
40236766Ssklower #ifdef	DECBIT
40336766Ssklower 		/* check if the congestion experienced bit is set */
40436766Ssklower 		if (oidxp->cni_qos_formatp) {
40536766Ssklower 			caddr_t	qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
40636766Ssklower 			u_char	qos = *qosp;
40736766Ssklower 
40836766Ssklower 			need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
40936766Ssklower 				(CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
41036766Ssklower 			if (need_afrin)
41136766Ssklower 				INCSTAT(cns_congest_rcvd);
41236766Ssklower 		}
41360359Sbostic #endif	/* DECBIT */
41436766Ssklower 
41536370Ssklower 		if (errcode != 0) {
41636370Ssklower 			clnp_discard(m, (char)errcode);
41736370Ssklower 			IFDEBUG(D_INPUT)
41836370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
41936370Ssklower 					errcode);
42036370Ssklower 			ENDDEBUG
42137469Ssklower 			return;
42236370Ssklower 		}
42336370Ssklower 	}
42436370Ssklower 
42536370Ssklower 	/*
42636370Ssklower 	 *	check if this packet is for us. if not, then forward
42736370Ssklower 	 */
42836370Ssklower 	if (clnp_ours(&dst) == 0) {
42936370Ssklower 		IFDEBUG(D_INPUT)
43036370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
43136370Ssklower 		ENDDEBUG
43236370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
43337469Ssklower 		return;
43436370Ssklower 	}
43536370Ssklower 
43636370Ssklower 	/*
43736370Ssklower 	 *	ESIS Configuration Response Function
43836370Ssklower 	 *
43936370Ssklower 	 *	If the packet received was sent to the multicast address
44036370Ssklower 	 *	all end systems, then send an esh to the source
44136370Ssklower 	 */
44237469Ssklower 	if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) {
44336370Ssklower 		extern short esis_holding_time;
44436370Ssklower 
44536370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
44643332Ssklower 			shp->snh_shost, 6, &dst);
44736370Ssklower 	}
44836370Ssklower 
44936370Ssklower 	/*
45036370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
45136370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
45236370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
45336370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
45436370Ssklower 	 *	we should have nothing more to do with it.
45536370Ssklower 	 */
45637469Ssklower 	if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) &&
45737469Ssklower 		(clnp->cnf_type & CNF_SEG_OK) &&
45836370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
45936370Ssklower 		struct mbuf	*m0;
46036370Ssklower 
46136370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
46236370Ssklower 			m = m0;
46336370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
46439195Ssklower 			INCSTAT(cns_reassembled);
46536370Ssklower 		} else {
46637469Ssklower 			return;
46736370Ssklower 		}
46836370Ssklower 	}
46936370Ssklower 
47036370Ssklower 	/*
47136370Ssklower 	 *	give the packet to the higher layer
47236370Ssklower 	 *
47336370Ssklower 	 *	Note: the total length of packet
47436370Ssklower 	 *	is the total length field of the segmentation part,
47536370Ssklower 	 *	or, if absent, the segment length field of the
47636370Ssklower 	 *	header.
47736370Ssklower 	 */
47839195Ssklower 	INCSTAT(cns_delivered);
47937469Ssklower 	switch (clnp->cnf_type & CNF_TYPE) {
48036370Ssklower 	case CLNP_ER:
48136370Ssklower 		/*
48236370Ssklower 		 *	This ER must have the er option.
48336370Ssklower 		 *	If the option is not present, discard datagram.
48436370Ssklower 		 */
48536370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
48636370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
48736370Ssklower 		} else {
48836370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
48936370Ssklower 		}
49036370Ssklower 		break;
49136370Ssklower 
49236370Ssklower 	case CLNP_DT:
49339930Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target,
49439931Ssklower 			clnp->cnf_hdr_len, need_afrin);
49536370Ssklower 		break;
49636370Ssklower 
49736370Ssklower  	case CLNP_RAW:
49836370Ssklower 	case CLNP_ECR:
49936370Ssklower 		IFDEBUG(D_INPUT)
50036370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
50137469Ssklower 				clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len);
50236370Ssklower 		ENDDEBUG
50341338Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target,
50436370Ssklower 					clnp->cnf_hdr_len);
50536370Ssklower 		break;
50636370Ssklower 
50736370Ssklower 	case CLNP_EC:
50836370Ssklower 		IFDEBUG(D_INPUT)
50936370Ssklower 			printf("clnp_input: echoing packet\n");
51036370Ssklower 		ENDDEBUG
51152487Ssklower 		(void)clnp_echoreply(m,
51252487Ssklower 			(clnp->cnf_type & CNF_SEG_OK ? (int)seg_part.cng_tot_len : seg_len),
51352487Ssklower 			&source, &target, oidxp);
51436370Ssklower 		break;
51536370Ssklower 
51636370Ssklower 	default:
51737469Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n",
51837469Ssklower 			clnp->cnf_type & CNF_TYPE);
51939195Ssklower 		clnp_stat.cns_delivered--;
52039195Ssklower 		clnp_stat.cns_noproto++;
52136370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
52236370Ssklower  		break;
52336370Ssklower 	}
52436370Ssklower }
52560359Sbostic #endif /* ISO */
526