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