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*47274Ssklower /* @(#)iso_snpac.c 7.11 (Berkeley) 03/12/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" 49*47274Ssklower #include "syslog.h" 5036392Ssklower 5136392Ssklower #include "../net/if.h" 5243071Ssklower #include "../net/if_dl.h" 5336392Ssklower #include "../net/route.h" 5436392Ssklower 5537469Ssklower #include "iso.h" 5637469Ssklower #include "iso_var.h" 5737469Ssklower #include "iso_snpac.h" 5837469Ssklower #include "clnp.h" 5937469Ssklower #include "clnp_stat.h" 6038841Ssklower #include "esis.h" 6137469Ssklower #include "argo_debug.h" 6236392Ssklower 6336392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6443423Ssklower extern short esis_holding_time, esis_config_time, esis_esconfig_time; 6543423Ssklower extern int esis_config(); 6636392Ssklower 6737469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 6837469Ssklower extern u_long iso_hashchar(); 6937469Ssklower static struct sockaddr_iso 7037469Ssklower dst = {sizeof(dst), AF_ISO}, 7137469Ssklower gte = {sizeof(dst), AF_ISO}, 7237469Ssklower src = {sizeof(dst), AF_ISO}, 7337469Ssklower msk = {sizeof(dst), AF_ISO}, 7437469Ssklower zmk = {1}; 7537469Ssklower #define zsi blank_siso 7637469Ssklower #define zero_isoa zsi.siso_addr 7737469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 7837469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 7937469Ssklower #define S(x) ((struct sockaddr *)&(x)) 8037469Ssklower 8143071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 8243071Ssklower static struct sockaddr_dl gte_dl; 8343071Ssklower #define zap_linkaddr(a, b, c, i) \ 8443071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8536392Ssklower 8636392Ssklower /* 8736392Ssklower * We only keep track of a single IS at a time. 8836392Ssklower */ 8943071Ssklower struct rtentry *known_is; 9036392Ssklower 9136392Ssklower /* 9236392Ssklower * Addresses taken from NBS agreements, December 1987. 9336392Ssklower * 9436392Ssklower * These addresses assume on-the-wire transmission of least significant 9536392Ssklower * bit first. This is the method used by 802.3. When these 9636392Ssklower * addresses are passed to the token ring driver, (802.5), they 9736392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 9836392Ssklower * 9936392Ssklower * Furthermore, according to IBM Austin, these addresses are not 10036392Ssklower * true token ring multicast addresses. More work is necessary 10136392Ssklower * to get multicast to work right on token ring. 10236392Ssklower * 10336392Ssklower * Currently, the token ring driver does not handle multicast, so 10436392Ssklower * these addresses are converted into the broadcast address in 10536392Ssklower * lan_output() That means that if these multicast addresses change 10636392Ssklower * the token ring driver must be altered. 10736392Ssklower */ 10843334Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 10943334Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 11045898Ssklower char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14}; 11145898Ssklower char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15}; 11236392Ssklower 11343071Ssklower union sockunion { 11443071Ssklower struct sockaddr_iso siso; 11543071Ssklower struct sockaddr_dl sdl; 11643071Ssklower struct sockaddr sa; 11743071Ssklower }; 11836392Ssklower 11936392Ssklower /* 12043071Ssklower * FUNCTION: llc_rtrequest 12143071Ssklower * 12243071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 12343071Ssklower * 12443071Ssklower * NOTES: This does a lot of obscure magic; 12543071Ssklower */ 12643071Ssklower llc_rtrequest(req, rt, sa) 12743071Ssklower int req; 12843071Ssklower register struct rtentry *rt; 12943071Ssklower struct sockaddr *sa; 13043071Ssklower { 13143071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 13243071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 13343071Ssklower struct rtentry *rt2; 13443071Ssklower struct ifnet *ifp = rt->rt_ifp; 13543071Ssklower int addrlen = ifp->if_addrlen; 13643334Ssklower static struct rtentry *recursing = 0; 13743071Ssklower 13843334Ssklower IFDEBUG (D_SNPA) 13943334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 14043334Ssklower ENDDEBUG 14143334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 14243334Ssklower if (recursing) { 143*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n", 14443334Ssklower recursing, rt); 14543334Ssklower } else switch (req) { 14643334Ssklower case RTM_RESOLVE: 14743334Ssklower case RTM_ADD: 14843334Ssklower recursing = rt; 14943334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 15043334Ssklower recursing = 0; 15143334Ssklower return; 15243334Ssklower 15343334Ssklower case RTM_DELETE: 15443334Ssklower if (lc) 15543334Ssklower RTFREE((struct rtentry *)lc); 15643334Ssklower rt->rt_llinfo = 0; 15743071Ssklower } 15843334Ssklower } else switch (req) { 15943071Ssklower case RTM_ADD: 16043334Ssklower /* 16143334Ssklower * Case 1: This route may come from a route to iface with mask 16243334Ssklower * or from a default route. 16343334Ssklower */ 16443071Ssklower if (rt->rt_flags & RTF_CLONING) { 16543334Ssklower register struct ifaddr *ifa; 16643334Ssklower register struct sockaddr *sa; 16743334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 16843334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 16943334Ssklower if (sa->sa_len > gate->sa.sa_len) 170*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n"); 17143334Ssklower else { 17243334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 17343334Ssklower gate->sdl.sdl_alen = 0; 17443334Ssklower } 17543334Ssklower return; 17643071Ssklower } 17743334Ssklower if (ifa == 0) 178*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n"); 17943334Ssklower return; 18043071Ssklower } 18143334Ssklower /* FALLTHROUGH */ 18243334Ssklower case RTM_RESOLVE: 18343334Ssklower /* 18443334Ssklower * Case 2: This route may come from cloning, or a manual route 18543334Ssklower * add with a LL address. 18643334Ssklower */ 18743334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 188*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n"); 18943334Ssklower return; 19043334Ssklower } 19143334Ssklower if (lc != 0) 192*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: losing old rt_llinfo\n"); 19343334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 19443334Ssklower rt->rt_llinfo = (caddr_t)lc; 19543334Ssklower if (lc == 0) { 196*47274Ssklower log(LOG_DEBUG, "llc_rtrequest: malloc failed\n"); 19743334Ssklower return; 19843334Ssklower } 19943334Ssklower Bzero(lc, sizeof(*lc)); 20043334Ssklower lc->lc_rt = rt; 20143334Ssklower rt->rt_flags |= RTF_LLINFO; 20243334Ssklower insque(lc, &llinfo_llc); 20343334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 20443334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 20543334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 20643334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 20743334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 20843334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 20943071Ssklower break; 21043071Ssklower case RTM_DELETE: 21143334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 21243334Ssklower return; 21343334Ssklower remque(lc); 21443334Ssklower Free(lc); 21543334Ssklower rt->rt_llinfo = 0; 21643334Ssklower rt->rt_flags &= ~RTF_LLINFO; 21743071Ssklower break; 21843071Ssklower } 21943071Ssklower } 22043071Ssklower /* 22136392Ssklower * FUNCTION: iso_snparesolve 22236392Ssklower * 22336392Ssklower * PURPOSE: Resolve an iso address into snpa address 22436392Ssklower * 22536392Ssklower * RETURNS: 0 if addr is resolved 22636392Ssklower * errno if addr is unknown 22736392Ssklower * 22836392Ssklower * SIDE EFFECTS: 22936392Ssklower * 23043071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 23143071Ssklower * table, we know there is no snpa address known for this 23243071Ssklower * destination. If we know of a default IS, then the address 23343071Ssklower * of the IS is returned. If no IS is known, then return the 23443071Ssklower * multi-cast address for "all ES" for this interface. 23536392Ssklower * 23636392Ssklower * NB: the last case described above constitutes the 23736392Ssklower * query configuration function 9542, sec 6.5 23836392Ssklower * A mechanism is needed to prevent this function from 23936392Ssklower * being invoked if the system is an IS. 24036392Ssklower */ 24137469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 24243071Ssklower struct ifnet *ifp; /* outgoing interface */ 24343071Ssklower struct sockaddr_iso *dest; /* destination */ 24443071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 24543071Ssklower int *snpa_len; /* RESULT: length of snpa */ 24636392Ssklower { 24743071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 24843071Ssklower caddr_t found_snpa; 24943071Ssklower int addrlen; 25036392Ssklower 25136392Ssklower /* 25236392Ssklower * This hack allows us to send esis packets that have the destination snpa 25336392Ssklower * addresss embedded in the destination nsap address 25436392Ssklower */ 25543071Ssklower if (dest->siso_data[0] == AFI_SNA) { 25636392Ssklower /* 25736392Ssklower * This is a subnetwork address. Return it immediately 25836392Ssklower */ 25936392Ssklower IFDEBUG(D_SNPA) 26036392Ssklower printf("iso_snparesolve: return SN address\n"); 26136392Ssklower ENDDEBUG 26243071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 26343071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 26436392Ssklower /* 26543071Ssklower * If we are an IS, we can't do much with the packet; 26643071Ssklower * Check if we know about an IS. 26736392Ssklower */ 26843071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 26943071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 27043071Ssklower (sc->lc_flags & SNPA_VALID)) { 27143071Ssklower register struct sockaddr_dl *sdl = 27243071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 27343071Ssklower found_snpa = LLADDR(sdl); 27443071Ssklower addrlen = sdl->sdl_alen; 27543071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 27643071Ssklower /* 27743071Ssklower * no IS, no match. Return "all es" multicast address for this 27843071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 27943071Ssklower * 28043071Ssklower * Note: there is a potential problem here. If the destination 28143071Ssklower * is on the subnet and it does not respond with a ESH, but 28243071Ssklower * does send back a TP CC, a connection could be established 28343071Ssklower * where we always transmit the CLNP packet to "all es" 28436392Ssklower */ 28543071Ssklower addrlen = ifp->if_addrlen; 28643071Ssklower found_snpa = (caddr_t)all_es_snpa; 28743071Ssklower } else 28843071Ssklower return (ENETUNREACH); 28943071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 29036392Ssklower return (0); 29136392Ssklower } 29236392Ssklower 29336392Ssklower 29436392Ssklower /* 29536392Ssklower * FUNCTION: snpac_free 29636392Ssklower * 29736392Ssklower * PURPOSE: free an entry in the iso address map table 29836392Ssklower * 29936392Ssklower * RETURNS: nothing 30036392Ssklower * 30136392Ssklower * SIDE EFFECTS: 30236392Ssklower * 30336392Ssklower * NOTES: If there is a route entry associated with cache 30436392Ssklower * entry, then delete that as well 30536392Ssklower */ 30643071Ssklower snpac_free(lc) 30743071Ssklower register struct llinfo_llc *lc; /* entry to free */ 30836392Ssklower { 30943071Ssklower register struct rtentry *rt = lc->lc_rt; 31037469Ssklower register struct iso_addr *r; 31136392Ssklower 31243071Ssklower if (known_is == rt) 31343071Ssklower known_is = 0; 31443071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 31543071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 31637469Ssklower RTFREE(rt); 31737469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 31837469Ssklower rt->rt_flags, (struct rtentry **)0); 31937469Ssklower RTFREE(rt); 32036392Ssklower } 32136392Ssklower } 32236392Ssklower 32336392Ssklower /* 32436392Ssklower * FUNCTION: snpac_add 32536392Ssklower * 32636392Ssklower * PURPOSE: Add an entry to the snpa cache 32736392Ssklower * 32836392Ssklower * RETURNS: 32936392Ssklower * 33036392Ssklower * SIDE EFFECTS: 33136392Ssklower * 33236392Ssklower * NOTES: If entry already exists, then update holding time. 33336392Ssklower */ 33443334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 33536392Ssklower struct ifnet *ifp; /* interface info is related to */ 33636392Ssklower struct iso_addr *nsap; /* nsap to add */ 33736392Ssklower caddr_t snpa; /* translation */ 33836392Ssklower char type; /* SNPA_IS or SNPA_ES */ 33937469Ssklower u_short ht; /* holding time (in seconds) */ 34043334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 34136392Ssklower { 34243071Ssklower register struct llinfo_llc *lc; 34343334Ssklower register struct rtentry *rt; 34443334Ssklower struct rtentry *mrt = 0; 34543071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 34643071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 34743071Ssklower int new_entry = 0, index = ifp->if_index; 34836392Ssklower 34943334Ssklower IFDEBUG(D_SNPA) 35043334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 35143334Ssklower ifp, nsap, snpa, type, ht, nsellength); 35243334Ssklower ENDDEBUG 35343071Ssklower zap_isoaddr(dst, nsap); 35443071Ssklower rt = rtalloc1(S(dst), 0); 35543334Ssklower IFDEBUG(D_SNPA) 35643334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 35743334Ssklower ENDDEBUG 35843071Ssklower if (rt == 0) { 35943334Ssklower struct sockaddr *netmask; 36043334Ssklower int flags; 36143334Ssklower add: 36243334Ssklower if (nsellength) { 36343334Ssklower netmask = S(msk); flags = RTF_UP; 36443334Ssklower snpac_fixdstandmask(nsellength); 36543334Ssklower } else { 36643334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 36743334Ssklower } 36843071Ssklower new_entry = 1; 36943071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 37043334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 37143334Ssklower mrt == 0) 37243071Ssklower return (0); 37343334Ssklower rt = mrt; 37443334Ssklower rt->rt_refcnt--; 37543071Ssklower } else { 37643071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 37743334Ssklower rt->rt_refcnt--; 37843334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 37943334Ssklower goto add; 38043334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 38143334Ssklower if (rt->rt_refcnt == 0) { 38243334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 38343334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 38443334Ssklower rt = 0; 38543334Ssklower goto add; 38643334Ssklower } else { 38743334Ssklower static struct iso_addr nsap2; register char *cp; 38843334Ssklower nsap2 = *nsap; 38943334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 39043334Ssklower while (cp < (char *)(1 + &nsap2)) 39143334Ssklower *cp++ = 0; 39243334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 39343334Ssklower } 39443334Ssklower } 39543071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 39643071Ssklower int old_sdl_len = sdl->sdl_len; 39743334Ssklower if (old_sdl_len < sizeof(*sdl)) { 398*47274Ssklower log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 39943071Ssklower return (0); 40043334Ssklower } 40143071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 40243071Ssklower sdl->sdl_len = old_sdl_len; 40343071Ssklower new_entry = 1; 40443071Ssklower } 40536392Ssklower } 40643334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 40743334Ssklower panic("snpac_rtrequest"); 40843334Ssklower rt->rt_idle = ht; 40943071Ssklower lc->lc_flags = SNPA_VALID | type; 41036392Ssklower if (type & SNPA_IS) 41143071Ssklower snpac_logdefis(rt); 41243334Ssklower return (new_entry); 41336392Ssklower } 41436392Ssklower 41543334Ssklower static snpac_fixdstandmask(nsellength) 41643334Ssklower { 41743334Ssklower register char *cp = msk.siso_data, *cplim; 41843334Ssklower 41943334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 42043334Ssklower msk.siso_len = cplim - (char *)&msk; 42143334Ssklower msk.siso_nlen = 0; 42243334Ssklower while (cp < cplim) 42343334Ssklower *cp++ = -1; 42443334Ssklower while (cp < (char *)msk.siso_pad) 42543334Ssklower *cp++ = 0; 42643334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 42743334Ssklower *cp++ = 0; 42843334Ssklower } 42943334Ssklower 43036392Ssklower /* 43136392Ssklower * FUNCTION: snpac_ioctl 43236392Ssklower * 43336392Ssklower * PURPOSE: Set/Get the system type and esis parameters 43436392Ssklower * 43536392Ssklower * RETURNS: 0 on success, or unix error code 43636392Ssklower * 43736392Ssklower * SIDE EFFECTS: 43836392Ssklower * 43936392Ssklower * NOTES: 44036392Ssklower */ 44143071Ssklower snpac_ioctl (cmd, data) 44236392Ssklower int cmd; /* ioctl to process */ 44336392Ssklower caddr_t data; /* data for the cmd */ 44436392Ssklower { 44536392Ssklower register struct systype_req *rq = (struct systype_req *)data; 44636392Ssklower 44743334Ssklower IFDEBUG(D_IOCTL) 44836392Ssklower if (cmd == SIOCSSTYPE) 44943071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 45036392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 45136392Ssklower else 45243071Ssklower printf("snpac_ioctl: cmd get\n"); 45336392Ssklower ENDDEBUG 45436392Ssklower 45536392Ssklower if (cmd == SIOCSSTYPE) { 45637551Smckusick if (suser(u.u_cred, &u.u_acflag)) 45736392Ssklower return(EACCES); 45836392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 45936392Ssklower return(EINVAL); 46036392Ssklower if (rq->sr_type & SNPA_ES) { 46136392Ssklower iso_systype = SNPA_ES; 46236392Ssklower } else if (rq->sr_type & SNPA_IS) { 46336392Ssklower iso_systype = SNPA_IS; 46436392Ssklower } else { 46536392Ssklower return(EINVAL); 46636392Ssklower } 46736392Ssklower esis_holding_time = rq->sr_holdt; 46836392Ssklower esis_config_time = rq->sr_configt; 46943423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 47043423Ssklower untimeout(esis_config, (caddr_t)0); 47143423Ssklower esis_esconfig_time = rq->sr_esconfigt; 47243423Ssklower esis_config(); 47343423Ssklower } 47436392Ssklower } else if (cmd == SIOCGSTYPE) { 47536392Ssklower rq->sr_type = iso_systype; 47636392Ssklower rq->sr_holdt = esis_holding_time; 47736392Ssklower rq->sr_configt = esis_config_time; 47843423Ssklower rq->sr_esconfigt = esis_esconfig_time; 47936392Ssklower } else { 48043071Ssklower return (EINVAL); 48136392Ssklower } 48243071Ssklower return (0); 48336392Ssklower } 48436392Ssklower 48536392Ssklower /* 48636392Ssklower * FUNCTION: snpac_logdefis 48736392Ssklower * 48836392Ssklower * PURPOSE: Mark the IS passed as the default IS 48936392Ssklower * 49036392Ssklower * RETURNS: nothing 49136392Ssklower * 49236392Ssklower * SIDE EFFECTS: 49336392Ssklower * 49436392Ssklower * NOTES: 49536392Ssklower */ 49636392Ssklower snpac_logdefis(sc) 49743071Ssklower register struct rtentry *sc; 49836392Ssklower { 49937469Ssklower register struct iso_addr *r; 50043071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 50137469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 50243071Ssklower 50343071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 50437469Ssklower if (known_is == 0) 50537469Ssklower known_is = sc; 50637469Ssklower if (known_is != sc) { 50743071Ssklower rtfree(known_is); 50837469Ssklower known_is = sc; 50936392Ssklower } 51037469Ssklower if (rt == 0) { 51143071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 51243071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 51337469Ssklower return; 51437469Ssklower } 51543334Ssklower rt->rt_refcnt--; 51637469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 51743071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 51837469Ssklower } 51936392Ssklower } 52036392Ssklower 52136392Ssklower /* 52236392Ssklower * FUNCTION: snpac_age 52336392Ssklower * 52436392Ssklower * PURPOSE: Time out snpac entries 52536392Ssklower * 52636392Ssklower * RETURNS: 52736392Ssklower * 52836392Ssklower * SIDE EFFECTS: 52936392Ssklower * 53036392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 53136392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 53236392Ssklower * if the entry is added a moment before snpac_age is 53336392Ssklower * called, the entry will immediately have SNPAC_AGE 53436392Ssklower * seconds taken off the holding time, even though 53536392Ssklower * it has only been held a brief moment. 53636392Ssklower * 53736392Ssklower * The proper way to do this is set an expiry timeval 53836392Ssklower * equal to current time + holding time. Then snpac_age 53936392Ssklower * would time out entries where expiry date is older 54036392Ssklower * than the current time. 54136392Ssklower */ 54236392Ssklower snpac_age() 54336392Ssklower { 54443071Ssklower register struct llinfo_llc *lc; 54536392Ssklower 54636392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 54736392Ssklower 54843071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 54943071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 55043334Ssklower lc->lc_rt->rt_idle -= SNPAC_AGE; 55143334Ssklower if (lc->lc_rt->rt_idle > 0) 55236392Ssklower continue; 55336392Ssklower else 55443071Ssklower snpac_free(lc); 55536392Ssklower } 55636392Ssklower } 55736392Ssklower } 55836392Ssklower 55936392Ssklower /* 56036392Ssklower * FUNCTION: snpac_ownmulti 56136392Ssklower * 56236392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 56336392Ssklower * of the same type as the system. 56436392Ssklower * 56536392Ssklower * RETURNS: true or false 56636392Ssklower * 56736392Ssklower * SIDE EFFECTS: 56836392Ssklower * 56936392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 57036392Ssklower * as interm kludge until 57136392Ssklower * real multicast addresses can be configured 57236392Ssklower */ 57336392Ssklower snpac_ownmulti(snpa, len) 57443071Ssklower caddr_t snpa; 57543071Ssklower u_int len; 57636392Ssklower { 57737469Ssklower return (((iso_systype & SNPA_ES) && 57843071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 57937469Ssklower ((iso_systype & SNPA_IS) && 58043071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 58136392Ssklower } 58236392Ssklower 58336392Ssklower /* 58436392Ssklower * FUNCTION: snpac_flushifp 58536392Ssklower * 58636392Ssklower * PURPOSE: Flush entries associated with specific ifp 58736392Ssklower * 58836392Ssklower * RETURNS: nothing 58936392Ssklower * 59036392Ssklower * SIDE EFFECTS: 59136392Ssklower * 59236392Ssklower * NOTES: 59336392Ssklower */ 59436392Ssklower snpac_flushifp(ifp) 59536392Ssklower struct ifnet *ifp; 59636392Ssklower { 59743071Ssklower register struct llinfo_llc *lc; 59836392Ssklower 59943071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 60043071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 60143071Ssklower snpac_free(lc); 60236392Ssklower } 60336392Ssklower } 60436392Ssklower 60536392Ssklower /* 60636392Ssklower * FUNCTION: snpac_rtrequest 60736392Ssklower * 60836392Ssklower * PURPOSE: Make a routing request 60936392Ssklower * 61036392Ssklower * RETURNS: nothing 61136392Ssklower * 61236392Ssklower * SIDE EFFECTS: 61336392Ssklower * 61436392Ssklower * NOTES: In the future, this should make a request of a user 61536392Ssklower * level routing daemon. 61636392Ssklower */ 61737469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 61836392Ssklower int req; 61937469Ssklower struct iso_addr *host; 62036392Ssklower struct iso_addr *gateway; 62137469Ssklower struct iso_addr *netmask; 62236392Ssklower short flags; 62337469Ssklower struct rtentry **ret_nrt; 62436392Ssklower { 62537469Ssklower register struct iso_addr *r; 62636392Ssklower 62736392Ssklower IFDEBUG(D_SNPA) 62836392Ssklower printf("snpac_rtrequest: "); 62937469Ssklower if (req == RTM_ADD) 63036392Ssklower printf("add"); 63137469Ssklower else if (req == RTM_DELETE) 63236392Ssklower printf("delete"); 63336392Ssklower else 63436392Ssklower printf("unknown command"); 63537469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 63636392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 63736392Ssklower ENDDEBUG 63836392Ssklower 63936392Ssklower 64037469Ssklower zap_isoaddr(dst, host); 64137469Ssklower zap_isoaddr(gte, gateway); 64243334Ssklower if (netmask) { 64343334Ssklower zap_isoaddr(msk, netmask); 64443334Ssklower msk.siso_nlen = 0; 64543334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 64643334Ssklower } 64737469Ssklower 64837469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 64937469Ssklower flags, ret_nrt); 65036392Ssklower } 65136392Ssklower 65236392Ssklower /* 65336392Ssklower * FUNCTION: snpac_addrt 65436392Ssklower * 65536392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 65636392Ssklower * 65736392Ssklower * RETURNS: nothing 65836392Ssklower * 65936392Ssklower * SIDE EFFECTS: 66036392Ssklower * 66136392Ssklower * NOTES: If a cache entry exists for gateway, then 66236392Ssklower * make a routing entry (host, gateway) and associate 66336392Ssklower * with gateway. 66436392Ssklower * 66536392Ssklower * If a route already exists and is different, first delete 66636392Ssklower * it. 66736392Ssklower * 66836392Ssklower * This could be made more efficient by checking 66936392Ssklower * the existing route before adding a new one. 67036392Ssklower */ 67139950Ssklower snpac_addrt(ifp, host, gateway, netmask) 67239950Ssklower struct ifnet *ifp; 67339950Ssklower struct iso_addr *host, *gateway, *netmask; 67436392Ssklower { 67537469Ssklower register struct iso_addr *r; 67636392Ssklower 67743071Ssklower zap_isoaddr(dst, host); 67843071Ssklower zap_isoaddr(gte, gateway); 67943071Ssklower if (netmask) { 68043334Ssklower zap_isoaddr(msk, netmask); 68143334Ssklower msk.siso_nlen = 0; 68243334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 68343071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 68443071Ssklower } else 68543071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 68643071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 68736392Ssklower } 68836392Ssklower #endif ISO 689