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