1145519Sdarrenr/* $FreeBSD$ */ 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) 874145510Sdarrenr yyerror("invalid ICMP Id number"); 875255332Scy if ($3.p2 < 0 || $3.p2 > 65535) 876145510Sdarrenr yyerror("invalid 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: 1061145510Sdarrenr compare portspec { $$.pc = $1; $$.p1 = $2; } 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) 1154255332Scy yyerror("unknwon 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; 1167255332Scy 1168255332Scy bzero(&$$, sizeof($$)); 1169255332Scy if (gethost(AF_INET, $1, 1170255332Scy &addr) == 0) { 1171255332Scy $$.a = addr; 1172255332Scy $$.f = AF_INET; 1173255332Scy } else 1174255332Scy if (gethost(AF_INET6, $1, 1175255332Scy &addr) == 0) { 1176255332Scy $$.a = addr; 1177255332Scy $$.f = AF_INET6; 1178255332Scy } else { 1179255332Scy FPRINTF(stderr, 1180145510Sdarrenr "Unknown host '%s'\n", 1181145510Sdarrenr $1); 1182255332Scy } 1183145510Sdarrenr free($1); 1184145510Sdarrenr } 1185255332Scy | YY_NUMBER { bzero(&$$, sizeof($$)); 1186255332Scy $$.a.in4.s_addr = htonl($1); 1187255332Scy if ($$.a.in4.s_addr != 0) 1188255332Scy $$.f = AF_INET; 1189255332Scy } 1190255332Scy | ipv4 { $$ = $1; } 1191255332Scy | YY_IPV6 { bzero(&$$, sizeof($$)); 1192255332Scy $$.a = $1; 1193255332Scy $$.f = AF_INET6; 1194255332Scy } 1195255332Scy | YY_NUMBER YY_IPV6 { bzero(&$$, sizeof($$)); 1196255332Scy $$.a = $2; 1197255332Scy $$.f = AF_INET6; 1198255332Scy } 1199145510Sdarrenr ; 1200145510Sdarrenr 1201145510Sdarrenrcompare: 1202145510Sdarrenr '=' { $$ = FR_EQUAL; } 1203145510Sdarrenr | YY_CMP_EQ { $$ = FR_EQUAL; } 1204145510Sdarrenr | YY_CMP_NE { $$ = FR_NEQUAL; } 1205145510Sdarrenr | YY_CMP_LT { $$ = FR_LESST; } 1206145510Sdarrenr | YY_CMP_LE { $$ = FR_LESSTE; } 1207145510Sdarrenr | YY_CMP_GT { $$ = FR_GREATERT; } 1208145510Sdarrenr | YY_CMP_GE { $$ = FR_GREATERTE; } 1209145510Sdarrenr 1210145510Sdarrenrrange: 1211145510Sdarrenr YY_RANGE_OUT { $$ = FR_OUTRANGE; } 1212145510Sdarrenr | YY_RANGE_IN { $$ = FR_INRANGE; } 1213172776Sdarrenr | ':' { $$ = FR_INCRANGE; } 1214145510Sdarrenr ; 1215145510Sdarrenr 1216255332Scyipaddr: ipv4 { $$ = $1; } 1217255332Scy | YY_IPV6 { $$.a = $1; 1218255332Scy $$.f = AF_INET6; 1219255332Scy } 1220255332Scy ; 1221255332Scy 1222145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 1223145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 1224145510Sdarrenr yyerror("Invalid octet string for IP address"); 1225145510Sdarrenr return 0; 1226145510Sdarrenr } 1227255332Scy bzero((char *)&$$, sizeof($$)); 1228255332Scy $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 1229255332Scy $$.a.in4.s_addr = htonl($$.a.in4.s_addr); 1230255332Scy $$.f = AF_INET; 1231145510Sdarrenr } 1232145510Sdarrenr ; 1233145510Sdarrenr 1234145510Sdarrenr%% 1235145510Sdarrenr 1236145510Sdarrenr 1237255332Scystatic wordtab_t proxies[] = { 1238255332Scy { "dns", IPNY_DNS } 1239255332Scy}; 1240255332Scy 1241255332Scystatic wordtab_t dnswords[] = { 1242255332Scy { "allow", IPNY_ALLOW }, 1243255332Scy { "block", IPNY_DENY }, 1244255332Scy { "deny", IPNY_DENY }, 1245255332Scy { "drop", IPNY_DENY }, 1246255332Scy { "pass", IPNY_ALLOW }, 1247255332Scy 1248255332Scy}; 1249255332Scy 1250145510Sdarrenrstatic wordtab_t yywords[] = { 1251145510Sdarrenr { "age", IPNY_AGE }, 1252145510Sdarrenr { "any", IPNY_ANY }, 1253145510Sdarrenr { "auto", IPNY_AUTO }, 1254145510Sdarrenr { "bimap", IPNY_BIMAP }, 1255255332Scy { "config", IPNY_CONFIG }, 1256255332Scy { "divert", IPNY_DIVERT }, 1257255332Scy { "dst", IPNY_DST }, 1258255332Scy { "dstlist", IPNY_DSTLIST }, 1259145510Sdarrenr { "frag", IPNY_FRAG }, 1260145510Sdarrenr { "from", IPNY_FROM }, 1261255332Scy { "hash", IPNY_HASH }, 1262145510Sdarrenr { "icmpidmap", IPNY_ICMPIDMAP }, 1263255332Scy { "in", IPNY_IN }, 1264255332Scy { "inet", IPNY_INET }, 1265255332Scy { "inet6", IPNY_INET6 }, 1266145510Sdarrenr { "mask", IPNY_MASK }, 1267145510Sdarrenr { "map", IPNY_MAP }, 1268145510Sdarrenr { "map-block", IPNY_MAPBLOCK }, 1269145510Sdarrenr { "mssclamp", IPNY_MSSCLAMP }, 1270145510Sdarrenr { "netmask", IPNY_MASK }, 1271255332Scy { "no", IPNY_NO }, 1272255332Scy { "on", IPNY_ON }, 1273255332Scy { "out", IPNY_OUT }, 1274255332Scy { "pool", IPNY_POOL }, 1275145510Sdarrenr { "port", IPNY_PORT }, 1276145510Sdarrenr { "portmap", IPNY_PORTMAP }, 1277145510Sdarrenr { "ports", IPNY_PORTS }, 1278255332Scy { "proto", IPNY_PROTO }, 1279145510Sdarrenr { "proxy", IPNY_PROXY }, 1280255332Scy { "purge", IPNY_PURGE }, 1281145510Sdarrenr { "range", IPNY_RANGE }, 1282255332Scy { "rewrite", IPNY_REWRITE }, 1283145510Sdarrenr { "rdr", IPNY_RDR }, 1284145510Sdarrenr { "round-robin",IPNY_ROUNDROBIN }, 1285180778Sdarrenr { "sequential", IPNY_SEQUENTIAL }, 1286255332Scy { "src", IPNY_SRC }, 1287145510Sdarrenr { "sticky", IPNY_STICKY }, 1288145510Sdarrenr { "tag", IPNY_TAG }, 1289145510Sdarrenr { "tcp", IPNY_TCP }, 1290145510Sdarrenr { "tcpudp", IPNY_TCPUDP }, 1291145510Sdarrenr { "to", IPNY_TO }, 1292145510Sdarrenr { "udp", IPNY_UDP }, 1293145510Sdarrenr { "-", '-' }, 1294145510Sdarrenr { "->", IPNY_TLATE }, 1295145510Sdarrenr { "eq", YY_CMP_EQ }, 1296145510Sdarrenr { "ne", YY_CMP_NE }, 1297145510Sdarrenr { "lt", YY_CMP_LT }, 1298145510Sdarrenr { "gt", YY_CMP_GT }, 1299145510Sdarrenr { "le", YY_CMP_LE }, 1300145510Sdarrenr { "ge", YY_CMP_GE }, 1301145510Sdarrenr { NULL, 0 } 1302145510Sdarrenr}; 1303145510Sdarrenr 1304145510Sdarrenr 1305255332Scyint 1306255332Scyipnat_parsefile(fd, addfunc, ioctlfunc, filename) 1307255332Scy int fd; 1308255332Scy addfunc_t addfunc; 1309255332Scy ioctlfunc_t ioctlfunc; 1310255332Scy char *filename; 1311145510Sdarrenr{ 1312145510Sdarrenr FILE *fp = NULL; 1313255332Scy int rval; 1314145510Sdarrenr char *s; 1315145510Sdarrenr 1316255332Scy yylineNum = 1; 1317255332Scy 1318145510Sdarrenr (void) yysettab(yywords); 1319145510Sdarrenr 1320145510Sdarrenr s = getenv("YYDEBUG"); 1321145510Sdarrenr if (s) 1322145510Sdarrenr yydebug = atoi(s); 1323145510Sdarrenr else 1324145510Sdarrenr yydebug = 0; 1325145510Sdarrenr 1326145510Sdarrenr if (strcmp(filename, "-")) { 1327145510Sdarrenr fp = fopen(filename, "r"); 1328145510Sdarrenr if (!fp) { 1329255332Scy FPRINTF(stderr, "fopen(%s) failed: %s\n", filename, 1330145510Sdarrenr STRERROR(errno)); 1331145510Sdarrenr return -1; 1332145510Sdarrenr } 1333145510Sdarrenr } else 1334145510Sdarrenr fp = stdin; 1335145510Sdarrenr 1336255332Scy while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0) 1337145510Sdarrenr ; 1338145510Sdarrenr if (fp != NULL) 1339145510Sdarrenr fclose(fp); 1340255332Scy if (rval == -1) 1341255332Scy rval = 0; 1342255332Scy else if (rval != 0) 1343255332Scy rval = 1; 1344255332Scy return rval; 1345145510Sdarrenr} 1346145510Sdarrenr 1347145510Sdarrenr 1348255332Scyint 1349255332Scyipnat_parsesome(fd, addfunc, ioctlfunc, fp) 1350255332Scy int fd; 1351255332Scy addfunc_t addfunc; 1352255332Scy ioctlfunc_t ioctlfunc; 1353255332Scy FILE *fp; 1354145510Sdarrenr{ 1355145510Sdarrenr char *s; 1356145510Sdarrenr int i; 1357145510Sdarrenr 1358145510Sdarrenr natfd = fd; 1359255332Scy parser_error = 0; 1360145510Sdarrenr nataddfunc = addfunc; 1361145510Sdarrenr natioctlfunc = ioctlfunc; 1362145510Sdarrenr 1363145510Sdarrenr if (feof(fp)) 1364255332Scy return -1; 1365145510Sdarrenr i = fgetc(fp); 1366145510Sdarrenr if (i == EOF) 1367255332Scy return -1; 1368145510Sdarrenr if (ungetc(i, fp) == EOF) 1369255332Scy return -1; 1370145510Sdarrenr if (feof(fp)) 1371255332Scy return -1; 1372145510Sdarrenr s = getenv("YYDEBUG"); 1373145510Sdarrenr if (s) 1374145510Sdarrenr yydebug = atoi(s); 1375145510Sdarrenr else 1376145510Sdarrenr yydebug = 0; 1377145510Sdarrenr 1378145510Sdarrenr yyin = fp; 1379145510Sdarrenr yyparse(); 1380255332Scy return parser_error; 1381145510Sdarrenr} 1382145510Sdarrenr 1383145510Sdarrenr 1384255332Scystatic void 1385255332Scynewnatrule() 1386145510Sdarrenr{ 1387145510Sdarrenr ipnat_t *n; 1388145510Sdarrenr 1389145510Sdarrenr n = calloc(1, sizeof(*n)); 1390145510Sdarrenr if (n == NULL) 1391145510Sdarrenr return; 1392145510Sdarrenr 1393255332Scy if (nat == NULL) { 1394145510Sdarrenr nattop = nat = n; 1395255332Scy n->in_pnext = &nattop; 1396255332Scy } else { 1397145510Sdarrenr nat->in_next = n; 1398255332Scy n->in_pnext = &nat->in_next; 1399145510Sdarrenr nat = n; 1400145510Sdarrenr } 1401161357Sguido 1402255332Scy n->in_flineno = yylineNum; 1403255332Scy n->in_ifnames[0] = -1; 1404255332Scy n->in_ifnames[1] = -1; 1405255332Scy n->in_plabel = -1; 1406255332Scy n->in_pconfig = -1; 1407255332Scy n->in_size = sizeof(*n); 1408255332Scy 1409161357Sguido suggest_port = 0; 1410145510Sdarrenr} 1411145510Sdarrenr 1412145510Sdarrenr 1413255332Scystatic void 1414255332Scysetnatproto(p) 1415255332Scy int p; 1416145510Sdarrenr{ 1417255332Scy nat->in_pr[0] = p; 1418255332Scy nat->in_pr[1] = p; 1419145510Sdarrenr 1420145510Sdarrenr switch (p) 1421145510Sdarrenr { 1422145510Sdarrenr case IPPROTO_TCP : 1423145510Sdarrenr nat->in_flags |= IPN_TCP; 1424145510Sdarrenr nat->in_flags &= ~IPN_UDP; 1425145510Sdarrenr break; 1426145510Sdarrenr case IPPROTO_UDP : 1427145510Sdarrenr nat->in_flags |= IPN_UDP; 1428145510Sdarrenr nat->in_flags &= ~IPN_TCP; 1429145510Sdarrenr break; 1430145510Sdarrenr case IPPROTO_ICMP : 1431145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1432255332Scy if (!(nat->in_flags & IPN_ICMPQUERY) && 1433255332Scy !(nat->in_redir & NAT_DIVERTUDP)) { 1434145510Sdarrenr nat->in_dcmp = 0; 1435145510Sdarrenr nat->in_scmp = 0; 1436255332Scy nat->in_dpmin = 0; 1437255332Scy nat->in_dpmax = 0; 1438255332Scy nat->in_dpnext = 0; 1439255332Scy nat->in_spmin = 0; 1440255332Scy nat->in_spmax = 0; 1441255332Scy nat->in_spnext = 0; 1442145510Sdarrenr } 1443145510Sdarrenr break; 1444145510Sdarrenr default : 1445145510Sdarrenr if ((nat->in_redir & NAT_MAPBLK) == 0) { 1446145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 1447145510Sdarrenr nat->in_dcmp = 0; 1448145510Sdarrenr nat->in_scmp = 0; 1449255332Scy nat->in_dpmin = 0; 1450255332Scy nat->in_dpmax = 0; 1451255332Scy nat->in_dpnext = 0; 1452255332Scy nat->in_spmin = 0; 1453255332Scy nat->in_spmax = 0; 1454255332Scy nat->in_spnext = 0; 1455145510Sdarrenr } 1456145510Sdarrenr break; 1457145510Sdarrenr } 1458145510Sdarrenr 1459255332Scy if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) { 1460255332Scy nat->in_stop = 0; 1461255332Scy nat->in_dtop = 0; 1462255332Scy nat->in_osport = 0; 1463255332Scy nat->in_odport = 0; 1464255332Scy nat->in_stop = 0; 1465255332Scy nat->in_osport = 0; 1466255332Scy nat->in_dtop = 0; 1467255332Scy nat->in_odport = 0; 1468255332Scy } 1469145510Sdarrenr if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) 1470145510Sdarrenr nat->in_flags &= ~IPN_FIXEDDPORT; 1471145510Sdarrenr} 1472145510Sdarrenr 1473145510Sdarrenr 1474255332Scyint 1475255332Scyipnat_addrule(fd, ioctlfunc, ptr) 1476255332Scy int fd; 1477255332Scy ioctlfunc_t ioctlfunc; 1478255332Scy void *ptr; 1479145510Sdarrenr{ 1480145510Sdarrenr ioctlcmd_t add, del; 1481145510Sdarrenr ipfobj_t obj; 1482145510Sdarrenr ipnat_t *ipn; 1483145510Sdarrenr 1484145510Sdarrenr ipn = ptr; 1485145510Sdarrenr bzero((char *)&obj, sizeof(obj)); 1486145510Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 1487255332Scy obj.ipfo_size = ipn->in_size; 1488145510Sdarrenr obj.ipfo_type = IPFOBJ_IPNAT; 1489145510Sdarrenr obj.ipfo_ptr = ptr; 1490145510Sdarrenr 1491145510Sdarrenr if ((opts & OPT_DONOTHING) != 0) 1492145510Sdarrenr fd = -1; 1493145510Sdarrenr 1494145510Sdarrenr if (opts & OPT_ZERORULEST) { 1495145510Sdarrenr add = SIOCZRLST; 1496255332Scy del = 0; 1497255332Scy } else if (opts & OPT_PURGE) { 1498255332Scy add = 0; 1499255332Scy del = SIOCPURGENAT; 1500145510Sdarrenr } else { 1501145510Sdarrenr add = SIOCADNAT; 1502145510Sdarrenr del = SIOCRMNAT; 1503145510Sdarrenr } 1504145510Sdarrenr 1505161357Sguido if ((opts & OPT_VERBOSE) != 0) 1506145510Sdarrenr printnat(ipn, opts); 1507145510Sdarrenr 1508145510Sdarrenr if (opts & OPT_DEBUG) 1509145510Sdarrenr binprint(ipn, sizeof(*ipn)); 1510145510Sdarrenr 1511145510Sdarrenr if ((opts & OPT_ZERORULEST) != 0) { 1512145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1513145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1514255332Scy char msg[80]; 1515255332Scy 1516255332Scy sprintf(msg, "%d:ioctl(zero nat rule)", 1517255332Scy ipn->in_flineno); 1518255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1519145510Sdarrenr } 1520145510Sdarrenr } else { 1521255332Scy PRINTF("hits %lu ", ipn->in_hits); 1522255332Scy#ifdef USE_QUAD_T 1523255332Scy PRINTF("bytes %"PRIu64" ", 1524255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1525145510Sdarrenr#else 1526255332Scy PRINTF("bytes %lu ", 1527255332Scy ipn->in_bytes[0] + ipn->in_bytes[1]); 1528145510Sdarrenr#endif 1529145510Sdarrenr printnat(ipn, opts); 1530145510Sdarrenr } 1531145510Sdarrenr } else if ((opts & OPT_REMOVE) != 0) { 1532145510Sdarrenr if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 1533145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1534255332Scy char msg[80]; 1535255332Scy 1536255332Scy sprintf(msg, "%d:ioctl(delete nat rule)", 1537255332Scy ipn->in_flineno); 1538255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1539145510Sdarrenr } 1540145510Sdarrenr } 1541145510Sdarrenr } else { 1542145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 1543145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 1544255332Scy char msg[80]; 1545255332Scy 1546255332Scy sprintf(msg, "%d:ioctl(add/insert nat rule)", 1547255332Scy ipn->in_flineno); 1548255332Scy if (errno == EEXIST) { 1549255332Scy sprintf(msg + strlen(msg), "(line %d)", 1550255332Scy ipn->in_flineno); 1551255332Scy } 1552255332Scy return ipf_perror_fd(fd, ioctlfunc, msg); 1553145510Sdarrenr } 1554145510Sdarrenr } 1555145510Sdarrenr } 1556255332Scy return 0; 1557145510Sdarrenr} 1558255332Scy 1559255332Scy 1560255332Scystatic void 1561255332Scysetmapifnames() 1562255332Scy{ 1563255332Scy if (nat->in_ifnames[1] == -1) 1564255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1565255332Scy 1566255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1567255332Scy nat->in_flags |= IPN_TCPUDP; 1568255332Scy 1569255332Scy if ((nat->in_flags & IPN_TCPUDP) == 0) 1570255332Scy setnatproto(nat->in_pr[1]); 1571255332Scy 1572255332Scy if (((nat->in_redir & NAT_MAPBLK) != 0) || 1573255332Scy ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 1574255332Scy nat_setgroupmap(nat); 1575255332Scy} 1576255332Scy 1577255332Scy 1578255332Scystatic void 1579255332Scysetrdrifnames() 1580255332Scy{ 1581255332Scy if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0) 1582255332Scy nat->in_flags |= IPN_TCPUDP; 1583255332Scy 1584255332Scy if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) && 1585255332Scy (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0)) 1586255332Scy setnatproto(IPPROTO_TCP); 1587255332Scy 1588255332Scy if (nat->in_ifnames[1] == -1) 1589255332Scy nat->in_ifnames[1] = nat->in_ifnames[0]; 1590255332Scy} 1591255332Scy 1592255332Scy 1593255332Scystatic void 1594255332Scyproxy_setconfig(proxy) 1595255332Scy int proxy; 1596255332Scy{ 1597255332Scy if (proxy == IPNY_DNS) { 1598255332Scy yysetfixeddict(dnswords); 1599255332Scy } 1600255332Scy} 1601255332Scy 1602255332Scy 1603255332Scystatic void 1604255332Scyproxy_unsetconfig() 1605255332Scy{ 1606255332Scy yyresetdict(); 1607255332Scy} 1608255332Scy 1609255332Scy 1610255332Scystatic namelist_t * 1611255332Scyproxy_dns_add_pass(prefix, name) 1612255332Scy char *prefix, *name; 1613255332Scy{ 1614255332Scy namelist_t *n; 1615255332Scy 1616255332Scy n = calloc(1, sizeof(*n)); 1617255332Scy if (n != NULL) { 1618255332Scy if (prefix == NULL || *prefix == '\0') { 1619255332Scy n->na_name = strdup(name); 1620255332Scy } else { 1621255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1622255332Scy strcpy(n->na_name, prefix); 1623255332Scy strcat(n->na_name, name); 1624255332Scy } 1625255332Scy } 1626255332Scy return n; 1627255332Scy} 1628255332Scy 1629255332Scy 1630255332Scystatic namelist_t * 1631255332Scyproxy_dns_add_block(prefix, name) 1632255332Scy char *prefix, *name; 1633255332Scy{ 1634255332Scy namelist_t *n; 1635255332Scy 1636255332Scy n = calloc(1, sizeof(*n)); 1637255332Scy if (n != NULL) { 1638255332Scy if (prefix == NULL || *prefix == '\0') { 1639255332Scy n->na_name = strdup(name); 1640255332Scy } else { 1641255332Scy n->na_name = malloc(strlen(name) + strlen(prefix) + 1); 1642255332Scy strcpy(n->na_name, prefix); 1643255332Scy strcat(n->na_name, name); 1644255332Scy } 1645255332Scy n->na_value = 1; 1646255332Scy } 1647255332Scy return n; 1648255332Scy} 1649255332Scy 1650255332Scy 1651255332Scystatic void 1652255332Scyproxy_addconfig(proxy, proto, conf, list) 1653255332Scy char *proxy, *conf; 1654255332Scy int proto; 1655255332Scy namelist_t *list; 1656255332Scy{ 1657255332Scy proxyrule_t *pr; 1658255332Scy 1659255332Scy pr = calloc(1, sizeof(*pr)); 1660255332Scy if (pr != NULL) { 1661255332Scy pr->pr_proto = proto; 1662255332Scy pr->pr_proxy = proxy; 1663255332Scy pr->pr_conf = conf; 1664255332Scy pr->pr_names = list; 1665255332Scy pr->pr_next = prules; 1666255332Scy prules = pr; 1667255332Scy } 1668255332Scy} 1669255332Scy 1670255332Scy 1671255332Scystatic void 1672255332Scyproxy_loadrules(fd, ioctlfunc, rules) 1673255332Scy int fd; 1674255332Scy ioctlfunc_t ioctlfunc; 1675255332Scy proxyrule_t *rules; 1676255332Scy{ 1677255332Scy proxyrule_t *pr; 1678255332Scy 1679255332Scy while ((pr = rules) != NULL) { 1680255332Scy proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto, 1681255332Scy pr->pr_conf, pr->pr_names); 1682255332Scy rules = pr->pr_next; 1683255332Scy free(pr->pr_conf); 1684255332Scy free(pr); 1685255332Scy } 1686255332Scy} 1687255332Scy 1688255332Scy 1689255332Scystatic void 1690255332Scyproxy_loadconfig(fd, ioctlfunc, proxy, proto, conf, list) 1691255332Scy int fd; 1692255332Scy ioctlfunc_t ioctlfunc; 1693255332Scy char *proxy, *conf; 1694255332Scy int proto; 1695255332Scy namelist_t *list; 1696255332Scy{ 1697255332Scy namelist_t *na; 1698255332Scy ipfobj_t obj; 1699255332Scy ap_ctl_t pcmd; 1700255332Scy 1701255332Scy obj.ipfo_rev = IPFILTER_VERSION; 1702255332Scy obj.ipfo_type = IPFOBJ_PROXYCTL; 1703255332Scy obj.ipfo_size = sizeof(pcmd); 1704255332Scy obj.ipfo_ptr = &pcmd; 1705255332Scy 1706255332Scy while ((na = list) != NULL) { 1707255332Scy if ((opts & OPT_REMOVE) != 0) 1708255332Scy pcmd.apc_cmd = APC_CMD_DEL; 1709255332Scy else 1710255332Scy pcmd.apc_cmd = APC_CMD_ADD; 1711255332Scy pcmd.apc_dsize = strlen(na->na_name) + 1; 1712255332Scy pcmd.apc_data = na->na_name; 1713255332Scy pcmd.apc_arg = na->na_value; 1714255332Scy pcmd.apc_p = proto; 1715255332Scy 1716255332Scy strncpy(pcmd.apc_label, proxy, APR_LABELLEN); 1717255332Scy pcmd.apc_label[APR_LABELLEN - 1] = '\0'; 1718255332Scy 1719255332Scy strncpy(pcmd.apc_config, conf, APR_LABELLEN); 1720255332Scy pcmd.apc_config[APR_LABELLEN - 1] = '\0'; 1721255332Scy 1722255332Scy if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) { 1723255332Scy if ((opts & OPT_DONOTHING) == 0) { 1724255332Scy char msg[80]; 1725255332Scy 1726255332Scy sprintf(msg, "%d:ioctl(add/remove proxy rule)", 1727255332Scy yylineNum); 1728255332Scy ipf_perror_fd(fd, ioctlfunc, msg); 1729255332Scy return; 1730255332Scy } 1731255332Scy } 1732255332Scy 1733255332Scy list = na->na_next; 1734255332Scy free(na->na_name); 1735255332Scy free(na); 1736255332Scy } 1737255332Scy} 1738255332Scy 1739255332Scy 1740255332Scystatic void 1741255332Scysetifname(np, idx, name) 1742255332Scy ipnat_t **np; 1743255332Scy int idx; 1744255332Scy char *name; 1745255332Scy{ 1746255332Scy int pos; 1747255332Scy 1748255332Scy pos = addname(np, name); 1749255332Scy if (pos == -1) 1750255332Scy return; 1751255332Scy (*np)->in_ifnames[idx] = pos; 1752255332Scy} 1753255332Scy 1754255332Scy 1755255332Scystatic int 1756255332Scyaddname(np, name) 1757255332Scy ipnat_t **np; 1758255332Scy char *name; 1759255332Scy{ 1760255332Scy ipnat_t *n; 1761255332Scy int nlen; 1762255332Scy int pos; 1763255332Scy 1764255332Scy nlen = strlen(name) + 1; 1765255332Scy n = realloc(*np, (*np)->in_size + nlen); 1766255332Scy if (*np == nattop) 1767255332Scy nattop = n; 1768255332Scy *np = n; 1769255332Scy if (n == NULL) 1770255332Scy return -1; 1771255332Scy if (n->in_pnext != NULL) 1772255332Scy *n->in_pnext = n; 1773255332Scy n->in_size += nlen; 1774255332Scy pos = n->in_namelen; 1775255332Scy n->in_namelen += nlen; 1776255332Scy strcpy(n->in_names + pos, name); 1777255332Scy n->in_names[n->in_namelen] = '\0'; 1778255332Scy return pos; 1779255332Scy} 1780