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