minor fix to return E_USAGE on -V instead of exit(0);
[oss-qm-packages.git] / lib / util-ank.c
blob43a7f1cb8410371b7f58ea7324b10001c263e49d
1 /*
2 * utils.c
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.
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
12 * Changes:
14 * Rani Assaf <rani@magic.metawire.com> 980929: resolve addresses
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>
29 #include "intl.h"
30 #include "util-ank.h"
32 #ifndef AF_INET6
33 #define AF_INET6 10
34 #endif
36 int scan_number(char *arg, unsigned *val)
38 unsigned long res;
39 char *ptr;
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;
50 int get_integer(int *val, char *arg, int base)
52 long res;
53 char *ptr;
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;
64 int get_unsigned(unsigned *val, char *arg, int base)
66 unsigned long res;
67 char *ptr;
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;
78 int get_u32(__u32 *val, char *arg, int base)
80 unsigned long res;
81 char *ptr;
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;
92 int get_u16(__u16 *val, char *arg, int base)
94 unsigned long res;
95 char *ptr;
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;
106 int get_u8(__u8 *val, char *arg, int base)
108 unsigned long res;
109 char *ptr;
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;
120 int get_s16(__s16 *val, char *arg, int base)
122 long res;
123 char *ptr;
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;
134 int get_s8(__s8 *val, char *arg, int base)
136 long res;
137 char *ptr;
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;
148 int get_addr_1(inet_prefix *addr, char *name, int family)
150 char *cp;
151 unsigned char *ap = (unsigned char*)addr->data;
152 int i;
154 memset(addr, 0, sizeof(*addr));
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;
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;
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;
184 if (*cp == '.' && ++i <= 3)
185 continue;
186 return -1;
188 return 0;
191 int get_prefix_1(inet_prefix *dst, char *arg, int family)
193 int err;
194 unsigned plen;
195 char *slash;
197 memset(dst, 0, sizeof(*dst));
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;
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;
217 dst->bitlen = plen;
220 done:
221 if (slash)
222 *slash = '/';
223 return err;
226 int get_addr(inet_prefix *dst, char *arg, int family)
228 if (get_addr_1(dst, arg, family)) {
229 fprintf(stderr, _("ip: %s is invalid inet address\n"), arg);
230 exit(1);
232 return 0;
235 int get_prefix(inet_prefix *dst, char *arg, int family)
237 if (get_prefix_1(dst, arg, family)) {
238 fprintf(stderr, _("ip: %s is invalid inet prefix\n"), arg);
239 exit(1);
241 return 0;
244 __u32 get_addr32(char *name)
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);
251 return addr.data[0];
254 void invarg(char *msg)
256 fprintf(stderr, _("ip: argument is wrong: %s\n"), msg);
257 exit(1);
260 int matches(char *cmd, char *pattern)
262 int len = strlen(cmd);
263 if (len > strlen(pattern))
264 return -1;
265 return memcmp(pattern, cmd, len);
268 int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
270 __u32 *a1 = a->data;
271 __u32 *a2 = b->data;
272 int words = bits >> 0x05;
274 bits &= 0x1f;
276 if (words)
277 if (memcmp(a1, a2, words << 2))
278 return -1;
280 if (bits) {
281 __u32 w1, w2;
282 __u32 mask;
284 w1 = a1[words];
285 w2 = a2[words];
287 mask = htonl((0xffffffff) << (0x20 - bits));
289 if ((w1 ^ w2) & mask)
290 return 1;
293 return 0;
296 const char *format_host(int af, void *addr, __u8 *abuf, int alen)
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;
310 if (addrlen &&
311 (h_ent = gethostbyaddr(addr, addrlen, af)) != NULL) {
312 snprintf(abuf, alen-1, "%s", h_ent->h_name);
313 return abuf;
316 #endif
317 return inet_ntop(af, addr, abuf, alen);