xref: /csrg-svn/sys/netiso/clnp_input.c (revision 36766)
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  */
27*36766Ssklower /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */
28*36766Ssklower /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */
29*36766Ssklower /*	@(#)clnp_input.c	7.3 (Berkeley) 02/14/89 */
3036370Ssklower 
3136370Ssklower #ifndef lint
32*36766Ssklower 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"
4636370Ssklower #include "../net/route.h"
4736370Ssklower 
4836370Ssklower #include "../netiso/iso.h"
4936370Ssklower #include "../netiso/iso_var.h"
5036370Ssklower #include "../netiso/iso_snpac.h"
5136370Ssklower #include "../netiso/clnp.h"
5236370Ssklower #include "../netiso/clnl.h"
5336370Ssklower #include "../netiso/esis.h"
5436370Ssklower #include "../netiso/clnp_stat.h"
5536370Ssklower #include "../netiso/argo_debug.h"
5636370Ssklower 
5736370Ssklower #ifdef ISO
5836370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
5936370Ssklower struct clnl_protosw clnl_protox[256];
6036370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
6136370Ssklower struct mbuf	*clnp_data_ck();
6236370Ssklower 
6336370Ssklower int	clnp_input();
6436370Ssklower 
6536370Ssklower int	esis_input();
6636370Ssklower 
6736370Ssklower #ifdef	ISO_X25ESIS
6836370Ssklower int	x25esis_input();
6936370Ssklower #endif	ISO_X25ESIS
7036370Ssklower 
7136370Ssklower /*
7236370Ssklower  * FUNCTION:		clnp_init
7336370Ssklower  *
7436370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
7536370Ssklower  *
7636370Ssklower  * RETURNS:			none
7736370Ssklower  *
7836370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
7936370Ssklower  *					the isosw table.
8036370Ssklower  *
8136370Ssklower  * NOTES:
8236370Ssklower  */
8336370Ssklower clnp_init()
8436370Ssklower {
8536370Ssklower 	register struct protosw *pr;
8636370Ssklower 
8736370Ssklower 	/*
8836370Ssklower 	 *	CLNP protox initialization
8936370Ssklower 	 */
9036370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
9136370Ssklower 		printf("clnl_init: no raw CLNP\n");
9236370Ssklower 	else
9336370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
9436370Ssklower 
9536370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
9636370Ssklower 		printf("clnl_init: no tp/clnp\n");
9736370Ssklower 	else
9836370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
9936370Ssklower 
10036370Ssklower 	/*
10136370Ssklower 	 *	CLNL protox initialization
10236370Ssklower 	 */
10336370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
10436370Ssklower 
10536370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
10636370Ssklower }
10736370Ssklower 
10836370Ssklower /*
10936370Ssklower  * FUNCTION:		clnlintr
11036370Ssklower  *
11136370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
11236370Ssklower  *
11336370Ssklower  * RETURNS:			nothing.
11436370Ssklower  *
11536370Ssklower  * SIDE EFFECTS:
11636370Ssklower  *
11736370Ssklower  * NOTES:
11836370Ssklower  */
11936370Ssklower clnlintr()
12036370Ssklower {
12136370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
12236370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
12336370Ssklower 	struct ifnet				*ifp;	/* ptr to interface pkt arrived on */
12436370Ssklower 	int							s;		/* save and restore priority */
12536370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
12636370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
12736370Ssklower 
12836370Ssklower 	/*
12936370Ssklower 	 *	Get next datagram off clnl input queue
13036370Ssklower 	 */
13136370Ssklower next:
13236370Ssklower 	s = splimp();
13336370Ssklower 
13436765Ssklower 	/* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/
13536765Ssklower 	IF_DEQUEUE(&clnlintrq, m);
13636370Ssklower 
13736765Ssklower 
13836765Ssklower 	splx(s);
13936765Ssklower 	if (m == 0)		/* nothing to do */
14036765Ssklower 		return;
14136765Ssklower 	if (m->m_flags & M_PKTHDR == 0) {
14236765Ssklower 		m_freem(m);
14336765Ssklower 		goto next;
14436765Ssklower 	}
14536765Ssklower 	bcopy((caddr_t)(mtod(m, struct llc_etherhdr *)->dst),
14636765Ssklower 		(caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost));
14736765Ssklower 	m->m_data += sizeof (struct llc_etherhdr);
14836765Ssklower 	m->m_len -= sizeof (struct llc_etherhdr);
14936765Ssklower 	m->m_pkthdr.len -= sizeof (struct llc_etherhdr);
15036765Ssklower 	sh.snh_ifp = m->m_pkthdr.rcvif;
15136370Ssklower 	IFDEBUG(D_INPUT)
15236370Ssklower 		int i;
15336370Ssklower 		printf("clnlintr: src:");
15436370Ssklower 		for (i=0; i<6; i++)
15536370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
15636370Ssklower 		printf(" dst:");
15736370Ssklower 		for (i=0; i<6; i++)
15836370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
15936370Ssklower 		printf("\n");
16036370Ssklower 	ENDDEBUG
16136370Ssklower 
16236370Ssklower 	/*
16336370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
16436370Ssklower 	 *	Drop the packet if this fails.
16536370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
16636370Ssklower 	 *	data is not there.
16736370Ssklower 	 */
16836370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
16936370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
17036370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
17136370Ssklower 		goto next;				/* m_pullup discards mbuf */
17236370Ssklower 	}
17336370Ssklower 
17436370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
17536370Ssklower 
17636370Ssklower 	/*
17736370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
17836370Ssklower 	 */
17936370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
18036370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
18136370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
18236370Ssklower 		m_freem(m);
18336370Ssklower 		goto next;
18436370Ssklower 	}
18536370Ssklower 
18636370Ssklower 	/*
18736370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
18836370Ssklower 	 *	Drop packet if this fails.
18936370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
19036370Ssklower 	 */
19136370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
19236370Ssklower 		if ((m = m_pullup(m, clnl->cnf_hdr_len)) == 0) {
19336370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
19436370Ssklower 			goto next;	/* m_pullup discards mbuf */
19536370Ssklower 		}
19636370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
19736370Ssklower 	}
19836370Ssklower 
19936370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
20036370Ssklower 
20136370Ssklower 
20236370Ssklower 	if (clnlsw->clnl_input)
20336370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
20436370Ssklower 	else
20536370Ssklower 		m_freem(m);
20636370Ssklower 
20736370Ssklower 	goto next;
20836370Ssklower }
20936370Ssklower 
21036370Ssklower /*
21136370Ssklower  * FUNCTION:		clnp_input
21236370Ssklower  *
21336370Ssklower  * PURPOSE:			process an incoming clnp packet
21436370Ssklower  *
21536370Ssklower  * RETURNS:			nothing
21636370Ssklower  *
21736370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
21836370Ssklower  *
21936370Ssklower  * NOTES:
22036370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
22136370Ssklower  *	will it be correctly aligned?
22236370Ssklower  */
22336370Ssklower int clnp_input(m, shp)
22436370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
22536370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
22636370Ssklower {
22736370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
22836370Ssklower 	struct iso_addr				src;	/* source address of pkt */
22936370Ssklower 	struct iso_addr				dst;	/* destination address of pkt */
23036370Ssklower 	caddr_t						hoff;	/* current offset in packet */
23136370Ssklower 	caddr_t						hend;	/* address of end of header info */
23236370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
23336370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
23436370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
23536370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
23636370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
237*36766Ssklower 	int							need_afrin = 0;
238*36766Ssklower 										/* true if congestion experienced */
239*36766Ssklower 										/* which means you need afrin nose */
240*36766Ssklower 										/* spray. How clever! */
24136370Ssklower 
24236370Ssklower 	IFDEBUG(D_INPUT)
24336370Ssklower 		printf(
244*36766Ssklower 		   "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n",
245*36766Ssklower 			m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal");
24636370Ssklower 	ENDDEBUG
247*36766Ssklower 	need_afrin = 0;
24836370Ssklower 
24936370Ssklower 	/*
25036370Ssklower 	 *	If no iso addresses have been set, there is nothing
25136370Ssklower 	 *	to do with the packet.
25236370Ssklower 	 */
25336370Ssklower 	if (iso_ifaddr == NULL) {
25436370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
25536370Ssklower 		return;
25636370Ssklower 	}
25736370Ssklower 
25836370Ssklower 	INCSTAT(cns_total);
25936370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
26036370Ssklower 
261*36766Ssklower 	IFDEBUG(D_DUMPIN)
262*36766Ssklower 		struct mbuf *mhead;
263*36766Ssklower 		int			total_len = 0;
264*36766Ssklower 		printf("clnp_input: clnp header:\n");
265*36766Ssklower 		dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len);
266*36766Ssklower 		printf("clnp_input: mbuf chain:\n");
267*36766Ssklower 		for (mhead = m; mhead != NULL; mhead=mhead->m_next) {
268*36766Ssklower 			printf("m x%x, len %d\n", mhead, mhead->m_len);
269*36766Ssklower 			total_len += mhead->m_len;
270*36766Ssklower 		}
271*36766Ssklower 		printf("clnp_input: total length of mbuf chain %d:\n", total_len);
272*36766Ssklower 	ENDDEBUG
273*36766Ssklower 
27436370Ssklower 	/*
27536370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
27636370Ssklower 	 *	checksum does not match
27736370Ssklower 	 */
27836370Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, clnp->cnf_hdr_len)) {
27936370Ssklower 		INCSTAT(cns_badcsum);
28036370Ssklower 		clnp_discard(m, GEN_BADCSUM);
281*36766Ssklower 		return 0;
28236370Ssklower 	}
28336370Ssklower 
28436370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
28536370Ssklower 		INCSTAT(cns_badvers);
28636370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
287*36766Ssklower 		return 0;
28836370Ssklower 	}
28936370Ssklower 
29036370Ssklower 
29136370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
29236370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
29336370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
294*36766Ssklower 		return 0;
29536370Ssklower 
29636370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
29736370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
29836370Ssklower 
29936370Ssklower 	/*
30036370Ssklower 	 *	extract the source and destination address
30136370Ssklower 	 *	drop packet on failure
30236370Ssklower 	 */
30336370Ssklower 	bzero((caddr_t)&src, sizeof(src));
30436370Ssklower 	bzero((caddr_t)&dst, sizeof(dst));
30536370Ssklower 
30636370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
30736370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
30836370Ssklower 	if (hoff == (caddr_t)0) {
30936370Ssklower 		INCSTAT(cns_badaddr);
31036370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
311*36766Ssklower 		return 0;
31236370Ssklower 	}
31336370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
31436370Ssklower 	if (hoff == (caddr_t)0) {
31536370Ssklower 		INCSTAT(cns_badaddr);
31636370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
317*36766Ssklower 		return 0;
31836370Ssklower 	}
31936370Ssklower 
32036370Ssklower 	IFDEBUG(D_INPUT)
32136370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
32236370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
32336370Ssklower 	ENDDEBUG
32436370Ssklower 
32536370Ssklower 	/*
32636370Ssklower 	 *	extract the segmentation information, if it is present.
32736370Ssklower 	 *	drop packet on failure
32836370Ssklower 	 */
32936370Ssklower 	if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok)) {
33036370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
33136370Ssklower 			INCSTAT(cns_noseg);
33236370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
333*36766Ssklower 			return 0;
33436370Ssklower 		} else {
33536370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
33636370Ssklower 			/* make sure segmentation fields are in host order */
33736370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
33836370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
33936370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
34036370Ssklower 			seg_off = hoff - (caddr_t)clnp;
34136370Ssklower 			hoff += sizeof(struct clnp_segment);
34236370Ssklower 		}
34336370Ssklower 	}
34436370Ssklower 
34536370Ssklower 	/*
34636370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
34736370Ssklower 	 *	false (indicating an error was found in the options) or
34836370Ssklower 	 *	an unsupported option was found
34936370Ssklower 	 *	then drop packet and emit an ER.
35036370Ssklower 	 */
35136370Ssklower 	if (hoff < hend) {
35236370Ssklower 		int		errcode;
35336370Ssklower 
35436370Ssklower 		oidxp = &oidx;
35536370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
35636370Ssklower 
35736370Ssklower 		/* we do not support security */
35836370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
35936370Ssklower 			errcode = DISC_UNSUPPSECURE;
36036370Ssklower 
36136370Ssklower 		/* the er option is valid with ER pdus only */
36236370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
36336370Ssklower 			(clnp->cnf_type != CLNP_ER))
36436370Ssklower 			errcode = DISC_UNSUPPOPT;
36536370Ssklower 
366*36766Ssklower #ifdef	DECBIT
367*36766Ssklower 		/* check if the congestion experienced bit is set */
368*36766Ssklower 		if (oidxp->cni_qos_formatp) {
369*36766Ssklower 			caddr_t	qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp);
370*36766Ssklower 			u_char	qos = *qosp;
371*36766Ssklower 
372*36766Ssklower 			need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) ==
373*36766Ssklower 				(CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED));
374*36766Ssklower 			if (need_afrin)
375*36766Ssklower 				INCSTAT(cns_congest_rcvd);
376*36766Ssklower 		}
377*36766Ssklower #endif	DECBIT
378*36766Ssklower 
37936370Ssklower 		if (errcode != 0) {
38036370Ssklower 			clnp_discard(m, (char)errcode);
38136370Ssklower 			IFDEBUG(D_INPUT)
38236370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
38336370Ssklower 					errcode);
38436370Ssklower 			ENDDEBUG
385*36766Ssklower 			return 0;
38636370Ssklower 		}
38736370Ssklower 	}
38836370Ssklower 
38936370Ssklower 	/*
39036370Ssklower 	 *	check if this packet is for us. if not, then forward
39136370Ssklower 	 */
39236370Ssklower 	if (clnp_ours(&dst) == 0) {
39336370Ssklower 		IFDEBUG(D_INPUT)
39436370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
39536370Ssklower 		ENDDEBUG
39636370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
397*36766Ssklower 		return 0;
39836370Ssklower 	}
39936370Ssklower 
40036370Ssklower 	/*
40136370Ssklower 	 *	ESIS Configuration Response Function
40236370Ssklower 	 *
40336370Ssklower 	 *	If the packet received was sent to the multicast address
40436370Ssklower 	 *	all end systems, then send an esh to the source
40536370Ssklower 	 */
40636370Ssklower 	if ((IS_MULTICAST(shp->snh_dhost)) && (iso_systype == SNPA_ES)) {
40736370Ssklower 		extern short esis_holding_time;
40836370Ssklower 
40936370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
41036370Ssklower 			shp->snh_shost, 6);
41136370Ssklower 	}
41236370Ssklower 
41336370Ssklower 	/*
41436370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
41536370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
41636370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
41736370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
41836370Ssklower 	 *	we should have nothing more to do with it.
41936370Ssklower 	 */
42036370Ssklower 	if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok) &&
42136370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
42236370Ssklower 		struct mbuf	*m0;
42336370Ssklower 
42436370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
42536370Ssklower 			m = m0;
42636370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
42736370Ssklower 		} else {
428*36766Ssklower 			return 0;
42936370Ssklower 		}
43036370Ssklower 	}
43136370Ssklower 
43236370Ssklower 	/*
43336370Ssklower 	 *	give the packet to the higher layer
43436370Ssklower 	 *
43536370Ssklower 	 *	Note: the total length of packet
43636370Ssklower 	 *	is the total length field of the segmentation part,
43736370Ssklower 	 *	or, if absent, the segment length field of the
43836370Ssklower 	 *	header.
43936370Ssklower 	 */
44036370Ssklower 	switch (clnp->cnf_type) {
44136370Ssklower 	case CLNP_ER:
44236370Ssklower 		/*
44336370Ssklower 		 *	This ER must have the er option.
44436370Ssklower 		 *	If the option is not present, discard datagram.
44536370Ssklower 		 */
44636370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
44736370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
44836370Ssklower 		} else {
44936370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
45036370Ssklower 		}
45136370Ssklower 		break;
45236370Ssklower 
45336370Ssklower 	case CLNP_DT:
454*36766Ssklower  		if (need_afrin) {
455*36766Ssklower  			/* NOTE: do this before TP gets the packet so tp ack can use info*/
456*36766Ssklower  			IFDEBUG(D_INPUT)
457*36766Ssklower  				printf("clnp_input: Calling tpclnp_ctlinput(%s)\n",
458*36766Ssklower  					clnp_iso_addrp(&src));
459*36766Ssklower  			ENDDEBUG
460*36766Ssklower  			tpclnp_ctlinput1(PRC_QUENCH2, &src);
461*36766Ssklower  		}
46236370Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst,
46336370Ssklower 			clnp->cnf_hdr_len);
46436370Ssklower 		break;
46536370Ssklower 
46636370Ssklower  	case CLNP_RAW:
46736370Ssklower 	case CLNP_ECR:
46836370Ssklower 		IFDEBUG(D_INPUT)
46936370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
47036370Ssklower 				clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len);
47136370Ssklower 		ENDDEBUG
47236370Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst,
47336370Ssklower 					clnp->cnf_hdr_len);
47436370Ssklower 		break;
47536370Ssklower 
47636370Ssklower 	case CLNP_EC:
47736370Ssklower 		IFDEBUG(D_INPUT)
47836370Ssklower 			printf("clnp_input: echoing packet\n");
47936370Ssklower 		ENDDEBUG
48036370Ssklower 		/*
48136370Ssklower 		 *	Switch the source and destination address,
48236370Ssklower 		 */
48336370Ssklower 		hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
48436370Ssklower 		CLNP_INSERT_ADDR(hoff, &src);
48536370Ssklower 		CLNP_INSERT_ADDR(hoff, &dst);
48636370Ssklower 		clnp->cnf_type = CLNP_ECR;
48736370Ssklower 
48836370Ssklower 		/*
48936370Ssklower 		 *	Forward back to sender
49036370Ssklower 		 */
49136370Ssklower  		clnp_forward(m, clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len,
49236370Ssklower 			&src, oidxp, seg_off, shp);
49336370Ssklower 		break;
49436370Ssklower 
49536370Ssklower 	default:
49636370Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n", clnp->cnf_type);
49736370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
49836370Ssklower  		break;
49936370Ssklower 	}
50036370Ssklower }
50136370Ssklower #endif ISO
502