1 /* vi: set sw=4 ts=4: */
3 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
9 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
14 #include "inet_common.h"
16 unsigned get_unsigned(char *arg
, const char *errmsg
)
22 res
= strtoul(arg
, &ptr
, 0);
23 //FIXME: "" will be accepted too, is it correct?!
24 if (!*ptr
&& res
<= UINT_MAX
) {
28 invarg(arg
, errmsg
); /* does not return */
31 uint32_t get_u32(char *arg
, const char *errmsg
)
37 res
= strtoul(arg
, &ptr
, 0);
38 //FIXME: "" will be accepted too, is it correct?!
39 if (!*ptr
&& res
<= 0xFFFFFFFFUL
) {
43 invarg(arg
, errmsg
); /* does not return */
46 uint16_t get_u16(char *arg
, const char *errmsg
)
52 res
= strtoul(arg
, &ptr
, 0);
53 //FIXME: "" will be accepted too, is it correct?!
54 if (!*ptr
&& res
<= 0xFFFF) {
58 invarg(arg
, errmsg
); /* does not return */
61 int get_addr_1(inet_prefix
*addr
, char *name
, int family
)
63 memset(addr
, 0, sizeof(*addr
));
65 if (strcmp(name
, "default") == 0
66 || strcmp(name
, "all") == 0
67 || strcmp(name
, "any") == 0
69 addr
->family
= family
;
70 addr
->bytelen
= (family
== AF_INET6
? 16 : 4);
75 if (strchr(name
, ':')) {
76 addr
->family
= AF_INET6
;
77 if (family
!= AF_UNSPEC
&& family
!= AF_INET6
)
79 if (inet_pton(AF_INET6
, name
, addr
->data
) <= 0)
86 if (family
!= AF_UNSPEC
&& family
!= AF_INET
)
89 /* Try to parse it as IPv4 */
90 addr
->family
= AF_INET
;
91 #if 0 /* Doesn't handle e.g. "10.10", for example, "ip r l root 10.10/16" */
92 if (inet_pton(AF_INET
, name
, addr
->data
) <= 0)
98 const char *cp
= name
- 1;
100 if ((unsigned char)(*cp
- '0') <= 9) {
101 n
= 10 * n
+ (unsigned char)(*cp
- '0');
104 ((uint8_t*)addr
->data
)[i
] = n
;
107 if (*cp
== '.' && ++i
<= 3) {
121 static void get_prefix_1(inet_prefix
*dst
, char *arg
, int family
)
125 memset(dst
, 0, sizeof(*dst
));
127 if (strcmp(arg
, "default") == 0
128 || strcmp(arg
, "all") == 0
129 || strcmp(arg
, "any") == 0
131 dst
->family
= family
;
132 /*dst->bytelen = 0; - done by memset */
137 slash
= strchr(arg
, '/');
141 if (get_addr_1(dst
, arg
, family
) == 0) {
142 dst
->bitlen
= (dst
->family
== AF_INET6
) ? 128 : 32;
145 inet_prefix netmask_pfx
;
147 netmask_pfx
.family
= AF_UNSPEC
;
148 plen
= bb_strtou(slash
+ 1, NULL
, 0);
149 if ((errno
|| plen
> dst
->bitlen
)
150 && get_addr_1(&netmask_pfx
, slash
+ 1, family
) != 0
154 if (netmask_pfx
.family
== AF_INET
) {
155 /* fill in prefix length of dotted quad */
156 uint32_t mask
= ntohl(netmask_pfx
.data
[0]);
157 uint32_t host
= ~mask
;
159 /* a valid netmask must be 2^n - 1 */
160 if (host
& (host
+ 1))
163 for (plen
= 0; mask
; mask
<<= 1)
165 if (plen
> dst
->bitlen
)
167 /* dst->flags |= PREFIXLEN_SPECIFIED; */
177 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "prefix", arg
);
180 int get_addr(inet_prefix
*dst
, char *arg
, int family
)
182 if (family
== AF_PACKET
) {
183 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg
, "address");
185 if (get_addr_1(dst
, arg
, family
)) {
186 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "inet", "address", arg
);
191 void get_prefix(inet_prefix
*dst
, char *arg
, int family
)
193 if (family
== AF_PACKET
) {
194 bb_error_msg_and_die("\"%s\" may be inet %s, but it is not allowed in this context", arg
, "prefix");
196 get_prefix_1(dst
, arg
, family
);
199 uint32_t get_addr32(char *name
)
203 if (get_addr_1(&addr
, name
, AF_INET
)) {
204 bb_error_msg_and_die("an %s %s is expected rather than \"%s\"", "IP", "address", name
);
209 void incomplete_command(void)
211 bb_error_msg_and_die("command line is not complete, try option \"help\"");
214 void invarg(const char *arg
, const char *opt
)
216 bb_error_msg_and_die(bb_msg_invalid_arg
, arg
, opt
);
219 void duparg(const char *key
, const char *arg
)
221 bb_error_msg_and_die("duplicate \"%s\": \"%s\" is the second value", key
, arg
);
224 void duparg2(const char *key
, const char *arg
)
226 bb_error_msg_and_die("either \"%s\" is duplicate, or \"%s\" is garbage", key
, arg
);
229 int inet_addr_match(const inet_prefix
*a
, const inet_prefix
*b
, int bits
)
231 const uint32_t *a1
= a
->data
;
232 const uint32_t *a2
= b
->data
;
233 int words
= bits
>> 5;
238 if (memcmp(a1
, a2
, words
<< 2))
248 mask
= htonl((0xffffffff) << (0x20 - bits
));
250 if ((w1
^ w2
) & mask
)
257 const char *rt_addr_n2a(int af
,
258 void *addr
, char *buf
, int buflen
)
263 return inet_ntop(af
, addr
, buf
, buflen
);
269 #ifdef RESOLVE_HOSTNAMES
270 const char *format_host(int af
, int len
, void *addr
, char *buf
, int buflen
)
273 struct hostent
*h_ent
;
287 h_ent
= gethostbyaddr(addr
, len
, af
);
289 safe_strncpy(buf
, h_ent
->h_name
, buflen
);
294 return rt_addr_n2a(af
, addr
, buf
, buflen
);