149268Sbostic /*- 249268Sbostic * Copyright (c) 1991 The Regents of the University of California. 349268Sbostic * All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*53691Ssklower * @(#)iso_snpac.c 7.18 (Berkeley) 05/27/92 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; 6750230Ssklower extern struct timeval time; 6850230Ssklower extern int esis_config(), hz; 6950230Ssklower 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}, 78*53691Ssklower zmk = {0}; 7937469Ssklower #define zsi blank_siso 8037469Ssklower #define zero_isoa zsi.siso_addr 8150230Ssklower #define zap_isoaddr(a, b) {Bzero(&a.siso_addr, sizeof(*r)); r = b; \ 8250230Ssklower 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; 14048732Ssklower #define LLC_SIZE 3 /* XXXXXX do this right later */ 14143071Ssklower 14243334Ssklower IFDEBUG (D_SNPA) 14343334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 14443334Ssklower ENDDEBUG 14550231Ssklower if (rt->rt_flags & RTF_GATEWAY) 14650231Ssklower return; 14750231Ssklower else switch (req) { 14843071Ssklower case RTM_ADD: 14943334Ssklower /* 15043334Ssklower * Case 1: This route may come from a route to iface with mask 15143334Ssklower * or from a default route. 15243334Ssklower */ 15343071Ssklower if (rt->rt_flags & RTF_CLONING) { 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: 18743334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 18843334Ssklower return; 18943334Ssklower remque(lc); 19043334Ssklower Free(lc); 19143334Ssklower rt->rt_llinfo = 0; 19243334Ssklower rt->rt_flags &= ~RTF_LLINFO; 19343071Ssklower break; 19443071Ssklower } 19548732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 19648732Ssklower rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE; 19748732Ssklower } 19843071Ssklower } 19943071Ssklower /* 20036392Ssklower * FUNCTION: iso_snparesolve 20136392Ssklower * 20236392Ssklower * PURPOSE: Resolve an iso address into snpa address 20336392Ssklower * 20436392Ssklower * RETURNS: 0 if addr is resolved 20536392Ssklower * errno if addr is unknown 20636392Ssklower * 20736392Ssklower * SIDE EFFECTS: 20836392Ssklower * 20943071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 21043071Ssklower * table, we know there is no snpa address known for this 21143071Ssklower * destination. If we know of a default IS, then the address 21243071Ssklower * of the IS is returned. If no IS is known, then return the 21343071Ssklower * multi-cast address for "all ES" for this interface. 21436392Ssklower * 21536392Ssklower * NB: the last case described above constitutes the 21636392Ssklower * query configuration function 9542, sec 6.5 21736392Ssklower * A mechanism is needed to prevent this function from 21836392Ssklower * being invoked if the system is an IS. 21936392Ssklower */ 22037469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 22143071Ssklower struct ifnet *ifp; /* outgoing interface */ 22243071Ssklower struct sockaddr_iso *dest; /* destination */ 22343071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 22443071Ssklower int *snpa_len; /* RESULT: length of snpa */ 22536392Ssklower { 22643071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 22743071Ssklower caddr_t found_snpa; 22843071Ssklower int addrlen; 22936392Ssklower 23036392Ssklower /* 23136392Ssklower * This hack allows us to send esis packets that have the destination snpa 23236392Ssklower * addresss embedded in the destination nsap address 23336392Ssklower */ 23443071Ssklower if (dest->siso_data[0] == AFI_SNA) { 23536392Ssklower /* 23636392Ssklower * This is a subnetwork address. Return it immediately 23736392Ssklower */ 23836392Ssklower IFDEBUG(D_SNPA) 23936392Ssklower printf("iso_snparesolve: return SN address\n"); 24036392Ssklower ENDDEBUG 24143071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 24243071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 24336392Ssklower /* 24443071Ssklower * If we are an IS, we can't do much with the packet; 24543071Ssklower * Check if we know about an IS. 24636392Ssklower */ 24743071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 24843071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 24943071Ssklower (sc->lc_flags & SNPA_VALID)) { 25043071Ssklower register struct sockaddr_dl *sdl = 25143071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 25243071Ssklower found_snpa = LLADDR(sdl); 25343071Ssklower addrlen = sdl->sdl_alen; 25443071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 25543071Ssklower /* 25643071Ssklower * no IS, no match. Return "all es" multicast address for this 25743071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 25843071Ssklower * 25943071Ssklower * Note: there is a potential problem here. If the destination 26043071Ssklower * is on the subnet and it does not respond with a ESH, but 26143071Ssklower * does send back a TP CC, a connection could be established 26243071Ssklower * where we always transmit the CLNP packet to "all es" 26336392Ssklower */ 26443071Ssklower addrlen = ifp->if_addrlen; 26543071Ssklower found_snpa = (caddr_t)all_es_snpa; 26643071Ssklower } else 26743071Ssklower return (ENETUNREACH); 26843071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 26936392Ssklower return (0); 27036392Ssklower } 27136392Ssklower 27236392Ssklower 27336392Ssklower /* 27436392Ssklower * FUNCTION: snpac_free 27536392Ssklower * 27636392Ssklower * PURPOSE: free an entry in the iso address map table 27736392Ssklower * 27836392Ssklower * RETURNS: nothing 27936392Ssklower * 28036392Ssklower * SIDE EFFECTS: 28136392Ssklower * 28236392Ssklower * NOTES: If there is a route entry associated with cache 28336392Ssklower * entry, then delete that as well 28436392Ssklower */ 28543071Ssklower snpac_free(lc) 28643071Ssklower register struct llinfo_llc *lc; /* entry to free */ 28736392Ssklower { 28843071Ssklower register struct rtentry *rt = lc->lc_rt; 28937469Ssklower register struct iso_addr *r; 29036392Ssklower 29143071Ssklower if (known_is == rt) 29243071Ssklower known_is = 0; 29343071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 29443071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 29537469Ssklower RTFREE(rt); 29637469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 29737469Ssklower rt->rt_flags, (struct rtentry **)0); 29837469Ssklower RTFREE(rt); 29936392Ssklower } 30036392Ssklower } 30136392Ssklower 30236392Ssklower /* 30336392Ssklower * FUNCTION: snpac_add 30436392Ssklower * 30536392Ssklower * PURPOSE: Add an entry to the snpa cache 30636392Ssklower * 30736392Ssklower * RETURNS: 30836392Ssklower * 30936392Ssklower * SIDE EFFECTS: 31036392Ssklower * 31136392Ssklower * NOTES: If entry already exists, then update holding time. 31236392Ssklower */ 31343334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 31436392Ssklower struct ifnet *ifp; /* interface info is related to */ 31536392Ssklower struct iso_addr *nsap; /* nsap to add */ 31636392Ssklower caddr_t snpa; /* translation */ 31736392Ssklower char type; /* SNPA_IS or SNPA_ES */ 31837469Ssklower u_short ht; /* holding time (in seconds) */ 31943334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 32036392Ssklower { 32143071Ssklower register struct llinfo_llc *lc; 32243334Ssklower register struct rtentry *rt; 32343334Ssklower struct rtentry *mrt = 0; 32443071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 32543071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 32652625Ssklower int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type; 32736392Ssklower 32843334Ssklower IFDEBUG(D_SNPA) 32943334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 33043334Ssklower ifp, nsap, snpa, type, ht, nsellength); 33143334Ssklower ENDDEBUG 33243071Ssklower zap_isoaddr(dst, nsap); 33343071Ssklower rt = rtalloc1(S(dst), 0); 33443334Ssklower IFDEBUG(D_SNPA) 33543334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 33643334Ssklower ENDDEBUG 33743071Ssklower if (rt == 0) { 33843334Ssklower struct sockaddr *netmask; 33943334Ssklower int flags; 34043334Ssklower add: 34143334Ssklower if (nsellength) { 34243334Ssklower netmask = S(msk); flags = RTF_UP; 34343334Ssklower snpac_fixdstandmask(nsellength); 34443334Ssklower } else { 34543334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 34643334Ssklower } 34743071Ssklower new_entry = 1; 34843071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 34952625Ssklower gte_dl.sdl_type = iftype; 35043334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 35143334Ssklower mrt == 0) 35243071Ssklower return (0); 35343334Ssklower rt = mrt; 35443334Ssklower rt->rt_refcnt--; 35543071Ssklower } else { 35643071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 35743334Ssklower rt->rt_refcnt--; 35843334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 35943334Ssklower goto add; 36043334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 36143334Ssklower if (rt->rt_refcnt == 0) { 36243334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 36343334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 36443334Ssklower rt = 0; 36543334Ssklower goto add; 36643334Ssklower } else { 36743334Ssklower static struct iso_addr nsap2; register char *cp; 36843334Ssklower nsap2 = *nsap; 36943334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 37043334Ssklower while (cp < (char *)(1 + &nsap2)) 37143334Ssklower *cp++ = 0; 37243334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 37343334Ssklower } 37443334Ssklower } 37543071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 37643071Ssklower int old_sdl_len = sdl->sdl_len; 37743334Ssklower if (old_sdl_len < sizeof(*sdl)) { 37847274Ssklower log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 37943071Ssklower return (0); 38043334Ssklower } 38143071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 38243071Ssklower sdl->sdl_len = old_sdl_len; 38352625Ssklower sdl->sdl_type = iftype; 38443071Ssklower new_entry = 1; 38543071Ssklower } 38636392Ssklower } 38743334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 38843334Ssklower panic("snpac_rtrequest"); 38950230Ssklower rt->rt_rmx.rmx_expire = ht + time.tv_sec; 39043071Ssklower lc->lc_flags = SNPA_VALID | type; 391*53691Ssklower if ((type & SNPA_IS) && !(iso_systype & SNPA_IS)) 39243071Ssklower snpac_logdefis(rt); 39343334Ssklower return (new_entry); 39436392Ssklower } 39536392Ssklower 39650230Ssklower static void 39750230Ssklower snpac_fixdstandmask(nsellength) 39843334Ssklower { 39943334Ssklower register char *cp = msk.siso_data, *cplim; 40043334Ssklower 40143334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 40243334Ssklower msk.siso_len = cplim - (char *)&msk; 40343334Ssklower msk.siso_nlen = 0; 40443334Ssklower while (cp < cplim) 40543334Ssklower *cp++ = -1; 40643334Ssklower while (cp < (char *)msk.siso_pad) 40743334Ssklower *cp++ = 0; 40843334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 40943334Ssklower *cp++ = 0; 41043334Ssklower } 41143334Ssklower 41236392Ssklower /* 41336392Ssklower * FUNCTION: snpac_ioctl 41436392Ssklower * 41536392Ssklower * PURPOSE: Set/Get the system type and esis parameters 41636392Ssklower * 41736392Ssklower * RETURNS: 0 on success, or unix error code 41836392Ssklower * 41936392Ssklower * SIDE EFFECTS: 42036392Ssklower * 42136392Ssklower * NOTES: 42236392Ssklower */ 42350230Ssklower snpac_ioctl (so, cmd, data) 42450230Ssklower struct socket *so; 42536392Ssklower int cmd; /* ioctl to process */ 42636392Ssklower caddr_t data; /* data for the cmd */ 42736392Ssklower { 42836392Ssklower register struct systype_req *rq = (struct systype_req *)data; 42936392Ssklower 43043334Ssklower IFDEBUG(D_IOCTL) 43136392Ssklower if (cmd == SIOCSSTYPE) 43243071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 43336392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 43436392Ssklower else 43543071Ssklower printf("snpac_ioctl: cmd get\n"); 43636392Ssklower ENDDEBUG 43736392Ssklower 43836392Ssklower if (cmd == SIOCSSTYPE) { 43950230Ssklower if ((so->so_state & SS_PRIV) == 0) 44050230Ssklower return (EPERM); 44136392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 44236392Ssklower return(EINVAL); 44336392Ssklower if (rq->sr_type & SNPA_ES) { 44436392Ssklower iso_systype = SNPA_ES; 44536392Ssklower } else if (rq->sr_type & SNPA_IS) { 44636392Ssklower iso_systype = SNPA_IS; 44736392Ssklower } else { 44836392Ssklower return(EINVAL); 44936392Ssklower } 45036392Ssklower esis_holding_time = rq->sr_holdt; 45136392Ssklower esis_config_time = rq->sr_configt; 45243423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 45343423Ssklower untimeout(esis_config, (caddr_t)0); 45443423Ssklower esis_esconfig_time = rq->sr_esconfigt; 45543423Ssklower esis_config(); 45643423Ssklower } 45736392Ssklower } else if (cmd == SIOCGSTYPE) { 45836392Ssklower rq->sr_type = iso_systype; 45936392Ssklower rq->sr_holdt = esis_holding_time; 46036392Ssklower rq->sr_configt = esis_config_time; 46143423Ssklower rq->sr_esconfigt = esis_esconfig_time; 46236392Ssklower } else { 46343071Ssklower return (EINVAL); 46436392Ssklower } 46543071Ssklower return (0); 46636392Ssklower } 46736392Ssklower 46836392Ssklower /* 46936392Ssklower * FUNCTION: snpac_logdefis 47036392Ssklower * 47136392Ssklower * PURPOSE: Mark the IS passed as the default IS 47236392Ssklower * 47336392Ssklower * RETURNS: nothing 47436392Ssklower * 47536392Ssklower * SIDE EFFECTS: 47636392Ssklower * 47736392Ssklower * NOTES: 47836392Ssklower */ 47936392Ssklower snpac_logdefis(sc) 48043071Ssklower register struct rtentry *sc; 48136392Ssklower { 48237469Ssklower register struct iso_addr *r; 48343071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 484*53691Ssklower register struct rtentry *rt; 48543071Ssklower 486*53691Ssklower if (known_is == sc || !(sc->rt_flags & RTF_HOST)) 48737469Ssklower return; 488*53691Ssklower if (known_is) { 489*53691Ssklower RTFREE(known_is); 49037469Ssklower } 491*53691Ssklower known_is = sc; 492*53691Ssklower sc->rt_refcnt++; 493*53691Ssklower rt = rtalloc1((struct sockaddr *)&zsi, 0); 494*53691Ssklower if (rt == 0) 495*53691Ssklower rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk), 496*53691Ssklower RTF_DYNAMIC|RTF_GATEWAY, 0); 497*53691Ssklower else { 498*53691Ssklower if ((rt->rt_flags & RTF_DYNAMIC) && 499*53691Ssklower (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0) 500*53691Ssklower rt_setgate(rt, rt_key(rt), rt_key(sc)); 50137469Ssklower } 50236392Ssklower } 50336392Ssklower 50436392Ssklower /* 50536392Ssklower * FUNCTION: snpac_age 50636392Ssklower * 50736392Ssklower * PURPOSE: Time out snpac entries 50836392Ssklower * 50936392Ssklower * RETURNS: 51036392Ssklower * 51136392Ssklower * SIDE EFFECTS: 51236392Ssklower * 51336392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 51436392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 51536392Ssklower * if the entry is added a moment before snpac_age is 51636392Ssklower * called, the entry will immediately have SNPAC_AGE 51736392Ssklower * seconds taken off the holding time, even though 51836392Ssklower * it has only been held a brief moment. 51936392Ssklower * 52036392Ssklower * The proper way to do this is set an expiry timeval 52136392Ssklower * equal to current time + holding time. Then snpac_age 52236392Ssklower * would time out entries where expiry date is older 52336392Ssklower * than the current time. 52436392Ssklower */ 52536392Ssklower snpac_age() 52636392Ssklower { 52750230Ssklower register struct llinfo_llc *lc, *nlc; 52850230Ssklower register struct rtentry *rt; 52936392Ssklower 53036392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 53136392Ssklower 53250230Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) { 53350230Ssklower nlc = lc->lc_next; 534*53691Ssklower if (lc->lc_flags & SNPA_VALID) { 53550230Ssklower rt = lc->lc_rt; 53650230Ssklower if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec) 53750230Ssklower snpac_free(lc); 53836392Ssklower } 53936392Ssklower } 54036392Ssklower } 54136392Ssklower 54236392Ssklower /* 54336392Ssklower * FUNCTION: snpac_ownmulti 54436392Ssklower * 54536392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 54636392Ssklower * of the same type as the system. 54736392Ssklower * 54836392Ssklower * RETURNS: true or false 54936392Ssklower * 55036392Ssklower * SIDE EFFECTS: 55136392Ssklower * 55236392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 55336392Ssklower * as interm kludge until 55436392Ssklower * real multicast addresses can be configured 55536392Ssklower */ 55636392Ssklower snpac_ownmulti(snpa, len) 55743071Ssklower caddr_t snpa; 55843071Ssklower u_int len; 55936392Ssklower { 56037469Ssklower return (((iso_systype & SNPA_ES) && 56143071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 56237469Ssklower ((iso_systype & SNPA_IS) && 56343071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 56436392Ssklower } 56536392Ssklower 56636392Ssklower /* 56736392Ssklower * FUNCTION: snpac_flushifp 56836392Ssklower * 56936392Ssklower * PURPOSE: Flush entries associated with specific ifp 57036392Ssklower * 57136392Ssklower * RETURNS: nothing 57236392Ssklower * 57336392Ssklower * SIDE EFFECTS: 57436392Ssklower * 57536392Ssklower * NOTES: 57636392Ssklower */ 57736392Ssklower snpac_flushifp(ifp) 57836392Ssklower struct ifnet *ifp; 57936392Ssklower { 58043071Ssklower register struct llinfo_llc *lc; 58136392Ssklower 58243071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 58343071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 58443071Ssklower snpac_free(lc); 58536392Ssklower } 58636392Ssklower } 58736392Ssklower 58836392Ssklower /* 58936392Ssklower * FUNCTION: snpac_rtrequest 59036392Ssklower * 59136392Ssklower * PURPOSE: Make a routing request 59236392Ssklower * 59336392Ssklower * RETURNS: nothing 59436392Ssklower * 59536392Ssklower * SIDE EFFECTS: 59636392Ssklower * 59736392Ssklower * NOTES: In the future, this should make a request of a user 59836392Ssklower * level routing daemon. 59936392Ssklower */ 60037469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 60136392Ssklower int req; 60237469Ssklower struct iso_addr *host; 60336392Ssklower struct iso_addr *gateway; 60437469Ssklower struct iso_addr *netmask; 60536392Ssklower short flags; 60637469Ssklower struct rtentry **ret_nrt; 60736392Ssklower { 60837469Ssklower register struct iso_addr *r; 60936392Ssklower 61036392Ssklower IFDEBUG(D_SNPA) 61136392Ssklower printf("snpac_rtrequest: "); 61237469Ssklower if (req == RTM_ADD) 61336392Ssklower printf("add"); 61437469Ssklower else if (req == RTM_DELETE) 61536392Ssklower printf("delete"); 61636392Ssklower else 61736392Ssklower printf("unknown command"); 61837469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 61936392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 62036392Ssklower ENDDEBUG 62136392Ssklower 62236392Ssklower 62337469Ssklower zap_isoaddr(dst, host); 62437469Ssklower zap_isoaddr(gte, gateway); 62543334Ssklower if (netmask) { 62643334Ssklower zap_isoaddr(msk, netmask); 62743334Ssklower msk.siso_nlen = 0; 62843334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 62943334Ssklower } 63037469Ssklower 63137469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 63237469Ssklower flags, ret_nrt); 63336392Ssklower } 63436392Ssklower 63536392Ssklower /* 63636392Ssklower * FUNCTION: snpac_addrt 63736392Ssklower * 63836392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 63936392Ssklower * 64036392Ssklower * RETURNS: nothing 64136392Ssklower * 64236392Ssklower * SIDE EFFECTS: 64336392Ssklower * 64436392Ssklower * NOTES: If a cache entry exists for gateway, then 64536392Ssklower * make a routing entry (host, gateway) and associate 64636392Ssklower * with gateway. 64736392Ssklower * 64836392Ssklower * If a route already exists and is different, first delete 64936392Ssklower * it. 65036392Ssklower * 65136392Ssklower * This could be made more efficient by checking 65236392Ssklower * the existing route before adding a new one. 65336392Ssklower */ 65439950Ssklower snpac_addrt(ifp, host, gateway, netmask) 65539950Ssklower struct ifnet *ifp; 65639950Ssklower struct iso_addr *host, *gateway, *netmask; 65736392Ssklower { 65837469Ssklower register struct iso_addr *r; 65936392Ssklower 66043071Ssklower zap_isoaddr(dst, host); 66143071Ssklower zap_isoaddr(gte, gateway); 66243071Ssklower if (netmask) { 66343334Ssklower zap_isoaddr(msk, netmask); 66443334Ssklower msk.siso_nlen = 0; 66543334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 66643071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 66743071Ssklower } else 66843071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 66943071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 67036392Ssklower } 67136392Ssklower #endif ISO 672