2015-05-15 05:44:48 +08:00
|
|
|
/*
|
|
|
|
|
|
|
|
nsjail - networking routines
|
|
|
|
-----------------------------------------
|
|
|
|
|
|
|
|
Copyright 2014 Google Inc. All Rights Reserved.
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
*/
|
2016-03-02 00:03:11 +08:00
|
|
|
|
2015-05-15 05:44:48 +08:00
|
|
|
#include "net.h"
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <errno.h>
|
2016-02-29 07:14:36 +08:00
|
|
|
#include <net/if.h>
|
2016-02-29 09:51:55 +08:00
|
|
|
#include <net/route.h>
|
2017-10-18 20:46:17 +08:00
|
|
|
#include <netinet/in.h>
|
2016-02-29 09:51:55 +08:00
|
|
|
#include <netinet/ip6.h>
|
|
|
|
#include <netinet/tcp.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <stdint.h>
|
2017-09-14 04:03:21 +08:00
|
|
|
#include <stdio.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
2016-02-29 07:14:36 +08:00
|
|
|
#include <sys/ioctl.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <sys/socket.h>
|
2015-05-28 09:37:08 +08:00
|
|
|
#include <sys/time.h>
|
2015-05-15 05:44:48 +08:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2018-02-11 00:49:15 +08:00
|
|
|
#include "logs.h"
|
2018-02-10 00:27:28 +08:00
|
|
|
#include "subproc.h"
|
2016-03-01 05:12:01 +08:00
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
extern char** environ;
|
2016-07-21 21:48:47 +08:00
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
namespace net {
|
|
|
|
|
|
|
|
#define IFACE_NAME "vs"
|
|
|
|
|
2016-03-01 05:12:01 +08:00
|
|
|
#if defined(NSJAIL_NL3_WITH_MACVLAN)
|
|
|
|
#include <netlink/route/link.h>
|
|
|
|
#include <netlink/route/link/macvlan.h>
|
2018-02-10 22:50:12 +08:00
|
|
|
bool initNsFromParent(nsjconf_t* nsjconf, int pid) {
|
2016-03-04 03:11:32 +08:00
|
|
|
if (nsjconf->clone_newnet == false) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-11 01:18:40 +08:00
|
|
|
if (nsjconf->iface_vs.empty()) {
|
2016-03-01 06:10:14 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
LOG_D("Putting iface:'%s' into namespace of PID:%d (with libnl3)",
|
|
|
|
nsjconf->iface_vs.c_str(), pid);
|
2017-05-22 04:29:01 +08:00
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
struct nl_sock* sk = nl_socket_alloc();
|
2016-03-09 08:16:50 +08:00
|
|
|
if (sk == NULL) {
|
|
|
|
LOG_E("Could not allocate socket with nl_socket_alloc()");
|
|
|
|
return false;
|
|
|
|
}
|
2016-03-09 01:37:07 +08:00
|
|
|
|
2016-03-09 08:16:50 +08:00
|
|
|
int err;
|
2016-03-01 05:12:01 +08:00
|
|
|
if ((err = nl_connect(sk, NETLINK_ROUTE)) < 0) {
|
|
|
|
LOG_E("Unable to connect socket: %s", nl_geterror(err));
|
2016-07-29 21:38:22 +08:00
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return false;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
struct rtnl_link* rmv = rtnl_link_macvlan_alloc();
|
2016-03-01 05:12:01 +08:00
|
|
|
if (rmv == NULL) {
|
|
|
|
LOG_E("rtnl_link_macvlan_alloc(): %s", nl_geterror(err));
|
2016-07-29 21:38:22 +08:00
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return false;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
struct nl_cache* link_cache;
|
2016-03-01 05:12:01 +08:00
|
|
|
if ((err = rtnl_link_alloc_cache(sk, AF_UNSPEC, &link_cache)) < 0) {
|
|
|
|
LOG_E("rtnl_link_alloc_cache(): %s", nl_geterror(err));
|
2016-07-29 21:38:22 +08:00
|
|
|
rtnl_link_put(rmv);
|
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return false;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
int master_index = rtnl_link_name2i(link_cache, nsjconf->iface_vs.c_str());
|
2016-03-09 08:16:50 +08:00
|
|
|
if (master_index == 0) {
|
2018-02-11 01:18:40 +08:00
|
|
|
LOG_E("rtnl_link_name2i(): Did not find '%s' interface", nsjconf->iface_vs.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
nl_cache_free(link_cache);
|
|
|
|
rtnl_link_put(rmv);
|
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return false;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
rtnl_link_set_name(rmv, IFACE_NAME);
|
|
|
|
rtnl_link_set_link(rmv, master_index);
|
|
|
|
rtnl_link_set_ns_pid(rmv, pid);
|
|
|
|
|
|
|
|
if ((err = rtnl_link_add(sk, rmv, NLM_F_CREATE)) < 0) {
|
2018-02-11 01:18:40 +08:00
|
|
|
LOG_E("rtnl_link_add(name:'%s' link:'%s'): %s", IFACE_NAME,
|
|
|
|
nsjconf->iface_vs.c_str(), nl_geterror(err));
|
2016-07-29 21:38:22 +08:00
|
|
|
nl_cache_free(link_cache);
|
|
|
|
rtnl_link_put(rmv);
|
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return false;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
|
|
|
|
2016-07-29 21:38:22 +08:00
|
|
|
nl_cache_free(link_cache);
|
|
|
|
rtnl_link_put(rmv);
|
|
|
|
nl_socket_free(sk);
|
2016-03-09 01:37:07 +08:00
|
|
|
return true;
|
2016-03-01 05:12:01 +08:00
|
|
|
}
|
2017-10-26 06:26:02 +08:00
|
|
|
#else // defined(NSJAIL_NL3_WITH_MACVLAN)
|
2015-05-28 09:37:08 +08:00
|
|
|
|
2018-02-10 22:50:12 +08:00
|
|
|
bool initNsFromParent(nsjconf_t* nsjconf, int pid) {
|
2016-03-04 03:11:32 +08:00
|
|
|
if (nsjconf->clone_newnet == false) {
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-11 01:18:40 +08:00
|
|
|
if (nsjconf->iface_vs.empty()) {
|
2015-05-28 09:37:08 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
LOG_D("Putting iface:'%s' into namespace of PID:%d (with /sbin/ip)",
|
|
|
|
nsjconf->iface_vs.c_str(), pid);
|
2017-05-22 04:29:01 +08:00
|
|
|
|
2016-03-01 00:59:49 +08:00
|
|
|
char pid_str[256];
|
|
|
|
snprintf(pid_str, sizeof(pid_str), "%d", pid);
|
2015-05-28 09:37:08 +08:00
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
const char* argv[] = {"/sbin/ip", "link", "add", "link", (char*)nsjconf->iface_vs.c_str(),
|
|
|
|
"name", IFACE_NAME, "netns", pid_str, "type", "macvlan", "mode", "bridge", NULL};
|
2018-02-10 01:45:50 +08:00
|
|
|
if (subproc::systemExe(argv, environ) != 0) {
|
2018-02-11 01:18:40 +08:00
|
|
|
LOG_E("Couldn't create MACVTAP interface for '%s'", nsjconf->iface_vs.c_str());
|
2015-05-28 09:37:08 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2017-10-26 06:26:02 +08:00
|
|
|
#endif // defined(NSJAIL_NL3_WITH_MACVLAN)
|
2015-05-28 09:37:08 +08:00
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
static bool isSocket(int fd) {
|
2015-05-15 05:44:48 +08:00
|
|
|
int optval;
|
|
|
|
socklen_t optlen = sizeof(optval);
|
|
|
|
int ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &optval, &optlen);
|
|
|
|
if (ret == -1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-10 22:50:12 +08:00
|
|
|
bool limitConns(nsjconf_t* nsjconf, int connsock) {
|
2015-05-15 05:44:48 +08:00
|
|
|
/* 0 means 'unlimited' */
|
|
|
|
if (nsjconf->max_conns_per_ip == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in6 addr;
|
|
|
|
char cs_addr[64];
|
2018-02-10 00:27:28 +08:00
|
|
|
connToText(connsock, true /* remote */, cs_addr, sizeof(cs_addr), &addr);
|
2015-05-15 05:44:48 +08:00
|
|
|
|
2018-02-10 12:13:25 +08:00
|
|
|
unsigned cnt = 0;
|
|
|
|
for (const auto& pid : nsjconf->pids) {
|
|
|
|
if (memcmp(addr.sin6_addr.s6_addr, pid.remote_addr.sin6_addr.s6_addr,
|
|
|
|
sizeof(pid.remote_addr.sin6_addr.s6_addr)) == 0) {
|
2015-05-15 05:44:48 +08:00
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cnt >= nsjconf->max_conns_per_ip) {
|
|
|
|
LOG_W("Rejecting connection from '%s', max_conns_per_ip limit reached: %u", cs_addr,
|
2017-10-09 05:00:45 +08:00
|
|
|
nsjconf->max_conns_per_ip);
|
2015-05-15 05:44:48 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
int getRecvSocket(const char* bindhost, int port) {
|
2015-05-15 05:44:48 +08:00
|
|
|
if (port < 1 || port > 65535) {
|
2017-10-26 06:26:02 +08:00
|
|
|
LOG_F(
|
|
|
|
"TCP port %d out of bounds (0 <= port <= 65535), specify one with --port "
|
|
|
|
"<port>",
|
2017-10-09 05:00:45 +08:00
|
|
|
port);
|
2015-05-15 05:44:48 +08:00
|
|
|
}
|
|
|
|
|
2017-06-20 04:35:57 +08:00
|
|
|
char bindaddr[128];
|
|
|
|
snprintf(bindaddr, sizeof(bindaddr), "%s", bindhost);
|
|
|
|
struct in_addr in4a;
|
|
|
|
if (inet_pton(AF_INET, bindaddr, &in4a) == 1) {
|
|
|
|
snprintf(bindaddr, sizeof(bindaddr), "::ffff:%s", bindhost);
|
2017-06-20 05:59:29 +08:00
|
|
|
LOG_D("Converting bind IPv4:'%s' to IPv6:'%s'", bindhost, bindaddr);
|
2017-06-20 04:35:57 +08:00
|
|
|
}
|
|
|
|
|
2016-02-26 01:27:48 +08:00
|
|
|
struct in6_addr in6a;
|
2017-06-20 04:35:57 +08:00
|
|
|
if (inet_pton(AF_INET6, bindaddr, &in6a) != 1) {
|
2017-10-17 21:22:23 +08:00
|
|
|
PLOG_E(
|
|
|
|
"Couldn't convert '%s' (orig:'%s') into AF_INET6 address", bindaddr, bindhost);
|
2016-02-26 01:27:48 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-05-15 05:44:48 +08:00
|
|
|
int sockfd = socket(AF_INET6, SOCK_STREAM, 0);
|
|
|
|
if (sockfd == -1) {
|
|
|
|
PLOG_E("socket(AF_INET6)");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
int so = 1;
|
|
|
|
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &so, sizeof(so)) == -1) {
|
|
|
|
PLOG_E("setsockopt(%d, SO_REUSEADDR)", sockfd);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
struct sockaddr_in6 addr = {
|
2017-10-26 06:26:02 +08:00
|
|
|
.sin6_family = AF_INET6,
|
|
|
|
.sin6_port = htons(port),
|
|
|
|
.sin6_flowinfo = 0,
|
|
|
|
.sin6_addr = in6a,
|
|
|
|
.sin6_scope_id = 0,
|
2015-05-15 05:44:48 +08:00
|
|
|
};
|
2017-10-09 05:00:45 +08:00
|
|
|
if (bind(sockfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sockfd);
|
2017-10-11 21:43:59 +08:00
|
|
|
PLOG_E("bind(host:[%s] (orig:'%s'), port:%d)", bindaddr, bindhost, port);
|
2015-05-15 05:44:48 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (listen(sockfd, SOMAXCONN) == -1) {
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sockfd);
|
2015-05-15 05:44:48 +08:00
|
|
|
PLOG_E("listen(%d)", SOMAXCONN);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char ss_addr[64];
|
2018-02-10 00:27:28 +08:00
|
|
|
connToText(sockfd, false /* remote */, ss_addr, sizeof(ss_addr), NULL);
|
2015-05-15 05:44:48 +08:00
|
|
|
LOG_I("Listening on %s", ss_addr);
|
|
|
|
|
|
|
|
return sockfd;
|
|
|
|
}
|
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
int acceptConn(int listenfd) {
|
2015-05-15 05:44:48 +08:00
|
|
|
struct sockaddr_in6 cli_addr;
|
|
|
|
socklen_t socklen = sizeof(cli_addr);
|
2017-10-09 05:00:45 +08:00
|
|
|
int connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &socklen);
|
2015-05-15 05:44:48 +08:00
|
|
|
if (connfd == -1) {
|
|
|
|
if (errno != EINTR) {
|
|
|
|
PLOG_E("accept(%d)", listenfd);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
char cs_addr[64], ss_addr[64];
|
2018-02-10 00:27:28 +08:00
|
|
|
connToText(connfd, true /* remote */, cs_addr, sizeof(cs_addr), NULL);
|
|
|
|
connToText(connfd, false /* remote */, ss_addr, sizeof(ss_addr), NULL);
|
2015-05-15 05:44:48 +08:00
|
|
|
LOG_I("New connection from: %s on: %s", cs_addr, ss_addr);
|
|
|
|
|
|
|
|
return connfd;
|
|
|
|
}
|
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
void connToText(int fd, bool remote, char* buf, size_t s, struct sockaddr_in6* addr_or_null) {
|
|
|
|
if (isSocket(fd) == false) {
|
2015-05-15 05:44:48 +08:00
|
|
|
snprintf(buf, s, "[STANDALONE_MODE]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct sockaddr_in6 addr;
|
|
|
|
socklen_t addrlen = sizeof(addr);
|
|
|
|
if (remote) {
|
2017-10-09 05:00:45 +08:00
|
|
|
if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) == -1) {
|
2015-05-15 05:44:48 +08:00
|
|
|
PLOG_W("getpeername(%d)", fd);
|
|
|
|
snprintf(buf, s, "[unknown]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2017-10-09 05:00:45 +08:00
|
|
|
if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) == -1) {
|
2015-05-15 05:44:48 +08:00
|
|
|
PLOG_W("getsockname(%d)", fd);
|
|
|
|
snprintf(buf, s, "[unknown]");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addr_or_null) {
|
|
|
|
memcpy(addr_or_null, &addr, sizeof(*addr_or_null));
|
|
|
|
}
|
|
|
|
|
|
|
|
char tmp[s];
|
|
|
|
if (inet_ntop(AF_INET6, addr.sin6_addr.s6_addr, tmp, s) == NULL) {
|
|
|
|
PLOG_W("inet_ntop()");
|
|
|
|
snprintf(buf, s, "[unknown]:%hu", ntohs(addr.sin6_port));
|
|
|
|
return;
|
|
|
|
}
|
2016-02-26 01:27:48 +08:00
|
|
|
snprintf(buf, s, "[%s]:%hu", tmp, ntohs(addr.sin6_port));
|
2015-05-15 05:44:48 +08:00
|
|
|
return;
|
|
|
|
}
|
2016-02-29 07:14:36 +08:00
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
static bool ifaceUp(const char* ifacename) {
|
2016-03-10 06:48:07 +08:00
|
|
|
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
2016-02-29 07:14:36 +08:00
|
|
|
if (sock == -1) {
|
|
|
|
PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-10 02:12:48 +08:00
|
|
|
struct ifreq ifr = {};
|
2016-02-29 07:14:36 +08:00
|
|
|
snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", ifacename);
|
|
|
|
|
|
|
|
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1) {
|
2016-02-29 09:51:55 +08:00
|
|
|
PLOG_E("ioctl(iface='%s', SIOCGIFFLAGS, IFF_UP)", ifacename);
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 07:14:36 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
|
|
|
|
|
|
|
|
if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1) {
|
2016-11-21 06:41:05 +08:00
|
|
|
PLOG_E("ioctl(iface='%s', SIOCSIFFLAGS, IFF_UP|IFF_RUNNING)", ifacename);
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-10 22:50:12 +08:00
|
|
|
static bool netConfigureVs(nsjconf_t* nsjconf) {
|
2018-02-10 02:12:48 +08:00
|
|
|
struct ifreq ifr = {};
|
2016-02-29 09:51:55 +08:00
|
|
|
snprintf(ifr.ifr_name, IF_NAMESIZE, "%s", IFACE_NAME);
|
|
|
|
struct in_addr addr;
|
|
|
|
|
2016-03-10 06:48:07 +08:00
|
|
|
int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
|
2016-02-29 09:51:55 +08:00
|
|
|
if (sock == -1) {
|
|
|
|
PLOG_E("socket(AF_INET, SOCK_STREAM, IPPROTO_IP)");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
if (inet_pton(AF_INET, nsjconf->iface_vs_ip.c_str(), &addr) != 1) {
|
|
|
|
PLOG_E("Cannot convert '%s' into an IPv4 address", nsjconf->iface_vs_ip.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
2016-03-01 00:50:25 +08:00
|
|
|
if (addr.s_addr == INADDR_ANY) {
|
2017-05-22 04:29:01 +08:00
|
|
|
LOG_D("IPv4 address for interface '%s' not set", IFACE_NAME);
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-03-01 00:50:25 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
struct sockaddr_in* sa = (struct sockaddr_in*)(&ifr.ifr_addr);
|
2016-02-29 09:51:55 +08:00
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
sa->sin_addr = addr;
|
|
|
|
if (ioctl(sock, SIOCSIFADDR, &ifr) == -1) {
|
2018-02-11 01:18:40 +08:00
|
|
|
PLOG_E("ioctl(iface='%s', SIOCSIFADDR, '%s')", IFACE_NAME,
|
|
|
|
nsjconf->iface_vs_ip.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
if (inet_pton(AF_INET, nsjconf->iface_vs_nm.c_str(), &addr) != 1) {
|
|
|
|
PLOG_E("Cannot convert '%s' into a IPv4 netmask", nsjconf->iface_vs_nm.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
sa->sin_family = AF_INET;
|
|
|
|
sa->sin_addr = addr;
|
|
|
|
if (ioctl(sock, SIOCSIFNETMASK, &ifr) == -1) {
|
2018-02-11 01:18:40 +08:00
|
|
|
PLOG_E("ioctl(iface='%s', SIOCSIFNETMASK, '%s')", IFACE_NAME,
|
|
|
|
nsjconf->iface_vs_nm.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-10 00:27:28 +08:00
|
|
|
if (ifaceUp(IFACE_NAME) == false) {
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-02-11 01:18:40 +08:00
|
|
|
if (inet_pton(AF_INET, nsjconf->iface_vs_gw.c_str(), &addr) != 1) {
|
|
|
|
PLOG_E("Cannot convert '%s' into a IPv4 GW address", nsjconf->iface_vs_gw.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 09:51:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
2016-02-29 22:36:31 +08:00
|
|
|
if (addr.s_addr == INADDR_ANY) {
|
2017-05-22 04:29:01 +08:00
|
|
|
LOG_D("Gateway address for '%s' is not set", IFACE_NAME);
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 22:36:31 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2018-02-10 02:12:48 +08:00
|
|
|
struct rtentry rt = {};
|
2016-02-29 09:51:55 +08:00
|
|
|
|
2017-10-09 05:00:45 +08:00
|
|
|
struct sockaddr_in* sdest = (struct sockaddr_in*)(&rt.rt_dst);
|
|
|
|
struct sockaddr_in* smask = (struct sockaddr_in*)(&rt.rt_genmask);
|
|
|
|
struct sockaddr_in* sgate = (struct sockaddr_in*)(&rt.rt_gateway);
|
2016-02-29 09:51:55 +08:00
|
|
|
sdest->sin_family = AF_INET;
|
|
|
|
sdest->sin_addr.s_addr = INADDR_ANY;
|
|
|
|
smask->sin_family = AF_INET;
|
|
|
|
smask->sin_addr.s_addr = INADDR_ANY;
|
|
|
|
sgate->sin_family = AF_INET;
|
|
|
|
sgate->sin_addr = addr;
|
|
|
|
|
|
|
|
rt.rt_flags = RTF_UP | RTF_GATEWAY;
|
2018-02-10 00:27:28 +08:00
|
|
|
char rt_dev[] = IFACE_NAME;
|
|
|
|
rt.rt_dev = rt_dev;
|
2016-02-29 09:51:55 +08:00
|
|
|
|
|
|
|
if (ioctl(sock, SIOCADDRT, &rt) == -1) {
|
2018-02-11 01:18:40 +08:00
|
|
|
PLOG_E("ioctl(SIOCADDRT, '%s')", nsjconf->iface_vs_gw.c_str());
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 07:14:36 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-07-29 21:38:22 +08:00
|
|
|
close(sock);
|
2016-02-29 07:14:36 +08:00
|
|
|
return true;
|
|
|
|
}
|
2016-03-03 22:37:04 +08:00
|
|
|
|
2018-02-10 22:50:12 +08:00
|
|
|
bool initNsFromChild(nsjconf_t* nsjconf) {
|
2018-02-11 01:22:51 +08:00
|
|
|
if (!nsjconf->clone_newnet) {
|
2016-03-04 03:11:32 +08:00
|
|
|
return true;
|
|
|
|
}
|
2018-02-11 01:22:51 +08:00
|
|
|
if (nsjconf->iface_lo) {
|
|
|
|
if (!ifaceUp("lo")) {
|
2016-03-03 22:37:04 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2018-02-11 01:18:40 +08:00
|
|
|
if (!nsjconf->iface_vs.empty()) {
|
2018-02-11 01:22:51 +08:00
|
|
|
if (!netConfigureVs(nsjconf)) {
|
2016-03-03 22:37:04 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2018-02-10 00:27:28 +08:00
|
|
|
|
|
|
|
} // namespace net
|