xref: /csrg-svn/sys/netiso/if_eon.c (revision 68165)
149268Sbostic /*-
263222Sbostic  * Copyright (c) 1991, 1993
363222Sbostic  *	The Regents of the University of California.  All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*68165Scgd  *	@(#)if_eon.c	8.2 (Berkeley) 01/09/95
849268Sbostic  */
949268Sbostic 
1036382Ssklower /***********************************************************
1136382Ssklower 		Copyright IBM Corporation 1987
1236382Ssklower 
1336382Ssklower                       All Rights Reserved
1436382Ssklower 
1536382Ssklower Permission to use, copy, modify, and distribute this software and its
1636382Ssklower documentation for any purpose and without fee is hereby granted,
1736382Ssklower provided that the above copyright notice appear in all copies and that
1836382Ssklower both that copyright notice and this permission notice appear in
1936382Ssklower supporting documentation, and that the name of IBM not be
2036382Ssklower used in advertising or publicity pertaining to distribution of the
2136382Ssklower software without specific, written prior permission.
2236382Ssklower 
2336382Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
2436382Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
2536382Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
2636382Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
2736382Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
2836382Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2936382Ssklower SOFTWARE.
3036382Ssklower 
3136382Ssklower ******************************************************************/
3236382Ssklower 
3336382Ssklower /*
3436382Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
3536382Ssklower  */
3636382Ssklower /*
3736382Ssklower  * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $
3836382Ssklower  * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $
3936382Ssklower  *
4036382Ssklower  *	EON rfc
4136382Ssklower  *  Layer between IP and CLNL
4236382Ssklower  *
4336382Ssklower  * TODO:
4436382Ssklower  * Put together a current rfc986 address format and get the right offset
4536382Ssklower  * for the nsel
4636382Ssklower  */
4736382Ssklower 
4837469Ssklower #ifdef EON
4937469Ssklower #define NEON 1
5036382Ssklower 
5137469Ssklower 
5256533Sbostic #include <sys/param.h>
5356533Sbostic #include <sys/systm.h>
5456533Sbostic #include <sys/mbuf.h>
5556533Sbostic #include <sys/buf.h>
5656533Sbostic #include <sys/protosw.h>
5756533Sbostic #include <sys/socket.h>
5856533Sbostic #include <sys/ioctl.h>
5956533Sbostic #include <sys/errno.h>
6056533Sbostic #include <sys/types.h>
6136382Ssklower 
6256533Sbostic #include <net/if.h>
6356533Sbostic #include <net/if_types.h>
6456533Sbostic #include <net/if_dl.h>
6556533Sbostic #include <net/netisr.h>
6656533Sbostic #include <net/route.h>
6756533Sbostic #include <machine/mtpr.h>
6836382Ssklower 
6956533Sbostic #include <netinet/in.h>
7056533Sbostic #include <netinet/in_systm.h>
7156533Sbostic #include <netinet/in_var.h>
7256533Sbostic #include <netinet/ip.h>
7356533Sbostic #include <netinet/ip_var.h>
7456533Sbostic #include <netinet/if_ether.h>
7536382Ssklower 
7656533Sbostic #include <netiso/iso.h>
7756533Sbostic #include <netiso/iso_var.h>
7856533Sbostic #include <netiso/iso_snpac.h>
7956533Sbostic #include <netiso/argo_debug.h>
8056533Sbostic #include <netiso/iso_errno.h>
8156533Sbostic #include <netiso/eonvar.h>
8256533Sbostic 
8339195Ssklower extern struct timeval time;
8450239Ssklower extern struct ifnet loif;
8536382Ssklower 
8636382Ssklower #define EOK 0
8736382Ssklower 
8836382Ssklower int						eoninput();
8936382Ssklower int						eonoutput();
9036382Ssklower int						eonioctl();
9136382Ssklower int						eonattach();
9236382Ssklower int						eoninit();
9358989Ssklower void						eonrtrequest();
9440778Ssklower struct ifnet			eonif[1];
9536382Ssklower 
eonprotoinit()9637469Ssklower eonprotoinit() {
9740778Ssklower 	(void) eonattach();
9837469Ssklower }
9940778Ssklower 
10040778Ssklower struct eon_llinfo eon_llinfo;
10137469Ssklower #define PROBE_OK 0;
10236382Ssklower 
10337469Ssklower 
10436382Ssklower /*
10536382Ssklower  * FUNCTION:		eonattach
10636382Ssklower  *
10736382Ssklower  * PURPOSE:			autoconf attach routine
10836382Ssklower  *
10936382Ssklower  * RETURNS:			void
11036382Ssklower  */
11136382Ssklower 
eonattach()11240778Ssklower eonattach()
11336382Ssklower {
11440778Ssklower 	register struct ifnet *ifp = eonif;
11536382Ssklower 
11636382Ssklower 	IFDEBUG(D_EON)
11736382Ssklower 		printf("eonattach()\n");
11836382Ssklower 	ENDDEBUG
11940778Ssklower 	ifp->if_unit = 0;
12036382Ssklower 	ifp->if_name = "eon";
12136382Ssklower 	ifp->if_mtu = ETHERMTU;
12236382Ssklower 		/* since everything will go out over ether or token ring */
12336382Ssklower 
12436382Ssklower 	ifp->if_init = eoninit;
12537469Ssklower 	ifp->if_ioctl = eonioctl;
12636382Ssklower 	ifp->if_output = eonoutput;
12737469Ssklower 	ifp->if_type = IFT_EON;
12837469Ssklower 	ifp->if_addrlen = 5;
12937469Ssklower 	ifp->if_hdrlen = EONIPLEN;
13036382Ssklower 	ifp->if_flags = IFF_BROADCAST;
13136382Ssklower 	if_attach(ifp);
13240778Ssklower 	eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist);
13340778Ssklower 	eon_llinfo.el_qhdr.link =
13440778Ssklower 		eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr);
13536382Ssklower 
13636382Ssklower 	IFDEBUG(D_EON)
13736382Ssklower 		printf("eonattach()\n");
13836382Ssklower 	ENDDEBUG
13936382Ssklower }
14036382Ssklower 
14136382Ssklower 
14236382Ssklower /*
14336382Ssklower  * FUNCTION:		eonioctl
14436382Ssklower  *
14536382Ssklower  * PURPOSE:			io controls - ifconfig
14636382Ssklower  *				need commands to
14736382Ssklower  *					link-UP (core addr) (flags: ES, IS)
14836382Ssklower  *					link-DOWN (core addr) (flags: ES, IS)
14936382Ssklower  *				must be callable from kernel or user
15036382Ssklower  *
15136382Ssklower  * RETURNS:			nothing
15236382Ssklower  */
eonioctl(ifp,cmd,data)15336382Ssklower eonioctl(ifp, cmd, data)
15436382Ssklower 	register struct ifnet *ifp;
155*68165Scgd 	u_long cmd;
15636382Ssklower 	register caddr_t data;
15736382Ssklower {
15840778Ssklower 	int s = splimp();
15936382Ssklower 	register int error = 0;
16036382Ssklower 
16136382Ssklower 	IFDEBUG(D_EON)
16236382Ssklower 		printf("eonioctl (cmd 0x%x) \n", cmd);
16336382Ssklower 	ENDDEBUG
16436382Ssklower 
16540778Ssklower 	switch (cmd) {
16640778Ssklower 		register struct ifaddr *ifa;
16736382Ssklower 
16836382Ssklower 	case SIOCSIFADDR:
16940778Ssklower 		if (ifa = (struct ifaddr *)data) {
17040778Ssklower 			ifp->if_flags |= IFF_UP;
17141393Ssklower 			if (ifa->ifa_addr->sa_family != AF_LINK)
17241393Ssklower 				ifa->ifa_rtrequest = eonrtrequest;
17341393Ssklower 		}
17436382Ssklower 		break;
17536382Ssklower 	}
17636382Ssklower 	splx(s);
17736382Ssklower 	return(error);
17836382Ssklower }
17936382Ssklower 
18040778Ssklower 
18140778Ssklower eoniphdr(hdr, loc, ro, class, zero)
18240778Ssklower struct route *ro;
18340778Ssklower register struct eon_iphdr *hdr;
18440778Ssklower caddr_t loc;
18540778Ssklower {
18640778Ssklower 	struct mbuf mhead;
18740778Ssklower 	register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst;
18840778Ssklower 	if (zero) {
18940778Ssklower 		bzero((caddr_t)hdr, sizeof (*hdr));
19040778Ssklower 		bzero((caddr_t)ro, sizeof (*ro));
19140778Ssklower 	}
19240778Ssklower 	sin->sin_family = AF_INET;
19340778Ssklower 	sin->sin_len = sizeof (*sin);
19440778Ssklower 	bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr));
19548751Ssklower 	/*
19648751Ssklower 	 * If there is a cached route,
19748751Ssklower 	 * check that it is to the same destination
19848751Ssklower 	 * and is still up.  If not, free it and try again.
19948751Ssklower 	 */
20048751Ssklower 	if (ro->ro_rt) {
20148751Ssklower 		struct sockaddr_in *dst =
20248751Ssklower 			(struct sockaddr_in *)rt_key(ro->ro_rt);
20348751Ssklower 		if ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
20448751Ssklower 		   sin->sin_addr.s_addr != dst->sin_addr.s_addr) {
20548751Ssklower 			RTFREE(ro->ro_rt);
20648751Ssklower 			ro->ro_rt = (struct rtentry *)0;
20748751Ssklower 		}
20848751Ssklower 	}
20948751Ssklower 	rtalloc(ro);
21048751Ssklower 	if (ro->ro_rt)
21148751Ssklower 		ro->ro_rt->rt_use++;
21240778Ssklower 	hdr->ei_ip.ip_dst = sin->sin_addr;
21340778Ssklower 	hdr->ei_ip.ip_p = IPPROTO_EON;
21440778Ssklower 	hdr->ei_ip.ip_ttl = MAXTTL;
21540778Ssklower 	hdr->ei_eh.eonh_class = class;
21640778Ssklower 	hdr->ei_eh.eonh_vers = EON_VERSION;
21740778Ssklower 	hdr->ei_eh.eonh_csum = 0;
21840778Ssklower 	mhead.m_data = (caddr_t) &hdr->ei_eh;
21940778Ssklower 	mhead.m_len = sizeof(struct eon_hdr);
22040778Ssklower 	mhead.m_next = 0;
22140778Ssklower 	IFDEBUG(D_EON)
22240778Ssklower 		printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
22340778Ssklower 			&mhead,
22440778Ssklower 			_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
22540778Ssklower 	ENDDEBUG
22640778Ssklower 	iso_gen_csum(&mhead,
22740778Ssklower 		_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
22840778Ssklower }
22936382Ssklower /*
23040778Ssklower  * FUNCTION:		eonrtrequest
23136382Ssklower  *
23240778Ssklower  * PURPOSE:			maintains list of direct eon recipients.
23340778Ssklower  *					sets up IP route for rest.
23436382Ssklower  *
23536382Ssklower  * RETURNS:			nothing
23636382Ssklower  */
23758989Ssklower void
eonrtrequest(cmd,rt,gate)23840778Ssklower eonrtrequest(cmd, rt, gate)
23940778Ssklower register struct rtentry *rt;
24042321Ssklower register struct sockaddr *gate;
24140778Ssklower {
24242321Ssklower 	unsigned long zerodst = 0;
24342321Ssklower 	caddr_t	ipaddrloc = (caddr_t) &zerodst;
24440778Ssklower 	register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo;
24536382Ssklower 
24640778Ssklower 	/*
24740778Ssklower 	 * Common Housekeeping
24840778Ssklower 	 */
24940778Ssklower 	switch (cmd) {
25043333Ssklower 	case RTM_DELETE:
25143333Ssklower 		if (el) {
25243333Ssklower 			remque(&(el->el_qhdr));
25343333Ssklower 			if (el->el_iproute.ro_rt)
25443333Ssklower 				RTFREE(el->el_iproute.ro_rt);
25543333Ssklower 			Free(el);
25643333Ssklower 			rt->rt_llinfo = 0;
25743333Ssklower 		}
25843333Ssklower 		return;
25940778Ssklower 
26048751Ssklower 	case RTM_ADD:
26143333Ssklower 	case RTM_RESOLVE:
26248751Ssklower 		rt->rt_rmx.rmx_mtu = loif.if_mtu; /* unless better below */
26343333Ssklower 		R_Malloc(el, struct eon_llinfo *, sizeof(*el));
26443333Ssklower 		rt->rt_llinfo = (caddr_t)el;
26543333Ssklower 		if (el == 0)
26643333Ssklower 			return;
26743333Ssklower 		Bzero(el, sizeof(*el));
26840778Ssklower 		insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
26940778Ssklower 		el->el_rt = rt;
27040778Ssklower 		break;
27140778Ssklower 	}
27240778Ssklower 	if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) {
27340778Ssklower 		case AF_LINK:
27442321Ssklower #define SDL(x) ((struct sockaddr_dl *)x)
27552486Ssklower 			if (SDL(gate)->sdl_alen == 1)
27642321Ssklower 				el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate));
27742321Ssklower 			else
27842321Ssklower 				ipaddrloc = LLADDR(SDL(gate));
27940778Ssklower 			break;
28040778Ssklower 		case AF_INET:
28142321Ssklower #define SIN(x) ((struct sockaddr_in *)x)
28242321Ssklower 			ipaddrloc = (caddr_t) &SIN(gate)->sin_addr;
28340778Ssklower 			break;
28440778Ssklower 		default:
28540778Ssklower 			return;
28640778Ssklower 	}
28740778Ssklower 	el->el_flags |= RTF_UP;
28841926Ssklower 	eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
28948751Ssklower 	if (el->el_iproute.ro_rt)
29049616Ssklower 		rt->rt_rmx.rmx_mtu = el->el_iproute.ro_rt->rt_rmx.rmx_mtu
29149572Ssklower 							- sizeof(el->el_ei);
29236382Ssklower }
29336382Ssklower 
29436382Ssklower /*
29540778Ssklower  * FUNCTION:		eoninit
29636382Ssklower  *
29740778Ssklower  * PURPOSE:			initialization
29836382Ssklower  *
29936382Ssklower  * RETURNS:			nothing
30036382Ssklower  */
30136382Ssklower 
eoninit(unit)30240778Ssklower eoninit(unit)
30340778Ssklower 	int unit;
30436382Ssklower {
30540778Ssklower 	printf("eon driver-init eon%d\n", unit);
30636382Ssklower }
30736382Ssklower 
30836382Ssklower 
30936382Ssklower /*
31036382Ssklower  * FUNCTION:		eonoutput
31136382Ssklower  *
31236382Ssklower  * PURPOSE:			prepend an eon header and hand to IP
31336382Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
31436382Ssklower  *					(m)  is an mbuf *, *m is a CLNL packet
31536382Ssklower  *					(dst) is a destination address - have to interp. as
31636382Ssklower  *					multicast or broadcast or real address.
31736382Ssklower  *
31836382Ssklower  * RETURNS:			unix error code
31936382Ssklower  *
32036382Ssklower  * NOTES:
32136382Ssklower  *
32236382Ssklower  */
32340778Ssklower eonoutput(ifp, m, dst, rt)
32437469Ssklower 	struct ifnet 	*ifp;
32540778Ssklower 	register struct mbuf	*m;		/* packet */
32636382Ssklower 	struct sockaddr_iso		*dst;		/* destination addr */
32740778Ssklower 	struct rtentry *rt;
32836382Ssklower {
32940778Ssklower 	register struct eon_llinfo *el;
33040778Ssklower 	register struct eon_iphdr *ei;
33140778Ssklower 	struct route *ro;
33240778Ssklower 	int	datalen;
33340778Ssklower 	struct mbuf *mh;
33445896Ssklower 	int	error = 0, class = 0, alen = 0;
33545896Ssklower 	caddr_t ipaddrloc;
33640778Ssklower 	static struct eon_iphdr eon_iphdr;
33740778Ssklower 	static struct route route;
33836382Ssklower 
33936382Ssklower 	IFDEBUG(D_EON)
34036382Ssklower 		printf("eonoutput \n" );
34136382Ssklower 	ENDDEBUG
34236382Ssklower 
34339195Ssklower 	ifp->if_lastchange = time;
34439195Ssklower 	ifp->if_opackets++;
34540778Ssklower 	if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) {
34640778Ssklower 		if (dst->siso_family == AF_LINK) {
34740778Ssklower 			register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst;
34840778Ssklower 
34945896Ssklower 			ipaddrloc = LLADDR(sdl);
35045896Ssklower 			alen = sdl->sdl_alen;
35145896Ssklower 		} else if (dst->siso_family == AF_ISO && dst->siso_data[0] == AFI_SNA) {
35245896Ssklower 			alen = dst->siso_nlen - 1;
35345896Ssklower 			ipaddrloc = (caddr_t) dst->siso_data + 1;
35440778Ssklower 		}
35545896Ssklower 		switch (alen) {
35645896Ssklower 		case 5:
35745896Ssklower 			class =  4[(u_char *)ipaddrloc];
35845896Ssklower 		case 4:
35945896Ssklower 			ro = &route;
36045896Ssklower 			ei = &eon_iphdr;
36145896Ssklower 			eoniphdr(ei, ipaddrloc, ro, class, 1);
36245896Ssklower 			goto send;
36345896Ssklower 		}
36440778Ssklower einval:
36537469Ssklower 		error =  EINVAL;
36637469Ssklower 		goto flush;
36737469Ssklower 	}
36840778Ssklower 	if ((el->el_flags & RTF_UP) == 0) {
36940778Ssklower 		eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0);
37040778Ssklower 		if ((el->el_flags & RTF_UP) == 0) {
37140778Ssklower 			error = EHOSTUNREACH;
37240778Ssklower 			goto flush;
37340778Ssklower 		}
37440778Ssklower 	}
37540778Ssklower 	if ((m->m_flags & M_PKTHDR) == 0) {
37637469Ssklower 		printf("eon: got non headered packet\n");
37737469Ssklower 		goto einval;
37837469Ssklower 	}
37940778Ssklower 	ei = &el->el_ei;
38040778Ssklower 	ro = &el->el_iproute;
38142321Ssklower 	if (el->el_snpaoffset) {
38242321Ssklower 		if (dst->siso_family == AF_ISO) {
38342321Ssklower 			bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset],
38442321Ssklower 					(caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
38542321Ssklower 		} else
38642321Ssklower 			goto einval;
38742321Ssklower 	}
38840778Ssklower send:
38940778Ssklower 	/* put an eon_hdr in the buffer, prepended by an ip header */
39040778Ssklower 	datalen = m->m_pkthdr.len + EONIPLEN;
39137469Ssklower 	MGETHDR(mh, M_DONTWAIT, MT_HEADER);
39237469Ssklower 	if(mh == (struct mbuf *)0)
39340778Ssklower 		goto flush;
39440778Ssklower 	mh->m_next = m;
39540778Ssklower 	m = mh;
39640778Ssklower 	MH_ALIGN(m, sizeof(struct eon_iphdr));
39740778Ssklower 	m->m_len = sizeof(struct eon_iphdr);
39839195Ssklower 	ifp->if_obytes +=
39940778Ssklower 		(ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen));
40040778Ssklower 	*mtod(m, struct eon_iphdr *) = *ei;
40136382Ssklower 
40236382Ssklower 	IFDEBUG(D_EON)
40340778Ssklower 		printf("eonoutput dst ip addr : %x\n",  ei->ei_ip.ip_dst.s_addr);
40440778Ssklower 		printf("eonoutput ip_output : eonip header:\n");
40540778Ssklower 		dump_buf(ei, sizeof(struct eon_iphdr));
40636382Ssklower 	ENDDEBUG
40736382Ssklower 
40861657Ssklower 	error = ip_output(m, (struct mbuf *)0, ro, 0, NULL);
40940778Ssklower 	m = 0;
41039195Ssklower 	if (error) {
41139195Ssklower 		ifp->if_oerrors++;
41239195Ssklower 		ifp->if_opackets--;
41340778Ssklower 		ifp->if_obytes -= datalen;
41439195Ssklower 	}
41540778Ssklower flush:
41640778Ssklower 	if (m)
41740778Ssklower 		m_freem(m);
41836382Ssklower 	return error;
41936382Ssklower }
42036382Ssklower 
eoninput(m,iphlen)42137469Ssklower eoninput(m, iphlen)
42236382Ssklower 	register struct mbuf	*m;
42337469Ssklower 	int iphlen;
42436382Ssklower {
42536382Ssklower 	register struct eon_hdr	*eonhdr;
42636382Ssklower 	register struct ip		*iphdr;
42736382Ssklower 	struct ifnet 			*eonifp;
42837469Ssklower 	int						s;
42936382Ssklower 
43036382Ssklower 	eonifp = &eonif[0]; /* kludge - really want to give CLNP
43136382Ssklower 						* the ifp for eon, not for the real device
43236382Ssklower 						*/
43336382Ssklower 
43436382Ssklower 	IFDEBUG(D_EON)
43537469Ssklower 		printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
43637469Ssklower 			m, m?m->m_data:0, m?m->m_len:0);
43736382Ssklower 	ENDDEBUG
43836382Ssklower 
43937469Ssklower 	if (m == 0)
44037469Ssklower 		return;
44137469Ssklower 	if (iphlen > sizeof (struct ip))
44237469Ssklower 		ip_stripoptions(m, (struct mbuf *)0);
44337469Ssklower 	if (m->m_len < EONIPLEN) {
44437469Ssklower 		if ((m = m_pullup(m, EONIPLEN)) == 0) {
44537469Ssklower 			IncStat(es_badhdr);
44637469Ssklower drop:
44737469Ssklower 			IFDEBUG(D_EON)
44837469Ssklower 				printf("eoninput: DROP \n" );
44937469Ssklower 			ENDDEBUG
45037469Ssklower 			eonifp->if_ierrors ++;
45137469Ssklower 			m_freem(m);
45237469Ssklower 			return;
45337469Ssklower 		}
45436382Ssklower 	}
45539195Ssklower 	eonif->if_ibytes += m->m_pkthdr.len;
45639195Ssklower 	eonif->if_lastchange = time;
45736382Ssklower 	iphdr = mtod(m, struct ip *);
45836382Ssklower 	/* do a few checks for debugging */
45936382Ssklower 	if( iphdr->ip_p != IPPROTO_EON ) {
46036382Ssklower 		IncStat(es_badhdr);
46136382Ssklower 		goto drop;
46236382Ssklower 	}
46337469Ssklower 	/* temporarily drop ip header from the mbuf */
46437469Ssklower 	m->m_data += sizeof(struct ip);
46536382Ssklower 	eonhdr = mtod(m, struct eon_hdr *);
46637469Ssklower 	if( iso_check_csum( m, sizeof(struct eon_hdr) )   != EOK ) {
46737469Ssklower 		IncStat(es_badcsum);
46837469Ssklower 		goto drop;
46937469Ssklower 	}
47037469Ssklower 	m->m_data -= sizeof(struct ip);
47137469Ssklower 
47236382Ssklower 	IFDEBUG(D_EON)
47337469Ssklower 		printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
47436382Ssklower 		printf("eoninput: eon header:\n");
47536382Ssklower 		dump_buf(eonhdr, sizeof(struct eon_hdr));
47636382Ssklower 	ENDDEBUG
47736382Ssklower 
47836382Ssklower 	/* checks for debugging */
47936382Ssklower 	if( eonhdr->eonh_vers != EON_VERSION) {
48036382Ssklower 		IncStat(es_badhdr);
48136382Ssklower 		goto drop;
48236382Ssklower 	}
48337469Ssklower 	m->m_flags &= ~(M_BCAST|M_MCAST);
48436382Ssklower 	switch( eonhdr->eonh_class) {
48536382Ssklower 		case EON_BROADCAST:
48636382Ssklower 			IncStat(es_in_broad);
48737469Ssklower 			m->m_flags |= M_BCAST;
48836382Ssklower 			break;
48936382Ssklower 		case EON_NORMAL_ADDR:
49036382Ssklower 			IncStat(es_in_normal);
49136382Ssklower 			break;
49236382Ssklower 		case EON_MULTICAST_ES:
49336382Ssklower 			IncStat(es_in_multi_es);
49437469Ssklower 			m->m_flags |= M_MCAST;
49536382Ssklower 			break;
49636382Ssklower 		case EON_MULTICAST_IS:
49736382Ssklower 			IncStat(es_in_multi_is);
49837469Ssklower 			m->m_flags |= M_MCAST;
49936382Ssklower 			break;
50036382Ssklower 	}
50139195Ssklower 	eonifp->if_ipackets++;
50236382Ssklower 
50336382Ssklower 	{
50436382Ssklower 		/* put it on the CLNP queue and set soft interrupt */
50536382Ssklower 		struct ifqueue 			*ifq;
50636382Ssklower 		extern struct ifqueue 	clnlintrq;
50736382Ssklower 
50837469Ssklower 		m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
50936382Ssklower 		IFDEBUG(D_EON)
51036382Ssklower 			printf("eoninput to clnl IFQ\n");
51136382Ssklower 		ENDDEBUG
51236382Ssklower 		ifq = &clnlintrq;
51337469Ssklower 		s = splimp();
51436382Ssklower 		if (IF_QFULL(ifq)) {
51536382Ssklower 			IF_DROP(ifq);
51636382Ssklower 			m_freem(m);
51739195Ssklower 			eonifp->if_iqdrops++;
51839195Ssklower 			eonifp->if_ipackets--;
51936382Ssklower 			splx(s);
52036382Ssklower 			return;
52136382Ssklower 		}
52236382Ssklower 		IF_ENQUEUE(ifq, m);
52336382Ssklower 		IFDEBUG(D_EON)
52436382Ssklower 			printf(
52537469Ssklower 	"0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
52637469Ssklower 				m, m->m_len, m->m_type, m->m_data);
52736382Ssklower 			dump_buf(mtod(m, caddr_t), m->m_len);
52836382Ssklower 		ENDDEBUG
52937469Ssklower 		schednetisr(NETISR_ISO);
53037469Ssklower 		splx(s);
53136382Ssklower 	}
53236382Ssklower }
53336382Ssklower 
53436382Ssklower int
eonctlinput(cmd,sin)53536382Ssklower eonctlinput(cmd, sin)
53636382Ssklower 	int cmd;
53736382Ssklower 	struct sockaddr_in *sin;
53836382Ssklower {
53936382Ssklower 	extern u_char inetctlerrmap[];
54036382Ssklower 
54136382Ssklower 	IFDEBUG(D_EON)
54236382Ssklower 		printf("eonctlinput: cmd 0x%x addr: ", cmd);
54336382Ssklower 		dump_isoaddr(sin);
54436382Ssklower 		printf("\n");
54536382Ssklower 	ENDDEBUG
54636382Ssklower 
54736382Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
54836382Ssklower 		return 0;
54936382Ssklower 
55036382Ssklower 	IncStat(es_icmp[cmd]);
55136382Ssklower 	switch (cmd) {
55236382Ssklower 
55337469Ssklower 		case	PRC_QUENCH:
55436382Ssklower 		case	PRC_QUENCH2:
55536382Ssklower 			/* TODO: set the dec bit */
55636382Ssklower 			break;
55736382Ssklower 		case	PRC_TIMXCEED_REASS:
55836382Ssklower 		case	PRC_ROUTEDEAD:
55936382Ssklower 		case	PRC_HOSTUNREACH:
56036382Ssklower 		case	PRC_UNREACH_NET:
56136382Ssklower 		case	PRC_IFDOWN:
56236382Ssklower 		case	PRC_UNREACH_HOST:
56336382Ssklower 		case	PRC_HOSTDEAD:
56436382Ssklower 		case	PRC_TIMXCEED_INTRANS:
56536382Ssklower 			/* TODO: mark the link down */
56636382Ssklower 			break;
56736382Ssklower 
56836382Ssklower 		case	PRC_UNREACH_PROTOCOL:
56936382Ssklower 		case	PRC_UNREACH_PORT:
57036382Ssklower 		case	PRC_UNREACH_SRCFAIL:
57136382Ssklower 		case	PRC_REDIRECT_NET:
57236382Ssklower 		case	PRC_REDIRECT_HOST:
57336382Ssklower 		case	PRC_REDIRECT_TOSNET:
57436382Ssklower 		case	PRC_REDIRECT_TOSHOST:
57536382Ssklower 		case	PRC_MSGSIZE:
57636382Ssklower 		case	PRC_PARAMPROB:
57745896Ssklower 			/* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/
57836382Ssklower 		break;
57936382Ssklower 	}
58036382Ssklower 	return 0;
58136382Ssklower }
58236382Ssklower 
58337469Ssklower #endif
584