blob: fa1548609dfb7a0f664de0ca4030159702b77535 [file] [log] [blame]
Glenn L McGrath9a2d2722002-11-10 01:33:55 +00001/*
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
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000017#include <stdlib.h>
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000018#include <string.h>
Eric Andersen496411b2003-02-12 10:56:53 +000019#include <unistd.h>
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000020#include <arpa/inet.h>
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000021
22#include "utils.h"
Glenn L McGrath82d2cd42002-11-28 12:45:48 +000023#include "libbb.h"
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000024
25int get_integer(int *val, char *arg, int base)
26{
27 long res;
28 char *ptr;
29
30 if (!arg || !*arg)
31 return -1;
32 res = strtol(arg, &ptr, base);
33 if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
34 return -1;
35 *val = res;
36 return 0;
37}
38
39int get_unsigned(unsigned *val, char *arg, int base)
40{
41 unsigned long res;
42 char *ptr;
43
44 if (!arg || !*arg)
45 return -1;
46 res = strtoul(arg, &ptr, base);
47 if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
48 return -1;
49 *val = res;
50 return 0;
51}
52
Glenn L McGrath50c00f42002-11-18 07:26:42 +000053int get_u32(__u32 * val, char *arg, int base)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000054{
55 unsigned long res;
56 char *ptr;
57
58 if (!arg || !*arg)
59 return -1;
60 res = strtoul(arg, &ptr, base);
61 if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
62 return -1;
63 *val = res;
64 return 0;
65}
66
Glenn L McGrath50c00f42002-11-18 07:26:42 +000067int get_u16(__u16 * val, char *arg, int base)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000068{
69 unsigned long res;
70 char *ptr;
71
72 if (!arg || !*arg)
73 return -1;
74 res = strtoul(arg, &ptr, base);
75 if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
76 return -1;
77 *val = res;
78 return 0;
79}
80
Glenn L McGrath50c00f42002-11-18 07:26:42 +000081int get_u8(__u8 * val, char *arg, int base)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000082{
83 unsigned long res;
84 char *ptr;
85
86 if (!arg || !*arg)
87 return -1;
88 res = strtoul(arg, &ptr, base);
89 if (!ptr || ptr == arg || *ptr || res > 0xFF)
90 return -1;
91 *val = res;
92 return 0;
93}
94
Glenn L McGrath50c00f42002-11-18 07:26:42 +000095int get_s16(__s16 * val, char *arg, int base)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +000096{
97 long res;
98 char *ptr;
99
100 if (!arg || !*arg)
101 return -1;
102 res = strtol(arg, &ptr, base);
103 if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
104 return -1;
105 *val = res;
106 return 0;
107}
108
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000109int get_s8(__s8 * val, char *arg, int base)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000110{
111 long res;
112 char *ptr;
113
114 if (!arg || !*arg)
115 return -1;
116 res = strtol(arg, &ptr, base);
117 if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
118 return -1;
119 *val = res;
120 return 0;
121}
122
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000123int get_addr_1(inet_prefix * addr, char *name, int family)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000124{
125 char *cp;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000126 unsigned char *ap = (unsigned char *) addr->data;
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000127 int i;
128
129 memset(addr, 0, sizeof(*addr));
130
131 if (strcmp(name, "default") == 0 ||
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000132 strcmp(name, "all") == 0 || strcmp(name, "any") == 0) {
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000133 addr->family = family;
134 addr->bytelen = (family == AF_INET6 ? 16 : 4);
135 addr->bitlen = -1;
136 return 0;
137 }
138
139 if (strchr(name, ':')) {
140 addr->family = AF_INET6;
141 if (family != AF_UNSPEC && family != AF_INET6)
142 return -1;
143 if (inet_pton(AF_INET6, name, addr->data) <= 0)
144 return -1;
145 addr->bytelen = 16;
146 addr->bitlen = -1;
147 return 0;
148 }
149
150 addr->family = AF_INET;
151 if (family != AF_UNSPEC && family != AF_INET)
152 return -1;
153 addr->bytelen = 4;
154 addr->bitlen = -1;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000155 for (cp = name, i = 0; *cp; cp++) {
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000156 if (*cp <= '9' && *cp >= '0') {
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000157 ap[i] = 10 * ap[i] + (*cp - '0');
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000158 continue;
159 }
160 if (*cp == '.' && ++i <= 3)
161 continue;
162 return -1;
163 }
164 return 0;
165}
166
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000167int get_prefix_1(inet_prefix * dst, char *arg, int family)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000168{
169 int err;
170 unsigned plen;
171 char *slash;
172
173 memset(dst, 0, sizeof(*dst));
174
175 if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
176 dst->family = family;
177 dst->bytelen = 0;
178 dst->bitlen = 0;
179 return 0;
180 }
181
182 slash = strchr(arg, '/');
183 if (slash)
184 *slash = 0;
185 err = get_addr_1(dst, arg, family);
186 if (err == 0) {
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000187 switch (dst->family) {
188 case AF_INET6:
189 dst->bitlen = 128;
190 break;
191 default:
192 case AF_INET:
193 dst->bitlen = 32;
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000194 }
195 if (slash) {
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000196 if (get_integer(&plen, slash + 1, 0) || plen > dst->bitlen) {
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000197 err = -1;
198 goto done;
199 }
200 dst->bitlen = plen;
201 }
202 }
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000203 done:
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000204 if (slash)
205 *slash = '/';
206 return err;
207}
208
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000209int get_addr(inet_prefix * dst, char *arg, int family)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000210{
211 if (family == AF_PACKET) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000212 bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000213 }
214 if (get_addr_1(dst, arg, family)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000215 bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000216 }
217 return 0;
218}
219
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000220int get_prefix(inet_prefix * dst, char *arg, int family)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000221{
222 if (family == AF_PACKET) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000223 bb_error_msg_and_die("\"%s\" may be inet address, but it is not allowed in this context.", arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000224 }
225 if (get_prefix_1(dst, arg, family)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000226 bb_error_msg_and_die("an inet address is expected rather than \"%s\".", arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000227 }
228 return 0;
229}
230
231__u32 get_addr32(char *name)
232{
233 inet_prefix addr;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000234
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000235 if (get_addr_1(&addr, name, AF_INET)) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000236 bb_error_msg_and_die("an IP address is expected rather than \"%s\"", name);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000237 }
238 return addr.data[0];
239}
240
241void incomplete_command()
242{
Manuel Novoa III cad53642003-03-19 09:13:01 +0000243 bb_error_msg("Command line is not complete. Try option \"help\"");
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000244 exit(-1);
245}
246
247void invarg(char *msg, char *arg)
248{
Manuel Novoa III cad53642003-03-19 09:13:01 +0000249 bb_error_msg("argument \"%s\" is wrong: %s", arg, msg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000250 exit(-1);
251}
252
253void duparg(char *key, char *arg)
254{
Manuel Novoa III cad53642003-03-19 09:13:01 +0000255 bb_error_msg("duplicate \"%s\": \"%s\" is the second value.", key, arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000256 exit(-1);
257}
258
259void duparg2(char *key, char *arg)
260{
Manuel Novoa III cad53642003-03-19 09:13:01 +0000261 bb_error_msg("either \"%s\" is duplicate, or \"%s\" is a garbage.", key, arg);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000262 exit(-1);
263}
264
265int matches(char *cmd, char *pattern)
266{
267 int len = strlen(cmd);
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000268
Glenn L McGrath82d2cd42002-11-28 12:45:48 +0000269 if (len > strlen(pattern)) {
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000270 return -1;
Glenn L McGrath82d2cd42002-11-28 12:45:48 +0000271 }
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000272 return memcmp(pattern, cmd, len);
273}
274
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000275int inet_addr_match(inet_prefix * a, inet_prefix * b, int bits)
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000276{
277 __u32 *a1 = a->data;
278 __u32 *a2 = b->data;
279 int words = bits >> 0x05;
280
281 bits &= 0x1f;
282
283 if (words)
284 if (memcmp(a1, a2, words << 2))
285 return -1;
286
287 if (bits) {
288 __u32 w1, w2;
289 __u32 mask;
290
291 w1 = a1[words];
292 w2 = a2[words];
293
294 mask = htonl((0xffffffff) << (0x20 - bits));
295
296 if ((w1 ^ w2) & mask)
297 return 1;
298 }
299
300 return 0;
301}
302
303int __iproute2_hz_internal;
304
305int __get_hz(void)
306{
307 int hz = 0;
308 FILE *fp = fopen("/proc/net/psched", "r");
309
310 if (fp) {
311 unsigned nom, denom;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000312
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000313 if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2)
314 if (nom == 1000000)
315 hz = denom;
316 fclose(fp);
317 }
318 if (hz)
319 return hz;
Eric Andersen496411b2003-02-12 10:56:53 +0000320 return sysconf(_SC_CLK_TCK);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000321}
322
323const char *rt_addr_n2a(int af, int len, void *addr, char *buf, int buflen)
324{
325 switch (af) {
326 case AF_INET:
327 case AF_INET6:
328 return inet_ntop(af, addr, buf, buflen);
329 default:
330 return "???";
331 }
332}
333
334
335const char *format_host(int af, int len, void *addr, char *buf, int buflen)
336{
337#ifdef RESOLVE_HOSTNAMES
338 if (resolve_hosts) {
339 struct hostent *h_ent;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000340
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000341 if (len <= 0) {
342 switch (af) {
343 case AF_INET:
344 len = 4;
345 break;
346 case AF_INET6:
347 len = 16;
348 break;
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000349 default:;
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000350 }
351 }
Glenn L McGrath50c00f42002-11-18 07:26:42 +0000352 if (len > 0 && (h_ent = gethostbyaddr(addr, len, af)) != NULL) {
353 snprintf(buf, buflen - 1, "%s", h_ent->h_name);
Glenn L McGrath9a2d2722002-11-10 01:33:55 +0000354 return buf;
355 }
356 }
357#endif
358 return rt_addr_n2a(af, len, addr, buf, buflen);
359}