1*36392Ssklower /*********************************************************** 2*36392Ssklower Copyright IBM Corporation 1987 3*36392Ssklower 4*36392Ssklower All Rights Reserved 5*36392Ssklower 6*36392Ssklower Permission to use, copy, modify, and distribute this software and its 7*36392Ssklower documentation for any purpose and without fee is hereby granted, 8*36392Ssklower provided that the above copyright notice appear in all copies and that 9*36392Ssklower both that copyright notice and this permission notice appear in 10*36392Ssklower supporting documentation, and that the name of IBM not be 11*36392Ssklower used in advertising or publicity pertaining to distribution of the 12*36392Ssklower software without specific, written prior permission. 13*36392Ssklower 14*36392Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15*36392Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16*36392Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17*36392Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18*36392Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19*36392Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20*36392Ssklower SOFTWARE. 21*36392Ssklower 22*36392Ssklower ******************************************************************/ 23*36392Ssklower 24*36392Ssklower /* 25*36392Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 26*36392Ssklower */ 27*36392Ssklower /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */ 28*36392Ssklower /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */ 29*36392Ssklower 30*36392Ssklower #ifndef lint 31*36392Ssklower static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $"; 32*36392Ssklower #endif lint 33*36392Ssklower 34*36392Ssklower #ifdef ISO 35*36392Ssklower 36*36392Ssklower #include "../h/types.h" 37*36392Ssklower #include "../h/param.h" 38*36392Ssklower #include "../h/mbuf.h" 39*36392Ssklower #include "../h/domain.h" 40*36392Ssklower #include "../h/protosw.h" 41*36392Ssklower #include "../h/socket.h" 42*36392Ssklower #include "../h/socketvar.h" 43*36392Ssklower #include "../h/errno.h" 44*36392Ssklower #include "../h/ioctl.h" 45*36392Ssklower #include "../h/time.h" 46*36392Ssklower #include "../h/kernel.h" 47*36392Ssklower 48*36392Ssklower #include "../net/if.h" 49*36392Ssklower #include "../net/route.h" 50*36392Ssklower 51*36392Ssklower #include "../netiso/iso.h" 52*36392Ssklower #include "../netiso/iso_var.h" 53*36392Ssklower #include "../netiso/iso_snpac.h" 54*36392Ssklower #include "../netiso/clnp.h" 55*36392Ssklower #include "../netiso/clnp_stat.h" 56*36392Ssklower #include "../netiso/argo_debug.h" 57*36392Ssklower #include "../netiso/esis.h" 58*36392Ssklower 59*36392Ssklower #define SNPAC_BSIZ 20 /* bucket size */ 60*36392Ssklower #define SNPAC_NB 13 /* number of buckets */ 61*36392Ssklower #define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB) 62*36392Ssklower struct snpa_cache iso_snpac[SNPAC_SIZE]; 63*36392Ssklower int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */ 64*36392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 65*36392Ssklower static struct iso_addr zero_isoa; 66*36392Ssklower 67*36392Ssklower #define SNPAC_HASH(addr) \ 68*36392Ssklower (((u_long) iso_hashchar(addr, addr->isoa_len)) % SNPAC_NB) 69*36392Ssklower 70*36392Ssklower #define SNPAC_LOOK(sc,addr) { \ 71*36392Ssklower register n; \ 72*36392Ssklower sc = &iso_snpac[SNPAC_HASH(addr) * SNPAC_BSIZ]; \ 73*36392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) \ 74*36392Ssklower if ((sc->sc_flags & SNPA_VALID) && \ 75*36392Ssklower (iso_addrmatch1(&sc->sc_nsap, addr))) \ 76*36392Ssklower break; \ 77*36392Ssklower if (n >= SNPAC_BSIZ) \ 78*36392Ssklower sc = 0; \ 79*36392Ssklower } 80*36392Ssklower 81*36392Ssklower struct snpa_cache *snpac_new(); 82*36392Ssklower 83*36392Ssklower /* 84*36392Ssklower * We only keep track of a single IS at a time. 85*36392Ssklower */ 86*36392Ssklower struct snpa_cache *known_is; 87*36392Ssklower 88*36392Ssklower /* 89*36392Ssklower * Addresses taken from NBS agreements, December 1987. 90*36392Ssklower * 91*36392Ssklower * These addresses assume on-the-wire transmission of least significant 92*36392Ssklower * bit first. This is the method used by 802.3. When these 93*36392Ssklower * addresses are passed to the token ring driver, (802.5), they 94*36392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 95*36392Ssklower * 96*36392Ssklower * Furthermore, according to IBM Austin, these addresses are not 97*36392Ssklower * true token ring multicast addresses. More work is necessary 98*36392Ssklower * to get multicast to work right on token ring. 99*36392Ssklower * 100*36392Ssklower * Currently, the token ring driver does not handle multicast, so 101*36392Ssklower * these addresses are converted into the broadcast address in 102*36392Ssklower * lan_output() That means that if these multicast addresses change 103*36392Ssklower * the token ring driver must be altered. 104*36392Ssklower */ 105*36392Ssklower struct snpa_cache all_es = { 106*36392Ssklower { { 0x0 }, /* sc_nsap */ 107*36392Ssklower 6, /* sc_len */ 108*36392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */ 109*36392Ssklower SNPA_VALID, /* sc_flags */ 110*36392Ssklower 0 } /* sc_ht */ 111*36392Ssklower }; 112*36392Ssklower struct snpa_cache all_is = { 113*36392Ssklower { { 0x0 }, /* sc_nsap */ 114*36392Ssklower 6, /* sc_len */ 115*36392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */ 116*36392Ssklower SNPA_VALID, /* sc_flags */ 117*36392Ssklower 0 } /* sc_ht */ 118*36392Ssklower }; 119*36392Ssklower 120*36392Ssklower 121*36392Ssklower /* 122*36392Ssklower * FUNCTION: iso_snparesolve 123*36392Ssklower * 124*36392Ssklower * PURPOSE: Resolve an iso address into snpa address 125*36392Ssklower * 126*36392Ssklower * RETURNS: 0 if addr is resolved 127*36392Ssklower * errno if addr is unknown 128*36392Ssklower * 129*36392Ssklower * SIDE EFFECTS: 130*36392Ssklower * 131*36392Ssklower * NOTES: If an entry is found that matches the address, that 132*36392Ssklower * snpa is returned. If no entry is found, but an IS is 133*36392Ssklower * known, then the address of the IS is returned. If 134*36392Ssklower * neither an address is found that matches or an IS is 135*36392Ssklower * known, then the multi-cast address for "all ES" for 136*36392Ssklower * this interface is returned. 137*36392Ssklower * 138*36392Ssklower * NB: the last case described above constitutes the 139*36392Ssklower * query configuration function 9542, sec 6.5 140*36392Ssklower * A mechanism is needed to prevent this function from 141*36392Ssklower * being invoked if the system is an IS. 142*36392Ssklower */ 143*36392Ssklower iso_snparesolve(ifp, dst, snpa, snpa_len) 144*36392Ssklower struct ifnet *ifp; /* outgoing interface */ 145*36392Ssklower struct sockaddr_iso *dst; /* destination */ 146*36392Ssklower char *snpa; /* RESULT: snpa to be used */ 147*36392Ssklower int *snpa_len; /* RESULT: length of snpa */ 148*36392Ssklower { 149*36392Ssklower extern struct ifnet loif; /* loopback interface */ 150*36392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 151*36392Ssklower struct iso_addr *destiso; /* destination iso addr */ 152*36392Ssklower int s; 153*36392Ssklower 154*36392Ssklower destiso = &dst->siso_addr; 155*36392Ssklower 156*36392Ssklower /* 157*36392Ssklower * This hack allows us to send esis packets that have the destination snpa 158*36392Ssklower * addresss embedded in the destination nsap address 159*36392Ssklower */ 160*36392Ssklower if (destiso->isoa_afi == AFI_SNA) { 161*36392Ssklower /* 162*36392Ssklower * This is a subnetwork address. Return it immediately 163*36392Ssklower */ 164*36392Ssklower IFDEBUG(D_SNPA) 165*36392Ssklower printf("iso_snparesolve: return SN address\n"); 166*36392Ssklower ENDDEBUG 167*36392Ssklower 168*36392Ssklower *snpa_len = destiso->isoa_len - 1; /* subtract size of AFI */ 169*36392Ssklower bcopy((caddr_t) destiso->sna_idi, (caddr_t)snpa, *snpa_len); 170*36392Ssklower return (0); 171*36392Ssklower } 172*36392Ssklower 173*36392Ssklower IFDEBUG(D_SNPA) 174*36392Ssklower printf("iso_snparesolve: resolving %s\n", clnp_iso_addrp(destiso)); 175*36392Ssklower ENDDEBUG 176*36392Ssklower 177*36392Ssklower /* 178*36392Ssklower * packet is not for us, check cache for an entry 179*36392Ssklower */ 180*36392Ssklower s = splimp(); 181*36392Ssklower SNPAC_LOOK(sc, destiso); 182*36392Ssklower if (sc == 0) { /* not found */ 183*36392Ssklower /* If we are an IS, we can't do much with the packet */ 184*36392Ssklower if (iso_systype == SNPA_IS) 185*36392Ssklower goto bad; 186*36392Ssklower 187*36392Ssklower /* 188*36392Ssklower * Check if we know about an IS 189*36392Ssklower */ 190*36392Ssklower if ((known_is) && (known_is->sc_flags & SNPA_VALID)) { 191*36392Ssklower sc = known_is; 192*36392Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 193*36392Ssklower /* 194*36392Ssklower * no IS, no match. Return "all es" multicast address for this 195*36392Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 196*36392Ssklower * 197*36392Ssklower * Note: there is a potential problem here. If the destination 198*36392Ssklower * is on the subnet and it does not respond with a ESH, but 199*36392Ssklower * does send back a TP CC, a connection could be established 200*36392Ssklower * where we always transmit the CLNP packet to "all es" 201*36392Ssklower */ 202*36392Ssklower sc = &all_es; 203*36392Ssklower } else { 204*36392Ssklower goto bad; 205*36392Ssklower } 206*36392Ssklower } 207*36392Ssklower 208*36392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 209*36392Ssklower *snpa_len = sc->sc_len; 210*36392Ssklower splx(s); 211*36392Ssklower return (0); 212*36392Ssklower 213*36392Ssklower bad: 214*36392Ssklower splx(s); 215*36392Ssklower return(ENETUNREACH); 216*36392Ssklower } 217*36392Ssklower 218*36392Ssklower 219*36392Ssklower /* 220*36392Ssklower * FUNCTION: snpac_look 221*36392Ssklower * 222*36392Ssklower * PURPOSE: Look up an entry in the snpa cache 223*36392Ssklower * 224*36392Ssklower * RETURNS: Pointer to snpa_cache structure, or null 225*36392Ssklower * 226*36392Ssklower * SIDE EFFECTS: 227*36392Ssklower * 228*36392Ssklower * NOTES: This is simply SNPAC_LOOK as a procedure. 229*36392Ssklower */ 230*36392Ssklower struct snpa_cache * 231*36392Ssklower snpac_look(isoa) 232*36392Ssklower struct iso_addr *isoa; /* destination nsap */ 233*36392Ssklower { 234*36392Ssklower struct snpa_cache *sc; 235*36392Ssklower int s = splimp(); 236*36392Ssklower 237*36392Ssklower SNPAC_LOOK(sc, isoa); 238*36392Ssklower 239*36392Ssklower splx(s); 240*36392Ssklower return(sc); 241*36392Ssklower } 242*36392Ssklower 243*36392Ssklower /* 244*36392Ssklower * FUNCTION: iso_8208snparesolve 245*36392Ssklower * 246*36392Ssklower * PURPOSE: Find the X.121 address that corresponds to an NSAP addr 247*36392Ssklower * 248*36392Ssklower * RETURNS: 0 or unix errno 249*36392Ssklower * 250*36392Ssklower * SIDE EFFECTS: 251*36392Ssklower * 252*36392Ssklower * NOTES: This ought to invoke the 8208 ES-IS function 253*36392Ssklower */ 254*36392Ssklower iso_8208snparesolve(dst, snpa, snpa_len) 255*36392Ssklower struct sockaddr_iso *dst; /* destination */ 256*36392Ssklower char *snpa; /* RESULT: snpa to be used */ 257*36392Ssklower int *snpa_len; /* RESULT: length of snpa */ 258*36392Ssklower { 259*36392Ssklower struct snpa_cache *sc; /* ptr to snpa table entry */ 260*36392Ssklower struct iso_addr *destiso; /* destination iso addr */ 261*36392Ssklower int s; 262*36392Ssklower int err = 0; 263*36392Ssklower 264*36392Ssklower destiso = &dst->siso_addr; 265*36392Ssklower 266*36392Ssklower s = splimp(); 267*36392Ssklower SNPAC_LOOK(sc, destiso); 268*36392Ssklower if (sc) { 269*36392Ssklower bcopy((caddr_t)sc->sc_snpa, (caddr_t)snpa, sc->sc_len); 270*36392Ssklower *snpa_len = sc->sc_len; 271*36392Ssklower } else { 272*36392Ssklower err = ENETUNREACH; 273*36392Ssklower } 274*36392Ssklower splx(s); 275*36392Ssklower return (err); 276*36392Ssklower } 277*36392Ssklower 278*36392Ssklower /* 279*36392Ssklower * FUNCTION: iso_8208snpaadd 280*36392Ssklower * 281*36392Ssklower * PURPOSE: Add an entry to the snpa cache 282*36392Ssklower * 283*36392Ssklower * RETURNS: 284*36392Ssklower * 285*36392Ssklower * SIDE EFFECTS: 286*36392Ssklower * 287*36392Ssklower * NOTES: used by cons 288*36392Ssklower */ 289*36392Ssklower iso_8208snpaadd(ifp, nsap, snpa, snpalen, ht) 290*36392Ssklower struct ifnet *ifp; /* interface info is related to */ 291*36392Ssklower struct iso_addr *nsap; /* nsap to add */ 292*36392Ssklower caddr_t snpa; /* translation */ 293*36392Ssklower int snpalen; /* length in bytes */ 294*36392Ssklower short ht; /* holding time (in seconds) */ 295*36392Ssklower { 296*36392Ssklower snpac_add(ifp, nsap, snpa, snpalen, SNPA_ES, ht); 297*36392Ssklower } 298*36392Ssklower 299*36392Ssklower /* 300*36392Ssklower * FUNCTION: iso_8208snpadelete 301*36392Ssklower * 302*36392Ssklower * PURPOSE: Delete an entry from the snpa cache 303*36392Ssklower * 304*36392Ssklower * RETURNS: nothing 305*36392Ssklower * 306*36392Ssklower * SIDE EFFECTS: 307*36392Ssklower * 308*36392Ssklower * NOTES: used by CONS 309*36392Ssklower */ 310*36392Ssklower iso_8208snpadelete(nsap) 311*36392Ssklower struct iso_addr *nsap; 312*36392Ssklower { 313*36392Ssklower struct snpa_cache *sc = snpac_look(nsap); 314*36392Ssklower 315*36392Ssklower if (sc != NULL) 316*36392Ssklower snpac_free(sc); 317*36392Ssklower } 318*36392Ssklower 319*36392Ssklower /* 320*36392Ssklower * FUNCTION: snpac_new 321*36392Ssklower * 322*36392Ssklower * PURPOSE: create a new entry in the iso address to ethernet 323*36392Ssklower * address table 324*36392Ssklower * 325*36392Ssklower * RETURNS: pointer to newest entry 326*36392Ssklower * 327*36392Ssklower * SIDE EFFECTS: times out old entries if no new entries are found 328*36392Ssklower * 329*36392Ssklower * NOTES: If the bucket is full, then timeout the oldest entry 330*36392Ssklower * (ie. the one with the youngest holding time) 331*36392Ssklower */ 332*36392Ssklower struct snpa_cache * 333*36392Ssklower snpac_new(isoa) 334*36392Ssklower struct iso_addr *isoa; /* iso address to enter into table */ 335*36392Ssklower { 336*36392Ssklower register struct snpa_cache *sc; 337*36392Ssklower register int n; 338*36392Ssklower int smallest_ht = 1000000; 339*36392Ssklower struct snpa_cache *maybe; 340*36392Ssklower 341*36392Ssklower sc = &iso_snpac[SNPAC_HASH(isoa) * SNPAC_BSIZ]; 342*36392Ssklower for (n = 0 ; n < SNPAC_BSIZ ; n++,sc++) { 343*36392Ssklower 344*36392Ssklower IFDEBUG (D_IOCTL) 345*36392Ssklower printf("snpac_new: sc x%x ", sc); 346*36392Ssklower 347*36392Ssklower if (sc->sc_flags & SNPA_VALID) { 348*36392Ssklower int i; 349*36392Ssklower 350*36392Ssklower printf("(valid) %s ", clnp_iso_addrp(&sc->sc_nsap)); 351*36392Ssklower for (i=0; i<sc->sc_len; i++) 352*36392Ssklower printf("%x%c", sc->sc_snpa[i], i < (sc->sc_len-1) ? ':' 353*36392Ssklower : '\n'); 354*36392Ssklower } else { 355*36392Ssklower printf("invalid\n"); 356*36392Ssklower } 357*36392Ssklower ENDDEBUG 358*36392Ssklower 359*36392Ssklower if (sc->sc_flags & SNPA_VALID) { 360*36392Ssklower if (sc->sc_ht < smallest_ht) { 361*36392Ssklower smallest_ht = sc->sc_ht; 362*36392Ssklower maybe = sc; 363*36392Ssklower } 364*36392Ssklower } else { 365*36392Ssklower return sc; /* found unused slot */ 366*36392Ssklower } 367*36392Ssklower } 368*36392Ssklower snpac_free(maybe); 369*36392Ssklower return maybe; 370*36392Ssklower } 371*36392Ssklower 372*36392Ssklower /* 373*36392Ssklower * FUNCTION: snpac_free 374*36392Ssklower * 375*36392Ssklower * PURPOSE: free an entry in the iso address map table 376*36392Ssklower * 377*36392Ssklower * RETURNS: nothing 378*36392Ssklower * 379*36392Ssklower * SIDE EFFECTS: 380*36392Ssklower * 381*36392Ssklower * NOTES: If there is a route entry associated with cache 382*36392Ssklower * entry, then delete that as well 383*36392Ssklower */ 384*36392Ssklower snpac_free(sc) 385*36392Ssklower register struct snpa_cache *sc; /* entry to free */ 386*36392Ssklower { 387*36392Ssklower int s = splimp(); 388*36392Ssklower 389*36392Ssklower if (known_is == sc) { 390*36392Ssklower snpac_rtrequest(SIOCDELRT, &zero_isoa, &known_is->sc_nsap, 391*36392Ssklower RTF_DYNAMIC|RTF_GATEWAY); 392*36392Ssklower known_is = NULL; 393*36392Ssklower } 394*36392Ssklower if (sc->sc_da.isoa_len > 0) { 395*36392Ssklower snpac_rtrequest(SIOCDELRT, &sc->sc_da, &known_is->sc_nsap, 396*36392Ssklower RTF_DYNAMIC|RTF_GATEWAY); 397*36392Ssklower } 398*36392Ssklower bzero((caddr_t)sc, sizeof(struct snpa_cache)); 399*36392Ssklower 400*36392Ssklower splx(s); 401*36392Ssklower } 402*36392Ssklower 403*36392Ssklower /* 404*36392Ssklower * FUNCTION: snpac_add 405*36392Ssklower * 406*36392Ssklower * PURPOSE: Add an entry to the snpa cache 407*36392Ssklower * 408*36392Ssklower * RETURNS: 409*36392Ssklower * 410*36392Ssklower * SIDE EFFECTS: 411*36392Ssklower * 412*36392Ssklower * NOTES: If entry already exists, then update holding time. 413*36392Ssklower */ 414*36392Ssklower snpac_add(ifp, nsap, snpa, snpalen, type, ht) 415*36392Ssklower struct ifnet *ifp; /* interface info is related to */ 416*36392Ssklower struct iso_addr *nsap; /* nsap to add */ 417*36392Ssklower caddr_t snpa; /* translation */ 418*36392Ssklower int snpalen; /* length in bytes */ 419*36392Ssklower char type; /* SNPA_IS or SNPA_ES */ 420*36392Ssklower short ht; /* holding time (in seconds) */ 421*36392Ssklower { 422*36392Ssklower struct snpa_cache *sc; 423*36392Ssklower int s = splimp(); 424*36392Ssklower 425*36392Ssklower SNPAC_LOOK(sc, nsap); 426*36392Ssklower if (sc == NULL) { 427*36392Ssklower sc = snpac_new(nsap); 428*36392Ssklower sc->sc_nsap = *nsap; 429*36392Ssklower } 430*36392Ssklower 431*36392Ssklower sc->sc_ht = ht; 432*36392Ssklower 433*36392Ssklower sc->sc_len = min(snpalen, MAX_SNPALEN); 434*36392Ssklower bcopy(snpa, sc->sc_snpa, sc->sc_len); 435*36392Ssklower sc->sc_flags = SNPA_VALID | type; 436*36392Ssklower sc->sc_ifp = ifp; 437*36392Ssklower 438*36392Ssklower if (type & SNPA_IS) 439*36392Ssklower snpac_logdefis(sc); 440*36392Ssklower 441*36392Ssklower splx(s); 442*36392Ssklower } 443*36392Ssklower 444*36392Ssklower /* 445*36392Ssklower * FUNCTION: snpac_ioctl 446*36392Ssklower * 447*36392Ssklower * PURPOSE: handle ioctls to change the iso address map 448*36392Ssklower * 449*36392Ssklower * RETURNS: unix error code 450*36392Ssklower * 451*36392Ssklower * SIDE EFFECTS: changes the snpa_cache table declared above. 452*36392Ssklower * 453*36392Ssklower * NOTES: 454*36392Ssklower */ 455*36392Ssklower snpac_ioctl(cmd, data) 456*36392Ssklower int cmd; /* ioctl to process */ 457*36392Ssklower caddr_t data; /* data for the cmd */ 458*36392Ssklower { 459*36392Ssklower register struct snpa_req *rq = (struct snpa_req *)data; 460*36392Ssklower register struct snpa_cache *sc; 461*36392Ssklower register struct iso_addr *isoa; 462*36392Ssklower int s; 463*36392Ssklower 464*36392Ssklower /* look up this address in table */ 465*36392Ssklower isoa = &rq->sr_isoa; 466*36392Ssklower 467*36392Ssklower /* sanity check */ 468*36392Ssklower if (rq->sr_len > MAX_SNPALEN) 469*36392Ssklower return(EINVAL); 470*36392Ssklower 471*36392Ssklower IFDEBUG (D_IOCTL) 472*36392Ssklower int i; 473*36392Ssklower 474*36392Ssklower printf("snpac_ioctl: "); 475*36392Ssklower switch(cmd) { 476*36392Ssklower case SIOCSISOMAP: printf("set"); break; 477*36392Ssklower case SIOCDISOMAP: printf("delete"); break; 478*36392Ssklower case SIOCGISOMAP: printf("get"); break; 479*36392Ssklower } 480*36392Ssklower printf(" %s to ", clnp_iso_addrp(isoa)); 481*36392Ssklower for (i=0; i<rq->sr_len; i++) 482*36392Ssklower printf("%x%c", rq->sr_snpa[i], i < (rq->sr_len-1) ? ':' : '\n'); 483*36392Ssklower ENDDEBUG 484*36392Ssklower 485*36392Ssklower s = splimp(); 486*36392Ssklower SNPAC_LOOK(sc, isoa); 487*36392Ssklower if (sc == NULL) { /* not found */ 488*36392Ssklower if (cmd != SIOCSISOMAP) 489*36392Ssklower return(ENXIO); 490*36392Ssklower } 491*36392Ssklower 492*36392Ssklower switch(cmd) { 493*36392Ssklower case SIOCSISOMAP: /* set entry */ 494*36392Ssklower snpac_add(NULL, isoa, rq->sr_snpa, rq->sr_len, 495*36392Ssklower rq->sr_flags & (SNPA_ES|SNPA_IS|SNPA_PERM), rq->sr_ht); 496*36392Ssklower break; 497*36392Ssklower 498*36392Ssklower case SIOCDISOMAP: /* delete entry */ 499*36392Ssklower snpac_free(sc); 500*36392Ssklower break; 501*36392Ssklower 502*36392Ssklower case SIOCGISOMAP: /* get entry */ 503*36392Ssklower bcopy((caddr_t)&sc->sc_sr, rq, sizeof(struct snpa_req)); 504*36392Ssklower break; 505*36392Ssklower } 506*36392Ssklower splx(s); 507*36392Ssklower return(0); 508*36392Ssklower } 509*36392Ssklower 510*36392Ssklower /* 511*36392Ssklower * FUNCTION: iso_tryloopback 512*36392Ssklower * 513*36392Ssklower * PURPOSE: Attempt to use the software loopback interface for pkt 514*36392Ssklower * 515*36392Ssklower * RETURNS: 0 if packet was sent successfully 516*36392Ssklower * errno if there was a problem sending the packet 517*36392Ssklower * Ie. the return value of looutput 518*36392Ssklower * -1 if software loopback is not appropriate 519*36392Ssklower * 520*36392Ssklower * SIDE EFFECTS: 521*36392Ssklower * 522*36392Ssklower * NOTES: 523*36392Ssklower */ 524*36392Ssklower iso_tryloopback(m, dst) 525*36392Ssklower struct mbuf *m; /* pkt */ 526*36392Ssklower struct sockaddr_iso *dst; /* destination */ 527*36392Ssklower { 528*36392Ssklower struct iso_addr *destiso; /* destination iso addr */ 529*36392Ssklower 530*36392Ssklower destiso = &dst->siso_addr; 531*36392Ssklower 532*36392Ssklower if (clnp_ours(destiso)) { 533*36392Ssklower IFDEBUG(D_SNPA) 534*36392Ssklower printf("iso_tryloopback: local destination\n"); 535*36392Ssklower ENDDEBUG 536*36392Ssklower if (loif.if_flags & IFF_UP) { 537*36392Ssklower IFDEBUG(D_SNPA) 538*36392Ssklower printf("iso_tryloopback: calling looutput\n"); 539*36392Ssklower ENDDEBUG 540*36392Ssklower return (looutput(&loif, m, (struct sockaddr *)dst)); 541*36392Ssklower } 542*36392Ssklower } 543*36392Ssklower return (-1); 544*36392Ssklower } 545*36392Ssklower 546*36392Ssklower /* 547*36392Ssklower * FUNCTION: snpac_systype 548*36392Ssklower * 549*36392Ssklower * PURPOSE: Set/Get the system type and esis parameters 550*36392Ssklower * 551*36392Ssklower * RETURNS: 0 on success, or unix error code 552*36392Ssklower * 553*36392Ssklower * SIDE EFFECTS: 554*36392Ssklower * 555*36392Ssklower * NOTES: 556*36392Ssklower */ 557*36392Ssklower snpac_systype (cmd, data) 558*36392Ssklower int cmd; /* ioctl to process */ 559*36392Ssklower caddr_t data; /* data for the cmd */ 560*36392Ssklower { 561*36392Ssklower register struct systype_req *rq = (struct systype_req *)data; 562*36392Ssklower extern short esis_holding_time, esis_config_time; 563*36392Ssklower 564*36392Ssklower IFDEBUG (D_IOCTL) 565*36392Ssklower if (cmd == SIOCSSTYPE) 566*36392Ssklower printf("snpac_systype: cmd set, type x%x, ht %d, ct %d\n", 567*36392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 568*36392Ssklower else 569*36392Ssklower printf("snpac_systype: cmd get\n"); 570*36392Ssklower ENDDEBUG 571*36392Ssklower 572*36392Ssklower if (cmd == SIOCSSTYPE) { 573*36392Ssklower if (!suser()) 574*36392Ssklower return(EACCES); 575*36392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 576*36392Ssklower return(EINVAL); 577*36392Ssklower if (rq->sr_type & SNPA_ES) { 578*36392Ssklower iso_systype = SNPA_ES; 579*36392Ssklower } else if (rq->sr_type & SNPA_IS) { 580*36392Ssklower iso_systype = SNPA_IS; 581*36392Ssklower } else { 582*36392Ssklower return(EINVAL); 583*36392Ssklower } 584*36392Ssklower esis_holding_time = rq->sr_holdt; 585*36392Ssklower esis_config_time = rq->sr_configt; 586*36392Ssklower } else if (cmd == SIOCGSTYPE) { 587*36392Ssklower rq->sr_type = iso_systype; 588*36392Ssklower rq->sr_holdt = esis_holding_time; 589*36392Ssklower rq->sr_configt = esis_config_time; 590*36392Ssklower } else { 591*36392Ssklower return(EINVAL); 592*36392Ssklower } 593*36392Ssklower return(0); 594*36392Ssklower } 595*36392Ssklower 596*36392Ssklower /* 597*36392Ssklower * FUNCTION: snpac_logdefis 598*36392Ssklower * 599*36392Ssklower * PURPOSE: Mark the IS passed as the default IS 600*36392Ssklower * 601*36392Ssklower * RETURNS: nothing 602*36392Ssklower * 603*36392Ssklower * SIDE EFFECTS: 604*36392Ssklower * 605*36392Ssklower * NOTES: 606*36392Ssklower */ 607*36392Ssklower snpac_logdefis(sc) 608*36392Ssklower struct snpa_cache *sc; 609*36392Ssklower { 610*36392Ssklower if (known_is) { 611*36392Ssklower snpac_rtrequest(SIOCDELRT, &zero_isoa, &known_is->sc_nsap, 612*36392Ssklower RTF_DYNAMIC|RTF_GATEWAY); 613*36392Ssklower } 614*36392Ssklower known_is = sc; 615*36392Ssklower snpac_rtrequest(SIOCADDRT, &zero_isoa, &sc->sc_nsap, 616*36392Ssklower RTF_DYNAMIC|RTF_GATEWAY); 617*36392Ssklower } 618*36392Ssklower 619*36392Ssklower /* 620*36392Ssklower * FUNCTION: snpac_age 621*36392Ssklower * 622*36392Ssklower * PURPOSE: Time out snpac entries 623*36392Ssklower * 624*36392Ssklower * RETURNS: 625*36392Ssklower * 626*36392Ssklower * SIDE EFFECTS: 627*36392Ssklower * 628*36392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 629*36392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 630*36392Ssklower * if the entry is added a moment before snpac_age is 631*36392Ssklower * called, the entry will immediately have SNPAC_AGE 632*36392Ssklower * seconds taken off the holding time, even though 633*36392Ssklower * it has only been held a brief moment. 634*36392Ssklower * 635*36392Ssklower * The proper way to do this is set an expiry timeval 636*36392Ssklower * equal to current time + holding time. Then snpac_age 637*36392Ssklower * would time out entries where expiry date is older 638*36392Ssklower * than the current time. 639*36392Ssklower */ 640*36392Ssklower snpac_age() 641*36392Ssklower { 642*36392Ssklower register struct snpa_cache *sc; 643*36392Ssklower register int i; 644*36392Ssklower 645*36392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 646*36392Ssklower 647*36392Ssklower sc = &iso_snpac[0]; 648*36392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 649*36392Ssklower if (((sc->sc_flags & SNPA_PERM) == 0) && (sc->sc_flags & SNPA_VALID)) { 650*36392Ssklower sc->sc_ht -= SNPAC_AGE; 651*36392Ssklower if (sc->sc_ht > 0) 652*36392Ssklower continue; 653*36392Ssklower else 654*36392Ssklower snpac_free(sc); 655*36392Ssklower } 656*36392Ssklower } 657*36392Ssklower } 658*36392Ssklower 659*36392Ssklower /* 660*36392Ssklower * FUNCTION: snpac_ownmulti 661*36392Ssklower * 662*36392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 663*36392Ssklower * of the same type as the system. 664*36392Ssklower * 665*36392Ssklower * RETURNS: true or false 666*36392Ssklower * 667*36392Ssklower * SIDE EFFECTS: 668*36392Ssklower * 669*36392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 670*36392Ssklower * as interm kludge until 671*36392Ssklower * real multicast addresses can be configured 672*36392Ssklower */ 673*36392Ssklower snpac_ownmulti(snpa, len) 674*36392Ssklower char *snpa; 675*36392Ssklower int len; 676*36392Ssklower { 677*36392Ssklower return (((iso_systype & SNPA_ES) && (!bcmp(snpa, all_es.sc_snpa, len))) 678*36392Ssklower || ((iso_systype & SNPA_IS) && (!bcmp(snpa, all_is.sc_snpa, len)))); 679*36392Ssklower } 680*36392Ssklower 681*36392Ssklower /* 682*36392Ssklower * FUNCTION: snpac_flushifp 683*36392Ssklower * 684*36392Ssklower * PURPOSE: Flush entries associated with specific ifp 685*36392Ssklower * 686*36392Ssklower * RETURNS: nothing 687*36392Ssklower * 688*36392Ssklower * SIDE EFFECTS: 689*36392Ssklower * 690*36392Ssklower * NOTES: 691*36392Ssklower */ 692*36392Ssklower snpac_flushifp(ifp) 693*36392Ssklower struct ifnet *ifp; 694*36392Ssklower { 695*36392Ssklower register struct snpa_cache *sc; 696*36392Ssklower register int i; 697*36392Ssklower 698*36392Ssklower sc = &iso_snpac[0]; 699*36392Ssklower for (i=0; i<SNPAC_SIZE; i++, sc++) { 700*36392Ssklower if ((sc->sc_ifp == ifp) && (sc->sc_flags & SNPA_VALID)) { 701*36392Ssklower snpac_free(sc); 702*36392Ssklower } 703*36392Ssklower } 704*36392Ssklower } 705*36392Ssklower 706*36392Ssklower /* 707*36392Ssklower * FUNCTION: snpac_rtrequest 708*36392Ssklower * 709*36392Ssklower * PURPOSE: Make a routing request 710*36392Ssklower * 711*36392Ssklower * RETURNS: nothing 712*36392Ssklower * 713*36392Ssklower * SIDE EFFECTS: 714*36392Ssklower * 715*36392Ssklower * NOTES: In the future, this should make a request of a user 716*36392Ssklower * level routing daemon. 717*36392Ssklower */ 718*36392Ssklower snpac_rtrequest(req, dst, gateway, flags) 719*36392Ssklower int req; 720*36392Ssklower struct iso_addr *dst; 721*36392Ssklower struct iso_addr *gateway; 722*36392Ssklower short flags; 723*36392Ssklower { 724*36392Ssklower struct rtentry rte; 725*36392Ssklower struct iso_addr *isoa; 726*36392Ssklower 727*36392Ssklower IFDEBUG(D_SNPA) 728*36392Ssklower printf("snpac_rtrequest: "); 729*36392Ssklower if (req == SIOCADDRT) 730*36392Ssklower printf("add"); 731*36392Ssklower else if (req == SIOCDELRT) 732*36392Ssklower printf("delete"); 733*36392Ssklower else 734*36392Ssklower printf("unknown command"); 735*36392Ssklower printf(" dst: %s\n", clnp_iso_addrp(dst)); 736*36392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 737*36392Ssklower ENDDEBUG 738*36392Ssklower 739*36392Ssklower bzero((caddr_t)&rte, sizeof(struct rtentry)); 740*36392Ssklower rte.rt_dst.sa_family = rte.rt_gateway.sa_family = AF_ISO; 741*36392Ssklower isoa = &((struct sockaddr_iso *)&rte.rt_dst)->siso_addr; 742*36392Ssklower *isoa = *dst; 743*36392Ssklower isoa = &((struct sockaddr_iso *)&rte.rt_gateway)->siso_addr; 744*36392Ssklower *isoa = *gateway; 745*36392Ssklower rte.rt_flags = RTF_UP|flags; 746*36392Ssklower 747*36392Ssklower rtrequest(req, &rte); 748*36392Ssklower } 749*36392Ssklower 750*36392Ssklower 751*36392Ssklower /* 752*36392Ssklower * FUNCTION: snpac_addrt 753*36392Ssklower * 754*36392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 755*36392Ssklower * 756*36392Ssklower * RETURNS: nothing 757*36392Ssklower * 758*36392Ssklower * SIDE EFFECTS: 759*36392Ssklower * 760*36392Ssklower * NOTES: If a cache entry exists for gateway, then 761*36392Ssklower * make a routing entry (host, gateway) and associate 762*36392Ssklower * with gateway. 763*36392Ssklower * 764*36392Ssklower * If a route already exists and is different, first delete 765*36392Ssklower * it. 766*36392Ssklower * 767*36392Ssklower * This could be made more efficient by checking 768*36392Ssklower * the existing route before adding a new one. 769*36392Ssklower */ 770*36392Ssklower snpac_addrt(host, gateway) 771*36392Ssklower struct iso_addr *host; 772*36392Ssklower struct iso_addr *gateway; 773*36392Ssklower { 774*36392Ssklower struct snpa_cache *sc; 775*36392Ssklower int s; 776*36392Ssklower 777*36392Ssklower s = splimp(); 778*36392Ssklower SNPAC_LOOK(sc, gateway); 779*36392Ssklower if (sc != NULL) { 780*36392Ssklower snpac_rtrequest(SIOCDELRT, &sc->sc_da, gateway, 781*36392Ssklower RTF_DYNAMIC|RTF_GATEWAY); 782*36392Ssklower snpac_rtrequest(SIOCADDRT, host, gateway, RTF_DYNAMIC|RTF_GATEWAY); 783*36392Ssklower bcopy(host, &sc->sc_da, sizeof(struct iso_addr)); 784*36392Ssklower } 785*36392Ssklower s = splx(s); 786*36392Ssklower } 787*36392Ssklower #endif ISO 788