📄 dyn_ip.c
字号:
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 + -