⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iso_snpac.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
 * * 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((&gte_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 + -