Merge branch 'iproute2-master' into iproute2-next

Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
David Ahern 2018-03-27 12:33:02 -07:00
commit 54eae5f76d
14 changed files with 186 additions and 105 deletions

17
configure vendored
View File

@ -336,6 +336,20 @@ EOF
rm -f $TMPDIR/strtest.c $TMPDIR/strtest
}
check_cap()
{
if ${PKG_CONFIG} libcap --exists
then
echo "HAVE_CAP:=y" >>$CONFIG
echo "yes"
echo 'CFLAGS += -DHAVE_LIBCAP' `${PKG_CONFIG} libcap --cflags` >>$CONFIG
echo 'LDLIBS +=' `${PKG_CONFIG} libcap --libs` >> $CONFIG
else
echo "no"
fi
}
quiet_config()
{
cat <<EOF
@ -410,6 +424,9 @@ check_berkeley_db
echo -n "need for strlcpy: "
check_strlcpy
echo -n "libcap support: "
check_cap
echo >> $CONFIG
echo "%.o: %.c" >> $CONFIG
echo ' $(QUIET_CC)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<' >> $CONFIG

View File

@ -2602,7 +2602,7 @@ static const char *cmd_name(uint8_t cmd)
case DEVLINK_CMD_DEL: return "del";
case DEVLINK_CMD_PORT_GET: return "get";
case DEVLINK_CMD_PORT_SET: return "set";
case DEVLINK_CMD_PORT_NEW: return "net";
case DEVLINK_CMD_PORT_NEW: return "new";
case DEVLINK_CMD_PORT_DEL: return "del";
default: return "<unknown cmd>";
}

View File

@ -308,4 +308,6 @@ size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);
#endif
void drop_cap(void);
#endif /* __UTILS_H__ */

12
ip/ip.c
View File

@ -174,6 +174,18 @@ int main(int argc, char **argv)
char *batch_file = NULL;
int color = 0;
/* to run vrf exec without root, capabilities might be set, drop them
* if not needed as the first thing.
* execv will drop them for the child command.
* vrf exec requires:
* - cap_dac_override to create the cgroup subdir in /sys
* - cap_sys_admin to load the BPF program
* - cap_net_admin to set the socket into the cgroup
*/
if (argc < 3 || strcmp(argv[1], "vrf") != 0 ||
strcmp(argv[2], "exec") != 0)
drop_cap();
basename = strrchr(argv[0], '/');
if (basename == NULL)
basename = argv[0];

View File

