Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ipf / tools / ippool.c
blob3fd1c0ec61745765d8e133e10a5aa201c3be055d
1 /* $NetBSD: ippool.c,v 1.6 2008/05/20 07:08:07 darrenr Exp $ */
3 /*
4 * Copyright (C) 2002-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #include <sys/types.h>
9 #include <sys/time.h>
10 #include <sys/param.h>
11 #include <sys/socket.h>
12 #if defined(BSD) && (BSD >= 199306)
13 # include <sys/cdefs.h>
14 #endif
15 #include <sys/ioctl.h>
17 #include <net/if.h>
18 #if __FreeBSD_version >= 300000
19 # include <net/if_var.h>
20 #endif
21 #include <netinet/in.h>
23 #include <arpa/inet.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <netdb.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #ifdef linux
33 # include <linux/a.out.h>
34 #else
35 # include <nlist.h>
36 #endif
38 #include "ipf.h"
39 #include "netinet/ipl.h"
40 #include "netinet/ip_lookup.h"
41 #include "netinet/ip_pool.h"
42 #include "netinet/ip_htable.h"
43 #include "kmem.h"
46 extern int ippool_yyparse __P((void));
47 extern int ippool_yydebug;
48 extern FILE *ippool_yyin;
49 extern char *optarg;
50 extern int lineNum;
52 void usage __P((char *));
53 int main __P((int, char **));
54 int poolcommand __P((int, int, char *[]));
55 int poolnodecommand __P((int, int, char *[]));
56 int loadpoolfile __P((int, char *[], char *));
57 int poollist __P((int, char *[]));
58 void poollist_dead __P((int, char *, int, char *, char *));
59 void poollist_live __P((int, char *, int, int));
60 int poolflush __P((int, char *[]));
61 int poolstats __P((int, char *[]));
62 int gettype __P((char *, u_int *));
63 int getrole __P((char *));
64 int setnodeaddr __P((ip_pool_node_t *node, char *arg));
65 void showpools_live __P((int, int, ip_pool_stat_t *, char *));
66 void showhashs_live __P((int, int, iphtstat_t *, char *));
68 int opts = 0;
69 int fd = -1;
70 int use_inet6 = 0;
73 void usage(prog)
74 char *prog;
76 fprintf(stderr, "Usage:\t%s\n", prog);
77 fprintf(stderr, "\t\t\t-a [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
78 fprintf(stderr, "\t\t\t-A [-dnv] [-m <name>] [-o <role>] [-S <seed>] [-t <type>]\n");
79 fprintf(stderr, "\t\t\t-f <file> [-dnuv]\n");
80 fprintf(stderr, "\t\t\t-F [-dv] [-o <role>] [-t <type>]\n");
81 fprintf(stderr, "\t\t\t-l [-dv] [-m <name>] [-t <type>]\n");
82 fprintf(stderr, "\t\t\t-r [-dnv] [-m <name>] [-o <role>] -i <ipaddr>[/netmask]\n");
83 fprintf(stderr, "\t\t\t-R [-dnv] [-m <name>] [-o <role>] [-t <type>]\n");
84 fprintf(stderr, "\t\t\t-s [-dtv] [-M <core>] [-N <namelist>]\n");
85 exit(1);
89 int main(argc, argv)
90 int argc;
91 char *argv[];
93 int err;
95 if (argc < 2)
96 usage(argv[0]);
98 switch (getopt(argc, argv, "aAf:FlrRs"))
100 case 'a' :
101 err = poolnodecommand(0, argc, argv);
102 break;
103 case 'A' :
104 err = poolcommand(0, argc, argv);
105 break;
106 case 'f' :
107 err = loadpoolfile(argc, argv, optarg);
108 break;
109 case 'F' :
110 err = poolflush(argc, argv);
111 break;
112 case 'l' :
113 err = poollist(argc, argv);
114 break;
115 case 'r' :
116 err = poolnodecommand(1, argc, argv);
117 break;
118 case 'R' :
119 err = poolcommand(1, argc, argv);
120 break;
121 case 's' :
122 err = poolstats(argc, argv);
123 break;
124 default :
125 exit(1);
128 if (err != 0)
129 exit(1);
130 return 0;
134 int poolnodecommand(remove, argc, argv)
135 int remove, argc;
136 char *argv[];
138 int err, c, ipset, role;
139 char *poolname = NULL;
140 ip_pool_node_t node;
142 ipset = 0;
143 role = IPL_LOGIPF;
144 bzero((char *)&node, sizeof(node));
146 while ((c = getopt(argc, argv, "di:m:no:Rv")) != -1)
147 switch (c)
149 case 'd' :
150 opts |= OPT_DEBUG;
151 ippool_yydebug++;
152 break;
153 case 'i' :
154 if (setnodeaddr(&node, optarg) == 0)
155 ipset = 1;
156 break;
157 case 'm' :
158 poolname = optarg;
159 break;
160 case 'n' :
161 opts |= OPT_DONOTHING;
162 break;
163 case 'o' :
164 role = getrole(optarg);
165 if (role == IPL_LOGNONE)
166 return -1;
167 break;
168 case 'R' :
169 opts |= OPT_NORESOLVE;
170 break;
171 case 'v' :
172 opts |= OPT_VERBOSE;
173 break;
176 if (argv[optind] != NULL && ipset == 0) {
177 if (setnodeaddr(&node, argv[optind]) == 0)
178 ipset = 1;
181 if (opts & OPT_DEBUG)
182 fprintf(stderr, "poolnodecommand: opts = %#x\n", opts);
184 if (ipset == 0) {
185 fprintf(stderr, "no IP address given with -i\n");
186 return -1;
189 if (poolname == NULL) {
190 fprintf(stderr, "poolname not given with add/remove node\n");
191 return -1;
194 if (remove == 0)
195 err = load_poolnode(0, poolname, &node, ioctl);
196 else
197 err = remove_poolnode(0, poolname, &node, ioctl);
198 return err;
202 int poolcommand(remove, argc, argv)
203 int remove, argc;
204 char *argv[];
206 int type, role, c, err;
207 char *poolname;
208 iphtable_t iph;
209 ip_pool_t pool;
211 err = 1;
212 role = 0;
213 type = 0;
214 poolname = NULL;
215 role = IPL_LOGIPF;
216 bzero((char *)&iph, sizeof(iph));
217 bzero((char *)&pool, sizeof(pool));
219 while ((c = getopt(argc, argv, "dm:no:RSt:v")) != -1)
220 switch (c)
222 case 'd' :
223 opts |= OPT_DEBUG;
224 ippool_yydebug++;
225 break;
226 case 'm' :
227 poolname = optarg;
228 break;
229 case 'n' :
230 opts |= OPT_DONOTHING;
231 break;
232 case 'o' :
233 role = getrole(optarg);
234 if (role == IPL_LOGNONE) {
235 fprintf(stderr, "unknown role '%s'\n", optarg);
236 return -1;
238 break;
239 case 'R' :
240 opts |= OPT_NORESOLVE;
241 break;
242 case 'S' :
243 iph.iph_seed = atoi(optarg);
244 break;
245 case 't' :
246 type = gettype(optarg, &iph.iph_type);
247 if (type == IPLT_NONE) {
248 fprintf(stderr, "unknown type '%s'\n", optarg);
249 return -1;
251 break;
252 case 'v' :
253 opts |= OPT_VERBOSE;
254 break;
257 if (opts & OPT_DEBUG)
258 fprintf(stderr, "poolcommand: opts = %#x\n", opts);
260 if (poolname == NULL) {
261 fprintf(stderr, "poolname not given with add/remove pool\n");
262 return -1;
265 if (type == IPLT_HASH) {
266 strncpy(iph.iph_name, poolname, sizeof(iph.iph_name));
267 iph.iph_name[sizeof(iph.iph_name) - 1] = '\0';
268 iph.iph_unit = role;
269 } else if (type == IPLT_POOL) {
270 strncpy(pool.ipo_name, poolname, sizeof(pool.ipo_name));
271 pool.ipo_name[sizeof(pool.ipo_name) - 1] = '\0';
272 pool.ipo_unit = role;
275 if (remove == 0) {
276 switch (type)
278 case IPLT_HASH :
279 err = load_hash(&iph, NULL, ioctl);
280 break;
281 case IPLT_POOL :
282 err = load_pool(&pool, ioctl);
283 break;
285 } else {
286 switch (type)
288 case IPLT_HASH :
289 err = remove_hash(&iph, ioctl);
290 break;
291 case IPLT_POOL :
292 err = remove_pool(&pool, ioctl);
293 break;
296 return err;
300 int loadpoolfile(argc, argv, infile)
301 int argc;
302 char *argv[], *infile;
304 int c;
306 infile = optarg;
308 while ((c = getopt(argc, argv, "dnRuv")) != -1)
309 switch (c)
311 case 'd' :
312 opts |= OPT_DEBUG;
313 ippool_yydebug++;
314 break;
315 case 'n' :
316 opts |= OPT_DONOTHING;
317 break;
318 case 'R' :
319 opts |= OPT_NORESOLVE;
320 break;
321 case 'u' :
322 opts |= OPT_REMOVE;
323 break;
324 case 'v' :
325 opts |= OPT_VERBOSE;
326 break;
329 if (opts & OPT_DEBUG)
330 fprintf(stderr, "loadpoolfile: opts = %#x\n", opts);
332 if (!(opts & OPT_DONOTHING) && (fd == -1)) {
333 fd = open(IPLOOKUP_NAME, O_RDWR);
334 if (fd == -1) {
335 perror("open(IPLOOKUP_NAME)");
336 exit(1);
340 if (ippool_parsefile(fd, infile, ioctl) != 0)
341 return -1;
342 return 0;
346 int poolstats(argc, argv)
347 int argc;
348 char *argv[];
350 int c, type, role, live_kernel;
351 ip_pool_stat_t plstat;
352 char *kernel, *core;
353 iphtstat_t htstat;
354 iplookupop_t op;
356 core = NULL;
357 kernel = NULL;
358 live_kernel = 1;
359 type = IPLT_ALL;
360 role = IPL_LOGALL;
362 bzero((char *)&op, sizeof(op));
364 while ((c = getopt(argc, argv, "dM:N:o:t:v")) != -1)
365 switch (c)
367 case 'd' :
368 opts |= OPT_DEBUG;
369 break;
370 case 'M' :
371 live_kernel = 0;
372 core = optarg;
373 break;
374 case 'N' :
375 live_kernel = 0;
376 kernel = optarg;
377 break;
378 case 'o' :
379 role = getrole(optarg);
380 if (role == IPL_LOGNONE) {
381 fprintf(stderr, "unknown role '%s'\n", optarg);
382 return -1;
384 break;
385 case 't' :
386 type = gettype(optarg, NULL);
387 if (type != IPLT_POOL) {
388 fprintf(stderr,
389 "-s not supported for this type yet\n");
390 return -1;
392 break;
393 case 'v' :
394 opts |= OPT_VERBOSE;
395 break;
398 if (opts & OPT_DEBUG)
399 fprintf(stderr, "poolstats: opts = %#x\n", opts);
401 if (!(opts & OPT_DONOTHING) && (fd == -1)) {
402 fd = open(IPLOOKUP_NAME, O_RDWR);
403 if (fd == -1) {
404 perror("open(IPLOOKUP_NAME)");
405 exit(1);
409 if (type == IPLT_ALL || type == IPLT_POOL) {
410 op.iplo_type = IPLT_POOL;
411 op.iplo_struct = &plstat;
412 op.iplo_size = sizeof(plstat);
413 if (!(opts & OPT_DONOTHING)) {
414 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
415 if (c == -1) {
416 perror("ioctl(SIOCLOOKUPSTAT)");
417 return -1;
419 printf("Pools:\t%lu\n", plstat.ipls_pools);
420 printf("Nodes:\t%lu\n", plstat.ipls_nodes);
424 if (type == IPLT_ALL || type == IPLT_HASH) {
425 op.iplo_type = IPLT_HASH;
426 op.iplo_struct = &htstat;
427 op.iplo_size = sizeof(htstat);
428 if (!(opts & OPT_DONOTHING)) {
429 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
430 if (c == -1) {
431 perror("ioctl(SIOCLOOKUPSTAT)");
432 return -1;
434 printf("Hash Tables:\t%lu\n", htstat.iphs_numtables);
435 printf("Nodes:\t%lu\n", htstat.iphs_numnodes);
436 printf("Out of Memory:\t%lu\n", htstat.iphs_nomem);
439 return 0;
443 int poolflush(argc, argv)
444 int argc;
445 char *argv[];
447 int c, role, type, arg;
448 iplookupflush_t flush;
450 arg = IPLT_ALL;
451 type = IPLT_ALL;
452 role = IPL_LOGALL;
454 while ((c = getopt(argc, argv, "do:t:v")) != -1)
455 switch (c)
457 case 'd' :
458 opts |= OPT_DEBUG;
459 break;
460 case 'o' :
461 role = getrole(optarg);
462 if (role == IPL_LOGNONE) {
463 fprintf(stderr, "unknown role '%s'\n", optarg);
464 return -1;
466 break;
467 case 't' :
468 type = gettype(optarg, NULL);
469 if (type == IPLT_NONE) {
470 fprintf(stderr, "unknown type '%s'\n", optarg);
471 return -1;
473 break;
474 case 'v' :
475 opts |= OPT_VERBOSE;
476 break;
479 if (opts & OPT_DEBUG)
480 fprintf(stderr, "poolflush: opts = %#x\n", opts);
482 if (!(opts & OPT_DONOTHING) && (fd == -1)) {
483 fd = open(IPLOOKUP_NAME, O_RDWR);
484 if (fd == -1) {
485 perror("open(IPLOOKUP_NAME)");
486 exit(1);
490 bzero((char *)&flush, sizeof(flush));
491 flush.iplf_type = type;
492 flush.iplf_unit = role;
493 flush.iplf_arg = arg;
495 if (!(opts & OPT_DONOTHING)) {
496 if (ioctl(fd, SIOCLOOKUPFLUSH, &flush) == -1) {
497 perror("ioctl(SIOCLOOKUPFLUSH)");
498 exit(1);
502 printf("%u object%s flushed\n", flush.iplf_count,
503 (flush.iplf_count == 1) ? "" : "s");
505 return 0;
509 int getrole(rolename)
510 char *rolename;
512 int role;
514 if (!strcasecmp(rolename, "ipf")) {
515 role = IPL_LOGIPF;
516 #if 0
517 } else if (!strcasecmp(rolename, "nat")) {
518 role = IPL_LOGNAT;
519 } else if (!strcasecmp(rolename, "state")) {
520 role = IPL_LOGSTATE;
521 } else if (!strcasecmp(rolename, "auth")) {
522 role = IPL_LOGAUTH;
523 } else if (!strcasecmp(rolename, "sync")) {
524 role = IPL_LOGSYNC;
525 } else if (!strcasecmp(rolename, "scan")) {
526 role = IPL_LOGSCAN;
527 } else if (!strcasecmp(rolename, "pool")) {
528 role = IPL_LOGLOOKUP;
529 } else if (!strcasecmp(rolename, "count")) {
530 role = IPL_LOGCOUNT;
531 #endif
532 } else {
533 role = IPL_LOGNONE;
536 return role;
540 int gettype(typename, minor)
541 char *typename;
542 u_int *minor;
544 int type;
546 if (!strcasecmp(optarg, "tree") || !strcasecmp(optarg, "pool")) {
547 type = IPLT_POOL;
548 } else if (!strcasecmp(optarg, "hash")) {
549 type = IPLT_HASH;
550 if (minor != NULL)
551 *minor = IPHASH_LOOKUP;
552 } else if (!strcasecmp(optarg, "group-map")) {
553 type = IPLT_HASH;
554 if (minor != NULL)
555 *minor = IPHASH_GROUPMAP;
556 } else {
557 type = IPLT_NONE;
559 return type;
563 int poollist(argc, argv)
564 int argc;
565 char *argv[];
567 char *kernel, *core, *poolname;
568 int c, role, type, live_kernel;
569 iplookupop_t op;
571 core = NULL;
572 kernel = NULL;
573 live_kernel = 1;
574 type = IPLT_ALL;
575 poolname = NULL;
576 role = IPL_LOGALL;
578 while ((c = getopt(argc, argv, "dm:M:N:o:Rt:v")) != -1)
579 switch (c)
581 case 'd' :
582 opts |= OPT_DEBUG;
583 break;
584 case 'm' :
585 poolname = optarg;
586 break;
587 case 'M' :
588 live_kernel = 0;
589 core = optarg;
590 break;
591 case 'N' :
592 live_kernel = 0;
593 kernel = optarg;
594 break;
595 case 'o' :
596 role = getrole(optarg);
597 if (role == IPL_LOGNONE) {
598 fprintf(stderr, "unknown role '%s'\n", optarg);
599 return -1;
601 break;
602 case 'R' :
603 opts |= OPT_NORESOLVE;
604 break;
605 case 't' :
606 type = gettype(optarg, NULL);
607 if (type == IPLT_NONE) {
608 fprintf(stderr, "unknown type '%s'\n", optarg);
609 return -1;
611 break;
612 case 'v' :
613 opts |= OPT_VERBOSE;
614 break;
617 if (opts & OPT_DEBUG)
618 fprintf(stderr, "poollist: opts = %#x\n", opts);
620 if (!(opts & OPT_DONOTHING) && (fd == -1)) {
621 fd = open(IPLOOKUP_NAME, O_RDWR);
622 if (fd == -1) {
623 perror("open(IPLOOKUP_NAME)");
624 exit(1);
628 bzero((char *)&op, sizeof(op));
629 if (poolname != NULL) {
630 strncpy(op.iplo_name, poolname, sizeof(op.iplo_name));
631 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
633 op.iplo_unit = role;
635 if (live_kernel)
636 poollist_live(role, poolname, type, fd);
637 else
638 poollist_dead(role, poolname, type, kernel, core);
639 return 0;
643 void poollist_dead(role, poolname, type, kernel, core)
644 int role, type;
645 char *poolname, *kernel, *core;
647 iphtable_t *hptr;
648 ip_pool_t *ptr;
650 if (openkmem(kernel, core) == -1)
651 exit(-1);
653 if (type == IPLT_ALL || type == IPLT_POOL) {
654 ip_pool_t *pools[IPL_LOGSIZE];
655 struct nlist names[2] = { { "ip_pool_list" } , { "" } };
657 if (nlist(kernel, names) != 1)
658 return;
660 bzero(&pools, sizeof(pools));
661 if (kmemcpy((char *)&pools, names[0].n_value, sizeof(pools)))
662 return;
664 if (role != IPL_LOGALL) {
665 ptr = pools[role];
666 while (ptr != NULL) {
667 ptr = printpool(ptr, kmemcpywrap, poolname,
668 opts);
670 } else {
671 for (role = 0; role <= IPL_LOGMAX; role++) {
672 ptr = pools[role];
673 while (ptr != NULL) {
674 ptr = printpool(ptr, kmemcpywrap,
675 poolname, opts);
678 role = IPL_LOGALL;
681 if (type == IPLT_ALL || type == IPLT_HASH) {
682 iphtable_t *tables[IPL_LOGSIZE];
683 struct nlist names[2] = { { "ipf_htables" } , { "" } };
685 if (nlist(kernel, names) != 1)
686 return;
688 bzero(&tables, sizeof(tables));
689 if (kmemcpy((char *)&tables, names[0].n_value, sizeof(tables)))
690 return;
692 if (role != IPL_LOGALL) {
693 hptr = tables[role];
694 while (hptr != NULL) {
695 hptr = printhash(hptr, kmemcpywrap,
696 poolname, opts);
698 } else {
699 for (role = 0; role <= IPL_LOGMAX; role++) {
700 hptr = tables[role];
701 while (hptr != NULL) {
702 hptr = printhash(hptr, kmemcpywrap,
703 poolname, opts);
711 void poollist_live(role, poolname, type, fd)
712 int role, type, fd;
713 char *poolname;
715 ip_pool_stat_t plstat;
716 iphtstat_t htstat;
717 iplookupop_t op;
718 int c;
720 if (type == IPLT_ALL || type == IPLT_POOL) {
721 op.iplo_type = IPLT_POOL;
722 op.iplo_size = sizeof(plstat);
723 op.iplo_struct = &plstat;
724 op.iplo_name[0] = '\0';
725 op.iplo_arg = 0;
727 if (role != IPL_LOGALL) {
728 op.iplo_unit = role;
730 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
731 if (c == -1) {
732 perror("ioctl(SIOCLOOKUPSTAT)");
733 return;
736 showpools_live(fd, role, &plstat, poolname);
737 } else {
738 for (role = 0; role <= IPL_LOGMAX; role++) {
739 op.iplo_unit = role;
741 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
742 if (c == -1) {
743 perror("ioctl(SIOCLOOKUPSTAT)");
744 return;
747 showpools_live(fd, role, &plstat, poolname);
750 role = IPL_LOGALL;
754 if (type == IPLT_ALL || type == IPLT_HASH) {
755 op.iplo_type = IPLT_HASH;
756 op.iplo_size = sizeof(htstat);
757 op.iplo_struct = &htstat;
758 op.iplo_name[0] = '\0';
759 op.iplo_arg = 0;
761 if (role != IPL_LOGALL) {
762 op.iplo_unit = role;
764 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
765 if (c == -1) {
766 perror("ioctl(SIOCLOOKUPSTAT)");
767 return;
769 showhashs_live(fd, role, &htstat, poolname);
770 } else {
771 for (role = 0; role <= IPL_LOGMAX; role++) {
773 op.iplo_unit = role;
774 c = ioctl(fd, SIOCLOOKUPSTAT, &op);
775 if (c == -1) {
776 perror("ioctl(SIOCLOOKUPSTAT)");
777 return;
780 showhashs_live(fd, role, &htstat, poolname);
787 void showpools_live(fd, role, plstp, poolname)
788 int fd, role;
789 ip_pool_stat_t *plstp;
790 char *poolname;
792 ipflookupiter_t iter;
793 ip_pool_t pool;
794 ipfobj_t obj;
796 obj.ipfo_rev = IPFILTER_VERSION;
797 obj.ipfo_type = IPFOBJ_LOOKUPITER;
798 obj.ipfo_size = sizeof(iter);
799 obj.ipfo_ptr = &iter;
801 iter.ili_type = IPLT_POOL;
802 iter.ili_otype = IPFLOOKUPITER_LIST;
803 iter.ili_ival = IPFGENITER_LOOKUP;
804 iter.ili_nitems = 1;
805 iter.ili_data = &pool;
806 iter.ili_unit = role;
807 *iter.ili_name = '\0';
809 while (plstp->ipls_list[role] != NULL) {
810 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
811 perror("ioctl(SIOCLOOKUPITER)");
812 break;
814 printpool_live(&pool, fd, poolname, opts);
816 plstp->ipls_list[role] = pool.ipo_next;
821 void showhashs_live(fd, role, htstp, poolname)
822 int fd, role;
823 iphtstat_t *htstp;
824 char *poolname;
826 ipflookupiter_t iter;
827 iphtable_t table;
828 ipfobj_t obj;
830 obj.ipfo_rev = IPFILTER_VERSION;
831 obj.ipfo_type = IPFOBJ_LOOKUPITER;
832 obj.ipfo_size = sizeof(iter);
833 obj.ipfo_ptr = &iter;
835 iter.ili_type = IPLT_HASH;
836 iter.ili_otype = IPFLOOKUPITER_LIST;
837 iter.ili_ival = IPFGENITER_LOOKUP;
838 iter.ili_nitems = 1;
839 iter.ili_data = &table;
840 iter.ili_unit = role;
841 *iter.ili_name = '\0';
843 while (htstp->iphs_tables != NULL) {
844 if (ioctl(fd, SIOCLOOKUPITER, &obj)) {
845 perror("ioctl(SIOCLOOKUPITER)");
846 break;
849 printhash_live(&table, fd, poolname, opts);
851 htstp->iphs_tables = table.iph_next;
856 int setnodeaddr(ip_pool_node_t *node, char *arg)
858 struct in_addr mask;
859 char *s;
861 s = strchr(arg, '/');
862 if (s == NULL)
863 mask.s_addr = 0xffffffff;
864 else if (strchr(s, '.') == NULL) {
865 if (ntomask(4, atoi(s + 1), &mask.s_addr) != 0)
866 return -1;
867 } else {
868 mask.s_addr = inet_addr(s + 1);
870 if (s != NULL)
871 *s = '\0';
872 node->ipn_addr.adf_len = sizeof(node->ipn_addr);
873 node->ipn_addr.adf_addr.in4.s_addr = inet_addr(arg);
874 node->ipn_mask.adf_len = sizeof(node->ipn_mask);
875 node->ipn_mask.adf_addr.in4.s_addr = mask.s_addr;
877 return 0;