4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #include <asm/types.h>
26 #include <linux/pkt_sched.h>
27 #include <linux/param.h>
28 #include <linux/if_arp.h>
29 #include <linux/mpls.h>
30 #include <linux/snmp.h>
35 #include <sys/capability.h>
41 #include "namespace.h"
46 const char *_SL_
= "\n";
48 int read_prop(const char *dev
, char *prop
, long *value
)
50 char fname
[128], buf
[80], *endp
, *nl
;
55 ret
= snprintf(fname
, sizeof(fname
), "/sys/class/net/%s/%s",
58 if (ret
<= 0 || ret
>= sizeof(fname
)) {
59 fprintf(stderr
, "could not build pathname for property\n");
63 fp
= fopen(fname
, "r");
65 fprintf(stderr
, "fopen %s: %s\n", fname
, strerror(errno
));
69 if (!fgets(buf
, sizeof(buf
), fp
)) {
70 fprintf(stderr
, "property \"%s\" in file %s is currently unknown\n", prop
, fname
);
75 nl
= strchr(buf
, '\n');
80 result
= strtol(buf
, &endp
, 0);
82 if (*endp
|| buf
== endp
) {
83 fprintf(stderr
, "value \"%s\" in file %s is not a number\n",
88 if ((result
== LONG_MAX
|| result
== LONG_MIN
) && errno
== ERANGE
) {
89 fprintf(stderr
, "strtol %s: %s", fname
, strerror(errno
));
96 fprintf(stderr
, "Failed to parse %s\n", fname
);
100 /* Parse a percent e.g: '30%'
101 * return: 0 = ok, -1 = error, 1 = out of range
103 int parse_percent(double *val
, const char *str
)
107 *val
= strtod(str
, &p
) / 100.;
108 if (*val
== HUGE_VALF
|| *val
== HUGE_VALL
)
110 if (*p
&& strcmp(p
, "%"))
118 if (c
>= 'A' && c
<= 'F')
120 if (c
>= 'a' && c
<= 'f')
122 if (c
>= '0' && c
<= '9')
128 int get_integer(int *val
, const char *arg
, int base
)
136 res
= strtol(arg
, &ptr
, base
);
138 /* If there were no digits at all, strtol() stores
139 * the original value of nptr in *endptr (and returns 0).
140 * In particular, if *nptr is not '\0' but **endptr is '\0' on return,
141 * the entire string is valid.
143 if (!ptr
|| ptr
== arg
|| *ptr
)
146 /* If an underflow occurs, strtol() returns LONG_MIN.
147 * If an overflow occurs, strtol() returns LONG_MAX.
148 * In both cases, errno is set to ERANGE.
150 if ((res
== LONG_MAX
|| res
== LONG_MIN
) && errno
== ERANGE
)
153 /* Outside range of int */
154 if (res
< INT_MIN
|| res
> INT_MAX
)
161 int mask2bits(__u32 netmask
)
163 unsigned int bits
= 0;
164 __u32 mask
= ntohl(netmask
);
167 /* a valid netmask must be 2^n - 1 */
168 if ((host
& (host
+ 1)) != 0)
171 for (; mask
; mask
<<= 1)
176 static int get_netmask(unsigned int *val
, const char *arg
, int base
)
180 if (!get_unsigned(val
, arg
, base
))
183 /* try coverting dotted quad to CIDR */
184 if (!get_addr_1(&addr
, arg
, AF_INET
) && addr
.family
== AF_INET
) {
185 int b
= mask2bits(addr
.data
[0]);
196 int get_unsigned(unsigned int *val
, const char *arg
, int base
)
204 res
= strtoul(arg
, &ptr
, base
);
206 /* empty string or trailing non-digits */
207 if (!ptr
|| ptr
== arg
|| *ptr
)
211 if (res
== ULONG_MAX
&& errno
== ERANGE
)
214 /* out side range of unsigned */
223 * get_time_rtt is "translated" from a similar routine "get_time" in
224 * tc_util.c. We don't use the exact same routine because tc passes
225 * microseconds to the kernel and the callers of get_time_rtt want to
226 * pass milliseconds (standard unit for rtt values since 2.6.27), and
227 * have a different assumption for the units of a "raw" number.
229 int get_time_rtt(unsigned int *val
, const char *arg
, int *raw
)
235 if (strchr(arg
, '.') != NULL
) {
245 if ((t
== HUGE_VALF
|| t
== HUGE_VALL
) && errno
== ERANGE
)
248 res
= strtoul(arg
, &p
, 0);
255 if (res
== ULONG_MAX
&& errno
== ERANGE
)
267 if (strcasecmp(p
, "s") == 0 ||
268 strcasecmp(p
, "sec") == 0 ||
269 strcasecmp(p
, "secs") == 0)
271 else if (strcasecmp(p
, "ms") == 0 ||
272 strcasecmp(p
, "msec") == 0 ||
273 strcasecmp(p
, "msecs") == 0)
274 t
*= 1.0; /* allow suffix, do nothing */
279 /* emulate ceil() without having to bring-in -lm and always be >= 1 */
288 int get_u64(__u64
*val
, const char *arg
, int base
)
290 unsigned long long res
;
296 res
= strtoull(arg
, &ptr
, base
);
298 /* empty string or trailing non-digits */
299 if (!ptr
|| ptr
== arg
|| *ptr
)
303 if (res
== ULLONG_MAX
&& errno
== ERANGE
)
306 /* in case ULL is 128 bits */
307 if (res
> 0xFFFFFFFFFFFFFFFFULL
)
314 int get_u32(__u32
*val
, const char *arg
, int base
)
321 res
= strtoul(arg
, &ptr
, base
);
323 /* empty string or trailing non-digits */
324 if (!ptr
|| ptr
== arg
|| *ptr
)
328 if (res
== ULONG_MAX
&& errno
== ERANGE
)
331 /* in case UL > 32 bits */
332 if (res
> 0xFFFFFFFFUL
)
339 int get_u16(__u16
*val
, const char *arg
, int base
)
346 res
= strtoul(arg
, &ptr
, base
);
348 /* empty string or trailing non-digits */
349 if (!ptr
|| ptr
== arg
|| *ptr
)
353 if (res
== ULONG_MAX
&& errno
== ERANGE
)
363 int get_u8(__u8
*val
, const char *arg
, int base
)
371 res
= strtoul(arg
, &ptr
, base
);
372 /* empty string or trailing non-digits */
373 if (!ptr
|| ptr
== arg
|| *ptr
)
377 if (res
== ULONG_MAX
&& errno
== ERANGE
)
387 int get_s32(__s32
*val
, const char *arg
, int base
)
396 res
= strtol(arg
, &ptr
, base
);
397 if (!ptr
|| ptr
== arg
|| *ptr
)
399 if ((res
== LONG_MIN
|| res
== LONG_MAX
) && errno
== ERANGE
)
401 if (res
> INT32_MAX
|| res
< INT32_MIN
)
408 int get_s16(__s16
*val
, const char *arg
, int base
)
415 res
= strtol(arg
, &ptr
, base
);
416 if (!ptr
|| ptr
== arg
|| *ptr
)
418 if ((res
== LONG_MIN
|| res
== LONG_MAX
) && errno
== ERANGE
)
420 if (res
> 0x7FFF || res
< -0x8000)
427 int get_s8(__s8
*val
, const char *arg
, int base
)
434 res
= strtol(arg
, &ptr
, base
);
435 if (!ptr
|| ptr
== arg
|| *ptr
)
437 if ((res
== LONG_MIN
|| res
== LONG_MAX
) && errno
== ERANGE
)
439 if (res
> 0x7F || res
< -0x80)
445 int get_be64(__be64
*val
, const char *arg
, int base
)
448 int ret
= get_u64(&v
, arg
, base
);
456 int get_be32(__be32
*val
, const char *arg
, int base
)
459 int ret
= get_u32(&v
, arg
, base
);
467 int get_be16(__be16
*val
, const char *arg
, int base
)
470 int ret
= get_u16(&v
, arg
, base
);
478 /* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
479 * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
481 static int get_addr_ipv4(__u8
*ap
, const char *cp
)
485 for (i
= 0; i
< 4; i
++) {
489 n
= strtoul(cp
, &endp
, 0);
491 return -1; /* bogus network value */
493 if (endp
== cp
) /* no digits */
501 if (i
== 3 || *endp
!= '.')
502 return -1; /* extra characters */
509 int get_addr64(__u64
*ap
, const char *cp
)
518 for (i
= 0; i
< 4; i
++) {
522 n
= strtoul(cp
, &endp
, 16);
524 return -1; /* bogus network value */
526 if (endp
== cp
) /* no digits */
529 val
.v16
[i
] = htons(n
);
534 if (i
== 3 || *endp
!= ':')
535 return -1; /* extra characters */
544 static void set_address_type(inet_prefix
*addr
)
546 switch (addr
->family
) {
549 addr
->flags
|= ADDRTYPE_INET_UNSPEC
;
550 else if (IN_MULTICAST(ntohl(addr
->data
[0])))
551 addr
->flags
|= ADDRTYPE_INET_MULTI
;
553 addr
->flags
|= ADDRTYPE_INET
;
556 if (IN6_IS_ADDR_UNSPECIFIED(addr
->data
))
557 addr
->flags
|= ADDRTYPE_INET_UNSPEC
;
558 else if (IN6_IS_ADDR_MULTICAST(addr
->data
))
559 addr
->flags
|= ADDRTYPE_INET_MULTI
;
561 addr
->flags
|= ADDRTYPE_INET
;
566 static int __get_addr_1(inet_prefix
*addr
, const char *name
, int family
)
568 memset(addr
, 0, sizeof(*addr
));
570 if (strcmp(name
, "default") == 0) {
571 if ((family
== AF_DECnet
) || (family
== AF_MPLS
))
573 addr
->family
= family
;
574 addr
->bytelen
= af_byte_len(addr
->family
);
576 addr
->flags
|= PREFIXLEN_SPECIFIED
;
580 if (strcmp(name
, "all") == 0 ||
581 strcmp(name
, "any") == 0) {
582 if ((family
== AF_DECnet
) || (family
== AF_MPLS
))
584 addr
->family
= family
;
590 if (family
== AF_PACKET
) {
593 len
= ll_addr_a2n((char *) &addr
->data
, sizeof(addr
->data
),
598 addr
->family
= AF_PACKET
;
600 addr
->bitlen
= len
* 8;
604 if (strchr(name
, ':')) {
605 addr
->family
= AF_INET6
;
606 if (family
!= AF_UNSPEC
&& family
!= AF_INET6
)
608 if (inet_pton(AF_INET6
, name
, addr
->data
) <= 0)
615 if (family
== AF_DECnet
) {
618 addr
->family
= AF_DECnet
;
619 if (dnet_pton(AF_DECnet
, name
, &dna
) <= 0)
621 memcpy(addr
->data
, dna
.a_addr
, 2);
627 if (family
== AF_MPLS
) {
628 unsigned int maxlabels
;
631 addr
->family
= AF_MPLS
;
632 if (mpls_pton(AF_MPLS
, name
, addr
->data
,
633 sizeof(addr
->data
)) <= 0)
637 /* How many bytes do I need? */
638 maxlabels
= sizeof(addr
->data
) / sizeof(struct mpls_label
);
639 for (i
= 0; i
< maxlabels
; i
++) {
640 if (ntohl(addr
->data
[i
]) & MPLS_LS_S_MASK
) {
641 addr
->bytelen
= (i
+ 1)*4;
648 addr
->family
= AF_INET
;
649 if (family
!= AF_UNSPEC
&& family
!= AF_INET
)
652 if (get_addr_ipv4((__u8
*)addr
->data
, name
) <= 0)
660 int get_addr_1(inet_prefix
*addr
, const char *name
, int family
)
664 ret
= __get_addr_1(addr
, name
, family
);
668 set_address_type(addr
);
672 int af_bit_len(int af
)
690 int af_byte_len(int af
)
692 return af_bit_len(af
) / 8;
695 int get_prefix_1(inet_prefix
*dst
, char *arg
, int family
)
698 int err
, bitlen
, flags
;
700 slash
= strchr(arg
, '/');
704 err
= get_addr_1(dst
, arg
, family
);
712 bitlen
= af_bit_len(dst
->family
);
718 if (dst
->bitlen
== -2)
720 if (get_netmask(&plen
, slash
+ 1, 0))
725 flags
|= PREFIXLEN_SPECIFIED
;
728 if (dst
->bitlen
== -2)
733 dst
->bitlen
= bitlen
;
738 static const char *family_name_verbose(int family
)
740 if (family
== AF_UNSPEC
)
742 return family_name(family
);
745 int get_addr(inet_prefix
*dst
, const char *arg
, int family
)
747 if (get_addr_1(dst
, arg
, family
)) {
749 "Error: %s address is expected rather than \"%s\".\n",
750 family_name_verbose(family
), arg
);
756 int get_addr_rta(inet_prefix
*dst
, const struct rtattr
*rta
, int family
)
758 const int len
= RTA_PAYLOAD(rta
);
759 const void *data
= RTA_DATA(rta
);
763 dst
->family
= AF_INET
;
765 memcpy(dst
->data
, data
, 4);
768 dst
->family
= AF_INET6
;
770 memcpy(dst
->data
, data
, 16);
773 dst
->family
= AF_DECnet
;
775 memcpy(dst
->data
, data
, 2);
778 dst
->family
= AF_IPX
;
780 memcpy(dst
->data
, data
, 10);
786 if (family
!= AF_UNSPEC
&& family
!= dst
->family
)
792 set_address_type(dst
);
796 int get_prefix(inet_prefix
*dst
, char *arg
, int family
)
798 if (family
== AF_PACKET
) {
800 "Error: \"%s\" may be inet prefix, but it is not allowed in this context.\n",
805 if (get_prefix_1(dst
, arg
, family
)) {
807 "Error: %s prefix is expected rather than \"%s\".\n",
808 family_name_verbose(family
), arg
);
814 __u32
get_addr32(const char *name
)
818 if (get_addr_1(&addr
, name
, AF_INET
)) {
820 "Error: an IP address is expected rather than \"%s\"\n",
827 void incomplete_command(void)
829 fprintf(stderr
, "Command line is not complete. Try option \"help\"\n");
833 void missarg(const char *key
)
835 fprintf(stderr
, "Error: argument \"%s\" is required\n", key
);
839 void invarg(const char *msg
, const char *arg
)
841 fprintf(stderr
, "Error: argument \"%s\" is wrong: %s\n", arg
, msg
);
845 void duparg(const char *key
, const char *arg
)
848 "Error: duplicate \"%s\": \"%s\" is the second value.\n",
853 void duparg2(const char *key
, const char *arg
)
856 "Error: either \"%s\" is duplicate, or \"%s\" is a garbage.\n",
861 int nodev(const char *dev
)
863 fprintf(stderr
, "Cannot find device \"%s\"\n", dev
);
867 int check_ifname(const char *name
)
869 /* These checks mimic kernel checks in dev_valid_name */
872 if (strlen(name
) >= IFNAMSIZ
)
876 if (*name
== '/' || isspace(*name
))
883 /* buf is assumed to be IFNAMSIZ */
884 int get_ifname(char *buf
, const char *name
)
888 ret
= check_ifname(name
);
890 strncpy(buf
, name
, IFNAMSIZ
);
895 const char *get_ifname_rta(int ifindex
, const struct rtattr
*rta
)
900 name
= rta_getattr_str(rta
);
903 "BUG: device with ifindex %d has nil ifname\n",
905 name
= ll_idx_n2a(ifindex
);
908 if (check_ifname(name
))
914 int matches(const char *cmd
, const char *pattern
)
916 int len
= strlen(cmd
);
918 if (len
> strlen(pattern
))
920 return memcmp(pattern
, cmd
, len
);
923 int inet_addr_match(const inet_prefix
*a
, const inet_prefix
*b
, int bits
)
925 const __u32
*a1
= a
->data
;
926 const __u32
*a2
= b
->data
;
927 int words
= bits
>> 0x05;
932 if (memcmp(a1
, a2
, words
<< 2))
942 mask
= htonl((0xffffffff) << (0x20 - bits
));
944 if ((w1
^ w2
) & mask
)
951 int inet_addr_match_rta(const inet_prefix
*m
, const struct rtattr
*rta
)
955 if (!rta
|| m
->family
== AF_UNSPEC
|| m
->bitlen
<= 0)
958 if (get_addr_rta(&dst
, rta
, m
->family
))
961 return inet_addr_match(&dst
, m
, m
->bitlen
);
964 int __iproute2_hz_internal
;
973 return atoi(getenv("HZ")) ? : HZ
;
975 if (getenv("PROC_NET_PSCHED"))
976 snprintf(name
, sizeof(name
)-1,
977 "%s", getenv("PROC_NET_PSCHED"));
978 else if (getenv("PROC_ROOT"))
979 snprintf(name
, sizeof(name
)-1,
980 "%s/net/psched", getenv("PROC_ROOT"));
982 strcpy(name
, "/proc/net/psched");
984 fp
= fopen(name
, "r");
987 unsigned int nom
, denom
;
989 if (fscanf(fp
, "%*08x%*08x%08x%08x", &nom
, &denom
) == 2)
999 int __iproute2_user_hz_internal
;
1001 int __get_user_hz(void)
1003 return sysconf(_SC_CLK_TCK
);
1006 const char *rt_addr_n2a_r(int af
, int len
,
1007 const void *addr
, char *buf
, int buflen
)
1012 return inet_ntop(af
, addr
, buf
, buflen
);
1014 return mpls_ntop(af
, addr
, buf
, buflen
);
1016 return ipx_ntop(af
, addr
, buf
, buflen
);
1019 struct dn_naddr dna
= { 2, { 0, 0, } };
1021 memcpy(dna
.a_addr
, addr
, 2);
1022 return dnet_ntop(af
, &dna
, buf
, buflen
);
1025 return ll_addr_n2a(addr
, len
, ARPHRD_VOID
, buf
, buflen
);
1030 struct sockaddr_in sin
;
1031 struct sockaddr_in6 sin6
;
1034 switch (sa
->sa
.sa_family
) {
1036 return inet_ntop(AF_INET
, &sa
->sin
.sin_addr
,
1039 return inet_ntop(AF_INET6
, &sa
->sin6
.sin6_addr
,
1050 const char *rt_addr_n2a(int af
, int len
, const void *addr
)
1052 static char buf
[256];
1054 return rt_addr_n2a_r(af
, len
, addr
, buf
, 256);
1057 int read_family(const char *name
)
1059 int family
= AF_UNSPEC
;
1061 if (strcmp(name
, "inet") == 0)
1063 else if (strcmp(name
, "inet6") == 0)
1065 else if (strcmp(name
, "dnet") == 0)
1067 else if (strcmp(name
, "link") == 0)
1069 else if (strcmp(name
, "ipx") == 0)
1071 else if (strcmp(name
, "mpls") == 0)
1073 else if (strcmp(name
, "bridge") == 0)
1078 const char *family_name(int family
)
1080 if (family
== AF_INET
)
1082 if (family
== AF_INET6
)
1084 if (family
== AF_DECnet
)
1086 if (family
== AF_PACKET
)
1088 if (family
== AF_IPX
)
1090 if (family
== AF_MPLS
)
1092 if (family
== AF_BRIDGE
)
1097 #ifdef RESOLVE_HOSTNAMES
1099 struct namerec
*next
;
1105 static struct namerec
*nht
[NHASH
];
1107 static const char *resolve_address(const void *addr
, int len
, int af
)
1110 struct hostent
*h_ent
;
1112 static int notfirst
;
1115 if (af
== AF_INET6
&& ((__u32
*)addr
)[0] == 0 &&
1116 ((__u32
*)addr
)[1] == 0 && ((__u32
*)addr
)[2] == htonl(0xffff)) {
1122 hash
= *(__u32
*)(addr
+ len
- 4) % NHASH
;
1124 for (n
= nht
[hash
]; n
; n
= n
->next
) {
1125 if (n
->addr
.family
== af
&&
1126 n
->addr
.bytelen
== len
&&
1127 memcmp(n
->addr
.data
, addr
, len
) == 0)
1130 n
= malloc(sizeof(*n
));
1133 n
->addr
.family
= af
;
1134 n
->addr
.bytelen
= len
;
1136 memcpy(n
->addr
.data
, addr
, len
);
1137 n
->next
= nht
[hash
];
1139 if (++notfirst
== 1)
1143 h_ent
= gethostbyaddr(addr
, len
, af
);
1145 n
->name
= strdup(h_ent
->h_name
);
1147 /* Even if we fail, "negative" entry is remembered. */
1152 const char *format_host_r(int af
, int len
, const void *addr
,
1153 char *buf
, int buflen
)
1155 #ifdef RESOLVE_HOSTNAMES
1156 if (resolve_hosts
) {
1159 len
= len
<= 0 ? af_byte_len(af
) : len
;
1162 (n
= resolve_address(addr
, len
, af
)) != NULL
)
1166 return rt_addr_n2a_r(af
, len
, addr
, buf
, buflen
);
1169 const char *format_host(int af
, int len
, const void *addr
)
1171 static char buf
[256];
1173 return format_host_r(af
, len
, addr
, buf
, 256);
1177 char *hexstring_n2a(const __u8
*str
, int len
, char *buf
, int blen
)
1182 for (i
= 0; i
< len
; i
++) {
1185 sprintf(ptr
, "%02x", str
[i
]);
1192 __u8
*hexstring_a2n(const char *str
, __u8
*buf
, int blen
, unsigned int *len
)
1194 unsigned int cnt
= 0;
1197 if (strlen(str
) % 2)
1199 while (cnt
< blen
&& strlen(str
) > 1) {
1203 strncpy(tmpstr
, str
, 2);
1206 tmp
= strtoul(tmpstr
, &endptr
, 16);
1207 if (errno
!= 0 || tmp
> 0xFF || *endptr
!= '\0')
1219 int hex2mem(const char *buf
, uint8_t *mem
, int count
)
1224 for (i
= 0, j
= 0; i
< count
; i
++, j
+= 2) {
1225 c
= get_hex(buf
[j
]);
1231 c
= get_hex(buf
[j
+ 1]);
1241 int addr64_n2a(__u64 addr
, char *buff
, size_t len
)
1243 __u16
*words
= (__u16
*)&addr
;
1249 for (i
= 0; i
< 4; i
++) {
1250 v
= ntohs(words
[i
]);
1255 ret
= snprintf(&buff
[written
], len
- written
, "%x%s", v
, sep
);
1265 /* Print buffer and escape bytes that are !isprint or among 'escape' */
1266 void print_escape_buf(const __u8
*buf
, size_t len
, const char *escape
)
1270 for (i
= 0; i
< len
; ++i
) {
1271 if (isprint(buf
[i
]) && buf
[i
] != '\\' &&
1272 !strchr(escape
, buf
[i
]))
1273 printf("%c", buf
[i
]);
1275 printf("\\%03o", buf
[i
]);
1279 int print_timestamp(FILE *fp
)
1284 gettimeofday(&tv
, NULL
);
1285 tm
= localtime(&tv
.tv_sec
);
1287 if (timestamp_short
) {
1290 strftime(tshort
, sizeof(tshort
), "%Y-%m-%dT%H:%M:%S", tm
);
1291 fprintf(fp
, "[%s.%06ld] ", tshort
, tv
.tv_usec
);
1293 char *tstr
= asctime(tm
);
1295 tstr
[strlen(tstr
)-1] = 0;
1296 fprintf(fp
, "Timestamp: %s %ld usec\n",
1303 unsigned int print_name_and_link(const char *fmt
,
1304 const char *name
, struct rtattr
*tb
[])
1306 const char *link
= NULL
;
1307 unsigned int m_flag
= 0;
1310 if (tb
[IFLA_LINK
]) {
1311 int iflink
= rta_getattr_u32(tb
[IFLA_LINK
]);
1314 if (tb
[IFLA_LINK_NETNSID
]) {
1315 if (is_json_context()) {
1316 print_int(PRINT_JSON
,
1317 "link_index", NULL
, iflink
);
1319 link
= ll_idx_n2a(iflink
);
1322 link
= ll_index_to_name(iflink
);
1324 if (is_json_context()) {
1325 print_string(PRINT_JSON
,
1326 "link", NULL
, link
);
1330 m_flag
= ll_index_to_flags(iflink
);
1331 m_flag
= !(m_flag
& IFF_UP
);
1334 if (is_json_context())
1335 print_null(PRINT_JSON
, "link", NULL
, NULL
);
1341 snprintf(b1
, sizeof(b1
), "%s@%s", name
, link
);
1346 print_color_string(PRINT_ANY
, COLOR_IFNAME
, "ifname", fmt
, name
);
1353 /* Like glibc getline but handle continuation lines and comments */
1354 ssize_t
getcmdline(char **linep
, size_t *lenp
, FILE *in
)
1359 cc
= getline(linep
, lenp
, in
);
1361 return cc
; /* eof or error */
1364 cp
= strchr(*linep
, '#');
1368 while ((cp
= strstr(*linep
, "\\\n")) != NULL
) {
1373 cc1
= getline(&line1
, &len1
, in
);
1375 fprintf(stderr
, "Missing continuation line\n");
1382 cp
= strchr(line1
, '#');
1386 *lenp
= strlen(*linep
) + strlen(line1
) + 1;
1387 *linep
= realloc(*linep
, *lenp
);
1389 fprintf(stderr
, "Out of memory\n");
1394 strcat(*linep
, line1
);
1400 /* split command line into argument vector */
1401 int makeargs(char *line
, char *argv
[], int maxargs
)
1403 static const char ws
[] = " \t\r\n";
1408 /* skip leading whitespace */
1409 cp
+= strspn(cp
, ws
);
1414 if (argc
>= (maxargs
- 1)) {
1415 fprintf(stderr
, "Too many arguments to command\n");
1419 /* word begins with quote */
1420 if (*cp
== '\'' || *cp
== '"') {
1424 /* find ending quote */
1425 cp
= strchr(cp
, quote
);
1427 fprintf(stderr
, "Unterminated quoted string\n");
1433 /* find end of word */
1434 cp
+= strcspn(cp
, ws
);
1439 /* separate words */
1447 void print_nlmsg_timestamp(FILE *fp
, const struct nlmsghdr
*n
)
1450 time_t secs
= ((__u32
*)NLMSG_DATA(n
))[0];
1451 long usecs
= ((__u32
*)NLMSG_DATA(n
))[1];
1453 tstr
= asctime(localtime(&secs
));
1454 tstr
[strlen(tstr
)-1] = 0;
1455 fprintf(fp
, "Timestamp: %s %lu us\n", tstr
, usecs
);
1458 static int on_netns(char *nsname
, void *arg
)
1460 struct netns_func
*f
= arg
;
1462 if (netns_switch(nsname
))
1465 return f
->func(nsname
, f
->arg
);
1468 static int on_netns_label(char *nsname
, void *arg
)
1470 printf("\nnetns: %s\n", nsname
);
1471 return on_netns(nsname
, arg
);
1474 int do_each_netns(int (*func
)(char *nsname
, void *arg
), void *arg
,
1477 struct netns_func nsf
= { .func
= func
, .arg
= arg
};
1480 return netns_foreach(on_netns_label
, &nsf
);
1482 return netns_foreach(on_netns
, &nsf
);
1485 char *int_to_str(int val
, char *buf
)
1487 sprintf(buf
, "%d", val
);
1491 int get_guid(__u64
*guid
, const char *arg
)
1493 unsigned long int tmp
;
1497 #define GUID_STR_LEN 23
1498 /* Verify strict format: format string must be
1499 * xx:xx:xx:xx:xx:xx:xx:xx where xx can be an arbitrary
1503 if (strlen(arg
) != GUID_STR_LEN
)
1506 /* make sure columns are in place */
1507 for (i
= 0; i
< 7; i
++)
1508 if (arg
[2 + i
* 3] != ':')
1512 for (i
= 0; i
< 8; i
++) {
1513 tmp
= strtoul(arg
+ i
* 3, &endptr
, 16);
1514 if (endptr
!= arg
+ i
* 3 + 2)
1520 *guid
|= tmp
<< (56 - 8 * i
);
1526 /* This is a necessary workaround for multicast route dumps */
1527 int get_real_family(int rtm_type
, int rtm_family
)
1529 if (rtm_type
!= RTN_MULTICAST
)
1532 if (rtm_family
== RTNL_FAMILY_IPMR
)
1535 if (rtm_family
== RTNL_FAMILY_IP6MR
)
1541 /* Based on copy_rtnl_link_stats() from kernel at net/core/rtnetlink.c */
1542 static void copy_rtnl_link_stats64(struct rtnl_link_stats64
*stats64
,
1543 const struct rtnl_link_stats
*stats
)
1545 __u64
*a
= (__u64
*)stats64
;
1546 const __u32
*b
= (const __u32
*)stats
;
1547 const __u32
*e
= b
+ sizeof(*stats
) / sizeof(*b
);
1553 #define IPSTATS_MIB_MAX_LEN (__IPSTATS_MIB_MAX * sizeof(__u64))
1554 static void get_snmp_counters(struct rtnl_link_stats64
*stats64
,
1557 __u64
*mib
= (__u64
*)RTA_DATA(s
);
1559 memset(stats64
, 0, sizeof(*stats64
));
1561 stats64
->rx_packets
= mib
[IPSTATS_MIB_INPKTS
];
1562 stats64
->rx_bytes
= mib
[IPSTATS_MIB_INOCTETS
];
1563 stats64
->tx_packets
= mib
[IPSTATS_MIB_OUTPKTS
];
1564 stats64
->tx_bytes
= mib
[IPSTATS_MIB_OUTOCTETS
];
1565 stats64
->rx_errors
= mib
[IPSTATS_MIB_INDISCARDS
];
1566 stats64
->tx_errors
= mib
[IPSTATS_MIB_OUTDISCARDS
];
1567 stats64
->multicast
= mib
[IPSTATS_MIB_INMCASTPKTS
];
1568 stats64
->rx_frame_errors
= mib
[IPSTATS_MIB_CSUMERRORS
];
1571 int get_rtnl_link_stats_rta(struct rtnl_link_stats64
*stats64
,
1572 struct rtattr
*tb
[])
1574 struct rtnl_link_stats stats
;
1579 if (tb
[IFLA_STATS64
]) {
1580 rta
= tb
[IFLA_STATS64
];
1581 size
= sizeof(struct rtnl_link_stats64
);
1583 } else if (tb
[IFLA_STATS
]) {
1584 rta
= tb
[IFLA_STATS
];
1585 size
= sizeof(struct rtnl_link_stats
);
1587 } else if (tb
[IFLA_PROTINFO
]) {
1588 struct rtattr
*ptb
[IPSTATS_MIB_MAX_LEN
+ 1];
1590 parse_rtattr_nested(ptb
, IPSTATS_MIB_MAX_LEN
,
1592 if (ptb
[IFLA_INET6_STATS
])
1593 get_snmp_counters(stats64
, ptb
[IFLA_INET6_STATS
]);
1594 return sizeof(*stats64
);
1599 len
= RTA_PAYLOAD(rta
);
1601 memset(s
+ len
, 0, size
- len
);
1605 memcpy(s
, RTA_DATA(rta
), len
);
1608 copy_rtnl_link_stats64(stats64
, s
);
1613 size_t strlcpy(char *dst
, const char *src
, size_t size
)
1615 size_t srclen
= strlen(src
);
1618 size_t minlen
= min(srclen
, size
- 1);
1620 memcpy(dst
, src
, minlen
);
1626 size_t strlcat(char *dst
, const char *src
, size_t size
)
1628 size_t dlen
= strlen(dst
);
1631 return dlen
+ strlen(src
);
1633 return dlen
+ strlcpy(dst
+ dlen
, src
, size
- dlen
);
1640 /* don't harmstring root/sudo */
1641 if (getuid() != 0 && geteuid() != 0) {
1643 cap_value_t net_admin
= CAP_NET_ADMIN
;
1644 cap_flag_t inheritable
= CAP_INHERITABLE
;
1645 cap_flag_value_t is_set
;
1647 capabilities
= cap_get_proc();
1650 if (cap_get_flag(capabilities
, net_admin
, inheritable
,
1653 /* apps with ambient caps can fork and call ip */
1654 if (is_set
== CAP_CLEAR
) {
1655 if (cap_clear(capabilities
) != 0)
1657 if (cap_set_proc(capabilities
) != 0)
1660 cap_free(capabilities
);