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*45898Ssklower /* @(#)iso_snpac.c 7.10 (Berkeley) 01/09/91 */ 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 */ 6343423Ssklower extern short esis_holding_time, esis_config_time, esis_esconfig_time; 6443423Ssklower 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 }; 109*45898Ssklower char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14}; 110*45898Ssklower char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15}; 11136392Ssklower 11243071Ssklower union sockunion { 11343071Ssklower struct sockaddr_iso siso; 11443071Ssklower struct sockaddr_dl sdl; 11543071Ssklower struct sockaddr sa; 11643071Ssklower }; 11736392Ssklower 11836392Ssklower /* 11943071Ssklower * FUNCTION: llc_rtrequest 12043071Ssklower * 12143071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 12243071Ssklower * 12343071Ssklower * NOTES: This does a lot of obscure magic; 12443071Ssklower */ 12543071Ssklower llc_rtrequest(req, rt, sa) 12643071Ssklower int req; 12743071Ssklower register struct rtentry *rt; 12843071Ssklower struct sockaddr *sa; 12943071Ssklower { 13043071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 13143071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 13243071Ssklower struct rtentry *rt2; 13343071Ssklower struct ifnet *ifp = rt->rt_ifp; 13443071Ssklower int addrlen = ifp->if_addrlen; 13543334Ssklower static struct rtentry *recursing = 0; 13643071Ssklower 13743334Ssklower IFDEBUG (D_SNPA) 13843334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 13943334Ssklower ENDDEBUG 14043334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 14143334Ssklower if (recursing) { 14243334Ssklower log("llc_rtrequest: gateway route points to same type %x %x\n", 14343334Ssklower recursing, rt); 14443334Ssklower } else switch (req) { 14543334Ssklower case RTM_RESOLVE: 14643334Ssklower case RTM_ADD: 14743334Ssklower recursing = rt; 14843334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 14943334Ssklower recursing = 0; 15043334Ssklower return; 15143334Ssklower 15243334Ssklower case RTM_DELETE: 15343334Ssklower if (lc) 15443334Ssklower RTFREE((struct rtentry *)lc); 15543334Ssklower rt->rt_llinfo = 0; 15643071Ssklower } 15743334Ssklower } else switch (req) { 15843071Ssklower case RTM_ADD: 15943334Ssklower /* 16043334Ssklower * Case 1: This route may come from a route to iface with mask 16143334Ssklower * or from a default route. 16243334Ssklower */ 16343071Ssklower if (rt->rt_flags & RTF_CLONING) { 16443334Ssklower register struct ifaddr *ifa; 16543334Ssklower register struct sockaddr *sa; 16643334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 16743334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 16843334Ssklower if (sa->sa_len > gate->sa.sa_len) 16943334Ssklower log("llc_rtrequest: cloning address too small\n"); 17043334Ssklower else { 17143334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 17243334Ssklower gate->sdl.sdl_alen = 0; 17343334Ssklower } 17443334Ssklower return; 17543071Ssklower } 17643334Ssklower if (ifa == 0) 17743334Ssklower log("llc_rtrequest: can't find LL ifaddr for iface\n"); 17843334Ssklower return; 17943071Ssklower } 18043334Ssklower /* FALLTHROUGH */ 18143334Ssklower case RTM_RESOLVE: 18243334Ssklower /* 18343334Ssklower * Case 2: This route may come from cloning, or a manual route 18443334Ssklower * add with a LL address. 18543334Ssklower */ 18643334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 18743334Ssklower log("llc_rtrequest: got non-link non-gateway route\n"); 18843334Ssklower return; 18943334Ssklower } 19043334Ssklower if (lc != 0) 19143334Ssklower log("llc_rtrequest: losing old rt_llinfo\n"); 19243334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 19343334Ssklower rt->rt_llinfo = (caddr_t)lc; 19443334Ssklower if (lc == 0) { 19543334Ssklower log("llc_rtrequest: malloc failed\n"); 19643334Ssklower return; 19743334Ssklower } 19843334Ssklower Bzero(lc, sizeof(*lc)); 19943334Ssklower lc->lc_rt = rt; 20043334Ssklower rt->rt_flags |= RTF_LLINFO; 20143334Ssklower insque(lc, &llinfo_llc); 20243334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 20343334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 20443334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 20543334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 20643334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 20743334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 20843071Ssklower break; 20943071Ssklower case RTM_DELETE: 21043334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 21143334Ssklower return; 21243334Ssklower remque(lc); 21343334Ssklower Free(lc); 21443334Ssklower rt->rt_llinfo = 0; 21543334Ssklower rt->rt_flags &= ~RTF_LLINFO; 21643071Ssklower break; 21743071Ssklower } 21843071Ssklower } 21943071Ssklower /* 22036392Ssklower * FUNCTION: iso_snparesolve 22136392Ssklower * 22236392Ssklower * PURPOSE: Resolve an iso address into snpa address 22336392Ssklower * 22436392Ssklower * RETURNS: 0 if addr is resolved 22536392Ssklower * errno if addr is unknown 22636392Ssklower * 22736392Ssklower * SIDE EFFECTS: 22836392Ssklower * 22943071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 23043071Ssklower * table, we know there is no snpa address known for this 23143071Ssklower * destination. If we know of a default IS, then the address 23243071Ssklower * of the IS is returned. If no IS is known, then return the 23343071Ssklower * multi-cast address for "all ES" for this interface. 23436392Ssklower * 23536392Ssklower * NB: the last case described above constitutes the 23636392Ssklower * query configuration function 9542, sec 6.5 23736392Ssklower * A mechanism is needed to prevent this function from 23836392Ssklower * being invoked if the system is an IS. 23936392Ssklower */ 24037469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 24143071Ssklower struct ifnet *ifp; /* outgoing interface */ 24243071Ssklower struct sockaddr_iso *dest; /* destination */ 24343071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 24443071Ssklower int *snpa_len; /* RESULT: length of snpa */ 24536392Ssklower { 24643071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 24743071Ssklower caddr_t found_snpa; 24843071Ssklower int addrlen; 24936392Ssklower 25036392Ssklower /* 25136392Ssklower * This hack allows us to send esis packets that have the destination snpa 25236392Ssklower * addresss embedded in the destination nsap address 25336392Ssklower */ 25443071Ssklower if (dest->siso_data[0] == AFI_SNA) { 25536392Ssklower /* 25636392Ssklower * This is a subnetwork address. Return it immediately 25736392Ssklower */ 25836392Ssklower IFDEBUG(D_SNPA) 25936392Ssklower printf("iso_snparesolve: return SN address\n"); 26036392Ssklower ENDDEBUG 26143071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 26243071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 26336392Ssklower /* 26443071Ssklower * If we are an IS, we can't do much with the packet; 26543071Ssklower * Check if we know about an IS. 26636392Ssklower */ 26743071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 26843071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 26943071Ssklower (sc->lc_flags & SNPA_VALID)) { 27043071Ssklower register struct sockaddr_dl *sdl = 27143071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 27243071Ssklower found_snpa = LLADDR(sdl); 27343071Ssklower addrlen = sdl->sdl_alen; 27443071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 27543071Ssklower /* 27643071Ssklower * no IS, no match. Return "all es" multicast address for this 27743071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 27843071Ssklower * 27943071Ssklower * Note: there is a potential problem here. If the destination 28043071Ssklower * is on the subnet and it does not respond with a ESH, but 28143071Ssklower * does send back a TP CC, a connection could be established 28243071Ssklower * where we always transmit the CLNP packet to "all es" 28336392Ssklower */ 28443071Ssklower addrlen = ifp->if_addrlen; 28543071Ssklower found_snpa = (caddr_t)all_es_snpa; 28643071Ssklower } else 28743071Ssklower return (ENETUNREACH); 28843071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 28936392Ssklower return (0); 29036392Ssklower } 29136392Ssklower 29236392Ssklower 29336392Ssklower /* 29436392Ssklower * FUNCTION: snpac_free 29536392Ssklower * 29636392Ssklower * PURPOSE: free an entry in the iso address map table 29736392Ssklower * 29836392Ssklower * RETURNS: nothing 29936392Ssklower * 30036392Ssklower * SIDE EFFECTS: 30136392Ssklower * 30236392Ssklower * NOTES: If there is a route entry associated with cache 30336392Ssklower * entry, then delete that as well 30436392Ssklower */ 30543071Ssklower snpac_free(lc) 30643071Ssklower register struct llinfo_llc *lc; /* entry to free */ 30736392Ssklower { 30843071Ssklower register struct rtentry *rt = lc->lc_rt; 30937469Ssklower register struct iso_addr *r; 31036392Ssklower 31143071Ssklower if (known_is == rt) 31243071Ssklower known_is = 0; 31343071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 31443071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 31537469Ssklower RTFREE(rt); 31637469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 31737469Ssklower rt->rt_flags, (struct rtentry **)0); 31837469Ssklower RTFREE(rt); 31936392Ssklower } 32036392Ssklower } 32136392Ssklower 32236392Ssklower /* 32336392Ssklower * FUNCTION: snpac_add 32436392Ssklower * 32536392Ssklower * PURPOSE: Add an entry to the snpa cache 32636392Ssklower * 32736392Ssklower * RETURNS: 32836392Ssklower * 32936392Ssklower * SIDE EFFECTS: 33036392Ssklower * 33136392Ssklower * NOTES: If entry already exists, then update holding time. 33236392Ssklower */ 33343334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 33436392Ssklower struct ifnet *ifp; /* interface info is related to */ 33536392Ssklower struct iso_addr *nsap; /* nsap to add */ 33636392Ssklower caddr_t snpa; /* translation */ 33736392Ssklower char type; /* SNPA_IS or SNPA_ES */ 33837469Ssklower u_short ht; /* holding time (in seconds) */ 33943334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 34036392Ssklower { 34143071Ssklower register struct llinfo_llc *lc; 34243334Ssklower register struct rtentry *rt; 34343334Ssklower struct rtentry *mrt = 0; 34443071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 34543071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 34643071Ssklower int new_entry = 0, index = ifp->if_index; 34736392Ssklower 34843334Ssklower IFDEBUG(D_SNPA) 34943334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 35043334Ssklower ifp, nsap, snpa, type, ht, nsellength); 35143334Ssklower ENDDEBUG 35243071Ssklower zap_isoaddr(dst, nsap); 35343071Ssklower rt = rtalloc1(S(dst), 0); 35443334Ssklower IFDEBUG(D_SNPA) 35543334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 35643334Ssklower ENDDEBUG 35743071Ssklower if (rt == 0) { 35843334Ssklower struct sockaddr *netmask; 35943334Ssklower int flags; 36043334Ssklower add: 36143334Ssklower if (nsellength) { 36243334Ssklower netmask = S(msk); flags = RTF_UP; 36343334Ssklower snpac_fixdstandmask(nsellength); 36443334Ssklower } else { 36543334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 36643334Ssklower } 36743071Ssklower new_entry = 1; 36843071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 36943334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 37043334Ssklower mrt == 0) 37143071Ssklower return (0); 37243334Ssklower rt = mrt; 37343334Ssklower rt->rt_refcnt--; 37443071Ssklower } else { 37543071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 37643334Ssklower rt->rt_refcnt--; 37743334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 37843334Ssklower goto add; 37943334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 38043334Ssklower if (rt->rt_refcnt == 0) { 38143334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 38243334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 38343334Ssklower rt = 0; 38443334Ssklower goto add; 38543334Ssklower } else { 38643334Ssklower static struct iso_addr nsap2; register char *cp; 38743334Ssklower nsap2 = *nsap; 38843334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 38943334Ssklower while (cp < (char *)(1 + &nsap2)) 39043334Ssklower *cp++ = 0; 39143334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 39243334Ssklower } 39343334Ssklower } 39443071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 39543071Ssklower int old_sdl_len = sdl->sdl_len; 39643334Ssklower if (old_sdl_len < sizeof(*sdl)) { 39743334Ssklower log("snpac_add: cant make room for lladdr\n"); 39843071Ssklower return (0); 39943334Ssklower } 40043071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 40143071Ssklower sdl->sdl_len = old_sdl_len; 40243071Ssklower new_entry = 1; 40343071Ssklower } 40436392Ssklower } 40543334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 40643334Ssklower panic("snpac_rtrequest"); 40743334Ssklower rt->rt_idle = ht; 40843071Ssklower lc->lc_flags = SNPA_VALID | type; 40936392Ssklower if (type & SNPA_IS) 41043071Ssklower snpac_logdefis(rt); 41143334Ssklower return (new_entry); 41236392Ssklower } 41336392Ssklower 41443334Ssklower static snpac_fixdstandmask(nsellength) 41543334Ssklower { 41643334Ssklower register char *cp = msk.siso_data, *cplim; 41743334Ssklower 41843334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 41943334Ssklower msk.siso_len = cplim - (char *)&msk; 42043334Ssklower msk.siso_nlen = 0; 42143334Ssklower while (cp < cplim) 42243334Ssklower *cp++ = -1; 42343334Ssklower while (cp < (char *)msk.siso_pad) 42443334Ssklower *cp++ = 0; 42543334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 42643334Ssklower *cp++ = 0; 42743334Ssklower } 42843334Ssklower 42936392Ssklower /* 43036392Ssklower * FUNCTION: snpac_ioctl 43136392Ssklower * 43236392Ssklower * PURPOSE: Set/Get the system type and esis parameters 43336392Ssklower * 43436392Ssklower * RETURNS: 0 on success, or unix error code 43536392Ssklower * 43636392Ssklower * SIDE EFFECTS: 43736392Ssklower * 43836392Ssklower * NOTES: 43936392Ssklower */ 44043071Ssklower snpac_ioctl (cmd, data) 44136392Ssklower int cmd; /* ioctl to process */ 44236392Ssklower caddr_t data; /* data for the cmd */ 44336392Ssklower { 44436392Ssklower register struct systype_req *rq = (struct systype_req *)data; 44536392Ssklower 44643334Ssklower IFDEBUG(D_IOCTL) 44736392Ssklower if (cmd == SIOCSSTYPE) 44843071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 44936392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 45036392Ssklower else 45143071Ssklower printf("snpac_ioctl: cmd get\n"); 45236392Ssklower ENDDEBUG 45336392Ssklower 45436392Ssklower if (cmd == SIOCSSTYPE) { 45537551Smckusick if (suser(u.u_cred, &u.u_acflag)) 45636392Ssklower return(EACCES); 45736392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 45836392Ssklower return(EINVAL); 45936392Ssklower if (rq->sr_type & SNPA_ES) { 46036392Ssklower iso_systype = SNPA_ES; 46136392Ssklower } else if (rq->sr_type & SNPA_IS) { 46236392Ssklower iso_systype = SNPA_IS; 46336392Ssklower } else { 46436392Ssklower return(EINVAL); 46536392Ssklower } 46636392Ssklower esis_holding_time = rq->sr_holdt; 46736392Ssklower esis_config_time = rq->sr_configt; 46843423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 46943423Ssklower untimeout(esis_config, (caddr_t)0); 47043423Ssklower esis_esconfig_time = rq->sr_esconfigt; 47143423Ssklower esis_config(); 47243423Ssklower } 47336392Ssklower } else if (cmd == SIOCGSTYPE) { 47436392Ssklower rq->sr_type = iso_systype; 47536392Ssklower rq->sr_holdt = esis_holding_time; 47636392Ssklower rq->sr_configt = esis_config_time; 47743423Ssklower rq->sr_esconfigt = esis_esconfig_time; 47836392Ssklower } else { 47943071Ssklower return (EINVAL); 48036392Ssklower } 48143071Ssklower return (0); 48236392Ssklower } 48336392Ssklower 48436392Ssklower /* 48536392Ssklower * FUNCTION: snpac_logdefis 48636392Ssklower * 48736392Ssklower * PURPOSE: Mark the IS passed as the default IS 48836392Ssklower * 48936392Ssklower * RETURNS: nothing 49036392Ssklower * 49136392Ssklower * SIDE EFFECTS: 49236392Ssklower * 49336392Ssklower * NOTES: 49436392Ssklower */ 49536392Ssklower snpac_logdefis(sc) 49643071Ssklower register struct rtentry *sc; 49736392Ssklower { 49837469Ssklower register struct iso_addr *r; 49943071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 50037469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 50143071Ssklower 50243071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 50337469Ssklower if (known_is == 0) 50437469Ssklower known_is = sc; 50537469Ssklower if (known_is != sc) { 50643071Ssklower rtfree(known_is); 50737469Ssklower known_is = sc; 50836392Ssklower } 50937469Ssklower if (rt == 0) { 51043071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 51143071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 51237469Ssklower return; 51337469Ssklower } 51443334Ssklower rt->rt_refcnt--; 51537469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 51643071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 51737469Ssklower } 51836392Ssklower } 51936392Ssklower 52036392Ssklower /* 52136392Ssklower * FUNCTION: snpac_age 52236392Ssklower * 52336392Ssklower * PURPOSE: Time out snpac entries 52436392Ssklower * 52536392Ssklower * RETURNS: 52636392Ssklower * 52736392Ssklower * SIDE EFFECTS: 52836392Ssklower * 52936392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 53036392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 53136392Ssklower * if the entry is added a moment before snpac_age is 53236392Ssklower * called, the entry will immediately have SNPAC_AGE 53336392Ssklower * seconds taken off the holding time, even though 53436392Ssklower * it has only been held a brief moment. 53536392Ssklower * 53636392Ssklower * The proper way to do this is set an expiry timeval 53736392Ssklower * equal to current time + holding time. Then snpac_age 53836392Ssklower * would time out entries where expiry date is older 53936392Ssklower * than the current time. 54036392Ssklower */ 54136392Ssklower snpac_age() 54236392Ssklower { 54343071Ssklower register struct llinfo_llc *lc; 54436392Ssklower 54536392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 54636392Ssklower 54743071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 54843071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 54943334Ssklower lc->lc_rt->rt_idle -= SNPAC_AGE; 55043334Ssklower if (lc->lc_rt->rt_idle > 0) 55136392Ssklower continue; 55236392Ssklower else 55343071Ssklower snpac_free(lc); 55436392Ssklower } 55536392Ssklower } 55636392Ssklower } 55736392Ssklower 55836392Ssklower /* 55936392Ssklower * FUNCTION: snpac_ownmulti 56036392Ssklower * 56136392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 56236392Ssklower * of the same type as the system. 56336392Ssklower * 56436392Ssklower * RETURNS: true or false 56536392Ssklower * 56636392Ssklower * SIDE EFFECTS: 56736392Ssklower * 56836392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 56936392Ssklower * as interm kludge until 57036392Ssklower * real multicast addresses can be configured 57136392Ssklower */ 57236392Ssklower snpac_ownmulti(snpa, len) 57343071Ssklower caddr_t snpa; 57443071Ssklower u_int len; 57536392Ssklower { 57637469Ssklower return (((iso_systype & SNPA_ES) && 57743071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 57837469Ssklower ((iso_systype & SNPA_IS) && 57943071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 58036392Ssklower } 58136392Ssklower 58236392Ssklower /* 58336392Ssklower * FUNCTION: snpac_flushifp 58436392Ssklower * 58536392Ssklower * PURPOSE: Flush entries associated with specific ifp 58636392Ssklower * 58736392Ssklower * RETURNS: nothing 58836392Ssklower * 58936392Ssklower * SIDE EFFECTS: 59036392Ssklower * 59136392Ssklower * NOTES: 59236392Ssklower */ 59336392Ssklower snpac_flushifp(ifp) 59436392Ssklower struct ifnet *ifp; 59536392Ssklower { 59643071Ssklower register struct llinfo_llc *lc; 59736392Ssklower 59843071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 59943071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 60043071Ssklower snpac_free(lc); 60136392Ssklower } 60236392Ssklower } 60336392Ssklower 60436392Ssklower /* 60536392Ssklower * FUNCTION: snpac_rtrequest 60636392Ssklower * 60736392Ssklower * PURPOSE: Make a routing request 60836392Ssklower * 60936392Ssklower * RETURNS: nothing 61036392Ssklower * 61136392Ssklower * SIDE EFFECTS: 61236392Ssklower * 61336392Ssklower * NOTES: In the future, this should make a request of a user 61436392Ssklower * level routing daemon. 61536392Ssklower */ 61637469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 61736392Ssklower int req; 61837469Ssklower struct iso_addr *host; 61936392Ssklower struct iso_addr *gateway; 62037469Ssklower struct iso_addr *netmask; 62136392Ssklower short flags; 62237469Ssklower struct rtentry **ret_nrt; 62336392Ssklower { 62437469Ssklower register struct iso_addr *r; 62536392Ssklower 62636392Ssklower IFDEBUG(D_SNPA) 62736392Ssklower printf("snpac_rtrequest: "); 62837469Ssklower if (req == RTM_ADD) 62936392Ssklower printf("add"); 63037469Ssklower else if (req == RTM_DELETE) 63136392Ssklower printf("delete"); 63236392Ssklower else 63336392Ssklower printf("unknown command"); 63437469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 63536392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 63636392Ssklower ENDDEBUG 63736392Ssklower 63836392Ssklower 63937469Ssklower zap_isoaddr(dst, host); 64037469Ssklower zap_isoaddr(gte, gateway); 64143334Ssklower if (netmask) { 64243334Ssklower zap_isoaddr(msk, netmask); 64343334Ssklower msk.siso_nlen = 0; 64443334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 64543334Ssklower } 64637469Ssklower 64737469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 64837469Ssklower flags, ret_nrt); 64936392Ssklower } 65036392Ssklower 65136392Ssklower /* 65236392Ssklower * FUNCTION: snpac_addrt 65336392Ssklower * 65436392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 65536392Ssklower * 65636392Ssklower * RETURNS: nothing 65736392Ssklower * 65836392Ssklower * SIDE EFFECTS: 65936392Ssklower * 66036392Ssklower * NOTES: If a cache entry exists for gateway, then 66136392Ssklower * make a routing entry (host, gateway) and associate 66236392Ssklower * with gateway. 66336392Ssklower * 66436392Ssklower * If a route already exists and is different, first delete 66536392Ssklower * it. 66636392Ssklower * 66736392Ssklower * This could be made more efficient by checking 66836392Ssklower * the existing route before adding a new one. 66936392Ssklower */ 67039950Ssklower snpac_addrt(ifp, host, gateway, netmask) 67139950Ssklower struct ifnet *ifp; 67239950Ssklower struct iso_addr *host, *gateway, *netmask; 67336392Ssklower { 67437469Ssklower register struct iso_addr *r; 67536392Ssklower 67643071Ssklower zap_isoaddr(dst, host); 67743071Ssklower zap_isoaddr(gte, gateway); 67843071Ssklower if (netmask) { 67943334Ssklower zap_isoaddr(msk, netmask); 68043334Ssklower msk.siso_nlen = 0; 68143334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 68243071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 68343071Ssklower } else 68443071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 68543071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 68636392Ssklower } 68736392Ssklower #endif ISO 688