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

📄 dyn_ip.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			saved_default_route_dev_index = idxmap->index;		} else {			memset(saved_default_route_dev, 0, IFNAMSIZ);			saved_default_route_dev_index = 0;		}		memset(&saved_default_route, 0, sizeof(saved_default_route));		saved_default_route.rtm_table = RT_TABLE_MAIN;		saved_default_route.rtm_protocol = RTPROT_BOOT;		saved_default_route.rtm_type = RTN_UNICAST;		saved_default_route.rtm_family = AF_INET;		saved_default_route.rtm_scope = RT_SCOPE_UNIVERSE;		default_route_saved = 1;	}        ll_free_map();	close(rth.fd);	return ret;}/** * dyn_ip_route_restore_default: * @force_dev: force given device for the new default route * * Restore the default route saved with dyn_ip_route_save_default(). * * Returns: 0 on success or -1 on failure. */int dyn_ip_route_restore_default(const char *force_dev){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct rtmsg r;		char buf[1024];	} req;	int idx;	const char *dev;	if (!default_route_saved) {		/* FIX: remove default route? */		return 0;	}	if (force_dev != NULL)		dev = force_dev;	else		dev = saved_default_route_dev;	memset(&req, 0, sizeof(req));	memcpy(&req.r, &saved_default_route, sizeof(struct rtmsg));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;	req.n.nlmsg_type = RTM_NEWROUTE;	if (saved_default_route_via_len > 0) {		DEBUG(DEBUG_FLAG, 		      "dyn_ip_route_restore_default: via %s\n",		      inet_ntoa(*(struct in_addr *)saved_default_route_via));		addattr_l(&req.n, sizeof(req), RTA_GATEWAY,			  saved_default_route_via,			  saved_default_route_via_len);	}	if (saved_default_route_prefsrc_len > 0) {		DEBUG(DEBUG_FLAG, 		      "dyn_ip_route_restore_default: prefsrc %s\n",		      inet_ntoa(*(struct in_addr *)				saved_default_route_prefsrc));		addattr_l(&req.n, sizeof(req), RTA_PREFSRC,			  saved_default_route_prefsrc,			  saved_default_route_prefsrc_len);	}	if (rtnl_open(&rth, 0) != 0)		return -1;	if (ll_init_map(&rth) != 0) {		ll_free_map();		close(rth.fd);		return -1;	}	idx = ll_name_to_index(dev);	ll_free_map();	DEBUG(DEBUG_FLAG,	      "dyn_ip_route_restore_default: idx=%i(%s) (was %i)\n",	      idx, dev, saved_default_route_dev_index);	if (idx == 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_route_restore_default: unknown interface %s\n",		      dev);		ll_free_map();		close(rth.fd);		return -1;	}	addattr32(&req.n, sizeof(req), RTA_OIF, idx);	if (rtnl_talk(&rth, &req.n, NULL) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_restore_default: rtnl_talk "		      "failed\n");		close(rth.fd);		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_route_replace_default: * @dev: new default route device * @via: new default route gateway address or %NULL if no gateway. * @prefsrc: new prefered source address or %NULL if not set. * * Replace the default route of the main routing table to @dev gateway address * @via. * * Returns: 0 on success or -1 on failure. */int dyn_ip_route_replace_default(const char *dev, const struct in_addr *via,				 const struct in_addr *prefsrc){	return rtnl_modify_route(RTM_NEWROUTE,				 NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE,				 RTN_UNICAST, dev, RT_TABLE_MAIN, NULL, 32,				 via, prefsrc);}static int dummy_iterator(struct sockaddr_nl *who, struct nlmsghdr *n,			     void *arg){	int len = n->nlmsg_len;	struct rtmsg *r = NLMSG_DATA(n);	len -= NLMSG_LENGTH(sizeof(*r));	if (len < 0) {		DEBUG(DEBUG_FLAG, "dummy_iterator: wrong len %d\n", len);		return -1;	}	return 0;}/** * dyn_ip_check_adv_routing: * * Check if kernel supports routing rules (advanced policy routing). * * Returns: *   -1: no support found, *    0: supported */int dyn_ip_check_adv_routing(void){	struct rtnl_handle rth;	if (rtnl_open(&rth, 0) != 0) {		fprintf(stderr, "Cannot open rtnetlink\n");		return -1;	}	if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETRULE) < 0) {		fprintf(stderr, "Cannot send dump request\n");		close(rth.fd);		return -1;	}	if (rtnl_dump_filter(&rth, dummy_iterator, NULL) < 0) {		DEBUG(DEBUG_FLAG,		      "rtnl_dump terminated\n");		close(rth.fd);		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_check_ipip: * * Check if kernel supports IP-within-IP (ipip.o module). *  * Returns:  *   -1: no support found, *    0: supported */int dyn_ip_check_ipip(void){	struct ifreq ifr;	struct ip_tunnel_parm p;	int s;	memset(&p, 0, sizeof(p));	p.iph.version = 4;	p.iph.ihl = 5;	p.iph.frag_off = htons(IP_DF);	dynamics_strlcpy(ifr.ifr_name, "tunl0", sizeof(ifr.ifr_name));	ifr.ifr_ifru.ifru_data = (void*) &p;	s = socket(AF_INET, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket");		return -1;	}	if (ioctl(s, SIOCGETTUNNEL, &ifr) != 0) {		perror("ioctl");		close(s);		return -1;	}	close(s);	return 0;}/** * dyn_ip_check_gre: * * Check if kernel supports GRE (ip_gre.o module). * * Returns: *   -1: no support found, *    0: supported */int dyn_ip_check_gre(void){	struct ifreq ifr;	struct ip_tunnel_parm p;	int s;	memset(&p, 0, sizeof(p));	p.iph.version = 4;	p.iph.ihl = 5;	p.iph.frag_off = htons(IP_DF);	dynamics_strlcpy(ifr.ifr_name, "gre0", sizeof(ifr.ifr_name));	ifr.ifr_ifru.ifru_data = (void*) &p;	s = socket(AF_INET, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket");		return -1;	}	if (ioctl(s, SIOCGETTUNNEL, &ifr) != 0) {		perror("ioctl");		close(s);		return -1;	}	close(s);	return 0;}/** * dyn_ip_check_netlink: * * Check if kernel supports netlink socket. * * Returns: *   -1: no support found, *    0: supported */int dyn_ip_check_netlink(void){	int ret;	struct rtnl_handle rth;	/* test for CONFIG_NETLINK */	if (rtnl_open(&rth, 0) != 0)		return -1;	/* test for CONFIG_RTNETLINK */	ret = 0;	if (ll_init_map(&rth) != 0)		ret = 1;	ll_free_map();	close(rth.fd);	return ret;}/** * dyn_ip_get_interface_map: * * Return the interface map from the kernel. The memory allocated for the map * must be released by the caller using dyn_ip_free_interface_map(). * * Returns: interface map or %NULL on failure */struct idxmap* dyn_ip_get_interface_map(void){	struct rtnl_handle rth;	struct idxmap *ret;	if (rtnl_open(&rth, 0) != 0)		return NULL;	if (ll_init_map(&rth) != 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_get_interface_map: ll_init_map() failed\n");		ll_free_map();		close(rth.fd);		return NULL;	}	close(rth.fd);	ret = idxmap;	idxmap = NULL; /* caller releases memory */	return ret;}/** * dyn_ip_get_ifindex: * @dev: selected device name * * Get the interface index of the selected device @dev. * * Returns: interface index or -1 on failure */int dyn_ip_get_ifindex(const char *dev){	int s;	struct ifreq ifr;	s = socket(AF_INET, SOCK_DGRAM, 0);	if (s < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifindex - socket: %s\n",		      strerror(errno));		return -1;	}	memset(&ifr, 0, sizeof(ifr));	memcpy(ifr.ifr_name, dev, IFNAMSIZ);	if (ioctl(s, SIOCGIFINDEX, &ifr) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifindex(%s): ioctl: %s\n",		      dev, strerror(errno));		close(s);		return -1;	}	close(s);	return ifr.ifr_ifindex;}/** * dyn_ip_get_ifname: * @ifindex: selected interface * @dev: buffer for the interface name * * Get the device name @dev of the selected interface @ifindex. * * Returns: 0 on success or -1 on failure */int dyn_ip_get_ifname(int ifindex, char *dev){	struct rtnl_handle rth;	struct idxmap *tmp;	if (rtnl_open(&rth, 0) != 0)		return -1;	if (ll_init_map(&rth) != 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_get_ifname: ll_init_map() failed\n");		ll_free_map();		close(rth.fd);		return -1;	}	close(rth.fd);	tmp = idxmap;	while (tmp != NULL) {		if (tmp->index == ifindex) {			memcpy(dev, tmp->name, IFNAMSIZ);			break;		}		tmp = tmp->next;	}	ll_free_map();	if (tmp == NULL) return -1;	return 0;}/** * dyn_ip_route_cache_flush: * * Flush the routing cache. * * Returns: 0 on success or -1 on error */int dyn_ip_route_cache_flush(void){	int l, fd;	char *buf = "0";	fd = open("/proc/sys/net/ipv4/route/flush", O_WRONLY);	if (fd < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_flush - cannot open "		      "/proc/sys/net/ipv4/route/flush\n");		return -1;	}	l = write(fd, buf, strlen(buf));	if (l < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_flush - %s\n",		      strerror(errno));		close(fd);		return -1;	}	close(fd);	if (l < strlen(buf)) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_flush - only %i/%i wrote\n",		      l, strlen(buf));		return -1;	}	return 0;}/** * dyn_ip_get_ifflags: * @dev: interface * * Get interface flags for @dev. * * Returns: interface flags or -1 on failure */int dyn_ip_get_ifflags(const char *dev){	struct ifreq ifr;	int s;	assert(dev != NULL);	assert(strlen(dev) < IFNAMSIZ);	dynamics_strlcpy(ifr.ifr_name, dev, IFNAMSIZ);	s = socket(AF_INET, SOCK_DGRAM, 0);	if (s < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifflags: socket: %s\n",		      strerror(errno));		return -1;	}	if (ioctl(s, SIOCGIFFLAGS, &ifr) != 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_get_ifflags: ioctl SIOCGIFFLAGS: %s\n",		      strerror(errno));		close(s);		return -1;	}	close(s);	return ifr.ifr_flags;}struct existance_data {	const struct in_addr *addr;	int prefix_len;	int found;};static int check_existance(struct sockaddr_nl *who, struct nlmsghdr *n,			   void *arg){	struct rtattr *tb[RTA_MAX + 1];	struct rtmsg *r = NLMSG_DATA(n);	int len = n->nlmsg_len;	struct existance_data *edata = (struct existance_data *) arg;	struct in_addr addr;	if (n->nlmsg_type != RTM_NEWROUTE || r == NULL) {		DEBUG(DEBUG_FLAG,		      "check_existance: not a route: %08x %08x %08x\n",		      n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);		return 0;	}	len -= NLMSG_LENGTH(sizeof(*r));	if (len < 0) {		DEBUG(DEBUG_FLAG, "check_existance: wrong len %d\n", len);		return -1;	}	memset(tb, 0, sizeof(tb));	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);	if (tb[RTA_DST] == NULL || r->rtm_dst_len != edata->prefix_len ||	    r->rtm_table != RT_TABLE_MAIN) return 0;	memcpy(&addr, RTA_DATA(tb[RTA_DST]), 4);	if (addr.s_addr != edata->addr->s_addr) return 0;	/* entry matches */	edata->found = 1;	return -2;}/** * dyn_ip_route_exists: * @addr: route destination address (host/network) * @prefix_len: prefix length for the network route * * Check whether a given route (@addr/@prefix_len) exists in the main routing * table. * * Returns: -1 on error, 0 if not found, 1 if found */int dyn_ip_route_exists(const struct in_addr *addr, int prefix_len){	struct rtnl_handle rth;	struct existance_data edata;	if (rtnl_open(&rth, 0) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_exists - rtnl_open failed\n");		return -1;	}	if (rtnl_wilddump_request(&rth, AF_UNSPEC, RTM_GETROUTE) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_exists - rtnl_wilddump_request"		      "failed\n");		close(rth.fd);		return -1;	}	edata.addr = addr;	edata.prefix_len = prefix_len;	edata.found = 0;	if (rtnl_dump_filter(&rth, check_existance, &edata) == -1) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_exists - rtnl_dump_filter "		      "failed\n");	}	close(rth.fd);	return edata.found;}/** * dyn_ip_route_delete_net_routes: * @addr: route destination address (host/network) * @prefix_len: prefix length for the network route * * Delete all routing entries to given network from main routing table. * * Returns: number of deleted routing entries or -1 on error. */int dyn_ip_route_delete_net_routes(const struct in_addr *addr, int prefix_len){	int count = 0;	while (dyn_ip_route_exists(addr, prefix_len) > 0) {		count++;		if (dyn_ip_route_del_net(NULL, addr, prefix_len) != 0) {			DEBUG(DEBUG_FLAG, "dyn_ip_route_delete_net_routes: "			      "delete failed for (%s/%i)\n",			      inet_ntoa(*addr), prefix_len);			return -1;		}	}

⌨️ 快捷键说明

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