Merge branch 'master' into net-next
This commit is contained in:
commit
c5ecc59f10
|
|
@ -44,5 +44,11 @@ static inline int setns(int fd, int nstype)
|
||||||
|
|
||||||
extern int netns_switch(char *netns);
|
extern int netns_switch(char *netns);
|
||||||
extern int netns_get_fd(const char *netns);
|
extern int netns_get_fd(const char *netns);
|
||||||
|
extern int netns_foreach(int (*func)(char *nsname, void *arg), void *arg);
|
||||||
|
|
||||||
|
struct netns_func {
|
||||||
|
int (*func)(char *nsname, void *arg);
|
||||||
|
void *arg;
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* __NAMESPACE_H__ */
|
#endif /* __NAMESPACE_H__ */
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
#include <resolv.h>
|
#include <resolv.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "libnetlink.h"
|
#include "libnetlink.h"
|
||||||
#include "ll_map.h"
|
#include "ll_map.h"
|
||||||
|
|
@ -23,6 +24,7 @@ extern int timestamp_short;
|
||||||
extern char * _SL_;
|
extern char * _SL_;
|
||||||
extern int max_flush_loops;
|
extern int max_flush_loops;
|
||||||
extern int batch_mode;
|
extern int batch_mode;
|
||||||
|
extern bool do_all;
|
||||||
|
|
||||||
#ifndef IPPROTO_ESP
|
#ifndef IPPROTO_ESP
|
||||||
#define IPPROTO_ESP 50
|
#define IPPROTO_ESP 50
|
||||||
|
|
@ -162,4 +164,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
|
||||||
char **name, char **type, char **link, char **dev,
|
char **name, char **type, char **link, char **dev,
|
||||||
int *group, int *index);
|
int *group, int *index);
|
||||||
|
|
||||||
|
extern int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
|
||||||
|
bool show_label);
|
||||||
|
|
||||||
#endif /* __UTILS_H__ */
|
#endif /* __UTILS_H__ */
|
||||||
|
|
|
||||||
5
ip/ip.c
5
ip/ip.c
|
|
@ -36,6 +36,7 @@ char * _SL_ = NULL;
|
||||||
int force = 0;
|
int force = 0;
|
||||||
int max_flush_loops = 10;
|
int max_flush_loops = 10;
|
||||||
int batch_mode = 0;
|
int batch_mode = 0;
|
||||||
|
bool do_all = false;
|
||||||
|
|
||||||
struct rtnl_handle rth = { .fd = -1 };
|
struct rtnl_handle rth = { .fd = -1 };
|
||||||
|
|
||||||
|
|
@ -55,7 +56,7 @@ static void usage(void)
|
||||||
" -4 | -6 | -I | -D | -B | -0 |\n"
|
" -4 | -6 | -I | -D | -B | -0 |\n"
|
||||||
" -l[oops] { maximum-addr-flush-attempts } |\n"
|
" -l[oops] { maximum-addr-flush-attempts } |\n"
|
||||||
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
|
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
|
||||||
" -rc[vbuf] [size] | -n[etns] name }\n");
|
" -rc[vbuf] [size] | -n[etns] name | -a[ll] }\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,6 +271,8 @@ int main(int argc, char **argv)
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
if (netns_switch(argv[1]))
|
if (netns_switch(argv[1]))
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
} else if (matches(opt, "-all") == 0) {
|
||||||
|
do_all = true;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
|
fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n", opt);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|
|
||||||
|
|
@ -970,7 +970,8 @@ struct nlmsg_chain
|
||||||
struct nlmsg_list *tail;
|
struct nlmsg_list *tail;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
|
static int print_selected_addrinfo(struct ifinfomsg *ifi,
|
||||||
|
struct nlmsg_list *ainfo, FILE *fp)
|
||||||
{
|
{
|
||||||
for ( ;ainfo ; ainfo = ainfo->next) {
|
for ( ;ainfo ; ainfo = ainfo->next) {
|
||||||
struct nlmsghdr *n = &ainfo->h;
|
struct nlmsghdr *n = &ainfo->h;
|
||||||
|
|
@ -982,10 +983,13 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *
|
||||||
if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
|
if (n->nlmsg_len < NLMSG_LENGTH(sizeof(ifa)))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (ifa->ifa_index != ifindex ||
|
if (ifa->ifa_index != ifi->ifi_index ||
|
||||||
(filter.family && filter.family != ifa->ifa_family))
|
(filter.family && filter.family != ifa->ifa_family))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (filter.up && !(ifi->ifi_flags&IFF_UP))
|
||||||
|
continue;
|
||||||
|
|
||||||
print_addrinfo(NULL, n, fp);
|
print_addrinfo(NULL, n, fp);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1446,7 +1450,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
|
||||||
if (no_link || (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) {
|
if (no_link || (res = print_linkinfo(NULL, &l->h, stdout)) >= 0) {
|
||||||
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
|
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
|
||||||
if (filter.family != AF_PACKET)
|
if (filter.family != AF_PACKET)
|
||||||
print_selected_addrinfo(ifi->ifi_index,
|
print_selected_addrinfo(ifi,
|
||||||
ainfo.head, stdout);
|
ainfo.head, stdout);
|
||||||
if (res > 0 && !do_link && show_stats)
|
if (res > 0 && !do_link && show_stats)
|
||||||
print_link_stats(stdout, &l->h);
|
print_link_stats(stdout, &l->h);
|
||||||
|
|
|
||||||
98
ip/ipnetns.c
98
ip/ipnetns.c
|
|
@ -23,10 +23,10 @@ static int usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: ip netns list\n");
|
fprintf(stderr, "Usage: ip netns list\n");
|
||||||
fprintf(stderr, " ip netns add NAME\n");
|
fprintf(stderr, " ip netns add NAME\n");
|
||||||
fprintf(stderr, " ip netns delete NAME\n");
|
fprintf(stderr, " ip [-all] netns delete [NAME]\n");
|
||||||
fprintf(stderr, " ip netns identify [PID]\n");
|
fprintf(stderr, " ip netns identify [PID]\n");
|
||||||
fprintf(stderr, " ip netns pids NAME\n");
|
fprintf(stderr, " ip netns pids NAME\n");
|
||||||
fprintf(stderr, " ip netns exec NAME cmd ...\n");
|
fprintf(stderr, " ip [-all] netns exec [NAME] cmd ...\n");
|
||||||
fprintf(stderr, " ip netns monitor\n");
|
fprintf(stderr, " ip netns monitor\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
@ -51,29 +51,10 @@ static int netns_list(int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netns_exec(int argc, char **argv)
|
static int cmd_exec(const char *cmd, char **argv, bool do_fork)
|
||||||
{
|
{
|
||||||
/* Setup the proper environment for apps that are not netns
|
|
||||||
* aware, and execute a program in that environment.
|
|
||||||
*/
|
|
||||||
const char *cmd;
|
|
||||||
|
|
||||||
if (argc < 1) {
|
|
||||||
fprintf(stderr, "No netns name specified\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (argc < 2) {
|
|
||||||
fprintf(stderr, "No command specified\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
cmd = argv[1];
|
|
||||||
|
|
||||||
if (netns_switch(argv[0]))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
if (do_fork) {
|
||||||
if (batch_mode) {
|
|
||||||
int status;
|
int status;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
|
||||||
|
|
@ -91,23 +72,56 @@ static int netns_exec(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
/* ip must return the status of the child,
|
return WEXITSTATUS(status);
|
||||||
* but do_cmd() will add a minus to this,
|
|
||||||
* so let's add another one here to cancel it.
|
|
||||||
*/
|
|
||||||
return -WEXITSTATUS(status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (execvp(cmd, argv + 1) < 0)
|
if (execvp(cmd, argv) < 0)
|
||||||
fprintf(stderr, "exec of \"%s\" failed: %s\n",
|
fprintf(stderr, "exec of \"%s\" failed: %s\n",
|
||||||
cmd, strerror(errno));
|
cmd, strerror(errno));
|
||||||
_exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int on_netns_exec(char *nsname, void *arg)
|
||||||
|
{
|
||||||
|
char **argv = arg;
|
||||||
|
cmd_exec(argv[1], argv + 1, true);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int netns_exec(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Setup the proper environment for apps that are not netns
|
||||||
|
* aware, and execute a program in that environment.
|
||||||
|
*/
|
||||||
|
const char *cmd;
|
||||||
|
|
||||||
|
if (argc < 1 && !do_all) {
|
||||||
|
fprintf(stderr, "No netns name specified\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((argc < 2 && !do_all) || (argc < 1 && do_all)) {
|
||||||
|
fprintf(stderr, "No command specified\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_all)
|
||||||
|
return do_each_netns(on_netns_exec, --argv, 1);
|
||||||
|
|
||||||
|
if (netns_switch(argv[0]))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* ip must return the status of the child,
|
||||||
|
* but do_cmd() will add a minus to this,
|
||||||
|
* so let's add another one here to cancel it.
|
||||||
|
*/
|
||||||
|
cmd = argv[1];
|
||||||
|
return -cmd_exec(cmd, argv + 1, !!batch_mode);
|
||||||
|
}
|
||||||
|
|
||||||
static int is_pid(const char *str)
|
static int is_pid(const char *str)
|
||||||
{
|
{
|
||||||
int ch;
|
int ch;
|
||||||
|
|
@ -245,18 +259,11 @@ static int netns_identify(int argc, char **argv)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int netns_delete(int argc, char **argv)
|
static int on_netns_del(char *nsname, void *arg)
|
||||||
{
|
{
|
||||||
const char *name;
|
|
||||||
char netns_path[MAXPATHLEN];
|
char netns_path[MAXPATHLEN];
|
||||||
|
|
||||||
if (argc < 1) {
|
snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, nsname);
|
||||||
fprintf(stderr, "No netns name specified\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
name = argv[0];
|
|
||||||
snprintf(netns_path, sizeof(netns_path), "%s/%s", NETNS_RUN_DIR, name);
|
|
||||||
umount2(netns_path, MNT_DETACH);
|
umount2(netns_path, MNT_DETACH);
|
||||||
if (unlink(netns_path) < 0) {
|
if (unlink(netns_path) < 0) {
|
||||||
fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
|
fprintf(stderr, "Cannot remove namespace file \"%s\": %s\n",
|
||||||
|
|
@ -266,6 +273,19 @@ static int netns_delete(int argc, char **argv)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int netns_delete(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 1 && !do_all) {
|
||||||
|
fprintf(stderr, "No netns name specified\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_all)
|
||||||
|
return netns_foreach(on_netns_del, NULL);
|
||||||
|
|
||||||
|
return on_netns_del(argv[0], NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int create_netns_dir(void)
|
static int create_netns_dir(void)
|
||||||
{
|
{
|
||||||
/* Create the base netns directory if it doesn't exist */
|
/* Create the base netns directory if it doesn't exist */
|
||||||
|
|
|
||||||
|
|
@ -99,3 +99,25 @@ int netns_get_fd(const char *name)
|
||||||
}
|
}
|
||||||
return open(path, O_RDONLY);
|
return open(path, O_RDONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int netns_foreach(int (*func)(char *nsname, void *arg), void *arg)
|
||||||
|
{
|
||||||
|
DIR *dir;
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
|
dir = opendir(NETNS_RUN_DIR);
|
||||||
|
if (!dir)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
if (strcmp(entry->d_name, ".") == 0)
|
||||||
|
continue;
|
||||||
|
if (strcmp(entry->d_name, "..") == 0)
|
||||||
|
continue;
|
||||||
|
if (func(entry->d_name, arg))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dir);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
28
lib/utils.c
28
lib/utils.c
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "namespace.h"
|
||||||
|
|
||||||
int timestamp_short = 0;
|
int timestamp_short = 0;
|
||||||
|
|
||||||
|
|
@ -878,3 +879,30 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n)
|
||||||
tstr[strlen(tstr)-1] = 0;
|
tstr[strlen(tstr)-1] = 0;
|
||||||
fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs);
|
fprintf(fp, "Timestamp: %s %lu us\n", tstr, usecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int on_netns(char *nsname, void *arg)
|
||||||
|
{
|
||||||
|
struct netns_func *f = arg;
|
||||||
|
|
||||||
|
if (netns_switch(nsname))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return f->func(nsname, f->arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int on_netns_label(char *nsname, void *arg)
|
||||||
|
{
|
||||||
|
printf("\nnetns: %s\n", nsname);
|
||||||
|
return on_netns(nsname, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_each_netns(int (*func)(char *nsname, void *arg), void *arg,
|
||||||
|
bool show_label)
|
||||||
|
{
|
||||||
|
struct netns_func nsf = { .func = func, .arg = arg };
|
||||||
|
|
||||||
|
if (show_label)
|
||||||
|
return netns_foreach(on_netns_label, &nsf);
|
||||||
|
|
||||||
|
return netns_foreach(on_netns, &nsf);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,13 @@ ip-netns \- process network namespace management
|
||||||
.BR "ip netns" " { " list " } "
|
.BR "ip netns" " { " list " } "
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns" " { " add " | " delete " } "
|
.B ip netns add
|
||||||
.I NETNSNAME
|
.I NETNSNAME
|
||||||
|
|
||||||
|
.ti -8
|
||||||
|
.B ip [-all] netns del
|
||||||
|
.RI "[ " NETNSNAME " ]"
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns identify"
|
.BR "ip netns identify"
|
||||||
.RI "[ " PID " ]"
|
.RI "[ " PID " ]"
|
||||||
|
|
@ -28,8 +32,8 @@ ip-netns \- process network namespace management
|
||||||
.I NETNSNAME
|
.I NETNSNAME
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns exec "
|
.BR "ip [-all] netns exec "
|
||||||
.I NETNSNAME command ...
|
.RI "[ " NETNSNAME " ] " command ...
|
||||||
|
|
||||||
.ti -8
|
.ti -8
|
||||||
.BR "ip netns monitor"
|
.BR "ip netns monitor"
|
||||||
|
|
@ -76,7 +80,7 @@ If NAME is available in /var/run/netns/ this command creates a new
|
||||||
network namespace and assigns NAME.
|
network namespace and assigns NAME.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B ip netns delete NAME - delete the name of a network namespace
|
.B ip [-all] netns delete [ NAME ] - delete the name of a network namespace(s)
|
||||||
.sp
|
.sp
|
||||||
If NAME is present in /var/run/netns it is umounted and the mount
|
If NAME is present in /var/run/netns it is umounted and the mount
|
||||||
point is removed. If this is the last user of the network namespace the
|
point is removed. If this is the last user of the network namespace the
|
||||||
|
|
@ -84,6 +88,10 @@ network namespace will be freed, otherwise the network namespace
|
||||||
persists until it has no more users. ip netns delete may fail if
|
persists until it has no more users. ip netns delete may fail if
|
||||||
the mount point is in use in another mount namespace.
|
the mount point is in use in another mount namespace.
|
||||||
|
|
||||||
|
If
|
||||||
|
.B -all
|
||||||
|
option was specified then all the network namespace names will be removed.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B ip netns identify [PID] - Report network namespaces names for process
|
.B ip netns identify [PID] - Report network namespaces names for process
|
||||||
.sp
|
.sp
|
||||||
|
|
@ -98,7 +106,7 @@ This command walks through proc and finds all of the process who have
|
||||||
the named network namespace as their primary network namespace.
|
the named network namespace as their primary network namespace.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B ip netns exec NAME cmd ... - Run cmd in the named network namespace
|
.B ip [-all] netns exec [ NAME ] cmd ... - Run cmd in the named network namespace
|
||||||
.sp
|
.sp
|
||||||
This command allows applications that are network namespace unaware
|
This command allows applications that are network namespace unaware
|
||||||
to be run in something other than the default network namespace with
|
to be run in something other than the default network namespace with
|
||||||
|
|
@ -107,6 +115,16 @@ in the customary global locations. A network namespace and bind mounts
|
||||||
are used to move files from their network namespace specific location
|
are used to move files from their network namespace specific location
|
||||||
to their default locations without affecting other processes.
|
to their default locations without affecting other processes.
|
||||||
|
|
||||||
|
If
|
||||||
|
.B -all
|
||||||
|
option was specified then
|
||||||
|
.B cmd
|
||||||
|
will be executed synchronously on the each named network namespace even if
|
||||||
|
.B cmd
|
||||||
|
fails on some of them. Network namespace name is printed on each
|
||||||
|
.B cmd
|
||||||
|
executing.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B ip netns monitor - Report as network namespace names are added and deleted
|
.B ip netns monitor - Report as network namespace names are added and deleted
|
||||||
.sp
|
.sp
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ ip \- show / manipulate routing, devices, policy routing and tunnels
|
||||||
\fB\-f\fR[\fIamily\fR] {
|
\fB\-f\fR[\fIamily\fR] {
|
||||||
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
|
.BR inet " | " inet6 " | " ipx " | " dnet " | " link " } | "
|
||||||
\fB\-o\fR[\fIneline\fR] |
|
\fB\-o\fR[\fIneline\fR] |
|
||||||
\fB\-n\fR[\fIetns\fR] name }
|
\fB\-n\fR[\fIetns\fR] name |
|
||||||
|
\fB\-a\fR[\fIll\fR] }
|
||||||
|
|
||||||
|
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
|
|
@ -155,6 +156,10 @@ to
|
||||||
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
.RI "-n[etns] " NETNS " [ " OPTIONS " ] " OBJECT " { " COMMAND " | "
|
||||||
.BR help " }"
|
.BR help " }"
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR "\-a" , " \-all"
|
||||||
|
executes specified command over all objects, it depends if command supports this option.
|
||||||
|
|
||||||
.SH IP - COMMAND SYNTAX
|
.SH IP - COMMAND SYNTAX
|
||||||
|
|
||||||
.SS
|
.SS
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue