Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ipf / tools / ipnat_y.y
blobe2e8383309c20c498155b010e917ea4cbfd72f81
1 /* $NetBSD: ipnat_y.y,v 1.15 2007/04/14 20:34:35 martin Exp $ */
3 /*
4 * Copyright (C) 2001-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 %{
9 #ifdef __FreeBSD__
10 # ifndef __FreeBSD_cc_version
11 # include <osreldate.h>
12 # else
13 # if __FreeBSD_cc_version < 430000
14 # include <osreldate.h>
15 # endif
16 # endif
17 #endif
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <fcntl.h>
22 #include <errno.h>
23 #if !defined(__SVR4) && !defined(__GNUC__)
24 #include <strings.h>
25 #endif
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/file.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <sys/time.h>
36 #include <syslog.h>
37 #include <net/if.h>
38 #if __FreeBSD_version >= 300000
39 # include <net/if_var.h>
40 #endif
41 #include <netdb.h>
42 #include <arpa/nameser.h>
43 #include <resolv.h>
44 #include "ipf.h"
45 #include "netinet/ipl.h"
46 #include "ipnat_l.h"
48 #define YYDEBUG 1
50 extern void yyerror __P((char *));
51 extern int yyparse __P((void));
52 extern int yylex __P((void));
53 extern int yydebug;
54 extern FILE *yyin;
55 extern int yylineNum;
57 static ipnat_t *nattop = NULL;
58 static ipnat_t *nat = NULL;
59 static int natfd = -1;
60 static ioctlfunc_t natioctlfunc = NULL;
61 static addfunc_t nataddfunc = NULL;
62 static int suggest_port = 0;
64 static void newnatrule __P((void));
65 static void setnatproto __P((int));
68 %union {
69 char *str;
70 u_32_t num;
71 struct in_addr ipa;
72 frentry_t fr;
73 frtuc_t *frt;
74 u_short port;
75 struct {
76 u_short p1;
77 u_short p2;
78 int pc;
79 } pc;
80 struct {
81 struct in_addr a;
82 struct in_addr m;
83 } ipp;
84 union i6addr ip6;
87 %token <num> YY_NUMBER YY_HEX
88 %token <str> YY_STR
89 %token YY_COMMENT
90 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
91 %token YY_RANGE_OUT YY_RANGE_IN
92 %token <ip6> YY_IPV6
94 %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
95 %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
96 %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
97 %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
98 %token IPNY_TLATE IPNY_SEQUENTIAL
99 %type <port> portspec
100 %type <num> hexnumber compare range proto
101 %type <ipa> hostname ipv4
102 %type <ipp> addr nummask rhaddr
103 %type <pc> portstuff
105 file: line
106 | assign
107 | file line
108 | file assign
111 line: xx rule { while ((nat = nattop) != NULL) {
112 nattop = nat->in_next;
113 (*nataddfunc)(natfd, natioctlfunc, nat);
114 free(nat);
116 resetlexer();
118 | YY_COMMENT
121 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
122 resetlexer();
123 free($1);
124 free($3);
125 yyvarnext = 0;
129 assigning:
130 '=' { yyvarnext = 1; }
133 xx: { newnatrule(); }
136 rule: map eol
137 | mapblock eol
138 | redir eol
141 eol: | ';'
144 map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
145 { nat->in_v = 4;
146 nat->in_inip = $3.a.s_addr;
147 nat->in_inmsk = $3.m.s_addr;
148 nat->in_outip = $5.a.s_addr;
149 nat->in_outmsk = $5.m.s_addr;
150 if (nat->in_ifnames[1][0] == '\0')
151 strncpy(nat->in_ifnames[1],
152 nat->in_ifnames[0],
153 sizeof(nat->in_ifnames[0]));
154 if ((nat->in_flags & IPN_TCPUDP) == 0)
155 setnatproto(nat->in_p);
156 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
157 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
158 nat_setgroupmap(nat);
160 | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
161 { nat->in_v = 4;
162 nat->in_inip = $3.a.s_addr;
163 nat->in_inmsk = $3.m.s_addr;
164 nat->in_outip = $5.a.s_addr;
165 nat->in_outmsk = $5.m.s_addr;
166 if (nat->in_ifnames[1][0] == '\0')
167 strncpy(nat->in_ifnames[1],
168 nat->in_ifnames[0],
169 sizeof(nat->in_ifnames[0]));
170 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
171 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
172 nat_setgroupmap(nat);
174 | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
175 { nat->in_v = 4;
176 nat->in_outip = $5.a.s_addr;
177 nat->in_outmsk = $5.m.s_addr;
178 if (nat->in_ifnames[1][0] == '\0')
179 strncpy(nat->in_ifnames[1],
180 nat->in_ifnames[0],
181 sizeof(nat->in_ifnames[0]));
182 if ((suggest_port == 1) &&
183 (nat->in_flags & IPN_TCPUDP) == 0)
184 nat->in_flags |= IPN_TCPUDP;
185 if ((nat->in_flags & IPN_TCPUDP) == 0)
186 setnatproto(nat->in_p);
187 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
188 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
189 nat_setgroupmap(nat);
191 | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
192 { nat->in_v = 4;
193 nat->in_outip = $5.a.s_addr;
194 nat->in_outmsk = $5.m.s_addr;
195 if (nat->in_ifnames[1][0] == '\0')
196 strncpy(nat->in_ifnames[1],
197 nat->in_ifnames[0],
198 sizeof(nat->in_ifnames[0]));
199 if ((suggest_port == 1) &&
200 (nat->in_flags & IPN_TCPUDP) == 0)
201 nat->in_flags |= IPN_TCPUDP;
202 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
203 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
204 nat_setgroupmap(nat);
208 mapblock:
209 mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
210 { nat->in_v = 4;
211 nat->in_inip = $3.a.s_addr;
212 nat->in_inmsk = $3.m.s_addr;
213 nat->in_outip = $5.a.s_addr;
214 nat->in_outmsk = $5.m.s_addr;
215 if (nat->in_ifnames[1][0] == '\0')
216 strncpy(nat->in_ifnames[1],
217 nat->in_ifnames[0],
218 sizeof(nat->in_ifnames[0]));
219 if ((nat->in_flags & IPN_TCPUDP) == 0)
220 setnatproto(nat->in_p);
221 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
222 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
223 nat_setgroupmap(nat);
227 redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
228 { nat->in_v = 4;
229 nat->in_outip = $3.a.s_addr;
230 nat->in_outmsk = $3.m.s_addr;
231 if (nat->in_ifnames[1][0] == '\0')
232 strncpy(nat->in_ifnames[1],
233 nat->in_ifnames[0],
234 sizeof(nat->in_ifnames[0]));
235 if ((nat->in_p == 0) &&
236 ((nat->in_flags & IPN_TCPUDP) == 0) &&
237 (nat->in_pmin != 0 ||
238 nat->in_pmax != 0 ||
239 nat->in_pnext != 0))
240 setnatproto(IPPROTO_TCP);
242 | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
243 { nat->in_v = 4;
244 if ((nat->in_p == 0) &&
245 ((nat->in_flags & IPN_TCPUDP) == 0) &&
246 (nat->in_pmin != 0 ||
247 nat->in_pmax != 0 ||
248 nat->in_pnext != 0))
249 setnatproto(IPPROTO_TCP);
250 if ((suggest_port == 1) &&
251 (nat->in_flags & IPN_TCPUDP) == 0)
252 nat->in_flags |= IPN_TCPUDP;
253 if (nat->in_ifnames[1][0] == '\0')
254 strncpy(nat->in_ifnames[1],
255 nat->in_ifnames[0],
256 sizeof(nat->in_ifnames[0]));
258 | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
259 { nat->in_v = 4;
260 nat->in_outip = $3.a.s_addr;
261 nat->in_outmsk = $3.m.s_addr;
262 if (nat->in_ifnames[1][0] == '\0')
263 strncpy(nat->in_ifnames[1],
264 nat->in_ifnames[0],
265 sizeof(nat->in_ifnames[0]));
267 | rdrit ifnames rdrfrom IPNY_TLATE dip setproto rdroptions
268 { nat->in_v = 4;
269 if ((suggest_port == 1) &&
270 (nat->in_flags & IPN_TCPUDP) == 0)
271 nat->in_flags |= IPN_TCPUDP;
272 if (nat->in_ifnames[1][0] == '\0')
273 strncpy(nat->in_ifnames[1],
274 nat->in_ifnames[0],
275 sizeof(nat->in_ifnames[0]));
279 proxy: | IPNY_PROXY port portspec YY_STR '/' proto
280 { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
281 if (nat->in_dcmp == 0) {
282 nat->in_dport = htons($3);
283 } else if ($3 != nat->in_dport) {
284 yyerror("proxy port numbers not consistant");
286 setnatproto($6);
287 free($4);
289 | IPNY_PROXY port YY_STR YY_STR '/' proto
290 { int pnum;
291 strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
292 pnum = getportproto($3, $6);
293 if (pnum == -1)
294 yyerror("invalid port number");
295 nat->in_dport = pnum;
296 setnatproto($6);
297 free($3);
298 free($4);
302 setproto:
303 | proto { if (nat->in_p != 0 ||
304 nat->in_flags & IPN_TCPUDP)
305 yyerror("protocol set twice");
306 setnatproto($1);
308 | IPNY_TCPUDP { if (nat->in_p != 0 ||
309 nat->in_flags & IPN_TCPUDP)
310 yyerror("protocol set twice");
311 nat->in_flags |= IPN_TCPUDP;
312 nat->in_p = 0;
314 | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 ||
315 nat->in_flags & IPN_TCPUDP)
316 yyerror("protocol set twice");
317 nat->in_flags |= IPN_TCPUDP;
318 nat->in_p = 0;
322 rhaddr: addr { $$.a = $1.a; $$.m = $1.m; }
323 | IPNY_RANGE ipv4 '-' ipv4
324 { $$.a = $2; $$.m = $4;
325 nat->in_flags |= IPN_IPRANGE; }
328 dip:
329 hostname { nat->in_inip = $1.s_addr;
330 nat->in_inmsk = 0xffffffff; }
331 | hostname '/' YY_NUMBER { if ($3 != 0 || $1.s_addr != 0)
332 yyerror("Only 0/0 supported");
333 nat->in_inip = 0;
334 nat->in_inmsk = 0;
336 | hostname ',' hostname { nat->in_flags |= IPN_SPLIT;
337 nat->in_inip = $1.s_addr;
338 nat->in_inmsk = $3.s_addr; }
341 port: IPNY_PORT { suggest_port = 1; }
344 portspec:
345 YY_NUMBER { if ($1 > 65535) /* Unsigned */
346 yyerror("invalid port number");
347 else
348 $$ = $1;
350 | YY_STR { if (getport(NULL, $1, &($$)) == -1)
351 yyerror("invalid port number");
352 $$ = ntohs($$);
356 dport: | port portspec { nat->in_pmin = htons($2);
357 nat->in_pmax = htons($2); }
358 | port portspec '-' portspec { nat->in_pmin = htons($2);
359 nat->in_pmax = htons($4); }
360 | port portspec ':' portspec { nat->in_pmin = htons($2);
361 nat->in_pmax = htons($4); }
364 nport: port portspec { nat->in_pnext = htons($2); }
365 | port '=' portspec { nat->in_pnext = htons($3);
366 nat->in_flags |= IPN_FIXEDDPORT;
370 ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; }
371 | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; }
374 mapit: IPNY_MAP { nat->in_redir = NAT_MAP; }
375 | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; }
378 rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; }
381 mapblockit:
382 IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; }
385 mapfrom:
386 from sobject IPNY_TO dobject
387 | from sobject '!' IPNY_TO dobject
388 { nat->in_flags |= IPN_NOTDST; }
389 | from sobject IPNY_TO '!' dobject
390 { nat->in_flags |= IPN_NOTDST; }
393 rdrfrom:
394 from sobject IPNY_TO dobject
395 | '!' from sobject IPNY_TO dobject
396 { nat->in_flags |= IPN_NOTSRC; }
397 | from '!' sobject IPNY_TO dobject
398 { nat->in_flags |= IPN_NOTSRC; }
401 from: IPNY_FROM { nat->in_flags |= IPN_FILTER; }
404 ifnames:
405 ifname
406 | ifname ',' otherifname
409 ifname: YY_STR { strncpy(nat->in_ifnames[0], $1,
410 sizeof(nat->in_ifnames[0]));
411 nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
412 free($1);
416 otherifname:
417 YY_STR { strncpy(nat->in_ifnames[1], $1,
418 sizeof(nat->in_ifnames[1]));
419 nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
420 free($1);
424 mapport:
425 IPNY_PORTMAP tcpudp portspec ':' portspec randport
426 { nat->in_pmin = htons($3);
427 nat->in_pmax = htons($5);
429 | IPNY_PORTMAP tcpudp IPNY_AUTO randport
430 { nat->in_flags |= IPN_AUTOPORTMAP;
431 nat->in_pmin = htons(1024);
432 nat->in_pmax = htons(65535);
434 | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
435 { if (strcmp($2, "icmp") != 0) {
436 yyerror("icmpidmap not followed by icmp");
438 free($2);
439 if ($3 < 0 || $3 > 65535)
440 yyerror("invalid ICMP Id number");
441 if ($5 < 0 || $5 > 65535)
442 yyerror("invalid ICMP Id number");
443 nat->in_flags = IPN_ICMPQUERY;
444 nat->in_pmin = htons($3);
445 nat->in_pmax = htons($5);
449 randport:
450 | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; }
453 sobject:
454 saddr
455 | saddr port portstuff { nat->in_sport = $3.p1;
456 nat->in_stop = $3.p2;
457 nat->in_scmp = $3.pc; }
460 saddr: addr { if (nat->in_redir == NAT_REDIRECT) {
461 nat->in_srcip = $1.a.s_addr;
462 nat->in_srcmsk = $1.m.s_addr;
463 } else {
464 nat->in_inip = $1.a.s_addr;
465 nat->in_inmsk = $1.m.s_addr;
470 dobject:
471 daddr
472 | daddr port portstuff { nat->in_dport = $3.p1;
473 nat->in_dtop = $3.p2;
474 nat->in_dcmp = $3.pc;
475 if (nat->in_redir == NAT_REDIRECT)
476 nat->in_pmin = htons($3.p1);
480 daddr: addr { if (nat->in_redir == NAT_REDIRECT) {
481 nat->in_outip = $1.a.s_addr;
482 nat->in_outmsk = $1.m.s_addr;
483 } else {
484 nat->in_srcip = $1.a.s_addr;
485 nat->in_srcmsk = $1.m.s_addr;
490 addr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; }
491 | nummask { $$.a = $1.a; $$.m = $1.m;
492 $$.a.s_addr &= $$.m.s_addr; }
493 | hostname '/' ipv4 { $$.a = $1; $$.m = $3;
494 $$.a.s_addr &= $$.m.s_addr; }
495 | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = htonl($3);
496 $$.a.s_addr &= $$.m.s_addr; }
497 | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3;
498 $$.a.s_addr &= $$.m.s_addr; }
499 | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = htonl($3);
500 $$.a.s_addr &= $$.m.s_addr; }
503 nummask:
504 hostname { $$.a = $1;
505 $$.m.s_addr = 0xffffffff; }
506 | hostname '/' YY_NUMBER { $$.a = $1;
507 ntomask(4, $3, &$$.m.s_addr); }
510 portstuff:
511 compare portspec { $$.pc = $1; $$.p1 = $2; }
512 | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
515 mapoptions:
516 rr frag age mssclamp nattag setproto
519 rdroptions:
520 rr frag age sticky mssclamp rdrproxy nattag
523 nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2,
524 sizeof(nat->in_tag.ipt_tag));
527 rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; }
530 frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; }
533 age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2;
534 nat->in_age[1] = $2; }
535 | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2;
536 nat->in_age[1] = $4; }
539 sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) &&
540 !(nat->in_flags & IPN_SPLIT)) {
541 fprintf(stderr,
542 "'sticky' for use with round-robin/IP splitting only\n");
543 } else
544 nat->in_flags |= IPN_STICKY;
548 mssclamp:
549 | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; }
552 tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); }
553 | IPNY_UDP { setnatproto(IPPROTO_UDP); }
554 | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP;
555 nat->in_p = 0;
557 | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP;
558 nat->in_p = 0;
562 rdrproxy:
563 IPNY_PROXY YY_STR
564 { strncpy(nat->in_plabel, $2,
565 sizeof(nat->in_plabel));
566 nat->in_dport = nat->in_pnext;
567 nat->in_dport = htons(nat->in_dport);
568 free($2);
570 | proxy { if (nat->in_plabel[0] != '\0') {
571 nat->in_pmin = nat->in_dport;
572 nat->in_pmax = nat->in_pmin;
573 nat->in_pnext = nat->in_pmin;
578 proto: YY_NUMBER { $$ = $1;
579 if ($$ != IPPROTO_TCP &&
580 $$ != IPPROTO_UDP)
581 suggest_port = 0;
583 | IPNY_TCP { $$ = IPPROTO_TCP; }
584 | IPNY_UDP { $$ = IPPROTO_UDP; }
585 | YY_STR { $$ = getproto($1); free($1);
586 if ($$ != IPPROTO_TCP &&
587 $$ != IPPROTO_UDP)
588 suggest_port = 0;
592 hexnumber:
593 YY_HEX { $$ = $1; }
596 hostname:
597 YY_STR { if (gethost($1, &$$.s_addr) == -1)
598 fprintf(stderr,
599 "Unknown host '%s'\n",
600 $1);
601 free($1);
603 | YY_NUMBER { $$.s_addr = htonl($1); }
604 | ipv4 { $$.s_addr = $1.s_addr; }
607 compare:
608 '=' { $$ = FR_EQUAL; }
609 | YY_CMP_EQ { $$ = FR_EQUAL; }
610 | YY_CMP_NE { $$ = FR_NEQUAL; }
611 | YY_CMP_LT { $$ = FR_LESST; }
612 | YY_CMP_LE { $$ = FR_LESSTE; }
613 | YY_CMP_GT { $$ = FR_GREATERT; }
614 | YY_CMP_GE { $$ = FR_GREATERTE; }
616 range:
617 YY_RANGE_OUT { $$ = FR_OUTRANGE; }
618 | YY_RANGE_IN { $$ = FR_INRANGE; }
619 | ':' { $$ = FR_INCRANGE; }
622 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
623 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
624 yyerror("Invalid octet string for IP address");
625 return 0;
627 $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
628 $$.s_addr = htonl($$.s_addr);
635 static wordtab_t yywords[] = {
636 { "age", IPNY_AGE },
637 { "any", IPNY_ANY },
638 { "auto", IPNY_AUTO },
639 { "bimap", IPNY_BIMAP },
640 { "frag", IPNY_FRAG },
641 { "from", IPNY_FROM },
642 { "icmpidmap", IPNY_ICMPIDMAP },
643 { "mask", IPNY_MASK },
644 { "map", IPNY_MAP },
645 { "map-block", IPNY_MAPBLOCK },
646 { "mssclamp", IPNY_MSSCLAMP },
647 { "netmask", IPNY_MASK },
648 { "port", IPNY_PORT },
649 { "portmap", IPNY_PORTMAP },
650 { "ports", IPNY_PORTS },
651 { "proxy", IPNY_PROXY },
652 { "range", IPNY_RANGE },
653 { "rdr", IPNY_RDR },
654 { "round-robin",IPNY_ROUNDROBIN },
655 { "sequential", IPNY_SEQUENTIAL },
656 { "sticky", IPNY_STICKY },
657 { "tag", IPNY_TAG },
658 { "tcp", IPNY_TCP },
659 { "tcpudp", IPNY_TCPUDP },
660 { "to", IPNY_TO },
661 { "udp", IPNY_UDP },
662 { "-", '-' },
663 { "->", IPNY_TLATE },
664 { "eq", YY_CMP_EQ },
665 { "ne", YY_CMP_NE },
666 { "lt", YY_CMP_LT },
667 { "gt", YY_CMP_GT },
668 { "le", YY_CMP_LE },
669 { "ge", YY_CMP_GE },
670 { NULL, 0 }
674 int ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
675 int fd;
676 addfunc_t addfunc;
677 ioctlfunc_t ioctlfunc;
678 char *filename;
680 FILE *fp = NULL;
681 char *s;
683 (void) yysettab(yywords);
685 s = getenv("YYDEBUG");
686 if (s)
687 yydebug = atoi(s);
688 else
689 yydebug = 0;
691 if (strcmp(filename, "-")) {
692 fp = fopen(filename, "r");
693 if (!fp) {
694 fprintf(stderr, "fopen(%s) failed: %s\n", filename,
695 STRERROR(errno));
696 return -1;
698 } else
699 fp = stdin;
701 while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
703 if (fp != NULL)
704 fclose(fp);
705 return 0;
709 int ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
710 int fd;
711 addfunc_t addfunc;
712 ioctlfunc_t ioctlfunc;
713 FILE *fp;
715 char *s;
716 int i;
718 yylineNum = 1;
720 natfd = fd;
721 nataddfunc = addfunc;
722 natioctlfunc = ioctlfunc;
724 if (feof(fp))
725 return 0;
726 i = fgetc(fp);
727 if (i == EOF)
728 return 0;
729 if (ungetc(i, fp) == EOF)
730 return 0;
731 if (feof(fp))
732 return 0;
733 s = getenv("YYDEBUG");
734 if (s)
735 yydebug = atoi(s);
736 else
737 yydebug = 0;
739 yyin = fp;
740 yyparse();
741 return 1;
745 static void newnatrule()
747 ipnat_t *n;
749 n = calloc(1, sizeof(*n));
750 if (n == NULL)
751 return;
753 if (nat == NULL)
754 nattop = nat = n;
755 else {
756 nat->in_next = n;
757 nat = n;
760 suggest_port = 0;
764 static void setnatproto(p)
765 int p;
767 nat->in_p = p;
769 switch (p)
771 case IPPROTO_TCP :
772 nat->in_flags |= IPN_TCP;
773 nat->in_flags &= ~IPN_UDP;
774 break;
775 case IPPROTO_UDP :
776 nat->in_flags |= IPN_UDP;
777 nat->in_flags &= ~IPN_TCP;
778 break;
779 case IPPROTO_ICMP :
780 nat->in_flags &= ~IPN_TCPUDP;
781 if (!(nat->in_flags & IPN_ICMPQUERY)) {
782 nat->in_dcmp = 0;
783 nat->in_scmp = 0;
784 nat->in_pmin = 0;
785 nat->in_pmax = 0;
786 nat->in_pnext = 0;
788 break;
789 default :
790 if ((nat->in_redir & NAT_MAPBLK) == 0) {
791 nat->in_flags &= ~IPN_TCPUDP;
792 nat->in_dcmp = 0;
793 nat->in_scmp = 0;
794 nat->in_pmin = 0;
795 nat->in_pmax = 0;
796 nat->in_pnext = 0;
798 break;
801 if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
802 nat->in_flags &= ~IPN_FIXEDDPORT;
806 void ipnat_addrule(fd, ioctlfunc, ptr)
807 int fd;
808 ioctlfunc_t ioctlfunc;
809 void *ptr;
811 ioctlcmd_t add, del;
812 ipfobj_t obj;
813 ipnat_t *ipn;
815 ipn = ptr;
816 bzero((char *)&obj, sizeof(obj));
817 obj.ipfo_rev = IPFILTER_VERSION;
818 obj.ipfo_size = sizeof(ipnat_t);
819 obj.ipfo_type = IPFOBJ_IPNAT;
820 obj.ipfo_ptr = ptr;
821 add = 0;
822 del = 0;
824 if ((opts & OPT_DONOTHING) != 0)
825 fd = -1;
827 if (opts & OPT_ZERORULEST) {
828 add = SIOCZRLST;
829 } else if (opts & OPT_INACTIVE) {
830 add = SIOCADNAT;
831 del = SIOCRMNAT;
832 } else {
833 add = SIOCADNAT;
834 del = SIOCRMNAT;
837 if ((opts & OPT_VERBOSE) != 0)
838 printnat(ipn, opts);
840 if (opts & OPT_DEBUG)
841 binprint(ipn, sizeof(*ipn));
843 if ((opts & OPT_ZERORULEST) != 0) {
844 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
845 if ((opts & OPT_DONOTHING) == 0) {
846 fprintf(stderr, "%d:", yylineNum);
847 perror("ioctl(SIOCZRLST)");
849 } else {
850 #ifdef USE_QUAD_T
852 printf("hits %qd bytes %qd ",
853 (long long)fr->fr_hits,
854 (long long)fr->fr_bytes);
856 #else
858 printf("hits %ld bytes %ld ",
859 fr->fr_hits, fr->fr_bytes);
861 #endif
862 printnat(ipn, opts);
864 } else if ((opts & OPT_REMOVE) != 0) {
865 if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
866 if ((opts & OPT_DONOTHING) == 0) {
867 fprintf(stderr, "%d:", yylineNum);
868 perror("ioctl(delete nat rule)");
871 } else {
872 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
873 if ((opts & OPT_DONOTHING) == 0) {
874 fprintf(stderr, "%d:", yylineNum);
875 perror("ioctl(add/insert nat rule)");