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

📄 dyn_ip.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		struct msghdr msg = {			(void *) &nladdr, sizeof(nladdr),			&iov,	1,			NULL,	0,			0		};		status = recvmsg(rth->fd, &msg, 0);		if (status < 0) {			if (errno == EINTR)				continue;			DEBUG(DEBUG_FLAG,			      "rtnl_dump_filter: recvmsg OVERRUN: %s\n",			      strerror(errno));			continue;		}		if (status == 0) {			DEBUG(DEBUG_FLAG,			      "rtnl_dump_filter: EOF on netlink\n");			return -1;		}		if (msg.msg_namelen != sizeof(nladdr)) {			DEBUG(DEBUG_FLAG,			      "rtnl_dump_filter: sender address length "			      "== %i\n", msg.msg_namelen);			return -1;		}		h = (struct nlmsghdr *) buf;		while (NLMSG_OK(h, status)) {			int err;			if (h->nlmsg_pid != rth->local.nl_pid ||			    h->nlmsg_seq != rth->dump) {				DEBUG(DEBUG_FLAG, "rtnl_dump_filter: junk?\n");				h = NLMSG_NEXT(h, status);				continue;			}			if (h->nlmsg_type == NLMSG_DONE)				return 0;			if (h->nlmsg_type == NLMSG_ERROR) {				struct nlmsgerr *err =					(struct nlmsgerr *) NLMSG_DATA(h);				if (h->nlmsg_len <				    NLMSG_LENGTH(sizeof(struct nlmsgerr))) {					DEBUG(DEBUG_FLAG,					      "rtnl_dump_filter: "					      "ERROR truncated\n");				} else {					errno = -err->error;					DEBUG(DEBUG_FLAG,					      "rtnl_dump_filter: "					      "RTNETLINK error: %s\n",					      strerror(errno));				}				return -1;			}			err = filter(&nladdr, h, arg1);			if (err < 0)				return err;			h = NLMSG_NEXT(h, status);		}		if (msg.msg_flags & MSG_TRUNC) {			DEBUG(DEBUG_FLAG,			      "rtnl_dump_filter: message truncated\n");			continue;		}		if (status) {			DEBUG(DEBUG_FLAG,			      "rtnl_dump_filter: remnant of size %d\n",			      status);			return -1;		}	} while (1);}static int parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta,			int len){	while (RTA_OK(rta, len)) {		if (rta->rta_type <= max)			tb[rta->rta_type] = rta;		rta = RTA_NEXT(rta,len);	}	if (len)		DEBUG(DEBUG_FLAG,  "parse_rtattr: Deficit %d, rta_len=%d\n",		      len, rta->rta_len);	return 0;}static int ll_remember_index(struct sockaddr_nl *who, struct nlmsghdr *n,			     void *arg){	struct idxmap **map = (struct idxmap **) arg;	struct ifinfomsg *ifi = NLMSG_DATA(n);	struct idxmap *im;	struct rtattr *tb[IFLA_MAX + 1];	if (map == NULL)		map = &idxmap;	if (n->nlmsg_type != RTM_NEWLINK)		return 0;	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifi)))		return -1;	memset(tb, 0, sizeof(tb));	parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(n));	if (tb[IFLA_IFNAME] == NULL)		return 0;	im = malloc(sizeof(*im));	if (im == NULL)		return -1;	im->next = *map;	im->index = ifi->ifi_index;	dynamics_strlcpy(im->name, RTA_DATA(tb[IFLA_IFNAME]),			 sizeof(im->name));	*map = im;	return 0;}static int ll_name_to_index(const char *name){	struct idxmap *im;	if (name == NULL)		return 0;	for (im = idxmap; im != NULL; im = im->next)		if (strcmp(im->name, name) == 0)			return im->index;	return 0;}static char *ll_index_to_name(int idx){	struct idxmap *im;	static char nbuf[64];	if (idx == 0)		return "*";	for (im = idxmap; im != NULL; im = im->next)		if (im->index == idx)			return im->name;	snprintf(nbuf, sizeof(nbuf), "if%d", idx);	return nbuf;}static int ll_init_map(struct rtnl_handle *rth){	if (rtnl_wilddump_request(rth, AF_UNSPEC, RTM_GETLINK) < 0) {		DEBUG(DEBUG_FLAG, "ll_init_map: cannot send dump request\n");		return -1;	}	assert(idxmap == NULL);	if (rtnl_dump_filter(rth, ll_remember_index, &idxmap) < 0) {		DEBUG(DEBUG_FLAG, "ll_init_map: dump terminated\n");		return -1;	}	return 0;}static void ll_free_map(void){	struct idxmap *idx, *prev;	idx = idxmap;	while (idx != NULL) {		prev = idx;		idx = idx->next;		free(prev);	}	idxmap = NULL;}/* Helper function for dyn_ip_addr_* functions */static int dyn_ip_addr_ops(const char *dev, struct in_addr addr, int type){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct ifaddrmsg ifa;		char buf[256];	} req;	memset(&req, 0, sizeof(req));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));	req.n.nlmsg_flags = NLM_F_REQUEST;	req.n.nlmsg_type = type;	req.ifa.ifa_family = AF_INET;	req.ifa.ifa_prefixlen = 32; /* bits */	addattr_l(&req.n, sizeof(req), IFA_LOCAL, (void *) &addr,		  sizeof(struct in_addr));	if (rtnl_open(&rth, 0) != 0)		return -1;	if (ll_init_map(&rth) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_addr_ops: ll_init_map() failed\n");		ll_free_map();		close(rth.fd);		return -1;	} 	if ((req.ifa.ifa_index = ll_name_to_index(dev)) == 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_addr_ops: interface(%s) not found\n",		      dev);		ll_free_map();		close(rth.fd);		return -1;	}	ll_free_map();	if (rtnl_talk(&rth, &req.n, NULL) < 0) {		DEBUG(DEBUG_FLAG,		      "dyn_ip_addr_ops: unknown interface %s\n", dev);		close(rth.fd);		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_addr_add: * @dev: network device name * @addr: IP address *  * Add IP address @addr to device @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_addr_add(const char *dev, struct in_addr addr){	return dyn_ip_addr_ops(dev, addr, RTM_NEWADDR);}/** * dyn_ip_addr_del: * @dev: network device name * @addr: IP address *  * Remove IP address @addr from device @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_addr_del(const char *dev, struct in_addr addr){	return dyn_ip_addr_ops(dev, addr, RTM_DELADDR);}/** * rtnl_modify_route: * @cmd:  * @flags:  * @type:  * @dev:  * @table:  * @dst:  * @bits:  * @via:  * @prefsrc: *  * Handle route modification (add/del). * If table == -1 then table is not set (use RT_TABLE_MAIN). * If dst != NULL then dst contains destinations address for the route. * If dst == NULL then dst is ignored and default route is added. * If via != NULL then via contains the gateway address. *  * Returns: 0 on success or -1 on failure */static int rtnl_modify_route(int cmd, int flags, int type, const char *dev,			     int table, const struct in_addr *dst, int bits,			     const struct in_addr *via,			     const struct in_addr *prefsrc){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct rtmsg r;		char buf[1024];	} req;	int idx;	memset(&req, 0, sizeof(req));	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = flags;	req.n.nlmsg_type = cmd;	req.r.rtm_table = RT_TABLE_MAIN;	if (cmd == RTM_DELROUTE) {		req.r.rtm_protocol = RTPROT_UNSPEC;		req.r.rtm_scope = RT_SCOPE_NOWHERE;	} else {		req.r.rtm_protocol = RTPROT_BOOT;		req.r.rtm_scope = RT_SCOPE_LINK;	}	req.r.rtm_type = type;	req.r.rtm_family = AF_INET;	if (dst != NULL) {		addattr_l(&req.n, sizeof(req), RTA_DST, (void *) dst, 4);		req.r.rtm_dst_len = bits;	}	if (table != -1) {		if (table < 0 || table > 255) {			DEBUG(DEBUG_FLAG,			      "rtnl_modify_route: invalid table id %i\n",			      table);			return -1;		}		req.r.rtm_table = table;	}	if (via != NULL) {		addattr_l(&req.n, sizeof(req), RTA_GATEWAY, (void *) via, 4);		req.r.rtm_scope = RT_SCOPE_UNIVERSE;	}	if (prefsrc != NULL) {		addattr_l(&req.n, sizeof(req), RTA_PREFSRC, (void *) prefsrc,			  4);	}	if (rtnl_open(&rth, 0) != 0) {		DEBUG(DEBUG_FLAG, "rtnl_modify_route: rtnl_open failed\n");		return -1;	}	if (dev != NULL) {		if (ll_init_map(&rth) != 0) {			ll_free_map();			close(rth.fd);			DEBUG(DEBUG_FLAG,			      "rtnl_modify_route: ll_init_map failed\n");			return -1;		}		if ((idx = ll_name_to_index((char*)dev)) == 0) {			DEBUG(DEBUG_FLAG,			      "rtnl_modify_route: unknown interface %s\n",			      dev);			ll_free_map();			close(rth.fd);			return -1;		}		addattr32(&req.n, sizeof(req), RTA_OIF, idx);		ll_free_map();	}	if (rtnl_talk(&rth, &req.n, NULL) < 0) {		close(rth.fd);		DEBUG(DEBUG_FLAG, "rtnl_modify_route: rtnl_talk failed\n");		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_route_add_table: * @dev: network device name * @table: routing table number * @dst: destination IP address *  * Add a route in table @table through to the host address @dst * through network device @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_route_add_table(const char *dev, int table, 			   const struct in_addr *dst){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE,				 RTN_UNICAST, dev, table, dst, 32, NULL, NULL);}/** * dyn_ip_route_del_table: * @dev: network device name * @table: routing table number * @dst: destination IP address *  * Delete the route to the address @dst through device @dev * from table @table. *  * Returns: 0 if successful, else -1 */int dyn_ip_route_del_table(const char *dev, int table, 			   const struct in_addr *dst){	return rtnl_modify_route(RTM_DELROUTE, NLM_F_REQUEST,				 RTN_UNSPEC, dev, table, dst, 32, NULL, NULL);}/** * dyn_ip_route_add_net: * @dev: network device name * @dst: destination network address * @plen: prefix length of the network address *  * Add a route to network @dst/@plen through @dev. *  * Returns: 0 if successful, else -1 */int dyn_ip_route_add_net(const char *dev, const struct in_addr *dst, int plen){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE,				 RTN_UNICAST, dev, -1, dst, plen, NULL, NULL);}/** * dyn_ip_route_replace_net: * @dev: network device name * @dst: destination network address * @plen: prefix length of the network address *  * Replace route to network @dst/@plen to go through @dev. *  * Returns:  0 on success or -1 on failure */int dyn_ip_route_replace_net(const char *dev, const struct in_addr *dst,			     int plen){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE |				 NLM_F_REPLACE, RTN_UNICAST, dev, -1, dst,				 plen, NULL, NULL);}/** * dyn_ip_route_del_net: * @dev: network device name * @dst: destination network address * @plen: prefix length of the network address * * Delete a route to network @dst/@plen through @dev. * * Returns: 0 on success or -1 on failure */int dyn_ip_route_del_net(const char *dev, const struct in_addr *dst, int plen){	return rtnl_modify_route(RTM_DELROUTE, NLM_F_REQUEST,				 RTN_UNSPEC, dev, -1, dst, plen, NULL, NULL);}/** * dyn_ip_route_add_blackhole: * @table: routing table number * * Add a blackhole default routing entry to the given routing @table. * * Returns: 0 on success or -1 on failure */int dyn_ip_route_add_blackhole(int table){	return rtnl_modify_route(RTM_NEWROUTE, NLM_F_REQUEST | NLM_F_CREATE,				 RTN_BLACKHOLE, NULL, table, NULL, 32, NULL,				 NULL);}/** * dyn_ip_route_del_blackhole: * @table: routing table number * * Delete the blackhole default routing entry from the given routing @table. * * Returns: 0 on sucess or -1 on failure */int dyn_ip_route_del_blackhole(int table){	return rtnl_modify_route(RTM_DELROUTE, NLM_F_REQUEST, RTN_BLACKHOLE,				 NULL, table, NULL, 32, NULL, NULL);}/* generic routing rule help function for dyn_ip_rule_add_table() and * dyn_ip_rule_del_table() */static int change_iprule(int cmd, int type, struct in_addr *src,			 struct in_addr *dst, int table,			 const char *device, int prio){	struct rtnl_handle rth;	struct {		struct nlmsghdr n;		struct rtmsg r;		char buf[1024];	} req;	memset(&req, 0, sizeof(req));	req.n.nlmsg_type = cmd;	req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));	req.n.nlmsg_flags = NLM_F_REQUEST;	req.r.rtm_family = AF_INET;	req.r.rtm_protocol = RTPROT_BOOT;	req.r.rtm_scope = RT_SCOPE_UNIVERSE;	req.r.rtm_table = 0;	req.r.rtm_type = type;	if (cmd == RTM_NEWRULE) {		req.n.nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;	}	if (src != NULL) {		req.r.rtm_src_len = 32; /* bits */		addattr_l(&req.n, sizeof(req), RTA_SRC, (void *) src,			  sizeof(struct in_addr));	}	if (dst != NULL) {		req.r.rtm_dst_len = 32; /* bits */		addattr_l(&req.n, sizeof(req), RTA_DST, (void *) dst,			  sizeof(struct in_addr));	}	if (table < 0 || table > 255) {		DEBUG(DEBUG_FLAG,		      "change_iprule: invalid table id %i\n", table);		return -1;	}	req.r.rtm_table = table;	if (prio >= 0) {		addattr32(&req.n, sizeof(req), RTA_PRIORITY, prio);	}	if (device != NULL) {		/* Use also the incoming device to distinct packages */		addattr_l(&req.n, sizeof(req), RTA_IIF, device,			  strlen(device) + 1);	}	if (rtnl_open(&rth, 0) != 0)		return -1;	if (rtnl_talk(&rth, &req.n, NULL) < 0) {		DEBUG(DEBUG_FLAG, "change_iprule: rtnl_talk failed\n");		close(rth.fd);		return -1;	}	close(rth.fd);	return 0;}/** * dyn_ip_rule_add_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

⌨️ 快捷键说明

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