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*43071Ssklower /* @(#)iso_snpac.c 7.7 (Berkeley) 06/09/90 */ 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" 39*43071Ssklower #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" 4936392Ssklower 5036392Ssklower #include "../net/if.h" 51*43071Ssklower #include "../net/if_dl.h" 5236392Ssklower #include "../net/route.h" 5336392Ssklower 5437469Ssklower #include "iso.h" 5537469Ssklower #include "iso_var.h" 5637469Ssklower #include "iso_snpac.h" 5737469Ssklower #include "clnp.h" 5837469Ssklower #include "clnp_stat.h" 5938841Ssklower #include "esis.h" 6037469Ssklower #include "argo_debug.h" 6136392Ssklower 6236392Ssklower #define SNPAC_BSIZ 20 /* bucket size */ 6336392Ssklower #define SNPAC_NB 13 /* number of buckets */ 6436392Ssklower #define SNPAC_SIZE (SNPAC_BSIZ * SNPAC_NB) 6536392Ssklower struct snpa_cache iso_snpac[SNPAC_SIZE]; 6637469Ssklower u_int iso_snpac_size = SNPAC_SIZE;/* for iso_map command */ 6736392Ssklower int iso_systype = SNPA_ES; /* default to be an ES */ 6836392Ssklower 6937469Ssklower struct sockaddr_iso blank_siso = {sizeof(blank_siso), AF_ISO}; 7037469Ssklower extern u_long iso_hashchar(); 7137469Ssklower static struct sockaddr_iso 7237469Ssklower dst = {sizeof(dst), AF_ISO}, 7337469Ssklower gte = {sizeof(dst), AF_ISO}, 7437469Ssklower src = {sizeof(dst), AF_ISO}, 7537469Ssklower msk = {sizeof(dst), AF_ISO}, 7637469Ssklower zmk = {1}; 7737469Ssklower #define zsi blank_siso 7837469Ssklower #define zero_isoa zsi.siso_addr 7937469Ssklower #define zap_isoaddr(a, b) (bzero((caddr_t)&a.siso_addr, sizeof(*r)), \ 8037469Ssklower ((r = b) && bcopy((caddr_t)r, (caddr_t)&a.siso_addr, 1 + (r)->isoa_len))) 8137469Ssklower #define S(x) ((struct sockaddr *)&(x)) 8237469Ssklower 83*43071Ssklower static struct sockaddr_dl blank_dl = {sizeof(blank_dl), AF_LINK}; 84*43071Ssklower static struct sockaddr_dl gte_dl; 85*43071Ssklower #define zap_linkaddr(a, b, c, i) \ 86*43071Ssklower (*a = blank_dl, bcopy(b, a->sdl_data, a->sdl_alen = c), a->sdl_index = i) 8736392Ssklower 8836392Ssklower /* 8936392Ssklower * We only keep track of a single IS at a time. 9036392Ssklower */ 91*43071Ssklower struct rtentry *known_is; 9236392Ssklower 9336392Ssklower /* 9436392Ssklower * Addresses taken from NBS agreements, December 1987. 9536392Ssklower * 9636392Ssklower * These addresses assume on-the-wire transmission of least significant 9736392Ssklower * bit first. This is the method used by 802.3. When these 9836392Ssklower * addresses are passed to the token ring driver, (802.5), they 9936392Ssklower * must be bit-swaped because 802.5 transmission order is MSb first. 10036392Ssklower * 10136392Ssklower * Furthermore, according to IBM Austin, these addresses are not 10236392Ssklower * true token ring multicast addresses. More work is necessary 10336392Ssklower * to get multicast to work right on token ring. 10436392Ssklower * 10536392Ssklower * Currently, the token ring driver does not handle multicast, so 10636392Ssklower * these addresses are converted into the broadcast address in 10736392Ssklower * lan_output() That means that if these multicast addresses change 10836392Ssklower * the token ring driver must be altered. 10936392Ssklower */ 11036392Ssklower struct snpa_cache all_es = { 11136392Ssklower { { 0x0 }, /* sc_nsap */ 11236392Ssklower 6, /* sc_len */ 11336392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }, /* sc_snpa */ 11436392Ssklower SNPA_VALID, /* sc_flags */ 11536392Ssklower 0 } /* sc_ht */ 11636392Ssklower }; 11736392Ssklower struct snpa_cache all_is = { 11836392Ssklower { { 0x0 }, /* sc_nsap */ 11936392Ssklower 6, /* sc_len */ 12036392Ssklower { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }, /* sc_snpa */ 12136392Ssklower SNPA_VALID, /* sc_flags */ 12236392Ssklower 0 } /* sc_ht */ 12336392Ssklower }; 124*43071Ssklower char all_es_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x04 }; /* sc_snpa */ 125*43071Ssklower char all_is_snpa[] = { 0x09, 0x00, 0x2b, 0x00, 0x00, 0x05 }; /* sc_snpa */ 12636392Ssklower 127*43071Ssklower union sockunion { 128*43071Ssklower struct sockaddr_iso siso; 129*43071Ssklower struct sockaddr_dl sdl; 130*43071Ssklower struct sockaddr sa; 131*43071Ssklower }; 13236392Ssklower 13336392Ssklower /* 134*43071Ssklower * FUNCTION: llc_rtrequest 135*43071Ssklower * 136*43071Ssklower * PURPOSE: Manage routing table entries specific to LLC for ISO. 137*43071Ssklower * 138*43071Ssklower * NOTES: This does a lot of obscure magic; 139*43071Ssklower */ 140*43071Ssklower llc_rtrequest(req, rt, sa) 141*43071Ssklower int req; 142*43071Ssklower register struct rtentry *rt; 143*43071Ssklower struct sockaddr *sa; 144*43071Ssklower { 145*43071Ssklower register union sockunion *gate = (union sockunion *)rt->rt_gateway; 146*43071Ssklower register struct llinfo_llc *lc = (struct llinfo_llc *)rt->rt_llinfo, *lc2; 147*43071Ssklower struct rtentry *rt2; 148*43071Ssklower struct ifnet *ifp = rt->rt_ifp; 149*43071Ssklower int addrlen = ifp->if_addrlen; 150*43071Ssklower 151*43071Ssklower if (lc == 0) 152*43071Ssklower panic("llc_rtrequest 1"); 153*43071Ssklower switch (req) { 154*43071Ssklower case RTM_RESOLVE: 155*43071Ssklower if (gate->sdl.sdl_family == AF_LINK) { 156*43071Ssklower /* We have just cloned a route to a host presumed to be on 157*43071Ssklower our local net */ 158*43071Ssklower gate->sdl.sdl_alen = 0; 159*43071Ssklower } 160*43071Ssklower /* Fall Through */ 161*43071Ssklower case RTM_ADD: 162*43071Ssklower lc->lc_rt = rt; 163*43071Ssklower if (rt->rt_flags & RTF_CLONING) { 164*43071Ssklower /* 165*43071Ssklower * Case 1: This route may come from a route to iface with mask 166*43071Ssklower * or from a default IS. 167*43071Ssklower */ 168*43071Ssklower rt->rt_gateway = ifp->if_addrlist->ifa_addr; 169*43071Ssklower } else if ((rt->rt_flags & RTF_GATEWAY == 0) && 170*43071Ssklower gate->sdl.sdl_family == AF_LINK) { 171*43071Ssklower /* 172*43071Ssklower * Case 2: This route may come from ESIS or a manual route 173*43071Ssklower * add with a LL address. 174*43071Ssklower */ 175*43071Ssklower insque(lc, &llinfo_llc); 176*43071Ssklower if (gate->sdl.sdl_alen == sizeof(struct esis_req) + addrlen) { 177*43071Ssklower gate->sdl.sdl_alen -= sizeof(struct esis_req); 178*43071Ssklower bcopy(addrlen + LLADDR(&gate->sdl), 179*43071Ssklower (caddr_t)&lc->lc_er, sizeof(lc->lc_er)); 180*43071Ssklower } else if (gate->sdl.sdl_alen == addrlen) 181*43071Ssklower lc->lc_flags = (SNPA_ES | SNPA_VALID | SNPA_PERM); 182*43071Ssklower } else { 183*43071Ssklower /* 184*43071Ssklower * Case 3: Told to add route via a gateway; 185*43071Ssklower * try to provoke LL route to exist for gateway by cloning. 186*43071Ssklower */ 187*43071Ssklower if (gate->siso.siso_family == AF_ISO && 188*43071Ssklower (rt->rt_flags & RTF_GATEWAY) && 189*43071Ssklower (rt2 = rtalloc1(&gate->sa, 1)) && 190*43071Ssklower (lc2 = (struct llinfo_llc *)rt2->rt_llinfo)) { 191*43071Ssklower lc->lc_rtgate = rt2; 192*43071Ssklower rt2->rt_use++; 193*43071Ssklower if (lc2->lc_rtgate == 0) { 194*43071Ssklower lc->lc_prev = lc->lc_next = lc; 195*43071Ssklower lc2->lc_rtgate = rt; 196*43071Ssklower rt->rt_use++; 197*43071Ssklower } else { 198*43071Ssklower if (lc2->lc_rtgate->rt_llinfo == 0) 199*43071Ssklower panic("llc_rtrequest 2"); 200*43071Ssklower insque(lc, lc2->lc_rtgate->rt_llinfo); 201*43071Ssklower } 202*43071Ssklower } 203*43071Ssklower } 204*43071Ssklower break; 205*43071Ssklower case RTM_DELETE: 206*43071Ssklower if (rt->rt_flags & RTF_GATEWAY) { 207*43071Ssklower if (rt2 = lc->lc_rtgate) { 208*43071Ssklower if ((lc2 = (struct llinfo_llc *)rt2->rt_llinfo) && 209*43071Ssklower (lc2->lc_rtgate == rt)) { 210*43071Ssklower rt->rt_use--; 211*43071Ssklower lc2->lc_rtgate = (lc->lc_next != lc->lc_prev) ? 212*43071Ssklower lc->lc_next->lc_rt : 0; 213*43071Ssklower } 214*43071Ssklower RTFREE(rt2); 215*43071Ssklower } 216*43071Ssklower } else { 217*43071Ssklower if ((rt2 = lc->lc_rtgate) && 218*43071Ssklower (lc2 == (struct llinfo_llc *)rt2->rt_llinfo)) { 219*43071Ssklower struct llinfo_llc *head = lc2; 220*43071Ssklower do { 221*43071Ssklower rt->rt_use--; 222*43071Ssklower lc2->lc_rtgate = 0; 223*43071Ssklower lc2 = lc2->lc_next; 224*43071Ssklower } while (lc2 != head); 225*43071Ssklower } 226*43071Ssklower } 227*43071Ssklower if (lc->lc_next) 228*43071Ssklower remque(lc); 229*43071Ssklower break; 230*43071Ssklower } 231*43071Ssklower } 232*43071Ssklower /* 23336392Ssklower * FUNCTION: iso_snparesolve 23436392Ssklower * 23536392Ssklower * PURPOSE: Resolve an iso address into snpa address 23636392Ssklower * 23736392Ssklower * RETURNS: 0 if addr is resolved 23836392Ssklower * errno if addr is unknown 23936392Ssklower * 24036392Ssklower * SIDE EFFECTS: 24136392Ssklower * 242*43071Ssklower * NOTES: Now that we have folded the snpa cache into the routing 243*43071Ssklower * table, we know there is no snpa address known for this 244*43071Ssklower * destination. If we know of a default IS, then the address 245*43071Ssklower * of the IS is returned. If no IS is known, then return the 246*43071Ssklower * multi-cast address for "all ES" for this interface. 24736392Ssklower * 24836392Ssklower * NB: the last case described above constitutes the 24936392Ssklower * query configuration function 9542, sec 6.5 25036392Ssklower * A mechanism is needed to prevent this function from 25136392Ssklower * being invoked if the system is an IS. 25236392Ssklower */ 25337469Ssklower iso_snparesolve(ifp, dest, snpa, snpa_len) 254*43071Ssklower struct ifnet *ifp; /* outgoing interface */ 255*43071Ssklower struct sockaddr_iso *dest; /* destination */ 256*43071Ssklower caddr_t snpa; /* RESULT: snpa to be used */ 257*43071Ssklower int *snpa_len; /* RESULT: length of snpa */ 25836392Ssklower { 259*43071Ssklower struct llinfo_llc *sc; /* ptr to snpa table entry */ 260*43071Ssklower caddr_t found_snpa; 261*43071Ssklower int addrlen; 26236392Ssklower 26336392Ssklower /* 26436392Ssklower * This hack allows us to send esis packets that have the destination snpa 26536392Ssklower * addresss embedded in the destination nsap address 26636392Ssklower */ 267*43071Ssklower if (dest->siso_data[0] == AFI_SNA) { 26836392Ssklower /* 26936392Ssklower * This is a subnetwork address. Return it immediately 27036392Ssklower */ 27136392Ssklower IFDEBUG(D_SNPA) 27236392Ssklower printf("iso_snparesolve: return SN address\n"); 27336392Ssklower ENDDEBUG 274*43071Ssklower addrlen = dest->siso_nlen - 1; /* subtract size of AFI */ 275*43071Ssklower found_snpa = (caddr_t) dest->siso_data + 1; 27636392Ssklower /* 277*43071Ssklower * If we are an IS, we can't do much with the packet; 278*43071Ssklower * Check if we know about an IS. 27936392Ssklower */ 280*43071Ssklower } else if (iso_systype != SNPA_IS && known_is != 0 && 281*43071Ssklower (sc = (struct llinfo_llc *)known_is->rt_llinfo) && 282*43071Ssklower (sc->lc_flags & SNPA_VALID)) { 283*43071Ssklower register struct sockaddr_dl *sdl = 284*43071Ssklower (struct sockaddr_dl *)(known_is->rt_gateway); 285*43071Ssklower found_snpa = LLADDR(sdl); 286*43071Ssklower addrlen = sdl->sdl_alen; 287*43071Ssklower } else if (ifp->if_flags & IFF_BROADCAST) { 288*43071Ssklower /* 289*43071Ssklower * no IS, no match. Return "all es" multicast address for this 290*43071Ssklower * interface, as per Query Configuration Function (9542 sec 6.5) 291*43071Ssklower * 292*43071Ssklower * Note: there is a potential problem here. If the destination 293*43071Ssklower * is on the subnet and it does not respond with a ESH, but 294*43071Ssklower * does send back a TP CC, a connection could be established 295*43071Ssklower * where we always transmit the CLNP packet to "all es" 29636392Ssklower */ 297*43071Ssklower addrlen = ifp->if_addrlen; 298*43071Ssklower found_snpa = (caddr_t)all_es_snpa; 299*43071Ssklower } else 300*43071Ssklower return (ENETUNREACH); 301*43071Ssklower bcopy(found_snpa, snpa, *snpa_len = addrlen); 30236392Ssklower return (0); 30336392Ssklower } 30436392Ssklower 30536392Ssklower 30636392Ssklower /* 30736392Ssklower * FUNCTION: snpac_free 30836392Ssklower * 30936392Ssklower * PURPOSE: free an entry in the iso address map table 31036392Ssklower * 31136392Ssklower * RETURNS: nothing 31236392Ssklower * 31336392Ssklower * SIDE EFFECTS: 31436392Ssklower * 31536392Ssklower * NOTES: If there is a route entry associated with cache 31636392Ssklower * entry, then delete that as well 31736392Ssklower */ 318*43071Ssklower snpac_free(lc) 319*43071Ssklower register struct llinfo_llc *lc; /* entry to free */ 32036392Ssklower { 321*43071Ssklower register struct rtentry *rt = lc->lc_rt; 32237469Ssklower register struct iso_addr *r; 32336392Ssklower 324*43071Ssklower if (known_is == rt) 325*43071Ssklower known_is = 0; 326*43071Ssklower if (rt && (rt->rt_flags & RTF_UP) && 327*43071Ssklower (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED))) { 32837469Ssklower RTFREE(rt); 32937469Ssklower rtrequest(RTM_DELETE, rt_key(rt), rt->rt_gateway, rt_mask(rt), 33037469Ssklower rt->rt_flags, (struct rtentry **)0); 33137469Ssklower RTFREE(rt); 33236392Ssklower } 33336392Ssklower } 33436392Ssklower 33536392Ssklower /* 33636392Ssklower * FUNCTION: snpac_add 33736392Ssklower * 33836392Ssklower * PURPOSE: Add an entry to the snpa cache 33936392Ssklower * 34036392Ssklower * RETURNS: 34136392Ssklower * 34236392Ssklower * SIDE EFFECTS: 34336392Ssklower * 34436392Ssklower * NOTES: If entry already exists, then update holding time. 34536392Ssklower */ 346*43071Ssklower snpac_add(ifp, nsap, snpa, type, ht) 34736392Ssklower struct ifnet *ifp; /* interface info is related to */ 34836392Ssklower struct iso_addr *nsap; /* nsap to add */ 34936392Ssklower caddr_t snpa; /* translation */ 35036392Ssklower char type; /* SNPA_IS or SNPA_ES */ 35137469Ssklower u_short ht; /* holding time (in seconds) */ 35236392Ssklower { 353*43071Ssklower register struct llinfo_llc *lc; 354*43071Ssklower struct rtentry *rt; 355*43071Ssklower register struct iso_addr *r; /* for zap_isoaddr macro */ 356*43071Ssklower int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); 357*43071Ssklower int new_entry = 0, index = ifp->if_index; 35836392Ssklower 359*43071Ssklower zap_isoaddr(dst, nsap); 360*43071Ssklower rt = rtalloc1(S(dst), 0); 361*43071Ssklower if (rt == 0) { 362*43071Ssklower new_entry = 1; 363*43071Ssklower zap_linkaddr((>e_dl), snpa, snpalen, index); 364*43071Ssklower if (rtrequest(RTM_ADD, S(dst), S(gte_dl), (struct sockaddr *)0, 365*43071Ssklower RTF_UP | RTF_HOST, &rt) || rt == 0) 366*43071Ssklower return (0); 367*43071Ssklower } else { 368*43071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; 369*43071Ssklower if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { 370*43071Ssklower int old_sdl_len = sdl->sdl_len; 371*43071Ssklower if (old_sdl_len < sizeof(*sdl)) 372*43071Ssklower return (0); 373*43071Ssklower zap_linkaddr(sdl, snpa, snpalen, index); 374*43071Ssklower sdl->sdl_len = old_sdl_len; 375*43071Ssklower new_entry = 1; 376*43071Ssklower } 37736392Ssklower } 378*43071Ssklower lc = (struct llinfo_llc *)rt->rt_llinfo; 379*43071Ssklower lc->lc_ht = ht; 380*43071Ssklower lc->lc_flags = SNPA_VALID | type; 38136392Ssklower if (type & SNPA_IS) 382*43071Ssklower snpac_logdefis(rt); 38336392Ssklower } 38436392Ssklower 38536392Ssklower /* 38636392Ssklower * FUNCTION: snpac_ioctl 38736392Ssklower * 38836392Ssklower * PURPOSE: Set/Get the system type and esis parameters 38936392Ssklower * 39036392Ssklower * RETURNS: 0 on success, or unix error code 39136392Ssklower * 39236392Ssklower * SIDE EFFECTS: 39336392Ssklower * 39436392Ssklower * NOTES: 39536392Ssklower */ 396*43071Ssklower snpac_ioctl (cmd, data) 39736392Ssklower int cmd; /* ioctl to process */ 39836392Ssklower caddr_t data; /* data for the cmd */ 39936392Ssklower { 40036392Ssklower register struct systype_req *rq = (struct systype_req *)data; 40136392Ssklower extern short esis_holding_time, esis_config_time; 40236392Ssklower 40336392Ssklower IFDEBUG (D_IOCTL) 40436392Ssklower if (cmd == SIOCSSTYPE) 405*43071Ssklower printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", 40636392Ssklower rq->sr_type, rq->sr_holdt, rq->sr_configt); 40736392Ssklower else 408*43071Ssklower printf("snpac_ioctl: cmd get\n"); 40936392Ssklower ENDDEBUG 41036392Ssklower 41136392Ssklower if (cmd == SIOCSSTYPE) { 41237551Smckusick if (suser(u.u_cred, &u.u_acflag)) 41336392Ssklower return(EACCES); 41436392Ssklower if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) 41536392Ssklower return(EINVAL); 41636392Ssklower if (rq->sr_type & SNPA_ES) { 41736392Ssklower iso_systype = SNPA_ES; 41836392Ssklower } else if (rq->sr_type & SNPA_IS) { 41936392Ssklower iso_systype = SNPA_IS; 42036392Ssklower } else { 42136392Ssklower return(EINVAL); 42236392Ssklower } 42336392Ssklower esis_holding_time = rq->sr_holdt; 42436392Ssklower esis_config_time = rq->sr_configt; 42536392Ssklower } else if (cmd == SIOCGSTYPE) { 42636392Ssklower rq->sr_type = iso_systype; 42736392Ssklower rq->sr_holdt = esis_holding_time; 42836392Ssklower rq->sr_configt = esis_config_time; 42936392Ssklower } else { 430*43071Ssklower return (EINVAL); 43136392Ssklower } 432*43071Ssklower return (0); 43336392Ssklower } 43436392Ssklower 43536392Ssklower /* 43636392Ssklower * FUNCTION: snpac_logdefis 43736392Ssklower * 43836392Ssklower * PURPOSE: Mark the IS passed as the default IS 43936392Ssklower * 44036392Ssklower * RETURNS: nothing 44136392Ssklower * 44236392Ssklower * SIDE EFFECTS: 44336392Ssklower * 44436392Ssklower * NOTES: 44536392Ssklower */ 44636392Ssklower snpac_logdefis(sc) 447*43071Ssklower register struct rtentry *sc; 44836392Ssklower { 44937469Ssklower register struct iso_addr *r; 450*43071Ssklower register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; 45137469Ssklower register struct rtentry *rt = rtalloc1((struct sockaddr *)&zsi, 0); 452*43071Ssklower 453*43071Ssklower zap_linkaddr((>e_dl), LLADDR(sdl), sdl->sdl_alen, sdl->sdl_index); 45437469Ssklower if (known_is == 0) 45537469Ssklower known_is = sc; 45637469Ssklower if (known_is != sc) { 457*43071Ssklower rtfree(known_is); 45837469Ssklower known_is = sc; 45936392Ssklower } 46037469Ssklower if (rt == 0) { 461*43071Ssklower rtrequest(RTM_ADD, S(zsi), S(gte_dl), S(zmk), 462*43071Ssklower RTF_DYNAMIC|RTF_GATEWAY|RTF_CLONING, 0); 46337469Ssklower return; 46437469Ssklower } 46537469Ssklower if (rt->rt_flags & (RTF_DYNAMIC | RTF_MODIFIED)) { 466*43071Ssklower *((struct sockaddr_dl *)rt->rt_gateway) = gte_dl; 46737469Ssklower } 46836392Ssklower } 46936392Ssklower 47036392Ssklower /* 47136392Ssklower * FUNCTION: snpac_age 47236392Ssklower * 47336392Ssklower * PURPOSE: Time out snpac entries 47436392Ssklower * 47536392Ssklower * RETURNS: 47636392Ssklower * 47736392Ssklower * SIDE EFFECTS: 47836392Ssklower * 47936392Ssklower * NOTES: When encountering an entry for the first time, snpac_age 48036392Ssklower * may delete up to SNPAC_AGE too many seconds. Ie. 48136392Ssklower * if the entry is added a moment before snpac_age is 48236392Ssklower * called, the entry will immediately have SNPAC_AGE 48336392Ssklower * seconds taken off the holding time, even though 48436392Ssklower * it has only been held a brief moment. 48536392Ssklower * 48636392Ssklower * The proper way to do this is set an expiry timeval 48736392Ssklower * equal to current time + holding time. Then snpac_age 48836392Ssklower * would time out entries where expiry date is older 48936392Ssklower * than the current time. 49036392Ssklower */ 49136392Ssklower snpac_age() 49236392Ssklower { 493*43071Ssklower register struct llinfo_llc *lc; 49436392Ssklower 49536392Ssklower timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); 49636392Ssklower 497*43071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 498*43071Ssklower if (((lc->lc_flags & SNPA_PERM) == 0) && (lc->lc_flags & SNPA_VALID)) { 499*43071Ssklower lc->lc_ht -= SNPAC_AGE; 500*43071Ssklower if (lc->lc_ht > 0) 50136392Ssklower continue; 50236392Ssklower else 503*43071Ssklower snpac_free(lc); 50436392Ssklower } 50536392Ssklower } 50636392Ssklower } 50736392Ssklower 50836392Ssklower /* 50936392Ssklower * FUNCTION: snpac_ownmulti 51036392Ssklower * 51136392Ssklower * PURPOSE: Determine if the snpa address is a multicast address 51236392Ssklower * of the same type as the system. 51336392Ssklower * 51436392Ssklower * RETURNS: true or false 51536392Ssklower * 51636392Ssklower * SIDE EFFECTS: 51736392Ssklower * 51836392Ssklower * NOTES: Used by interface drivers when not in eavesdrop mode 51936392Ssklower * as interm kludge until 52036392Ssklower * real multicast addresses can be configured 52136392Ssklower */ 52236392Ssklower snpac_ownmulti(snpa, len) 523*43071Ssklower caddr_t snpa; 524*43071Ssklower u_int len; 52536392Ssklower { 52637469Ssklower return (((iso_systype & SNPA_ES) && 527*43071Ssklower (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || 52837469Ssklower ((iso_systype & SNPA_IS) && 529*43071Ssklower (!bcmp(snpa, (caddr_t)all_is_snpa, len)))); 53036392Ssklower } 53136392Ssklower 53236392Ssklower /* 53336392Ssklower * FUNCTION: snpac_flushifp 53436392Ssklower * 53536392Ssklower * PURPOSE: Flush entries associated with specific ifp 53636392Ssklower * 53736392Ssklower * RETURNS: nothing 53836392Ssklower * 53936392Ssklower * SIDE EFFECTS: 54036392Ssklower * 54136392Ssklower * NOTES: 54236392Ssklower */ 54336392Ssklower snpac_flushifp(ifp) 54436392Ssklower struct ifnet *ifp; 54536392Ssklower { 546*43071Ssklower register struct llinfo_llc *lc; 54736392Ssklower 548*43071Ssklower for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { 549*43071Ssklower if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) 550*43071Ssklower snpac_free(lc); 55136392Ssklower } 55236392Ssklower } 55336392Ssklower 55436392Ssklower /* 55536392Ssklower * FUNCTION: snpac_rtrequest 55636392Ssklower * 55736392Ssklower * PURPOSE: Make a routing request 55836392Ssklower * 55936392Ssklower * RETURNS: nothing 56036392Ssklower * 56136392Ssklower * SIDE EFFECTS: 56236392Ssklower * 56336392Ssklower * NOTES: In the future, this should make a request of a user 56436392Ssklower * level routing daemon. 56536392Ssklower */ 56637469Ssklower snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt) 56736392Ssklower int req; 56837469Ssklower struct iso_addr *host; 56936392Ssklower struct iso_addr *gateway; 57037469Ssklower struct iso_addr *netmask; 57136392Ssklower short flags; 57237469Ssklower struct rtentry **ret_nrt; 57336392Ssklower { 57437469Ssklower register struct iso_addr *r; 57536392Ssklower 57636392Ssklower IFDEBUG(D_SNPA) 57736392Ssklower printf("snpac_rtrequest: "); 57837469Ssklower if (req == RTM_ADD) 57936392Ssklower printf("add"); 58037469Ssklower else if (req == RTM_DELETE) 58136392Ssklower printf("delete"); 58236392Ssklower else 58336392Ssklower printf("unknown command"); 58437469Ssklower printf(" dst: %s\n", clnp_iso_addrp(host)); 58536392Ssklower printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); 58636392Ssklower ENDDEBUG 58736392Ssklower 58836392Ssklower 58937469Ssklower zap_isoaddr(dst, host); 59037469Ssklower zap_isoaddr(gte, gateway); 59137469Ssklower zap_isoaddr(msk, netmask); 59237469Ssklower 59337469Ssklower rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), 59437469Ssklower flags, ret_nrt); 59536392Ssklower } 59636392Ssklower 59736392Ssklower /* 59836392Ssklower * FUNCTION: snpac_addrt 59936392Ssklower * 60036392Ssklower * PURPOSE: Associate a routing entry with an snpac entry 60136392Ssklower * 60236392Ssklower * RETURNS: nothing 60336392Ssklower * 60436392Ssklower * SIDE EFFECTS: 60536392Ssklower * 60636392Ssklower * NOTES: If a cache entry exists for gateway, then 60736392Ssklower * make a routing entry (host, gateway) and associate 60836392Ssklower * with gateway. 60936392Ssklower * 61036392Ssklower * If a route already exists and is different, first delete 61136392Ssklower * it. 61236392Ssklower * 61336392Ssklower * This could be made more efficient by checking 61436392Ssklower * the existing route before adding a new one. 61536392Ssklower */ 61639950Ssklower snpac_addrt(ifp, host, gateway, netmask) 61739950Ssklower struct ifnet *ifp; 61839950Ssklower struct iso_addr *host, *gateway, *netmask; 61936392Ssklower { 62037469Ssklower register struct iso_addr *r; 62136392Ssklower 622*43071Ssklower zap_isoaddr(dst, host); 623*43071Ssklower zap_isoaddr(gte, gateway); 624*43071Ssklower zap_isoaddr(msk, netmask); 625*43071Ssklower if (netmask) { 626*43071Ssklower rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); 627*43071Ssklower } else 628*43071Ssklower rtredirect(S(dst), S(gte), (struct sockaddr *)0, 629*43071Ssklower RTF_DONE | RTF_HOST, S(gte), 0); 63036392Ssklower } 63136392Ssklower #endif ISO 632