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