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