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