diff --git a/src/api.h b/src/api.h index 24b5de11..2b458224 100644 --- a/src/api.h +++ b/src/api.h @@ -31,6 +31,7 @@ enum { REMOVECONTAINER, PROCESSASYNCEVENT, SIGNALPROCESS, + DELETEINTERFACE, // 25 }; // "hyperstart" is the special container ID for adding processes. diff --git a/src/init.c b/src/init.c index 2683fb4e..782b23fd 100644 --- a/src/init.c +++ b/src/init.c @@ -1292,6 +1292,9 @@ static int hyper_ctlmsg_handle(struct hyper_event *he, uint32_t len) case SETUPINTERFACE: ret = hyper_cmd_setup_interface((char *)buf->data + 8, len - 8, pod); break; + case DELETEINTERFACE: + ret = hyper_cmd_delete_interface((char *)buf->data + 8, len - 8); + break; case SETUPROUTE: ret = hyper_cmd_setup_route((char *)buf->data + 8, len - 8, pod); break; diff --git a/src/net.c b/src/net.c index 305c13c8..ee1295a8 100644 --- a/src/net.c +++ b/src/net.c @@ -423,6 +423,64 @@ static int hyper_set_interface_attr(struct rtnl_handle *rth, return 0; } +static int hyper_set_interface_ipaddrs(struct rtnl_handle *rth, + int ifindex, + struct list_head* ipaddresses){ + uint8_t data[4]; + unsigned mask; + struct { + struct nlmsghdr n; + struct ifaddrmsg ifa; + char buf[256]; + } req; + struct hyper_ipaddress *ip; + + memset(&req, 0, sizeof(req)); + req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); + req.ifa.ifa_family = AF_INET; + req.ifa.ifa_index = ifindex; + req.ifa.ifa_scope = 0; + + list_for_each_entry(ip, ipaddresses, list) { + if (ip->addr[0]=='\0'){ + continue; + } else if (ip->addr[0]=='-') { + //start with '-' means delete an existing address + req.n.nlmsg_flags = NLM_F_REQUEST; + req.n.nlmsg_type = RTM_DELADDR;; + if (get_addr_ipv4((uint8_t *)&data, &ip->addr[1]) <= 0) { + fprintf(stderr, "get addr failed\n"); + return -1; + } + } else{ + req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; + req.n.nlmsg_type = RTM_NEWADDR; + if (get_addr_ipv4((uint8_t *)&data, ip->addr) <= 0) { + fprintf(stderr, "get addr failed\n"); + return -1; + } + } + + if (addattr_l(&req.n, sizeof(req), IFA_LOCAL, &data, 4)) { + fprintf(stderr, "setup attr failed\n"); + return -1; + } + + if (get_netmask(&mask, ip->mask) < 0) { + fprintf(stderr, "get netamsk failed\n"); + return -1; + } + + req.ifa.ifa_prefixlen = mask; + fprintf(stdout, "interface get netamsk %d %s\n", req.ifa.ifa_prefixlen, ip->mask); + if (rtnl_talk(rth, &req.n, 0, 0, NULL) < 0) { + perror("rtnl_talk failed"); + return -1; + } + } + return 0; +} + static int hyper_set_interface_name(struct rtnl_handle *rth, int ifindex, char *new_device_name) @@ -452,56 +510,22 @@ static int hyper_setup_interface(struct rtnl_handle *rth, struct hyper_interface *iface, struct hyper_pod *pod) { - uint8_t data[4]; - unsigned mask; - struct { - struct nlmsghdr n; - struct ifaddrmsg ifa; - char buf[256]; - } req; int ifindex; - struct hyper_ipaddress *ip; - - if (!iface->device || list_empty(&iface->ipaddresses)) { - fprintf(stderr, "interface information incorrect\n"); + if (!iface->device) { + fprintf(stderr, "device name can't be empty\n"); return -1; } - memset(&req, 0, sizeof(req)); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)); - req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - req.n.nlmsg_type = RTM_NEWADDR; - req.ifa.ifa_family = AF_INET; - ifindex = hyper_get_ifindex(iface->device, pod); if (ifindex < 0) { fprintf(stderr, "failed to get the ifindix of %s\n", iface->device); return -1; } - req.ifa.ifa_index = ifindex; - req.ifa.ifa_scope = 0; - - list_for_each_entry(ip, &iface->ipaddresses, list) { - if (get_addr_ipv4((uint8_t *)&data, ip->addr) <= 0) { - fprintf(stderr, "get addr failed\n"); - return -1; - } - - if (addattr_l(&req.n, sizeof(req), IFA_LOCAL, &data, 4)) { - fprintf(stderr, "setup attr failed\n"); - return -1; - } - - if (get_netmask(&mask, ip->mask) < 0) { - fprintf(stderr, "get netamsk failed\n"); - return -1; - } - - req.ifa.ifa_prefixlen = mask; - fprintf(stdout, "interface get netamsk %d %s\n", req.ifa.ifa_prefixlen, ip->mask); - if (rtnl_talk(rth, &req.n, 0, 0, NULL) < 0) { - perror("rtnl_talk failed"); + if (!list_empty(&iface->ipaddresses)) { + if (hyper_set_interface_ipaddrs(rth, ifindex, &iface->ipaddresses) < 0) { + fprintf(stderr, "set ip addresses failed for interface %s\n", + iface->device); return -1; } } @@ -603,7 +627,6 @@ int hyper_cmd_setup_interface(char *json, int length, struct hyper_pod *pod) if (netlink_open(&rth) < 0) return -1; - iface = hyper_parse_setup_interface(json, length); if (iface == NULL) { fprintf(stderr, "parse interface failed\n"); @@ -623,6 +646,71 @@ int hyper_cmd_setup_interface(char *json, int length, struct hyper_pod *pod) return ret; } +static int hyper_remove_nic(char *device) +{ + char path[256], real[128]; + int fd; + ssize_t size; + + sprintf(path, "/sys/class/net/%s", device); + + size = readlink(path, real, 128); + if (size < 0 || size > 127) { + perror("fail to read link directory"); + return -1; + } + + real[size] = '\0'; + sprintf(path, "/sys/%s/../../../remove", real + 5); + + fprintf(stdout, "get net sys path %s\n", path); + + fd = open(path, O_WRONLY); + if (fd < 0) { + perror("open file failed"); + return -1; + } + + if (write(fd, "1\n", 2) < 0) { + perror("write 1 to file failed"); + close(fd); + return 1; + } + + close(fd); + return 0; +} + +int hyper_cmd_delete_interface(char *json, int length) +{ + int ret = -1; + struct hyper_interface *iface; + struct rtnl_handle rth; + + fprintf(stdout, "client demands to remove network interface\n"); + if (netlink_open(&rth) < 0) + return -1; + + iface = hyper_parse_setup_interface(json, length); + if (iface == NULL) { + fprintf(stderr, "parse interface failed\n"); + goto out; + } + + if (hyper_remove_nic(iface->device) < 0){ + fprintf(stderr, "remove device %s failed\n", iface->device); + goto out1; + } + fprintf(stdout, "remove device %s successfully\n", iface->device); + ret = 0; +out1: + hyper_free_interface(iface); + free(iface); +out: + netlink_close(&rth); + return ret; +} + int hyper_cmd_setup_route(char *json, int length, struct hyper_pod *pod) { struct hyper_route *rts = NULL; @@ -780,3 +868,4 @@ int hyper_setup_dns(struct hyper_pod *pod) close(fd); return ret; } + diff --git a/src/net.h b/src/net.h index 7031a597..a67170d8 100644 --- a/src/net.h +++ b/src/net.h @@ -52,4 +52,5 @@ int hyper_setup_dns(struct hyper_pod *pod); int hyper_setup_hostname(struct hyper_pod *pod); int hyper_send_data_block(int fd, uint8_t *data, uint32_t len); int hyper_send_data(int fd, uint8_t *data, uint32_t len); +int hyper_cmd_delete_interface(char *json, int length); #endif