xref: /csrg-svn/sys/netiso/if_eon.c (revision 49616)
149268Sbostic /*-
249268Sbostic  * Copyright (c) 1991 The Regents of the University of California.
349268Sbostic  * All rights reserved.
449268Sbostic  *
549268Sbostic  * %sccs.include.redist.c%
649268Sbostic  *
7*49616Ssklower  *	@(#)if_eon.c	7.15 (Berkeley) 05/09/91
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 
5236382Ssklower #include "param.h"
5336382Ssklower #include "systm.h"
5436382Ssklower #include "types.h"
5536382Ssklower #include "mbuf.h"
5636382Ssklower #include "buf.h"
5736382Ssklower #include "protosw.h"
5836382Ssklower #include "socket.h"
5936382Ssklower #include "ioctl.h"
6036382Ssklower #include "errno.h"
6136382Ssklower #include "types.h"
6236382Ssklower 
6336382Ssklower #include "../net/if.h"
6439195Ssklower #include "../net/if_types.h"
6540778Ssklower #include "../net/if_dl.h"
6636382Ssklower #include "../net/netisr.h"
6736382Ssklower #include "../net/route.h"
6837518Smckusick #include "machine/mtpr.h"
6936382Ssklower 
7036382Ssklower #include "../netinet/in.h"
7136382Ssklower #include "../netinet/in_systm.h"
7240778Ssklower #include "../netinet/in_var.h"
7336382Ssklower #include "../netinet/ip.h"
7436382Ssklower #include "../netinet/ip_var.h"
7536382Ssklower #include "../netinet/if_ether.h"
7636382Ssklower 
7737469Ssklower #include "iso.h"
7837469Ssklower #include "iso_var.h"
7937469Ssklower #include "iso_snpac.h"
8037469Ssklower #include "argo_debug.h"
8137469Ssklower #include "iso_errno.h"
8237469Ssklower #include "eonvar.h"
8339195Ssklower extern struct timeval time;
8436382Ssklower 
8536382Ssklower #define EOK 0
8636382Ssklower 
8736382Ssklower int						eoninput();
8836382Ssklower int						eonoutput();
8936382Ssklower int						eonioctl();
9036382Ssklower int						eonattach();
9136382Ssklower int						eoninit();
9240778Ssklower int						eonrtrequest();
9336382Ssklower extern 	int				ip_output();
9440778Ssklower struct ifnet			eonif[1];
9536382Ssklower 
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 
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  */
15336382Ssklower eonioctl(ifp, cmd, data)
15436382Ssklower 	register struct ifnet *ifp;
15540778Ssklower 	int 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;
17340778Ssklower 			ifa->ifa_llinfolen = sizeof(struct eon_llinfo);
17441393Ssklower 		}
17536382Ssklower 		break;
17636382Ssklower 	}
17736382Ssklower 	splx(s);
17836382Ssklower 	return(error);
17936382Ssklower }
18036382Ssklower 
18140778Ssklower 
18240778Ssklower eoniphdr(hdr, loc, ro, class, zero)
18340778Ssklower struct route *ro;
18440778Ssklower register struct eon_iphdr *hdr;
18540778Ssklower caddr_t loc;
18640778Ssklower {
18740778Ssklower 	struct mbuf mhead;
18848751Ssklower 	extern struct ifnet loif;
18940778Ssklower 	register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst;
19040778Ssklower 	if (zero) {
19140778Ssklower 		bzero((caddr_t)hdr, sizeof (*hdr));
19240778Ssklower 		bzero((caddr_t)ro, sizeof (*ro));
19340778Ssklower 	}
19440778Ssklower 	sin->sin_family = AF_INET;
19540778Ssklower 	sin->sin_len = sizeof (*sin);
19640778Ssklower 	bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr));
19748751Ssklower 	/*
19848751Ssklower 	 * If there is a cached route,
19948751Ssklower 	 * check that it is to the same destination
20048751Ssklower 	 * and is still up.  If not, free it and try again.
20148751Ssklower 	 */
20248751Ssklower 	if (ro->ro_rt) {
20348751Ssklower 		struct sockaddr_in *dst =
20448751Ssklower 			(struct sockaddr_in *)rt_key(ro->ro_rt);
20548751Ssklower 		if ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
20648751Ssklower 		   sin->sin_addr.s_addr != dst->sin_addr.s_addr) {
20748751Ssklower 			RTFREE(ro->ro_rt);
20848751Ssklower 			ro->ro_rt = (struct rtentry *)0;
20948751Ssklower 		}
21048751Ssklower 	}
21148751Ssklower 	rtalloc(ro);
21248751Ssklower 	if (ro->ro_rt)
21348751Ssklower 		ro->ro_rt->rt_use++;
21440778Ssklower 	hdr->ei_ip.ip_dst = sin->sin_addr;
21540778Ssklower 	hdr->ei_ip.ip_p = IPPROTO_EON;
21640778Ssklower 	hdr->ei_ip.ip_ttl = MAXTTL;
21740778Ssklower 	hdr->ei_eh.eonh_class = class;
21840778Ssklower 	hdr->ei_eh.eonh_vers = EON_VERSION;
21940778Ssklower 	hdr->ei_eh.eonh_csum = 0;
22040778Ssklower 	mhead.m_data = (caddr_t) &hdr->ei_eh;
22140778Ssklower 	mhead.m_len = sizeof(struct eon_hdr);
22240778Ssklower 	mhead.m_next = 0;
22340778Ssklower 	IFDEBUG(D_EON)
22440778Ssklower 		printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
22540778Ssklower 			&mhead,
22640778Ssklower 			_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
22740778Ssklower 	ENDDEBUG
22840778Ssklower 	iso_gen_csum(&mhead,
22940778Ssklower 		_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
23040778Ssklower }
23136382Ssklower /*
23240778Ssklower  * FUNCTION:		eonrtrequest
23336382Ssklower  *
23440778Ssklower  * PURPOSE:			maintains list of direct eon recipients.
23540778Ssklower  *					sets up IP route for rest.
23636382Ssklower  *
23736382Ssklower  * RETURNS:			nothing
23836382Ssklower  */
23940778Ssklower eonrtrequest(cmd, rt, gate)
24040778Ssklower register struct rtentry *rt;
24142321Ssklower register struct sockaddr *gate;
24240778Ssklower {
24342321Ssklower 	unsigned long zerodst = 0;
24442321Ssklower 	caddr_t	ipaddrloc = (caddr_t) &zerodst;
24540778Ssklower 	register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo;
24636382Ssklower 
24740778Ssklower 	/*
24840778Ssklower 	 * Common Housekeeping
24940778Ssklower 	 */
25040778Ssklower 	switch (cmd) {
25143333Ssklower 	case RTM_DELETE:
25243333Ssklower 		if (el) {
25343333Ssklower 			remque(&(el->el_qhdr));
25443333Ssklower 			if (el->el_iproute.ro_rt)
25543333Ssklower 				RTFREE(el->el_iproute.ro_rt);
25643333Ssklower 			Free(el);
25743333Ssklower 			rt->rt_llinfo = 0;
25843333Ssklower 		}
25943333Ssklower 		return;
26040778Ssklower 
26148751Ssklower 	case RTM_ADD:
26243333Ssklower 	case RTM_RESOLVE:
26348751Ssklower 		rt->rt_rmx.rmx_mtu = loif.if_mtu; /* unless better below */
26443333Ssklower 		R_Malloc(el, struct eon_llinfo *, sizeof(*el));
26543333Ssklower 		rt->rt_llinfo = (caddr_t)el;
26643333Ssklower 		if (el == 0)
26743333Ssklower 			return;
26843333Ssklower 		Bzero(el, sizeof(*el));
26940778Ssklower 		insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
27040778Ssklower 		el->el_rt = rt;
27140778Ssklower 		break;
27240778Ssklower 	}
27340778Ssklower 	if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) {
27440778Ssklower 		case AF_LINK:
27542321Ssklower #define SDL(x) ((struct sockaddr_dl *)x)
27642321Ssklower 			if (SDL(gate)->sdl_alen = 1)
27742321Ssklower 				el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate));
27842321Ssklower 			else
27942321Ssklower 				ipaddrloc = LLADDR(SDL(gate));
28040778Ssklower 			break;
28140778Ssklower 		case AF_INET:
28242321Ssklower #define SIN(x) ((struct sockaddr_in *)x)
28342321Ssklower 			ipaddrloc = (caddr_t) &SIN(gate)->sin_addr;
28440778Ssklower 			break;
28540778Ssklower 		default:
28640778Ssklower 			return;
28740778Ssklower 	}
28840778Ssklower 	el->el_flags |= RTF_UP;
28941926Ssklower 	eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
29048751Ssklower 	if (el->el_iproute.ro_rt)
291*49616Ssklower 		rt->rt_rmx.rmx_mtu = el->el_iproute.ro_rt->rt_rmx.rmx_mtu
29249572Ssklower 							- sizeof(el->el_ei);
29336382Ssklower }
29436382Ssklower 
29536382Ssklower /*
29640778Ssklower  * FUNCTION:		eoninit
29736382Ssklower  *
29840778Ssklower  * PURPOSE:			initialization
29936382Ssklower  *
30036382Ssklower  * RETURNS:			nothing
30136382Ssklower  */
30236382Ssklower 
30340778Ssklower eoninit(unit)
30440778Ssklower 	int unit;
30536382Ssklower {
30640778Ssklower 	printf("eon driver-init eon%d\n", unit);
30736382Ssklower }
30836382Ssklower 
30936382Ssklower 
31036382Ssklower /*
31136382Ssklower  * FUNCTION:		eonoutput
31236382Ssklower  *
31336382Ssklower  * PURPOSE:			prepend an eon header and hand to IP
31436382Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
31536382Ssklower  *					(m)  is an mbuf *, *m is a CLNL packet
31636382Ssklower  *					(dst) is a destination address - have to interp. as
31736382Ssklower  *					multicast or broadcast or real address.
31836382Ssklower  *
31936382Ssklower  * RETURNS:			unix error code
32036382Ssklower  *
32136382Ssklower  * NOTES:
32236382Ssklower  *
32336382Ssklower  */
32440778Ssklower eonoutput(ifp, m, dst, rt)
32537469Ssklower 	struct ifnet 	*ifp;
32640778Ssklower 	register struct mbuf	*m;		/* packet */
32736382Ssklower 	struct sockaddr_iso		*dst;		/* destination addr */
32840778Ssklower 	struct rtentry *rt;
32936382Ssklower {
33040778Ssklower 	register struct eon_llinfo *el;
33140778Ssklower 	register struct eon_iphdr *ei;
33240778Ssklower 	struct route *ro;
33340778Ssklower 	int	datalen;
33440778Ssklower 	struct mbuf *mh;
33545896Ssklower 	int	error = 0, class = 0, alen = 0;
33645896Ssklower 	caddr_t ipaddrloc;
33740778Ssklower 	static struct eon_iphdr eon_iphdr;
33840778Ssklower 	static struct route route;
33936382Ssklower 
34036382Ssklower 	IFDEBUG(D_EON)
34136382Ssklower 		printf("eonoutput \n" );
34236382Ssklower 	ENDDEBUG
34336382Ssklower 
34439195Ssklower 	ifp->if_lastchange = time;
34539195Ssklower 	ifp->if_opackets++;
34640778Ssklower 	if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) {
34740778Ssklower 		if (dst->siso_family == AF_LINK) {
34840778Ssklower 			register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst;
34940778Ssklower 
35045896Ssklower 			ipaddrloc = LLADDR(sdl);
35145896Ssklower 			alen = sdl->sdl_alen;
35245896Ssklower 		} else if (dst->siso_family == AF_ISO && dst->siso_data[0] == AFI_SNA) {
35345896Ssklower 			alen = dst->siso_nlen - 1;
35445896Ssklower 			ipaddrloc = (caddr_t) dst->siso_data + 1;
35540778Ssklower 		}
35645896Ssklower 		switch (alen) {
35745896Ssklower 		case 5:
35845896Ssklower 			class =  4[(u_char *)ipaddrloc];
35945896Ssklower 		case 4:
36045896Ssklower 			ro = &route;
36145896Ssklower 			ei = &eon_iphdr;
36245896Ssklower 			eoniphdr(ei, ipaddrloc, ro, class, 1);
36345896Ssklower 			goto send;
36445896Ssklower 		}
36540778Ssklower einval:
36637469Ssklower 		error =  EINVAL;
36737469Ssklower 		goto flush;
36837469Ssklower 	}
36940778Ssklower 	if ((el->el_flags & RTF_UP) == 0) {
37040778Ssklower 		eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0);
37140778Ssklower 		if ((el->el_flags & RTF_UP) == 0) {
37240778Ssklower 			error = EHOSTUNREACH;
37340778Ssklower 			goto flush;
37440778Ssklower 		}
37540778Ssklower 	}
37640778Ssklower 	if ((m->m_flags & M_PKTHDR) == 0) {
37737469Ssklower 		printf("eon: got non headered packet\n");
37837469Ssklower 		goto einval;
37937469Ssklower 	}
38040778Ssklower 	ei = &el->el_ei;
38140778Ssklower 	ro = &el->el_iproute;
38242321Ssklower 	if (el->el_snpaoffset) {
38342321Ssklower 		if (dst->siso_family == AF_ISO) {
38442321Ssklower 			bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset],
38542321Ssklower 					(caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
38642321Ssklower 		} else
38742321Ssklower 			goto einval;
38842321Ssklower 	}
38940778Ssklower send:
39040778Ssklower 	/* put an eon_hdr in the buffer, prepended by an ip header */
39140778Ssklower 	datalen = m->m_pkthdr.len + EONIPLEN;
39237469Ssklower 	MGETHDR(mh, M_DONTWAIT, MT_HEADER);
39337469Ssklower 	if(mh == (struct mbuf *)0)
39440778Ssklower 		goto flush;
39540778Ssklower 	mh->m_next = m;
39640778Ssklower 	m = mh;
39740778Ssklower 	MH_ALIGN(m, sizeof(struct eon_iphdr));
39840778Ssklower 	m->m_len = sizeof(struct eon_iphdr);
39939195Ssklower 	ifp->if_obytes +=
40040778Ssklower 		(ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen));
40140778Ssklower 	*mtod(m, struct eon_iphdr *) = *ei;
40236382Ssklower 
40336382Ssklower 	IFDEBUG(D_EON)
40440778Ssklower 		printf("eonoutput dst ip addr : %x\n",  ei->ei_ip.ip_dst.s_addr);
40540778Ssklower 		printf("eonoutput ip_output : eonip header:\n");
40640778Ssklower 		dump_buf(ei, sizeof(struct eon_iphdr));
40736382Ssklower 	ENDDEBUG
40836382Ssklower 
40940778Ssklower 	error = ip_output(m, (struct mbuf *)0, ro, 0);
41040778Ssklower 	m = 0;
41139195Ssklower 	if (error) {
41239195Ssklower 		ifp->if_oerrors++;
41339195Ssklower 		ifp->if_opackets--;
41440778Ssklower 		ifp->if_obytes -= datalen;
41539195Ssklower 	}
41640778Ssklower flush:
41740778Ssklower 	if (m)
41840778Ssklower 		m_freem(m);
41936382Ssklower 	return error;
42036382Ssklower }
42136382Ssklower 
42237469Ssklower eoninput(m, iphlen)
42336382Ssklower 	register struct mbuf	*m;
42437469Ssklower 	int iphlen;
42536382Ssklower {
42636382Ssklower 	register struct eon_hdr	*eonhdr;
42736382Ssklower 	register struct ip		*iphdr;
42836382Ssklower 	struct ifnet 			*eonifp;
42937469Ssklower 	int						s;
43036382Ssklower 
43136382Ssklower 	eonifp = &eonif[0]; /* kludge - really want to give CLNP
43236382Ssklower 						* the ifp for eon, not for the real device
43336382Ssklower 						*/
43436382Ssklower 
43536382Ssklower 	IFDEBUG(D_EON)
43637469Ssklower 		printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
43737469Ssklower 			m, m?m->m_data:0, m?m->m_len:0);
43836382Ssklower 	ENDDEBUG
43936382Ssklower 
44037469Ssklower 	if (m == 0)
44137469Ssklower 		return;
44237469Ssklower 	if (iphlen > sizeof (struct ip))
44337469Ssklower 		ip_stripoptions(m, (struct mbuf *)0);
44437469Ssklower 	if (m->m_len < EONIPLEN) {
44537469Ssklower 		if ((m = m_pullup(m, EONIPLEN)) == 0) {
44637469Ssklower 			IncStat(es_badhdr);
44737469Ssklower drop:
44837469Ssklower 			IFDEBUG(D_EON)
44937469Ssklower 				printf("eoninput: DROP \n" );
45037469Ssklower 			ENDDEBUG
45137469Ssklower 			eonifp->if_ierrors ++;
45237469Ssklower 			m_freem(m);
45337469Ssklower 			return;
45437469Ssklower 		}
45536382Ssklower 	}
45639195Ssklower 	eonif->if_ibytes += m->m_pkthdr.len;
45739195Ssklower 	eonif->if_lastchange = time;
45836382Ssklower 	iphdr = mtod(m, struct ip *);
45936382Ssklower 	/* do a few checks for debugging */
46036382Ssklower 	if( iphdr->ip_p != IPPROTO_EON ) {
46136382Ssklower 		IncStat(es_badhdr);
46236382Ssklower 		goto drop;
46336382Ssklower 	}
46437469Ssklower 	/* temporarily drop ip header from the mbuf */
46537469Ssklower 	m->m_data += sizeof(struct ip);
46636382Ssklower 	eonhdr = mtod(m, struct eon_hdr *);
46737469Ssklower 	if( iso_check_csum( m, sizeof(struct eon_hdr) )   != EOK ) {
46837469Ssklower 		IncStat(es_badcsum);
46937469Ssklower 		goto drop;
47037469Ssklower 	}
47137469Ssklower 	m->m_data -= sizeof(struct ip);
47237469Ssklower 
47336382Ssklower 	IFDEBUG(D_EON)
47437469Ssklower 		printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
47536382Ssklower 		printf("eoninput: eon header:\n");
47636382Ssklower 		dump_buf(eonhdr, sizeof(struct eon_hdr));
47736382Ssklower 	ENDDEBUG
47836382Ssklower 
47936382Ssklower 	/* checks for debugging */
48036382Ssklower 	if( eonhdr->eonh_vers != EON_VERSION) {
48136382Ssklower 		IncStat(es_badhdr);
48236382Ssklower 		goto drop;
48336382Ssklower 	}
48437469Ssklower 	m->m_flags &= ~(M_BCAST|M_MCAST);
48536382Ssklower 	switch( eonhdr->eonh_class) {
48636382Ssklower 		case EON_BROADCAST:
48736382Ssklower 			IncStat(es_in_broad);
48837469Ssklower 			m->m_flags |= M_BCAST;
48936382Ssklower 			break;
49036382Ssklower 		case EON_NORMAL_ADDR:
49136382Ssklower 			IncStat(es_in_normal);
49236382Ssklower 			break;
49336382Ssklower 		case EON_MULTICAST_ES:
49436382Ssklower 			IncStat(es_in_multi_es);
49537469Ssklower 			m->m_flags |= M_MCAST;
49636382Ssklower 			break;
49736382Ssklower 		case EON_MULTICAST_IS:
49836382Ssklower 			IncStat(es_in_multi_is);
49937469Ssklower 			m->m_flags |= M_MCAST;
50036382Ssklower 			break;
50136382Ssklower 	}
50239195Ssklower 	eonifp->if_ipackets++;
50336382Ssklower 
50436382Ssklower 	{
50536382Ssklower 		/* put it on the CLNP queue and set soft interrupt */
50636382Ssklower 		struct ifqueue 			*ifq;
50736382Ssklower 		extern struct ifqueue 	clnlintrq;
50836382Ssklower 
50937469Ssklower 		m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
51036382Ssklower 		IFDEBUG(D_EON)
51136382Ssklower 			printf("eoninput to clnl IFQ\n");
51236382Ssklower 		ENDDEBUG
51336382Ssklower 		ifq = &clnlintrq;
51437469Ssklower 		s = splimp();
51536382Ssklower 		if (IF_QFULL(ifq)) {
51636382Ssklower 			IF_DROP(ifq);
51736382Ssklower 			m_freem(m);
51839195Ssklower 			eonifp->if_iqdrops++;
51939195Ssklower 			eonifp->if_ipackets--;
52036382Ssklower 			splx(s);
52136382Ssklower 			return;
52236382Ssklower 		}
52336382Ssklower 		IF_ENQUEUE(ifq, m);
52436382Ssklower 		IFDEBUG(D_EON)
52536382Ssklower 			printf(
52637469Ssklower 	"0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
52737469Ssklower 				m, m->m_len, m->m_type, m->m_data);
52836382Ssklower 			dump_buf(mtod(m, caddr_t), m->m_len);
52936382Ssklower 		ENDDEBUG
53037469Ssklower 		schednetisr(NETISR_ISO);
53137469Ssklower 		splx(s);
53236382Ssklower 	}
53336382Ssklower }
53436382Ssklower 
53536382Ssklower int
53636382Ssklower eonctlinput(cmd, sin)
53736382Ssklower 	int cmd;
53836382Ssklower 	struct sockaddr_in *sin;
53936382Ssklower {
54036382Ssklower 	extern u_char inetctlerrmap[];
54136382Ssklower 
54236382Ssklower 	IFDEBUG(D_EON)
54336382Ssklower 		printf("eonctlinput: cmd 0x%x addr: ", cmd);
54436382Ssklower 		dump_isoaddr(sin);
54536382Ssklower 		printf("\n");
54636382Ssklower 	ENDDEBUG
54736382Ssklower 
54836382Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
54936382Ssklower 		return 0;
55036382Ssklower 
55136382Ssklower 	IncStat(es_icmp[cmd]);
55236382Ssklower 	switch (cmd) {
55336382Ssklower 
55437469Ssklower 		case	PRC_QUENCH:
55536382Ssklower 		case	PRC_QUENCH2:
55636382Ssklower 			/* TODO: set the dec bit */
55736382Ssklower 			break;
55836382Ssklower 		case	PRC_TIMXCEED_REASS:
55936382Ssklower 		case	PRC_ROUTEDEAD:
56036382Ssklower 		case	PRC_HOSTUNREACH:
56136382Ssklower 		case	PRC_UNREACH_NET:
56236382Ssklower 		case	PRC_IFDOWN:
56336382Ssklower 		case	PRC_UNREACH_HOST:
56436382Ssklower 		case	PRC_HOSTDEAD:
56536382Ssklower 		case	PRC_TIMXCEED_INTRANS:
56636382Ssklower 			/* TODO: mark the link down */
56736382Ssklower 			break;
56836382Ssklower 
56936382Ssklower 		case	PRC_UNREACH_PROTOCOL:
57036382Ssklower 		case	PRC_UNREACH_PORT:
57136382Ssklower 		case	PRC_UNREACH_SRCFAIL:
57236382Ssklower 		case	PRC_REDIRECT_NET:
57336382Ssklower 		case	PRC_REDIRECT_HOST:
57436382Ssklower 		case	PRC_REDIRECT_TOSNET:
57536382Ssklower 		case	PRC_REDIRECT_TOSHOST:
57636382Ssklower 		case	PRC_MSGSIZE:
57736382Ssklower 		case	PRC_PARAMPROB:
57845896Ssklower 			/* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/
57936382Ssklower 		break;
58036382Ssklower 	}
58136382Ssklower 	return 0;
58236382Ssklower }
58336382Ssklower 
58437469Ssklower #endif
585