xref: /csrg-svn/sys/netiso/if_eon.c (revision 37518)
136382Ssklower /***********************************************************
236382Ssklower 		Copyright IBM Corporation 1987
336382Ssklower 
436382Ssklower                       All Rights Reserved
536382Ssklower 
636382Ssklower Permission to use, copy, modify, and distribute this software and its
736382Ssklower documentation for any purpose and without fee is hereby granted,
836382Ssklower provided that the above copyright notice appear in all copies and that
936382Ssklower both that copyright notice and this permission notice appear in
1036382Ssklower supporting documentation, and that the name of IBM not be
1136382Ssklower used in advertising or publicity pertaining to distribution of the
1236382Ssklower software without specific, written prior permission.
1336382Ssklower 
1436382Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536382Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636382Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736382Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836382Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936382Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036382Ssklower SOFTWARE.
2136382Ssklower 
2236382Ssklower ******************************************************************/
2336382Ssklower 
2436382Ssklower /*
2536382Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636382Ssklower  */
2736382Ssklower /*
2836382Ssklower  * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $
2936382Ssklower  * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $
3036382Ssklower  *
3136382Ssklower  *	EON rfc
3236382Ssklower  *  Layer between IP and CLNL
3336382Ssklower  *
3436382Ssklower  * TODO:
3536382Ssklower  * Put together a current rfc986 address format and get the right offset
3636382Ssklower  * for the nsel
3736382Ssklower  */
3836382Ssklower 
3936382Ssklower #ifndef lint
4036382Ssklower static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $";
4136382Ssklower #endif lint
4236382Ssklower 
4337469Ssklower #ifdef EON
4437469Ssklower #define NEON 1
4536382Ssklower 
4637469Ssklower 
4736382Ssklower #include "param.h"
4836382Ssklower #include "systm.h"
4936382Ssklower #include "types.h"
5036382Ssklower #include "mbuf.h"
5136382Ssklower #include "buf.h"
5236382Ssklower #include "protosw.h"
5336382Ssklower #include "socket.h"
5436382Ssklower #include "ioctl.h"
5536382Ssklower #include "errno.h"
5636382Ssklower #include "types.h"
5736382Ssklower 
5836382Ssklower #include "../net/if.h"
5937469Ssklower #include "../net/iftypes.h"
6036382Ssklower #include "../net/netisr.h"
6136382Ssklower #include "../net/route.h"
62*37518Smckusick #include "machine/mtpr.h"
6336382Ssklower 
6436382Ssklower #include "../netinet/in.h"
6536382Ssklower #include "../netinet/in_systm.h"
6636382Ssklower #include "../netinet/ip.h"
6736382Ssklower #include "../netinet/ip_var.h"
6836382Ssklower #include "../netinet/if_ether.h"
6936382Ssklower 
7037469Ssklower #include "iso.h"
7137469Ssklower #include "iso_var.h"
7237469Ssklower #include "iso_snpac.h"
7337469Ssklower extern struct snpa_cache all_es, all_is;
7437469Ssklower #include "argo_debug.h"
7537469Ssklower #include "iso_errno.h"
7637469Ssklower #include "eonvar.h"
7736382Ssklower 
7836382Ssklower #define EOK 0
7936382Ssklower 
8036382Ssklower int						eoninput();
8136382Ssklower int						eonint();
8236382Ssklower int						eonoutput();
8336382Ssklower int						eonioctl();
8436382Ssklower int						eonprobe();
8536382Ssklower int						eonattach();
8636382Ssklower int						eoninit();
8736382Ssklower extern 	int				ip_output();
8836382Ssklower struct ifnet			eonif[NEON];
8936382Ssklower 
9037469Ssklower #ifdef FAKEIOCCDEV
91*37518Smckusick #include "machine/io.h"
9237469Ssklower #include "../machineio/ioccvar.h"
9337469Ssklower 
9436382Ssklower #define EON_FAKE_CSR 0
9536382Ssklower int eon_fakeautoconf[2]; /* need at least 2 ints */
9636382Ssklower 
9736382Ssklower caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 };
9836382Ssklower struct	iocc_device *eoninfo[NEON];
9936382Ssklower 
10036382Ssklower struct	iocc_driver eondriver = {
10136382Ssklower 	eonprobe, 	/* idr_probe */
10236382Ssklower 	0,			/* idr_slave */
10336382Ssklower 	eonattach,	/* idr_attach */
10436382Ssklower 	0,			/* idr_dgo */
10536382Ssklower 	eonstd,		/* idr_addr - list of standard addresses for device */
10636382Ssklower 	"eon",		/* idr_dname */
10736382Ssklower 	eoninfo,	/* idr_dinfo - backptrs to iodinit structs */
10836382Ssklower 	0,			/* idr_mname - controller name */
10936382Ssklower 	0,			/* idr_minfo -- backptrs to iominit structs */
11036382Ssklower 	eonint,		/* idr_intr - interrupt rtn */
11136382Ssklower 	0,  		/* idr_csr - offset to read/write csr */
11236382Ssklower 	EON_FAKE_CSR,	 /* idr_chanrelse */
11336382Ssklower 	0, 			/* idr_flags */
11436382Ssklower };
11537469Ssklower #else
11637469Ssklower struct iocc_device {
11737469Ssklower 	int iod_unit;
11837469Ssklower } bsd_iocc_fakeout;
11936382Ssklower 
12037469Ssklower eonprotoinit() {
12137469Ssklower 	(void) eonprobe();
12237469Ssklower 	(void) eonattach(&bsd_iocc_fakeout);
12337469Ssklower }
12437469Ssklower #define PROBE_OK 0;
12537469Ssklower #endif
12636382Ssklower 
12737469Ssklower 
12836382Ssklower /*
12936382Ssklower  * entry in the EON address cache (list)
13036382Ssklower  * (or pt-pt links list, however you view it)
13136382Ssklower  */
13236382Ssklower 
13336382Ssklower struct eon_centry {
13436382Ssklower 	struct qhdr eonc_q_LINK;
13536382Ssklower #define eonc_nextLINK eonc_q_LINK.link
13636382Ssklower #define eonc_prevLINK eonc_q_LINK.flink
13736382Ssklower 
13836382Ssklower 	struct qhdr eonc_q_IS;
13936382Ssklower #define eonc_nextIS eonc_q_IS.link
14036382Ssklower #define eonc_prevIS eonc_q_IS.flink
14136382Ssklower 
14236382Ssklower 	struct qhdr eonc_q_ES;
14336382Ssklower #define eonc_nextES eonc_q_ES.link
14436382Ssklower #define eonc_prevES eonc_q_ES.flink
14536382Ssklower 
14636382Ssklower 	struct in_addr	eonc_addr;
14736382Ssklower 	u_short		eonc_status;
14836382Ssklower };
14936382Ssklower 
15036382Ssklower /* kinda like mtod() but for eon_centries */
15136382Ssklower #define qtocentry(q, off)  ((struct eon_centry *)  (((caddr_t)(q)) - off))
15236382Ssklower #define centrytoq(c, off)  ((struct qhdr *)  (((caddr_t)(c)) + off))
15336382Ssklower 
15436382Ssklower struct qhdr 			eon_LINK_hdr = {
15536382Ssklower 	(struct qhdr *)0,
15636382Ssklower 	(struct qhdr *)0,
15736382Ssklower };
15836382Ssklower static struct qhdr 		eon_IS_hdr = {
15936382Ssklower 	(struct qhdr *)0,
16036382Ssklower 	(struct qhdr *)0,
16136382Ssklower };
16236382Ssklower static struct qhdr 		eon_ES_hdr = {
16336382Ssklower 	(struct qhdr *)0,
16436382Ssklower 	(struct qhdr *)0,
16536382Ssklower };
16636382Ssklower static struct qhdr 		eon_FREE_hdr = {
16736382Ssklower 	(struct qhdr *)0,
16836382Ssklower 	(struct qhdr *)0,
16936382Ssklower };
17036382Ssklower 
17136382Ssklower #define INITQ(q)  (q)->rlink = (q)->link = (q)
17236382Ssklower 
17336382Ssklower /*
17436382Ssklower  * FUNCTION:		eon_dumpcache
17536382Ssklower  *
17636382Ssklower  * PURPOSE:			dump the cache beginning with the argument given
17736382Ssklower  *
17836382Ssklower  * RETURNS:			0
17936382Ssklower  */
18036382Ssklower 
18136382Ssklower eon_dumpcache(which)
18236382Ssklower 	int 						which;
18336382Ssklower {
18436382Ssklower 	register int 				off;
18536382Ssklower 	register struct eon_centry 	*ent;
18636382Ssklower 	struct	qhdr				*hdr;
18736382Ssklower 
18836382Ssklower 	switch (which) {
18936382Ssklower 		case E_FREE:
19036382Ssklower 			printf("FREE LIST\n");
19136382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_LINK);
19236382Ssklower 			hdr = &eon_FREE_hdr;
19336382Ssklower 			ent = qtocentry( hdr->link,
19436382Ssklower 				_offsetof( struct eon_centry, eonc_q_LINK));
19536382Ssklower 			break;
19636382Ssklower 		case E_ES:
19736382Ssklower 			printf("ES LIST\n");
19836382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_ES);
19936382Ssklower 			hdr = &eon_ES_hdr;
20036382Ssklower 			ent = qtocentry( hdr->link,
20136382Ssklower 				_offsetof( struct eon_centry, eonc_q_ES));
20236382Ssklower 			break;
20336382Ssklower 		case E_IS:
20436382Ssklower 			printf("IS LIST\n");
20536382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_IS);
20636382Ssklower 			hdr = &eon_IS_hdr;
20736382Ssklower 			ent = qtocentry( hdr->link,
20836382Ssklower 				_offsetof( struct eon_centry, eonc_q_IS));
20936382Ssklower 			break;
21036382Ssklower 		case E_LINK:
21136382Ssklower 			printf("LINK LIST\n");
21236382Ssklower 			off = _offsetof( struct eon_centry, eonc_q_LINK);
21336382Ssklower 			hdr = &eon_LINK_hdr;
21436382Ssklower 			ent = qtocentry( hdr->link,
21536382Ssklower 				_offsetof( struct eon_centry, eonc_q_LINK));
21636382Ssklower 			break;
21736382Ssklower 	}
21836382Ssklower 	if(hdr == centrytoq(ent, off)->link )
21936382Ssklower 		printf("EMPTY\n");
22036382Ssklower 	else while(1) {
22136382Ssklower 		printf("0x%x: %d.%d.%d.%d, %s %s\n", ent,
22236382Ssklower 			(ent->eonc_addr.s_addr>>24)&0xff,
22336382Ssklower 			(ent->eonc_addr.s_addr>>16)&0xff,
22436382Ssklower 			(ent->eonc_addr.s_addr>>8)&0xff,
22536382Ssklower 			(ent->eonc_addr.s_addr)&0xff,
22636382Ssklower 			((ent->eonc_status & EON_ESLINK_UP)?"ES^":
22736382Ssklower 				(ent->eonc_status & EON_ESLINK_DOWN)?"es*": "   "),
22836382Ssklower 			((ent->eonc_status & EON_ISLINK_UP)?"IS^":
22936382Ssklower 				(ent->eonc_status & EON_ISLINK_DOWN)?"is*": "   ")
23036382Ssklower 			);
23136382Ssklower 		dump_buf(ent, sizeof(struct eon_centry) );
23236382Ssklower 
23336382Ssklower 		{ 	/* ent = ent.next: */
23436382Ssklower 			register struct qhdr 	*q;
23536382Ssklower 
23636382Ssklower 			q = centrytoq(ent, off)->link;
23736382Ssklower 			if( q == hdr)
23836382Ssklower 				break;
23936382Ssklower 			if( q == (struct qhdr *)0) /* panic */ {
24036382Ssklower 				printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n",
24136382Ssklower 					q, ent, off);
24236382Ssklower 				break;
24336382Ssklower 			}
24436382Ssklower 			ent = qtocentry( q,  off );
24536382Ssklower 		}
24636382Ssklower 	}
24736382Ssklower }
24836382Ssklower /*
24936382Ssklower  * FUNCTION:		eon_initcache
25036382Ssklower  *
25136382Ssklower  * PURPOSE:			allocs a bunch of free cache entries
25236382Ssklower  *
25336382Ssklower  * RETURNS:			0
25436382Ssklower  */
25536382Ssklower 
25636382Ssklower eon_initcache()
25736382Ssklower {
25836382Ssklower 	static struct eon_centry	eoncache[EON_CACHESIZE];
25936382Ssklower 	register int 				i;
26036382Ssklower 	register struct eon_centry 	*ent;
26136382Ssklower 
26236382Ssklower 	bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry));
26336382Ssklower 	INITQ( &eon_FREE_hdr );
26436382Ssklower 	INITQ( &eon_LINK_hdr );
26536382Ssklower 	INITQ( &eon_IS_hdr );
26636382Ssklower 	INITQ( &eon_ES_hdr );
26736382Ssklower 
26836382Ssklower 	ent = eoncache;
26936382Ssklower 
27036382Ssklower 	for(i=0; i< EON_CACHESIZE; i++,ent++) {
27136382Ssklower 		_insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)),
27236382Ssklower 			&eon_FREE_hdr);
27336382Ssklower 	}
27436382Ssklower 	printf("eon0: cache initialized\n");
27536382Ssklower }
27636382Ssklower 
27736382Ssklower /*
27836382Ssklower  * FUNCTION:		eonprobe
27936382Ssklower  *
28036382Ssklower  * PURPOSE:			filler for device configuration
28136382Ssklower  *
28236382Ssklower  * RETURNS:			PROBE_OK
28336382Ssklower  */
28436382Ssklower 
28537469Ssklower int int_level, int_irq;
28636382Ssklower eonprobe()
28736382Ssklower {
28836382Ssklower 	extern int	int_level, int_irq;
28936382Ssklower 
29036382Ssklower 	printf("eonprobe() \n");
29136382Ssklower 	int_level = int_irq = 0x3; /* pick something - anything but -1 */
29236382Ssklower 	return PROBE_OK;
29336382Ssklower }
29436382Ssklower 
29536382Ssklower /*
29636382Ssklower  * FUNCTION:		eonattach
29736382Ssklower  *
29836382Ssklower  * PURPOSE:			autoconf attach routine
29936382Ssklower  *
30036382Ssklower  * RETURNS:			void
30136382Ssklower  */
30236382Ssklower 
30336382Ssklower eonattach(iod)
30436382Ssklower 	register struct iocc_device *iod;
30536382Ssklower {
30636382Ssklower 	register struct ifnet *ifp = &eonif[iod->iod_unit];
30736382Ssklower 
30836382Ssklower 	IFDEBUG(D_EON)
30936382Ssklower 		printf("eonattach()\n");
31036382Ssklower 	ENDDEBUG
31136382Ssklower 	ifp->if_unit = iod->iod_unit;
31236382Ssklower 	ifp->if_name = "eon";
31336382Ssklower 	ifp->if_mtu = ETHERMTU;
31436382Ssklower 		/* since everything will go out over ether or token ring */
31536382Ssklower 
31636382Ssklower 	ifp->if_init = eoninit;
31737469Ssklower 	ifp->if_ioctl = eonioctl;
31836382Ssklower 	ifp->if_output = eonoutput;
31937469Ssklower 	ifp->if_type = IFT_EON;
32037469Ssklower 	ifp->if_addrlen = 5;
32137469Ssklower 	ifp->if_hdrlen = EONIPLEN;
32236382Ssklower 	ifp->if_flags = IFF_BROADCAST;
32336382Ssklower 	if_attach(ifp);
32436382Ssklower 
32536382Ssklower 	IFDEBUG(D_EON)
32636382Ssklower 		printf("eonattach()\n");
32736382Ssklower 	ENDDEBUG
32836382Ssklower 	eon_initcache();
32936382Ssklower 	IFDEBUG(D_EON)
33036382Ssklower 		printf("eon%d: attached\n", iod->iod_unit);
33136382Ssklower 	ENDDEBUG
33236382Ssklower }
33336382Ssklower 
33436382Ssklower static struct eon_centry *
33536382Ssklower find_oldent( ea )
33636382Ssklower 	struct sockaddr_eon *ea;
33736382Ssklower {
33836382Ssklower 	register	int				offset =
33936382Ssklower 						_offsetof( struct eon_centry, eonc_q_LINK);
34037469Ssklower 	register struct eon_centry 	*ent, *oent;
34136382Ssklower 
34237469Ssklower 	oent = ent = qtocentry(eon_LINK_hdr.link, offset);
34336382Ssklower 	IFDEBUG(D_EON)
34436382Ssklower 		printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n",
34536382Ssklower 			(ea->seon_ipaddr>>24)&0xff,
34636382Ssklower 			(ea->seon_ipaddr>>16)&0xff,
34736382Ssklower 			(ea->seon_ipaddr>>8)&0xff,
34836382Ssklower 			(ea->seon_ipaddr)&0xff );
34936382Ssklower 	ENDDEBUG
35037469Ssklower 	do {
35136382Ssklower 		if( ent->eonc_addr.s_addr == ea->seon_ipaddr )
35236382Ssklower 			return ent;
35337469Ssklower 		ent = qtocentry(ent->eonc_nextLINK, offset);
35437469Ssklower 	} while (ent != oent);
35536382Ssklower 	return (struct eon_centry *)0;
35636382Ssklower }
35736382Ssklower 
35836382Ssklower /*
35936382Ssklower  * FUNCTION:		eonioctl
36036382Ssklower  *
36136382Ssklower  * PURPOSE:			io controls - ifconfig
36236382Ssklower  *				need commands to
36336382Ssklower  *					link-UP (core addr) (flags: ES, IS)
36436382Ssklower  *					link-DOWN (core addr) (flags: ES, IS)
36536382Ssklower  *				must be callable from kernel or user
36636382Ssklower  *
36736382Ssklower  * RETURNS:			nothing
36836382Ssklower  */
36936382Ssklower eonioctl(ifp, cmd, data)
37036382Ssklower 	register struct ifnet *ifp;
37136382Ssklower 	register int cmd;
37236382Ssklower 	register caddr_t data;
37336382Ssklower {
37437469Ssklower 	struct iso_ifreq *ifr = (struct iso_ifreq *)data;
37536382Ssklower 	register struct sockaddr_eon *eoa =
37637469Ssklower 				(struct sockaddr_eon *)&(ifr->ifr_Addr);
37736382Ssklower 	register int s = splimp();
37836382Ssklower 	register int error = 0;
37936382Ssklower 
38036382Ssklower 	IFDEBUG(D_EON)
38136382Ssklower 		printf("eonioctl (cmd 0x%x) \n", cmd);
38236382Ssklower 	ENDDEBUG
38336382Ssklower 
38436382Ssklower 	switch (cmd){
38537469Ssklower 	case SIOCSEONCORE: {
38636382Ssklower 			/* add pt-pt link to the set of core addrs */
38736382Ssklower 			register 	struct eon_centry *ent, *oldent;
38836382Ssklower 			register	u_short			  which;
38936382Ssklower 
39036382Ssklower 			/* "which" tells which lists to put these guys in - don't
39136382Ssklower 			 * want to insert something in a list if it's already there
39236382Ssklower 			 */
39336382Ssklower #define LEGIT_EONADDR(a)\
39437469Ssklower 	((a->seon_family == AF_ISO) && (a->seon_afi == AFI_RFC986) &&\
39536382Ssklower 	(a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \
39637469Ssklower 	&& (a->seon_vers == EON_986_VERSION) && (a->seon_adrlen == 0x14))
39736382Ssklower 
39836382Ssklower 			if( ! LEGIT_EONADDR(eoa) ) {
39936382Ssklower 				error = EADDRNOTAVAIL;
40036382Ssklower 				break;
40136382Ssklower 			}
40236382Ssklower 
40336382Ssklower 			oldent = find_oldent( eoa );
40436382Ssklower 			IFDEBUG(D_EON)
40536382Ssklower 				printf("eonioctl legit seon_status 0x%x oldent %s\n",
40636382Ssklower 					eoa->seon_status, oldent?"found":"not found");
40736382Ssklower 			ENDDEBUG
40836382Ssklower 
40936382Ssklower 			if( eoa->seon_status & UPBITS ) {
41036382Ssklower 				if (!oldent) {
41136382Ssklower 					/* doesn't exist - need to create one */
41237469Ssklower 					if (eon_FREE_hdr.link == eon_FREE_hdr.rlink)
41337469Ssklower 						return ENOBUFS;
41436382Ssklower 					ent = qtocentry(eon_FREE_hdr.link,
41536382Ssklower 								_offsetof( struct eon_centry, eonc_q_LINK));
41636382Ssklower 					remque( &(ent->eonc_q_LINK) );
41736382Ssklower 					ent->eonc_addr.s_addr = eoa->seon_ipaddr;
41837469Ssklower 					insque( &(ent->eonc_q_LINK), (&eon_LINK_hdr));
41936382Ssklower 					oldent = ent;
42036382Ssklower 				}
42136382Ssklower 
42236382Ssklower 				which = (eoa->seon_status ^ oldent->eonc_status) &
42336382Ssklower 					eoa->seon_status & UPBITS;
42436382Ssklower 
42536382Ssklower 				oldent->eonc_status |= (eoa->seon_status & UPBITS);
42636382Ssklower 
42736382Ssklower 				if( which & EON_ESLINK_UP )
42836382Ssklower 					insque( &oldent->eonc_q_ES, (&eon_ES_hdr));
42936382Ssklower 				if( which & EON_ISLINK_UP )
43036382Ssklower 					insque( &oldent->eonc_q_IS, (&eon_IS_hdr));
43136382Ssklower 			}
43236382Ssklower 
43336382Ssklower 			if( eoa->seon_status & DOWNBITS ) {
43436382Ssklower 				if(!oldent) {
43536382Ssklower 					return ENOENT; /* no such entry */
43636382Ssklower 				}
43736382Ssklower 				which = (eoa->seon_status ^ oldent->eonc_status) &
43836382Ssklower 					eoa->seon_status & DOWNBITS;
43936382Ssklower 
44036382Ssklower 				oldent->eonc_status |= (eoa->seon_status & DOWNBITS);
44136382Ssklower 
44236382Ssklower 				if( which & EON_ESLINK_DOWN )
44336382Ssklower 					remque( &(oldent->eonc_q_ES) );
44436382Ssklower 				if( which & EON_ISLINK_DOWN )
44536382Ssklower 					remque( &(oldent->eonc_q_IS) );
44636382Ssklower 			}
44736382Ssklower 
44836382Ssklower 		IFDEBUG(D_EON)
44936382Ssklower 			printf("at end status 0x%x\n", oldent->eonc_status);
45036382Ssklower 		ENDDEBUG
45136382Ssklower 		break;
45236382Ssklower 		}
45336382Ssklower 
45437469Ssklower 	case SIOCGEONCORE:
45536382Ssklower 		{
45636382Ssklower 			register 	struct eon_centry *oldent;
45736382Ssklower 
45836382Ssklower 			oldent = find_oldent( eoa );
45936382Ssklower 			if( oldent == (struct eon_centry *)0 )
46036382Ssklower 				error = EADDRNOTAVAIL;
46136382Ssklower 			else
46236382Ssklower 				eoa->seon_status = oldent->eonc_status;
46336382Ssklower 		}
46436382Ssklower 		break;
46536382Ssklower 
46636382Ssklower 	case SIOCSIFADDR:
46736382Ssklower 		ifp->if_flags |= IFF_UP;
46836382Ssklower 		break;
46936382Ssklower 
47036382Ssklower 	case SIOCSIFFLAGS:
47136382Ssklower 		if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags &
47236382Ssklower 		  IFF_RUNNING){
47336382Ssklower 			ifp->if_flags &= ~IFF_RUNNING;
47436382Ssklower 		} else if (ifp->if_flags & IFF_UP && (ifp->if_flags &
47536382Ssklower 		  IFF_RUNNING) == 0)
47636382Ssklower 			eoninit(ifp->if_unit);
47736382Ssklower 		break;
47836382Ssklower 	default:
47936382Ssklower 		error = EINVAL;
48036382Ssklower 	}
48136382Ssklower 	splx(s);
48236382Ssklower 	return(error);
48336382Ssklower }
48436382Ssklower 
48536382Ssklower /*
48636382Ssklower  * FUNCTION:		eoninit
48736382Ssklower  *
48836382Ssklower  * PURPOSE:			initialization
48936382Ssklower  *
49036382Ssklower  * RETURNS:			nothing
49136382Ssklower  */
49236382Ssklower 
49336382Ssklower eoninit(unit)
49436382Ssklower 	int unit;
49536382Ssklower {
49637469Ssklower 	printf("eon driver-init eon%d\n", unit);
49736382Ssklower }
49836382Ssklower 
49936382Ssklower 
50036382Ssklower /*
50136382Ssklower  * FUNCTION:		eonint
50236382Ssklower  *
50336382Ssklower  * PURPOSE:			filler for device configuration
50436382Ssklower  *
50536382Ssklower  * RETURNS:			nothing
50636382Ssklower  *
50736382Ssklower  * NOTES:			*should* never get called - for debugging it's here
50836382Ssklower  */
50936382Ssklower 
51036382Ssklower eonint()
51136382Ssklower {
51236382Ssklower 	/* silent - so no more stray interrupt messages from the aed! yay
51336382Ssklower 	printf("eonint() called - BOGUS INTERRUPT\n");
51436382Ssklower 	*/
51536382Ssklower }
51636382Ssklower 
51736382Ssklower 
51836382Ssklower /*
51936382Ssklower  * FUNCTION:		eonoutput
52036382Ssklower  *
52136382Ssklower  * PURPOSE:			prepend an eon header and hand to IP
52236382Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
52336382Ssklower  *					(m)  is an mbuf *, *m is a CLNL packet
52436382Ssklower  *					(dst) is a destination address - have to interp. as
52536382Ssklower  *					multicast or broadcast or real address.
52636382Ssklower  *
52736382Ssklower  * RETURNS:			unix error code
52836382Ssklower  *
52936382Ssklower  * NOTES:
53036382Ssklower  *
53136382Ssklower  */
53236382Ssklower eonoutput(ifp, morig, dst)
53337469Ssklower 	struct ifnet 	*ifp;
53436382Ssklower 	register struct mbuf	*morig;		/* packet */
53536382Ssklower 	struct sockaddr_iso		*dst;		/* destination addr */
53636382Ssklower {
53736382Ssklower 	int						s;
53836382Ssklower 	struct eon_hdr			*eonhdr;
53936382Ssklower 	struct ip				*iphdr;
54036382Ssklower 	struct mbuf				*mh;
54136382Ssklower 	int						error = 0;
54236382Ssklower 	register int			datalen;
54336382Ssklower 	caddr_t					dstipaddrloc;
54437469Ssklower 	int						single = 0, class, qoffset = 0, snpalen;
54536382Ssklower 	register struct eon_centry	*ent;
54637469Ssklower 	register struct sockaddr_eon *eoa;
54736382Ssklower 	struct qhdr				*q;
54837469Ssklower 	char edst[6];
54936382Ssklower 
55036382Ssklower 	IFDEBUG(D_EON)
55136382Ssklower 		printf("eonoutput \n" );
55236382Ssklower 	ENDDEBUG
55336382Ssklower 
55437469Ssklower 	if( dst->siso_family != AF_ISO ) {
55537469Ssklower 	einval:
55637469Ssklower 		error =  EINVAL;
55737469Ssklower 		goto flush;
55837469Ssklower 	}
55937469Ssklower 	if ((morig->m_flags & M_PKTHDR) == 0) {
56037469Ssklower 		printf("eon: got non headered packet\n");
56137469Ssklower 		goto einval;
56237469Ssklower 	}
56337469Ssklower 	eoa = (struct sockaddr_eon *)dst;
56437469Ssklower 	if (LEGIT_EONADDR(eoa)) {
56537469Ssklower 		class = eoa->seon_protoid;
56637469Ssklower 		dstipaddrloc = (caddr_t)&(eoa->seon_ipaddr);
56737469Ssklower 	} else if (eoa->seon_afi == AFI_SNA) {
56837469Ssklower 		dstipaddrloc = (caddr_t)&(dst->siso_data[1]);
56937469Ssklower 		if (dst->siso_nlen == 6) {
57037469Ssklower 			class = dst->siso_data[5];
57137469Ssklower 		} else if (dst->siso_nlen == 7) {
57237469Ssklower 			if (bcmp(dstipaddrloc, all_is.sc_snpa, 6))
57337469Ssklower 				class = EON_MULTICAST_ES;
57437469Ssklower 			else if (bcmp(dstipaddrloc, all_es.sc_snpa, 6))
57537469Ssklower 				class = EON_MULTICAST_IS;
57637469Ssklower 			else
57737469Ssklower 				goto einval;
57837469Ssklower 		} else
57937469Ssklower 				goto einval;
58037469Ssklower 	} else if (0 == iso_snparesolve(ifp, dst, edst, &snpalen)) {
58137469Ssklower 		dstipaddrloc = (caddr_t)edst;
58237469Ssklower 		class = edst[4];
58337469Ssklower 	} else {
58437469Ssklower 		error = EINVAL;
58537469Ssklower 		goto flush;
58637469Ssklower 	}
58737469Ssklower 	switch (class) {
58836382Ssklower 		case EON_NORMAL_ADDR:
58936382Ssklower 			IncStat(es_out_normal);
59036382Ssklower 			single = 1;
59136382Ssklower 			break;
59236382Ssklower 
59336382Ssklower 		case EON_BROADCAST:
59436382Ssklower 			IncStat(es_out_broad);
59537469Ssklower 			if(eon_LINK_hdr.link == eon_LINK_hdr.rlink) {
59636382Ssklower 				error = EADDRNOTAVAIL;
59736382Ssklower 			} else {
59836382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
59936382Ssklower 				ent = qtocentry(eon_LINK_hdr.link, qoffset);
60036382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
60136382Ssklower 			}
60236382Ssklower 			break;
60336382Ssklower 		case EON_MULTICAST_ES:
60436382Ssklower 			IncStat(es_out_multi_es);
60537469Ssklower 			if (eon_ES_hdr.link == eon_ES_hdr.rlink) {
60636382Ssklower 				error = EADDRNOTAVAIL;
60736382Ssklower 			} else {
60836382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_ES);
60936382Ssklower 				ent = qtocentry(eon_ES_hdr.link, qoffset);
61036382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
61136382Ssklower 			}
61236382Ssklower 			break;
61336382Ssklower 		case EON_MULTICAST_IS:
61436382Ssklower 			IncStat(es_out_multi_is);
61537469Ssklower 			if (eon_IS_hdr.link == eon_IS_hdr.rlink) {
61636382Ssklower 				error = EADDRNOTAVAIL;
61736382Ssklower 			} else {
61836382Ssklower 				qoffset = _offsetof( struct eon_centry, eonc_q_LINK);
61936382Ssklower 				ent = qtocentry(eon_IS_hdr.link, qoffset);
62036382Ssklower 				dstipaddrloc = (caddr_t) &(ent->eonc_addr);
62136382Ssklower 			}
62236382Ssklower 			break;
62336382Ssklower 		default:
62437469Ssklower 			printf("bad class value; treated as EON_NORMAL_ADDR\n");
62537469Ssklower 			class = EON_NORMAL_ADDR;
62636382Ssklower 			single = 1;
62736382Ssklower 			break;
62836382Ssklower 	}
62936382Ssklower 	if( error )
63036382Ssklower 		goto done;
63136382Ssklower 
63236382Ssklower 	/* get data length -- needed later */
63337469Ssklower 	datalen = morig->m_pkthdr.len;
63436382Ssklower 	IFDEBUG(D_EON)
63536382Ssklower 		printf("eonoutput : m_datalen returns %d\n", datalen);
63636382Ssklower 	ENDDEBUG
63736382Ssklower 
63837469Ssklower 	MGETHDR(mh, M_DONTWAIT, MT_HEADER);
63937469Ssklower 	if(mh == (struct mbuf *)0)
64036382Ssklower 		goto done;
64136382Ssklower 
64236382Ssklower 	/* put an eon_hdr in the buffer, prepended by an ip header */
64336382Ssklower 	mh->m_len = sizeof(struct eon_hdr);
64437469Ssklower 	MH_ALIGN(mh, sizeof(struct eon_hdr));
64536382Ssklower 	mh->m_next = morig;
64636382Ssklower 	eonhdr = mtod(mh, struct eon_hdr *);
64737469Ssklower 	eonhdr->eonh_class = class;
64836382Ssklower 	eonhdr->eonh_vers = EON_VERSION;
64937469Ssklower 	eonhdr->eonh_csum = 0;
65036382Ssklower 
65136382Ssklower 	IFDEBUG(D_EON)
65236382Ssklower 		printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
65336382Ssklower 			mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
65436382Ssklower 	ENDDEBUG
65536382Ssklower 	iso_gen_csum(mh,
65636382Ssklower 		_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
65736382Ssklower 
65837469Ssklower 	mh->m_data -= sizeof(*iphdr);
65937469Ssklower 	mh->m_len += sizeof(*iphdr);
66036382Ssklower 	iphdr = mtod(mh, struct ip *);
66137469Ssklower 	bzero((caddr_t)iphdr, sizeof (*iphdr));
66236382Ssklower 
66336382Ssklower 	iphdr->ip_p = IPPROTO_EON;
66437469Ssklower 	iphdr->ip_len = (u_short)(mh->m_pkthdr.len = EONIPLEN + datalen);
66536382Ssklower 	iphdr->ip_ttl = MAXTTL;
66636382Ssklower 	iphdr->ip_src.s_addr = INADDR_ANY;
66736382Ssklower 
66836382Ssklower 	IFDEBUG(D_EON)
66936382Ssklower 		printf("eonoutput : after gen csum: ip_len %d/0x%x\n",
67037469Ssklower 						mh->m_pkthdr.len, mh->m_pkthdr.len);
67136382Ssklower 	ENDDEBUG
67236382Ssklower 
67336382Ssklower 	morig = mh;
67436382Ssklower 
67536382Ssklower 	for(;;) {
67636382Ssklower 
67736382Ssklower 		if( !single ) {
67836382Ssklower 			/* make a copy to send */
67936382Ssklower 			IFDEBUG(D_EON)
68036382Ssklower 				printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n",
68136382Ssklower 					morig, iphdr->ip_len);
68236382Ssklower 			ENDDEBUG
68337469Ssklower 			if (((mh = m_copy(morig, 0, morig->m_pkthdr.len)) == 0) ||
68437469Ssklower 			    ((mh = m_pullup(mh, sizeof(struct ip))) == 0)) {
68537469Ssklower 				error = ENOBUFS;
68637469Ssklower 				goto done;
68737469Ssklower 			}
68836382Ssklower 			iphdr = mtod(mh, struct ip *);
68936382Ssklower 		}
69036382Ssklower 		IFDEBUG(D_EON)
69136382Ssklower 			printf("eonoutput : bcopy 0x%x to 0x%x length %d\n",
69236382Ssklower 				dstipaddrloc,
69336382Ssklower 				(caddr_t)&(iphdr->ip_dst.s_addr),
69436382Ssklower 				sizeof(iphdr->ip_dst.s_addr));
69536382Ssklower 		ENDDEBUG
69637469Ssklower 		bcopy(dstipaddrloc, (caddr_t)&(iphdr->ip_dst.s_addr),
69737469Ssklower 										sizeof(iphdr->ip_dst.s_addr));
69836382Ssklower 		IFDEBUG(D_EON)
69936382Ssklower 			printf("eonoutput : dst ip addr : %d.%d.%d.%d",
70036382Ssklower 				(iphdr->ip_dst.s_addr>>24)&0xff,
70136382Ssklower 				(iphdr->ip_dst.s_addr>>16)&0xff,
70236382Ssklower 				(iphdr->ip_dst.s_addr>>8)&0xff,
70336382Ssklower 				(iphdr->ip_dst.s_addr)&0xff );
70436382Ssklower 		ENDDEBUG
70536382Ssklower 
70636382Ssklower 		IFDEBUG(D_EON)
70736382Ssklower 			printf("eonoutput ip_output : eon header:\n");
70836382Ssklower 			dump_buf(eonhdr, sizeof(struct eon_hdr));
70936382Ssklower 			printf("ip header:\n");
71036382Ssklower 			dump_buf(iphdr, sizeof(struct ip));
71136382Ssklower 		ENDDEBUG
71236382Ssklower 
71336382Ssklower 		IncStat(es_ipout);
71436382Ssklower 		if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) )
71536382Ssklower 				break;
71636382Ssklower 
71736382Ssklower 		IFDEBUG(D_EON)
71836382Ssklower 			printf("eonoutput ip_output returns 0x%x; single %d\n",
71936382Ssklower 				error, single);
72036382Ssklower 		ENDDEBUG
72136382Ssklower 
72236382Ssklower 		if(single)
72336382Ssklower 			break;
72436382Ssklower 
72536382Ssklower 		q = centrytoq(ent, qoffset)->link;
72636382Ssklower 		if( q == (struct qhdr *)0)
72736382Ssklower 			break;
72836382Ssklower 		ent = qtocentry( q,  qoffset );
72936382Ssklower 		IFDEBUG(D_EON)
73036382Ssklower 			printf("eonoutput : get next entry: 0x%x\n", ent);
73136382Ssklower 		ENDDEBUG
73236382Ssklower 		dstipaddrloc = (caddr_t) &(ent->eonc_addr);
73336382Ssklower 		IFDEBUG(D_EON)
73436382Ssklower 			printf("eonoutput : dump of eon_centry 0x%x:\n", ent );
73536382Ssklower 			dump_buf(ent, sizeof(struct eon_centry) );
73636382Ssklower 		ENDDEBUG
73736382Ssklower 	}
73836382Ssklower done:
73936382Ssklower 	if( !single ) {
74036382Ssklower 		IFDEBUG(D_EON)
74136382Ssklower 			printf("eonoutput : freeing morig 0x%x\n", morig);
74236382Ssklower 		ENDDEBUG
74337469Ssklower flush:
74436382Ssklower 		m_freem(morig);
74536382Ssklower 	}
74636382Ssklower 	return error;
74736382Ssklower }
74836382Ssklower 
74937469Ssklower eoninput(m, iphlen)
75036382Ssklower 	register struct mbuf	*m;
75137469Ssklower 	int iphlen;
75236382Ssklower {
75336382Ssklower 	register struct eon_hdr	*eonhdr;
75436382Ssklower 	register struct ip		*iphdr;
75536382Ssklower 	struct ifnet 			*eonifp;
75637469Ssklower 	int						s;
75736382Ssklower 
75836382Ssklower 	eonifp = &eonif[0]; /* kludge - really want to give CLNP
75936382Ssklower 						* the ifp for eon, not for the real device
76036382Ssklower 						*/
76136382Ssklower 
76236382Ssklower 	IFDEBUG(D_EON)
76337469Ssklower 		printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
76437469Ssklower 			m, m?m->m_data:0, m?m->m_len:0);
76536382Ssklower 	ENDDEBUG
76636382Ssklower 
76737469Ssklower 	if (m == 0)
76837469Ssklower 		return;
76937469Ssklower 	if (iphlen > sizeof (struct ip))
77037469Ssklower 		ip_stripoptions(m, (struct mbuf *)0);
77137469Ssklower 	if (m->m_len < EONIPLEN) {
77237469Ssklower 		if ((m = m_pullup(m, EONIPLEN)) == 0) {
77337469Ssklower 			IncStat(es_badhdr);
77437469Ssklower drop:
77537469Ssklower 			IFDEBUG(D_EON)
77637469Ssklower 				printf("eoninput: DROP \n" );
77737469Ssklower 			ENDDEBUG
77837469Ssklower 			eonifp->if_ierrors ++;
77937469Ssklower 			m_freem(m);
78037469Ssklower 			return;
78137469Ssklower 		}
78236382Ssklower 	}
78336382Ssklower 	iphdr = mtod(m, struct ip *);
78436382Ssklower 	/* do a few checks for debugging */
78536382Ssklower 	if( iphdr->ip_p != IPPROTO_EON ) {
78636382Ssklower 		IncStat(es_badhdr);
78736382Ssklower 		goto drop;
78836382Ssklower 	}
78937469Ssklower 	/* temporarily drop ip header from the mbuf */
79037469Ssklower 	m->m_data += sizeof(struct ip);
79136382Ssklower 	eonhdr = mtod(m, struct eon_hdr *);
79237469Ssklower 	if( iso_check_csum( m, sizeof(struct eon_hdr) )   != EOK ) {
79337469Ssklower 		IncStat(es_badcsum);
79437469Ssklower 		goto drop;
79537469Ssklower 	}
79637469Ssklower 	m->m_data -= sizeof(struct ip);
79737469Ssklower 
79836382Ssklower 	IFDEBUG(D_EON)
79937469Ssklower 		printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
80036382Ssklower 		printf("eoninput: eon header:\n");
80136382Ssklower 		dump_buf(eonhdr, sizeof(struct eon_hdr));
80236382Ssklower 	ENDDEBUG
80336382Ssklower 
80436382Ssklower 	/* checks for debugging */
80536382Ssklower 	if( eonhdr->eonh_vers != EON_VERSION) {
80636382Ssklower 		IncStat(es_badhdr);
80736382Ssklower 		goto drop;
80836382Ssklower 	}
80937469Ssklower 	m->m_flags &= ~(M_BCAST|M_MCAST);
81036382Ssklower 	switch( eonhdr->eonh_class) {
81136382Ssklower 		case EON_BROADCAST:
81236382Ssklower 			IncStat(es_in_broad);
81337469Ssklower 			m->m_flags |= M_BCAST;
81436382Ssklower 			break;
81536382Ssklower 		case EON_NORMAL_ADDR:
81636382Ssklower 			IncStat(es_in_normal);
81736382Ssklower 			break;
81836382Ssklower 		case EON_MULTICAST_ES:
81936382Ssklower 			IncStat(es_in_multi_es);
82037469Ssklower 			m->m_flags |= M_MCAST;
82136382Ssklower 			break;
82236382Ssklower 		case EON_MULTICAST_IS:
82336382Ssklower 			IncStat(es_in_multi_is);
82437469Ssklower 			m->m_flags |= M_MCAST;
82536382Ssklower 			break;
82636382Ssklower 	}
82736382Ssklower 	eonifp->if_ipackets ++;
82836382Ssklower 
82936382Ssklower 	{
83036382Ssklower 		/* put it on the CLNP queue and set soft interrupt */
83136382Ssklower 		struct ifqueue 			*ifq;
83236382Ssklower 		extern struct ifqueue 	clnlintrq;
83336382Ssklower 
83437469Ssklower 		m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
83536382Ssklower 		IFDEBUG(D_EON)
83636382Ssklower 			printf("eoninput to clnl IFQ\n");
83736382Ssklower 		ENDDEBUG
83836382Ssklower 		ifq = &clnlintrq;
83937469Ssklower 		s = splimp();
84036382Ssklower 		if (IF_QFULL(ifq)) {
84136382Ssklower 			IF_DROP(ifq);
84236382Ssklower 			m_freem(m);
84337469Ssklower 			eonifp->if_ierrors ++;
84436382Ssklower 			splx(s);
84536382Ssklower 			return;
84636382Ssklower 		}
84736382Ssklower 		IF_ENQUEUE(ifq, m);
84836382Ssklower 		IFDEBUG(D_EON)
84936382Ssklower 			printf(
85037469Ssklower 	"0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
85137469Ssklower 				m, m->m_len, m->m_type, m->m_data);
85236382Ssklower 			dump_buf(mtod(m, caddr_t), m->m_len);
85336382Ssklower 		ENDDEBUG
85437469Ssklower 		schednetisr(NETISR_ISO);
85537469Ssklower 		splx(s);
85636382Ssklower 	}
85736382Ssklower }
85836382Ssklower 
85936382Ssklower int
86036382Ssklower eonctlinput(cmd, sin)
86136382Ssklower 	int cmd;
86236382Ssklower 	struct sockaddr_in *sin;
86336382Ssklower {
86436382Ssklower 	extern u_char inetctlerrmap[];
86536382Ssklower 
86636382Ssklower 	IFDEBUG(D_EON)
86736382Ssklower 		printf("eonctlinput: cmd 0x%x addr: ", cmd);
86836382Ssklower 		dump_isoaddr(sin);
86936382Ssklower 		printf("\n");
87036382Ssklower 	ENDDEBUG
87136382Ssklower 
87236382Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
87336382Ssklower 		return 0;
87436382Ssklower 
87536382Ssklower 	IncStat(es_icmp[cmd]);
87636382Ssklower 	switch (cmd) {
87736382Ssklower 
87837469Ssklower 		case	PRC_QUENCH:
87936382Ssklower 		case	PRC_QUENCH2:
88036382Ssklower 			/* TODO: set the dec bit */
88136382Ssklower 			break;
88236382Ssklower 		case	PRC_TIMXCEED_REASS:
88336382Ssklower 		case	PRC_ROUTEDEAD:
88436382Ssklower 		case	PRC_HOSTUNREACH:
88536382Ssklower 		case	PRC_UNREACH_NET:
88636382Ssklower 		case	PRC_IFDOWN:
88736382Ssklower 		case	PRC_UNREACH_HOST:
88836382Ssklower 		case	PRC_HOSTDEAD:
88936382Ssklower 		case	PRC_TIMXCEED_INTRANS:
89036382Ssklower 			/* TODO: mark the link down */
89136382Ssklower 			break;
89236382Ssklower 
89336382Ssklower 		case	PRC_UNREACH_PROTOCOL:
89436382Ssklower 		case	PRC_UNREACH_PORT:
89536382Ssklower 		case	PRC_UNREACH_NEEDFRAG:
89636382Ssklower 		case	PRC_UNREACH_SRCFAIL:
89736382Ssklower 		case	PRC_REDIRECT_NET:
89836382Ssklower 		case	PRC_REDIRECT_HOST:
89936382Ssklower 		case	PRC_REDIRECT_TOSNET:
90036382Ssklower 		case	PRC_REDIRECT_TOSHOST:
90136382Ssklower 		case	PRC_MSGSIZE:
90236382Ssklower 		case	PRC_PARAMPROB:
90336382Ssklower 			printf("eonctlinput: ICMP cmd 0x%x\n", cmd );
90436382Ssklower 		break;
90536382Ssklower 	}
90636382Ssklower 	return 0;
90736382Ssklower }
90836382Ssklower 
90937469Ssklower #endif
910