ipnat_y.y revision 170268
1145519Sdarrenr/* $FreeBSD: head/contrib/ipfilter/tools/ipnat_y.y 170268 2007-06-04 02:54:36Z darrenr $ */ 2145510Sdarrenr 3170268Sdarrenr/* 4170268Sdarrenr * Copyright (C) 2001-2006 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; 63145510Sdarrenr 64145510Sdarrenrstatic void newnatrule __P((void)); 65145510Sdarrenrstatic void setnatproto __P((int)); 66145510Sdarrenr 67145510Sdarrenr%} 68145510Sdarrenr%union { 69145510Sdarrenr char *str; 70145510Sdarrenr u_32_t num; 71145510Sdarrenr struct in_addr ipa; 72145510Sdarrenr frentry_t fr; 73145510Sdarrenr frtuc_t *frt; 74145510Sdarrenr u_short port; 75145510Sdarrenr struct { 76145510Sdarrenr u_short p1; 77145510Sdarrenr u_short p2; 78145510Sdarrenr int pc; 79145510Sdarrenr } pc; 80145510Sdarrenr struct { 81145510Sdarrenr struct in_addr a; 82145510Sdarrenr struct in_addr m; 83145510Sdarrenr } ipp; 84145510Sdarrenr union i6addr ip6; 85145510Sdarrenr}; 86145510Sdarrenr 87145510Sdarrenr%token <num> YY_NUMBER YY_HEX 88145510Sdarrenr%token <str> YY_STR 89145510Sdarrenr%token YY_COMMENT 90145510Sdarrenr%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 91145510Sdarrenr%token YY_RANGE_OUT YY_RANGE_IN 92145510Sdarrenr%token <ip6> YY_IPV6 93145510Sdarrenr 94145510Sdarrenr%token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE 95145510Sdarrenr%token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY 96145510Sdarrenr%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY 97145510Sdarrenr%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG 98145510Sdarrenr%token IPNY_TLATE 99145510Sdarrenr%type <port> portspec 100145510Sdarrenr%type <num> hexnumber compare range proto 101145510Sdarrenr%type <ipa> hostname ipv4 102145510Sdarrenr%type <ipp> addr nummask rhaddr 103145510Sdarrenr%type <pc> portstuff 104145510Sdarrenr%% 105145510Sdarrenrfile: line 106145510Sdarrenr | assign 107145510Sdarrenr | file line 108145510Sdarrenr | file assign 109145510Sdarrenr ; 110145510Sdarrenr 111145510Sdarrenrline: xx rule { while ((nat = nattop) != NULL) { 112145510Sdarrenr nattop = nat->in_next; 113145510Sdarrenr (*nataddfunc)(natfd, natioctlfunc, nat); 114145510Sdarrenr free(nat); 115145510Sdarrenr } 116145510Sdarrenr resetlexer(); 117145510Sdarrenr } 118145510Sdarrenr | YY_COMMENT 119145510Sdarrenr ; 120145510Sdarrenr 121145510Sdarrenrassign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 122145510Sdarrenr resetlexer(); 123145510Sdarrenr free($1); 124145510Sdarrenr free($3); 125170268Sdarrenr yyvarnext = 0; 126145510Sdarrenr } 127145510Sdarrenr ; 128145510Sdarrenr 129145510Sdarrenrassigning: 130145510Sdarrenr '=' { yyvarnext = 1; } 131145510Sdarrenr ; 132145510Sdarrenr 133145510Sdarrenrxx: { newnatrule(); } 134145510Sdarrenr ; 135145510Sdarrenr 136145510Sdarrenrrule: map eol 137145510Sdarrenr | mapblock eol 138145510Sdarrenr | redir eol 139145510Sdarrenr ; 140145510Sdarrenr 141145510Sdarrenreol: | ';' 142145510Sdarrenr ; 143145510Sdarrenr 144145510Sdarrenrmap: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions 145145510Sdarrenr { nat->in_v = 4; 146145510Sdarrenr nat->in_inip = $3.a.s_addr; 147145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 148145510Sdarrenr nat->in_outip = $5.a.s_addr; 149145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 150145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 151145510Sdarrenr strncpy(nat->in_ifnames[1], 152145510Sdarrenr nat->in_ifnames[0], 153145510Sdarrenr sizeof(nat->in_ifnames[0])); 154145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 155145510Sdarrenr setnatproto(nat->in_p); 156145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 157145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 158145510Sdarrenr nat_setgroupmap(nat); 159145510Sdarrenr } 160145510Sdarrenr | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions 161145510Sdarrenr { nat->in_v = 4; 162145510Sdarrenr nat->in_inip = $3.a.s_addr; 163145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 164145510Sdarrenr nat->in_outip = $5.a.s_addr; 165145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 166145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 167145510Sdarrenr strncpy(nat->in_ifnames[1], 168145510Sdarrenr nat->in_ifnames[0], 169145510Sdarrenr sizeof(nat->in_ifnames[0])); 170145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 171145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 172145510Sdarrenr nat_setgroupmap(nat); 173145510Sdarrenr } 174145510Sdarrenr | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions 175145510Sdarrenr { nat->in_v = 4; 176145510Sdarrenr nat->in_outip = $5.a.s_addr; 177145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 178145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 179145510Sdarrenr strncpy(nat->in_ifnames[1], 180145510Sdarrenr nat->in_ifnames[0], 181145510Sdarrenr sizeof(nat->in_ifnames[0])); 182161357Sguido if ((suggest_port == 1) && 183161357Sguido (nat->in_flags & IPN_TCPUDP) == 0) 184161357Sguido nat->in_flags |= IPN_TCPUDP; 185145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 186145510Sdarrenr setnatproto(nat->in_p); 187145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 188145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 189145510Sdarrenr nat_setgroupmap(nat); 190145510Sdarrenr } 191145510Sdarrenr | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions 192145510Sdarrenr { nat->in_v = 4; 193145510Sdarrenr nat->in_outip = $5.a.s_addr; 194145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 195145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 196145510Sdarrenr strncpy(nat->in_ifnames[1], 197145510Sdarrenr nat->in_ifnames[0], 198145510Sdarrenr sizeof(nat->in_ifnames[0])); 199161357Sguido if ((suggest_port == 1) && 200161357Sguido (nat->in_flags & IPN_TCPUDP) == 0) 201161357Sguido nat->in_flags |= IPN_TCPUDP; 202145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 203145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 204145510Sdarrenr nat_setgroupmap(nat); 205145510Sdarrenr } 206145510Sdarrenr ; 207145510Sdarrenr 208145510Sdarrenrmapblock: 209145510Sdarrenr mapblockit ifnames addr IPNY_TLATE addr ports mapoptions 210145510Sdarrenr { nat->in_v = 4; 211145510Sdarrenr nat->in_inip = $3.a.s_addr; 212145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 213145510Sdarrenr nat->in_outip = $5.a.s_addr; 214145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 215145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 216145510Sdarrenr strncpy(nat->in_ifnames[1], 217145510Sdarrenr nat->in_ifnames[0], 218145510Sdarrenr sizeof(nat->in_ifnames[0])); 219145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 220145510Sdarrenr setnatproto(nat->in_p); 221145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 222145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 223145510Sdarrenr nat_setgroupmap(nat); 224145510Sdarrenr } 225145510Sdarrenr ; 226145510Sdarrenr 227145510Sdarrenrredir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions 228145510Sdarrenr { nat->in_v = 4; 229145510Sdarrenr nat->in_outip = $3.a.s_addr; 230145510Sdarrenr nat->in_outmsk = $3.m.s_addr; 231145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 232145510Sdarrenr strncpy(nat->in_ifnames[1], 233145510Sdarrenr nat->in_ifnames[0], 234145510Sdarrenr sizeof(nat->in_ifnames[0])); 235145510Sdarrenr if ((nat->in_p == 0) && 236145510Sdarrenr ((nat->in_flags & IPN_TCPUDP) == 0) && 237145510Sdarrenr (nat->in_pmin != 0 || 238145510Sdarrenr nat->in_pmax != 0 || 239145510Sdarrenr nat->in_pnext != 0)) 240161357Sguido setnatproto(IPPROTO_TCP); 241145510Sdarrenr } 242145510Sdarrenr | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions 243145510Sdarrenr { nat->in_v = 4; 244145510Sdarrenr if ((nat->in_p == 0) && 245145510Sdarrenr ((nat->in_flags & IPN_TCPUDP) == 0) && 246145510Sdarrenr (nat->in_pmin != 0 || 247145510Sdarrenr nat->in_pmax != 0 || 248145510Sdarrenr nat->in_pnext != 0)) 249145510Sdarrenr setnatproto(IPPROTO_TCP); 250161357Sguido if ((suggest_port == 1) && 251161357Sguido (nat->in_flags & IPN_TCPUDP) == 0) 252161357Sguido nat->in_flags |= IPN_TCPUDP; 253145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 254145510Sdarrenr strncpy(nat->in_ifnames[1], 255145510Sdarrenr nat->in_ifnames[0], 256145510Sdarrenr sizeof(nat->in_ifnames[0])); 257145510Sdarrenr } 258145510Sdarrenr | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions 259145510Sdarrenr { nat->in_v = 4; 260145510Sdarrenr nat->in_outip = $3.a.s_addr; 261145510Sdarrenr nat->in_outmsk = $3.m.s_addr; 262145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 263145510Sdarrenr strncpy(nat->in_ifnames[1], 264145510Sdarrenr nat->in_ifnames[0], 265145510Sdarrenr sizeof(nat->in_ifnames[0])); 266145510Sdarrenr } 267161357Sguido | rdrit ifnames rdrfrom IPNY_TLATE dip setproto rdroptions 268161357Sguido { nat->in_v = 4; 269161357Sguido if ((suggest_port == 1) && 270161357Sguido (nat->in_flags & IPN_TCPUDP) == 0) 271161357Sguido nat->in_flags |= IPN_TCPUDP; 272161357Sguido if (nat->in_ifnames[1][0] == '\0') 273161357Sguido strncpy(nat->in_ifnames[1], 274161357Sguido nat->in_ifnames[0], 275161357Sguido sizeof(nat->in_ifnames[0])); 276161357Sguido } 277145510Sdarrenr ; 278145510Sdarrenr 279161357Sguidoproxy: | IPNY_PROXY port portspec YY_STR '/' proto 280145510Sdarrenr { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); 281145510Sdarrenr if (nat->in_dcmp == 0) { 282145510Sdarrenr nat->in_dport = htons($3); 283145510Sdarrenr } else if ($3 != nat->in_dport) { 284145510Sdarrenr yyerror("proxy port numbers not consistant"); 285145510Sdarrenr } 286145510Sdarrenr setnatproto($6); 287145510Sdarrenr free($4); 288145510Sdarrenr } 289161357Sguido | IPNY_PROXY port YY_STR YY_STR '/' proto 290145510Sdarrenr { int pnum; 291145510Sdarrenr strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); 292145510Sdarrenr pnum = getportproto($3, $6); 293145510Sdarrenr if (pnum == -1) 294145510Sdarrenr yyerror("invalid port number"); 295145510Sdarrenr nat->in_dport = pnum; 296145510Sdarrenr setnatproto($6); 297145510Sdarrenr free($3); 298145510Sdarrenr free($4); 299145510Sdarrenr } 300145510Sdarrenr ; 301145510Sdarrenr 302145510Sdarrenrsetproto: 303145510Sdarrenr | proto { if (nat->in_p != 0 || 304145510Sdarrenr nat->in_flags & IPN_TCPUDP) 305145510Sdarrenr yyerror("protocol set twice"); 306145510Sdarrenr setnatproto($1); 307145510Sdarrenr } 308145510Sdarrenr | IPNY_TCPUDP { if (nat->in_p != 0 || 309145510Sdarrenr nat->in_flags & IPN_TCPUDP) 310145510Sdarrenr yyerror("protocol set twice"); 311145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 312145510Sdarrenr nat->in_p = 0; 313145510Sdarrenr } 314145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 || 315145510Sdarrenr nat->in_flags & IPN_TCPUDP) 316145510Sdarrenr yyerror("protocol set twice"); 317145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 318145510Sdarrenr nat->in_p = 0; 319145510Sdarrenr } 320145510Sdarrenr ; 321145510Sdarrenr 322145510Sdarrenrrhaddr: addr { $$.a = $1.a; $$.m = $1.m; } 323145510Sdarrenr | IPNY_RANGE ipv4 '-' ipv4 324145510Sdarrenr { $$.a = $2; $$.m = $4; 325145510Sdarrenr nat->in_flags |= IPN_IPRANGE; } 326145510Sdarrenr ; 327145510Sdarrenr 328145510Sdarrenrdip: 329145510Sdarrenr hostname { nat->in_inip = $1.s_addr; 330145510Sdarrenr nat->in_inmsk = 0xffffffff; } 331153881Sguido | hostname '/' YY_NUMBER { if ($3 != 0 || $1.s_addr != 0) 332153881Sguido yyerror("Only 0/0 supported"); 333153881Sguido nat->in_inip = 0; 334153881Sguido nat->in_inmsk = 0; 335153881Sguido } 336145510Sdarrenr | hostname ',' hostname { nat->in_flags |= IPN_SPLIT; 337145510Sdarrenr nat->in_inip = $1.s_addr; 338145510Sdarrenr nat->in_inmsk = $3.s_addr; } 339145510Sdarrenr ; 340145510Sdarrenr 341161357Sguidoport: IPNY_PORT { suggest_port = 1; } 342161357Sguido ; 343161357Sguido 344145510Sdarrenrportspec: 345145510Sdarrenr YY_NUMBER { if ($1 > 65535) /* Unsigned */ 346145510Sdarrenr yyerror("invalid port number"); 347145510Sdarrenr else 348145510Sdarrenr $$ = $1; 349145510Sdarrenr } 350145510Sdarrenr | YY_STR { if (getport(NULL, $1, &($$)) == -1) 351145510Sdarrenr yyerror("invalid port number"); 352145510Sdarrenr $$ = ntohs($$); 353145510Sdarrenr } 354145510Sdarrenr ; 355145510Sdarrenr 356161357Sguidodport: | port portspec { nat->in_pmin = htons($2); 357170268Sdarrenr nat->in_pmax = htons($2); } 358161357Sguido | port portspec '-' portspec { nat->in_pmin = htons($2); 359170268Sdarrenr nat->in_pmax = htons($4); } 360161357Sguido | port portspec ':' portspec { nat->in_pmin = htons($2); 361170268Sdarrenr nat->in_pmax = htons($4); } 362145510Sdarrenr ; 363145510Sdarrenr 364161357Sguidonport: port portspec { nat->in_pnext = htons($2); } 365161357Sguido | port '=' portspec { nat->in_pnext = htons($3); 366145510Sdarrenr nat->in_flags |= IPN_FIXEDDPORT; 367145510Sdarrenr } 368145510Sdarrenr ; 369145510Sdarrenr 370145510Sdarrenrports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; } 371145510Sdarrenr | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } 372145510Sdarrenr ; 373145510Sdarrenr 374145510Sdarrenrmapit: IPNY_MAP { nat->in_redir = NAT_MAP; } 375145510Sdarrenr | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; } 376145510Sdarrenr ; 377145510Sdarrenr 378145510Sdarrenrrdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; } 379145510Sdarrenr ; 380145510Sdarrenr 381145510Sdarrenrmapblockit: 382145510Sdarrenr IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; } 383145510Sdarrenr ; 384145510Sdarrenr 385145510Sdarrenrmapfrom: 386145510Sdarrenr from sobject IPNY_TO dobject 387145510Sdarrenr | from sobject '!' IPNY_TO dobject 388145510Sdarrenr { nat->in_flags |= IPN_NOTDST; } 389161357Sguido | from sobject IPNY_TO '!' dobject 390161357Sguido { nat->in_flags |= IPN_NOTDST; } 391145510Sdarrenr ; 392145510Sdarrenr 393145510Sdarrenrrdrfrom: 394145510Sdarrenr from sobject IPNY_TO dobject 395145510Sdarrenr | '!' from sobject IPNY_TO dobject 396145510Sdarrenr { nat->in_flags |= IPN_NOTSRC; } 397161357Sguido | from '!' sobject IPNY_TO dobject 398161357Sguido { nat->in_flags |= IPN_NOTSRC; } 399145510Sdarrenr ; 400145510Sdarrenr 401145510Sdarrenrfrom: IPNY_FROM { nat->in_flags |= IPN_FILTER; } 402145510Sdarrenr ; 403145510Sdarrenr 404145510Sdarrenrifnames: 405145510Sdarrenr ifname 406145510Sdarrenr | ifname ',' otherifname 407145510Sdarrenr ; 408145510Sdarrenr 409145510Sdarrenrifname: YY_STR { strncpy(nat->in_ifnames[0], $1, 410145510Sdarrenr sizeof(nat->in_ifnames[0])); 411145510Sdarrenr nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; 412145510Sdarrenr free($1); 413145510Sdarrenr } 414145510Sdarrenr ; 415145510Sdarrenr 416145510Sdarrenrotherifname: 417145510Sdarrenr YY_STR { strncpy(nat->in_ifnames[1], $1, 418145510Sdarrenr sizeof(nat->in_ifnames[1])); 419145510Sdarrenr nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; 420145510Sdarrenr free($1); 421145510Sdarrenr } 422145510Sdarrenr ; 423145510Sdarrenr 424145510Sdarrenrmapport: 425145510Sdarrenr IPNY_PORTMAP tcpudp portspec ':' portspec 426145510Sdarrenr { nat->in_pmin = htons($3); 427145510Sdarrenr nat->in_pmax = htons($5); 428145510Sdarrenr } 429145510Sdarrenr | IPNY_PORTMAP tcpudp IPNY_AUTO 430145510Sdarrenr { nat->in_flags |= IPN_AUTOPORTMAP; 431145510Sdarrenr nat->in_pmin = htons(1024); 432145510Sdarrenr nat->in_pmax = htons(65535); 433145510Sdarrenr } 434145510Sdarrenr | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER 435145510Sdarrenr { if (strcmp($2, "icmp") != 0) { 436145510Sdarrenr yyerror("icmpidmap not followed by icmp"); 437145510Sdarrenr } 438145510Sdarrenr free($2); 439145510Sdarrenr if ($3 < 0 || $3 > 65535) 440145510Sdarrenr yyerror("invalid ICMP Id number"); 441145510Sdarrenr if ($5 < 0 || $5 > 65535) 442145510Sdarrenr yyerror("invalid ICMP Id number"); 443145510Sdarrenr nat->in_flags = IPN_ICMPQUERY; 444145510Sdarrenr nat->in_pmin = htons($3); 445145510Sdarrenr nat->in_pmax = htons($5); 446145510Sdarrenr } 447145510Sdarrenr ; 448145510Sdarrenr 449145510Sdarrenrsobject: 450145510Sdarrenr saddr 451161357Sguido | saddr port portstuff { nat->in_sport = $3.p1; 452145510Sdarrenr nat->in_stop = $3.p2; 453145510Sdarrenr nat->in_scmp = $3.pc; } 454145510Sdarrenr ; 455145510Sdarrenr 456145510Sdarrenrsaddr: addr { if (nat->in_redir == NAT_REDIRECT) { 457145510Sdarrenr nat->in_srcip = $1.a.s_addr; 458145510Sdarrenr nat->in_srcmsk = $1.m.s_addr; 459145510Sdarrenr } else { 460145510Sdarrenr nat->in_inip = $1.a.s_addr; 461145510Sdarrenr nat->in_inmsk = $1.m.s_addr; 462145510Sdarrenr } 463145510Sdarrenr } 464145510Sdarrenr ; 465145510Sdarrenr 466145510Sdarrenrdobject: 467145510Sdarrenr daddr 468161357Sguido | daddr port portstuff { nat->in_dport = $3.p1; 469145510Sdarrenr nat->in_dtop = $3.p2; 470145510Sdarrenr nat->in_dcmp = $3.pc; 471145510Sdarrenr if (nat->in_redir == NAT_REDIRECT) 472145510Sdarrenr nat->in_pmin = htons($3.p1); 473145510Sdarrenr } 474145510Sdarrenr ; 475145510Sdarrenr 476145510Sdarrenrdaddr: addr { if (nat->in_redir == NAT_REDIRECT) { 477145510Sdarrenr nat->in_outip = $1.a.s_addr; 478145510Sdarrenr nat->in_outmsk = $1.m.s_addr; 479145510Sdarrenr } else { 480145510Sdarrenr nat->in_srcip = $1.a.s_addr; 481145510Sdarrenr nat->in_srcmsk = $1.m.s_addr; 482145510Sdarrenr } 483145510Sdarrenr } 484145510Sdarrenr ; 485145510Sdarrenr 486145510Sdarrenraddr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; } 487145510Sdarrenr | nummask { $$.a = $1.a; $$.m = $1.m; 488145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 489145510Sdarrenr | hostname '/' ipv4 { $$.a = $1; $$.m = $3; 490145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 491153881Sguido | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); 492145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 493145510Sdarrenr | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3; 494145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 495153881Sguido | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); 496145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 497145510Sdarrenr ; 498145510Sdarrenr 499145510Sdarrenrnummask: 500145510Sdarrenr hostname { $$.a = $1; 501145510Sdarrenr $$.m.s_addr = 0xffffffff; } 502145510Sdarrenr | hostname '/' YY_NUMBER { $$.a = $1; 503145510Sdarrenr ntomask(4, $3, &$$.m.s_addr); } 504145510Sdarrenr ; 505145510Sdarrenr 506145510Sdarrenrportstuff: 507145510Sdarrenr compare portspec { $$.pc = $1; $$.p1 = $2; } 508153881Sguido | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } 509145510Sdarrenr ; 510145510Sdarrenr 511145510Sdarrenrmapoptions: 512145510Sdarrenr rr frag age mssclamp nattag setproto 513145510Sdarrenr ; 514145510Sdarrenr 515145510Sdarrenrrdroptions: 516145510Sdarrenr rr frag age sticky mssclamp rdrproxy nattag 517145510Sdarrenr ; 518145510Sdarrenr 519145510Sdarrenrnattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, 520145510Sdarrenr sizeof(nat->in_tag.ipt_tag)); 521145510Sdarrenr } 522145510Sdarrenrrr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; } 523145510Sdarrenr ; 524145510Sdarrenr 525145510Sdarrenrfrag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; } 526145510Sdarrenr ; 527145510Sdarrenr 528145510Sdarrenrage: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; 529145510Sdarrenr nat->in_age[1] = $2; } 530145510Sdarrenr | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2; 531145510Sdarrenr nat->in_age[1] = $4; } 532145510Sdarrenr ; 533145510Sdarrenr 534145510Sdarrenrsticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && 535145510Sdarrenr !(nat->in_flags & IPN_SPLIT)) { 536145510Sdarrenr fprintf(stderr, 537145510Sdarrenr "'sticky' for use with round-robin/IP splitting only\n"); 538145510Sdarrenr } else 539145510Sdarrenr nat->in_flags |= IPN_STICKY; 540145510Sdarrenr } 541145510Sdarrenr ; 542145510Sdarrenr 543145510Sdarrenrmssclamp: 544145510Sdarrenr | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } 545145510Sdarrenr ; 546145510Sdarrenr 547145510Sdarrenrtcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); } 548145510Sdarrenr | IPNY_UDP { setnatproto(IPPROTO_UDP); } 549145510Sdarrenr | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; 550145510Sdarrenr nat->in_p = 0; 551145510Sdarrenr } 552145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; 553145510Sdarrenr nat->in_p = 0; 554145510Sdarrenr } 555145510Sdarrenr ; 556145510Sdarrenr 557145510Sdarrenrrdrproxy: 558145510Sdarrenr IPNY_PROXY YY_STR 559145510Sdarrenr { strncpy(nat->in_plabel, $2, 560145510Sdarrenr sizeof(nat->in_plabel)); 561145510Sdarrenr nat->in_dport = nat->in_pnext; 562145510Sdarrenr nat->in_dport = htons(nat->in_dport); 563145510Sdarrenr free($2); 564145510Sdarrenr } 565145510Sdarrenr | proxy { if (nat->in_plabel[0] != '\0') { 566145510Sdarrenr nat->in_pmin = nat->in_dport; 567145510Sdarrenr nat->in_pmax = nat->in_pmin; 568145510Sdarrenr nat->in_pnext = nat->in_pmin; 569145510Sdarrenr } 570145510Sdarrenr } 571145510Sdarrenr ; 572145510Sdarrenr 573161357Sguidoproto: YY_NUMBER { $$ = $1; 574161357Sguido if ($$ != IPPROTO_TCP && 575161357Sguido $$ != IPPROTO_UDP) 576161357Sguido suggest_port = 0; 577161357Sguido } 578145510Sdarrenr | IPNY_TCP { $$ = IPPROTO_TCP; } 579145510Sdarrenr | IPNY_UDP { $$ = IPPROTO_UDP; } 580161357Sguido | YY_STR { $$ = getproto($1); free($1); 581161357Sguido if ($$ != IPPROTO_TCP && 582161357Sguido $$ != IPPROTO_UDP) 583161357Sguido suggest_port = 0; 584161357Sguido } 585145510Sdarrenr ; 586145510Sdarrenr 587145510Sdarrenrhexnumber: 588145510Sdarrenr YY_HEX { $$ = $1; } 589145510Sdarrenr ; 590145510Sdarrenr 591145510Sdarrenrhostname: 592145510Sdarrenr YY_STR { if (gethost($1, &$$.s_addr) == -1) 593145510Sdarrenr fprintf(stderr, 594145510Sdarrenr "Unknown host '%s'\n", 595145510Sdarrenr $1); 596145510Sdarrenr free($1); 597145510Sdarrenr } 598145510Sdarrenr | YY_NUMBER { $$.s_addr = htonl($1); } 599145510Sdarrenr | ipv4 { $$.s_addr = $1.s_addr; } 600145510Sdarrenr ; 601145510Sdarrenr 602145510Sdarrenrcompare: 603145510Sdarrenr '=' { $$ = FR_EQUAL; } 604145510Sdarrenr | YY_CMP_EQ { $$ = FR_EQUAL; } 605145510Sdarrenr | YY_CMP_NE { $$ = FR_NEQUAL; } 606145510Sdarrenr | YY_CMP_LT { $$ = FR_LESST; } 607145510Sdarrenr | YY_CMP_LE { $$ = FR_LESSTE; } 608145510Sdarrenr | YY_CMP_GT { $$ = FR_GREATERT; } 609145510Sdarrenr | YY_CMP_GE { $$ = FR_GREATERTE; } 610145510Sdarrenr 611145510Sdarrenrrange: 612145510Sdarrenr YY_RANGE_OUT { $$ = FR_OUTRANGE; } 613145510Sdarrenr | YY_RANGE_IN { $$ = FR_INRANGE; } 614145510Sdarrenr ; 615145510Sdarrenr 616145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 617145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 618145510Sdarrenr yyerror("Invalid octet string for IP address"); 619145510Sdarrenr return 0; 620145510Sdarrenr } 621145510Sdarrenr $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 622145510Sdarrenr $$.s_addr = htonl($$.s_addr); 623145510Sdarrenr } 624145510Sdarrenr ; 625145510Sdarrenr 626145510Sdarrenr%% 627145510Sdarrenr 628145510Sdarrenr 629145510Sdarrenrstatic wordtab_t yywords[] = { 630145510Sdarrenr { "age", IPNY_AGE }, 631145510Sdarrenr { "any", IPNY_ANY }, 632145510Sdarrenr { "auto", IPNY_AUTO }, 633145510Sdarrenr { "bimap", IPNY_BIMAP }, 634145510Sdarrenr { "frag", IPNY_FRAG }, 635145510Sdarrenr { "from", IPNY_FROM }, 636145510Sdarrenr { "icmpidmap", IPNY_ICMPIDMAP }, 637145510Sdarrenr { "mask", IPNY_MASK }, 638145510Sdarrenr { "map", IPNY_MAP }, 639145510Sdarrenr { "map-block", IPNY_MAPBLOCK }, 640145510Sdarrenr { "mssclamp", IPNY_MSSCLAMP }, 641145510Sdarrenr { "netmask", IPNY_MASK }, 642145510Sdarrenr { "port", IPNY_PORT }, 643145510Sdarrenr { "portmap", IPNY_PORTMAP }, 644145510Sdarrenr { "ports", IPNY_PORTS }, 645145510Sdarrenr { "proxy", IPNY_PROXY }, 646145510Sdarrenr { "range", IPNY_RANGE }, 647145510Sdarrenr { "rdr", IPNY_RDR }, 648145510Sdarrenr { "round-robin",IPNY_ROUNDROBIN }, 649145510Sdarrenr { "sticky", IPNY_STICKY }, 650145510Sdarrenr { "tag", IPNY_TAG }, 651145510Sdarrenr { "tcp", IPNY_TCP }, 652145510Sdarrenr { "tcpudp", IPNY_TCPUDP }, 653145510Sdarrenr { "to", IPNY_TO }, 654145510Sdarrenr { "udp", IPNY_UDP }, 655145510Sdarrenr { "-", '-' }, 656145510Sdarrenr { "->", IPNY_TLATE }, 657145510Sdarrenr { "eq", YY_CMP_EQ }, 658145510Sdarrenr { "ne", YY_CMP_NE }, 659145510Sdarrenr { "lt", YY_CMP_LT }, 660145510Sdarrenr { "gt", YY_CMP_GT }, 661145510Sdarrenr { "le", YY_CMP_LE }, 662145510Sdarrenr { "ge", YY_CMP_GE }, 663145510Sdarrenr { NULL, 0 } 664145510Sdarrenr}; 665145510Sdarrenr 666145510Sdarrenr 667145510Sdarrenrint ipnat_parsefile(fd, addfunc, ioctlfunc, filename) 668145510Sdarrenrint fd; 669145510Sdarrenraddfunc_t addfunc; 670145510Sdarrenrioctlfunc_t ioctlfunc; 671145510Sdarrenrchar *filename; 672145510Sdarrenr{ 673145510Sdarrenr FILE *fp = NULL; 674145510Sdarrenr char *s; 675145510Sdarrenr 676145510Sdarrenr (void) yysettab(yywords); 677145510Sdarrenr 678145510Sdarrenr s = getenv("YYDEBUG"); 679145510Sdarrenr if (s) 680145510Sdarrenr yydebug = atoi(s); 681145510Sdarrenr else 682145510Sdarrenr yydebug = 0; 683145510Sdarrenr 684145510Sdarrenr if (strcmp(filename, "-")) { 685145510Sdarrenr fp = fopen(filename, "r"); 686145510Sdarrenr if (!fp) { 687145510Sdarrenr fprintf(stderr, "fopen(%s) failed: %s\n", filename, 688145510Sdarrenr STRERROR(errno)); 689145510Sdarrenr return -1; 690145510Sdarrenr } 691145510Sdarrenr } else 692145510Sdarrenr fp = stdin; 693145510Sdarrenr 694145510Sdarrenr while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1) 695145510Sdarrenr ; 696145510Sdarrenr if (fp != NULL) 697145510Sdarrenr fclose(fp); 698145510Sdarrenr return 0; 699145510Sdarrenr} 700145510Sdarrenr 701145510Sdarrenr 702145510Sdarrenrint ipnat_parsesome(fd, addfunc, ioctlfunc, fp) 703145510Sdarrenrint fd; 704145510Sdarrenraddfunc_t addfunc; 705145510Sdarrenrioctlfunc_t ioctlfunc; 706145510SdarrenrFILE *fp; 707145510Sdarrenr{ 708145510Sdarrenr char *s; 709145510Sdarrenr int i; 710145510Sdarrenr 711145510Sdarrenr yylineNum = 1; 712145510Sdarrenr 713145510Sdarrenr natfd = fd; 714145510Sdarrenr nataddfunc = addfunc; 715145510Sdarrenr natioctlfunc = ioctlfunc; 716145510Sdarrenr 717145510Sdarrenr if (feof(fp)) 718145510Sdarrenr return 0; 719145510Sdarrenr i = fgetc(fp); 720145510Sdarrenr if (i == EOF) 721145510Sdarrenr return 0; 722145510Sdarrenr if (ungetc(i, fp) == EOF) 723145510Sdarrenr return 0; 724145510Sdarrenr if (feof(fp)) 725145510Sdarrenr return 0; 726145510Sdarrenr s = getenv("YYDEBUG"); 727145510Sdarrenr if (s) 728145510Sdarrenr yydebug = atoi(s); 729145510Sdarrenr else 730145510Sdarrenr yydebug = 0; 731145510Sdarrenr 732145510Sdarrenr yyin = fp; 733145510Sdarrenr yyparse(); 734145510Sdarrenr return 1; 735145510Sdarrenr} 736145510Sdarrenr 737145510Sdarrenr 738145510Sdarrenrstatic void newnatrule() 739145510Sdarrenr{ 740145510Sdarrenr ipnat_t *n; 741145510Sdarrenr 742145510Sdarrenr n = calloc(1, sizeof(*n)); 743145510Sdarrenr if (n == NULL) 744145510Sdarrenr return; 745145510Sdarrenr 746145510Sdarrenr if (nat == NULL) 747145510Sdarrenr nattop = nat = n; 748145510Sdarrenr else { 749145510Sdarrenr nat->in_next = n; 750145510Sdarrenr nat = n; 751145510Sdarrenr } 752161357Sguido 753161357Sguido suggest_port = 0; 754145510Sdarrenr} 755145510Sdarrenr 756145510Sdarrenr 757145510Sdarrenrstatic void setnatproto(p) 758145510Sdarrenrint p; 759145510Sdarrenr{ 760145510Sdarrenr nat->in_p = p; 761145510Sdarrenr 762145510Sdarrenr switch (p) 763145510Sdarrenr { 764145510Sdarrenr case IPPROTO_TCP : 765145510Sdarrenr nat->in_flags |= IPN_TCP; 766145510Sdarrenr nat->in_flags &= ~IPN_UDP; 767145510Sdarrenr break; 768145510Sdarrenr case IPPROTO_UDP : 769145510Sdarrenr nat->in_flags |= IPN_UDP; 770145510Sdarrenr nat->in_flags &= ~IPN_TCP; 771145510Sdarrenr break; 772145510Sdarrenr case IPPROTO_ICMP : 773145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 774145510Sdarrenr if (!(nat->in_flags & IPN_ICMPQUERY)) { 775145510Sdarrenr nat->in_dcmp = 0; 776145510Sdarrenr nat->in_scmp = 0; 777145510Sdarrenr nat->in_pmin = 0; 778145510Sdarrenr nat->in_pmax = 0; 779145510Sdarrenr nat->in_pnext = 0; 780145510Sdarrenr } 781145510Sdarrenr break; 782145510Sdarrenr default : 783145510Sdarrenr if ((nat->in_redir & NAT_MAPBLK) == 0) { 784145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 785145510Sdarrenr nat->in_dcmp = 0; 786145510Sdarrenr nat->in_scmp = 0; 787145510Sdarrenr nat->in_pmin = 0; 788145510Sdarrenr nat->in_pmax = 0; 789145510Sdarrenr nat->in_pnext = 0; 790145510Sdarrenr } 791145510Sdarrenr break; 792145510Sdarrenr } 793145510Sdarrenr 794145510Sdarrenr if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) 795145510Sdarrenr nat->in_flags &= ~IPN_FIXEDDPORT; 796145510Sdarrenr} 797145510Sdarrenr 798145510Sdarrenr 799145510Sdarrenrvoid ipnat_addrule(fd, ioctlfunc, ptr) 800145510Sdarrenrint fd; 801145510Sdarrenrioctlfunc_t ioctlfunc; 802145510Sdarrenrvoid *ptr; 803145510Sdarrenr{ 804145510Sdarrenr ioctlcmd_t add, del; 805145510Sdarrenr ipfobj_t obj; 806145510Sdarrenr ipnat_t *ipn; 807145510Sdarrenr 808145510Sdarrenr ipn = ptr; 809145510Sdarrenr bzero((char *)&obj, sizeof(obj)); 810145510Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 811145510Sdarrenr obj.ipfo_size = sizeof(ipnat_t); 812145510Sdarrenr obj.ipfo_type = IPFOBJ_IPNAT; 813145510Sdarrenr obj.ipfo_ptr = ptr; 814145510Sdarrenr add = 0; 815145510Sdarrenr del = 0; 816145510Sdarrenr 817145510Sdarrenr if ((opts & OPT_DONOTHING) != 0) 818145510Sdarrenr fd = -1; 819145510Sdarrenr 820145510Sdarrenr if (opts & OPT_ZERORULEST) { 821145510Sdarrenr add = SIOCZRLST; 822145510Sdarrenr } else if (opts & OPT_INACTIVE) { 823145510Sdarrenr add = SIOCADNAT; 824145510Sdarrenr del = SIOCRMNAT; 825145510Sdarrenr } else { 826145510Sdarrenr add = SIOCADNAT; 827145510Sdarrenr del = SIOCRMNAT; 828145510Sdarrenr } 829145510Sdarrenr 830161357Sguido if ((opts & OPT_VERBOSE) != 0) 831145510Sdarrenr printnat(ipn, opts); 832145510Sdarrenr 833145510Sdarrenr if (opts & OPT_DEBUG) 834145510Sdarrenr binprint(ipn, sizeof(*ipn)); 835145510Sdarrenr 836145510Sdarrenr if ((opts & OPT_ZERORULEST) != 0) { 837145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 838145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 839145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 840145510Sdarrenr perror("ioctl(SIOCZRLST)"); 841145510Sdarrenr } 842145510Sdarrenr } else { 843145510Sdarrenr#ifdef USE_QUAD_T 844145510Sdarrenr/* 845145510Sdarrenr printf("hits %qd bytes %qd ", 846145510Sdarrenr (long long)fr->fr_hits, 847145510Sdarrenr (long long)fr->fr_bytes); 848145510Sdarrenr*/ 849145510Sdarrenr#else 850145510Sdarrenr/* 851145510Sdarrenr printf("hits %ld bytes %ld ", 852145510Sdarrenr fr->fr_hits, fr->fr_bytes); 853145510Sdarrenr*/ 854145510Sdarrenr#endif 855145510Sdarrenr printnat(ipn, opts); 856145510Sdarrenr } 857145510Sdarrenr } else if ((opts & OPT_REMOVE) != 0) { 858145510Sdarrenr if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 859145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 860145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 861145510Sdarrenr perror("ioctl(delete nat rule)"); 862145510Sdarrenr } 863145510Sdarrenr } 864145510Sdarrenr } else { 865145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 866145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 867145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 868145510Sdarrenr perror("ioctl(add/insert nat rule)"); 869145510Sdarrenr } 870145510Sdarrenr } 871145510Sdarrenr } 872145510Sdarrenr} 873