man/pt_BR/ifconfig.8: remove untranslated paragraph
[platform/upstream/net-tools.git] / lib / util-ank.c
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
29 #include "intl.h"
30 #include "util-ank.h"
31
32 #ifndef AF_INET6
33 #define AF_INET6        10
34 #endif
35
36 int scan_number(char *arg, unsigned *val)
37 {
38         unsigned long res;
39         char *ptr;
40
41         if (!arg || !*arg)
42                 return -1;
43         res = strtoul(arg, &ptr, 0);
44         if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
45                 return -1;
46         *val = res;
47         return 0;
48 }
49
50 int get_integer(int *val, char *arg, int base)
51 {
52         long res;
53         char *ptr;
54
55         if (!arg || !*arg)
56                 return -1;
57         res = strtol(arg, &ptr, base);
58         if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
59                 return -1;
60         *val = res;
61         return 0;
62 }
63
64 int get_unsigned(unsigned *val, char *arg, int base)
65 {
66         unsigned long res;
67         char *ptr;
68
69         if (!arg || !*arg)
70                 return -1;
71         res = strtoul(arg, &ptr, base);
72         if (!ptr || ptr == arg || *ptr || res > UINT_MAX)
73                 return -1;
74         *val = res;
75         return 0;
76 }
77
78 int get_u32(__u32 *val, char *arg, int base)
79 {
80         unsigned long res;
81         char *ptr;
82
83         if (!arg || !*arg)
84                 return -1;
85         res = strtoul(arg, &ptr, base);
86         if (!ptr || ptr == arg || *ptr || res > 0xFFFFFFFFUL)
87                 return -1;
88         *val = res;
89         return 0;
90 }
91
92 int get_u16(__u16 *val, char *arg, int base)
93 {
94         unsigned long res;
95         char *ptr;
96
97         if (!arg || !*arg)
98                 return -1;
99         res = strtoul(arg, &ptr, base);
100         if (!ptr || ptr == arg || *ptr || res > 0xFFFF)
101                 return -1;
102         *val = res;
103         return 0;
104 }
105
106 int get_u8(__u8 *val, char *arg, int base)
107 {
108         unsigned long res;
109         char *ptr;
110
111         if (!arg || !*arg)
112                 return -1;
113         res = strtoul(arg, &ptr, base);
114         if (!ptr || ptr == arg || *ptr || res > 0xFF)
115                 return -1;
116         *val = res;
117         return 0;
118 }
119
120 int get_s16(__s16 *val, char *arg, int base)
121 {
122         long res;
123         char *ptr;
124
125         if (!arg || !*arg)
126                 return -1;
127         res = strtol(arg, &ptr, base);
128         if (!ptr || ptr == arg || *ptr || res > 0x7FFF || res < -0x8000)
129                 return -1;
130         *val = res;
131         return 0;
132 }
133
134 int get_s8(__s8 *val, char *arg, int base)
135 {
136         long res;
137         char *ptr;
138
139         if (!arg || !*arg)
140                 return -1;
141         res = strtol(arg, &ptr, base);
142         if (!ptr || ptr == arg || *ptr || res > 0x7F || res < -0x80)
143                 return -1;
144         *val = res;
145         return 0;
146 }
147
148 int get_addr_1(inet_prefix *addr, char *name, int family)
149 {
150         char *cp;
151         unsigned char *ap = (unsigned char*)addr->data;
152         int i;
153
154         memset(addr, 0, sizeof(*addr));
155
156         if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) {
157                 addr->family = family;
158                 addr->bytelen = (family == AF_INET6 ? 16 : 4);
159                 addr->bitlen = -1;
160                 return 0;
161         }
162
163         if (strchr(name, ':')) {
164                 addr->family = AF_INET6;
165                 if (family != AF_UNSPEC && family != AF_INET6)
166                         return -1;
167                 if (inet_pton(AF_INET6, name, addr->data) <= 0)
168                         return -1;
169                 addr->bytelen = 16;
170                 addr->bitlen = -1;
171                 return 0;
172         }
173
174         addr->family = AF_INET;
175         if (family != AF_UNSPEC && family != AF_INET)
176                 return -1;
177         addr->bytelen = 4;
178         addr->bitlen = -1;
179         for (cp=name, i=0; *cp; cp++) {
180                 if (*cp <= '9' && *cp >= '0') {
181                         ap[i] = 10*ap[i] + (*cp-'0');
182                         continue;
183                 }
184                 if (*cp == '.' && ++i <= 3)
185                         continue;
186                 return -1;
187         }
188         return 0;
189 }
190
191 int get_prefix_1(inet_prefix *dst, char *arg, int family)
192 {
193         int err;
194         unsigned plen;
195         char *slash;
196
197         memset(dst, 0, sizeof(*dst));
198
199         if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
200                 dst->family = family;
201                 dst->bytelen = 0;
202                 dst->bitlen = 0;
203                 return 0;
204         }
205
206         slash = strchr(arg, '/');
207         if (slash)
208                 *slash = 0;
209         err = get_addr_1(dst, arg, family);
210         if (err == 0) {
211                 dst->bitlen = (dst->family == AF_INET6 ? 128 : 32);
212                 if (slash) {
213                         if (scan_number(slash+1, &plen) || plen > dst->bitlen) {
214                                 err = -1;
215                                 goto done;
216                         }
217                         dst->bitlen = plen;
218                 }
219         }
220 done:
221         if (slash)
222                 *slash = '/';
223         return err;
224 }
225
226 int get_addr(inet_prefix *dst, char *arg, int family)
227 {
228         if (get_addr_1(dst, arg, family)) {
229                 fprintf(stderr, _("ip: %s is invalid inet address\n"), arg);
230                 exit(1);
231         }
232         return 0;
233 }
234
235 int get_prefix(inet_prefix *dst, char *arg, int family)
236 {
237         if (get_prefix_1(dst, arg, family)) {
238                 fprintf(stderr, _("ip: %s is invalid inet prefix\n"), arg);
239                 exit(1);
240         }
241         return 0;
242 }
243
244 __u32 get_addr32(char *name)
245 {
246         inet_prefix addr;
247         if (get_addr_1(&addr, name, AF_INET)) {
248                 fprintf(stderr, _("ip: %s is invalid IPv4 address\n"), name);
249                 exit(1);
250         }
251         return addr.data[0];
252 }
253
254 void invarg(char *msg)
255 {
256         fprintf(stderr, _("ip: argument is wrong: %s\n"), msg);
257         exit(1);
258 }
259
260 int matches(char *cmd, char *pattern)
261 {
262         int len = strlen(cmd);
263         if (len > strlen(pattern))
264                 return -1;
265         return memcmp(pattern, cmd, len);
266 }
267
268 int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
269 {
270         __u32 *a1 = a->data;
271         __u32 *a2 = b->data;
272         int words = bits >> 0x05;
273
274         bits &= 0x1f;
275
276         if (words)
277                 if (memcmp(a1, a2, words << 2))
278                         return -1;
279
280         if (bits) {
281                 __u32 w1, w2;
282                 __u32 mask;
283
284                 w1 = a1[words];
285                 w2 = a2[words];
286
287                 mask = htonl((0xffffffff) << (0x20 - bits));
288
289                 if ((w1 ^ w2) & mask)
290                         return 1;
291         }
292
293         return 0;
294 }
295
296 const char *format_host(int af, void *addr, char *abuf, int alen)
297 {
298 #ifdef RESOLVE_HOSTNAMES
299         if (resolve_hosts) {
300                 int addrlen = 0;
301                 struct hostent *h_ent;
302                 switch (af) {
303                 case AF_INET:
304                         addrlen = 4;
305                         break;
306                 case AF_INET6:
307                         addrlen = 16;
308                         break;
309                 }
310                 if (addrlen &&
311                     (h_ent = gethostbyaddr(addr, addrlen, af)) != NULL) {
312                         snprintf(abuf, alen-1, "%s", h_ent->h_name);
313                         return abuf;
314                 }
315         }
316 #endif
317         return inet_ntop(af, addr, abuf, alen);
318 }