mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-17 14:25:56 +00:00
Merge branch 'merge-4.10' of /tmp/iproute2
This commit is contained in:
commit
b6d8c4a606
@ -59,6 +59,7 @@ int do_ipnetconf(int argc, char **argv);
|
||||
int do_iptoken(int argc, char **argv);
|
||||
int do_ipvrf(int argc, char **argv);
|
||||
void vrf_reset(void);
|
||||
int netns_identify_pid(const char *pidstr, char *name, int len);
|
||||
|
||||
int iplink_get(unsigned int flags, char *name, __u32 filt_mask);
|
||||
|
||||
|
47
ip/ipnetns.c
47
ip/ipnetns.c
@ -468,28 +468,15 @@ static int netns_pids(int argc, char **argv)
|
||||
|
||||
}
|
||||
|
||||
static int netns_identify(int argc, char **argv)
|
||||
int netns_identify_pid(const char *pidstr, char *name, int len)
|
||||
{
|
||||
const char *pidstr;
|
||||
char net_path[PATH_MAX];
|
||||
int netns;
|
||||
struct stat netst;
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
|
||||
if (argc < 1) {
|
||||
pidstr = "self";
|
||||
} else if (argc > 1) {
|
||||
fprintf(stderr, "extra arguments specified\n");
|
||||
return -1;
|
||||
} else {
|
||||
pidstr = argv[0];
|
||||
if (!is_pid(pidstr)) {
|
||||
fprintf(stderr, "Specified string '%s' is not a pid\n",
|
||||
pidstr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
name[0] = '\0';
|
||||
|
||||
snprintf(net_path, sizeof(net_path), "/proc/%s/ns/net", pidstr);
|
||||
netns = open(net_path, O_RDONLY);
|
||||
@ -531,7 +518,8 @@ static int netns_identify(int argc, char **argv)
|
||||
|
||||
if ((st.st_dev == netst.st_dev) &&
|
||||
(st.st_ino == netst.st_ino)) {
|
||||
printf("%s\n", entry->d_name);
|
||||
strncpy(name, entry->d_name, len - 1);
|
||||
name[len - 1] = '\0';
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
@ -539,6 +527,33 @@ static int netns_identify(int argc, char **argv)
|
||||
|
||||
}
|
||||
|
||||
static int netns_identify(int argc, char **argv)
|
||||
{
|
||||
const char *pidstr;
|
||||
char name[256];
|
||||
int rc;
|
||||
|
||||
if (argc < 1) {
|
||||
pidstr = "self";
|
||||
} else if (argc > 1) {
|
||||
fprintf(stderr, "extra arguments specified\n");
|
||||
return -1;
|
||||
} else {
|
||||
pidstr = argv[0];
|
||||
if (!is_pid(pidstr)) {
|
||||
fprintf(stderr, "Specified string '%s' is not a pid\n",
|
||||
pidstr);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rc = netns_identify_pid(pidstr, name, sizeof(name));
|
||||
if (!rc)
|
||||
printf("%s\n", name);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int on_netns_del(char *nsname, void *arg)
|
||||
{
|
||||
char netns_path[PATH_MAX];
|
||||
|
224
ip/ipvrf.c
224
ip/ipvrf.c
@ -21,6 +21,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
@ -40,6 +41,10 @@ static void usage(void)
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* parse process based cgroup file looking for PATH/vrf/NAME where
|
||||
* NAME is the name of the vrf the process is associated with
|
||||
*/
|
||||
static int vrf_identify(pid_t pid, char *name, size_t len)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
@ -55,9 +60,13 @@ static int vrf_identify(pid_t pid, char *name, size_t len)
|
||||
memset(name, 0, len);
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
vrf = strstr(buf, "::/vrf/");
|
||||
/* want the controller-less cgroup */
|
||||
if (strstr(buf, "::/") == NULL)
|
||||
continue;
|
||||
|
||||
vrf = strstr(buf, "/vrf/");
|
||||
if (vrf) {
|
||||
vrf += 7; /* skip past "::/vrf/" */
|
||||
vrf += 5; /* skip past "/vrf/" */
|
||||
end = strchr(vrf, '\n');
|
||||
if (end)
|
||||
*end = '\0';
|
||||
@ -97,13 +106,105 @@ static int ipvrf_identify(int argc, char **argv)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ipvrf_pids(int argc, char **argv)
|
||||
/* read PATH/vrf/NAME/cgroup.procs file */
|
||||
static void read_cgroup_pids(const char *base_path, char *name)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[4096];
|
||||
char *mnt, *vrf;
|
||||
int fd, rc = -1;
|
||||
ssize_t n;
|
||||
int fd;
|
||||
|
||||
if (snprintf(path, sizeof(path), "%s/vrf/%s%s",
|
||||
base_path, name, CGRP_PROC_FILE) >= sizeof(path))
|
||||
return;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return; /* no cgroup file, nothing to show */
|
||||
|
||||
/* dump contents (pids) of cgroup.procs */
|
||||
while (1) {
|
||||
n = read(fd, buf, sizeof(buf) - 1);
|
||||
if (n <= 0)
|
||||
break;
|
||||
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/* recurse path looking for PATH[/NETNS]/vrf/NAME */
|
||||
static int recurse_dir(char *base_path, char *name, const char *netns)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
struct dirent *de;
|
||||
struct stat fstat;
|
||||
int rc;
|
||||
DIR *d;
|
||||
|
||||
d = opendir(base_path);
|
||||
if (!d)
|
||||
return -1;
|
||||
|
||||
while ((de = readdir(d)) != NULL) {
|
||||
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
|
||||
continue;
|
||||
|
||||
if (!strcmp(de->d_name, "vrf")) {
|
||||
const char *pdir = strrchr(base_path, '/');
|
||||
|
||||
/* found a 'vrf' directory. if it is for the given
|
||||
* namespace then dump the cgroup pids
|
||||
*/
|
||||
if (*netns == '\0' ||
|
||||
(pdir && !strcmp(pdir+1, netns)))
|
||||
read_cgroup_pids(base_path, name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* is this a subdir that needs to be walked */
|
||||
if (snprintf(path, sizeof(path), "%s/%s",
|
||||
base_path, de->d_name) >= sizeof(path))
|
||||
continue;
|
||||
|
||||
if (lstat(path, &fstat) < 0)
|
||||
continue;
|
||||
|
||||
if (S_ISDIR(fstat.st_mode)) {
|
||||
rc = recurse_dir(path, name, netns);
|
||||
if (rc != 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
closedir(d);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ipvrf_get_netns(char *netns, int len)
|
||||
{
|
||||
if (netns_identify_pid("self", netns, len-3)) {
|
||||
fprintf(stderr, "Failed to get name of network namespace: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*netns != '\0')
|
||||
strcat(netns, "-ns");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipvrf_pids(int argc, char **argv)
|
||||
{
|
||||
char *mnt, *vrf;
|
||||
char netns[256];
|
||||
int ret = -1;
|
||||
|
||||
if (argc != 1) {
|
||||
fprintf(stderr, "Invalid arguments\n");
|
||||
@ -111,34 +212,24 @@ static int ipvrf_pids(int argc, char **argv)
|
||||
}
|
||||
|
||||
vrf = argv[0];
|
||||
if (!name_is_vrf(vrf)) {
|
||||
fprintf(stderr, "Invalid VRF name\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mnt = find_cgroup2_mount();
|
||||
if (!mnt)
|
||||
return -1;
|
||||
|
||||
snprintf(path, sizeof(path), "%s/vrf/%s%s", mnt, vrf, CGRP_PROC_FILE);
|
||||
if (ipvrf_get_netns(netns, sizeof(netns)) < 0)
|
||||
goto out;
|
||||
|
||||
ret = recurse_dir(mnt, vrf, netns);
|
||||
|
||||
out:
|
||||
free(mnt);
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return 0; /* no cgroup file, nothing to show */
|
||||
|
||||
while (1) {
|
||||
n = read(fd, buf, sizeof(buf) - 1);
|
||||
if (n < 0) {
|
||||
fprintf(stderr,
|
||||
"Failed to read cgroups file: %s\n",
|
||||
strerror(errno));
|
||||
break;
|
||||
} else if (n == 0) {
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
return rc;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* load BPF program to set sk_bound_dev_if for sockets */
|
||||
@ -203,9 +294,60 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* get base path for controller-less cgroup for a process.
|
||||
* path returned does not include /vrf/NAME if it exists
|
||||
*/
|
||||
static int vrf_path(char *vpath, size_t len)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
char buf[4096];
|
||||
char *vrf;
|
||||
FILE *fp;
|
||||
|
||||
snprintf(path, sizeof(path), "/proc/%d/cgroup", getpid());
|
||||
fp = fopen(path, "r");
|
||||
if (!fp)
|
||||
return -1;
|
||||
|
||||
vpath[0] = '\0';
|
||||
|
||||
while (fgets(buf, sizeof(buf), fp)) {
|
||||
char *start, *nl;
|
||||
|
||||
start = strstr(buf, "::/");
|
||||
if (!start)
|
||||
continue;
|
||||
|
||||
/* advance past '::' */
|
||||
start += 2;
|
||||
|
||||
nl = strchr(start, '\n');
|
||||
if (nl)
|
||||
*nl = '\0';
|
||||
|
||||
vrf = strstr(start, "/vrf");
|
||||
if (vrf)
|
||||
*vrf = '\0';
|
||||
|
||||
strncpy(vpath, start, len - 1);
|
||||
vpath[len - 1] = '\0';
|
||||
|
||||
/* if vrf path is just / then return nothing */
|
||||
if (!strcmp(vpath, "/"))
|
||||
vpath[0] = '\0';
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vrf_switch(const char *name)
|
||||
{
|
||||
char path[PATH_MAX], *mnt, pid[16];
|
||||
char vpath[PATH_MAX], netns[256];
|
||||
int ifindex = 0;
|
||||
int rc = -1, len, fd = -1;
|
||||
|
||||
@ -221,11 +363,37 @@ static int vrf_switch(const char *name)
|
||||
if (!mnt)
|
||||
return -1;
|
||||
|
||||
/* -1 on length to add '/' to the end */
|
||||
if (ipvrf_get_netns(netns, sizeof(netns) - 1) < 0)
|
||||
return -1;
|
||||
|
||||
if (vrf_path(vpath, sizeof(vpath)) < 0) {
|
||||
fprintf(stderr, "Failed to get base cgroup path: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if path already ends in netns then don't add it again */
|
||||
if (*netns != '\0') {
|
||||
char *pdir = strrchr(vpath, '/');
|
||||
|
||||
if (!pdir)
|
||||
pdir = vpath;
|
||||
else
|
||||
pdir++;
|
||||
|
||||
if (strcmp(pdir, netns) == 0)
|
||||
*pdir = '\0';
|
||||
|
||||
strcat(netns, "/");
|
||||
}
|
||||
|
||||
/* path to cgroup; make sure buffer has room to cat "/cgroup.procs"
|
||||
* to the end of the path
|
||||
*/
|
||||
len = snprintf(path, sizeof(path) - sizeof(CGRP_PROC_FILE), "%s/vrf/%s",
|
||||
mnt, ifindex ? name : "");
|
||||
len = snprintf(path, sizeof(path) - sizeof(CGRP_PROC_FILE),
|
||||
"%s%s/%svrf/%s",
|
||||
mnt, vpath, netns, ifindex ? name : "");
|
||||
if (len > sizeof(path) - sizeof(CGRP_PROC_FILE)) {
|
||||
fprintf(stderr, "Invalid path to cgroup2 mount\n");
|
||||
goto out;
|
||||
|
@ -119,7 +119,7 @@ static void rtnl_tab_initialize(const char *file, char **tab, int size)
|
||||
}
|
||||
|
||||
static char *rtnl_rtprot_tab[256] = {
|
||||
[RTPROT_UNSPEC] = "none",
|
||||
[RTPROT_UNSPEC] = "unspec",
|
||||
[RTPROT_REDIRECT] = "redirect",
|
||||
[RTPROT_KERNEL] = "kernel",
|
||||
[RTPROT_BOOT] = "boot",
|
||||
|
@ -130,6 +130,15 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f,
|
||||
sprint_tc_classid(rta_getattr_u32(tb[TCA_MATCHALL_CLASSID]), b1));
|
||||
}
|
||||
|
||||
if (tb[TCA_MATCHALL_FLAGS]) {
|
||||
__u32 flags = rta_getattr_u32(tb[TCA_MATCHALL_FLAGS]);
|
||||
|
||||
if (flags & TCA_CLS_FLAGS_SKIP_HW)
|
||||
fprintf(f, "\n skip_hw");
|
||||
if (flags & TCA_CLS_FLAGS_SKIP_SW)
|
||||
fprintf(f, "\n skip_sw");
|
||||
}
|
||||
|
||||
if (tb[TCA_MATCHALL_ACT])
|
||||
tc_print_action(f, tb[TCA_MATCHALL_ACT]);
|
||||
|
||||
|
@ -17,8 +17,9 @@ ifneq (,$(wildcard /proc/config.gz))
|
||||
KENV := $(shell cat /proc/config.gz | gunzip | grep ^CONFIG)
|
||||
else
|
||||
KVER := $(shell uname -r)
|
||||
KCPATH := /lib/modules/${KVER}/config
|
||||
ifneq (,$(wildcard ${KCPATH}))
|
||||
KCPATHS := /lib/modules/$(KVER)/config /boot/config-$(KVER)
|
||||
KCPATH := $(firstword $(wildcard $(KCPATHS)))
|
||||
ifneq (,$(KCPATH))
|
||||
KENV := $(shell cat ${KCPATH} | grep ^CONFIG)
|
||||
endif
|
||||
endif
|
||||
|
Loading…
Reference in New Issue
Block a user