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