xref: /csrg-svn/sys/netiso/if_eon.c (revision 48751)
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 $
30*48751Ssklower  *	@(#)if_eon.c	7.12 (Berkeley) 04/26/91 *
3136382Ssklower  *
3236382Ssklower  *	EON rfc
3336382Ssklower  *  Layer between IP and CLNL
3436382Ssklower  *
3536382Ssklower  * TODO:
3636382Ssklower  * Put together a current rfc986 address format and get the right offset
3736382Ssklower  * for the nsel
3836382Ssklower  */
3936382Ssklower 
4036382Ssklower #ifndef lint
4136382Ssklower static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $";
4236382Ssklower #endif lint
4336382Ssklower 
4437469Ssklower #ifdef EON
4537469Ssklower #define NEON 1
4636382Ssklower 
4737469Ssklower 
4836382Ssklower #include "param.h"
4936382Ssklower #include "systm.h"
5036382Ssklower #include "types.h"
5136382Ssklower #include "mbuf.h"
5236382Ssklower #include "buf.h"
5336382Ssklower #include "protosw.h"
5436382Ssklower #include "socket.h"
5536382Ssklower #include "ioctl.h"
5636382Ssklower #include "errno.h"
5736382Ssklower #include "types.h"
5836382Ssklower 
5936382Ssklower #include "../net/if.h"
6039195Ssklower #include "../net/if_types.h"
6140778Ssklower #include "../net/if_dl.h"
6236382Ssklower #include "../net/netisr.h"
6336382Ssklower #include "../net/route.h"
6437518Smckusick #include "machine/mtpr.h"
6536382Ssklower 
6636382Ssklower #include "../netinet/in.h"
6736382Ssklower #include "../netinet/in_systm.h"
6840778Ssklower #include "../netinet/in_var.h"
6936382Ssklower #include "../netinet/ip.h"
7036382Ssklower #include "../netinet/ip_var.h"
7136382Ssklower #include "../netinet/if_ether.h"
7236382Ssklower 
7337469Ssklower #include "iso.h"
7437469Ssklower #include "iso_var.h"
7537469Ssklower #include "iso_snpac.h"
7637469Ssklower #include "argo_debug.h"
7737469Ssklower #include "iso_errno.h"
7837469Ssklower #include "eonvar.h"
7939195Ssklower extern struct timeval time;
8036382Ssklower 
8136382Ssklower #define EOK 0
8236382Ssklower 
8336382Ssklower int						eoninput();
8436382Ssklower int						eonoutput();
8536382Ssklower int						eonioctl();
8636382Ssklower int						eonattach();
8736382Ssklower int						eoninit();
8840778Ssklower int						eonrtrequest();
8936382Ssklower extern 	int				ip_output();
9040778Ssklower struct ifnet			eonif[1];
9136382Ssklower 
9237469Ssklower eonprotoinit() {
9340778Ssklower 	(void) eonattach();
9437469Ssklower }
9540778Ssklower 
9640778Ssklower struct eon_llinfo eon_llinfo;
9737469Ssklower #define PROBE_OK 0;
9836382Ssklower 
9937469Ssklower 
10036382Ssklower /*
10136382Ssklower  * FUNCTION:		eonattach
10236382Ssklower  *
10336382Ssklower  * PURPOSE:			autoconf attach routine
10436382Ssklower  *
10536382Ssklower  * RETURNS:			void
10636382Ssklower  */
10736382Ssklower 
10840778Ssklower eonattach()
10936382Ssklower {
11040778Ssklower 	register struct ifnet *ifp = eonif;
11136382Ssklower 
11236382Ssklower 	IFDEBUG(D_EON)
11336382Ssklower 		printf("eonattach()\n");
11436382Ssklower 	ENDDEBUG
11540778Ssklower 	ifp->if_unit = 0;
11636382Ssklower 	ifp->if_name = "eon";
11736382Ssklower 	ifp->if_mtu = ETHERMTU;
11836382Ssklower 		/* since everything will go out over ether or token ring */
11936382Ssklower 
12036382Ssklower 	ifp->if_init = eoninit;
12137469Ssklower 	ifp->if_ioctl = eonioctl;
12236382Ssklower 	ifp->if_output = eonoutput;
12337469Ssklower 	ifp->if_type = IFT_EON;
12437469Ssklower 	ifp->if_addrlen = 5;
12537469Ssklower 	ifp->if_hdrlen = EONIPLEN;
12636382Ssklower 	ifp->if_flags = IFF_BROADCAST;
12736382Ssklower 	if_attach(ifp);
12840778Ssklower 	eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist);
12940778Ssklower 	eon_llinfo.el_qhdr.link =
13040778Ssklower 		eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr);
13136382Ssklower 
13236382Ssklower 	IFDEBUG(D_EON)
13336382Ssklower 		printf("eonattach()\n");
13436382Ssklower 	ENDDEBUG
13536382Ssklower }
13636382Ssklower 
13736382Ssklower 
13836382Ssklower /*
13936382Ssklower  * FUNCTION:		eonioctl
14036382Ssklower  *
14136382Ssklower  * PURPOSE:			io controls - ifconfig
14236382Ssklower  *				need commands to
14336382Ssklower  *					link-UP (core addr) (flags: ES, IS)
14436382Ssklower  *					link-DOWN (core addr) (flags: ES, IS)
14536382Ssklower  *				must be callable from kernel or user
14636382Ssklower  *
14736382Ssklower  * RETURNS:			nothing
14836382Ssklower  */
14936382Ssklower eonioctl(ifp, cmd, data)
15036382Ssklower 	register struct ifnet *ifp;
15140778Ssklower 	int cmd;
15236382Ssklower 	register caddr_t data;
15336382Ssklower {
15440778Ssklower 	int s = splimp();
15536382Ssklower 	register int error = 0;
15636382Ssklower 
15736382Ssklower 	IFDEBUG(D_EON)
15836382Ssklower 		printf("eonioctl (cmd 0x%x) \n", cmd);
15936382Ssklower 	ENDDEBUG
16036382Ssklower 
16140778Ssklower 	switch (cmd) {
16240778Ssklower 		register struct ifaddr *ifa;
16336382Ssklower 
16436382Ssklower 	case SIOCSIFADDR:
16540778Ssklower 		if (ifa = (struct ifaddr *)data) {
16640778Ssklower 			ifp->if_flags |= IFF_UP;
16741393Ssklower 			if (ifa->ifa_addr->sa_family != AF_LINK)
16841393Ssklower 				ifa->ifa_rtrequest = eonrtrequest;
16940778Ssklower 			ifa->ifa_llinfolen = sizeof(struct eon_llinfo);
17041393Ssklower 		}
17136382Ssklower 		break;
17236382Ssklower 	}
17336382Ssklower 	splx(s);
17436382Ssklower 	return(error);
17536382Ssklower }
17636382Ssklower 
17740778Ssklower 
17840778Ssklower eoniphdr(hdr, loc, ro, class, zero)
17940778Ssklower struct route *ro;
18040778Ssklower register struct eon_iphdr *hdr;
18140778Ssklower caddr_t loc;
18240778Ssklower {
18340778Ssklower 	struct mbuf mhead;
184*48751Ssklower 	extern struct ifnet loif;
18540778Ssklower 	register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst;
18640778Ssklower 	if (zero) {
18740778Ssklower 		bzero((caddr_t)hdr, sizeof (*hdr));
18840778Ssklower 		bzero((caddr_t)ro, sizeof (*ro));
18940778Ssklower 	}
19040778Ssklower 	sin->sin_family = AF_INET;
19140778Ssklower 	sin->sin_len = sizeof (*sin);
19240778Ssklower 	bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr));
193*48751Ssklower 	/*
194*48751Ssklower 	 * If there is a cached route,
195*48751Ssklower 	 * check that it is to the same destination
196*48751Ssklower 	 * and is still up.  If not, free it and try again.
197*48751Ssklower 	 */
198*48751Ssklower 	if (ro->ro_rt) {
199*48751Ssklower 		struct sockaddr_in *dst =
200*48751Ssklower 			(struct sockaddr_in *)rt_key(ro->ro_rt);
201*48751Ssklower 		if ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
202*48751Ssklower 		   sin->sin_addr.s_addr != dst->sin_addr.s_addr) {
203*48751Ssklower 			RTFREE(ro->ro_rt);
204*48751Ssklower 			ro->ro_rt = (struct rtentry *)0;
205*48751Ssklower 		}
206*48751Ssklower 	}
207*48751Ssklower 	rtalloc(ro);
208*48751Ssklower 	if (ro->ro_rt)
209*48751Ssklower 		ro->ro_rt->rt_use++;
21040778Ssklower 	hdr->ei_ip.ip_dst = sin->sin_addr;
21140778Ssklower 	hdr->ei_ip.ip_p = IPPROTO_EON;
21240778Ssklower 	hdr->ei_ip.ip_ttl = MAXTTL;
21340778Ssklower 	hdr->ei_eh.eonh_class = class;
21440778Ssklower 	hdr->ei_eh.eonh_vers = EON_VERSION;
21540778Ssklower 	hdr->ei_eh.eonh_csum = 0;
21640778Ssklower 	mhead.m_data = (caddr_t) &hdr->ei_eh;
21740778Ssklower 	mhead.m_len = sizeof(struct eon_hdr);
21840778Ssklower 	mhead.m_next = 0;
21940778Ssklower 	IFDEBUG(D_EON)
22040778Ssklower 		printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n",
22140778Ssklower 			&mhead,
22240778Ssklower 			_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
22340778Ssklower 	ENDDEBUG
22440778Ssklower 	iso_gen_csum(&mhead,
22540778Ssklower 		_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
22640778Ssklower }
22736382Ssklower /*
22840778Ssklower  * FUNCTION:		eonrtrequest
22936382Ssklower  *
23040778Ssklower  * PURPOSE:			maintains list of direct eon recipients.
23140778Ssklower  *					sets up IP route for rest.
23236382Ssklower  *
23336382Ssklower  * RETURNS:			nothing
23436382Ssklower  */
23540778Ssklower eonrtrequest(cmd, rt, gate)
23640778Ssklower register struct rtentry *rt;
23742321Ssklower register struct sockaddr *gate;
23840778Ssklower {
23942321Ssklower 	unsigned long zerodst = 0;
24042321Ssklower 	caddr_t	ipaddrloc = (caddr_t) &zerodst;
24140778Ssklower 	register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo;
24236382Ssklower 
24340778Ssklower 	/*
24440778Ssklower 	 * Common Housekeeping
24540778Ssklower 	 */
24640778Ssklower 	switch (cmd) {
24743333Ssklower 	case RTM_DELETE:
24843333Ssklower 		if (el) {
24943333Ssklower 			remque(&(el->el_qhdr));
25043333Ssklower 			if (el->el_iproute.ro_rt)
25143333Ssklower 				RTFREE(el->el_iproute.ro_rt);
25243333Ssklower 			Free(el);
25343333Ssklower 			rt->rt_llinfo = 0;
25443333Ssklower 		}
25543333Ssklower 		return;
25640778Ssklower 
257*48751Ssklower 	case RTM_ADD:
25843333Ssklower 	case RTM_RESOLVE:
259*48751Ssklower 		rt->rt_rmx.rmx_mtu = loif.if_mtu; /* unless better below */
26043333Ssklower 		R_Malloc(el, struct eon_llinfo *, sizeof(*el));
26143333Ssklower 		rt->rt_llinfo = (caddr_t)el;
26243333Ssklower 		if (el == 0)
26343333Ssklower 			return;
26443333Ssklower 		Bzero(el, sizeof(*el));
26540778Ssklower 		insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
26640778Ssklower 		el->el_rt = rt;
26740778Ssklower 		break;
26840778Ssklower 	}
26940778Ssklower 	if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) {
27040778Ssklower 		case AF_LINK:
27142321Ssklower #define SDL(x) ((struct sockaddr_dl *)x)
27242321Ssklower 			if (SDL(gate)->sdl_alen = 1)
27342321Ssklower 				el->el_snpaoffset = *(u_char *)LLADDR(SDL(gate));
27442321Ssklower 			else
27542321Ssklower 				ipaddrloc = LLADDR(SDL(gate));
27640778Ssklower 			break;
27740778Ssklower 		case AF_INET:
27842321Ssklower #define SIN(x) ((struct sockaddr_in *)x)
27942321Ssklower 			ipaddrloc = (caddr_t) &SIN(gate)->sin_addr;
28040778Ssklower 			break;
28140778Ssklower 		default:
28240778Ssklower 			return;
28340778Ssklower 	}
28440778Ssklower 	el->el_flags |= RTF_UP;
28541926Ssklower 	eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
286*48751Ssklower 	if (el->el_iproute.ro_rt)
287*48751Ssklower 		rt->rt_rmx.rmx_mtu = el->el_iproute.ro_rt - sizeof(el->el_ei);
28836382Ssklower }
28936382Ssklower 
29036382Ssklower /*
29140778Ssklower  * FUNCTION:		eoninit
29236382Ssklower  *
29340778Ssklower  * PURPOSE:			initialization
29436382Ssklower  *
29536382Ssklower  * RETURNS:			nothing
29636382Ssklower  */
29736382Ssklower 
29840778Ssklower eoninit(unit)
29940778Ssklower 	int unit;
30036382Ssklower {
30140778Ssklower 	printf("eon driver-init eon%d\n", unit);
30236382Ssklower }
30336382Ssklower 
30436382Ssklower 
30536382Ssklower /*
30636382Ssklower  * FUNCTION:		eonoutput
30736382Ssklower  *
30836382Ssklower  * PURPOSE:			prepend an eon header and hand to IP
30936382Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
31036382Ssklower  *					(m)  is an mbuf *, *m is a CLNL packet
31136382Ssklower  *					(dst) is a destination address - have to interp. as
31236382Ssklower  *					multicast or broadcast or real address.
31336382Ssklower  *
31436382Ssklower  * RETURNS:			unix error code
31536382Ssklower  *
31636382Ssklower  * NOTES:
31736382Ssklower  *
31836382Ssklower  */
31940778Ssklower eonoutput(ifp, m, dst, rt)
32037469Ssklower 	struct ifnet 	*ifp;
32140778Ssklower 	register struct mbuf	*m;		/* packet */
32236382Ssklower 	struct sockaddr_iso		*dst;		/* destination addr */
32340778Ssklower 	struct rtentry *rt;
32436382Ssklower {
32540778Ssklower 	register struct eon_llinfo *el;
32640778Ssklower 	register struct eon_iphdr *ei;
32740778Ssklower 	struct route *ro;
32840778Ssklower 	int	datalen;
32940778Ssklower 	struct mbuf *mh;
33045896Ssklower 	int	error = 0, class = 0, alen = 0;
33145896Ssklower 	caddr_t ipaddrloc;
33240778Ssklower 	static struct eon_iphdr eon_iphdr;
33340778Ssklower 	static struct route route;
33436382Ssklower 
33536382Ssklower 	IFDEBUG(D_EON)
33636382Ssklower 		printf("eonoutput \n" );
33736382Ssklower 	ENDDEBUG
33836382Ssklower 
33939195Ssklower 	ifp->if_lastchange = time;
34039195Ssklower 	ifp->if_opackets++;
34140778Ssklower 	if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) {
34240778Ssklower 		if (dst->siso_family == AF_LINK) {
34340778Ssklower 			register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst;
34440778Ssklower 
34545896Ssklower 			ipaddrloc = LLADDR(sdl);
34645896Ssklower 			alen = sdl->sdl_alen;
34745896Ssklower 		} else if (dst->siso_family == AF_ISO && dst->siso_data[0] == AFI_SNA) {
34845896Ssklower 			alen = dst->siso_nlen - 1;
34945896Ssklower 			ipaddrloc = (caddr_t) dst->siso_data + 1;
35040778Ssklower 		}
35145896Ssklower 		switch (alen) {
35245896Ssklower 		case 5:
35345896Ssklower 			class =  4[(u_char *)ipaddrloc];
35445896Ssklower 		case 4:
35545896Ssklower 			ro = &route;
35645896Ssklower 			ei = &eon_iphdr;
35745896Ssklower 			eoniphdr(ei, ipaddrloc, ro, class, 1);
35845896Ssklower 			goto send;
35945896Ssklower 		}
36040778Ssklower einval:
36137469Ssklower 		error =  EINVAL;
36237469Ssklower 		goto flush;
36337469Ssklower 	}
36440778Ssklower 	if ((el->el_flags & RTF_UP) == 0) {
36540778Ssklower 		eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0);
36640778Ssklower 		if ((el->el_flags & RTF_UP) == 0) {
36740778Ssklower 			error = EHOSTUNREACH;
36840778Ssklower 			goto flush;
36940778Ssklower 		}
37040778Ssklower 	}
37140778Ssklower 	if ((m->m_flags & M_PKTHDR) == 0) {
37237469Ssklower 		printf("eon: got non headered packet\n");
37337469Ssklower 		goto einval;
37437469Ssklower 	}
37540778Ssklower 	ei = &el->el_ei;
37640778Ssklower 	ro = &el->el_iproute;
37742321Ssklower 	if (el->el_snpaoffset) {
37842321Ssklower 		if (dst->siso_family == AF_ISO) {
37942321Ssklower 			bcopy((caddr_t) &dst->siso_data[el->el_snpaoffset],
38042321Ssklower 					(caddr_t) &ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
38142321Ssklower 		} else
38242321Ssklower 			goto einval;
38342321Ssklower 	}
38440778Ssklower send:
38540778Ssklower 	/* put an eon_hdr in the buffer, prepended by an ip header */
38640778Ssklower 	datalen = m->m_pkthdr.len + EONIPLEN;
38737469Ssklower 	MGETHDR(mh, M_DONTWAIT, MT_HEADER);
38837469Ssklower 	if(mh == (struct mbuf *)0)
38940778Ssklower 		goto flush;
39040778Ssklower 	mh->m_next = m;
39140778Ssklower 	m = mh;
39240778Ssklower 	MH_ALIGN(m, sizeof(struct eon_iphdr));
39340778Ssklower 	m->m_len = sizeof(struct eon_iphdr);
39439195Ssklower 	ifp->if_obytes +=
39540778Ssklower 		(ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen));
39640778Ssklower 	*mtod(m, struct eon_iphdr *) = *ei;
39736382Ssklower 
39836382Ssklower 	IFDEBUG(D_EON)
39940778Ssklower 		printf("eonoutput dst ip addr : %x\n",  ei->ei_ip.ip_dst.s_addr);
40040778Ssklower 		printf("eonoutput ip_output : eonip header:\n");
40140778Ssklower 		dump_buf(ei, sizeof(struct eon_iphdr));
40236382Ssklower 	ENDDEBUG
40336382Ssklower 
40440778Ssklower 	error = ip_output(m, (struct mbuf *)0, ro, 0);
40540778Ssklower 	m = 0;
40639195Ssklower 	if (error) {
40739195Ssklower 		ifp->if_oerrors++;
40839195Ssklower 		ifp->if_opackets--;
40940778Ssklower 		ifp->if_obytes -= datalen;
41039195Ssklower 	}
41140778Ssklower flush:
41240778Ssklower 	if (m)
41340778Ssklower 		m_freem(m);
41436382Ssklower 	return error;
41536382Ssklower }
41636382Ssklower 
41737469Ssklower eoninput(m, iphlen)
41836382Ssklower 	register struct mbuf	*m;
41937469Ssklower 	int iphlen;
42036382Ssklower {
42136382Ssklower 	register struct eon_hdr	*eonhdr;
42236382Ssklower 	register struct ip		*iphdr;
42336382Ssklower 	struct ifnet 			*eonifp;
42437469Ssklower 	int						s;
42536382Ssklower 
42636382Ssklower 	eonifp = &eonif[0]; /* kludge - really want to give CLNP
42736382Ssklower 						* the ifp for eon, not for the real device
42836382Ssklower 						*/
42936382Ssklower 
43036382Ssklower 	IFDEBUG(D_EON)
43137469Ssklower 		printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n",
43237469Ssklower 			m, m?m->m_data:0, m?m->m_len:0);
43336382Ssklower 	ENDDEBUG
43436382Ssklower 
43537469Ssklower 	if (m == 0)
43637469Ssklower 		return;
43737469Ssklower 	if (iphlen > sizeof (struct ip))
43837469Ssklower 		ip_stripoptions(m, (struct mbuf *)0);
43937469Ssklower 	if (m->m_len < EONIPLEN) {
44037469Ssklower 		if ((m = m_pullup(m, EONIPLEN)) == 0) {
44137469Ssklower 			IncStat(es_badhdr);
44237469Ssklower drop:
44337469Ssklower 			IFDEBUG(D_EON)
44437469Ssklower 				printf("eoninput: DROP \n" );
44537469Ssklower 			ENDDEBUG
44637469Ssklower 			eonifp->if_ierrors ++;
44737469Ssklower 			m_freem(m);
44837469Ssklower 			return;
44937469Ssklower 		}
45036382Ssklower 	}
45139195Ssklower 	eonif->if_ibytes += m->m_pkthdr.len;
45239195Ssklower 	eonif->if_lastchange = time;
45336382Ssklower 	iphdr = mtod(m, struct ip *);
45436382Ssklower 	/* do a few checks for debugging */
45536382Ssklower 	if( iphdr->ip_p != IPPROTO_EON ) {
45636382Ssklower 		IncStat(es_badhdr);
45736382Ssklower 		goto drop;
45836382Ssklower 	}
45937469Ssklower 	/* temporarily drop ip header from the mbuf */
46037469Ssklower 	m->m_data += sizeof(struct ip);
46136382Ssklower 	eonhdr = mtod(m, struct eon_hdr *);
46237469Ssklower 	if( iso_check_csum( m, sizeof(struct eon_hdr) )   != EOK ) {
46337469Ssklower 		IncStat(es_badcsum);
46437469Ssklower 		goto drop;
46537469Ssklower 	}
46637469Ssklower 	m->m_data -= sizeof(struct ip);
46737469Ssklower 
46836382Ssklower 	IFDEBUG(D_EON)
46937469Ssklower 		printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class );
47036382Ssklower 		printf("eoninput: eon header:\n");
47136382Ssklower 		dump_buf(eonhdr, sizeof(struct eon_hdr));
47236382Ssklower 	ENDDEBUG
47336382Ssklower 
47436382Ssklower 	/* checks for debugging */
47536382Ssklower 	if( eonhdr->eonh_vers != EON_VERSION) {
47636382Ssklower 		IncStat(es_badhdr);
47736382Ssklower 		goto drop;
47836382Ssklower 	}
47937469Ssklower 	m->m_flags &= ~(M_BCAST|M_MCAST);
48036382Ssklower 	switch( eonhdr->eonh_class) {
48136382Ssklower 		case EON_BROADCAST:
48236382Ssklower 			IncStat(es_in_broad);
48337469Ssklower 			m->m_flags |= M_BCAST;
48436382Ssklower 			break;
48536382Ssklower 		case EON_NORMAL_ADDR:
48636382Ssklower 			IncStat(es_in_normal);
48736382Ssklower 			break;
48836382Ssklower 		case EON_MULTICAST_ES:
48936382Ssklower 			IncStat(es_in_multi_es);
49037469Ssklower 			m->m_flags |= M_MCAST;
49136382Ssklower 			break;
49236382Ssklower 		case EON_MULTICAST_IS:
49336382Ssklower 			IncStat(es_in_multi_is);
49437469Ssklower 			m->m_flags |= M_MCAST;
49536382Ssklower 			break;
49636382Ssklower 	}
49739195Ssklower 	eonifp->if_ipackets++;
49836382Ssklower 
49936382Ssklower 	{
50036382Ssklower 		/* put it on the CLNP queue and set soft interrupt */
50136382Ssklower 		struct ifqueue 			*ifq;
50236382Ssklower 		extern struct ifqueue 	clnlintrq;
50336382Ssklower 
50437469Ssklower 		m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
50536382Ssklower 		IFDEBUG(D_EON)
50636382Ssklower 			printf("eoninput to clnl IFQ\n");
50736382Ssklower 		ENDDEBUG
50836382Ssklower 		ifq = &clnlintrq;
50937469Ssklower 		s = splimp();
51036382Ssklower 		if (IF_QFULL(ifq)) {
51136382Ssklower 			IF_DROP(ifq);
51236382Ssklower 			m_freem(m);
51339195Ssklower 			eonifp->if_iqdrops++;
51439195Ssklower 			eonifp->if_ipackets--;
51536382Ssklower 			splx(s);
51636382Ssklower 			return;
51736382Ssklower 		}
51836382Ssklower 		IF_ENQUEUE(ifq, m);
51936382Ssklower 		IFDEBUG(D_EON)
52036382Ssklower 			printf(
52137469Ssklower 	"0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n",
52237469Ssklower 				m, m->m_len, m->m_type, m->m_data);
52336382Ssklower 			dump_buf(mtod(m, caddr_t), m->m_len);
52436382Ssklower 		ENDDEBUG
52537469Ssklower 		schednetisr(NETISR_ISO);
52637469Ssklower 		splx(s);
52736382Ssklower 	}
52836382Ssklower }
52936382Ssklower 
53036382Ssklower int
53136382Ssklower eonctlinput(cmd, sin)
53236382Ssklower 	int cmd;
53336382Ssklower 	struct sockaddr_in *sin;
53436382Ssklower {
53536382Ssklower 	extern u_char inetctlerrmap[];
53636382Ssklower 
53736382Ssklower 	IFDEBUG(D_EON)
53836382Ssklower 		printf("eonctlinput: cmd 0x%x addr: ", cmd);
53936382Ssklower 		dump_isoaddr(sin);
54036382Ssklower 		printf("\n");
54136382Ssklower 	ENDDEBUG
54236382Ssklower 
54336382Ssklower 	if (cmd < 0 || cmd > PRC_NCMDS)
54436382Ssklower 		return 0;
54536382Ssklower 
54636382Ssklower 	IncStat(es_icmp[cmd]);
54736382Ssklower 	switch (cmd) {
54836382Ssklower 
54937469Ssklower 		case	PRC_QUENCH:
55036382Ssklower 		case	PRC_QUENCH2:
55136382Ssklower 			/* TODO: set the dec bit */
55236382Ssklower 			break;
55336382Ssklower 		case	PRC_TIMXCEED_REASS:
55436382Ssklower 		case	PRC_ROUTEDEAD:
55536382Ssklower 		case	PRC_HOSTUNREACH:
55636382Ssklower 		case	PRC_UNREACH_NET:
55736382Ssklower 		case	PRC_IFDOWN:
55836382Ssklower 		case	PRC_UNREACH_HOST:
55936382Ssklower 		case	PRC_HOSTDEAD:
56036382Ssklower 		case	PRC_TIMXCEED_INTRANS:
56136382Ssklower 			/* TODO: mark the link down */
56236382Ssklower 			break;
56336382Ssklower 
56436382Ssklower 		case	PRC_UNREACH_PROTOCOL:
56536382Ssklower 		case	PRC_UNREACH_PORT:
56636382Ssklower 		case	PRC_UNREACH_SRCFAIL:
56736382Ssklower 		case	PRC_REDIRECT_NET:
56836382Ssklower 		case	PRC_REDIRECT_HOST:
56936382Ssklower 		case	PRC_REDIRECT_TOSNET:
57036382Ssklower 		case	PRC_REDIRECT_TOSHOST:
57136382Ssklower 		case	PRC_MSGSIZE:
57236382Ssklower 		case	PRC_PARAMPROB:
57345896Ssklower 			/* printf("eonctlinput: ICMP cmd 0x%x\n", cmd );*/
57436382Ssklower 		break;
57536382Ssklower 	}
57636382Ssklower 	return 0;
57736382Ssklower }
57836382Ssklower 
57937469Ssklower #endif
580