]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - lib/utils.c
Merge branch 'master' into net-2.6.25
[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  * Changes:
13  *
14  * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <syslog.h>
21 #include <fcntl.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <string.h>
25 #include <netdb.h>
26 #include <arpa/inet.h>
27 #include <resolv.h>
28 #include <asm/types.h>
29 #include <linux/pkt_sched.h>
30 #include <time.h>
31 #include <sys/time.h>
32
33
34 #include "utils.h"
35
36 int get_integer(int *val, const char *arg, int base)
37 {
38         long res;
39         char *ptr;
40
41         if (!arg || !*arg)
42                 return -1;
43         res = strtol(arg, &ptr, base);
44         if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
45                 return -1;
46         *val = res;
47         return 0;
48 }
49
50 /* a valid netmask must be 2^n - 1 */
51 static int is_valid_netmask(const inet_prefix *addr)
52 {
53         uint32_t host;
54
55         if (addr->family != AF_INET)
56                 return 0;
57
58         host = ~ntohl(addr->data[0]);
59
60         return (host & (host + 1)) == 0;
61 }
62
63 static unsigned cidr(const inet_prefix *addr)
64 {
65         unsigned bits = 0;
66         u_int32_t mask;
67
68         for (mask = ntohl(addr->data[0]); mask; mask <<= 1)
69                 ++bits;
70
71         return bits;
72 }
73
74 static int get_netmask(unsigned *val, const char *arg, int base)
75 {
76         inet_prefix addr;
77
78         if (!get_unsigned(val, arg, base))
79                 return 0;
80
81         /* try coverting dotted quad to CIDR */
82         if (!get_addr_1(&addr, arg, AF_INET)) {
83                 if (is_valid_netmask(&addr))
84                         return 0;
85
86                 *val = cidr(&addr);
87         }
88
89         return -1;
90 }
91
92 int get_unsigned(unsigned *val, const char *arg, int base)
93 {
94         unsigned long res;
95         char *ptr;
96
97         if (!arg || !*arg)
98                 return -1;
99         res = strtoul(arg, &ptr, base);
100         if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
101                 return -1;
102         *val = res;
103         return 0;
104 }
105
106 /*
107  * get_jiffies is "translated" from a similar routine "get_time" in
108  * tc_util.c.  we don't use the exact same routine because tc passes
109  * microseconds to the kernel and the callers of get_jiffies want 
110  * to pass jiffies, and have a different assumption for the units of
111  * a "raw" number.
112  */
113
114 int get_jiffies(unsigned *jiffies, const char *arg, int base, int *raw)
115 {
116         double t;
117         unsigned long res;
118         char *p;
119
120         if (strchr(arg,'.') != NULL) {
121                 t = strtod(arg,&p);
122                 if (t < 0.0)
123                         return -1;
124         }
125         else {
126                 res = strtoul(arg,&p,base);
127                 if (res > UINT_MAX)
128                         return -1;
129                 t = (double)res;
130         }
131         if (p == arg)
132                 return -1;
133
134         if (__iproute2_hz_internal == 0)
135                 __iproute2_hz_internal = __get_hz();
136         
137         *raw = 1;
138
139         if (*p) {
140                 *raw = 0;
141                 if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
142                     strcasecmp(p, "secs")==0)
143                         t *= __iproute2_hz_internal;
144                 else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
145                          strcasecmp(p, "msecs") == 0)
146                         t *= __iproute2_hz_internal/1000.0;
147                 else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
148                          strcasecmp(p, "usecs") == 0)
149                         t *= __iproute2_hz_internal/1000000.0;
150                 else if (strcasecmp(p, "ns") == 0 || strcasecmp(p, "nsec")==0 ||
151                          strcasecmp(p, "nsecs") == 0)
152                         t *= __iproute2_hz_internal/1000000000.0;
153                 else if (strcasecmp(p, "j") == 0 || strcasecmp(p, "hz") == 0 ||
154                          strcasecmp(p,"jiffies") == 0)
155                         t *= 1.0; /* allow suffix, do nothing */
156                 else
157                         return -1;
158         }
159
160         /* emulate ceil() without having to bring-in -lm and always be >= 1 */
161
162         *jiffies = t;
163         if (*jiffies < t)
164                 *jiffies += 1;
165         
166         return 0;
167
168 }
169
170 int get_u64(__u64 *val, const char *arg, int base)
171 {
172         unsigned long long res;
173         char *ptr;
174
175         if (!arg || !*arg)
176                 return -1;
177         res = strtoull(arg, &ptr, base);
178         if (!ptr || ptr == arg || *ptr || res == 0xFFFFFFFFULL)
179                 return -1;
180         *val = res;
181         return 0;
182 }
183
184 int get_u32(__u32 *val, const char *arg, int base)
185 {
186         unsigned long res;
187         char *ptr;
188
189         if (!arg || !*arg)
190                 return -1;
191         res = strtoul(arg, &ptr, base);
192         if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
193                 return -1;
194         *val = res;
195         return 0;
196 }
197
198 int get_u16(__u16 *val, const char *arg, int base)
199 {
200         unsigned long res;
201         char *ptr;
202
203         if (!arg || !*arg)
204                 return -1;
205         res = strtoul(arg, &ptr, base);
206         if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
207                 return -1;
208         *val = res;
209         return 0;
210 }
211
212 int get_u8(__u8 *val, const char *arg, int base)
213 {
214         unsigned long res;
215         char *ptr;
216
217         if (!arg || !*arg)
218                 return -1;
219         res = strtoul(arg, &ptr, base);
220         if (!ptr || ptr == arg || *ptr || res > 0xFF)
221                 return -1;
222         *val = res;
223         return 0;
224 }
225
226 int get_s16(__s16 *val, const char *arg, int base)
227 {
228         long res;
229         char *ptr;
230
231         if (!arg || !*arg)
232                 return -1;
233         res = strtol(arg, &ptr, base);
234         if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
235                 return -1;
236         *val = res;
237         return 0;
238 }
239
240 int get_s8(__s8 *val, const char *arg, int base)
241 {
242         long res;
243         char *ptr;
244
245         if (!arg || !*arg)
246                 return -1;
247         res = strtol(arg, &ptr, base);
248         if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
249                 return -1;
250         *val = res;
251         return 0;
252 }
253
254 int get_addr_1(inet_prefix *addr, const char *name, int family)
255 {
256         const char *cp;
257         unsigned char *ap = (unsigned char*)addr->data;
258         int i;
259
260         memset(addr, 0, sizeof(*addr));
261
262         if (strcmp(name, "default") == 0 ||
263             strcmp(name, "all") == 0 ||
264             strcmp(name, "any") == 0) {
265                 if (family == AF_DECnet)
266                         return -1;
267                 addr->family = family;
268                 addr->bytelen = (family == AF_INET6 ? 16 : 4);
269                 addr->bitlen = -1;
270                 return 0;
271         }
272
273         if (strchr(name, ':')) {
274                 addr->family = AF_INET6;
275                 if (family != AF_UNSPEC && family != AF_INET6)
276                         return -1;
277                 if (inet_pton(AF_INET6, name, addr->data) <= 0)
278                         return -1;
279                 addr->bytelen = 16;
280                 addr->bitlen = -1;
281                 return 0;
282         }
283
284         if (family == AF_DECnet) {
285                 struct dn_naddr dna;
286                 addr->family = AF_DECnet;
287                 if (dnet_pton(AF_DECnet, name, &dna) <= 0)
288                         return -1;
289                 memcpy(addr->data, dna.a_addr, 2);
290                 addr->bytelen = 2;
291                 addr->bitlen = -1;
292                 return 0;
293         }
294
295         addr->family = AF_INET;
296         if (family != AF_UNSPEC && family != AF_INET)
297                 return -1;
298         addr->bytelen = 4;
299         addr->bitlen = -1;
300         for (cp=name, i=0; *cp; cp++) {
301                 if (*cp <= '9' && *cp >= '0') {
302                         ap[i] = 10*ap[i] + (*cp-'0');
303                         continue;
304                 }
305                 if (*cp == '.' && ++i <= 3)
306                         continue;
307                 return -1;
308         }
309         return 0;
310 }
311
312 int get_prefix_1(inet_prefix *dst, char *arg, int family)
313 {
314         int err;
315         unsigned plen;
316         char *slash;
317
318         memset(dst, 0, sizeof(*dst));
319
320         if (strcmp(arg, "default") == 0 ||
321             strcmp(arg, "any") == 0 ||
322             strcmp(arg, "all") == 0) {
323                 if (family == AF_DECnet)
324                         return -1;
325                 dst->family = family;
326                 dst->bytelen = 0;
327                 dst->bitlen = 0;
328                 return 0;
329         }
330
331         slash = strchr(arg, '/');
332         if (slash)
333                 *slash = 0;
334
335         err = get_addr_1(dst, arg, family);
336         if (err == 0) {
337                 switch(dst->family) {
338                         case AF_INET6:
339                                 dst->bitlen = 128;
340                                 break;
341                         case AF_DECnet:
342                                 dst->bitlen = 16;
343                                 break;
344                         default:
345                         case AF_INET:
346                                 dst->bitlen = 32;
347                 }
348                 if (slash) {
349                         if (get_netmask(&plen, slash+1, 0)
350                                         || plen > dst->bitlen) {
351                                 err = -1;
352                                 goto done;
353                         }
354                         dst->flags |= PREFIXLEN_SPECIFIED;
355                         dst->bitlen = plen;
356                 }
357         }
358 done:
359         if (slash)
360                 *slash = '/';
361         return err;
362 }
363
364 int get_addr(inet_prefix *dst, const char *arg, int family)
365 {
366         if (family == AF_PACKET) {
367                 fprintf(stderr, "Error: \"%s\" may be inet address, but it is not allowed in this context.\n", arg);
368                 exit(1);
369         }
370         if (get_addr_1(dst, arg, family)) {
371                 fprintf(stderr, "Error: an inet address is expected rather than \"%s\".\n", arg);
372                 exit(1);
373         }
374         return 0;
375 }
376
377 int get_prefix(inet_prefix *dst, char *arg, int family)
378 {
379         if (family == AF_PACKET) {
380                 fprintf(stderr, "Error: \"%s\" may be inet prefix, but it is not allowed in this context.\n", arg);
381                 exit(1);
382         }
383         if (get_prefix_1(dst, arg, family)) {
384                 fprintf(stderr, "Error: an inet prefix is expected rather than \"%s\".\n", arg);
385                 exit(1);
386         }
387         return 0;
388 }
389
390 __u32 get_addr32(const char *name)
391 {
392         inet_prefix addr;
393         if (get_addr_1(&addr, name, AF_INET)) {
394                 fprintf(stderr, "Error: an IP address is expected rather than \"%s\"\n", name);
395                 exit(1);
396         }
397         return addr.data[0];
398 }
399
400 void incomplete_command(void)
401 {
402         fprintf(stderr, "Command line is not complete. Try option \"help\"\n");
403         exit(-1);
404 }
405
406 void missarg(const char *key)
407 {
408         fprintf(stderr, "Error: argument \"%s\" is required\n", key);
409         exit(-1);
410 }
411
412 void invarg(const char *msg, const char *arg)
413 {
414         fprintf(stderr, "Error: argument \"%s\" is wrong: %s\n", arg, msg);
415         exit(-1);
416 }
417
418 void duparg(const char *key, const char *arg)
419 {
420         fprintf(stderr, "Error: duplicate \"%s\": \"%s\" is the second value.\n", key, arg);
421         exit(-1);
422 }
423
424 void duparg2(const char *key, const char *arg)
425 {
426         fprintf(stderr, "Error: either \"%s\" is duplicate, or \"%s\" is a garbage.\n", key, arg);
427         exit(-1);
428 }
429
430 int matches(const char *cmd, const char *pattern)
431 {
432         int len = strlen(cmd);
433         if (len > strlen(pattern))
434                 return -1;
435         return memcmp(pattern, cmd, len);
436 }
437
438 int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
439 {
440         const __u32 *a1 = a->data;
441         const __u32 *a2 = b->data;
442         int words = bits >> 0x05;
443
444         bits &= 0x1f;
445
446         if (words)
447                 if (memcmp(a1, a2, words << 2))
448                         return -1;
449
450         if (bits) {
451                 __u32 w1, w2;
452                 __u32 mask;
453
454                 w1 = a1[words];
455                 w2 = a2[words];
456
457                 mask = htonl((0xffffffff) << (0x20 - bits));
458
459                 if ((w1 ^ w2) & mask)
460                         return 1;
461         }
462
463         return 0;
464 }
465
466 int __iproute2_hz_internal;
467
468 int __get_hz(void)
469 {
470         char name[1024];
471         int hz = 0;
472         FILE *fp;
473
474         if (getenv("HZ"))
475                 return atoi(getenv("HZ")) ? : HZ;
476
477         if (getenv("PROC_NET_PSCHED")) {
478                 snprintf(name, sizeof(name)-1, "%s", getenv("PROC_NET_PSCHED"));
479         } else if (getenv("PROC_ROOT")) {
480                 snprintf(name, sizeof(name)-1, "%s/net/psched", getenv("PROC_ROOT"));
481         } else {
482                 strcpy(name, "/proc/net/psched");
483         }
484         fp = fopen(name, "r");
485
486         if (fp) {
487                 unsigned nom, denom;
488                 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
489                         if (nom == 1000000)
490                                 hz = denom;
491                 fclose(fp);
492         }
493         if (hz)
494                 return hz;
495         return HZ;
496 }
497
498 int __iproute2_user_hz_internal;
499
500 int __get_user_hz(void)
501 {
502         return sysconf(_SC_CLK_TCK);
503 }
504
505 const char *rt_addr_n2a(int af, int len, const void *addr, char *buf, int buflen)
506 {
507         switch (af) {
508         case AF_INET:
509         case AF_INET6:
510                 return inet_ntop(af, addr, buf, buflen);
511         case AF_IPX:
512                 return ipx_ntop(af, addr, buf, buflen);
513         case AF_DECnet:
514         {
515                 struct dn_naddr dna = { 2, { 0, 0, }};
516                 memcpy(dna.a_addr, addr, 2);
517                 return dnet_ntop(af, &dna, buf, buflen);
518         }
519         default:
520                 return "???";
521         }
522 }
523
524 #ifdef RESOLVE_HOSTNAMES
525 struct namerec
526 {
527         struct namerec *next;
528         inet_prefix addr;
529         char        *name;
530 };
531
532 static struct namerec *nht[256];
533
534 char *resolve_address(const char *addr, int len, int af)
535 {
536         struct namerec *n;
537         struct hostent *h_ent;
538         unsigned hash;
539         static int notfirst;
540
541
542         if (af == AF_INET6 && ((__u32*)addr)[0] == 0 &&
543             ((__u32*)addr)[1] == 0 && ((__u32*)addr)[2] == htonl(0xffff)) {
544                 af = AF_INET;
545                 addr += 12;
546                 len = 4;
547         }
548
549         hash = addr[len-1] ^ addr[len-2] ^ addr[len-3] ^ addr[len-4];
550
551         for (n = nht[hash]; n; n = n->next) {
552                 if (n->addr.family == af &&
553                     n->addr.bytelen == len &&
554                     memcmp(n->addr.data, addr, len) == 0)
555                         return n->name;
556         }
557         if ((n = malloc(sizeof(*n))) == NULL)
558                 return NULL;
559         n->addr.family = af;
560         n->addr.bytelen = len;
561         n->name = NULL;
562         memcpy(n->addr.data, addr, len);
563         n->next = nht[hash];
564         nht[hash] = n;
565         if (++notfirst == 1)
566                 sethostent(1);
567         fflush(stdout);
568
569         if ((h_ent = gethostbyaddr(addr, len, af)) != NULL)
570                 n->name = strdup(h_ent->h_name);
571
572         /* Even if we fail, "negative" entry is remembered. */
573         return n->name;
574 }
575 #endif
576
577
578 const char *format_host(int af, int len, const void *addr,
579                         char *buf, int buflen)
580 {
581 #ifdef RESOLVE_HOSTNAMES
582         if (resolve_hosts) {
583                 char *n;
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 }