int netlink_get_interfaces(struct ifaces_list **iface_list) { int fd; int seq; int status; *iface_list = NULL; *iface_list = calloc(sizeof(struct ifaces_list), 1); if(*iface_list == NULL) { return ENOMEM; } fd = netlink_socket(NETLINK_ROUTE); if(fd == -1) { dprintf("failed with netlink"); return ERROR_NOT_SUPPORTED; } seq = netlink_request(fd, AF_UNSPEC, RTM_GETLINK); if(seq == -1) { dprintf("netlink_request RTM_GETLINK failed"); close(fd); return ERROR_NOT_SUPPORTED; } // will create one iface_entry for each interface status = netlink_parse(fd, seq, netlink_parse_interface_link, iface_list); if(status != 0) { if (*iface_list) free(*iface_list); *iface_list = NULL; return status; } seq = netlink_request(fd, AF_UNSPEC, RTM_GETADDR); if(seq == -1) { dprintf("netlink_request RTM_GETADDR failed"); close(fd); return ERROR_NOT_SUPPORTED; } // for each interface created before, will get the IPv4 / IPv6 addr status = netlink_parse(fd, seq, netlink_parse_interface_address, iface_list); close(fd); if(status != 0) { if (*iface_list) free(*iface_list); *iface_list = NULL; } return status; }
int netlink_get_routing_table(struct ipv4_routing_table **table_ipv4, struct ipv6_routing_table **table_ipv6) { int fd; int seq; int status; struct routing_table table; *table_ipv4 = NULL; *table_ipv6 = NULL; table.table_ipv4 = table_ipv4; table.table_ipv6 = table_ipv6; *table_ipv4 = calloc(sizeof(struct ipv4_routing_table), 1); *table_ipv6 = calloc(sizeof(struct ipv6_routing_table), 1); if(*table_ipv4 == NULL) { return ENOMEM; } if(*table_ipv6 == NULL) { free(*table_ipv4); return ENOMEM; } fd = netlink_socket(NETLINK_ROUTE); if(fd == -1) { dprintf("failed with netlink"); return ERROR_NOT_SUPPORTED; } seq = netlink_request(fd, AF_UNSPEC, RTM_GETROUTE); if(seq == -1) { dprintf("netlink_request RTM_GETROUTE failed"); close(fd); return ERROR_NOT_SUPPORTED; } status = netlink_parse(fd, seq, netlink_parse_routing_table, &table); close(fd); if(status != 0) { if (*table_ipv4) free(*table_ipv4); if (*table_ipv6) free(*table_ipv6); *table_ipv4 = NULL; *table_ipv6 = NULL; } return status; }
static int netlink_recv(int sock_fd, int *client_sockfd) { int save_errno = 0; char buf[NLMSG_SIZE]; while (1) { memset(buf, '\0', NLMSG_SIZE); struct nlmsghdr *nlh; struct sockaddr_nl snl; struct iovec iov = {buf, sizeof buf}; struct msghdr msg = {(void *)&snl, sizeof snl, &iov, 1, NULL, 0, 0}; int recvlen = recvmsg(sock_fd, &msg, 0); save_errno = errno; HACK_DEBUG(0, "receive msg success with recvlen = %d\n", recvlen); if (recvlen < 0) { HACK_DEBUG(9, "receive msg failed, %s", strerror(save_errno)); if (save_errno == EINTR) continue; if (save_errno == EWOULDBLOCK || save_errno == EAGAIN) break; continue; }else if (recvlen == 0) { HACK_DEBUG(9, "receive end because of the peer has performed an orderly shutdown\n"); return -1; } if (msg.msg_namelen != sizeof snl) { HACK_DEBUG(9, "Sender address length error: length %d", msg.msg_namelen); return -2; } nlh = (struct nlmsghdr *)buf; if (nlh->nlmsg_type == NLMSG_TYPE_HACK_EXECVE) { netlink_parse(nlh, client_sockfd); } } return 0; }
int netlink_get_ipv4_routing_table(struct ipv4_routing_table **table) { *table = NULL; int fd; int seq; int status; *table = calloc(sizeof(struct ipv4_routing_table), 1); if(*table == NULL) { return ENOMEM; } fd = netlink_socket(NETLINK_ROUTE); if(fd == -1) { dprintf("[%s] failed with netlink", __FUNCTION__); return ERROR_NOT_SUPPORTED; } seq = netlink_request(fd, AF_INET, RTM_GETROUTE); if(seq == -1) { dprintf("[%s] netlink_request failed", __FUNCTION__); close(fd); return ERROR_NOT_SUPPORTED; } status = netlink_parse(fd, seq, netlink_parse_ipv4_routing_table, table); close(fd); if(status != 0 && *table) { free(*table); *table = NULL; } return status; }