3 * Copyright (C) 2001-2008 by Darren Reed.
5 * See the IPFILTER.LICENCE file for details on licencing.
7 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
8 * Use is subject to license terms.
11 #pragma ident "%Z%%M% %I% %E% SMI"
14 # ifndef __FreeBSD_cc_version
15 # include <osreldate.h>
17 # if __FreeBSD_cc_version < 430000
18 # include <osreldate.h>
27 #if !defined(__SVR4) && !defined(__GNUC__)
30 #include <sys/types.h>
31 #include <sys/param.h>
35 #include <sys/socket.h>
36 #include <sys/ioctl.h>
37 #include <netinet/in.h>
38 #include <netinet/in_systm.h>
42 #if __FreeBSD_version >= 300000
43 # include <net/if_var.h>
46 #include <arpa/nameser.h>
49 #include "netinet/ipl.h"
54 extern
void yyerror __P
((char *));
55 extern
int yyparse __P
((void));
56 extern
int yylex __P
((void));
61 static ipnat_t
*nattop
= NULL
;
62 static ipnat_t
*nat
= NULL
;
63 static int natfd
= -1;
64 static ioctlfunc_t natioctlfunc
= NULL
;
65 static addfunc_t nataddfunc
= NULL
;
67 static void newnatrule __P
((void));
68 static void setnatproto __P
((int));
94 %token
<num
> YY_NUMBER YY_HEX
97 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
98 %token YY_RANGE_OUT YY_RANGE_IN
101 %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
102 %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
103 %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
104 %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
105 %token IPNY_TLATE IPNY_SEQUENTIAL
106 %type
<port
> portspec
107 %type
<num
> hexnumber compare range proto
108 %type
<num
> saddr daddr sobject dobject mapfrom rdrfrom dip
109 %type
<ipa
> hostname ipv4 ipaddr
110 %type
<ipp
> addr rhaddr
119 line: xx rule
{ while
((nat
= nattop
) != NULL
) {
122 nattop
= nat
->in_next
;
123 (*nataddfunc
)(natfd
, natioctlfunc
, nat
);
131 assign: YY_STR assigning YY_STR
';' { set_variable
($1, $3);
139 '=' { yyvarnext
= 1; }
142 xx: { newnatrule
(); }
153 map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
154 { if
($3.v
!= 0 && $3.v
!= $5.v
&& $5.v
!= 0)
155 yyerror("1.address family mismatch");
156 bcopy
(&$3.a
, &nat
->in_in
[0], sizeof
($3.a
));
157 bcopy
(&$3.m
, &nat
->in_in
[1], sizeof
($3.a
));
158 bcopy
(&$5.a
, &nat
->in_out
[0], sizeof
($5.a
));
159 bcopy
(&$5.m
, &nat
->in_out
[1], sizeof
($5.a
));
160 if
(nat
->in_ifnames
[1][0] == '\0')
161 strncpy
(nat
->in_ifnames
[1],
163 sizeof
(nat
->in_ifnames
[0]));
164 if
((nat
->in_flags
& IPN_TCPUDP
) == 0)
165 setnatproto
(nat
->in_p
);
166 if
(((nat
->in_redir
& NAT_MAPBLK
) != 0) ||
167 ((nat
->in_flags
& IPN_AUTOPORTMAP
) != 0))
168 nat_setgroupmap
(nat
);
170 | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
171 { if
($3.v
!= 0 && $3.v
!= $5.v
&& $5.v
!= 0)
172 yyerror("2.address family mismatch");
173 bcopy
(&$3.a
, &nat
->in_in
[0], sizeof
($3.a
));
174 bcopy
(&$3.m
, &nat
->in_in
[1], sizeof
($3.a
));
175 bcopy
(&$5.a
, &nat
->in_out
[0], sizeof
($5.a
));
176 bcopy
(&$5.m
, &nat
->in_out
[1], sizeof
($5.a
));
177 if
(nat
->in_ifnames
[1][0] == '\0')
178 strncpy
(nat
->in_ifnames
[1],
180 sizeof
(nat
->in_ifnames
[0]));
181 if
((nat
->in_flags
& IPN_TCPUDPICMPQ
) == 0)
182 setnatproto
(nat
->in_p
);
183 if
(((nat
->in_redir
& NAT_MAPBLK
) != 0) ||
184 ((nat
->in_flags
& IPN_AUTOPORTMAP
) != 0))
185 nat_setgroupmap
(nat
);
187 | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
188 { if
($3 != 0 && $3 != $5.v
&& $5.v
!= 0)
189 yyerror("3.address family mismatch");
190 bcopy
(&$5.a
, &nat
->in_out
[0], sizeof
($5.a
));
191 bcopy
(&$5.m
, &nat
->in_out
[1], sizeof
($5.a
));
192 if
(nat
->in_ifnames
[1][0] == '\0')
193 strncpy
(nat
->in_ifnames
[1],
195 sizeof
(nat
->in_ifnames
[0]));
196 if
((nat
->in_flags
& IPN_TCPUDP
) == 0)
197 setnatproto
(nat
->in_p
);
198 if
(((nat
->in_redir
& NAT_MAPBLK
) != 0) ||
199 ((nat
->in_flags
& IPN_AUTOPORTMAP
) != 0))
200 nat_setgroupmap
(nat
);
202 | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
203 { if
($3 != 0 && $3 != $5.v
&& $5.v
!= 0)
204 yyerror("4.address family mismatch");
205 bcopy
(&$5.a
, &nat
->in_out
[0], sizeof
($5.a
));
206 bcopy
(&$5.m
, &nat
->in_out
[1], sizeof
($5.a
));
207 if
(nat
->in_ifnames
[1][0] == '\0')
208 strncpy
(nat
->in_ifnames
[1],
210 sizeof
(nat
->in_ifnames
[0]));
211 if
((nat
->in_flags
& IPN_TCPUDPICMPQ
) == 0)
212 setnatproto
(nat
->in_p
);
213 if
(((nat
->in_redir
& NAT_MAPBLK
) != 0) ||
214 ((nat
->in_flags
& IPN_AUTOPORTMAP
) != 0))
215 nat_setgroupmap
(nat
);
220 mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
221 { if
($3.v
!= 0 && $3.v
!= $5.v
&& $5.v
!= 0)
222 yyerror("5.address family mismatch");
223 bcopy
(&$3.a
, &nat
->in_in
[0], sizeof
($3.a
));
224 bcopy
(&$3.m
, &nat
->in_in
[1], sizeof
($3.a
));
225 bcopy
(&$5.a
, &nat
->in_out
[0], sizeof
($5.a
));
226 bcopy
(&$5.m
, &nat
->in_out
[1], sizeof
($5.a
));
227 if
(nat
->in_ifnames
[1][0] == '\0')
228 strncpy
(nat
->in_ifnames
[1],
230 sizeof
(nat
->in_ifnames
[0]));
231 if
((nat
->in_flags
& IPN_TCPUDP
) == 0)
232 setnatproto
(nat
->in_p
);
233 if
(((nat
->in_redir
& NAT_MAPBLK
) != 0) ||
234 ((nat
->in_flags
& IPN_AUTOPORTMAP
) != 0))
235 nat_setgroupmap
(nat
);
239 redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
240 { if
($6 != 0 && $3.v
!= 0 && $6 != $3.v
)
241 yyerror("6.address family mismatch");
242 bcopy
(&$3.a
, &nat
->in_out
[0], sizeof
($3.a
));
243 bcopy
(&$3.m
, &nat
->in_out
[1], sizeof
($3.a
));
244 if
(nat
->in_ifnames
[1][0] == '\0')
245 strncpy
(nat
->in_ifnames
[1],
247 sizeof
(nat
->in_ifnames
[0]));
248 if
((nat
->in_p
== 0) &&
249 ((nat
->in_flags
& IPN_TCPUDP
) == 0) &&
250 (nat
->in_pmin
!= 0 ||
253 setnatproto
(IPPROTO_TCP
);
255 | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
256 { if
($5 != 0 && $3 != 0 && $5 != $3)
257 yyerror("7.address family mismatch");
258 if
((nat
->in_p
== 0) &&
259 ((nat
->in_flags
& IPN_TCPUDP
) == 0) &&
260 (nat
->in_pmin
!= 0 ||
263 setnatproto
(IPPROTO_TCP
);
264 if
(nat
->in_ifnames
[1][0] == '\0')
265 strncpy
(nat
->in_ifnames
[1],
267 sizeof
(nat
->in_ifnames
[0]));
269 | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
270 { if
($5 != 0 && $3.v
!= 0 && $5 != $3.v
)
271 yyerror("8.address family mismatch");
272 bcopy
(&$3.a
, &nat
->in_out
[0], sizeof
($3.a
));
273 bcopy
(&$3.m
, &nat
->in_out
[1], sizeof
($3.a
));
274 if
(nat
->in_ifnames
[1][0] == '\0')
275 strncpy
(nat
->in_ifnames
[1],
277 sizeof
(nat
->in_ifnames
[0]));
281 proxy: | IPNY_PROXY IPNY_PORT portspec YY_STR
'/' proto
282 { strncpy
(nat
->in_plabel
, $4, sizeof
(nat
->in_plabel
));
283 if
(nat
->in_dcmp
== 0) {
284 nat
->in_dport
= htons
($3);
285 } else if
($3 != nat
->in_dport
) {
286 yyerror("proxy port numbers not consistant");
291 | IPNY_PROXY IPNY_PORT YY_STR YY_STR
'/' proto
293 strncpy
(nat
->in_plabel
, $4, sizeof
(nat
->in_plabel
));
294 pnum
= getportproto
($3, $6);
296 yyerror("invalid port number");
297 nat
->in_dport
= pnum
;
305 | proto
{ if
(nat
->in_p
!= 0 ||
306 nat
->in_flags
& IPN_TCPUDP
)
307 yyerror("protocol set twice");
310 | IPNY_TCPUDP
{ if
(nat
->in_p
!= 0 ||
311 nat
->in_flags
& IPN_TCPUDP
)
312 yyerror("protocol set twice");
313 nat
->in_flags |
= IPN_TCPUDP
;
316 | IPNY_TCP
'/' IPNY_UDP
{ if
(nat
->in_p
!= 0 ||
317 nat
->in_flags
& IPN_TCPUDP
)
318 yyerror("protocol set twice");
319 nat
->in_flags |
= IPN_TCPUDP
;
324 rhaddr: addr
{ $$.a
= $1.a
;
330 | IPNY_RANGE hostname
'-' hostname
331 { if
($2.v
!= 0 && $4.v
!= 0 && $4.v
!= $2.v
)
332 yyerror("9.address family "
337 nat
->in_flags |
= IPN_IPRANGE
;
342 hostname
{ bcopy
(&$1.a
, &nat
->in_in
[0],
347 nat
->in_inmsk
= 0xffffffff;
349 nat
->in_in
[1].i6
[0] = 0xffffffff;
350 nat
->in_in
[1].i6
[1] = 0xffffffff;
351 nat
->in_in
[1].i6
[2] = 0xffffffff;
352 nat
->in_in
[1].i6
[3] = 0xffffffff;
356 | hostname
'/' YY_NUMBER
{ if
($1.v
== 0)
359 ($1.a.in4.s_addr
!= 0 ||
360 ($3 != 0 && $3 != 32)))
361 yyerror("Invalid mask for dip");
362 else if
($1.v
== 6 &&
363 ($1.a.in4.s_addr
!= 0 ||
364 ($3 != 0 && $3 != 128)))
365 yyerror("Invalid mask for dip");
366 else if
($1.v
== 0 ) {
367 if
($1.a.in4.s_addr
== 0 &&
368 ($3 == 32 ||
$3 == 0))
373 bcopy
(&$1.a
, &nat
->in_in
[0],
376 (u_32_t
*)&nat
->in_in
[1]);
377 nat
->in_in
[0].i6
[0] &= nat
->in_in
[1].i6
[0];
378 nat
->in_in
[0].i6
[0] &= nat
->in_in
[1].i6
[1];
379 nat
->in_in
[0].i6
[0] &= nat
->in_in
[1].i6
[2];
380 nat
->in_in
[0].i6
[0] &= nat
->in_in
[1].i6
[3];
384 | hostname
',' { yyexpectaddr
= 1; } hostname
386 yyerror("10.address family "
389 nat
->in_flags |
= IPN_SPLIT
;
390 bcopy
(&$1.a
, &nat
->in_in
[0],
392 bcopy
(&$4.a
, &nat
->in_in
[1],
398 YY_NUMBER
{ if
($1 > 65535) /* Unsigned */
399 yyerror("invalid port number");
403 | YY_STR
{ if
(getport
(NULL
, $1, &($$
)) == -1)
404 yyerror("invalid port number");
409 dport: | IPNY_PORT portspec
{ nat
->in_pmin
= htons
($2);
410 nat
->in_pmax
= htons
($2); }
411 | IPNY_PORT portspec
'-' portspec
{ nat
->in_pmin
= htons
($2);
412 nat
->in_pmax
= htons
($4); }
413 | IPNY_PORT portspec
':' portspec
{ nat
->in_pmin
= htons
($2);
414 nat
->in_pmax
= htons
($4); }
417 nport: IPNY_PORT portspec
{ nat
->in_pnext
= htons
($2); }
418 | IPNY_PORT
'=' portspec
{ nat
->in_pnext
= htons
($3);
419 nat
->in_flags |
= IPN_FIXEDDPORT
;
423 ports: | IPNY_PORTS YY_NUMBER
{ nat
->in_pmin
= $2; }
424 | IPNY_PORTS IPNY_AUTO
{ nat
->in_flags |
= IPN_AUTOPORTMAP
; }
427 mapit: IPNY_MAP
{ nat
->in_redir
= NAT_MAP
; }
428 | IPNY_BIMAP
{ nat
->in_redir
= NAT_BIMAP
; }
431 rdrit: IPNY_RDR
{ nat
->in_redir
= NAT_REDIRECT
; }
435 IPNY_MAPBLOCK
{ nat
->in_redir
= NAT_MAPBLK
; }
439 from sobject IPNY_TO dobject
{ if
($2 != 0 && $4 != 0 && $2 != $4)
440 yyerror("11.address family "
444 | from sobject
'!' IPNY_TO dobject
445 { if
($2 != 0 && $5 != 0 && $2 != $5)
446 yyerror("12.address family "
448 nat
->in_flags |
= IPN_NOTDST
;
454 from sobject IPNY_TO dobject
{ if
($2 != 0 && $4 != 0 && $2 != $4)
455 yyerror("13.address family "
459 |
'!' from sobject IPNY_TO dobject
460 { if
($3 != 0 && $5 != 0 && $3 != $5)
461 yyerror("14.address family "
463 nat
->in_flags |
= IPN_NOTSRC
;
468 from: IPNY_FROM
{ nat
->in_flags |
= IPN_FILTER
;
473 ifname
{ yyexpectaddr
= 1; }
474 | ifname
',' otherifname
{ yyexpectaddr
= 1; }
477 ifname: YY_STR
{ strncpy
(nat
->in_ifnames
[0], $1,
478 sizeof
(nat
->in_ifnames
[0]));
479 nat
->in_ifnames
[0][LIFNAMSIZ
- 1] = '\0';
485 YY_STR
{ strncpy
(nat
->in_ifnames
[1], $1,
486 sizeof
(nat
->in_ifnames
[1]));
487 nat
->in_ifnames
[1][LIFNAMSIZ
- 1] = '\0';
493 IPNY_PORTMAP tcpudp portspec
':' portspec randport
494 { nat
->in_pmin
= htons
($3);
495 nat
->in_pmax
= htons
($5);
497 | IPNY_PORTMAP tcpudp IPNY_AUTO randport
498 { nat
->in_flags |
= IPN_AUTOPORTMAP
;
499 nat
->in_pmin
= htons
(1024);
500 nat
->in_pmax
= htons
(65535);
502 | IPNY_ICMPIDMAP YY_STR YY_NUMBER
':' YY_NUMBER
503 { if
(strcmp
($2, "icmp") != 0) {
504 yyerror("icmpidmap not followed by icmp");
507 if
($3 < 0 ||
$3 > 65535)
508 yyerror("invalid ICMP Id number");
509 if
($5 < 0 ||
$5 > 65535)
510 yyerror("invalid ICMP Id number");
511 nat
->in_flags
= IPN_ICMPQUERY
;
512 nat
->in_pmin
= htons
($3);
513 nat
->in_pmax
= htons
($5);
518 | IPNY_SEQUENTIAL
{ nat
->in_flags |
= IPN_SEQUENTIAL
; }
523 | saddr IPNY_PORT portstuff
{ nat
->in_sport
= $3.p1
;
524 nat
->in_stop
= $3.p2
;
525 nat
->in_scmp
= $3.pc
;
530 saddr: addr
{ if
(nat
->in_redir
== NAT_REDIRECT
) {
531 bcopy
(&$1.a
, &nat
->in_src
[0],
533 bcopy
(&$1.m
, &nat
->in_src
[1],
536 bcopy
(&$1.a
, &nat
->in_in
[0],
538 bcopy
(&$1.m
, &nat
->in_in
[1],
547 | daddr IPNY_PORT portstuff
{ nat
->in_dport
= $3.p1
;
548 nat
->in_dtop
= $3.p2
;
549 nat
->in_dcmp
= $3.pc
;
550 if
(nat
->in_redir
== NAT_REDIRECT
)
551 nat
->in_pmin
= htons
($3.p1
);
555 daddr: addr
{ if
(nat
->in_redir
== NAT_REDIRECT
) {
556 bcopy
(&$1.a
, &nat
->in_out
[0],
558 bcopy
(&$1.m
, &nat
->in_out
[1],
561 bcopy
(&$1.a
, &nat
->in_src
[0],
563 bcopy
(&$1.m
, &nat
->in_src
[1],
570 addr: IPNY_ANY
{ yyexpectaddr
= 0;
571 bzero
(&$$.a
, sizeof
($$.a
));
572 bzero
(&$$.m
, sizeof
($$.a
));
575 | hostname
{ $$.a
= $1.a
;
578 $$.m.in4.s_addr
= 0xffffffff;
580 $$.m.i6
[0] = 0xffffffff;
581 $$.m.i6
[1] = 0xffffffff;
582 $$.m.i6
[2] = 0xffffffff;
583 $$.m.i6
[3] = 0xffffffff;
587 | hostname
'/' YY_NUMBER
{ $$.a
= $1.a
;
589 if
($1.a.in4.s_addr
!= 0)
590 yyerror("invalid addr");
591 if
($3 == 0 ||
$3 == 32)
596 yyerror("invalid mask");
599 ntomask
($1.v
, $3, (u_32_t
*)&$$.m
);
600 $$.a.i6
[0] &= $$.m.i6
[0];
601 $$.a.i6
[1] &= $$.m.i6
[1];
602 $$.a.i6
[2] &= $$.m.i6
[2];
603 $$.a.i6
[3] &= $$.m.i6
[3];
607 | hostname
'/' ipaddr
{ if
($1.v
!= $3.v
) {
608 yyerror("1.address family "
613 $$.a.i6
[0] &= $$.m.i6
[0];
614 $$.a.i6
[1] &= $$.m.i6
[1];
615 $$.a.i6
[2] &= $$.m.i6
[2];
616 $$.a.i6
[3] &= $$.m.i6
[3];
620 | hostname
'/' hexnumber
{ $$.a
= $1.a
;
621 $$.m.in4.s_addr
= htonl
($3);
622 $$.a.in4.s_addr
&= $$.m.in4.s_addr
;
625 | hostname IPNY_MASK ipaddr
{ if
($1.v
!= $3.v
) {
626 yyerror("2.address family "
631 $$.a.i6
[0] &= $$.m.i6
[0];
632 $$.a.i6
[1] &= $$.m.i6
[1];
633 $$.a.i6
[2] &= $$.m.i6
[2];
634 $$.a.i6
[3] &= $$.m.i6
[3];
638 | hostname IPNY_MASK hexnumber
{ $$.a
= $1.a
;
639 $$.m.in4.s_addr
= htonl
($3);
640 $$.a.in4.s_addr
&= $$.m.in4.s_addr
;
646 compare portspec
{ $$.pc
= $1; $$.p1
= $2; }
647 | portspec range portspec
{ $$.pc
= $2; $$.p1
= $1; $$.p2
= $3; }
651 rr frag age mssclamp nattag setproto
655 rr frag age sticky mssclamp rdrproxy nattag
658 nattag: | IPNY_TAG YY_STR
{ strncpy
(nat
->in_tag.ipt_tag
, $2,
659 sizeof
(nat
->in_tag.ipt_tag
));
662 rr: | IPNY_ROUNDROBIN
{ nat
->in_flags |
= IPN_ROUNDR
; }
665 frag: | IPNY_FRAG
{ nat
->in_flags |
= IPN_FRAG
; }
668 age: | IPNY_AGE YY_NUMBER
{ nat
->in_age
[0] = $2;
669 nat
->in_age
[1] = $2; }
670 | IPNY_AGE YY_NUMBER
'/' YY_NUMBER
{ nat
->in_age
[0] = $2;
671 nat
->in_age
[1] = $4; }
674 sticky: | IPNY_STICKY
{ if
(!(nat
->in_flags
& IPN_ROUNDR
) &&
675 !(nat
->in_flags
& IPN_SPLIT
)) {
677 "'sticky' for use with round-robin/IP splitting only\n");
679 nat
->in_flags |
= IPN_STICKY
;
684 | IPNY_MSSCLAMP YY_NUMBER
{ nat
->in_mssclamp
= $2; }
687 tcpudp: | IPNY_TCP
{ setnatproto
(IPPROTO_TCP
); }
688 | IPNY_UDP
{ setnatproto
(IPPROTO_UDP
); }
689 | IPNY_TCPUDP
{ nat
->in_flags |
= IPN_TCPUDP
;
692 | IPNY_TCP
'/' IPNY_UDP
{ nat
->in_flags |
= IPN_TCPUDP
;
699 { strncpy
(nat
->in_plabel
, $2,
700 sizeof
(nat
->in_plabel
));
701 nat
->in_dport
= nat
->in_pnext
;
702 nat
->in_dport
= htons
(nat
->in_dport
);
705 | proxy
{ if
(nat
->in_plabel
[0] != '\0') {
706 nat
->in_pmin
= nat
->in_dport
;
707 nat
->in_pmax
= nat
->in_pmin
;
708 nat
->in_pnext
= nat
->in_pmin
;
713 proto: YY_NUMBER
{ $$
= $1; }
714 | IPNY_TCP
{ $$
= IPPROTO_TCP
; }
715 | IPNY_UDP
{ $$
= IPPROTO_UDP
; }
716 | YY_STR
{ $$
= getproto
($1); free
($1); }
724 YY_STR
{ i6addr_t addr
;
725 if
(gethost
($1, &addr
, 0) == 0) {
729 if
(gethost
($1, &addr
, 1) == 0) {
733 yyerror("Unknown hostname");
739 | YY_NUMBER
{ bzero
(&$$.a
, sizeof
($$.a
));
740 $$.a.in4.s_addr
= htonl
($1);
741 if
($$.a.in4.s_addr
!= 0)
751 | YY_IPV6
{ $$.a
= $1;
755 | YY_NUMBER YY_IPV6
{ $$.a
= $2;
761 '=' { $$
= FR_EQUAL
; }
762 | YY_CMP_EQ
{ $$
= FR_EQUAL
; }
763 | YY_CMP_NE
{ $$
= FR_NEQUAL
; }
764 | YY_CMP_LT
{ $$
= FR_LESST
; }
765 | YY_CMP_LE
{ $$
= FR_LESSTE
; }
766 | YY_CMP_GT
{ $$
= FR_GREATERT
; }
767 | YY_CMP_GE
{ $$
= FR_GREATERTE
; }
770 YY_RANGE_OUT
{ $$
= FR_OUTRANGE
; }
771 | YY_RANGE_IN
{ $$
= FR_INRANGE
; }
774 ipaddr: ipv4
{ $$
= $1; }
775 | YY_IPV6
{ $$.a
= $1;
780 ipv4: YY_NUMBER
'.' YY_NUMBER
'.' YY_NUMBER
'.' YY_NUMBER
781 { if
($1 > 255 ||
$3 > 255 ||
$5 > 255 ||
$7 > 255) {
782 yyerror("Invalid octet string for IP address");
785 $$.a.in4.s_addr
= ($1 << 24) |
($3 << 16) |
($5 << 8) |
$7;
786 $$.a.in4.s_addr
= htonl
($$.a.in4.s_addr
);
794 static wordtab_t yywords
[] = {
797 { "auto", IPNY_AUTO
},
798 { "bimap", IPNY_BIMAP
},
799 { "frag", IPNY_FRAG
},
800 { "from", IPNY_FROM
},
801 { "icmpidmap", IPNY_ICMPIDMAP
},
802 { "mask", IPNY_MASK
},
804 { "map-block", IPNY_MAPBLOCK
},
805 { "mssclamp", IPNY_MSSCLAMP
},
806 { "netmask", IPNY_MASK
},
807 { "port", IPNY_PORT
},
808 { "portmap", IPNY_PORTMAP
},
809 { "ports", IPNY_PORTS
},
810 { "proxy", IPNY_PROXY
},
811 { "range", IPNY_RANGE
},
813 { "round-robin",IPNY_ROUNDROBIN
},
814 { "sequential", IPNY_SEQUENTIAL
},
815 { "sticky", IPNY_STICKY
},
818 { "tcpudp", IPNY_TCPUDP
},
822 { "->", IPNY_TLATE
},
833 int ipnat_parsefile
(fd
, addfunc
, ioctlfunc
, filename
)
836 ioctlfunc_t ioctlfunc
;
842 (void) yysettab
(yywords
);
844 s
= getenv
("YYDEBUG");
850 if
(strcmp
(filename
, "-")) {
851 fp
= fopen
(filename
, "r");
853 fprintf
(stderr
, "fopen(%s) failed: %s\n", filename
,
860 while
(ipnat_parsesome
(fd
, addfunc
, ioctlfunc
, fp
) == 1)
868 int ipnat_parsesome
(fd
, addfunc
, ioctlfunc
, fp
)
871 ioctlfunc_t ioctlfunc
;
880 nataddfunc
= addfunc
;
881 natioctlfunc
= ioctlfunc
;
888 if
(ungetc
(i
, fp
) == EOF
)
892 s
= getenv
("YYDEBUG");
904 static void newnatrule
()
908 n
= calloc
(1, sizeof
(*n
));
921 static void setnatproto
(p
)
929 nat
->in_flags |
= IPN_TCP
;
930 nat
->in_flags
&= ~IPN_UDP
;
933 nat
->in_flags |
= IPN_UDP
;
934 nat
->in_flags
&= ~IPN_TCP
;
937 nat
->in_flags
&= ~IPN_TCPUDP
;
938 if
(!(nat
->in_flags
& IPN_ICMPQUERY
)) {
947 if
((nat
->in_redir
& NAT_MAPBLK
) == 0) {
948 /* Only reset dcmp/scmp in case dport/sport not set */
949 if
(0 == nat
->in_tuc.ftu_dport
)
951 if
(0 == nat
->in_tuc.ftu_sport
)
956 nat
->in_flags
&= ~IPN_TCPUDP
;
961 if
((nat
->in_flags
& (IPN_TCPUDP|IPN_FIXEDDPORT
)) == IPN_FIXEDDPORT
)
962 nat
->in_flags
&= ~IPN_FIXEDDPORT
;
966 void ipnat_addrule
(fd
, ioctlfunc
, ptr
)
968 ioctlfunc_t ioctlfunc
;
976 bzero
((char *)&obj
, sizeof
(obj
));
977 obj.ipfo_rev
= IPFILTER_VERSION
;
978 obj.ipfo_size
= sizeof
(ipnat_t
);
979 obj.ipfo_type
= IPFOBJ_IPNAT
;
984 if
((opts
& OPT_DONOTHING
) != 0)
987 if
(opts
& OPT_ZERORULEST
) {
989 } else if
(opts
& OPT_INACTIVE
) {
997 if
(ipn
&& (opts
& OPT_VERBOSE
))
1000 if
(opts
& OPT_DEBUG
)
1001 binprint
(ipn
, sizeof
(*ipn
));
1003 if
((opts
& OPT_ZERORULEST
) != 0) {
1004 if
((*ioctlfunc
)(fd
, add
, (void *)&obj
) == -1) {
1005 if
((opts
& OPT_DONOTHING
) == 0) {
1006 fprintf
(stderr
, "%d:", yylineNum
);
1007 perror
("ioctl(SIOCZRLST)");
1012 printf("hits %qd bytes %qd ",
1013 (long long)fr->fr_hits,
1014 (long long)fr->fr_bytes);
1018 printf("hits %ld bytes %ld ",
1019 fr->fr_hits, fr->fr_bytes);
1022 printnat
(ipn
, opts
);
1024 } else if
((opts
& OPT_REMOVE
) != 0) {
1025 if
((*ioctlfunc
)(fd
, del
, (void *)&obj
) == -1) {
1026 if
((opts
& OPT_DONOTHING
) == 0) {
1027 fprintf
(stderr
, "%d:", yylineNum
);
1028 perror
("ioctl(delete nat rule)");
1032 if
((*ioctlfunc
)(fd
, add
, (void *)&obj
) == -1) {
1033 if
((opts
& OPT_DONOTHING
) == 0) {
1034 fprintf
(stderr
, "%d:", yylineNum
);
1035 perror
("ioctl(add/insert nat rule)");