136392Ssklower /*********************************************************** 236392Ssklower Copyright IBM Corporation 1987 336392Ssklower 436392Ssklower All Rights Reserved 536392Ssklower 636392Ssklower Permission to use, copy, modify, and distribute this software and its 736392Ssklower documentation for any purpose and without fee is hereby granted, 836392Ssklower provided that the above copyright notice appear in all copies and that 936392Ssklower both that copyright notice and this permission notice appear in 1036392Ssklower supporting documentation, and that the name of IBM not be 1136392Ssklower used in advertising or publicity pertaining to distribution of the 1236392Ssklower software without specific, written prior permission. 1336392Ssklower 1436392Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536392Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636392Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736392Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836392Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936392Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036392Ssklower SOFTWARE. 2136392Ssklower 2236392Ssklower ******************************************************************/ 2336392Ssklower 2436392Ssklower /* 2536392Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636392Ssklower */ 2736392Ssklower /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */ 2836392Ssklower /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */ 29*43334Ssklower /* @(#)iso_snpac.c 7.8 (Berkeley) 06/20/90 */ 3036392Ssklower 3136392Ssklower #ifndef lint 3236392Ssklower static char *rcsid = "$Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $"; 3336392Ssklower #endif lint 3436392Ssklower 3536392Ssklower #ifdef ISO 3636392Ssklower 3737469Ssklower #include "types.h" 3837469Ssklower #include "param.h" 3943071Ssklower #include "systm.h" 4037551Smckusick #include "user.h" 4137469Ssklower #include "mbuf.h" 4237469Ssklower #include "domain.h" 4337469Ssklower #include "protosw.h" 4437469Ssklower #include "socket.h" 4537469Ssklower #include "socketvar.h" 4637469Ssklower #include "errno.h" 4737469Ssklower #include "ioctl.h" 4837469Ssklower #include "kernel.h" 4936392Ssklower 5036392Ssklower #include "../net/if.h" 5143071Ssklower #include "../net/if_dl.h" 5236392Ssklower #include "../net/route.h" 5336392Ssklower 5437469Ssklower #include "iso.h" 5537469Ssklower #include "iso_var.h" 5637469Ssklower #include "iso_snpac.h" 5737469Ssklower #include "clnp.h" 5837469Ssklower #include "clnp_stat.h" 5938841Ssklower #include "esis.h" 6037469Ssklower #include "argo_debug.h" 6136392Ssklower 6236392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6336392Ssklower 6437469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 6537469Ssklower extern u_long iso_hashchar(); 6637469Ssklower static struct sockaddr_iso 6737469Ssklower dst = {sizeof(dst), AF_ISO}, 6837469Ssklower gte = {sizeof(dst), AF_ISO}, 6937469Ssklower src = {sizeof(dst), AF_ISO}, 7037469Ssklower msk = {sizeof(dst), AF_ISO}, 7137469Ssklower zmk = {1}; 7237469Ssklower #define zsi blank_siso 7337469Ssklower #define zero_isoa zsi.siso_addr 7437469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 7537469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 7637469Ssklower #define S(x) ((struct sockaddr *)&(x)) 7737469Ssklower 7843071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 7943071Ssklower static struct sockaddr_dl gte_dl; 8043071Ssklower #define zap_linkaddr(a, b, c, i) \ 8143071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8236392Ssklower 8336392Ssklower /* 8436392Ssklower * We only keep track of a single IS at a time. 8536392Ssklower */ 8643071Ssklower struct rtentry *known_is; 8736392Ssklower 8836392Ssklower /* 8936392Ssklower * Addresses taken from NBS agreements, December 1987. 9036392Ssklower * 9136392Ssklower * These addresses assume on-the-wire transmission of least significant 9236392Ssklower * bit first. This is the method used by 802.3. When these 9336392Ssklower * addresses are passed to the token ring driver, (802.5), they 9436392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 9536392Ssklower * 9636392Ssklower * Furthermore, according to IBM Austin, these addresses are not 9736392Ssklower * true token ring multicast addresses. More work is necessary 9836392Ssklower * to get multicast to work right on token ring. 9936392Ssklower * 10036392Ssklower * Currently, the token ring driver does not handle multicast, so 10136392Ssklower * these addresses are converted into the broadcast address in 10236392Ssklower * lan_output() That means that if these multicast addresses change 10336392Ssklower * the token ring driver must be altered. 10436392Ssklower */ 105*43334Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 106*43334Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 10736392Ssklower 10843071Ssklower union sockunion { 10943071Ssklower struct sockaddr_iso siso; 11043071Ssklower struct sockaddr_dl sdl; 11143071Ssklower struct sockaddr sa; 11243071Ssklower }; 11336392Ssklower 11436392Ssklower /* 11543071Ssklower * FUNCTION: llc_rtrequest 11643071Ssklower * 11743071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 11843071Ssklower * 11943071Ssklower * NOTES: This does a lot of obscure magic; 12043071Ssklower */ 12143071Ssklower llc_rtrequest(req, rt, sa) 12243071Ssklower int req; 12343071Ssklower register struct rtentry *rt; 12443071Ssklower struct sockaddr *sa; 12543071Ssklower { 12643071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 12743071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 12843071Ssklower struct rtentry *rt2; 12943071Ssklower struct ifnet *ifp = rt->rt_ifp; 13043071Ssklower int addrlen = ifp->if_addrlen; 131*43334Ssklower static struct rtentry *recursing = 0; 13243071Ssklower 133*43334Ssklower IFDEBUG (D_SNPA) 134*43334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 135*43334Ssklower ENDDEBUG 136*43334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 137*43334Ssklower if (recursing) { 138*43334Ssklower log("llc_rtrequest: gateway route points to same type %x %x\n", 139*43334Ssklower recursing, rt); 140*43334Ssklower } else switch (req) { 141*43334Ssklower case RTM_RESOLVE: 142*43334Ssklower case RTM_ADD: 143*43334Ssklower recursing = rt; 144*43334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 145*43334Ssklower recursing = 0; 146*43334Ssklower return; 147*43334Ssklower 148*43334Ssklower case RTM_DELETE: 149*43334Ssklower if (lc) 150*43334Ssklower RTFREE((struct rtentry *)lc); 151*43334Ssklower rt->rt_llinfo = 0; 15243071Ssklower } 153*43334Ssklower } else switch (req) { 15443071Ssklower case RTM_ADD: 155*43334Ssklower /* 156*43334Ssklower * Case 1: This route may come from a route to iface with mask 157*43334Ssklower * or from a default route. 158*43334Ssklower */ 15943071Ssklower if (rt->rt_flags & RTF_CLONING) { 160*43334Ssklower register struct ifaddr *ifa; 161*43334Ssklower register struct sockaddr *sa; 162*43334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 163*43334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 164*43334Ssklower if (sa->sa_len > gate->sa.sa_len) 165*43334Ssklower log("llc_rtrequest: cloning address too small\n"); 166*43334Ssklower else { 167*43334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 168*43334Ssklower gate->sdl.sdl_alen = 0; 169*43334Ssklower } 170*43334Ssklower return; 17143071Ssklower } 172*43334Ssklower if (ifa == 0) 173*43334Ssklower log("llc_rtrequest: can't find LL ifaddr for iface\n"); 174*43334Ssklower return; 17543071Ssklower } 176*43334Ssklower /* FALLTHROUGH */ 177*43334Ssklower case RTM_RESOLVE: 178*43334Ssklower /* 179*43334Ssklower * Case 2: This route may come from cloning, or a manual route 180*43334Ssklower * add with a LL address. 181*43334Ssklower */ 182*43334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 183*43334Ssklower log("llc_rtrequest: got non-link non-gateway route\n"); 184*43334Ssklower return; 185*43334Ssklower } 186*43334Ssklower if (lc != 0) 187*43334Ssklower log("llc_rtrequest: losing old rt_llinfo\n"); 188*43334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 189*43334Ssklower rt->rt_llinfo = (caddr_t)lc; 190*43334Ssklower if (lc == 0) { 191*43334Ssklower log("llc_rtrequest: malloc failed\n"); 192*43334Ssklower return; 193*43334Ssklower } 194*43334Ssklower Bzero(lc, sizeof(*lc)); 195*43334Ssklower lc->lc_rt = rt; 196*43334Ssklower rt->rt_flags |= RTF_LLINFO; 197*43334Ssklower insque(lc, &llinfo_llc); 198*43334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 199*43334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 200*43334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 201*43334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 202*43334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 203*43334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 20443071Ssklower break; 20543071Ssklower case RTM_DELETE: 206*43334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 207*43334Ssklower return; 208*43334Ssklower remque(lc); 209*43334Ssklower Free(lc); 210*43334Ssklower rt->rt_llinfo = 0; 211*43334Ssklower rt->rt_flags &= ~RTF_LLINFO; 21243071Ssklower break; 21343071Ssklower } 21443071Ssklower } 21543071Ssklower /* 21636392Ssklower * FUNCTION: iso_snparesolve 21736392Ssklower * 21836392Ssklower * PURPOSE: Resolve an iso address into snpa address 21936392Ssklower * 22036392Ssklower * RETURNS: 0 if addr is resolved 22136392Ssklower * errno if addr is unknown 22236392Ssklower * 22336392Ssklower * SIDE EFFECTS: 22436392Ssklower * 22543071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 22643071Ssklower * table, we know there is no snpa address known for this 22743071Ssklower * destination. If we know of a default IS, then the address 22843071Ssklower * of the IS is returned. If no IS is known, then return the 22943071Ssklower * multi-cast address for "all ES" for this interface. 23036392Ssklower * 23136392Ssklower * NB: the last case described above constitutes the 23236392Ssklower * query configuration function 9542, sec 6.5 23336392Ssklower * A mechanism is needed to prevent this function from 23436392Ssklower * being invoked if the system is an IS. 23536392Ssklower */ 23637469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 23743071Ssklower struct ifnet *ifp; /* outgoing interface */ 23843071Ssklower struct sockaddr_iso *dest; /* destination */ 23943071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 24043071Ssklower int *snpa_len; /* RESULT: length of snpa */ 24136392Ssklower { 24243071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 24343071Ssklower caddr_t found_snpa; 24443071Ssklower int addrlen; 24536392Ssklower 24636392Ssklower /* 24736392Ssklower * This hack allows us to send esis packets that have the destination snpa 24836392Ssklower * addresss embedded in the destination nsap address 24936392Ssklower */ 25043071Ssklower if (dest->siso_data[0] == AFI_SNA) { 25136392Ssklower /* 25236392Ssklower * This is a subnetwork address. Return it immediately 25336392Ssklower */ 25436392Ssklower IFDEBUG(D_SNPA) 25536392Ssklower printf("iso_snparesolve: return SN address\n"); 25636392Ssklower ENDDEBUG 25743071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 25843071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 25936392Ssklower /* 26043071Ssklower * If we are an IS, we can't do much with the packet; 26143071Ssklower * Check if we know about an IS. 26236392Ssklower */ 26343071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 26443071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 26543071Ssklower (sc->lc_flags & SNPA_VALID)) { 26643071Ssklower register struct sockaddr_dl *sdl = 26743071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 26843071Ssklower found_snpa = LLADDR(sdl); 26943071Ssklower addrlen = sdl->sdl_alen; 27043071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 27143071Ssklower /* 27243071Ssklower * no IS, no match. Return "all es" multicast address for this 27343071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 27443071Ssklower * 27543071Ssklower * Note: there is a potential problem here. If the destination 27643071Ssklower * is on the subnet and it does not respond with a ESH, but 27743071Ssklower * does send back a TP CC, a connection could be established 27843071Ssklower * where we always transmit the CLNP packet to "all es" 27936392Ssklower */ 28043071Ssklower addrlen = ifp->if_addrlen; 28143071Ssklower found_snpa = (caddr_t)all_es_snpa; 28243071Ssklower } else 28343071Ssklower return (ENETUNREACH); 28443071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 28536392Ssklower return (0); 28636392Ssklower } 28736392Ssklower 28836392Ssklower 28936392Ssklower /* 29036392Ssklower * FUNCTION: snpac_free 29136392Ssklower * 29236392Ssklower * PURPOSE: free an entry in the iso address map table 29336392Ssklower * 29436392Ssklower * RETURNS: nothing 29536392Ssklower * 29636392Ssklower * SIDE EFFECTS: 29736392Ssklower * 29836392Ssklower * NOTES: If there is a route entry associated with cache 29936392Ssklower * entry, then delete that as well 30036392Ssklower */ 30143071Ssklower snpac_free(lc) 30243071Ssklower register struct llinfo_llc *lc; /* entry to free */ 30336392Ssklower { 30443071Ssklower register struct rtentry *rt = lc->lc_rt; 30537469Ssklower register struct iso_addr *r; 30636392Ssklower 30743071Ssklower if (known_is == rt) 30843071Ssklower known_is = 0; 30943071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 31043071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 31137469Ssklower RTFREE(rt); 31237469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 31337469Ssklower rt->rt_flags, (struct rtentry **)0); 31437469Ssklower RTFREE(rt); 31536392Ssklower } 31636392Ssklower } 31736392Ssklower 31836392Ssklower /* 31936392Ssklower * FUNCTION: snpac_add 32036392Ssklower * 32136392Ssklower * PURPOSE: Add an entry to the snpa cache 32236392Ssklower * 32336392Ssklower * RETURNS: 32436392Ssklower * 32536392Ssklower * SIDE EFFECTS: 32636392Ssklower * 32736392Ssklower * NOTES: If entry already exists, then update holding time. 32836392Ssklower */ 329*43334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 33036392Ssklower struct ifnet *ifp; /* interface info is related to */ 33136392Ssklower struct iso_addr *nsap; /* nsap to add */ 33236392Ssklower caddr_t snpa; /* translation */ 33336392Ssklower char type; /* SNPA_IS or SNPA_ES */ 33437469Ssklower u_short ht; /* holding time (in seconds) */ 335*43334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 33636392Ssklower { 33743071Ssklower register struct llinfo_llc *lc; 338*43334Ssklower register struct rtentry *rt; 339*43334Ssklower struct rtentry *mrt = 0; 34043071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 34143071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 34243071Ssklower int new_entry = 0, index = ifp->if_index; 34336392Ssklower 344*43334Ssklower IFDEBUG(D_SNPA) 345*43334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 346*43334Ssklower ifp, nsap, snpa, type, ht, nsellength); 347*43334Ssklower ENDDEBUG 34843071Ssklower zap_isoaddr(dst, nsap); 34943071Ssklower rt = rtalloc1(S(dst), 0); 350*43334Ssklower IFDEBUG(D_SNPA) 351*43334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 352*43334Ssklower ENDDEBUG 35343071Ssklower if (rt == 0) { 354*43334Ssklower struct sockaddr *netmask; 355*43334Ssklower int flags; 356*43334Ssklower add: 357*43334Ssklower if (nsellength) { 358*43334Ssklower netmask = S(msk); flags = RTF_UP; 359*43334Ssklower snpac_fixdstandmask(nsellength); 360*43334Ssklower } else { 361*43334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 362*43334Ssklower } 36343071Ssklower new_entry = 1; 36443071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 365*43334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 366*43334Ssklower mrt == 0) 36743071Ssklower return (0); 368*43334Ssklower rt = mrt; 369*43334Ssklower rt->rt_refcnt--; 37043071Ssklower } else { 37143071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 372*43334Ssklower rt->rt_refcnt--; 373*43334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 374*43334Ssklower goto add; 375*43334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 376*43334Ssklower if (rt->rt_refcnt == 0) { 377*43334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 378*43334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 379*43334Ssklower rt = 0; 380*43334Ssklower goto add; 381*43334Ssklower } else { 382*43334Ssklower static struct iso_addr nsap2; register char *cp; 383*43334Ssklower nsap2 = *nsap; 384*43334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 385*43334Ssklower while (cp < (char *)(1 + &nsap2)) 386*43334Ssklower *cp++ = 0; 387*43334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 388*43334Ssklower } 389*43334Ssklower } 39043071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 39143071Ssklower int old_sdl_len = sdl->sdl_len; 392*43334Ssklower if (old_sdl_len < sizeof(*sdl)) { 393*43334Ssklower log("snpac_add: cant make room for lladdr\n"); 39443071Ssklower return (0); 395*43334Ssklower } 39643071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 39743071Ssklower sdl->sdl_len = old_sdl_len; 39843071Ssklower new_entry = 1; 39943071Ssklower } 40036392Ssklower } 401*43334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 402*43334Ssklower panic("snpac_rtrequest"); 403*43334Ssklower rt->rt_idle = ht; 40443071Ssklower lc->lc_flags = SNPA_VALID | type; 40536392Ssklower if (type & SNPA_IS) 40643071Ssklower snpac_logdefis(rt); 407*43334Ssklower return (new_entry); 40836392Ssklower } 40936392Ssklower 410*43334Ssklower static snpac_fixdstandmask(nsellength) 411*43334Ssklower { 412*43334Ssklower register char *cp = msk.siso_data, *cplim; 413*43334Ssklower 414*43334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 415*43334Ssklower msk.siso_len = cplim - (char *)&msk; 416*43334Ssklower msk.siso_nlen = 0; 417*43334Ssklower while (cp < cplim) 418*43334Ssklower *cp++ = -1; 419*43334Ssklower while (cp < (char *)msk.siso_pad) 420*43334Ssklower *cp++ = 0; 421*43334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 422*43334Ssklower *cp++ = 0; 423*43334Ssklower } 424*43334Ssklower 42536392Ssklower /* 42636392Ssklower * FUNCTION: snpac_ioctl 42736392Ssklower * 42836392Ssklower * PURPOSE: Set/Get the system type and esis parameters 42936392Ssklower * 43036392Ssklower * RETURNS: 0 on success, or unix error code 43136392Ssklower * 43236392Ssklower * SIDE EFFECTS: 43336392Ssklower * 43436392Ssklower * NOTES: 43536392Ssklower */ 43643071Ssklower snpac_ioctl (cmd, data) 43736392Ssklower int cmd; /* ioctl to process */ 43836392Ssklower caddr_t data; /* data for the cmd */ 43936392Ssklower { 44036392Ssklower register struct systype_req *rq = (struct systype_req *)data; 44136392Ssklower extern short esis_holding_time, esis_config_time; 44236392Ssklower 443*43334Ssklower IFDEBUG(D_IOCTL) 44436392Ssklower if (cmd == SIOCSSTYPE) 44543071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 44636392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 44736392Ssklower else 44843071Ssklower printf("snpac_ioctl: cmd get\n"); 44936392Ssklower ENDDEBUG 45036392Ssklower 45136392Ssklower if (cmd == SIOCSSTYPE) { 45237551Smckusick if (suser(u.u_cred, &u.u_acflag)) 45336392Ssklower return(EACCES); 45436392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 45536392Ssklower return(EINVAL); 45636392Ssklower if (rq->sr_type & SNPA_ES) { 45736392Ssklower iso_systype = SNPA_ES; 45836392Ssklower } else if (rq->sr_type & SNPA_IS) { 45936392Ssklower iso_systype = SNPA_IS; 46036392Ssklower } else { 46136392Ssklower return(EINVAL); 46236392Ssklower } 46336392Ssklower esis_holding_time = rq->sr_holdt; 46436392Ssklower esis_config_time = rq->sr_configt; 46536392Ssklower } else if (cmd == SIOCGSTYPE) { 46636392Ssklower rq->sr_type = iso_systype; 46736392Ssklower rq->sr_holdt = esis_holding_time; 46836392Ssklower rq->sr_configt = esis_config_time; 46936392Ssklower } else { 47043071Ssklower return (EINVAL); 47136392Ssklower } 47243071Ssklower return (0); 47336392Ssklower } 47436392Ssklower 47536392Ssklower /* 47636392Ssklower * FUNCTION: snpac_logdefis 47736392Ssklower * 47836392Ssklower * PURPOSE: Mark the IS passed as the default IS 47936392Ssklower * 48036392Ssklower * RETURNS: nothing 48136392Ssklower * 48236392Ssklower * SIDE EFFECTS: 48336392Ssklower * 48436392Ssklower * NOTES: 48536392Ssklower */ 48636392Ssklower snpac_logdefis(sc) 48743071Ssklower register struct rtentry *sc; 48836392Ssklower { 48937469Ssklower register struct iso_addr *r; 49043071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 49137469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 49243071Ssklower 49343071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 49437469Ssklower if (known_is == 0) 49537469Ssklower known_is = sc; 49637469Ssklower if (known_is != sc) { 49743071Ssklower rtfree(known_is); 49837469Ssklower known_is = sc; 49936392Ssklower } 50037469Ssklower if (rt == 0) { 50143071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 50243071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 50337469Ssklower return; 50437469Ssklower } 505*43334Ssklower rt->rt_refcnt--; 50637469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 50743071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 50837469Ssklower } 50936392Ssklower } 51036392Ssklower 51136392Ssklower /* 51236392Ssklower * FUNCTION: snpac_age 51336392Ssklower * 51436392Ssklower * PURPOSE: Time out snpac entries 51536392Ssklower * 51636392Ssklower * RETURNS: 51736392Ssklower * 51836392Ssklower * SIDE EFFECTS: 51936392Ssklower * 52036392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 52136392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 52236392Ssklower * if the entry is added a moment before snpac_age is 52336392Ssklower * called, the entry will immediately have SNPAC_AGE 52436392Ssklower * seconds taken off the holding time, even though 52536392Ssklower * it has only been held a brief moment. 52636392Ssklower * 52736392Ssklower * The proper way to do this is set an expiry timeval 52836392Ssklower * equal to current time + holding time. Then snpac_age 52936392Ssklower * would time out entries where expiry date is older 53036392Ssklower * than the current time. 53136392Ssklower */ 53236392Ssklower snpac_age() 53336392Ssklower { 53443071Ssklower register struct llinfo_llc *lc; 53536392Ssklower 53636392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 53736392Ssklower 53843071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 53943071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 540*43334Ssklower lc->lc_rt->rt_idle -= SNPAC_AGE; 541*43334Ssklower if (lc->lc_rt->rt_idle > 0) 54236392Ssklower continue; 54336392Ssklower else 54443071Ssklower snpac_free(lc); 54536392Ssklower } 54636392Ssklower } 54736392Ssklower } 54836392Ssklower 54936392Ssklower /* 55036392Ssklower * FUNCTION: snpac_ownmulti 55136392Ssklower * 55236392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 55336392Ssklower * of the same type as the system. 55436392Ssklower * 55536392Ssklower * RETURNS: true or false 55636392Ssklower * 55736392Ssklower * SIDE EFFECTS: 55836392Ssklower * 55936392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 56036392Ssklower * as interm kludge until 56136392Ssklower * real multicast addresses can be configured 56236392Ssklower */ 56336392Ssklower snpac_ownmulti(snpa, len) 56443071Ssklower caddr_t snpa; 56543071Ssklower u_int len; 56636392Ssklower { 56737469Ssklower return (((iso_systype & SNPA_ES) && 56843071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 56937469Ssklower ((iso_systype & SNPA_IS) && 57043071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 57136392Ssklower } 57236392Ssklower 57336392Ssklower /* 57436392Ssklower * FUNCTION: snpac_flushifp 57536392Ssklower * 57636392Ssklower * PURPOSE: Flush entries associated with specific ifp 57736392Ssklower * 57836392Ssklower * RETURNS: nothing 57936392Ssklower * 58036392Ssklower * SIDE EFFECTS: 58136392Ssklower * 58236392Ssklower * NOTES: 58336392Ssklower */ 58436392Ssklower snpac_flushifp(ifp) 58536392Ssklower struct ifnet *ifp; 58636392Ssklower { 58743071Ssklower register struct llinfo_llc *lc; 58836392Ssklower 58943071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 59043071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 59143071Ssklower snpac_free(lc); 59236392Ssklower } 59336392Ssklower } 59436392Ssklower 59536392Ssklower /* 59636392Ssklower * FUNCTION: snpac_rtrequest 59736392Ssklower * 59836392Ssklower * PURPOSE: Make a routing request 59936392Ssklower * 60036392Ssklower * RETURNS: nothing 60136392Ssklower * 60236392Ssklower * SIDE EFFECTS: 60336392Ssklower * 60436392Ssklower * NOTES: In the future, this should make a request of a user 60536392Ssklower * level routing daemon. 60636392Ssklower */ 60737469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 60836392Ssklower int req; 60937469Ssklower struct iso_addr *host; 61036392Ssklower struct iso_addr *gateway; 61137469Ssklower struct iso_addr *netmask; 61236392Ssklower short flags; 61337469Ssklower struct rtentry **ret_nrt; 61436392Ssklower { 61537469Ssklower register struct iso_addr *r; 61636392Ssklower 61736392Ssklower IFDEBUG(D_SNPA) 61836392Ssklower printf("snpac_rtrequest: "); 61937469Ssklower if (req == RTM_ADD) 62036392Ssklower printf("add"); 62137469Ssklower else if (req == RTM_DELETE) 62236392Ssklower printf("delete"); 62336392Ssklower else 62436392Ssklower printf("unknown command"); 62537469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 62636392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 62736392Ssklower ENDDEBUG 62836392Ssklower 62936392Ssklower 63037469Ssklower zap_isoaddr(dst, host); 63137469Ssklower zap_isoaddr(gte, gateway); 632*43334Ssklower if (netmask) { 633*43334Ssklower zap_isoaddr(msk, netmask); 634*43334Ssklower msk.siso_nlen = 0; 635*43334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 636*43334Ssklower } 63737469Ssklower 63837469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 63937469Ssklower flags, ret_nrt); 64036392Ssklower } 64136392Ssklower 64236392Ssklower /* 64336392Ssklower * FUNCTION: snpac_addrt 64436392Ssklower * 64536392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 64636392Ssklower * 64736392Ssklower * RETURNS: nothing 64836392Ssklower * 64936392Ssklower * SIDE EFFECTS: 65036392Ssklower * 65136392Ssklower * NOTES: If a cache entry exists for gateway, then 65236392Ssklower * make a routing entry (host, gateway) and associate 65336392Ssklower * with gateway. 65436392Ssklower * 65536392Ssklower * If a route already exists and is different, first delete 65636392Ssklower * it. 65736392Ssklower * 65836392Ssklower * This could be made more efficient by checking 65936392Ssklower * the existing route before adding a new one. 66036392Ssklower */ 66139950Ssklower snpac_addrt(ifp, host, gateway, netmask) 66239950Ssklower struct ifnet *ifp; 66339950Ssklower struct iso_addr *host, *gateway, *netmask; 66436392Ssklower { 66537469Ssklower register struct iso_addr *r; 66636392Ssklower 66743071Ssklower zap_isoaddr(dst, host); 66843071Ssklower zap_isoaddr(gte, gateway); 66943071Ssklower if (netmask) { 670*43334Ssklower zap_isoaddr(msk, netmask); 671*43334Ssklower msk.siso_nlen = 0; 672*43334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 67343071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 67443071Ssklower } else 67543071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 67643071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 67736392Ssklower } 67836392Ssklower #endif ISO 679