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*39195Ssklower * @(#)if_eon.c 7.5 (Berkeley) 09/22/89 * 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" 60*39195Ssklower #include "../net/if_types.h" 6136382Ssklower #include "../net/netisr.h" 6236382Ssklower #include "../net/route.h" 6337518Smckusick #include "machine/mtpr.h" 6436382Ssklower 6536382Ssklower #include "../netinet/in.h" 6636382Ssklower #include "../netinet/in_systm.h" 6736382Ssklower #include "../netinet/ip.h" 6836382Ssklower #include "../netinet/ip_var.h" 6936382Ssklower #include "../netinet/if_ether.h" 7036382Ssklower 7137469Ssklower #include "iso.h" 7237469Ssklower #include "iso_var.h" 7337469Ssklower #include "iso_snpac.h" 7437469Ssklower extern struct snpa_cache all_es, all_is; 7537469Ssklower #include "argo_debug.h" 7637469Ssklower #include "iso_errno.h" 7737469Ssklower #include "eonvar.h" 78*39195Ssklower extern struct timeval time; 7936382Ssklower 8036382Ssklower #define EOK 0 8136382Ssklower 8236382Ssklower int eoninput(); 8336382Ssklower int eonint(); 8436382Ssklower int eonoutput(); 8536382Ssklower int eonioctl(); 8636382Ssklower int eonprobe(); 8736382Ssklower int eonattach(); 8836382Ssklower int eoninit(); 8936382Ssklower extern int ip_output(); 9036382Ssklower struct ifnet eonif[NEON]; 9136382Ssklower 9237469Ssklower #ifdef FAKEIOCCDEV 9337518Smckusick #include "machine/io.h" 9437469Ssklower #include "../machineio/ioccvar.h" 9537469Ssklower 9636382Ssklower #define EON_FAKE_CSR 0 9736382Ssklower int eon_fakeautoconf[2]; /* need at least 2 ints */ 9836382Ssklower 9936382Ssklower caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 }; 10036382Ssklower struct iocc_device *eoninfo[NEON]; 10136382Ssklower 10236382Ssklower struct iocc_driver eondriver = { 10336382Ssklower eonprobe, /* idr_probe */ 10436382Ssklower 0, /* idr_slave */ 10536382Ssklower eonattach, /* idr_attach */ 10636382Ssklower 0, /* idr_dgo */ 10736382Ssklower eonstd, /* idr_addr - list of standard addresses for device */ 10836382Ssklower "eon", /* idr_dname */ 10936382Ssklower eoninfo, /* idr_dinfo - backptrs to iodinit structs */ 11036382Ssklower 0, /* idr_mname - controller name */ 11136382Ssklower 0, /* idr_minfo -- backptrs to iominit structs */ 11236382Ssklower eonint, /* idr_intr - interrupt rtn */ 11336382Ssklower 0, /* idr_csr - offset to read/write csr */ 11436382Ssklower EON_FAKE_CSR, /* idr_chanrelse */ 11536382Ssklower 0, /* idr_flags */ 11636382Ssklower }; 11737469Ssklower #else 11837469Ssklower struct iocc_device { 11937469Ssklower int iod_unit; 12037469Ssklower } bsd_iocc_fakeout; 12136382Ssklower 12237469Ssklower eonprotoinit() { 12337469Ssklower (void) eonprobe(); 12437469Ssklower (void) eonattach(&bsd_iocc_fakeout); 12537469Ssklower } 12637469Ssklower #define PROBE_OK 0; 12737469Ssklower #endif 12836382Ssklower 12937469Ssklower 13036382Ssklower /* 13136382Ssklower * entry in the EON address cache (list) 13236382Ssklower * (or pt-pt links list, however you view it) 13336382Ssklower */ 13436382Ssklower 13536382Ssklower struct eon_centry { 13636382Ssklower struct qhdr eonc_q_LINK; 13736382Ssklower #define eonc_nextLINK eonc_q_LINK.link 13836382Ssklower #define eonc_prevLINK eonc_q_LINK.flink 13936382Ssklower 14036382Ssklower struct qhdr eonc_q_IS; 14136382Ssklower #define eonc_nextIS eonc_q_IS.link 14236382Ssklower #define eonc_prevIS eonc_q_IS.flink 14336382Ssklower 14436382Ssklower struct qhdr eonc_q_ES; 14536382Ssklower #define eonc_nextES eonc_q_ES.link 14636382Ssklower #define eonc_prevES eonc_q_ES.flink 14736382Ssklower 14836382Ssklower struct in_addr eonc_addr; 14936382Ssklower u_short eonc_status; 15036382Ssklower }; 15136382Ssklower 15236382Ssklower /* kinda like mtod() but for eon_centries */ 15336382Ssklower #define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off)) 15436382Ssklower #define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off)) 15536382Ssklower 15636382Ssklower struct qhdr eon_LINK_hdr = { 15736382Ssklower (struct qhdr *)0, 15836382Ssklower (struct qhdr *)0, 15936382Ssklower }; 16036382Ssklower static struct qhdr eon_IS_hdr = { 16136382Ssklower (struct qhdr *)0, 16236382Ssklower (struct qhdr *)0, 16336382Ssklower }; 16436382Ssklower static struct qhdr eon_ES_hdr = { 16536382Ssklower (struct qhdr *)0, 16636382Ssklower (struct qhdr *)0, 16736382Ssklower }; 16836382Ssklower static struct qhdr eon_FREE_hdr = { 16936382Ssklower (struct qhdr *)0, 17036382Ssklower (struct qhdr *)0, 17136382Ssklower }; 17236382Ssklower 17336382Ssklower #define INITQ(q) (q)->rlink = (q)->link = (q) 17436382Ssklower 17536382Ssklower /* 17636382Ssklower * FUNCTION: eon_dumpcache 17736382Ssklower * 17836382Ssklower * PURPOSE: dump the cache beginning with the argument given 17936382Ssklower * 18036382Ssklower * RETURNS: 0 18136382Ssklower */ 18236382Ssklower 18336382Ssklower eon_dumpcache(which) 18436382Ssklower int which; 18536382Ssklower { 18636382Ssklower register int off; 18736382Ssklower register struct eon_centry *ent; 18836382Ssklower struct qhdr *hdr; 18936382Ssklower 19036382Ssklower switch (which) { 19136382Ssklower case E_FREE: 19236382Ssklower printf("FREE LIST\n"); 19336382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 19436382Ssklower hdr = &eon_FREE_hdr; 19536382Ssklower ent = qtocentry( hdr->link, 19636382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 19736382Ssklower break; 19836382Ssklower case E_ES: 19936382Ssklower printf("ES LIST\n"); 20036382Ssklower off = _offsetof( struct eon_centry, eonc_q_ES); 20136382Ssklower hdr = &eon_ES_hdr; 20236382Ssklower ent = qtocentry( hdr->link, 20336382Ssklower _offsetof( struct eon_centry, eonc_q_ES)); 20436382Ssklower break; 20536382Ssklower case E_IS: 20636382Ssklower printf("IS LIST\n"); 20736382Ssklower off = _offsetof( struct eon_centry, eonc_q_IS); 20836382Ssklower hdr = &eon_IS_hdr; 20936382Ssklower ent = qtocentry( hdr->link, 21036382Ssklower _offsetof( struct eon_centry, eonc_q_IS)); 21136382Ssklower break; 21236382Ssklower case E_LINK: 21336382Ssklower printf("LINK LIST\n"); 21436382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 21536382Ssklower hdr = &eon_LINK_hdr; 21636382Ssklower ent = qtocentry( hdr->link, 21736382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 21836382Ssklower break; 21936382Ssklower } 22036382Ssklower if(hdr == centrytoq(ent, off)->link ) 22136382Ssklower printf("EMPTY\n"); 22236382Ssklower else while(1) { 22336382Ssklower printf("0x%x: %d.%d.%d.%d, %s %s\n", ent, 22436382Ssklower (ent->eonc_addr.s_addr>>24)&0xff, 22536382Ssklower (ent->eonc_addr.s_addr>>16)&0xff, 22636382Ssklower (ent->eonc_addr.s_addr>>8)&0xff, 22736382Ssklower (ent->eonc_addr.s_addr)&0xff, 22836382Ssklower ((ent->eonc_status & EON_ESLINK_UP)?"ES^": 22936382Ssklower (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "), 23036382Ssklower ((ent->eonc_status & EON_ISLINK_UP)?"IS^": 23136382Ssklower (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ") 23236382Ssklower ); 23336382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 23436382Ssklower 23536382Ssklower { /* ent = ent.next: */ 23636382Ssklower register struct qhdr *q; 23736382Ssklower 23836382Ssklower q = centrytoq(ent, off)->link; 23936382Ssklower if( q == hdr) 24036382Ssklower break; 24136382Ssklower if( q == (struct qhdr *)0) /* panic */ { 24236382Ssklower printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n", 24336382Ssklower q, ent, off); 24436382Ssklower break; 24536382Ssklower } 24636382Ssklower ent = qtocentry( q, off ); 24736382Ssklower } 24836382Ssklower } 24936382Ssklower } 25036382Ssklower /* 25136382Ssklower * FUNCTION: eon_initcache 25236382Ssklower * 25336382Ssklower * PURPOSE: allocs a bunch of free cache entries 25436382Ssklower * 25536382Ssklower * RETURNS: 0 25636382Ssklower */ 25736382Ssklower 25836382Ssklower eon_initcache() 25936382Ssklower { 26036382Ssklower static struct eon_centry eoncache[EON_CACHESIZE]; 26136382Ssklower register int i; 26236382Ssklower register struct eon_centry *ent; 26336382Ssklower 26436382Ssklower bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry)); 26536382Ssklower INITQ( &eon_FREE_hdr ); 26636382Ssklower INITQ( &eon_LINK_hdr ); 26736382Ssklower INITQ( &eon_IS_hdr ); 26836382Ssklower INITQ( &eon_ES_hdr ); 26936382Ssklower 27036382Ssklower ent = eoncache; 27136382Ssklower 27236382Ssklower for(i=0; i< EON_CACHESIZE; i++,ent++) { 27336382Ssklower _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)), 27436382Ssklower &eon_FREE_hdr); 27536382Ssklower } 27636382Ssklower printf("eon0: cache initialized\n"); 27736382Ssklower } 27836382Ssklower 27936382Ssklower /* 28036382Ssklower * FUNCTION: eonprobe 28136382Ssklower * 28236382Ssklower * PURPOSE: filler for device configuration 28336382Ssklower * 28436382Ssklower * RETURNS: PROBE_OK 28536382Ssklower */ 28636382Ssklower 28737469Ssklower int int_level, int_irq; 28836382Ssklower eonprobe() 28936382Ssklower { 29036382Ssklower extern int int_level, int_irq; 29136382Ssklower 29236382Ssklower printf("eonprobe() \n"); 29336382Ssklower int_level = int_irq = 0x3; /* pick something - anything but -1 */ 29436382Ssklower return PROBE_OK; 29536382Ssklower } 29636382Ssklower 29736382Ssklower /* 29836382Ssklower * FUNCTION: eonattach 29936382Ssklower * 30036382Ssklower * PURPOSE: autoconf attach routine 30136382Ssklower * 30236382Ssklower * RETURNS: void 30336382Ssklower */ 30436382Ssklower 30536382Ssklower eonattach(iod) 30636382Ssklower register struct iocc_device *iod; 30736382Ssklower { 30836382Ssklower register struct ifnet *ifp = &eonif[iod->iod_unit]; 30936382Ssklower 31036382Ssklower IFDEBUG(D_EON) 31136382Ssklower printf("eonattach()\n"); 31236382Ssklower ENDDEBUG 31336382Ssklower ifp->if_unit = iod->iod_unit; 31436382Ssklower ifp->if_name = "eon"; 31536382Ssklower ifp->if_mtu = ETHERMTU; 31636382Ssklower /* since everything will go out over ether or token ring */ 31736382Ssklower 31836382Ssklower ifp->if_init = eoninit; 31937469Ssklower ifp->if_ioctl = eonioctl; 32036382Ssklower ifp->if_output = eonoutput; 32137469Ssklower ifp->if_type = IFT_EON; 32237469Ssklower ifp->if_addrlen = 5; 32337469Ssklower ifp->if_hdrlen = EONIPLEN; 32436382Ssklower ifp->if_flags = IFF_BROADCAST; 32536382Ssklower if_attach(ifp); 32636382Ssklower 32736382Ssklower IFDEBUG(D_EON) 32836382Ssklower printf("eonattach()\n"); 32936382Ssklower ENDDEBUG 33036382Ssklower eon_initcache(); 33136382Ssklower IFDEBUG(D_EON) 33236382Ssklower printf("eon%d: attached\n", iod->iod_unit); 33336382Ssklower ENDDEBUG 33436382Ssklower } 33536382Ssklower 33636382Ssklower static struct eon_centry * 33736382Ssklower find_oldent( ea ) 33836382Ssklower struct sockaddr_eon *ea; 33936382Ssklower { 34036382Ssklower register int offset = 34136382Ssklower _offsetof( struct eon_centry, eonc_q_LINK); 34237469Ssklower register struct eon_centry *ent, *oent; 34336382Ssklower 34437469Ssklower oent = ent = qtocentry(eon_LINK_hdr.link, offset); 34536382Ssklower IFDEBUG(D_EON) 34636382Ssklower printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n", 34736382Ssklower (ea->seon_ipaddr>>24)&0xff, 34836382Ssklower (ea->seon_ipaddr>>16)&0xff, 34936382Ssklower (ea->seon_ipaddr>>8)&0xff, 35036382Ssklower (ea->seon_ipaddr)&0xff ); 35136382Ssklower ENDDEBUG 35237469Ssklower do { 35336382Ssklower if( ent->eonc_addr.s_addr == ea->seon_ipaddr ) 35436382Ssklower return ent; 35537469Ssklower ent = qtocentry(ent->eonc_nextLINK, offset); 35637469Ssklower } while (ent != oent); 35736382Ssklower return (struct eon_centry *)0; 35836382Ssklower } 35936382Ssklower 36036382Ssklower /* 36136382Ssklower * FUNCTION: eonioctl 36236382Ssklower * 36336382Ssklower * PURPOSE: io controls - ifconfig 36436382Ssklower * need commands to 36536382Ssklower * link-UP (core addr) (flags: ES, IS) 36636382Ssklower * link-DOWN (core addr) (flags: ES, IS) 36736382Ssklower * must be callable from kernel or user 36836382Ssklower * 36936382Ssklower * RETURNS: nothing 37036382Ssklower */ 37136382Ssklower eonioctl(ifp, cmd, data) 37236382Ssklower register struct ifnet *ifp; 37336382Ssklower register int cmd; 37436382Ssklower register caddr_t data; 37536382Ssklower { 37637469Ssklower struct iso_ifreq *ifr = (struct iso_ifreq *)data; 37736382Ssklower register struct sockaddr_eon *eoa = 37837469Ssklower (struct sockaddr_eon *)&(ifr->ifr_Addr); 37936382Ssklower register int s = splimp(); 38036382Ssklower register int error = 0; 38136382Ssklower 38236382Ssklower IFDEBUG(D_EON) 38336382Ssklower printf("eonioctl (cmd 0x%x) \n", cmd); 38436382Ssklower ENDDEBUG 38536382Ssklower 38636382Ssklower switch (cmd){ 38737469Ssklower case SIOCSEONCORE: { 38836382Ssklower /* add pt-pt link to the set of core addrs */ 38936382Ssklower register struct eon_centry *ent, *oldent; 39036382Ssklower register u_short which; 39136382Ssklower 39236382Ssklower /* "which" tells which lists to put these guys in - don't 39336382Ssklower * want to insert something in a list if it's already there 39436382Ssklower */ 39536382Ssklower #define LEGIT_EONADDR(a)\ 39637469Ssklower ((a->seon_family == AF_ISO) && (a->seon_afi == AFI_RFC986) &&\ 39736382Ssklower (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \ 39837469Ssklower && (a->seon_vers == EON_986_VERSION) && (a->seon_adrlen == 0x14)) 39936382Ssklower 40036382Ssklower if( ! LEGIT_EONADDR(eoa) ) { 40136382Ssklower error = EADDRNOTAVAIL; 40236382Ssklower break; 40336382Ssklower } 40436382Ssklower 40536382Ssklower oldent = find_oldent( eoa ); 40636382Ssklower IFDEBUG(D_EON) 40736382Ssklower printf("eonioctl legit seon_status 0x%x oldent %s\n", 40836382Ssklower eoa->seon_status, oldent?"found":"not found"); 40936382Ssklower ENDDEBUG 41036382Ssklower 41136382Ssklower if( eoa->seon_status & UPBITS ) { 41236382Ssklower if (!oldent) { 41336382Ssklower /* doesn't exist - need to create one */ 41437469Ssklower if (eon_FREE_hdr.link == eon_FREE_hdr.rlink) 41537469Ssklower return ENOBUFS; 41636382Ssklower ent = qtocentry(eon_FREE_hdr.link, 41736382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 41836382Ssklower remque( &(ent->eonc_q_LINK) ); 41936382Ssklower ent->eonc_addr.s_addr = eoa->seon_ipaddr; 42037469Ssklower insque( &(ent->eonc_q_LINK), (&eon_LINK_hdr)); 42136382Ssklower oldent = ent; 42236382Ssklower } 42336382Ssklower 42436382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 42536382Ssklower eoa->seon_status & UPBITS; 42636382Ssklower 42736382Ssklower oldent->eonc_status |= (eoa->seon_status & UPBITS); 42836382Ssklower 42936382Ssklower if( which & EON_ESLINK_UP ) 43036382Ssklower insque( &oldent->eonc_q_ES, (&eon_ES_hdr)); 43136382Ssklower if( which & EON_ISLINK_UP ) 43236382Ssklower insque( &oldent->eonc_q_IS, (&eon_IS_hdr)); 43336382Ssklower } 43436382Ssklower 43536382Ssklower if( eoa->seon_status & DOWNBITS ) { 43636382Ssklower if(!oldent) { 43736382Ssklower return ENOENT; /* no such entry */ 43836382Ssklower } 43936382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 44036382Ssklower eoa->seon_status & DOWNBITS; 44136382Ssklower 44236382Ssklower oldent->eonc_status |= (eoa->seon_status & DOWNBITS); 44336382Ssklower 44436382Ssklower if( which & EON_ESLINK_DOWN ) 44536382Ssklower remque( &(oldent->eonc_q_ES) ); 44636382Ssklower if( which & EON_ISLINK_DOWN ) 44736382Ssklower remque( &(oldent->eonc_q_IS) ); 44836382Ssklower } 44936382Ssklower 45036382Ssklower IFDEBUG(D_EON) 45136382Ssklower printf("at end status 0x%x\n", oldent->eonc_status); 45236382Ssklower ENDDEBUG 45336382Ssklower break; 45436382Ssklower } 45536382Ssklower 45637469Ssklower case SIOCGEONCORE: 45736382Ssklower { 45836382Ssklower register struct eon_centry *oldent; 45936382Ssklower 46036382Ssklower oldent = find_oldent( eoa ); 46136382Ssklower if( oldent == (struct eon_centry *)0 ) 46236382Ssklower error = EADDRNOTAVAIL; 46336382Ssklower else 46436382Ssklower eoa->seon_status = oldent->eonc_status; 46536382Ssklower } 46636382Ssklower break; 46736382Ssklower 46836382Ssklower case SIOCSIFADDR: 46936382Ssklower ifp->if_flags |= IFF_UP; 47036382Ssklower break; 47136382Ssklower 47236382Ssklower case SIOCSIFFLAGS: 47336382Ssklower if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & 47436382Ssklower IFF_RUNNING){ 47536382Ssklower ifp->if_flags &= ~IFF_RUNNING; 47636382Ssklower } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & 47736382Ssklower IFF_RUNNING) == 0) 47836382Ssklower eoninit(ifp->if_unit); 47936382Ssklower break; 48036382Ssklower default: 48136382Ssklower error = EINVAL; 48236382Ssklower } 48336382Ssklower splx(s); 48436382Ssklower return(error); 48536382Ssklower } 48636382Ssklower 48736382Ssklower /* 48836382Ssklower * FUNCTION: eoninit 48936382Ssklower * 49036382Ssklower * PURPOSE: initialization 49136382Ssklower * 49236382Ssklower * RETURNS: nothing 49336382Ssklower */ 49436382Ssklower 49536382Ssklower eoninit(unit) 49636382Ssklower int unit; 49736382Ssklower { 49837469Ssklower printf("eon driver-init eon%d\n", unit); 49936382Ssklower } 50036382Ssklower 50136382Ssklower 50236382Ssklower /* 50336382Ssklower * FUNCTION: eonint 50436382Ssklower * 50536382Ssklower * PURPOSE: filler for device configuration 50636382Ssklower * 50736382Ssklower * RETURNS: nothing 50836382Ssklower * 50936382Ssklower * NOTES: *should* never get called - for debugging it's here 51036382Ssklower */ 51136382Ssklower 51236382Ssklower eonint() 51336382Ssklower { 51436382Ssklower /* silent - so no more stray interrupt messages from the aed! yay 51536382Ssklower printf("eonint() called - BOGUS INTERRUPT\n"); 51636382Ssklower */ 51736382Ssklower } 51836382Ssklower 51936382Ssklower 52036382Ssklower /* 52136382Ssklower * FUNCTION: eonoutput 52236382Ssklower * 52336382Ssklower * PURPOSE: prepend an eon header and hand to IP 52436382Ssklower * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device 52536382Ssklower * (m) is an mbuf *, *m is a CLNL packet 52636382Ssklower * (dst) is a destination address - have to interp. as 52736382Ssklower * multicast or broadcast or real address. 52836382Ssklower * 52936382Ssklower * RETURNS: unix error code 53036382Ssklower * 53136382Ssklower * NOTES: 53236382Ssklower * 53336382Ssklower */ 53436382Ssklower eonoutput(ifp, morig, dst) 53537469Ssklower struct ifnet *ifp; 53636382Ssklower register struct mbuf *morig; /* packet */ 53736382Ssklower struct sockaddr_iso *dst; /* destination addr */ 53836382Ssklower { 53936382Ssklower int s; 54036382Ssklower struct eon_hdr *eonhdr; 54136382Ssklower struct ip *iphdr; 54236382Ssklower struct mbuf *mh; 54336382Ssklower int error = 0; 54436382Ssklower register int datalen; 54536382Ssklower caddr_t dstipaddrloc; 54637469Ssklower int single = 0, class, qoffset = 0, snpalen; 54736382Ssklower register struct eon_centry *ent; 54837469Ssklower register struct sockaddr_eon *eoa; 54936382Ssklower struct qhdr *q; 55037469Ssklower char edst[6]; 55136382Ssklower 55236382Ssklower IFDEBUG(D_EON) 55336382Ssklower printf("eonoutput \n" ); 55436382Ssklower ENDDEBUG 55536382Ssklower 556*39195Ssklower ifp->if_lastchange = time; 557*39195Ssklower ifp->if_opackets++; 55837469Ssklower if( dst->siso_family != AF_ISO ) { 55937469Ssklower einval: 56037469Ssklower error = EINVAL; 56137469Ssklower goto flush; 56237469Ssklower } 56337469Ssklower if ((morig->m_flags & M_PKTHDR) == 0) { 56437469Ssklower printf("eon: got non headered packet\n"); 56537469Ssklower goto einval; 56637469Ssklower } 56737469Ssklower eoa = (struct sockaddr_eon *)dst; 56837469Ssklower if (LEGIT_EONADDR(eoa)) { 56937469Ssklower class = eoa->seon_protoid; 57037469Ssklower dstipaddrloc = (caddr_t)&(eoa->seon_ipaddr); 57137469Ssklower } else if (eoa->seon_afi == AFI_SNA) { 57237469Ssklower dstipaddrloc = (caddr_t)&(dst->siso_data[1]); 57337469Ssklower if (dst->siso_nlen == 6) { 57437469Ssklower class = dst->siso_data[5]; 57537469Ssklower } else if (dst->siso_nlen == 7) { 57637469Ssklower if (bcmp(dstipaddrloc, all_is.sc_snpa, 6)) 57737469Ssklower class = EON_MULTICAST_ES; 57837469Ssklower else if (bcmp(dstipaddrloc, all_es.sc_snpa, 6)) 57937469Ssklower class = EON_MULTICAST_IS; 58037469Ssklower else 58137469Ssklower goto einval; 58237469Ssklower } else 58337469Ssklower goto einval; 58437469Ssklower } else if (0 == iso_snparesolve(ifp, dst, edst, &snpalen)) { 58537469Ssklower dstipaddrloc = (caddr_t)edst; 58637469Ssklower class = edst[4]; 58737469Ssklower } else { 58837469Ssklower error = EINVAL; 58937469Ssklower goto flush; 59037469Ssklower } 59137469Ssklower switch (class) { 59236382Ssklower case EON_NORMAL_ADDR: 59336382Ssklower IncStat(es_out_normal); 59436382Ssklower single = 1; 59536382Ssklower break; 59636382Ssklower 59736382Ssklower case EON_BROADCAST: 59836382Ssklower IncStat(es_out_broad); 59937469Ssklower if(eon_LINK_hdr.link == eon_LINK_hdr.rlink) { 60036382Ssklower error = EADDRNOTAVAIL; 60136382Ssklower } else { 60236382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 60336382Ssklower ent = qtocentry(eon_LINK_hdr.link, qoffset); 60436382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 60536382Ssklower } 60636382Ssklower break; 60736382Ssklower case EON_MULTICAST_ES: 60836382Ssklower IncStat(es_out_multi_es); 60937469Ssklower if (eon_ES_hdr.link == eon_ES_hdr.rlink) { 61036382Ssklower error = EADDRNOTAVAIL; 61136382Ssklower } else { 61236382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_ES); 61336382Ssklower ent = qtocentry(eon_ES_hdr.link, qoffset); 61436382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 61536382Ssklower } 61636382Ssklower break; 61736382Ssklower case EON_MULTICAST_IS: 61836382Ssklower IncStat(es_out_multi_is); 61937469Ssklower if (eon_IS_hdr.link == eon_IS_hdr.rlink) { 62036382Ssklower error = EADDRNOTAVAIL; 62136382Ssklower } else { 62236382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 62336382Ssklower ent = qtocentry(eon_IS_hdr.link, qoffset); 62436382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 62536382Ssklower } 62636382Ssklower break; 62736382Ssklower default: 62837469Ssklower printf("bad class value; treated as EON_NORMAL_ADDR\n"); 62937469Ssklower class = EON_NORMAL_ADDR; 63036382Ssklower single = 1; 63136382Ssklower break; 63236382Ssklower } 63336382Ssklower if( error ) 63436382Ssklower goto done; 63536382Ssklower 63636382Ssklower /* get data length -- needed later */ 63737469Ssklower datalen = morig->m_pkthdr.len; 63836382Ssklower IFDEBUG(D_EON) 63936382Ssklower printf("eonoutput : m_datalen returns %d\n", datalen); 64036382Ssklower ENDDEBUG 64136382Ssklower 64237469Ssklower MGETHDR(mh, M_DONTWAIT, MT_HEADER); 64337469Ssklower if(mh == (struct mbuf *)0) 64436382Ssklower goto done; 64536382Ssklower 64636382Ssklower /* put an eon_hdr in the buffer, prepended by an ip header */ 64736382Ssklower mh->m_len = sizeof(struct eon_hdr); 64837469Ssklower MH_ALIGN(mh, sizeof(struct eon_hdr)); 64936382Ssklower mh->m_next = morig; 65036382Ssklower eonhdr = mtod(mh, struct eon_hdr *); 65137469Ssklower eonhdr->eonh_class = class; 65236382Ssklower eonhdr->eonh_vers = EON_VERSION; 65337469Ssklower eonhdr->eonh_csum = 0; 65436382Ssklower 65536382Ssklower IFDEBUG(D_EON) 65636382Ssklower printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", 65736382Ssklower mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 65836382Ssklower ENDDEBUG 65936382Ssklower iso_gen_csum(mh, 66036382Ssklower _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 66136382Ssklower 66237469Ssklower mh->m_data -= sizeof(*iphdr); 66337469Ssklower mh->m_len += sizeof(*iphdr); 66436382Ssklower iphdr = mtod(mh, struct ip *); 66537469Ssklower bzero((caddr_t)iphdr, sizeof (*iphdr)); 66636382Ssklower 66736382Ssklower iphdr->ip_p = IPPROTO_EON; 668*39195Ssklower ifp->if_obytes += 669*39195Ssklower (iphdr->ip_len = (u_short)(mh->m_pkthdr.len = EONIPLEN + datalen)); 67036382Ssklower iphdr->ip_ttl = MAXTTL; 67136382Ssklower iphdr->ip_src.s_addr = INADDR_ANY; 67236382Ssklower 67336382Ssklower IFDEBUG(D_EON) 67436382Ssklower printf("eonoutput : after gen csum: ip_len %d/0x%x\n", 67537469Ssklower mh->m_pkthdr.len, mh->m_pkthdr.len); 67636382Ssklower ENDDEBUG 67736382Ssklower 67836382Ssklower morig = mh; 67936382Ssklower 68036382Ssklower for(;;) { 68136382Ssklower 68236382Ssklower if( !single ) { 68336382Ssklower /* make a copy to send */ 68436382Ssklower IFDEBUG(D_EON) 68536382Ssklower printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n", 68636382Ssklower morig, iphdr->ip_len); 68736382Ssklower ENDDEBUG 68837469Ssklower if (((mh = m_copy(morig, 0, morig->m_pkthdr.len)) == 0) || 68937469Ssklower ((mh = m_pullup(mh, sizeof(struct ip))) == 0)) { 69037469Ssklower error = ENOBUFS; 69137469Ssklower goto done; 69237469Ssklower } 69336382Ssklower iphdr = mtod(mh, struct ip *); 69436382Ssklower } 69536382Ssklower IFDEBUG(D_EON) 69636382Ssklower printf("eonoutput : bcopy 0x%x to 0x%x length %d\n", 69736382Ssklower dstipaddrloc, 69836382Ssklower (caddr_t)&(iphdr->ip_dst.s_addr), 69936382Ssklower sizeof(iphdr->ip_dst.s_addr)); 70036382Ssklower ENDDEBUG 70137469Ssklower bcopy(dstipaddrloc, (caddr_t)&(iphdr->ip_dst.s_addr), 70237469Ssklower sizeof(iphdr->ip_dst.s_addr)); 70336382Ssklower IFDEBUG(D_EON) 70436382Ssklower printf("eonoutput : dst ip addr : %d.%d.%d.%d", 70536382Ssklower (iphdr->ip_dst.s_addr>>24)&0xff, 70636382Ssklower (iphdr->ip_dst.s_addr>>16)&0xff, 70736382Ssklower (iphdr->ip_dst.s_addr>>8)&0xff, 70836382Ssklower (iphdr->ip_dst.s_addr)&0xff ); 70936382Ssklower ENDDEBUG 71036382Ssklower 71136382Ssklower IFDEBUG(D_EON) 71236382Ssklower printf("eonoutput ip_output : eon header:\n"); 71336382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 71436382Ssklower printf("ip header:\n"); 71536382Ssklower dump_buf(iphdr, sizeof(struct ip)); 71636382Ssklower ENDDEBUG 71736382Ssklower 71836382Ssklower IncStat(es_ipout); 71936382Ssklower if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) ) 72036382Ssklower break; 72136382Ssklower 72236382Ssklower IFDEBUG(D_EON) 72336382Ssklower printf("eonoutput ip_output returns 0x%x; single %d\n", 72436382Ssklower error, single); 72536382Ssklower ENDDEBUG 72636382Ssklower 72736382Ssklower if(single) 72836382Ssklower break; 72936382Ssklower 73036382Ssklower q = centrytoq(ent, qoffset)->link; 73136382Ssklower if( q == (struct qhdr *)0) 73236382Ssklower break; 73336382Ssklower ent = qtocentry( q, qoffset ); 73436382Ssklower IFDEBUG(D_EON) 73536382Ssklower printf("eonoutput : get next entry: 0x%x\n", ent); 73636382Ssklower ENDDEBUG 73736382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 73836382Ssklower IFDEBUG(D_EON) 73936382Ssklower printf("eonoutput : dump of eon_centry 0x%x:\n", ent ); 74036382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 74136382Ssklower ENDDEBUG 74236382Ssklower } 74336382Ssklower done: 74436382Ssklower if( !single ) { 74536382Ssklower IFDEBUG(D_EON) 74636382Ssklower printf("eonoutput : freeing morig 0x%x\n", morig); 74736382Ssklower ENDDEBUG 74837469Ssklower flush: 74936382Ssklower m_freem(morig); 75036382Ssklower } 751*39195Ssklower if (error) { 752*39195Ssklower ifp->if_oerrors++; 753*39195Ssklower ifp->if_opackets--; 754*39195Ssklower ifp->if_obytes -= datalen + EONIPLEN; 755*39195Ssklower } 75636382Ssklower return error; 75736382Ssklower } 75836382Ssklower 75937469Ssklower eoninput(m, iphlen) 76036382Ssklower register struct mbuf *m; 76137469Ssklower int iphlen; 76236382Ssklower { 76336382Ssklower register struct eon_hdr *eonhdr; 76436382Ssklower register struct ip *iphdr; 76536382Ssklower struct ifnet *eonifp; 76637469Ssklower int s; 76736382Ssklower 76836382Ssklower eonifp = &eonif[0]; /* kludge - really want to give CLNP 76936382Ssklower * the ifp for eon, not for the real device 77036382Ssklower */ 77136382Ssklower 77236382Ssklower IFDEBUG(D_EON) 77337469Ssklower printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n", 77437469Ssklower m, m?m->m_data:0, m?m->m_len:0); 77536382Ssklower ENDDEBUG 77636382Ssklower 77737469Ssklower if (m == 0) 77837469Ssklower return; 77937469Ssklower if (iphlen > sizeof (struct ip)) 78037469Ssklower ip_stripoptions(m, (struct mbuf *)0); 78137469Ssklower if (m->m_len < EONIPLEN) { 78237469Ssklower if ((m = m_pullup(m, EONIPLEN)) == 0) { 78337469Ssklower IncStat(es_badhdr); 78437469Ssklower drop: 78537469Ssklower IFDEBUG(D_EON) 78637469Ssklower printf("eoninput: DROP \n" ); 78737469Ssklower ENDDEBUG 78837469Ssklower eonifp->if_ierrors ++; 78937469Ssklower m_freem(m); 79037469Ssklower return; 79137469Ssklower } 79236382Ssklower } 793*39195Ssklower eonif->if_ibytes += m->m_pkthdr.len; 794*39195Ssklower eonif->if_lastchange = time; 79536382Ssklower iphdr = mtod(m, struct ip *); 79636382Ssklower /* do a few checks for debugging */ 79736382Ssklower if( iphdr->ip_p != IPPROTO_EON ) { 79836382Ssklower IncStat(es_badhdr); 79936382Ssklower goto drop; 80036382Ssklower } 80137469Ssklower /* temporarily drop ip header from the mbuf */ 80237469Ssklower m->m_data += sizeof(struct ip); 80336382Ssklower eonhdr = mtod(m, struct eon_hdr *); 80437469Ssklower if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) { 80537469Ssklower IncStat(es_badcsum); 80637469Ssklower goto drop; 80737469Ssklower } 80837469Ssklower m->m_data -= sizeof(struct ip); 80937469Ssklower 81036382Ssklower IFDEBUG(D_EON) 81137469Ssklower printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class ); 81236382Ssklower printf("eoninput: eon header:\n"); 81336382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 81436382Ssklower ENDDEBUG 81536382Ssklower 81636382Ssklower /* checks for debugging */ 81736382Ssklower if( eonhdr->eonh_vers != EON_VERSION) { 81836382Ssklower IncStat(es_badhdr); 81936382Ssklower goto drop; 82036382Ssklower } 82137469Ssklower m->m_flags &= ~(M_BCAST|M_MCAST); 82236382Ssklower switch( eonhdr->eonh_class) { 82336382Ssklower case EON_BROADCAST: 82436382Ssklower IncStat(es_in_broad); 82537469Ssklower m->m_flags |= M_BCAST; 82636382Ssklower break; 82736382Ssklower case EON_NORMAL_ADDR: 82836382Ssklower IncStat(es_in_normal); 82936382Ssklower break; 83036382Ssklower case EON_MULTICAST_ES: 83136382Ssklower IncStat(es_in_multi_es); 83237469Ssklower m->m_flags |= M_MCAST; 83336382Ssklower break; 83436382Ssklower case EON_MULTICAST_IS: 83536382Ssklower IncStat(es_in_multi_is); 83637469Ssklower m->m_flags |= M_MCAST; 83736382Ssklower break; 83836382Ssklower } 839*39195Ssklower eonifp->if_ipackets++; 84036382Ssklower 84136382Ssklower { 84236382Ssklower /* put it on the CLNP queue and set soft interrupt */ 84336382Ssklower struct ifqueue *ifq; 84436382Ssklower extern struct ifqueue clnlintrq; 84536382Ssklower 84637469Ssklower m->m_pkthdr.rcvif = eonifp; /* KLUDGE */ 84736382Ssklower IFDEBUG(D_EON) 84836382Ssklower printf("eoninput to clnl IFQ\n"); 84936382Ssklower ENDDEBUG 85036382Ssklower ifq = &clnlintrq; 85137469Ssklower s = splimp(); 85236382Ssklower if (IF_QFULL(ifq)) { 85336382Ssklower IF_DROP(ifq); 85436382Ssklower m_freem(m); 855*39195Ssklower eonifp->if_iqdrops++; 856*39195Ssklower eonifp->if_ipackets--; 85736382Ssklower splx(s); 85836382Ssklower return; 85936382Ssklower } 86036382Ssklower IF_ENQUEUE(ifq, m); 86136382Ssklower IFDEBUG(D_EON) 86236382Ssklower printf( 86337469Ssklower "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n", 86437469Ssklower m, m->m_len, m->m_type, m->m_data); 86536382Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 86636382Ssklower ENDDEBUG 86737469Ssklower schednetisr(NETISR_ISO); 86837469Ssklower splx(s); 86936382Ssklower } 87036382Ssklower } 87136382Ssklower 87236382Ssklower int 87336382Ssklower eonctlinput(cmd, sin) 87436382Ssklower int cmd; 87536382Ssklower struct sockaddr_in *sin; 87636382Ssklower { 87736382Ssklower extern u_char inetctlerrmap[]; 87836382Ssklower 87936382Ssklower IFDEBUG(D_EON) 88036382Ssklower printf("eonctlinput: cmd 0x%x addr: ", cmd); 88136382Ssklower dump_isoaddr(sin); 88236382Ssklower printf("\n"); 88336382Ssklower ENDDEBUG 88436382Ssklower 88536382Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 88636382Ssklower return 0; 88736382Ssklower 88836382Ssklower IncStat(es_icmp[cmd]); 88936382Ssklower switch (cmd) { 89036382Ssklower 89137469Ssklower case PRC_QUENCH: 89236382Ssklower case PRC_QUENCH2: 89336382Ssklower /* TODO: set the dec bit */ 89436382Ssklower break; 89536382Ssklower case PRC_TIMXCEED_REASS: 89636382Ssklower case PRC_ROUTEDEAD: 89736382Ssklower case PRC_HOSTUNREACH: 89836382Ssklower case PRC_UNREACH_NET: 89936382Ssklower case PRC_IFDOWN: 90036382Ssklower case PRC_UNREACH_HOST: 90136382Ssklower case PRC_HOSTDEAD: 90236382Ssklower case PRC_TIMXCEED_INTRANS: 90336382Ssklower /* TODO: mark the link down */ 90436382Ssklower break; 90536382Ssklower 90636382Ssklower case PRC_UNREACH_PROTOCOL: 90736382Ssklower case PRC_UNREACH_PORT: 90836382Ssklower case PRC_UNREACH_NEEDFRAG: 90936382Ssklower case PRC_UNREACH_SRCFAIL: 91036382Ssklower case PRC_REDIRECT_NET: 91136382Ssklower case PRC_REDIRECT_HOST: 91236382Ssklower case PRC_REDIRECT_TOSNET: 91336382Ssklower case PRC_REDIRECT_TOSHOST: 91436382Ssklower case PRC_MSGSIZE: 91536382Ssklower case PRC_PARAMPROB: 91636382Ssklower printf("eonctlinput: ICMP cmd 0x%x\n", cmd ); 91736382Ssklower break; 91836382Ssklower } 91936382Ssklower return 0; 92036382Ssklower } 92136382Ssklower 92237469Ssklower #endif 923