1145519Sdarrenr/* $FreeBSD: releng/10.3/contrib/ipfilter/tools/ipnat_y.y 272990 2014-10-12 17:03:47Z cy $ */ 2145510Sdarrenr 3170268Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5170268Sdarrenr * 6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7170268Sdarrenr */ 8145510Sdarrenr%{ 9145510Sdarrenr#ifdef __FreeBSD__ 10145510Sdarrenr# ifndef __FreeBSD_cc_version 11145510Sdarrenr# include <osreldate.h> 12145510Sdarrenr# else 13145510Sdarrenr# if __FreeBSD_cc_version < 430000 14145510Sdarrenr# include <osreldate.h> 15145510Sdarrenr# endif 16145510Sdarrenr# endif 17145510Sdarrenr#endif 18145510Sdarrenr#include <stdio.h> 19145510Sdarrenr#include <unistd.h> 20145510Sdarrenr#include <string.h> 21145510Sdarrenr#include <fcntl.h> 22145510Sdarrenr#include <errno.h> 23145510Sdarrenr#if !defined(__SVR4) && !defined(__GNUC__) 24145510Sdarrenr#include <strings.h> 25145510Sdarrenr#endif 26145510Sdarrenr#include <sys/types.h> 27145510Sdarrenr#include <sys/param.h> 28145510Sdarrenr#include <sys/file.h> 29145510Sdarrenr#include <stdlib.h> 30145510Sdarrenr#include <stddef.h> 31145510Sdarrenr#include <sys/socket.h> 32145510Sdarrenr#include <sys/ioctl.h> 33145510Sdarrenr#include <netinet/in.h> 34145510Sdarrenr#include <netinet/in_systm.h> 35145510Sdarrenr#include <sys/time.h> 36145510Sdarrenr#include <syslog.h> 37145510Sdarrenr#include <net/if.h> 38145510Sdarrenr#if __FreeBSD_version >= 300000 39145510Sdarrenr# include <net/if_var.h> 40145510Sdarrenr#endif 41145510Sdarrenr#include <netdb.h> 42145510Sdarrenr#include <arpa/nameser.h> 43145510Sdarrenr#include <resolv.h> 44145510Sdarrenr#include "ipf.h" 45145510Sdarrenr#include "netinet/ipl.h" 46145510Sdarrenr#include "ipnat_l.h" 47145510Sdarrenr 48145510Sdarrenr#define YYDEBUG 1 49145510Sdarrenr 50145510Sdarrenrextern void yyerror __P((char *)); 51145510Sdarrenrextern int yyparse __P((void)); 52145510Sdarrenrextern int yylex __P((void)); 53145510Sdarrenrextern int yydebug; 54145510Sdarrenrextern FILE *yyin; 55145510Sdarrenrextern int yylineNum; 56145510Sdarrenr 57145510Sdarrenrstatic ipnat_t *nattop = NULL; 58145510Sdarrenrstatic ipnat_t *nat = NULL; 59145510Sdarrenrstatic int natfd = -1; 60145510Sdarrenrstatic ioctlfunc_t natioctlfunc = NULL; 61145510Sdarrenrstatic addfunc_t nataddfunc = NULL; 62161357Sguidostatic int suggest_port = 0; 63255332Scystatic proxyrule_t *prules = NULL; 64255332Scystatic int parser_error = 0; 65145510Sdarrenr 66145510Sdarrenrstatic void newnatrule __P((void)); 67145510Sdarrenrstatic void setnatproto __P((int)); 68255332Scystatic void setmapifnames __P((void)); 69255332Scystatic void setrdrifnames __P((void)); 70255332Scystatic void proxy_setconfig __P((int)); 71255332Scystatic void proxy_unsetconfig __P((void)); 72255332Scystatic namelist_t *proxy_dns_add_pass __P((char *, char *)); 73255332Scystatic namelist_t *proxy_dns_add_block __P((char *, char *)); 74255332Scystatic void proxy_addconfig __P((char *, int, char *, namelist_t *)); 75255332Scystatic void proxy_loadconfig __P((int, ioctlfunc_t, char *, int, 76255332Scy char *, namelist_t *)); 77255332Scystatic void proxy_loadrules __P((int, ioctlfunc_t, proxyrule_t *)); 78255332Scystatic void setmapifnames __P((void)); 79255332Scystatic void setrdrifnames __P((void)); 80255332Scystatic void setifname __P((ipnat_t **, int, char *)); 81255332Scystatic int addname __P((ipnat_t **, char *)); 82145510Sdarrenr%} 83145510Sdarrenr%union { 84145510Sdarrenr char *str; 85145510Sdarrenr u_32_t num; 86255332Scy struct { 87255332Scy i6addr_t a; 88255332Scy int f; 89255332Scy } ipa; 90145510Sdarrenr frentry_t fr; 91145510Sdarrenr frtuc_t *frt; 92145510Sdarrenr u_short port; 93145510Sdarrenr struct { 94255332Scy int p1; 95255332Scy int p2; 96145510Sdarrenr int pc; 97145510Sdarrenr } pc; 98145510Sdarrenr struct { 99255332Scy i6addr_t a; 100255332Scy i6addr_t m; 101255332Scy int t; /* Address type */ 102255332Scy int u; 103255332Scy int f; /* Family */ 104255332Scy int v; /* IP version */ 105255332Scy int s; /* 0 = number, 1 = text */ 106255332Scy int n; /* number */ 107145510Sdarrenr } ipp; 108145510Sdarrenr union i6addr ip6; 109255332Scy namelist_t *names; 110145510Sdarrenr}; 111145510Sdarrenr 112145510Sdarrenr%token <num> YY_NUMBER YY_HEX 113145510Sdarrenr%token <str> YY_STR 114255332Scy%token YY_COMMENT 115145510Sdarrenr%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 116145510Sdarrenr%token YY_RANGE_OUT YY_RANGE_IN 117145510Sdarrenr%token <ip6> YY_IPV6 118145510Sdarrenr 119145510Sdarrenr%token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE 120145510Sdarrenr%token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY 121145510Sdarrenr%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY 122145510Sdarrenr%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG 123255332Scy%token IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO 124255332Scy%token IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT 125255332Scy%token IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6 126255332Scy%token IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE 127145510Sdarrenr%type <port> portspec 128145510Sdarrenr%type <num> hexnumber compare range proto 129255332Scy%type <num> saddr daddr sobject dobject mapfrom rdrfrom dip 130255332Scy%type <ipa> hostname ipv4 ipaddr 131255332Scy%type <ipp> addr rhsaddr rhdaddr erhdaddr 132255332Scy%type <pc> portstuff portpair comaports srcports dstports 133255332Scy%type <names> dnslines dnsline 134145510Sdarrenr%% 135145510Sdarrenrfile: line 136145510Sdarrenr | assign 137145510Sdarrenr | file line 138145510Sdarrenr | file assign 139255332Scy | file pconf ';' 140145510Sdarrenr ; 141145510Sdarrenr 142255332Scyline: xx rule { int err; 143255332Scy while ((nat = nattop) != NULL) { 144255332Scy if (nat->in_v[0] == 0) 145255332Scy nat->in_v[0] = 4; 146255332Scy if (nat->in_v[1] == 0) 147255332Scy nat->in_v[1] = nat->in_v[0]; 148145510Sdarrenr nattop = nat->in_next; 149255332Scy err = (*nataddfunc)(natfd, natioctlfunc, nat); 150145510Sdarrenr free(nat); 151255332Scy if (err != 0) { 152255332Scy parser_error = err; 153255332Scy break; 154255332Scy } 155145510Sdarrenr } 156255332Scy if (parser_error == 0 && prules != NULL) { 157255332Scy proxy_loadrules(natfd, natioctlfunc, prules); 158255332Scy prules = NULL; 159255332Scy } 160145510Sdarrenr resetlexer(); 161145510Sdarrenr } 162145510Sdarrenr | YY_COMMENT 163145510Sdarrenr ; 164145510Sdarrenr 165145510Sdarrenrassign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 166145510Sdarrenr resetlexer(); 167145510Sdarrenr free($1); 168145510Sdarrenr free($3); 169170268Sdarrenr yyvarnext = 0; 170145510Sdarrenr } 171145510Sdarrenr ; 172145510Sdarrenr 173145510Sdarrenrassigning: 174145510Sdarrenr '=' { yyvarnext = 1; } 175145510Sdarrenr ; 176145510Sdarrenr 177145510Sdarrenrxx: { newnatrule(); } 178145510Sdarrenr ; 179145510Sdarrenr 180145510Sdarrenrrule: map eol 181145510Sdarrenr | mapblock eol 182145510Sdarrenr | redir eol 183255332Scy | rewrite ';' 184255332Scy | divert ';' 185145510Sdarrenr ; 186145510Sdarrenr 187255332Scyno: IPNY_NO { nat->in_flags |= IPN_NO; } 188255332Scy ; 189255332Scy 190145510Sdarrenreol: | ';' 191145510Sdarrenr ; 192145510Sdarrenr 193255332Scymap: mapit ifnames addr tlate rhsaddr proxy mapoptions 194255332Scy { if ($3.f != 0 && $3.f != $5.f && $5.f != 0) 195255332Scy yyerror("3.address family mismatch"); 196255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 197255332Scy nat->in_v[0] = $5.v; 198255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 199255332Scy nat->in_v[0] = $3.v; 200255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 201255332Scy nat->in_v[1] = $5.v; 202255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 203255332Scy nat->in_v[1] = $3.v; 204255332Scy nat->in_osrcatype = $3.t; 205255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 206255332Scy sizeof($3.a)); 207255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 208255332Scy sizeof($3.a)); 209255332Scy nat->in_nsrcatype = $5.t; 210255332Scy nat->in_nsrcafunc = $5.u; 211255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 212255332Scy sizeof($5.a)); 213255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 214255332Scy sizeof($5.a)); 215255332Scy 216255332Scy setmapifnames(); 217145510Sdarrenr } 218255332Scy | mapit ifnames addr tlate rhsaddr mapport mapoptions 219255332Scy { if ($3.f != $5.f && $3.f != 0 && $5.f != 0) 220255332Scy yyerror("4.address family mismatch"); 221255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 222255332Scy nat->in_v[1] = $5.v; 223255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 224255332Scy nat->in_v[0] = $3.v; 225255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 226255332Scy nat->in_v[0] = $5.v; 227255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 228255332Scy nat->in_v[1] = $3.v; 229255332Scy nat->in_osrcatype = $3.t; 230255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 231255332Scy sizeof($3.a)); 232255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 233255332Scy sizeof($3.a)); 234255332Scy nat->in_nsrcatype = $5.t; 235255332Scy nat->in_nsrcafunc = $5.u; 236255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 237255332Scy sizeof($5.a)); 238255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 239255332Scy sizeof($5.a)); 240255332Scy 241255332Scy setmapifnames(); 242145510Sdarrenr } 243255332Scy | no mapit ifnames addr setproto ';' 244255332Scy { if (nat->in_v[0] == 0) 245255332Scy nat->in_v[0] = $4.v; 246255332Scy nat->in_osrcatype = $4.t; 247255332Scy bcopy(&$4.a, &nat->in_osrc.na_addr[0], 248255332Scy sizeof($4.a)); 249255332Scy bcopy(&$4.m, &nat->in_osrc.na_addr[1], 250255332Scy sizeof($4.a)); 251255332Scy 252255332Scy setmapifnames(); 253145510Sdarrenr } 254255332Scy | mapit ifnames mapfrom tlate rhsaddr proxy mapoptions 255255332Scy { if ($3 != 0 && $5.f != 0 && $3 != $5.f) 256255332Scy yyerror("5.address family mismatch"); 257255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 258255332Scy nat->in_v[0] = $5.v; 259255332Scy else if (nat->in_v[0] == 0 && $3 != 0) 260255332Scy nat->in_v[0] = ftov($3); 261255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 262255332Scy nat->in_v[1] = $5.v; 263255332Scy else if (nat->in_v[1] == 0 && $3 != 0) 264255332Scy nat->in_v[1] = ftov($3); 265255332Scy nat->in_nsrcatype = $5.t; 266255332Scy nat->in_nsrcafunc = $5.u; 267255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 268255332Scy sizeof($5.a)); 269255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 270255332Scy sizeof($5.a)); 271255332Scy 272255332Scy setmapifnames(); 273145510Sdarrenr } 274255332Scy | no mapit ifnames mapfrom setproto ';' 275255332Scy { nat->in_v[0] = ftov($4); 276255332Scy setmapifnames(); 277255332Scy } 278255332Scy | mapit ifnames mapfrom tlate rhsaddr mapport mapoptions 279255332Scy { if ($3 != 0 && $5.f != 0 && $3 != $5.f) 280255332Scy yyerror("6.address family mismatch"); 281255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 282255332Scy nat->in_v[0] = $5.v; 283255332Scy else if (nat->in_v[0] == 0 && $3 != 0) 284255332Scy nat->in_v[0] = ftov($3); 285255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 286255332Scy nat->in_v[1] = $5.v; 287255332Scy else if (nat->in_v[1] == 0 && $3 != 0) 288255332Scy nat->in_v[1] = ftov($3); 289255332Scy nat->in_nsrcatype = $5.t; 290255332Scy nat->in_nsrcafunc = $5.u; 291255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 292255332Scy sizeof($5.a)); 293255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 294255332Scy sizeof($5.a)); 295255332Scy 296255332Scy setmapifnames(); 297255332Scy } 298145510Sdarrenr ; 299145510Sdarrenr 300145510Sdarrenrmapblock: 301255332Scy mapblockit ifnames addr tlate addr ports mapoptions 302255332Scy { if ($3.f != 0 && $5.f != 0 && $3.f != $5.f) 303255332Scy yyerror("7.address family mismatch"); 304255332Scy if (nat->in_v[0] == 0 && $5.v != 0) 305255332Scy nat->in_v[0] = $5.v; 306255332Scy else if (nat->in_v[0] == 0 && $3.v != 0) 307255332Scy nat->in_v[0] = $3.v; 308255332Scy if (nat->in_v[1] == 0 && $5.v != 0) 309255332Scy nat->in_v[1] = $5.v; 310255332Scy else if (nat->in_v[1] == 0 && $3.v != 0) 311255332Scy nat->in_v[1] = $3.v; 312255332Scy nat->in_osrcatype = $3.t; 313255332Scy bcopy(&$3.a, &nat->in_osrc.na_addr[0], 314255332Scy sizeof($3.a)); 315255332Scy bcopy(&$3.m, &nat->in_osrc.na_addr[1], 316255332Scy sizeof($3.a)); 317255332Scy nat->in_nsrcatype = $5.t; 318255332Scy nat->in_nsrcafunc = $5.u; 319255332Scy bcopy(&$5.a, &nat->in_nsrc.na_addr[0], 320255332Scy sizeof($5.a)); 321255332Scy bcopy(&$5.m, &nat->in_nsrc.na_addr[1], 322255332Scy sizeof($5.a)); 323255332Scy 324255332Scy setmapifnames(); 325145510Sdarrenr } 326255332Scy | no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';' 327255332Scy { if (nat->in_v[0] == 0) 328255332Scy nat->in_v[0] = $5.v; 329255332Scy if (nat->in_v[1] == 0) 330255332Scy nat->in_v[1] = $5.v; 331255332Scy nat->in_osrcatype = $5.t; 332255332Scy bcopy(&$5.a, &nat->in_osrc.na_addr[0], 333255332Scy sizeof($5.a)); 334255332Scy bcopy(&$5.m, &nat->in_osrc.na_addr[1], 335255332Scy sizeof($5.a)); 336255332Scy 337255332Scy setmapifnames(); 338255332Scy } 339145510Sdarrenr ; 340145510Sdarrenr 341255332Scyredir: rdrit ifnames addr dport tlate dip nport setproto rdroptions 342255332Scy { if ($6 != 0 && $3.f != 0 && $6 != $3.f) 343255332Scy yyerror("21.address family mismatch"); 344255332Scy if (nat->in_v[0] == 0) { 345255332Scy if ($3.v != AF_UNSPEC) 346255332Scy nat->in_v[0] = ftov($3.f); 347255332Scy else 348255332Scy nat->in_v[0] = ftov($6); 349255332Scy } 350255332Scy nat->in_odstatype = $3.t; 351255332Scy bcopy(&$3.a, &nat->in_odst.na_addr[0], 352255332Scy sizeof($3.a)); 353255332Scy bcopy(&$3.m, &nat->in_odst.na_addr[1], 354255332Scy sizeof($3.a)); 355255332Scy 356255332Scy setrdrifnames(); 357145510Sdarrenr } 358255332Scy | no rdrit ifnames addr dport setproto ';' 359255332Scy { if (nat->in_v[0] == 0) 360255332Scy nat->in_v[0] = ftov($4.f); 361255332Scy nat->in_odstatype = $4.t; 362255332Scy bcopy(&$4.a, &nat->in_odst.na_addr[0], 363255332Scy sizeof($4.a)); 364255332Scy bcopy(&$4.m, &nat->in_odst.na_addr[1], 365255332Scy sizeof($4.a)); 366255332Scy 367255332Scy setrdrifnames(); 368145510Sdarrenr } 369255332Scy | rdrit ifnames rdrfrom tlate dip nport setproto rdroptions 370255332Scy { if ($5 != 0 && $3 != 0 && $5 != $3) 371255332Scy yyerror("20.address family mismatch"); 372255332Scy if (nat->in_v[0] == 0) { 373255332Scy if ($3 != AF_UNSPEC) 374255332Scy nat->in_v[0] = ftov($3); 375255332Scy else 376255332Scy nat->in_v[0] = ftov($5); 377255332Scy } 378255332Scy setrdrifnames(); 379145510Sdarrenr } 380255332Scy | no rdrit ifnames rdrfrom setproto ';' 381255332Scy { nat->in_v[0] = ftov($4); 382255332Scy 383255332Scy setrdrifnames(); 384161357Sguido } 385145510Sdarrenr ; 386145510Sdarrenr 387255332Scyrewrite: 388255332Scy IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts 389255332Scy { if (nat->in_v[0] == 0) 390255332Scy nat->in_v[0] = ftov($4); 391255332Scy if (nat->in_redir & NAT_MAP) 392255332Scy setmapifnames(); 393255332Scy else 394255332Scy setrdrifnames(); 395255332Scy nat->in_redir |= NAT_REWRITE; 396255332Scy } 397255332Scy ; 398255332Scy 399255332Scydivert: IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts 400255332Scy { if (nat->in_v[0] == 0) 401255332Scy nat->in_v[0] = ftov($4); 402255332Scy if (nat->in_redir & NAT_MAP) { 403255332Scy setmapifnames(); 404255332Scy nat->in_pr[0] = IPPROTO_UDP; 405255332Scy } else { 406255332Scy setrdrifnames(); 407255332Scy nat->in_pr[1] = IPPROTO_UDP; 408255332Scy } 409255332Scy nat->in_flags &= ~IPN_TCP; 410255332Scy } 411255332Scy ; 412255332Scy 413255332Scytlate: IPNY_TLATE { yyexpectaddr = 1; } 414255332Scy ; 415255332Scy 416255332Scypconf: IPNY_PROXY { yysetdict(proxies); } 417255332Scy IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{' 418255332Scy { proxy_setconfig(IPNY_DNS); } 419255332Scy dnslines ';' '}' 420255332Scy { proxy_addconfig("dns", $5, $7, $10); 421255332Scy proxy_unsetconfig(); 422255332Scy } 423255332Scy ; 424255332Scy 425255332Scydnslines: 426255332Scy dnsline { $$ = $1; } 427255332Scy | dnslines ';' dnsline { $$ = $1; $1->na_next = $3; } 428255332Scy ; 429255332Scy 430255332Scydnsline: 431255332Scy IPNY_ALLOW YY_STR { $$ = proxy_dns_add_pass(NULL, $2); } 432255332Scy | IPNY_DENY YY_STR { $$ = proxy_dns_add_block(NULL, $2); } 433255332Scy | IPNY_ALLOW '.' YY_STR { $$ = proxy_dns_add_pass(".", $3); } 434255332Scy | IPNY_DENY '.' YY_STR { $$ = proxy_dns_add_block(".", $3); } 435255332Scy ; 436255332Scy 437255332Scyoninout: 438255332Scy inout IPNY_ON ifnames { ; } 439255332Scy ; 440255332Scy 441255332Scyinout: IPNY_IN { nat->in_redir = NAT_REDIRECT; } 442255332Scy | IPNY_OUT { nat->in_redir = NAT_MAP; } 443255332Scy ; 444255332Scy 445255332Scyrwrproto: 446255332Scy | IPNY_PROTO setproto 447255332Scy ; 448255332Scy 449255332Scynewdst: src rhsaddr srcports dst erhdaddr dstports 450255332Scy { nat->in_nsrc.na_addr[0] = $2.a; 451255332Scy nat->in_nsrc.na_addr[1] = $2.m; 452255332Scy nat->in_nsrc.na_atype = $2.t; 453255332Scy if ($2.t == FRI_LOOKUP) { 454255332Scy nat->in_nsrc.na_type = $2.u; 455255332Scy nat->in_nsrc.na_subtype = $2.s; 456255332Scy nat->in_nsrc.na_num = $2.n; 457255332Scy } 458255332Scy nat->in_nsports[0] = $3.p1; 459255332Scy nat->in_nsports[1] = $3.p2; 460255332Scy nat->in_ndst.na_addr[0] = $5.a; 461255332Scy nat->in_ndst.na_addr[1] = $5.m; 462255332Scy nat->in_ndst.na_atype = $5.t; 463255332Scy if ($5.t == FRI_LOOKUP) { 464255332Scy nat->in_ndst.na_type = $5.u; 465255332Scy nat->in_ndst.na_subtype = $5.s; 466255332Scy nat->in_ndst.na_num = $5.n; 467255332Scy } 468255332Scy nat->in_ndports[0] = $6.p1; 469255332Scy nat->in_ndports[1] = $6.p2; 470255332Scy } 471255332Scy ; 472255332Scy 473255332Scydivdst: src addr ',' portspec dst addr ',' portspec IPNY_UDP 474255332Scy { nat->in_nsrc.na_addr[0] = $2.a; 475255332Scy if ($2.m.in4.s_addr != 0xffffffff) 476255332Scy yyerror("divert must have /32 dest"); 477255332Scy nat->in_nsrc.na_addr[1] = $2.m; 478255332Scy nat->in_nsports[0] = $4; 479255332Scy nat->in_nsports[1] = $4; 480255332Scy 481255332Scy nat->in_ndst.na_addr[0] = $6.a; 482255332Scy nat->in_ndst.na_addr[1] = $6.m; 483255332Scy if ($6.m.in4.s_addr != 0xffffffff) 484255332Scy yyerror("divert must have /32 dest"); 485255332Scy nat->in_ndports[0] = $8; 486255332Scy nat->in_ndports[1] = $8; 487255332Scy 488255332Scy nat->in_redir |= NAT_DIVERTUDP; 489255332Scy } 490255332Scy ; 491255332Scy 492255332Scysrc: IPNY_SRC { yyexpectaddr = 1; } 493255332Scy ; 494255332Scy 495255332Scydst: IPNY_DST { yyexpectaddr = 1; } 496255332Scy ; 497255332Scy 498255332Scysrcports: 499255332Scy comaports { $$.p1 = $1.p1; 500255332Scy $$.p2 = $1.p2; 501255332Scy } 502255332Scy | IPNY_PORT '=' portspec 503255332Scy { $$.p1 = $3; 504255332Scy $$.p2 = $3; 505255332Scy nat->in_flags |= IPN_FIXEDSPORT; 506255332Scy } 507255332Scy ; 508255332Scy 509255332Scydstports: 510255332Scy comaports { $$.p1 = $1.p1; 511255332Scy $$.p2 = $1.p2; 512255332Scy } 513255332Scy | IPNY_PORT '=' portspec 514255332Scy { $$.p1 = $3; 515255332Scy $$.p2 = $3; 516255332Scy nat->in_flags |= IPN_FIXEDDPORT; 517255332Scy } 518255332Scy ; 519255332Scy 520255332Scycomaports: 521255332Scy { $$.p1 = 0; 522255332Scy $$.p2 = 0; 523255332Scy } 524255332Scy | ',' { if (!(nat->in_flags & IPN_TCPUDP)) 525255332Scy yyerror("must be TCP/UDP for ports"); 526255332Scy } 527255332Scy portpair { $$.p1 = $3.p1; 528255332Scy $$.p2 = $3.p2; 529255332Scy } 530255332Scy ; 531255332Scy 532161357Sguidoproxy: | IPNY_PROXY port portspec YY_STR '/' proto 533255332Scy { int pos; 534255332Scy pos = addname(&nat, $4); 535255332Scy nat->in_plabel = pos; 536145510Sdarrenr if (nat->in_dcmp == 0) { 537255332Scy nat->in_odport = $3; 538255332Scy } else if ($3 != nat->in_odport) { 539145510Sdarrenr yyerror("proxy port numbers not consistant"); 540145510Sdarrenr } 541255332Scy nat->in_ndport = $3; 542145510Sdarrenr setnatproto($6); 543145510Sdarrenr free($4); 544145510Sdarrenr } 545161357Sguido | IPNY_PROXY port YY_STR YY_STR '/' proto 546255332Scy { int pnum, pos; 547255332Scy pos = addname(&nat, $4); 548255332Scy nat->in_plabel = pos; 549145510Sdarrenr pnum = getportproto($3, $6); 550145510Sdarrenr if (pnum == -1) 551145510Sdarrenr yyerror("invalid port number"); 552255332Scy nat->in_odport = ntohs(pnum); 553255332Scy nat->in_ndport = ntohs(pnum); 554145510Sdarrenr setnatproto($6); 555145510Sdarrenr free($3); 556145510Sdarrenr free($4); 557145510Sdarrenr } 558255332Scy | IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR 559255332Scy { int pos; 560255332Scy pos = addname(&nat, $4); 561255332Scy nat->in_plabel = pos; 562255332Scy if (nat->in_dcmp == 0) { 563255332Scy nat->in_odport = $3; 564255332Scy } else if ($3 != nat->in_odport) { 565255332Scy yyerror("proxy port numbers not consistant"); 566255332Scy } 567255332Scy nat->in_ndport = $3; 568255332Scy setnatproto($6); 569255332Scy nat->in_pconfig = addname(&nat, $8); 570255332Scy free($4); 571255332Scy free($8); 572255332Scy } 573255332Scy | IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR 574255332Scy { int pnum, pos; 575255332Scy pos = addname(&nat, $4); 576255332Scy nat->in_plabel = pos; 577255332Scy pnum = getportproto($3, $6); 578255332Scy if (pnum == -1) 579255332Scy yyerror("invalid port number"); 580255332Scy nat->in_odport = ntohs(pnum); 581255332Scy nat->in_ndport = ntohs(pnum); 582255332Scy setnatproto($6); 583255332Scy pos = addname(&nat, $8); 584255332Scy nat->in_pconfig = pos; 585255332Scy free($3); 586255332Scy free($4); 587255332Scy free($8); 588255332Scy } 589145510Sdarrenr ; 590145510Sdarrenrsetproto: 591255332Scy | proto { if (nat->in_pr[0] != 0 || 592255332Scy nat->in_pr[1] != 0 || 593145510Sdarrenr nat->in_flags & IPN_TCPUDP) 594145510Sdarrenr yyerror("protocol set twice"); 595145510Sdarrenr setnatproto($1); 596145510Sdarrenr } 597255332Scy | IPNY_TCPUDP { if (nat->in_pr[0] != 0 || 598255332Scy nat->in_pr[1] != 0 || 599145510Sdarrenr nat->in_flags & IPN_TCPUDP) 600145510Sdarrenr yyerror("protocol set twice"); 601145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 602255332Scy nat->in_pr[0] = 0; 603255332Scy nat->in_pr[1] = 0; 604145510Sdarrenr } 605255332Scy | IPNY_TCP '/' IPNY_UDP { if (nat->in_pr[0] != 0 || 606255332Scy nat->in_pr[1] != 0 || 607145510Sdarrenr nat->in_flags & IPN_TCPUDP) 608145510Sdarrenr yyerror("protocol set twice"); 609145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 610255332Scy nat->in_pr[0] = 0; 611255332Scy nat->in_pr[1] = 0; 612145510Sdarrenr } 613145510Sdarrenr ; 614145510Sdarrenr 615255332Scyrhsaddr: 616255332Scy addr { $$ = $1; 617255332Scy yyexpectaddr = 0; 618255332Scy } 619255332Scy | hostname '-' { yyexpectaddr = 1; } hostname 620255332Scy { $$.t = FRI_RANGE; 621255332Scy if ($1.f != $4.f) 622255332Scy yyerror("8.address family " 623255332Scy "mismatch"); 624255332Scy $$.f = $1.f; 625255332Scy $$.v = ftov($1.f); 626255332Scy $$.a = $1.a; 627255332Scy $$.m = $4.a; 628255332Scy nat->in_flags |= IPN_SIPRANGE; 629255332Scy yyexpectaddr = 0; 630255332Scy } 631255332Scy | IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname 632255332Scy { $$.t = FRI_RANGE; 633255332Scy if ($2.f != $5.f) 634255332Scy yyerror("9.address family " 635255332Scy "mismatch"); 636255332Scy $$.f = $2.f; 637255332Scy $$.v = ftov($2.f); 638255332Scy $$.a = $2.a; 639255332Scy $$.m = $5.a; 640255332Scy nat->in_flags |= IPN_SIPRANGE; 641255332Scy yyexpectaddr = 0; 642255332Scy } 643145510Sdarrenr ; 644145510Sdarrenr 645145510Sdarrenrdip: 646255332Scy hostname ',' { yyexpectaddr = 1; } hostname 647255332Scy { nat->in_flags |= IPN_SPLIT; 648255332Scy if ($1.f != $4.f) 649255332Scy yyerror("10.address family " 650255332Scy "mismatch"); 651255332Scy $$ = $1.f; 652255332Scy nat->in_ndstip6 = $1.a; 653255332Scy nat->in_ndstmsk6 = $4.a; 654255332Scy nat->in_ndstatype = FRI_SPLIT; 655255332Scy yyexpectaddr = 0; 656255332Scy } 657255332Scy | rhdaddr { int bits; 658255332Scy nat->in_ndstip6 = $1.a; 659255332Scy nat->in_ndstmsk6 = $1.m; 660255332Scy nat->in_ndst.na_atype = $1.t; 661255332Scy yyexpectaddr = 0; 662255332Scy if ($1.f == AF_INET) 663255332Scy bits = count4bits($1.m.in4.s_addr); 664255332Scy else 665255332Scy bits = count6bits($1.m.i6); 666255332Scy if (($1.f == AF_INET) && (bits != 0) && 667255332Scy (bits != 32)) { 668255332Scy yyerror("dest ip bitmask not /32"); 669255332Scy } else if (($1.f == AF_INET6) && 670255332Scy (bits != 0) && (bits != 128)) { 671255332Scy yyerror("dest ip bitmask not /128"); 672255332Scy } 673255332Scy $$ = $1.f; 674255332Scy } 675255332Scy ; 676255332Scy 677255332Scyrhdaddr: 678255332Scy addr { $$ = $1; 679255332Scy yyexpectaddr = 0; 680153881Sguido } 681255332Scy | hostname '-' hostname { bzero(&$$, sizeof($$)); 682255332Scy $$.t = FRI_RANGE; 683255332Scy if ($1.f != 0 && $3.f != 0 && 684255332Scy $1.f != $3.f) 685255332Scy yyerror("11.address family " 686255332Scy "mismatch"); 687255332Scy $$.a = $1.a; 688255332Scy $$.m = $3.a; 689255332Scy nat->in_flags |= IPN_DIPRANGE; 690255332Scy yyexpectaddr = 0; 691255332Scy } 692255332Scy | IPNY_RANGE hostname '-' hostname 693255332Scy { bzero(&$$, sizeof($$)); 694255332Scy $$.t = FRI_RANGE; 695255332Scy if ($2.f != 0 && $4.f != 0 && 696255332Scy $2.f != $4.f) 697255332Scy yyerror("12.address family " 698255332Scy "mismatch"); 699255332Scy $$.a = $2.a; 700255332Scy $$.m = $4.a; 701255332Scy nat->in_flags |= IPN_DIPRANGE; 702255332Scy yyexpectaddr = 0; 703255332Scy } 704145510Sdarrenr ; 705145510Sdarrenr 706255332Scyerhdaddr: 707255332Scy rhdaddr { $$ = $1; } 708255332Scy | IPNY_DSTLIST '/' YY_NUMBER { $$.t = FRI_LOOKUP; 709255332Scy $$.u = IPLT_DSTLIST; 710255332Scy $$.s = 0; 711255332Scy $$.n = $3; 712255332Scy } 713255332Scy | IPNY_DSTLIST '/' YY_STR { $$.t = FRI_LOOKUP; 714255332Scy $$.u = IPLT_DSTLIST; 715255332Scy $$.s = 1; 716255332Scy $$.n = addname(&nat, $3); 717255332Scy } 718255332Scy ; 719255332Scy 720161357Sguidoport: IPNY_PORT { suggest_port = 1; } 721161357Sguido ; 722161357Sguido 723145510Sdarrenrportspec: 724145510Sdarrenr YY_NUMBER { if ($1 > 65535) /* Unsigned */ 725145510Sdarrenr yyerror("invalid port number"); 726145510Sdarrenr else 727145510Sdarrenr $$ = $1; 728145510Sdarrenr } 729255332Scy | YY_STR { if (getport(NULL, $1, 730255332Scy &($$), NULL) == -1) 731145510Sdarrenr yyerror("invalid port number"); 732145510Sdarrenr $$ = ntohs($$); 733145510Sdarrenr } 734145510Sdarrenr ; 735145510Sdarrenr 736255332Scyportpair: 737255332Scy portspec { $$.p1 = $1; $$.p2 = $1; } 738255332Scy | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; } 739255332Scy | portspec ':' portspec { $$.p1 = $1; $$.p2 = $3; } 740145510Sdarrenr ; 741145510Sdarrenr 742255332Scydport: | port portpair { nat->in_odport = $2.p1; 743255332Scy if ($2.p2 == 0) 744255332Scy nat->in_dtop = $2.p1; 745255332Scy else 746255332Scy nat->in_dtop = $2.p2; 747255332Scy } 748255332Scy ; 749255332Scy 750255332Scynport: | port portpair { nat->in_dpmin = $2.p1; 751255332Scy nat->in_dpnext = $2.p1; 752255332Scy nat->in_dpmax = $2.p2; 753255332Scy nat->in_ndport = $2.p1; 754255332Scy if (nat->in_dtop == 0) 755255332Scy nat->in_dtop = $2.p2; 756255332Scy } 757255332Scy | port '=' portspec { nat->in_dpmin = $3; 758255332Scy nat->in_dpnext = $3; 759255332Scy nat->in_ndport = $3; 760255332Scy if (nat->in_dtop == 0) 761255332Scy nat->in_dtop = nat->in_odport; 762145510Sdarrenr nat->in_flags |= IPN_FIXEDDPORT; 763145510Sdarrenr } 764145510Sdarrenr ; 765145510Sdarrenr 766255332Scyports: | IPNY_PORTS YY_NUMBER { nat->in_spmin = $2; } 767145510Sdarrenr | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } 768145510Sdarrenr ; 769145510Sdarrenr 770145510Sdarrenrmapit: IPNY_MAP { nat->in_redir = NAT_MAP; } 771145510Sdarrenr | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; } 772145510Sdarrenr ; 773145510Sdarrenr 774145510Sdarrenrrdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; } 775145510Sdarrenr ; 776145510Sdarrenr 777145510Sdarrenrmapblockit: 778145510Sdarrenr IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; } 779145510Sdarrenr ; 780145510Sdarrenr 781145510Sdarrenrmapfrom: 782255332Scy from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) 783255332Scy yyerror("13.address family " 784255332Scy "mismatch"); 785255332Scy $$ = $2; 786255332Scy } 787255332Scy | from sobject '!' to dobject 788255332Scy { if ($2 != 0 && $5 != 0 && $2 != $5) 789255332Scy yyerror("14.address family " 790255332Scy "mismatch"); 791255332Scy nat->in_flags |= IPN_NOTDST; 792255332Scy $$ = $2; 793255332Scy } 794255332Scy | from sobject to '!' dobject 795255332Scy { if ($2 != 0 && $5 != 0 && $2 != $5) 796255332Scy yyerror("15.address family " 797255332Scy "mismatch"); 798255332Scy nat->in_flags |= IPN_NOTDST; 799255332Scy $$ = $2; 800255332Scy } 801145510Sdarrenr ; 802145510Sdarrenr 803145510Sdarrenrrdrfrom: 804255332Scy from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4) 805255332Scy yyerror("16.address family " 806255332Scy "mismatch"); 807255332Scy $$ = $2; 808255332Scy } 809255332Scy | '!' from sobject to dobject 810255332Scy { if ($3 != 0 && $5 != 0 && $3 != $5) 811255332Scy yyerror("17.address family " 812255332Scy "mismatch"); 813255332Scy nat->in_flags |= IPN_NOTSRC; 814255332Scy $$ = $3; 815255332Scy } 816255332Scy | from '!' sobject to dobject 817255332Scy { if ($3 != 0 && $5 != 0 && $3 != $5) 818255332Scy yyerror("18.address family " 819255332Scy "mismatch"); 820255332Scy nat->in_flags |= IPN_NOTSRC; 821255332Scy $$ = $3; 822255332Scy } 823145510Sdarrenr ; 824145510Sdarrenr 825255332Scyfrom: IPNY_FROM { nat->in_flags |= IPN_FILTER; 826255332Scy yyexpectaddr = 1; 827255332Scy } 828145510Sdarrenr ; 829145510Sdarrenr 830255332Scyto: IPNY_TO { yyexpectaddr = 1; } 831255332Scy ; 832255332Scy 833145510Sdarrenrifnames: 834255332Scy ifname family { yyexpectaddr = 1; } 835255332Scy | ifname ',' otherifname family { yyexpectaddr = 1; } 836145510Sdarrenr ; 837145510Sdarrenr 838255332Scyifname: YY_STR { setifname(&nat, 0, $1); 839255332Scy free($1); 840255332Scy } 841145510Sdarrenr ; 842145510Sdarrenr 843255332Scyfamily: | IPNY_INET { nat->in_v[0] = 4; nat->in_v[1] = 4; } 844255332Scy | IPNY_INET6 { nat->in_v[0] = 6; nat->in_v[1] = 6; } 845255332Scy ; 846255332Scy 847145510Sdarrenrotherifname: 848255332Scy YY_STR { setifname(&nat, 1, $1); 849255332Scy free($1); 850255332Scy } 851145510Sdarrenr ; 852145510Sdarrenr 853145510Sdarrenrmapport: 854255332Scy IPNY_PORTMAP tcpudp portpair sequential 855255332Scy { nat->in_spmin = $3.p1; 856255332Scy nat->in_spmax = $3.p2; 857255332Scy } 858255332Scy | IPNY_PORTMAP portpair tcpudp sequential 859255332Scy { nat->in_spmin = $2.p1; 860255332Scy nat->in_spmax = $2.p2; 861255332Scy } 862255332Scy | IPNY_PORTMAP tcpudp IPNY_AUTO sequential 863255332Scy { nat->in_flags |= IPN_AUTOPORTMAP; 864255332Scy nat->in_spmin = 1024; 865255332Scy nat->in_spmax = 65535; 866255332Scy } 867255332Scy | IPNY_ICMPIDMAP YY_STR portpair sequential 868255332Scy { if (strcmp($2, "icmp") != 0 && 869255332Scy strcmp($2, "ipv6-icmp") != 0) { 870145510Sdarrenr yyerror("icmpidmap not followed by icmp"); 871145510Sdarrenr } 872145510Sdarrenr free($2); 873255332Scy if ($3.p1 < 0 || $3.p1 > 65535) 874272990Scy yyerror("invalid 1st ICMP Id number"); 875255332Scy if ($3.p2 < 0 || $3.p2 > 65535) 876272990Scy yyerror("invalid 2nd ICMP Id number"); 877255332Scy if (strcmp($2, "ipv6-icmp") == 0) { 878255332Scy nat->in_pr[0] = IPPROTO_ICMPV6; 879255332Scy nat->in_pr[1] = IPPROTO_ICMPV6; 880255332Scy } else { 881255332Scy nat->in_pr[0] = IPPROTO_ICMP; 882255332Scy nat->in_pr[1] = IPPROTO_ICMP; 883255332Scy } 884145510Sdarrenr nat->in_flags = IPN_ICMPQUERY; 885255332Scy nat->in_spmin = $3.p1; 886255332Scy nat->in_spmax = $3.p2; 887145510Sdarrenr } 888145510Sdarrenr ; 889145510Sdarrenr 890145510Sdarrenrsobject: 891255332Scy saddr { $$ = $1; } 892255332Scy | saddr port portstuff { nat->in_osport = $3.p1; 893145510Sdarrenr nat->in_stop = $3.p2; 894255332Scy nat->in_scmp = $3.pc; 895255332Scy $$ = $1; 896255332Scy } 897145510Sdarrenr ; 898145510Sdarrenr 899255332Scysaddr: addr { nat->in_osrcatype = $1.t; 900255332Scy bcopy(&$1.a, 901255332Scy &nat->in_osrc.na_addr[0], 902255332Scy sizeof($1.a)); 903255332Scy bcopy(&$1.m, 904255332Scy &nat->in_osrc.na_addr[1], 905255332Scy sizeof($1.m)); 906255332Scy $$ = $1.f; 907145510Sdarrenr } 908145510Sdarrenr ; 909145510Sdarrenr 910145510Sdarrenrdobject: 911255332Scy daddr { $$ = $1; } 912255332Scy | daddr port portstuff { nat->in_odport = $3.p1; 913145510Sdarrenr nat->in_dtop = $3.p2; 914145510Sdarrenr nat->in_dcmp = $3.pc; 915255332Scy $$ = $1; 916145510Sdarrenr } 917145510Sdarrenr ; 918145510Sdarrenr 919255332Scydaddr: addr { nat->in_odstatype = $1.t; 920255332Scy bcopy(&$1.a, 921255332Scy &nat->in_odst.na_addr[0], 922255332Scy sizeof($1.a)); 923255332Scy bcopy(&$1.m, 924255332Scy &nat->in_odst.na_addr[1], 925255332Scy sizeof($1.m)); 926255332Scy $$ = $1.f; 927255332Scy } 928255332Scy ; 929255332Scy 930255332Scyaddr: IPNY_ANY { yyexpectaddr = 0; 931255332Scy bzero(&$$, sizeof($$)); 932255332Scy $$.t = FRI_NORMAL; 933255332Scy } 934255332Scy | hostname { bzero(&$$, sizeof($$)); 935255332Scy $$.a = $1.a; 936255332Scy $$.t = FRI_NORMAL; 937255332Scy $$.v = ftov($1.f); 938255332Scy $$.f = $1.f; 939255332Scy if ($$.f == AF_INET) { 940255332Scy $$.m.in4.s_addr = 0xffffffff; 941255332Scy } else if ($$.f == AF_INET6) { 942255332Scy $$.m.i6[0] = 0xffffffff; 943255332Scy $$.m.i6[1] = 0xffffffff; 944255332Scy $$.m.i6[2] = 0xffffffff; 945255332Scy $$.m.i6[3] = 0xffffffff; 946145510Sdarrenr } 947255332Scy yyexpectaddr = 0; 948145510Sdarrenr } 949255332Scy | hostname slash YY_NUMBER 950255332Scy { bzero(&$$, sizeof($$)); 951255332Scy $$.a = $1.a; 952255332Scy $$.f = $1.f; 953255332Scy $$.v = ftov($1.f); 954255332Scy $$.t = FRI_NORMAL; 955255332Scy ntomask($$.f, $3, (u_32_t *)&$$.m); 956255332Scy $$.a.i6[0] &= $$.m.i6[0]; 957255332Scy $$.a.i6[1] &= $$.m.i6[1]; 958255332Scy $$.a.i6[2] &= $$.m.i6[2]; 959255332Scy $$.a.i6[3] &= $$.m.i6[3]; 960255332Scy yyexpectaddr = 0; 961255332Scy } 962255332Scy | hostname slash ipaddr { bzero(&$$, sizeof($$)); 963255332Scy if ($1.f != $3.f) { 964255332Scy yyerror("1.address family " 965255332Scy "mismatch"); 966255332Scy } 967255332Scy $$.a = $1.a; 968255332Scy $$.m = $3.a; 969255332Scy $$.t = FRI_NORMAL; 970255332Scy $$.a.i6[0] &= $$.m.i6[0]; 971255332Scy $$.a.i6[1] &= $$.m.i6[1]; 972255332Scy $$.a.i6[2] &= $$.m.i6[2]; 973255332Scy $$.a.i6[3] &= $$.m.i6[3]; 974255332Scy $$.f = $1.f; 975255332Scy $$.v = ftov($1.f); 976255332Scy yyexpectaddr = 0; 977255332Scy } 978255332Scy | hostname slash hexnumber { bzero(&$$, sizeof($$)); 979255332Scy $$.a = $1.a; 980255332Scy $$.m.in4.s_addr = htonl($3); 981255332Scy $$.t = FRI_NORMAL; 982255332Scy $$.a.in4.s_addr &= $$.m.in4.s_addr; 983255332Scy $$.f = $1.f; 984255332Scy $$.v = ftov($1.f); 985255332Scy if ($$.f == AF_INET6) 986255332Scy yyerror("incorrect inet6 mask"); 987255332Scy } 988255332Scy | hostname mask ipaddr { bzero(&$$, sizeof($$)); 989255332Scy if ($1.f != $3.f) { 990255332Scy yyerror("2.address family " 991255332Scy "mismatch"); 992255332Scy } 993255332Scy $$.a = $1.a; 994255332Scy $$.m = $3.a; 995255332Scy $$.t = FRI_NORMAL; 996255332Scy $$.a.i6[0] &= $$.m.i6[0]; 997255332Scy $$.a.i6[1] &= $$.m.i6[1]; 998255332Scy $$.a.i6[2] &= $$.m.i6[2]; 999255332Scy $$.a.i6[3] &= $$.m.i6[3]; 1000255332Scy $$.f = $1.f; 1001255332Scy $$.v = ftov($1.f); 1002255332Scy yyexpectaddr = 0; 1003255332Scy } 1004255332Scy | hostname mask hexnumber { bzero(&$$, sizeof($$)); 1005255332Scy $$.a = $1.a; 1006255332Scy $$.m.in4.s_addr = htonl($3); 1007255332Scy $$.t = FRI_NORMAL; 1008255332Scy $$.a.in4.s_addr &= $$.m.in4.s_addr; 1009255332Scy $$.f = AF_INET; 1010255332Scy $$.v = 4; 1011255332Scy } 1012255332Scy | pool slash YY_NUMBER { bzero(&$$, sizeof($$)); 1013255332Scy $$.a.iplookupnum = $3; 1014255332Scy $$.a.iplookuptype = IPLT_POOL; 1015255332Scy $$.a.iplookupsubtype = 0; 1016255332Scy $$.t = FRI_LOOKUP; 1017255332Scy } 1018255332Scy | pool slash YY_STR { bzero(&$$, sizeof($$)); 1019255332Scy $$.a.iplookupname = addname(&nat,$3); 1020255332Scy $$.a.iplookuptype = IPLT_POOL; 1021255332Scy $$.a.iplookupsubtype = 1; 1022255332Scy $$.t = FRI_LOOKUP; 1023255332Scy } 1024255332Scy | hash slash YY_NUMBER { bzero(&$$, sizeof($$)); 1025255332Scy $$.a.iplookupnum = $3; 1026255332Scy $$.a.iplookuptype = IPLT_HASH; 1027255332Scy $$.a.iplookupsubtype = 0; 1028255332Scy $$.t = FRI_LOOKUP; 1029255332Scy } 1030255332Scy | hash slash YY_STR { bzero(&$$, sizeof($$)); 1031255332Scy $$.a.iplookupname = addname(&nat,$3); 1032255332Scy $$.a.iplookuptype = IPLT_HASH; 1033255332Scy $$.a.iplookupsubtype = 1; 1034255332Scy $$.t = FRI_LOOKUP; 1035255332Scy } 1036145510Sdarrenr ; 1037145510Sdarrenr 1038255332Scyslash: '/' { yyexpectaddr = 0; } 1039145510Sdarrenr ; 1040145510Sdarrenr 1041255332Scymask: IPNY_MASK { yyexpectaddr = 0; } 1042145510Sdarrenr ; 1043145510Sdarrenr 1044255332Scypool: IPNY_POOL { if (!(nat->in_flags & IPN_FILTER)) { 1045255332Scy yyerror("Can only use pool with from/to rules\n"); 1046255332Scy } 1047255332Scy yyexpectaddr = 0; 1048255332Scy yyresetdict(); 1049255332Scy } 1050255332Scy ; 1051255332Scy 1052255332Scyhash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) { 1053255332Scy yyerror("Can only use hash with from/to rules\n"); 1054255332Scy } 1055255332Scy yyexpectaddr = 0; 1056255332Scy yyresetdict(); 1057255332Scy } 1058255332Scy ; 1059255332Scy 1060145510Sdarrenrportstuff: 1061272990Scy compare portspec { $$.pc = $1; $$.p1 = $2; $$.p2 = 0; } 1062153881Sguido | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } 1063145510Sdarrenr ; 1064145510Sdarrenr 1065145510Sdarrenrmapoptions: 1066255332Scy rr frag age mssclamp nattag setproto purge 1067145510Sdarrenr ; 1068145510Sdarrenr 1069145510Sdarrenrrdroptions: 1070255332Scy rr frag age sticky mssclamp rdrproxy nattag purge 1071145510Sdarrenr ; 1072145510Sdarrenr 1073145510Sdarrenrnattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, 1074145510Sdarrenr sizeof(nat->in_tag.ipt_tag)); 1075145510Sdarrenr } 1076145510Sdarrenrrr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; } 1077145510Sdarrenr ; 1078145510Sdarrenr 1079145510Sdarrenrfrag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; } 1080145510Sdarrenr ; 1081145510Sdarrenr 1082145510Sdarrenrage: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; 1083145510Sdarrenr nat->in_age[1] = $2; } 1084145510Sdarrenr | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2; 1085145510Sdarrenr nat->in_age[1] = $4; } 1086145510Sdarrenr ; 1087145510Sdarrenr 1088255332Scysticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && 1089145510Sdarrenr !(nat->in_flags & IPN_SPLIT)) { 1090255332Scy FPRINTF(stderr, 1091145510Sdarrenr "'sticky' for use with round-robin/IP splitting only\n"); 1092145510Sdarrenr } else 1093145510Sdarrenr nat->in_flags |= IPN_STICKY; 1094145510Sdarrenr } 1095145510Sdarrenr ; 1096145510Sdarrenr 1097145510Sdarrenrmssclamp: 1098145510Sdarrenr | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } 1099145510Sdarrenr ; 1100145510Sdarrenr 1101255332Scytcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); } 1102145510Sdarrenr | IPNY_UDP { setnatproto(IPPROTO_UDP); } 1103145510Sdarrenr | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; 1104255332Scy nat->in_pr[0] = 0; 1105255332Scy nat->in_pr[1] = 0; 1106145510Sdarrenr } 1107145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; 1108255332Scy nat->in_pr[0] = 0; 1109255332Scy nat->in_pr[1] = 0; 1110145510Sdarrenr } 1111145510Sdarrenr ; 1112145510Sdarrenr 1113255332Scysequential: 1114255332Scy | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; } 1115255332Scy ; 1116255332Scy 1117255332Scypurge: 1118255332Scy | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } 1119255332Scy ; 1120255332Scy 1121145510Sdarrenrrdrproxy: 1122145510Sdarrenr IPNY_PROXY YY_STR 1123255332Scy { int pos; 1124255332Scy pos = addname(&nat, $2); 1125255332Scy nat->in_plabel = pos; 1126255332Scy nat->in_odport = nat->in_dpnext; 1127255332Scy nat->in_dtop = nat->in_odport; 1128145510Sdarrenr free($2); 1129145510Sdarrenr } 1130255332Scy | proxy { if (nat->in_plabel != -1) { 1131255332Scy nat->in_ndport = nat->in_odport; 1132255332Scy nat->in_dpmin = nat->in_odport; 1133255332Scy nat->in_dpmax = nat->in_dpmin; 1134255332Scy nat->in_dtop = nat->in_dpmin; 1135255332Scy nat->in_dpnext = nat->in_dpmin; 1136255332Scy } 1137255332Scy } 1138145510Sdarrenr ; 1139145510Sdarrenr 1140255332Scynewopts: 1141255332Scy | IPNY_PURGE { nat->in_flags |= IPN_PURGE; } 1142255332Scy ; 1143255332Scy 1144161357Sguidoproto: YY_NUMBER { $$ = $1; 1145161357Sguido if ($$ != IPPROTO_TCP && 1146161357Sguido $$ != IPPROTO_UDP) 1147161357Sguido suggest_port = 0; 1148161357Sguido } 1149145510Sdarrenr | IPNY_TCP { $$ = IPPROTO_TCP; } 1150145510Sdarrenr | IPNY_UDP { $$ = IPPROTO_UDP; } 1151255332Scy | YY_STR { $$ = getproto($1); 1152255332Scy free($1); 1153255332Scy if ($$ == -1) 1154272990Scy yyerror("unknown protocol"); 1155161357Sguido if ($$ != IPPROTO_TCP && 1156161357Sguido $$ != IPPROTO_UDP) 1157161357Sguido suggest_port = 0; 1158161357Sguido } 1159145510Sdarrenr ; 1160145510Sdarrenr 1161145510Sdarrenrhexnumber: 1162145510Sdarrenr YY_HEX { $$ = $1; } 1163145510Sdarrenr ; 1164145510Sdarrenr 1165145510Sdarrenrhostname: 1166255332Scy YY_STR { i6addr_t addr; 1167272989Scy int family; 1168255332Scy 1169272989Scy#ifdef USE_INET6 1170272989Scy if (nat->in_v[0] == 6) 1171272989Scy family = AF_INET6; 1172272989Scy else 1173272989Scy#endif 1174272989Scy family = AF_INET; 1175272990Scy memset(&($$), 0, sizeof($$)); 1176272990Scy memset(&addr, 0, sizeof(addr)); 1177272989Scy $$.f = family; 1178272989Scy if (gethost(family, $1, 1179255332Scy &addr) == 0) { 1180255332Scy $$.a = addr; 1181255332Scy } else { 1182255332Scy FPRINTF(stderr, 1183145510Sdarrenr "Unknown host '%s'\n", 1184145510Sdarrenr $1); 1185255332Scy } 1186145510Sdarrenr free($1); 1187145510Sdarrenr } 1188272990Scy | YY_NUMBER { memset(&($$), 0, sizeof($$)); 1189255332Scy $$.a.in4.s_addr = htonl($1); 1190255332Scy if ($$.a.in4.s_addr != 0) 1191255332Scy $$.f = AF_INET; 1192255332Scy } 1193255332Scy | ipv4 { $$ = $1; } 1194272990Scy | YY_IPV6 { memset(&($$), 0, sizeof($$)); 1195255332Scy $$.a = $1; 1196255332Scy $$.f = AF_INET6; 1197255332Scy } 1198272990Scy | YY_NUMBER YY_IPV6 { memset(&($$), 0, sizeof($$)); 1199255332Scy $$.a = $2; 1200255332Scy $$.f = AF_INET6; 1201255332Scy } 1202145510Sdarrenr ; 1203145510Sdarrenr 1204145510Sdarrenrcompare: 1205145510Sdarrenr '=' { $$ = FR_EQUAL; } 1206145510Sdarrenr | YY_CMP_EQ { $$ = FR_EQUAL; } 1207145510Sdarrenr | YY_CMP_NE { $$ = FR_NEQUAL; } 1208145510Sdarrenr | YY_CMP_LT { $$ = FR_LESST; } 1209145510Sdarrenr | YY_CMP_LE { $$ = FR_LESSTE; } 1210145510Sdarrenr | YY_CMP_GT { $$ = FR_GREATERT; } 1211145510Sdarrenr | YY_CMP_GE { $$ = FR_GREATERTE; } 1212145510Sdarrenr 1213145510Sdarrenrrange: 1214145510Sdarrenr YY_RANGE_OUT { $$ = FR_OUTRANGE; } 1215145510Sdarrenr | YY_RANGE_IN { $$ = FR_INRANGE; } 1216172776Sdarrenr | ':' { $$ = FR_INCRANGE; } 1217145510Sdarrenr ; 1218145510Sdarrenr 1219255332Scyipaddr: ipv4 { $$ = $1; } 1220255332Scy | YY_IPV6 { $$.a = $1; 1221255332Scy $$.f = AF_INET6; 1222255332Scy } 1223255332Scy ; 1224255332Scy 1225145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 1226145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 1227145510Sdarrenr yyerror("Invalid octet string for IP address"); 1228145510Sdarrenr return 0; 1229145510Sdarrenr } 1230255332Scy bzero((char *)&$$, sizeof($$)); 1231255332Scy $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 1232255332Scy $$.a.in4.s_addr = htonl($$.a.in4.s_addr); 1233255332Scy $$.f = AF_INET; 1234145510Sdarrenr } 1235145510Sdarrenr ; 1236145510Sdarrenr 1237145510Sdarrenr%% 1238145510Sdarrenr 1239145510Sdarrenr 1240255332Scystatic wordtab_t proxies[] = { 1241255332Scy { "dns", IPNY_DNS } 1242255332Scy}; 1243255332Scy 1244255332Scystatic wordtab_t dnswords[] = { 1245255332Scy { "allow", IPNY_ALLOW }, 1246255332Scy { "block", IPNY_DENY }, 1247255332Scy { "deny", IPNY_DENY }, 1248255332Scy { "drop", IPNY_DENY }, 1249255332Scy { "pass", IPNY_ALLOW }, 1250255332Scy 1251255332Scy}; 1252255332Scy 1253145510Sdarrenrstatic wordtab_t yywords[] = { 1254145510Sdarrenr { "age", IPNY_AGE }, 1255145510Sdarrenr { "any", IPNY_ANY }, 1256145510Sdarrenr { "auto", IPNY_AUTO }, 1257145510Sdarrenr { "bimap", IPNY_BIMAP }, 1258255332Scy { "config", IPNY_CONFIG }, 1259255332Scy { "divert", IPNY_DIVERT }, 1260255332Scy { "dst", IPNY_DST }, 1261255332Scy { "dstlist", IPNY_DSTLIST }, 1262145510Sdarrenr { "frag", IPNY_FRAG }, 1263145510Sdarrenr { "from", IPNY_FROM }, 1264255332Scy { "hash", IPNY_HASH }, 1265145510Sdarrenr { "icmpidmap", IPNY_ICMPIDMAP }, 1266255332Scy { "in", IPNY_IN }, 1267255332Scy { "inet", IPNY_INET }, 1268255332Scy { "inet6", IPNY_INET6 }, 1269145510Sdarrenr { "mask", IPNY_MASK }, 1270145510Sdarrenr { "map", IPNY_MAP }, 1271145510Sdarrenr { "map-block", IPNY_MAPBLOCK }, 1272145510Sdarrenr { "mssclamp", IPNY_MSSCLAMP }, 1273145510Sdarrenr { "netmask", IPNY_MASK }, 1274255332Scy { "no", IPNY_NO }, 1275255332Scy { "on", IPNY_ON }, 1276255332Scy { "out", IPNY_OUT }, 1277255332Scy { "pool", IPNY_POOL }, 1278145510Sdarrenr { "port", IPNY_PORT }, 1279145510Sdarrenr { "portmap", IPNY_PORTMAP }, 1280145510Sdarrenr { "ports", IPNY_PORTS }, 1281255332Scy { "proto", IPNY_PROTO }, 1282145510Sdarrenr { "proxy", IPNY_PROXY }, 1283255332Scy { "purge", IPNY_PURGE }, 1284145510Sdarrenr { "range", IPNY_RANGE }, 1285255332Scy { "rewrite", IPNY_REWRITE }, 1286145510Sdarrenr { "rdr", IPNY_RDR }, 1287145510Sdarrenr { "round-robin",IPNY_ROUNDROBIN }, 1288180778Sdarrenr { "sequential", IPNY_SEQUENTIAL }, 1289255332Scy { "src", IPNY_SRC }, 1290145510Sdarrenr { "sticky", IPNY_STICKY }, 1291145510Sdarrenr { "tag", IPNY_TAG }, 1292145510Sdarrenr { "tcp", IPNY_TCP }, 1293145510Sdarrenr { "tcpudp", IPNY_TCPUDP }, 1294145510Sdarrenr { "to", IPNY_TO }, 1295145510Sdarrenr { "udp", IPNY_UDP }, 1296145510Sdarrenr { "-", '-' }, 1297145510Sdarrenr { "->", IPNY_TLATE }, 1298145510Sdarrenr { "eq", YY_CMP_EQ }, 1299145510Sdarrenr { "ne", YY_CMP_NE }, 1300145510Sdarrenr { "lt", YY_CMP_LT }, 1301145510Sdarrenr { "gt", YY_CMP_GT }, 1302145510Sdarrenr { "le", YY_CMP_LE }, 1303145510Sdarrenr { "ge", YY_CMP_GE }, 1304145510Sdarrenr { NULL, 0 } 1305145510Sdarrenr}; 1306145510Sdarrenr 1307145510Sdarrenr 1308255332Scyint 1309255332Scyipnat_parsefile(fd, addfunc, ioctlfunc, filename) 1310255332Scy int fd; 1311255332Scy addfunc_t addfunc; 1312255332Scy ioctlfunc_t ioctlfunc; 1313255332Scy char *filename; 1314145510Sdarrenr{ 1315145510Sdarrenr FILE *fp = NULL; 1316255332Scy int rval; 1317145510Sdarrenr char *s; 1318145510Sdarrenr 1319255332Scy yylineNum = 1; 1320255332Scy 1321145510Sdarrenr (void) yysettab(yywords); 1322145510Sdarrenr 1323145510Sdarrenr s = getenv("YYDEBUG"); 1324145510Sdarrenr if (s) 1325145510Sdarrenr yydebug = atoi(s); 1326145510Sdarrenr else 1327145510Sdarrenr yydebug = 0; 1328145510Sdarrenr 1329145510Sdarrenr if (strcmp(filename, "-")) { 1330145510Sdarrenr fp = fopen(filename, "r"); 1331145510Sdarrenr if (!fp) { 1332255332Scy FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, 1333145510Sdarrenr STRERROR(errno)); 1334145510Sdarrenr return -1; 1335145510Sdarrenr } 1336145510Sdarrenr } else 1337145510Sdarrenr fp = stdin; 1338145510Sdarrenr 1339255332Scy while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) 1340145510Sdarrenr ; 1341145510Sdarrenr if (fp != NULL) 1342145510Sdarrenr fclose(fp); 1343255332Scy if (rval == -1) 1344255332Scy rval = 0; 1345255332Scy else if (rval != 0) 1346255332Scy rval = 1; 1347255332Scy return rval; 1348145510Sdarrenr} 1349145510Sdarrenr 1350145510Sdarrenr 1351255332Scyint 1352255332Scyipnat_parsesome(fd, addfunc, ioctlfunc, fp) 1353255332Scy int fd; 1354255332Scy addfunc_t addfunc; 1355255332Scy ioctlfunc_t ioctlfunc; 1356255332Scy FILE *fp; 1357145510Sdarrenr{ 1358145510Sdarrenr char *s; 1359145510Sdarrenr int i; 1360145510Sdarrenr 1361145510Sdarrenr natfd = fd; 1362255332Scy parser_error = 0; 1363145510Sdarrenr nataddfunc = addfunc; 1364145510Sdarrenr natioctlfunc = ioctlfunc; 1365145510Sdarrenr 1366145510Sdarrenr if (feof(fp)) 1367255332Scy return -1; 1368145510Sdarrenr i = fgetc(fp); 1369145510Sdarrenr if (i == EOF) 1370255332Scy return -1; 1371145510Sdarrenr if (ungetc(i, fp) == EOF) 1372255332Scy return -1; 1373145510Sdarrenr if (feof(fp)) 1374255332Scy return -1; 1375145510Sdarrenr s = getenv("YYDEBUG"); 1376145510Sdarrenr if (s) 1377145510Sdarrenr yydebug = atoi(s); 1378145510Sdarrenr else 1379145510Sdarrenr yydebug = 0; 1380145510Sdarrenr 1381145510Sdarrenr yyin = fp; 1382145510Sdarrenr yyparse(); 1383255332Scy return parser_error; 1384145510Sdarrenr} 1385145510Sdarrenr 1386145510Sdarrenr 1387255332Scystatic void 1388255332Scynewnatrule() 1389145510Sdarrenr{ 1390145510Sdarrenr ipnat_t *n; 1391145510Sdarrenr 1392145510Sdarrenr n = calloc(1, sizeof(*n)); 1393145510Sdarrenr if (n == NULL) 1394145510Sdarrenr return; 1395145510Sdarrenr 1396255332Scy if (nat == NULL) { 1397145510Sdarrenr nattop = nat = n; 1398255332Scy n->in_pnext = &nattop; 1399255332Scy } else { 1400145510Sdarrenr nat->in_next = n; 1401255332Scy n->in_pnext = &nat->in_next; 1402145510Sdarrenr nat = n; 1403145510Sdarrenr } 1404161357Sguido 1405255332Scy n->in_flineno = yylineNum; 1406255332Scy n->in_ifnames[0] = -1; 1407255332Scy n->in_ifnames[1] = -1; 1408255332Scy n->in_plabel = -1; 1409255332Scy n->in_pconfig = -1; 1410255332Scy n->in_size = sizeof(*n); 1411255332Scy 1412161357Sguido suggest_port = 0; 1413145510Sdarrenr} 1414145510Sdarrenr 1415145510Sdarrenr 1416255332Scystatic void 1417255332Scysetnatproto(p) 1418255332Scy int p; 1419145510Sdarrenr{ 1420255332Scy nat->in_pr[0] = p; 1421255332Scy nat->in_pr[1] = p; 1422145510Sdarrenr 1423145510Sdarrenr switch (p) 1424145510Sdarrenr { 1425145510Sdarrenr case IPPROTO_TCP : 1426145510Sdarrenr nat->in_flags |= IPN_TCP; 1427145510Sdarrenr nat->in_flags &= ~IPN_UDP; 1428145510Sdarrenr break; 1429145510Sdarrenr case IPPROTO_UDP : 1430145510Sdarrenr nat->in_flags |= IPN_UDP; 1431145510Sdarrenr nat->in_flags &= ~IPN_TCP; 1432145510Sdarrenr break; 1433272990Scy#ifdef USE_INET6 1434272990Scy case IPPROTO_ICMPV6 : 1435272990Scy#endif 1436145510Sdarrenr case IPPROTO_ICMP : 1437145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1438255332Scy if (!(nat->in_flags & IPN_ICMPQUERY) && 1439255332Scy !(nat->in_redir & NAT_DIVERTUDP)) { 1440145510Sdarrenr nat->in_dcmp = 0; 1441145510Sdarrenr nat->in_scmp = 0; 1442255332Scy nat->in_dpmin = 0; 1443255332Scy nat->in_dpmax = 0; 1444255332Scy nat->in_dpnext = 0; 1445255332Scy nat->in_spmin = 0; 1446255332Scy nat->in_spmax = 0; 1447255332Scy nat->in_spnext = 0; 1448145510Sdarrenr } 1449145510Sdarrenr break; 1450145510Sdarrenr default : 1451145510Sdarrenr if ((nat->in_redir & NAT_MAPBLK) == 0) { 1452145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1453145510Sdarrenr nat->in_dcmp = 0; 1454145510Sdarrenr nat->in_scmp = 0; 1455255332Scy nat->in_dpmin = 0; 1456255332Scy nat->in_dpmax = 0; 1457255332Scy nat->in_dpnext = 0; 1458255332Scy nat->in_spmin = 0; 1459255332Scy nat->in_spmax = 0; 1460255332Scy nat->in_spnext = 0; 1461145510Sdarrenr } 1462145510Sdarrenr break; 1463145510Sdarrenr } 1464145510Sdarrenr 1465255332Scy if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) { 1466255332Scy nat->in_stop = 0; 1467255332Scy nat->in_dtop = 0; 1468255332Scy nat->in_osport = 0; 1469255332Scy nat->in_odport = 0; 1470255332Scy nat->in_stop = 0; 1471255332Scy nat->in_osport = 0; 1472255332Scy nat->in_dtop = 0; 1473255332Scy nat->in_odport = 0; 1474255332Scy } 1475145510Sdarrenr if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) 1476145510Sdarrenr nat->in_flags &= ~IPN_FIXEDDPORT; 1477145510Sdarrenr} 1478145510Sdarrenr 1479145510Sdarrenr 1480255332Scyint 1481255332Scyipnat_addrule(fd, ioctlfunc, ptr) 1482255332Scy int fd; 1483255332Scy ioctlfunc_t ioctlfunc; 1484255332Scy void *ptr; 1485145510Sdarrenr{ 1486145510Sdarrenr ioctlcmd_t add, del; 1487145510Sdarrenr ipfobj_t obj; 1488145510Sdarrenr ipnat_t *ipn; 1489145510Sdarrenr 1490145510Sdarrenr ipn = ptr; 1491145510Sdarrenr bzero((char *)&obj, sizeof(obj)); 1492145510Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1493255332Scy obj.ipfo_size = ipn->in_size; 1494145510Sdarrenr obj.ipfo_type = IPFOBJ_IPNAT; 1495145510Sdarrenr obj.ipfo_ptr = ptr; 1496145510Sdarrenr 1497145510Sdarrenr if ((opts & OPT_DONOTHING) != 0) 1498145510Sdarrenr fd = -1; 1499145510Sdarrenr 1500145510Sdarrenr if (opts & OPT_ZERORULEST) { 1501145510Sdarrenr add = SIOCZRLST; 1502255332Scy del = 0; 1503255332Scy } else if (opts & OPT_PURGE) { 1504255332Scy add = 0; 1505255332Scy del = SIOCPURGENAT; 1506145510Sdarrenr } else { 1507145510Sdarrenr add = SIOCADNAT; 1508145510Sdarrenr del = SIOCRMNAT; 1509145510Sdarrenr } 1510145510Sdarrenr 1511161357Sguido if ((opts & OPT_VERBOSE) != 0) 1512145510Sdarrenr printnat(ipn, opts); 1513145510Sdarrenr 1514145510Sdarrenr if (opts & OPT_DEBUG) 1515272990Scy binprint(ipn, ipn->in_size); 1516145510Sdarrenr 1517145510Sdarrenr if ((opts & OPT_ZERORULEST) != 0) { 1518145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1519145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1520255332Scy char msg[80]; 1521255332Scy 1522255332Scy sprintf(msg, "%d:ioctl(zero nat rule)", 1523255332Scy ipn->in_flineno); 1524255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1525145510Sdarrenr } 1526145510Sdarrenr } else { 1527255332Scy PRINTF("hits %lu ", ipn->in_hits); 1528255332Scy#ifdef USE_QUAD_T 1529255332Scy PRINTF("bytes %"PRIu64" ", 1530255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1531145510Sdarrenr#else 1532255332Scy PRINTF("bytes %lu ", 1533255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1534145510Sdarrenr#endif 1535145510Sdarrenr printnat(ipn, opts); 1536145510Sdarrenr } 1537145510Sdarrenr } else if ((opts & OPT_REMOVE) != 0) { 1538145510Sdarrenr if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 1539145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1540255332Scy char msg[80]; 1541255332Scy 1542255332Scy sprintf(msg, "%d:ioctl(delete nat rule)", 1543255332Scy ipn->in_flineno); 1544255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1545145510Sdarrenr } 1546145510Sdarrenr } 1547145510Sdarrenr } else { 1548145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1549145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1550255332Scy char msg[80]; 1551255332Scy 1552255332Scy sprintf(msg, "%d:ioctl(add/insert nat rule)", 1553255332Scy ipn->in_flineno); 1554255332Scy if (errno == EEXIST) { 1555255332Scy sprintf(msg + strlen(msg), "(line %d)", 1556255332Scy ipn->in_flineno); 1557255332Scy } 1558255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1559145510Sdarrenr } 1560145510Sdarrenr } 1561145510Sdarrenr } 1562255332Scy return 0; 1563145510Sdarrenr} 1564255332Scy 1565255332Scy 1566255332Scystatic void 1567255332Scysetmapifnames() 1568255332Scy{ 1569255332Scy if (nat->in_ifnames[1] == -1) 1570255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1571255332Scy 1572255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1573255332Scy nat->in_flags |= IPN_TCPUDP; 1574255332Scy 1575255332Scy if ((nat->in_flags & IPN_TCPUDP) == 0) 1576255332Scy setnatproto(nat->in_pr[1]); 1577255332Scy 1578255332Scy if (((nat->in_redir & NAT_MAPBLK) != 0) || 1579255332Scy ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 1580255332Scy nat_setgroupmap(nat); 1581255332Scy} 1582255332Scy 1583255332Scy 1584255332Scystatic void 1585255332Scysetrdrifnames() 1586255332Scy{ 1587255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1588255332Scy nat->in_flags |= IPN_TCPUDP; 1589255332Scy 1590255332Scy if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && 1591255332Scy (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0)) 1592255332Scy setnatproto(IPPROTO_TCP); 1593255332Scy 1594255332Scy if (nat->in_ifnames[1] == -1) 1595255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1596255332Scy} 1597255332Scy 1598255332Scy 1599255332Scystatic void 1600255332Scyproxy_setconfig(proxy) 1601255332Scy int proxy; 1602255332Scy{ 1603255332Scy if (proxy == IPNY_DNS) { 1604255332Scy yysetfixeddict(dnswords); 1605255332Scy } 1606255332Scy} 1607255332Scy 1608255332Scy 1609255332Scystatic void 1610255332Scyproxy_unsetconfig() 1611255332Scy{ 1612255332Scy yyresetdict(); 1613255332Scy} 1614255332Scy 1615255332Scy 1616255332Scystatic namelist_t * 1617255332Scyproxy_dns_add_pass(prefix, name) 1618255332Scy char *prefix, *name; 1619255332Scy{ 1620255332Scy namelist_t *n; 1621255332Scy 1622255332Scy n = calloc(1, sizeof(*n)); 1623255332Scy if (n != NULL) { 1624255332Scy if (prefix == NULL || *prefix == '\0') { 1625255332Scy n->na_name = strdup(name); 1626255332Scy } else { 1627255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1628255332Scy strcpy(n->na_name, prefix); 1629255332Scy strcat(n->na_name, name); 1630255332Scy } 1631255332Scy } 1632255332Scy return n; 1633255332Scy} 1634255332Scy 1635255332Scy 1636255332Scystatic namelist_t * 1637255332Scyproxy_dns_add_block(prefix, name) 1638255332Scy char *prefix, *name; 1639255332Scy{ 1640255332Scy namelist_t *n; 1641255332Scy 1642255332Scy n = calloc(1, sizeof(*n)); 1643255332Scy if (n != NULL) { 1644255332Scy if (prefix == NULL || *prefix == '\0') { 1645255332Scy n->na_name = strdup(name); 1646255332Scy } else { 1647255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1648255332Scy strcpy(n->na_name, prefix); 1649255332Scy strcat(n->na_name, name); 1650255332Scy } 1651255332Scy n->na_value = 1; 1652255332Scy } 1653255332Scy return n; 1654255332Scy} 1655255332Scy 1656255332Scy 1657255332Scystatic void 1658255332Scyproxy_addconfig(proxy, proto, conf, list) 1659255332Scy char *proxy, *conf; 1660255332Scy int proto; 1661255332Scy namelist_t *list; 1662255332Scy{ 1663255332Scy proxyrule_t *pr; 1664255332Scy 1665255332Scy pr = calloc(1, sizeof(*pr)); 1666255332Scy if (pr != NULL) { 1667255332Scy pr->pr_proto = proto; 1668255332Scy pr->pr_proxy = proxy; 1669255332Scy pr->pr_conf = conf; 1670255332Scy pr->pr_names = list; 1671255332Scy pr->pr_next = prules; 1672255332Scy prules = pr; 1673255332Scy } 1674255332Scy} 1675255332Scy 1676255332Scy 1677255332Scystatic void 1678255332Scyproxy_loadrules(fd, ioctlfunc, rules) 1679255332Scy int fd; 1680255332Scy ioctlfunc_t ioctlfunc; 1681255332Scy proxyrule_t *rules; 1682255332Scy{ 1683255332Scy proxyrule_t *pr; 1684255332Scy 1685255332Scy while ((pr = rules) != NULL) { 1686255332Scy proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto, 1687255332Scy pr->pr_conf, pr->pr_names); 1688255332Scy rules = pr->pr_next; 1689255332Scy free(pr->pr_conf); 1690255332Scy free(pr); 1691255332Scy } 1692255332Scy} 1693255332Scy 1694255332Scy 1695255332Scystatic void 1696255332Scyproxy_loadconfig(fd, ioctlfunc, proxy, proto, conf, list) 1697255332Scy int fd; 1698255332Scy ioctlfunc_t ioctlfunc; 1699255332Scy char *proxy, *conf; 1700255332Scy int proto; 1701255332Scy namelist_t *list; 1702255332Scy{ 1703255332Scy namelist_t *na; 1704255332Scy ipfobj_t obj; 1705255332Scy ap_ctl_t pcmd; 1706255332Scy 1707255332Scy obj.ipfo_rev = IPFILTER_VERSION; 1708255332Scy obj.ipfo_type = IPFOBJ_PROXYCTL; 1709255332Scy obj.ipfo_size = sizeof(pcmd); 1710255332Scy obj.ipfo_ptr = &pcmd; 1711255332Scy 1712255332Scy while ((na = list) != NULL) { 1713255332Scy if ((opts & OPT_REMOVE) != 0) 1714255332Scy pcmd.apc_cmd = APC_CMD_DEL; 1715255332Scy else 1716255332Scy pcmd.apc_cmd = APC_CMD_ADD; 1717255332Scy pcmd.apc_dsize = strlen(na->na_name) + 1; 1718255332Scy pcmd.apc_data = na->na_name; 1719255332Scy pcmd.apc_arg = na->na_value; 1720255332Scy pcmd.apc_p = proto; 1721255332Scy 1722255332Scy strncpy(pcmd.apc_label, proxy, APR_LABELLEN); 1723255332Scy pcmd.apc_label[APR_LABELLEN - 1] = '\0'; 1724255332Scy 1725255332Scy strncpy(pcmd.apc_config, conf, APR_LABELLEN); 1726255332Scy pcmd.apc_config[APR_LABELLEN - 1] = '\0'; 1727255332Scy 1728255332Scy if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) { 1729255332Scy if ((opts & OPT_DONOTHING) == 0) { 1730255332Scy char msg[80]; 1731255332Scy 1732255332Scy sprintf(msg, "%d:ioctl(add/remove proxy rule)", 1733255332Scy yylineNum); 1734255332Scy ipf_perror_fd(fd, ioctlfunc, msg); 1735255332Scy return; 1736255332Scy } 1737255332Scy } 1738255332Scy 1739255332Scy list = na->na_next; 1740255332Scy free(na->na_name); 1741255332Scy free(na); 1742255332Scy } 1743255332Scy} 1744255332Scy 1745255332Scy 1746255332Scystatic void 1747255332Scysetifname(np, idx, name) 1748255332Scy ipnat_t **np; 1749255332Scy int idx; 1750255332Scy char *name; 1751255332Scy{ 1752255332Scy int pos; 1753255332Scy 1754255332Scy pos = addname(np, name); 1755255332Scy if (pos == -1) 1756255332Scy return; 1757255332Scy (*np)->in_ifnames[idx] = pos; 1758255332Scy} 1759255332Scy 1760255332Scy 1761255332Scystatic int 1762255332Scyaddname(np, name) 1763255332Scy ipnat_t **np; 1764255332Scy char *name; 1765255332Scy{ 1766255332Scy ipnat_t *n; 1767255332Scy int nlen; 1768255332Scy int pos; 1769255332Scy 1770255332Scy nlen = strlen(name) + 1; 1771255332Scy n = realloc(*np, (*np)->in_size + nlen); 1772255332Scy if (*np == nattop) 1773255332Scy nattop = n; 1774255332Scy *np = n; 1775255332Scy if (n == NULL) 1776255332Scy return -1; 1777255332Scy if (n->in_pnext != NULL) 1778255332Scy *n->in_pnext = n; 1779255332Scy n->in_size += nlen; 1780255332Scy pos = n->in_namelen; 1781255332Scy n->in_namelen += nlen; 1782255332Scy strcpy(n->in_names + pos, name); 1783255332Scy n->in_names[n->in_namelen] = '\0'; 1784255332Scy return pos; 1785255332Scy} 1786