]> git.proxmox.com Git - mirror_iproute2.git/blame - lib/utils.c
add short description of batch mode in tc man page
[mirror_iproute2.git] / lib / utils.c
CommitLineData
aba5acdf
SH
1/*
2 * utils.c
3 *
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.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 *
aba5acdf
SH
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
16#include <syslog.h>
17#include <fcntl.h>
5bd9dd49 18#include <limits.h>
aba5acdf
SH
19#include <sys/socket.h>
20#include <netinet/in.h>
21#include <string.h>
22#include <netdb.h>
23#include <arpa/inet.h>
5dfe5561 24#include <asm/types.h>
aba5acdf 25#include <linux/pkt_sched.h>
5bd9dd49 26#include <linux/param.h>
90f93024
SH
27#include <time.h>
28#include <sys/time.h>
30d10db5 29#include <errno.h>
90f93024 30
aba5acdf
SH
31
32#include "utils.h"
33
4094db72 34int get_integer(int *val, const char *arg, int base)
aba5acdf
SH
35{
36 long res;
37 char *ptr;
38
39 if (!arg || !*arg)
40 return -1;
41 res = strtol(arg, &ptr, base);
42 if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
43 return -1;
44 *val = res;
45 return 0;
46}
47
6b1ac654 48int mask2bits(__u32 netmask)
4b270b17
SH
49{
50 unsigned bits = 0;
6b1ac654
SH
51 __u32 mask = ntohl(netmask);
52 __u32 host = ~mask;
4b270b17 53
6b1ac654
SH
54 /* a valid netmask must be 2^n - 1 */
55 if ((host & (host + 1)) != 0)
56 return -1;
4b270b17 57
6b1ac654
SH
58 for (; mask; mask <<= 1)
59 ++bits;
4b270b17
SH
60 return bits;
61}
62
5a0d1cbf
AH
63static int get_netmask(unsigned *val, const char *arg, int base)
64{
65 inet_prefix addr;
66
67 if (!get_unsigned(val, arg, base))
68 return 0;
69
70 /* try coverting dotted quad to CIDR */
6b1ac654
SH
71 if (!get_addr_1(&addr, arg, AF_INET) && addr.family == AF_INET) {
72 int b = mask2bits(addr.data[0]);
73
74 if (b >= 0) {
75 *val = b;
5a0d1cbf 76 return 0;
6b1ac654 77 }
5a0d1cbf
AH
78 }
79
80 return -1;
81}
82
4094db72 83int get_unsigned(unsigned *val, const char *arg, int base)
aba5acdf
SH
84{
85 unsigned long res;
86 char *ptr;
87
88 if (!arg || !*arg)
89 return -1;
90 res = strtoul(arg, &ptr, base);
91 if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
92 return -1;
93 *val = res;
94 return 0;
95}
96
54e0b2e7 97/*
db6b0cfa
GR
98 * get_time_rtt is "translated" from a similar routine "get_time" in
99 * tc_util.c. We don't use the exact same routine because tc passes
100 * microseconds to the kernel and the callers of get_time_rtt want to
101 * pass milliseconds (standard unit for rtt values since 2.6.27), and
102 * have a different assumption for the units of a "raw" number.
54e0b2e7 103 */
db6b0cfa 104int get_time_rtt(unsigned *val, const char *arg, int *raw)
54e0b2e7
RJ
105{
106 double t;
107 unsigned long res;
108 char *p;
109
110 if (strchr(arg,'.') != NULL) {
111 t = strtod(arg,&p);
112 if (t < 0.0)
113 return -1;
114 }
115 else {
897fb84f 116 res = strtoul(arg, &p, 0);
54e0b2e7
RJ
117 if (res > UINT_MAX)
118 return -1;
119 t = (double)res;
120 }
121 if (p == arg)
122 return -1;
54e0b2e7
RJ
123 *raw = 1;
124
125 if (*p) {
126 *raw = 0;
127 if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
128 strcasecmp(p, "secs")==0)
fca1dae8 129 t *= 1000;
54e0b2e7
RJ
130 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
131 strcasecmp(p, "msecs") == 0)
54e0b2e7
RJ
132 t *= 1.0; /* allow suffix, do nothing */
133 else
134 return -1;
135 }
136
137 /* emulate ceil() without having to bring-in -lm and always be >= 1 */
138
db6b0cfa
GR
139 *val = t;
140 if (*val < t)
141 *val += 1;
54e0b2e7
RJ
142
143 return 0;
144
145}
146
c7699875 147int get_u64(__u64 *val, const char *arg, int base)
148{
149 unsigned long long res;
150 char *ptr;
151
152 if (!arg || !*arg)
153 return -1;
154 res = strtoull(arg, &ptr, base);
155 if (!ptr || ptr == arg || *ptr || res == 0xFFFFFFFFULL)
156 return -1;
157 *val = res;
158 return 0;
159}
160
4094db72 161int get_u32(__u32 *val, const char *arg, int base)
aba5acdf
SH
162{
163 unsigned long res;
164 char *ptr;
165
166 if (!arg || !*arg)
167 return -1;
168 res = strtoul(arg, &ptr, base);
169 if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
170 return -1;
171 *val = res;
172 return 0;
173}
174
4094db72 175int get_u16(__u16 *val, const char *arg, int base)
aba5acdf
SH
176{
177 unsigned long res;
178 char *ptr;
179
180 if (!arg || !*arg)
181 return -1;
182 res = strtoul(arg, &ptr, base);
183 if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
184 return -1;
185 *val = res;
186 return 0;
187}
188
4094db72 189int get_u8(__u8 *val, const char *arg, int base)
aba5acdf
SH
190{
191 unsigned long res;
192 char *ptr;
193
194 if (!arg || !*arg)
195 return -1;
196 res = strtoul(arg, &ptr, base);
197 if (!ptr || ptr == arg || *ptr || res > 0xFF)
198 return -1;
199 *val = res;
200 return 0;
201}
202
30d10db5
HPP
203int get_s32(__s32 *val, const char *arg, int base)
204{
205 long res;
206 char *ptr;
207
208 errno = 0;
209
210 if (!arg || !*arg)
211 return -1;
212 res = strtol(arg, &ptr, base);
213 if (ptr == arg || *ptr ||
214 ((res == LONG_MIN || res == LONG_MAX) && errno == ERANGE) ||
215 res > INT32_MAX || res < INT32_MIN)
216 return -1;
217 *val = res;
218 return 0;
219}
220
4094db72 221int get_s16(__s16 *val, const char *arg, int base)
aba5acdf
SH
222{
223 long res;
224 char *ptr;
225
226 if (!arg || !*arg)
227 return -1;
228 res = strtol(arg, &ptr, base);
229 if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
230 return -1;
231 *val = res;
232 return 0;
233}
234
4094db72 235int get_s8(__s8 *val, const char *arg, int base)
aba5acdf
SH
236{
237 long res;
238 char *ptr;
239
240 if (!arg || !*arg)
241 return -1;
242 res = strtol(arg, &ptr, base);
243 if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
244 return -1;
245 *val = res;
246 return 0;
247}
248
cafa6c8e
SH
249/* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
250 * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
251 */
252static int get_addr_ipv4(__u8 *ap, const char *cp)
aba5acdf 253{
cafa6c8e
SH
254 int i;
255
256 for (i = 0; i < 4; i++) {
257 unsigned long n;
258 char *endp;
259
260 n = strtoul(cp, &endp, 0);
261 if (n > 255)
262 return -1; /* bogus network value */
263
264 if (endp == cp) /* no digits */
265 return -1;
94afda75 266
cafa6c8e
SH
267 ap[i] = n;
268
269 if (*endp == '\0')
270 break;
271
272 if (i == 3 || *endp != '.')
273 return -1; /* extra characters */
274 cp = endp + 1;
275 }
276
277 return 1;
278}
279
280int get_addr_1(inet_prefix *addr, const char *name, int family)
281{
aba5acdf
SH
282 memset(addr, 0, sizeof(*addr));
283
284 if (strcmp(name, "default") == 0 ||
285 strcmp(name, "all") == 0 ||
286 strcmp(name, "any") == 0) {
287 if (family == AF_DECnet)
288 return -1;
289 addr->family = family;
290 addr->bytelen = (family == AF_INET6 ? 16 : 4);
291 addr->bitlen = -1;
292 return 0;
293 }
294
295 if (strchr(name, ':')) {
296 addr->family = AF_INET6;
297 if (family != AF_UNSPEC && family != AF_INET6)
298 return -1;
299 if (inet_pton(AF_INET6, name, addr->data) <= 0)
300 return -1;
301 addr->bytelen = 16;
302 addr->bitlen = -1;
303 return 0;
304 }
305
306 if (family == AF_DECnet) {
307 struct dn_naddr dna;
308 addr->family = AF_DECnet;
309 if (dnet_pton(AF_DECnet, name, &dna) <= 0)
310 return -1;
311 memcpy(addr->data, dna.a_addr, 2);
312 addr->bytelen = 2;
313 addr->bitlen = -1;
314 return 0;
315 }
316
317 addr->family = AF_INET;
318 if (family != AF_UNSPEC && family != AF_INET)
319 return -1;
94afda75 320
cafa6c8e 321 if (get_addr_ipv4((__u8 *)addr->data, name) <= 0)
516ffb6b 322 return -1;
94afda75 323
aba5acdf
SH
324 addr->bytelen = 4;
325 addr->bitlen = -1;
aba5acdf
SH
326 return 0;
327}
328
fb9b1d0f 329int get_prefix_1(inet_prefix *dst, char *arg, int family)
aba5acdf
SH
330{
331 int err;
332 unsigned plen;
333 char *slash;
334
335 memset(dst, 0, sizeof(*dst));
336
337 if (strcmp(arg, "default") == 0 ||
338 strcmp(arg, "any") == 0 ||
339 strcmp(arg, "all") == 0) {
340 if (family == AF_DECnet)
341 return -1;
342 dst->family = family;
343 dst->bytelen = 0;
344 dst->bitlen = 0;
345 return 0;
346 }
347
348 slash = strchr(arg, '/');
349 if (slash)
350 *slash = 0;
fb9b1d0f 351
aba5acdf
SH
352 err = get_addr_1(dst, arg, family);
353 if (err == 0) {
354 switch(dst->family) {
355 case AF_INET6:
356 dst->bitlen = 128;
357 break;
358 case AF_DECnet:
359 dst->bitlen = 16;
360 break;
361 default:
362 case AF_INET:
363 dst->bitlen = 32;
364 }
365 if (slash) {
5a0d1cbf
AH
366 if (get_netmask(&plen, slash+1, 0)
367 || plen > dst->bitlen) {
aba5acdf
SH
368 err = -1;
369 goto done;
370 }
f082b64f 371 dst->flags |= PREFIXLEN_SPECIFIED;
aba5acdf
SH
372 dst->bitlen = plen;
373 }
374 }
375done:
376 if (slash)
377 *slash = '/';
378 return err;
379}
380
c7699875 381int get_addr(inet_prefix *dst, const char *arg, int family)
aba5acdf
SH
382{
383 if (family == AF_PACKET) {
384 fprintf(stderr, "Error: \"%s\" may be inet address, but it is not allowed in this context.\n", arg);
385 exit(1);
386 }
387 if (get_addr_1(dst, arg, family)) {
388 fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", arg);
389 exit(1);
390 }
391 return 0;
392}
393
fb9b1d0f 394int get_prefix(inet_prefix *dst, char *arg, int family)
aba5acdf
SH
395{
396 if (family == AF_PACKET) {
397 fprintf(stderr, "Error: \"%s\" may be inet prefix, but it is not allowed in this context.\n", arg);
398 exit(1);
399 }
400 if (get_prefix_1(dst, arg, family)) {
401 fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", arg);
402 exit(1);
403 }
404 return 0;
405}
406
c7699875 407__u32 get_addr32(const char *name)
aba5acdf
SH
408{
409 inet_prefix addr;
410 if (get_addr_1(&addr, name, AF_INET)) {
411 fprintf(stderr, "Error: an IP address is expected rather than \"%s\"\n", name);
412 exit(1);
413 }
414 return addr.data[0];
415}
416
4094db72 417void incomplete_command(void)
aba5acdf
SH
418{
419 fprintf(stderr, "Command line is not complete. Try option \"help\"\n");
420 exit(-1);
421}
422
c7699875 423void missarg(const char *key)
424{
425 fprintf(stderr, "Error: argument \"%s\" is required\n", key);
426 exit(-1);
427}
428
4094db72 429void invarg(const char *msg, const char *arg)
aba5acdf
SH
430{
431 fprintf(stderr, "Error: argument \"%s\" is wrong: %s\n", arg, msg);
432 exit(-1);
433}
434
4094db72 435void duparg(const char *key, const char *arg)
aba5acdf
SH
436{
437 fprintf(stderr, "Error: duplicate \"%s\": \"%s\" is the second value.\n", key, arg);
438 exit(-1);
439}
440
4094db72 441void duparg2(const char *key, const char *arg)
aba5acdf
SH
442{
443 fprintf(stderr, "Error: either \"%s\" is duplicate, or \"%s\" is a garbage.\n", key, arg);
444 exit(-1);
445}
446
4094db72 447int matches(const char *cmd, const char *pattern)
aba5acdf
SH
448{
449 int len = strlen(cmd);
450 if (len > strlen(pattern))
451 return -1;
452 return memcmp(pattern, cmd, len);
453}
454
4094db72 455int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
aba5acdf 456{
9626dfd5
SH
457 const __u32 *a1 = a->data;
458 const __u32 *a2 = b->data;
aba5acdf
SH
459 int words = bits >> 0x05;
460
461 bits &= 0x1f;
462
463 if (words)
464 if (memcmp(a1, a2, words << 2))
465 return -1;
466
467 if (bits) {
468 __u32 w1, w2;
469 __u32 mask;
470
471 w1 = a1[words];
472 w2 = a2[words];
473
474 mask = htonl((0xffffffff) << (0x20 - bits));
475
476 if ((w1 ^ w2) & mask)
477 return 1;
478 }
479
480 return 0;
481}
482
483int __iproute2_hz_internal;
484
485int __get_hz(void)
486{
487 char name[1024];
488 int hz = 0;
489 FILE *fp;
490
491 if (getenv("HZ"))
492 return atoi(getenv("HZ")) ? : HZ;
493
494 if (getenv("PROC_NET_PSCHED")) {
495 snprintf(name, sizeof(name)-1, "%s", getenv("PROC_NET_PSCHED"));
c7699875 496 } else if (getenv("PROC_ROOT")) {
aba5acdf
SH
497 snprintf(name, sizeof(name)-1, "%s/net/psched", getenv("PROC_ROOT"));
498 } else {
499 strcpy(name, "/proc/net/psched");
500 }
501 fp = fopen(name, "r");
502
503 if (fp) {
504 unsigned nom, denom;
505 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
506 if (nom == 1000000)
507 hz = denom;
508 fclose(fp);
509 }
510 if (hz)
511 return hz;
512 return HZ;
513}
514
5e8bc631 515int __iproute2_user_hz_internal;
516
517int __get_user_hz(void)
518{
519 return sysconf(_SC_CLK_TCK);
520}
521
4094db72 522const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflen)
aba5acdf
SH
523{
524 switch (af) {
525 case AF_INET:
526 case AF_INET6:
527 return inet_ntop(af, addr, buf, buflen);
528 case AF_IPX:
529 return ipx_ntop(af, addr, buf, buflen);
530 case AF_DECnet:
531 {
532 struct dn_naddr dna = { 2, { 0, 0, }};
533 memcpy(dna.a_addr, addr, 2);
534 return dnet_ntop(af, &dna, buf, buflen);
535 }
536 default:
537 return "???";
538 }
539}
540
541#ifdef RESOLVE_HOSTNAMES
542struct namerec
543{
544 struct namerec *next;
7dec1bf8 545 const char *name;
aba5acdf 546 inet_prefix addr;
aba5acdf
SH
547};
548
7dec1bf8
SH
549#define NHASH 257
550static struct namerec *nht[NHASH];
aba5acdf 551
7dec1bf8 552static const char *resolve_address(const void *addr, int len, int af)
aba5acdf
SH
553{
554 struct namerec *n;
555 struct hostent *h_ent;
556 unsigned hash;
557 static int notfirst;
558
559
560 if (af == AF_INET6 && ((__u32*)addr)[0] == 0 &&
561 ((__u32*)addr)[1] == 0 && ((__u32*)addr)[2] == htonl(0xffff)) {
562 af = AF_INET;
563 addr += 12;
564 len = 4;
565 }
566
7dec1bf8 567 hash = *(__u32 *)(addr + len - 4) % NHASH;
aba5acdf
SH
568
569 for (n = nht[hash]; n; n = n->next) {
570 if (n->addr.family == af &&
571 n->addr.bytelen == len &&
572 memcmp(n->addr.data, addr, len) == 0)
573 return n->name;
574 }
575 if ((n = malloc(sizeof(*n))) == NULL)
576 return NULL;
577 n->addr.family = af;
578 n->addr.bytelen = len;
579 n->name = NULL;
580 memcpy(n->addr.data, addr, len);
581 n->next = nht[hash];
582 nht[hash] = n;
583 if (++notfirst == 1)
584 sethostent(1);
585 fflush(stdout);
586
c7699875 587 if ((h_ent = gethostbyaddr(addr, len, af)) != NULL)
aba5acdf
SH
588 n->name = strdup(h_ent->h_name);
589
590 /* Even if we fail, "negative" entry is remembered. */
591 return n->name;
592}
593#endif
594
595
c7699875 596const char *format_host(int af, int len, const void *addr,
4094db72 597 char *buf, int buflen)
aba5acdf
SH
598{
599#ifdef RESOLVE_HOSTNAMES
600 if (resolve_hosts) {
7dec1bf8
SH
601 const char *n;
602
aba5acdf
SH
603 if (len <= 0) {
604 switch (af) {
605 case AF_INET:
606 len = 4;
607 break;
608 case AF_INET6:
609 len = 16;
610 break;
611 case AF_IPX:
612 len = 10;
613 break;
614#ifdef AF_DECnet
615 /* I see no reasons why gethostbyname
616 may not work for DECnet */
617 case AF_DECnet:
618 len = 2;
619 break;
620#endif
621 default: ;
622 }
623 }
624 if (len > 0 &&
625 (n = resolve_address(addr, len, af)) != NULL)
626 return n;
627 }
628#endif
629 return rt_addr_n2a(af, len, addr, buf, buflen);
630}
631
632
f332d169 633char *hexstring_n2a(const __u8 *str, int len, char *buf, int blen)
aba5acdf 634{
f332d169 635 char *ptr = buf;
aba5acdf
SH
636 int i;
637
638 for (i=0; i<len; i++) {
639 if (blen < 3)
640 break;
641 sprintf(ptr, "%02x", str[i]);
642 ptr += 2;
643 blen -= 2;
644 if (i != len-1 && blen > 1) {
645 *ptr++ = ':';
646 blen--;
647 }
648 }
649 return buf;
650}
651
f332d169 652__u8* hexstring_a2n(const char *str, __u8 *buf, int blen)
aba5acdf
SH
653{
654 int cnt = 0;
655
656 for (;;) {
657 unsigned acc;
658 char ch;
659
660 acc = 0;
661
662 while ((ch = *str) != ':' && ch != 0) {
663 if (ch >= '0' && ch <= '9')
664 ch -= '0';
665 else if (ch >= 'a' && ch <= 'f')
666 ch -= 'a'-10;
667 else if (ch >= 'A' && ch <= 'F')
668 ch -= 'A'-10;
669 else
670 return NULL;
671 acc = (acc<<4) + ch;
672 str++;
673 }
674
675 if (acc > 255)
676 return NULL;
677 if (cnt < blen) {
678 buf[cnt] = acc;
679 cnt++;
680 }
681 if (ch == 0)
682 break;
683 ++str;
684 }
685 if (cnt < blen)
686 memset(buf+cnt, 0, blen-cnt);
687 return buf;
688}
90f93024
SH
689
690int print_timestamp(FILE *fp)
691{
692 struct timeval tv;
693 char *tstr;
694
695 memset(&tv, 0, sizeof(tv));
696 gettimeofday(&tv, NULL);
697
698 tstr = asctime(localtime(&tv.tv_sec));
699 tstr[strlen(tstr)-1] = 0;
700 fprintf(fp, "Timestamp: %s %lu usec\n", tstr, tv.tv_usec);
701 return 0;
702}
351efcde
SH
703
704int cmdlineno;
705
706/* Like glibc getline but handle continuation lines and comments */
d21e8835 707ssize_t getcmdline(char **linep, size_t *lenp, FILE *in)
351efcde 708{
d21e8835 709 ssize_t cc;
351efcde 710 char *cp;
ae665a52 711
351efcde
SH
712 if ((cc = getline(linep, lenp, in)) < 0)
713 return cc; /* eof or error */
714 ++cmdlineno;
715
716 cp = strchr(*linep, '#');
ae665a52 717 if (cp)
351efcde 718 *cp = '\0';
ae665a52 719
351efcde
SH
720 while ((cp = strstr(*linep, "\\\n")) != NULL) {
721 char *line1 = NULL;
722 size_t len1 = 0;
21a85d3b 723 ssize_t cc1;
351efcde
SH
724
725 if ((cc1 = getline(&line1, &len1, in)) < 0) {
726 fprintf(stderr, "Missing continuation line\n");
727 return cc1;
728 }
729
730 ++cmdlineno;
731 *cp = 0;
732
733 cp = strchr(line1, '#');
ae665a52 734 if (cp)
351efcde
SH
735 *cp = '\0';
736
d21e8835
AH
737 *lenp = strlen(*linep) + strlen(line1) + 1;
738 *linep = realloc(*linep, *lenp);
351efcde
SH
739 if (!*linep) {
740 fprintf(stderr, "Out of memory\n");
d21e8835 741 *lenp = 0;
351efcde
SH
742 return -1;
743 }
744 cc += cc1 - 2;
745 strcat(*linep, line1);
746 free(line1);
747 }
748 return cc;
749}
750
751/* split command line into argument vector */
752int makeargs(char *line, char *argv[], int maxargs)
753{
754 static const char ws[] = " \t\r\n";
755 char *cp;
756 int argc = 0;
757
758 for (cp = strtok(line, ws); cp; cp = strtok(NULL, ws)) {
759 if (argc >= (maxargs - 1)) {
760 fprintf(stderr, "Too many arguments to command\n");
761 exit(1);
762 }
763 argv[argc++] = cp;
764 }
765 argv[argc] = NULL;
766
767 return argc;
768}