5 #include <sys/socket.h>
10 #include <linux/netfilter_ipv4/ip_pool.h>
11 #include <libippool/ip_pool_support.h>
13 /* translate errnos, as returned by our *sockopt() functions */
14 static char *errno2msg(int op, int err)
18 return "Address out of pool range";
23 static void usage(char *msg)
25 if (msg) fprintf(stderr, "ERROR: %s\n", msg);
27 "Usage: ippool [-LADCNF] [POOL] [args]\n"
28 "The POOL argument is either a number, or a name from %s\n"
31 "ippool [-n] [-l|-L POOL] [-u] [-v]\n"
32 "\tLists all (-l), or a single (-L) pool.\n"
33 "\tWith -u, summarized usage counts are listed.\n"
34 "\tWith -v, each pool membership is shown, one per line.\n"
35 "ippool [-n] [-f|-F [POOL]]\n"
36 "\tflushes POOL (or all pools.)\n"
37 "ippool [-n] [-x|-X [POOL]]\n"
38 "\tremoves POOL (or all pools.)\n"
40 "\tcreates all fully specified pools found in the config file.\n"
41 "ippool [-n] -N POOL [-t type] [FIRST LAST]\n"
42 "\tcreates POOL of IP addresses FIRST to LAST (inclusive). If a\n"
43 "\tpool name from the config file %s is used, type and\n"
44 "\taddress information can be defined there. The -t argument\n"
45 "\tgives the type (default bitmap).\n"
46 "ippool [-n] -A POOL ADDR\n"
47 "\tadds ADDR to POOL\n"
48 "ippool [-n] -D POOL ADDR\n"
49 "\tremoves ADDR from POOL\n"
50 "ippool [-n] -C POOL ADDR\n"
51 "\ttests ADDR against membership in POOL\n"
56 /* config file parsing */
58 #define IP_POOL_T_NONE 0
59 #define IP_POOL_T_BITMAP 1
61 static int conf_type = IP_POOL_T_NONE;
62 static unsigned long conf_addr = 0;
63 static unsigned long conf_addr2 = 0;
65 #define SCAN_EOF (IP_POOL_NONE-1)
67 static ip_pool_t get_index_line(
77 if (namep) *namep = 0;
78 if (typep) *typep = 0;
81 if (!fgets(buf, sizeof(buf), fp)) return SCAN_EOF;
83 p = strtok(buf, " \t\n");
84 if (!p || *p == '#') return IP_POOL_NONE;
87 p = strtok(0, " \t\n");
88 if (!p || *p == '#') return index;
89 if (namep) *namep = p;
91 p = strtok(0, " \t\n");
92 if (!p || *p == '#') return index;
93 if (typep) *typep = p;
101 static ip_pool_t get_index(char *name)
104 char *poolname, *type, *arg, *p;
109 fp = fopen(IPPOOL_CONF, "r");
111 fprintf(stderr, "cannot open %s - no pool names", IPPOOL_CONF);
114 while (SCAN_EOF != (res=get_index_line(fp, &poolname, &type, &arg))) {
115 if (poolname && 0 == strcmp(poolname, name)) {
116 if (!type || (0 == strcmp(type, "bitmap"))) {
117 conf_type = IP_POOL_T_BITMAP;
118 p = strtok(arg, " \t");
120 conf_addr = inet_addr(p);
121 p = strtok(0, " \t");
123 conf_addr2 = inet_addr(p);
132 if (res == SCAN_EOF) {
133 fprintf(stderr, "pool '%s' not found in %s\n",
140 static char *get_name(ip_pool_t index)
143 static char sbuf[256];
146 fp = fopen(IPPOOL_CONF, "r");
148 while (fgets(sbuf, sizeof(sbuf), fp)) {
149 char *p = strtok(sbuf, " \t\n");
151 if (!p || *p == '#') continue;
152 if (index != atoi(p)) continue;
153 p = strtok(0, " \t\n");
154 if (!p || *p == '#') continue;
155 memmove(sbuf, p, strlen(p)+1);
161 if (!ok) sprintf(sbuf, "%d", index);
165 /* user/kernel interaction */
168 static int flag_n = 0; /* do not do anything; just brag about it */
169 static int flag_v = 0; /* be verbose (list members) */
170 static int flag_q = 0; /* be quiet */
171 static int flag_u = 0; /* show usage counts in listings */
172 static char *flag_t = "bitmap"; /* pool type */
174 static ip_pool_t high_nr(void)
176 struct ip_pool_request req;
177 int reqlen = sizeof(req);
179 req.op = IP_POOL_HIGH_NR;
180 if (0 > getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
182 "IP_POOL_HIGH_NR failed: %s\n",
183 errno2msg(IP_POOL_HIGH_NR, errno));
189 static void do_list(ip_pool_t pool)
191 struct ip_pool_request req;
192 int reqlen = sizeof(req);
196 req.op = IP_POOL_LOOKUP;
198 req.addr = req.addr2 = 0;
199 reqlen = sizeof(req);
200 if (0 == getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
202 ina.s_addr = req.addr;
203 printf("%s %s", get_name(req.index), inet_ntoa(ina));
204 ina.s_addr = req.addr2;
205 printf(" %s", inet_ntoa(ina));
206 first_ip = ntohl(req.addr);
207 last_ip = ntohl(req.addr2);
209 req.op = IP_POOL_USAGE;
211 reqlen = sizeof(req);
212 if (0 == getsockopt(fd, SOL_IP, SO_IP_POOL,
214 printf(" %d %d", req.addr, req.addr2);
221 while (first_ip <= last_ip) {
222 req.op = IP_POOL_TEST_ADDR;
224 ina.s_addr = req.addr = htonl(first_ip);
225 reqlen = sizeof(req);
226 if (0 == getsockopt(fd, SOL_IP, SO_IP_POOL,
228 if (req.addr) printf("\t%s\n",
237 static void do_list_all(void)
239 ip_pool_t i, highest = high_nr();
241 for (i=0; i<=highest; i++)
245 static void do_flush(ip_pool_t pool)
247 struct ip_pool_request req;
248 int reqlen = sizeof(req);
250 req.op = IP_POOL_FLUSH;
253 printf("ippool -F %d\n", req.index);
256 if (0 > getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
259 "IP_POOL_FLUSH %s failed: %s\n",
260 get_name(pool), errno2msg(IP_POOL_FLUSH, err));
265 static void do_flush_all(void)
267 ip_pool_t i, highest = high_nr();
269 for (i=0; i<=highest; i++)
273 static void do_destroy(ip_pool_t pool)
275 struct ip_pool_request req;
276 int reqlen = sizeof(req);
278 req.op = IP_POOL_DESTROY;
281 printf("ippool -X %d\n", req.index);
284 if (0 > getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
287 "IP_POOL_DESTROY %s failed: %s\n",
288 get_name(pool), errno2msg(IP_POOL_DESTROY, err));
293 static void do_destroy_all(void)
295 ip_pool_t i, highest = high_nr();
297 for (i=0; i<=highest; i++)
301 static int do_adddel(ip_pool_t pool, char *straddr, int op)
303 struct ip_pool_request req;
305 int reqlen = sizeof(req);
309 req.addr = inet_addr(straddr);
312 printf("ippool -%c %s %s\n",
313 (op == IP_POOL_ADD_ADDR) ? 'A' : 'D',
314 get_name(req.index), straddr);
317 res = getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen);
321 "IP_POOL_ADD/DEL %s in %s failed: %s\n",
322 straddr, get_name(pool), errno2msg(op, err));
326 printf("%s %s %d %d\n", get_name(pool), straddr, req.addr,
327 op == IP_POOL_ADD_ADDR ? 1 : 0);
331 static int do_check(ip_pool_t pool, char *straddr)
333 struct ip_pool_request req;
334 int reqlen = sizeof(req);
336 req.op = IP_POOL_TEST_ADDR;
338 req.addr = inet_addr(straddr);
339 if (0 > getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
342 "IP_POOL_TEST_ADDR %s in %s failed: %s\n",
343 straddr, get_name(pool),
344 errno2msg(IP_POOL_TEST_ADDR, err));
348 printf("%s %s %d\n", get_name(req.index), straddr, req.addr);
352 static void do_new(ip_pool_t pool, int argc, char **argv)
354 struct ip_pool_request req;
355 int reqlen = sizeof(req);
357 req.op = IP_POOL_INIT;
360 conf_type = IP_POOL_T_BITMAP;
361 conf_addr = inet_addr(argv[0]);
362 conf_addr2 = inet_addr(argv[1]);
364 if (conf_type != IP_POOL_T_BITMAP || conf_addr == 0 || conf_addr2 == 0)
365 usage("bad pool specification");
366 req.addr = conf_addr;
367 req.addr2 = conf_addr2;
369 printf("ippool -N %s [-T %s] ...\n", get_name(pool),
370 conf_type == IP_POOL_T_BITMAP
375 if (0 > getsockopt(fd, SOL_IP, SO_IP_POOL, &req, &reqlen)) {
378 ina.s_addr = conf_addr;
380 "IP_POOL_INIT %s [%s-",
381 get_name(pool), inet_ntoa(ina));
382 ina.s_addr = conf_addr2;
385 inet_ntoa(ina), errno2msg(IP_POOL_INIT, err));
390 static void do_new_all(void)
393 char *poolname, *type, *arg, *p;
396 fp = fopen(IPPOOL_CONF, "r");
398 fprintf(stderr, "cannot open %s - no pool names", IPPOOL_CONF);
401 while (SCAN_EOF != (res=get_index_line(fp, &poolname, &type, &arg))) {
402 if (poolname && type && (0 == strcmp(type, "bitmap"))) {
403 conf_type = IP_POOL_T_BITMAP;
404 p = strtok(arg, " \t");
406 conf_addr = inet_addr(p);
407 p = strtok(0, " \t");
409 conf_addr2 = inet_addr(p);
413 if (conf_addr != 0) {
415 printf("ippool -N %s (%s) [%s]\n",
416 poolname, type, arg);
424 int main(int argc, char **argv)
430 #define OP_LIST_ALL 2
432 #define OP_FLUSH_ALL 4
434 #define OP_DESTROY_ALL 6
439 #define OP_NEW_ALL 11
440 #define OP_HIGHEST 12
443 fd = socket(AF_INET, SOCK_DGRAM, 0);
445 fprintf(stderr, "cannot get DGRAM socket: %s\n",
451 /* GRRR. I thought getopt() would allow an "L*" specifier, for an -L
452 * taking an optional argument. Does not work. Bad.
453 * Adding -l for -L without argument, also -f/-F and -x/-X.
455 while (EOF != (opt=getopt( argc, argv, "HhnvuqA:D:C:N:t:L:F:X:lfxB")))
458 if (op != OP_NONE) usage("conflicting operations");
462 if (op != OP_NONE) usage("conflicting operations");
467 if (op != OP_NONE) usage("conflicting operations");
471 if (op != OP_NONE) usage("conflicting operations");
476 if (op != OP_NONE) usage("conflicting operations");
480 if (op != OP_NONE) usage("conflicting operations");
485 if (op != OP_NONE) usage("conflicting operations");
490 if (op != OP_NONE) usage("conflicting operations");
495 if (op != OP_NONE) usage("conflicting operations");
500 if (op != OP_NONE) usage("conflicting operations");
504 if (op != OP_NONE) usage("conflicting operations");
509 if (op != OP_NONE) usage("conflicting operations");
533 usage("no operation specified");
534 if (op == OP_LIST_ALL) {
539 do_list(get_index(op_pool));
542 if (op == OP_FLUSH_ALL) {
546 if (op == OP_FLUSH) {
547 do_flush(get_index(op_pool));
550 if (op == OP_DESTROY_ALL) {
554 if (op == OP_DESTROY) {
555 do_destroy(get_index(op_pool));
558 if (op == OP_CHECK) {
560 usage("missing address to check");
561 return do_check(get_index(op_pool), argv[optind]);
563 if (op == OP_NEW_ALL) {
568 do_new(get_index(op_pool), argc-optind, argv+optind);
573 usage("missing address to add");
574 return do_adddel(get_index(op_pool),
575 argv[optind], IP_POOL_ADD_ADDR);
579 usage("missing address to delete");
580 return do_adddel(get_index(op_pool),
581 argv[optind], IP_POOL_DEL_ADDR);
583 if (op == OP_HIGHEST) {
584 printf("%d\n", high_nr());
587 usage("no operation specified");