📄 iso_snpac.c
字号:
* * RETURNS: * * SIDE EFFECTS: * * NOTES: If entry already exists, then update holding time. */snpac_add(ifp, nsap, snpa, type, ht, nsellength)struct ifnet *ifp; /* interface info is related to */struct iso_addr *nsap; /* nsap to add */caddr_t snpa; /* translation */char type; /* SNPA_IS or SNPA_ES */u_short ht; /* holding time (in seconds) */int nsellength; /* nsaps may differ only in trailing bytes */{ register struct llinfo_llc *lc; register struct rtentry *rt; struct rtentry *mrt = 0; register struct iso_addr *r; /* for zap_isoaddr macro */ int snpalen = min(ifp->if_addrlen, MAX_SNPALEN); int new_entry = 0, index = ifp->if_index, iftype = ifp->if_type; IFDEBUG(D_SNPA) printf("snpac_add(%x, %x, %x, %x, %x, %x)\n", ifp, nsap, snpa, type, ht, nsellength); ENDDEBUG zap_isoaddr(dst, nsap); rt = rtalloc1(S(dst), 0); IFDEBUG(D_SNPA) printf("snpac_add: rtalloc1 returns %x\n", rt); ENDDEBUG if (rt == 0) { struct sockaddr *netmask; int flags; add: if (nsellength) { netmask = S(msk); flags = RTF_UP; snpac_fixdstandmask(nsellength); } else { netmask = 0; flags = RTF_UP | RTF_HOST; } new_entry = 1; zap_linkaddr((>e_dl), snpa, snpalen, index); gte_dl.sdl_type = iftype; if (rtrequest(RTM_ADD, S(dst), S(gte_dl), netmask, flags, &mrt) || mrt == 0) return (0); rt = mrt; rt->rt_refcnt--; } else { register struct sockaddr_dl *sdl = (struct sockaddr_dl *)rt->rt_gateway; rt->rt_refcnt--; if ((rt->rt_flags & RTF_LLINFO) == 0) goto add; if (nsellength && (rt->rt_flags & RTF_HOST)) { if (rt->rt_refcnt == 0) { rtrequest(RTM_DELETE, S(dst), (struct sockaddr *)0, (struct sockaddr *)0, 0, (struct rtentry *)0); rt = 0; goto add; } else { static struct iso_addr nsap2; register char *cp; nsap2 = *nsap; cp = nsap2.isoa_genaddr + nsap->isoa_len - nsellength; while (cp < (char *)(1 + &nsap2)) *cp++ = 0; (void) snpac_add(ifp, &nsap2, snpa, type, ht, nsellength); } } if (sdl->sdl_family != AF_LINK || sdl->sdl_alen == 0) { int old_sdl_len = sdl->sdl_len; if (old_sdl_len < sizeof(*sdl)) { log(LOG_DEBUG, "snpac_add: cant make room for lladdr\n"); return (0); } zap_linkaddr(sdl, snpa, snpalen, index); sdl->sdl_len = old_sdl_len; sdl->sdl_type = iftype; new_entry = 1; } } if ((lc = (struct llinfo_llc *)rt->rt_llinfo) == 0) panic("snpac_rtrequest"); rt->rt_rmx.rmx_expire = ht + time.tv_sec; lc->lc_flags = SNPA_VALID | type; if ((type & SNPA_IS) && !(iso_systype & SNPA_IS)) snpac_logdefis(rt); return (new_entry);}static voidsnpac_fixdstandmask(nsellength){ register char *cp = msk.siso_data, *cplim; cplim = cp + (dst.siso_nlen -= nsellength); msk.siso_len = cplim - (char *)&msk; msk.siso_nlen = 0; while (cp < cplim) *cp++ = -1; while (cp < (char *)msk.siso_pad) *cp++ = 0; for (cp = dst.siso_data + dst.siso_nlen; cp < (char *)dst.siso_pad; ) *cp++ = 0;}/* * FUNCTION: snpac_ioctl * * PURPOSE: Set/Get the system type and esis parameters * * RETURNS: 0 on success, or unix error code * * SIDE EFFECTS: * * NOTES: */snpac_ioctl (so, cmd, data)struct socket *so;int cmd; /* ioctl to process */caddr_t data; /* data for the cmd */{ register struct systype_req *rq = (struct systype_req *)data; IFDEBUG(D_IOCTL) if (cmd == SIOCSSTYPE) printf("snpac_ioctl: cmd set, type x%x, ht %d, ct %d\n", rq->sr_type, rq->sr_holdt, rq->sr_configt); else printf("snpac_ioctl: cmd get\n"); ENDDEBUG if (cmd == SIOCSSTYPE) { if ((so->so_state & SS_PRIV) == 0) return (EPERM); if ((rq->sr_type & (SNPA_ES|SNPA_IS)) == (SNPA_ES|SNPA_IS)) return(EINVAL); if (rq->sr_type & SNPA_ES) { iso_systype = SNPA_ES; } else if (rq->sr_type & SNPA_IS) { iso_systype = SNPA_IS; } else { return(EINVAL); } esis_holding_time = rq->sr_holdt; esis_config_time = rq->sr_configt; if (esis_esconfig_time != rq->sr_esconfigt) { untimeout(esis_config, (caddr_t)0); esis_esconfig_time = rq->sr_esconfigt; esis_config(); } } else if (cmd == SIOCGSTYPE) { rq->sr_type = iso_systype; rq->sr_holdt = esis_holding_time; rq->sr_configt = esis_config_time; rq->sr_esconfigt = esis_esconfig_time; } else { return (EINVAL); } return (0);}/* * FUNCTION: snpac_logdefis * * PURPOSE: Mark the IS passed as the default IS * * RETURNS: nothing * * SIDE EFFECTS: * * NOTES: */snpac_logdefis(sc)register struct rtentry *sc;{ register struct iso_addr *r; register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sc->rt_gateway; register struct rtentry *rt; if (known_is == sc || !(sc->rt_flags & RTF_HOST)) return; if (known_is) { RTFREE(known_is); } known_is = sc; sc->rt_refcnt++; rt = rtalloc1((struct sockaddr *)&zsi, 0); if (rt == 0) rtrequest(RTM_ADD, S(zsi), rt_key(sc), S(zmk), RTF_DYNAMIC|RTF_GATEWAY, 0); else { if ((rt->rt_flags & RTF_DYNAMIC) && (rt->rt_flags & RTF_GATEWAY) && rt_mask(rt)->sa_len == 0) rt_setgate(rt, rt_key(rt), rt_key(sc)); }}/* * FUNCTION: snpac_age * * PURPOSE: Time out snpac entries * * RETURNS: * * SIDE EFFECTS: * * NOTES: When encountering an entry for the first time, snpac_age * may delete up to SNPAC_AGE too many seconds. Ie. * if the entry is added a moment before snpac_age is * called, the entry will immediately have SNPAC_AGE * seconds taken off the holding time, even though * it has only been held a brief moment. * * The proper way to do this is set an expiry timeval * equal to current time + holding time. Then snpac_age * would time out entries where expiry date is older * than the current time. */voidsnpac_age(){ register struct llinfo_llc *lc, *nlc; register struct rtentry *rt; timeout(snpac_age, (caddr_t)0, SNPAC_AGE * hz); for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = nlc) { nlc = lc->lc_next; if (lc->lc_flags & SNPA_VALID) { rt = lc->lc_rt; if (rt->rt_rmx.rmx_expire && rt->rt_rmx.rmx_expire < time.tv_sec) snpac_free(lc); } }}/* * FUNCTION: snpac_ownmulti * * PURPOSE: Determine if the snpa address is a multicast address * of the same type as the system. * * RETURNS: true or false * * SIDE EFFECTS: * * NOTES: Used by interface drivers when not in eavesdrop mode * as interm kludge until * real multicast addresses can be configured */snpac_ownmulti(snpa, len)caddr_t snpa;u_int len;{ return (((iso_systype & SNPA_ES) && (!bcmp(snpa, (caddr_t)all_es_snpa, len))) || ((iso_systype & SNPA_IS) && (!bcmp(snpa, (caddr_t)all_is_snpa, len))));}/* * FUNCTION: snpac_flushifp * * PURPOSE: Flush entries associated with specific ifp * * RETURNS: nothing * * SIDE EFFECTS: * * NOTES: */snpac_flushifp(ifp)struct ifnet *ifp;{ register struct llinfo_llc *lc; for (lc = llinfo_llc.lc_next; lc != & llinfo_llc; lc = lc->lc_next) { if (lc->lc_rt->rt_ifp == ifp && (lc->lc_flags & SNPA_VALID)) snpac_free(lc); }}/* * FUNCTION: snpac_rtrequest * * PURPOSE: Make a routing request * * RETURNS: nothing * * SIDE EFFECTS: * * NOTES: In the future, this should make a request of a user * level routing daemon. */snpac_rtrequest(req, host, gateway, netmask, flags, ret_nrt)int req;struct iso_addr *host;struct iso_addr *gateway;struct iso_addr *netmask;short flags;struct rtentry **ret_nrt;{ register struct iso_addr *r; IFDEBUG(D_SNPA) printf("snpac_rtrequest: "); if (req == RTM_ADD) printf("add"); else if (req == RTM_DELETE) printf("delete"); else printf("unknown command"); printf(" dst: %s\n", clnp_iso_addrp(host)); printf("\tgateway: %s\n", clnp_iso_addrp(gateway)); ENDDEBUG zap_isoaddr(dst, host); zap_isoaddr(gte, gateway); if (netmask) { zap_isoaddr(msk, netmask); msk.siso_nlen = 0; msk.siso_len = msk.siso_pad - (u_char *)&msk; } rtrequest(req, S(dst), S(gte), (netmask ? S(msk) : (struct sockaddr *)0), flags, ret_nrt);}/* * FUNCTION: snpac_addrt * * PURPOSE: Associate a routing entry with an snpac entry * * RETURNS: nothing * * SIDE EFFECTS: * * NOTES: If a cache entry exists for gateway, then * make a routing entry (host, gateway) and associate * with gateway. * * If a route already exists and is different, first delete * it. * * This could be made more efficient by checking * the existing route before adding a new one. */snpac_addrt(ifp, host, gateway, netmask)struct ifnet *ifp;struct iso_addr *host, *gateway, *netmask;{ register struct iso_addr *r; zap_isoaddr(dst, host); zap_isoaddr(gte, gateway); if (netmask) { zap_isoaddr(msk, netmask); msk.siso_nlen = 0; msk.siso_len = msk.siso_pad - (u_char *)&msk; rtredirect(S(dst), S(gte), S(msk), RTF_DONE, S(gte), 0); } else rtredirect(S(dst), S(gte), (struct sockaddr *)0, RTF_DONE | RTF_HOST, S(gte), 0);}#endif /* ISO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -