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

📄 rsrr_unicast.c

📁 radius协议源码÷The Radius Stack will connect to a Radius Server. This stack implementation is built upo
💻 C
📖 第 1 页 / 共 3 页
字号:
static int dsttable_size;static int vif_by_if(int, int);int dst_init(void (*refresh)(struct dstentry*)){	if (rtnl_open(&rt_nl, 0) < 0)		return -1;	dst_refresh = refresh;	return rt_nl.fd;}static void dst_rmseq(struct dstentry *d){	struct dstentry **dp;	for (dp = &dstqueue; *dp; dp = &(*dp)->queue_next) {		if (d == *dp) {			*dp = d->queue_next;			break;		}	}	d->seq = 0;}static __inline__ void dst_addseq(struct dstentry *d){	if (d->seq) {		d->next = dstqueue;		dstqueue = d;	}}static struct dstentry * dst_findseq(__u32 seq){	struct dstentry **dp, *d;	for (dp = &dstqueue; (d=*dp)!=NULL; dp = &d->queue_next) {		if (d->seq == seq) {			*dp = d->queue_next;			d->seq = 0;			return d;		}	}	return NULL;}static void release_path(struct dstentry *d){	if (d->path) {		free(d->path);		d->path = NULL;	}}static __inline__ unsigned hash(int family, const void *dst, const void *src){	unsigned h;	int offset = (family == AF_INET) ? 0 : 3;	h = ((__u32*)dst)[offset];	if (src)		h ^= (((__u32*)src)[offset])>>4;	h ^= h>>16;	h ^= h>>8;	return h&0xFF;}static __inline__ struct dstentry*dst_lookup4(unsigned h, int iif, const void *dst, const void *src){	__u32 saddr = src ? *(__u32*)src : 0;	__u32 daddr = dst ? *(__u32*)dst : 0;	struct dstentry *d;	for (d = dsttable[h]; d; d = d->next) {		if (d->family == AF_INET &&		    d->iif == iif &&		    d->dst[0] == daddr &&		    d->src[0] == saddr)			return d;	}	return NULL;}static __inline__ struct dstentry*dst_lookup6(unsigned h, int iif, const void *dst, const void *src){	struct dstentry *d;	if (src == NULL)		src = &zerokey;	if (dst == NULL)		dst = &zerokey;	for (d = dsttable[h]; d; d = d->next) {		if (d->family == AF_INET6 &&		    d->iif == iif &&		    memcmp(dst, d->dst, 16) == 0 &&		    memcmp(dst, d->src, 16) == 0)			return d;	}	return NULL;}static struct dstentry*dst_lookup(int fam, int iif, const void *dst, const void *src){	unsigned h = hash(fam, dst, src);	return (fam==AF_INET?dst_lookup4:dst_lookup6)(h, iif, dst, src);}static void dst_gc(){	static int expires = R_GC_TMO;	struct dstentry **dp, *d;	time_t now = time(NULL);	int h;	for (h = 0; h<256; h++) {		dp = &dsttable[h];		while ((d=*dp)!=NULL) {			if (!d->block) {				if (now - d->accessed > expires) {					*dp = d->next;					if (d->seq)						dst_rmseq(d);					release_path(d);					free(d);					dsttable_size--;					continue;				}				if (d->seq && now - d->updated > R_CANCEL_TMO)					dst_rmseq(d);			}			dp = &d->next;		}	}	if (dsttable_size > MAXDSTENTRIES)		expires = ((expires+R_ASYNC_TMO)>>1) + 1;	else		expires = R_GC_TMO;}struct dstentry * dst_alloc(int family, void *dst, void *src, int iif){	unsigned h;	struct dstentry *d;	d = calloc(1, sizeof(*d));	if (d == NULL)		return NULL;	d->iif = iif;	d->family = family;	if (family == AF_INET) {		d->dst[0] = *(__u32*)dst;		if (src)			d->src[0] = *(__u32*)src;	}#ifdef USE_IPV6	else {		memcpy(d->dst, dst, 16);		memcpy(d->src, src ? : &zerokey, 16);	}#endif	if (dsttable_size > MAXDSTENTRIES)		dst_gc();	dsttable_size++;	h = hash(family,dst,src);	d->next = dsttable[h];	dsttable[h] = d;	return d;}static int dst_request(struct dstentry *d){	int rlen;	char buf[256];	struct nlmsghdr *n = (struct nlmsghdr *) buf;	struct rtmsg *r = NLMSG_DATA(n);	struct sockaddr_nl addr;	n->nlmsg_type = RTM_GETROUTE;	n->nlmsg_flags = NLM_F_REQUEST;	n->nlmsg_len = NLMSG_LENGTH(sizeof(*r));	n->nlmsg_pid = rt_nl.local.nl_pid;	if (++rt_nl.seq == 0)		rt_nl.seq = 1;	n->nlmsg_seq = rt_nl.seq;	if (d->seq)		dst_rmseq(d);	d->seq = n->nlmsg_seq;	memset(r, 0, sizeof(*r));	r->rtm_family = d->family;	r->rtm_flags = RTM_F_NOTIFY;	if (d->iif)		addattr32(n, sizeof(buf), RTA_IIF, d->iif);	if (d->family == AF_INET) {		r->rtm_dst_len = 32;		if (d->src[0])			r->rtm_src_len = 32;	}#ifdef USE_IPV6	else {		r->rtm_dst_len = 128;		if (d->src[0] || d->src[1] || d->src[2] || d->src[3])			r->rtm_src_len = 128;	}#endif	if (r->rtm_dst_len)		addattr_l(n, sizeof(buf), RTA_DST, d->dst, r->rtm_dst_len/8);	if (r->rtm_src_len)		addattr_l(n, sizeof(buf), RTA_SRC, d->src, r->rtm_src_len/8);	addr.nl_family = AF_NETLINK;	addr.nl_groups = 0;	addr.nl_pid = 0;	if ((rlen = sendto(rt_nl.fd, buf, n->nlmsg_len, 0, (struct sockaddr *) &addr, sizeof(addr))) < 0) {		d->seq = 0;		return rlen;	}	dst_addseq(d);	return 0;}static void netlink_accept(char *buf, int len){	struct nlmsghdr *n = (void*)buf;	struct rtmsg *r = NLMSG_DATA(n);	struct rtattr *rta[RTA_MAX + 1];	struct dstentry *d;	time_t now = time(NULL);	__u32 *dst = NULL;	__u32 *src = NULL;	int   iif = 0;	int   err = 0;	if (len < sizeof(struct nlmsghdr) || n->nlmsg_len > len)		return;	if (n->nlmsg_type == NLMSG_ERROR) {		if (n->nlmsg_pid != rt_nl.local.nl_pid)			return;		err = ((struct nlmsgerr*)NLMSG_DATA(n))->error;		d = dst_findseq(n->nlmsg_seq);		if (d)			goto failure;		return;	}	if (n->nlmsg_type != RTM_NEWROUTE && n->nlmsg_type != RTM_DELROUTE)		return;	d = NULL;	if (n->nlmsg_pid == rt_nl.local.nl_pid)		d = dst_findseq(n->nlmsg_seq);	if (parse_rtattr(rta, RTA_MAX, RTM_RTA(r), RTM_PAYLOAD(n))) {		err = EINVAL;		if (d)			goto failure;		return;	}	if (rta[RTA_DST])		dst = RTA_DATA(rta[RTA_DST]);	if (rta[RTA_SRC])		src = RTA_DATA(rta[RTA_SRC]);	if (rta[RTA_IIF])		iif = *(int*)RTA_DATA(rta[RTA_IIF]);	if (d == NULL || d->iif != iif) {		struct dstentry *d1 = d;		d = dst_lookup(r->rtm_family,iif,dst,src);		if (d == NULL) {			if (d1) {				d = dst_alloc(r->rtm_family,dst,src,iif);				if (d == NULL)					return;				d->state = R_INCOMPLETE;			}		}		if (d->seq)			dst_rmseq(d);	}	if (n->nlmsg_type == RTM_DELROUTE) {		if (d->state&R_VALID)			d->state = R_STALE;		return;	}	if (r->rtm_type == RTN_LOCAL) {		release_path(d);		d->state = R_FRESH;		d->error = 0;	} else if (r->rtm_type == RTN_UNICAST || r->rtm_type == RTN_MULTICAST) {		struct rtattr *path = rta[RTA_MULTIPATH];		int do_free = 0;		if (path == NULL) {			struct rtnexthop *nh;			int len = sizeof(struct rtnexthop);			err = EINVAL;			if (rta[RTA_OIF] == NULL)				goto failure;			if (rta[RTA_GATEWAY]) {				if (memcmp(RTA_DATA(rta[RTA_GATEWAY]), dst,					   RTA_PAYLOAD(rta[RTA_GATEWAY])))					len += rta[RTA_GATEWAY]->rta_len;				else					rta[RTA_GATEWAY] = NULL;			}			path = malloc(RTA_LENGTH(len));			if (path == NULL)				return;			path->rta_type = RTA_MULTIPATH;			path->rta_len = RTA_LENGTH(len);			nh = RTA_DATA(path);			nh->rtnh_len = len;			nh->rtnh_hops = 0;			nh->rtnh_flags = r->rtm_flags;			nh->rtnh_ifindex = *(int*)RTA_DATA(rta[RTA_OIF]);			if (rta[RTA_GATEWAY])				memcpy(RTNH_DATA(nh), rta[RTA_GATEWAY], rta[RTA_GATEWAY]->rta_len);			do_free = 1;		}		if (d->path &&		    d->path->rta_len == path->rta_len &&		    memcmp(d->path, path, path->rta_len) == 0) {			int old_state = d->state;			d->state = R_FRESH;			if (do_free)				free(path);			if (old_state&R_VALID)				return;			goto update;		}		if (!do_free) {			struct rtattr *np = malloc(path->rta_len);			if (np == NULL)				return;			memcpy(np, path, path->rta_len);			path = np;		}		release_path(d);		d->path = path;		d->state = R_FRESH;	} else {		err = EINVAL;failure:		release_path(d);		d->state = R_FAILED;		d->error = err;		d->updated = now;		return;	}update:	d->updated = now;	if (!d->block && d->refresh) {		d->refresh = 0;		d->block++;		if (dst_refresh)			dst_refresh(d);		d->block--;	}	return;}int netlink_read_wakeup(){	char buf[8192];	int recvlen;	struct sockaddr_nl nladdr;	int addr_len = sizeof(nladdr);	recvlen = recvfrom(rt_nl.fd, buf, sizeof(buf), MSG_DONTWAIT,			   (struct sockaddr*)&nladdr, &addr_len);	if (recvlen < 0) {		if (errno == EAGAIN)			return 1;		return -1;	}	if (addr_len != sizeof(nladdr) || nladdr.nl_pid)		return -1;	netlink_accept(buf, recvlen);	return 0;}struct dstentry *dst_route(int family, void *dst, void *src, int iif, unsigned flags){	time_t entered, now;	struct dstentry *d;	now = entered = time(NULL);	d = dst_lookup(family, iif, dst, src);	if (d == NULL) {		if (flags&RTO_NOUPDATE)			return NULL;		d = dst_alloc(family, dst, src, iif);		if (d == NULL)			return NULL;	}	for (;;) {		time_t age;		int need_upd = 0;		d->accessed = now;		age = now - d->updated;		if (d->state == R_FRESH) {			if (age <= R_STALETIME)				return d;			d->state = R_STALE;		}		if ((d->state&(R_PROBE|R_INCOMPLETE)) && age > R_ASYNC_TMO) {			d->state = R_FAILED;			d->error = ETIMEDOUT;		} else if (d->state == R_STALE) {			need_upd = 1;			d->state = R_PROBE;		} else if (d->state == R_NONE ||		    (d->state == R_FAILED && age > R_LOAD)) {			need_upd = 1;			d->updated = now;			d->state = R_INCOMPLETE;		}		if (!(d->state&R_VALID))			release_path(d);		if (need_upd) {			int err = dst_request(d);			if (err) {				d->state = R_FAILED;				d->updated = now;				d->error = errno;				release_path(d);			}			d->block++;			while (netlink_read_wakeup() == 0)				/* NOTHING */;			d->block--;		}		if (d->state&(R_VALID|R_FAILED))			return d;		if (flags&RTO_NOWAIT || now-entered > R_SYNC_TMO)			return d;		if (1) {			fd_set fds;			struct timeval tv;			FD_ZERO(&fds);			FD_SET(rt_nl.fd,&fds);			tv.tv_sec = R_SYNC_TMO-(now-entered);			tv.tv_usec = 0;			select(rt_nl.fd+1, &fds, NULL, NULL, &tv);			d->block++;			netlink_read_wakeup();			d->block--;		}		now = time(NULL);	}}int dst_is_connected(struct dstentry *d){	if (!(d->state&R_VALID))		return 0;	if (d->path==NULL ||	    d->path->rta_len <= RTA_LENGTH(sizeof(struct rtnexthop)))		return 1;	return 0;}int dst_oif(struct dstentry *d){	struct rtnexthop *nh;	if (!(d->state&R_VALID))		return 0;	if (d->path==NULL)		return 0;	nh = RTA_DATA(d->path);	return nh->rtnh_ifindex;}int dst_route_oif(net_addr *addr){	int i;	int family = AF_INET;	net_addr *addr2;	net_if *inf;	struct dstentry *d;	int best = -1;	int out;	int vif;	addr2 = net_addr_ip(addr);#ifdef USE_IPV6	if (addr2->type == NET_ADDR_IPv6)		family = AF_INET6;#endif	d = dst_route(family, &NET_GET_ADDR(addr2), NULL, 0, RTO_NOWAIT);	if (d == NULL || !(d->state&R_VALID)) {		d = NULL;		goto fallback;	}	if (d->path == NULL)		return -1;	out = dst_oif(d);	vif = vif_by_if(family, out);	/* log(LOG_DEBUG, 0, "dst_route_oif: out = %d\n", out); */	/* log(LOG_DEBUG, 0, "dst_route_oif: vif = %d\n", vif); */	return vif;fallback:	/* First pass: check primary addresses */	for (i=0; i<if_num; i++) {		if (IsNumAPI(i))			continue;		if (IF_DOWN(i))		        continue;		inf = &GET_IF(i);		if (NET_GET_TYPE(inf) != NET_IF_PHY)			continue;		if (net_addr_equal(addr2,&NET_GET_IF_PHY_ADDR(inf)))			return i;	}	if (best >= 0)		return best;	if (d) {		best = local_v4;#ifdef USE_IPV6		if (family == AF_INET6)			best = local_v6;#endif	}			return best;}static int vif_by_if(int family, int ifindex){	int i;	net_if *inf2;	int type = NET_ADDR_IPv4;#ifdef USE_IPV6	if (family == AF_INET6)		type = NET_ADDR_IPv6;#endif	for (i=0; i<if_num; i++) {		if (IsNumAPI(i))			continue;		inf2 = &GET_IF(i);		if (NET_GET_TYPE(inf2) == NET_IF_PHY &&		    NET_GET_IF_PHY_ID(inf2) == ifindex &&		    NET_GET_IF_PHY_ADDR(inf2).type == type)			return i;	}	log(LOG_WARNING, 0, "ifindex %d/%d is not mapped to a vif\n", ifindex, type);	return -1;}#elif	sgi_53/* Do not have support for access to unicast routing table in IRIX 5.3. */intunicast_init()	{#ifdef HOST_ONLY	return(0);#else	return(1);#endif}intunicast_route1(u_long dest){	/*  This dummy routine is here to allow pre-routing-socket code to	 *  compile.  It should never be called.	 */	assert(0);	return(0);}#else  /* !sgi_53 && !linux *//*	Following code should work for many systems derived from *	older BSDs, but it is known to work for Sun OS. *//* * Copyright (c) 1983 Regents of the University of California. * All rights reserved.  The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */#include <fcntl.h>#include <kvm.h>#include <nlist.h>#include <stdio.h>#include <sys/sockio.h>#include <sys/mbuf.h>#include <net/if.h>#include <net/route.h>#include <netinet/in.h>#include <netdb.h>#include <assert.h>#include <syslog.h>struct nlist nl[] = {#define	N_RTHOST	0	{ "_rthost" },#define	N_RTNET		1	{ "_rtnet" },#define N_RTHASHSIZE	2	{ "_rthashsize" },	{""}};kvm_t	*kd;char	usage[] = "[-n] host";struct xroute {	char ifname[IFNAMSIZ];	struct sockaddr_in netmask;	struct sockaddr_in out_if;	struct sockaddr_in dst;	struct sockaddr_in gw;} routes[256];int nhost = 0;int nroute = 0;struct xroute default_route;int have_default = 0;int unicast_fd;/* forward declarations */int read_routes();int net_match(struct sockaddr_in *, struct xroute *);int rtfindx(struct sockaddr_in *);int ifname_to_if(char *);int kread(unsigned long addr, char *buf, unsigned nbytes);static int inet_netmatch(struct sockaddr_in *, struct sockaddr_in *);intunicast_init() {	if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL) {		log(LOG_INFO, 0, "Unicast routing information unavailable\n");		init_failed = 1;		NoUnicast = 1;		return(0);	}	if (kvm_nlist(kd, nl) < 0) {		log(LOG_ERR, 0, "netstat: bad namelist\n");		init_failed = 1;		NoUnicast = 1;		return(0);	}	unicast_fd = socket(AF_INET, SOCK_DGRAM, 0);	if (unicast_fd < 0) {		log(LOG_ERR, errno, "unicast socket");		init_failed = 1;		NoUnicast = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -