Print this page
OS-7667 IPFilter needs to keep and report state for cloud firewall logging
Portions contributed by: Mike Gerdts <mike.gerdts@joyent.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/ipf/tools/ipnat_y.y
+++ new/usr/src/cmd/ipf/tools/ipnat_y.y
1 1 %{
2 2 /*
3 3 * Copyright (C) 2001-2008 by Darren Reed.
4 4 *
5 5 * See the IPFILTER.LICENCE file for details on licencing.
6 6 *
7 7 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
8 8 * Use is subject to license terms.
9 + * Copyright 2019 Joyent, Inc.
9 10 */
10 11
11 12 #pragma ident "%Z%%M% %I% %E% SMI"
12 13
13 14 #ifdef __FreeBSD__
14 15 # ifndef __FreeBSD_cc_version
15 16 # include <osreldate.h>
16 17 # else
17 18 # if __FreeBSD_cc_version < 430000
18 19 # include <osreldate.h>
19 20 # endif
20 21 # endif
21 22 #endif
22 23 #include <stdio.h>
23 24 #include <unistd.h>
24 25 #include <string.h>
25 26 #include <fcntl.h>
26 27 #include <errno.h>
27 28 #if !defined(__SVR4) && !defined(__GNUC__)
28 29 #include <strings.h>
29 30 #endif
30 31 #include <sys/types.h>
31 32 #include <sys/param.h>
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
32 33 #include <sys/file.h>
33 34 #include <stdlib.h>
34 35 #include <stddef.h>
35 36 #include <sys/socket.h>
36 37 #include <sys/ioctl.h>
37 38 #include <netinet/in.h>
38 39 #include <netinet/in_systm.h>
39 40 #include <sys/time.h>
40 41 #include <syslog.h>
41 42 #include <net/if.h>
43 +#include <uuid/uuid.h>
42 44 #if __FreeBSD_version >= 300000
43 45 # include <net/if_var.h>
44 46 #endif
45 47 #include <netdb.h>
46 48 #include <arpa/nameser.h>
47 49 #include <resolv.h>
48 50 #include "ipf.h"
49 51 #include "netinet/ipl.h"
50 52 #include "ipnat_l.h"
51 53
52 54 #define YYDEBUG 1
53 55
54 56 extern void yyerror __P((char *));
55 57 extern int yyparse __P((void));
56 58 extern int yylex __P((void));
57 59 extern int yydebug;
58 60 extern FILE *yyin;
59 61 extern int yylineNum;
60 62
61 63 static ipnat_t *nattop = NULL;
62 64 static ipnat_t *nat = NULL;
63 65 static int natfd = -1;
64 66 static ioctlfunc_t natioctlfunc = NULL;
65 67 static addfunc_t nataddfunc = NULL;
66 68
67 69 static void newnatrule __P((void));
68 70 static void setnatproto __P((int));
69 71
70 72 %}
71 73 %union {
72 74 char *str;
73 75 u_32_t num;
74 76 struct {
75 77 i6addr_t a;
76 78 int v;
77 79 } ipa;
78 80 frentry_t fr;
79 81 frtuc_t *frt;
80 82 u_short port;
81 83 struct {
|
↓ open down ↓ |
30 lines elided |
↑ open up ↑ |
82 84 u_short p1;
83 85 u_short p2;
84 86 int pc;
85 87 } pc;
86 88 struct {
87 89 i6addr_t a;
88 90 i6addr_t m;
89 91 int v;
90 92 } ipp;
91 93 union i6addr ip6;
94 + uuid_t uuid;
92 95 };
93 96
94 97 %token <num> YY_NUMBER YY_HEX
95 98 %token <str> YY_STR
96 99 %token YY_COMMENT
97 100 %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
98 101 %token YY_RANGE_OUT YY_RANGE_IN
99 102 %token <ip6> YY_IPV6
103 +%token <uuid> YY_UUID
100 104
101 105 %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
102 106 %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
103 107 %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
104 108 %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
105 109 %token IPNY_TLATE IPNY_SEQUENTIAL
106 110 %type <port> portspec
107 111 %type <num> hexnumber compare range proto
108 112 %type <num> saddr daddr sobject dobject mapfrom rdrfrom dip
109 113 %type <ipa> hostname ipv4 ipaddr
110 114 %type <ipp> addr rhaddr
111 115 %type <pc> portstuff
112 116 %%
113 117 file: line
114 118 | assign
115 119 | file line
116 120 | file assign
117 121 ;
118 122
119 123 line: xx rule { while ((nat = nattop) != NULL) {
120 124 if (nat->in_v == 0)
121 125 nat->in_v = 4;
122 126 nattop = nat->in_next;
123 127 (*nataddfunc)(natfd, natioctlfunc, nat);
124 128 free(nat);
125 129 }
126 130 resetlexer();
127 131 }
128 132 | YY_COMMENT
129 133 ;
130 134
131 135 assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
132 136 resetlexer();
133 137 free($1);
134 138 free($3);
135 139 }
136 140 ;
137 141
138 142 assigning:
139 143 '=' { yyvarnext = 1; }
140 144 ;
141 145
142 146 xx: { newnatrule(); }
143 147 ;
144 148
145 149 rule: map eol
146 150 | mapblock eol
147 151 | redir eol
148 152 ;
149 153
150 154 eol: | ';'
151 155 ;
152 156
153 157 map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
154 158 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
155 159 yyerror("1.address family mismatch");
156 160 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
157 161 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
158 162 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
159 163 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
160 164 if (nat->in_ifnames[1][0] == '\0')
161 165 strncpy(nat->in_ifnames[1],
162 166 nat->in_ifnames[0],
163 167 sizeof(nat->in_ifnames[0]));
164 168 if ((nat->in_flags & IPN_TCPUDP) == 0)
165 169 setnatproto(nat->in_p);
166 170 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
167 171 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
168 172 nat_setgroupmap(nat);
169 173 }
170 174 | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
171 175 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
172 176 yyerror("2.address family mismatch");
173 177 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
174 178 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
175 179 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
176 180 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
177 181 if (nat->in_ifnames[1][0] == '\0')
178 182 strncpy(nat->in_ifnames[1],
179 183 nat->in_ifnames[0],
180 184 sizeof(nat->in_ifnames[0]));
181 185 if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
182 186 setnatproto(nat->in_p);
183 187 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
184 188 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
185 189 nat_setgroupmap(nat);
186 190 }
187 191 | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
188 192 { if ($3 != 0 && $3 != $5.v && $5.v != 0)
189 193 yyerror("3.address family mismatch");
190 194 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
191 195 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
192 196 if (nat->in_ifnames[1][0] == '\0')
193 197 strncpy(nat->in_ifnames[1],
194 198 nat->in_ifnames[0],
195 199 sizeof(nat->in_ifnames[0]));
196 200 if ((nat->in_flags & IPN_TCPUDP) == 0)
197 201 setnatproto(nat->in_p);
198 202 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
199 203 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
200 204 nat_setgroupmap(nat);
201 205 }
202 206 | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
203 207 { if ($3 != 0 && $3 != $5.v && $5.v != 0)
204 208 yyerror("4.address family mismatch");
205 209 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
206 210 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
207 211 if (nat->in_ifnames[1][0] == '\0')
208 212 strncpy(nat->in_ifnames[1],
209 213 nat->in_ifnames[0],
210 214 sizeof(nat->in_ifnames[0]));
211 215 if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
212 216 setnatproto(nat->in_p);
213 217 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
214 218 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
215 219 nat_setgroupmap(nat);
216 220 }
217 221 ;
218 222
219 223 mapblock:
220 224 mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
221 225 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
222 226 yyerror("5.address family mismatch");
223 227 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
224 228 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
225 229 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
226 230 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
227 231 if (nat->in_ifnames[1][0] == '\0')
228 232 strncpy(nat->in_ifnames[1],
229 233 nat->in_ifnames[0],
230 234 sizeof(nat->in_ifnames[0]));
231 235 if ((nat->in_flags & IPN_TCPUDP) == 0)
232 236 setnatproto(nat->in_p);
233 237 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
234 238 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
235 239 nat_setgroupmap(nat);
236 240 }
237 241 ;
238 242
239 243 redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
240 244 { if ($6 != 0 && $3.v != 0 && $6 != $3.v)
241 245 yyerror("6.address family mismatch");
242 246 bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
243 247 bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
244 248 if (nat->in_ifnames[1][0] == '\0')
245 249 strncpy(nat->in_ifnames[1],
246 250 nat->in_ifnames[0],
247 251 sizeof(nat->in_ifnames[0]));
248 252 if ((nat->in_p == 0) &&
249 253 ((nat->in_flags & IPN_TCPUDP) == 0) &&
250 254 (nat->in_pmin != 0 ||
251 255 nat->in_pmax != 0 ||
252 256 nat->in_pnext != 0))
253 257 setnatproto(IPPROTO_TCP);
254 258 }
255 259 | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
256 260 { if ($5 != 0 && $3 != 0 && $5 != $3)
257 261 yyerror("7.address family mismatch");
258 262 if ((nat->in_p == 0) &&
259 263 ((nat->in_flags & IPN_TCPUDP) == 0) &&
260 264 (nat->in_pmin != 0 ||
261 265 nat->in_pmax != 0 ||
262 266 nat->in_pnext != 0))
263 267 setnatproto(IPPROTO_TCP);
264 268 if (nat->in_ifnames[1][0] == '\0')
265 269 strncpy(nat->in_ifnames[1],
266 270 nat->in_ifnames[0],
267 271 sizeof(nat->in_ifnames[0]));
268 272 }
269 273 | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
270 274 { if ($5 != 0 && $3.v != 0 && $5 != $3.v)
271 275 yyerror("8.address family mismatch");
272 276 bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
273 277 bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
274 278 if (nat->in_ifnames[1][0] == '\0')
275 279 strncpy(nat->in_ifnames[1],
276 280 nat->in_ifnames[0],
277 281 sizeof(nat->in_ifnames[0]));
278 282 }
279 283 ;
280 284
281 285 proxy: | IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto
282 286 { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
283 287 if (nat->in_dcmp == 0) {
284 288 nat->in_dport = htons($3);
285 289 } else if ($3 != nat->in_dport) {
286 290 yyerror("proxy port numbers not consistant");
287 291 }
288 292 setnatproto($6);
289 293 free($4);
290 294 }
291 295 | IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto
292 296 { int pnum;
293 297 strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
294 298 pnum = getportproto($3, $6);
295 299 if (pnum == -1)
296 300 yyerror("invalid port number");
297 301 nat->in_dport = pnum;
298 302 setnatproto($6);
299 303 free($3);
300 304 free($4);
301 305 }
302 306 ;
303 307
304 308 setproto:
305 309 | proto { if (nat->in_p != 0 ||
306 310 nat->in_flags & IPN_TCPUDP)
307 311 yyerror("protocol set twice");
308 312 setnatproto($1);
309 313 }
310 314 | IPNY_TCPUDP { if (nat->in_p != 0 ||
311 315 nat->in_flags & IPN_TCPUDP)
312 316 yyerror("protocol set twice");
313 317 nat->in_flags |= IPN_TCPUDP;
314 318 nat->in_p = 0;
315 319 }
316 320 | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 ||
317 321 nat->in_flags & IPN_TCPUDP)
318 322 yyerror("protocol set twice");
319 323 nat->in_flags |= IPN_TCPUDP;
320 324 nat->in_p = 0;
321 325 }
322 326 ;
323 327
324 328 rhaddr: addr { $$.a = $1.a;
325 329 $$.m = $1.m;
326 330 $$.v = $1.v;
327 331 if ($$.v == 0)
328 332 $$.v = nat->in_v;
329 333 yyexpectaddr = 0; }
330 334 | IPNY_RANGE hostname '-' hostname
331 335 { if ($2.v != 0 && $4.v != 0 && $4.v != $2.v)
332 336 yyerror("9.address family "
333 337 "mismatch");
334 338 $$.v = $2.v;
335 339 $$.a = $2.a;
336 340 $$.m = $4.a;
337 341 nat->in_flags |= IPN_IPRANGE;
338 342 yyexpectaddr = 0; }
339 343 ;
340 344
341 345 dip:
342 346 hostname { bcopy(&$1.a, &nat->in_in[0],
343 347 sizeof($1.a));
344 348 if ($1.v == 0)
345 349 $1.v = nat->in_v;
346 350 if ($1.v == 4) {
347 351 nat->in_inmsk = 0xffffffff;
348 352 } else {
349 353 nat->in_in[1].i6[0] = 0xffffffff;
350 354 nat->in_in[1].i6[1] = 0xffffffff;
351 355 nat->in_in[1].i6[2] = 0xffffffff;
352 356 nat->in_in[1].i6[3] = 0xffffffff;
353 357 }
354 358 $$ = $1.v;
355 359 }
356 360 | hostname '/' YY_NUMBER { if ($1.v == 0)
357 361 $1.v = nat->in_v;
358 362 if ($1.v == 4 &&
359 363 ($1.a.in4.s_addr != 0 ||
360 364 ($3 != 0 && $3 != 32)))
361 365 yyerror("Invalid mask for dip");
362 366 else if ($1.v == 6 &&
363 367 ($1.a.in4.s_addr != 0 ||
364 368 ($3 != 0 && $3 != 128)))
365 369 yyerror("Invalid mask for dip");
366 370 else if ($1.v == 0 ) {
367 371 if ($1.a.in4.s_addr == 0 &&
368 372 ($3 == 32 || $3 == 0))
369 373 $1.v = 4;
370 374 else if ($3 == 128)
371 375 $1.v = 6;
372 376 }
373 377 bcopy(&$1.a, &nat->in_in[0],
374 378 sizeof($1.a));
375 379 ntomask($1.v, $3,
376 380 (u_32_t *)&nat->in_in[1]);
377 381 nat->in_in[0].i6[0] &= nat->in_in[1].i6[0];
378 382 nat->in_in[0].i6[0] &= nat->in_in[1].i6[1];
379 383 nat->in_in[0].i6[0] &= nat->in_in[1].i6[2];
380 384 nat->in_in[0].i6[0] &= nat->in_in[1].i6[3];
381 385 nat->in_v = $1.v;
382 386 $$ = $1.v;
383 387 }
384 388 | hostname ',' { yyexpectaddr = 1; } hostname
385 389 { if ($1.v != $4.v)
386 390 yyerror("10.address family "
387 391 "mismatch");
388 392 $$ = $1.v;
389 393 nat->in_flags |= IPN_SPLIT;
390 394 bcopy(&$1.a, &nat->in_in[0],
391 395 sizeof($1.a));
392 396 bcopy(&$4.a, &nat->in_in[1],
393 397 sizeof($4.a));
394 398 yyexpectaddr = 0; }
395 399 ;
396 400
397 401 portspec:
398 402 YY_NUMBER { if ($1 > 65535) /* Unsigned */
399 403 yyerror("invalid port number");
400 404 else
401 405 $$ = $1;
402 406 }
403 407 | YY_STR { if (getport(NULL, $1, &($$)) == -1)
404 408 yyerror("invalid port number");
405 409 $$ = ntohs($$);
406 410 }
407 411 ;
408 412
409 413 dport: | IPNY_PORT portspec { nat->in_pmin = htons($2);
410 414 nat->in_pmax = htons($2); }
411 415 | IPNY_PORT portspec '-' portspec { nat->in_pmin = htons($2);
412 416 nat->in_pmax = htons($4); }
413 417 | IPNY_PORT portspec ':' portspec { nat->in_pmin = htons($2);
414 418 nat->in_pmax = htons($4); }
415 419 ;
416 420
417 421 nport: IPNY_PORT portspec { nat->in_pnext = htons($2); }
418 422 | IPNY_PORT '=' portspec { nat->in_pnext = htons($3);
419 423 nat->in_flags |= IPN_FIXEDDPORT;
420 424 }
421 425 ;
422 426
423 427 ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; }
424 428 | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; }
425 429 ;
426 430
427 431 mapit: IPNY_MAP { nat->in_redir = NAT_MAP; }
428 432 | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; }
429 433 ;
430 434
431 435 rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; }
432 436 ;
433 437
434 438 mapblockit:
435 439 IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; }
436 440 ;
437 441
438 442 mapfrom:
439 443 from sobject IPNY_TO dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
440 444 yyerror("11.address family "
441 445 "mismatch");
442 446 $$ = $2;
443 447 }
444 448 | from sobject '!' IPNY_TO dobject
445 449 { if ($2 != 0 && $5 != 0 && $2 != $5)
446 450 yyerror("12.address family "
447 451 "mismatch");
448 452 nat->in_flags |= IPN_NOTDST;
449 453 $$ = $2;
450 454 }
451 455 ;
452 456
453 457 rdrfrom:
454 458 from sobject IPNY_TO dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
455 459 yyerror("13.address family "
456 460 "mismatch");
457 461 $$ = $2;
458 462 }
459 463 | '!' from sobject IPNY_TO dobject
460 464 { if ($3 != 0 && $5 != 0 && $3 != $5)
461 465 yyerror("14.address family "
462 466 "mismatch");
463 467 nat->in_flags |= IPN_NOTSRC;
464 468 $$ = $3;
465 469 }
466 470 ;
467 471
468 472 from: IPNY_FROM { nat->in_flags |= IPN_FILTER;
469 473 yyexpectaddr = 1; }
470 474 ;
471 475
472 476 ifnames:
473 477 ifname { yyexpectaddr = 1; }
474 478 | ifname ',' otherifname { yyexpectaddr = 1; }
475 479 ;
476 480
477 481 ifname: YY_STR { strncpy(nat->in_ifnames[0], $1,
478 482 sizeof(nat->in_ifnames[0]));
479 483 nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
480 484 free($1);
481 485 }
482 486 ;
483 487
484 488 otherifname:
485 489 YY_STR { strncpy(nat->in_ifnames[1], $1,
486 490 sizeof(nat->in_ifnames[1]));
487 491 nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
488 492 free($1);
489 493 }
490 494 ;
491 495
492 496 mapport:
493 497 IPNY_PORTMAP tcpudp portspec ':' portspec randport
494 498 { nat->in_pmin = htons($3);
495 499 nat->in_pmax = htons($5);
496 500 }
497 501 | IPNY_PORTMAP tcpudp IPNY_AUTO randport
498 502 { nat->in_flags |= IPN_AUTOPORTMAP;
499 503 nat->in_pmin = htons(1024);
500 504 nat->in_pmax = htons(65535);
501 505 }
502 506 | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
503 507 { if (strcmp($2, "icmp") != 0) {
504 508 yyerror("icmpidmap not followed by icmp");
505 509 }
506 510 free($2);
507 511 if ($3 < 0 || $3 > 65535)
508 512 yyerror("invalid ICMP Id number");
509 513 if ($5 < 0 || $5 > 65535)
510 514 yyerror("invalid ICMP Id number");
511 515 nat->in_flags = IPN_ICMPQUERY;
512 516 nat->in_pmin = htons($3);
513 517 nat->in_pmax = htons($5);
514 518 }
515 519 ;
516 520
517 521 randport:
518 522 | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; }
519 523 ;
520 524
521 525 sobject:
522 526 saddr { $$ = $1; }
523 527 | saddr IPNY_PORT portstuff { nat->in_sport = $3.p1;
524 528 nat->in_stop = $3.p2;
525 529 nat->in_scmp = $3.pc;
526 530 $$ = $1;
527 531 }
528 532 ;
529 533
530 534 saddr: addr { if (nat->in_redir == NAT_REDIRECT) {
531 535 bcopy(&$1.a, &nat->in_src[0],
532 536 sizeof($1.a));
533 537 bcopy(&$1.m, &nat->in_src[1],
534 538 sizeof($1.a));
535 539 } else {
536 540 bcopy(&$1.a, &nat->in_in[0],
537 541 sizeof($1.a));
538 542 bcopy(&$1.m, &nat->in_in[1],
539 543 sizeof($1.a));
540 544 }
541 545 $$ = $1.v;
542 546 }
543 547 ;
544 548
545 549 dobject:
546 550 daddr { $$ = $1; }
547 551 | daddr IPNY_PORT portstuff { nat->in_dport = $3.p1;
548 552 nat->in_dtop = $3.p2;
549 553 nat->in_dcmp = $3.pc;
550 554 if (nat->in_redir == NAT_REDIRECT)
551 555 nat->in_pmin = htons($3.p1);
552 556 }
553 557 ;
554 558
555 559 daddr: addr { if (nat->in_redir == NAT_REDIRECT) {
556 560 bcopy(&$1.a, &nat->in_out[0],
557 561 sizeof($1.a));
558 562 bcopy(&$1.m, &nat->in_out[1],
559 563 sizeof($1.a));
560 564 } else {
561 565 bcopy(&$1.a, &nat->in_src[0],
562 566 sizeof($1.a));
563 567 bcopy(&$1.m, &nat->in_src[1],
564 568 sizeof($1.a));
565 569 }
566 570 $$ = $1.v;
567 571 }
568 572 ;
569 573
570 574 addr: IPNY_ANY { yyexpectaddr = 0;
571 575 bzero(&$$.a, sizeof($$.a));
572 576 bzero(&$$.m, sizeof($$.a));
573 577 $$.v = nat->in_v;
574 578 }
575 579 | hostname { $$.a = $1.a;
576 580 $$.v = $1.v;
577 581 if ($$.v == 4) {
578 582 $$.m.in4.s_addr = 0xffffffff;
579 583 } else {
580 584 $$.m.i6[0] = 0xffffffff;
581 585 $$.m.i6[1] = 0xffffffff;
582 586 $$.m.i6[2] = 0xffffffff;
583 587 $$.m.i6[3] = 0xffffffff;
584 588 }
585 589 yyexpectaddr = 0;
586 590 }
587 591 | hostname '/' YY_NUMBER { $$.a = $1.a;
588 592 if ($1.v == 0) {
589 593 if ($1.a.in4.s_addr != 0)
590 594 yyerror("invalid addr");
591 595 if ($3 == 0 || $3 == 32)
592 596 $1.v = 4;
593 597 else if ($3 == 128)
594 598 $1.v = 6;
595 599 else
596 600 yyerror("invalid mask");
597 601 nat->in_v = $1.v;
598 602 }
599 603 ntomask($1.v, $3, (u_32_t *)&$$.m);
600 604 $$.a.i6[0] &= $$.m.i6[0];
601 605 $$.a.i6[1] &= $$.m.i6[1];
602 606 $$.a.i6[2] &= $$.m.i6[2];
603 607 $$.a.i6[3] &= $$.m.i6[3];
604 608 $$.v = $1.v;
605 609 yyexpectaddr = 0;
606 610 }
607 611 | hostname '/' ipaddr { if ($1.v != $3.v) {
608 612 yyerror("1.address family "
609 613 "mismatch");
610 614 }
611 615 $$.a = $1.a;
612 616 $$.m = $3.a;
613 617 $$.a.i6[0] &= $$.m.i6[0];
614 618 $$.a.i6[1] &= $$.m.i6[1];
615 619 $$.a.i6[2] &= $$.m.i6[2];
616 620 $$.a.i6[3] &= $$.m.i6[3];
617 621 $$.v = $1.v;
618 622 yyexpectaddr = 0;
619 623 }
620 624 | hostname '/' hexnumber { $$.a = $1.a;
621 625 $$.m.in4.s_addr = htonl($3);
622 626 $$.a.in4.s_addr &= $$.m.in4.s_addr;
623 627 $$.v = 4;
624 628 }
625 629 | hostname IPNY_MASK ipaddr { if ($1.v != $3.v) {
626 630 yyerror("2.address family "
627 631 "mismatch");
628 632 }
629 633 $$.a = $1.a;
630 634 $$.m = $3.a;
631 635 $$.a.i6[0] &= $$.m.i6[0];
632 636 $$.a.i6[1] &= $$.m.i6[1];
633 637 $$.a.i6[2] &= $$.m.i6[2];
634 638 $$.a.i6[3] &= $$.m.i6[3];
635 639 $$.v = $1.v;
636 640 yyexpectaddr = 0;
637 641 }
638 642 | hostname IPNY_MASK hexnumber { $$.a = $1.a;
639 643 $$.m.in4.s_addr = htonl($3);
640 644 $$.a.in4.s_addr &= $$.m.in4.s_addr;
641 645 $$.v = 4;
642 646 }
643 647 ;
644 648
645 649 portstuff:
646 650 compare portspec { $$.pc = $1; $$.p1 = $2; }
647 651 | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
648 652 ;
649 653
650 654 mapoptions:
651 655 rr frag age mssclamp nattag setproto
652 656 ;
653 657
654 658 rdroptions:
655 659 rr frag age sticky mssclamp rdrproxy nattag
656 660 ;
657 661
658 662 nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2,
659 663 sizeof(nat->in_tag.ipt_tag));
660 664 }
661 665
662 666 rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; }
663 667 ;
664 668
665 669 frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; }
666 670 ;
667 671
668 672 age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2;
669 673 nat->in_age[1] = $2; }
670 674 | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2;
671 675 nat->in_age[1] = $4; }
672 676 ;
673 677
674 678 sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) &&
675 679 !(nat->in_flags & IPN_SPLIT)) {
676 680 fprintf(stderr,
677 681 "'sticky' for use with round-robin/IP splitting only\n");
678 682 } else
679 683 nat->in_flags |= IPN_STICKY;
680 684 }
681 685 ;
682 686
683 687 mssclamp:
684 688 | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; }
685 689 ;
686 690
687 691 tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); }
688 692 | IPNY_UDP { setnatproto(IPPROTO_UDP); }
689 693 | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP;
690 694 nat->in_p = 0;
691 695 }
692 696 | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP;
693 697 nat->in_p = 0;
694 698 }
695 699 ;
696 700
697 701 rdrproxy:
698 702 IPNY_PROXY YY_STR
699 703 { strncpy(nat->in_plabel, $2,
700 704 sizeof(nat->in_plabel));
701 705 nat->in_dport = nat->in_pnext;
702 706 nat->in_dport = htons(nat->in_dport);
703 707 free($2);
704 708 }
705 709 | proxy { if (nat->in_plabel[0] != '\0') {
706 710 nat->in_pmin = nat->in_dport;
707 711 nat->in_pmax = nat->in_pmin;
708 712 nat->in_pnext = nat->in_pmin;
709 713 }
710 714 }
711 715 ;
712 716
713 717 proto: YY_NUMBER { $$ = $1; }
714 718 | IPNY_TCP { $$ = IPPROTO_TCP; }
715 719 | IPNY_UDP { $$ = IPPROTO_UDP; }
716 720 | YY_STR { $$ = getproto($1); free($1); }
717 721 ;
718 722
719 723 hexnumber:
720 724 YY_HEX { $$ = $1; }
721 725 ;
722 726
723 727 hostname:
724 728 YY_STR { i6addr_t addr;
725 729 if (gethost($1, &addr, 0) == 0) {
726 730 $$.a = addr;
727 731 $$.v = 4;
728 732 } else
729 733 if (gethost($1, &addr, 1) == 0) {
730 734 $$.a = addr;
731 735 $$.v = 6;
732 736 } else {
733 737 yyerror("Unknown hostname");
734 738 }
735 739 if ($$.v != 0)
736 740 nat->in_v = $$.v;
737 741 free($1);
738 742 }
739 743 | YY_NUMBER { bzero(&$$.a, sizeof($$.a));
740 744 $$.a.in4.s_addr = htonl($1);
741 745 if ($$.a.in4.s_addr != 0)
742 746 $$.v = 4;
743 747 else
744 748 $$.v = nat->in_v;
745 749 if ($$.v != 0)
746 750 nat->in_v = $$.v;
747 751 }
748 752 | ipv4 { $$ = $1;
749 753 nat->in_v = 4;
750 754 }
751 755 | YY_IPV6 { $$.a = $1;
752 756 $$.v = 6;
753 757 nat->in_v = 6;
754 758 }
755 759 | YY_NUMBER YY_IPV6 { $$.a = $2;
756 760 $$.v = 6;
757 761 }
758 762 ;
759 763
760 764 compare:
761 765 '=' { $$ = FR_EQUAL; }
762 766 | YY_CMP_EQ { $$ = FR_EQUAL; }
763 767 | YY_CMP_NE { $$ = FR_NEQUAL; }
764 768 | YY_CMP_LT { $$ = FR_LESST; }
765 769 | YY_CMP_LE { $$ = FR_LESSTE; }
766 770 | YY_CMP_GT { $$ = FR_GREATERT; }
767 771 | YY_CMP_GE { $$ = FR_GREATERTE; }
768 772
769 773 range:
770 774 YY_RANGE_OUT { $$ = FR_OUTRANGE; }
771 775 | YY_RANGE_IN { $$ = FR_INRANGE; }
772 776 ;
773 777
774 778 ipaddr: ipv4 { $$ = $1; }
775 779 | YY_IPV6 { $$.a = $1;
776 780 $$.v = 6;
777 781 }
778 782 ;
779 783
780 784 ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
781 785 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
782 786 yyerror("Invalid octet string for IP address");
783 787 return 0;
784 788 }
785 789 $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
786 790 $$.a.in4.s_addr = htonl($$.a.in4.s_addr);
787 791 $$.v = 4;
788 792 }
789 793 ;
790 794
791 795 %%
792 796
793 797
794 798 static wordtab_t yywords[] = {
795 799 { "age", IPNY_AGE },
796 800 { "any", IPNY_ANY },
797 801 { "auto", IPNY_AUTO },
798 802 { "bimap", IPNY_BIMAP },
799 803 { "frag", IPNY_FRAG },
800 804 { "from", IPNY_FROM },
801 805 { "icmpidmap", IPNY_ICMPIDMAP },
802 806 { "mask", IPNY_MASK },
803 807 { "map", IPNY_MAP },
804 808 { "map-block", IPNY_MAPBLOCK },
805 809 { "mssclamp", IPNY_MSSCLAMP },
806 810 { "netmask", IPNY_MASK },
807 811 { "port", IPNY_PORT },
808 812 { "portmap", IPNY_PORTMAP },
809 813 { "ports", IPNY_PORTS },
810 814 { "proxy", IPNY_PROXY },
811 815 { "range", IPNY_RANGE },
812 816 { "rdr", IPNY_RDR },
813 817 { "round-robin",IPNY_ROUNDROBIN },
814 818 { "sequential", IPNY_SEQUENTIAL },
815 819 { "sticky", IPNY_STICKY },
816 820 { "tag", IPNY_TAG },
817 821 { "tcp", IPNY_TCP },
818 822 { "tcpudp", IPNY_TCPUDP },
819 823 { "to", IPNY_TO },
820 824 { "udp", IPNY_UDP },
821 825 { "-", '-' },
822 826 { "->", IPNY_TLATE },
823 827 { "eq", YY_CMP_EQ },
824 828 { "ne", YY_CMP_NE },
825 829 { "lt", YY_CMP_LT },
826 830 { "gt", YY_CMP_GT },
827 831 { "le", YY_CMP_LE },
828 832 { "ge", YY_CMP_GE },
829 833 { NULL, 0 }
830 834 };
831 835
832 836
833 837 int ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
834 838 int fd;
835 839 addfunc_t addfunc;
836 840 ioctlfunc_t ioctlfunc;
837 841 char *filename;
838 842 {
839 843 FILE *fp = NULL;
840 844 char *s;
841 845
842 846 (void) yysettab(yywords);
843 847
844 848 s = getenv("YYDEBUG");
845 849 if (s)
846 850 yydebug = atoi(s);
847 851 else
848 852 yydebug = 0;
849 853
850 854 if (strcmp(filename, "-")) {
851 855 fp = fopen(filename, "r");
852 856 if (!fp) {
853 857 fprintf(stderr, "fopen(%s) failed: %s\n", filename,
854 858 STRERROR(errno));
855 859 return -1;
856 860 }
857 861 } else
858 862 fp = stdin;
859 863
860 864 while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
861 865 ;
862 866 if (fp != NULL)
863 867 fclose(fp);
864 868 return 0;
865 869 }
866 870
867 871
868 872 int ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
869 873 int fd;
870 874 addfunc_t addfunc;
871 875 ioctlfunc_t ioctlfunc;
872 876 FILE *fp;
873 877 {
874 878 char *s;
875 879 int i;
876 880
877 881 yylineNum = 1;
878 882
879 883 natfd = fd;
880 884 nataddfunc = addfunc;
881 885 natioctlfunc = ioctlfunc;
882 886
883 887 if (feof(fp))
884 888 return 0;
885 889 i = fgetc(fp);
886 890 if (i == EOF)
887 891 return 0;
888 892 if (ungetc(i, fp) == EOF)
889 893 return 0;
890 894 if (feof(fp))
891 895 return 0;
892 896 s = getenv("YYDEBUG");
893 897 if (s)
894 898 yydebug = atoi(s);
895 899 else
896 900 yydebug = 0;
897 901
898 902 yyin = fp;
899 903 yyparse();
900 904 return 1;
901 905 }
902 906
903 907
904 908 static void newnatrule()
905 909 {
906 910 ipnat_t *n;
907 911
908 912 n = calloc(1, sizeof(*n));
909 913 if (n == NULL)
910 914 return;
911 915
912 916 if (nat == NULL)
913 917 nattop = nat = n;
914 918 else {
915 919 nat->in_next = n;
916 920 nat = n;
917 921 }
918 922 }
919 923
920 924
921 925 static void setnatproto(p)
922 926 int p;
923 927 {
924 928 nat->in_p = p;
925 929
926 930 switch (p)
927 931 {
928 932 case IPPROTO_TCP :
929 933 nat->in_flags |= IPN_TCP;
930 934 nat->in_flags &= ~IPN_UDP;
931 935 break;
932 936 case IPPROTO_UDP :
933 937 nat->in_flags |= IPN_UDP;
934 938 nat->in_flags &= ~IPN_TCP;
935 939 break;
936 940 case IPPROTO_ICMP :
937 941 nat->in_flags &= ~IPN_TCPUDP;
938 942 if (!(nat->in_flags & IPN_ICMPQUERY)) {
939 943 nat->in_dcmp = 0;
940 944 nat->in_scmp = 0;
941 945 nat->in_pmin = 0;
942 946 nat->in_pmax = 0;
943 947 nat->in_pnext = 0;
944 948 }
945 949 break;
946 950 default :
947 951 if ((nat->in_redir & NAT_MAPBLK) == 0) {
948 952 /* Only reset dcmp/scmp in case dport/sport not set */
949 953 if (0 == nat->in_tuc.ftu_dport)
950 954 nat->in_dcmp = 0;
951 955 if (0 == nat->in_tuc.ftu_sport)
952 956 nat->in_scmp = 0;
953 957 nat->in_pmin = 0;
954 958 nat->in_pmax = 0;
955 959 nat->in_pnext = 0;
956 960 nat->in_flags &= ~IPN_TCPUDP;
957 961 }
958 962 break;
959 963 }
960 964
961 965 if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
962 966 nat->in_flags &= ~IPN_FIXEDDPORT;
963 967 }
964 968
965 969
966 970 void ipnat_addrule(fd, ioctlfunc, ptr)
967 971 int fd;
968 972 ioctlfunc_t ioctlfunc;
969 973 void *ptr;
970 974 {
971 975 ioctlcmd_t add, del;
972 976 ipfobj_t obj;
973 977 ipnat_t *ipn;
974 978
975 979 ipn = ptr;
976 980 bzero((char *)&obj, sizeof(obj));
977 981 obj.ipfo_rev = IPFILTER_VERSION;
978 982 obj.ipfo_size = sizeof(ipnat_t);
979 983 obj.ipfo_type = IPFOBJ_IPNAT;
980 984 obj.ipfo_ptr = ptr;
981 985 add = 0;
982 986 del = 0;
983 987
984 988 if ((opts & OPT_DONOTHING) != 0)
985 989 fd = -1;
986 990
987 991 if (opts & OPT_ZERORULEST) {
988 992 add = SIOCZRLST;
989 993 } else if (opts & OPT_INACTIVE) {
990 994 add = SIOCADNAT;
991 995 del = SIOCRMNAT;
992 996 } else {
993 997 add = SIOCADNAT;
994 998 del = SIOCRMNAT;
995 999 }
996 1000
997 1001 if (ipn && (opts & OPT_VERBOSE))
998 1002 printnat(ipn, opts);
999 1003
1000 1004 if (opts & OPT_DEBUG)
1001 1005 binprint(ipn, sizeof(*ipn));
1002 1006
1003 1007 if ((opts & OPT_ZERORULEST) != 0) {
1004 1008 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
1005 1009 if ((opts & OPT_DONOTHING) == 0) {
1006 1010 fprintf(stderr, "%d:", yylineNum);
1007 1011 perror("ioctl(SIOCZRLST)");
1008 1012 }
1009 1013 } else {
1010 1014 #ifdef USE_QUAD_T
1011 1015 /*
1012 1016 printf("hits %qd bytes %qd ",
1013 1017 (long long)fr->fr_hits,
1014 1018 (long long)fr->fr_bytes);
1015 1019 */
1016 1020 #else
1017 1021 /*
1018 1022 printf("hits %ld bytes %ld ",
1019 1023 fr->fr_hits, fr->fr_bytes);
1020 1024 */
1021 1025 #endif
1022 1026 printnat(ipn, opts);
1023 1027 }
1024 1028 } else if ((opts & OPT_REMOVE) != 0) {
1025 1029 if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
1026 1030 if ((opts & OPT_DONOTHING) == 0) {
1027 1031 fprintf(stderr, "%d:", yylineNum);
1028 1032 perror("ioctl(delete nat rule)");
1029 1033 }
1030 1034 }
1031 1035 } else {
1032 1036 if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
1033 1037 if ((opts & OPT_DONOTHING) == 0) {
1034 1038 fprintf(stderr, "%d:", yylineNum);
1035 1039 perror("ioctl(add/insert nat rule)");
1036 1040 }
1037 1041 }
1038 1042 }
1039 1043 }
1040 1044
|
↓ open down ↓ |
931 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX