xref: /csrg-svn/sys/netiso/clnp_input.c (revision 36370)
1*36370Ssklower /***********************************************************
2*36370Ssklower 		Copyright IBM Corporation 1987
3*36370Ssklower 
4*36370Ssklower                       All Rights Reserved
5*36370Ssklower 
6*36370Ssklower Permission to use, copy, modify, and distribute this software and its
7*36370Ssklower documentation for any purpose and without fee is hereby granted,
8*36370Ssklower provided that the above copyright notice appear in all copies and that
9*36370Ssklower both that copyright notice and this permission notice appear in
10*36370Ssklower supporting documentation, and that the name of IBM not be
11*36370Ssklower used in advertising or publicity pertaining to distribution of the
12*36370Ssklower software without specific, written prior permission.
13*36370Ssklower 
14*36370Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36370Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36370Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36370Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36370Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36370Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36370Ssklower SOFTWARE.
21*36370Ssklower 
22*36370Ssklower ******************************************************************/
23*36370Ssklower 
24*36370Ssklower /*
25*36370Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36370Ssklower  */
27*36370Ssklower /* $Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $ */
28*36370Ssklower /* $Source: /usr/argo/sys/netiso/RCS/clnp_input.c,v $ */
29*36370Ssklower 
30*36370Ssklower #ifndef lint
31*36370Ssklower static char *rcsid = "$Header: clnp_input.c,v 4.4 88/09/08 08:38:15 hagens Exp $";
32*36370Ssklower #endif lint
33*36370Ssklower 
34*36370Ssklower #include "../h/types.h"
35*36370Ssklower #include "../h/param.h"
36*36370Ssklower #include "../h/mbuf.h"
37*36370Ssklower #include "../h/domain.h"
38*36370Ssklower #include "../h/protosw.h"
39*36370Ssklower #include "../h/socket.h"
40*36370Ssklower #include "../h/socketvar.h"
41*36370Ssklower #include "../h/errno.h"
42*36370Ssklower #include "../h/time.h"
43*36370Ssklower 
44*36370Ssklower #include "../net/if.h"
45*36370Ssklower #include "../net/route.h"
46*36370Ssklower 
47*36370Ssklower #include "../netiso/iso.h"
48*36370Ssklower #include "../netiso/iso_var.h"
49*36370Ssklower #include "../netiso/iso_snpac.h"
50*36370Ssklower #include "../netiso/clnp.h"
51*36370Ssklower #include "../netiso/clnl.h"
52*36370Ssklower #include "../netiso/esis.h"
53*36370Ssklower #include "../netiso/clnp_stat.h"
54*36370Ssklower #include "../netiso/argo_debug.h"
55*36370Ssklower 
56*36370Ssklower #ifdef ISO
57*36370Ssklower u_char		clnp_protox[ISOPROTO_MAX];
58*36370Ssklower struct clnl_protosw clnl_protox[256];
59*36370Ssklower int			clnpqmaxlen = IFQ_MAXLEN;	/* RAH? why is this a variable */
60*36370Ssklower struct mbuf	*clnp_data_ck();
61*36370Ssklower 
62*36370Ssklower int	clnp_input();
63*36370Ssklower 
64*36370Ssklower int	esis_input();
65*36370Ssklower 
66*36370Ssklower #ifdef	ISO_X25ESIS
67*36370Ssklower int	x25esis_input();
68*36370Ssklower #endif	ISO_X25ESIS
69*36370Ssklower 
70*36370Ssklower /*
71*36370Ssklower  * FUNCTION:		clnp_init
72*36370Ssklower  *
73*36370Ssklower  * PURPOSE:			clnp initialization. Fill in clnp switch tables.
74*36370Ssklower  *
75*36370Ssklower  * RETURNS:			none
76*36370Ssklower  *
77*36370Ssklower  * SIDE EFFECTS:	fills in clnp_protox table with correct offsets into
78*36370Ssklower  *					the isosw table.
79*36370Ssklower  *
80*36370Ssklower  * NOTES:
81*36370Ssklower  */
82*36370Ssklower clnp_init()
83*36370Ssklower {
84*36370Ssklower 	register struct protosw *pr;
85*36370Ssklower 
86*36370Ssklower 	/*
87*36370Ssklower 	 *	CLNP protox initialization
88*36370Ssklower 	 */
89*36370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0)
90*36370Ssklower 		printf("clnl_init: no raw CLNP\n");
91*36370Ssklower 	else
92*36370Ssklower 		clnp_protox[ISOPROTO_RAW] = pr - isosw;
93*36370Ssklower 
94*36370Ssklower 	if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0)
95*36370Ssklower 		printf("clnl_init: no tp/clnp\n");
96*36370Ssklower 	else
97*36370Ssklower 		clnp_protox[ISOPROTO_TP] = pr - isosw;
98*36370Ssklower 
99*36370Ssklower 	/*
100*36370Ssklower 	 *	CLNL protox initialization
101*36370Ssklower 	 */
102*36370Ssklower 	clnl_protox[ISO8473_CLNP].clnl_input = clnp_input;
103*36370Ssklower 
104*36370Ssklower 	clnlintrq.ifq_maxlen = clnpqmaxlen;
105*36370Ssklower }
106*36370Ssklower 
107*36370Ssklower /*
108*36370Ssklower  * FUNCTION:		clnlintr
109*36370Ssklower  *
110*36370Ssklower  * PURPOSE:			Process a packet on the clnl input queue
111*36370Ssklower  *
112*36370Ssklower  * RETURNS:			nothing.
113*36370Ssklower  *
114*36370Ssklower  * SIDE EFFECTS:
115*36370Ssklower  *
116*36370Ssklower  * NOTES:
117*36370Ssklower  */
118*36370Ssklower clnlintr()
119*36370Ssklower {
120*36370Ssklower 	register struct mbuf		*m;		/* ptr to first mbuf of pkt */
121*36370Ssklower 	register struct clnl_fixed	*clnl;	/* ptr to fixed part of clnl hdr */
122*36370Ssklower 	struct ifnet				*ifp;	/* ptr to interface pkt arrived on */
123*36370Ssklower 	int							s;		/* save and restore priority */
124*36370Ssklower 	struct clnl_protosw			*clnlsw;/* ptr to protocol switch */
125*36370Ssklower 	struct snpa_hdr				sh;		/* subnetwork hdr */
126*36370Ssklower 
127*36370Ssklower 	/*
128*36370Ssklower 	 *	Get next datagram off clnl input queue
129*36370Ssklower 	 */
130*36370Ssklower next:
131*36370Ssklower 	s = splimp();
132*36370Ssklower 
133*36370Ssklower 	IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);
134*36370Ssklower 
135*36370Ssklower 	IFDEBUG(D_INPUT)
136*36370Ssklower 		int i;
137*36370Ssklower 		printf("clnlintr: src:");
138*36370Ssklower 		for (i=0; i<6; i++)
139*36370Ssklower 			printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' ');
140*36370Ssklower 		printf(" dst:");
141*36370Ssklower 		for (i=0; i<6; i++)
142*36370Ssklower 			printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' ');
143*36370Ssklower 		printf("\n");
144*36370Ssklower 	ENDDEBUG
145*36370Ssklower 
146*36370Ssklower 	splx(s);
147*36370Ssklower 	if (m == 0)		/* nothing to do */
148*36370Ssklower 		return;
149*36370Ssklower 
150*36370Ssklower 	/*
151*36370Ssklower 	 *	Get the fixed part of the clnl header into the first mbuf.
152*36370Ssklower 	 *	Drop the packet if this fails.
153*36370Ssklower 	 *	Do not call m_pullup if we have a cluster mbuf or the
154*36370Ssklower 	 *	data is not there.
155*36370Ssklower 	 */
156*36370Ssklower 	if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) &&
157*36370Ssklower 		((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) {
158*36370Ssklower 		INCSTAT(cns_toosmall);	/* TODO: use clnl stats */
159*36370Ssklower 		goto next;				/* m_pullup discards mbuf */
160*36370Ssklower 	}
161*36370Ssklower 
162*36370Ssklower 	clnl = mtod(m, struct clnl_fixed *);
163*36370Ssklower 
164*36370Ssklower 	/*
165*36370Ssklower 	 *	Drop packet if the length of the header is not reasonable.
166*36370Ssklower 	 */
167*36370Ssklower 	if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) ||
168*36370Ssklower 		(clnl->cnf_hdr_len > CLNP_HDR_MAX)) {
169*36370Ssklower 		INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
170*36370Ssklower 		m_freem(m);
171*36370Ssklower 		goto next;
172*36370Ssklower 	}
173*36370Ssklower 
174*36370Ssklower 	/*
175*36370Ssklower 	 *	If the header is not contained in this mbuf, make it so.
176*36370Ssklower 	 *	Drop packet if this fails.
177*36370Ssklower 	 *	Note: m_pullup will allocate a cluster mbuf if necessary
178*36370Ssklower 	 */
179*36370Ssklower 	if (clnl->cnf_hdr_len > m->m_len) {
180*36370Ssklower 		if ((m = m_pullup(m, clnl->cnf_hdr_len)) == 0) {
181*36370Ssklower 			INCSTAT(cns_badhlen);	/* TODO: use clnl stats */
182*36370Ssklower 			goto next;	/* m_pullup discards mbuf */
183*36370Ssklower 		}
184*36370Ssklower 		clnl = mtod(m, struct clnl_fixed *);
185*36370Ssklower 	}
186*36370Ssklower 
187*36370Ssklower 	clnlsw = &clnl_protox[clnl->cnf_proto_id];
188*36370Ssklower 
189*36370Ssklower 
190*36370Ssklower 	if (clnlsw->clnl_input)
191*36370Ssklower 		(*clnlsw->clnl_input) (m, &sh);
192*36370Ssklower 	else
193*36370Ssklower 		m_freem(m);
194*36370Ssklower 
195*36370Ssklower 	goto next;
196*36370Ssklower }
197*36370Ssklower 
198*36370Ssklower /*
199*36370Ssklower  * FUNCTION:		clnp_input
200*36370Ssklower  *
201*36370Ssklower  * PURPOSE:			process an incoming clnp packet
202*36370Ssklower  *
203*36370Ssklower  * RETURNS:			nothing
204*36370Ssklower  *
205*36370Ssklower  * SIDE EFFECTS:	increments fields of clnp_stat structure.
206*36370Ssklower  *
207*36370Ssklower  * NOTES:
208*36370Ssklower  *	TODO: I would like to make seg_part a pointer into the mbuf, but
209*36370Ssklower  *	will it be correctly aligned?
210*36370Ssklower  */
211*36370Ssklower int clnp_input(m, shp)
212*36370Ssklower struct mbuf		*m;		/* ptr to first mbuf of pkt */
213*36370Ssklower struct snpa_hdr	*shp;	/* subnetwork header */
214*36370Ssklower {
215*36370Ssklower 	register struct clnp_fixed	*clnp;	/* ptr to fixed part of header */
216*36370Ssklower 	struct iso_addr				src;	/* source address of pkt */
217*36370Ssklower 	struct iso_addr				dst;	/* destination address of pkt */
218*36370Ssklower 	caddr_t						hoff;	/* current offset in packet */
219*36370Ssklower 	caddr_t						hend;	/* address of end of header info */
220*36370Ssklower 	struct clnp_segment			seg_part; /* segment part of hdr */
221*36370Ssklower 	int							seg_off=0; /* offset of segment part of hdr */
222*36370Ssklower 	int							seg_len;/* length of packet data&hdr in bytes */
223*36370Ssklower 	struct clnp_optidx			oidx, *oidxp = NULL;	/* option index */
224*36370Ssklower 	extern int 					iso_systype;	/* used by ESIS config resp */
225*36370Ssklower 
226*36370Ssklower 	IFDEBUG(D_INPUT)
227*36370Ssklower 		printf(
228*36370Ssklower 		"clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, data:\n",
229*36370Ssklower 			m->m_len, m->m_type);
230*36370Ssklower 	ENDDEBUG
231*36370Ssklower 	IFDEBUG(D_DUMPIN)
232*36370Ssklower 		printf("clnp_input: first mbuf:\n");
233*36370Ssklower 		dump_buf(mtod(m, caddr_t), m->m_len);
234*36370Ssklower 	ENDDEBUG
235*36370Ssklower 
236*36370Ssklower 	/*
237*36370Ssklower 	 *	If no iso addresses have been set, there is nothing
238*36370Ssklower 	 *	to do with the packet.
239*36370Ssklower 	 */
240*36370Ssklower 	if (iso_ifaddr == NULL) {
241*36370Ssklower 		clnp_discard(m, ADDR_DESTUNREACH);
242*36370Ssklower 		return;
243*36370Ssklower 	}
244*36370Ssklower 
245*36370Ssklower 	INCSTAT(cns_total);
246*36370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
247*36370Ssklower 
248*36370Ssklower 	/*
249*36370Ssklower 	 *	Compute checksum (if necessary) and drop packet if
250*36370Ssklower 	 *	checksum does not match
251*36370Ssklower 	 */
252*36370Ssklower 	if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, clnp->cnf_hdr_len)) {
253*36370Ssklower 		INCSTAT(cns_badcsum);
254*36370Ssklower 		clnp_discard(m, GEN_BADCSUM);
255*36370Ssklower 		return;
256*36370Ssklower 	}
257*36370Ssklower 
258*36370Ssklower 	if (clnp->cnf_vers != ISO8473_V1) {
259*36370Ssklower 		INCSTAT(cns_badvers);
260*36370Ssklower 		clnp_discard(m, DISC_UNSUPPVERS);
261*36370Ssklower 		return;
262*36370Ssklower 	}
263*36370Ssklower 
264*36370Ssklower 
265*36370Ssklower  	/* check mbuf data length: clnp_data_ck will free mbuf upon error */
266*36370Ssklower 	CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len);
267*36370Ssklower 	if ((m = clnp_data_ck(m, seg_len)) == 0)
268*36370Ssklower 		return;
269*36370Ssklower 
270*36370Ssklower 	clnp = mtod(m, struct clnp_fixed *);
271*36370Ssklower 	hend = (caddr_t)clnp + clnp->cnf_hdr_len;
272*36370Ssklower 
273*36370Ssklower 	/*
274*36370Ssklower 	 *	extract the source and destination address
275*36370Ssklower 	 *	drop packet on failure
276*36370Ssklower 	 */
277*36370Ssklower 	bzero((caddr_t)&src, sizeof(src));
278*36370Ssklower 	bzero((caddr_t)&dst, sizeof(dst));
279*36370Ssklower 
280*36370Ssklower 	hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
281*36370Ssklower 	CLNP_EXTRACT_ADDR(dst, hoff, hend);
282*36370Ssklower 	if (hoff == (caddr_t)0) {
283*36370Ssklower 		INCSTAT(cns_badaddr);
284*36370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
285*36370Ssklower 		return;
286*36370Ssklower 	}
287*36370Ssklower 	CLNP_EXTRACT_ADDR(src, hoff, hend);
288*36370Ssklower 	if (hoff == (caddr_t)0) {
289*36370Ssklower 		INCSTAT(cns_badaddr);
290*36370Ssklower 		clnp_discard(m, GEN_INCOMPLETE);
291*36370Ssklower 		return;
292*36370Ssklower 	}
293*36370Ssklower 
294*36370Ssklower 	IFDEBUG(D_INPUT)
295*36370Ssklower 		printf("clnp_input: from %s", clnp_iso_addrp(&src));
296*36370Ssklower 		printf(" to %s\n", clnp_iso_addrp(&dst));
297*36370Ssklower 	ENDDEBUG
298*36370Ssklower 
299*36370Ssklower 	/*
300*36370Ssklower 	 *	extract the segmentation information, if it is present.
301*36370Ssklower 	 *	drop packet on failure
302*36370Ssklower 	 */
303*36370Ssklower 	if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok)) {
304*36370Ssklower 		if (hoff + sizeof(struct clnp_segment) > hend) {
305*36370Ssklower 			INCSTAT(cns_noseg);
306*36370Ssklower 			clnp_discard(m, GEN_INCOMPLETE);
307*36370Ssklower 			return;
308*36370Ssklower 		} else {
309*36370Ssklower 			(void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment));
310*36370Ssklower 			/* make sure segmentation fields are in host order */
311*36370Ssklower 			seg_part.cng_id = ntohs(seg_part.cng_id);
312*36370Ssklower 			seg_part.cng_off = ntohs(seg_part.cng_off);
313*36370Ssklower 			seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len);
314*36370Ssklower 			seg_off = hoff - (caddr_t)clnp;
315*36370Ssklower 			hoff += sizeof(struct clnp_segment);
316*36370Ssklower 		}
317*36370Ssklower 	}
318*36370Ssklower 
319*36370Ssklower 	/*
320*36370Ssklower 	 *	process options if present. If clnp_opt_sanity returns
321*36370Ssklower 	 *	false (indicating an error was found in the options) or
322*36370Ssklower 	 *	an unsupported option was found
323*36370Ssklower 	 *	then drop packet and emit an ER.
324*36370Ssklower 	 */
325*36370Ssklower 	if (hoff < hend) {
326*36370Ssklower 		int		errcode;
327*36370Ssklower 
328*36370Ssklower 		oidxp = &oidx;
329*36370Ssklower 		errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp);
330*36370Ssklower 
331*36370Ssklower 		/* we do not support security */
332*36370Ssklower 		if ((errcode == 0) && (oidxp->cni_securep))
333*36370Ssklower 			errcode = DISC_UNSUPPSECURE;
334*36370Ssklower 
335*36370Ssklower 		/* the er option is valid with ER pdus only */
336*36370Ssklower 		if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) &&
337*36370Ssklower 			(clnp->cnf_type != CLNP_ER))
338*36370Ssklower 			errcode = DISC_UNSUPPOPT;
339*36370Ssklower 
340*36370Ssklower 		if (errcode != 0) {
341*36370Ssklower 			clnp_discard(m, (char)errcode);
342*36370Ssklower 			IFDEBUG(D_INPUT)
343*36370Ssklower 				printf("clnp_input: dropped (err x%x) due to bad options\n",
344*36370Ssklower 					errcode);
345*36370Ssklower 			ENDDEBUG
346*36370Ssklower 			return;
347*36370Ssklower 		}
348*36370Ssklower 	}
349*36370Ssklower 
350*36370Ssklower 	/*
351*36370Ssklower 	 *	check if this packet is for us. if not, then forward
352*36370Ssklower 	 */
353*36370Ssklower 	if (clnp_ours(&dst) == 0) {
354*36370Ssklower 		IFDEBUG(D_INPUT)
355*36370Ssklower 			printf("clnp_input: forwarding packet not for us\n");
356*36370Ssklower 		ENDDEBUG
357*36370Ssklower  		clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp);
358*36370Ssklower 		return;
359*36370Ssklower 	}
360*36370Ssklower 
361*36370Ssklower 	/*
362*36370Ssklower 	 *	ESIS Configuration Response Function
363*36370Ssklower 	 *
364*36370Ssklower 	 *	If the packet received was sent to the multicast address
365*36370Ssklower 	 *	all end systems, then send an esh to the source
366*36370Ssklower 	 */
367*36370Ssklower 	if ((IS_MULTICAST(shp->snh_dhost)) && (iso_systype == SNPA_ES)) {
368*36370Ssklower 		extern short esis_holding_time;
369*36370Ssklower 
370*36370Ssklower 		esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time,
371*36370Ssklower 			shp->snh_shost, 6);
372*36370Ssklower 	}
373*36370Ssklower 
374*36370Ssklower 	/*
375*36370Ssklower 	 *	If this is a fragment, then try to reassemble it. If clnp_reass
376*36370Ssklower 	 *	returns non NULL, the packet has been reassembled, and should
377*36370Ssklower 	 *	be give to TP. Otherwise the fragment has been delt with
378*36370Ssklower 	 *	by the reassembly code (either stored or deleted). In either case
379*36370Ssklower 	 *	we should have nothing more to do with it.
380*36370Ssklower 	 */
381*36370Ssklower 	if ((clnp->cnf_type != CLNP_ER) && (clnp->cnf_seg_ok) &&
382*36370Ssklower 		(seg_len != seg_part.cng_tot_len)) {
383*36370Ssklower 		struct mbuf	*m0;
384*36370Ssklower 
385*36370Ssklower 		if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) {
386*36370Ssklower 			m = m0;
387*36370Ssklower 			clnp = mtod(m, struct clnp_fixed *);
388*36370Ssklower 		} else {
389*36370Ssklower 			return;
390*36370Ssklower 		}
391*36370Ssklower 	}
392*36370Ssklower 
393*36370Ssklower 	/*
394*36370Ssklower 	 *	give the packet to the higher layer
395*36370Ssklower 	 *	TODO: how do we tell TP that congestion bit is on in QOS option?
396*36370Ssklower 	 *
397*36370Ssklower 	 *	Note: the total length of packet
398*36370Ssklower 	 *	is the total length field of the segmentation part,
399*36370Ssklower 	 *	or, if absent, the segment length field of the
400*36370Ssklower 	 *	header.
401*36370Ssklower 	 */
402*36370Ssklower 	switch (clnp->cnf_type) {
403*36370Ssklower 	case CLNP_ER:
404*36370Ssklower 		/*
405*36370Ssklower 		 *	This ER must have the er option.
406*36370Ssklower 		 *	If the option is not present, discard datagram.
407*36370Ssklower 		 */
408*36370Ssklower 		if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) {
409*36370Ssklower 			clnp_discard(m, GEN_HDRSYNTAX);
410*36370Ssklower 		} else {
411*36370Ssklower 			clnp_er_input(m, &src, oidxp->cni_er_reason);
412*36370Ssklower 		}
413*36370Ssklower 		break;
414*36370Ssklower 
415*36370Ssklower 	case CLNP_DT:
416*36370Ssklower 		(*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &src, &dst,
417*36370Ssklower 			clnp->cnf_hdr_len);
418*36370Ssklower 		break;
419*36370Ssklower 
420*36370Ssklower  	case CLNP_RAW:
421*36370Ssklower 	case CLNP_ECR:
422*36370Ssklower 		IFDEBUG(D_INPUT)
423*36370Ssklower 			printf("clnp_input: raw input of %d bytes\n",
424*36370Ssklower 				clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len);
425*36370Ssklower 		ENDDEBUG
426*36370Ssklower 		(*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &src, &dst,
427*36370Ssklower 					clnp->cnf_hdr_len);
428*36370Ssklower 		break;
429*36370Ssklower 
430*36370Ssklower 	case CLNP_EC:
431*36370Ssklower 		IFDEBUG(D_INPUT)
432*36370Ssklower 			printf("clnp_input: echoing packet\n");
433*36370Ssklower 		ENDDEBUG
434*36370Ssklower 		/*
435*36370Ssklower 		 *	Switch the source and destination address,
436*36370Ssklower 		 */
437*36370Ssklower 		hoff = (caddr_t)clnp + sizeof(struct clnp_fixed);
438*36370Ssklower 		CLNP_INSERT_ADDR(hoff, &src);
439*36370Ssklower 		CLNP_INSERT_ADDR(hoff, &dst);
440*36370Ssklower 		clnp->cnf_type = CLNP_ECR;
441*36370Ssklower 
442*36370Ssklower 		/*
443*36370Ssklower 		 *	Forward back to sender
444*36370Ssklower 		 */
445*36370Ssklower  		clnp_forward(m, clnp->cnf_seg_ok ? seg_part.cng_tot_len : seg_len,
446*36370Ssklower 			&src, oidxp, seg_off, shp);
447*36370Ssklower 		break;
448*36370Ssklower 
449*36370Ssklower 	default:
450*36370Ssklower  		printf("clnp_input: unknown clnp pkt type %d\n", clnp->cnf_type);
451*36370Ssklower 		clnp_discard(m, GEN_HDRSYNTAX);
452*36370Ssklower  		break;
453*36370Ssklower 	}
454*36370Ssklower }
455*36370Ssklower 
456*36370Ssklower int clnp_ctlinput()
457*36370Ssklower {
458*36370Ssklower }
459*36370Ssklower 
460*36370Ssklower #endif ISO
461