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 $ 3036382Ssklower * 3136382Ssklower * EON rfc 3236382Ssklower * Layer between IP and CLNL 3336382Ssklower * 3436382Ssklower * TODO: 3536382Ssklower * Put together a current rfc986 address format and get the right offset 3636382Ssklower * for the nsel 3736382Ssklower */ 3836382Ssklower 3936382Ssklower #ifndef lint 4036382Ssklower static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $"; 4136382Ssklower #endif lint 4236382Ssklower 4337469Ssklower #ifdef EON 4437469Ssklower #define NEON 1 4536382Ssklower 4637469Ssklower 4736382Ssklower #include "param.h" 4836382Ssklower #include "systm.h" 4936382Ssklower #include "types.h" 5036382Ssklower #include "mbuf.h" 5136382Ssklower #include "buf.h" 5236382Ssklower #include "protosw.h" 5336382Ssklower #include "socket.h" 5436382Ssklower #include "ioctl.h" 5536382Ssklower #include "errno.h" 5636382Ssklower #include "types.h" 5736382Ssklower 5836382Ssklower #include "../net/if.h" 5937469Ssklower #include "../net/iftypes.h" 6036382Ssklower #include "../net/netisr.h" 6136382Ssklower #include "../net/route.h" 62*37518Smckusick #include "machine/mtpr.h" 6336382Ssklower 6436382Ssklower #include "../netinet/in.h" 6536382Ssklower #include "../netinet/in_systm.h" 6636382Ssklower #include "../netinet/ip.h" 6736382Ssklower #include "../netinet/ip_var.h" 6836382Ssklower #include "../netinet/if_ether.h" 6936382Ssklower 7037469Ssklower #include "iso.h" 7137469Ssklower #include "iso_var.h" 7237469Ssklower #include "iso_snpac.h" 7337469Ssklower extern struct snpa_cache all_es, all_is; 7437469Ssklower #include "argo_debug.h" 7537469Ssklower #include "iso_errno.h" 7637469Ssklower #include "eonvar.h" 7736382Ssklower 7836382Ssklower #define EOK 0 7936382Ssklower 8036382Ssklower int eoninput(); 8136382Ssklower int eonint(); 8236382Ssklower int eonoutput(); 8336382Ssklower int eonioctl(); 8436382Ssklower int eonprobe(); 8536382Ssklower int eonattach(); 8636382Ssklower int eoninit(); 8736382Ssklower extern int ip_output(); 8836382Ssklower struct ifnet eonif[NEON]; 8936382Ssklower 9037469Ssklower #ifdef FAKEIOCCDEV 91*37518Smckusick #include "machine/io.h" 9237469Ssklower #include "../machineio/ioccvar.h" 9337469Ssklower 9436382Ssklower #define EON_FAKE_CSR 0 9536382Ssklower int eon_fakeautoconf[2]; /* need at least 2 ints */ 9636382Ssklower 9736382Ssklower caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 }; 9836382Ssklower struct iocc_device *eoninfo[NEON]; 9936382Ssklower 10036382Ssklower struct iocc_driver eondriver = { 10136382Ssklower eonprobe, /* idr_probe */ 10236382Ssklower 0, /* idr_slave */ 10336382Ssklower eonattach, /* idr_attach */ 10436382Ssklower 0, /* idr_dgo */ 10536382Ssklower eonstd, /* idr_addr - list of standard addresses for device */ 10636382Ssklower "eon", /* idr_dname */ 10736382Ssklower eoninfo, /* idr_dinfo - backptrs to iodinit structs */ 10836382Ssklower 0, /* idr_mname - controller name */ 10936382Ssklower 0, /* idr_minfo -- backptrs to iominit structs */ 11036382Ssklower eonint, /* idr_intr - interrupt rtn */ 11136382Ssklower 0, /* idr_csr - offset to read/write csr */ 11236382Ssklower EON_FAKE_CSR, /* idr_chanrelse */ 11336382Ssklower 0, /* idr_flags */ 11436382Ssklower }; 11537469Ssklower #else 11637469Ssklower struct iocc_device { 11737469Ssklower int iod_unit; 11837469Ssklower } bsd_iocc_fakeout; 11936382Ssklower 12037469Ssklower eonprotoinit() { 12137469Ssklower (void) eonprobe(); 12237469Ssklower (void) eonattach(&bsd_iocc_fakeout); 12337469Ssklower } 12437469Ssklower #define PROBE_OK 0; 12537469Ssklower #endif 12636382Ssklower 12737469Ssklower 12836382Ssklower /* 12936382Ssklower * entry in the EON address cache (list) 13036382Ssklower * (or pt-pt links list, however you view it) 13136382Ssklower */ 13236382Ssklower 13336382Ssklower struct eon_centry { 13436382Ssklower struct qhdr eonc_q_LINK; 13536382Ssklower #define eonc_nextLINK eonc_q_LINK.link 13636382Ssklower #define eonc_prevLINK eonc_q_LINK.flink 13736382Ssklower 13836382Ssklower struct qhdr eonc_q_IS; 13936382Ssklower #define eonc_nextIS eonc_q_IS.link 14036382Ssklower #define eonc_prevIS eonc_q_IS.flink 14136382Ssklower 14236382Ssklower struct qhdr eonc_q_ES; 14336382Ssklower #define eonc_nextES eonc_q_ES.link 14436382Ssklower #define eonc_prevES eonc_q_ES.flink 14536382Ssklower 14636382Ssklower struct in_addr eonc_addr; 14736382Ssklower u_short eonc_status; 14836382Ssklower }; 14936382Ssklower 15036382Ssklower /* kinda like mtod() but for eon_centries */ 15136382Ssklower #define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off)) 15236382Ssklower #define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off)) 15336382Ssklower 15436382Ssklower struct qhdr eon_LINK_hdr = { 15536382Ssklower (struct qhdr *)0, 15636382Ssklower (struct qhdr *)0, 15736382Ssklower }; 15836382Ssklower static struct qhdr eon_IS_hdr = { 15936382Ssklower (struct qhdr *)0, 16036382Ssklower (struct qhdr *)0, 16136382Ssklower }; 16236382Ssklower static struct qhdr eon_ES_hdr = { 16336382Ssklower (struct qhdr *)0, 16436382Ssklower (struct qhdr *)0, 16536382Ssklower }; 16636382Ssklower static struct qhdr eon_FREE_hdr = { 16736382Ssklower (struct qhdr *)0, 16836382Ssklower (struct qhdr *)0, 16936382Ssklower }; 17036382Ssklower 17136382Ssklower #define INITQ(q) (q)->rlink = (q)->link = (q) 17236382Ssklower 17336382Ssklower /* 17436382Ssklower * FUNCTION: eon_dumpcache 17536382Ssklower * 17636382Ssklower * PURPOSE: dump the cache beginning with the argument given 17736382Ssklower * 17836382Ssklower * RETURNS: 0 17936382Ssklower */ 18036382Ssklower 18136382Ssklower eon_dumpcache(which) 18236382Ssklower int which; 18336382Ssklower { 18436382Ssklower register int off; 18536382Ssklower register struct eon_centry *ent; 18636382Ssklower struct qhdr *hdr; 18736382Ssklower 18836382Ssklower switch (which) { 18936382Ssklower case E_FREE: 19036382Ssklower printf("FREE LIST\n"); 19136382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 19236382Ssklower hdr = &eon_FREE_hdr; 19336382Ssklower ent = qtocentry( hdr->link, 19436382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 19536382Ssklower break; 19636382Ssklower case E_ES: 19736382Ssklower printf("ES LIST\n"); 19836382Ssklower off = _offsetof( struct eon_centry, eonc_q_ES); 19936382Ssklower hdr = &eon_ES_hdr; 20036382Ssklower ent = qtocentry( hdr->link, 20136382Ssklower _offsetof( struct eon_centry, eonc_q_ES)); 20236382Ssklower break; 20336382Ssklower case E_IS: 20436382Ssklower printf("IS LIST\n"); 20536382Ssklower off = _offsetof( struct eon_centry, eonc_q_IS); 20636382Ssklower hdr = &eon_IS_hdr; 20736382Ssklower ent = qtocentry( hdr->link, 20836382Ssklower _offsetof( struct eon_centry, eonc_q_IS)); 20936382Ssklower break; 21036382Ssklower case E_LINK: 21136382Ssklower printf("LINK LIST\n"); 21236382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 21336382Ssklower hdr = &eon_LINK_hdr; 21436382Ssklower ent = qtocentry( hdr->link, 21536382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 21636382Ssklower break; 21736382Ssklower } 21836382Ssklower if(hdr == centrytoq(ent, off)->link ) 21936382Ssklower printf("EMPTY\n"); 22036382Ssklower else while(1) { 22136382Ssklower printf("0x%x: %d.%d.%d.%d, %s %s\n", ent, 22236382Ssklower (ent->eonc_addr.s_addr>>24)&0xff, 22336382Ssklower (ent->eonc_addr.s_addr>>16)&0xff, 22436382Ssklower (ent->eonc_addr.s_addr>>8)&0xff, 22536382Ssklower (ent->eonc_addr.s_addr)&0xff, 22636382Ssklower ((ent->eonc_status & EON_ESLINK_UP)?"ES^": 22736382Ssklower (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "), 22836382Ssklower ((ent->eonc_status & EON_ISLINK_UP)?"IS^": 22936382Ssklower (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ") 23036382Ssklower ); 23136382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 23236382Ssklower 23336382Ssklower { /* ent = ent.next: */ 23436382Ssklower register struct qhdr *q; 23536382Ssklower 23636382Ssklower q = centrytoq(ent, off)->link; 23736382Ssklower if( q == hdr) 23836382Ssklower break; 23936382Ssklower if( q == (struct qhdr *)0) /* panic */ { 24036382Ssklower printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n", 24136382Ssklower q, ent, off); 24236382Ssklower break; 24336382Ssklower } 24436382Ssklower ent = qtocentry( q, off ); 24536382Ssklower } 24636382Ssklower } 24736382Ssklower } 24836382Ssklower /* 24936382Ssklower * FUNCTION: eon_initcache 25036382Ssklower * 25136382Ssklower * PURPOSE: allocs a bunch of free cache entries 25236382Ssklower * 25336382Ssklower * RETURNS: 0 25436382Ssklower */ 25536382Ssklower 25636382Ssklower eon_initcache() 25736382Ssklower { 25836382Ssklower static struct eon_centry eoncache[EON_CACHESIZE]; 25936382Ssklower register int i; 26036382Ssklower register struct eon_centry *ent; 26136382Ssklower 26236382Ssklower bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry)); 26336382Ssklower INITQ( &eon_FREE_hdr ); 26436382Ssklower INITQ( &eon_LINK_hdr ); 26536382Ssklower INITQ( &eon_IS_hdr ); 26636382Ssklower INITQ( &eon_ES_hdr ); 26736382Ssklower 26836382Ssklower ent = eoncache; 26936382Ssklower 27036382Ssklower for(i=0; i< EON_CACHESIZE; i++,ent++) { 27136382Ssklower _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)), 27236382Ssklower &eon_FREE_hdr); 27336382Ssklower } 27436382Ssklower printf("eon0: cache initialized\n"); 27536382Ssklower } 27636382Ssklower 27736382Ssklower /* 27836382Ssklower * FUNCTION: eonprobe 27936382Ssklower * 28036382Ssklower * PURPOSE: filler for device configuration 28136382Ssklower * 28236382Ssklower * RETURNS: PROBE_OK 28336382Ssklower */ 28436382Ssklower 28537469Ssklower int int_level, int_irq; 28636382Ssklower eonprobe() 28736382Ssklower { 28836382Ssklower extern int int_level, int_irq; 28936382Ssklower 29036382Ssklower printf("eonprobe() \n"); 29136382Ssklower int_level = int_irq = 0x3; /* pick something - anything but -1 */ 29236382Ssklower return PROBE_OK; 29336382Ssklower } 29436382Ssklower 29536382Ssklower /* 29636382Ssklower * FUNCTION: eonattach 29736382Ssklower * 29836382Ssklower * PURPOSE: autoconf attach routine 29936382Ssklower * 30036382Ssklower * RETURNS: void 30136382Ssklower */ 30236382Ssklower 30336382Ssklower eonattach(iod) 30436382Ssklower register struct iocc_device *iod; 30536382Ssklower { 30636382Ssklower register struct ifnet *ifp = &eonif[iod->iod_unit]; 30736382Ssklower 30836382Ssklower IFDEBUG(D_EON) 30936382Ssklower printf("eonattach()\n"); 31036382Ssklower ENDDEBUG 31136382Ssklower ifp->if_unit = iod->iod_unit; 31236382Ssklower ifp->if_name = "eon"; 31336382Ssklower ifp->if_mtu = ETHERMTU; 31436382Ssklower /* since everything will go out over ether or token ring */ 31536382Ssklower 31636382Ssklower ifp->if_init = eoninit; 31737469Ssklower ifp->if_ioctl = eonioctl; 31836382Ssklower ifp->if_output = eonoutput; 31937469Ssklower ifp->if_type = IFT_EON; 32037469Ssklower ifp->if_addrlen = 5; 32137469Ssklower ifp->if_hdrlen = EONIPLEN; 32236382Ssklower ifp->if_flags = IFF_BROADCAST; 32336382Ssklower if_attach(ifp); 32436382Ssklower 32536382Ssklower IFDEBUG(D_EON) 32636382Ssklower printf("eonattach()\n"); 32736382Ssklower ENDDEBUG 32836382Ssklower eon_initcache(); 32936382Ssklower IFDEBUG(D_EON) 33036382Ssklower printf("eon%d: attached\n", iod->iod_unit); 33136382Ssklower ENDDEBUG 33236382Ssklower } 33336382Ssklower 33436382Ssklower static struct eon_centry * 33536382Ssklower find_oldent( ea ) 33636382Ssklower struct sockaddr_eon *ea; 33736382Ssklower { 33836382Ssklower register int offset = 33936382Ssklower _offsetof( struct eon_centry, eonc_q_LINK); 34037469Ssklower register struct eon_centry *ent, *oent; 34136382Ssklower 34237469Ssklower oent = ent = qtocentry(eon_LINK_hdr.link, offset); 34336382Ssklower IFDEBUG(D_EON) 34436382Ssklower printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n", 34536382Ssklower (ea->seon_ipaddr>>24)&0xff, 34636382Ssklower (ea->seon_ipaddr>>16)&0xff, 34736382Ssklower (ea->seon_ipaddr>>8)&0xff, 34836382Ssklower (ea->seon_ipaddr)&0xff ); 34936382Ssklower ENDDEBUG 35037469Ssklower do { 35136382Ssklower if( ent->eonc_addr.s_addr == ea->seon_ipaddr ) 35236382Ssklower return ent; 35337469Ssklower ent = qtocentry(ent->eonc_nextLINK, offset); 35437469Ssklower } while (ent != oent); 35536382Ssklower return (struct eon_centry *)0; 35636382Ssklower } 35736382Ssklower 35836382Ssklower /* 35936382Ssklower * FUNCTION: eonioctl 36036382Ssklower * 36136382Ssklower * PURPOSE: io controls - ifconfig 36236382Ssklower * need commands to 36336382Ssklower * link-UP (core addr) (flags: ES, IS) 36436382Ssklower * link-DOWN (core addr) (flags: ES, IS) 36536382Ssklower * must be callable from kernel or user 36636382Ssklower * 36736382Ssklower * RETURNS: nothing 36836382Ssklower */ 36936382Ssklower eonioctl(ifp, cmd, data) 37036382Ssklower register struct ifnet *ifp; 37136382Ssklower register int cmd; 37236382Ssklower register caddr_t data; 37336382Ssklower { 37437469Ssklower struct iso_ifreq *ifr = (struct iso_ifreq *)data; 37536382Ssklower register struct sockaddr_eon *eoa = 37637469Ssklower (struct sockaddr_eon *)&(ifr->ifr_Addr); 37736382Ssklower register int s = splimp(); 37836382Ssklower register int error = 0; 37936382Ssklower 38036382Ssklower IFDEBUG(D_EON) 38136382Ssklower printf("eonioctl (cmd 0x%x) \n", cmd); 38236382Ssklower ENDDEBUG 38336382Ssklower 38436382Ssklower switch (cmd){ 38537469Ssklower case SIOCSEONCORE: { 38636382Ssklower /* add pt-pt link to the set of core addrs */ 38736382Ssklower register struct eon_centry *ent, *oldent; 38836382Ssklower register u_short which; 38936382Ssklower 39036382Ssklower /* "which" tells which lists to put these guys in - don't 39136382Ssklower * want to insert something in a list if it's already there 39236382Ssklower */ 39336382Ssklower #define LEGIT_EONADDR(a)\ 39437469Ssklower ((a->seon_family == AF_ISO) && (a->seon_afi == AFI_RFC986) &&\ 39536382Ssklower (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \ 39637469Ssklower && (a->seon_vers == EON_986_VERSION) && (a->seon_adrlen == 0x14)) 39736382Ssklower 39836382Ssklower if( ! LEGIT_EONADDR(eoa) ) { 39936382Ssklower error = EADDRNOTAVAIL; 40036382Ssklower break; 40136382Ssklower } 40236382Ssklower 40336382Ssklower oldent = find_oldent( eoa ); 40436382Ssklower IFDEBUG(D_EON) 40536382Ssklower printf("eonioctl legit seon_status 0x%x oldent %s\n", 40636382Ssklower eoa->seon_status, oldent?"found":"not found"); 40736382Ssklower ENDDEBUG 40836382Ssklower 40936382Ssklower if( eoa->seon_status & UPBITS ) { 41036382Ssklower if (!oldent) { 41136382Ssklower /* doesn't exist - need to create one */ 41237469Ssklower if (eon_FREE_hdr.link == eon_FREE_hdr.rlink) 41337469Ssklower return ENOBUFS; 41436382Ssklower ent = qtocentry(eon_FREE_hdr.link, 41536382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 41636382Ssklower remque( &(ent->eonc_q_LINK) ); 41736382Ssklower ent->eonc_addr.s_addr = eoa->seon_ipaddr; 41837469Ssklower insque( &(ent->eonc_q_LINK), (&eon_LINK_hdr)); 41936382Ssklower oldent = ent; 42036382Ssklower } 42136382Ssklower 42236382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 42336382Ssklower eoa->seon_status & UPBITS; 42436382Ssklower 42536382Ssklower oldent->eonc_status |= (eoa->seon_status & UPBITS); 42636382Ssklower 42736382Ssklower if( which & EON_ESLINK_UP ) 42836382Ssklower insque( &oldent->eonc_q_ES, (&eon_ES_hdr)); 42936382Ssklower if( which & EON_ISLINK_UP ) 43036382Ssklower insque( &oldent->eonc_q_IS, (&eon_IS_hdr)); 43136382Ssklower } 43236382Ssklower 43336382Ssklower if( eoa->seon_status & DOWNBITS ) { 43436382Ssklower if(!oldent) { 43536382Ssklower return ENOENT; /* no such entry */ 43636382Ssklower } 43736382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 43836382Ssklower eoa->seon_status & DOWNBITS; 43936382Ssklower 44036382Ssklower oldent->eonc_status |= (eoa->seon_status & DOWNBITS); 44136382Ssklower 44236382Ssklower if( which & EON_ESLINK_DOWN ) 44336382Ssklower remque( &(oldent->eonc_q_ES) ); 44436382Ssklower if( which & EON_ISLINK_DOWN ) 44536382Ssklower remque( &(oldent->eonc_q_IS) ); 44636382Ssklower } 44736382Ssklower 44836382Ssklower IFDEBUG(D_EON) 44936382Ssklower printf("at end status 0x%x\n", oldent->eonc_status); 45036382Ssklower ENDDEBUG 45136382Ssklower break; 45236382Ssklower } 45336382Ssklower 45437469Ssklower case SIOCGEONCORE: 45536382Ssklower { 45636382Ssklower register struct eon_centry *oldent; 45736382Ssklower 45836382Ssklower oldent = find_oldent( eoa ); 45936382Ssklower if( oldent == (struct eon_centry *)0 ) 46036382Ssklower error = EADDRNOTAVAIL; 46136382Ssklower else 46236382Ssklower eoa->seon_status = oldent->eonc_status; 46336382Ssklower } 46436382Ssklower break; 46536382Ssklower 46636382Ssklower case SIOCSIFADDR: 46736382Ssklower ifp->if_flags |= IFF_UP; 46836382Ssklower break; 46936382Ssklower 47036382Ssklower case SIOCSIFFLAGS: 47136382Ssklower if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & 47236382Ssklower IFF_RUNNING){ 47336382Ssklower ifp->if_flags &= ~IFF_RUNNING; 47436382Ssklower } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & 47536382Ssklower IFF_RUNNING) == 0) 47636382Ssklower eoninit(ifp->if_unit); 47736382Ssklower break; 47836382Ssklower default: 47936382Ssklower error = EINVAL; 48036382Ssklower } 48136382Ssklower splx(s); 48236382Ssklower return(error); 48336382Ssklower } 48436382Ssklower 48536382Ssklower /* 48636382Ssklower * FUNCTION: eoninit 48736382Ssklower * 48836382Ssklower * PURPOSE: initialization 48936382Ssklower * 49036382Ssklower * RETURNS: nothing 49136382Ssklower */ 49236382Ssklower 49336382Ssklower eoninit(unit) 49436382Ssklower int unit; 49536382Ssklower { 49637469Ssklower printf("eon driver-init eon%d\n", unit); 49736382Ssklower } 49836382Ssklower 49936382Ssklower 50036382Ssklower /* 50136382Ssklower * FUNCTION: eonint 50236382Ssklower * 50336382Ssklower * PURPOSE: filler for device configuration 50436382Ssklower * 50536382Ssklower * RETURNS: nothing 50636382Ssklower * 50736382Ssklower * NOTES: *should* never get called - for debugging it's here 50836382Ssklower */ 50936382Ssklower 51036382Ssklower eonint() 51136382Ssklower { 51236382Ssklower /* silent - so no more stray interrupt messages from the aed! yay 51336382Ssklower printf("eonint() called - BOGUS INTERRUPT\n"); 51436382Ssklower */ 51536382Ssklower } 51636382Ssklower 51736382Ssklower 51836382Ssklower /* 51936382Ssklower * FUNCTION: eonoutput 52036382Ssklower * 52136382Ssklower * PURPOSE: prepend an eon header and hand to IP 52236382Ssklower * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device 52336382Ssklower * (m) is an mbuf *, *m is a CLNL packet 52436382Ssklower * (dst) is a destination address - have to interp. as 52536382Ssklower * multicast or broadcast or real address. 52636382Ssklower * 52736382Ssklower * RETURNS: unix error code 52836382Ssklower * 52936382Ssklower * NOTES: 53036382Ssklower * 53136382Ssklower */ 53236382Ssklower eonoutput(ifp, morig, dst) 53337469Ssklower struct ifnet *ifp; 53436382Ssklower register struct mbuf *morig; /* packet */ 53536382Ssklower struct sockaddr_iso *dst; /* destination addr */ 53636382Ssklower { 53736382Ssklower int s; 53836382Ssklower struct eon_hdr *eonhdr; 53936382Ssklower struct ip *iphdr; 54036382Ssklower struct mbuf *mh; 54136382Ssklower int error = 0; 54236382Ssklower register int datalen; 54336382Ssklower caddr_t dstipaddrloc; 54437469Ssklower int single = 0, class, qoffset = 0, snpalen; 54536382Ssklower register struct eon_centry *ent; 54637469Ssklower register struct sockaddr_eon *eoa; 54736382Ssklower struct qhdr *q; 54837469Ssklower char edst[6]; 54936382Ssklower 55036382Ssklower IFDEBUG(D_EON) 55136382Ssklower printf("eonoutput \n" ); 55236382Ssklower ENDDEBUG 55336382Ssklower 55437469Ssklower if( dst->siso_family != AF_ISO ) { 55537469Ssklower einval: 55637469Ssklower error = EINVAL; 55737469Ssklower goto flush; 55837469Ssklower } 55937469Ssklower if ((morig->m_flags & M_PKTHDR) == 0) { 56037469Ssklower printf("eon: got non headered packet\n"); 56137469Ssklower goto einval; 56237469Ssklower } 56337469Ssklower eoa = (struct sockaddr_eon *)dst; 56437469Ssklower if (LEGIT_EONADDR(eoa)) { 56537469Ssklower class = eoa->seon_protoid; 56637469Ssklower dstipaddrloc = (caddr_t)&(eoa->seon_ipaddr); 56737469Ssklower } else if (eoa->seon_afi == AFI_SNA) { 56837469Ssklower dstipaddrloc = (caddr_t)&(dst->siso_data[1]); 56937469Ssklower if (dst->siso_nlen == 6) { 57037469Ssklower class = dst->siso_data[5]; 57137469Ssklower } else if (dst->siso_nlen == 7) { 57237469Ssklower if (bcmp(dstipaddrloc, all_is.sc_snpa, 6)) 57337469Ssklower class = EON_MULTICAST_ES; 57437469Ssklower else if (bcmp(dstipaddrloc, all_es.sc_snpa, 6)) 57537469Ssklower class = EON_MULTICAST_IS; 57637469Ssklower else 57737469Ssklower goto einval; 57837469Ssklower } else 57937469Ssklower goto einval; 58037469Ssklower } else if (0 == iso_snparesolve(ifp, dst, edst, &snpalen)) { 58137469Ssklower dstipaddrloc = (caddr_t)edst; 58237469Ssklower class = edst[4]; 58337469Ssklower } else { 58437469Ssklower error = EINVAL; 58537469Ssklower goto flush; 58637469Ssklower } 58737469Ssklower switch (class) { 58836382Ssklower case EON_NORMAL_ADDR: 58936382Ssklower IncStat(es_out_normal); 59036382Ssklower single = 1; 59136382Ssklower break; 59236382Ssklower 59336382Ssklower case EON_BROADCAST: 59436382Ssklower IncStat(es_out_broad); 59537469Ssklower if(eon_LINK_hdr.link == eon_LINK_hdr.rlink) { 59636382Ssklower error = EADDRNOTAVAIL; 59736382Ssklower } else { 59836382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 59936382Ssklower ent = qtocentry(eon_LINK_hdr.link, qoffset); 60036382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 60136382Ssklower } 60236382Ssklower break; 60336382Ssklower case EON_MULTICAST_ES: 60436382Ssklower IncStat(es_out_multi_es); 60537469Ssklower if (eon_ES_hdr.link == eon_ES_hdr.rlink) { 60636382Ssklower error = EADDRNOTAVAIL; 60736382Ssklower } else { 60836382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_ES); 60936382Ssklower ent = qtocentry(eon_ES_hdr.link, qoffset); 61036382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 61136382Ssklower } 61236382Ssklower break; 61336382Ssklower case EON_MULTICAST_IS: 61436382Ssklower IncStat(es_out_multi_is); 61537469Ssklower if (eon_IS_hdr.link == eon_IS_hdr.rlink) { 61636382Ssklower error = EADDRNOTAVAIL; 61736382Ssklower } else { 61836382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 61936382Ssklower ent = qtocentry(eon_IS_hdr.link, qoffset); 62036382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 62136382Ssklower } 62236382Ssklower break; 62336382Ssklower default: 62437469Ssklower printf("bad class value; treated as EON_NORMAL_ADDR\n"); 62537469Ssklower class = EON_NORMAL_ADDR; 62636382Ssklower single = 1; 62736382Ssklower break; 62836382Ssklower } 62936382Ssklower if( error ) 63036382Ssklower goto done; 63136382Ssklower 63236382Ssklower /* get data length -- needed later */ 63337469Ssklower datalen = morig->m_pkthdr.len; 63436382Ssklower IFDEBUG(D_EON) 63536382Ssklower printf("eonoutput : m_datalen returns %d\n", datalen); 63636382Ssklower ENDDEBUG 63736382Ssklower 63837469Ssklower MGETHDR(mh, M_DONTWAIT, MT_HEADER); 63937469Ssklower if(mh == (struct mbuf *)0) 64036382Ssklower goto done; 64136382Ssklower 64236382Ssklower /* put an eon_hdr in the buffer, prepended by an ip header */ 64336382Ssklower mh->m_len = sizeof(struct eon_hdr); 64437469Ssklower MH_ALIGN(mh, sizeof(struct eon_hdr)); 64536382Ssklower mh->m_next = morig; 64636382Ssklower eonhdr = mtod(mh, struct eon_hdr *); 64737469Ssklower eonhdr->eonh_class = class; 64836382Ssklower eonhdr->eonh_vers = EON_VERSION; 64937469Ssklower eonhdr->eonh_csum = 0; 65036382Ssklower 65136382Ssklower IFDEBUG(D_EON) 65236382Ssklower printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", 65336382Ssklower mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 65436382Ssklower ENDDEBUG 65536382Ssklower iso_gen_csum(mh, 65636382Ssklower _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 65736382Ssklower 65837469Ssklower mh->m_data -= sizeof(*iphdr); 65937469Ssklower mh->m_len += sizeof(*iphdr); 66036382Ssklower iphdr = mtod(mh, struct ip *); 66137469Ssklower bzero((caddr_t)iphdr, sizeof (*iphdr)); 66236382Ssklower 66336382Ssklower iphdr->ip_p = IPPROTO_EON; 66437469Ssklower iphdr->ip_len = (u_short)(mh->m_pkthdr.len = EONIPLEN + datalen); 66536382Ssklower iphdr->ip_ttl = MAXTTL; 66636382Ssklower iphdr->ip_src.s_addr = INADDR_ANY; 66736382Ssklower 66836382Ssklower IFDEBUG(D_EON) 66936382Ssklower printf("eonoutput : after gen csum: ip_len %d/0x%x\n", 67037469Ssklower mh->m_pkthdr.len, mh->m_pkthdr.len); 67136382Ssklower ENDDEBUG 67236382Ssklower 67336382Ssklower morig = mh; 67436382Ssklower 67536382Ssklower for(;;) { 67636382Ssklower 67736382Ssklower if( !single ) { 67836382Ssklower /* make a copy to send */ 67936382Ssklower IFDEBUG(D_EON) 68036382Ssklower printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n", 68136382Ssklower morig, iphdr->ip_len); 68236382Ssklower ENDDEBUG 68337469Ssklower if (((mh = m_copy(morig, 0, morig->m_pkthdr.len)) == 0) || 68437469Ssklower ((mh = m_pullup(mh, sizeof(struct ip))) == 0)) { 68537469Ssklower error = ENOBUFS; 68637469Ssklower goto done; 68737469Ssklower } 68836382Ssklower iphdr = mtod(mh, struct ip *); 68936382Ssklower } 69036382Ssklower IFDEBUG(D_EON) 69136382Ssklower printf("eonoutput : bcopy 0x%x to 0x%x length %d\n", 69236382Ssklower dstipaddrloc, 69336382Ssklower (caddr_t)&(iphdr->ip_dst.s_addr), 69436382Ssklower sizeof(iphdr->ip_dst.s_addr)); 69536382Ssklower ENDDEBUG 69637469Ssklower bcopy(dstipaddrloc, (caddr_t)&(iphdr->ip_dst.s_addr), 69737469Ssklower sizeof(iphdr->ip_dst.s_addr)); 69836382Ssklower IFDEBUG(D_EON) 69936382Ssklower printf("eonoutput : dst ip addr : %d.%d.%d.%d", 70036382Ssklower (iphdr->ip_dst.s_addr>>24)&0xff, 70136382Ssklower (iphdr->ip_dst.s_addr>>16)&0xff, 70236382Ssklower (iphdr->ip_dst.s_addr>>8)&0xff, 70336382Ssklower (iphdr->ip_dst.s_addr)&0xff ); 70436382Ssklower ENDDEBUG 70536382Ssklower 70636382Ssklower IFDEBUG(D_EON) 70736382Ssklower printf("eonoutput ip_output : eon header:\n"); 70836382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 70936382Ssklower printf("ip header:\n"); 71036382Ssklower dump_buf(iphdr, sizeof(struct ip)); 71136382Ssklower ENDDEBUG 71236382Ssklower 71336382Ssklower IncStat(es_ipout); 71436382Ssklower if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) ) 71536382Ssklower break; 71636382Ssklower 71736382Ssklower IFDEBUG(D_EON) 71836382Ssklower printf("eonoutput ip_output returns 0x%x; single %d\n", 71936382Ssklower error, single); 72036382Ssklower ENDDEBUG 72136382Ssklower 72236382Ssklower if(single) 72336382Ssklower break; 72436382Ssklower 72536382Ssklower q = centrytoq(ent, qoffset)->link; 72636382Ssklower if( q == (struct qhdr *)0) 72736382Ssklower break; 72836382Ssklower ent = qtocentry( q, qoffset ); 72936382Ssklower IFDEBUG(D_EON) 73036382Ssklower printf("eonoutput : get next entry: 0x%x\n", ent); 73136382Ssklower ENDDEBUG 73236382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 73336382Ssklower IFDEBUG(D_EON) 73436382Ssklower printf("eonoutput : dump of eon_centry 0x%x:\n", ent ); 73536382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 73636382Ssklower ENDDEBUG 73736382Ssklower } 73836382Ssklower done: 73936382Ssklower if( !single ) { 74036382Ssklower IFDEBUG(D_EON) 74136382Ssklower printf("eonoutput : freeing morig 0x%x\n", morig); 74236382Ssklower ENDDEBUG 74337469Ssklower flush: 74436382Ssklower m_freem(morig); 74536382Ssklower } 74636382Ssklower return error; 74736382Ssklower } 74836382Ssklower 74937469Ssklower eoninput(m, iphlen) 75036382Ssklower register struct mbuf *m; 75137469Ssklower int iphlen; 75236382Ssklower { 75336382Ssklower register struct eon_hdr *eonhdr; 75436382Ssklower register struct ip *iphdr; 75536382Ssklower struct ifnet *eonifp; 75637469Ssklower int s; 75736382Ssklower 75836382Ssklower eonifp = &eonif[0]; /* kludge - really want to give CLNP 75936382Ssklower * the ifp for eon, not for the real device 76036382Ssklower */ 76136382Ssklower 76236382Ssklower IFDEBUG(D_EON) 76337469Ssklower printf("eoninput() 0x%x m_data 0x%x m_len 0x%x dequeued\n", 76437469Ssklower m, m?m->m_data:0, m?m->m_len:0); 76536382Ssklower ENDDEBUG 76636382Ssklower 76737469Ssklower if (m == 0) 76837469Ssklower return; 76937469Ssklower if (iphlen > sizeof (struct ip)) 77037469Ssklower ip_stripoptions(m, (struct mbuf *)0); 77137469Ssklower if (m->m_len < EONIPLEN) { 77237469Ssklower if ((m = m_pullup(m, EONIPLEN)) == 0) { 77337469Ssklower IncStat(es_badhdr); 77437469Ssklower drop: 77537469Ssklower IFDEBUG(D_EON) 77637469Ssklower printf("eoninput: DROP \n" ); 77737469Ssklower ENDDEBUG 77837469Ssklower eonifp->if_ierrors ++; 77937469Ssklower m_freem(m); 78037469Ssklower return; 78137469Ssklower } 78236382Ssklower } 78336382Ssklower iphdr = mtod(m, struct ip *); 78436382Ssklower /* do a few checks for debugging */ 78536382Ssklower if( iphdr->ip_p != IPPROTO_EON ) { 78636382Ssklower IncStat(es_badhdr); 78736382Ssklower goto drop; 78836382Ssklower } 78937469Ssklower /* temporarily drop ip header from the mbuf */ 79037469Ssklower m->m_data += sizeof(struct ip); 79136382Ssklower eonhdr = mtod(m, struct eon_hdr *); 79237469Ssklower if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) { 79337469Ssklower IncStat(es_badcsum); 79437469Ssklower goto drop; 79537469Ssklower } 79637469Ssklower m->m_data -= sizeof(struct ip); 79737469Ssklower 79836382Ssklower IFDEBUG(D_EON) 79937469Ssklower printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class ); 80036382Ssklower printf("eoninput: eon header:\n"); 80136382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 80236382Ssklower ENDDEBUG 80336382Ssklower 80436382Ssklower /* checks for debugging */ 80536382Ssklower if( eonhdr->eonh_vers != EON_VERSION) { 80636382Ssklower IncStat(es_badhdr); 80736382Ssklower goto drop; 80836382Ssklower } 80937469Ssklower m->m_flags &= ~(M_BCAST|M_MCAST); 81036382Ssklower switch( eonhdr->eonh_class) { 81136382Ssklower case EON_BROADCAST: 81236382Ssklower IncStat(es_in_broad); 81337469Ssklower m->m_flags |= M_BCAST; 81436382Ssklower break; 81536382Ssklower case EON_NORMAL_ADDR: 81636382Ssklower IncStat(es_in_normal); 81736382Ssklower break; 81836382Ssklower case EON_MULTICAST_ES: 81936382Ssklower IncStat(es_in_multi_es); 82037469Ssklower m->m_flags |= M_MCAST; 82136382Ssklower break; 82236382Ssklower case EON_MULTICAST_IS: 82336382Ssklower IncStat(es_in_multi_is); 82437469Ssklower m->m_flags |= M_MCAST; 82536382Ssklower break; 82636382Ssklower } 82736382Ssklower eonifp->if_ipackets ++; 82836382Ssklower 82936382Ssklower { 83036382Ssklower /* put it on the CLNP queue and set soft interrupt */ 83136382Ssklower struct ifqueue *ifq; 83236382Ssklower extern struct ifqueue clnlintrq; 83336382Ssklower 83437469Ssklower m->m_pkthdr.rcvif = eonifp; /* KLUDGE */ 83536382Ssklower IFDEBUG(D_EON) 83636382Ssklower printf("eoninput to clnl IFQ\n"); 83736382Ssklower ENDDEBUG 83836382Ssklower ifq = &clnlintrq; 83937469Ssklower s = splimp(); 84036382Ssklower if (IF_QFULL(ifq)) { 84136382Ssklower IF_DROP(ifq); 84236382Ssklower m_freem(m); 84337469Ssklower eonifp->if_ierrors ++; 84436382Ssklower splx(s); 84536382Ssklower return; 84636382Ssklower } 84736382Ssklower IF_ENQUEUE(ifq, m); 84836382Ssklower IFDEBUG(D_EON) 84936382Ssklower printf( 85037469Ssklower "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_data 0x%x\n", 85137469Ssklower m, m->m_len, m->m_type, m->m_data); 85236382Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 85336382Ssklower ENDDEBUG 85437469Ssklower schednetisr(NETISR_ISO); 85537469Ssklower splx(s); 85636382Ssklower } 85736382Ssklower } 85836382Ssklower 85936382Ssklower int 86036382Ssklower eonctlinput(cmd, sin) 86136382Ssklower int cmd; 86236382Ssklower struct sockaddr_in *sin; 86336382Ssklower { 86436382Ssklower extern u_char inetctlerrmap[]; 86536382Ssklower 86636382Ssklower IFDEBUG(D_EON) 86736382Ssklower printf("eonctlinput: cmd 0x%x addr: ", cmd); 86836382Ssklower dump_isoaddr(sin); 86936382Ssklower printf("\n"); 87036382Ssklower ENDDEBUG 87136382Ssklower 87236382Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 87336382Ssklower return 0; 87436382Ssklower 87536382Ssklower IncStat(es_icmp[cmd]); 87636382Ssklower switch (cmd) { 87736382Ssklower 87837469Ssklower case PRC_QUENCH: 87936382Ssklower case PRC_QUENCH2: 88036382Ssklower /* TODO: set the dec bit */ 88136382Ssklower break; 88236382Ssklower case PRC_TIMXCEED_REASS: 88336382Ssklower case PRC_ROUTEDEAD: 88436382Ssklower case PRC_HOSTUNREACH: 88536382Ssklower case PRC_UNREACH_NET: 88636382Ssklower case PRC_IFDOWN: 88736382Ssklower case PRC_UNREACH_HOST: 88836382Ssklower case PRC_HOSTDEAD: 88936382Ssklower case PRC_TIMXCEED_INTRANS: 89036382Ssklower /* TODO: mark the link down */ 89136382Ssklower break; 89236382Ssklower 89336382Ssklower case PRC_UNREACH_PROTOCOL: 89436382Ssklower case PRC_UNREACH_PORT: 89536382Ssklower case PRC_UNREACH_NEEDFRAG: 89636382Ssklower case PRC_UNREACH_SRCFAIL: 89736382Ssklower case PRC_REDIRECT_NET: 89836382Ssklower case PRC_REDIRECT_HOST: 89936382Ssklower case PRC_REDIRECT_TOSNET: 90036382Ssklower case PRC_REDIRECT_TOSHOST: 90136382Ssklower case PRC_MSGSIZE: 90236382Ssklower case PRC_PARAMPROB: 90336382Ssklower printf("eonctlinput: ICMP cmd 0x%x\n", cmd ); 90436382Ssklower break; 90536382Ssklower } 90636382Ssklower return 0; 90736382Ssklower } 90836382Ssklower 90937469Ssklower #endif 910