ipnat_y.y revision 153881
1145519Sdarrenr/* $FreeBSD: head/contrib/ipfilter/tools/ipnat_y.y 153881 2005-12-30 11:52:26Z guido $ */ 2145510Sdarrenr 3145510Sdarrenr%{ 4145510Sdarrenr#ifdef __FreeBSD__ 5145510Sdarrenr# ifndef __FreeBSD_cc_version 6145510Sdarrenr# include <osreldate.h> 7145510Sdarrenr# else 8145510Sdarrenr# if __FreeBSD_cc_version < 430000 9145510Sdarrenr# include <osreldate.h> 10145510Sdarrenr# endif 11145510Sdarrenr# endif 12145510Sdarrenr#endif 13145510Sdarrenr#include <stdio.h> 14145510Sdarrenr#include <unistd.h> 15145510Sdarrenr#include <string.h> 16145510Sdarrenr#include <fcntl.h> 17145510Sdarrenr#include <errno.h> 18145510Sdarrenr#if !defined(__SVR4) && !defined(__GNUC__) 19145510Sdarrenr#include <strings.h> 20145510Sdarrenr#endif 21145510Sdarrenr#include <sys/types.h> 22145510Sdarrenr#include <sys/param.h> 23145510Sdarrenr#include <sys/file.h> 24145510Sdarrenr#include <stdlib.h> 25145510Sdarrenr#include <stddef.h> 26145510Sdarrenr#include <sys/socket.h> 27145510Sdarrenr#include <sys/ioctl.h> 28145510Sdarrenr#include <netinet/in.h> 29145510Sdarrenr#include <netinet/in_systm.h> 30145510Sdarrenr#include <sys/time.h> 31145510Sdarrenr#include <syslog.h> 32145510Sdarrenr#include <net/if.h> 33145510Sdarrenr#if __FreeBSD_version >= 300000 34145510Sdarrenr# include <net/if_var.h> 35145510Sdarrenr#endif 36145510Sdarrenr#include <netdb.h> 37145510Sdarrenr#include <arpa/nameser.h> 38145510Sdarrenr#include <resolv.h> 39145510Sdarrenr#include "ipf.h" 40145510Sdarrenr#include "netinet/ipl.h" 41145510Sdarrenr#include "ipnat_l.h" 42145510Sdarrenr 43145510Sdarrenr#define YYDEBUG 1 44145510Sdarrenr 45145510Sdarrenrextern void yyerror __P((char *)); 46145510Sdarrenrextern int yyparse __P((void)); 47145510Sdarrenrextern int yylex __P((void)); 48145510Sdarrenrextern int yydebug; 49145510Sdarrenrextern FILE *yyin; 50145510Sdarrenrextern int yylineNum; 51145510Sdarrenr 52145510Sdarrenrstatic ipnat_t *nattop = NULL; 53145510Sdarrenrstatic ipnat_t *nat = NULL; 54145510Sdarrenrstatic int natfd = -1; 55145510Sdarrenrstatic ioctlfunc_t natioctlfunc = NULL; 56145510Sdarrenrstatic addfunc_t nataddfunc = NULL; 57145510Sdarrenr 58145510Sdarrenrstatic void newnatrule __P((void)); 59145510Sdarrenrstatic void setnatproto __P((int)); 60145510Sdarrenr 61145510Sdarrenr%} 62145510Sdarrenr%union { 63145510Sdarrenr char *str; 64145510Sdarrenr u_32_t num; 65145510Sdarrenr struct in_addr ipa; 66145510Sdarrenr frentry_t fr; 67145510Sdarrenr frtuc_t *frt; 68145510Sdarrenr u_short port; 69145510Sdarrenr struct { 70145510Sdarrenr u_short p1; 71145510Sdarrenr u_short p2; 72145510Sdarrenr int pc; 73145510Sdarrenr } pc; 74145510Sdarrenr struct { 75145510Sdarrenr struct in_addr a; 76145510Sdarrenr struct in_addr m; 77145510Sdarrenr } ipp; 78145510Sdarrenr union i6addr ip6; 79145510Sdarrenr}; 80145510Sdarrenr 81145510Sdarrenr%token <num> YY_NUMBER YY_HEX 82145510Sdarrenr%token <str> YY_STR 83145510Sdarrenr%token YY_COMMENT 84145510Sdarrenr%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 85145510Sdarrenr%token YY_RANGE_OUT YY_RANGE_IN 86145510Sdarrenr%token <ip6> YY_IPV6 87145510Sdarrenr 88145510Sdarrenr%token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE 89145510Sdarrenr%token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY 90145510Sdarrenr%token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY 91145510Sdarrenr%token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG 92145510Sdarrenr%token IPNY_TLATE 93145510Sdarrenr%type <port> portspec 94145510Sdarrenr%type <num> hexnumber compare range proto 95145510Sdarrenr%type <ipa> hostname ipv4 96145510Sdarrenr%type <ipp> addr nummask rhaddr 97145510Sdarrenr%type <pc> portstuff 98145510Sdarrenr%% 99145510Sdarrenrfile: line 100145510Sdarrenr | assign 101145510Sdarrenr | file line 102145510Sdarrenr | file assign 103145510Sdarrenr ; 104145510Sdarrenr 105145510Sdarrenrline: xx rule { while ((nat = nattop) != NULL) { 106145510Sdarrenr nattop = nat->in_next; 107145510Sdarrenr (*nataddfunc)(natfd, natioctlfunc, nat); 108145510Sdarrenr free(nat); 109145510Sdarrenr } 110145510Sdarrenr resetlexer(); 111145510Sdarrenr } 112145510Sdarrenr | YY_COMMENT 113145510Sdarrenr ; 114145510Sdarrenr 115145510Sdarrenrassign: YY_STR assigning YY_STR ';' { set_variable($1, $3); 116145510Sdarrenr resetlexer(); 117145510Sdarrenr free($1); 118145510Sdarrenr free($3); 119145510Sdarrenr } 120145510Sdarrenr ; 121145510Sdarrenr 122145510Sdarrenrassigning: 123145510Sdarrenr '=' { yyvarnext = 1; } 124145510Sdarrenr ; 125145510Sdarrenr 126145510Sdarrenrxx: { newnatrule(); } 127145510Sdarrenr ; 128145510Sdarrenr 129145510Sdarrenrrule: map eol 130145510Sdarrenr | mapblock eol 131145510Sdarrenr | redir eol 132145510Sdarrenr ; 133145510Sdarrenr 134145510Sdarrenreol: | ';' 135145510Sdarrenr ; 136145510Sdarrenr 137145510Sdarrenrmap: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions 138145510Sdarrenr { nat->in_v = 4; 139145510Sdarrenr nat->in_inip = $3.a.s_addr; 140145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 141145510Sdarrenr nat->in_outip = $5.a.s_addr; 142145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 143145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 144145510Sdarrenr strncpy(nat->in_ifnames[1], 145145510Sdarrenr nat->in_ifnames[0], 146145510Sdarrenr sizeof(nat->in_ifnames[0])); 147145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 148145510Sdarrenr setnatproto(nat->in_p); 149145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 150145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 151145510Sdarrenr nat_setgroupmap(nat); 152145510Sdarrenr } 153145510Sdarrenr | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions 154145510Sdarrenr { nat->in_v = 4; 155145510Sdarrenr nat->in_inip = $3.a.s_addr; 156145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 157145510Sdarrenr nat->in_outip = $5.a.s_addr; 158145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 159145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 160145510Sdarrenr strncpy(nat->in_ifnames[1], 161145510Sdarrenr nat->in_ifnames[0], 162145510Sdarrenr sizeof(nat->in_ifnames[0])); 163145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 164145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 165145510Sdarrenr nat_setgroupmap(nat); 166145510Sdarrenr } 167145510Sdarrenr | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions 168145510Sdarrenr { nat->in_v = 4; 169145510Sdarrenr nat->in_outip = $5.a.s_addr; 170145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 171145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 172145510Sdarrenr strncpy(nat->in_ifnames[1], 173145510Sdarrenr nat->in_ifnames[0], 174145510Sdarrenr sizeof(nat->in_ifnames[0])); 175145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 176145510Sdarrenr setnatproto(nat->in_p); 177145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 178145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 179145510Sdarrenr nat_setgroupmap(nat); 180145510Sdarrenr } 181145510Sdarrenr | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions 182145510Sdarrenr { nat->in_v = 4; 183145510Sdarrenr nat->in_outip = $5.a.s_addr; 184145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 185145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 186145510Sdarrenr strncpy(nat->in_ifnames[1], 187145510Sdarrenr nat->in_ifnames[0], 188145510Sdarrenr sizeof(nat->in_ifnames[0])); 189145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 190145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 191145510Sdarrenr nat_setgroupmap(nat); 192145510Sdarrenr } 193145510Sdarrenr ; 194145510Sdarrenr 195145510Sdarrenrmapblock: 196145510Sdarrenr mapblockit ifnames addr IPNY_TLATE addr ports mapoptions 197145510Sdarrenr { nat->in_v = 4; 198145510Sdarrenr nat->in_inip = $3.a.s_addr; 199145510Sdarrenr nat->in_inmsk = $3.m.s_addr; 200145510Sdarrenr nat->in_outip = $5.a.s_addr; 201145510Sdarrenr nat->in_outmsk = $5.m.s_addr; 202145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 203145510Sdarrenr strncpy(nat->in_ifnames[1], 204145510Sdarrenr nat->in_ifnames[0], 205145510Sdarrenr sizeof(nat->in_ifnames[0])); 206145510Sdarrenr if ((nat->in_flags & IPN_TCPUDP) == 0) 207145510Sdarrenr setnatproto(nat->in_p); 208145510Sdarrenr if (((nat->in_redir & NAT_MAPBLK) != 0) || 209145510Sdarrenr ((nat->in_flags & IPN_AUTOPORTMAP) != 0)) 210145510Sdarrenr nat_setgroupmap(nat); 211145510Sdarrenr } 212145510Sdarrenr ; 213145510Sdarrenr 214145510Sdarrenrredir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions 215145510Sdarrenr { nat->in_v = 4; 216145510Sdarrenr nat->in_outip = $3.a.s_addr; 217145510Sdarrenr nat->in_outmsk = $3.m.s_addr; 218145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 219145510Sdarrenr strncpy(nat->in_ifnames[1], 220145510Sdarrenr nat->in_ifnames[0], 221145510Sdarrenr sizeof(nat->in_ifnames[0])); 222145510Sdarrenr if ((nat->in_p == 0) && 223145510Sdarrenr ((nat->in_flags & IPN_TCPUDP) == 0) && 224145510Sdarrenr (nat->in_pmin != 0 || 225145510Sdarrenr nat->in_pmax != 0 || 226145510Sdarrenr nat->in_pnext != 0)) 227145510Sdarrenr setnatproto(IPPROTO_TCP); 228145510Sdarrenr } 229145510Sdarrenr | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions 230145510Sdarrenr { nat->in_v = 4; 231145510Sdarrenr if ((nat->in_p == 0) && 232145510Sdarrenr ((nat->in_flags & IPN_TCPUDP) == 0) && 233145510Sdarrenr (nat->in_pmin != 0 || 234145510Sdarrenr nat->in_pmax != 0 || 235145510Sdarrenr nat->in_pnext != 0)) 236145510Sdarrenr setnatproto(IPPROTO_TCP); 237145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 238145510Sdarrenr strncpy(nat->in_ifnames[1], 239145510Sdarrenr nat->in_ifnames[0], 240145510Sdarrenr sizeof(nat->in_ifnames[0])); 241145510Sdarrenr } 242145510Sdarrenr | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions 243145510Sdarrenr { nat->in_v = 4; 244145510Sdarrenr nat->in_outip = $3.a.s_addr; 245145510Sdarrenr nat->in_outmsk = $3.m.s_addr; 246145510Sdarrenr if (nat->in_ifnames[1][0] == '\0') 247145510Sdarrenr strncpy(nat->in_ifnames[1], 248145510Sdarrenr nat->in_ifnames[0], 249145510Sdarrenr sizeof(nat->in_ifnames[0])); 250145510Sdarrenr } 251145510Sdarrenr ; 252145510Sdarrenr 253145510Sdarrenrproxy: | IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto 254145510Sdarrenr { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); 255145510Sdarrenr if (nat->in_dcmp == 0) { 256145510Sdarrenr nat->in_dport = htons($3); 257145510Sdarrenr } else if ($3 != nat->in_dport) { 258145510Sdarrenr yyerror("proxy port numbers not consistant"); 259145510Sdarrenr } 260145510Sdarrenr setnatproto($6); 261145510Sdarrenr free($4); 262145510Sdarrenr } 263145510Sdarrenr | IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto 264145510Sdarrenr { int pnum; 265145510Sdarrenr strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel)); 266145510Sdarrenr pnum = getportproto($3, $6); 267145510Sdarrenr if (pnum == -1) 268145510Sdarrenr yyerror("invalid port number"); 269145510Sdarrenr nat->in_dport = pnum; 270145510Sdarrenr setnatproto($6); 271145510Sdarrenr free($3); 272145510Sdarrenr free($4); 273145510Sdarrenr } 274145510Sdarrenr ; 275145510Sdarrenr 276145510Sdarrenrsetproto: 277145510Sdarrenr | proto { if (nat->in_p != 0 || 278145510Sdarrenr nat->in_flags & IPN_TCPUDP) 279145510Sdarrenr yyerror("protocol set twice"); 280145510Sdarrenr setnatproto($1); 281145510Sdarrenr } 282145510Sdarrenr | IPNY_TCPUDP { if (nat->in_p != 0 || 283145510Sdarrenr nat->in_flags & IPN_TCPUDP) 284145510Sdarrenr yyerror("protocol set twice"); 285145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 286145510Sdarrenr nat->in_p = 0; 287145510Sdarrenr } 288145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 || 289145510Sdarrenr nat->in_flags & IPN_TCPUDP) 290145510Sdarrenr yyerror("protocol set twice"); 291145510Sdarrenr nat->in_flags |= IPN_TCPUDP; 292145510Sdarrenr nat->in_p = 0; 293145510Sdarrenr } 294145510Sdarrenr ; 295145510Sdarrenr 296145510Sdarrenrrhaddr: addr { $$.a = $1.a; $$.m = $1.m; } 297145510Sdarrenr | IPNY_RANGE ipv4 '-' ipv4 298145510Sdarrenr { $$.a = $2; $$.m = $4; 299145510Sdarrenr nat->in_flags |= IPN_IPRANGE; } 300145510Sdarrenr ; 301145510Sdarrenr 302145510Sdarrenrdip: 303145510Sdarrenr hostname { nat->in_inip = $1.s_addr; 304145510Sdarrenr nat->in_inmsk = 0xffffffff; } 305153881Sguido | hostname '/' YY_NUMBER { if ($3 != 0 || $1.s_addr != 0) 306153881Sguido yyerror("Only 0/0 supported"); 307153881Sguido nat->in_inip = 0; 308153881Sguido nat->in_inmsk = 0; 309153881Sguido } 310145510Sdarrenr | hostname ',' hostname { nat->in_flags |= IPN_SPLIT; 311145510Sdarrenr nat->in_inip = $1.s_addr; 312145510Sdarrenr nat->in_inmsk = $3.s_addr; } 313145510Sdarrenr ; 314145510Sdarrenr 315145510Sdarrenrportspec: 316145510Sdarrenr YY_NUMBER { if ($1 > 65535) /* Unsigned */ 317145510Sdarrenr yyerror("invalid port number"); 318145510Sdarrenr else 319145510Sdarrenr $$ = $1; 320145510Sdarrenr } 321145510Sdarrenr | YY_STR { if (getport(NULL, $1, &($$)) == -1) 322145510Sdarrenr yyerror("invalid port number"); 323145510Sdarrenr $$ = ntohs($$); 324145510Sdarrenr } 325145510Sdarrenr ; 326145510Sdarrenr 327145510Sdarrenrdport: | IPNY_PORT portspec { nat->in_pmin = htons($2); 328145510Sdarrenr nat->in_pmax = htons($2); } 329145510Sdarrenr | IPNY_PORT portspec '-' portspec { nat->in_pmin = htons($2); 330145510Sdarrenr nat->in_pmax = htons($4); } 331145510Sdarrenr | IPNY_PORT portspec ':' portspec { nat->in_pmin = htons($2); 332145510Sdarrenr nat->in_pmax = htons($4); } 333145510Sdarrenr ; 334145510Sdarrenr 335145510Sdarrenrnport: IPNY_PORT portspec { nat->in_pnext = htons($2); } 336145510Sdarrenr | IPNY_PORT '=' portspec { nat->in_pnext = htons($3); 337145510Sdarrenr nat->in_flags |= IPN_FIXEDDPORT; 338145510Sdarrenr } 339145510Sdarrenr ; 340145510Sdarrenr 341145510Sdarrenrports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; } 342145510Sdarrenr | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; } 343145510Sdarrenr ; 344145510Sdarrenr 345145510Sdarrenrmapit: IPNY_MAP { nat->in_redir = NAT_MAP; } 346145510Sdarrenr | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; } 347145510Sdarrenr ; 348145510Sdarrenr 349145510Sdarrenrrdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; } 350145510Sdarrenr ; 351145510Sdarrenr 352145510Sdarrenrmapblockit: 353145510Sdarrenr IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; } 354145510Sdarrenr ; 355145510Sdarrenr 356145510Sdarrenrmapfrom: 357145510Sdarrenr from sobject IPNY_TO dobject 358145510Sdarrenr | from sobject '!' IPNY_TO dobject 359145510Sdarrenr { nat->in_flags |= IPN_NOTDST; } 360145510Sdarrenr ; 361145510Sdarrenr 362145510Sdarrenrrdrfrom: 363145510Sdarrenr from sobject IPNY_TO dobject 364145510Sdarrenr | '!' from sobject IPNY_TO dobject 365145510Sdarrenr { nat->in_flags |= IPN_NOTSRC; } 366145510Sdarrenr ; 367145510Sdarrenr 368145510Sdarrenrfrom: IPNY_FROM { nat->in_flags |= IPN_FILTER; } 369145510Sdarrenr ; 370145510Sdarrenr 371145510Sdarrenrifnames: 372145510Sdarrenr ifname 373145510Sdarrenr | ifname ',' otherifname 374145510Sdarrenr ; 375145510Sdarrenr 376145510Sdarrenrifname: YY_STR { strncpy(nat->in_ifnames[0], $1, 377145510Sdarrenr sizeof(nat->in_ifnames[0])); 378145510Sdarrenr nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0'; 379145510Sdarrenr free($1); 380145510Sdarrenr } 381145510Sdarrenr ; 382145510Sdarrenr 383145510Sdarrenrotherifname: 384145510Sdarrenr YY_STR { strncpy(nat->in_ifnames[1], $1, 385145510Sdarrenr sizeof(nat->in_ifnames[1])); 386145510Sdarrenr nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0'; 387145510Sdarrenr free($1); 388145510Sdarrenr } 389145510Sdarrenr ; 390145510Sdarrenr 391145510Sdarrenrmapport: 392145510Sdarrenr IPNY_PORTMAP tcpudp portspec ':' portspec 393145510Sdarrenr { nat->in_pmin = htons($3); 394145510Sdarrenr nat->in_pmax = htons($5); 395145510Sdarrenr } 396145510Sdarrenr | IPNY_PORTMAP tcpudp IPNY_AUTO 397145510Sdarrenr { nat->in_flags |= IPN_AUTOPORTMAP; 398145510Sdarrenr nat->in_pmin = htons(1024); 399145510Sdarrenr nat->in_pmax = htons(65535); 400145510Sdarrenr } 401145510Sdarrenr | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER 402145510Sdarrenr { if (strcmp($2, "icmp") != 0) { 403145510Sdarrenr yyerror("icmpidmap not followed by icmp"); 404145510Sdarrenr } 405145510Sdarrenr free($2); 406145510Sdarrenr if ($3 < 0 || $3 > 65535) 407145510Sdarrenr yyerror("invalid ICMP Id number"); 408145510Sdarrenr if ($5 < 0 || $5 > 65535) 409145510Sdarrenr yyerror("invalid ICMP Id number"); 410145510Sdarrenr nat->in_flags = IPN_ICMPQUERY; 411145510Sdarrenr nat->in_pmin = htons($3); 412145510Sdarrenr nat->in_pmax = htons($5); 413145510Sdarrenr } 414145510Sdarrenr ; 415145510Sdarrenr 416145510Sdarrenrsobject: 417145510Sdarrenr saddr 418145510Sdarrenr | saddr IPNY_PORT portstuff { nat->in_sport = $3.p1; 419145510Sdarrenr nat->in_stop = $3.p2; 420145510Sdarrenr nat->in_scmp = $3.pc; } 421145510Sdarrenr ; 422145510Sdarrenr 423145510Sdarrenrsaddr: addr { if (nat->in_redir == NAT_REDIRECT) { 424145510Sdarrenr nat->in_srcip = $1.a.s_addr; 425145510Sdarrenr nat->in_srcmsk = $1.m.s_addr; 426145510Sdarrenr } else { 427145510Sdarrenr nat->in_inip = $1.a.s_addr; 428145510Sdarrenr nat->in_inmsk = $1.m.s_addr; 429145510Sdarrenr } 430145510Sdarrenr } 431145510Sdarrenr ; 432145510Sdarrenr 433145510Sdarrenrdobject: 434145510Sdarrenr daddr 435145510Sdarrenr | daddr IPNY_PORT portstuff { nat->in_dport = $3.p1; 436145510Sdarrenr nat->in_dtop = $3.p2; 437145510Sdarrenr nat->in_dcmp = $3.pc; 438145510Sdarrenr if (nat->in_redir == NAT_REDIRECT) 439145510Sdarrenr nat->in_pmin = htons($3.p1); 440145510Sdarrenr } 441145510Sdarrenr ; 442145510Sdarrenr 443145510Sdarrenrdaddr: addr { if (nat->in_redir == NAT_REDIRECT) { 444145510Sdarrenr nat->in_outip = $1.a.s_addr; 445145510Sdarrenr nat->in_outmsk = $1.m.s_addr; 446145510Sdarrenr } else { 447145510Sdarrenr nat->in_srcip = $1.a.s_addr; 448145510Sdarrenr nat->in_srcmsk = $1.m.s_addr; 449145510Sdarrenr } 450145510Sdarrenr } 451145510Sdarrenr ; 452145510Sdarrenr 453145510Sdarrenraddr: IPNY_ANY { $$.a.s_addr = 0; $$.m.s_addr = 0; } 454145510Sdarrenr | nummask { $$.a = $1.a; $$.m = $1.m; 455145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 456145510Sdarrenr | hostname '/' ipv4 { $$.a = $1; $$.m = $3; 457145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 458153881Sguido | hostname '/' hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); 459145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 460145510Sdarrenr | hostname IPNY_MASK ipv4 { $$.a = $1; $$.m = $3; 461145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 462153881Sguido | hostname IPNY_MASK hexnumber { $$.a = $1; $$.m.s_addr = htonl($3); 463145510Sdarrenr $$.a.s_addr &= $$.m.s_addr; } 464145510Sdarrenr ; 465145510Sdarrenr 466145510Sdarrenrnummask: 467145510Sdarrenr hostname { $$.a = $1; 468145510Sdarrenr $$.m.s_addr = 0xffffffff; } 469145510Sdarrenr | hostname '/' YY_NUMBER { $$.a = $1; 470145510Sdarrenr ntomask(4, $3, &$$.m.s_addr); } 471145510Sdarrenr ; 472145510Sdarrenr 473145510Sdarrenrportstuff: 474145510Sdarrenr compare portspec { $$.pc = $1; $$.p1 = $2; } 475153881Sguido | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; } 476145510Sdarrenr ; 477145510Sdarrenr 478145510Sdarrenrmapoptions: 479145510Sdarrenr rr frag age mssclamp nattag setproto 480145510Sdarrenr ; 481145510Sdarrenr 482145510Sdarrenrrdroptions: 483145510Sdarrenr rr frag age sticky mssclamp rdrproxy nattag 484145510Sdarrenr ; 485145510Sdarrenr 486145510Sdarrenrnattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2, 487145510Sdarrenr sizeof(nat->in_tag.ipt_tag)); 488145510Sdarrenr } 489145510Sdarrenrrr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; } 490145510Sdarrenr ; 491145510Sdarrenr 492145510Sdarrenrfrag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; } 493145510Sdarrenr ; 494145510Sdarrenr 495145510Sdarrenrage: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2; 496145510Sdarrenr nat->in_age[1] = $2; } 497145510Sdarrenr | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2; 498145510Sdarrenr nat->in_age[1] = $4; } 499145510Sdarrenr ; 500145510Sdarrenr 501145510Sdarrenrsticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) && 502145510Sdarrenr !(nat->in_flags & IPN_SPLIT)) { 503145510Sdarrenr fprintf(stderr, 504145510Sdarrenr "'sticky' for use with round-robin/IP splitting only\n"); 505145510Sdarrenr } else 506145510Sdarrenr nat->in_flags |= IPN_STICKY; 507145510Sdarrenr } 508145510Sdarrenr ; 509145510Sdarrenr 510145510Sdarrenrmssclamp: 511145510Sdarrenr | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; } 512145510Sdarrenr ; 513145510Sdarrenr 514145510Sdarrenrtcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); } 515145510Sdarrenr | IPNY_UDP { setnatproto(IPPROTO_UDP); } 516145510Sdarrenr | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP; 517145510Sdarrenr nat->in_p = 0; 518145510Sdarrenr } 519145510Sdarrenr | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP; 520145510Sdarrenr nat->in_p = 0; 521145510Sdarrenr } 522145510Sdarrenr ; 523145510Sdarrenr 524145510Sdarrenrrdrproxy: 525145510Sdarrenr IPNY_PROXY YY_STR 526145510Sdarrenr { strncpy(nat->in_plabel, $2, 527145510Sdarrenr sizeof(nat->in_plabel)); 528145510Sdarrenr nat->in_dport = nat->in_pnext; 529145510Sdarrenr nat->in_dport = htons(nat->in_dport); 530145510Sdarrenr free($2); 531145510Sdarrenr } 532145510Sdarrenr | proxy { if (nat->in_plabel[0] != '\0') { 533145510Sdarrenr nat->in_pmin = nat->in_dport; 534145510Sdarrenr nat->in_pmax = nat->in_pmin; 535145510Sdarrenr nat->in_pnext = nat->in_pmin; 536145510Sdarrenr } 537145510Sdarrenr } 538145510Sdarrenr ; 539145510Sdarrenr 540145510Sdarrenrproto: YY_NUMBER { $$ = $1; } 541145510Sdarrenr | IPNY_TCP { $$ = IPPROTO_TCP; } 542145510Sdarrenr | IPNY_UDP { $$ = IPPROTO_UDP; } 543145510Sdarrenr | YY_STR { $$ = getproto($1); free($1); } 544145510Sdarrenr ; 545145510Sdarrenr 546145510Sdarrenrhexnumber: 547145510Sdarrenr YY_HEX { $$ = $1; } 548145510Sdarrenr ; 549145510Sdarrenr 550145510Sdarrenrhostname: 551145510Sdarrenr YY_STR { if (gethost($1, &$$.s_addr) == -1) 552145510Sdarrenr fprintf(stderr, 553145510Sdarrenr "Unknown host '%s'\n", 554145510Sdarrenr $1); 555145510Sdarrenr free($1); 556145510Sdarrenr } 557145510Sdarrenr | YY_NUMBER { $$.s_addr = htonl($1); } 558145510Sdarrenr | ipv4 { $$.s_addr = $1.s_addr; } 559145510Sdarrenr ; 560145510Sdarrenr 561145510Sdarrenrcompare: 562145510Sdarrenr '=' { $$ = FR_EQUAL; } 563145510Sdarrenr | YY_CMP_EQ { $$ = FR_EQUAL; } 564145510Sdarrenr | YY_CMP_NE { $$ = FR_NEQUAL; } 565145510Sdarrenr | YY_CMP_LT { $$ = FR_LESST; } 566145510Sdarrenr | YY_CMP_LE { $$ = FR_LESSTE; } 567145510Sdarrenr | YY_CMP_GT { $$ = FR_GREATERT; } 568145510Sdarrenr | YY_CMP_GE { $$ = FR_GREATERTE; } 569145510Sdarrenr 570145510Sdarrenrrange: 571145510Sdarrenr YY_RANGE_OUT { $$ = FR_OUTRANGE; } 572145510Sdarrenr | YY_RANGE_IN { $$ = FR_INRANGE; } 573145510Sdarrenr ; 574145510Sdarrenr 575145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 576145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 577145510Sdarrenr yyerror("Invalid octet string for IP address"); 578145510Sdarrenr return 0; 579145510Sdarrenr } 580145510Sdarrenr $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 581145510Sdarrenr $$.s_addr = htonl($$.s_addr); 582145510Sdarrenr } 583145510Sdarrenr ; 584145510Sdarrenr 585145510Sdarrenr%% 586145510Sdarrenr 587145510Sdarrenr 588145510Sdarrenrstatic wordtab_t yywords[] = { 589145510Sdarrenr { "age", IPNY_AGE }, 590145510Sdarrenr { "any", IPNY_ANY }, 591145510Sdarrenr { "auto", IPNY_AUTO }, 592145510Sdarrenr { "bimap", IPNY_BIMAP }, 593145510Sdarrenr { "frag", IPNY_FRAG }, 594145510Sdarrenr { "from", IPNY_FROM }, 595145510Sdarrenr { "icmpidmap", IPNY_ICMPIDMAP }, 596145510Sdarrenr { "mask", IPNY_MASK }, 597145510Sdarrenr { "map", IPNY_MAP }, 598145510Sdarrenr { "map-block", IPNY_MAPBLOCK }, 599145510Sdarrenr { "mssclamp", IPNY_MSSCLAMP }, 600145510Sdarrenr { "netmask", IPNY_MASK }, 601145510Sdarrenr { "port", IPNY_PORT }, 602145510Sdarrenr { "portmap", IPNY_PORTMAP }, 603145510Sdarrenr { "ports", IPNY_PORTS }, 604145510Sdarrenr { "proxy", IPNY_PROXY }, 605145510Sdarrenr { "range", IPNY_RANGE }, 606145510Sdarrenr { "rdr", IPNY_RDR }, 607145510Sdarrenr { "round-robin",IPNY_ROUNDROBIN }, 608145510Sdarrenr { "sticky", IPNY_STICKY }, 609145510Sdarrenr { "tag", IPNY_TAG }, 610145510Sdarrenr { "tcp", IPNY_TCP }, 611145510Sdarrenr { "tcpudp", IPNY_TCPUDP }, 612145510Sdarrenr { "to", IPNY_TO }, 613145510Sdarrenr { "udp", IPNY_UDP }, 614145510Sdarrenr { "-", '-' }, 615145510Sdarrenr { "->", IPNY_TLATE }, 616145510Sdarrenr { "eq", YY_CMP_EQ }, 617145510Sdarrenr { "ne", YY_CMP_NE }, 618145510Sdarrenr { "lt", YY_CMP_LT }, 619145510Sdarrenr { "gt", YY_CMP_GT }, 620145510Sdarrenr { "le", YY_CMP_LE }, 621145510Sdarrenr { "ge", YY_CMP_GE }, 622145510Sdarrenr { NULL, 0 } 623145510Sdarrenr}; 624145510Sdarrenr 625145510Sdarrenr 626145510Sdarrenrint ipnat_parsefile(fd, addfunc, ioctlfunc, filename) 627145510Sdarrenrint fd; 628145510Sdarrenraddfunc_t addfunc; 629145510Sdarrenrioctlfunc_t ioctlfunc; 630145510Sdarrenrchar *filename; 631145510Sdarrenr{ 632145510Sdarrenr FILE *fp = NULL; 633145510Sdarrenr char *s; 634145510Sdarrenr 635145510Sdarrenr (void) yysettab(yywords); 636145510Sdarrenr 637145510Sdarrenr s = getenv("YYDEBUG"); 638145510Sdarrenr if (s) 639145510Sdarrenr yydebug = atoi(s); 640145510Sdarrenr else 641145510Sdarrenr yydebug = 0; 642145510Sdarrenr 643145510Sdarrenr if (strcmp(filename, "-")) { 644145510Sdarrenr fp = fopen(filename, "r"); 645145510Sdarrenr if (!fp) { 646145510Sdarrenr fprintf(stderr, "fopen(%s) failed: %s\n", filename, 647145510Sdarrenr STRERROR(errno)); 648145510Sdarrenr return -1; 649145510Sdarrenr } 650145510Sdarrenr } else 651145510Sdarrenr fp = stdin; 652145510Sdarrenr 653145510Sdarrenr while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1) 654145510Sdarrenr ; 655145510Sdarrenr if (fp != NULL) 656145510Sdarrenr fclose(fp); 657145510Sdarrenr return 0; 658145510Sdarrenr} 659145510Sdarrenr 660145510Sdarrenr 661145510Sdarrenrint ipnat_parsesome(fd, addfunc, ioctlfunc, fp) 662145510Sdarrenrint fd; 663145510Sdarrenraddfunc_t addfunc; 664145510Sdarrenrioctlfunc_t ioctlfunc; 665145510SdarrenrFILE *fp; 666145510Sdarrenr{ 667145510Sdarrenr char *s; 668145510Sdarrenr int i; 669145510Sdarrenr 670145510Sdarrenr yylineNum = 1; 671145510Sdarrenr 672145510Sdarrenr natfd = fd; 673145510Sdarrenr nataddfunc = addfunc; 674145510Sdarrenr natioctlfunc = ioctlfunc; 675145510Sdarrenr 676145510Sdarrenr if (feof(fp)) 677145510Sdarrenr return 0; 678145510Sdarrenr i = fgetc(fp); 679145510Sdarrenr if (i == EOF) 680145510Sdarrenr return 0; 681145510Sdarrenr if (ungetc(i, fp) == EOF) 682145510Sdarrenr return 0; 683145510Sdarrenr if (feof(fp)) 684145510Sdarrenr return 0; 685145510Sdarrenr s = getenv("YYDEBUG"); 686145510Sdarrenr if (s) 687145510Sdarrenr yydebug = atoi(s); 688145510Sdarrenr else 689145510Sdarrenr yydebug = 0; 690145510Sdarrenr 691145510Sdarrenr yyin = fp; 692145510Sdarrenr yyparse(); 693145510Sdarrenr return 1; 694145510Sdarrenr} 695145510Sdarrenr 696145510Sdarrenr 697145510Sdarrenrstatic void newnatrule() 698145510Sdarrenr{ 699145510Sdarrenr ipnat_t *n; 700145510Sdarrenr 701145510Sdarrenr n = calloc(1, sizeof(*n)); 702145510Sdarrenr if (n == NULL) 703145510Sdarrenr return; 704145510Sdarrenr 705145510Sdarrenr if (nat == NULL) 706145510Sdarrenr nattop = nat = n; 707145510Sdarrenr else { 708145510Sdarrenr nat->in_next = n; 709145510Sdarrenr nat = n; 710145510Sdarrenr } 711145510Sdarrenr} 712145510Sdarrenr 713145510Sdarrenr 714145510Sdarrenrstatic void setnatproto(p) 715145510Sdarrenrint p; 716145510Sdarrenr{ 717145510Sdarrenr nat->in_p = p; 718145510Sdarrenr 719145510Sdarrenr switch (p) 720145510Sdarrenr { 721145510Sdarrenr case IPPROTO_TCP : 722145510Sdarrenr nat->in_flags |= IPN_TCP; 723145510Sdarrenr nat->in_flags &= ~IPN_UDP; 724145510Sdarrenr break; 725145510Sdarrenr case IPPROTO_UDP : 726145510Sdarrenr nat->in_flags |= IPN_UDP; 727145510Sdarrenr nat->in_flags &= ~IPN_TCP; 728145510Sdarrenr break; 729145510Sdarrenr case IPPROTO_ICMP : 730145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 731145510Sdarrenr if (!(nat->in_flags & IPN_ICMPQUERY)) { 732145510Sdarrenr nat->in_dcmp = 0; 733145510Sdarrenr nat->in_scmp = 0; 734145510Sdarrenr nat->in_pmin = 0; 735145510Sdarrenr nat->in_pmax = 0; 736145510Sdarrenr nat->in_pnext = 0; 737145510Sdarrenr } 738145510Sdarrenr break; 739145510Sdarrenr default : 740145510Sdarrenr if ((nat->in_redir & NAT_MAPBLK) == 0) { 741145510Sdarrenr nat->in_flags &= ~IPN_TCPUDP; 742145510Sdarrenr nat->in_dcmp = 0; 743145510Sdarrenr nat->in_scmp = 0; 744145510Sdarrenr nat->in_pmin = 0; 745145510Sdarrenr nat->in_pmax = 0; 746145510Sdarrenr nat->in_pnext = 0; 747145510Sdarrenr } 748145510Sdarrenr break; 749145510Sdarrenr } 750145510Sdarrenr 751145510Sdarrenr if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT) 752145510Sdarrenr nat->in_flags &= ~IPN_FIXEDDPORT; 753145510Sdarrenr} 754145510Sdarrenr 755145510Sdarrenr 756145510Sdarrenrvoid ipnat_addrule(fd, ioctlfunc, ptr) 757145510Sdarrenrint fd; 758145510Sdarrenrioctlfunc_t ioctlfunc; 759145510Sdarrenrvoid *ptr; 760145510Sdarrenr{ 761145510Sdarrenr ioctlcmd_t add, del; 762145510Sdarrenr ipfobj_t obj; 763145510Sdarrenr ipnat_t *ipn; 764145510Sdarrenr 765145510Sdarrenr ipn = ptr; 766145510Sdarrenr bzero((char *)&obj, sizeof(obj)); 767145510Sdarrenr obj.ipfo_rev = IPFILTER_VERSION; 768145510Sdarrenr obj.ipfo_size = sizeof(ipnat_t); 769145510Sdarrenr obj.ipfo_type = IPFOBJ_IPNAT; 770145510Sdarrenr obj.ipfo_ptr = ptr; 771145510Sdarrenr add = 0; 772145510Sdarrenr del = 0; 773145510Sdarrenr 774145510Sdarrenr if ((opts & OPT_DONOTHING) != 0) 775145510Sdarrenr fd = -1; 776145510Sdarrenr 777145510Sdarrenr if (opts & OPT_ZERORULEST) { 778145510Sdarrenr add = SIOCZRLST; 779145510Sdarrenr } else if (opts & OPT_INACTIVE) { 780145510Sdarrenr add = SIOCADNAT; 781145510Sdarrenr del = SIOCRMNAT; 782145510Sdarrenr } else { 783145510Sdarrenr add = SIOCADNAT; 784145510Sdarrenr del = SIOCRMNAT; 785145510Sdarrenr } 786145510Sdarrenr 787145510Sdarrenr if (ipn && (opts & OPT_VERBOSE)) 788145510Sdarrenr printnat(ipn, opts); 789145510Sdarrenr 790145510Sdarrenr if (opts & OPT_DEBUG) 791145510Sdarrenr binprint(ipn, sizeof(*ipn)); 792145510Sdarrenr 793145510Sdarrenr if ((opts & OPT_ZERORULEST) != 0) { 794145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 795145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 796145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 797145510Sdarrenr perror("ioctl(SIOCZRLST)"); 798145510Sdarrenr } 799145510Sdarrenr } else { 800145510Sdarrenr#ifdef USE_QUAD_T 801145510Sdarrenr/* 802145510Sdarrenr printf("hits %qd bytes %qd ", 803145510Sdarrenr (long long)fr->fr_hits, 804145510Sdarrenr (long long)fr->fr_bytes); 805145510Sdarrenr*/ 806145510Sdarrenr#else 807145510Sdarrenr/* 808145510Sdarrenr printf("hits %ld bytes %ld ", 809145510Sdarrenr fr->fr_hits, fr->fr_bytes); 810145510Sdarrenr*/ 811145510Sdarrenr#endif 812145510Sdarrenr printnat(ipn, opts); 813145510Sdarrenr } 814145510Sdarrenr } else if ((opts & OPT_REMOVE) != 0) { 815145510Sdarrenr if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) { 816145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 817145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 818145510Sdarrenr perror("ioctl(delete nat rule)"); 819145510Sdarrenr } 820145510Sdarrenr } 821145510Sdarrenr } else { 822145510Sdarrenr if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) { 823145510Sdarrenr if ((opts & OPT_DONOTHING) == 0) { 824145510Sdarrenr fprintf(stderr, "%d:", yylineNum); 825145510Sdarrenr perror("ioctl(add/insert nat rule)"); 826145510Sdarrenr } 827145510Sdarrenr } 828145510Sdarrenr } 829145510Sdarrenr} 830