xref: /csrg-svn/sys/netiso/if_eon.c (revision 36382)
1*36382Ssklower /***********************************************************
2*36382Ssklower 		Copyright IBM Corporation 1987
3*36382Ssklower 
4*36382Ssklower                       All Rights Reserved
5*36382Ssklower 
6*36382Ssklower Permission to use, copy, modify, and distribute this software and its
7*36382Ssklower documentation for any purpose and without fee is hereby granted,
8*36382Ssklower provided that the above copyright notice appear in all copies and that
9*36382Ssklower both that copyright notice and this permission notice appear in
10*36382Ssklower supporting documentation, and that the name of IBM not be
11*36382Ssklower used in advertising or publicity pertaining to distribution of the
12*36382Ssklower software without specific, written prior permission.
13*36382Ssklower 
14*36382Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*36382Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*36382Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*36382Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*36382Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*36382Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*36382Ssklower SOFTWARE.
21*36382Ssklower 
22*36382Ssklower ******************************************************************/
23*36382Ssklower 
24*36382Ssklower /*
25*36382Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26*36382Ssklower  */
27*36382Ssklower /*
28*36382Ssklower  * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $
29*36382Ssklower  * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $
30*36382Ssklower  *
31*36382Ssklower  *	EON rfc
32*36382Ssklower  *  Layer between IP and CLNL
33*36382Ssklower  *
34*36382Ssklower  * TODO:
35*36382Ssklower  * Put together a current rfc986 address format and get the right offset
36*36382Ssklower  * for the nsel
37*36382Ssklower  */
38*36382Ssklower #define RFC986_NSEL_OFFSET 5
39*36382Ssklower 
40*36382Ssklower #ifndef lint
41*36382Ssklower static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $";
42*36382Ssklower #endif lint
43*36382Ssklower 
44*36382Ssklower #include "eon.h"
45*36382Ssklower #if NEON>0
46*36382Ssklower 
47*36382Ssklower #include "param.h"
48*36382Ssklower #include "systm.h"
49*36382Ssklower #include "types.h"
50*36382Ssklower #include "mbuf.h"
51*36382Ssklower #include "buf.h"
52*36382Ssklower #include "protosw.h"
53*36382Ssklower #include "socket.h"
54*36382Ssklower #include "ioctl.h"
55*36382Ssklower #include "errno.h"
56*36382Ssklower #include "types.h"
57*36382Ssklower 
58*36382Ssklower #include "../machine/io.h"
59*36382Ssklower #include "../machineio/ioccvar.h"
60*36382Ssklower 
61*36382Ssklower #include "../net/if.h"
62*36382Ssklower #include "../net/netisr.h"
63*36382Ssklower #include "../net/route.h"
64*36382Ssklower 
65*36382Ssklower #include "../netinet/in.h"
66*36382Ssklower #include "../netinet/in_systm.h"
67*36382Ssklower #include "../netinet/ip.h"
68*36382Ssklower #include "../netinet/ip_var.h"
69*36382Ssklower #include "../netinet/if_ether.h"
70*36382Ssklower 
71*36382Ssklower #include "../netiso/iso.h"
72*36382Ssklower #include "../netiso/argo_debug.h"
73*36382Ssklower #include "../netiso/iso_errno.h"
74*36382Ssklower #include "../netiso/eonvar.h"
75*36382Ssklower 
76*36382Ssklower #define EOK 0
77*36382Ssklower 
78*36382Ssklower int						eoninput();
79*36382Ssklower int						eonint();
80*36382Ssklower int						eonoutput();
81*36382Ssklower int						eonioctl();
82*36382Ssklower int						eonprobe();
83*36382Ssklower int						eonattach();
84*36382Ssklower int						eoninit();
85*36382Ssklower extern 	int				ip_output();
86*36382Ssklower struct ifnet			eonif[NEON];
87*36382Ssklower 
88*36382Ssklower #define EON_FAKE_CSR 0
89*36382Ssklower int eon_fakeautoconf[2]; /* need at least 2 ints */
90*36382Ssklower 
91*36382Ssklower caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 };
92*36382Ssklower struct	iocc_device *eoninfo[NEON];
93*36382Ssklower 
94*36382Ssklower struct	iocc_driver eondriver = {
95*36382Ssklower 	eonprobe, 	/* idr_probe */
96*36382Ssklower 	0,			/* idr_slave */
97*36382Ssklower 	eonattach,	/* idr_attach */
98*36382Ssklower 	0,			/* idr_dgo */
99*36382Ssklower 	eonstd,		/* idr_addr - list of standard addresses for device */
100*36382Ssklower 	"eon",		/* idr_dname */
101*36382Ssklower 	eoninfo,	/* idr_dinfo - backptrs to iodinit structs */
102*36382Ssklower 	0,			/* idr_mname - controller name */
103*36382Ssklower 	0,			/* idr_minfo -- backptrs to iominit structs */
104*36382Ssklower 	eonint,		/* idr_intr - interrupt rtn */
105*36382Ssklower 	0,  		/* idr_csr - offset to read/write csr */
106*36382Ssklower 	EON_FAKE_CSR,	 /* idr_chanrelse */
107*36382Ssklower 	0, 			/* idr_flags */
108*36382Ssklower };
109*36382Ssklower 
110*36382Ssklower 
111*36382Ssklower /*
112*36382Ssklower  * entry in the EON address cache (list)
113*36382Ssklower  * (or pt-pt links list, however you view it)
114*36382Ssklower  */
115*36382Ssklower 
116*36382Ssklower struct eon_centry {
117*36382Ssklower 	struct qhdr eonc_q_LINK;
118*36382Ssklower #define eonc_nextLINK eonc_q_LINK.link
119*36382Ssklower #define eonc_prevLINK eonc_q_LINK.flink
120*36382Ssklower 
121*36382Ssklower 	struct qhdr eonc_q_IS;
122*36382Ssklower #define eonc_nextIS eonc_q_IS.link
123*36382Ssklower #define eonc_prevIS eonc_q_IS.flink
124*36382Ssklower 
125*36382Ssklower 	struct qhdr eonc_q_ES;
126*36382Ssklower #define eonc_nextES eonc_q_ES.link
127*36382Ssklower #define eonc_prevES eonc_q_ES.flink
128*36382Ssklower 
129*36382Ssklower 	struct in_addr	eonc_addr;
130*36382Ssklower 	u_short		eonc_status;
131*36382Ssklower };
132*36382Ssklower 
133*36382Ssklower /* kinda like mtod() but for eon_centries */
134*36382Ssklower #define qtocentry(q, off)  ((struct eon_centry *)  (((caddr_t)(q)) - off))
135*36382Ssklower #define centrytoq(c, off)  ((struct qhdr *)  (((caddr_t)(c)) + off))
136*36382Ssklower 
137*36382Ssklower struct qhdr 			eon_LINK_hdr = {
138*36382Ssklower 	(struct qhdr *)0,
139*36382Ssklower 	(struct qhdr *)0,
140*36382Ssklower };
141*36382Ssklower static struct qhdr 		eon_IS_hdr = {
142*36382Ssklower 	(struct qhdr *)0,
143*36382Ssklower 	(struct qhdr *)0,
144*36382Ssklower };
145*36382Ssklower static struct qhdr 		eon_ES_hdr = {
146*36382Ssklower 	(struct qhdr *)0,
147*36382Ssklower 	(struct qhdr *)0,
148*36382Ssklower };
149*36382Ssklower static struct qhdr 		eon_FREE_hdr = {
150*36382Ssklower 	(struct qhdr *)0,
151*36382Ssklower 	(struct qhdr *)0,
152*36382Ssklower };
153*36382Ssklower 
154*36382Ssklower #define INITQ(q)  (q)->rlink = (q)->link = (q)
155*36382Ssklower 
156*36382Ssklower /*
157*36382Ssklower  * FUNCTION:		eon_dumpcache
158*36382Ssklower  *
159*36382Ssklower  * PURPOSE:			dump the cache beginning with the argument given
160*36382Ssklower  *
161*36382Ssklower  * RETURNS:			0
162*36382Ssklower  */
163*36382Ssklower 
164*36382Ssklower eon_dumpcache(which)
165*36382Ssklower 	int 						which;
166*36382Ssklower {
167*36382Ssklower 	register int 				off;
168*36382Ssklower 	register struct eon_centry 	*ent;
169*36382Ssklower 	struct	qhdr				*hdr;
170*36382Ssklower 
171*36382Ssklower 	switch (which) {
172*36382Ssklower 		case E_FREE:
173*36382Ssklower 			printf("FREE LIST\n");
174*36382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_LINK);
175*36382Ssklower 			hdr = &eon_FREE_hdr;
176*36382Ssklower 			ent = qtocentry( hdr->link,
177*36382Ssklower 				_offsetof( struct eon_centry, eonc_q_LINK));
178*36382Ssklower 			break;
179*36382Ssklower 		case E_ES:
180*36382Ssklower 			printf("ES LIST\n");
181*36382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_ES);
182*36382Ssklower 			hdr = &eon_ES_hdr;
183*36382Ssklower 			ent = qtocentry( hdr->link,
184*36382Ssklower 				_offsetof( struct eon_centry, eonc_q_ES));
185*36382Ssklower 			break;
186*36382Ssklower 		case E_IS:
187*36382Ssklower 			printf("IS LIST\n");
188*36382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_IS);
189*36382Ssklower 			hdr = &eon_IS_hdr;
190*36382Ssklower 			ent = qtocentry( hdr->link,
191*36382Ssklower 				_offsetof( struct eon_centry, eonc_q_IS));
192*36382Ssklower 			break;
193*36382Ssklower 		case E_LINK:
194*36382Ssklower 			printf("LINK LIST\n");
195*36382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_LINK);
196*36382Ssklower 			hdr = &eon_LINK_hdr;
197*36382Ssklower 			ent = qtocentry( hdr->link,
198*36382Ssklower 				_offsetof( struct eon_centry, eonc_q_LINK));
199*36382Ssklower 			break;
200*36382Ssklower 	}
201*36382Ssklower 	if(hdr == centrytoq(ent, off)->link )
202*36382Ssklower 		printf("EMPTY\n");
203*36382Ssklower 	else while(1) {
204*36382Ssklower 		printf("0x%x: %d.%d.%d.%d, %s %s\n", ent,
205*36382Ssklower 			(ent->eonc_addr.s_addr>>24)&0xff,
206*36382Ssklower 			(ent->eonc_addr.s_addr>>16)&0xff,
207*36382Ssklower 			(ent->eonc_addr.s_addr>>8)&0xff,
208*36382Ssklower 			(ent->eonc_addr.s_addr)&0xff,
209*36382Ssklower 			((ent->eonc_status & EON_ESLINK_UP)?"ES^":
210*36382Ssklower 				(ent->eonc_status & EON_ESLINK_DOWN)?"es*": "   "),
211*36382Ssklower 			((ent->eonc_status & EON_ISLINK_UP)?"IS^":
212*36382Ssklower 				(ent->eonc_status & EON_ISLINK_DOWN)?"is*": "   ")
213*36382Ssklower 			);
214*36382Ssklower 		dump_buf(ent, sizeof(struct eon_centry) );
215*36382Ssklower 
216*36382Ssklower 		{ 	/* ent = ent.next: */
217*36382Ssklower 			register struct qhdr 	*q;
218*36382Ssklower 
219*36382Ssklower 			q = centrytoq(ent, off)->link;
220*36382Ssklower 			if( q == hdr)
221*36382Ssklower 				break;
222*36382Ssklower 			if( q == (struct qhdr *)0) /* panic */ {
223*36382Ssklower 				printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n",
224*36382Ssklower 					q, ent, off);
225*36382Ssklower 				break;
226*36382Ssklower 			}
227*36382Ssklower 			ent = qtocentry( q,  off );
228*36382Ssklower 		}
229*36382Ssklower 	}
230*36382Ssklower }
231*36382Ssklower /*
232*36382Ssklower  * FUNCTION:		eon_initcache
233*36382Ssklower  *
234*36382Ssklower  * PURPOSE:			allocs a bunch of free cache entries
235*36382Ssklower  *
236*36382Ssklower  * RETURNS:			0
237*36382Ssklower  */
238*36382Ssklower 
239*36382Ssklower eon_initcache()
240*36382Ssklower {
241*36382Ssklower 	static struct eon_centry	eoncache[EON_CACHESIZE];
242*36382Ssklower 	register int 				i;
243*36382Ssklower 	register struct eon_centry 	*ent;
244*36382Ssklower 
245*36382Ssklower 	bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry));
246*36382Ssklower 	INITQ( &eon_FREE_hdr );
247*36382Ssklower 	INITQ( &eon_LINK_hdr );
248*36382Ssklower 	INITQ( &eon_IS_hdr );
249*36382Ssklower 	INITQ( &eon_ES_hdr );
250*36382Ssklower 
251*36382Ssklower 	ent = eoncache;
252*36382Ssklower 
253*36382Ssklower 	for(i=0; i< EON_CACHESIZE; i++,ent++) {
254*36382Ssklower 		_insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)),
255*36382Ssklower 			&eon_FREE_hdr);
256*36382Ssklower 	}
257*36382Ssklower 	printf("eon0: cache initialized\n");
258*36382Ssklower }
259*36382Ssklower 
260*36382Ssklower /*
261*36382Ssklower  * FUNCTION:		eonprobe
262*36382Ssklower  *
263*36382Ssklower  * PURPOSE:			filler for device configuration
264*36382Ssklower  *
265*36382Ssklower  * RETURNS:			PROBE_OK
266*36382Ssklower  */
267*36382Ssklower 
268*36382Ssklower eonprobe()
269*36382Ssklower {
270*36382Ssklower 	extern int	int_level, int_irq;
271*36382Ssklower 
272*36382Ssklower 	printf("eonprobe() \n");
273*36382Ssklower 	int_level = int_irq = 0x3; /* pick something - anything but -1 */
274*36382Ssklower 	return PROBE_OK;
275*36382Ssklower }
276*36382Ssklower 
277*36382Ssklower /*
278*36382Ssklower  * FUNCTION:		eonattach
279*36382Ssklower  *
280*36382Ssklower  * PURPOSE:			autoconf attach routine
281*36382Ssklower  *
282*36382Ssklower  * RETURNS:			void
283*36382Ssklower  */
284*36382Ssklower 
285*36382Ssklower eonattach(iod)
286*36382Ssklower 	register struct iocc_device *iod;
287*36382Ssklower {
288*36382Ssklower 	register struct ifnet *ifp = &eonif[iod->iod_unit];
289*36382Ssklower 
290*36382Ssklower 	IFDEBUG(D_EON)
291*36382Ssklower 		printf("eonattach()\n");
292*36382Ssklower 	ENDDEBUG
293*36382Ssklower 	ifp->if_unit = iod->iod_unit;
294*36382Ssklower 	ifp->if_name = "eon";
295*36382Ssklower 	ifp->if_mtu = ETHERMTU;
296*36382Ssklower 		/* since everything will go out over ether or token ring */
297*36382Ssklower 
298*36382Ssklower 	ifp->if_init = eoninit;
299*36382Ssklower 	ifp->if_ioctl = eonioctl; /* needed? */
300*36382Ssklower 	ifp->if_output = eonoutput;
301*36382Ssklower 	ifp->if_reset = 0;
302*36382Ssklower 	ifp->if_flags = IFF_BROADCAST;
303*36382Ssklower 	if_attach(ifp);
304*36382Ssklower 
305*36382Ssklower 	IFDEBUG(D_EON)
306*36382Ssklower 		printf("eonattach()\n");
307*36382Ssklower 	ENDDEBUG
308*36382Ssklower 	eon_initcache();
309*36382Ssklower 	IFDEBUG(D_EON)
310*36382Ssklower 		printf("eon%d: attached\n", iod->iod_unit);
311*36382Ssklower 	ENDDEBUG
312*36382Ssklower }
313*36382Ssklower 
314*36382Ssklower static struct eon_centry *
315*36382Ssklower find_oldent( ea )
316*36382Ssklower 	struct sockaddr_eon *ea;
317*36382Ssklower {
318*36382Ssklower 	register	int				offset =
319*36382Ssklower 						_offsetof( struct eon_centry, eonc_q_LINK);
320*36382Ssklower 	register struct eon_centry 	*ent = qtocentry(eon_LINK_hdr.link, offset);
321*36382Ssklower 
322*36382Ssklower 	IFDEBUG(D_EON)
323*36382Ssklower 		printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n",
324*36382Ssklower 			(ea->seon_ipaddr>>24)&0xff,
325*36382Ssklower 			(ea->seon_ipaddr>>16)&0xff,
326*36382Ssklower 			(ea->seon_ipaddr>>8)&0xff,
327*36382Ssklower 			(ea->seon_ipaddr)&0xff );
328*36382Ssklower 	ENDDEBUG
329*36382Ssklower 	for (; ent; ent = qtocentry(ent->eonc_nextLINK, offset) ) {
330*36382Ssklower 		if( ent->eonc_addr.s_addr == ea->seon_ipaddr )
331*36382Ssklower 			return ent;
332*36382Ssklower 	}
333*36382Ssklower 	return (struct eon_centry *)0;
334*36382Ssklower }
335*36382Ssklower 
336*36382Ssklower /*
337*36382Ssklower  * FUNCTION:		eonioctl
338*36382Ssklower  *
339*36382Ssklower  * PURPOSE:			io controls - ifconfig
340*36382Ssklower  *				need commands to
341*36382Ssklower  *					link-UP (core addr) (flags: ES, IS)
342*36382Ssklower  *					link-DOWN (core addr) (flags: ES, IS)
343*36382Ssklower  *				must be callable from kernel or user
344*36382Ssklower  *
345*36382Ssklower  * RETURNS:			nothing
346*36382Ssklower  */
347*36382Ssklower eonioctl(ifp, cmd, data)
348*36382Ssklower 	register struct ifnet *ifp;
349*36382Ssklower 	register int cmd;
350*36382Ssklower 	register caddr_t data;
351*36382Ssklower {
352*36382Ssklower 	struct ifreq *ifr = (struct ifreq *)data;
353*36382Ssklower 	register struct sockaddr_eon *eoa =
354*36382Ssklower 				(struct sockaddr_eon *)&(ifr->ifr_addr);
355*36382Ssklower 	register int s = splimp();
356*36382Ssklower 	register int error = 0;
357*36382Ssklower 
358*36382Ssklower 	IFDEBUG(D_EON)
359*36382Ssklower 		printf("eonioctl (cmd 0x%x) \n", cmd);
360*36382Ssklower 	ENDDEBUG
361*36382Ssklower 
362*36382Ssklower 	switch (cmd){
363*36382Ssklower 	case SIOCSIFDSTADDR: {
364*36382Ssklower 			/* add pt-pt link to the set of core addrs */
365*36382Ssklower 			register 	struct eon_centry *ent, *oldent;
366*36382Ssklower 			register	u_short			  which;
367*36382Ssklower 
368*36382Ssklower 			/* "which" tells which lists to put these guys in - don't
369*36382Ssklower 			 * want to insert something in a list if it's already there
370*36382Ssklower 			 */
371*36382Ssklower #define LEGIT_EONADDR(a)\
372*36382Ssklower 	((a->seon_family == AF_ISO) && (a->seon_afi == 0x47) &&\
373*36382Ssklower 	(a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \
374*36382Ssklower 	)
375*36382Ssklower #ifdef notdef
376*36382Ssklower 	/* GET THESE RIGHT AND ADD THEM */
377*36382Ssklower 	&& (a->seon_vers == 3) && (a->seon_adrlen == 0xa)
378*36382Ssklower #endif notdef
379*36382Ssklower 
380*36382Ssklower 			if( ! LEGIT_EONADDR(eoa) ) {
381*36382Ssklower 				error = EADDRNOTAVAIL;
382*36382Ssklower 				break;
383*36382Ssklower 			}
384*36382Ssklower 
385*36382Ssklower 			oldent = find_oldent( eoa );
386*36382Ssklower 			IFDEBUG(D_EON)
387*36382Ssklower 				printf("eonioctl legit seon_status 0x%x oldent %s\n",
388*36382Ssklower 					eoa->seon_status, oldent?"found":"not found");
389*36382Ssklower 			ENDDEBUG
390*36382Ssklower 
391*36382Ssklower 			if( eoa->seon_status & UPBITS ) {
392*36382Ssklower 				if (!oldent) {
393*36382Ssklower 					/* doesn't exist - need to create one */
394*36382Ssklower 					/* TODO : check for null free list */
395*36382Ssklower 					ent = qtocentry(eon_FREE_hdr.link,
396*36382Ssklower 								_offsetof( struct eon_centry, eonc_q_LINK));
397*36382Ssklower 					remque( &(ent->eonc_q_LINK) );
398*36382Ssklower 					ent->eonc_addr.s_addr = eoa->seon_ipaddr;
399*36382Ssklower 					insque( &oldent->eonc_q_LINK, (&eon_LINK_hdr));
400*36382Ssklower 					oldent = ent;
401*36382Ssklower 				}
402*36382Ssklower 
403*36382Ssklower 				which = (eoa->seon_status ^ oldent->eonc_status) &
404*36382Ssklower 					eoa->seon_status & UPBITS;
405*36382Ssklower 
406*36382Ssklower 				oldent->eonc_status |= (eoa->seon_status & UPBITS);
407*36382Ssklower 
408*36382Ssklower 				if( which & EON_ESLINK_UP )
409*36382Ssklower 					insque( &oldent->eonc_q_ES, (&eon_ES_hdr));
410*36382Ssklower 				if( which & EON_ISLINK_UP )
411*36382Ssklower 					insque( &oldent->eonc_q_IS, (&eon_IS_hdr));
412*36382Ssklower 			}
413*36382Ssklower 
414*36382Ssklower 			if( eoa->seon_status & DOWNBITS ) {
415*36382Ssklower 				if(!oldent) {
416*36382Ssklower 					return ENOENT; /* no such entry */
417*36382Ssklower 				}
418*36382Ssklower 				which = (eoa->seon_status ^ oldent->eonc_status) &
419*36382Ssklower 					eoa->seon_status & DOWNBITS;
420*36382Ssklower 
421*36382Ssklower 				oldent->eonc_status |= (eoa->seon_status & DOWNBITS);
422*36382Ssklower 
423*36382Ssklower 				if( which & EON_ESLINK_DOWN )
424*36382Ssklower 					remque( &(oldent->eonc_q_ES) );
425*36382Ssklower 				if( which & EON_ISLINK_DOWN )
426*36382Ssklower 					remque( &(oldent->eonc_q_IS) );
427*36382Ssklower 			}
428*36382Ssklower 
429*36382Ssklower 		IFDEBUG(D_EON)
430*36382Ssklower 			printf("at end status 0x%x\n", oldent->eonc_status);
431*36382Ssklower 		ENDDEBUG
432*36382Ssklower 		break;
433*36382Ssklower 		}
434*36382Ssklower 
435*36382Ssklower 	case SIOCGIFDSTADDR:
436*36382Ssklower 		{
437*36382Ssklower 			register 	struct eon_centry *oldent;
438*36382Ssklower 
439*36382Ssklower 			oldent = find_oldent( eoa );
440*36382Ssklower 			if( oldent == (struct eon_centry *)0 )
441*36382Ssklower 				error = EADDRNOTAVAIL;
442*36382Ssklower 			else
443*36382Ssklower 				eoa->seon_status = oldent->eonc_status;
444*36382Ssklower 		}
445*36382Ssklower 		break;
446*36382Ssklower 
447*36382Ssklower 	case SIOCSIFADDR:
448*36382Ssklower 		ifp->if_flags |= IFF_UP;
449*36382Ssklower 		break;
450*36382Ssklower 
451*36382Ssklower 	case SIOCSIFFLAGS:
452*36382Ssklower 		if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags &
453*36382Ssklower 		  IFF_RUNNING){
454*36382Ssklower 			ifp->if_flags &= ~IFF_RUNNING;
455*36382Ssklower 		} else if (ifp->if_flags & IFF_UP && (ifp->if_flags &
456*36382Ssklower 		  IFF_RUNNING) == 0)
457*36382Ssklower 			eoninit(ifp->if_unit);
458*36382Ssklower 		break;
459*36382Ssklower 	default:
460*36382Ssklower 		error = EINVAL;
461*36382Ssklower 	}
462*36382Ssklower 	splx(s);
463*36382Ssklower 	return(error);
464*36382Ssklower }
465*36382Ssklower 
466*36382Ssklower /*
467*36382Ssklower  * FUNCTION:		eoninit
468*36382Ssklower  *
469*36382Ssklower  * PURPOSE:			initialization
470*36382Ssklower  *
471*36382Ssklower  * RETURNS:			nothing
472*36382Ssklower  */
473*36382Ssklower 
474*36382Ssklower eoninit(unit)
475*36382Ssklower 	int unit;
476*36382Ssklower {
477*36382Ssklower 	printf("eoninit ecn%d\n", unit);
478*36382Ssklower }
479*36382Ssklower 
480*36382Ssklower 
481*36382Ssklower /*
482*36382Ssklower  * FUNCTION:		eonint
483*36382Ssklower  *
484*36382Ssklower  * PURPOSE:			filler for device configuration
485*36382Ssklower  *
486*36382Ssklower  * RETURNS:			nothing
487*36382Ssklower  *
488*36382Ssklower  * NOTES:			*should* never get called - for debugging it's here
489*36382Ssklower  */
490*36382Ssklower 
491*36382Ssklower eonint()
492*36382Ssklower {
493*36382Ssklower 	/* silent - so no more stray interrupt messages from the aed! yay
494*36382Ssklower 	printf("eonint() called - BOGUS INTERRUPT\n");
495*36382Ssklower 	*/
496*36382Ssklower }
497*36382Ssklower 
498*36382Ssklower 
499*36382Ssklower /*
500*36382Ssklower  * FUNCTION:		eonoutput
501*36382Ssklower  *
502*36382Ssklower  * PURPOSE:			prepend an eon header and hand to IP
503*36382Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
504*36382Ssklower  *					(m)  is an mbuf *, *m is a CLNL packet
505*36382Ssklower  *					(dst) is a destination address - have to interp. as
506*36382Ssklower  *					multicast or broadcast or real address.
507*36382Ssklower  *
508*36382Ssklower  * RETURNS:			unix error code
509*36382Ssklower  *
510*36382Ssklower  * NOTES:
511*36382Ssklower  *
512*36382Ssklower  */
513*36382Ssklower eonoutput(ifp, morig, dst)
514*36382Ssklower 	register struct ifnet 	*ifp;
515*36382Ssklower 	register struct mbuf	*morig;		/* packet */
516*36382Ssklower 	struct sockaddr_iso		*dst;		/* destination addr */
517*36382Ssklower {
518*36382Ssklower 	int						s;
519*36382Ssklower 	struct eon_hdr			*eonhdr;
520*36382Ssklower 	struct ip				*iphdr;
521*36382Ssklower 	struct mbuf				*mh;
522*36382Ssklower 	int						error = 0;
523*36382Ssklower 	register int			datalen;
524*36382Ssklower 	caddr_t					dstipaddrloc;
525*36382Ssklower 	int						single=0;
526*36382Ssklower 	int						qoffset=0;
527*36382Ssklower 	register struct eon_centry	*ent;
528*36382Ssklower 	struct qhdr				*q;
529*36382Ssklower 
530*36382Ssklower 	IFDEBUG(D_EON)
531*36382Ssklower 		printf("eonoutput \n" );
532*36382Ssklower 	ENDDEBUG
533*36382Ssklower 
534*36382Ssklower 	if( dst->siso_family != AF_ISO )
535*36382Ssklower 		return EINVAL;
536*36382Ssklower 	if( dst->siso_addr.isoa_afi != AFI_RFC986 )
537*36382Ssklower 		return EINVAL;
538*36382Ssklower 
539*36382Ssklower 	s = splnet();
540*36382Ssklower 
541*36382Ssklower 	/* Nsel tells what type of multicast address, if multicast */
542*36382Ssklower 	switch( dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET]) {
543*36382Ssklower 		case EON_NORMAL_ADDR:
544*36382Ssklower 			IncStat(es_out_normal);
545*36382Ssklower 			dstipaddrloc = (caddr_t)&(dst->siso_addr.rfc986_dsp[1]);
546*36382Ssklower 			single = 1;
547*36382Ssklower 			break;
548*36382Ssklower 
549*36382Ssklower 		case EON_BROADCAST:
550*36382Ssklower 			IncStat(es_out_broad);
551*36382Ssklower 			if( eon_LINK_hdr.link == (struct qhdr *)0 ) {
552*36382Ssklower 				error = EADDRNOTAVAIL;
553*36382Ssklower 			} else {
554*36382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
555*36382Ssklower 				ent = qtocentry(eon_LINK_hdr.link, qoffset);
556*36382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
557*36382Ssklower 			}
558*36382Ssklower 			break;
559*36382Ssklower 		case EON_MULTICAST_ES:
560*36382Ssklower 			IncStat(es_out_multi_es);
561*36382Ssklower 			if( eon_ES_hdr.link == (struct qhdr *)0 ) {
562*36382Ssklower 				error = EADDRNOTAVAIL;
563*36382Ssklower 			} else {
564*36382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_ES);
565*36382Ssklower 				ent = qtocentry(eon_ES_hdr.link, qoffset);
566*36382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
567*36382Ssklower 			}
568*36382Ssklower 			break;
569*36382Ssklower 		case EON_MULTICAST_IS:
570*36382Ssklower 			IncStat(es_out_multi_is);
571*36382Ssklower 			if( eon_IS_hdr.link == (struct qhdr *)0 ) {
572*36382Ssklower 				error = EADDRNOTAVAIL;
573*36382Ssklower 			} else {
574*36382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
575*36382Ssklower 				ent = qtocentry(eon_IS_hdr.link, qoffset);
576*36382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
577*36382Ssklower 			}
578*36382Ssklower 			break;
579*36382Ssklower 		default:
580*36382Ssklower 			printf("NSEL bad value; treated as EON_NORMAL_ADDR\n");
581*36382Ssklower 			dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET] = EON_NORMAL_ADDR;
582*36382Ssklower 			single = 1;
583*36382Ssklower 			break;
584*36382Ssklower 	}
585*36382Ssklower 	if( error )
586*36382Ssklower 		goto done;
587*36382Ssklower 
588*36382Ssklower 	/* get data length -- needed later */
589*36382Ssklower 	datalen = m_datalen( morig );
590*36382Ssklower 	IFDEBUG(D_EON)
591*36382Ssklower 		printf("eonoutput : m_datalen returns %d\n", datalen);
592*36382Ssklower 	ENDDEBUG
593*36382Ssklower 
594*36382Ssklower 	mh = m_getclr( M_DONTWAIT, MT_HEADER);
595*36382Ssklower 	if(mh == (struct mbuf *)0) {
596*36382Ssklower 		goto done;
597*36382Ssklower 	}
598*36382Ssklower 
599*36382Ssklower 	/* put an eon_hdr in the buffer, prepended by an ip header */
600*36382Ssklower 	mh->m_act = (struct mbuf *)0;
601*36382Ssklower 	mh->m_len = sizeof(struct eon_hdr);
602*36382Ssklower 	mh->m_off = MMAXOFF - sizeof(struct eon_hdr);
603*36382Ssklower 	mh->m_next = morig;
604*36382Ssklower 	eonhdr = mtod(mh, struct eon_hdr *);
605*36382Ssklower 	eonhdr->eonh_class =
606*36382Ssklower 		dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET];
607*36382Ssklower 	eonhdr->eonh_vers = EON_VERSION;
608*36382Ssklower 
609*36382Ssklower 	IFDEBUG(D_EON)
610*36382Ssklower 		printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
611*36382Ssklower 			mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
612*36382Ssklower 	ENDDEBUG
613*36382Ssklower 	iso_gen_csum(mh,
614*36382Ssklower 		_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
615*36382Ssklower 
616*36382Ssklower 	mh->m_len += sizeof(struct ip);
617*36382Ssklower 	mh->m_off -= sizeof(struct ip);
618*36382Ssklower 	iphdr = mtod(mh, struct ip *);
619*36382Ssklower 
620*36382Ssklower 	iphdr->ip_p = IPPROTO_EON;
621*36382Ssklower 	iphdr->ip_len = (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen);
622*36382Ssklower 	iphdr->ip_ttl = MAXTTL;
623*36382Ssklower 	iphdr->ip_src.s_addr = INADDR_ANY;
624*36382Ssklower 
625*36382Ssklower 	IFDEBUG(D_EON)
626*36382Ssklower 		printf("eonoutput : after gen csum: ip_len %d/0x%x\n",
627*36382Ssklower 			(sizeof(struct eon_hdr) + sizeof(struct ip) + datalen),
628*36382Ssklower 			(sizeof(struct eon_hdr) + sizeof(struct ip) + datalen)
629*36382Ssklower 			);
630*36382Ssklower 	ENDDEBUG
631*36382Ssklower 
632*36382Ssklower 	morig = mh;
633*36382Ssklower 
634*36382Ssklower 	for(;;) {
635*36382Ssklower 
636*36382Ssklower 		if( !single ) {
637*36382Ssklower 			/* make a copy to send */
638*36382Ssklower 			IFDEBUG(D_EON)
639*36382Ssklower 				printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n",
640*36382Ssklower 					morig, iphdr->ip_len);
641*36382Ssklower 			ENDDEBUG
642*36382Ssklower 			mh = m_copy(morig, 0, iphdr->ip_len);
643*36382Ssklower 			mh = m_pullup(mh, sizeof(struct ip));
644*36382Ssklower 			iphdr = mtod(mh, struct ip *);
645*36382Ssklower 		}
646*36382Ssklower 		IFDEBUG(D_EON)
647*36382Ssklower 			printf("eonoutput : bcopy 0x%x to 0x%x length %d\n",
648*36382Ssklower 				dstipaddrloc,
649*36382Ssklower 				(caddr_t)&(iphdr->ip_dst.s_addr),
650*36382Ssklower 				sizeof(iphdr->ip_dst.s_addr));
651*36382Ssklower 		ENDDEBUG
652*36382Ssklower 		bcopy(
653*36382Ssklower 			dstipaddrloc,
654*36382Ssklower 			(caddr_t)&(iphdr->ip_dst.s_addr), sizeof(iphdr->ip_dst.s_addr));
655*36382Ssklower 		IFDEBUG(D_EON)
656*36382Ssklower 			printf("eonoutput : dst ip addr : %d.%d.%d.%d",
657*36382Ssklower 				(iphdr->ip_dst.s_addr>>24)&0xff,
658*36382Ssklower 				(iphdr->ip_dst.s_addr>>16)&0xff,
659*36382Ssklower 				(iphdr->ip_dst.s_addr>>8)&0xff,
660*36382Ssklower 				(iphdr->ip_dst.s_addr)&0xff );
661*36382Ssklower 		ENDDEBUG
662*36382Ssklower 
663*36382Ssklower 		IFDEBUG(D_EON)
664*36382Ssklower 			printf("eonoutput ip_output : eon header:\n");
665*36382Ssklower 			dump_buf(eonhdr, sizeof(struct eon_hdr));
666*36382Ssklower 			printf("ip header:\n");
667*36382Ssklower 			dump_buf(iphdr, sizeof(struct ip));
668*36382Ssklower 		ENDDEBUG
669*36382Ssklower 
670*36382Ssklower 		IncStat(es_ipout);
671*36382Ssklower 		if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) )
672*36382Ssklower 				break;
673*36382Ssklower 
674*36382Ssklower 		IFDEBUG(D_EON)
675*36382Ssklower 			printf("eonoutput ip_output returns 0x%x; single %d\n",
676*36382Ssklower 				error, single);
677*36382Ssklower 		ENDDEBUG
678*36382Ssklower 
679*36382Ssklower 		if(single)
680*36382Ssklower 			break;
681*36382Ssklower 
682*36382Ssklower 		q = centrytoq(ent, qoffset)->link;
683*36382Ssklower 		if( q == (struct qhdr *)0)
684*36382Ssklower 			break;
685*36382Ssklower 		ent = qtocentry( q,  qoffset );
686*36382Ssklower 		IFDEBUG(D_EON)
687*36382Ssklower 			printf("eonoutput : get next entry: 0x%x\n", ent);
688*36382Ssklower 		ENDDEBUG
689*36382Ssklower 		dstipaddrloc = (caddr_t) &(ent->eonc_addr);
690*36382Ssklower 		IFDEBUG(D_EON)
691*36382Ssklower 			printf("eonoutput : dump of eon_centry 0x%x:\n", ent );
692*36382Ssklower 			dump_buf(ent, sizeof(struct eon_centry) );
693*36382Ssklower 		ENDDEBUG
694*36382Ssklower 	}
695*36382Ssklower done:
696*36382Ssklower 	if( !single ) {
697*36382Ssklower 		IFDEBUG(D_EON)
698*36382Ssklower 			printf("eonoutput : freeing morig 0x%x\n", morig);
699*36382Ssklower 		ENDDEBUG
700*36382Ssklower 		m_freem(morig);
701*36382Ssklower 	}
702*36382Ssklower 	splx(s);
703*36382Ssklower 	return error;
704*36382Ssklower }
705*36382Ssklower 
706*36382Ssklower eoninput(m, ifp)
707*36382Ssklower 	register struct mbuf	*m;
708*36382Ssklower 	struct ifnet 			*ifp; /* real ifp */
709*36382Ssklower {
710*36382Ssklower 	int						s;
711*36382Ssklower 	register struct eon_hdr	*eonhdr;
712*36382Ssklower 	register struct ip		*iphdr;
713*36382Ssklower 	struct ifnet 			*eonifp;
714*36382Ssklower 	register	int			datalen;
715*36382Ssklower 
716*36382Ssklower 	s = splnet();
717*36382Ssklower 
718*36382Ssklower 	eonifp = &eonif[0]; /* kludge - really want to give CLNP
719*36382Ssklower 						* the ifp for eon, not for the real device
720*36382Ssklower 						*/
721*36382Ssklower 
722*36382Ssklower 	IFDEBUG(D_EON)
723*36382Ssklower 		printf("eoninput() 0x%x m_off 0x%x m_len 0x%x dequeued\n",
724*36382Ssklower 			m, m?m->m_off:0, m?m->m_len:0);
725*36382Ssklower 	ENDDEBUG
726*36382Ssklower 
727*36382Ssklower 	if (m == 0) {
728*36382Ssklower 		goto drop;
729*36382Ssklower 	}
730*36382Ssklower 	m = m_pullup(m, (sizeof(struct eon_hdr)+sizeof(struct ip)));
731*36382Ssklower 	if (m == 0) {
732*36382Ssklower 		IncStat(es_badhdr);
733*36382Ssklower 		goto drop;
734*36382Ssklower 	}
735*36382Ssklower 
736*36382Ssklower 	iphdr = mtod(m, struct ip *);
737*36382Ssklower 
738*36382Ssklower 	/* do a few checks for debugging */
739*36382Ssklower 	if( iphdr->ip_p != IPPROTO_EON ) {
740*36382Ssklower 		IncStat(es_badhdr);
741*36382Ssklower 		goto drop;
742*36382Ssklower 	}
743*36382Ssklower 
744*36382Ssklower 	/* drop ip header from the mbuf */
745*36382Ssklower 	m->m_len -= sizeof(struct ip);
746*36382Ssklower 	m->m_off += sizeof(struct ip);
747*36382Ssklower 
748*36382Ssklower 	eonhdr = mtod(m, struct eon_hdr *);
749*36382Ssklower 
750*36382Ssklower 	IFDEBUG(D_EON)
751*36382Ssklower 		printf("eoninput: eon header:\n");
752*36382Ssklower 		dump_buf(eonhdr, sizeof(struct eon_hdr));
753*36382Ssklower 	ENDDEBUG
754*36382Ssklower 
755*36382Ssklower 	/* checks for debugging */
756*36382Ssklower 	if( eonhdr->eonh_vers != EON_VERSION) {
757*36382Ssklower 		IncStat(es_badhdr);
758*36382Ssklower 		goto drop;
759*36382Ssklower 	}
760*36382Ssklower 
761*36382Ssklower 	datalen = m_datalen( m );
762*36382Ssklower 	if( iso_check_csum( m, sizeof(struct eon_hdr) )   != EOK ) {
763*36382Ssklower 		IncStat(es_badcsum);
764*36382Ssklower 		goto drop;
765*36382Ssklower 	}
766*36382Ssklower 
767*36382Ssklower 	IFDEBUG(D_EON)
768*36382Ssklower 		printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
769*36382Ssklower 	ENDDEBUG
770*36382Ssklower 	switch( eonhdr->eonh_class) {
771*36382Ssklower 		case EON_BROADCAST:
772*36382Ssklower 			IncStat(es_in_broad);
773*36382Ssklower 			break;
774*36382Ssklower 		case EON_NORMAL_ADDR:
775*36382Ssklower 			IncStat(es_in_normal);
776*36382Ssklower 			break;
777*36382Ssklower 		case EON_MULTICAST_ES:
778*36382Ssklower 			if( ( eonifp->if_flags & IFF_ES) == 0 )
779*36382Ssklower 				goto drop;
780*36382Ssklower 			IncStat(es_in_multi_es);
781*36382Ssklower 			break;
782*36382Ssklower 		case EON_MULTICAST_IS:
783*36382Ssklower 			if( ( eonifp->if_flags & IFF_IS) == 0 )
784*36382Ssklower 				goto drop;
785*36382Ssklower 			IncStat(es_in_multi_is);
786*36382Ssklower 			break;
787*36382Ssklower 	}
788*36382Ssklower 	eonifp->if_ipackets ++;
789*36382Ssklower 
790*36382Ssklower 	/* drop eonhdr from the mbuf */
791*36382Ssklower 	m->m_len -= sizeof(struct eon_hdr);
792*36382Ssklower 	m->m_off += sizeof(struct eon_hdr);
793*36382Ssklower 
794*36382Ssklower 	{
795*36382Ssklower 		/* put it on the CLNP queue and set soft interrupt */
796*36382Ssklower 		struct ifqueue 			*ifq;
797*36382Ssklower 		extern struct ifqueue 	clnlintrq;
798*36382Ssklower 		int						len;
799*36382Ssklower 
800*36382Ssklower 		/* when acting as a subnet service, have to prepend a
801*36382Ssklower 		 * pointer to the ifnet before handing this to clnp (GAG)
802*36382Ssklower 		 */
803*36382Ssklower 		len = sizeof(struct snpa_hdr);
804*36382Ssklower 		if( ( m->m_off > MMINOFF + len) &&
805*36382Ssklower 			( m->m_off <= MMAXOFF )) {
806*36382Ssklower 			m->m_off -= len;
807*36382Ssklower 			m->m_len += len;
808*36382Ssklower 		}
809*36382Ssklower 		( mtod(m, struct snpa_hdr *) )->snh_ifp = eonifp; /* KLUDGE */
810*36382Ssklower 
811*36382Ssklower 		/* this is cutting it close */
812*36382Ssklower 		bcopy( &iphdr->ip_src, ( mtod(m, struct snpa_hdr *))->snh_shost,
813*36382Ssklower 			sizeof(struct in_addr));
814*36382Ssklower 		bcopy( &iphdr->ip_dst, ( mtod(m, struct snpa_hdr *))->snh_dhost,
815*36382Ssklower 			sizeof(struct in_addr));
816*36382Ssklower 
817*36382Ssklower 		IFDEBUG(D_EON)
818*36382Ssklower 			printf("eoninput to clnl IFQ\n");
819*36382Ssklower 		ENDDEBUG
820*36382Ssklower 		ifq = &clnlintrq;
821*36382Ssklower 		splimp();
822*36382Ssklower 		if (IF_QFULL(ifq)) {
823*36382Ssklower 			IF_DROP(ifq);
824*36382Ssklower 			m_freem(m);
825*36382Ssklower 			splx(s);
826*36382Ssklower 			eonifp->if_ierrors ++;
827*36382Ssklower 			return;
828*36382Ssklower 		}
829*36382Ssklower 		IF_ENQUEUE(ifq, m);
830*36382Ssklower 		IFDEBUG(D_EON)
831*36382Ssklower 			printf(
832*36382Ssklower 	"0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_off 0x%x\n",
833*36382Ssklower 				m, m->m_len, m->m_type, m->m_off);
834*36382Ssklower 			dump_buf(mtod(m, caddr_t), m->m_len);
835*36382Ssklower 		ENDDEBUG
836*36382Ssklower 		schednetisr(NETISR_CLNP);
837*36382Ssklower 	}
838*36382Ssklower done:
839*36382Ssklower 	splx(s);
840*36382Ssklower 	return 0;
841*36382Ssklower drop:
842*36382Ssklower 	IFDEBUG(D_EON)
843*36382Ssklower 		printf("eoninput: DROP \n" );
844*36382Ssklower 	ENDDEBUG
845*36382Ssklower 	eonifp->if_ierrors ++;
846*36382Ssklower 	m_freem(m);
847*36382Ssklower 	goto done;
848*36382Ssklower }
849*36382Ssklower 
850*36382Ssklower int
851*36382Ssklower eonctlinput(cmd, sin)
852*36382Ssklower 	int cmd;
853*36382Ssklower 	struct sockaddr_in *sin;
854*36382Ssklower {
855*36382Ssklower 	extern u_char inetctlerrmap[];
856*36382Ssklower 
857*36382Ssklower 	IFDEBUG(D_EON)
858*36382Ssklower 		printf("eonctlinput: cmd 0x%x addr: ", cmd);
859*36382Ssklower 		dump_isoaddr(sin);
860*36382Ssklower 		printf("\n");
861*36382Ssklower 	ENDDEBUG
862*36382Ssklower 
863*36382Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
864*36382Ssklower 		return 0;
865*36382Ssklower 
866*36382Ssklower 	IncStat(es_icmp[cmd]);
867*36382Ssklower 	switch (cmd) {
868*36382Ssklower 
869*36382Ssklower 		case	PRC_QUENCH2:
870*36382Ssklower 		case	PRC_QUENCH:
871*36382Ssklower 			/* TODO: set the dec bit */
872*36382Ssklower 			break;
873*36382Ssklower 		case	PRC_TIMXCEED_REASS:
874*36382Ssklower 		case	PRC_ROUTEDEAD:
875*36382Ssklower 		case	PRC_HOSTUNREACH:
876*36382Ssklower 		case	PRC_UNREACH_NET:
877*36382Ssklower 		case	PRC_IFDOWN:
878*36382Ssklower 		case	PRC_UNREACH_HOST:
879*36382Ssklower 		case	PRC_HOSTDEAD:
880*36382Ssklower 		case	PRC_TIMXCEED_INTRANS:
881*36382Ssklower 			/* TODO: mark the link down */
882*36382Ssklower 			break;
883*36382Ssklower 
884*36382Ssklower 		case	PRC_UNREACH_PROTOCOL:
885*36382Ssklower 		case	PRC_UNREACH_PORT:
886*36382Ssklower 		case	PRC_UNREACH_NEEDFRAG:
887*36382Ssklower 		case	PRC_UNREACH_SRCFAIL:
888*36382Ssklower 		case	PRC_REDIRECT_NET:
889*36382Ssklower 		case	PRC_REDIRECT_HOST:
890*36382Ssklower 		case	PRC_REDIRECT_TOSNET:
891*36382Ssklower 		case	PRC_REDIRECT_TOSHOST:
892*36382Ssklower 		case	PRC_MSGSIZE:
893*36382Ssklower 		case	PRC_PARAMPROB:
894*36382Ssklower 			printf("eonctlinput: ICMP cmd 0x%x\n", cmd );
895*36382Ssklower 		break;
896*36382Ssklower 	}
897*36382Ssklower 	return 0;
898*36382Ssklower }
899*36382Ssklower 
900*36382Ssklower #endif NEON>0
901