1145519Sdarrenr/* $FreeBSD: stable/11/contrib/ipfilter/tools/ipnat_y.y 369245 2021-02-09 13:47:46Z git2svn $ */ 2145510Sdarrenr 3170268Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5170268Sdarrenr * 6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7170268Sdarrenr */ 8145510Sdarrenr%{ 9145510Sdarrenr#include <stdio.h> 10145510Sdarrenr#include <unistd.h> 11145510Sdarrenr#include <string.h> 12145510Sdarrenr#include <fcntl.h> 13145510Sdarrenr#include <errno.h> 14145510Sdarrenr#if !defined(__SVR4) && !defined(__GNUC__) 15145510Sdarrenr#include <strings.h> 16145510Sdarrenr#endif 17145510Sdarrenr#include <sys/types.h> 18145510Sdarrenr#include <sys/param.h> 19145510Sdarrenr#include <sys/file.h> 20145510Sdarrenr#include <stdlib.h> 21145510Sdarrenr#include <stddef.h> 22145510Sdarrenr#include <sys/socket.h> 23145510Sdarrenr#include <sys/ioctl.h> 24145510Sdarrenr#include <netinet/in.h> 25145510Sdarrenr#include <netinet/in_systm.h> 26145510Sdarrenr#include <sys/time.h> 27145510Sdarrenr#include <syslog.h> 28145510Sdarrenr#include <net/if.h> 29145510Sdarrenr#include <netdb.h> 30145510Sdarrenr#include <arpa/nameser.h> 31145510Sdarrenr#include <resolv.h> 32145510Sdarrenr#include "ipf.h" 33145510Sdarrenr#include "netinet/ipl.h" 34145510Sdarrenr#include "ipnat_l.h" 35145510Sdarrenr 36145510Sdarrenr#define YYDEBUG 1 37145510Sdarrenr 38369245Sgit2svnextern void yyerror(char *); 39369245Sgit2svnextern int yyparse(void); 40369245Sgit2svnextern int yylex(void); 41145510Sdarrenrextern int yydebug; 42145510Sdarrenrextern FILE *yyin; 43145510Sdarrenrextern int yylineNum; 44145510Sdarrenr 45145510Sdarrenrstatic ipnat_t *nattop = NULL; 46145510Sdarrenrstatic ipnat_t *nat = NULL; 47145510Sdarrenrstatic int natfd = -1; 48145510Sdarrenrstatic ioctlfunc_t natioctlfunc = NULL; 49145510Sdarrenrstatic addfunc_t nataddfunc = NULL; 50161357Sguidostatic int suggest_port = 0; 51255332Scystatic proxyrule_t *prules = NULL; 52255332Scystatic int parser_error = 0; 53145510Sdarrenr 54369245Sgit2svnstatic void newnatrule(void); 55369245Sgit2svnstatic void setnatproto(int); 56369245Sgit2svnstatic void setmapifnames(void); 57369245Sgit2svnstatic void setrdrifnames(void); 58369245Sgit2svnstatic void proxy_setconfig(int); 59369245Sgit2svnstatic void proxy_unsetconfig(void); 60369245Sgit2svnstatic namelist_t *proxy_dns_add_pass(char *, char *); 61369245Sgit2svnstatic namelist_t *proxy_dns_add_block(char *, char *); 62369245Sgit2svnstatic void proxy_addconfig(char *, int, char *, namelist_t *); 63369245Sgit2svnstatic void proxy_loadconfig(int, ioctlfunc_t, char *, int, 64369245Sgit2svn char *, namelist_t *); 65369245Sgit2svnstatic void proxy_loadrules(int, ioctlfunc_t, proxyrule_t *); 66369245Sgit2svnstatic void setmapifnames(void); 67369245Sgit2svnstatic void setrdrifnames(void); 68369245Sgit2svnstatic void setifname(ipnat_t **, int, char *); 69369245Sgit2svnstatic int addname(ipnat_t **, char *); 70145510Sdarrenr%} 71145510Sdarrenr%union { 72145510Sdarrenr char *str; 73145510Sdarrenr u_32_t num; 74255332Scy struct { 75255332Scy i6addr_t a; 76255332Scy int f; 77255332Scy } ipa; 78145510Sdarrenr frentry_t fr; 79145510Sdarrenr frtuc_t *frt; 80145510Sdarrenr u_short port; 81145510Sdarrenr struct { 82255332Scy int p1; 83255332Scy int p2; 84145510Sdarrenr int pc; 85145510Sdarrenr } pc; 86145510Sdarrenr struct { 87255332Scy i6addr_t a; 88255332Scy i6addr_t m; 89255332Scy int t; /* Address type */ 90255332Scy int u; 91255332Scy int f; /* Family */ 92255332Scy int v; /* IP version */ 93255332Scy int s; /* 0 = number, 1 = text */ 94255332Scy int n; /* number */ 95145510Sdarrenr } ipp; 96145510Sdarrenr union i6addr ip6; 97255332Scy namelist_t *names; 98145510Sdarrenr}; 99145510Sdarrenr 100145510Sdarrenr%token <num> YY_NUMBER YY_HEX 101145510Sdarrenr%token <str> YY_STR 102255332Scy%token YY_COMMENT 103145510Sdarrenr%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 104145510Sdarrenr%token YY_RANGE_OUT YY_RANGE_IN 105145510Sdarrenr%token <ip6> YY_IPV6 106145510Sdarrenr 107145510Sdarrenr%token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE 108145510Sdarrenr%token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY 109145510Sdarrenr%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY 110145510Sdarrenr%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG 111255332Scy%token IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO 112255332Scy%token IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT 113255332Scy%token IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6 114255332Scy%token IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE 115145510Sdarrenr%type <port> portspec 116145510Sdarrenr%type <num> hexnumber compare range proto 117255332Scy%type <num> saddr daddr sobject dobject mapfrom rdrfrom dip 118255332Scy%type <ipa> hostname ipv4 ipaddr 119255332Scy%type <ipp> addr rhsaddr rhdaddr erhdaddr 120255332Scy%type <pc> portstuff portpair comaports srcports dstports 121255332Scy%type <names> dnslines dnsline 122145510Sdarrenr%% 123145510Sdarrenrfile: line 124145510Sdarrenr | assign 125145510Sdarrenr | file line 126145510Sdarrenr | file assign 127255332Scy | file pconf ';' 128145510Sdarrenr ; 129145510Sdarrenr 130255332Scyline: xx rule { int err; 131255332Scy while ((nat = nattop) != NULL) { 132255332Scy if (nat->in_v[0] == 0) 133255332Scy nat->in_v[0] = 4; 134255332Scy if (nat->in_v[1] == 0) 135255332Scy nat->in_v[1] = nat->in_v[0]; 136145510Sdarrenr nattop = nat->in_next; 137255332Scy err = (*nataddfunc)(natfd, natioctlfunc, nat); 138145510Sdarrenr free(nat); 139255332Scy if (err != 0) { 140255332Scy parser_error = err; 141255332Scy break; 142255332Scy } 143145510Sdarrenr } 144255332Scy if (parser_error == 0 && prules != NULL) { 145255332Scy proxy_loadrules(natfd, natioctlfunc, prules); 146255332Scy prules = NULL; 147255332Scy } 148145510Sdarrenr resetlexer(); 149145510Sdarrenr } 150145510Sdarrenr | YY_COMMENT 151145510Sdarrenr ; 152145510Sdarrenr 153145510Sdarrenrassign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 154145510Sdarrenr resetlexer(); 155145510Sdarrenr free($1); 156145510Sdarrenr free($3); 157170268Sdarrenr yyvarnext = 0; 158145510Sdarrenr } 159145510Sdarrenr ; 160145510Sdarrenr 161145510Sdarrenrassigning: 162145510Sdarrenr '=' { yyvarnext = 1; } 163145510Sdarrenr ; 164145510Sdarrenr 165145510Sdarrenrxx: { newnatrule(); } 166145510Sdarrenr ; 167145510Sdarrenr 168145510Sdarrenrrule: map eol 169145510Sdarrenr | mapblock eol 170145510Sdarrenr | redir eol 171255332Scy | rewrite ';' 172255332Scy | divert ';' 173145510Sdarrenr ; 174145510Sdarrenr 175255332Scyno: IPNY_NO { nat->in_flags |= IPN_NO; } 176255332Scy ; 177255332Scy 178145510Sdarrenreol: | ';' 179145510Sdarrenr ; 180145510Sdarrenr 181255332Scymap: mapit ifnames addr tlate rhsaddr proxy mapoptions 182255332Scy { if ($3.f != 0 && $3.f != $5.f && $5.f != 0) 183255332Scy yyerror("3.address family mismatch"); 184255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 185255332Scy nat->in_v[0] = $5.v; 186255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 187255332Scy nat->in_v[0] = $3.v; 188255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 189255332Scy nat->in_v[1] = $5.v; 190255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 191255332Scy nat->in_v[1] = $3.v; 192255332Scy nat->in_osrcatype = $3.t; 193255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 194255332Scy sizeof($3.a)); 195255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 196255332Scy sizeof($3.a)); 197255332Scy nat->in_nsrcatype = $5.t; 198255332Scy nat->in_nsrcafunc = $5.u; 199255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 200255332Scy sizeof($5.a)); 201255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 202255332Scy sizeof($5.a)); 203255332Scy 204255332Scy setmapifnames(); 205145510Sdarrenr } 206255332Scy | mapit ifnames addr tlate rhsaddr mapport mapoptions 207255332Scy { if ($3.f != $5.f && $3.f != 0 && $5.f != 0) 208255332Scy yyerror("4.address family mismatch"); 209255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 210255332Scy nat->in_v[1] = $5.v; 211255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 212255332Scy nat->in_v[0] = $3.v; 213255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 214255332Scy nat->in_v[0] = $5.v; 215255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 216255332Scy nat->in_v[1] = $3.v; 217255332Scy nat->in_osrcatype = $3.t; 218255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 219255332Scy sizeof($3.a)); 220255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 221255332Scy sizeof($3.a)); 222255332Scy nat->in_nsrcatype = $5.t; 223255332Scy nat->in_nsrcafunc = $5.u; 224255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 225255332Scy sizeof($5.a)); 226255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 227255332Scy sizeof($5.a)); 228255332Scy 229255332Scy setmapifnames(); 230145510Sdarrenr } 231255332Scy | no mapit ifnames addr setproto ';' 232255332Scy { if (nat->in_v[0] == 0) 233255332Scy nat->in_v[0] = $4.v; 234255332Scy nat->in_osrcatype = $4.t; 235255332Scy bcopy(&$4.a, &nat->in_osrc.na_addr[0], 236255332Scy sizeof($4.a)); 237255332Scy bcopy(&$4.m, &nat->in_osrc.na_addr[1], 238255332Scy sizeof($4.a)); 239255332Scy 240255332Scy setmapifnames(); 241145510Sdarrenr } 242255332Scy | mapit ifnames mapfrom tlate rhsaddr proxy mapoptions 243255332Scy { if ($3 != 0 && $5.f != 0 && $3 != $5.f) 244255332Scy yyerror("5.address family mismatch"); 245255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 246255332Scy nat->in_v[0] = $5.v; 247255332Scy else if (nat->in_v[0] == 0 && $3 != 0) 248255332Scy nat->in_v[0] = ftov($3); 249255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 250255332Scy nat->in_v[1] = $5.v; 251255332Scy else if (nat->in_v[1] == 0 && $3 != 0) 252255332Scy nat->in_v[1] = ftov($3); 253255332Scy nat->in_nsrcatype = $5.t; 254255332Scy nat->in_nsrcafunc = $5.u; 255255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 256255332Scy sizeof($5.a)); 257255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 258255332Scy sizeof($5.a)); 259255332Scy 260255332Scy setmapifnames(); 261145510Sdarrenr } 262255332Scy | no mapit ifnames mapfrom setproto ';' 263255332Scy { nat->in_v[0] = ftov($4); 264255332Scy setmapifnames(); 265255332Scy } 266255332Scy | mapit ifnames mapfrom tlate rhsaddr mapport mapoptions 267255332Scy { if ($3 != 0 && $5.f != 0 && $3 != $5.f) 268255332Scy yyerror("6.address family mismatch"); 269255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 270255332Scy nat->in_v[0] = $5.v; 271255332Scy else if (nat->in_v[0] == 0 && $3 != 0) 272255332Scy nat->in_v[0] = ftov($3); 273255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 274255332Scy nat->in_v[1] = $5.v; 275255332Scy else if (nat->in_v[1] == 0 && $3 != 0) 276255332Scy nat->in_v[1] = ftov($3); 277255332Scy nat->in_nsrcatype = $5.t; 278255332Scy nat->in_nsrcafunc = $5.u; 279255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 280255332Scy sizeof($5.a)); 281255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 282255332Scy sizeof($5.a)); 283255332Scy 284255332Scy setmapifnames(); 285255332Scy } 286145510Sdarrenr ; 287145510Sdarrenr 288145510Sdarrenrmapblock: 289255332Scy mapblockit ifnames addr tlate addr ports mapoptions 290255332Scy { if ($3.f != 0 && $5.f != 0 && $3.f != $5.f) 291255332Scy yyerror("7.address family mismatch"); 292255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 293255332Scy nat->in_v[0] = $5.v; 294255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 295255332Scy nat->in_v[0] = $3.v; 296255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 297255332Scy nat->in_v[1] = $5.v; 298255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 299255332Scy nat->in_v[1] = $3.v; 300255332Scy nat->in_osrcatype = $3.t; 301255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 302255332Scy sizeof($3.a)); 303255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 304255332Scy sizeof($3.a)); 305255332Scy nat->in_nsrcatype = $5.t; 306255332Scy nat->in_nsrcafunc = $5.u; 307255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 308255332Scy sizeof($5.a)); 309255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 310255332Scy sizeof($5.a)); 311255332Scy 312255332Scy setmapifnames(); 313145510Sdarrenr } 314255332Scy | no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';' 315255332Scy { if (nat->in_v[0] == 0) 316255332Scy nat->in_v[0] = $5.v; 317255332Scy if (nat->in_v[1] == 0) 318255332Scy nat->in_v[1] = $5.v; 319255332Scy nat->in_osrcatype = $5.t; 320255332Scy bcopy(&$5.a, &nat->in_osrc.na_addr[0], 321255332Scy sizeof($5.a)); 322255332Scy bcopy(&$5.m, &nat->in_osrc.na_addr[1], 323255332Scy sizeof($5.a)); 324255332Scy 325255332Scy setmapifnames(); 326255332Scy } 327145510Sdarrenr ; 328145510Sdarrenr 329255332Scyredir: rdrit ifnames addr dport tlate dip nport setproto rdroptions 330255332Scy { if ($6 != 0 && $3.f != 0 && $6 != $3.f) 331255332Scy yyerror("21.address family mismatch"); 332255332Scy if (nat->in_v[0] == 0) { 333255332Scy if ($3.v != AF_UNSPEC) 334255332Scy nat->in_v[0] = ftov($3.f); 335255332Scy else 336255332Scy nat->in_v[0] = ftov($6); 337255332Scy } 338255332Scy nat->in_odstatype = $3.t; 339255332Scy bcopy(&$3.a, &nat->in_odst.na_addr[0], 340255332Scy sizeof($3.a)); 341255332Scy bcopy(&$3.m, &nat->in_odst.na_addr[1], 342255332Scy sizeof($3.a)); 343255332Scy 344255332Scy setrdrifnames(); 345145510Sdarrenr } 346255332Scy | no rdrit ifnames addr dport setproto ';' 347255332Scy { if (nat->in_v[0] == 0) 348255332Scy nat->in_v[0] = ftov($4.f); 349255332Scy nat->in_odstatype = $4.t; 350255332Scy bcopy(&$4.a, &nat->in_odst.na_addr[0], 351255332Scy sizeof($4.a)); 352255332Scy bcopy(&$4.m, &nat->in_odst.na_addr[1], 353255332Scy sizeof($4.a)); 354255332Scy 355255332Scy setrdrifnames(); 356145510Sdarrenr } 357255332Scy | rdrit ifnames rdrfrom tlate dip nport setproto rdroptions 358255332Scy { if ($5 != 0 && $3 != 0 && $5 != $3) 359255332Scy yyerror("20.address family mismatch"); 360255332Scy if (nat->in_v[0] == 0) { 361255332Scy if ($3 != AF_UNSPEC) 362255332Scy nat->in_v[0] = ftov($3); 363255332Scy else 364255332Scy nat->in_v[0] = ftov($5); 365255332Scy } 366255332Scy setrdrifnames(); 367145510Sdarrenr } 368255332Scy | no rdrit ifnames rdrfrom setproto ';' 369255332Scy { nat->in_v[0] = ftov($4); 370255332Scy 371255332Scy setrdrifnames(); 372161357Sguido } 373145510Sdarrenr ; 374145510Sdarrenr 375255332Scyrewrite: 376255332Scy IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts 377255332Scy { if (nat->in_v[0] == 0) 378255332Scy nat->in_v[0] = ftov($4); 379255332Scy if (nat->in_redir & NAT_MAP) 380255332Scy setmapifnames(); 381255332Scy else 382255332Scy setrdrifnames(); 383255332Scy nat->in_redir |= NAT_REWRITE; 384255332Scy } 385255332Scy ; 386255332Scy 387255332Scydivert: IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts 388255332Scy { if (nat->in_v[0] == 0) 389255332Scy nat->in_v[0] = ftov($4); 390255332Scy if (nat->in_redir & NAT_MAP) { 391255332Scy setmapifnames(); 392255332Scy nat->in_pr[0] = IPPROTO_UDP; 393255332Scy } else { 394255332Scy setrdrifnames(); 395255332Scy nat->in_pr[1] = IPPROTO_UDP; 396255332Scy } 397255332Scy nat->in_flags &= ~IPN_TCP; 398255332Scy } 399255332Scy ; 400255332Scy 401255332Scytlate: IPNY_TLATE { yyexpectaddr = 1; } 402255332Scy ; 403255332Scy 404255332Scypconf: IPNY_PROXY { yysetdict(proxies); } 405255332Scy IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{' 406255332Scy { proxy_setconfig(IPNY_DNS); } 407255332Scy dnslines ';' '}' 408255332Scy { proxy_addconfig("dns", $5, $7, $10); 409255332Scy proxy_unsetconfig(); 410255332Scy } 411255332Scy ; 412255332Scy 413255332Scydnslines: 414255332Scy dnsline { $$ = $1; } 415255332Scy | dnslines ';' dnsline { $$ = $1; $1->na_next = $3; } 416255332Scy ; 417255332Scy 418255332Scydnsline: 419255332Scy IPNY_ALLOW YY_STR { $$ = proxy_dns_add_pass(NULL, $2); } 420255332Scy | IPNY_DENY YY_STR { $$ = proxy_dns_add_block(NULL, $2); } 421255332Scy | IPNY_ALLOW '.' YY_STR { $$ = proxy_dns_add_pass(".", $3); } 422255332Scy | IPNY_DENY '.' YY_STR { $$ = proxy_dns_add_block(".", $3); } 423255332Scy ; 424255332Scy 425255332Scyoninout: 426255332Scy inout IPNY_ON ifnames { ; } 427255332Scy ; 428255332Scy 429255332Scyinout: IPNY_IN { nat->in_redir = NAT_REDIRECT; } 430255332Scy | IPNY_OUT { nat->in_redir = NAT_MAP; } 431255332Scy ; 432255332Scy 433255332Scyrwrproto: 434255332Scy | IPNY_PROTO setproto 435255332Scy ; 436255332Scy 437255332Scynewdst: src rhsaddr srcports dst erhdaddr dstports 438255332Scy { nat->in_nsrc.na_addr[0] = $2.a; 439255332Scy nat->in_nsrc.na_addr[1] = $2.m; 440255332Scy nat->in_nsrc.na_atype = $2.t; 441255332Scy if ($2.t == FRI_LOOKUP) { 442255332Scy nat->in_nsrc.na_type = $2.u; 443255332Scy nat->in_nsrc.na_subtype = $2.s; 444255332Scy nat->in_nsrc.na_num = $2.n; 445255332Scy } 446255332Scy nat->in_nsports[0] = $3.p1; 447255332Scy nat->in_nsports[1] = $3.p2; 448255332Scy nat->in_ndst.na_addr[0] = $5.a; 449255332Scy nat->in_ndst.na_addr[1] = $5.m; 450255332Scy nat->in_ndst.na_atype = $5.t; 451255332Scy if ($5.t == FRI_LOOKUP) { 452255332Scy nat->in_ndst.na_type = $5.u; 453255332Scy nat->in_ndst.na_subtype = $5.s; 454255332Scy nat->in_ndst.na_num = $5.n; 455255332Scy } 456255332Scy nat->in_ndports[0] = $6.p1; 457255332Scy nat->in_ndports[1] = $6.p2; 458255332Scy } 459255332Scy ; 460255332Scy 461255332Scydivdst: src addr ',' portspec dst addr ',' portspec IPNY_UDP 462255332Scy { nat->in_nsrc.na_addr[0] = $2.a; 463255332Scy if ($2.m.in4.s_addr != 0xffffffff) 464255332Scy yyerror("divert must have /32 dest"); 465255332Scy nat->in_nsrc.na_addr[1] = $2.m; 466255332Scy nat->in_nsports[0] = $4; 467255332Scy nat->in_nsports[1] = $4; 468255332Scy 469255332Scy nat->in_ndst.na_addr[0] = $6.a; 470255332Scy nat->in_ndst.na_addr[1] = $6.m; 471255332Scy if ($6.m.in4.s_addr != 0xffffffff) 472255332Scy yyerror("divert must have /32 dest"); 473255332Scy nat->in_ndports[0] = $8; 474255332Scy nat->in_ndports[1] = $8; 475255332Scy 476255332Scy nat->in_redir |= NAT_DIVERTUDP; 477255332Scy } 478255332Scy ; 479255332Scy 480255332Scysrc: IPNY_SRC { yyexpectaddr = 1; } 481255332Scy ; 482255332Scy 483255332Scydst: IPNY_DST { yyexpectaddr = 1; } 484255332Scy ; 485255332Scy 486255332Scysrcports: 487255332Scy comaports { $$.p1 = $1.p1; 488255332Scy $$.p2 = $1.p2; 489255332Scy } 490255332Scy | IPNY_PORT '=' portspec 491255332Scy { $$.p1 = $3; 492255332Scy $$.p2 = $3; 493255332Scy nat->in_flags |= IPN_FIXEDSPORT; 494255332Scy } 495255332Scy ; 496255332Scy 497255332Scydstports: 498255332Scy comaports { $$.p1 = $1.p1; 499255332Scy $$.p2 = $1.p2; 500255332Scy } 501255332Scy | IPNY_PORT '=' portspec 502255332Scy { $$.p1 = $3; 503255332Scy $$.p2 = $3; 504255332Scy nat->in_flags |= IPN_FIXEDDPORT; 505255332Scy } 506255332Scy ; 507255332Scy 508255332Scycomaports: 509255332Scy { $$.p1 = 0; 510255332Scy $$.p2 = 0; 511255332Scy } 512255332Scy | ',' { if (!(nat->in_flags & IPN_TCPUDP)) 513255332Scy yyerror("must be TCP/UDP for ports"); 514255332Scy } 515255332Scy portpair { $$.p1 = $3.p1; 516255332Scy $$.p2 = $3.p2; 517255332Scy } 518255332Scy ; 519255332Scy 520161357Sguidoproxy: | IPNY_PROXY port portspec YY_STR '/' proto 521255332Scy { int pos; 522255332Scy pos = addname(&nat, $4); 523255332Scy nat->in_plabel = pos; 524145510Sdarrenr if (nat->in_dcmp == 0) { 525255332Scy nat->in_odport = $3; 526255332Scy } else if ($3 != nat->in_odport) { 527145510Sdarrenr yyerror("proxy port numbers not consistant"); 528145510Sdarrenr } 529255332Scy nat->in_ndport = $3; 530145510Sdarrenr setnatproto($6); 531145510Sdarrenr free($4); 532145510Sdarrenr } 533161357Sguido | IPNY_PROXY port YY_STR YY_STR '/' proto 534255332Scy { int pnum, pos; 535255332Scy pos = addname(&nat, $4); 536255332Scy nat->in_plabel = pos; 537145510Sdarrenr pnum = getportproto($3, $6); 538145510Sdarrenr if (pnum == -1) 539145510Sdarrenr yyerror("invalid port number"); 540255332Scy nat->in_odport = ntohs(pnum); 541255332Scy nat->in_ndport = ntohs(pnum); 542145510Sdarrenr setnatproto($6); 543145510Sdarrenr free($3); 544145510Sdarrenr free($4); 545145510Sdarrenr } 546255332Scy | IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR 547255332Scy { int pos; 548255332Scy pos = addname(&nat, $4); 549255332Scy nat->in_plabel = pos; 550255332Scy if (nat->in_dcmp == 0) { 551255332Scy nat->in_odport = $3; 552255332Scy } else if ($3 != nat->in_odport) { 553255332Scy yyerror("proxy port numbers not consistant"); 554255332Scy } 555255332Scy nat->in_ndport = $3; 556255332Scy setnatproto($6); 557255332Scy nat->in_pconfig = addname(&nat, $8); 558255332Scy free($4); 559255332Scy free($8); 560255332Scy } 561255332Scy | IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR 562255332Scy { int pnum, pos; 563255332Scy pos = addname(&nat, $4); 564255332Scy nat->in_plabel = pos; 565255332Scy pnum = getportproto($3, $6); 566255332Scy if (pnum == -1) 567255332Scy yyerror("invalid port number"); 568255332Scy nat->in_odport = ntohs(pnum); 569255332Scy nat->in_ndport = ntohs(pnum); 570255332Scy setnatproto($6); 571255332Scy pos = addname(&nat, $8); 572255332Scy nat->in_pconfig = pos; 573255332Scy free($3); 574255332Scy free($4); 575255332Scy free($8); 576255332Scy } 577145510Sdarrenr ; 578145510Sdarrenrsetproto: 579255332Scy | proto { if (nat->in_pr[0] != 0 || 580255332Scy nat->in_pr[1] != 0 || 581145510Sdarrenr nat->in_flags & IPN_TCPUDP) 582145510Sdarrenr yyerror("protocol set twice"); 583145510Sdarrenr setnatproto($1); 584145510Sdarrenr } 585255332Scy | IPNY_TCPUDP { if (nat->in_pr[0] != 0 || 586255332Scy nat->in_pr[1] != 0 || 587145510Sdarrenr nat->in_flags & IPN_TCPUDP) 588145510Sdarrenr yyerror("protocol set twice"); 589145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 590255332Scy nat->in_pr[0] = 0; 591255332Scy nat->in_pr[1] = 0; 592145510Sdarrenr } 593255332Scy | IPNY_TCP '/' IPNY_UDP { if (nat->in_pr[0] != 0 || 594255332Scy nat->in_pr[1] != 0 || 595145510Sdarrenr nat->in_flags & IPN_TCPUDP) 596145510Sdarrenr yyerror("protocol set twice"); 597145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 598255332Scy nat->in_pr[0] = 0; 599255332Scy nat->in_pr[1] = 0; 600145510Sdarrenr } 601145510Sdarrenr ; 602145510Sdarrenr 603255332Scyrhsaddr: 604255332Scy addr { $$ = $1; 605255332Scy yyexpectaddr = 0; 606255332Scy } 607255332Scy | hostname '-' { yyexpectaddr = 1; } hostname 608255332Scy { $$.t = FRI_RANGE; 609255332Scy if ($1.f != $4.f) 610255332Scy yyerror("8.address family " 611255332Scy "mismatch"); 612255332Scy $$.f = $1.f; 613255332Scy $$.v = ftov($1.f); 614255332Scy $$.a = $1.a; 615255332Scy $$.m = $4.a; 616255332Scy nat->in_flags |= IPN_SIPRANGE; 617255332Scy yyexpectaddr = 0; 618255332Scy } 619255332Scy | IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname 620255332Scy { $$.t = FRI_RANGE; 621255332Scy if ($2.f != $5.f) 622255332Scy yyerror("9.address family " 623255332Scy "mismatch"); 624255332Scy $$.f = $2.f; 625255332Scy $$.v = ftov($2.f); 626255332Scy $$.a = $2.a; 627255332Scy $$.m = $5.a; 628255332Scy nat->in_flags |= IPN_SIPRANGE; 629255332Scy yyexpectaddr = 0; 630255332Scy } 631145510Sdarrenr ; 632145510Sdarrenr 633145510Sdarrenrdip: 634255332Scy hostname ',' { yyexpectaddr = 1; } hostname 635255332Scy { nat->in_flags |= IPN_SPLIT; 636255332Scy if ($1.f != $4.f) 637255332Scy yyerror("10.address family " 638255332Scy "mismatch"); 639255332Scy $$ = $1.f; 640255332Scy nat->in_ndstip6 = $1.a; 641255332Scy nat->in_ndstmsk6 = $4.a; 642255332Scy nat->in_ndstatype = FRI_SPLIT; 643255332Scy yyexpectaddr = 0; 644255332Scy } 645255332Scy | rhdaddr { int bits; 646255332Scy nat->in_ndstip6 = $1.a; 647255332Scy nat->in_ndstmsk6 = $1.m; 648255332Scy nat->in_ndst.na_atype = $1.t; 649255332Scy yyexpectaddr = 0; 650255332Scy if ($1.f == AF_INET) 651255332Scy bits = count4bits($1.m.in4.s_addr); 652255332Scy else 653255332Scy bits = count6bits($1.m.i6); 654255332Scy if (($1.f == AF_INET) && (bits != 0) && 655255332Scy (bits != 32)) { 656255332Scy yyerror("dest ip bitmask not /32"); 657255332Scy } else if (($1.f == AF_INET6) && 658255332Scy (bits != 0) && (bits != 128)) { 659255332Scy yyerror("dest ip bitmask not /128"); 660255332Scy } 661255332Scy $$ = $1.f; 662255332Scy } 663255332Scy ; 664255332Scy 665255332Scyrhdaddr: 666255332Scy addr { $$ = $1; 667255332Scy yyexpectaddr = 0; 668153881Sguido } 669255332Scy | hostname '-' hostname { bzero(&$$, sizeof($$)); 670255332Scy $$.t = FRI_RANGE; 671255332Scy if ($1.f != 0 && $3.f != 0 && 672255332Scy $1.f != $3.f) 673255332Scy yyerror("11.address family " 674255332Scy "mismatch"); 675255332Scy $$.a = $1.a; 676255332Scy $$.m = $3.a; 677255332Scy nat->in_flags |= IPN_DIPRANGE; 678255332Scy yyexpectaddr = 0; 679255332Scy } 680255332Scy | IPNY_RANGE hostname '-' hostname 681255332Scy { bzero(&$$, sizeof($$)); 682255332Scy $$.t = FRI_RANGE; 683255332Scy if ($2.f != 0 && $4.f != 0 && 684255332Scy $2.f != $4.f) 685255332Scy yyerror("12.address family " 686255332Scy "mismatch"); 687255332Scy $$.a = $2.a; 688255332Scy $$.m = $4.a; 689255332Scy nat->in_flags |= IPN_DIPRANGE; 690255332Scy yyexpectaddr = 0; 691255332Scy } 692145510Sdarrenr ; 693145510Sdarrenr 694255332Scyerhdaddr: 695255332Scy rhdaddr { $$ = $1; } 696255332Scy | IPNY_DSTLIST '/' YY_NUMBER { $$.t = FRI_LOOKUP; 697255332Scy $$.u = IPLT_DSTLIST; 698255332Scy $$.s = 0; 699255332Scy $$.n = $3; 700255332Scy } 701255332Scy | IPNY_DSTLIST '/' YY_STR { $$.t = FRI_LOOKUP; 702255332Scy $$.u = IPLT_DSTLIST; 703255332Scy $$.s = 1; 704255332Scy $$.n = addname(&nat, $3); 705255332Scy } 706255332Scy ; 707255332Scy 708161357Sguidoport: IPNY_PORT { suggest_port = 1; } 709161357Sguido ; 710161357Sguido 711145510Sdarrenrportspec: 712145510Sdarrenr YY_NUMBER { if ($1 > 65535) /* Unsigned */ 713145510Sdarrenr yyerror("invalid port number"); 714145510Sdarrenr else 715145510Sdarrenr $$ = $1; 716145510Sdarrenr } 717255332Scy | YY_STR { if (getport(NULL, $1, 718255332Scy &($$), NULL) == -1) 719145510Sdarrenr yyerror("invalid port number"); 720145510Sdarrenr $$ = ntohs($$); 721145510Sdarrenr } 722145510Sdarrenr ; 723145510Sdarrenr 724255332Scyportpair: 725255332Scy portspec { $$.p1 = $1; $$.p2 = $1; } 726255332Scy | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; } 727255332Scy | portspec ':' portspec { $$.p1 = $1; $$.p2 = $3; } 728145510Sdarrenr ; 729145510Sdarrenr 730255332Scydport: | port portpair { nat->in_odport = $2.p1; 731255332Scy if ($2.p2 == 0) 732255332Scy nat->in_dtop = $2.p1; 733255332Scy else 734255332Scy nat->in_dtop = $2.p2; 735255332Scy } 736255332Scy ; 737255332Scy 738255332Scynport: | port portpair { nat->in_dpmin = $2.p1; 739255332Scy nat->in_dpnext = $2.p1; 740255332Scy nat->in_dpmax = $2.p2; 741255332Scy nat->in_ndport = $2.p1; 742255332Scy if (nat->in_dtop == 0) 743255332Scy nat->in_dtop = $2.p2; 744255332Scy } 745255332Scy | port '=' portspec { nat->in_dpmin = $3; 746255332Scy nat->in_dpnext = $3; 747255332Scy nat->in_ndport = $3; 748255332Scy if (nat->in_dtop == 0) 749255332Scy nat->in_dtop = nat->in_odport; 750145510Sdarrenr nat->in_flags |= IPN_FIXEDDPORT; 751145510Sdarrenr } 752145510Sdarrenr ; 753145510Sdarrenr 754255332Scyports: | IPNY_PORTS YY_NUMBER { nat->in_spmin = $2; } 755145510Sdarrenr | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } 756145510Sdarrenr ; 757145510Sdarrenr 758145510Sdarrenrmapit: IPNY_MAP { nat->in_redir = NAT_MAP; } 759145510Sdarrenr | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; } 760145510Sdarrenr ; 761145510Sdarrenr 762145510Sdarrenrrdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; } 763145510Sdarrenr ; 764145510Sdarrenr 765145510Sdarrenrmapblockit: 766145510Sdarrenr IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; } 767145510Sdarrenr ; 768145510Sdarrenr 769145510Sdarrenrmapfrom: 770255332Scy from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) 771255332Scy yyerror("13.address family " 772255332Scy "mismatch"); 773255332Scy $$ = $2; 774255332Scy } 775255332Scy | from sobject '!' to dobject 776255332Scy { if ($2 != 0 && $5 != 0 && $2 != $5) 777255332Scy yyerror("14.address family " 778255332Scy "mismatch"); 779255332Scy nat->in_flags |= IPN_NOTDST; 780255332Scy $$ = $2; 781255332Scy } 782255332Scy | from sobject to '!' dobject 783255332Scy { if ($2 != 0 && $5 != 0 && $2 != $5) 784255332Scy yyerror("15.address family " 785255332Scy "mismatch"); 786255332Scy nat->in_flags |= IPN_NOTDST; 787255332Scy $$ = $2; 788255332Scy } 789145510Sdarrenr ; 790145510Sdarrenr 791145510Sdarrenrrdrfrom: 792255332Scy from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) 793255332Scy yyerror("16.address family " 794255332Scy "mismatch"); 795255332Scy $$ = $2; 796255332Scy } 797255332Scy | '!' from sobject to dobject 798255332Scy { if ($3 != 0 && $5 != 0 && $3 != $5) 799255332Scy yyerror("17.address family " 800255332Scy "mismatch"); 801255332Scy nat->in_flags |= IPN_NOTSRC; 802255332Scy $$ = $3; 803255332Scy } 804255332Scy | from '!' sobject to dobject 805255332Scy { if ($3 != 0 && $5 != 0 && $3 != $5) 806255332Scy yyerror("18.address family " 807255332Scy "mismatch"); 808255332Scy nat->in_flags |= IPN_NOTSRC; 809255332Scy $$ = $3; 810255332Scy } 811145510Sdarrenr ; 812145510Sdarrenr 813255332Scyfrom: IPNY_FROM { nat->in_flags |= IPN_FILTER; 814255332Scy yyexpectaddr = 1; 815255332Scy } 816145510Sdarrenr ; 817145510Sdarrenr 818255332Scyto: IPNY_TO { yyexpectaddr = 1; } 819255332Scy ; 820255332Scy 821145510Sdarrenrifnames: 822255332Scy ifname family { yyexpectaddr = 1; } 823255332Scy | ifname ',' otherifname family { yyexpectaddr = 1; } 824145510Sdarrenr ; 825145510Sdarrenr 826255332Scyifname: YY_STR { setifname(&nat, 0, $1); 827255332Scy free($1); 828255332Scy } 829145510Sdarrenr ; 830145510Sdarrenr 831255332Scyfamily: | IPNY_INET { nat->in_v[0] = 4; nat->in_v[1] = 4; } 832255332Scy | IPNY_INET6 { nat->in_v[0] = 6; nat->in_v[1] = 6; } 833255332Scy ; 834255332Scy 835145510Sdarrenrotherifname: 836255332Scy YY_STR { setifname(&nat, 1, $1); 837255332Scy free($1); 838255332Scy } 839145510Sdarrenr ; 840145510Sdarrenr 841145510Sdarrenrmapport: 842255332Scy IPNY_PORTMAP tcpudp portpair sequential 843255332Scy { nat->in_spmin = $3.p1; 844255332Scy nat->in_spmax = $3.p2; 845255332Scy } 846255332Scy | IPNY_PORTMAP portpair tcpudp sequential 847255332Scy { nat->in_spmin = $2.p1; 848255332Scy nat->in_spmax = $2.p2; 849255332Scy } 850255332Scy | IPNY_PORTMAP tcpudp IPNY_AUTO sequential 851255332Scy { nat->in_flags |= IPN_AUTOPORTMAP; 852255332Scy nat->in_spmin = 1024; 853255332Scy nat->in_spmax = 65535; 854255332Scy } 855255332Scy | IPNY_ICMPIDMAP YY_STR portpair sequential 856255332Scy { if (strcmp($2, "icmp") != 0 && 857255332Scy strcmp($2, "ipv6-icmp") != 0) { 858145510Sdarrenr yyerror("icmpidmap not followed by icmp"); 859145510Sdarrenr } 860145510Sdarrenr free($2); 861255332Scy if ($3.p1 < 0 || $3.p1 > 65535) 862271978Scy yyerror("invalid 1st ICMP Id number"); 863255332Scy if ($3.p2 < 0 || $3.p2 > 65535) 864271978Scy yyerror("invalid 2nd ICMP Id number"); 865255332Scy if (strcmp($2, "ipv6-icmp") == 0) { 866255332Scy nat->in_pr[0] = IPPROTO_ICMPV6; 867255332Scy nat->in_pr[1] = IPPROTO_ICMPV6; 868255332Scy } else { 869255332Scy nat->in_pr[0] = IPPROTO_ICMP; 870255332Scy nat->in_pr[1] = IPPROTO_ICMP; 871255332Scy } 872145510Sdarrenr nat->in_flags = IPN_ICMPQUERY; 873255332Scy nat->in_spmin = $3.p1; 874255332Scy nat->in_spmax = $3.p2; 875145510Sdarrenr } 876145510Sdarrenr ; 877145510Sdarrenr 878145510Sdarrenrsobject: 879255332Scy saddr { $$ = $1; } 880255332Scy | saddr port portstuff { nat->in_osport = $3.p1; 881145510Sdarrenr nat->in_stop = $3.p2; 882255332Scy nat->in_scmp = $3.pc; 883255332Scy $$ = $1; 884255332Scy } 885145510Sdarrenr ; 886145510Sdarrenr 887255332Scysaddr: addr { nat->in_osrcatype = $1.t; 888255332Scy bcopy(&$1.a, 889255332Scy &nat->in_osrc.na_addr[0], 890255332Scy sizeof($1.a)); 891255332Scy bcopy(&$1.m, 892255332Scy &nat->in_osrc.na_addr[1], 893255332Scy sizeof($1.m)); 894255332Scy $$ = $1.f; 895145510Sdarrenr } 896145510Sdarrenr ; 897145510Sdarrenr 898145510Sdarrenrdobject: 899255332Scy daddr { $$ = $1; } 900255332Scy | daddr port portstuff { nat->in_odport = $3.p1; 901145510Sdarrenr nat->in_dtop = $3.p2; 902145510Sdarrenr nat->in_dcmp = $3.pc; 903255332Scy $$ = $1; 904145510Sdarrenr } 905145510Sdarrenr ; 906145510Sdarrenr 907255332Scydaddr: addr { nat->in_odstatype = $1.t; 908255332Scy bcopy(&$1.a, 909255332Scy &nat->in_odst.na_addr[0], 910255332Scy sizeof($1.a)); 911255332Scy bcopy(&$1.m, 912255332Scy &nat->in_odst.na_addr[1], 913255332Scy sizeof($1.m)); 914255332Scy $$ = $1.f; 915255332Scy } 916255332Scy ; 917255332Scy 918255332Scyaddr: IPNY_ANY { yyexpectaddr = 0; 919255332Scy bzero(&$$, sizeof($$)); 920255332Scy $$.t = FRI_NORMAL; 921255332Scy } 922255332Scy | hostname { bzero(&$$, sizeof($$)); 923255332Scy $$.a = $1.a; 924255332Scy $$.t = FRI_NORMAL; 925255332Scy $$.v = ftov($1.f); 926255332Scy $$.f = $1.f; 927255332Scy if ($$.f == AF_INET) { 928255332Scy $$.m.in4.s_addr = 0xffffffff; 929255332Scy } else if ($$.f == AF_INET6) { 930255332Scy $$.m.i6[0] = 0xffffffff; 931255332Scy $$.m.i6[1] = 0xffffffff; 932255332Scy $$.m.i6[2] = 0xffffffff; 933255332Scy $$.m.i6[3] = 0xffffffff; 934145510Sdarrenr } 935255332Scy yyexpectaddr = 0; 936145510Sdarrenr } 937255332Scy | hostname slash YY_NUMBER 938255332Scy { bzero(&$$, sizeof($$)); 939255332Scy $$.a = $1.a; 940255332Scy $$.f = $1.f; 941255332Scy $$.v = ftov($1.f); 942255332Scy $$.t = FRI_NORMAL; 943255332Scy ntomask($$.f, $3, (u_32_t *)&$$.m); 944255332Scy $$.a.i6[0] &= $$.m.i6[0]; 945255332Scy $$.a.i6[1] &= $$.m.i6[1]; 946255332Scy $$.a.i6[2] &= $$.m.i6[2]; 947255332Scy $$.a.i6[3] &= $$.m.i6[3]; 948255332Scy yyexpectaddr = 0; 949255332Scy } 950255332Scy | hostname slash ipaddr { bzero(&$$, sizeof($$)); 951255332Scy if ($1.f != $3.f) { 952255332Scy yyerror("1.address family " 953255332Scy "mismatch"); 954255332Scy } 955255332Scy $$.a = $1.a; 956255332Scy $$.m = $3.a; 957255332Scy $$.t = FRI_NORMAL; 958255332Scy $$.a.i6[0] &= $$.m.i6[0]; 959255332Scy $$.a.i6[1] &= $$.m.i6[1]; 960255332Scy $$.a.i6[2] &= $$.m.i6[2]; 961255332Scy $$.a.i6[3] &= $$.m.i6[3]; 962255332Scy $$.f = $1.f; 963255332Scy $$.v = ftov($1.f); 964255332Scy yyexpectaddr = 0; 965255332Scy } 966255332Scy | hostname slash hexnumber { bzero(&$$, sizeof($$)); 967255332Scy $$.a = $1.a; 968255332Scy $$.m.in4.s_addr = htonl($3); 969255332Scy $$.t = FRI_NORMAL; 970255332Scy $$.a.in4.s_addr &= $$.m.in4.s_addr; 971255332Scy $$.f = $1.f; 972255332Scy $$.v = ftov($1.f); 973255332Scy if ($$.f == AF_INET6) 974255332Scy yyerror("incorrect inet6 mask"); 975255332Scy } 976255332Scy | hostname mask ipaddr { bzero(&$$, sizeof($$)); 977255332Scy if ($1.f != $3.f) { 978255332Scy yyerror("2.address family " 979255332Scy "mismatch"); 980255332Scy } 981255332Scy $$.a = $1.a; 982255332Scy $$.m = $3.a; 983255332Scy $$.t = FRI_NORMAL; 984255332Scy $$.a.i6[0] &= $$.m.i6[0]; 985255332Scy $$.a.i6[1] &= $$.m.i6[1]; 986255332Scy $$.a.i6[2] &= $$.m.i6[2]; 987255332Scy $$.a.i6[3] &= $$.m.i6[3]; 988255332Scy $$.f = $1.f; 989255332Scy $$.v = ftov($1.f); 990255332Scy yyexpectaddr = 0; 991255332Scy } 992255332Scy | hostname mask hexnumber { bzero(&$$, sizeof($$)); 993255332Scy $$.a = $1.a; 994255332Scy $$.m.in4.s_addr = htonl($3); 995255332Scy $$.t = FRI_NORMAL; 996255332Scy $$.a.in4.s_addr &= $$.m.in4.s_addr; 997255332Scy $$.f = AF_INET; 998255332Scy $$.v = 4; 999255332Scy } 1000255332Scy | pool slash YY_NUMBER { bzero(&$$, sizeof($$)); 1001255332Scy $$.a.iplookupnum = $3; 1002255332Scy $$.a.iplookuptype = IPLT_POOL; 1003255332Scy $$.a.iplookupsubtype = 0; 1004255332Scy $$.t = FRI_LOOKUP; 1005255332Scy } 1006255332Scy | pool slash YY_STR { bzero(&$$, sizeof($$)); 1007255332Scy $$.a.iplookupname = addname(&nat,$3); 1008255332Scy $$.a.iplookuptype = IPLT_POOL; 1009255332Scy $$.a.iplookupsubtype = 1; 1010255332Scy $$.t = FRI_LOOKUP; 1011255332Scy } 1012255332Scy | hash slash YY_NUMBER { bzero(&$$, sizeof($$)); 1013255332Scy $$.a.iplookupnum = $3; 1014255332Scy $$.a.iplookuptype = IPLT_HASH; 1015255332Scy $$.a.iplookupsubtype = 0; 1016255332Scy $$.t = FRI_LOOKUP; 1017255332Scy } 1018255332Scy | hash slash YY_STR { bzero(&$$, sizeof($$)); 1019255332Scy $$.a.iplookupname = addname(&nat,$3); 1020255332Scy $$.a.iplookuptype = IPLT_HASH; 1021255332Scy $$.a.iplookupsubtype = 1; 1022255332Scy $$.t = FRI_LOOKUP; 1023255332Scy } 1024145510Sdarrenr ; 1025145510Sdarrenr 1026255332Scyslash: '/' { yyexpectaddr = 0; } 1027145510Sdarrenr ; 1028145510Sdarrenr 1029255332Scymask: IPNY_MASK { yyexpectaddr = 0; } 1030145510Sdarrenr ; 1031145510Sdarrenr 1032255332Scypool: IPNY_POOL { if (!(nat->in_flags & IPN_FILTER)) { 1033255332Scy yyerror("Can only use pool with from/to rules\n"); 1034255332Scy } 1035255332Scy yyexpectaddr = 0; 1036255332Scy yyresetdict(); 1037255332Scy } 1038255332Scy ; 1039255332Scy 1040255332Scyhash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) { 1041255332Scy yyerror("Can only use hash with from/to rules\n"); 1042255332Scy } 1043255332Scy yyexpectaddr = 0; 1044255332Scy yyresetdict(); 1045255332Scy } 1046255332Scy ; 1047255332Scy 1048145510Sdarrenrportstuff: 1049271978Scy compare portspec { $$.pc = $1; $$.p1 = $2; $$.p2 = 0; } 1050153881Sguido | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } 1051145510Sdarrenr ; 1052145510Sdarrenr 1053145510Sdarrenrmapoptions: 1054255332Scy rr frag age mssclamp nattag setproto purge 1055145510Sdarrenr ; 1056145510Sdarrenr 1057145510Sdarrenrrdroptions: 1058255332Scy rr frag age sticky mssclamp rdrproxy nattag purge 1059145510Sdarrenr ; 1060145510Sdarrenr 1061145510Sdarrenrnattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, 1062145510Sdarrenr sizeof(nat->in_tag.ipt_tag)); 1063145510Sdarrenr } 1064145510Sdarrenrrr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; } 1065145510Sdarrenr ; 1066145510Sdarrenr 1067145510Sdarrenrfrag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; } 1068145510Sdarrenr ; 1069145510Sdarrenr 1070145510Sdarrenrage: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; 1071145510Sdarrenr nat->in_age[1] = $2; } 1072145510Sdarrenr | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2; 1073145510Sdarrenr nat->in_age[1] = $4; } 1074145510Sdarrenr ; 1075145510Sdarrenr 1076255332Scysticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && 1077145510Sdarrenr !(nat->in_flags & IPN_SPLIT)) { 1078255332Scy FPRINTF(stderr, 1079145510Sdarrenr "'sticky' for use with round-robin/IP splitting only\n"); 1080145510Sdarrenr } else 1081145510Sdarrenr nat->in_flags |= IPN_STICKY; 1082145510Sdarrenr } 1083145510Sdarrenr ; 1084145510Sdarrenr 1085145510Sdarrenrmssclamp: 1086145510Sdarrenr | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } 1087145510Sdarrenr ; 1088145510Sdarrenr 1089255332Scytcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); } 1090145510Sdarrenr | IPNY_UDP { setnatproto(IPPROTO_UDP); } 1091145510Sdarrenr | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; 1092255332Scy nat->in_pr[0] = 0; 1093255332Scy nat->in_pr[1] = 0; 1094145510Sdarrenr } 1095145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; 1096255332Scy nat->in_pr[0] = 0; 1097255332Scy nat->in_pr[1] = 0; 1098145510Sdarrenr } 1099145510Sdarrenr ; 1100145510Sdarrenr 1101255332Scysequential: 1102255332Scy | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; } 1103255332Scy ; 1104255332Scy 1105255332Scypurge: 1106255332Scy | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } 1107255332Scy ; 1108255332Scy 1109145510Sdarrenrrdrproxy: 1110145510Sdarrenr IPNY_PROXY YY_STR 1111255332Scy { int pos; 1112255332Scy pos = addname(&nat, $2); 1113255332Scy nat->in_plabel = pos; 1114255332Scy nat->in_odport = nat->in_dpnext; 1115255332Scy nat->in_dtop = nat->in_odport; 1116145510Sdarrenr free($2); 1117145510Sdarrenr } 1118255332Scy | proxy { if (nat->in_plabel != -1) { 1119255332Scy nat->in_ndport = nat->in_odport; 1120255332Scy nat->in_dpmin = nat->in_odport; 1121255332Scy nat->in_dpmax = nat->in_dpmin; 1122255332Scy nat->in_dtop = nat->in_dpmin; 1123255332Scy nat->in_dpnext = nat->in_dpmin; 1124255332Scy } 1125255332Scy } 1126145510Sdarrenr ; 1127145510Sdarrenr 1128255332Scynewopts: 1129255332Scy | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } 1130255332Scy ; 1131255332Scy 1132161357Sguidoproto: YY_NUMBER { $$ = $1; 1133161357Sguido if ($$ != IPPROTO_TCP && 1134161357Sguido $$ != IPPROTO_UDP) 1135161357Sguido suggest_port = 0; 1136161357Sguido } 1137145510Sdarrenr | IPNY_TCP { $$ = IPPROTO_TCP; } 1138145510Sdarrenr | IPNY_UDP { $$ = IPPROTO_UDP; } 1139255332Scy | YY_STR { $$ = getproto($1); 1140255332Scy free($1); 1141255332Scy if ($$ == -1) 1142271978Scy yyerror("unknown protocol"); 1143161357Sguido if ($$ != IPPROTO_TCP && 1144161357Sguido $$ != IPPROTO_UDP) 1145161357Sguido suggest_port = 0; 1146161357Sguido } 1147145510Sdarrenr ; 1148145510Sdarrenr 1149145510Sdarrenrhexnumber: 1150145510Sdarrenr YY_HEX { $$ = $1; } 1151145510Sdarrenr ; 1152145510Sdarrenr 1153145510Sdarrenrhostname: 1154255332Scy YY_STR { i6addr_t addr; 1155271977Scy int family; 1156255332Scy 1157271977Scy#ifdef USE_INET6 1158271977Scy if (nat->in_v[0] == 6) 1159271977Scy family = AF_INET6; 1160271977Scy else 1161271977Scy#endif 1162271977Scy family = AF_INET; 1163271978Scy memset(&($$), 0, sizeof($$)); 1164271978Scy memset(&addr, 0, sizeof(addr)); 1165271977Scy $$.f = family; 1166271977Scy if (gethost(family, $1, 1167255332Scy &addr) == 0) { 1168255332Scy $$.a = addr; 1169255332Scy } else { 1170255332Scy FPRINTF(stderr, 1171145510Sdarrenr "Unknown host '%s'\n", 1172145510Sdarrenr $1); 1173255332Scy } 1174145510Sdarrenr free($1); 1175145510Sdarrenr } 1176271978Scy | YY_NUMBER { memset(&($$), 0, sizeof($$)); 1177255332Scy $$.a.in4.s_addr = htonl($1); 1178255332Scy if ($$.a.in4.s_addr != 0) 1179255332Scy $$.f = AF_INET; 1180255332Scy } 1181255332Scy | ipv4 { $$ = $1; } 1182271978Scy | YY_IPV6 { memset(&($$), 0, sizeof($$)); 1183255332Scy $$.a = $1; 1184255332Scy $$.f = AF_INET6; 1185255332Scy } 1186271978Scy | YY_NUMBER YY_IPV6 { memset(&($$), 0, sizeof($$)); 1187255332Scy $$.a = $2; 1188255332Scy $$.f = AF_INET6; 1189255332Scy } 1190145510Sdarrenr ; 1191145510Sdarrenr 1192145510Sdarrenrcompare: 1193145510Sdarrenr '=' { $$ = FR_EQUAL; } 1194145510Sdarrenr | YY_CMP_EQ { $$ = FR_EQUAL; } 1195145510Sdarrenr | YY_CMP_NE { $$ = FR_NEQUAL; } 1196145510Sdarrenr | YY_CMP_LT { $$ = FR_LESST; } 1197145510Sdarrenr | YY_CMP_LE { $$ = FR_LESSTE; } 1198145510Sdarrenr | YY_CMP_GT { $$ = FR_GREATERT; } 1199145510Sdarrenr | YY_CMP_GE { $$ = FR_GREATERTE; } 1200145510Sdarrenr 1201145510Sdarrenrrange: 1202145510Sdarrenr YY_RANGE_OUT { $$ = FR_OUTRANGE; } 1203145510Sdarrenr | YY_RANGE_IN { $$ = FR_INRANGE; } 1204172776Sdarrenr | ':' { $$ = FR_INCRANGE; } 1205145510Sdarrenr ; 1206145510Sdarrenr 1207255332Scyipaddr: ipv4 { $$ = $1; } 1208255332Scy | YY_IPV6 { $$.a = $1; 1209255332Scy $$.f = AF_INET6; 1210255332Scy } 1211255332Scy ; 1212255332Scy 1213145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 1214145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 1215145510Sdarrenr yyerror("Invalid octet string for IP address"); 1216145510Sdarrenr return 0; 1217145510Sdarrenr } 1218255332Scy bzero((char *)&$$, sizeof($$)); 1219255332Scy $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 1220255332Scy $$.a.in4.s_addr = htonl($$.a.in4.s_addr); 1221255332Scy $$.f = AF_INET; 1222145510Sdarrenr } 1223145510Sdarrenr ; 1224145510Sdarrenr 1225145510Sdarrenr%% 1226145510Sdarrenr 1227145510Sdarrenr 1228255332Scystatic wordtab_t proxies[] = { 1229255332Scy { "dns", IPNY_DNS } 1230255332Scy}; 1231255332Scy 1232255332Scystatic wordtab_t dnswords[] = { 1233255332Scy { "allow", IPNY_ALLOW }, 1234255332Scy { "block", IPNY_DENY }, 1235255332Scy { "deny", IPNY_DENY }, 1236255332Scy { "drop", IPNY_DENY }, 1237255332Scy { "pass", IPNY_ALLOW }, 1238255332Scy 1239255332Scy}; 1240255332Scy 1241145510Sdarrenrstatic wordtab_t yywords[] = { 1242145510Sdarrenr { "age", IPNY_AGE }, 1243145510Sdarrenr { "any", IPNY_ANY }, 1244145510Sdarrenr { "auto", IPNY_AUTO }, 1245145510Sdarrenr { "bimap", IPNY_BIMAP }, 1246255332Scy { "config", IPNY_CONFIG }, 1247255332Scy { "divert", IPNY_DIVERT }, 1248255332Scy { "dst", IPNY_DST }, 1249255332Scy { "dstlist", IPNY_DSTLIST }, 1250145510Sdarrenr { "frag", IPNY_FRAG }, 1251145510Sdarrenr { "from", IPNY_FROM }, 1252255332Scy { "hash", IPNY_HASH }, 1253145510Sdarrenr { "icmpidmap", IPNY_ICMPIDMAP }, 1254255332Scy { "in", IPNY_IN }, 1255255332Scy { "inet", IPNY_INET }, 1256255332Scy { "inet6", IPNY_INET6 }, 1257145510Sdarrenr { "mask", IPNY_MASK }, 1258145510Sdarrenr { "map", IPNY_MAP }, 1259145510Sdarrenr { "map-block", IPNY_MAPBLOCK }, 1260145510Sdarrenr { "mssclamp", IPNY_MSSCLAMP }, 1261145510Sdarrenr { "netmask", IPNY_MASK }, 1262255332Scy { "no", IPNY_NO }, 1263255332Scy { "on", IPNY_ON }, 1264255332Scy { "out", IPNY_OUT }, 1265255332Scy { "pool", IPNY_POOL }, 1266145510Sdarrenr { "port", IPNY_PORT }, 1267145510Sdarrenr { "portmap", IPNY_PORTMAP }, 1268145510Sdarrenr { "ports", IPNY_PORTS }, 1269255332Scy { "proto", IPNY_PROTO }, 1270145510Sdarrenr { "proxy", IPNY_PROXY }, 1271255332Scy { "purge", IPNY_PURGE }, 1272145510Sdarrenr { "range", IPNY_RANGE }, 1273255332Scy { "rewrite", IPNY_REWRITE }, 1274145510Sdarrenr { "rdr", IPNY_RDR }, 1275145510Sdarrenr { "round-robin",IPNY_ROUNDROBIN }, 1276180778Sdarrenr { "sequential", IPNY_SEQUENTIAL }, 1277255332Scy { "src", IPNY_SRC }, 1278145510Sdarrenr { "sticky", IPNY_STICKY }, 1279145510Sdarrenr { "tag", IPNY_TAG }, 1280145510Sdarrenr { "tcp", IPNY_TCP }, 1281145510Sdarrenr { "tcpudp", IPNY_TCPUDP }, 1282145510Sdarrenr { "to", IPNY_TO }, 1283145510Sdarrenr { "udp", IPNY_UDP }, 1284145510Sdarrenr { "-", '-' }, 1285145510Sdarrenr { "->", IPNY_TLATE }, 1286145510Sdarrenr { "eq", YY_CMP_EQ }, 1287145510Sdarrenr { "ne", YY_CMP_NE }, 1288145510Sdarrenr { "lt", YY_CMP_LT }, 1289145510Sdarrenr { "gt", YY_CMP_GT }, 1290145510Sdarrenr { "le", YY_CMP_LE }, 1291145510Sdarrenr { "ge", YY_CMP_GE }, 1292145510Sdarrenr { NULL, 0 } 1293145510Sdarrenr}; 1294145510Sdarrenr 1295145510Sdarrenr 1296255332Scyint 1297255332Scyipnat_parsefile(fd, addfunc, ioctlfunc, filename) 1298255332Scy int fd; 1299255332Scy addfunc_t addfunc; 1300255332Scy ioctlfunc_t ioctlfunc; 1301255332Scy char *filename; 1302145510Sdarrenr{ 1303145510Sdarrenr FILE *fp = NULL; 1304255332Scy int rval; 1305145510Sdarrenr char *s; 1306145510Sdarrenr 1307255332Scy yylineNum = 1; 1308255332Scy 1309145510Sdarrenr (void) yysettab(yywords); 1310145510Sdarrenr 1311145510Sdarrenr s = getenv("YYDEBUG"); 1312145510Sdarrenr if (s) 1313145510Sdarrenr yydebug = atoi(s); 1314145510Sdarrenr else 1315145510Sdarrenr yydebug = 0; 1316145510Sdarrenr 1317145510Sdarrenr if (strcmp(filename, "-")) { 1318145510Sdarrenr fp = fopen(filename, "r"); 1319145510Sdarrenr if (!fp) { 1320255332Scy FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, 1321145510Sdarrenr STRERROR(errno)); 1322145510Sdarrenr return -1; 1323145510Sdarrenr } 1324145510Sdarrenr } else 1325145510Sdarrenr fp = stdin; 1326145510Sdarrenr 1327255332Scy while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) 1328145510Sdarrenr ; 1329145510Sdarrenr if (fp != NULL) 1330145510Sdarrenr fclose(fp); 1331255332Scy if (rval == -1) 1332255332Scy rval = 0; 1333255332Scy else if (rval != 0) 1334255332Scy rval = 1; 1335255332Scy return rval; 1336145510Sdarrenr} 1337145510Sdarrenr 1338145510Sdarrenr 1339255332Scyint 1340255332Scyipnat_parsesome(fd, addfunc, ioctlfunc, fp) 1341255332Scy int fd; 1342255332Scy addfunc_t addfunc; 1343255332Scy ioctlfunc_t ioctlfunc; 1344255332Scy FILE *fp; 1345145510Sdarrenr{ 1346145510Sdarrenr char *s; 1347145510Sdarrenr int i; 1348145510Sdarrenr 1349145510Sdarrenr natfd = fd; 1350255332Scy parser_error = 0; 1351145510Sdarrenr nataddfunc = addfunc; 1352145510Sdarrenr natioctlfunc = ioctlfunc; 1353145510Sdarrenr 1354145510Sdarrenr if (feof(fp)) 1355255332Scy return -1; 1356145510Sdarrenr i = fgetc(fp); 1357145510Sdarrenr if (i == EOF) 1358255332Scy return -1; 1359145510Sdarrenr if (ungetc(i, fp) == EOF) 1360255332Scy return -1; 1361145510Sdarrenr if (feof(fp)) 1362255332Scy return -1; 1363145510Sdarrenr s = getenv("YYDEBUG"); 1364145510Sdarrenr if (s) 1365145510Sdarrenr yydebug = atoi(s); 1366145510Sdarrenr else 1367145510Sdarrenr yydebug = 0; 1368145510Sdarrenr 1369145510Sdarrenr yyin = fp; 1370145510Sdarrenr yyparse(); 1371255332Scy return parser_error; 1372145510Sdarrenr} 1373145510Sdarrenr 1374145510Sdarrenr 1375255332Scystatic void 1376255332Scynewnatrule() 1377145510Sdarrenr{ 1378145510Sdarrenr ipnat_t *n; 1379145510Sdarrenr 1380145510Sdarrenr n = calloc(1, sizeof(*n)); 1381145510Sdarrenr if (n == NULL) 1382145510Sdarrenr return; 1383145510Sdarrenr 1384255332Scy if (nat == NULL) { 1385145510Sdarrenr nattop = nat = n; 1386255332Scy n->in_pnext = &nattop; 1387255332Scy } else { 1388145510Sdarrenr nat->in_next = n; 1389255332Scy n->in_pnext = &nat->in_next; 1390145510Sdarrenr nat = n; 1391145510Sdarrenr } 1392161357Sguido 1393255332Scy n->in_flineno = yylineNum; 1394255332Scy n->in_ifnames[0] = -1; 1395255332Scy n->in_ifnames[1] = -1; 1396255332Scy n->in_plabel = -1; 1397255332Scy n->in_pconfig = -1; 1398255332Scy n->in_size = sizeof(*n); 1399255332Scy 1400161357Sguido suggest_port = 0; 1401145510Sdarrenr} 1402145510Sdarrenr 1403145510Sdarrenr 1404255332Scystatic void 1405255332Scysetnatproto(p) 1406255332Scy int p; 1407145510Sdarrenr{ 1408255332Scy nat->in_pr[0] = p; 1409255332Scy nat->in_pr[1] = p; 1410145510Sdarrenr 1411145510Sdarrenr switch (p) 1412145510Sdarrenr { 1413145510Sdarrenr case IPPROTO_TCP : 1414145510Sdarrenr nat->in_flags |= IPN_TCP; 1415145510Sdarrenr nat->in_flags &= ~IPN_UDP; 1416145510Sdarrenr break; 1417145510Sdarrenr case IPPROTO_UDP : 1418145510Sdarrenr nat->in_flags |= IPN_UDP; 1419145510Sdarrenr nat->in_flags &= ~IPN_TCP; 1420145510Sdarrenr break; 1421271978Scy#ifdef USE_INET6 1422271978Scy case IPPROTO_ICMPV6 : 1423271978Scy#endif 1424145510Sdarrenr case IPPROTO_ICMP : 1425145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1426255332Scy if (!(nat->in_flags & IPN_ICMPQUERY) && 1427255332Scy !(nat->in_redir & NAT_DIVERTUDP)) { 1428145510Sdarrenr nat->in_dcmp = 0; 1429145510Sdarrenr nat->in_scmp = 0; 1430255332Scy nat->in_dpmin = 0; 1431255332Scy nat->in_dpmax = 0; 1432255332Scy nat->in_dpnext = 0; 1433255332Scy nat->in_spmin = 0; 1434255332Scy nat->in_spmax = 0; 1435255332Scy nat->in_spnext = 0; 1436145510Sdarrenr } 1437145510Sdarrenr break; 1438145510Sdarrenr default : 1439145510Sdarrenr if ((nat->in_redir & NAT_MAPBLK) == 0) { 1440145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1441145510Sdarrenr nat->in_dcmp = 0; 1442145510Sdarrenr nat->in_scmp = 0; 1443255332Scy nat->in_dpmin = 0; 1444255332Scy nat->in_dpmax = 0; 1445255332Scy nat->in_dpnext = 0; 1446255332Scy nat->in_spmin = 0; 1447255332Scy nat->in_spmax = 0; 1448255332Scy nat->in_spnext = 0; 1449145510Sdarrenr } 1450145510Sdarrenr break; 1451145510Sdarrenr } 1452145510Sdarrenr 1453255332Scy if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) { 1454255332Scy nat->in_stop = 0; 1455255332Scy nat->in_dtop = 0; 1456255332Scy nat->in_osport = 0; 1457255332Scy nat->in_odport = 0; 1458255332Scy nat->in_stop = 0; 1459255332Scy nat->in_osport = 0; 1460255332Scy nat->in_dtop = 0; 1461255332Scy nat->in_odport = 0; 1462255332Scy } 1463145510Sdarrenr if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) 1464145510Sdarrenr nat->in_flags &= ~IPN_FIXEDDPORT; 1465145510Sdarrenr} 1466145510Sdarrenr 1467145510Sdarrenr 1468255332Scyint 1469255332Scyipnat_addrule(fd, ioctlfunc, ptr) 1470255332Scy int fd; 1471255332Scy ioctlfunc_t ioctlfunc; 1472255332Scy void *ptr; 1473145510Sdarrenr{ 1474145510Sdarrenr ioctlcmd_t add, del; 1475145510Sdarrenr ipfobj_t obj; 1476145510Sdarrenr ipnat_t *ipn; 1477145510Sdarrenr 1478145510Sdarrenr ipn = ptr; 1479145510Sdarrenr bzero((char *)&obj, sizeof(obj)); 1480145510Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1481255332Scy obj.ipfo_size = ipn->in_size; 1482145510Sdarrenr obj.ipfo_type = IPFOBJ_IPNAT; 1483145510Sdarrenr obj.ipfo_ptr = ptr; 1484145510Sdarrenr 1485145510Sdarrenr if ((opts & OPT_DONOTHING) != 0) 1486145510Sdarrenr fd = -1; 1487145510Sdarrenr 1488145510Sdarrenr if (opts & OPT_ZERORULEST) { 1489145510Sdarrenr add = SIOCZRLST; 1490255332Scy del = 0; 1491255332Scy } else if (opts & OPT_PURGE) { 1492255332Scy add = 0; 1493255332Scy del = SIOCPURGENAT; 1494145510Sdarrenr } else { 1495145510Sdarrenr add = SIOCADNAT; 1496145510Sdarrenr del = SIOCRMNAT; 1497145510Sdarrenr } 1498145510Sdarrenr 1499161357Sguido if ((opts & OPT_VERBOSE) != 0) 1500145510Sdarrenr printnat(ipn, opts); 1501145510Sdarrenr 1502145510Sdarrenr if (opts & OPT_DEBUG) 1503271978Scy binprint(ipn, ipn->in_size); 1504145510Sdarrenr 1505145510Sdarrenr if ((opts & OPT_ZERORULEST) != 0) { 1506145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1507145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1508255332Scy char msg[80]; 1509255332Scy 1510255332Scy sprintf(msg, "%d:ioctl(zero nat rule)", 1511255332Scy ipn->in_flineno); 1512255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1513145510Sdarrenr } 1514145510Sdarrenr } else { 1515255332Scy PRINTF("hits %lu ", ipn->in_hits); 1516255332Scy#ifdef USE_QUAD_T 1517255332Scy PRINTF("bytes %"PRIu64" ", 1518255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1519145510Sdarrenr#else 1520255332Scy PRINTF("bytes %lu ", 1521255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1522145510Sdarrenr#endif 1523145510Sdarrenr printnat(ipn, opts); 1524145510Sdarrenr } 1525145510Sdarrenr } else if ((opts & OPT_REMOVE) != 0) { 1526145510Sdarrenr if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 1527145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1528255332Scy char msg[80]; 1529255332Scy 1530255332Scy sprintf(msg, "%d:ioctl(delete nat rule)", 1531255332Scy ipn->in_flineno); 1532255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1533145510Sdarrenr } 1534145510Sdarrenr } 1535145510Sdarrenr } else { 1536145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1537145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1538255332Scy char msg[80]; 1539255332Scy 1540255332Scy sprintf(msg, "%d:ioctl(add/insert nat rule)", 1541255332Scy ipn->in_flineno); 1542255332Scy if (errno == EEXIST) { 1543255332Scy sprintf(msg + strlen(msg), "(line %d)", 1544255332Scy ipn->in_flineno); 1545255332Scy } 1546255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1547145510Sdarrenr } 1548145510Sdarrenr } 1549145510Sdarrenr } 1550255332Scy return 0; 1551145510Sdarrenr} 1552255332Scy 1553255332Scy 1554255332Scystatic void 1555255332Scysetmapifnames() 1556255332Scy{ 1557255332Scy if (nat->in_ifnames[1] == -1) 1558255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1559255332Scy 1560255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1561255332Scy nat->in_flags |= IPN_TCPUDP; 1562255332Scy 1563255332Scy if ((nat->in_flags & IPN_TCPUDP) == 0) 1564255332Scy setnatproto(nat->in_pr[1]); 1565255332Scy 1566255332Scy if (((nat->in_redir & NAT_MAPBLK) != 0) || 1567255332Scy ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 1568255332Scy nat_setgroupmap(nat); 1569255332Scy} 1570255332Scy 1571255332Scy 1572255332Scystatic void 1573255332Scysetrdrifnames() 1574255332Scy{ 1575255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1576255332Scy nat->in_flags |= IPN_TCPUDP; 1577255332Scy 1578255332Scy if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && 1579255332Scy (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0)) 1580255332Scy setnatproto(IPPROTO_TCP); 1581255332Scy 1582255332Scy if (nat->in_ifnames[1] == -1) 1583255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1584255332Scy} 1585255332Scy 1586255332Scy 1587255332Scystatic void 1588255332Scyproxy_setconfig(proxy) 1589255332Scy int proxy; 1590255332Scy{ 1591255332Scy if (proxy == IPNY_DNS) { 1592255332Scy yysetfixeddict(dnswords); 1593255332Scy } 1594255332Scy} 1595255332Scy 1596255332Scy 1597255332Scystatic void 1598255332Scyproxy_unsetconfig() 1599255332Scy{ 1600255332Scy yyresetdict(); 1601255332Scy} 1602255332Scy 1603255332Scy 1604255332Scystatic namelist_t * 1605255332Scyproxy_dns_add_pass(prefix, name) 1606255332Scy char *prefix, *name; 1607255332Scy{ 1608255332Scy namelist_t *n; 1609255332Scy 1610255332Scy n = calloc(1, sizeof(*n)); 1611255332Scy if (n != NULL) { 1612255332Scy if (prefix == NULL || *prefix == '\0') { 1613255332Scy n->na_name = strdup(name); 1614255332Scy } else { 1615255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1616255332Scy strcpy(n->na_name, prefix); 1617255332Scy strcat(n->na_name, name); 1618255332Scy } 1619255332Scy } 1620255332Scy return n; 1621255332Scy} 1622255332Scy 1623255332Scy 1624255332Scystatic namelist_t * 1625255332Scyproxy_dns_add_block(prefix, name) 1626255332Scy char *prefix, *name; 1627255332Scy{ 1628255332Scy namelist_t *n; 1629255332Scy 1630255332Scy n = calloc(1, sizeof(*n)); 1631255332Scy if (n != NULL) { 1632255332Scy if (prefix == NULL || *prefix == '\0') { 1633255332Scy n->na_name = strdup(name); 1634255332Scy } else { 1635255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1636255332Scy strcpy(n->na_name, prefix); 1637255332Scy strcat(n->na_name, name); 1638255332Scy } 1639255332Scy n->na_value = 1; 1640255332Scy } 1641255332Scy return n; 1642255332Scy} 1643255332Scy 1644255332Scy 1645255332Scystatic void 1646255332Scyproxy_addconfig(proxy, proto, conf, list) 1647255332Scy char *proxy, *conf; 1648255332Scy int proto; 1649255332Scy namelist_t *list; 1650255332Scy{ 1651255332Scy proxyrule_t *pr; 1652255332Scy 1653255332Scy pr = calloc(1, sizeof(*pr)); 1654255332Scy if (pr != NULL) { 1655255332Scy pr->pr_proto = proto; 1656255332Scy pr->pr_proxy = proxy; 1657255332Scy pr->pr_conf = conf; 1658255332Scy pr->pr_names = list; 1659255332Scy pr->pr_next = prules; 1660255332Scy prules = pr; 1661255332Scy } 1662255332Scy} 1663255332Scy 1664255332Scy 1665255332Scystatic void 1666255332Scyproxy_loadrules(fd, ioctlfunc, rules) 1667255332Scy int fd; 1668255332Scy ioctlfunc_t ioctlfunc; 1669255332Scy proxyrule_t *rules; 1670255332Scy{ 1671255332Scy proxyrule_t *pr; 1672255332Scy 1673255332Scy while ((pr = rules) != NULL) { 1674255332Scy proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto, 1675255332Scy pr->pr_conf, pr->pr_names); 1676255332Scy rules = pr->pr_next; 1677255332Scy free(pr->pr_conf); 1678255332Scy free(pr); 1679255332Scy } 1680255332Scy} 1681255332Scy 1682255332Scy 1683255332Scystatic void 1684255332Scyproxy_loadconfig(fd, ioctlfunc, proxy, proto, conf, list) 1685255332Scy int fd; 1686255332Scy ioctlfunc_t ioctlfunc; 1687255332Scy char *proxy, *conf; 1688255332Scy int proto; 1689255332Scy namelist_t *list; 1690255332Scy{ 1691255332Scy namelist_t *na; 1692255332Scy ipfobj_t obj; 1693255332Scy ap_ctl_t pcmd; 1694255332Scy 1695255332Scy obj.ipfo_rev = IPFILTER_VERSION; 1696255332Scy obj.ipfo_type = IPFOBJ_PROXYCTL; 1697255332Scy obj.ipfo_size = sizeof(pcmd); 1698255332Scy obj.ipfo_ptr = &pcmd; 1699255332Scy 1700255332Scy while ((na = list) != NULL) { 1701255332Scy if ((opts & OPT_REMOVE) != 0) 1702255332Scy pcmd.apc_cmd = APC_CMD_DEL; 1703255332Scy else 1704255332Scy pcmd.apc_cmd = APC_CMD_ADD; 1705255332Scy pcmd.apc_dsize = strlen(na->na_name) + 1; 1706255332Scy pcmd.apc_data = na->na_name; 1707255332Scy pcmd.apc_arg = na->na_value; 1708255332Scy pcmd.apc_p = proto; 1709255332Scy 1710255332Scy strncpy(pcmd.apc_label, proxy, APR_LABELLEN); 1711255332Scy pcmd.apc_label[APR_LABELLEN - 1] = '\0'; 1712255332Scy 1713255332Scy strncpy(pcmd.apc_config, conf, APR_LABELLEN); 1714255332Scy pcmd.apc_config[APR_LABELLEN - 1] = '\0'; 1715255332Scy 1716255332Scy if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) { 1717255332Scy if ((opts & OPT_DONOTHING) == 0) { 1718255332Scy char msg[80]; 1719255332Scy 1720255332Scy sprintf(msg, "%d:ioctl(add/remove proxy rule)", 1721255332Scy yylineNum); 1722255332Scy ipf_perror_fd(fd, ioctlfunc, msg); 1723255332Scy return; 1724255332Scy } 1725255332Scy } 1726255332Scy 1727255332Scy list = na->na_next; 1728255332Scy free(na->na_name); 1729255332Scy free(na); 1730255332Scy } 1731255332Scy} 1732255332Scy 1733255332Scy 1734255332Scystatic void 1735255332Scysetifname(np, idx, name) 1736255332Scy ipnat_t **np; 1737255332Scy int idx; 1738255332Scy char *name; 1739255332Scy{ 1740255332Scy int pos; 1741255332Scy 1742255332Scy pos = addname(np, name); 1743255332Scy if (pos == -1) 1744255332Scy return; 1745255332Scy (*np)->in_ifnames[idx] = pos; 1746255332Scy} 1747255332Scy 1748255332Scy 1749255332Scystatic int 1750255332Scyaddname(np, name) 1751255332Scy ipnat_t **np; 1752255332Scy char *name; 1753255332Scy{ 1754255332Scy ipnat_t *n; 1755255332Scy int nlen; 1756255332Scy int pos; 1757255332Scy 1758255332Scy nlen = strlen(name) + 1; 1759255332Scy n = realloc(*np, (*np)->in_size + nlen); 1760255332Scy if (*np == nattop) 1761255332Scy nattop = n; 1762255332Scy *np = n; 1763255332Scy if (n == NULL) 1764255332Scy return -1; 1765255332Scy if (n->in_pnext != NULL) 1766255332Scy *n->in_pnext = n; 1767255332Scy n->in_size += nlen; 1768255332Scy pos = n->in_namelen; 1769255332Scy n->in_namelen += nlen; 1770255332Scy strcpy(n->in_names + pos, name); 1771255332Scy n->in_names[n->in_namelen] = '\0'; 1772255332Scy return pos; 1773255332Scy} 1774