From 6ffae239496bf6e326006c868bf78c954701f7f2 Mon Sep 17 00:00:00 2001 From: Keith Sklower Date: Thu, 5 Apr 1990 18:20:20 -0800 Subject: [PATCH] rewrite if_eon.c to allow arbitrary nsaps routed via IP; use new rt_change mechnism to maintain list of routes\; SCCS-vsn: sys/netiso/eonvar.h 7.3 SCCS-vsn: sys/netiso/if_eon.c 7.6 --- usr/src/sys/netiso/eonvar.h | 17 +- usr/src/sys/netiso/if_eon.c | 706 +++++++++--------------------------- 2 files changed, 178 insertions(+), 545 deletions(-) diff --git a/usr/src/sys/netiso/eonvar.h b/usr/src/sys/netiso/eonvar.h index 9cb56f099b..efea7c107e 100644 --- a/usr/src/sys/netiso/eonvar.h +++ b/usr/src/sys/netiso/eonvar.h @@ -23,7 +23,7 @@ SOFTWARE. /* * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison - * @(#)eonvar.h 7.2 (Berkeley) %G% + * @(#)eonvar.h 7.3 (Berkeley) %G% */ #define EON_986_VERSION 0x3 @@ -89,6 +89,10 @@ struct eon_hdr { #define EON_BROADCAST 0x3 u_short eonh_csum; /* osi checksum (choke)*/ }; +struct eon_iphdr { + struct ip ei_ip; + struct eon_hdr ei_eh; +}; #define EONIPLEN (sizeof(struct eon_hdr) + sizeof(struct ip)) /* stole these 2 fields of the flags for I-am-ES and I-am-IS */ @@ -118,3 +122,14 @@ struct eon_stat { typedef struct qhdr { struct qhdr *link, *rlink; } *queue_t; + +struct eon_llinfo { + struct qhdr el_qhdr; /* keep all in a list */ + int el_flags; /* cache valid ? */ + struct rtentry *el_rt; /* back pointer to parent route */ + struct eon_iphdr el_ei; /* precomputed portion of hdr */ + struct route el_iproute; /* if direct route cache IP info */ + /* if gateway, cache secondary route */ +}; +#define el_iphdr el_ei.ei_ip +#define el_eonhdr el_ei.ei_eh diff --git a/usr/src/sys/netiso/if_eon.c b/usr/src/sys/netiso/if_eon.c index 0115334892..dffc372934 100644 --- a/usr/src/sys/netiso/if_eon.c +++ b/usr/src/sys/netiso/if_eon.c @@ -27,7 +27,7 @@ SOFTWARE. /* * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $ * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $ - * @(#)if_eon.c 7.5 (Berkeley) %G% * + * @(#)if_eon.c 7.6 (Berkeley) %G% * * * EON rfc * Layer between IP and CLNL @@ -58,12 +58,14 @@ static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $"; #include "../net/if.h" #include "../net/if_types.h" +#include "../net/if_dl.h" #include "../net/netisr.h" #include "../net/route.h" #include "machine/mtpr.h" #include "../netinet/in.h" #include "../netinet/in_systm.h" +#include "../netinet/in_var.h" #include "../netinet/ip.h" #include "../netinet/ip_var.h" #include "../netinet/if_ether.h" @@ -80,219 +82,21 @@ extern struct timeval time; #define EOK 0 int eoninput(); -int eonint(); int eonoutput(); int eonioctl(); -int eonprobe(); int eonattach(); int eoninit(); +int eonrtrequest(); extern int ip_output(); -struct ifnet eonif[NEON]; - -#ifdef FAKEIOCCDEV -#include "machine/io.h" -#include "../machineio/ioccvar.h" - -#define EON_FAKE_CSR 0 -int eon_fakeautoconf[2]; /* need at least 2 ints */ - -caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 }; -struct iocc_device *eoninfo[NEON]; - -struct iocc_driver eondriver = { - eonprobe, /* idr_probe */ - 0, /* idr_slave */ - eonattach, /* idr_attach */ - 0, /* idr_dgo */ - eonstd, /* idr_addr - list of standard addresses for device */ - "eon", /* idr_dname */ - eoninfo, /* idr_dinfo - backptrs to iodinit structs */ - 0, /* idr_mname - controller name */ - 0, /* idr_minfo -- backptrs to iominit structs */ - eonint, /* idr_intr - interrupt rtn */ - 0, /* idr_csr - offset to read/write csr */ - EON_FAKE_CSR, /* idr_chanrelse */ - 0, /* idr_flags */ -}; -#else -struct iocc_device { - int iod_unit; -} bsd_iocc_fakeout; +struct ifnet eonif[1]; eonprotoinit() { - (void) eonprobe(); - (void) eonattach(&bsd_iocc_fakeout); + (void) eonattach(); } -#define PROBE_OK 0; -#endif - - -/* - * entry in the EON address cache (list) - * (or pt-pt links list, however you view it) - */ - -struct eon_centry { - struct qhdr eonc_q_LINK; -#define eonc_nextLINK eonc_q_LINK.link -#define eonc_prevLINK eonc_q_LINK.flink - - struct qhdr eonc_q_IS; -#define eonc_nextIS eonc_q_IS.link -#define eonc_prevIS eonc_q_IS.flink - - struct qhdr eonc_q_ES; -#define eonc_nextES eonc_q_ES.link -#define eonc_prevES eonc_q_ES.flink - - struct in_addr eonc_addr; - u_short eonc_status; -}; - -/* kinda like mtod() but for eon_centries */ -#define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off)) -#define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off)) - -struct qhdr eon_LINK_hdr = { - (struct qhdr *)0, - (struct qhdr *)0, -}; -static struct qhdr eon_IS_hdr = { - (struct qhdr *)0, - (struct qhdr *)0, -}; -static struct qhdr eon_ES_hdr = { - (struct qhdr *)0, - (struct qhdr *)0, -}; -static struct qhdr eon_FREE_hdr = { - (struct qhdr *)0, - (struct qhdr *)0, -}; - -#define INITQ(q) (q)->rlink = (q)->link = (q) - -/* - * FUNCTION: eon_dumpcache - * - * PURPOSE: dump the cache beginning with the argument given - * - * RETURNS: 0 - */ -eon_dumpcache(which) - int which; -{ - register int off; - register struct eon_centry *ent; - struct qhdr *hdr; - - switch (which) { - case E_FREE: - printf("FREE LIST\n"); - off = _offsetof( struct eon_centry, eonc_q_LINK); - hdr = &eon_FREE_hdr; - ent = qtocentry( hdr->link, - _offsetof( struct eon_centry, eonc_q_LINK)); - break; - case E_ES: - printf("ES LIST\n"); - off = _offsetof( struct eon_centry, eonc_q_ES); - hdr = &eon_ES_hdr; - ent = qtocentry( hdr->link, - _offsetof( struct eon_centry, eonc_q_ES)); - break; - case E_IS: - printf("IS LIST\n"); - off = _offsetof( struct eon_centry, eonc_q_IS); - hdr = &eon_IS_hdr; - ent = qtocentry( hdr->link, - _offsetof( struct eon_centry, eonc_q_IS)); - break; - case E_LINK: - printf("LINK LIST\n"); - off = _offsetof( struct eon_centry, eonc_q_LINK); - hdr = &eon_LINK_hdr; - ent = qtocentry( hdr->link, - _offsetof( struct eon_centry, eonc_q_LINK)); - break; - } - if(hdr == centrytoq(ent, off)->link ) - printf("EMPTY\n"); - else while(1) { - printf("0x%x: %d.%d.%d.%d, %s %s\n", ent, - (ent->eonc_addr.s_addr>>24)&0xff, - (ent->eonc_addr.s_addr>>16)&0xff, - (ent->eonc_addr.s_addr>>8)&0xff, - (ent->eonc_addr.s_addr)&0xff, - ((ent->eonc_status & EON_ESLINK_UP)?"ES^": - (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "), - ((ent->eonc_status & EON_ISLINK_UP)?"IS^": - (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ") - ); - dump_buf(ent, sizeof(struct eon_centry) ); - - { /* ent = ent.next: */ - register struct qhdr *q; - - q = centrytoq(ent, off)->link; - if( q == hdr) - break; - if( q == (struct qhdr *)0) /* panic */ { - printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n", - q, ent, off); - break; - } - ent = qtocentry( q, off ); - } - } -} -/* - * FUNCTION: eon_initcache - * - * PURPOSE: allocs a bunch of free cache entries - * - * RETURNS: 0 - */ - -eon_initcache() -{ - static struct eon_centry eoncache[EON_CACHESIZE]; - register int i; - register struct eon_centry *ent; - - bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry)); - INITQ( &eon_FREE_hdr ); - INITQ( &eon_LINK_hdr ); - INITQ( &eon_IS_hdr ); - INITQ( &eon_ES_hdr ); - - ent = eoncache; - - for(i=0; i< EON_CACHESIZE; i++,ent++) { - _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)), - &eon_FREE_hdr); - } - printf("eon0: cache initialized\n"); -} - -/* - * FUNCTION: eonprobe - * - * PURPOSE: filler for device configuration - * - * RETURNS: PROBE_OK - */ - -int int_level, int_irq; -eonprobe() -{ - extern int int_level, int_irq; +struct eon_llinfo eon_llinfo; +#define PROBE_OK 0; - printf("eonprobe() \n"); - int_level = int_irq = 0x3; /* pick something - anything but -1 */ - return PROBE_OK; -} /* * FUNCTION: eonattach @@ -302,15 +106,14 @@ eonprobe() * RETURNS: void */ -eonattach(iod) - register struct iocc_device *iod; +eonattach() { - register struct ifnet *ifp = &eonif[iod->iod_unit]; + register struct ifnet *ifp = eonif; IFDEBUG(D_EON) printf("eonattach()\n"); ENDDEBUG - ifp->if_unit = iod->iod_unit; + ifp->if_unit = 0; ifp->if_name = "eon"; ifp->if_mtu = ETHERMTU; /* since everything will go out over ether or token ring */ @@ -323,39 +126,15 @@ eonattach(iod) ifp->if_hdrlen = EONIPLEN; ifp->if_flags = IFF_BROADCAST; if_attach(ifp); + eonioctl(ifp, SIOCSIFADDR, (caddr_t)ifp->if_addrlist); + eon_llinfo.el_qhdr.link = + eon_llinfo.el_qhdr.rlink = &(eon_llinfo.el_qhdr); IFDEBUG(D_EON) printf("eonattach()\n"); ENDDEBUG - eon_initcache(); - IFDEBUG(D_EON) - printf("eon%d: attached\n", iod->iod_unit); - ENDDEBUG } -static struct eon_centry * -find_oldent( ea ) - struct sockaddr_eon *ea; -{ - register int offset = - _offsetof( struct eon_centry, eonc_q_LINK); - register struct eon_centry *ent, *oent; - - oent = ent = qtocentry(eon_LINK_hdr.link, offset); - IFDEBUG(D_EON) - printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n", - (ea->seon_ipaddr>>24)&0xff, - (ea->seon_ipaddr>>16)&0xff, - (ea->seon_ipaddr>>8)&0xff, - (ea->seon_ipaddr)&0xff ); - ENDDEBUG - do { - if( ent->eonc_addr.s_addr == ea->seon_ipaddr ) - return ent; - ent = qtocentry(ent->eonc_nextLINK, offset); - } while (ent != oent); - return (struct eon_centry *)0; -} /* * FUNCTION: eonioctl @@ -370,150 +149,129 @@ find_oldent( ea ) */ eonioctl(ifp, cmd, data) register struct ifnet *ifp; - register int cmd; + int cmd; register caddr_t data; { - struct iso_ifreq *ifr = (struct iso_ifreq *)data; - register struct sockaddr_eon *eoa = - (struct sockaddr_eon *)&(ifr->ifr_Addr); - register int s = splimp(); + int s = splimp(); register int error = 0; IFDEBUG(D_EON) printf("eonioctl (cmd 0x%x) \n", cmd); ENDDEBUG - switch (cmd){ - case SIOCSEONCORE: { - /* add pt-pt link to the set of core addrs */ - register struct eon_centry *ent, *oldent; - register u_short which; - - /* "which" tells which lists to put these guys in - don't - * want to insert something in a list if it's already there - */ -#define LEGIT_EONADDR(a)\ - ((a->seon_family == AF_ISO) && (a->seon_afi == AFI_RFC986) &&\ - (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \ - && (a->seon_vers == EON_986_VERSION) && (a->seon_adrlen == 0x14)) - - if( ! LEGIT_EONADDR(eoa) ) { - error = EADDRNOTAVAIL; - break; - } - - oldent = find_oldent( eoa ); - IFDEBUG(D_EON) - printf("eonioctl legit seon_status 0x%x oldent %s\n", - eoa->seon_status, oldent?"found":"not found"); - ENDDEBUG - - if( eoa->seon_status & UPBITS ) { - if (!oldent) { - /* doesn't exist - need to create one */ - if (eon_FREE_hdr.link == eon_FREE_hdr.rlink) - return ENOBUFS; - ent = qtocentry(eon_FREE_hdr.link, - _offsetof( struct eon_centry, eonc_q_LINK)); - remque( &(ent->eonc_q_LINK) ); - ent->eonc_addr.s_addr = eoa->seon_ipaddr; - insque( &(ent->eonc_q_LINK), (&eon_LINK_hdr)); - oldent = ent; - } - - which = (eoa->seon_status ^ oldent->eonc_status) & - eoa->seon_status & UPBITS; - - oldent->eonc_status |= (eoa->seon_status & UPBITS); - - if( which & EON_ESLINK_UP ) - insque( &oldent->eonc_q_ES, (&eon_ES_hdr)); - if( which & EON_ISLINK_UP ) - insque( &oldent->eonc_q_IS, (&eon_IS_hdr)); - } - - if( eoa->seon_status & DOWNBITS ) { - if(!oldent) { - return ENOENT; /* no such entry */ - } - which = (eoa->seon_status ^ oldent->eonc_status) & - eoa->seon_status & DOWNBITS; - - oldent->eonc_status |= (eoa->seon_status & DOWNBITS); - - if( which & EON_ESLINK_DOWN ) - remque( &(oldent->eonc_q_ES) ); - if( which & EON_ISLINK_DOWN ) - remque( &(oldent->eonc_q_IS) ); - } - - IFDEBUG(D_EON) - printf("at end status 0x%x\n", oldent->eonc_status); - ENDDEBUG - break; - } - - case SIOCGEONCORE: - { - register struct eon_centry *oldent; - - oldent = find_oldent( eoa ); - if( oldent == (struct eon_centry *)0 ) - error = EADDRNOTAVAIL; - else - eoa->seon_status = oldent->eonc_status; - } - break; + switch (cmd) { + register struct ifaddr *ifa; case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - break; - - case SIOCSIFFLAGS: - if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & - IFF_RUNNING){ - ifp->if_flags &= ~IFF_RUNNING; - } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & - IFF_RUNNING) == 0) - eoninit(ifp->if_unit); + if (ifa = (struct ifaddr *)data) { + ifp->if_flags |= IFF_UP; + ifa->ifa_rtrequest = eonrtrequest; + ifa->ifa_llinfolen = sizeof(struct eon_llinfo); + } break; - default: - error = EINVAL; } splx(s); return(error); } + +eoniphdr(hdr, loc, ro, class, zero) +struct route *ro; +register struct eon_iphdr *hdr; +caddr_t loc; +{ + struct mbuf mhead; + register struct sockaddr_in *sin = (struct sockaddr_in *)&ro->ro_dst; + if (zero) { + bzero((caddr_t)hdr, sizeof (*hdr)); + bzero((caddr_t)ro, sizeof (*ro)); + } + sin->sin_family = AF_INET; + sin->sin_len = sizeof (*sin); + bcopy(loc, (caddr_t)&sin->sin_addr, sizeof(struct in_addr)); + hdr->ei_ip.ip_dst = sin->sin_addr; + hdr->ei_ip.ip_p = IPPROTO_EON; + hdr->ei_ip.ip_ttl = MAXTTL; + hdr->ei_eh.eonh_class = class; + hdr->ei_eh.eonh_vers = EON_VERSION; + hdr->ei_eh.eonh_csum = 0; + mhead.m_data = (caddr_t) &hdr->ei_eh; + mhead.m_len = sizeof(struct eon_hdr); + mhead.m_next = 0; + IFDEBUG(D_EON) + printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", + &mhead, + _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); + ENDDEBUG + iso_gen_csum(&mhead, + _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); +} /* - * FUNCTION: eoninit + * FUNCTION: eonrtrequest * - * PURPOSE: initialization + * PURPOSE: maintains list of direct eon recipients. + * sets up IP route for rest. * * RETURNS: nothing */ - -eoninit(unit) - int unit; +eonrtrequest(cmd, rt, gate) +register struct rtentry *rt; +struct sockaddr *gate; { - printf("eon driver-init eon%d\n", unit); -} + caddr_t ipaddrloc = 0; + register struct eon_llinfo *el = (struct eon_llinfo *)rt->rt_llinfo; + register struct rtentry *iprt; + register struct sockaddr_in sin; + + if (el == 0) + panic("eonrtrequest"); + iprt = el->el_iproute.ro_rt; + /* + * Common Housekeeping + */ + switch (cmd) { + + case RTM_ADD: + insque(&(el->el_qhdr), &eon_llinfo.el_qhdr); + el->el_rt = rt; + break; + case RTM_DELETE: + remque(&(el->el_qhdr)); + /* FALLTHROUGH */ + case RTM_CHANGE: + el->el_flags &= ~RTF_UP; + if (iprt) + RTFREE(iprt); + if (cmd = RTM_DELETE) + return; + } + if (gate || (gate = rt->rt_gateway)) switch (gate->sa_family) { + case AF_LINK: + ipaddrloc = LLADDR((struct sockaddr_dl *)gate); + break; + case AF_INET: + ipaddrloc = (caddr_t) &((struct sockaddr_in *)gate)->sin_addr; + break; + default: + return; + } + el->el_flags |= RTF_UP; + eoniphdr(&el->el_ei, &el->el_iproute, ipaddrloc, EON_NORMAL_ADDR, 0); +} /* - * FUNCTION: eonint + * FUNCTION: eoninit * - * PURPOSE: filler for device configuration + * PURPOSE: initialization * * RETURNS: nothing - * - * NOTES: *should* never get called - for debugging it's here */ -eonint() +eoninit(unit) + int unit; { - /* silent - so no more stray interrupt messages from the aed! yay - printf("eonint() called - BOGUS INTERRUPT\n"); - */ + printf("eon driver-init eon%d\n", unit); } @@ -531,23 +289,21 @@ eonint() * NOTES: * */ -eonoutput(ifp, morig, dst) +eonoutput(ifp, m, dst, rt) struct ifnet *ifp; - register struct mbuf *morig; /* packet */ + register struct mbuf *m; /* packet */ struct sockaddr_iso *dst; /* destination addr */ + struct rtentry *rt; { - int s; - struct eon_hdr *eonhdr; - struct ip *iphdr; - struct mbuf *mh; - int error = 0; - register int datalen; - caddr_t dstipaddrloc; - int single = 0, class, qoffset = 0, snpalen; - register struct eon_centry *ent; - register struct sockaddr_eon *eoa; - struct qhdr *q; - char edst[6]; + register struct eon_llinfo *el; + register struct eon_iphdr *ei; + struct route *ro; + int datalen; + struct mbuf *mh; + int error = 0; + caddr_t ippaddrloc; + static struct eon_iphdr eon_iphdr; + static struct route route; IFDEBUG(D_EON) printf("eonoutput \n" ); @@ -555,204 +311,67 @@ eonoutput(ifp, morig, dst) ifp->if_lastchange = time; ifp->if_opackets++; - if( dst->siso_family != AF_ISO ) { - einval: + if (rt == 0 || (el = (struct eon_llinfo *)rt->rt_llinfo) == 0) { + if (dst->siso_family == AF_LINK) { + register struct sockaddr_dl *sdl = (struct sockaddr_dl *)dst; + caddr_t ipaddrloc = LLADDR(sdl); + int class = (sdl->sdl_alen == 5) ? 4[(u_char *)ipaddrloc] : 0; + + if (sdl->sdl_alen == 4 || sdl->sdl_alen == 5) { + ipaddrloc = LLADDR(sdl); + ro = &route; + ei = &eon_iphdr; + eoniphdr(ei, ipaddrloc, ro, class, 1); + goto send; + } + } +einval: error = EINVAL; goto flush; } - if ((morig->m_flags & M_PKTHDR) == 0) { + if ((el->el_flags & RTF_UP) == 0) { + eonrtrequest(RTM_CHANGE, rt, (struct sockaddr *)0); + if ((el->el_flags & RTF_UP) == 0) { + error = EHOSTUNREACH; + goto flush; + } + } + if ((m->m_flags & M_PKTHDR) == 0) { printf("eon: got non headered packet\n"); goto einval; } - eoa = (struct sockaddr_eon *)dst; - if (LEGIT_EONADDR(eoa)) { - class = eoa->seon_protoid; - dstipaddrloc = (caddr_t)&(eoa->seon_ipaddr); - } else if (eoa->seon_afi == AFI_SNA) { - dstipaddrloc = (caddr_t)&(dst->siso_data[1]); - if (dst->siso_nlen == 6) { - class = dst->siso_data[5]; - } else if (dst->siso_nlen == 7) { - if (bcmp(dstipaddrloc, all_is.sc_snpa, 6)) - class = EON_MULTICAST_ES; - else if (bcmp(dstipaddrloc, all_es.sc_snpa, 6)) - class = EON_MULTICAST_IS; - else - goto einval; - } else - goto einval; - } else if (0 == iso_snparesolve(ifp, dst, edst, &snpalen)) { - dstipaddrloc = (caddr_t)edst; - class = edst[4]; - } else { - error = EINVAL; - goto flush; - } - switch (class) { - case EON_NORMAL_ADDR: - IncStat(es_out_normal); - single = 1; - break; - - case EON_BROADCAST: - IncStat(es_out_broad); - if(eon_LINK_hdr.link == eon_LINK_hdr.rlink) { - error = EADDRNOTAVAIL; - } else { - qoffset = _offsetof( struct eon_centry, eonc_q_LINK); - ent = qtocentry(eon_LINK_hdr.link, qoffset); - dstipaddrloc = (caddr_t) &(ent->eonc_addr); - } - break; - case EON_MULTICAST_ES: - IncStat(es_out_multi_es); - if (eon_ES_hdr.link == eon_ES_hdr.rlink) { - error = EADDRNOTAVAIL; - } else { - qoffset = _offsetof( struct eon_centry, eonc_q_ES); - ent = qtocentry(eon_ES_hdr.link, qoffset); - dstipaddrloc = (caddr_t) &(ent->eonc_addr); - } - break; - case EON_MULTICAST_IS: - IncStat(es_out_multi_is); - if (eon_IS_hdr.link == eon_IS_hdr.rlink) { - error = EADDRNOTAVAIL; - } else { - qoffset = _offsetof( struct eon_centry, eonc_q_LINK); - ent = qtocentry(eon_IS_hdr.link, qoffset); - dstipaddrloc = (caddr_t) &(ent->eonc_addr); - } - break; - default: - printf("bad class value; treated as EON_NORMAL_ADDR\n"); - class = EON_NORMAL_ADDR; - single = 1; - break; - } - if( error ) - goto done; - - /* get data length -- needed later */ - datalen = morig->m_pkthdr.len; - IFDEBUG(D_EON) - printf("eonoutput : m_datalen returns %d\n", datalen); - ENDDEBUG - + ei = &el->el_ei; + ro = &el->el_iproute; +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); if(mh == (struct mbuf *)0) - goto done; - - /* put an eon_hdr in the buffer, prepended by an ip header */ - mh->m_len = sizeof(struct eon_hdr); - MH_ALIGN(mh, sizeof(struct eon_hdr)); - mh->m_next = morig; - eonhdr = mtod(mh, struct eon_hdr *); - eonhdr->eonh_class = class; - eonhdr->eonh_vers = EON_VERSION; - eonhdr->eonh_csum = 0; - - IFDEBUG(D_EON) - printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", - mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); - ENDDEBUG - iso_gen_csum(mh, - _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); - - mh->m_data -= sizeof(*iphdr); - mh->m_len += sizeof(*iphdr); - iphdr = mtod(mh, struct ip *); - bzero((caddr_t)iphdr, sizeof (*iphdr)); - - iphdr->ip_p = IPPROTO_EON; + 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 += - (iphdr->ip_len = (u_short)(mh->m_pkthdr.len = EONIPLEN + datalen)); - iphdr->ip_ttl = MAXTTL; - iphdr->ip_src.s_addr = INADDR_ANY; + (ei->ei_ip.ip_len = (u_short)(m->m_pkthdr.len = datalen)); + *mtod(m, struct eon_iphdr *) = *ei; IFDEBUG(D_EON) - printf("eonoutput : after gen csum: ip_len %d/0x%x\n", - mh->m_pkthdr.len, mh->m_pkthdr.len); + printf("eonoutput dst ip addr : %x\n", ei->ei_ip.ip_dst.s_addr); + printf("eonoutput ip_output : eonip header:\n"); + dump_buf(ei, sizeof(struct eon_iphdr)); ENDDEBUG - morig = mh; - - for(;;) { - - if( !single ) { - /* make a copy to send */ - IFDEBUG(D_EON) - printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n", - morig, iphdr->ip_len); - ENDDEBUG - if (((mh = m_copy(morig, 0, morig->m_pkthdr.len)) == 0) || - ((mh = m_pullup(mh, sizeof(struct ip))) == 0)) { - error = ENOBUFS; - goto done; - } - iphdr = mtod(mh, struct ip *); - } - IFDEBUG(D_EON) - printf("eonoutput : bcopy 0x%x to 0x%x length %d\n", - dstipaddrloc, - (caddr_t)&(iphdr->ip_dst.s_addr), - sizeof(iphdr->ip_dst.s_addr)); - ENDDEBUG - bcopy(dstipaddrloc, (caddr_t)&(iphdr->ip_dst.s_addr), - sizeof(iphdr->ip_dst.s_addr)); - IFDEBUG(D_EON) - printf("eonoutput : dst ip addr : %d.%d.%d.%d", - (iphdr->ip_dst.s_addr>>24)&0xff, - (iphdr->ip_dst.s_addr>>16)&0xff, - (iphdr->ip_dst.s_addr>>8)&0xff, - (iphdr->ip_dst.s_addr)&0xff ); - ENDDEBUG - - IFDEBUG(D_EON) - printf("eonoutput ip_output : eon header:\n"); - dump_buf(eonhdr, sizeof(struct eon_hdr)); - printf("ip header:\n"); - dump_buf(iphdr, sizeof(struct ip)); - ENDDEBUG - - IncStat(es_ipout); - if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) ) - break; - - IFDEBUG(D_EON) - printf("eonoutput ip_output returns 0x%x; single %d\n", - error, single); - ENDDEBUG - - if(single) - break; - - q = centrytoq(ent, qoffset)->link; - if( q == (struct qhdr *)0) - break; - ent = qtocentry( q, qoffset ); - IFDEBUG(D_EON) - printf("eonoutput : get next entry: 0x%x\n", ent); - ENDDEBUG - dstipaddrloc = (caddr_t) &(ent->eonc_addr); - IFDEBUG(D_EON) - printf("eonoutput : dump of eon_centry 0x%x:\n", ent ); - dump_buf(ent, sizeof(struct eon_centry) ); - ENDDEBUG - } -done: - if( !single ) { - IFDEBUG(D_EON) - printf("eonoutput : freeing morig 0x%x\n", morig); - ENDDEBUG -flush: - m_freem(morig); - } + error = ip_output(m, (struct mbuf *)0, ro, 0); + m = 0; if (error) { ifp->if_oerrors++; ifp->if_opackets--; - ifp->if_obytes -= datalen + EONIPLEN; + ifp->if_obytes -= datalen; } +flush: + if (m) + m_freem(m); return error; } @@ -905,7 +524,6 @@ eonctlinput(cmd, sin) case PRC_UNREACH_PROTOCOL: case PRC_UNREACH_PORT: - case PRC_UNREACH_NEEDFRAG: case PRC_UNREACH_SRCFAIL: case PRC_REDIRECT_NET: case PRC_REDIRECT_HOST: -- 2.20.1