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>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
22 #include <arpa/inet.h>
24 #include <asm/types.h>
25 #include <linux/pkt_sched.h>
33 int get_integer(int *val
, const char *arg
, int base
)
40 res
= strtol(arg
, &ptr
, base
);
41 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> INT_MAX
|| res
< INT_MIN
)
47 int mask2bits(__u32 netmask
)
50 __u32 mask
= ntohl(netmask
);
53 /* a valid netmask must be 2^n - 1 */
54 if ((host
& (host
+ 1)) != 0)
57 for (; mask
; mask
<<= 1)
62 static int get_netmask(unsigned *val
, const char *arg
, int base
)
66 if (!get_unsigned(val
, arg
, base
))
69 /* try coverting dotted quad to CIDR */
70 if (!get_addr_1(&addr
, arg
, AF_INET
) && addr
.family
== AF_INET
) {
71 int b
= mask2bits(addr
.data
[0]);
82 int get_unsigned(unsigned *val
, const char *arg
, int base
)
89 res
= strtoul(arg
, &ptr
, base
);
90 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> UINT_MAX
)
97 * get_time_rtt is "translated" from a similar routine "get_time" in
98 * tc_util.c. We don't use the exact same routine because tc passes
99 * microseconds to the kernel and the callers of get_time_rtt want to
100 * pass milliseconds (standard unit for rtt values since 2.6.27), and
101 * have a different assumption for the units of a "raw" number.
103 int get_time_rtt(unsigned *val
, const char *arg
, int *raw
)
109 if (strchr(arg
,'.') != NULL
) {
115 res
= strtoul(arg
, &p
, 0);
126 if (strcasecmp(p
, "s") == 0 || strcasecmp(p
, "sec")==0 ||
127 strcasecmp(p
, "secs")==0)
129 else if (strcasecmp(p
, "ms") == 0 || strcasecmp(p
, "msec")==0 ||
130 strcasecmp(p
, "msecs") == 0)
131 t
*= 1.0; /* allow suffix, do nothing */
136 /* emulate ceil() without having to bring-in -lm and always be >= 1 */
146 int get_u64(__u64
*val
, const char *arg
, int base
)
148 unsigned long long res
;
153 res
= strtoull(arg
, &ptr
, base
);
154 if (!ptr
|| ptr
== arg
|| *ptr
|| res
== 0xFFFFFFFFULL
)
160 int get_u32(__u32
*val
, const char *arg
, int base
)
167 res
= strtoul(arg
, &ptr
, base
);
168 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> 0xFFFFFFFFUL
)
174 int get_u16(__u16
*val
, const char *arg
, int base
)
181 res
= strtoul(arg
, &ptr
, base
);
182 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> 0xFFFF)
188 int get_u8(__u8
*val
, const char *arg
, int base
)
195 res
= strtoul(arg
, &ptr
, base
);
196 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> 0xFF)
202 int get_s32(__s32
*val
, const char *arg
, int base
)
211 res
= strtol(arg
, &ptr
, base
);
212 if (ptr
== arg
|| *ptr
||
213 ((res
== LONG_MIN
|| res
== LONG_MAX
) && errno
== ERANGE
) ||
214 res
> INT32_MAX
|| res
< INT32_MIN
)
220 int get_s16(__s16
*val
, const char *arg
, int base
)
227 res
= strtol(arg
, &ptr
, base
);
228 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> 0x7FFF || res
< -0x8000)
234 int get_s8(__s8
*val
, const char *arg
, int base
)
241 res
= strtol(arg
, &ptr
, base
);
242 if (!ptr
|| ptr
== arg
|| *ptr
|| res
> 0x7F || res
< -0x80)
248 /* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
249 * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
251 static int get_addr_ipv4(__u8
*ap
, const char *cp
)
255 for (i
= 0; i
< 4; i
++) {
259 n
= strtoul(cp
, &endp
, 0);
261 return -1; /* bogus network value */
263 if (endp
== cp
) /* no digits */
271 if (i
== 3 || *endp
!= '.')
272 return -1; /* extra characters */
279 int get_addr_1(inet_prefix
*addr
, const char *name
, int family
)
281 memset(addr
, 0, sizeof(*addr
));
283 if (strcmp(name
, "default") == 0 ||
284 strcmp(name
, "all") == 0 ||
285 strcmp(name
, "any") == 0) {
286 if (family
== AF_DECnet
)
288 addr
->family
= family
;
289 addr
->bytelen
= (family
== AF_INET6
? 16 : 4);
294 if (strchr(name
, ':')) {
295 addr
->family
= AF_INET6
;
296 if (family
!= AF_UNSPEC
&& family
!= AF_INET6
)
298 if (inet_pton(AF_INET6
, name
, addr
->data
) <= 0)
305 if (family
== AF_DECnet
) {
307 addr
->family
= AF_DECnet
;
308 if (dnet_pton(AF_DECnet
, name
, &dna
) <= 0)
310 memcpy(addr
->data
, dna
.a_addr
, 2);
316 addr
->family
= AF_INET
;
317 if (family
!= AF_UNSPEC
&& family
!= AF_INET
)
320 if (get_addr_ipv4((__u8
*)addr
->data
, name
) <= 0)
328 int get_prefix_1(inet_prefix
*dst
, char *arg
, int family
)
334 memset(dst
, 0, sizeof(*dst
));
336 if (strcmp(arg
, "default") == 0 ||
337 strcmp(arg
, "any") == 0 ||
338 strcmp(arg
, "all") == 0) {
339 if (family
== AF_DECnet
)
341 dst
->family
= family
;
347 slash
= strchr(arg
, '/');
351 err
= get_addr_1(dst
, arg
, family
);
353 switch(dst
->family
) {
365 if (get_netmask(&plen
, slash
+1, 0)
366 || plen
> dst
->bitlen
) {
370 dst
->flags
|= PREFIXLEN_SPECIFIED
;
380 int get_addr(inet_prefix
*dst
, const char *arg
, int family
)
382 if (family
== AF_PACKET
) {
383 fprintf(stderr
, "Error: \"%s\" may be inet address, but it is not allowed in this context.\n", arg
);
386 if (get_addr_1(dst
, arg
, family
)) {
387 fprintf(stderr
, "Error: an inet address is expected rather than \"%s\".\n", arg
);
393 int get_prefix(inet_prefix
*dst
, char *arg
, int family
)
395 if (family
== AF_PACKET
) {
396 fprintf(stderr
, "Error: \"%s\" may be inet prefix, but it is not allowed in this context.\n", arg
);
399 if (get_prefix_1(dst
, arg
, family
)) {
400 fprintf(stderr
, "Error: an inet prefix is expected rather than \"%s\".\n", arg
);
406 __u32
get_addr32(const char *name
)
409 if (get_addr_1(&addr
, name
, AF_INET
)) {
410 fprintf(stderr
, "Error: an IP address is expected rather than \"%s\"\n", name
);
416 void incomplete_command(void)
418 fprintf(stderr
, "Command line is not complete. Try option \"help\"\n");
422 void missarg(const char *key
)
424 fprintf(stderr
, "Error: argument \"%s\" is required\n", key
);
428 void invarg(const char *msg
, const char *arg
)
430 fprintf(stderr
, "Error: argument \"%s\" is wrong: %s\n", arg
, msg
);
434 void duparg(const char *key
, const char *arg
)
436 fprintf(stderr
, "Error: duplicate \"%s\": \"%s\" is the second value.\n", key
, arg
);
440 void duparg2(const char *key
, const char *arg
)
442 fprintf(stderr
, "Error: either \"%s\" is duplicate, or \"%s\" is a garbage.\n", key
, arg
);
446 int matches(const char *cmd
, const char *pattern
)
448 int len
= strlen(cmd
);
449 if (len
> strlen(pattern
))
451 return memcmp(pattern
, cmd
, len
);
454 int inet_addr_match(const inet_prefix
*a
, const inet_prefix
*b
, int bits
)
456 const __u32
*a1
= a
->data
;
457 const __u32
*a2
= b
->data
;
458 int words
= bits
>> 0x05;
463 if (memcmp(a1
, a2
, words
<< 2))
473 mask
= htonl((0xffffffff) << (0x20 - bits
));
475 if ((w1
^ w2
) & mask
)
482 int __iproute2_hz_internal
;
491 return atoi(getenv("HZ")) ? : HZ
;
493 if (getenv("PROC_NET_PSCHED")) {
494 snprintf(name
, sizeof(name
)-1, "%s", getenv("PROC_NET_PSCHED"));
495 } else if (getenv("PROC_ROOT")) {
496 snprintf(name
, sizeof(name
)-1, "%s/net/psched", getenv("PROC_ROOT"));
498 strcpy(name
, "/proc/net/psched");
500 fp
= fopen(name
, "r");
504 if (fscanf(fp
, "%*08x%*08x%08x%08x", &nom
, &denom
) == 2)
514 int __iproute2_user_hz_internal
;
516 int __get_user_hz(void)
518 return sysconf(_SC_CLK_TCK
);
521 const char *rt_addr_n2a(int af
, int len
, const void *addr
, char *buf
, int buflen
)
526 return inet_ntop(af
, addr
, buf
, buflen
);
528 return ipx_ntop(af
, addr
, buf
, buflen
);
531 struct dn_naddr dna
= { 2, { 0, 0, }};
532 memcpy(dna
.a_addr
, addr
, 2);
533 return dnet_ntop(af
, &dna
, buf
, buflen
);
540 #ifdef RESOLVE_HOSTNAMES
543 struct namerec
*next
;
549 static struct namerec
*nht
[NHASH
];
551 static const char *resolve_address(const void *addr
, int len
, int af
)
554 struct hostent
*h_ent
;
559 if (af
== AF_INET6
&& ((__u32
*)addr
)[0] == 0 &&
560 ((__u32
*)addr
)[1] == 0 && ((__u32
*)addr
)[2] == htonl(0xffff)) {
566 hash
= *(__u32
*)(addr
+ len
- 4) % NHASH
;
568 for (n
= nht
[hash
]; n
; n
= n
->next
) {
569 if (n
->addr
.family
== af
&&
570 n
->addr
.bytelen
== len
&&
571 memcmp(n
->addr
.data
, addr
, len
) == 0)
574 if ((n
= malloc(sizeof(*n
))) == NULL
)
577 n
->addr
.bytelen
= len
;
579 memcpy(n
->addr
.data
, addr
, len
);
586 if ((h_ent
= gethostbyaddr(addr
, len
, af
)) != NULL
)
587 n
->name
= strdup(h_ent
->h_name
);
589 /* Even if we fail, "negative" entry is remembered. */
595 const char *format_host(int af
, int len
, const void *addr
,
596 char *buf
, int buflen
)
598 #ifdef RESOLVE_HOSTNAMES
614 /* I see no reasons why gethostbyname
615 may not work for DECnet */
624 (n
= resolve_address(addr
, len
, af
)) != NULL
)
628 return rt_addr_n2a(af
, len
, addr
, buf
, buflen
);
632 char *hexstring_n2a(const __u8
*str
, int len
, char *buf
, int blen
)
637 for (i
=0; i
<len
; i
++) {
640 sprintf(ptr
, "%02x", str
[i
]);
643 if (i
!= len
-1 && blen
> 1) {
651 __u8
* hexstring_a2n(const char *str
, __u8
*buf
, int blen
)
661 while ((ch
= *str
) != ':' && ch
!= 0) {
662 if (ch
>= '0' && ch
<= '9')
664 else if (ch
>= 'a' && ch
<= 'f')
666 else if (ch
>= 'A' && ch
<= 'F')
685 memset(buf
+cnt
, 0, blen
-cnt
);
689 int print_timestamp(FILE *fp
)
694 memset(&tv
, 0, sizeof(tv
));
695 gettimeofday(&tv
, NULL
);
697 tstr
= asctime(localtime(&tv
.tv_sec
));
698 tstr
[strlen(tstr
)-1] = 0;
699 fprintf(fp
, "Timestamp: %s %lu usec\n", tstr
, tv
.tv_usec
);
705 /* Like glibc getline but handle continuation lines and comments */
706 ssize_t
getcmdline(char **linep
, size_t *lenp
, FILE *in
)
711 if ((cc
= getline(linep
, lenp
, in
)) < 0)
712 return cc
; /* eof or error */
715 cp
= strchr(*linep
, '#');
719 while ((cp
= strstr(*linep
, "\\\n")) != NULL
) {
724 if ((cc1
= getline(&line1
, &len1
, in
)) < 0) {
725 fprintf(stderr
, "Missing continuation line\n");
732 cp
= strchr(line1
, '#');
736 *lenp
= strlen(*linep
) + strlen(line1
) + 1;
737 *linep
= realloc(*linep
, *lenp
);
739 fprintf(stderr
, "Out of memory\n");
744 strcat(*linep
, line1
);
750 /* split command line into argument vector */
751 int makeargs(char *line
, char *argv
[], int maxargs
)
753 static const char ws
[] = " \t\r\n";
757 for (cp
= strtok(line
, ws
); cp
; cp
= strtok(NULL
, ws
)) {
758 if (argc
>= (maxargs
- 1)) {
759 fprintf(stderr
, "Too many arguments to command\n");