network "default" --> bb_INET_default. Reduce 2 exported from find applet
[oweals/busybox.git] / networking / libiproute / 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 <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <arpa/inet.h>
21
22 #include "utils.h"
23 #include "libbb.h"
24 #include "inet_common.h"
25
26 int get_integer(int *val, char *arg, int base)
27 {
28         long res;
29         char *ptr;
30
31         if (!arg || !*arg)
32                 return -1;
33         res = strtol(arg, &ptr, base);
34         if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
35                 return -1;
36         *val = res;
37         return 0;
38 }
39
40 int get_unsigned(unsigned *val, char *arg, int base)
41 {
42         unsigned long res;
43         char *ptr;
44
45         if (!arg || !*arg)
46                 return -1;
47         res = strtoul(arg, &ptr, base);
48         if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
49                 return -1;
50         *val = res;
51         return 0;
52 }
53
54 int get_u32(__u32 * val, char *arg, int base)
55 {
56         unsigned long res;
57         char *ptr;
58
59         if (!arg || !*arg)
60                 return -1;
61         res = strtoul(arg, &ptr, base);
62         if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
63                 return -1;
64         *val = res;
65         return 0;
66 }
67
68 int get_u16(__u16 * val, char *arg, int base)
69 {
70         unsigned long res;
71         char *ptr;
72
73         if (!arg || !*arg)
74                 return -1;
75         res = strtoul(arg, &ptr, base);
76         if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
77                 return -1;
78         *val = res;
79         return 0;
80 }
81
82 int get_u8(__u8 * val, char *arg, int base)
83 {
84         unsigned long res;
85         char *ptr;
86
87         if (!arg || !*arg)
88                 return -1;
89         res = strtoul(arg, &ptr, base);
90         if (!ptr || ptr == arg || *ptr || res > 0xFF)
91                 return -1;
92         *val = res;
93         return 0;
94 }
95
96 int get_s16(__s16 * val, char *arg, int base)
97 {
98         long res;
99         char *ptr;
100
101         if (!arg || !*arg)
102                 return -1;
103         res = strtol(arg, &ptr, base);
104         if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
105                 return -1;
106         *val = res;
107         return 0;
108 }
109
110 int get_s8(__s8 * val, char *arg, int base)
111 {
112         long res;
113         char *ptr;
114
115         if (!arg || !*arg)
116                 return -1;
117         res = strtol(arg, &ptr, base);
118         if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
119                 return -1;
120         *val = res;
121         return 0;
122 }
123
124 int get_addr_1(inet_prefix * addr, char *name, int family)
125 {
126         char *cp;
127         unsigned char *ap = (unsigned char *) addr->data;
128         int i;
129
130         memset(addr, 0, sizeof(*addr));
131
132         if (strcmp(name, bb_INET_default) == 0 ||
133                 strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
134                 addr->family = family;
135                 addr->bytelen = (family == AF_INET6 ? 16 : 4);
136                 addr->bitlen = -1;
137                 return 0;
138         }
139
140         if (strchr(name, ':')) {
141                 addr->family = AF_INET6;
142                 if (family != AF_UNSPEC && family != AF_INET6)
143                         return -1;
144                 if (inet_pton(AF_INET6, name, addr->data) <= 0)
145                         return -1;
146                 addr->bytelen = 16;
147                 addr->bitlen = -1;
148                 return 0;
149         }
150
151         addr->family = AF_INET;
152         if (family != AF_UNSPEC && family != AF_INET)
153                 return -1;
154         addr->bytelen = 4;
155         addr->bitlen = -1;
156         for (cp = name, i = 0; *cp; cp++) {
157                 if (*cp <= '9' && *cp >= '0') {
158                         ap[i] = 10 * ap[i] + (*cp - '0');
159                         continue;
160                 }
161                 if (*cp == '.' && ++i <= 3)
162                         continue;
163                 return -1;
164         }
165         return 0;
166 }
167
168 int get_prefix_1(inet_prefix * dst, char *arg, int family)
169 {
170         int err;
171         unsigned plen;
172         char *slash;
173
174         memset(dst, 0, sizeof(*dst));
175
176         if (strcmp(arg, bb_INET_default) == 0 || strcmp(arg, "any") == 0) {
177                 dst->family = family;
178                 dst->bytelen = 0;
179                 dst->bitlen = 0;
180                 return 0;
181         }
182
183         slash = strchr(arg, '/');
184         if (slash)
185                 *slash = 0;
186         err = get_addr_1(dst, arg, family);
187         if (err == 0) {
188                 switch (dst->family) {
189                 case AF_INET6:
190                         dst->bitlen = 128;
191                         break;
192                 default:
193                 case AF_INET:
194                         dst->bitlen = 32;
195                 }
196                 if (slash) {
197                         if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
198                                 err = -1;
199                                 goto done;
200                         }
201                         dst->bitlen = plen;
202                 }
203         }
204   done:
205         if (slash)
206                 *slash = '/';
207         return err;
208 }
209
210 int get_addr(inet_prefix * dst, char *arg, int family)
211 {
212         if (family == AF_PACKET) {
213                 bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
214         }
215         if (get_addr_1(dst, arg, family)) {
216                 bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
217         }
218         return 0;
219 }
220
221 int get_prefix(inet_prefix * dst, char *arg, int family)
222 {
223         if (family == AF_PACKET) {
224                 bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
225         }
226         if (get_prefix_1(dst, arg, family)) {
227                 bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
228         }
229         return 0;
230 }
231
232 __u32 get_addr32(char *name)
233 {
234         inet_prefix addr;
235
236         if (get_addr_1(&addr, name, AF_INET)) {
237                 bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
238         }
239         return addr.data[0];
240 }
241
242 void incomplete_command(void)
243 {
244         bb_error_msg("Command line is not complete. Try option \"help\"");
245         exit(-1);
246 }
247
248 void invarg(char *msg, char *arg)
249 {
250         bb_error_msg("argument \"%s\" is wrong: %s", arg, msg);
251         exit(-1);
252 }
253
254 void duparg(char *key, char *arg)
255 {
256         bb_error_msg("duplicate \"%s\": \"%s\" is the second value.", key, arg);
257         exit(-1);
258 }
259
260 void duparg2(char *key, char *arg)
261 {
262         bb_error_msg("either \"%s\" is duplicate, or \"%s\" is a garbage.", key, arg);
263         exit(-1);
264 }
265
266 int matches(char *cmd, char *pattern)
267 {
268         int len = strlen(cmd);
269
270         if (len > strlen(pattern)) {
271                 return -1;
272         }
273         return memcmp(pattern, cmd, len);
274 }
275
276 int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
277 {
278         __u32 *a1 = a->data;
279         __u32 *a2 = b->data;
280         int words = bits >> 0x05;
281
282         bits &= 0x1f;
283
284         if (words)
285                 if (memcmp(a1, a2, words << 2))
286                         return -1;
287
288         if (bits) {
289                 __u32 w1, w2;
290                 __u32 mask;
291
292                 w1 = a1[words];
293                 w2 = a2[words];
294
295                 mask = htonl((0xffffffff) << (0x20 - bits));
296
297                 if ((w1 ^ w2) & mask)
298                         return 1;
299         }
300
301         return 0;
302 }
303
304 int __iproute2_hz_internal;
305
306 int __get_hz(void)
307 {
308         int hz = 0;
309         FILE *fp = fopen("/proc/net/psched", "r");
310
311         if (fp) {
312                 unsigned nom, denom;
313
314                 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
315                         if (nom == 1000000)
316                                 hz = denom;
317                 fclose(fp);
318         }
319         if (hz)
320                 return hz;
321         return sysconf(_SC_CLK_TCK);
322 }
323
324 const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen)
325 {
326         switch (af) {
327         case AF_INET:
328         case AF_INET6:
329                 return inet_ntop(af, addr, buf, buflen);
330         default:
331                 return "???";
332         }
333 }
334
335
336 const char *format_host(int af, int len, void *addr, char *buf, int buflen)
337 {
338 #ifdef RESOLVE_HOSTNAMES
339         if (resolve_hosts) {
340                 struct hostent *h_ent;
341
342                 if (len <= 0) {
343                         switch (af) {
344                         case AF_INET:
345                                 len = 4;
346                                 break;
347                         case AF_INET6:
348                                 len = 16;
349                                 break;
350                         default:;
351                         }
352                 }
353                 if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
354                         snprintf(buf, buflen - 1, "%s", h_ent->h_name);
355                         return buf;
356                 }
357         }
358 #endif
359         return rt_addr_n2a(af, len, addr, buf, buflen);
360 }