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

📄 dyn_ip.c

📁 mobile ip 在linux下的一种实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	return count;}/** * dyn_ip_monitor_open: * * Open netlink monitor socket * * Returns: file descriptor for the netlink socket, or -1 on error */int dyn_ip_monitor_open(void){	struct rtnl_handle rth;	if (rtnl_open(&rth, RTMGRP_LINK | RTMGRP_IPV4_IFADDR |		RTMGRP_IPV4_ROUTE) != 0)		return -1;	return rth.fd;}static int handle_route_add(const struct current_route_info *cur,			    struct nlmsghdr *h){	struct in_addr tmp;	struct rtattr *tb[RTA_MAX + 1];	struct rtmsg *r;	int len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*r));	int ret;	char dev[IFNAMSIZ];	if (cur == NULL || !cur->known) return -1;	if (len < 0) {		DEBUG(DEBUG_FLAG, "handle_route_add: len < 0\n");		return -1;	}	r = NLMSG_DATA(h);	if (r->rtm_family != AF_INET) {		DEBUG(DEBUG_FLAG, "handle_route_add: unknown family %i\n",		      r->rtm_family);		return 0;	}	ret = 0;	memset(tb, 0, sizeof(tb));	parse_rtattr(tb, RTA_MAX, RTM_RTA(r), len);	if (tb[RTA_DST] == NULL) {		int ok = 1;		/* handle default route */		if (!tb[RTA_OIF])			return 0;		if (*(int*)RTA_DATA(tb[RTA_OIF]) != cur->ifindex)			ok = 0;		if (tb[RTA_GATEWAY] == NULL && cur->via.s_addr != 0)			ok = 0;		if (tb[RTA_GATEWAY] && cur->via.s_addr !=		    *(int*)RTA_DATA(tb[RTA_GATEWAY]))			ok = 0;		if (tb[RTA_PREFSRC] == NULL && cur->prefsrc.s_addr != 0)			ok = 0;		if (tb[RTA_PREFSRC] && cur->prefsrc.s_addr !=		    *(int*)RTA_DATA(tb[RTA_PREFSRC]))			ok = 0;		if (ok)			return 0;		DEBUG(DEBUG_FLAG,		      "Enforcing default route to dev %s (index=%i)",		      cur->ifname, cur->ifindex);		if (cur->via.s_addr != 0)			DEBUG(DEBUG_FLAG, " via %s", inet_ntoa(cur->via));		if (cur->prefsrc.s_addr != 0)			DEBUG(DEBUG_FLAG, " prefsrc %s",			      inet_ntoa(cur->prefsrc));		DEBUG(DEBUG_FLAG, "\n");		ret = dyn_ip_route_replace_default(cur->ifname,						   cur->via.s_addr == 0 ?						   NULL : &cur->via,						   cur->prefsrc.s_addr == 0 ?						   NULL : &cur->prefsrc);	} else {		int ifindex;		/* handle net/host route */		memcpy(&tmp, RTA_DATA(tb[RTA_DST]), 4);		if (tmp.s_addr != cur->net.s_addr ||		    r->rtm_dst_len != cur->prefix_len)			return 0;		if (tb[RTA_OIF] == NULL)			return 0;		ifindex = *(int*)RTA_DATA(tb[RTA_OIF]);		if (ifindex == cur->ifindex_net)			return 0;		if (cur->ifindex_net == -1) {			DEBUG(DEBUG_FLAG,			      "Enforcing no net route situation\n");			if (dyn_ip_get_ifname(ifindex, dev) < 0)				return -1;			ret = dyn_ip_route_del_net(dev, &cur->net,						   cur->prefix_len);		} else {			DEBUG(DEBUG_FLAG,			      "Enforcing net route to dev %s (index=%i)\n",			      cur->ifname_net, cur->ifindex_net);			ret = dyn_ip_route_replace_net(cur->ifname_net,						       &cur->net,						       cur->prefix_len);		}	}	if (ret < 0) return ret;	return 3;}/** * dyn_ip_monitor_get: * @fd: file descriptor for the netlink monitor socket * @cur: information about the current default home network route * * Get a netlink message from the given file descriptor. * If @cur != NULL, then the added net routes with metric 0 will be changed * to use metric 1 (workaround for multiple PC Card situations). * * Returns: *  -1 on error, *   0 if not a link message, *   1 if a device changed (added or removed), *   2 if an address changed (added or remove), *   3 if net route metric changed */int dyn_ip_monitor_get(int fd, const struct current_route_info *cur){	int status;	struct nlmsghdr *h;	struct sockaddr_nl nladdr;	struct iovec iov;	char   buf[8192];	struct msghdr msg = {		(void *) &nladdr, sizeof(nladdr),		&iov, 1,		NULL, 0,		0	};	iov.iov_base = buf;	iov.iov_len = sizeof(buf);	status = recvmsg(fd, &msg, 0);	if (status < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_monitor_get - recvmsg: %s\n",		      strerror(errno));		return -1;	}	if (status == 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_monitor_get - overrun\n");		return -1;	}	for (h = (struct nlmsghdr*) buf; status >= sizeof(*h); ) {		int len = h->nlmsg_len;		int l = len - sizeof(*h);		if (l < 0 || len > status) {			if (msg.msg_flags & MSG_TRUNC) {				DEBUG(DEBUG_FLAG, "dyn_ip_monitor_get: "				      "truncated message\n");				return -1;			}			DEBUG(DEBUG_FLAG, "dyn_ip_monitor_get: "			      "malformed message: len=%d\n", len);			return -1;		}		if (h->nlmsg_type == RTM_NEWLINK ||		    h->nlmsg_type == RTM_DELLINK)			return 1;		if (h->nlmsg_type == RTM_NEWADDR ||		    h->nlmsg_type == RTM_DELADDR)			return 2;		if (h->nlmsg_type == RTM_NEWROUTE && cur != NULL && cur->known)			return handle_route_add(cur, h);		status -= NLMSG_ALIGN(len);		h = (struct nlmsghdr *) (((char *) h) + NLMSG_ALIGN(len));	}	return 0;}struct addr_iface_struct {	int found;	int ifindex;	const struct in_addr *addr;	int count;};static int check_iface_address(struct sockaddr_nl *who, struct nlmsghdr *n,			       void *arg){	struct addr_iface_struct *data = (struct addr_iface_struct *) arg;	struct ifaddrmsg *ifa = NLMSG_DATA(n);	struct rtattr *tb[IFA_MAX + 1];	if (n->nlmsg_type != RTM_NEWADDR) {		DEBUG(DEBUG_FLAG,		      "check_iface_address: not RTM_NEWADDR (0x%x)\n",		      n->nlmsg_type);		return 0;	}	if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))		return -1;        memset(tb, 0, sizeof(tb));        parse_rtattr(tb, IFA_MAX, IFA_RTA(ifa),		     n->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));	if (tb[IFA_LOCAL] == NULL)		tb[IFA_LOCAL] = tb[IFA_ADDRESS];	if (tb[IFA_LOCAL]) {		int alen = RTA_PAYLOAD(tb[IFA_LOCAL]);		if (alen != 4) {			DEBUG(DEBUG_FLAG, "check_iface_address alen=%i != 4\n",			      alen);		}		if (ifa->ifa_index == data->ifindex) {			data->count++;			if (memcmp(RTA_DATA(tb[IFA_LOCAL]), data->addr, alen)			    == 0) {				data->found = 1;				return -2;			}		}	}	return 0;}/** * dyn_ip_iface_address: * @ifindex: interface index * @addr: address to be checked * * Check if address @addr is assigned in the interface @ifindex. * * Returns: * -1 on failure, *  0 address was not assigned, *  1 the given address is assigned to the interface, *  2 no addresses in the given interface */int dyn_ip_iface_address(int ifindex, const struct in_addr *addr){	struct addr_iface_struct data;	struct rtnl_handle rth;	if (rtnl_open(&rth, 0) != 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_iface_address: rtnl_open failed\n");		return -1;	}		if (rtnl_wilddump_request(&rth, AF_INET, RTM_GETADDR) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_iface_address: cannot send dump "		      "request\n");		close(rth.fd);		return -1;	}	data.found = 0;	data.ifindex = ifindex;	data.addr = addr;	data.count = 0;	if (rtnl_dump_filter(&rth, check_iface_address, &data) == -1) {		close(rth.fd);		DEBUG(DEBUG_FLAG, "dyn_ip_iface_address: dump terminated\n");		return -1;	}	close(rth.fd);	if (data.count == 0 && !data.found)		return 2;	return data.found;}/** * dyn_ip_get_hwaddr: * @dev: selected interface * @hwaddr: data buffer for the MAC address * @max_len: size of @hwaddr buffer in bytes * * Get MAC address of the given interface. * * Returns: 0 on success, -1 on failure, or -2 on too small max_len. */int dyn_ip_get_hwaddr(const char *dev, char *hwaddr, int max_len){	int s, i;	struct ifreq ifr;	memcpy(ifr.ifr_name, dev, strlen(dev) + 1);	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);	if (s < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_hwaddr: socket failed: %s\n",		      strerror(errno));		return -1;	}	if (ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_hwaddr: ioctl SIOGIFHWADDR "		      "failed: %s\n", strerror(errno));		close(s);		return -1;	}	close(s);	if (ifr.ifr_hwaddr.sa_family == ARPHRD_ETHER) {		if (max_len < IFNAMSIZ * 3 + 1)			return -2;		dynamics_strlcpy(hwaddr,			ether_hwtoa((unsigned char *) ifr.ifr_hwaddr.sa_data),			max_len);	} else {		if (max_len < sizeof(ifr.ifr_hwaddr.sa_data) * 3 + 1)			return -2;		for (i = 0; i < sizeof(ifr.ifr_hwaddr.sa_data); i++) {			sprintf(hwaddr + i * 3, "%02X",				ifr.ifr_hwaddr.sa_data[i]);			if (i + 1 == sizeof(ifr.ifr_hwaddr.sa_data))				hwaddr[i * 3 + 2] = '\0';			else				hwaddr[i * 3 + 2] = ':';		}	}	return 0;}#endif /* DYN_TARGET_LINUX */#ifdef DYN_TARGET_WINDOWSint dyn_ip_addr_add(const char *dev, struct in_addr addr) { return -1; }int dyn_ip_addr_del(const char *dev, struct in_addr addr) { return -1; }int dyn_ip_check_adv_routing(void) { return 0; }int dyn_ip_check_ipip(void) { return 0; }int dyn_ip_check_gre(void) { return 0; }int dyn_ip_check_netlink(void) { return 0; }int dyn_ip_get_hwaddr(const char *dev, char *hwaddr, int max_len){ return -1; }int dyn_ip_get_ifaddr(const char *dev, struct in_addr *addr){	char buf[8192];	PMIB_IPADDRTABLE info = (PMIB_IPADDRTABLE) buf;	DWORD res;	ULONG blen;	int i;	int index = dyn_ip_get_ifindex(dev);	if (index < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifaddr: dyn_ip_get_ifindex ==> "		      "%i\n", index);		return -1;	}	blen = sizeof(buf);	res = GetIpAddrTable(info, &blen, 0);	if (res != NO_ERROR) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifaddr - GetIpAddrTable"		      " returned %li (blen=%li)\n", res, blen);		return -1;	}	for (i = 0; i < info->dwNumEntries; i++) {		if (info->table[i].dwIndex == index) {			addr->s_addr = info->table[i].dwAddr;			return 0;		}	}	DEBUG(DEBUG_FLAG, "dyn_ip_get_ifaddr - could not found address for dev"	      " '%s' (index=%i)\n", dev, index);	return -1;}int dyn_ip_get_bcaddr(const char *dev, struct in_addr *addr) { return -1; }int dyn_ip_get_ifflags(const char *dev) { return IFF_UP; }int dyn_ip_get_ifindex(const char *dev){	struct idxmap *map, *pos;	int ret = -1;	map = dyn_ip_get_interface_map();	if (map == NULL) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifindex: could not get "		      "interface map\n");		return -1;	}	pos = map;	while (pos != NULL) {		/* FIX: Name is actually WCHAR (16bit characters), but at least		 * some cases are 8bit strings.. */		if (strncmp(dev, (char *) pos->name, IFNAMSIZ) == 0) {			ret = pos->index;			break;		}		pos = pos->next;	}	if (ret < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_ifindex: interface not found\n");		if (map != NULL) {			DEBUG(DEBUG_FLAG, "   using the index of the first "			      "interface..\n");			ret = map->index;		}	}	dyn_ip_free_interface_map(map);	return ret;}struct idxmap* dyn_ip_get_interface_map_alt(void){	char buf[8192];	PMIB_IFTABLE info = (PMIB_IFTABLE) buf;	ULONG blen;	DWORD res;	struct idxmap *map = NULL, *nmap;	int i;	blen = sizeof(buf);	res = GetIfTable(info, &blen, 0);	if (res != NO_ERROR) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_interface_map_alt - "		      "GetIfTable returned %li (blen=%li)\n", res, blen);		if (res == ERROR_NOT_SUPPORTED)			DEBUG(DEBUG_FLAG, "\tGetIfTable() not supported "			      "in this OS\n");		return NULL;	}	DEBUG(DEBUG_FLAG, "dwNumEntries=%li\n", info->dwNumEntries);	for (i = 0; i < info->dwNumEntries; i++) {		nmap = (struct idxmap *) malloc(sizeof(struct idxmap));		if (nmap == NULL) {			DEBUG(DEBUG_FLAG, "dyn_ip_get_interface_map_alt - "			      "malloc failed\n");			return map;		}		DEBUG(DEBUG_FLAG, "Index=%li Type=%li Descr='%s' Name='%s'\n",		      info->table[i].dwIndex,		      info->table[i].dwType,		      info->table[i].bDescr,		      info->table[i].wszName);		if (info->table[i].dwType == MIB_IF_TYPE_LOOPBACK) {			DEBUG(DEBUG_FLAG, "\tloopback iface - skipping\n");			free(nmap);			continue;		}		nmap->index = info->table[i].dwIndex;		if (info->table[i].wszName[0] == 0) {			/* WinNT does not seem to give interface names, so			 * create a temporary name for the interface */			snprintf(nmap->name, sizeof(nmap->name), "if#%i",				 info->table[i].dwIndex);		} else {			/* FIX: Name is actually WCHAR (16bit characters), but			 * at least some cases are 8bit strings.. */			dynamics_strlcpy(nmap->name,					 (char *) info->table[i].wszName,					 IFNAMSIZ);		}		nmap->name[IFNAMSIZ-1] = '\0';		nmap->next = map;		map = nmap;	}	return map;}struct idxmap* dyn_ip_get_interface_map(void){	char buf[8192];	PIP_INTERFACE_INFO info = (PIP_INTERFACE_INFO) buf;	struct idxmap *map = NULL, *nmap;	DWORD res;	ULONG blen;	int i;	blen = sizeof(buf);	/* GetInterfaceInfo() works with Win98 and Win2k (not with WinNT), try	 * GetIfEntry() if GetInterfaceInfo() failes (this should work also "	 * with NT) */	res = GetInterfaceInfo(info, &blen);	if (res != NO_ERROR) {		DEBUG(DEBUG_FLAG, "dyn_ip_get_interface_map - GetInterfaceInfo"		      " returned %li (blen=%li)\n", res, blen);		if (res == ERROR_NOT_SUPPORTED) {			DEBUG(DEBUG_FLAG, "\tGetInterfaceInfo() not supported "			      "in this OS\n");			return dyn_ip_get_interface_map_alt();		}		return NULL;	}	for (i = 0; i < info->NumAdapters; i++) {		nmap = (struct idxmap *) malloc(sizeof(struct idxmap));		if (nmap == NULL) {			DEBUG(DEBUG_FLAG, "dyn_ip_get_interface_map - malloc "			      "failed\n");			return map;		}		nmap->index = info->Adapter[i].Index;		/* FIX: Name is actually WCHAR (16bit characters), but at least		 * Win98 uses 8bit strings (NT and W2k should use unicode) */		dynamics_strlcpy(nmap->name, (char *) info->Adapter[i].Name,				 IFNAMSIZ);		nmap->name[IFNAMSIZ-1] = '\0';		nmap->next = map;		map = nmap;	}	return map;}int dyn_ip_get_saved_ifindex(void) { return -1; }int dyn_ip_iface_address(int ifindex, const struct in_addr *addr) { return 1; }int dyn_ip_link_set_dev_up(const char *dev) { return -1; }int dyn_ip_monitor_open(void) { return -1; }int dyn_ip_monitor_get(int fd, const struct current_route_info *cur){ return -1; }int dyn_ip_route_add(struct in_addr dst_addr, const char *dev){	MIB_IPFORWARDROW route;	DWORD res;	int ifindex;	struct in_addr own_addr;	ifindex = dyn_ip_get_ifindex(dev);	if (ifindex < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_add - dyn_ip_get_ifindex() "		      "failed\n");		return -1;	}	if (dyn_ip_get_ifaddr(dev, &own_addr) < 0) {		DEBUG(DEBUG_FLAG, "dyn_ip_route_add - dyn_ip_get_ifaddr() "		      "failed\n");		return -1;	}	memset(&route, 0, sizeof(route));	route.dwForwardDest = dst_addr.s_addr;	route.dwForwardMask = -1;	route.dwForwardNextHop = ow

⌨️ 快捷键说明

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