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*48732Ssklower /* @(#)iso_snpac.c 7.12 (Berkeley) 04/26/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" 4947274Ssklower #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; 137*48732Ssklower #define LLC_SIZE 3 /* XXXXXX do this right later */ 13843071Ssklower 13943334Ssklower IFDEBUG (D_SNPA) 14043334Ssklower printf("llc_rtrequest(%d, %x, %x)\n", req, rt, sa); 14143334Ssklower ENDDEBUG 14243334Ssklower if (rt->rt_flags & RTF_GATEWAY) { 14343334Ssklower if (recursing) { 14447274Ssklower log(LOG_DEBUG, "llc_rtrequest: gateway route points to same type %x %x\n", 14543334Ssklower recursing, rt); 14643334Ssklower } else switch (req) { 14743334Ssklower case RTM_RESOLVE: 14843334Ssklower case RTM_ADD: 14943334Ssklower recursing = rt; 15043334Ssklower rt->rt_llinfo = (caddr_t)rtalloc1(&gate->sa, 1); 15143334Ssklower recursing = 0; 152*48732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 153*48732Ssklower rt->rt_rmx.rmx_mtu = 154*48732Ssklower ((rt2 = (struct rtentry *)rt->rt_llinfo) && 155*48732Ssklower (rt2->rt_rmx.rmx_mtu)) ? 156*48732Ssklower rt2->rt_rmx.rmx_mtu : 157*48732Ssklower rt->rt_ifp->if_mtu - LLC_SIZE; 158*48732Ssklower } 15943334Ssklower return; 16043334Ssklower 16143334Ssklower case RTM_DELETE: 16243334Ssklower if (lc) 16343334Ssklower RTFREE((struct rtentry *)lc); 16443334Ssklower rt->rt_llinfo = 0; 16543071Ssklower } 16643334Ssklower } else switch (req) { 16743071Ssklower case RTM_ADD: 16843334Ssklower /* 16943334Ssklower * Case 1: This route may come from a route to iface with mask 17043334Ssklower * or from a default route. 17143334Ssklower */ 17243071Ssklower if (rt->rt_flags & RTF_CLONING) { 17343334Ssklower register struct ifaddr *ifa; 17443334Ssklower register struct sockaddr *sa; 17543334Ssklower for (ifa = ifp->if_addrlist; ifa; ifa->ifa_next) 17643334Ssklower if ((sa = ifa->ifa_addr)->sa_family == AF_LINK) { 17743334Ssklower if (sa->sa_len > gate->sa.sa_len) 17847274Ssklower log(LOG_DEBUG, "llc_rtrequest: cloning address too small\n"); 17943334Ssklower else { 18043334Ssklower Bcopy(sa, gate, gate->sa.sa_len); 18143334Ssklower gate->sdl.sdl_alen = 0; 18243334Ssklower } 183*48732Ssklower break; 18443071Ssklower } 18543334Ssklower if (ifa == 0) 18647274Ssklower log(LOG_DEBUG, "llc_rtrequest: can't find LL ifaddr for iface\n"); 187*48732Ssklower break; 18843071Ssklower } 18943334Ssklower /* FALLTHROUGH */ 19043334Ssklower case RTM_RESOLVE: 19143334Ssklower /* 19243334Ssklower * Case 2: This route may come from cloning, or a manual route 19343334Ssklower * add with a LL address. 19443334Ssklower */ 19543334Ssklower if (gate->sdl.sdl_family != AF_LINK) { 19647274Ssklower log(LOG_DEBUG, "llc_rtrequest: got non-link non-gateway route\n"); 197*48732Ssklower break; 19843334Ssklower } 19943334Ssklower if (lc != 0) 20047274Ssklower log(LOG_DEBUG, "llc_rtrequest: losing old rt_llinfo\n"); 20143334Ssklower R_Malloc(lc, struct llinfo_llc *, sizeof (*lc)); 20243334Ssklower rt->rt_llinfo = (caddr_t)lc; 20343334Ssklower if (lc == 0) { 20447274Ssklower log(LOG_DEBUG, "llc_rtrequest: malloc failed\n"); 205*48732Ssklower break; 20643334Ssklower } 20743334Ssklower Bzero(lc, sizeof(*lc)); 20843334Ssklower lc->lc_rt = rt; 20943334Ssklower rt->rt_flags |= RTF_LLINFO; 21043334Ssklower insque(lc, &llinfo_llc); 21143334Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 21243334Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 21343334Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 21443334Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 21543334Ssklower } else if (gate->sdl.sdl_alen == addrlen) 21643334Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 21743071Ssklower break; 21843071Ssklower case RTM_DELETE: 21943334Ssklower if (lc == 0 || (rt->rt_flags & RTF_CLONING)) 22043334Ssklower return; 22143334Ssklower remque(lc); 22243334Ssklower Free(lc); 22343334Ssklower rt->rt_llinfo = 0; 22443334Ssklower rt->rt_flags &= ~RTF_LLINFO; 22543071Ssklower break; 22643071Ssklower } 227*48732Ssklower if (rt->rt_rmx.rmx_mtu == 0) { 228*48732Ssklower rt->rt_rmx.rmx_mtu = rt->rt_ifp->if_mtu - LLC_SIZE; 229*48732Ssklower } 23043071Ssklower } 23143071Ssklower /* 23236392Ssklower * FUNCTION: iso_snparesolve 23336392Ssklower * 23436392Ssklower * PURPOSE: Resolve an iso address into snpa address 23536392Ssklower * 23636392Ssklower * RETURNS: 0 if addr is resolved 23736392Ssklower * errno if addr is unknown 23836392Ssklower * 23936392Ssklower * SIDE EFFECTS: 24036392Ssklower * 24143071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 24243071Ssklower * table, we know there is no snpa address known for this 24343071Ssklower * destination. If we know of a default IS, then the address 24443071Ssklower * of the IS is returned. If no IS is known, then return the 24543071Ssklower * multi-cast address for "all ES" for this interface. 24636392Ssklower * 24736392Ssklower * NB: the last case described above constitutes the 24836392Ssklower * query configuration function 9542, sec 6.5 24936392Ssklower * A mechanism is needed to prevent this function from 25036392Ssklower * being invoked if the system is an IS. 25136392Ssklower */ 25237469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 25343071Ssklower struct ifnet *ifp; /* outgoing interface */ 25443071Ssklower struct sockaddr_iso *dest; /* destination */ 25543071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 25643071Ssklower int *snpa_len; /* RESULT: length of snpa */ 25736392Ssklower { 25843071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 25943071Ssklower caddr_t found_snpa; 26043071Ssklower int addrlen; 26136392Ssklower 26236392Ssklower /* 26336392Ssklower * This hack allows us to send esis packets that have the destination snpa 26436392Ssklower * addresss embedded in the destination nsap address 26536392Ssklower */ 26643071Ssklower if (dest->siso_data[0] == AFI_SNA) { 26736392Ssklower /* 26836392Ssklower * This is a subnetwork address. Return it immediately 26936392Ssklower */ 27036392Ssklower IFDEBUG(D_SNPA) 27136392Ssklower printf("iso_snparesolve: return SN address\n"); 27236392Ssklower ENDDEBUG 27343071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 27443071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 27536392Ssklower /* 27643071Ssklower * If we are an IS, we can't do much with the packet; 27743071Ssklower * Check if we know about an IS. 27836392Ssklower */ 27943071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 28043071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 28143071Ssklower (sc->lc_flags & SNPA_VALID)) { 28243071Ssklower register struct sockaddr_dl *sdl = 28343071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 28443071Ssklower found_snpa = LLADDR(sdl); 28543071Ssklower addrlen = sdl->sdl_alen; 28643071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 28743071Ssklower /* 28843071Ssklower * no IS, no match. Return "all es" multicast address for this 28943071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 29043071Ssklower * 29143071Ssklower * Note: there is a potential problem here. If the destination 29243071Ssklower * is on the subnet and it does not respond with a ESH, but 29343071Ssklower * does send back a TP CC, a connection could be established 29443071Ssklower * where we always transmit the CLNP packet to "all es" 29536392Ssklower */ 29643071Ssklower addrlen = ifp->if_addrlen; 29743071Ssklower found_snpa = (caddr_t)all_es_snpa; 29843071Ssklower } else 29943071Ssklower return (ENETUNREACH); 30043071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 30136392Ssklower return (0); 30236392Ssklower } 30336392Ssklower 30436392Ssklower 30536392Ssklower /* 30636392Ssklower * FUNCTION: snpac_free 30736392Ssklower * 30836392Ssklower * PURPOSE: free an entry in the iso address map table 30936392Ssklower * 31036392Ssklower * RETURNS: nothing 31136392Ssklower * 31236392Ssklower * SIDE EFFECTS: 31336392Ssklower * 31436392Ssklower * NOTES: If there is a route entry associated with cache 31536392Ssklower * entry, then delete that as well 31636392Ssklower */ 31743071Ssklower snpac_free(lc) 31843071Ssklower register struct llinfo_llc *lc; /* entry to free */ 31936392Ssklower { 32043071Ssklower register struct rtentry *rt = lc->lc_rt; 32137469Ssklower register struct iso_addr *r; 32236392Ssklower 32343071Ssklower if (known_is == rt) 32443071Ssklower known_is = 0; 32543071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 32643071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 32737469Ssklower RTFREE(rt); 32837469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 32937469Ssklower rt->rt_flags, (struct rtentry **)0); 33037469Ssklower RTFREE(rt); 33136392Ssklower } 33236392Ssklower } 33336392Ssklower 33436392Ssklower /* 33536392Ssklower * FUNCTION: snpac_add 33636392Ssklower * 33736392Ssklower * PURPOSE: Add an entry to the snpa cache 33836392Ssklower * 33936392Ssklower * RETURNS: 34036392Ssklower * 34136392Ssklower * SIDE EFFECTS: 34236392Ssklower * 34336392Ssklower * NOTES: If entry already exists, then update holding time. 34436392Ssklower */ 34543334Ssklower snpac_add(ifp, nsap, snpa, type, ht, nsellength) 34636392Ssklower struct ifnet *ifp; /* interface info is related to */ 34736392Ssklower struct iso_addr *nsap; /* nsap to add */ 34836392Ssklower caddr_t snpa; /* translation */ 34936392Ssklower char type; /* SNPA_IS or SNPA_ES */ 35037469Ssklower u_short ht; /* holding time (in seconds) */ 35143334Ssklower int nsellength; /* nsaps may differ only in trailing bytes */ 35236392Ssklower { 35343071Ssklower register struct llinfo_llc *lc; 35443334Ssklower register struct rtentry *rt; 35543334Ssklower struct rtentry *mrt = 0; 35643071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 35743071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 35843071Ssklower int new_entry = 0, index = ifp->if_index; 35936392Ssklower 36043334Ssklower IFDEBUG(D_SNPA) 36143334Ssklower printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", 36243334Ssklower ifp, nsap, snpa, type, ht, nsellength); 36343334Ssklower ENDDEBUG 36443071Ssklower zap_isoaddr(dst, nsap); 36543071Ssklower rt = rtalloc1(S(dst), 0); 36643334Ssklower IFDEBUG(D_SNPA) 36743334Ssklower printf("snpac_add: rtalloc1 returns %x\n", rt); 36843334Ssklower ENDDEBUG 36943071Ssklower if (rt == 0) { 37043334Ssklower struct sockaddr *netmask; 37143334Ssklower int flags; 37243334Ssklower add: 37343334Ssklower if (nsellength) { 37443334Ssklower netmask = S(msk); flags = RTF_UP; 37543334Ssklower snpac_fixdstandmask(nsellength); 37643334Ssklower } else { 37743334Ssklower netmask = 0; flags = RTF_UP | RTF_HOST; 37843334Ssklower } 37943071Ssklower new_entry = 1; 38043071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 38143334Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || 38243334Ssklower mrt == 0) 38343071Ssklower return (0); 38443334Ssklower rt = mrt; 38543334Ssklower rt->rt_refcnt--; 38643071Ssklower } else { 38743071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 38843334Ssklower rt->rt_refcnt--; 38943334Ssklower if ((rt->rt_flags & RTF_LLINFO) == 0) 39043334Ssklower goto add; 39143334Ssklower if (nsellength && (rt->rt_flags & RTF_HOST)) { 39243334Ssklower if (rt->rt_refcnt == 0) { 39343334Ssklower rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, 39443334Ssklower (struct sockaddr *)0, 0, (struct rtentry *)0); 39543334Ssklower rt = 0; 39643334Ssklower goto add; 39743334Ssklower } else { 39843334Ssklower static struct iso_addr nsap2; register char *cp; 39943334Ssklower nsap2 = *nsap; 40043334Ssklower cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; 40143334Ssklower while (cp < (char *)(1 + &nsap2)) 40243334Ssklower *cp++ = 0; 40343334Ssklower (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); 40443334Ssklower } 40543334Ssklower } 40643071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 40743071Ssklower int old_sdl_len = sdl->sdl_len; 40843334Ssklower if (old_sdl_len < sizeof(*sdl)) { 40947274Ssklower log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); 41043071Ssklower return (0); 41143334Ssklower } 41243071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 41343071Ssklower sdl->sdl_len = old_sdl_len; 41443071Ssklower new_entry = 1; 41543071Ssklower } 41636392Ssklower } 41743334Ssklower if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) 41843334Ssklower panic("snpac_rtrequest"); 41943334Ssklower rt->rt_idle = ht; 42043071Ssklower lc->lc_flags = SNPA_VALID | type; 42136392Ssklower if (type & SNPA_IS) 42243071Ssklower snpac_logdefis(rt); 42343334Ssklower return (new_entry); 42436392Ssklower } 42536392Ssklower 42643334Ssklower static snpac_fixdstandmask(nsellength) 42743334Ssklower { 42843334Ssklower register char *cp = msk.siso_data, *cplim; 42943334Ssklower 43043334Ssklower cplim = cp + (dst.siso_nlen -= nsellength); 43143334Ssklower msk.siso_len = cplim - (char *)&msk; 43243334Ssklower msk.siso_nlen = 0; 43343334Ssklower while (cp < cplim) 43443334Ssklower *cp++ = -1; 43543334Ssklower while (cp < (char *)msk.siso_pad) 43643334Ssklower *cp++ = 0; 43743334Ssklower for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) 43843334Ssklower *cp++ = 0; 43943334Ssklower } 44043334Ssklower 44136392Ssklower /* 44236392Ssklower * FUNCTION: snpac_ioctl 44336392Ssklower * 44436392Ssklower * PURPOSE: Set/Get the system type and esis parameters 44536392Ssklower * 44636392Ssklower * RETURNS: 0 on success, or unix error code 44736392Ssklower * 44836392Ssklower * SIDE EFFECTS: 44936392Ssklower * 45036392Ssklower * NOTES: 45136392Ssklower */ 45243071Ssklower snpac_ioctl (cmd, data) 45336392Ssklower int cmd; /* ioctl to process */ 45436392Ssklower caddr_t data; /* data for the cmd */ 45536392Ssklower { 45636392Ssklower register struct systype_req *rq = (struct systype_req *)data; 45736392Ssklower 45843334Ssklower IFDEBUG(D_IOCTL) 45936392Ssklower if (cmd == SIOCSSTYPE) 46043071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 46136392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 46236392Ssklower else 46343071Ssklower printf("snpac_ioctl: cmd get\n"); 46436392Ssklower ENDDEBUG 46536392Ssklower 46636392Ssklower if (cmd == SIOCSSTYPE) { 46737551Smckusick if (suser(u.u_cred, &u.u_acflag)) 46836392Ssklower return(EACCES); 46936392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 47036392Ssklower return(EINVAL); 47136392Ssklower if (rq->sr_type & SNPA_ES) { 47236392Ssklower iso_systype = SNPA_ES; 47336392Ssklower } else if (rq->sr_type & SNPA_IS) { 47436392Ssklower iso_systype = SNPA_IS; 47536392Ssklower } else { 47636392Ssklower return(EINVAL); 47736392Ssklower } 47836392Ssklower esis_holding_time = rq->sr_holdt; 47936392Ssklower esis_config_time = rq->sr_configt; 48043423Ssklower if (esis_esconfig_time != rq->sr_esconfigt) { 48143423Ssklower untimeout(esis_config, (caddr_t)0); 48243423Ssklower esis_esconfig_time = rq->sr_esconfigt; 48343423Ssklower esis_config(); 48443423Ssklower } 48536392Ssklower } else if (cmd == SIOCGSTYPE) { 48636392Ssklower rq->sr_type = iso_systype; 48736392Ssklower rq->sr_holdt = esis_holding_time; 48836392Ssklower rq->sr_configt = esis_config_time; 48943423Ssklower rq->sr_esconfigt = esis_esconfig_time; 49036392Ssklower } else { 49143071Ssklower return (EINVAL); 49236392Ssklower } 49343071Ssklower return (0); 49436392Ssklower } 49536392Ssklower 49636392Ssklower /* 49736392Ssklower * FUNCTION: snpac_logdefis 49836392Ssklower * 49936392Ssklower * PURPOSE: Mark the IS passed as the default IS 50036392Ssklower * 50136392Ssklower * RETURNS: nothing 50236392Ssklower * 50336392Ssklower * SIDE EFFECTS: 50436392Ssklower * 50536392Ssklower * NOTES: 50636392Ssklower */ 50736392Ssklower snpac_logdefis(sc) 50843071Ssklower register struct rtentry *sc; 50936392Ssklower { 51037469Ssklower register struct iso_addr *r; 51143071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 51237469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 51343071Ssklower 51443071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 51537469Ssklower if (known_is == 0) 51637469Ssklower known_is = sc; 51737469Ssklower if (known_is != sc) { 51843071Ssklower rtfree(known_is); 51937469Ssklower known_is = sc; 52036392Ssklower } 52137469Ssklower if (rt == 0) { 52243071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 52343071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 52437469Ssklower return; 52537469Ssklower } 52643334Ssklower rt->rt_refcnt--; 52737469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 52843071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 52937469Ssklower } 53036392Ssklower } 53136392Ssklower 53236392Ssklower /* 53336392Ssklower * FUNCTION: snpac_age 53436392Ssklower * 53536392Ssklower * PURPOSE: Time out snpac entries 53636392Ssklower * 53736392Ssklower * RETURNS: 53836392Ssklower * 53936392Ssklower * SIDE EFFECTS: 54036392Ssklower * 54136392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 54236392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 54336392Ssklower * if the entry is added a moment before snpac_age is 54436392Ssklower * called, the entry will immediately have SNPAC_AGE 54536392Ssklower * seconds taken off the holding time, even though 54636392Ssklower * it has only been held a brief moment. 54736392Ssklower * 54836392Ssklower * The proper way to do this is set an expiry timeval 54936392Ssklower * equal to current time + holding time. Then snpac_age 55036392Ssklower * would time out entries where expiry date is older 55136392Ssklower * than the current time. 55236392Ssklower */ 55336392Ssklower snpac_age() 55436392Ssklower { 55543071Ssklower register struct llinfo_llc *lc; 55636392Ssklower 55736392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 55836392Ssklower 55943071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 56043071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 56143334Ssklower lc->lc_rt->rt_idle -= SNPAC_AGE; 56243334Ssklower if (lc->lc_rt->rt_idle > 0) 56336392Ssklower continue; 56436392Ssklower else 56543071Ssklower snpac_free(lc); 56636392Ssklower } 56736392Ssklower } 56836392Ssklower } 56936392Ssklower 57036392Ssklower /* 57136392Ssklower * FUNCTION: snpac_ownmulti 57236392Ssklower * 57336392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 57436392Ssklower * of the same type as the system. 57536392Ssklower * 57636392Ssklower * RETURNS: true or false 57736392Ssklower * 57836392Ssklower * SIDE EFFECTS: 57936392Ssklower * 58036392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 58136392Ssklower * as interm kludge until 58236392Ssklower * real multicast addresses can be configured 58336392Ssklower */ 58436392Ssklower snpac_ownmulti(snpa, len) 58543071Ssklower caddr_t snpa; 58643071Ssklower u_int len; 58736392Ssklower { 58837469Ssklower return (((iso_systype & SNPA_ES) && 58943071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 59037469Ssklower ((iso_systype & SNPA_IS) && 59143071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 59236392Ssklower } 59336392Ssklower 59436392Ssklower /* 59536392Ssklower * FUNCTION: snpac_flushifp 59636392Ssklower * 59736392Ssklower * PURPOSE: Flush entries associated with specific ifp 59836392Ssklower * 59936392Ssklower * RETURNS: nothing 60036392Ssklower * 60136392Ssklower * SIDE EFFECTS: 60236392Ssklower * 60336392Ssklower * NOTES: 60436392Ssklower */ 60536392Ssklower snpac_flushifp(ifp) 60636392Ssklower struct ifnet *ifp; 60736392Ssklower { 60843071Ssklower register struct llinfo_llc *lc; 60936392Ssklower 61043071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 61143071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 61243071Ssklower snpac_free(lc); 61336392Ssklower } 61436392Ssklower } 61536392Ssklower 61636392Ssklower /* 61736392Ssklower * FUNCTION: snpac_rtrequest 61836392Ssklower * 61936392Ssklower * PURPOSE: Make a routing request 62036392Ssklower * 62136392Ssklower * RETURNS: nothing 62236392Ssklower * 62336392Ssklower * SIDE EFFECTS: 62436392Ssklower * 62536392Ssklower * NOTES: In the future, this should make a request of a user 62636392Ssklower * level routing daemon. 62736392Ssklower */ 62837469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 62936392Ssklower int req; 63037469Ssklower struct iso_addr *host; 63136392Ssklower struct iso_addr *gateway; 63237469Ssklower struct iso_addr *netmask; 63336392Ssklower short flags; 63437469Ssklower struct rtentry **ret_nrt; 63536392Ssklower { 63637469Ssklower register struct iso_addr *r; 63736392Ssklower 63836392Ssklower IFDEBUG(D_SNPA) 63936392Ssklower printf("snpac_rtrequest: "); 64037469Ssklower if (req == RTM_ADD) 64136392Ssklower printf("add"); 64237469Ssklower else if (req == RTM_DELETE) 64336392Ssklower printf("delete"); 64436392Ssklower else 64536392Ssklower printf("unknown command"); 64637469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 64736392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 64836392Ssklower ENDDEBUG 64936392Ssklower 65036392Ssklower 65137469Ssklower zap_isoaddr(dst, host); 65237469Ssklower zap_isoaddr(gte, gateway); 65343334Ssklower if (netmask) { 65443334Ssklower zap_isoaddr(msk, netmask); 65543334Ssklower msk.siso_nlen = 0; 65643334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 65743334Ssklower } 65837469Ssklower 65937469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 66037469Ssklower flags, ret_nrt); 66136392Ssklower } 66236392Ssklower 66336392Ssklower /* 66436392Ssklower * FUNCTION: snpac_addrt 66536392Ssklower * 66636392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 66736392Ssklower * 66836392Ssklower * RETURNS: nothing 66936392Ssklower * 67036392Ssklower * SIDE EFFECTS: 67136392Ssklower * 67236392Ssklower * NOTES: If a cache entry exists for gateway, then 67336392Ssklower * make a routing entry (host, gateway) and associate 67436392Ssklower * with gateway. 67536392Ssklower * 67636392Ssklower * If a route already exists and is different, first delete 67736392Ssklower * it. 67836392Ssklower * 67936392Ssklower * This could be made more efficient by checking 68036392Ssklower * the existing route before adding a new one. 68136392Ssklower */ 68239950Ssklower snpac_addrt(ifp, host, gateway, netmask) 68339950Ssklower struct ifnet *ifp; 68439950Ssklower struct iso_addr *host, *gateway, *netmask; 68536392Ssklower { 68637469Ssklower register struct iso_addr *r; 68736392Ssklower 68843071Ssklower zap_isoaddr(dst, host); 68943071Ssklower zap_isoaddr(gte, gateway); 69043071Ssklower if (netmask) { 69143334Ssklower zap_isoaddr(msk, netmask); 69243334Ssklower msk.siso_nlen = 0; 69343334Ssklower msk.siso_len = msk.siso_pad - (u_char *)&msk; 69443071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 69543071Ssklower } else 69643071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 69743071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 69836392Ssklower } 69936392Ssklower #endif ISO 700