]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/tools/ipnat.c
Merge compiler-rt trunk r321017 to contrib/compiler-rt.
[FreeBSD/FreeBSD.git] / contrib / ipfilter / tools / ipnat.c
1 /*      $FreeBSD$       */
2
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  *
8  * Added redirect stuff and a variety of bug fixes. (mcn@EnGarde.com)
9  */
10 #include <stdio.h>
11 #include <string.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <sys/types.h>
15 #if !defined(__SVR4) && !defined(__svr4__)
16 #include <strings.h>
17 #else
18 #include <sys/byteorder.h>
19 #endif
20 #include <sys/time.h>
21 #include <sys/param.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <stddef.h>
25 #include <sys/file.h>
26 #define _KERNEL
27 #include <sys/uio.h>
28 #undef _KERNEL
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #if defined(sun) && (defined(__svr4__) || defined(__SVR4))
32 # include <sys/ioccom.h>
33 # include <sys/sysmacros.h>
34 #endif
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/tcp.h>
39 #include <net/if.h>
40 #include <netdb.h>
41 #include <arpa/nameser.h>
42 #include <arpa/inet.h>
43 #include <resolv.h>
44 #include <ctype.h>
45 #if defined(linux)
46 # include <linux/a.out.h>
47 #else
48 # include <nlist.h>
49 #endif
50 #include "ipf.h"
51 #include "netinet/ipl.h"
52 #include "kmem.h"
53
54 #ifdef  __hpux
55 # define        nlist   nlist64
56 #endif
57
58 #if     defined(sun) && !SOLARIS2
59 # define        STRERROR(x)     sys_errlist[x]
60 extern  char    *sys_errlist[];
61 #else
62 # define        STRERROR(x)     strerror(x)
63 #endif
64
65 #if !defined(lint)
66 static const char sccsid[] ="@(#)ipnat.c        1.9 6/5/96 (C) 1993 Darren Reed";
67 static const char rcsid[] = "@(#)$Id$";
68 #endif
69
70
71 #if     SOLARIS
72 #define bzero(a,b)      memset(a,0,b)
73 #endif
74 int     use_inet6 = 0;
75 char    thishost[MAXHOSTNAMELEN];
76
77 extern  char    *optarg;
78
79 void    dostats __P((int, natstat_t *, int, int, int *));
80 void    dotable __P((natstat_t *, int, int, int, char *));
81 void    flushtable __P((int, int, int *));
82 void    usage __P((char *));
83 int     main __P((int, char*[]));
84 void    showhostmap __P((natstat_t *nsp));
85 void    natstat_dead __P((natstat_t *, char *));
86 void    dostats_live __P((int, natstat_t *, int, int *));
87 void    showhostmap_dead __P((natstat_t *));
88 void    showhostmap_live __P((int, natstat_t *));
89 void    dostats_dead __P((natstat_t *, int, int *));
90 int     nat_matcharray __P((nat_t *, int *));
91
92 int             opts;
93 int             nohdrfields = 0;
94 wordtab_t       *nat_fields = NULL;
95
96 void usage(name)
97         char *name;
98 {
99         fprintf(stderr, "Usage: %s [-CFhlnrRsv] [-f filename]\n", name);
100         exit(1);
101 }
102
103
104 int main(argc, argv)
105         int argc;
106         char *argv[];
107 {
108         int fd, c, mode, *natfilter;
109         char *file, *core, *kernel;
110         natstat_t ns, *nsp;
111         ipfobj_t obj;
112
113         fd = -1;
114         opts = 0;
115         nsp = &ns;
116         file = NULL;
117         core = NULL;
118         kernel = NULL;
119         mode = O_RDWR;
120         natfilter = NULL;
121
122         assigndefined(getenv("IPNAT_PREDEFINED"));
123
124         while ((c = getopt(argc, argv, "CdFf:hlm:M:N:nO:prRsv")) != -1)
125                 switch (c)
126                 {
127                 case 'C' :
128                         opts |= OPT_CLEAR;
129                         break;
130                 case 'd' :
131                         opts |= OPT_DEBUG;
132                         break;
133                 case 'f' :
134                         file = optarg;
135                         break;
136                 case 'F' :
137                         opts |= OPT_FLUSH;
138                         break;
139                 case 'h' :
140                         opts |=OPT_HITS;
141                         break;
142                 case 'l' :
143                         opts |= OPT_LIST;
144                         mode = O_RDONLY;
145                         break;
146                 case 'm' :
147                         natfilter = parseipfexpr(optarg, NULL);
148                         break;
149                 case 'M' :
150                         core = optarg;
151                         break;
152                 case 'N' :
153                         kernel = optarg;
154                         break;
155                 case 'n' :
156                         opts |= OPT_DONOTHING|OPT_DONTOPEN;
157                         mode = O_RDONLY;
158                         break;
159                 case 'O' :
160                         nat_fields = parsefields(natfields, optarg);
161                         break;
162                 case 'p' :
163                         opts |= OPT_PURGE;
164                         break;
165                 case 'R' :
166                         opts |= OPT_NORESOLVE;
167                         break;
168                 case 'r' :
169                         opts |= OPT_REMOVE;
170                         break;
171                 case 's' :
172                         opts |= OPT_STAT;
173                         mode = O_RDONLY;
174                         break;
175                 case 'v' :
176                         opts |= OPT_VERBOSE;
177                         break;
178                 default :
179                         usage(argv[0]);
180                 }
181
182         if (((opts & OPT_PURGE) != 0) && ((opts & OPT_REMOVE) == 0)) {
183                 (void) fprintf(stderr, "%s: -p must be used with -r\n",
184                                argv[0]);
185                 exit(1);
186         }
187
188         initparse();
189
190         if ((kernel != NULL) || (core != NULL)) {
191                 (void) setgid(getgid());
192                 (void) setuid(getuid());
193         }
194
195         if (!(opts & OPT_DONOTHING)) {
196                 if (((fd = open(IPNAT_NAME, mode)) == -1) &&
197                     ((fd = open(IPNAT_NAME, O_RDONLY)) == -1)) {
198                         (void) fprintf(stderr, "%s: open: %s\n", IPNAT_NAME,
199                                 STRERROR(errno));
200                         exit(1);
201                 }
202         }
203
204         bzero((char *)&ns, sizeof(ns));
205
206         if ((opts & OPT_DONOTHING) == 0) {
207                 if (checkrev(IPL_NAME) == -1) {
208                         fprintf(stderr, "User/kernel version check failed\n");
209                         exit(1);
210                 }
211         }
212
213         if (!(opts & OPT_DONOTHING) && (kernel == NULL) && (core == NULL)) {
214                 bzero((char *)&obj, sizeof(obj));
215                 obj.ipfo_rev = IPFILTER_VERSION;
216                 obj.ipfo_type = IPFOBJ_NATSTAT;
217                 obj.ipfo_size = sizeof(*nsp);
218                 obj.ipfo_ptr = (void *)nsp;
219                 if (ioctl(fd, SIOCGNATS, &obj) == -1) {
220                         ipferror(fd, "ioctl(SIOCGNATS)");
221                         exit(1);
222                 }
223                 (void) setgid(getgid());
224                 (void) setuid(getuid());
225         } else if ((kernel != NULL) || (core != NULL)) {
226                 if (openkmem(kernel, core) == -1)
227                         exit(1);
228
229                 natstat_dead(nsp, kernel);
230                 if (opts & (OPT_LIST|OPT_STAT))
231                         dostats(fd, nsp, opts, 0, natfilter);
232                 exit(0);
233         }
234
235         if (opts & (OPT_FLUSH|OPT_CLEAR))
236                 flushtable(fd, opts, natfilter);
237         if (file) {
238                 return ipnat_parsefile(fd, ipnat_addrule, ioctl, file);
239         }
240         if (opts & (OPT_LIST|OPT_STAT))
241                 dostats(fd, nsp, opts, 1, natfilter);
242         return 0;
243 }
244
245
246 /*
247  * Read NAT statistic information in using a symbol table and memory file
248  * rather than doing ioctl's.
249  */
250 void natstat_dead(nsp, kernel)
251         natstat_t *nsp;
252         char *kernel;
253 {
254         struct nlist nat_nlist[10] = {
255                 { "nat_table" },                /* 0 */
256                 { "nat_list" },
257                 { "maptable" },
258                 { "ipf_nattable_sz" },
259                 { "ipf_natrules_sz" },
260                 { "ipf_rdrrules_sz" },          /* 5 */
261                 { "ipf_hostmap_sz" },
262                 { "nat_instances" },
263                 { NULL }
264         };
265         void *tables[2];
266
267         if (nlist(kernel, nat_nlist) == -1) {
268                 fprintf(stderr, "nlist error\n");
269                 return;
270         }
271
272         /*
273          * Normally the ioctl copies all of these values into the structure
274          * for us, before returning it to userland, so here we must copy each
275          * one in individually.
276          */
277         kmemcpy((char *)&tables, nat_nlist[0].n_value, sizeof(tables));
278         nsp->ns_side[0].ns_table = tables[0];
279         nsp->ns_side[1].ns_table = tables[1];
280
281         kmemcpy((char *)&nsp->ns_list, nat_nlist[1].n_value,
282                 sizeof(nsp->ns_list));
283         kmemcpy((char *)&nsp->ns_maptable, nat_nlist[2].n_value,
284                 sizeof(nsp->ns_maptable));
285         kmemcpy((char *)&nsp->ns_nattab_sz, nat_nlist[3].n_value,
286                 sizeof(nsp->ns_nattab_sz));
287         kmemcpy((char *)&nsp->ns_rultab_sz, nat_nlist[4].n_value,
288                 sizeof(nsp->ns_rultab_sz));
289         kmemcpy((char *)&nsp->ns_rdrtab_sz, nat_nlist[5].n_value,
290                 sizeof(nsp->ns_rdrtab_sz));
291         kmemcpy((char *)&nsp->ns_hostmap_sz, nat_nlist[6].n_value,
292                 sizeof(nsp->ns_hostmap_sz));
293         kmemcpy((char *)&nsp->ns_instances, nat_nlist[7].n_value,
294                 sizeof(nsp->ns_instances));
295 }
296
297
298 /*
299  * Issue an ioctl to flush either the NAT rules table or the active mapping
300  * table or both.
301  */
302 void flushtable(fd, opts, match)
303         int fd, opts, *match;
304 {
305         int n = 0;
306
307         if (opts & OPT_FLUSH) {
308                 n = 0;
309                 if (!(opts & OPT_DONOTHING)) {
310                         if (match != NULL) {
311                                 ipfobj_t obj;
312
313                                 obj.ipfo_rev = IPFILTER_VERSION;
314                                 obj.ipfo_size = match[0] * sizeof(int);
315                                 obj.ipfo_type = IPFOBJ_IPFEXPR;
316                                 obj.ipfo_ptr = match;
317                                 if (ioctl(fd, SIOCMATCHFLUSH, &obj) == -1) {
318                                         ipferror(fd, "ioctl(SIOCMATCHFLUSH)");
319                                         n = -1;
320                                 } else {
321                                         n = obj.ipfo_retval;
322                                 }
323                         } else if (ioctl(fd, SIOCIPFFL, &n) == -1) {
324                                 ipferror(fd, "ioctl(SIOCIPFFL)");
325                                 n = -1;
326                         }
327                 }
328                 if (n >= 0)
329                         printf("%d entries flushed from NAT table\n", n);
330         }
331
332         if (opts & OPT_CLEAR) {
333                 n = 1;
334                 if (!(opts & OPT_DONOTHING) && ioctl(fd, SIOCIPFFL, &n) == -1)
335                         ipferror(fd, "ioctl(SIOCCNATL)");
336                 else
337                         printf("%d entries flushed from NAT list\n", n);
338         }
339 }
340
341
342 /*
343  * Display NAT statistics.
344  */
345 void dostats_dead(nsp, opts, filter)
346         natstat_t *nsp;
347         int opts, *filter;
348 {
349         nat_t *np, nat;
350         ipnat_t ipn;
351         int i;
352
353         if (nat_fields == NULL) {
354                 printf("List of active MAP/Redirect filters:\n");
355                 while (nsp->ns_list) {
356                         if (kmemcpy((char *)&ipn, (long)nsp->ns_list,
357                                     sizeof(ipn))) {
358                                 perror("kmemcpy");
359                                 break;
360                         }
361                         if (opts & OPT_HITS)
362                                 printf("%lu ", ipn.in_hits);
363                         printnat(&ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
364                         nsp->ns_list = ipn.in_next;
365                 }
366         }
367
368         if (nat_fields == NULL) {
369                 printf("\nList of active sessions:\n");
370
371         } else if (nohdrfields == 0) {
372                 for (i = 0; nat_fields[i].w_value != 0; i++) {
373                         printfieldhdr(natfields, nat_fields + i);
374                         if (nat_fields[i + 1].w_value != 0)
375                                 printf("\t");
376                 }
377                 printf("\n");
378         }
379
380         for (np = nsp->ns_instances; np; np = nat.nat_next) {
381                 if (kmemcpy((char *)&nat, (long)np, sizeof(nat)))
382                         break;
383                 if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0))
384                         continue;
385                 if (nat_fields != NULL) {
386                         for (i = 0; nat_fields[i].w_value != 0; i++) {
387                                 printnatfield(&nat, nat_fields[i].w_value);
388                                 if (nat_fields[i + 1].w_value != 0)
389                                         printf("\t");
390                         }
391                         printf("\n");
392                 } else {
393                         printactivenat(&nat, opts, nsp->ns_ticks);
394                         if (nat.nat_aps) {
395                                 int proto;
396
397                                 if (nat.nat_dir & NAT_OUTBOUND)
398                                         proto = nat.nat_pr[1];
399                                 else
400                                         proto = nat.nat_pr[0];
401                                 printaps(nat.nat_aps, opts, proto);
402                         }
403                 }
404         }
405
406         if (opts & OPT_VERBOSE)
407                 showhostmap_dead(nsp);
408 }
409
410
411 void dotable(nsp, fd, alive, which, side)
412         natstat_t *nsp;
413         int fd, alive, which;
414         char *side;
415 {
416         int sz, i, used, maxlen, minlen, totallen;
417         ipftable_t table;
418         u_int *buckets;
419         ipfobj_t obj;
420
421         sz = sizeof(*buckets) * nsp->ns_nattab_sz;
422         buckets = (u_int *)malloc(sz);
423         if (buckets == NULL) {
424                 fprintf(stderr,
425                         "cannot allocate memory (%d) for buckets\n", sz);
426                 return;
427         }
428
429         obj.ipfo_rev = IPFILTER_VERSION;
430         obj.ipfo_type = IPFOBJ_GTABLE;
431         obj.ipfo_size = sizeof(table);
432         obj.ipfo_ptr = &table;
433
434         if (which == 0) {
435                 table.ita_type = IPFTABLE_BUCKETS_NATIN;
436         } else if (which == 1) {
437                 table.ita_type = IPFTABLE_BUCKETS_NATOUT;
438         }
439         table.ita_table = buckets;
440
441         if (alive) {
442                 if (ioctl(fd, SIOCGTABL, &obj) != 0) {
443                         ipferror(fd, "SIOCFTABL");
444                         free(buckets);
445                         return;
446                 }
447         } else {
448                 if (kmemcpy((char *)buckets, (u_long)nsp->ns_nattab_sz, sz)) {
449                         free(buckets);
450                         return;
451                 }
452         }
453
454         minlen = nsp->ns_side[which].ns_inuse;
455         totallen = 0;
456         maxlen = 0;
457         used = 0;
458
459         for (i = 0; i < nsp->ns_nattab_sz; i++) {
460                 if (buckets[i] > maxlen)
461                         maxlen = buckets[i];
462                 if (buckets[i] < minlen)
463                         minlen = buckets[i];
464                 if (buckets[i] != 0)
465                         used++;
466                 totallen += buckets[i];
467         }
468
469         printf("%d%%\thash efficiency %s\n",
470                totallen ? used * 100 / totallen : 0, side);
471         printf("%2.2f%%\tbucket usage %s\n",
472                ((float)used / nsp->ns_nattab_sz) * 100.0, side);
473         printf("%d\tminimal length %s\n", minlen, side);
474         printf("%d\tmaximal length %s\n", maxlen, side);
475         printf("%.3f\taverage length %s\n",
476                used ? ((float)totallen / used) : 0.0, side);
477
478         free(buckets);
479 }
480
481
482 void dostats(fd, nsp, opts, alive, filter)
483         natstat_t *nsp;
484         int fd, opts, alive, *filter;
485 {
486         /*
487          * Show statistics ?
488          */
489         if (opts & OPT_STAT) {
490                 printnatside("in", &nsp->ns_side[0]);
491                 dotable(nsp, fd, alive, 0, "in");
492
493                 printnatside("out", &nsp->ns_side[1]);
494                 dotable(nsp, fd, alive, 1, "out");
495
496                 printf("%lu\tlog successes\n", nsp->ns_side[0].ns_log);
497                 printf("%lu\tlog failures\n", nsp->ns_side[1].ns_log);
498                 printf("%lu\tadded in\n%lu\tadded out\n",
499                         nsp->ns_side[0].ns_added,
500                         nsp->ns_side[1].ns_added);
501                 printf("%u\tactive\n", nsp->ns_active);
502                 printf("%lu\ttransparent adds\n", nsp->ns_addtrpnt);
503                 printf("%lu\tdivert build\n", nsp->ns_divert_build);
504                 printf("%lu\texpired\n", nsp->ns_expire);
505                 printf("%lu\tflush all\n", nsp->ns_flush_all);
506                 printf("%lu\tflush closing\n", nsp->ns_flush_closing);
507                 printf("%lu\tflush queue\n", nsp->ns_flush_queue);
508                 printf("%lu\tflush state\n", nsp->ns_flush_state);
509                 printf("%lu\tflush timeout\n", nsp->ns_flush_timeout);
510                 printf("%lu\thostmap new\n", nsp->ns_hm_new);
511                 printf("%lu\thostmap fails\n", nsp->ns_hm_newfail);
512                 printf("%lu\thostmap add\n", nsp->ns_hm_addref);
513                 printf("%lu\thostmap NULL rule\n", nsp->ns_hm_nullnp);
514                 printf("%lu\tlog ok\n", nsp->ns_log_ok);
515                 printf("%lu\tlog fail\n", nsp->ns_log_fail);
516                 printf("%u\torphan count\n", nsp->ns_orphans);
517                 printf("%u\trule count\n", nsp->ns_rules);
518                 printf("%u\tmap rules\n", nsp->ns_rules_map);
519                 printf("%u\trdr rules\n", nsp->ns_rules_rdr);
520                 printf("%u\twilds\n", nsp->ns_wilds);
521                 if (opts & OPT_VERBOSE)
522                         printf("list %p\n", nsp->ns_list);
523         }
524
525         if (opts & OPT_LIST) {
526                 if (alive)
527                         dostats_live(fd, nsp, opts, filter);
528                 else
529                         dostats_dead(nsp, opts, filter);
530         }
531 }
532
533
534 /*
535  * Display NAT statistics.
536  */
537 void dostats_live(fd, nsp, opts, filter)
538         natstat_t *nsp;
539         int fd, opts, *filter;
540 {
541         ipfgeniter_t iter;
542         char buffer[2000];
543         ipfobj_t obj;
544         ipnat_t *ipn;
545         nat_t nat;
546         int i;
547
548         bzero((char *)&obj, sizeof(obj));
549         obj.ipfo_rev = IPFILTER_VERSION;
550         obj.ipfo_type = IPFOBJ_GENITER;
551         obj.ipfo_size = sizeof(iter);
552         obj.ipfo_ptr = &iter;
553
554         iter.igi_type = IPFGENITER_IPNAT;
555         iter.igi_nitems = 1;
556         iter.igi_data = buffer;
557         ipn = (ipnat_t *)buffer;
558
559         /*
560          * Show list of NAT rules and NAT sessions ?
561          */
562         if (nat_fields == NULL) {
563                 printf("List of active MAP/Redirect filters:\n");
564                 while (nsp->ns_list) {
565                         if (ioctl(fd, SIOCGENITER, &obj) == -1)
566                                 break;
567                         if (opts & OPT_HITS)
568                                 printf("%lu ", ipn->in_hits);
569                         printnat(ipn, opts & (OPT_DEBUG|OPT_VERBOSE));
570                         nsp->ns_list = ipn->in_next;
571                 }
572         }
573
574         if (nat_fields == NULL) {
575                 printf("\nList of active sessions:\n");
576
577         } else if (nohdrfields == 0) {
578                 for (i = 0; nat_fields[i].w_value != 0; i++) {
579                         printfieldhdr(natfields, nat_fields + i);
580                         if (nat_fields[i + 1].w_value != 0)
581                                 printf("\t");
582                 }
583                 printf("\n");
584         }
585
586         i = IPFGENITER_IPNAT;
587         (void) ioctl(fd,SIOCIPFDELTOK, &i);
588
589
590         iter.igi_type = IPFGENITER_NAT;
591         iter.igi_nitems = 1;
592         iter.igi_data = &nat;
593
594         while (nsp->ns_instances != NULL) {
595                 if (ioctl(fd, SIOCGENITER, &obj) == -1)
596                         break;
597                 if ((filter != NULL) && (nat_matcharray(&nat, filter) == 0))
598                         continue;
599                 if (nat_fields != NULL) {
600                         for (i = 0; nat_fields[i].w_value != 0; i++) {
601                                 printnatfield(&nat, nat_fields[i].w_value);
602                                 if (nat_fields[i + 1].w_value != 0)
603                                         printf("\t");
604                         }
605                         printf("\n");
606                 } else {
607                         printactivenat(&nat, opts, nsp->ns_ticks);
608                         if (nat.nat_aps) {
609                                 int proto;
610
611                                 if (nat.nat_dir & NAT_OUTBOUND)
612                                         proto = nat.nat_pr[1];
613                                 else
614                                         proto = nat.nat_pr[0];
615                                 printaps(nat.nat_aps, opts, proto);
616                         }
617                 }
618                 nsp->ns_instances = nat.nat_next;
619         }
620
621         if (opts & OPT_VERBOSE)
622                 showhostmap_live(fd, nsp);
623
624         i = IPFGENITER_NAT;
625         (void) ioctl(fd,SIOCIPFDELTOK, &i);
626 }
627
628
629 /*
630  * Display the active host mapping table.
631  */
632 void showhostmap_dead(nsp)
633         natstat_t *nsp;
634 {
635         hostmap_t hm, *hmp, **maptable;
636         u_int hv;
637
638         printf("\nList of active host mappings:\n");
639
640         maptable = (hostmap_t **)malloc(sizeof(hostmap_t *) *
641                                         nsp->ns_hostmap_sz);
642         if (kmemcpy((char *)maptable, (u_long)nsp->ns_maptable,
643                     sizeof(hostmap_t *) * nsp->ns_hostmap_sz)) {
644                 perror("kmemcpy (maptable)");
645                 return;
646         }
647
648         for (hv = 0; hv < nsp->ns_hostmap_sz; hv++) {
649                 hmp = maptable[hv];
650
651                 while (hmp) {
652                         if (kmemcpy((char *)&hm, (u_long)hmp, sizeof(hm))) {
653                                 perror("kmemcpy (hostmap)");
654                                 return;
655                         }
656
657                         printhostmap(&hm, hv);
658                         hmp = hm.hm_next;
659                 }
660         }
661         free(maptable);
662 }
663
664
665 /*
666  * Display the active host mapping table.
667  */
668 void showhostmap_live(fd, nsp)
669         int fd;
670         natstat_t *nsp;
671 {
672         ipfgeniter_t iter;
673         hostmap_t hm;
674         ipfobj_t obj;
675         int i;
676
677         bzero((char *)&obj, sizeof(obj));
678         obj.ipfo_rev = IPFILTER_VERSION;
679         obj.ipfo_type = IPFOBJ_GENITER;
680         obj.ipfo_size = sizeof(iter);
681         obj.ipfo_ptr = &iter;
682
683         iter.igi_type = IPFGENITER_HOSTMAP;
684         iter.igi_nitems = 1;
685         iter.igi_data = &hm;
686
687         printf("\nList of active host mappings:\n");
688
689         while (nsp->ns_maplist != NULL) {
690                 if (ioctl(fd, SIOCGENITER, &obj) == -1)
691                         break;
692                 printhostmap(&hm, hm.hm_hv);
693                 nsp->ns_maplist = hm.hm_next;
694         }
695
696         i = IPFGENITER_HOSTMAP;
697         (void) ioctl(fd,SIOCIPFDELTOK, &i);
698 }
699
700
701 int nat_matcharray(nat, array)
702         nat_t *nat;
703         int *array;
704 {
705         int i, n, *x, rv, p;
706         ipfexp_t *e;
707
708         rv = 0;
709         n = array[0];
710         x = array + 1;
711
712         for (; n > 0; x += 3 + x[3], rv = 0) {
713                 e = (ipfexp_t *)x;
714                 if (e->ipfe_cmd == IPF_EXP_END)
715                         break;
716                 n -= e->ipfe_size;
717
718                 p = e->ipfe_cmd >> 16;
719                 if ((p != 0) && (p != nat->nat_pr[1]))
720                         break;
721
722                 switch (e->ipfe_cmd)
723                 {
724                 case IPF_EXP_IP_PR :
725                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
726                                 rv |= (nat->nat_pr[1] == e->ipfe_arg0[i]);
727                         }
728                         break;
729
730                 case IPF_EXP_IP_SRCADDR :
731                         if (nat->nat_v[0] != 4)
732                                 break;
733                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
734                                 rv |= ((nat->nat_osrcaddr &
735                                         e->ipfe_arg0[i * 2 + 1]) ==
736                                        e->ipfe_arg0[i * 2]) ||
737                                       ((nat->nat_nsrcaddr &
738                                         e->ipfe_arg0[i * 2 + 1]) ==
739                                        e->ipfe_arg0[i * 2]);
740                         }
741                         break;
742
743                 case IPF_EXP_IP_DSTADDR :
744                         if (nat->nat_v[0] != 4)
745                                 break;
746                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
747                                 rv |= ((nat->nat_odstaddr &
748                                         e->ipfe_arg0[i * 2 + 1]) ==
749                                        e->ipfe_arg0[i * 2]) ||
750                                       ((nat->nat_ndstaddr &
751                                         e->ipfe_arg0[i * 2 + 1]) ==
752                                        e->ipfe_arg0[i * 2]);
753                         }
754                         break;
755
756                 case IPF_EXP_IP_ADDR :
757                         if (nat->nat_v[0] != 4)
758                                 break;
759                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
760                                 rv |= ((nat->nat_osrcaddr &
761                                         e->ipfe_arg0[i * 2 + 1]) ==
762                                        e->ipfe_arg0[i * 2]) ||
763                                       ((nat->nat_nsrcaddr &
764                                         e->ipfe_arg0[i * 2 + 1]) ==
765                                        e->ipfe_arg0[i * 2]) ||
766                                      ((nat->nat_odstaddr &
767                                         e->ipfe_arg0[i * 2 + 1]) ==
768                                        e->ipfe_arg0[i * 2]) ||
769                                      ((nat->nat_ndstaddr &
770                                         e->ipfe_arg0[i * 2 + 1]) ==
771                                        e->ipfe_arg0[i * 2]);
772                         }
773                         break;
774
775 #ifdef USE_INET6
776                 case IPF_EXP_IP6_SRCADDR :
777                         if (nat->nat_v[0] != 6)
778                                 break;
779                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
780                                 rv |= IP6_MASKEQ(&nat->nat_osrc6,
781                                                  &e->ipfe_arg0[i * 8 + 4],
782                                                  &e->ipfe_arg0[i * 8]) ||
783                                       IP6_MASKEQ(&nat->nat_nsrc6,
784                                                  &e->ipfe_arg0[i * 8 + 4],
785                                                  &e->ipfe_arg0[i * 8]);
786                         }
787                         break;
788
789                 case IPF_EXP_IP6_DSTADDR :
790                         if (nat->nat_v[0] != 6)
791                                 break;
792                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
793                                 rv |= IP6_MASKEQ(&nat->nat_odst6,
794                                                  &e->ipfe_arg0[i * 8 + 4],
795                                                  &e->ipfe_arg0[i * 8]) ||
796                                       IP6_MASKEQ(&nat->nat_ndst6,
797                                                  &e->ipfe_arg0[i * 8 + 4],
798                                                  &e->ipfe_arg0[i * 8]);
799                         }
800                         break;
801
802                 case IPF_EXP_IP6_ADDR :
803                         if (nat->nat_v[0] != 6)
804                                 break;
805                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
806                                 rv |= IP6_MASKEQ(&nat->nat_osrc6,
807                                                  &e->ipfe_arg0[i * 8 + 4],
808                                                  &e->ipfe_arg0[i * 8]) ||
809                                       IP6_MASKEQ(&nat->nat_nsrc6,
810                                                  &e->ipfe_arg0[i * 8 + 4],
811                                                  &e->ipfe_arg0[i * 8]) ||
812                                       IP6_MASKEQ(&nat->nat_odst6,
813                                                  &e->ipfe_arg0[i * 8 + 4],
814                                                  &e->ipfe_arg0[i * 8]) ||
815                                       IP6_MASKEQ(&nat->nat_ndst6,
816                                                  &e->ipfe_arg0[i * 8 + 4],
817                                                  &e->ipfe_arg0[i * 8]);
818                         }
819                         break;
820 #endif
821
822                 case IPF_EXP_UDP_PORT :
823                 case IPF_EXP_TCP_PORT :
824                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
825                                 rv |= (nat->nat_osport == e->ipfe_arg0[i]) ||
826                                       (nat->nat_nsport == e->ipfe_arg0[i]) ||
827                                       (nat->nat_odport == e->ipfe_arg0[i]) ||
828                                       (nat->nat_ndport == e->ipfe_arg0[i]);
829                         }
830                         break;
831
832                 case IPF_EXP_UDP_SPORT :
833                 case IPF_EXP_TCP_SPORT :
834                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
835                                 rv |= (nat->nat_osport == e->ipfe_arg0[i]) ||
836                                       (nat->nat_nsport == e->ipfe_arg0[i]);
837                         }
838                         break;
839
840                 case IPF_EXP_UDP_DPORT :
841                 case IPF_EXP_TCP_DPORT :
842                         for (i = 0; !rv && i < e->ipfe_narg; i++) {
843                                 rv |= (nat->nat_odport == e->ipfe_arg0[i]) ||
844                                       (nat->nat_ndport == e->ipfe_arg0[i]);
845                         }
846                         break;
847                 }
848                 rv ^= e->ipfe_not;
849
850                 if (rv == 0)
851                         break;
852         }
853
854         return rv;
855 }