1*36382Ssklower /*********************************************************** 2*36382Ssklower Copyright IBM Corporation 1987 3*36382Ssklower 4*36382Ssklower All Rights Reserved 5*36382Ssklower 6*36382Ssklower Permission to use, copy, modify, and distribute this software and its 7*36382Ssklower documentation for any purpose and without fee is hereby granted, 8*36382Ssklower provided that the above copyright notice appear in all copies and that 9*36382Ssklower both that copyright notice and this permission notice appear in 10*36382Ssklower supporting documentation, and that the name of IBM not be 11*36382Ssklower used in advertising or publicity pertaining to distribution of the 12*36382Ssklower software without specific, written prior permission. 13*36382Ssklower 14*36382Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36382Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36382Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36382Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36382Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36382Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36382Ssklower SOFTWARE. 21*36382Ssklower 22*36382Ssklower ******************************************************************/ 23*36382Ssklower 24*36382Ssklower /* 25*36382Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36382Ssklower */ 27*36382Ssklower /* 28*36382Ssklower * $Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $ 29*36382Ssklower * $Source: /usr/argo/sys/netiso/RCS/if_eon.c,v $ 30*36382Ssklower * 31*36382Ssklower * EON rfc 32*36382Ssklower * Layer between IP and CLNL 33*36382Ssklower * 34*36382Ssklower * TODO: 35*36382Ssklower * Put together a current rfc986 address format and get the right offset 36*36382Ssklower * for the nsel 37*36382Ssklower */ 38*36382Ssklower #define RFC986_NSEL_OFFSET 5 39*36382Ssklower 40*36382Ssklower #ifndef lint 41*36382Ssklower static char *rcsid = "$Header: if_eon.c,v 1.4 88/07/19 15:53:59 hagens Exp $"; 42*36382Ssklower #endif lint 43*36382Ssklower 44*36382Ssklower #include "eon.h" 45*36382Ssklower #if NEON>0 46*36382Ssklower 47*36382Ssklower #include "param.h" 48*36382Ssklower #include "systm.h" 49*36382Ssklower #include "types.h" 50*36382Ssklower #include "mbuf.h" 51*36382Ssklower #include "buf.h" 52*36382Ssklower #include "protosw.h" 53*36382Ssklower #include "socket.h" 54*36382Ssklower #include "ioctl.h" 55*36382Ssklower #include "errno.h" 56*36382Ssklower #include "types.h" 57*36382Ssklower 58*36382Ssklower #include "../machine/io.h" 59*36382Ssklower #include "../machineio/ioccvar.h" 60*36382Ssklower 61*36382Ssklower #include "../net/if.h" 62*36382Ssklower #include "../net/netisr.h" 63*36382Ssklower #include "../net/route.h" 64*36382Ssklower 65*36382Ssklower #include "../netinet/in.h" 66*36382Ssklower #include "../netinet/in_systm.h" 67*36382Ssklower #include "../netinet/ip.h" 68*36382Ssklower #include "../netinet/ip_var.h" 69*36382Ssklower #include "../netinet/if_ether.h" 70*36382Ssklower 71*36382Ssklower #include "../netiso/iso.h" 72*36382Ssklower #include "../netiso/argo_debug.h" 73*36382Ssklower #include "../netiso/iso_errno.h" 74*36382Ssklower #include "../netiso/eonvar.h" 75*36382Ssklower 76*36382Ssklower #define EOK 0 77*36382Ssklower 78*36382Ssklower int eoninput(); 79*36382Ssklower int eonint(); 80*36382Ssklower int eonoutput(); 81*36382Ssklower int eonioctl(); 82*36382Ssklower int eonprobe(); 83*36382Ssklower int eonattach(); 84*36382Ssklower int eoninit(); 85*36382Ssklower extern int ip_output(); 86*36382Ssklower struct ifnet eonif[NEON]; 87*36382Ssklower 88*36382Ssklower #define EON_FAKE_CSR 0 89*36382Ssklower int eon_fakeautoconf[2]; /* need at least 2 ints */ 90*36382Ssklower 91*36382Ssklower caddr_t eonstd[] = { (caddr_t) eon_fakeautoconf, 0 }; 92*36382Ssklower struct iocc_device *eoninfo[NEON]; 93*36382Ssklower 94*36382Ssklower struct iocc_driver eondriver = { 95*36382Ssklower eonprobe, /* idr_probe */ 96*36382Ssklower 0, /* idr_slave */ 97*36382Ssklower eonattach, /* idr_attach */ 98*36382Ssklower 0, /* idr_dgo */ 99*36382Ssklower eonstd, /* idr_addr - list of standard addresses for device */ 100*36382Ssklower "eon", /* idr_dname */ 101*36382Ssklower eoninfo, /* idr_dinfo - backptrs to iodinit structs */ 102*36382Ssklower 0, /* idr_mname - controller name */ 103*36382Ssklower 0, /* idr_minfo -- backptrs to iominit structs */ 104*36382Ssklower eonint, /* idr_intr - interrupt rtn */ 105*36382Ssklower 0, /* idr_csr - offset to read/write csr */ 106*36382Ssklower EON_FAKE_CSR, /* idr_chanrelse */ 107*36382Ssklower 0, /* idr_flags */ 108*36382Ssklower }; 109*36382Ssklower 110*36382Ssklower 111*36382Ssklower /* 112*36382Ssklower * entry in the EON address cache (list) 113*36382Ssklower * (or pt-pt links list, however you view it) 114*36382Ssklower */ 115*36382Ssklower 116*36382Ssklower struct eon_centry { 117*36382Ssklower struct qhdr eonc_q_LINK; 118*36382Ssklower #define eonc_nextLINK eonc_q_LINK.link 119*36382Ssklower #define eonc_prevLINK eonc_q_LINK.flink 120*36382Ssklower 121*36382Ssklower struct qhdr eonc_q_IS; 122*36382Ssklower #define eonc_nextIS eonc_q_IS.link 123*36382Ssklower #define eonc_prevIS eonc_q_IS.flink 124*36382Ssklower 125*36382Ssklower struct qhdr eonc_q_ES; 126*36382Ssklower #define eonc_nextES eonc_q_ES.link 127*36382Ssklower #define eonc_prevES eonc_q_ES.flink 128*36382Ssklower 129*36382Ssklower struct in_addr eonc_addr; 130*36382Ssklower u_short eonc_status; 131*36382Ssklower }; 132*36382Ssklower 133*36382Ssklower /* kinda like mtod() but for eon_centries */ 134*36382Ssklower #define qtocentry(q, off) ((struct eon_centry *) (((caddr_t)(q)) - off)) 135*36382Ssklower #define centrytoq(c, off) ((struct qhdr *) (((caddr_t)(c)) + off)) 136*36382Ssklower 137*36382Ssklower struct qhdr eon_LINK_hdr = { 138*36382Ssklower (struct qhdr *)0, 139*36382Ssklower (struct qhdr *)0, 140*36382Ssklower }; 141*36382Ssklower static struct qhdr eon_IS_hdr = { 142*36382Ssklower (struct qhdr *)0, 143*36382Ssklower (struct qhdr *)0, 144*36382Ssklower }; 145*36382Ssklower static struct qhdr eon_ES_hdr = { 146*36382Ssklower (struct qhdr *)0, 147*36382Ssklower (struct qhdr *)0, 148*36382Ssklower }; 149*36382Ssklower static struct qhdr eon_FREE_hdr = { 150*36382Ssklower (struct qhdr *)0, 151*36382Ssklower (struct qhdr *)0, 152*36382Ssklower }; 153*36382Ssklower 154*36382Ssklower #define INITQ(q) (q)->rlink = (q)->link = (q) 155*36382Ssklower 156*36382Ssklower /* 157*36382Ssklower * FUNCTION: eon_dumpcache 158*36382Ssklower * 159*36382Ssklower * PURPOSE: dump the cache beginning with the argument given 160*36382Ssklower * 161*36382Ssklower * RETURNS: 0 162*36382Ssklower */ 163*36382Ssklower 164*36382Ssklower eon_dumpcache(which) 165*36382Ssklower int which; 166*36382Ssklower { 167*36382Ssklower register int off; 168*36382Ssklower register struct eon_centry *ent; 169*36382Ssklower struct qhdr *hdr; 170*36382Ssklower 171*36382Ssklower switch (which) { 172*36382Ssklower case E_FREE: 173*36382Ssklower printf("FREE LIST\n"); 174*36382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 175*36382Ssklower hdr = &eon_FREE_hdr; 176*36382Ssklower ent = qtocentry( hdr->link, 177*36382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 178*36382Ssklower break; 179*36382Ssklower case E_ES: 180*36382Ssklower printf("ES LIST\n"); 181*36382Ssklower off = _offsetof( struct eon_centry, eonc_q_ES); 182*36382Ssklower hdr = &eon_ES_hdr; 183*36382Ssklower ent = qtocentry( hdr->link, 184*36382Ssklower _offsetof( struct eon_centry, eonc_q_ES)); 185*36382Ssklower break; 186*36382Ssklower case E_IS: 187*36382Ssklower printf("IS LIST\n"); 188*36382Ssklower off = _offsetof( struct eon_centry, eonc_q_IS); 189*36382Ssklower hdr = &eon_IS_hdr; 190*36382Ssklower ent = qtocentry( hdr->link, 191*36382Ssklower _offsetof( struct eon_centry, eonc_q_IS)); 192*36382Ssklower break; 193*36382Ssklower case E_LINK: 194*36382Ssklower printf("LINK LIST\n"); 195*36382Ssklower off = _offsetof( struct eon_centry, eonc_q_LINK); 196*36382Ssklower hdr = &eon_LINK_hdr; 197*36382Ssklower ent = qtocentry( hdr->link, 198*36382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 199*36382Ssklower break; 200*36382Ssklower } 201*36382Ssklower if(hdr == centrytoq(ent, off)->link ) 202*36382Ssklower printf("EMPTY\n"); 203*36382Ssklower else while(1) { 204*36382Ssklower printf("0x%x: %d.%d.%d.%d, %s %s\n", ent, 205*36382Ssklower (ent->eonc_addr.s_addr>>24)&0xff, 206*36382Ssklower (ent->eonc_addr.s_addr>>16)&0xff, 207*36382Ssklower (ent->eonc_addr.s_addr>>8)&0xff, 208*36382Ssklower (ent->eonc_addr.s_addr)&0xff, 209*36382Ssklower ((ent->eonc_status & EON_ESLINK_UP)?"ES^": 210*36382Ssklower (ent->eonc_status & EON_ESLINK_DOWN)?"es*": " "), 211*36382Ssklower ((ent->eonc_status & EON_ISLINK_UP)?"IS^": 212*36382Ssklower (ent->eonc_status & EON_ISLINK_DOWN)?"is*": " ") 213*36382Ssklower ); 214*36382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 215*36382Ssklower 216*36382Ssklower { /* ent = ent.next: */ 217*36382Ssklower register struct qhdr *q; 218*36382Ssklower 219*36382Ssklower q = centrytoq(ent, off)->link; 220*36382Ssklower if( q == hdr) 221*36382Ssklower break; 222*36382Ssklower if( q == (struct qhdr *)0) /* panic */ { 223*36382Ssklower printf("eon0: BAD Q HDR or CENTRY! q 0x%x ent 0x%x off 0x%x\n", 224*36382Ssklower q, ent, off); 225*36382Ssklower break; 226*36382Ssklower } 227*36382Ssklower ent = qtocentry( q, off ); 228*36382Ssklower } 229*36382Ssklower } 230*36382Ssklower } 231*36382Ssklower /* 232*36382Ssklower * FUNCTION: eon_initcache 233*36382Ssklower * 234*36382Ssklower * PURPOSE: allocs a bunch of free cache entries 235*36382Ssklower * 236*36382Ssklower * RETURNS: 0 237*36382Ssklower */ 238*36382Ssklower 239*36382Ssklower eon_initcache() 240*36382Ssklower { 241*36382Ssklower static struct eon_centry eoncache[EON_CACHESIZE]; 242*36382Ssklower register int i; 243*36382Ssklower register struct eon_centry *ent; 244*36382Ssklower 245*36382Ssklower bzero( eoncache, EON_CACHESIZE*sizeof(struct eon_centry)); 246*36382Ssklower INITQ( &eon_FREE_hdr ); 247*36382Ssklower INITQ( &eon_LINK_hdr ); 248*36382Ssklower INITQ( &eon_IS_hdr ); 249*36382Ssklower INITQ( &eon_ES_hdr ); 250*36382Ssklower 251*36382Ssklower ent = eoncache; 252*36382Ssklower 253*36382Ssklower for(i=0; i< EON_CACHESIZE; i++,ent++) { 254*36382Ssklower _insque( centrytoq(ent, _offsetof( struct eon_centry, eonc_q_LINK)), 255*36382Ssklower &eon_FREE_hdr); 256*36382Ssklower } 257*36382Ssklower printf("eon0: cache initialized\n"); 258*36382Ssklower } 259*36382Ssklower 260*36382Ssklower /* 261*36382Ssklower * FUNCTION: eonprobe 262*36382Ssklower * 263*36382Ssklower * PURPOSE: filler for device configuration 264*36382Ssklower * 265*36382Ssklower * RETURNS: PROBE_OK 266*36382Ssklower */ 267*36382Ssklower 268*36382Ssklower eonprobe() 269*36382Ssklower { 270*36382Ssklower extern int int_level, int_irq; 271*36382Ssklower 272*36382Ssklower printf("eonprobe() \n"); 273*36382Ssklower int_level = int_irq = 0x3; /* pick something - anything but -1 */ 274*36382Ssklower return PROBE_OK; 275*36382Ssklower } 276*36382Ssklower 277*36382Ssklower /* 278*36382Ssklower * FUNCTION: eonattach 279*36382Ssklower * 280*36382Ssklower * PURPOSE: autoconf attach routine 281*36382Ssklower * 282*36382Ssklower * RETURNS: void 283*36382Ssklower */ 284*36382Ssklower 285*36382Ssklower eonattach(iod) 286*36382Ssklower register struct iocc_device *iod; 287*36382Ssklower { 288*36382Ssklower register struct ifnet *ifp = &eonif[iod->iod_unit]; 289*36382Ssklower 290*36382Ssklower IFDEBUG(D_EON) 291*36382Ssklower printf("eonattach()\n"); 292*36382Ssklower ENDDEBUG 293*36382Ssklower ifp->if_unit = iod->iod_unit; 294*36382Ssklower ifp->if_name = "eon"; 295*36382Ssklower ifp->if_mtu = ETHERMTU; 296*36382Ssklower /* since everything will go out over ether or token ring */ 297*36382Ssklower 298*36382Ssklower ifp->if_init = eoninit; 299*36382Ssklower ifp->if_ioctl = eonioctl; /* needed? */ 300*36382Ssklower ifp->if_output = eonoutput; 301*36382Ssklower ifp->if_reset = 0; 302*36382Ssklower ifp->if_flags = IFF_BROADCAST; 303*36382Ssklower if_attach(ifp); 304*36382Ssklower 305*36382Ssklower IFDEBUG(D_EON) 306*36382Ssklower printf("eonattach()\n"); 307*36382Ssklower ENDDEBUG 308*36382Ssklower eon_initcache(); 309*36382Ssklower IFDEBUG(D_EON) 310*36382Ssklower printf("eon%d: attached\n", iod->iod_unit); 311*36382Ssklower ENDDEBUG 312*36382Ssklower } 313*36382Ssklower 314*36382Ssklower static struct eon_centry * 315*36382Ssklower find_oldent( ea ) 316*36382Ssklower struct sockaddr_eon *ea; 317*36382Ssklower { 318*36382Ssklower register int offset = 319*36382Ssklower _offsetof( struct eon_centry, eonc_q_LINK); 320*36382Ssklower register struct eon_centry *ent = qtocentry(eon_LINK_hdr.link, offset); 321*36382Ssklower 322*36382Ssklower IFDEBUG(D_EON) 323*36382Ssklower printf("eon: find_oldent() ipaddr: %d.%d.%d.%d\n", 324*36382Ssklower (ea->seon_ipaddr>>24)&0xff, 325*36382Ssklower (ea->seon_ipaddr>>16)&0xff, 326*36382Ssklower (ea->seon_ipaddr>>8)&0xff, 327*36382Ssklower (ea->seon_ipaddr)&0xff ); 328*36382Ssklower ENDDEBUG 329*36382Ssklower for (; ent; ent = qtocentry(ent->eonc_nextLINK, offset) ) { 330*36382Ssklower if( ent->eonc_addr.s_addr == ea->seon_ipaddr ) 331*36382Ssklower return ent; 332*36382Ssklower } 333*36382Ssklower return (struct eon_centry *)0; 334*36382Ssklower } 335*36382Ssklower 336*36382Ssklower /* 337*36382Ssklower * FUNCTION: eonioctl 338*36382Ssklower * 339*36382Ssklower * PURPOSE: io controls - ifconfig 340*36382Ssklower * need commands to 341*36382Ssklower * link-UP (core addr) (flags: ES, IS) 342*36382Ssklower * link-DOWN (core addr) (flags: ES, IS) 343*36382Ssklower * must be callable from kernel or user 344*36382Ssklower * 345*36382Ssklower * RETURNS: nothing 346*36382Ssklower */ 347*36382Ssklower eonioctl(ifp, cmd, data) 348*36382Ssklower register struct ifnet *ifp; 349*36382Ssklower register int cmd; 350*36382Ssklower register caddr_t data; 351*36382Ssklower { 352*36382Ssklower struct ifreq *ifr = (struct ifreq *)data; 353*36382Ssklower register struct sockaddr_eon *eoa = 354*36382Ssklower (struct sockaddr_eon *)&(ifr->ifr_addr); 355*36382Ssklower register int s = splimp(); 356*36382Ssklower register int error = 0; 357*36382Ssklower 358*36382Ssklower IFDEBUG(D_EON) 359*36382Ssklower printf("eonioctl (cmd 0x%x) \n", cmd); 360*36382Ssklower ENDDEBUG 361*36382Ssklower 362*36382Ssklower switch (cmd){ 363*36382Ssklower case SIOCSIFDSTADDR: { 364*36382Ssklower /* add pt-pt link to the set of core addrs */ 365*36382Ssklower register struct eon_centry *ent, *oldent; 366*36382Ssklower register u_short which; 367*36382Ssklower 368*36382Ssklower /* "which" tells which lists to put these guys in - don't 369*36382Ssklower * want to insert something in a list if it's already there 370*36382Ssklower */ 371*36382Ssklower #define LEGIT_EONADDR(a)\ 372*36382Ssklower ((a->seon_family == AF_ISO) && (a->seon_afi == 0x47) &&\ 373*36382Ssklower (a->seon_idi[0] == 0) && (a->seon_idi[1] == 6) \ 374*36382Ssklower ) 375*36382Ssklower #ifdef notdef 376*36382Ssklower /* GET THESE RIGHT AND ADD THEM */ 377*36382Ssklower && (a->seon_vers == 3) && (a->seon_adrlen == 0xa) 378*36382Ssklower #endif notdef 379*36382Ssklower 380*36382Ssklower if( ! LEGIT_EONADDR(eoa) ) { 381*36382Ssklower error = EADDRNOTAVAIL; 382*36382Ssklower break; 383*36382Ssklower } 384*36382Ssklower 385*36382Ssklower oldent = find_oldent( eoa ); 386*36382Ssklower IFDEBUG(D_EON) 387*36382Ssklower printf("eonioctl legit seon_status 0x%x oldent %s\n", 388*36382Ssklower eoa->seon_status, oldent?"found":"not found"); 389*36382Ssklower ENDDEBUG 390*36382Ssklower 391*36382Ssklower if( eoa->seon_status & UPBITS ) { 392*36382Ssklower if (!oldent) { 393*36382Ssklower /* doesn't exist - need to create one */ 394*36382Ssklower /* TODO : check for null free list */ 395*36382Ssklower ent = qtocentry(eon_FREE_hdr.link, 396*36382Ssklower _offsetof( struct eon_centry, eonc_q_LINK)); 397*36382Ssklower remque( &(ent->eonc_q_LINK) ); 398*36382Ssklower ent->eonc_addr.s_addr = eoa->seon_ipaddr; 399*36382Ssklower insque( &oldent->eonc_q_LINK, (&eon_LINK_hdr)); 400*36382Ssklower oldent = ent; 401*36382Ssklower } 402*36382Ssklower 403*36382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 404*36382Ssklower eoa->seon_status & UPBITS; 405*36382Ssklower 406*36382Ssklower oldent->eonc_status |= (eoa->seon_status & UPBITS); 407*36382Ssklower 408*36382Ssklower if( which & EON_ESLINK_UP ) 409*36382Ssklower insque( &oldent->eonc_q_ES, (&eon_ES_hdr)); 410*36382Ssklower if( which & EON_ISLINK_UP ) 411*36382Ssklower insque( &oldent->eonc_q_IS, (&eon_IS_hdr)); 412*36382Ssklower } 413*36382Ssklower 414*36382Ssklower if( eoa->seon_status & DOWNBITS ) { 415*36382Ssklower if(!oldent) { 416*36382Ssklower return ENOENT; /* no such entry */ 417*36382Ssklower } 418*36382Ssklower which = (eoa->seon_status ^ oldent->eonc_status) & 419*36382Ssklower eoa->seon_status & DOWNBITS; 420*36382Ssklower 421*36382Ssklower oldent->eonc_status |= (eoa->seon_status & DOWNBITS); 422*36382Ssklower 423*36382Ssklower if( which & EON_ESLINK_DOWN ) 424*36382Ssklower remque( &(oldent->eonc_q_ES) ); 425*36382Ssklower if( which & EON_ISLINK_DOWN ) 426*36382Ssklower remque( &(oldent->eonc_q_IS) ); 427*36382Ssklower } 428*36382Ssklower 429*36382Ssklower IFDEBUG(D_EON) 430*36382Ssklower printf("at end status 0x%x\n", oldent->eonc_status); 431*36382Ssklower ENDDEBUG 432*36382Ssklower break; 433*36382Ssklower } 434*36382Ssklower 435*36382Ssklower case SIOCGIFDSTADDR: 436*36382Ssklower { 437*36382Ssklower register struct eon_centry *oldent; 438*36382Ssklower 439*36382Ssklower oldent = find_oldent( eoa ); 440*36382Ssklower if( oldent == (struct eon_centry *)0 ) 441*36382Ssklower error = EADDRNOTAVAIL; 442*36382Ssklower else 443*36382Ssklower eoa->seon_status = oldent->eonc_status; 444*36382Ssklower } 445*36382Ssklower break; 446*36382Ssklower 447*36382Ssklower case SIOCSIFADDR: 448*36382Ssklower ifp->if_flags |= IFF_UP; 449*36382Ssklower break; 450*36382Ssklower 451*36382Ssklower case SIOCSIFFLAGS: 452*36382Ssklower if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & 453*36382Ssklower IFF_RUNNING){ 454*36382Ssklower ifp->if_flags &= ~IFF_RUNNING; 455*36382Ssklower } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & 456*36382Ssklower IFF_RUNNING) == 0) 457*36382Ssklower eoninit(ifp->if_unit); 458*36382Ssklower break; 459*36382Ssklower default: 460*36382Ssklower error = EINVAL; 461*36382Ssklower } 462*36382Ssklower splx(s); 463*36382Ssklower return(error); 464*36382Ssklower } 465*36382Ssklower 466*36382Ssklower /* 467*36382Ssklower * FUNCTION: eoninit 468*36382Ssklower * 469*36382Ssklower * PURPOSE: initialization 470*36382Ssklower * 471*36382Ssklower * RETURNS: nothing 472*36382Ssklower */ 473*36382Ssklower 474*36382Ssklower eoninit(unit) 475*36382Ssklower int unit; 476*36382Ssklower { 477*36382Ssklower printf("eoninit ecn%d\n", unit); 478*36382Ssklower } 479*36382Ssklower 480*36382Ssklower 481*36382Ssklower /* 482*36382Ssklower * FUNCTION: eonint 483*36382Ssklower * 484*36382Ssklower * PURPOSE: filler for device configuration 485*36382Ssklower * 486*36382Ssklower * RETURNS: nothing 487*36382Ssklower * 488*36382Ssklower * NOTES: *should* never get called - for debugging it's here 489*36382Ssklower */ 490*36382Ssklower 491*36382Ssklower eonint() 492*36382Ssklower { 493*36382Ssklower /* silent - so no more stray interrupt messages from the aed! yay 494*36382Ssklower printf("eonint() called - BOGUS INTERRUPT\n"); 495*36382Ssklower */ 496*36382Ssklower } 497*36382Ssklower 498*36382Ssklower 499*36382Ssklower /* 500*36382Ssklower * FUNCTION: eonoutput 501*36382Ssklower * 502*36382Ssklower * PURPOSE: prepend an eon header and hand to IP 503*36382Ssklower * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device 504*36382Ssklower * (m) is an mbuf *, *m is a CLNL packet 505*36382Ssklower * (dst) is a destination address - have to interp. as 506*36382Ssklower * multicast or broadcast or real address. 507*36382Ssklower * 508*36382Ssklower * RETURNS: unix error code 509*36382Ssklower * 510*36382Ssklower * NOTES: 511*36382Ssklower * 512*36382Ssklower */ 513*36382Ssklower eonoutput(ifp, morig, dst) 514*36382Ssklower register struct ifnet *ifp; 515*36382Ssklower register struct mbuf *morig; /* packet */ 516*36382Ssklower struct sockaddr_iso *dst; /* destination addr */ 517*36382Ssklower { 518*36382Ssklower int s; 519*36382Ssklower struct eon_hdr *eonhdr; 520*36382Ssklower struct ip *iphdr; 521*36382Ssklower struct mbuf *mh; 522*36382Ssklower int error = 0; 523*36382Ssklower register int datalen; 524*36382Ssklower caddr_t dstipaddrloc; 525*36382Ssklower int single=0; 526*36382Ssklower int qoffset=0; 527*36382Ssklower register struct eon_centry *ent; 528*36382Ssklower struct qhdr *q; 529*36382Ssklower 530*36382Ssklower IFDEBUG(D_EON) 531*36382Ssklower printf("eonoutput \n" ); 532*36382Ssklower ENDDEBUG 533*36382Ssklower 534*36382Ssklower if( dst->siso_family != AF_ISO ) 535*36382Ssklower return EINVAL; 536*36382Ssklower if( dst->siso_addr.isoa_afi != AFI_RFC986 ) 537*36382Ssklower return EINVAL; 538*36382Ssklower 539*36382Ssklower s = splnet(); 540*36382Ssklower 541*36382Ssklower /* Nsel tells what type of multicast address, if multicast */ 542*36382Ssklower switch( dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET]) { 543*36382Ssklower case EON_NORMAL_ADDR: 544*36382Ssklower IncStat(es_out_normal); 545*36382Ssklower dstipaddrloc = (caddr_t)&(dst->siso_addr.rfc986_dsp[1]); 546*36382Ssklower single = 1; 547*36382Ssklower break; 548*36382Ssklower 549*36382Ssklower case EON_BROADCAST: 550*36382Ssklower IncStat(es_out_broad); 551*36382Ssklower if( eon_LINK_hdr.link == (struct qhdr *)0 ) { 552*36382Ssklower error = EADDRNOTAVAIL; 553*36382Ssklower } else { 554*36382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 555*36382Ssklower ent = qtocentry(eon_LINK_hdr.link, qoffset); 556*36382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 557*36382Ssklower } 558*36382Ssklower break; 559*36382Ssklower case EON_MULTICAST_ES: 560*36382Ssklower IncStat(es_out_multi_es); 561*36382Ssklower if( eon_ES_hdr.link == (struct qhdr *)0 ) { 562*36382Ssklower error = EADDRNOTAVAIL; 563*36382Ssklower } else { 564*36382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_ES); 565*36382Ssklower ent = qtocentry(eon_ES_hdr.link, qoffset); 566*36382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 567*36382Ssklower } 568*36382Ssklower break; 569*36382Ssklower case EON_MULTICAST_IS: 570*36382Ssklower IncStat(es_out_multi_is); 571*36382Ssklower if( eon_IS_hdr.link == (struct qhdr *)0 ) { 572*36382Ssklower error = EADDRNOTAVAIL; 573*36382Ssklower } else { 574*36382Ssklower qoffset = _offsetof( struct eon_centry, eonc_q_LINK); 575*36382Ssklower ent = qtocentry(eon_IS_hdr.link, qoffset); 576*36382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 577*36382Ssklower } 578*36382Ssklower break; 579*36382Ssklower default: 580*36382Ssklower printf("NSEL bad value; treated as EON_NORMAL_ADDR\n"); 581*36382Ssklower dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET] = EON_NORMAL_ADDR; 582*36382Ssklower single = 1; 583*36382Ssklower break; 584*36382Ssklower } 585*36382Ssklower if( error ) 586*36382Ssklower goto done; 587*36382Ssklower 588*36382Ssklower /* get data length -- needed later */ 589*36382Ssklower datalen = m_datalen( morig ); 590*36382Ssklower IFDEBUG(D_EON) 591*36382Ssklower printf("eonoutput : m_datalen returns %d\n", datalen); 592*36382Ssklower ENDDEBUG 593*36382Ssklower 594*36382Ssklower mh = m_getclr( M_DONTWAIT, MT_HEADER); 595*36382Ssklower if(mh == (struct mbuf *)0) { 596*36382Ssklower goto done; 597*36382Ssklower } 598*36382Ssklower 599*36382Ssklower /* put an eon_hdr in the buffer, prepended by an ip header */ 600*36382Ssklower mh->m_act = (struct mbuf *)0; 601*36382Ssklower mh->m_len = sizeof(struct eon_hdr); 602*36382Ssklower mh->m_off = MMAXOFF - sizeof(struct eon_hdr); 603*36382Ssklower mh->m_next = morig; 604*36382Ssklower eonhdr = mtod(mh, struct eon_hdr *); 605*36382Ssklower eonhdr->eonh_class = 606*36382Ssklower dst->siso_addr.rfc986_dsp[RFC986_NSEL_OFFSET]; 607*36382Ssklower eonhdr->eonh_vers = EON_VERSION; 608*36382Ssklower 609*36382Ssklower IFDEBUG(D_EON) 610*36382Ssklower printf("eonoutput : gen csum (0x%x, offset %d, datalen %d)\n", 611*36382Ssklower mh, _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 612*36382Ssklower ENDDEBUG 613*36382Ssklower iso_gen_csum(mh, 614*36382Ssklower _offsetof(struct eon_hdr, eonh_csum), sizeof(struct eon_hdr)); 615*36382Ssklower 616*36382Ssklower mh->m_len += sizeof(struct ip); 617*36382Ssklower mh->m_off -= sizeof(struct ip); 618*36382Ssklower iphdr = mtod(mh, struct ip *); 619*36382Ssklower 620*36382Ssklower iphdr->ip_p = IPPROTO_EON; 621*36382Ssklower iphdr->ip_len = (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen); 622*36382Ssklower iphdr->ip_ttl = MAXTTL; 623*36382Ssklower iphdr->ip_src.s_addr = INADDR_ANY; 624*36382Ssklower 625*36382Ssklower IFDEBUG(D_EON) 626*36382Ssklower printf("eonoutput : after gen csum: ip_len %d/0x%x\n", 627*36382Ssklower (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen), 628*36382Ssklower (sizeof(struct eon_hdr) + sizeof(struct ip) + datalen) 629*36382Ssklower ); 630*36382Ssklower ENDDEBUG 631*36382Ssklower 632*36382Ssklower morig = mh; 633*36382Ssklower 634*36382Ssklower for(;;) { 635*36382Ssklower 636*36382Ssklower if( !single ) { 637*36382Ssklower /* make a copy to send */ 638*36382Ssklower IFDEBUG(D_EON) 639*36382Ssklower printf("eonoutput : m_copy (0x%x, 0, 0x%x)\n", 640*36382Ssklower morig, iphdr->ip_len); 641*36382Ssklower ENDDEBUG 642*36382Ssklower mh = m_copy(morig, 0, iphdr->ip_len); 643*36382Ssklower mh = m_pullup(mh, sizeof(struct ip)); 644*36382Ssklower iphdr = mtod(mh, struct ip *); 645*36382Ssklower } 646*36382Ssklower IFDEBUG(D_EON) 647*36382Ssklower printf("eonoutput : bcopy 0x%x to 0x%x length %d\n", 648*36382Ssklower dstipaddrloc, 649*36382Ssklower (caddr_t)&(iphdr->ip_dst.s_addr), 650*36382Ssklower sizeof(iphdr->ip_dst.s_addr)); 651*36382Ssklower ENDDEBUG 652*36382Ssklower bcopy( 653*36382Ssklower dstipaddrloc, 654*36382Ssklower (caddr_t)&(iphdr->ip_dst.s_addr), sizeof(iphdr->ip_dst.s_addr)); 655*36382Ssklower IFDEBUG(D_EON) 656*36382Ssklower printf("eonoutput : dst ip addr : %d.%d.%d.%d", 657*36382Ssklower (iphdr->ip_dst.s_addr>>24)&0xff, 658*36382Ssklower (iphdr->ip_dst.s_addr>>16)&0xff, 659*36382Ssklower (iphdr->ip_dst.s_addr>>8)&0xff, 660*36382Ssklower (iphdr->ip_dst.s_addr)&0xff ); 661*36382Ssklower ENDDEBUG 662*36382Ssklower 663*36382Ssklower IFDEBUG(D_EON) 664*36382Ssklower printf("eonoutput ip_output : eon header:\n"); 665*36382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 666*36382Ssklower printf("ip header:\n"); 667*36382Ssklower dump_buf(iphdr, sizeof(struct ip)); 668*36382Ssklower ENDDEBUG 669*36382Ssklower 670*36382Ssklower IncStat(es_ipout); 671*36382Ssklower if( error = ip_output(mh, (struct mbuf *)0, (struct route *)0, 0) ) 672*36382Ssklower break; 673*36382Ssklower 674*36382Ssklower IFDEBUG(D_EON) 675*36382Ssklower printf("eonoutput ip_output returns 0x%x; single %d\n", 676*36382Ssklower error, single); 677*36382Ssklower ENDDEBUG 678*36382Ssklower 679*36382Ssklower if(single) 680*36382Ssklower break; 681*36382Ssklower 682*36382Ssklower q = centrytoq(ent, qoffset)->link; 683*36382Ssklower if( q == (struct qhdr *)0) 684*36382Ssklower break; 685*36382Ssklower ent = qtocentry( q, qoffset ); 686*36382Ssklower IFDEBUG(D_EON) 687*36382Ssklower printf("eonoutput : get next entry: 0x%x\n", ent); 688*36382Ssklower ENDDEBUG 689*36382Ssklower dstipaddrloc = (caddr_t) &(ent->eonc_addr); 690*36382Ssklower IFDEBUG(D_EON) 691*36382Ssklower printf("eonoutput : dump of eon_centry 0x%x:\n", ent ); 692*36382Ssklower dump_buf(ent, sizeof(struct eon_centry) ); 693*36382Ssklower ENDDEBUG 694*36382Ssklower } 695*36382Ssklower done: 696*36382Ssklower if( !single ) { 697*36382Ssklower IFDEBUG(D_EON) 698*36382Ssklower printf("eonoutput : freeing morig 0x%x\n", morig); 699*36382Ssklower ENDDEBUG 700*36382Ssklower m_freem(morig); 701*36382Ssklower } 702*36382Ssklower splx(s); 703*36382Ssklower return error; 704*36382Ssklower } 705*36382Ssklower 706*36382Ssklower eoninput(m, ifp) 707*36382Ssklower register struct mbuf *m; 708*36382Ssklower struct ifnet *ifp; /* real ifp */ 709*36382Ssklower { 710*36382Ssklower int s; 711*36382Ssklower register struct eon_hdr *eonhdr; 712*36382Ssklower register struct ip *iphdr; 713*36382Ssklower struct ifnet *eonifp; 714*36382Ssklower register int datalen; 715*36382Ssklower 716*36382Ssklower s = splnet(); 717*36382Ssklower 718*36382Ssklower eonifp = &eonif[0]; /* kludge - really want to give CLNP 719*36382Ssklower * the ifp for eon, not for the real device 720*36382Ssklower */ 721*36382Ssklower 722*36382Ssklower IFDEBUG(D_EON) 723*36382Ssklower printf("eoninput() 0x%x m_off 0x%x m_len 0x%x dequeued\n", 724*36382Ssklower m, m?m->m_off:0, m?m->m_len:0); 725*36382Ssklower ENDDEBUG 726*36382Ssklower 727*36382Ssklower if (m == 0) { 728*36382Ssklower goto drop; 729*36382Ssklower } 730*36382Ssklower m = m_pullup(m, (sizeof(struct eon_hdr)+sizeof(struct ip))); 731*36382Ssklower if (m == 0) { 732*36382Ssklower IncStat(es_badhdr); 733*36382Ssklower goto drop; 734*36382Ssklower } 735*36382Ssklower 736*36382Ssklower iphdr = mtod(m, struct ip *); 737*36382Ssklower 738*36382Ssklower /* do a few checks for debugging */ 739*36382Ssklower if( iphdr->ip_p != IPPROTO_EON ) { 740*36382Ssklower IncStat(es_badhdr); 741*36382Ssklower goto drop; 742*36382Ssklower } 743*36382Ssklower 744*36382Ssklower /* drop ip header from the mbuf */ 745*36382Ssklower m->m_len -= sizeof(struct ip); 746*36382Ssklower m->m_off += sizeof(struct ip); 747*36382Ssklower 748*36382Ssklower eonhdr = mtod(m, struct eon_hdr *); 749*36382Ssklower 750*36382Ssklower IFDEBUG(D_EON) 751*36382Ssklower printf("eoninput: eon header:\n"); 752*36382Ssklower dump_buf(eonhdr, sizeof(struct eon_hdr)); 753*36382Ssklower ENDDEBUG 754*36382Ssklower 755*36382Ssklower /* checks for debugging */ 756*36382Ssklower if( eonhdr->eonh_vers != EON_VERSION) { 757*36382Ssklower IncStat(es_badhdr); 758*36382Ssklower goto drop; 759*36382Ssklower } 760*36382Ssklower 761*36382Ssklower datalen = m_datalen( m ); 762*36382Ssklower if( iso_check_csum( m, sizeof(struct eon_hdr) ) != EOK ) { 763*36382Ssklower IncStat(es_badcsum); 764*36382Ssklower goto drop; 765*36382Ssklower } 766*36382Ssklower 767*36382Ssklower IFDEBUG(D_EON) 768*36382Ssklower printf("eoninput csum ok class 0x%x\n", eonhdr->eonh_class ); 769*36382Ssklower ENDDEBUG 770*36382Ssklower switch( eonhdr->eonh_class) { 771*36382Ssklower case EON_BROADCAST: 772*36382Ssklower IncStat(es_in_broad); 773*36382Ssklower break; 774*36382Ssklower case EON_NORMAL_ADDR: 775*36382Ssklower IncStat(es_in_normal); 776*36382Ssklower break; 777*36382Ssklower case EON_MULTICAST_ES: 778*36382Ssklower if( ( eonifp->if_flags & IFF_ES) == 0 ) 779*36382Ssklower goto drop; 780*36382Ssklower IncStat(es_in_multi_es); 781*36382Ssklower break; 782*36382Ssklower case EON_MULTICAST_IS: 783*36382Ssklower if( ( eonifp->if_flags & IFF_IS) == 0 ) 784*36382Ssklower goto drop; 785*36382Ssklower IncStat(es_in_multi_is); 786*36382Ssklower break; 787*36382Ssklower } 788*36382Ssklower eonifp->if_ipackets ++; 789*36382Ssklower 790*36382Ssklower /* drop eonhdr from the mbuf */ 791*36382Ssklower m->m_len -= sizeof(struct eon_hdr); 792*36382Ssklower m->m_off += sizeof(struct eon_hdr); 793*36382Ssklower 794*36382Ssklower { 795*36382Ssklower /* put it on the CLNP queue and set soft interrupt */ 796*36382Ssklower struct ifqueue *ifq; 797*36382Ssklower extern struct ifqueue clnlintrq; 798*36382Ssklower int len; 799*36382Ssklower 800*36382Ssklower /* when acting as a subnet service, have to prepend a 801*36382Ssklower * pointer to the ifnet before handing this to clnp (GAG) 802*36382Ssklower */ 803*36382Ssklower len = sizeof(struct snpa_hdr); 804*36382Ssklower if( ( m->m_off > MMINOFF + len) && 805*36382Ssklower ( m->m_off <= MMAXOFF )) { 806*36382Ssklower m->m_off -= len; 807*36382Ssklower m->m_len += len; 808*36382Ssklower } 809*36382Ssklower ( mtod(m, struct snpa_hdr *) )->snh_ifp = eonifp; /* KLUDGE */ 810*36382Ssklower 811*36382Ssklower /* this is cutting it close */ 812*36382Ssklower bcopy( &iphdr->ip_src, ( mtod(m, struct snpa_hdr *))->snh_shost, 813*36382Ssklower sizeof(struct in_addr)); 814*36382Ssklower bcopy( &iphdr->ip_dst, ( mtod(m, struct snpa_hdr *))->snh_dhost, 815*36382Ssklower sizeof(struct in_addr)); 816*36382Ssklower 817*36382Ssklower IFDEBUG(D_EON) 818*36382Ssklower printf("eoninput to clnl IFQ\n"); 819*36382Ssklower ENDDEBUG 820*36382Ssklower ifq = &clnlintrq; 821*36382Ssklower splimp(); 822*36382Ssklower if (IF_QFULL(ifq)) { 823*36382Ssklower IF_DROP(ifq); 824*36382Ssklower m_freem(m); 825*36382Ssklower splx(s); 826*36382Ssklower eonifp->if_ierrors ++; 827*36382Ssklower return; 828*36382Ssklower } 829*36382Ssklower IF_ENQUEUE(ifq, m); 830*36382Ssklower IFDEBUG(D_EON) 831*36382Ssklower printf( 832*36382Ssklower "0x%x enqueued on clnp Q: m_len 0x%x m_type 0x%x m_off 0x%x\n", 833*36382Ssklower m, m->m_len, m->m_type, m->m_off); 834*36382Ssklower dump_buf(mtod(m, caddr_t), m->m_len); 835*36382Ssklower ENDDEBUG 836*36382Ssklower schednetisr(NETISR_CLNP); 837*36382Ssklower } 838*36382Ssklower done: 839*36382Ssklower splx(s); 840*36382Ssklower return 0; 841*36382Ssklower drop: 842*36382Ssklower IFDEBUG(D_EON) 843*36382Ssklower printf("eoninput: DROP \n" ); 844*36382Ssklower ENDDEBUG 845*36382Ssklower eonifp->if_ierrors ++; 846*36382Ssklower m_freem(m); 847*36382Ssklower goto done; 848*36382Ssklower } 849*36382Ssklower 850*36382Ssklower int 851*36382Ssklower eonctlinput(cmd, sin) 852*36382Ssklower int cmd; 853*36382Ssklower struct sockaddr_in *sin; 854*36382Ssklower { 855*36382Ssklower extern u_char inetctlerrmap[]; 856*36382Ssklower 857*36382Ssklower IFDEBUG(D_EON) 858*36382Ssklower printf("eonctlinput: cmd 0x%x addr: ", cmd); 859*36382Ssklower dump_isoaddr(sin); 860*36382Ssklower printf("\n"); 861*36382Ssklower ENDDEBUG 862*36382Ssklower 863*36382Ssklower if (cmd < 0 || cmd > PRC_NCMDS) 864*36382Ssklower return 0; 865*36382Ssklower 866*36382Ssklower IncStat(es_icmp[cmd]); 867*36382Ssklower switch (cmd) { 868*36382Ssklower 869*36382Ssklower case PRC_QUENCH2: 870*36382Ssklower case PRC_QUENCH: 871*36382Ssklower /* TODO: set the dec bit */ 872*36382Ssklower break; 873*36382Ssklower case PRC_TIMXCEED_REASS: 874*36382Ssklower case PRC_ROUTEDEAD: 875*36382Ssklower case PRC_HOSTUNREACH: 876*36382Ssklower case PRC_UNREACH_NET: 877*36382Ssklower case PRC_IFDOWN: 878*36382Ssklower case PRC_UNREACH_HOST: 879*36382Ssklower case PRC_HOSTDEAD: 880*36382Ssklower case PRC_TIMXCEED_INTRANS: 881*36382Ssklower /* TODO: mark the link down */ 882*36382Ssklower break; 883*36382Ssklower 884*36382Ssklower case PRC_UNREACH_PROTOCOL: 885*36382Ssklower case PRC_UNREACH_PORT: 886*36382Ssklower case PRC_UNREACH_NEEDFRAG: 887*36382Ssklower case PRC_UNREACH_SRCFAIL: 888*36382Ssklower case PRC_REDIRECT_NET: 889*36382Ssklower case PRC_REDIRECT_HOST: 890*36382Ssklower case PRC_REDIRECT_TOSNET: 891*36382Ssklower case PRC_REDIRECT_TOSHOST: 892*36382Ssklower case PRC_MSGSIZE: 893*36382Ssklower case PRC_PARAMPROB: 894*36382Ssklower printf("eonctlinput: ICMP cmd 0x%x\n", cmd ); 895*36382Ssklower break; 896*36382Ssklower } 897*36382Ssklower return 0; 898*36382Ssklower } 899*36382Ssklower 900*36382Ssklower #endif NEON>0 901