149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*57952Ssklower * @(#)iso_snpac.c 7.22 (Berkeley) 02/12/93 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 4156533Sbostic #include <sys/param.h> 4256533Sbostic #include <sys/systm.h> 4356533Sbostic #include <sys/mbuf.h> 4456533Sbostic #include <sys/domain.h> 4556533Sbostic #include <sys/protosw.h> 4656533Sbostic #include <sys/socket.h> 4756533Sbostic #include <sys/socketvar.h> 4856533Sbostic #include <sys/errno.h> 4956533Sbostic #include <sys/ioctl.h> 5056533Sbostic #include <sys/syslog.h> 5136392Ssklower 5256533Sbostic #include <net/if.h> 5356533Sbostic #include <net/if_dl.h> 5456533Sbostic #include <net/route.h> 5536392Ssklower 5656533Sbostic #include <netiso/iso.h> 5756533Sbostic #include <netiso/iso_var.h> 5856533Sbostic #include <netiso/iso_snpac.h> 5956533Sbostic #include <netiso/clnp.h> 6056533Sbostic #include <netiso/clnp_stat.h> 6156533Sbostic #include <netiso/esis.h> 6256533Sbostic #include <netiso/argo_debug.h> 6336392Ssklower 6436392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6543423Ssklower extern short esis_holding_time, esis_config_time, esis_esconfig_time; 6650230Ssklower extern struct timeval time; 6750230Ssklower extern int esis_config(), hz; 6850230Ssklower static void snpac_fixdstandmask(); 6936392Ssklower 7037469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 7137469Ssklower extern u_long iso_hashchar(); 7237469Ssklower static struct sockaddr_iso 7337469Ssklower dst = {sizeof(dst), AF_ISO}, 7437469Ssklower gte = {sizeof(dst), AF_ISO}, 7537469Ssklower src = {sizeof(dst), AF_ISO}, 7637469Ssklower msk = {sizeof(dst), AF_ISO}, 7753691Ssklower zmk = {0}; 7837469Ssklower #define zsi blank_siso 7937469Ssklower #define zero_isoa zsi.siso_addr 8050230Ssklower #define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \ 8150230Ssklower Bcopy(r, &a.siso_addr, 1 + (r)->isoa_len);} 8237469Ssklower #define S(x) ((struct sockaddr *)&(x)) 8337469Ssklower 8443071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 8543071Ssklower static struct sockaddr_dl gte_dl; 8643071Ssklower #define zap_linkaddr(a, b, c, i) \ 8743071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8836392Ssklower 8936392Ssklower /* 9036392Ssklower * We only keep track of a single IS at a time. 9136392Ssklower */ 9243071Ssklower struct rtentry *known_is; 9336392Ssklower 9436392Ssklower /* 9536392Ssklower * Addresses taken from NBS agreements, December 1987. 9636392Ssklower * 9736392Ssklower * These addresses assume on-the-wire transmission of least significant 9836392Ssklower * bit first. This is the method used by 802.3. When these 9936392Ssklower * addresses are passed to the token ring driver, (802.5), they 10036392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 10136392Ssklower * 10236392Ssklower * Furthermore, according to IBM Austin, these addresses are not 10336392Ssklower * true token ring multicast addresses. More work is necessary 10436392Ssklower * to get multicast to work right on token ring. 10536392Ssklower * 10636392Ssklower * Currently, the token ring driver does not handle multicast, so 10736392Ssklower * these addresses are converted into the broadcast address in 10836392Ssklower * lan_output() That means that if these multicast addresses change 10936392Ssklower * the token ring driver must be altered. 11036392Ssklower */ 11143334Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; 11243334Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; 11345898Ssklower char all_l1is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x14}; 11445898Ssklower char all_l2is_snpa[] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x15}; 11536392Ssklower 11643071Ssklower union sockunion { 11743071Ssklower struct sockaddr_iso siso; 11843071Ssklower struct sockaddr_dl sdl; 11943071Ssklower struct sockaddr sa; 12043071Ssklower }; 12136392Ssklower 12236392Ssklower /* 12343071Ssklower * FUNCTION: llc_rtrequest 12443071Ssklower * 12543071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 12643071Ssklower * 12743071Ssklower * NOTES: This does a lot of obscure magic; 12843071Ssklower */ 12943071Ssklower llc_rtrequest(req, rt, sa) 13043071Ssklower int req; 13143071Ssklower register struct rtentry *rt; 13243071Ssklower struct sockaddr *sa; 13343071Ssklower { 13443071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 13543071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 13643071Ssklower struct rtentry *rt2; 13743071Ssklower struct ifnet *ifp = rt->rt_ifp; 13843071Ssklower int addrlen = ifp->if_addrlen; 13948732Ssklower #define LLC_SIZE 3 /* XXXXXX do this right later */ 14043071Ssklower 14143334Ssklower IFDEBUG (D_SNPA) 14243334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 14343334Ssklower ENDDEBUG 14450231Ssklower if (rt->rt_flags & RTF_GATEWAY) 14550231Ssklower return; 14650231Ssklower else switch (req) { 14743071Ssklower case RTM_ADD: 14843334Ssklower /* 14943334Ssklower * Case 1: This route may come from a route to iface with mask 15043334Ssklower * or from a default route. 15143334Ssklower */ 15243071Ssklower if (rt->rt_flags & RTF_CLONING) { 15354717Ssklower iso_setmcasts(ifp, req); 15450231Ssklower rt_setgate(rt, rt_key(rt), &blank_dl); 15550231Ssklower return; 15643071Ssklower } 15750231Ssklower if (lc != 0) 15850231Ssklower return; /* happens on a route change */ 15943334Ssklower /* FALLTHROUGH */ 16043334Ssklower case RTM_RESOLVE: 16143334Ssklower /* 16243334Ssklower * Case 2: This route may come from cloning, or a manual route 16343334Ssklower * add with a LL address. 16443334Ssklower */ 16543334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 16647274Ssklower log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n"); 16748732Ssklower break; 16843334Ssklower } 16943334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 17043334Ssklower rt->rt_llinfo = (caddr_t)lc; 17143334Ssklower if (lc == 0) { 17247274Ssklower log(LOG_DEBUG, "llc_rtrequest: malloc failed\n"); 17348732Ssklower break; 17443334Ssklower } 17543334Ssklower Bzero(lc, sizeof(*lc)); 17643334Ssklower lc->lc_rt = rt; 17743334Ssklower rt->rt_flags |= RTF_LLINFO; 17843334Ssklower insque(lc, &llinfo_llc); 17943334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 18043334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 18143334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 18243334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 18343334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 18443334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 18543071Ssklower break; 18643071Ssklower case RTM_DELETE: 18754717Ssklower if (rt->rt_flags & RTF_CLONING) 18854717Ssklower iso_setmcasts(ifp, req); 18954717Ssklower if (lc == 0) 19043334Ssklower return; 19143334Ssklower remque(lc); 19243334Ssklower Free(lc); 19343334Ssklower rt->rt_llinfo = 0; 19443334Ssklower rt->rt_flags &= ~RTF_LLINFO; 19543071Ssklower break; 19643071Ssklower } 19748732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 19848732Ssklower rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE; 19948732Ssklower } 20043071Ssklower } 20143071Ssklower /* 20254717Ssklower * FUNCTION: iso_setmcasts 20354717Ssklower * 20454717Ssklower * PURPOSE: Enable/Disable ESIS/ISIS multicast reception on interfaces. 20554717Ssklower * 20654717Ssklower * NOTES: This also does a lot of obscure magic; 20754717Ssklower */ 20854717Ssklower iso_setmcasts(ifp, req) 20954717Ssklower struct ifnet *ifp; 21054717Ssklower int req; 21154717Ssklower { 21254717Ssklower static char *addrlist[] = 21354717Ssklower { all_es_snpa, all_is_snpa, all_l1is_snpa, all_l2is_snpa, 0}; 21454717Ssklower struct ifreq ifr; 21554717Ssklower register caddr_t *cpp; 21654717Ssklower int doreset = 0; 21754717Ssklower 21854717Ssklower bzero((caddr_t)&ifr, sizeof(ifr)); 21955903Ssklower for (cpp = (caddr_t *)addrlist; *cpp; cpp++) { 22054717Ssklower bcopy(*cpp, (caddr_t)ifr.ifr_addr.sa_data, 6); 22154717Ssklower if (req == RTM_ADD) 22254717Ssklower if (ether_addmulti(&ifr, (struct arpcom *)ifp) == ENETRESET) 22354717Ssklower doreset++; 22454717Ssklower else 225*57952Ssklower if (ether_delmulti(&ifr, (struct arpcom *)ifp) == ENETRESET) 22654717Ssklower doreset++; 22754717Ssklower } 228*57952Ssklower if (doreset) { 229*57952Ssklower if (ifp->if_reset) 230*57952Ssklower (*ifp->if_reset)(ifp->if_unit); 231*57952Ssklower else 232*57952Ssklower printf("iso_setmcasts: %s%d needs reseting to receive iso mcasts\n", 233*57952Ssklower ifp->if_name, ifp->if_unit); 234*57952Ssklower } 23554717Ssklower } 23654717Ssklower /* 23736392Ssklower * FUNCTION: iso_snparesolve 23836392Ssklower * 23936392Ssklower * PURPOSE: Resolve an iso address into snpa address 24036392Ssklower * 24136392Ssklower * RETURNS: 0 if addr is resolved 24236392Ssklower * errno if addr is unknown 24336392Ssklower * 24436392Ssklower * SIDE EFFECTS: 24536392Ssklower * 24643071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 24743071Ssklower * table, we know there is no snpa address known for this 24843071Ssklower * destination. If we know of a default IS, then the address 24943071Ssklower * of the IS is returned. If no IS is known, then return the 25043071Ssklower * multi-cast address for "all ES" for this interface. 25136392Ssklower * 25236392Ssklower * NB: the last case described above constitutes the 25336392Ssklower * query configuration function 9542, sec 6.5 25436392Ssklower * A mechanism is needed to prevent this function from 25536392Ssklower * being invoked if the system is an IS. 25636392Ssklower */ 25737469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 25843071Ssklower struct ifnet *ifp; /* outgoing interface */ 25943071Ssklower struct sockaddr_iso *dest; /* destination */ 26043071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 26143071Ssklower int *snpa_len; /* RESULT: length of snpa */ 26236392Ssklower { 26343071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 26443071Ssklower caddr_t found_snpa; 26543071Ssklower int addrlen; 26636392Ssklower 26736392Ssklower /* 26836392Ssklower * This hack allows us to send esis packets that have the destination snpa 26936392Ssklower * addresss embedded in the destination nsap address 27036392Ssklower */ 27143071Ssklower if (dest->siso_data[0] == AFI_SNA) { 27236392Ssklower /* 27336392Ssklower * This is a subnetwork address. Return it immediately 27436392Ssklower */ 27536392Ssklower IFDEBUG(D_SNPA) 27636392Ssklower printf("iso_snparesolve: return SN address\n"); 27736392Ssklower ENDDEBUG 27843071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 27943071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 28036392Ssklower /* 28143071Ssklower * If we are an IS, we can't do much with the packet; 28243071Ssklower * Check if we know about an IS. 28336392Ssklower */ 28443071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 28543071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 28643071Ssklower (sc->lc_flags & SNPA_VALID)) { 28743071Ssklower register struct sockaddr_dl *sdl = 28843071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 28943071Ssklower found_snpa = LLADDR(sdl); 29043071Ssklower addrlen = sdl->sdl_alen; 29143071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 29243071Ssklower /* 29343071Ssklower * no IS, no match. Return "all es" multicast address for this 29443071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 29543071Ssklower * 29643071Ssklower * Note: there is a potential problem here. If the destination 29743071Ssklower * is on the subnet and it does not respond with a ESH, but 29843071Ssklower * does send back a TP CC, a connection could be established 29943071Ssklower * where we always transmit the CLNP packet to "all es" 30036392Ssklower */ 30143071Ssklower addrlen = ifp->if_addrlen; 30243071Ssklower found_snpa = (caddr_t)all_es_snpa; 30343071Ssklower } else 30443071Ssklower return (ENETUNREACH); 30543071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 30636392Ssklower return (0); 30736392Ssklower } 30836392Ssklower 30936392Ssklower 31036392Ssklower /* 31136392Ssklower * FUNCTION: snpac_free 31236392Ssklower * 31336392Ssklower * PURPOSE: free an entry in the iso address map table 31436392Ssklower * 31536392Ssklower * RETURNS: nothing 31636392Ssklower * 31736392Ssklower * SIDE EFFECTS: 31836392Ssklower * 31936392Ssklower * NOTES: If there is a route entry associated with cache 32036392Ssklower * entry, then delete that as well 32136392Ssklower */ 32243071Ssklower snpac_free(lc) 32343071Ssklower register struct llinfo_llc *lc; /* entry to free */ 32436392Ssklower { 32543071Ssklower register struct rtentry *rt = lc->lc_rt; 32637469Ssklower register struct iso_addr *r; 32736392Ssklower 32843071Ssklower if (known_is == rt) 32943071Ssklower known_is = 0; 33043071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 33143071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 33237469Ssklower RTFREE(rt); 33337469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 33437469Ssklower rt->rt_flags, (struct rtentry **)0); 33537469Ssklower RTFREE(rt); 33636392Ssklower } 33736392Ssklower } 33836392Ssklower 33936392Ssklower /* 34036392Ssklower * FUNCTION: snpac_add 34136392Ssklower * 34236392Ssklower * PURPOSE: Add an entry to the snpa cache 34336392Ssklower * 34436392Ssklower * RETURNS: 34536392Ssklower * 34636392Ssklower * SIDE EFFECTS: 34736392Ssklower * 34836392Ssklower * NOTES: If entry already exists, then update holding time. 34936392Ssklower */ 35043334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 35136392Ssklower struct ifnet *ifp; /* interface info is related to */ 35236392Ssklower struct iso_addr *nsap; /* nsap to add */ 35336392Ssklower caddr_t snpa; /* translation */ 35436392Ssklower char type; /* SNPA_IS or SNPA_ES */ 35537469Ssklower u_short ht; /* holding time (in seconds) */ 35643334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 35736392Ssklower { 35843071Ssklower register struct llinfo_llc *lc; 35943334Ssklower register struct rtentry *rt; 36043334Ssklower struct rtentry *mrt = 0; 36143071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 36243071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 36352625Ssklower int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type; 36436392Ssklower 36543334Ssklower IFDEBUG(D_SNPA) 36643334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 36743334Ssklower ifp, nsap, snpa, type, ht, nsellength); 36843334Ssklower ENDDEBUG 36943071Ssklower zap_isoaddr(dst, nsap); 37043071Ssklower rt = rtalloc1(S(dst), 0); 37143334Ssklower IFDEBUG(D_SNPA) 37243334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 37343334Ssklower ENDDEBUG 37443071Ssklower if (rt == 0) { 37543334Ssklower struct sockaddr *netmask; 37643334Ssklower int flags; 37743334Ssklower add: 37843334Ssklower if (nsellength) { 37943334Ssklower netmask = S(msk); flags = RTF_UP; 38043334Ssklower snpac_fixdstandmask(nsellength); 38143334Ssklower } else { 38243334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 38343334Ssklower } 38443071Ssklower new_entry = 1; 38543071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 38652625Ssklower gte_dl.sdl_type = iftype; 38743334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 38843334Ssklower mrt == 0) 38943071Ssklower return (0); 39043334Ssklower rt = mrt; 39143334Ssklower rt->rt_refcnt--; 39243071Ssklower } else { 39343071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 39443334Ssklower rt->rt_refcnt--; 39543334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 39643334Ssklower goto add; 39743334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 39843334Ssklower if (rt->rt_refcnt == 0) { 39943334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 40043334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 40143334Ssklower rt = 0; 40243334Ssklower goto add; 40343334Ssklower } else { 40443334Ssklower static struct iso_addr nsap2; register char *cp; 40543334Ssklower nsap2 = *nsap; 40643334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 40743334Ssklower while (cp < (char *)(1 + &nsap2)) 40843334Ssklower *cp++ = 0; 40943334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 41043334Ssklower } 41143334Ssklower } 41243071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 41343071Ssklower int old_sdl_len = sdl->sdl_len; 41443334Ssklower if (old_sdl_len < sizeof(*sdl)) { 41547274Ssklower log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 41643071Ssklower return (0); 41743334Ssklower } 41843071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 41943071Ssklower sdl->sdl_len = old_sdl_len; 42052625Ssklower sdl->sdl_type = iftype; 42143071Ssklower new_entry = 1; 42243071Ssklower } 42336392Ssklower } 42443334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 42543334Ssklower panic("snpac_rtrequest"); 42650230Ssklower rt->rt_rmx.rmx_expire = ht + time.tv_sec; 42743071Ssklower lc->lc_flags = SNPA_VALID | type; 42853691Ssklower if ((type & SNPA_IS) && !(iso_systype & SNPA_IS)) 42943071Ssklower snpac_logdefis(rt); 43043334Ssklower return (new_entry); 43136392Ssklower } 43236392Ssklower 43350230Ssklower static void 43450230Ssklower snpac_fixdstandmask(nsellength) 43543334Ssklower { 43643334Ssklower register char *cp = msk.siso_data, *cplim; 43743334Ssklower 43843334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 43943334Ssklower msk.siso_len = cplim - (char *)&msk; 44043334Ssklower msk.siso_nlen = 0; 44143334Ssklower while (cp < cplim) 44243334Ssklower *cp++ = -1; 44343334Ssklower while (cp < (char *)msk.siso_pad) 44443334Ssklower *cp++ = 0; 44543334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 44643334Ssklower *cp++ = 0; 44743334Ssklower } 44843334Ssklower 44936392Ssklower /* 45036392Ssklower * FUNCTION: snpac_ioctl 45136392Ssklower * 45236392Ssklower * PURPOSE: Set/Get the system type and esis parameters 45336392Ssklower * 45436392Ssklower * RETURNS: 0 on success, or unix error code 45536392Ssklower * 45636392Ssklower * SIDE EFFECTS: 45736392Ssklower * 45836392Ssklower * NOTES: 45936392Ssklower */ 46050230Ssklower snpac_ioctl (so, cmd, data) 46150230Ssklower struct socket *so; 46236392Ssklower int cmd; /* ioctl to process */ 46336392Ssklower caddr_t data; /* data for the cmd */ 46436392Ssklower { 46536392Ssklower register struct systype_req *rq = (struct systype_req *)data; 46636392Ssklower 46743334Ssklower IFDEBUG(D_IOCTL) 46836392Ssklower if (cmd == SIOCSSTYPE) 46943071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 47036392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 47136392Ssklower else 47243071Ssklower printf("snpac_ioctl: cmd get\n"); 47336392Ssklower ENDDEBUG 47436392Ssklower 47536392Ssklower if (cmd == SIOCSSTYPE) { 47650230Ssklower if ((so->so_state & SS_PRIV) == 0) 47750230Ssklower return (EPERM); 47836392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 47936392Ssklower return(EINVAL); 48036392Ssklower if (rq->sr_type & SNPA_ES) { 48136392Ssklower iso_systype = SNPA_ES; 48236392Ssklower } else if (rq->sr_type & SNPA_IS) { 48336392Ssklower iso_systype = SNPA_IS; 48436392Ssklower } else { 48536392Ssklower return(EINVAL); 48636392Ssklower } 48736392Ssklower esis_holding_time = rq->sr_holdt; 48836392Ssklower esis_config_time = rq->sr_configt; 48943423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 49043423Ssklower untimeout(esis_config, (caddr_t)0); 49143423Ssklower esis_esconfig_time = rq->sr_esconfigt; 49243423Ssklower esis_config(); 49343423Ssklower } 49436392Ssklower } else if (cmd == SIOCGSTYPE) { 49536392Ssklower rq->sr_type = iso_systype; 49636392Ssklower rq->sr_holdt = esis_holding_time; 49736392Ssklower rq->sr_configt = esis_config_time; 49843423Ssklower rq->sr_esconfigt = esis_esconfig_time; 49936392Ssklower } else { 50043071Ssklower return (EINVAL); 50136392Ssklower } 50243071Ssklower return (0); 50336392Ssklower } 50436392Ssklower 50536392Ssklower /* 50636392Ssklower * FUNCTION: snpac_logdefis 50736392Ssklower * 50836392Ssklower * PURPOSE: Mark the IS passed as the default IS 50936392Ssklower * 51036392Ssklower * RETURNS: nothing 51136392Ssklower * 51236392Ssklower * SIDE EFFECTS: 51336392Ssklower * 51436392Ssklower * NOTES: 51536392Ssklower */ 51636392Ssklower snpac_logdefis(sc) 51743071Ssklower register struct rtentry *sc; 51836392Ssklower { 51937469Ssklower register struct iso_addr *r; 52043071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 52153691Ssklower register struct rtentry *rt; 52243071Ssklower 52353691Ssklower if (known_is == sc || !(sc->rt_flags & RTF_HOST)) 52437469Ssklower return; 52553691Ssklower if (known_is) { 52653691Ssklower RTFREE(known_is); 52737469Ssklower } 52853691Ssklower known_is = sc; 52953691Ssklower sc->rt_refcnt++; 53053691Ssklower rt = rtalloc1((struct sockaddr *)&zsi, 0); 53153691Ssklower if (rt == 0) 53253691Ssklower rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk), 53353691Ssklower RTF_DYNAMIC|RTF_GATEWAY, 0); 53453691Ssklower else { 53553691Ssklower if ((rt->rt_flags & RTF_DYNAMIC) && 53653691Ssklower (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0) 53753691Ssklower rt_setgate(rt, rt_key(rt), rt_key(sc)); 53837469Ssklower } 53936392Ssklower } 54036392Ssklower 54136392Ssklower /* 54236392Ssklower * FUNCTION: snpac_age 54336392Ssklower * 54436392Ssklower * PURPOSE: Time out snpac entries 54536392Ssklower * 54636392Ssklower * RETURNS: 54736392Ssklower * 54836392Ssklower * SIDE EFFECTS: 54936392Ssklower * 55036392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 55136392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 55236392Ssklower * if the entry is added a moment before snpac_age is 55336392Ssklower * called, the entry will immediately have SNPAC_AGE 55436392Ssklower * seconds taken off the holding time, even though 55536392Ssklower * it has only been held a brief moment. 55636392Ssklower * 55736392Ssklower * The proper way to do this is set an expiry timeval 55836392Ssklower * equal to current time + holding time. Then snpac_age 55936392Ssklower * would time out entries where expiry date is older 56036392Ssklower * than the current time. 56136392Ssklower */ 56236392Ssklower snpac_age() 56336392Ssklower { 56450230Ssklower register struct llinfo_llc *lc, *nlc; 56550230Ssklower register struct rtentry *rt; 56636392Ssklower 56736392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 56836392Ssklower 56950230Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) { 57050230Ssklower nlc = lc->lc_next; 57153691Ssklower if (lc->lc_flags & SNPA_VALID) { 57250230Ssklower rt = lc->lc_rt; 57350230Ssklower if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec) 57450230Ssklower snpac_free(lc); 57536392Ssklower } 57636392Ssklower } 57736392Ssklower } 57836392Ssklower 57936392Ssklower /* 58036392Ssklower * FUNCTION: snpac_ownmulti 58136392Ssklower * 58236392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 58336392Ssklower * of the same type as the system. 58436392Ssklower * 58536392Ssklower * RETURNS: true or false 58636392Ssklower * 58736392Ssklower * SIDE EFFECTS: 58836392Ssklower * 58936392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 59036392Ssklower * as interm kludge until 59136392Ssklower * real multicast addresses can be configured 59236392Ssklower */ 59336392Ssklower snpac_ownmulti(snpa, len) 59443071Ssklower caddr_t snpa; 59543071Ssklower u_int len; 59636392Ssklower { 59737469Ssklower return (((iso_systype & SNPA_ES) && 59843071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 59937469Ssklower ((iso_systype & SNPA_IS) && 60043071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 60136392Ssklower } 60236392Ssklower 60336392Ssklower /* 60436392Ssklower * FUNCTION: snpac_flushifp 60536392Ssklower * 60636392Ssklower * PURPOSE: Flush entries associated with specific ifp 60736392Ssklower * 60836392Ssklower * RETURNS: nothing 60936392Ssklower * 61036392Ssklower * SIDE EFFECTS: 61136392Ssklower * 61236392Ssklower * NOTES: 61336392Ssklower */ 61436392Ssklower snpac_flushifp(ifp) 61536392Ssklower struct ifnet *ifp; 61636392Ssklower { 61743071Ssklower register struct llinfo_llc *lc; 61836392Ssklower 61943071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 62043071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 62143071Ssklower snpac_free(lc); 62236392Ssklower } 62336392Ssklower } 62436392Ssklower 62536392Ssklower /* 62636392Ssklower * FUNCTION: snpac_rtrequest 62736392Ssklower * 62836392Ssklower * PURPOSE: Make a routing request 62936392Ssklower * 63036392Ssklower * RETURNS: nothing 63136392Ssklower * 63236392Ssklower * SIDE EFFECTS: 63336392Ssklower * 63436392Ssklower * NOTES: In the future, this should make a request of a user 63536392Ssklower * level routing daemon. 63636392Ssklower */ 63737469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 63836392Ssklower int req; 63937469Ssklower struct iso_addr *host; 64036392Ssklower struct iso_addr *gateway; 64137469Ssklower struct iso_addr *netmask; 64236392Ssklower short flags; 64337469Ssklower struct rtentry **ret_nrt; 64436392Ssklower { 64537469Ssklower register struct iso_addr *r; 64636392Ssklower 64736392Ssklower IFDEBUG(D_SNPA) 64836392Ssklower printf("snpac_rtrequest: "); 64937469Ssklower if (req == RTM_ADD) 65036392Ssklower printf("add"); 65137469Ssklower else if (req == RTM_DELETE) 65236392Ssklower printf("delete"); 65336392Ssklower else 65436392Ssklower printf("unknown command"); 65537469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 65636392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 65736392Ssklower ENDDEBUG 65836392Ssklower 65936392Ssklower 66037469Ssklower zap_isoaddr(dst, host); 66137469Ssklower zap_isoaddr(gte, gateway); 66243334Ssklower if (netmask) { 66343334Ssklower zap_isoaddr(msk, netmask); 66443334Ssklower msk.siso_nlen = 0; 66543334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 66643334Ssklower } 66737469Ssklower 66837469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 66937469Ssklower flags, ret_nrt); 67036392Ssklower } 67136392Ssklower 67236392Ssklower /* 67336392Ssklower * FUNCTION: snpac_addrt 67436392Ssklower * 67536392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 67636392Ssklower * 67736392Ssklower * RETURNS: nothing 67836392Ssklower * 67936392Ssklower * SIDE EFFECTS: 68036392Ssklower * 68136392Ssklower * NOTES: If a cache entry exists for gateway, then 68236392Ssklower * make a routing entry (host, gateway) and associate 68336392Ssklower * with gateway. 68436392Ssklower * 68536392Ssklower * If a route already exists and is different, first delete 68636392Ssklower * it. 68736392Ssklower * 68836392Ssklower * This could be made more efficient by checking 68936392Ssklower * the existing route before adding a new one. 69036392Ssklower */ 69139950Ssklower snpac_addrt(ifp, host, gateway, netmask) 69239950Ssklower struct ifnet *ifp; 69339950Ssklower struct iso_addr *host, *gateway, *netmask; 69436392Ssklower { 69537469Ssklower register struct iso_addr *r; 69636392Ssklower 69743071Ssklower zap_isoaddr(dst, host); 69843071Ssklower zap_isoaddr(gte, gateway); 69943071Ssklower if (netmask) { 70043334Ssklower zap_isoaddr(msk, netmask); 70143334Ssklower msk.siso_nlen = 0; 70243334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 70343071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 70443071Ssklower } else 70543071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 70643071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 70736392Ssklower } 70836392Ssklower #endif ISO 709