@ -190,42 +190,20 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
return 0;
if ((filter.tos^r->rtm_tos)&filter.tosmask)
return 0;
if (filter.rdst.family) {
if (r->rtm_family != filter.rdst.family ||
filter.rdst.bitlen > r->rtm_dst_len)
return 0;
} else if (filter.rdst.flags & PREFIXLEN_SPECIFIED) {
if (filter.rdst.bitlen > r->rtm_dst_len)
return 0;
}
if (filter.mdst.family) {
if (r->rtm_family != filter.mdst.family ||
(filter.mdst.bitlen >= 0 &&
filter.mdst.bitlen < r->rtm_dst_len))
return 0;
} else if (filter.mdst.flags & PREFIXLEN_SPECIFIED) {
if (filter.mdst.bitlen >= 0 &&
filter.mdst.bitlen < r->rtm_dst_len)
return 0;
}
if (filter.rsrc.family) {
if (r->rtm_family != filter.rsrc.family ||
filter.rsrc.bitlen > r->rtm_src_len)
return 0;
} else if (filter.rsrc.flags & PREFIXLEN_SPECIFIED) {
if (filter.rsrc.bitlen > r->rtm_src_len)
return 0;
}
if (filter.msrc.family) {
if (r->rtm_family != filter.msrc.family ||
(filter.msrc.bitlen >= 0 &&
filter.msrc.bitlen < r->rtm_src_len))
return 0;
} else if (filter.msrc.flags & PREFIXLEN_SPECIFIED) {
if (filter.msrc.bitlen >= 0 &&
filter.msrc.bitlen < r->rtm_src_len)
return 0;
}
if (filter.rdst.family &&
(r->rtm_family != filter.rdst.family || filter.rdst.bitlen > r->rtm_dst_len))
return 0;
if (filter.mdst.family &&
(r->rtm_family != filter.mdst.family ||
(filter.mdst.bitlen >= 0 && filter.mdst.bitlen < r->rtm_dst_len)))
return 0;
if (filter.rsrc.family &&
(r->rtm_family != filter.rsrc.family || filter.rsrc.bitlen > r->rtm_src_len))
return 0;
if (filter.msrc.family &&
(r->rtm_family != filter.msrc.family ||
(filter.msrc.bitlen >= 0 && filter.msrc.bitlen < r->rtm_src_len)))
return 0;
if (filter.rvia.family) {
int family = r->rtm_family;
@ -242,9 +220,7 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
if (tb[RTA_DST])
memcpy(&dst.data, RTA_DATA(tb[RTA_DST]), (r->rtm_dst_len+7)/8);
if (filter.rsrc.family || filter.msrc.family ||
filter.rsrc.flags & PREFIXLEN_SPECIFIED ||
filter.msrc.flags & PREFIXLEN_SPECIFIED) {
if (filter.rsrc.family || filter.msrc.family) {
if (tb[RTA_SRC])
memcpy(&src.data, RTA_DATA(tb[RTA_SRC]), (r->rtm_src_len+7)/8);
}
@ -264,18 +240,15 @@ static int filter_nlmsg(struct nlmsghdr *n, struct rtattr **tb, int host_len)
memcpy(&prefsrc.data, RTA_DATA(tb[RTA_PREFSRC]), host_len/8);
}
if ((filter.rdst.family || filter.rdst.flags & PREFIXLEN_SPECIFIED) &&
inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
if (filter.rdst.family && inet_addr_match(&dst, &filter.rdst, filter.rdst.bitlen))
return 0;
if ((filter.mdst.family || filter.mdst.flags & PREFIXLEN_SPECIFIED) &&
if (filter.mdst.family && filter.mdst.bitlen >= 0 &&
inet_addr_match(&dst, &filter.mdst, r->rtm_dst_len))
return 0;
if ((filter.rsrc.family || filter.rsrc.flags & PREFIXLEN_SPECIFIED) &&
inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
if (filter.rsrc.family && inet_addr_match(&src, &filter.rsrc, filter.rsrc.bitlen))
return 0;
if ((filter.msrc.family || filter.msrc.flags & PREFIXLEN_SPECIFIED) &&
filter.msrc.bitlen >= 0 &&
if (filter.msrc.family && filter.msrc.bitlen >= 0 &&
inet_addr_match(&src, &filter.msrc, r->rtm_src_len))
return 0;

View File

@ -436,6 +436,8 @@ out2:
out:
free(mnt);
drop_cap();
return rc;
}

View File

@ -30,6 +30,9 @@
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#ifdef HAVE_LIBCAP
#include <sys/capability.h>
#endif
#include "rt_names.h"
#include "utils.h"
@ -562,14 +565,23 @@ static int __get_addr_1(inet_prefix *addr, const char *name, int family)
{
memset(addr, 0, sizeof(*addr));
if (strcmp(name, "default") == 0 ||
strcmp(name, "all") == 0 ||
strcmp(name, "any") == 0) {
if (strcmp(name, "default") == 0) {
if ((family == AF_DECnet) || (family == AF_MPLS))
return -1;
addr->family = (family != AF_UNSPEC) ? family : AF_INET;
addr->bytelen = af_byte_len(addr->family);
addr->bitlen = -2;
addr->flags |= PREFIXLEN_SPECIFIED;
return 0;
}
if (strcmp(name, "all") == 0 ||
strcmp(name, "any") == 0) {
if ((family == AF_DECnet) || (family == AF_MPLS))
return -1;
addr->family = AF_UNSPEC;
addr->bytelen = 0;
addr->bitlen = -2;
return 0;
}
@ -683,6 +695,19 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
char *slash;
int err, bitlen, flags;
memset(dst, 0, sizeof(*dst));
if (strcmp(arg, "default") == 0 ||
strcmp(arg, "any") == 0 ||
strcmp(arg, "all") == 0) {
if ((family == AF_DECnet) || (family == AF_MPLS))
return -1;
dst->family = family;
dst->bytelen = 0;
dst->bitlen = 0;
return 0;
}
slash = strchr(arg, '/');
if (slash)
*slash = 0;
@ -697,7 +722,7 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
bitlen = af_bit_len(dst->family);
flags = PREFIXLEN_SPECIFIED;
flags = 0;
if (slash) {
unsigned int plen;
@ -708,12 +733,11 @@ int get_prefix_1(inet_prefix *dst, char *arg, int family)
if (plen > bitlen)
return -1;
flags |= PREFIXLEN_SPECIFIED;
bitlen = plen;
} else {
if (dst->bitlen == -2)
bitlen = 0;
else
flags = 0;
}
dst->flags |= flags;
@ -1594,3 +1618,22 @@ size_t strlcat(char *dst, const char *src, size_t size)
return dlen + strlcpy(dst + dlen, src, size - dlen);
}
#endif
void drop_cap(void)
{
#ifdef HAVE_LIBCAP
/* don't harmstring root/sudo */
if (getuid() != 0 && geteuid() != 0) {
cap_t capabilities;
capabilities = cap_get_proc();
if (!capabilities)
exit(EXIT_FAILURE);
if (cap_clear(capabilities) != 0)
exit(EXIT_FAILURE);
if (cap_set_proc(capabilities) != 0)
exit(EXIT_FAILURE);
cap_free(capabilities);
}
#endif
}

View File

@ -125,7 +125,7 @@ replace " } "
.B cwnd
.IR NUMBER " ] [ "
.B ssthresh
.IR REALM " ] [ "
.IR NUMBER " ] [ "
.B realms
.IR REALM " ] [ "
.B rto_min

View File

@ -63,6 +63,14 @@ a VRF other than the default VRF (main table). A command can be run against
the default VRF by passing the "default" as the VRF name. This is useful if
the current shell is associated with another VRF (e.g, Management VRF).
This command requires the system to be booted with cgroup v2 (e.g. with systemd,
add systemd.unified_cgroup_hierarchy=1 to the kernel command line).
This command also requires to be ran as root or with the CAP_SYS_ADMIN,
CAP_NET_ADMIN and CAP_DAC_OVERRIDE capabilities. If built with libcap and if
capabilities are added to the ip binary program via setcap, the program will
drop them as the first thing when invoked, unless the command is vrf exec.
.TP
.B ip vrf identify [PID] - Report VRF association for process
.sp

View File

@ -103,7 +103,7 @@ into VLAN ID 123:
#tc qdisc add dev eth0 handle ffff: ingress
#tc filter add dev eth0 parent ffff: pref 11 protocol ip \\
u32 match ip protocol 1 0xff flowid 1:1 \\
u32 match ip src 10.0.0.2 flowid 1:1 \\
match ip src 10.0.0.2 flowid 1:1 \\
action vlan push id 123
.EE
.RE

View File

@ -1106,15 +1106,33 @@ static void buf_free_all(void)
buffer.head = NULL;
}
/* Get current screen width, default to 80 columns if TIOCGWINSZ fails */
static int render_screen_width(void)
{
int width = 80;
if (isatty(STDOUT_FILENO)) {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
if (w.ws_col > 0)
width = w.ws_col;
}
}
return width;
}
/* Calculate column width from contents length. If columns don't fit on one
* line, break them into the least possible amount of lines and keep them
* aligned across lines. Available screen space is equally spread between fields
* as additional spacing.
*/
static void render_calc_width(int screen_width)
static void render_calc_width(void)
{
int first, len = 0, linecols = 0;
int screen_width = render_screen_width();
struct column *c, *eol = columns - 1;
int first, len = 0, linecols = 0;
/* First pass: set width for each column to measured content length */
for (first = 1, c = columns; c - columns < COL_MAX; c++) {
@ -1195,7 +1213,7 @@ newline:
}
/* Render buffered output with spacing and delimiters, then free up buffers */
static void render(int screen_width)
static void render(void)
{
struct buf_token *token;
int printed, line_started = 0;
@ -1209,7 +1227,7 @@ static void render(int screen_width)
/* Ensure end alignment of last token, it wasn't necessarily flushed */
buffer.tail->end += buffer.cur->len % 2;
render_calc_width(screen_width);
render_calc_width();
/* Rewind and replay */
buffer.tail = buffer.head;
@ -1245,6 +1263,7 @@ static void render(int screen_width)
}
buf_free_all();
current_field = columns;
}
static void sock_state_print(struct sockstat *s)
@ -4267,23 +4286,33 @@ static int generic_show_sock(const struct sockaddr_nl *addr,
{
struct sock_diag_msg *r = NLMSG_DATA(nlh);
struct inet_diag_arg inet_arg = { .f = arg, .protocol = IPPROTO_MAX };
int ret;
switch (r->sdiag_family) {
case AF_INET:
case AF_INET6:
inet_arg.rth = inet_arg.f->rth_for_killing;
return show_one_inet_sock(addr, nlh, &inet_arg);
ret = show_one_inet_sock(addr, nlh, &inet_arg);
break;
case AF_UNIX:
return unix_show_sock(addr, nlh, arg);
ret = unix_show_sock(addr, nlh, arg);
break;
case AF_PACKET:
return packet_show_sock(addr, nlh, arg);
ret = packet_show_sock(addr, nlh, arg);
break;
case AF_NETLINK:
return netlink_show_sock(addr, nlh, arg);
ret = netlink_show_sock(addr, nlh, arg);
break;
case AF_VSOCK:
return vsock_show_sock(addr, nlh, arg);
ret = vsock_show_sock(addr, nlh, arg);
break;
default:
return -1;
ret = -1;
}
render();
return ret;
}
static int handle_follow_request(struct filter *f)
@ -4650,7 +4679,6 @@ int main(int argc, char *argv[])
FILE *filter_fp = NULL;
int ch;
int state_filter = 0;
int screen_width = 80;
while ((ch = getopt_long(argc, argv,
"dhaletuwxnro460spbEf:miA:D:F:vVzZN:KHS",
@ -4952,15 +4980,6 @@ int main(int argc, char *argv[])
if (!(current_filter.states & (current_filter.states - 1)))
columns[COL_STATE].disabled = 1;
if (isatty(STDOUT_FILENO)) {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1) {
if (w.ws_col > 0)
screen_width = w.ws_col;
}
}
if (show_header)
print_header();
@ -4991,7 +5010,7 @@ int main(int argc, char *argv[])
if (show_users || show_proc_ctx || show_sock_ctx)
user_ent_destroy();
render(screen_width);
render();
return 0;
}

View File

@ -42,7 +42,7 @@ static void yyerror(char *s)
%nonassoc '!'
%%
applet: null expr
applet: null exprlist
{
*yy_ret = $2;
$$ = $2;
@ -51,6 +51,32 @@ applet: null expr
;
null: /* NOTHING */ { $$ = NULL; }
;
exprlist: expr
| '!' expr
{
$$ = alloc_node(SSF_NOT, $2);
}
| '(' exprlist ')'
{
$$ = $2;
}
| exprlist '|' expr
{
$$ = alloc_node(SSF_OR, $1);
$$->post = $3;
}
| exprlist '&' expr
{
$$ = alloc_node(SSF_AND, $1);
$$->post = $3;
}
| exprlist expr
{
$$ = alloc_node(SSF_AND, $1);
$$->post = $2;
}
;
expr: DCOND HOSTCOND
{
$$ = alloc_node(SSF_DCOND, $2);
@ -128,30 +154,6 @@ expr: DCOND HOSTCOND
{
$$ = alloc_node(SSF_S_AUTO, NULL);
}
| expr '|' expr
{
$$ = alloc_node(SSF_OR, $1);
$$->post = $3;
}
| expr expr
{
$$ = alloc_node(SSF_AND, $1);
$$->post = $2;
}
| expr '&' expr
{
$$ = alloc_node(SSF_AND, $1);
$$->post = $3;
}
| '!' expr
{
$$ = alloc_node(SSF_NOT, $2);
}
| '(' expr ')'
{
$$ = $2;
}
;
%%

View File

@ -120,7 +120,8 @@ static int print_connmark(struct action_util *au, FILE *f, struct rtattr *arg)
ci = RTA_DATA(tb[TCA_CONNMARK_PARMS]);
fprintf(f, " connmark zone %d\n", ci->zone);
fprintf(f, " connmark zone %d", ci->zone);
print_action_control(f, " ", ci->action, "\n");
fprintf(f, "\t index %u ref %d bind %d", ci->index,
ci->refcnt, ci->bindcnt);

View File

@ -65,7 +65,7 @@ static int parse_sample(struct action_util *a, int *argc_p, char ***argv_p,
while (argc > 0) {
if (matches(*argv, "rate") == 0) {
NEXT_ARG();
if (get_unsigned(&rate, *argv, 10) != 0) {
if (get_u32(&rate, *argv, 10) != 0) {
fprintf(stderr, "Illegal rate %s\n", *argv);
usage();
return -1;
@ -73,7 +73,7 @@ static int parse_sample(struct action_util *a, int *argc_p, char ***argv_p,
rate_set = true;
} else if (matches(*argv, "group") == 0) {
NEXT_ARG();
if (get_unsigned(&group, *argv, 10) != 0) {
if (get_u32(&group, *argv, 10) != 0) {
fprintf(stderr, "Illegal group num %s\n",
*argv);
usage();
@ -82,7 +82,7 @@ static int parse_sample(struct action_util *a, int *argc_p, char ***argv_p,
group_set = true;
} else if (matches(*argv, "trunc") == 0) {
NEXT_ARG();
if (get_unsigned(&trunc, *argv, 10) != 0) {
if (get_u32(&trunc, *argv, 10) != 0) {
fprintf(stderr, "Illegal truncation size %s\n",
*argv);
usage();
@ -162,6 +162,8 @@ static int print_sample(struct action_util *au, FILE *f, struct rtattr *arg)
fprintf(f, " trunc_size %d",
rta_getattr_u32(tb[TCA_SAMPLE_TRUNC_SIZE]));
print_action_control(f, " ", p->action, "");
fprintf(f, "\n\tindex %d ref %d bind %d", p->index, p->refcnt,
p->bindcnt);