source: trunk/mindi-busybox/networking/libiproute/utils.c @ 904

Last change on this file since 904 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

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