source: MondoRescue/branches/3.3/mindi-busybox/networking/libiproute/utils.c@ 3803

Last change on this file since 3803 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 6.3 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
4 *
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
6 *
7 * Changes:
8 *
9 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
10 */
11
12#include "libbb.h"
13#include "utils.h"
14#include "inet_common.h"
15
16unsigned get_hz(void)
17{
18 static unsigned hz_internal;
19 FILE *fp;
20
21 if (hz_internal)
22 return hz_internal;
23
24 fp = fopen_for_read("/proc/net/psched");
25 if (fp) {
26 unsigned nom, denom;
27
28 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
29 if (nom == 1000000)
30 hz_internal = denom;
31 fclose(fp);
32 }
33 if (!hz_internal)
34 hz_internal = bb_clk_tck();
35 return hz_internal;
36}
37
38unsigned get_unsigned(char *arg, const char *errmsg)
39{
40 unsigned long res;
41 char *ptr;
42
43 if (*arg) {
44 res = strtoul(arg, &ptr, 0);
45//FIXME: "" will be accepted too, is it correct?!
46 if (!*ptr && res <= UINT_MAX) {
47 return res;
48 }
49 }
50 invarg_1_to_2(arg, errmsg); /* does not return */
51}
52
53uint32_t get_u32(char *arg, const char *errmsg)
54{
55 unsigned long res;
56 char *ptr;
57
58 if (*arg) {
59 res = strtoul(arg, &ptr, 0);
60//FIXME: "" will be accepted too, is it correct?!
61 if (!*ptr && res <= 0xFFFFFFFFUL) {
62 return res;
63 }
64 }
65 invarg_1_to_2(arg, errmsg); /* does not return */
66}
67
68uint16_t get_u16(char *arg, const char *errmsg)
69{
70 unsigned long res;
71 char *ptr;
72
73 if (*arg) {
74 res = strtoul(arg, &ptr, 0);
75//FIXME: "" will be accepted too, is it correct?!
76 if (!*ptr && res <= 0xFFFF) {
77 return res;
78 }
79 }
80 invarg_1_to_2(arg, errmsg); /* does not return */
81}
82
83int get_addr_1(inet_prefix *addr, char *name, int family)
84{
85 memset(addr, 0, sizeof(*addr));
86
87 if (strcmp(name, "default") == 0
88 || strcmp(name, "all") == 0
89 || strcmp(name, "any") == 0
90 ) {
91 addr->family = family;
92 addr->bytelen = (family == AF_INET6 ? 16 : 4);
93 addr->bitlen = -1;
94 return 0;
95 }
96
97 if (strchr(name, ':')) {
98 addr->family = AF_INET6;
99 if (family != AF_UNSPEC && family != AF_INET6)
100 return -1;
101 if (inet_pton(AF_INET6, name, addr->data) <= 0)
102 return -1;
103 addr->bytelen = 16;
104 addr->bitlen = -1;
105 return 0;
106 }
107
108 if (family != AF_UNSPEC && family != AF_INET)
109 return -1;
110
111 /* Try to parse it as IPv4 */
112 addr->family = AF_INET;
113#if 0 /* Doesn't handle e.g. "10.10", for example, "ip r l root 10.10/16" */
114 if (inet_pton(AF_INET, name, addr->data) <= 0)
115 return -1;
116#else
117 {
118 unsigned i = 0;
119 unsigned n = 0;
120 const char *cp = name - 1;
121 while (*++cp) {
122 if ((unsigned char)(*cp - '0') <= 9) {
123 n = 10 * n + (unsigned char)(*cp - '0');
124 if (n >= 256)
125 return -1;
126 ((uint8_t*)addr->data)[i] = n;
127 continue;
128 }
129 if (*cp == '.' && ++i <= 3) {
130 n = 0;
131 continue;
132 }
133 return -1;
134 }
135 }
136#endif
137 addr->bytelen = 4;
138 addr->bitlen = -1;
139
140 return 0;
141}
142
143static void get_prefix_1(inet_prefix *dst, char *arg, int family)
144{
145 char *slash;
146
147 memset(dst, 0, sizeof(*dst));
148
149 if (strcmp(arg, "default") == 0
150 || strcmp(arg, "all") == 0
151 || strcmp(arg, "any") == 0
152 ) {
153 dst->family = family;
154 /*dst->bytelen = 0; - done by memset */
155 /*dst->bitlen = 0;*/
156 return;
157 }
158
159 slash = strchr(arg, '/');
160 if (slash)
161 *slash = '\0';
162
163 if (get_addr_1(dst, arg, family) == 0) {
164 dst->bitlen = (dst->family == AF_INET6) ? 128 : 32;
165 if (slash) {
166 unsigned plen;
167 inet_prefix netmask_pfx;
168
169 netmask_pfx.family = AF_UNSPEC;
170 plen = bb_strtou(slash + 1, NULL, 0);
171 if ((errno || plen > dst->bitlen)
172 && get_addr_1(&netmask_pfx, slash + 1, family) != 0
173 ) {
174 goto bad;
175 }
176 if (netmask_pfx.family == AF_INET) {
177 /* fill in prefix length of dotted quad */
178 uint32_t mask = ntohl(netmask_pfx.data[0]);
179 uint32_t host = ~mask;
180
181 /* a valid netmask must be 2^n - 1 */
182 if (host & (host + 1))
183 goto bad;
184
185 for (plen = 0; mask; mask <<= 1)
186 ++plen;
187 if (plen > dst->bitlen)
188 goto bad;
189 /* dst->flags |= PREFIXLEN_SPECIFIED; */
190 }
191 dst->bitlen = plen;
192 }
193 }
194
195 if (slash)
196 *slash = '/';
197 return;
198 bad:
199 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg);
200}
201
202int get_addr(inet_prefix *dst, char *arg, int family)
203{
204 if (family == AF_PACKET) {
205 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "address");
206 }
207 if (get_addr_1(dst, arg, family)) {
208 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "address", arg);
209 }
210 return 0;
211}
212
213void get_prefix(inet_prefix *dst, char *arg, int family)
214{
215 if (family == AF_PACKET) {
216 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg, "prefix");
217 }
218 get_prefix_1(dst, arg, family);
219}
220
221uint32_t get_addr32(char *name)
222{
223 inet_prefix addr;
224
225 if (get_addr_1(&addr, name, AF_INET)) {
226 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "IP", "address", name);
227 }
228 return addr.data[0];
229}
230
231void incomplete_command(void)
232{
233 bb_error_msg_and_die("command line is not complete, try \"help\"");
234}
235
236void invarg_1_to_2(const char *arg, const char *opt)
237{
238 bb_error_msg_and_die(bb_msg_invalid_arg_to, arg, opt);
239}
240
241void duparg(const char *key, const char *arg)
242{
243 bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key, arg);
244}
245
246void duparg2(const char *key, const char *arg)
247{
248 bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key, arg);
249}
250
251int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits)
252{
253 const uint32_t *a1 = a->data;
254 const uint32_t *a2 = b->data;
255 int words = bits >> 5;
256
257 bits &= 0x1f;
258
259 if (words)
260 if (memcmp(a1, a2, words << 2))
261 return -1;
262
263 if (bits) {
264 uint32_t w1, w2;
265 uint32_t mask;
266
267 w1 = a1[words];
268 w2 = a2[words];
269
270 mask = htonl((0xffffffff) << (0x20 - bits));
271
272 if ((w1 ^ w2) & mask)
273 return 1;
274 }
275
276 return 0;
277}
278
279const char *rt_addr_n2a(int af, void *addr)
280{
281 switch (af) {
282 case AF_INET:
283 case AF_INET6:
284 return inet_ntop(af, addr,
285 auto_string(xzalloc(INET6_ADDRSTRLEN)), INET6_ADDRSTRLEN
286 );
287 default:
288 return "???";
289 }
290}
291
292#ifdef RESOLVE_HOSTNAMES
293const char *format_host(int af, int len, void *addr)
294{
295 if (resolve_hosts) {
296 struct hostent *h_ent;
297
298 if (len <= 0) {
299 switch (af) {
300 case AF_INET:
301 len = 4;
302 break;
303 case AF_INET6:
304 len = 16;
305 break;
306 default:;
307 }
308 }
309 if (len > 0) {
310 h_ent = gethostbyaddr(addr, len, af);
311 if (h_ent != NULL) {
312 return auto_string(xstrdup(h_ent->h_name));
313 }
314 }
315 }
316 return rt_addr_n2a(af, addr);
317}
318#endif
Note: See TracBrowser for help on using the repository browser.