149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*50230Ssklower * @(#)iso_snpac.c 7.14 (Berkeley) 06/27/91 849268Sbostic */ 949268Sbostic 1036392Ssklower /*********************************************************** 1136392Ssklower Copyright IBM Corporation 1987 1236392Ssklower 1336392Ssklower All Rights Reserved 1436392Ssklower 1536392Ssklower Permission to use, copy, modify, and distribute this software and its 1636392Ssklower documentation for any purpose and without fee is hereby granted, 1736392Ssklower provided that the above copyright notice appear in all copies and that 1836392Ssklower both that copyright notice and this permission notice appear in 1936392Ssklower supporting documentation, and that the name of IBM not be 2036392Ssklower used in advertising or publicity pertaining to distribution of the 2136392Ssklower software without specific, written prior permission. 2236392Ssklower 2336392Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436392Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536392Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636392Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736392Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836392Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936392Ssklower SOFTWARE. 3036392Ssklower 3136392Ssklower ******************************************************************/ 3236392Ssklower 3336392Ssklower /* 3436392Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536392Ssklower */ 3636392Ssklower /* $Header: iso_snpac.c,v 1.8 88/09/19 13:51:36 hagens Exp $ */ 3736392Ssklower /* $Source: /usr/argo/sys/netiso/RCS/iso_snpac.c,v $ */ 3836392Ssklower 3936392Ssklower #ifdef ISO 4036392Ssklower 4137469Ssklower #include "types.h" 4237469Ssklower #include "param.h" 4343071Ssklower #include "systm.h" 4437469Ssklower #include "mbuf.h" 4537469Ssklower #include "domain.h" 4637469Ssklower #include "protosw.h" 4737469Ssklower #include "socket.h" 4837469Ssklower #include "socketvar.h" 4937469Ssklower #include "errno.h" 5037469Ssklower #include "ioctl.h" 5147274Ssklower #include "syslog.h" 5236392Ssklower 5336392Ssklower #include "../net/if.h" 5443071Ssklower #include "../net/if_dl.h" 5536392Ssklower #include "../net/route.h" 5636392Ssklower 5737469Ssklower #include "iso.h" 5837469Ssklower #include "iso_var.h" 5937469Ssklower #include "iso_snpac.h" 6037469Ssklower #include "clnp.h" 6137469Ssklower #include "clnp_stat.h" 6238841Ssklower #include "esis.h" 6337469Ssklower #include "argo_debug.h" 6436392Ssklower 6536392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6643423Ssklower extern short esis_holding_time, esis_config_time, esis_esconfig_time; 67*50230Ssklower extern struct timeval time; 68*50230Ssklower extern int esis_config(), hz; 69*50230Ssklower static void snpac_fixdstandmask(); 7036392Ssklower 7137469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 7237469Ssklower extern u_long iso_hashchar(); 7337469Ssklower static struct sockaddr_iso 7437469Ssklower dst = {sizeof(dst), AF_ISO}, 7537469Ssklower gte = {sizeof(dst), AF_ISO}, 7637469Ssklower src = {sizeof(dst), AF_ISO}, 7737469Ssklower msk = {sizeof(dst), AF_ISO}, 7837469Ssklower zmk = {1}; 7937469Ssklower #define zsi blank_siso 8037469Ssklower #define zero_isoa zsi.siso_addr 81*50230Ssklower #define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \ 82*50230Ssklower Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);} 8337469Ssklower #define S(x) ((struct sockaddr *)&(x)) 8437469Ssklower 8543071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 8643071Ssklower static struct sockaddr_dl gte_dl; 8743071Ssklower #define zap_linkaddr(a, b, c, i) \ 8843071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8936392Ssklower 9036392Ssklower /* 9136392Ssklower * We only keep track of a single IS at a time. 9236392Ssklower */ 9343071Ssklower struct rtentry *known_is; 9436392Ssklower 9536392Ssklower /* 9636392Ssklower * Addresses taken from NBS agreements, December 1987. 9736392Ssklower * 9836392Ssklower * These addresses assume on-the-wire transmission of least significant 9936392Ssklower * bit first. This is the method used by 802.3. When these 10036392Ssklower * addresses are passed to the token ring driver, (802.5), they 10136392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 10236392Ssklower * 10336392Ssklower * Furthermore, according to IBM Austin, these addresses are not 10436392Ssklower * true token ring multicast addresses. More work is necessary 10536392Ssklower * to get multicast to work right on token ring. 10636392Ssklower * 10736392Ssklower * Currently, the token ring driver does not handle multicast, so 10836392Ssklower * these addresses are converted into the broadcast address in 10936392Ssklower * lan_output() That means that if these multicast addresses change 11036392Ssklower * the token ring driver must be altered. 11136392Ssklower */ 11243334Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 11343334Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 11445898Ssklower char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14}; 11545898Ssklower char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15}; 11636392Ssklower 11743071Ssklower union sockunion { 11843071Ssklower struct sockaddr_iso siso; 11943071Ssklower struct sockaddr_dl sdl; 12043071Ssklower struct sockaddr sa; 12143071Ssklower }; 12236392Ssklower 12336392Ssklower /* 12443071Ssklower * FUNCTION: llc_rtrequest 12543071Ssklower * 12643071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 12743071Ssklower * 12843071Ssklower * NOTES: This does a lot of obscure magic; 12943071Ssklower */ 13043071Ssklower llc_rtrequest(req, rt, sa) 13143071Ssklower int req; 13243071Ssklower register struct rtentry *rt; 13343071Ssklower struct sockaddr *sa; 13443071Ssklower { 13543071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 13643071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 13743071Ssklower struct rtentry *rt2; 13843071Ssklower struct ifnet *ifp = rt->rt_ifp; 13943071Ssklower int addrlen = ifp->if_addrlen; 14043334Ssklower static struct rtentry *recursing = 0; 14148732Ssklower #define LLC_SIZE 3 /* XXXXXX do this right later */ 14243071Ssklower 14343334Ssklower IFDEBUG (D_SNPA) 14443334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 14543334Ssklower ENDDEBUG 14643334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 14743334Ssklower if (recursing) { 14847274Ssklower log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n", 14943334Ssklower recursing, rt); 15043334Ssklower } else switch (req) { 15143334Ssklower case RTM_RESOLVE: 15243334Ssklower case RTM_ADD: 15343334Ssklower recursing = rt; 15443334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 15543334Ssklower recursing = 0; 15648732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 15748732Ssklower rt->rt_rmx.rmx_mtu = 15848732Ssklower ((rt2 = (struct rtentry *)rt->rt_llinfo) && 15948732Ssklower (rt2->rt_rmx.rmx_mtu)) ? 16048732Ssklower rt2->rt_rmx.rmx_mtu : 16148732Ssklower rt->rt_ifp->if_mtu - LLC_SIZE; 16248732Ssklower } 16343334Ssklower return; 16443334Ssklower 16543334Ssklower case RTM_DELETE: 16643334Ssklower if (lc) 16743334Ssklower RTFREE((struct rtentry *)lc); 16843334Ssklower rt->rt_llinfo = 0; 16943071Ssklower } 17043334Ssklower } else switch (req) { 17143071Ssklower case RTM_ADD: 17243334Ssklower /* 17343334Ssklower * Case 1: This route may come from a route to iface with mask 17443334Ssklower * or from a default route. 17543334Ssklower */ 17643071Ssklower if (rt->rt_flags & RTF_CLONING) { 17743334Ssklower register struct ifaddr *ifa; 17843334Ssklower register struct sockaddr *sa; 17943334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 18043334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 18143334Ssklower if (sa->sa_len > gate->sa.sa_len) 18247274Ssklower log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n"); 18343334Ssklower else { 18443334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 18543334Ssklower gate->sdl.sdl_alen = 0; 18643334Ssklower } 18748732Ssklower break; 18843071Ssklower } 18943334Ssklower if (ifa == 0) 19047274Ssklower log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n"); 19148732Ssklower break; 19243071Ssklower } 19343334Ssklower /* FALLTHROUGH */ 19443334Ssklower case RTM_RESOLVE: 19543334Ssklower /* 19643334Ssklower * Case 2: This route may come from cloning, or a manual route 19743334Ssklower * add with a LL address. 19843334Ssklower */ 19943334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 20047274Ssklower log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n"); 20148732Ssklower break; 20243334Ssklower } 20343334Ssklower if (lc != 0) 204*50230Ssklower return; /* happens on a route change */ 20543334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 20643334Ssklower rt->rt_llinfo = (caddr_t)lc; 20743334Ssklower if (lc == 0) { 20847274Ssklower log(LOG_DEBUG, "llc_rtrequest: malloc failed\n"); 20948732Ssklower break; 21043334Ssklower } 21143334Ssklower Bzero(lc, sizeof(*lc)); 21243334Ssklower lc->lc_rt = rt; 21343334Ssklower rt->rt_flags |= RTF_LLINFO; 21443334Ssklower insque(lc, &llinfo_llc); 21543334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 21643334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 21743334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 21843334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 21943334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 22043334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 22143071Ssklower break; 22243071Ssklower case RTM_DELETE: 22343334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 22443334Ssklower return; 22543334Ssklower remque(lc); 22643334Ssklower Free(lc); 22743334Ssklower rt->rt_llinfo = 0; 22843334Ssklower rt->rt_flags &= ~RTF_LLINFO; 22943071Ssklower break; 23043071Ssklower } 23148732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 23248732Ssklower rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE; 23348732Ssklower } 23443071Ssklower } 23543071Ssklower /* 23636392Ssklower * FUNCTION: iso_snparesolve 23736392Ssklower * 23836392Ssklower * PURPOSE: Resolve an iso address into snpa address 23936392Ssklower * 24036392Ssklower * RETURNS: 0 if addr is resolved 24136392Ssklower * errno if addr is unknown 24236392Ssklower * 24336392Ssklower * SIDE EFFECTS: 24436392Ssklower * 24543071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 24643071Ssklower * table, we know there is no snpa address known for this 24743071Ssklower * destination. If we know of a default IS, then the address 24843071Ssklower * of the IS is returned. If no IS is known, then return the 24943071Ssklower * multi-cast address for "all ES" for this interface. 25036392Ssklower * 25136392Ssklower * NB: the last case described above constitutes the 25236392Ssklower * query configuration function 9542, sec 6.5 25336392Ssklower * A mechanism is needed to prevent this function from 25436392Ssklower * being invoked if the system is an IS. 25536392Ssklower */ 25637469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 25743071Ssklower struct ifnet *ifp; /* outgoing interface */ 25843071Ssklower struct sockaddr_iso *dest; /* destination */ 25943071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 26043071Ssklower int *snpa_len; /* RESULT: length of snpa */ 26136392Ssklower { 26243071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 26343071Ssklower caddr_t found_snpa; 26443071Ssklower int addrlen; 26536392Ssklower 26636392Ssklower /* 26736392Ssklower * This hack allows us to send esis packets that have the destination snpa 26836392Ssklower * addresss embedded in the destination nsap address 26936392Ssklower */ 27043071Ssklower if (dest->siso_data[0] == AFI_SNA) { 27136392Ssklower /* 27236392Ssklower * This is a subnetwork address. Return it immediately 27336392Ssklower */ 27436392Ssklower IFDEBUG(D_SNPA) 27536392Ssklower printf("iso_snparesolve: return SN address\n"); 27636392Ssklower ENDDEBUG 27743071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 27843071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 27936392Ssklower /* 28043071Ssklower * If we are an IS, we can't do much with the packet; 28143071Ssklower * Check if we know about an IS. 28236392Ssklower */ 28343071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 28443071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 28543071Ssklower (sc->lc_flags & SNPA_VALID)) { 28643071Ssklower register struct sockaddr_dl *sdl = 28743071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 28843071Ssklower found_snpa = LLADDR(sdl); 28943071Ssklower addrlen = sdl->sdl_alen; 29043071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 29143071Ssklower /* 29243071Ssklower * no IS, no match. Return "all es" multicast address for this 29343071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 29443071Ssklower * 29543071Ssklower * Note: there is a potential problem here. If the destination 29643071Ssklower * is on the subnet and it does not respond with a ESH, but 29743071Ssklower * does send back a TP CC, a connection could be established 29843071Ssklower * where we always transmit the CLNP packet to "all es" 29936392Ssklower */ 30043071Ssklower addrlen = ifp->if_addrlen; 30143071Ssklower found_snpa = (caddr_t)all_es_snpa; 30243071Ssklower } else 30343071Ssklower return (ENETUNREACH); 30443071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 30536392Ssklower return (0); 30636392Ssklower } 30736392Ssklower 30836392Ssklower 30936392Ssklower /* 31036392Ssklower * FUNCTION: snpac_free 31136392Ssklower * 31236392Ssklower * PURPOSE: free an entry in the iso address map table 31336392Ssklower * 31436392Ssklower * RETURNS: nothing 31536392Ssklower * 31636392Ssklower * SIDE EFFECTS: 31736392Ssklower * 31836392Ssklower * NOTES: If there is a route entry associated with cache 31936392Ssklower * entry, then delete that as well 32036392Ssklower */ 32143071Ssklower snpac_free(lc) 32243071Ssklower register struct llinfo_llc *lc; /* entry to free */ 32336392Ssklower { 32443071Ssklower register struct rtentry *rt = lc->lc_rt; 32537469Ssklower register struct iso_addr *r; 32636392Ssklower 32743071Ssklower if (known_is == rt) 32843071Ssklower known_is = 0; 32943071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 33043071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 33137469Ssklower RTFREE(rt); 33237469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 33337469Ssklower rt->rt_flags, (struct rtentry **)0); 33437469Ssklower RTFREE(rt); 33536392Ssklower } 33636392Ssklower } 33736392Ssklower 33836392Ssklower /* 33936392Ssklower * FUNCTION: snpac_add 34036392Ssklower * 34136392Ssklower * PURPOSE: Add an entry to the snpa cache 34236392Ssklower * 34336392Ssklower * RETURNS: 34436392Ssklower * 34536392Ssklower * SIDE EFFECTS: 34636392Ssklower * 34736392Ssklower * NOTES: If entry already exists, then update holding time. 34836392Ssklower */ 34943334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 35036392Ssklower struct ifnet *ifp; /* interface info is related to */ 35136392Ssklower struct iso_addr *nsap; /* nsap to add */ 35236392Ssklower caddr_t snpa; /* translation */ 35336392Ssklower char type; /* SNPA_IS or SNPA_ES */ 35437469Ssklower u_short ht; /* holding time (in seconds) */ 35543334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 35636392Ssklower { 35743071Ssklower register struct llinfo_llc *lc; 35843334Ssklower register struct rtentry *rt; 35943334Ssklower struct rtentry *mrt = 0; 36043071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 36143071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 36243071Ssklower int new_entry = 0, index = ifp->if_index; 36336392Ssklower 36443334Ssklower IFDEBUG(D_SNPA) 36543334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 36643334Ssklower ifp, nsap, snpa, type, ht, nsellength); 36743334Ssklower ENDDEBUG 36843071Ssklower zap_isoaddr(dst, nsap); 36943071Ssklower rt = rtalloc1(S(dst), 0); 37043334Ssklower IFDEBUG(D_SNPA) 37143334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 37243334Ssklower ENDDEBUG 37343071Ssklower if (rt == 0) { 37443334Ssklower struct sockaddr *netmask; 37543334Ssklower int flags; 37643334Ssklower add: 37743334Ssklower if (nsellength) { 37843334Ssklower netmask = S(msk); flags = RTF_UP; 37943334Ssklower snpac_fixdstandmask(nsellength); 38043334Ssklower } else { 38143334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 38243334Ssklower } 38343071Ssklower new_entry = 1; 38443071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 38543334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 38643334Ssklower mrt == 0) 38743071Ssklower return (0); 38843334Ssklower rt = mrt; 38943334Ssklower rt->rt_refcnt--; 39043071Ssklower } else { 39143071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 39243334Ssklower rt->rt_refcnt--; 39343334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 39443334Ssklower goto add; 39543334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 39643334Ssklower if (rt->rt_refcnt == 0) { 39743334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 39843334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 39943334Ssklower rt = 0; 40043334Ssklower goto add; 40143334Ssklower } else { 40243334Ssklower static struct iso_addr nsap2; register char *cp; 40343334Ssklower nsap2 = *nsap; 40443334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 40543334Ssklower while (cp < (char *)(1 + &nsap2)) 40643334Ssklower *cp++ = 0; 40743334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 40843334Ssklower } 40943334Ssklower } 41043071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 41143071Ssklower int old_sdl_len = sdl->sdl_len; 41243334Ssklower if (old_sdl_len < sizeof(*sdl)) { 41347274Ssklower log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 41443071Ssklower return (0); 41543334Ssklower } 41643071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 41743071Ssklower sdl->sdl_len = old_sdl_len; 41843071Ssklower new_entry = 1; 41943071Ssklower } 42036392Ssklower } 42143334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 42243334Ssklower panic("snpac_rtrequest"); 423*50230Ssklower rt->rt_rmx.rmx_expire = ht + time.tv_sec; 42443071Ssklower lc->lc_flags = SNPA_VALID | type; 42536392Ssklower if (type & SNPA_IS) 42643071Ssklower snpac_logdefis(rt); 42743334Ssklower return (new_entry); 42836392Ssklower } 42936392Ssklower 430*50230Ssklower static void 431*50230Ssklower snpac_fixdstandmask(nsellength) 43243334Ssklower { 43343334Ssklower register char *cp = msk.siso_data, *cplim; 43443334Ssklower 43543334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 43643334Ssklower msk.siso_len = cplim - (char *)&msk; 43743334Ssklower msk.siso_nlen = 0; 43843334Ssklower while (cp < cplim) 43943334Ssklower *cp++ = -1; 44043334Ssklower while (cp < (char *)msk.siso_pad) 44143334Ssklower *cp++ = 0; 44243334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 44343334Ssklower *cp++ = 0; 44443334Ssklower } 44543334Ssklower 44636392Ssklower /* 44736392Ssklower * FUNCTION: snpac_ioctl 44836392Ssklower * 44936392Ssklower * PURPOSE: Set/Get the system type and esis parameters 45036392Ssklower * 45136392Ssklower * RETURNS: 0 on success, or unix error code 45236392Ssklower * 45336392Ssklower * SIDE EFFECTS: 45436392Ssklower * 45536392Ssklower * NOTES: 45636392Ssklower */ 457*50230Ssklower snpac_ioctl (so, cmd, data) 458*50230Ssklower struct socket *so; 45936392Ssklower int cmd; /* ioctl to process */ 46036392Ssklower caddr_t data; /* data for the cmd */ 46136392Ssklower { 46236392Ssklower register struct systype_req *rq = (struct systype_req *)data; 46336392Ssklower 46443334Ssklower IFDEBUG(D_IOCTL) 46536392Ssklower if (cmd == SIOCSSTYPE) 46643071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 46736392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 46836392Ssklower else 46943071Ssklower printf("snpac_ioctl: cmd get\n"); 47036392Ssklower ENDDEBUG 47136392Ssklower 47236392Ssklower if (cmd == SIOCSSTYPE) { 473*50230Ssklower if ((so->so_state & SS_PRIV) == 0) 474*50230Ssklower return (EPERM); 47536392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 47636392Ssklower return(EINVAL); 47736392Ssklower if (rq->sr_type & SNPA_ES) { 47836392Ssklower iso_systype = SNPA_ES; 47936392Ssklower } else if (rq->sr_type & SNPA_IS) { 48036392Ssklower iso_systype = SNPA_IS; 48136392Ssklower } else { 48236392Ssklower return(EINVAL); 48336392Ssklower } 48436392Ssklower esis_holding_time = rq->sr_holdt; 48536392Ssklower esis_config_time = rq->sr_configt; 48643423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 48743423Ssklower untimeout(esis_config, (caddr_t)0); 48843423Ssklower esis_esconfig_time = rq->sr_esconfigt; 48943423Ssklower esis_config(); 49043423Ssklower } 49136392Ssklower } else if (cmd == SIOCGSTYPE) { 49236392Ssklower rq->sr_type = iso_systype; 49336392Ssklower rq->sr_holdt = esis_holding_time; 49436392Ssklower rq->sr_configt = esis_config_time; 49543423Ssklower rq->sr_esconfigt = esis_esconfig_time; 49636392Ssklower } else { 49743071Ssklower return (EINVAL); 49836392Ssklower } 49943071Ssklower return (0); 50036392Ssklower } 50136392Ssklower 50236392Ssklower /* 50336392Ssklower * FUNCTION: snpac_logdefis 50436392Ssklower * 50536392Ssklower * PURPOSE: Mark the IS passed as the default IS 50636392Ssklower * 50736392Ssklower * RETURNS: nothing 50836392Ssklower * 50936392Ssklower * SIDE EFFECTS: 51036392Ssklower * 51136392Ssklower * NOTES: 51236392Ssklower */ 51336392Ssklower snpac_logdefis(sc) 51443071Ssklower register struct rtentry *sc; 51536392Ssklower { 51637469Ssklower register struct iso_addr *r; 51743071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 51837469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 51943071Ssklower 52043071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 52137469Ssklower if (known_is == 0) 52237469Ssklower known_is = sc; 52337469Ssklower if (known_is != sc) { 52443071Ssklower rtfree(known_is); 52537469Ssklower known_is = sc; 52636392Ssklower } 52737469Ssklower if (rt == 0) { 52843071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 52943071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 53037469Ssklower return; 53137469Ssklower } 53243334Ssklower rt->rt_refcnt--; 53337469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 53443071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 53537469Ssklower } 53636392Ssklower } 53736392Ssklower 53836392Ssklower /* 53936392Ssklower * FUNCTION: snpac_age 54036392Ssklower * 54136392Ssklower * PURPOSE: Time out snpac entries 54236392Ssklower * 54336392Ssklower * RETURNS: 54436392Ssklower * 54536392Ssklower * SIDE EFFECTS: 54636392Ssklower * 54736392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 54836392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 54936392Ssklower * if the entry is added a moment before snpac_age is 55036392Ssklower * called, the entry will immediately have SNPAC_AGE 55136392Ssklower * seconds taken off the holding time, even though 55236392Ssklower * it has only been held a brief moment. 55336392Ssklower * 55436392Ssklower * The proper way to do this is set an expiry timeval 55536392Ssklower * equal to current time + holding time. Then snpac_age 55636392Ssklower * would time out entries where expiry date is older 55736392Ssklower * than the current time. 55836392Ssklower */ 55936392Ssklower snpac_age() 56036392Ssklower { 561*50230Ssklower register struct llinfo_llc *lc, *nlc; 562*50230Ssklower register struct rtentry *rt; 56336392Ssklower 56436392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 56536392Ssklower 566*50230Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) { 567*50230Ssklower nlc = lc->lc_next; 56843071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 569*50230Ssklower rt = lc->lc_rt; 570*50230Ssklower if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec) 571*50230Ssklower snpac_free(lc); 572*50230Ssklower else 57336392Ssklower continue; 57436392Ssklower } 57536392Ssklower } 57636392Ssklower } 57736392Ssklower 57836392Ssklower /* 57936392Ssklower * FUNCTION: snpac_ownmulti 58036392Ssklower * 58136392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 58236392Ssklower * of the same type as the system. 58336392Ssklower * 58436392Ssklower * RETURNS: true or false 58536392Ssklower * 58636392Ssklower * SIDE EFFECTS: 58736392Ssklower * 58836392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 58936392Ssklower * as interm kludge until 59036392Ssklower * real multicast addresses can be configured 59136392Ssklower */ 59236392Ssklower snpac_ownmulti(snpa, len) 59343071Ssklower caddr_t snpa; 59443071Ssklower u_int len; 59536392Ssklower { 59637469Ssklower return (((iso_systype & SNPA_ES) && 59743071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 59837469Ssklower ((iso_systype & SNPA_IS) && 59943071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 60036392Ssklower } 60136392Ssklower 60236392Ssklower /* 60336392Ssklower * FUNCTION: snpac_flushifp 60436392Ssklower * 60536392Ssklower * PURPOSE: Flush entries associated with specific ifp 60636392Ssklower * 60736392Ssklower * RETURNS: nothing 60836392Ssklower * 60936392Ssklower * SIDE EFFECTS: 61036392Ssklower * 61136392Ssklower * NOTES: 61236392Ssklower */ 61336392Ssklower snpac_flushifp(ifp) 61436392Ssklower struct ifnet *ifp; 61536392Ssklower { 61643071Ssklower register struct llinfo_llc *lc; 61736392Ssklower 61843071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 61943071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 62043071Ssklower snpac_free(lc); 62136392Ssklower } 62236392Ssklower } 62336392Ssklower 62436392Ssklower /* 62536392Ssklower * FUNCTION: snpac_rtrequest 62636392Ssklower * 62736392Ssklower * PURPOSE: Make a routing request 62836392Ssklower * 62936392Ssklower * RETURNS: nothing 63036392Ssklower * 63136392Ssklower * SIDE EFFECTS: 63236392Ssklower * 63336392Ssklower * NOTES: In the future, this should make a request of a user 63436392Ssklower * level routing daemon. 63536392Ssklower */ 63637469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 63736392Ssklower int req; 63837469Ssklower struct iso_addr *host; 63936392Ssklower struct iso_addr *gateway; 64037469Ssklower struct iso_addr *netmask; 64136392Ssklower short flags; 64237469Ssklower struct rtentry **ret_nrt; 64336392Ssklower { 64437469Ssklower register struct iso_addr *r; 64536392Ssklower 64636392Ssklower IFDEBUG(D_SNPA) 64736392Ssklower printf("snpac_rtrequest: "); 64837469Ssklower if (req == RTM_ADD) 64936392Ssklower printf("add"); 65037469Ssklower else if (req == RTM_DELETE) 65136392Ssklower printf("delete"); 65236392Ssklower else 65336392Ssklower printf("unknown command"); 65437469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 65536392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 65636392Ssklower ENDDEBUG 65736392Ssklower 65836392Ssklower 65937469Ssklower zap_isoaddr(dst, host); 66037469Ssklower zap_isoaddr(gte, gateway); 66143334Ssklower if (netmask) { 66243334Ssklower zap_isoaddr(msk, netmask); 66343334Ssklower msk.siso_nlen = 0; 66443334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 66543334Ssklower } 66637469Ssklower 66737469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 66837469Ssklower flags, ret_nrt); 66936392Ssklower } 67036392Ssklower 67136392Ssklower /* 67236392Ssklower * FUNCTION: snpac_addrt 67336392Ssklower * 67436392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 67536392Ssklower * 67636392Ssklower * RETURNS: nothing 67736392Ssklower * 67836392Ssklower * SIDE EFFECTS: 67936392Ssklower * 68036392Ssklower * NOTES: If a cache entry exists for gateway, then 68136392Ssklower * make a routing entry (host, gateway) and associate 68236392Ssklower * with gateway. 68336392Ssklower * 68436392Ssklower * If a route already exists and is different, first delete 68536392Ssklower * it. 68636392Ssklower * 68736392Ssklower * This could be made more efficient by checking 68836392Ssklower * the existing route before adding a new one. 68936392Ssklower */ 69039950Ssklower snpac_addrt(ifp, host, gateway, netmask) 69139950Ssklower struct ifnet *ifp; 69239950Ssklower struct iso_addr *host, *gateway, *netmask; 69336392Ssklower { 69437469Ssklower register struct iso_addr *r; 69536392Ssklower 69643071Ssklower zap_isoaddr(dst, host); 69743071Ssklower zap_isoaddr(gte, gateway); 69843071Ssklower if (netmask) { 69943334Ssklower zap_isoaddr(msk, netmask); 70043334Ssklower msk.siso_nlen = 0; 70143334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 70243071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 70343071Ssklower } else 70443071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 70543071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 70636392Ssklower } 70736392Ssklower #endif ISO 708