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*43423Ssklower /* @(#)iso_snpac.c 7.9 (Berkeley) 06/22/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 */ 63*43423Ssklower extern short esis_holding_time, esis_config_time, esis_esconfig_time; 64*43423Ssklower extern int esis_config(); 6536392Ssklower 6637469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 6737469Ssklower extern u_long iso_hashchar(); 6837469Ssklower static struct sockaddr_iso 6937469Ssklower dst = {sizeof(dst), AF_ISO}, 7037469Ssklower gte = {sizeof(dst), AF_ISO}, 7137469Ssklower src = {sizeof(dst), AF_ISO}, 7237469Ssklower msk = {sizeof(dst), AF_ISO}, 7337469Ssklower zmk = {1}; 7437469Ssklower #define zsi blank_siso 7537469Ssklower #define zero_isoa zsi.siso_addr 7637469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 7737469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 7837469Ssklower #define S(x) ((struct sockaddr *)&(x)) 7937469Ssklower 8043071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 8143071Ssklower static struct sockaddr_dl gte_dl; 8243071Ssklower #define zap_linkaddr(a, b, c, i) \ 8343071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8436392Ssklower 8536392Ssklower /* 8636392Ssklower * We only keep track of a single IS at a time. 8736392Ssklower */ 8843071Ssklower struct rtentry *known_is; 8936392Ssklower 9036392Ssklower /* 9136392Ssklower * Addresses taken from NBS agreements, December 1987. 9236392Ssklower * 9336392Ssklower * These addresses assume on-the-wire transmission of least significant 9436392Ssklower * bit first. This is the method used by 802.3. When these 9536392Ssklower * addresses are passed to the token ring driver, (802.5), they 9636392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 9736392Ssklower * 9836392Ssklower * Furthermore, according to IBM Austin, these addresses are not 9936392Ssklower * true token ring multicast addresses. More work is necessary 10036392Ssklower * to get multicast to work right on token ring. 10136392Ssklower * 10236392Ssklower * Currently, the token ring driver does not handle multicast, so 10336392Ssklower * these addresses are converted into the broadcast address in 10436392Ssklower * lan_output() That means that if these multicast addresses change 10536392Ssklower * the token ring driver must be altered. 10636392Ssklower */ 10743334Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 10843334Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 10936392Ssklower 11043071Ssklower union sockunion { 11143071Ssklower struct sockaddr_iso siso; 11243071Ssklower struct sockaddr_dl sdl; 11343071Ssklower struct sockaddr sa; 11443071Ssklower }; 11536392Ssklower 11636392Ssklower /* 11743071Ssklower * FUNCTION: llc_rtrequest 11843071Ssklower * 11943071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 12043071Ssklower * 12143071Ssklower * NOTES: This does a lot of obscure magic; 12243071Ssklower */ 12343071Ssklower llc_rtrequest(req, rt, sa) 12443071Ssklower int req; 12543071Ssklower register struct rtentry *rt; 12643071Ssklower struct sockaddr *sa; 12743071Ssklower { 12843071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 12943071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 13043071Ssklower struct rtentry *rt2; 13143071Ssklower struct ifnet *ifp = rt->rt_ifp; 13243071Ssklower int addrlen = ifp->if_addrlen; 13343334Ssklower static struct rtentry *recursing = 0; 13443071Ssklower 13543334Ssklower IFDEBUG (D_SNPA) 13643334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 13743334Ssklower ENDDEBUG 13843334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 13943334Ssklower if (recursing) { 14043334Ssklower log("llc_rtrequest: gateway route points to same type %x %x\n", 14143334Ssklower recursing, rt); 14243334Ssklower } else switch (req) { 14343334Ssklower case RTM_RESOLVE: 14443334Ssklower case RTM_ADD: 14543334Ssklower recursing = rt; 14643334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 14743334Ssklower recursing = 0; 14843334Ssklower return; 14943334Ssklower 15043334Ssklower case RTM_DELETE: 15143334Ssklower if (lc) 15243334Ssklower RTFREE((struct rtentry *)lc); 15343334Ssklower rt->rt_llinfo = 0; 15443071Ssklower } 15543334Ssklower } else switch (req) { 15643071Ssklower case RTM_ADD: 15743334Ssklower /* 15843334Ssklower * Case 1: This route may come from a route to iface with mask 15943334Ssklower * or from a default route. 16043334Ssklower */ 16143071Ssklower if (rt->rt_flags & RTF_CLONING) { 16243334Ssklower register struct ifaddr *ifa; 16343334Ssklower register struct sockaddr *sa; 16443334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 16543334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 16643334Ssklower if (sa->sa_len > gate->sa.sa_len) 16743334Ssklower log("llc_rtrequest: cloning address too small\n"); 16843334Ssklower else { 16943334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 17043334Ssklower gate->sdl.sdl_alen = 0; 17143334Ssklower } 17243334Ssklower return; 17343071Ssklower } 17443334Ssklower if (ifa == 0) 17543334Ssklower log("llc_rtrequest: can't find LL ifaddr for iface\n"); 17643334Ssklower return; 17743071Ssklower } 17843334Ssklower /* FALLTHROUGH */ 17943334Ssklower case RTM_RESOLVE: 18043334Ssklower /* 18143334Ssklower * Case 2: This route may come from cloning, or a manual route 18243334Ssklower * add with a LL address. 18343334Ssklower */ 18443334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 18543334Ssklower log("llc_rtrequest: got non-link non-gateway route\n"); 18643334Ssklower return; 18743334Ssklower } 18843334Ssklower if (lc != 0) 18943334Ssklower log("llc_rtrequest: losing old rt_llinfo\n"); 19043334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 19143334Ssklower rt->rt_llinfo = (caddr_t)lc; 19243334Ssklower if (lc == 0) { 19343334Ssklower log("llc_rtrequest: malloc failed\n"); 19443334Ssklower return; 19543334Ssklower } 19643334Ssklower Bzero(lc, sizeof(*lc)); 19743334Ssklower lc->lc_rt = rt; 19843334Ssklower rt->rt_flags |= RTF_LLINFO; 19943334Ssklower insque(lc, &llinfo_llc); 20043334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 20143334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 20243334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 20343334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 20443334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 20543334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 20643071Ssklower break; 20743071Ssklower case RTM_DELETE: 20843334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 20943334Ssklower return; 21043334Ssklower remque(lc); 21143334Ssklower Free(lc); 21243334Ssklower rt->rt_llinfo = 0; 21343334Ssklower rt->rt_flags &= ~RTF_LLINFO; 21443071Ssklower break; 21543071Ssklower } 21643071Ssklower } 21743071Ssklower /* 21836392Ssklower * FUNCTION: iso_snparesolve 21936392Ssklower * 22036392Ssklower * PURPOSE: Resolve an iso address into snpa address 22136392Ssklower * 22236392Ssklower * RETURNS: 0 if addr is resolved 22336392Ssklower * errno if addr is unknown 22436392Ssklower * 22536392Ssklower * SIDE EFFECTS: 22636392Ssklower * 22743071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 22843071Ssklower * table, we know there is no snpa address known for this 22943071Ssklower * destination. If we know of a default IS, then the address 23043071Ssklower * of the IS is returned. If no IS is known, then return the 23143071Ssklower * multi-cast address for "all ES" for this interface. 23236392Ssklower * 23336392Ssklower * NB: the last case described above constitutes the 23436392Ssklower * query configuration function 9542, sec 6.5 23536392Ssklower * A mechanism is needed to prevent this function from 23636392Ssklower * being invoked if the system is an IS. 23736392Ssklower */ 23837469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 23943071Ssklower struct ifnet *ifp; /* outgoing interface */ 24043071Ssklower struct sockaddr_iso *dest; /* destination */ 24143071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 24243071Ssklower int *snpa_len; /* RESULT: length of snpa */ 24336392Ssklower { 24443071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 24543071Ssklower caddr_t found_snpa; 24643071Ssklower int addrlen; 24736392Ssklower 24836392Ssklower /* 24936392Ssklower * This hack allows us to send esis packets that have the destination snpa 25036392Ssklower * addresss embedded in the destination nsap address 25136392Ssklower */ 25243071Ssklower if (dest->siso_data[0] == AFI_SNA) { 25336392Ssklower /* 25436392Ssklower * This is a subnetwork address. Return it immediately 25536392Ssklower */ 25636392Ssklower IFDEBUG(D_SNPA) 25736392Ssklower printf("iso_snparesolve: return SN address\n"); 25836392Ssklower ENDDEBUG 25943071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 26043071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 26136392Ssklower /* 26243071Ssklower * If we are an IS, we can't do much with the packet; 26343071Ssklower * Check if we know about an IS. 26436392Ssklower */ 26543071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 26643071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 26743071Ssklower (sc->lc_flags & SNPA_VALID)) { 26843071Ssklower register struct sockaddr_dl *sdl = 26943071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 27043071Ssklower found_snpa = LLADDR(sdl); 27143071Ssklower addrlen = sdl->sdl_alen; 27243071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 27343071Ssklower /* 27443071Ssklower * no IS, no match. Return "all es" multicast address for this 27543071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 27643071Ssklower * 27743071Ssklower * Note: there is a potential problem here. If the destination 27843071Ssklower * is on the subnet and it does not respond with a ESH, but 27943071Ssklower * does send back a TP CC, a connection could be established 28043071Ssklower * where we always transmit the CLNP packet to "all es" 28136392Ssklower */ 28243071Ssklower addrlen = ifp->if_addrlen; 28343071Ssklower found_snpa = (caddr_t)all_es_snpa; 28443071Ssklower } else 28543071Ssklower return (ENETUNREACH); 28643071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 28736392Ssklower return (0); 28836392Ssklower } 28936392Ssklower 29036392Ssklower 29136392Ssklower /* 29236392Ssklower * FUNCTION: snpac_free 29336392Ssklower * 29436392Ssklower * PURPOSE: free an entry in the iso address map table 29536392Ssklower * 29636392Ssklower * RETURNS: nothing 29736392Ssklower * 29836392Ssklower * SIDE EFFECTS: 29936392Ssklower * 30036392Ssklower * NOTES: If there is a route entry associated with cache 30136392Ssklower * entry, then delete that as well 30236392Ssklower */ 30343071Ssklower snpac_free(lc) 30443071Ssklower register struct llinfo_llc *lc; /* entry to free */ 30536392Ssklower { 30643071Ssklower register struct rtentry *rt = lc->lc_rt; 30737469Ssklower register struct iso_addr *r; 30836392Ssklower 30943071Ssklower if (known_is == rt) 31043071Ssklower known_is = 0; 31143071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 31243071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 31337469Ssklower RTFREE(rt); 31437469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 31537469Ssklower rt->rt_flags, (struct rtentry **)0); 31637469Ssklower RTFREE(rt); 31736392Ssklower } 31836392Ssklower } 31936392Ssklower 32036392Ssklower /* 32136392Ssklower * FUNCTION: snpac_add 32236392Ssklower * 32336392Ssklower * PURPOSE: Add an entry to the snpa cache 32436392Ssklower * 32536392Ssklower * RETURNS: 32636392Ssklower * 32736392Ssklower * SIDE EFFECTS: 32836392Ssklower * 32936392Ssklower * NOTES: If entry already exists, then update holding time. 33036392Ssklower */ 33143334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 33236392Ssklower struct ifnet *ifp; /* interface info is related to */ 33336392Ssklower struct iso_addr *nsap; /* nsap to add */ 33436392Ssklower caddr_t snpa; /* translation */ 33536392Ssklower char type; /* SNPA_IS or SNPA_ES */ 33637469Ssklower u_short ht; /* holding time (in seconds) */ 33743334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 33836392Ssklower { 33943071Ssklower register struct llinfo_llc *lc; 34043334Ssklower register struct rtentry *rt; 34143334Ssklower struct rtentry *mrt = 0; 34243071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 34343071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 34443071Ssklower int new_entry = 0, index = ifp->if_index; 34536392Ssklower 34643334Ssklower IFDEBUG(D_SNPA) 34743334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 34843334Ssklower ifp, nsap, snpa, type, ht, nsellength); 34943334Ssklower ENDDEBUG 35043071Ssklower zap_isoaddr(dst, nsap); 35143071Ssklower rt = rtalloc1(S(dst), 0); 35243334Ssklower IFDEBUG(D_SNPA) 35343334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 35443334Ssklower ENDDEBUG 35543071Ssklower if (rt == 0) { 35643334Ssklower struct sockaddr *netmask; 35743334Ssklower int flags; 35843334Ssklower add: 35943334Ssklower if (nsellength) { 36043334Ssklower netmask = S(msk); flags = RTF_UP; 36143334Ssklower snpac_fixdstandmask(nsellength); 36243334Ssklower } else { 36343334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 36443334Ssklower } 36543071Ssklower new_entry = 1; 36643071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 36743334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 36843334Ssklower mrt == 0) 36943071Ssklower return (0); 37043334Ssklower rt = mrt; 37143334Ssklower rt->rt_refcnt--; 37243071Ssklower } else { 37343071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 37443334Ssklower rt->rt_refcnt--; 37543334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 37643334Ssklower goto add; 37743334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 37843334Ssklower if (rt->rt_refcnt == 0) { 37943334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 38043334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 38143334Ssklower rt = 0; 38243334Ssklower goto add; 38343334Ssklower } else { 38443334Ssklower static struct iso_addr nsap2; register char *cp; 38543334Ssklower nsap2 = *nsap; 38643334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 38743334Ssklower while (cp < (char *)(1 + &nsap2)) 38843334Ssklower *cp++ = 0; 38943334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 39043334Ssklower } 39143334Ssklower } 39243071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 39343071Ssklower int old_sdl_len = sdl->sdl_len; 39443334Ssklower if (old_sdl_len < sizeof(*sdl)) { 39543334Ssklower log("snpac_add: cant make room for lladdr\n"); 39643071Ssklower return (0); 39743334Ssklower } 39843071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 39943071Ssklower sdl->sdl_len = old_sdl_len; 40043071Ssklower new_entry = 1; 40143071Ssklower } 40236392Ssklower } 40343334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 40443334Ssklower panic("snpac_rtrequest"); 40543334Ssklower rt->rt_idle = ht; 40643071Ssklower lc->lc_flags = SNPA_VALID | type; 40736392Ssklower if (type & SNPA_IS) 40843071Ssklower snpac_logdefis(rt); 40943334Ssklower return (new_entry); 41036392Ssklower } 41136392Ssklower 41243334Ssklower static snpac_fixdstandmask(nsellength) 41343334Ssklower { 41443334Ssklower register char *cp = msk.siso_data, *cplim; 41543334Ssklower 41643334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 41743334Ssklower msk.siso_len = cplim - (char *)&msk; 41843334Ssklower msk.siso_nlen = 0; 41943334Ssklower while (cp < cplim) 42043334Ssklower *cp++ = -1; 42143334Ssklower while (cp < (char *)msk.siso_pad) 42243334Ssklower *cp++ = 0; 42343334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 42443334Ssklower *cp++ = 0; 42543334Ssklower } 42643334Ssklower 42736392Ssklower /* 42836392Ssklower * FUNCTION: snpac_ioctl 42936392Ssklower * 43036392Ssklower * PURPOSE: Set/Get the system type and esis parameters 43136392Ssklower * 43236392Ssklower * RETURNS: 0 on success, or unix error code 43336392Ssklower * 43436392Ssklower * SIDE EFFECTS: 43536392Ssklower * 43636392Ssklower * NOTES: 43736392Ssklower */ 43843071Ssklower snpac_ioctl (cmd, data) 43936392Ssklower int cmd; /* ioctl to process */ 44036392Ssklower caddr_t data; /* data for the cmd */ 44136392Ssklower { 44236392Ssklower register struct systype_req *rq = (struct systype_req *)data; 44336392Ssklower 44443334Ssklower IFDEBUG(D_IOCTL) 44536392Ssklower if (cmd == SIOCSSTYPE) 44643071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 44736392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 44836392Ssklower else 44943071Ssklower printf("snpac_ioctl: cmd get\n"); 45036392Ssklower ENDDEBUG 45136392Ssklower 45236392Ssklower if (cmd == SIOCSSTYPE) { 45337551Smckusick if (suser(u.u_cred, &u.u_acflag)) 45436392Ssklower return(EACCES); 45536392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 45636392Ssklower return(EINVAL); 45736392Ssklower if (rq->sr_type & SNPA_ES) { 45836392Ssklower iso_systype = SNPA_ES; 45936392Ssklower } else if (rq->sr_type & SNPA_IS) { 46036392Ssklower iso_systype = SNPA_IS; 46136392Ssklower } else { 46236392Ssklower return(EINVAL); 46336392Ssklower } 46436392Ssklower esis_holding_time = rq->sr_holdt; 46536392Ssklower esis_config_time = rq->sr_configt; 466*43423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 467*43423Ssklower untimeout(esis_config, (caddr_t)0); 468*43423Ssklower esis_esconfig_time = rq->sr_esconfigt; 469*43423Ssklower esis_config(); 470*43423Ssklower } 47136392Ssklower } else if (cmd == SIOCGSTYPE) { 47236392Ssklower rq->sr_type = iso_systype; 47336392Ssklower rq->sr_holdt = esis_holding_time; 47436392Ssklower rq->sr_configt = esis_config_time; 475*43423Ssklower rq->sr_esconfigt = esis_esconfig_time; 47636392Ssklower } else { 47743071Ssklower return (EINVAL); 47836392Ssklower } 47943071Ssklower return (0); 48036392Ssklower } 48136392Ssklower 48236392Ssklower /* 48336392Ssklower * FUNCTION: snpac_logdefis 48436392Ssklower * 48536392Ssklower * PURPOSE: Mark the IS passed as the default IS 48636392Ssklower * 48736392Ssklower * RETURNS: nothing 48836392Ssklower * 48936392Ssklower * SIDE EFFECTS: 49036392Ssklower * 49136392Ssklower * NOTES: 49236392Ssklower */ 49336392Ssklower snpac_logdefis(sc) 49443071Ssklower register struct rtentry *sc; 49536392Ssklower { 49637469Ssklower register struct iso_addr *r; 49743071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 49837469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 49943071Ssklower 50043071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 50137469Ssklower if (known_is == 0) 50237469Ssklower known_is = sc; 50337469Ssklower if (known_is != sc) { 50443071Ssklower rtfree(known_is); 50537469Ssklower known_is = sc; 50636392Ssklower } 50737469Ssklower if (rt == 0) { 50843071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 50943071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 51037469Ssklower return; 51137469Ssklower } 51243334Ssklower rt->rt_refcnt--; 51337469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 51443071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 51537469Ssklower } 51636392Ssklower } 51736392Ssklower 51836392Ssklower /* 51936392Ssklower * FUNCTION: snpac_age 52036392Ssklower * 52136392Ssklower * PURPOSE: Time out snpac entries 52236392Ssklower * 52336392Ssklower * RETURNS: 52436392Ssklower * 52536392Ssklower * SIDE EFFECTS: 52636392Ssklower * 52736392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 52836392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 52936392Ssklower * if the entry is added a moment before snpac_age is 53036392Ssklower * called, the entry will immediately have SNPAC_AGE 53136392Ssklower * seconds taken off the holding time, even though 53236392Ssklower * it has only been held a brief moment. 53336392Ssklower * 53436392Ssklower * The proper way to do this is set an expiry timeval 53536392Ssklower * equal to current time + holding time. Then snpac_age 53636392Ssklower * would time out entries where expiry date is older 53736392Ssklower * than the current time. 53836392Ssklower */ 53936392Ssklower snpac_age() 54036392Ssklower { 54143071Ssklower register struct llinfo_llc *lc; 54236392Ssklower 54336392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 54436392Ssklower 54543071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 54643071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 54743334Ssklower lc->lc_rt->rt_idle -= SNPAC_AGE; 54843334Ssklower if (lc->lc_rt->rt_idle > 0) 54936392Ssklower continue; 55036392Ssklower else 55143071Ssklower snpac_free(lc); 55236392Ssklower } 55336392Ssklower } 55436392Ssklower } 55536392Ssklower 55636392Ssklower /* 55736392Ssklower * FUNCTION: snpac_ownmulti 55836392Ssklower * 55936392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 56036392Ssklower * of the same type as the system. 56136392Ssklower * 56236392Ssklower * RETURNS: true or false 56336392Ssklower * 56436392Ssklower * SIDE EFFECTS: 56536392Ssklower * 56636392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 56736392Ssklower * as interm kludge until 56836392Ssklower * real multicast addresses can be configured 56936392Ssklower */ 57036392Ssklower snpac_ownmulti(snpa, len) 57143071Ssklower caddr_t snpa; 57243071Ssklower u_int len; 57336392Ssklower { 57437469Ssklower return (((iso_systype & SNPA_ES) && 57543071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 57637469Ssklower ((iso_systype & SNPA_IS) && 57743071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 57836392Ssklower } 57936392Ssklower 58036392Ssklower /* 58136392Ssklower * FUNCTION: snpac_flushifp 58236392Ssklower * 58336392Ssklower * PURPOSE: Flush entries associated with specific ifp 58436392Ssklower * 58536392Ssklower * RETURNS: nothing 58636392Ssklower * 58736392Ssklower * SIDE EFFECTS: 58836392Ssklower * 58936392Ssklower * NOTES: 59036392Ssklower */ 59136392Ssklower snpac_flushifp(ifp) 59236392Ssklower struct ifnet *ifp; 59336392Ssklower { 59443071Ssklower register struct llinfo_llc *lc; 59536392Ssklower 59643071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 59743071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 59843071Ssklower snpac_free(lc); 59936392Ssklower } 60036392Ssklower } 60136392Ssklower 60236392Ssklower /* 60336392Ssklower * FUNCTION: snpac_rtrequest 60436392Ssklower * 60536392Ssklower * PURPOSE: Make a routing request 60636392Ssklower * 60736392Ssklower * RETURNS: nothing 60836392Ssklower * 60936392Ssklower * SIDE EFFECTS: 61036392Ssklower * 61136392Ssklower * NOTES: In the future, this should make a request of a user 61236392Ssklower * level routing daemon. 61336392Ssklower */ 61437469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 61536392Ssklower int req; 61637469Ssklower struct iso_addr *host; 61736392Ssklower struct iso_addr *gateway; 61837469Ssklower struct iso_addr *netmask; 61936392Ssklower short flags; 62037469Ssklower struct rtentry **ret_nrt; 62136392Ssklower { 62237469Ssklower register struct iso_addr *r; 62336392Ssklower 62436392Ssklower IFDEBUG(D_SNPA) 62536392Ssklower printf("snpac_rtrequest: "); 62637469Ssklower if (req == RTM_ADD) 62736392Ssklower printf("add"); 62837469Ssklower else if (req == RTM_DELETE) 62936392Ssklower printf("delete"); 63036392Ssklower else 63136392Ssklower printf("unknown command"); 63237469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 63336392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 63436392Ssklower ENDDEBUG 63536392Ssklower 63636392Ssklower 63737469Ssklower zap_isoaddr(dst, host); 63837469Ssklower zap_isoaddr(gte, gateway); 63943334Ssklower if (netmask) { 64043334Ssklower zap_isoaddr(msk, netmask); 64143334Ssklower msk.siso_nlen = 0; 64243334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 64343334Ssklower } 64437469Ssklower 64537469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 64637469Ssklower flags, ret_nrt); 64736392Ssklower } 64836392Ssklower 64936392Ssklower /* 65036392Ssklower * FUNCTION: snpac_addrt 65136392Ssklower * 65236392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 65336392Ssklower * 65436392Ssklower * RETURNS: nothing 65536392Ssklower * 65636392Ssklower * SIDE EFFECTS: 65736392Ssklower * 65836392Ssklower * NOTES: If a cache entry exists for gateway, then 65936392Ssklower * make a routing entry (host, gateway) and associate 66036392Ssklower * with gateway. 66136392Ssklower * 66236392Ssklower * If a route already exists and is different, first delete 66336392Ssklower * it. 66436392Ssklower * 66536392Ssklower * This could be made more efficient by checking 66636392Ssklower * the existing route before adding a new one. 66736392Ssklower */ 66839950Ssklower snpac_addrt(ifp, host, gateway, netmask) 66939950Ssklower struct ifnet *ifp; 67039950Ssklower struct iso_addr *host, *gateway, *netmask; 67136392Ssklower { 67237469Ssklower register struct iso_addr *r; 67336392Ssklower 67443071Ssklower zap_isoaddr(dst, host); 67543071Ssklower zap_isoaddr(gte, gateway); 67643071Ssklower if (netmask) { 67743334Ssklower zap_isoaddr(msk, netmask); 67843334Ssklower msk.siso_nlen = 0; 67943334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 68043071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 68143071Ssklower } else 68243071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 68343071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 68436392Ssklower } 68536392Ssklower #endif ISO 686