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