mirror of
https://github.com/ntop/n2n.git
synced 2024-09-20 00:51:10 +02:00
Add support for linux capabilities to proper routes cleanup
This commit is contained in:
parent
62b9530425
commit
0e48e2f24c
|
@ -49,6 +49,12 @@ if test x$pcap_immediate_mode != x; then
|
||||||
AC_DEFINE([HAVE_PCAP_IMMEDIATE_MODE], [], [Have pcap_immediate_mode])
|
AC_DEFINE([HAVE_PCAP_IMMEDIATE_MODE], [], [Have pcap_immediate_mode])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_CHECK_LIB([cap], [cap_get_proc], cap=true)
|
||||||
|
if test x$cap != x; then
|
||||||
|
LDFLAGS="${LDFLAGS} -lcap"
|
||||||
|
AC_DEFINE([HAVE_LIBCAP],[1],[Support for linux capabilities])
|
||||||
|
fi
|
||||||
|
|
||||||
MACHINE=`uname -m`
|
MACHINE=`uname -m`
|
||||||
SYSTEM=`uname -s`
|
SYSTEM=`uname -s`
|
||||||
|
|
||||||
|
|
45
edge.c
45
edge.c
|
@ -37,6 +37,21 @@
|
||||||
|
|
||||||
/* ***************************************************** */
|
/* ***************************************************** */
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCAP
|
||||||
|
|
||||||
|
#include <sys/capability.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
|
static cap_value_t cap_values[] = {
|
||||||
|
//CAP_NET_RAW, /* Use RAW and PACKET sockets */
|
||||||
|
CAP_NET_ADMIN /* Needed to performs routes cleanup at exit */
|
||||||
|
};
|
||||||
|
|
||||||
|
int num_cap = sizeof(cap_values)/sizeof(cap_value_t);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ***************************************************** */
|
||||||
|
|
||||||
typedef struct n2n_priv_config {
|
typedef struct n2n_priv_config {
|
||||||
char tuntap_dev_name[N2N_IFNAMSIZ];
|
char tuntap_dev_name[N2N_IFNAMSIZ];
|
||||||
char ip_mode[N2N_IF_MODE_SIZE];
|
char ip_mode[N2N_IF_MODE_SIZE];
|
||||||
|
@ -681,6 +696,9 @@ int main(int argc, char* argv[]) {
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
struct passwd *pw = NULL;
|
struct passwd *pw = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LIBCAP
|
||||||
|
cap_t caps;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Defaults */
|
/* Defaults */
|
||||||
edge_init_conf_defaults(&conf);
|
edge_init_conf_defaults(&conf);
|
||||||
|
@ -774,6 +792,22 @@ int main(int argc, char* argv[]) {
|
||||||
#endif /* #ifndef WIN32 */
|
#endif /* #ifndef WIN32 */
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCAP
|
||||||
|
/* Before dropping the privileges, retain capabilities to regain them in future. */
|
||||||
|
caps = cap_get_proc();
|
||||||
|
|
||||||
|
cap_set_flag(caps, CAP_PERMITTED, num_cap, cap_values, CAP_SET);
|
||||||
|
cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET);
|
||||||
|
|
||||||
|
if((cap_set_proc(caps) != 0) || (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0))
|
||||||
|
traceEvent(TRACE_WARNING, "Unable to retain permitted capabilities [%s]\n", strerror(errno));
|
||||||
|
#else
|
||||||
|
#ifndef __APPLE__
|
||||||
|
traceEvent(TRACE_WARNING, "n2n has not been compiled with libcap-dev. Some commands may fail.");
|
||||||
|
#endif
|
||||||
|
#endif /* HAVE_LIBCAP */
|
||||||
|
|
||||||
if((ec.userid != 0) || (ec.groupid != 0)) {
|
if((ec.userid != 0) || (ec.groupid != 0)) {
|
||||||
traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d",
|
traceEvent(TRACE_NORMAL, "Dropping privileges to uid=%d, gid=%d",
|
||||||
(signed int)ec.userid, (signed int)ec.groupid);
|
(signed int)ec.userid, (signed int)ec.groupid);
|
||||||
|
@ -803,6 +837,17 @@ int main(int argc, char* argv[]) {
|
||||||
rc = run_edge_loop(eee, &keep_on_running);
|
rc = run_edge_loop(eee, &keep_on_running);
|
||||||
print_edge_stats(eee);
|
print_edge_stats(eee);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBCAP
|
||||||
|
/* Before completing the cleanup, regain the capabilities as some
|
||||||
|
* cleanup tasks require them (e.g. routes cleanup). */
|
||||||
|
cap_set_flag(caps, CAP_EFFECTIVE, num_cap, cap_values, CAP_SET);
|
||||||
|
|
||||||
|
if(cap_set_proc(caps) != 0)
|
||||||
|
traceEvent(TRACE_WARNING, "Could not regain the capabilities [%s]\n", strerror(errno));
|
||||||
|
|
||||||
|
cap_free(caps);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
edge_term(eee);
|
edge_term(eee);
|
||||||
edge_term_conf(&conf);
|
edge_term_conf(&conf);
|
||||||
|
|
27
edge_utils.c
27
edge_utils.c
|
@ -2042,10 +2042,10 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size
|
||||||
|
|
||||||
switch(cmd) {
|
switch(cmd) {
|
||||||
case RTM_NEWROUTE:
|
case RTM_NEWROUTE:
|
||||||
cmd_str = "ADD";
|
cmd_str = "Add";
|
||||||
break;
|
break;
|
||||||
case RTM_DELROUTE:
|
case RTM_DELROUTE:
|
||||||
cmd_str = "DELETE";
|
cmd_str = "Delete";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cmd_str = "?";
|
cmd_str = "?";
|
||||||
|
@ -2056,7 +2056,7 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size
|
||||||
addr.s_addr = route->gateway;
|
addr.s_addr = route->gateway;
|
||||||
inet_ntop(AF_INET, &addr, gwbuf, sizeof(gwbuf));
|
inet_ntop(AF_INET, &addr, gwbuf, sizeof(gwbuf));
|
||||||
|
|
||||||
snprintf(buf, bufsize, "[%s] %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf);
|
snprintf(buf, bufsize, "%s %s/%d via %s", cmd_str, netbuf, route->net_bitlen, gwbuf);
|
||||||
|
|
||||||
return(buf);
|
return(buf);
|
||||||
}
|
}
|
||||||
|
@ -2088,10 +2088,11 @@ static int rtattr_add(struct nlmsghdr *n, int maxlen, int type, const void *data
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t ignore_failure) {
|
static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx) {
|
||||||
int rv = -1;
|
int rv = -1;
|
||||||
int rv2;
|
int rv2;
|
||||||
char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */
|
char nl_buf[8192]; /* >= 8192 to avoid truncation, see "man 7 netlink" */
|
||||||
|
char route_buf[256];
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
struct sockaddr_nl sa;
|
struct sockaddr_nl sa;
|
||||||
|
@ -2194,7 +2195,6 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t
|
||||||
read_reply = 0;
|
read_reply = 0;
|
||||||
|
|
||||||
if(nh->nlmsg_type == NLMSG_ERROR) {
|
if(nh->nlmsg_type == NLMSG_ERROR) {
|
||||||
char buf[256];
|
|
||||||
struct nlmsgerr *err = NLMSG_DATA(nh);
|
struct nlmsgerr *err = NLMSG_DATA(nh);
|
||||||
int errcode = err->error;
|
int errcode = err->error;
|
||||||
|
|
||||||
|
@ -2202,8 +2202,8 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t
|
||||||
errcode = -errcode;
|
errcode = -errcode;
|
||||||
|
|
||||||
/* Ignore EEXIST as existing rules are ok */
|
/* Ignore EEXIST as existing rules are ok */
|
||||||
if(!ignore_failure && (errcode != EEXIST)) {
|
if(errcode != EEXIST) {
|
||||||
traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, buf, sizeof(buf)));
|
traceEvent(TRACE_ERROR, "[err=%d] route: %s", errcode, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf)));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2211,11 +2211,14 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx, uint8_t
|
||||||
if(nh->nlmsg_type == NLMSG_DONE)
|
if(nh->nlmsg_type == NLMSG_DONE)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(nh->nlmsg_type == cmd)
|
if(nh->nlmsg_type == cmd) {
|
||||||
|
traceEvent(TRACE_DEBUG, "Found netlink reply");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
traceEvent(TRACE_DEBUG, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf)));
|
||||||
rv = 0;
|
rv = 0;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -2278,7 +2281,7 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ip route add supernode via internet_gateway */
|
/* ip route add supernode via internet_gateway */
|
||||||
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1, 0) < 0)
|
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, -1) < 0)
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
/* Save the route to delete it when n2n is stopped */
|
/* Save the route to delete it when n2n is stopped */
|
||||||
|
@ -2293,11 +2296,11 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r
|
||||||
custom_route.net_bitlen = 1;
|
custom_route.net_bitlen = 1;
|
||||||
custom_route.gateway = route->gateway;
|
custom_route.gateway = route->gateway;
|
||||||
|
|
||||||
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx, 0) < 0)
|
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0)
|
||||||
return(-1);
|
return(-1);
|
||||||
} else {
|
} else {
|
||||||
/* ip route add net via n2n_gateway */
|
/* ip route add net via n2n_gateway */
|
||||||
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx, 0) < 0)
|
if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, route, eee->device.if_idx) < 0)
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2312,7 +2315,7 @@ static void edge_cleanup_routes(n2n_edge_t *eee) {
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if(eee->sn_route_to_clean) {
|
if(eee->sn_route_to_clean) {
|
||||||
/* ip route del supernode via internet_gateway */
|
/* ip route del supernode via internet_gateway */
|
||||||
routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1, 1 /* can fail as we have dropped capabilities */);
|
routectl(RTM_DELROUTE, 0, eee->sn_route_to_clean, -1);
|
||||||
free(eee->sn_route_to_clean);
|
free(eee->sn_route_to_clean);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user