1997-03-15 21:09:08 +03:00
|
|
|
/* $NetBSD: if_eon.c,v 1.20 1997/03/15 18:12:38 is Exp $ */
|
1994-06-29 10:39:25 +04:00
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
/*-
|
1994-05-13 10:08:03 +04:00
|
|
|
* Copyright (c) 1991, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
1993-04-09 16:00:07 +04:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
|
|
* must display the following acknowledgement:
|
|
|
|
* This product includes software developed by the University of
|
|
|
|
* California, Berkeley and its contributors.
|
|
|
|
* 4. Neither the name of the University nor the names of its contributors
|
|
|
|
* may be used to endorse or promote products derived from this software
|
|
|
|
* without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
1994-06-29 10:39:25 +04:00
|
|
|
* @(#)if_eon.c 8.1 (Berkeley) 6/10/93
|
1993-04-09 16:00:07 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
/***********************************************************
|
|
|
|
Copyright IBM Corporation 1987
|
|
|
|
|
|
|
|
All Rights Reserved
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
Permission to use, copy, modify, and distribute this software and its
|
|
|
|
documentation for any purpose and without fee is hereby granted,
|
1993-04-09 16:00:07 +04:00
|
|
|
provided that the above copyright notice appear in all copies and that
|
1996-02-14 01:07:57 +03:00
|
|
|
both that copyright notice and this permission notice appear in
|
1993-04-09 16:00:07 +04:00
|
|
|
supporting documentation, and that the name of IBM not be
|
|
|
|
used in advertising or publicity pertaining to distribution of the
|
1996-02-14 01:07:57 +03:00
|
|
|
software without specific, written prior permission.
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
|
|
IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
|
|
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
|
|
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
|
|
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
SOFTWARE.
|
|
|
|
|
|
|
|
******************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
|
|
|
|
*/
|
|
|
|
/*
|
1996-02-14 01:07:57 +03:00
|
|
|
* EON rfc
|
1993-04-09 16:00:07 +04:00
|
|
|
* Layer between IP and CLNL
|
|
|
|
*
|
|
|
|
* TODO:
|
|
|
|
* Put together a current rfc986 address format and get the right offset
|
|
|
|
* for the nsel
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef EON
|
|
|
|
#define NEON 1
|
|
|
|
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/buf.h>
|
|
|
|
#include <sys/protosw.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
1996-05-10 02:29:25 +04:00
|
|
|
#include <machine/cpu.h> /* XXX for setsoftnet(). This must die. */
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/netisr.h>
|
|
|
|
#include <net/route.h>
|
|
|
|
|
1997-03-15 21:09:08 +03:00
|
|
|
#include <net/if_ether.h>
|
|
|
|
|
1993-12-18 03:40:47 +03:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
#include <netinet/ip_var.h>
|
|
|
|
|
|
|
|
#include <netiso/iso.h>
|
|
|
|
#include <netiso/iso_var.h>
|
|
|
|
#include <netiso/iso_snpac.h>
|
|
|
|
#include <netiso/argo_debug.h>
|
|
|
|
#include <netiso/iso_errno.h>
|
|
|
|
#include <netiso/eonvar.h>
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#include <machine/stdarg.h>
|
|
|
|
|
1993-04-09 16:00:07 +04:00
|
|
|
extern struct timeval time;
|
|
|
|
extern struct ifnet loif;
|
|
|
|
|
|
|
|
#define EOK 0
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
struct ifnet eonif[1];
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
void
|
|
|
|
eonprotoinit()
|
|
|
|
{
|
1993-04-09 16:00:07 +04:00
|
|
|
(void) eonattach();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct eon_llinfo eon_llinfo;
|
|
|
|
#define PROBE_OK 0;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: eonattach
|
|
|
|
*
|
|
|
|
* PURPOSE: autoconf attach routine
|
|
|
|
*
|
|
|
|
* RETURNS: void
|
|
|
|
*/
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
void
|
1993-04-09 16:00:07 +04:00
|
|
|
eonattach()
|
|
|
|
{
|
|
|
|
register struct ifnet *ifp = eonif;
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonattach()\n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1996-10-13 06:03:00 +04:00
|
|
|
sprintf(ifp->if_xname, "eon%d", 0);
|
1996-02-14 01:07:57 +03:00
|
|
|
ifp->if_mtu = ETHERMTU;
|
1996-05-07 06:40:22 +04:00
|
|
|
ifp->if_softc = NULL;
|
1996-02-14 01:07:57 +03:00
|
|
|
/* since everything will go out over ether or token ring */
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
ifp->if_ioctl = eonioctl;
|
|
|
|
ifp->if_output = eonoutput;
|
|
|
|
ifp->if_type = IFT_EON;
|
|
|
|
ifp->if_addrlen = 5;
|
|
|
|
ifp->if_hdrlen = EONIPLEN;
|
|
|
|
ifp->if_flags = IFF_BROADCAST;
|
|
|
|
if_attach(ifp);
|
1996-02-14 01:07:57 +03:00
|
|
|
eonioctl(ifp, SIOCSIFADDR, (caddr_t) ifp->if_addrlist.tqh_first);
|
|
|
|
eon_llinfo.el_qhdr.link =
|
1993-04-09 16:00:07 +04:00
|
|
|
eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr);
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonattach()\n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: eonioctl
|
|
|
|
*
|
|
|
|
* PURPOSE: io controls - ifconfig
|
1996-02-14 01:07:57 +03:00
|
|
|
* need commands to
|
1993-04-09 16:00:07 +04:00
|
|
|
* link-UP (core addr) (flags: ES, IS)
|
|
|
|
* link-DOWN (core addr) (flags: ES, IS)
|
|
|
|
* must be callable from kernel or user
|
|
|
|
*
|
|
|
|
* RETURNS: nothing
|
|
|
|
*/
|
1996-02-14 01:07:57 +03:00
|
|
|
int
|
1993-04-09 16:00:07 +04:00
|
|
|
eonioctl(ifp, cmd, data)
|
|
|
|
register struct ifnet *ifp;
|
1996-02-14 01:07:57 +03:00
|
|
|
u_long cmd;
|
1993-04-09 16:00:07 +04:00
|
|
|
register caddr_t data;
|
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
int s = splimp();
|
|
|
|
register int error = 0;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonioctl (cmd 0x%lx) \n", cmd);
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
register struct ifaddr *ifa;
|
|
|
|
|
|
|
|
case SIOCSIFADDR:
|
1996-02-14 01:07:57 +03:00
|
|
|
if ((ifa = (struct ifaddr *) data) != NULL) {
|
1993-04-09 16:00:07 +04:00
|
|
|
ifp->if_flags |= IFF_UP;
|
|
|
|
if (ifa->ifa_addr->sa_family != AF_LINK)
|
|
|
|
ifa->ifa_rtrequest = eonrtrequest;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
splx(s);
|
1996-02-14 01:07:57 +03:00
|
|
|
return (error);
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
void
|
1993-04-09 16:00:07 +04:00
|
|
|
eoniphdr(hdr, loc, ro, class, zero)
|
1996-02-14 01:07:57 +03:00
|
|
|
struct route *ro;
|
|
|
|
register struct eon_iphdr *hdr;
|
|
|
|
caddr_t loc;
|
|
|
|
int class, zero;
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
struct mbuf mhead;
|
1995-06-13 11:13:14 +04:00
|
|
|
register struct sockaddr_in *sin = satosin(&ro->ro_dst);
|
1993-04-09 16:00:07 +04:00
|
|
|
if (zero) {
|
1996-02-14 01:07:57 +03:00
|
|
|
bzero((caddr_t) hdr, sizeof(*hdr));
|
|
|
|
bzero((caddr_t) ro, sizeof(*ro));
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
sin->sin_family = AF_INET;
|
1996-02-14 01:07:57 +03:00
|
|
|
sin->sin_len = sizeof(*sin);
|
|
|
|
bcopy(loc, (caddr_t) & sin->sin_addr, sizeof(struct in_addr));
|
1993-04-09 16:00:07 +04:00
|
|
|
/*
|
|
|
|
* If there is a cached route,
|
|
|
|
* check that it is to the same destination
|
|
|
|
* and is still up. If not, free it and try again.
|
|
|
|
*/
|
|
|
|
if (ro->ro_rt) {
|
1995-06-13 11:13:14 +04:00
|
|
|
struct sockaddr_in *dst = satosin(rt_key(ro->ro_rt));
|
1993-04-09 16:00:07 +04:00
|
|
|
if ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
|
1996-02-14 01:07:57 +03:00
|
|
|
sin->sin_addr.s_addr != dst->sin_addr.s_addr) {
|
1993-04-09 16:00:07 +04:00
|
|
|
RTFREE(ro->ro_rt);
|
1996-02-14 01:07:57 +03:00
|
|
|
ro->ro_rt = (struct rtentry *) 0;
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rtalloc(ro);
|
|
|
|
if (ro->ro_rt)
|
|
|
|
ro->ro_rt->rt_use++;
|
|
|
|
hdr->ei_ip.ip_dst = sin->sin_addr;
|
|
|
|
hdr->ei_ip.ip_p = IPPROTO_EON;
|
1996-02-14 01:07:57 +03:00
|
|
|
hdr->ei_ip.ip_ttl = MAXTTL;
|
1993-04-09 16:00:07 +04:00
|
|
|
hdr->ei_eh.eonh_class = class;
|
|
|
|
hdr->ei_eh.eonh_vers = EON_VERSION;
|
|
|
|
hdr->ei_eh.eonh_csum = 0;
|
1996-02-14 01:07:57 +03:00
|
|
|
mhead.m_data = (caddr_t) & hdr->ei_eh;
|
1993-04-09 16:00:07 +04:00
|
|
|
mhead.m_len = sizeof(struct eon_hdr);
|
|
|
|
mhead.m_next = 0;
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-11-13 23:00:15 +03:00
|
|
|
printf("eonoutput : gen csum (%p, offset %d, datalen %ld)\n",
|
1996-10-11 03:12:43 +04:00
|
|
|
&mhead, _offsetof(struct eon_hdr, eonh_csum),
|
1996-11-24 00:13:18 +03:00
|
|
|
(long)sizeof(struct eon_hdr));
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
iso_gen_csum(&mhead,
|
|
|
|
_offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr));
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* FUNCTION: eonrtrequest
|
|
|
|
*
|
|
|
|
* PURPOSE: maintains list of direct eon recipients.
|
|
|
|
* sets up IP route for rest.
|
|
|
|
*
|
|
|
|
* RETURNS: nothing
|
|
|
|
*/
|
1994-05-13 10:08:03 +04:00
|
|
|
void
|
1993-04-09 16:00:07 +04:00
|
|
|
eonrtrequest(cmd, rt, gate)
|
1996-02-14 01:07:57 +03:00
|
|
|
int cmd;
|
|
|
|
register struct rtentry *rt;
|
|
|
|
register struct sockaddr *gate;
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
unsigned long zerodst = 0;
|
|
|
|
caddr_t ipaddrloc = (caddr_t) & zerodst;
|
|
|
|
register struct eon_llinfo *el = (struct eon_llinfo *) rt->rt_llinfo;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Common Housekeeping
|
|
|
|
*/
|
|
|
|
switch (cmd) {
|
|
|
|
case RTM_DELETE:
|
|
|
|
if (el) {
|
|
|
|
remque(&(el->el_qhdr));
|
|
|
|
if (el->el_iproute.ro_rt)
|
|
|
|
RTFREE(el->el_iproute.ro_rt);
|
|
|
|
Free(el);
|
|
|
|
rt->rt_llinfo = 0;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
case RTM_ADD:
|
|
|
|
case RTM_RESOLVE:
|
1996-02-14 01:07:57 +03:00
|
|
|
rt->rt_rmx.rmx_mtu = loif.if_mtu; /* unless better below */
|
1993-04-09 16:00:07 +04:00
|
|
|
R_Malloc(el, struct eon_llinfo *, sizeof(*el));
|
1996-02-14 01:07:57 +03:00
|
|
|
rt->rt_llinfo = (caddr_t) el;
|
1993-04-09 16:00:07 +04:00
|
|
|
if (el == 0)
|
|
|
|
return;
|
|
|
|
Bzero(el, sizeof(*el));
|
|
|
|
insque(&(el->el_qhdr), &eon_llinfo.el_qhdr);
|
|
|
|
el->el_rt = rt;
|
|
|
|
break;
|
|
|
|
}
|
1996-02-14 01:07:57 +03:00
|
|
|
if (gate || (gate = rt->rt_gateway))
|
|
|
|
switch (gate->sa_family) {
|
1993-04-09 16:00:07 +04:00
|
|
|
case AF_LINK:
|
|
|
|
#define SDL(x) ((struct sockaddr_dl *)x)
|
1994-05-13 10:08:03 +04:00
|
|
|
if (SDL(gate)->sdl_alen == 1)
|
1996-02-14 01:07:57 +03:00
|
|
|
el->el_snpaoffset = *(u_char *) LLADDR(SDL(gate));
|
1993-04-09 16:00:07 +04:00
|
|
|
else
|
|
|
|
ipaddrloc = LLADDR(SDL(gate));
|
|
|
|
break;
|
|
|
|
case AF_INET:
|
1996-02-14 01:07:57 +03:00
|
|
|
ipaddrloc = (caddr_t) & satosin(gate)->sin_addr;
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
1993-04-09 16:00:07 +04:00
|
|
|
el->el_flags |= RTF_UP;
|
|
|
|
eoniphdr(&el->el_ei, ipaddrloc, &el->el_iproute, EON_NORMAL_ADDR, 0);
|
|
|
|
if (el->el_iproute.ro_rt)
|
|
|
|
rt->rt_rmx.rmx_mtu = el->el_iproute.ro_rt->rt_rmx.rmx_mtu
|
1996-02-14 01:07:57 +03:00
|
|
|
- sizeof(el->el_ei);
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FUNCTION: eonoutput
|
|
|
|
*
|
1996-02-14 01:07:57 +03:00
|
|
|
* PURPOSE: prepend an eon header and hand to IP
|
|
|
|
* ARGUMENTS: (ifp) is points to the ifnet structure for this
|
|
|
|
* unit/device (m) is an mbuf *, *m is a CLNL packet
|
|
|
|
* (dst) is a destination address - have to interp. as
|
|
|
|
* multicast or broadcast or real address.
|
1993-04-09 16:00:07 +04:00
|
|
|
*
|
1996-02-14 01:07:57 +03:00
|
|
|
* RETURNS: unix error code
|
1993-04-09 16:00:07 +04:00
|
|
|
*
|
1996-02-14 01:07:57 +03:00
|
|
|
* NOTES:
|
1993-04-09 16:00:07 +04:00
|
|
|
*
|
|
|
|
*/
|
1996-02-14 01:07:57 +03:00
|
|
|
int
|
|
|
|
eonoutput(ifp, m, sdst, rt)
|
|
|
|
struct ifnet *ifp;
|
|
|
|
register struct mbuf *m; /* packet */
|
|
|
|
struct sockaddr *sdst; /* destination addr */
|
1993-04-09 16:00:07 +04:00
|
|
|
struct rtentry *rt;
|
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
struct sockaddr_iso *dst = (struct sockaddr_iso *) sdst;
|
1993-04-09 16:00:07 +04:00
|
|
|
register struct eon_llinfo *el;
|
|
|
|
register struct eon_iphdr *ei;
|
1996-02-14 01:07:57 +03:00
|
|
|
struct route *ro;
|
|
|
|
int datalen;
|
|
|
|
struct mbuf *mh;
|
|
|
|
int error = 0, class = 0, alen = 0;
|
|
|
|
caddr_t ipaddrloc = NULL;
|
1993-04-09 16:00:07 +04:00
|
|
|
static struct eon_iphdr eon_iphdr;
|
|
|
|
static struct route route;
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonoutput \n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
ifp->if_lastchange = time;
|
|
|
|
ifp->if_opackets++;
|
1996-02-14 01:07:57 +03:00
|
|
|
if (rt == 0 || (el = (struct eon_llinfo *) rt->rt_llinfo) == 0) {
|
1993-04-09 16:00:07 +04:00
|
|
|
if (dst->siso_family == AF_LINK) {
|
1996-02-14 01:07:57 +03:00
|
|
|
register struct sockaddr_dl *sdl = (struct sockaddr_dl *) dst;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
ipaddrloc = LLADDR(sdl);
|
|
|
|
alen = sdl->sdl_alen;
|
1996-02-14 01:07:57 +03:00
|
|
|
} else if (dst->siso_family == AF_ISO &&
|
|
|
|
dst->siso_data[0] == AFI_SNA) {
|
1993-04-09 16:00:07 +04:00
|
|
|
alen = dst->siso_nlen - 1;
|
|
|
|
ipaddrloc = (caddr_t) dst->siso_data + 1;
|
|
|
|
}
|
|
|
|
switch (alen) {
|
|
|
|
case 5:
|
1996-02-14 01:07:57 +03:00
|
|
|
class = 4[(u_char *) ipaddrloc];
|
1993-04-09 16:00:07 +04:00
|
|
|
case 4:
|
|
|
|
ro = &route;
|
|
|
|
ei = &eon_iphdr;
|
|
|
|
eoniphdr(ei, ipaddrloc, ro, class, 1);
|
|
|
|
goto send;
|
|
|
|
}
|
|
|
|
einval:
|
1996-02-14 01:07:57 +03:00
|
|
|
error = EINVAL;
|
1993-04-09 16:00:07 +04:00
|
|
|
goto flush;
|
|
|
|
}
|
|
|
|
if ((el->el_flags & RTF_UP) == 0) {
|
1996-02-14 01:07:57 +03:00
|
|
|
eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *) 0);
|
1993-04-09 16:00:07 +04:00
|
|
|
if ((el->el_flags & RTF_UP) == 0) {
|
|
|
|
error = EHOSTUNREACH;
|
|
|
|
goto flush;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((m->m_flags & M_PKTHDR) == 0) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eon: got non headered packet\n");
|
1993-04-09 16:00:07 +04:00
|
|
|
goto einval;
|
|
|
|
}
|
|
|
|
ei = &el->el_ei;
|
|
|
|
ro = &el->el_iproute;
|
|
|
|
if (el->el_snpaoffset) {
|
|
|
|
if (dst->siso_family == AF_ISO) {
|
1996-02-14 01:07:57 +03:00
|
|
|
bcopy((caddr_t) & dst->siso_data[el->el_snpaoffset],
|
|
|
|
(caddr_t) & ei->ei_ip.ip_dst, sizeof(ei->ei_ip.ip_dst));
|
1993-04-09 16:00:07 +04:00
|
|
|
} else
|
|
|
|
goto einval;
|
|
|
|
}
|
|
|
|
send:
|
|
|
|
/* put an eon_hdr in the buffer, prepended by an ip header */
|
|
|
|
datalen = m->m_pkthdr.len + EONIPLEN;
|
|
|
|
MGETHDR(mh, M_DONTWAIT, MT_HEADER);
|
1996-02-14 01:07:57 +03:00
|
|
|
if (mh == (struct mbuf *) 0)
|
1993-04-09 16:00:07 +04:00
|
|
|
goto flush;
|
|
|
|
mh->m_next = m;
|
|
|
|
m = mh;
|
|
|
|
MH_ALIGN(m, sizeof(struct eon_iphdr));
|
|
|
|
m->m_len = sizeof(struct eon_iphdr);
|
|
|
|
ifp->if_obytes +=
|
1996-02-14 01:07:57 +03:00
|
|
|
(ei->ei_ip.ip_len = (u_short) (m->m_pkthdr.len = datalen));
|
1993-04-09 16:00:07 +04:00
|
|
|
*mtod(m, struct eon_iphdr *) = *ei;
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonoutput dst ip addr : %x\n", ei->ei_ip.ip_dst.s_addr);
|
|
|
|
printf("eonoutput ip_output : eonip header:\n");
|
1993-04-09 16:00:07 +04:00
|
|
|
dump_buf(ei, sizeof(struct eon_iphdr));
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
error = ip_output(m, (struct mbuf *) 0, ro, 0, NULL);
|
1993-04-09 16:00:07 +04:00
|
|
|
m = 0;
|
|
|
|
if (error) {
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
ifp->if_opackets--;
|
|
|
|
ifp->if_obytes -= datalen;
|
|
|
|
}
|
|
|
|
flush:
|
|
|
|
if (m)
|
|
|
|
m_freem(m);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
void
|
|
|
|
#if __STDC__
|
|
|
|
eoninput(struct mbuf *m, ...)
|
|
|
|
#else
|
|
|
|
eoninput(m, va_alist)
|
|
|
|
struct mbuf *m;
|
|
|
|
va_dcl
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
int iphlen;
|
|
|
|
register struct eon_hdr *eonhdr;
|
|
|
|
register struct ip *iphdr;
|
|
|
|
struct ifnet *eonifp;
|
|
|
|
int s;
|
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
va_start(ap, m);
|
|
|
|
iphlen = va_arg(ap, int);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
eonifp = &eonif[0]; /* kludge - really want to give CLNP the ifp
|
|
|
|
* for eon, not for the real device */
|
|
|
|
|
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eoninput() %p m_data %p m_len 0x%x dequeued\n",
|
1996-10-11 03:12:43 +04:00
|
|
|
m, (m ? m->m_data : 0), m ? m->m_len : 0);
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
if (m == 0)
|
|
|
|
return;
|
1996-02-14 01:07:57 +03:00
|
|
|
if (iphlen > sizeof(struct ip))
|
|
|
|
ip_stripoptions(m, (struct mbuf *) 0);
|
1993-04-09 16:00:07 +04:00
|
|
|
if (m->m_len < EONIPLEN) {
|
|
|
|
if ((m = m_pullup(m, EONIPLEN)) == 0) {
|
|
|
|
IncStat(es_badhdr);
|
1996-02-14 01:07:57 +03:00
|
|
|
drop:
|
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eoninput: DROP \n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
eonifp->if_ierrors++;
|
1993-04-09 16:00:07 +04:00
|
|
|
m_freem(m);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
eonif->if_ibytes += m->m_pkthdr.len;
|
|
|
|
eonif->if_lastchange = time;
|
|
|
|
iphdr = mtod(m, struct ip *);
|
|
|
|
/* do a few checks for debugging */
|
1996-02-14 01:07:57 +03:00
|
|
|
if (iphdr->ip_p != IPPROTO_EON) {
|
1993-04-09 16:00:07 +04:00
|
|
|
IncStat(es_badhdr);
|
|
|
|
goto drop;
|
|
|
|
}
|
|
|
|
/* temporarily drop ip header from the mbuf */
|
|
|
|
m->m_data += sizeof(struct ip);
|
|
|
|
eonhdr = mtod(m, struct eon_hdr *);
|
1996-02-14 01:07:57 +03:00
|
|
|
if (iso_check_csum(m, sizeof(struct eon_hdr)) != EOK) {
|
1993-04-09 16:00:07 +04:00
|
|
|
IncStat(es_badcsum);
|
|
|
|
goto drop;
|
|
|
|
}
|
|
|
|
m->m_data -= sizeof(struct ip);
|
1996-02-14 01:07:57 +03:00
|
|
|
|
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class);
|
|
|
|
printf("eoninput: eon header:\n");
|
1993-04-09 16:00:07 +04:00
|
|
|
dump_buf(eonhdr, sizeof(struct eon_hdr));
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
/* checks for debugging */
|
1996-02-14 01:07:57 +03:00
|
|
|
if (eonhdr->eonh_vers != EON_VERSION) {
|
1993-04-09 16:00:07 +04:00
|
|
|
IncStat(es_badhdr);
|
|
|
|
goto drop;
|
|
|
|
}
|
1996-02-14 01:07:57 +03:00
|
|
|
m->m_flags &= ~(M_BCAST | M_MCAST);
|
|
|
|
switch (eonhdr->eonh_class) {
|
|
|
|
case EON_BROADCAST:
|
|
|
|
IncStat(es_in_broad);
|
|
|
|
m->m_flags |= M_BCAST;
|
|
|
|
break;
|
|
|
|
case EON_NORMAL_ADDR:
|
|
|
|
IncStat(es_in_normal);
|
|
|
|
break;
|
|
|
|
case EON_MULTICAST_ES:
|
|
|
|
IncStat(es_in_multi_es);
|
|
|
|
m->m_flags |= M_MCAST;
|
|
|
|
break;
|
|
|
|
case EON_MULTICAST_IS:
|
|
|
|
IncStat(es_in_multi_is);
|
|
|
|
m->m_flags |= M_MCAST;
|
|
|
|
break;
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
eonifp->if_ipackets++;
|
|
|
|
|
|
|
|
{
|
|
|
|
/* put it on the CLNP queue and set soft interrupt */
|
1996-02-14 01:07:57 +03:00
|
|
|
struct ifqueue *ifq;
|
|
|
|
extern struct ifqueue clnlintrq;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
m->m_pkthdr.rcvif = eonifp; /* KLUDGE */
|
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eoninput to clnl IFQ\n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
ifq = &clnlintrq;
|
|
|
|
s = splimp();
|
|
|
|
if (IF_QFULL(ifq)) {
|
|
|
|
IF_DROP(ifq);
|
|
|
|
m_freem(m);
|
|
|
|
eonifp->if_iqdrops++;
|
|
|
|
eonifp->if_ipackets--;
|
|
|
|
splx(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
IF_ENQUEUE(ifq, m);
|
1996-02-14 01:07:57 +03:00
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf(
|
1996-10-11 03:12:43 +04:00
|
|
|
"%p enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data %p\n",
|
|
|
|
m, m->m_len, m->m_type, m->m_data);
|
1993-04-09 16:00:07 +04:00
|
|
|
dump_buf(mtod(m, caddr_t), m->m_len);
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
schednetisr(NETISR_ISO);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
void *
|
|
|
|
eonctlinput(cmd, sa, dummy)
|
|
|
|
int cmd;
|
|
|
|
struct sockaddr *sa;
|
|
|
|
void *dummy;
|
1993-04-09 16:00:07 +04:00
|
|
|
{
|
1996-02-14 01:07:57 +03:00
|
|
|
struct sockaddr_in *sin = (struct sockaddr_in *) sa;
|
|
|
|
#ifdef ARGO_DEBUG
|
|
|
|
if (argo_debug[D_EON]) {
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonctlinput: cmd 0x%x addr: ", cmd);
|
1996-02-14 01:07:57 +03:00
|
|
|
dump_isoaddr((struct sockaddr_iso *) sin);
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("\n");
|
1996-02-14 01:07:57 +03:00
|
|
|
}
|
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
if (cmd < 0 || cmd > PRC_NCMDS)
|
1996-02-14 01:07:57 +03:00
|
|
|
return NULL;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
|
|
|
IncStat(es_icmp[cmd]);
|
|
|
|
switch (cmd) {
|
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
case PRC_QUENCH:
|
|
|
|
case PRC_QUENCH2:
|
|
|
|
/* TODO: set the dec bit */
|
|
|
|
break;
|
|
|
|
case PRC_TIMXCEED_REASS:
|
|
|
|
case PRC_ROUTEDEAD:
|
|
|
|
case PRC_HOSTUNREACH:
|
|
|
|
case PRC_UNREACH_NET:
|
|
|
|
case PRC_IFDOWN:
|
|
|
|
case PRC_UNREACH_HOST:
|
|
|
|
case PRC_HOSTDEAD:
|
|
|
|
case PRC_TIMXCEED_INTRANS:
|
|
|
|
/* TODO: mark the link down */
|
|
|
|
break;
|
1993-04-09 16:00:07 +04:00
|
|
|
|
1996-02-14 01:07:57 +03:00
|
|
|
case PRC_UNREACH_PROTOCOL:
|
|
|
|
case PRC_UNREACH_PORT:
|
|
|
|
case PRC_UNREACH_SRCFAIL:
|
|
|
|
case PRC_REDIRECT_NET:
|
|
|
|
case PRC_REDIRECT_HOST:
|
|
|
|
case PRC_REDIRECT_TOSNET:
|
|
|
|
case PRC_REDIRECT_TOSHOST:
|
|
|
|
case PRC_MSGSIZE:
|
|
|
|
case PRC_PARAMPROB:
|
1996-10-11 03:12:43 +04:00
|
|
|
#if 0
|
1996-10-13 06:03:00 +04:00
|
|
|
printf("eonctlinput: ICMP cmd 0x%x\n", cmd );
|
1996-10-11 03:12:43 +04:00
|
|
|
#endif
|
1993-04-09 16:00:07 +04:00
|
|
|
break;
|
|
|
|
}
|
1996-02-14 01:07:57 +03:00
|
|
|
return NULL;
|
1993-04-09 16:00:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|