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

📄 dyn_ip.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
 * @device: incoming network device name (iif), or %NULL if not set * * Add a routing rule for packets from @src to @dst using iif @device to * @table. * * Returns: 0 on success or -1 on failure */int dyn_ip_rule_add_table(struct in_addr *src, struct in_addr *dst, int table,			  const char *device){	DEBUG(DEBUG_FLAG, "\tip rule add from %s to %s table %d iif %s\n",	      src != NULL ? inet_ntoa(*src) : "N/A",	      dst != NULL ? inet_ntoa(*dst) : "N/A",	      table, device != NULL ? device : "N/A");	return change_iprule(RTM_NEWRULE, RTN_UNICAST, src, dst, table, device,			     -1);}/** * dyn_ip_rule_del_table: * @src: source IP address (from), or %NULL if not set * @dst: destination IP address (to), or %NULL if not set * @table: routing table number * @device: incoming network device name (iif), or %NULL if not set * * Delete the routing rule for packets from @src to @dst using iif @device to * @table. * * Returns: 0 on success or -1 on failure */int dyn_ip_rule_del_table(struct in_addr *src, struct in_addr *dst, int table,			  const char *device){	DEBUG(DEBUG_FLAG, "\tip rule del from %s to %s table %d iif %s\n",	      src != NULL ? inet_ntoa(*src) : "N/A",	      dst != NULL ? inet_ntoa(*dst) : "N/A",	      table, device != NULL ? device : "N/A");	return change_iprule(RTM_DELRULE, RTN_UNICAST, src, dst, table, device,			     -1);}/** * dyn_ip_route_get: * @dst: destination address * @dev: memory buffer for the interface name * @max_len: maximum length of the buffer (buffer will have to have space  * for the name including null termination) * * Find out the correct interface from the destination address * * Returns: 0 on success, -1 if failed, -2 if the buffer for the interface  * name is too small */int dyn_ip_route_get(struct in_addr dst, char *dev, int max_len){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct rtmsg r;		char buf[1024];	} req;	struct rtattr * tb[RTA_MAX+1];	int len;	char *tmp;	memset(&req, 0, sizeof(req));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = NLM_F_REQUEST;	req.n.nlmsg_type = RTM_GETROUTE;	req.r.rtm_table = 0;	req.r.rtm_protocol = 0;	req.r.rtm_scope = 0;	req.r.rtm_type = 0;	req.r.rtm_src_len = 0;	req.r.rtm_tos = 0;	req.r.rtm_family = AF_INET;	req.r.rtm_dst_len = 32; /* bits */	addattr_l(&req.n, sizeof(req), RTA_DST, (void*) &dst,		  sizeof(struct in_addr));	if (rtnl_open(&rth, 0) != 0)		return -1;	if (ll_init_map(&rth) != 0) {		ll_free_map();		close(rth.fd);		return -1;	}	if (rtnl_talk(&rth, &req.n, &req.n) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_get(%s): rtnl_talk failed\n",		      inet_ntoa(dst));		ll_free_map();		close(rth.fd);		return -1;	}	close(rth.fd);	if (req.n.nlmsg_type != RTM_NEWROUTE) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_get: not a route\n");		ll_free_map();		return -1;	}	len = req.n.nlmsg_len - NLMSG_LENGTH(sizeof(req.r));	if (len < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_get: invalid length\n");		ll_free_map();		return -1;	}	memset(tb, 0, sizeof(tb));	parse_rtattr(tb, RTA_MAX, RTM_RTA(&req.r), len);	if (tb[RTA_OIF] == 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_get: no RTA_OIF?\n");		ll_free_map();		return -1;	}	tmp = ll_index_to_name(*(int *) RTA_DATA(tb[RTA_OIF]));	if (tmp == NULL) {		ll_free_map();		DEBUG(DEBUG_FLAG, "ll_index_to_name failed\n");		return -1;	}	if (strlen(tmp) >= max_len) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_route_get: device name does not fit "		      "to the given buffer\n");		ll_free_map();		return -2;	}	dynamics_strlcpy(dev, tmp, max_len);	ll_free_map();	return 0;}/** * dyn_ip_route_to_host: * @dst: destination IP address *  * Get current routing entry for a given host @dst and add a host route with * that information. *  * Returns: 0 if successful, else -1 */int dyn_ip_route_to_host(struct in_addr dst){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct rtmsg r;		char buf[1024];	} req;	struct rtattr *tb[RTA_MAX+1];	int len;	memset(&req, 0, sizeof(req));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = NLM_F_REQUEST;	req.n.nlmsg_type = RTM_GETROUTE;	req.r.rtm_table = 0;	req.r.rtm_protocol = 0;	req.r.rtm_scope = 0;	req.r.rtm_type = 0;	req.r.rtm_src_len = 0;	req.r.rtm_tos = 0;	req.r.rtm_family = AF_INET;	req.r.rtm_dst_len = 32; /* bits */	addattr_l(&req.n, sizeof(req), RTA_DST, (void*) &dst,		  sizeof(struct in_addr));	if (rtnl_open(&rth, 0) != 0)		return -1;	if (rtnl_talk(&rth, &req.n, &req.n) < 0) {		close(rth.fd);		DEBUG(DEBUG_FLAG, "dyn_ip_route_to_host: rtnl_talk (get) "		      "failed\n");		return -1;	}	req.n.nlmsg_type = RTM_NEWROUTE;	req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;	/* make sure this is a host route and remove cache information */	req.r.rtm_dst_len = 32;	req.r.rtm_flags &= ~RTM_F_CLONED;	req.r.rtm_protocol = RTPROT_BOOT;	req.r.rtm_type = RTN_UNICAST;	memset(tb, 0, sizeof(tb));	len = req.n.nlmsg_len - NLMSG_LENGTH(sizeof(req.r));	if (len < 0) {		close(rth.fd);		DEBUG(DEBUG_FLAG, "dyn_ip_route_to_host: invalid len\n");		return -1;	}	parse_rtattr(tb, RTA_MAX, RTM_RTA(&req.r), len);	if (tb[RTA_METRICS]) {		int i;		unsigned mxlock = 0;		struct rtattr *mxrta[RTAX_MAX+1];		memset(mxrta, 0, sizeof(mxrta));		parse_rtattr(mxrta, RTAX_MAX, RTA_DATA(tb[RTA_METRICS]),			    RTA_PAYLOAD(tb[RTA_METRICS]));		if (mxrta[RTAX_LOCK])			mxlock = *(unsigned*)RTA_DATA(mxrta[RTAX_LOCK]);		for (i=2; i<=RTAX_MAX; i++) {			if (mxrta[i] != NULL)				*(unsigned*)RTA_DATA(mxrta[i]) = 0;		}	}	if (rtnl_talk(&rth, &req.n, NULL) < 0) {		close(rth.fd);		DEBUG(DEBUG_FLAG, "dyn_ip_route_to_host: rtnl_talk (set) "		      "failed\n");		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_get_ifaddr: * @dev: network interface name * @addr: address of the interface *  * Fill in @addr with the IP address of @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_get_ifaddr(const char *dev, struct in_addr *addr){	struct ifreq ifr;	int s;	struct sockaddr_in *saddr;	memset(&ifr, 0, sizeof(ifr));	assert(dev != NULL && 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_ifaddr: socket: %s\n",		      strerror(errno));		return -1;	}	if (ioctl(s, SIOCGIFADDR, &ifr) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifaddr(%s): ioctl: %s\n",		      dev, strerror(errno));		close(s);		return -1;	}	close(s);	saddr = (struct sockaddr_in *) &ifr.ifr_addr;	if (saddr->sin_family != AF_INET) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_get_ifaddr(%s): invalid address family %i\n",		      dev, saddr->sin_family);		return -1;	}	memcpy(addr, &saddr->sin_addr, sizeof(*addr));	return 0;}/** * dyn_ip_get_bcaddr: * @dev: network interface name * @addr: broadcast address of the interface *  * Fill in @addr with the broadcast IP address of @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_get_bcaddr(const char *dev, struct in_addr *addr){	struct ifreq ifr;	int s;	struct sockaddr_in *saddr;	memset(&ifr, 0, sizeof(ifr));	assert(dev != NULL && 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_bcaddr: socket: %s\n",		      strerror(errno));		return -1;	}	if (ioctl(s, SIOCGIFBRDADDR, &ifr) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_bcaddr(%s): ioctl: %s\n",		      dev, strerror(errno));		close(s);		return -1;	}	close(s);	saddr = (struct sockaddr_in *) &ifr.ifr_addr;	if (saddr->sin_family != AF_INET) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_get_bcaddr(%s): invalid address family %i\n",		      dev, saddr->sin_family);		return -1;	}	memcpy(addr, &saddr->sin_addr, sizeof(*addr));	return 0;}/** * dyn_ip_get_local_addr: * @remote: destination IP address * @local: buffer for the local IP address *  * Get the @local address of the interface to which the packet to @remote * address are sent. *  * Returns: 0 if successful, else -1 */int dyn_ip_get_local_addr(const struct in_addr *remote, struct in_addr *local){	char dev[IFNAMSIZ];	if (dyn_ip_route_get(*remote, dev, IFNAMSIZ) != 0)		return -1;	if (dyn_ip_get_ifaddr(dev, local) != 0)		return -1;	DEBUG(DEBUG_FLAG, "dyn_ip_get_local_addr: %s =>", inet_ntoa(*remote));	DEBUG(DEBUG_FLAG, " %s (%s)\n", inet_ntoa(*local), dev);	return 0;}/** * dyn_ip_route_replace: * @dst_addr: destination address * @dev: network device name *  * Replace the route to @dst_addr to go to @dev. *  * Returns: 0 on success or -1 on failure */int dyn_ip_route_replace(struct in_addr dst_addr, const char *dev){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE |				 NLM_F_REPLACE, RTN_UNICAST,				 dev, -1, &dst_addr, 32, NULL, NULL);}/** * dyn_ip_route_replace_table: * @dst_addr: destination address * @dev: network device name * @table: routing table number *  * Replace the route to @dst_addr in @table to go to @dev. *  * Returns: 0 on success or -1 on failure */int dyn_ip_route_replace_table(struct in_addr dst_addr, const char *dev,			       int table){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE |				 NLM_F_REPLACE, RTN_UNICAST,				 dev, table, &dst_addr, 32, NULL, NULL);}/** * dyn_ip_route_add: * @dst_addr: destination address * @dev: network device name *  * Add a routing entry for @dst_addr to @dev. *  * Returns: 0 on success or -1 on failure */int dyn_ip_route_add(struct in_addr dst_addr, const char *dev){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE,				 RTN_UNICAST, dev, -1, &dst_addr, 32, NULL,				 NULL);}/** * dyn_ip_route_del: * @dst_addr: destination address * @dev: network device name * * Delete the route of @dst_addr to @dev. * * Returns: 0 on success or -1 on failure */int dyn_ip_route_del(struct in_addr dst_addr, const char *dev){	return rtnl_modify_route(RTM_DELROUTE, NLM_F_REQUEST, RTN_UNSPEC,				 dev, -1, &dst_addr, 32, NULL, NULL);}#define MAX_ROUTE_ADDR_LEN 8static int default_route_saved = 0;static struct rtmsg saved_default_route;static char saved_default_route_dev[IFNAMSIZ];static int saved_default_route_dev_index;static char saved_default_route_via[MAX_ROUTE_ADDR_LEN];static int saved_default_route_via_len;static char saved_default_route_prefsrc[MAX_ROUTE_ADDR_LEN];static int saved_default_route_prefsrc_len;/** * dyn_ip_get_saved_ifindex: *  * Return the interface index of the saved default route. *  * Returns: interface index or -1 on failure */int dyn_ip_get_saved_ifindex(void){	if (default_route_saved)		return saved_default_route_dev_index;	else		return -1;}static int get_default_route(struct sockaddr_nl *who, struct nlmsghdr *n,			     void *arg){	struct in_addr *forced_gateway = (struct in_addr *) arg;	struct rtattr *tb[RTA_MAX + 1];	struct rtmsg *r = NLMSG_DATA(n);	int len = n->nlmsg_len;	if (n->nlmsg_type != RTM_NEWROUTE || r == NULL) {		DEBUG(DEBUG_FLAG,		      "get_default_route: 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, "get_default_route: 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] || r->rtm_dst_len != 0 ||	    r->rtm_table != RT_TABLE_MAIN) {		/* not the default route */		return 0;	}	if (forced_gateway != NULL) {		saved_default_route_via_len = 4;		memcpy(saved_default_route_via, forced_gateway, 4);	} else if (tb[RTA_GATEWAY]) {		if (tb[RTA_GATEWAY]->rta_len > MAX_ROUTE_ADDR_LEN) {			saved_default_route_via_len = 0;			DEBUG(DEBUG_FLAG,			      "get_default_route: too long (%i) via address\n",			      tb[RTA_GATEWAY]->rta_len);		} else {			saved_default_route_via_len = tb[RTA_GATEWAY]->rta_len;			memcpy(saved_default_route_via,			       RTA_DATA(tb[RTA_GATEWAY]),			       saved_default_route_via_len);		}	} else {		saved_default_route_via_len = 0;	}	if (tb[RTA_OIF]) {		saved_default_route_dev_index = *(int *) RTA_DATA(tb[RTA_OIF]);		memcpy(saved_default_route_dev,		       ll_index_to_name(saved_default_route_dev_index),		       IFNAMSIZ);		DEBUG(DEBUG_FLAG, "get_default_route: idx=%i(%s)\n",		      saved_default_route_dev_index, saved_default_route_dev);	} else {		DEBUG(DEBUG_FLAG,		      "get_default_route: no device for default route\n");		saved_default_route_dev[0] = '\0';	}	if (tb[RTA_PREFSRC]) {		if (tb[RTA_PREFSRC]->rta_len > MAX_ROUTE_ADDR_LEN) {			saved_default_route_prefsrc_len = 0;			DEBUG(DEBUG_FLAG,			      "get_default_route: too long (%i) prefsrc "			      "address\n",			      tb[RTA_PREFSRC]->rta_len);		} else {			saved_default_route_prefsrc_len =				tb[RTA_PREFSRC]->rta_len;			memcpy(saved_default_route_prefsrc,			       RTA_DATA(tb[RTA_PREFSRC]),			       saved_default_route_prefsrc_len);		}	}	memcpy(&saved_default_route, r, sizeof(struct rtmsg));	default_route_saved = 1;	return 0;}/** * dyn_ip_route_save_default: * @forced_gateway: forced gateway address or %NULL if none * * Save the current default route. If @forced_gateway != %NULL, set the via * entry of the saved data (i.e., not of the routing table) to point to * @forced_gateway. * * Returns: 0 on success or -1 on failure */int dyn_ip_route_save_default(struct in_addr *forced_gateway){	struct rtnl_handle rth;	int ret = 0;	default_route_saved = 0;	if (rtnl_open(&rth, 0) != 0)		return -1;        if (ll_init_map(&rth) != 0) {		ret = -1;        }	if (ret == 0 &&	    rtnl_wilddump_request(&rth, AF_INET, RTM_GETROUTE) < 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_route_get_default: cannot send dump request\n");		ret = -1;	}	if (ret == 0 &&	    rtnl_dump_filter(&rth, get_default_route, forced_gateway) < 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_route_get_default: dump terminated\n");		ret = -1;	}	if (!default_route_saved && forced_gateway != NULL) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_get_default: "		      "Using forced gateway\n");		saved_default_route_via_len = 4;		memcpy(saved_default_route_via, forced_gateway, 4);			if (idxmap != NULL) {			memcpy(saved_default_route_dev, idxmap->name,			       IFNAMSIZ);

⌨️ 快捷键说明

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