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