10Sstevel@tonic-gate %{
2570Syx160601 /*
37176Syx160601 * Copyright (C) 2001-2008 by Darren Reed.
4570Syx160601 *
5570Syx160601 * See the IPFILTER.LICENCE file for details on licencing.
6570Syx160601 *
77176Syx160601 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
8570Syx160601 * Use is subject to license terms.
9570Syx160601 */
102609Sjojemann
112609Sjojemann #pragma ident "%Z%%M% %I% %E% SMI"
12570Syx160601
130Sstevel@tonic-gate #ifdef __FreeBSD__
140Sstevel@tonic-gate # ifndef __FreeBSD_cc_version
150Sstevel@tonic-gate # include <osreldate.h>
160Sstevel@tonic-gate # else
170Sstevel@tonic-gate # if __FreeBSD_cc_version < 430000
180Sstevel@tonic-gate # include <osreldate.h>
190Sstevel@tonic-gate # endif
200Sstevel@tonic-gate # endif
210Sstevel@tonic-gate #endif
220Sstevel@tonic-gate #include <stdio.h>
230Sstevel@tonic-gate #include <unistd.h>
240Sstevel@tonic-gate #include <string.h>
250Sstevel@tonic-gate #include <fcntl.h>
260Sstevel@tonic-gate #include <errno.h>
270Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__GNUC__)
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #endif
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/param.h>
320Sstevel@tonic-gate #include <sys/file.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <stddef.h>
350Sstevel@tonic-gate #include <sys/socket.h>
360Sstevel@tonic-gate #include <sys/ioctl.h>
370Sstevel@tonic-gate #include <netinet/in.h>
380Sstevel@tonic-gate #include <netinet/in_systm.h>
390Sstevel@tonic-gate #include <sys/time.h>
400Sstevel@tonic-gate #include <syslog.h>
410Sstevel@tonic-gate #include <net/if.h>
420Sstevel@tonic-gate #if __FreeBSD_version >= 300000
430Sstevel@tonic-gate # include <net/if_var.h>
440Sstevel@tonic-gate #endif
450Sstevel@tonic-gate #include <netdb.h>
460Sstevel@tonic-gate #include <arpa/nameser.h>
470Sstevel@tonic-gate #include <resolv.h>
480Sstevel@tonic-gate #include "ipf.h"
490Sstevel@tonic-gate #include "netinet/ipl.h"
500Sstevel@tonic-gate #include "ipnat_l.h"
510Sstevel@tonic-gate
520Sstevel@tonic-gate #define YYDEBUG 1
530Sstevel@tonic-gate
540Sstevel@tonic-gate extern void yyerror __P((char *));
550Sstevel@tonic-gate extern int yyparse __P((void));
560Sstevel@tonic-gate extern int yylex __P((void));
570Sstevel@tonic-gate extern int yydebug;
580Sstevel@tonic-gate extern FILE *yyin;
590Sstevel@tonic-gate extern int yylineNum;
600Sstevel@tonic-gate
610Sstevel@tonic-gate static ipnat_t *nattop = NULL;
620Sstevel@tonic-gate static ipnat_t *nat = NULL;
630Sstevel@tonic-gate static int natfd = -1;
640Sstevel@tonic-gate static ioctlfunc_t natioctlfunc = NULL;
650Sstevel@tonic-gate static addfunc_t nataddfunc = NULL;
660Sstevel@tonic-gate
670Sstevel@tonic-gate static void newnatrule __P((void));
680Sstevel@tonic-gate static void setnatproto __P((int));
690Sstevel@tonic-gate
700Sstevel@tonic-gate %}
710Sstevel@tonic-gate %union {
720Sstevel@tonic-gate char *str;
730Sstevel@tonic-gate u_32_t num;
747176Syx160601 struct {
757176Syx160601 i6addr_t a;
767176Syx160601 int v;
777176Syx160601 } ipa;
780Sstevel@tonic-gate frentry_t fr;
790Sstevel@tonic-gate frtuc_t *frt;
802393Syz155240 u_short port;
810Sstevel@tonic-gate struct {
820Sstevel@tonic-gate u_short p1;
830Sstevel@tonic-gate u_short p2;
840Sstevel@tonic-gate int pc;
850Sstevel@tonic-gate } pc;
860Sstevel@tonic-gate struct {
877176Syx160601 i6addr_t a;
887176Syx160601 i6addr_t m;
897176Syx160601 int v;
900Sstevel@tonic-gate } ipp;
910Sstevel@tonic-gate union i6addr ip6;
920Sstevel@tonic-gate };
930Sstevel@tonic-gate
940Sstevel@tonic-gate %token <num> YY_NUMBER YY_HEX
950Sstevel@tonic-gate %token <str> YY_STR
960Sstevel@tonic-gate %token YY_COMMENT
970Sstevel@tonic-gate %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
980Sstevel@tonic-gate %token YY_RANGE_OUT YY_RANGE_IN
990Sstevel@tonic-gate %token <ip6> YY_IPV6
1000Sstevel@tonic-gate
1010Sstevel@tonic-gate %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
1020Sstevel@tonic-gate %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
1030Sstevel@tonic-gate %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
1040Sstevel@tonic-gate %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
105*7259Sdr146992 %token IPNY_TLATE IPNY_SEQUENTIAL
1062393Syz155240 %type <port> portspec
1072393Syz155240 %type <num> hexnumber compare range proto
1087176Syx160601 %type <num> saddr daddr sobject dobject mapfrom rdrfrom dip
1097176Syx160601 %type <ipa> hostname ipv4 ipaddr
1107176Syx160601 %type <ipp> addr rhaddr
1110Sstevel@tonic-gate %type <pc> portstuff
1120Sstevel@tonic-gate %%
1130Sstevel@tonic-gate file: line
1140Sstevel@tonic-gate | assign
1150Sstevel@tonic-gate | file line
1160Sstevel@tonic-gate | file assign
1170Sstevel@tonic-gate ;
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate line: xx rule { while ((nat = nattop) != NULL) {
1207176Syx160601 if (nat->in_v == 0)
1217176Syx160601 nat->in_v = 4;
1220Sstevel@tonic-gate nattop = nat->in_next;
1230Sstevel@tonic-gate (*nataddfunc)(natfd, natioctlfunc, nat);
1240Sstevel@tonic-gate free(nat);
1250Sstevel@tonic-gate }
1260Sstevel@tonic-gate resetlexer();
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate | YY_COMMENT
1290Sstevel@tonic-gate ;
1300Sstevel@tonic-gate
1310Sstevel@tonic-gate assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
1320Sstevel@tonic-gate resetlexer();
1330Sstevel@tonic-gate free($1);
1340Sstevel@tonic-gate free($3);
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate ;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate assigning:
1390Sstevel@tonic-gate '=' { yyvarnext = 1; }
1400Sstevel@tonic-gate ;
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate xx: { newnatrule(); }
1430Sstevel@tonic-gate ;
1440Sstevel@tonic-gate
1452393Syz155240 rule: map eol
1462393Syz155240 | mapblock eol
1472393Syz155240 | redir eol
1482393Syz155240 ;
1492393Syz155240
1502393Syz155240 eol: | ';'
1510Sstevel@tonic-gate ;
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate map: mapit ifnames addr IPNY_TLATE rhaddr proxy mapoptions
1547176Syx160601 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
1557176Syx160601 yyerror("1.address family mismatch");
1567176Syx160601 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
1577176Syx160601 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
1587176Syx160601 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1597176Syx160601 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1600Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
1610Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
1620Sstevel@tonic-gate nat->in_ifnames[0],
1630Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
1640Sstevel@tonic-gate if ((nat->in_flags & IPN_TCPUDP) == 0)
1650Sstevel@tonic-gate setnatproto(nat->in_p);
1660Sstevel@tonic-gate if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1670Sstevel@tonic-gate ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1680Sstevel@tonic-gate nat_setgroupmap(nat);
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate | mapit ifnames addr IPNY_TLATE rhaddr mapport mapoptions
1717176Syx160601 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
1727176Syx160601 yyerror("2.address family mismatch");
1737176Syx160601 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
1747176Syx160601 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
1757176Syx160601 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1767176Syx160601 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1770Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
1780Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
1790Sstevel@tonic-gate nat->in_ifnames[0],
1800Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
1812393Syz155240 if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
1822393Syz155240 setnatproto(nat->in_p);
1832393Syz155240 if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1842393Syz155240 ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
1852393Syz155240 nat_setgroupmap(nat);
1862393Syz155240 }
1872393Syz155240 | mapit ifnames mapfrom IPNY_TLATE rhaddr proxy mapoptions
1887176Syx160601 { if ($3 != 0 && $3 != $5.v && $5.v != 0)
1897176Syx160601 yyerror("3.address family mismatch");
1907176Syx160601 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
1917176Syx160601 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
1922393Syz155240 if (nat->in_ifnames[1][0] == '\0')
1932393Syz155240 strncpy(nat->in_ifnames[1],
1942393Syz155240 nat->in_ifnames[0],
1952393Syz155240 sizeof(nat->in_ifnames[0]));
1960Sstevel@tonic-gate if ((nat->in_flags & IPN_TCPUDP) == 0)
1970Sstevel@tonic-gate setnatproto(nat->in_p);
1980Sstevel@tonic-gate if (((nat->in_redir & NAT_MAPBLK) != 0) ||
1990Sstevel@tonic-gate ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2000Sstevel@tonic-gate nat_setgroupmap(nat);
2010Sstevel@tonic-gate }
2022393Syz155240 | mapit ifnames mapfrom IPNY_TLATE rhaddr mapport mapoptions
2037176Syx160601 { if ($3 != 0 && $3 != $5.v && $5.v != 0)
2047176Syx160601 yyerror("4.address family mismatch");
2057176Syx160601 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
2067176Syx160601 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2070Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
2080Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
2090Sstevel@tonic-gate nat->in_ifnames[0],
2100Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
2112393Syz155240 if ((nat->in_flags & IPN_TCPUDPICMPQ) == 0)
2120Sstevel@tonic-gate setnatproto(nat->in_p);
2130Sstevel@tonic-gate if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2140Sstevel@tonic-gate ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2150Sstevel@tonic-gate nat_setgroupmap(nat);
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate ;
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate mapblock:
2200Sstevel@tonic-gate mapblockit ifnames addr IPNY_TLATE addr ports mapoptions
2217176Syx160601 { if ($3.v != 0 && $3.v != $5.v && $5.v != 0)
2227176Syx160601 yyerror("5.address family mismatch");
2237176Syx160601 bcopy(&$3.a, &nat->in_in[0], sizeof($3.a));
2247176Syx160601 bcopy(&$3.m, &nat->in_in[1], sizeof($3.a));
2257176Syx160601 bcopy(&$5.a, &nat->in_out[0], sizeof($5.a));
2267176Syx160601 bcopy(&$5.m, &nat->in_out[1], sizeof($5.a));
2270Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
2280Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
2290Sstevel@tonic-gate nat->in_ifnames[0],
2300Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
2310Sstevel@tonic-gate if ((nat->in_flags & IPN_TCPUDP) == 0)
2320Sstevel@tonic-gate setnatproto(nat->in_p);
2330Sstevel@tonic-gate if (((nat->in_redir & NAT_MAPBLK) != 0) ||
2340Sstevel@tonic-gate ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
2350Sstevel@tonic-gate nat_setgroupmap(nat);
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate ;
2380Sstevel@tonic-gate
2392393Syz155240 redir: rdrit ifnames addr dport IPNY_TLATE dip nport setproto rdroptions
2407176Syx160601 { if ($6 != 0 && $3.v != 0 && $6 != $3.v)
2417176Syx160601 yyerror("6.address family mismatch");
2427176Syx160601 bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
2437176Syx160601 bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2440Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
2450Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
2460Sstevel@tonic-gate nat->in_ifnames[0],
2470Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
2480Sstevel@tonic-gate if ((nat->in_p == 0) &&
2490Sstevel@tonic-gate ((nat->in_flags & IPN_TCPUDP) == 0) &&
2500Sstevel@tonic-gate (nat->in_pmin != 0 ||
2510Sstevel@tonic-gate nat->in_pmax != 0 ||
2520Sstevel@tonic-gate nat->in_pnext != 0))
2530Sstevel@tonic-gate setnatproto(IPPROTO_TCP);
2540Sstevel@tonic-gate }
2552393Syz155240 | rdrit ifnames rdrfrom IPNY_TLATE dip nport setproto rdroptions
2567176Syx160601 { if ($5 != 0 && $3 != 0 && $5 != $3)
2577176Syx160601 yyerror("7.address family mismatch");
2582393Syz155240 if ((nat->in_p == 0) &&
2590Sstevel@tonic-gate ((nat->in_flags & IPN_TCPUDP) == 0) &&
2600Sstevel@tonic-gate (nat->in_pmin != 0 ||
2610Sstevel@tonic-gate nat->in_pmax != 0 ||
2620Sstevel@tonic-gate nat->in_pnext != 0))
2630Sstevel@tonic-gate setnatproto(IPPROTO_TCP);
2640Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
2650Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
2660Sstevel@tonic-gate nat->in_ifnames[0],
2670Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
2680Sstevel@tonic-gate }
2692393Syz155240 | rdrit ifnames addr IPNY_TLATE dip setproto rdroptions
2707176Syx160601 { if ($5 != 0 && $3.v != 0 && $5 != $3.v)
2717176Syx160601 yyerror("8.address family mismatch");
2727176Syx160601 bcopy(&$3.a, &nat->in_out[0], sizeof($3.a));
2737176Syx160601 bcopy(&$3.m, &nat->in_out[1], sizeof($3.a));
2740Sstevel@tonic-gate if (nat->in_ifnames[1][0] == '\0')
2750Sstevel@tonic-gate strncpy(nat->in_ifnames[1],
2760Sstevel@tonic-gate nat->in_ifnames[0],
2770Sstevel@tonic-gate sizeof(nat->in_ifnames[0]));
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate ;
2800Sstevel@tonic-gate
2812393Syz155240 proxy: | IPNY_PROXY IPNY_PORT portspec YY_STR '/' proto
2820Sstevel@tonic-gate { strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
2830Sstevel@tonic-gate if (nat->in_dcmp == 0) {
2840Sstevel@tonic-gate nat->in_dport = htons($3);
2850Sstevel@tonic-gate } else if ($3 != nat->in_dport) {
2860Sstevel@tonic-gate yyerror("proxy port numbers not consistant");
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate setnatproto($6);
2890Sstevel@tonic-gate free($4);
2900Sstevel@tonic-gate }
2910Sstevel@tonic-gate | IPNY_PROXY IPNY_PORT YY_STR YY_STR '/' proto
2922393Syz155240 { int pnum;
2932393Syz155240 strncpy(nat->in_plabel, $4, sizeof(nat->in_plabel));
2942393Syz155240 pnum = getportproto($3, $6);
2952393Syz155240 if (pnum == -1)
2962393Syz155240 yyerror("invalid port number");
2972393Syz155240 nat->in_dport = pnum;
2980Sstevel@tonic-gate setnatproto($6);
2990Sstevel@tonic-gate free($3);
3000Sstevel@tonic-gate free($4);
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate ;
3030Sstevel@tonic-gate
3042393Syz155240 setproto:
3052393Syz155240 | proto { if (nat->in_p != 0 ||
3062393Syz155240 nat->in_flags & IPN_TCPUDP)
3072393Syz155240 yyerror("protocol set twice");
3082393Syz155240 setnatproto($1);
3092393Syz155240 }
3102393Syz155240 | IPNY_TCPUDP { if (nat->in_p != 0 ||
3112393Syz155240 nat->in_flags & IPN_TCPUDP)
3122393Syz155240 yyerror("protocol set twice");
3132393Syz155240 nat->in_flags |= IPN_TCPUDP;
3142393Syz155240 nat->in_p = 0;
3152393Syz155240 }
3162393Syz155240 | IPNY_TCP '/' IPNY_UDP { if (nat->in_p != 0 ||
3172393Syz155240 nat->in_flags & IPN_TCPUDP)
3182393Syz155240 yyerror("protocol set twice");
3192393Syz155240 nat->in_flags |= IPN_TCPUDP;
3202393Syz155240 nat->in_p = 0;
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate ;
3230Sstevel@tonic-gate
3247176Syx160601 rhaddr: addr { $$.a = $1.a;
3257176Syx160601 $$.m = $1.m;
3267176Syx160601 $$.v = $1.v;
3277176Syx160601 if ($$.v == 0)
3287176Syx160601 $$.v = nat->in_v;
3297176Syx160601 yyexpectaddr = 0; }
3307176Syx160601 | IPNY_RANGE hostname '-' hostname
3317176Syx160601 { if ($2.v != 0 && $4.v != 0 && $4.v != $2.v)
3327176Syx160601 yyerror("9.address family "
3337176Syx160601 "mismatch");
3347176Syx160601 $$.v = $2.v;
3357176Syx160601 $$.a = $2.a;
3367176Syx160601 $$.m = $4.a;
3377176Syx160601 nat->in_flags |= IPN_IPRANGE;
3387176Syx160601 yyexpectaddr = 0; }
3392393Syz155240 ;
3402393Syz155240
3410Sstevel@tonic-gate dip:
3427176Syx160601 hostname { bcopy(&$1.a, &nat->in_in[0],
3437176Syx160601 sizeof($1.a));
3447176Syx160601 if ($1.v == 0)
3457176Syx160601 $1.v = nat->in_v;
3467176Syx160601 if ($1.v == 4) {
3477176Syx160601 nat->in_inmsk = 0xffffffff;
3487176Syx160601 } else {
3497176Syx160601 nat->in_in[1].i6[0] = 0xffffffff;
3507176Syx160601 nat->in_in[1].i6[1] = 0xffffffff;
3517176Syx160601 nat->in_in[1].i6[2] = 0xffffffff;
3527176Syx160601 nat->in_in[1].i6[3] = 0xffffffff;
3537176Syx160601 }
3547176Syx160601 $$ = $1.v;
3557176Syx160601 }
3567176Syx160601 | hostname '/' YY_NUMBER { if ($1.v == 0)
3577176Syx160601 $1.v = nat->in_v;
3587176Syx160601 if ($1.v == 4 &&
3597176Syx160601 ($1.a.in4.s_addr != 0 ||
3607176Syx160601 ($3 != 0 && $3 != 32)))
3617176Syx160601 yyerror("Invalid mask for dip");
3627176Syx160601 else if ($1.v == 6 &&
3637176Syx160601 ($1.a.in4.s_addr != 0 ||
3647176Syx160601 ($3 != 0 && $3 != 128)))
3652873Sjojemann yyerror("Invalid mask for dip");
3667176Syx160601 else if ($1.v == 0 ) {
3677176Syx160601 if ($1.a.in4.s_addr == 0 &&
3687176Syx160601 ($3 == 32 || $3 == 0))
3697176Syx160601 $1.v = 4;
3707176Syx160601 else if ($3 == 128)
3717176Syx160601 $1.v = 6;
3727176Syx160601 }
3737176Syx160601 bcopy(&$1.a, &nat->in_in[0],
3747176Syx160601 sizeof($1.a));
3757176Syx160601 ntomask($1.v, $3,
3767176Syx160601 (u_32_t *)&nat->in_in[1]);
3777176Syx160601 nat->in_in[0].i6[0] &= nat->in_in[1].i6[0];
3787176Syx160601 nat->in_in[0].i6[0] &= nat->in_in[1].i6[1];
3797176Syx160601 nat->in_in[0].i6[0] &= nat->in_in[1].i6[2];
3807176Syx160601 nat->in_in[0].i6[0] &= nat->in_in[1].i6[3];
3817176Syx160601 nat->in_v = $1.v;
3827176Syx160601 $$ = $1.v;
3837176Syx160601 }
3847176Syx160601 | hostname ',' { yyexpectaddr = 1; } hostname
3857176Syx160601 { if ($1.v != $4.v)
3867176Syx160601 yyerror("10.address family "
3877176Syx160601 "mismatch");
3887176Syx160601 $$ = $1.v;
3897176Syx160601 nat->in_flags |= IPN_SPLIT;
3907176Syx160601 bcopy(&$1.a, &nat->in_in[0],
3917176Syx160601 sizeof($1.a));
3927176Syx160601 bcopy(&$4.a, &nat->in_in[1],
3937176Syx160601 sizeof($4.a));
3947176Syx160601 yyexpectaddr = 0; }
3950Sstevel@tonic-gate ;
3960Sstevel@tonic-gate
3972393Syz155240 portspec:
3982393Syz155240 YY_NUMBER { if ($1 > 65535) /* Unsigned */
3992393Syz155240 yyerror("invalid port number");
4002393Syz155240 else
4012393Syz155240 $$ = $1;
4022393Syz155240 }
4032393Syz155240 | YY_STR { if (getport(NULL, $1, &($$)) == -1)
4042393Syz155240 yyerror("invalid port number");
4052393Syz155240 $$ = ntohs($$);
4062393Syz155240 }
4072393Syz155240 ;
4082393Syz155240
4092393Syz155240 dport: | IPNY_PORT portspec { nat->in_pmin = htons($2);
4100Sstevel@tonic-gate nat->in_pmax = htons($2); }
4112393Syz155240 | IPNY_PORT portspec '-' portspec { nat->in_pmin = htons($2);
4122393Syz155240 nat->in_pmax = htons($4); }
4132393Syz155240 | IPNY_PORT portspec ':' portspec { nat->in_pmin = htons($2);
4140Sstevel@tonic-gate nat->in_pmax = htons($4); }
4150Sstevel@tonic-gate ;
4160Sstevel@tonic-gate
4172393Syz155240 nport: IPNY_PORT portspec { nat->in_pnext = htons($2); }
4182393Syz155240 | IPNY_PORT '=' portspec { nat->in_pnext = htons($3);
4192393Syz155240 nat->in_flags |= IPN_FIXEDDPORT;
4202393Syz155240 }
4210Sstevel@tonic-gate ;
4220Sstevel@tonic-gate
4232393Syz155240 ports: | IPNY_PORTS YY_NUMBER { nat->in_pmin = $2; }
4240Sstevel@tonic-gate | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; }
4250Sstevel@tonic-gate ;
4260Sstevel@tonic-gate
4270Sstevel@tonic-gate mapit: IPNY_MAP { nat->in_redir = NAT_MAP; }
4280Sstevel@tonic-gate | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; }
4290Sstevel@tonic-gate ;
4300Sstevel@tonic-gate
4310Sstevel@tonic-gate rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; }
4320Sstevel@tonic-gate ;
4330Sstevel@tonic-gate
4340Sstevel@tonic-gate mapblockit:
4350Sstevel@tonic-gate IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; }
4360Sstevel@tonic-gate ;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate mapfrom:
4397176Syx160601 from sobject IPNY_TO dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
4407176Syx160601 yyerror("11.address family "
4417176Syx160601 "mismatch");
4427176Syx160601 $$ = $2;
4437176Syx160601 }
4440Sstevel@tonic-gate | from sobject '!' IPNY_TO dobject
4457176Syx160601 { if ($2 != 0 && $5 != 0 && $2 != $5)
4467176Syx160601 yyerror("12.address family "
4477176Syx160601 "mismatch");
4487176Syx160601 nat->in_flags |= IPN_NOTDST;
4497176Syx160601 $$ = $2;
4507176Syx160601 }
4510Sstevel@tonic-gate ;
4520Sstevel@tonic-gate
4530Sstevel@tonic-gate rdrfrom:
4547176Syx160601 from sobject IPNY_TO dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
4557176Syx160601 yyerror("13.address family "
4567176Syx160601 "mismatch");
4577176Syx160601 $$ = $2;
4587176Syx160601 }
4590Sstevel@tonic-gate | '!' from sobject IPNY_TO dobject
4607176Syx160601 { if ($3 != 0 && $5 != 0 && $3 != $5)
4617176Syx160601 yyerror("14.address family "
4627176Syx160601 "mismatch");
4637176Syx160601 nat->in_flags |= IPN_NOTSRC;
4647176Syx160601 $$ = $3;
4657176Syx160601 }
4660Sstevel@tonic-gate ;
4670Sstevel@tonic-gate
4687176Syx160601 from: IPNY_FROM { nat->in_flags |= IPN_FILTER;
4697176Syx160601 yyexpectaddr = 1; }
4700Sstevel@tonic-gate ;
4710Sstevel@tonic-gate
4720Sstevel@tonic-gate ifnames:
4737176Syx160601 ifname { yyexpectaddr = 1; }
4747176Syx160601 | ifname ',' otherifname { yyexpectaddr = 1; }
4750Sstevel@tonic-gate ;
4760Sstevel@tonic-gate
4772393Syz155240 ifname: YY_STR { strncpy(nat->in_ifnames[0], $1,
4782393Syz155240 sizeof(nat->in_ifnames[0]));
4792393Syz155240 nat->in_ifnames[0][LIFNAMSIZ - 1] = '\0';
4802393Syz155240 free($1);
4812393Syz155240 }
4820Sstevel@tonic-gate ;
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate otherifname:
4852393Syz155240 YY_STR { strncpy(nat->in_ifnames[1], $1,
4862393Syz155240 sizeof(nat->in_ifnames[1]));
4872393Syz155240 nat->in_ifnames[1][LIFNAMSIZ - 1] = '\0';
4882393Syz155240 free($1);
4892393Syz155240 }
4900Sstevel@tonic-gate ;
4910Sstevel@tonic-gate
4920Sstevel@tonic-gate mapport:
493*7259Sdr146992 IPNY_PORTMAP tcpudp portspec ':' portspec randport
4942393Syz155240 { nat->in_pmin = htons($3);
4952393Syz155240 nat->in_pmax = htons($5);
4962393Syz155240 }
497*7259Sdr146992 | IPNY_PORTMAP tcpudp IPNY_AUTO randport
4982393Syz155240 { nat->in_flags |= IPN_AUTOPORTMAP;
4992393Syz155240 nat->in_pmin = htons(1024);
5002393Syz155240 nat->in_pmax = htons(65535);
5012393Syz155240 }
5022393Syz155240 | IPNY_ICMPIDMAP YY_STR YY_NUMBER ':' YY_NUMBER
5032393Syz155240 { if (strcmp($2, "icmp") != 0) {
5042393Syz155240 yyerror("icmpidmap not followed by icmp");
5052393Syz155240 }
5062393Syz155240 free($2);
5072393Syz155240 if ($3 < 0 || $3 > 65535)
5082393Syz155240 yyerror("invalid ICMP Id number");
5092393Syz155240 if ($5 < 0 || $5 > 65535)
5102393Syz155240 yyerror("invalid ICMP Id number");
5112393Syz155240 nat->in_flags = IPN_ICMPQUERY;
5122393Syz155240 nat->in_pmin = htons($3);
5132393Syz155240 nat->in_pmax = htons($5);
5142393Syz155240 }
5150Sstevel@tonic-gate ;
5160Sstevel@tonic-gate
517*7259Sdr146992 randport:
518*7259Sdr146992 | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; }
519*7259Sdr146992 ;
520*7259Sdr146992
5210Sstevel@tonic-gate sobject:
5227176Syx160601 saddr { $$ = $1; }
5230Sstevel@tonic-gate | saddr IPNY_PORT portstuff { nat->in_sport = $3.p1;
5240Sstevel@tonic-gate nat->in_stop = $3.p2;
5257176Syx160601 nat->in_scmp = $3.pc;
5267176Syx160601 $$ = $1;
5277176Syx160601 }
5280Sstevel@tonic-gate ;
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate saddr: addr { if (nat->in_redir == NAT_REDIRECT) {
5317176Syx160601 bcopy(&$1.a, &nat->in_src[0],
5327176Syx160601 sizeof($1.a));
5337176Syx160601 bcopy(&$1.m, &nat->in_src[1],
5347176Syx160601 sizeof($1.a));
5350Sstevel@tonic-gate } else {
5367176Syx160601 bcopy(&$1.a, &nat->in_in[0],
5377176Syx160601 sizeof($1.a));
5387176Syx160601 bcopy(&$1.m, &nat->in_in[1],
5397176Syx160601 sizeof($1.a));
5400Sstevel@tonic-gate }
5417176Syx160601 $$ = $1.v;
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate ;
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate dobject:
5467176Syx160601 daddr { $$ = $1; }
5470Sstevel@tonic-gate | daddr IPNY_PORT portstuff { nat->in_dport = $3.p1;
5480Sstevel@tonic-gate nat->in_dtop = $3.p2;
5490Sstevel@tonic-gate nat->in_dcmp = $3.pc;
5500Sstevel@tonic-gate if (nat->in_redir == NAT_REDIRECT)
5510Sstevel@tonic-gate nat->in_pmin = htons($3.p1);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate ;
5540Sstevel@tonic-gate
5550Sstevel@tonic-gate daddr: addr { if (nat->in_redir == NAT_REDIRECT) {
5567176Syx160601 bcopy(&$1.a, &nat->in_out[0],
5577176Syx160601 sizeof($1.a));
5587176Syx160601 bcopy(&$1.m, &nat->in_out[1],
5597176Syx160601 sizeof($1.a));
5600Sstevel@tonic-gate } else {
5617176Syx160601 bcopy(&$1.a, &nat->in_src[0],
5627176Syx160601 sizeof($1.a));
5637176Syx160601 bcopy(&$1.m, &nat->in_src[1],
5647176Syx160601 sizeof($1.a));
5650Sstevel@tonic-gate }
5667176Syx160601 $$ = $1.v;
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate ;
5690Sstevel@tonic-gate
5707176Syx160601 addr: IPNY_ANY { yyexpectaddr = 0;
5717176Syx160601 bzero(&$$.a, sizeof($$.a));
5727176Syx160601 bzero(&$$.m, sizeof($$.a));
5737176Syx160601 $$.v = nat->in_v;
5747176Syx160601 }
5757176Syx160601 | hostname { $$.a = $1.a;
5767176Syx160601 $$.v = $1.v;
5777176Syx160601 if ($$.v == 4) {
5787176Syx160601 $$.m.in4.s_addr = 0xffffffff;
5797176Syx160601 } else {
5807176Syx160601 $$.m.i6[0] = 0xffffffff;
5817176Syx160601 $$.m.i6[1] = 0xffffffff;
5827176Syx160601 $$.m.i6[2] = 0xffffffff;
5837176Syx160601 $$.m.i6[3] = 0xffffffff;
5847176Syx160601 }
5857176Syx160601 yyexpectaddr = 0;
5867176Syx160601 }
5877176Syx160601 | hostname '/' YY_NUMBER { $$.a = $1.a;
5887176Syx160601 if ($1.v == 0) {
5897176Syx160601 if ($1.a.in4.s_addr != 0)
5907176Syx160601 yyerror("invalid addr");
5917176Syx160601 if ($3 == 0 || $3 == 32)
5927176Syx160601 $1.v = 4;
5937176Syx160601 else if ($3 == 128)
5947176Syx160601 $1.v = 6;
5957176Syx160601 else
5967176Syx160601 yyerror("invalid mask");
5977176Syx160601 nat->in_v = $1.v;
5987176Syx160601 }
5997176Syx160601 ntomask($1.v, $3, (u_32_t *)&$$.m);
6007176Syx160601 $$.a.i6[0] &= $$.m.i6[0];
6017176Syx160601 $$.a.i6[1] &= $$.m.i6[1];
6027176Syx160601 $$.a.i6[2] &= $$.m.i6[2];
6037176Syx160601 $$.a.i6[3] &= $$.m.i6[3];
6047176Syx160601 $$.v = $1.v;
6057176Syx160601 yyexpectaddr = 0;
6067176Syx160601 }
6077176Syx160601 | hostname '/' ipaddr { if ($1.v != $3.v) {
6087176Syx160601 yyerror("1.address family "
6097176Syx160601 "mismatch");
6107176Syx160601 }
6117176Syx160601 $$.a = $1.a;
6127176Syx160601 $$.m = $3.a;
6137176Syx160601 $$.a.i6[0] &= $$.m.i6[0];
6147176Syx160601 $$.a.i6[1] &= $$.m.i6[1];
6157176Syx160601 $$.a.i6[2] &= $$.m.i6[2];
6167176Syx160601 $$.a.i6[3] &= $$.m.i6[3];
6177176Syx160601 $$.v = $1.v;
6187176Syx160601 yyexpectaddr = 0;
6197176Syx160601 }
6207176Syx160601 | hostname '/' hexnumber { $$.a = $1.a;
6217176Syx160601 $$.m.in4.s_addr = htonl($3);
6227176Syx160601 $$.a.in4.s_addr &= $$.m.in4.s_addr;
6237176Syx160601 $$.v = 4;
6247176Syx160601 }
6257176Syx160601 | hostname IPNY_MASK ipaddr { if ($1.v != $3.v) {
6267176Syx160601 yyerror("2.address family "
6277176Syx160601 "mismatch");
6287176Syx160601 }
6297176Syx160601 $$.a = $1.a;
6307176Syx160601 $$.m = $3.a;
6317176Syx160601 $$.a.i6[0] &= $$.m.i6[0];
6327176Syx160601 $$.a.i6[1] &= $$.m.i6[1];
6337176Syx160601 $$.a.i6[2] &= $$.m.i6[2];
6347176Syx160601 $$.a.i6[3] &= $$.m.i6[3];
6357176Syx160601 $$.v = $1.v;
6367176Syx160601 yyexpectaddr = 0;
6377176Syx160601 }
6387176Syx160601 | hostname IPNY_MASK hexnumber { $$.a = $1.a;
6397176Syx160601 $$.m.in4.s_addr = htonl($3);
6407176Syx160601 $$.a.in4.s_addr &= $$.m.in4.s_addr;
6417176Syx160601 $$.v = 4;
6427176Syx160601 }
6430Sstevel@tonic-gate ;
6440Sstevel@tonic-gate
6450Sstevel@tonic-gate portstuff:
6462393Syz155240 compare portspec { $$.pc = $1; $$.p1 = $2; }
6472873Sjojemann | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
6480Sstevel@tonic-gate ;
6490Sstevel@tonic-gate
6500Sstevel@tonic-gate mapoptions:
6512393Syz155240 rr frag age mssclamp nattag setproto
6520Sstevel@tonic-gate ;
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate rdroptions:
6550Sstevel@tonic-gate rr frag age sticky mssclamp rdrproxy nattag
6560Sstevel@tonic-gate ;
6570Sstevel@tonic-gate
6580Sstevel@tonic-gate nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2,
6590Sstevel@tonic-gate sizeof(nat->in_tag.ipt_tag));
6600Sstevel@tonic-gate }
661*7259Sdr146992
6620Sstevel@tonic-gate rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; }
6630Sstevel@tonic-gate ;
6640Sstevel@tonic-gate
6650Sstevel@tonic-gate frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; }
6660Sstevel@tonic-gate ;
6670Sstevel@tonic-gate
6680Sstevel@tonic-gate age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2;
6690Sstevel@tonic-gate nat->in_age[1] = $2; }
6700Sstevel@tonic-gate | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2;
6710Sstevel@tonic-gate nat->in_age[1] = $4; }
6720Sstevel@tonic-gate ;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) &&
6750Sstevel@tonic-gate !(nat->in_flags & IPN_SPLIT)) {
6760Sstevel@tonic-gate fprintf(stderr,
6770Sstevel@tonic-gate "'sticky' for use with round-robin/IP splitting only\n");
6780Sstevel@tonic-gate } else
6790Sstevel@tonic-gate nat->in_flags |= IPN_STICKY;
6800Sstevel@tonic-gate }
6810Sstevel@tonic-gate ;
6820Sstevel@tonic-gate
6830Sstevel@tonic-gate mssclamp:
6840Sstevel@tonic-gate | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; }
6850Sstevel@tonic-gate ;
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate tcpudp: | IPNY_TCP { setnatproto(IPPROTO_TCP); }
6880Sstevel@tonic-gate | IPNY_UDP { setnatproto(IPPROTO_UDP); }
6890Sstevel@tonic-gate | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP;
6900Sstevel@tonic-gate nat->in_p = 0;
6910Sstevel@tonic-gate }
6920Sstevel@tonic-gate | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP;
6930Sstevel@tonic-gate nat->in_p = 0;
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate ;
6960Sstevel@tonic-gate
6970Sstevel@tonic-gate rdrproxy:
6982393Syz155240 IPNY_PROXY YY_STR
6990Sstevel@tonic-gate { strncpy(nat->in_plabel, $2,
7000Sstevel@tonic-gate sizeof(nat->in_plabel));
7010Sstevel@tonic-gate nat->in_dport = nat->in_pnext;
7022393Syz155240 nat->in_dport = htons(nat->in_dport);
7030Sstevel@tonic-gate free($2);
7040Sstevel@tonic-gate }
7050Sstevel@tonic-gate | proxy { if (nat->in_plabel[0] != '\0') {
7060Sstevel@tonic-gate nat->in_pmin = nat->in_dport;
7070Sstevel@tonic-gate nat->in_pmax = nat->in_pmin;
7080Sstevel@tonic-gate nat->in_pnext = nat->in_pmin;
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate }
7110Sstevel@tonic-gate ;
7120Sstevel@tonic-gate
7130Sstevel@tonic-gate proto: YY_NUMBER { $$ = $1; }
7140Sstevel@tonic-gate | IPNY_TCP { $$ = IPPROTO_TCP; }
7150Sstevel@tonic-gate | IPNY_UDP { $$ = IPPROTO_UDP; }
7160Sstevel@tonic-gate | YY_STR { $$ = getproto($1); free($1); }
7170Sstevel@tonic-gate ;
7180Sstevel@tonic-gate
7190Sstevel@tonic-gate hexnumber:
7200Sstevel@tonic-gate YY_HEX { $$ = $1; }
7210Sstevel@tonic-gate ;
7220Sstevel@tonic-gate
7230Sstevel@tonic-gate hostname:
7247176Syx160601 YY_STR { i6addr_t addr;
7257176Syx160601 if (gethost($1, &addr, 0) == 0) {
7267176Syx160601 $$.a = addr;
7277176Syx160601 $$.v = 4;
7287176Syx160601 } else
7297176Syx160601 if (gethost($1, &addr, 1) == 0) {
7307176Syx160601 $$.a = addr;
7317176Syx160601 $$.v = 6;
7327176Syx160601 } else {
7332609Sjojemann yyerror("Unknown hostname");
7347176Syx160601 }
7357176Syx160601 if ($$.v != 0)
7367176Syx160601 nat->in_v = $$.v;
7377176Syx160601 free($1);
7380Sstevel@tonic-gate }
7397176Syx160601 | YY_NUMBER { bzero(&$$.a, sizeof($$.a));
7407176Syx160601 $$.a.in4.s_addr = htonl($1);
7417176Syx160601 if ($$.a.in4.s_addr != 0)
7427176Syx160601 $$.v = 4;
7437176Syx160601 else
7447176Syx160601 $$.v = nat->in_v;
7457176Syx160601 if ($$.v != 0)
7467176Syx160601 nat->in_v = $$.v;
7477176Syx160601 }
7487176Syx160601 | ipv4 { $$ = $1;
7497176Syx160601 nat->in_v = 4;
7507176Syx160601 }
7517176Syx160601 | YY_IPV6 { $$.a = $1;
7527176Syx160601 $$.v = 6;
7537176Syx160601 nat->in_v = 6;
7547176Syx160601 }
7557176Syx160601 | YY_NUMBER YY_IPV6 { $$.a = $2;
7567176Syx160601 $$.v = 6;
7577176Syx160601 }
7580Sstevel@tonic-gate ;
7590Sstevel@tonic-gate
7600Sstevel@tonic-gate compare:
7610Sstevel@tonic-gate '=' { $$ = FR_EQUAL; }
7620Sstevel@tonic-gate | YY_CMP_EQ { $$ = FR_EQUAL; }
7630Sstevel@tonic-gate | YY_CMP_NE { $$ = FR_NEQUAL; }
7640Sstevel@tonic-gate | YY_CMP_LT { $$ = FR_LESST; }
7650Sstevel@tonic-gate | YY_CMP_LE { $$ = FR_LESSTE; }
7660Sstevel@tonic-gate | YY_CMP_GT { $$ = FR_GREATERT; }
7670Sstevel@tonic-gate | YY_CMP_GE { $$ = FR_GREATERTE; }
7680Sstevel@tonic-gate
7690Sstevel@tonic-gate range:
7700Sstevel@tonic-gate YY_RANGE_OUT { $$ = FR_OUTRANGE; }
7710Sstevel@tonic-gate | YY_RANGE_IN { $$ = FR_INRANGE; }
7720Sstevel@tonic-gate ;
7730Sstevel@tonic-gate
7747176Syx160601 ipaddr: ipv4 { $$ = $1; }
7757176Syx160601 | YY_IPV6 { $$.a = $1;
7767176Syx160601 $$.v = 6;
7777176Syx160601 }
7787176Syx160601 ;
7797176Syx160601
7800Sstevel@tonic-gate ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
7810Sstevel@tonic-gate { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
7820Sstevel@tonic-gate yyerror("Invalid octet string for IP address");
7830Sstevel@tonic-gate return 0;
7840Sstevel@tonic-gate }
7857176Syx160601 $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
7867176Syx160601 $$.a.in4.s_addr = htonl($$.a.in4.s_addr);
7877176Syx160601 $$.v = 4;
7880Sstevel@tonic-gate }
7890Sstevel@tonic-gate ;
7900Sstevel@tonic-gate
7910Sstevel@tonic-gate %%
7920Sstevel@tonic-gate
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate static wordtab_t yywords[] = {
7950Sstevel@tonic-gate { "age", IPNY_AGE },
7960Sstevel@tonic-gate { "any", IPNY_ANY },
7970Sstevel@tonic-gate { "auto", IPNY_AUTO },
7980Sstevel@tonic-gate { "bimap", IPNY_BIMAP },
7990Sstevel@tonic-gate { "frag", IPNY_FRAG },
8000Sstevel@tonic-gate { "from", IPNY_FROM },
8010Sstevel@tonic-gate { "icmpidmap", IPNY_ICMPIDMAP },
8020Sstevel@tonic-gate { "mask", IPNY_MASK },
8030Sstevel@tonic-gate { "map", IPNY_MAP },
8040Sstevel@tonic-gate { "map-block", IPNY_MAPBLOCK },
8050Sstevel@tonic-gate { "mssclamp", IPNY_MSSCLAMP },
8062393Syz155240 { "netmask", IPNY_MASK },
8070Sstevel@tonic-gate { "port", IPNY_PORT },
8080Sstevel@tonic-gate { "portmap", IPNY_PORTMAP },
8090Sstevel@tonic-gate { "ports", IPNY_PORTS },
8100Sstevel@tonic-gate { "proxy", IPNY_PROXY },
8110Sstevel@tonic-gate { "range", IPNY_RANGE },
8120Sstevel@tonic-gate { "rdr", IPNY_RDR },
8130Sstevel@tonic-gate { "round-robin",IPNY_ROUNDROBIN },
814*7259Sdr146992 { "sequential", IPNY_SEQUENTIAL },
8150Sstevel@tonic-gate { "sticky", IPNY_STICKY },
8160Sstevel@tonic-gate { "tag", IPNY_TAG },
8170Sstevel@tonic-gate { "tcp", IPNY_TCP },
8182393Syz155240 { "tcpudp", IPNY_TCPUDP },
8190Sstevel@tonic-gate { "to", IPNY_TO },
8200Sstevel@tonic-gate { "udp", IPNY_UDP },
8210Sstevel@tonic-gate { "-", '-' },
8220Sstevel@tonic-gate { "->", IPNY_TLATE },
8230Sstevel@tonic-gate { "eq", YY_CMP_EQ },
8240Sstevel@tonic-gate { "ne", YY_CMP_NE },
8250Sstevel@tonic-gate { "lt", YY_CMP_LT },
8260Sstevel@tonic-gate { "gt", YY_CMP_GT },
8270Sstevel@tonic-gate { "le", YY_CMP_LE },
8280Sstevel@tonic-gate { "ge", YY_CMP_GE },
8290Sstevel@tonic-gate { NULL, 0 }
8300Sstevel@tonic-gate };
8310Sstevel@tonic-gate
8320Sstevel@tonic-gate
ipnat_parsefile(fd,addfunc,ioctlfunc,filename)8330Sstevel@tonic-gate int ipnat_parsefile(fd, addfunc, ioctlfunc, filename)
8340Sstevel@tonic-gate int fd;
8350Sstevel@tonic-gate addfunc_t addfunc;
8360Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
8370Sstevel@tonic-gate char *filename;
8380Sstevel@tonic-gate {
8390Sstevel@tonic-gate FILE *fp = NULL;
8400Sstevel@tonic-gate char *s;
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate (void) yysettab(yywords);
8430Sstevel@tonic-gate
8440Sstevel@tonic-gate s = getenv("YYDEBUG");
8450Sstevel@tonic-gate if (s)
8460Sstevel@tonic-gate yydebug = atoi(s);
8470Sstevel@tonic-gate else
8480Sstevel@tonic-gate yydebug = 0;
8490Sstevel@tonic-gate
8500Sstevel@tonic-gate if (strcmp(filename, "-")) {
8510Sstevel@tonic-gate fp = fopen(filename, "r");
8520Sstevel@tonic-gate if (!fp) {
8530Sstevel@tonic-gate fprintf(stderr, "fopen(%s) failed: %s\n", filename,
8540Sstevel@tonic-gate STRERROR(errno));
8550Sstevel@tonic-gate return -1;
8560Sstevel@tonic-gate }
8570Sstevel@tonic-gate } else
8580Sstevel@tonic-gate fp = stdin;
8590Sstevel@tonic-gate
8600Sstevel@tonic-gate while (ipnat_parsesome(fd, addfunc, ioctlfunc, fp) == 1)
8610Sstevel@tonic-gate ;
8620Sstevel@tonic-gate if (fp != NULL)
8630Sstevel@tonic-gate fclose(fp);
8640Sstevel@tonic-gate return 0;
8650Sstevel@tonic-gate }
8660Sstevel@tonic-gate
8670Sstevel@tonic-gate
ipnat_parsesome(fd,addfunc,ioctlfunc,fp)8680Sstevel@tonic-gate int ipnat_parsesome(fd, addfunc, ioctlfunc, fp)
8690Sstevel@tonic-gate int fd;
8700Sstevel@tonic-gate addfunc_t addfunc;
8710Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
8720Sstevel@tonic-gate FILE *fp;
8730Sstevel@tonic-gate {
8740Sstevel@tonic-gate char *s;
8750Sstevel@tonic-gate int i;
8760Sstevel@tonic-gate
8770Sstevel@tonic-gate yylineNum = 1;
8780Sstevel@tonic-gate
8790Sstevel@tonic-gate natfd = fd;
8800Sstevel@tonic-gate nataddfunc = addfunc;
8810Sstevel@tonic-gate natioctlfunc = ioctlfunc;
8820Sstevel@tonic-gate
8830Sstevel@tonic-gate if (feof(fp))
8840Sstevel@tonic-gate return 0;
8850Sstevel@tonic-gate i = fgetc(fp);
8860Sstevel@tonic-gate if (i == EOF)
8870Sstevel@tonic-gate return 0;
8880Sstevel@tonic-gate if (ungetc(i, fp) == EOF)
8890Sstevel@tonic-gate return 0;
8900Sstevel@tonic-gate if (feof(fp))
8910Sstevel@tonic-gate return 0;
8920Sstevel@tonic-gate s = getenv("YYDEBUG");
8930Sstevel@tonic-gate if (s)
8940Sstevel@tonic-gate yydebug = atoi(s);
8950Sstevel@tonic-gate else
8960Sstevel@tonic-gate yydebug = 0;
8970Sstevel@tonic-gate
8980Sstevel@tonic-gate yyin = fp;
8990Sstevel@tonic-gate yyparse();
9000Sstevel@tonic-gate return 1;
9010Sstevel@tonic-gate }
9020Sstevel@tonic-gate
9030Sstevel@tonic-gate
newnatrule()9040Sstevel@tonic-gate static void newnatrule()
9050Sstevel@tonic-gate {
9060Sstevel@tonic-gate ipnat_t *n;
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate n = calloc(1, sizeof(*n));
9090Sstevel@tonic-gate if (n == NULL)
9100Sstevel@tonic-gate return;
9110Sstevel@tonic-gate
9120Sstevel@tonic-gate if (nat == NULL)
9130Sstevel@tonic-gate nattop = nat = n;
9140Sstevel@tonic-gate else {
9150Sstevel@tonic-gate nat->in_next = n;
9160Sstevel@tonic-gate nat = n;
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate
9200Sstevel@tonic-gate
setnatproto(p)9210Sstevel@tonic-gate static void setnatproto(p)
9220Sstevel@tonic-gate int p;
9230Sstevel@tonic-gate {
9240Sstevel@tonic-gate nat->in_p = p;
9250Sstevel@tonic-gate
9260Sstevel@tonic-gate switch (p)
9270Sstevel@tonic-gate {
9280Sstevel@tonic-gate case IPPROTO_TCP :
9290Sstevel@tonic-gate nat->in_flags |= IPN_TCP;
9300Sstevel@tonic-gate nat->in_flags &= ~IPN_UDP;
9310Sstevel@tonic-gate break;
9320Sstevel@tonic-gate case IPPROTO_UDP :
9330Sstevel@tonic-gate nat->in_flags |= IPN_UDP;
9340Sstevel@tonic-gate nat->in_flags &= ~IPN_TCP;
9350Sstevel@tonic-gate break;
9362393Syz155240 case IPPROTO_ICMP :
9372393Syz155240 nat->in_flags &= ~IPN_TCPUDP;
9382393Syz155240 if (!(nat->in_flags & IPN_ICMPQUERY)) {
9392393Syz155240 nat->in_dcmp = 0;
9402393Syz155240 nat->in_scmp = 0;
9412393Syz155240 nat->in_pmin = 0;
9422393Syz155240 nat->in_pmax = 0;
9432393Syz155240 nat->in_pnext = 0;
9442393Syz155240 }
9452393Syz155240 break;
9460Sstevel@tonic-gate default :
9470Sstevel@tonic-gate if ((nat->in_redir & NAT_MAPBLK) == 0) {
9482393Syz155240 /* Only reset dcmp/scmp in case dport/sport not set */
9492393Syz155240 if (0 == nat->in_tuc.ftu_dport)
9502393Syz155240 nat->in_dcmp = 0;
9512393Syz155240 if (0 == nat->in_tuc.ftu_sport)
9522393Syz155240 nat->in_scmp = 0;
9530Sstevel@tonic-gate nat->in_pmin = 0;
9540Sstevel@tonic-gate nat->in_pmax = 0;
9550Sstevel@tonic-gate nat->in_pnext = 0;
9560Sstevel@tonic-gate nat->in_flags &= ~IPN_TCPUDP;
9570Sstevel@tonic-gate }
9580Sstevel@tonic-gate break;
9590Sstevel@tonic-gate }
9602393Syz155240
9612393Syz155240 if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
9622393Syz155240 nat->in_flags &= ~IPN_FIXEDDPORT;
9630Sstevel@tonic-gate }
9640Sstevel@tonic-gate
9650Sstevel@tonic-gate
ipnat_addrule(fd,ioctlfunc,ptr)9660Sstevel@tonic-gate void ipnat_addrule(fd, ioctlfunc, ptr)
9670Sstevel@tonic-gate int fd;
9680Sstevel@tonic-gate ioctlfunc_t ioctlfunc;
9690Sstevel@tonic-gate void *ptr;
9700Sstevel@tonic-gate {
9712393Syz155240 ioctlcmd_t add, del;
9720Sstevel@tonic-gate ipfobj_t obj;
9730Sstevel@tonic-gate ipnat_t *ipn;
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate ipn = ptr;
9760Sstevel@tonic-gate bzero((char *)&obj, sizeof(obj));
9770Sstevel@tonic-gate obj.ipfo_rev = IPFILTER_VERSION;
9780Sstevel@tonic-gate obj.ipfo_size = sizeof(ipnat_t);
9790Sstevel@tonic-gate obj.ipfo_type = IPFOBJ_IPNAT;
9800Sstevel@tonic-gate obj.ipfo_ptr = ptr;
9810Sstevel@tonic-gate add = 0;
9820Sstevel@tonic-gate del = 0;
9830Sstevel@tonic-gate
9840Sstevel@tonic-gate if ((opts & OPT_DONOTHING) != 0)
9850Sstevel@tonic-gate fd = -1;
9860Sstevel@tonic-gate
9870Sstevel@tonic-gate if (opts & OPT_ZERORULEST) {
9880Sstevel@tonic-gate add = SIOCZRLST;
9890Sstevel@tonic-gate } else if (opts & OPT_INACTIVE) {
9900Sstevel@tonic-gate add = SIOCADNAT;
9910Sstevel@tonic-gate del = SIOCRMNAT;
9920Sstevel@tonic-gate } else {
9930Sstevel@tonic-gate add = SIOCADNAT;
9940Sstevel@tonic-gate del = SIOCRMNAT;
9950Sstevel@tonic-gate }
9960Sstevel@tonic-gate
9970Sstevel@tonic-gate if (ipn && (opts & OPT_VERBOSE))
9980Sstevel@tonic-gate printnat(ipn, opts);
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate if (opts & OPT_DEBUG)
10010Sstevel@tonic-gate binprint(ipn, sizeof(*ipn));
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate if ((opts & OPT_ZERORULEST) != 0) {
10040Sstevel@tonic-gate if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
10050Sstevel@tonic-gate if ((opts & OPT_DONOTHING) == 0) {
10060Sstevel@tonic-gate fprintf(stderr, "%d:", yylineNum);
10070Sstevel@tonic-gate perror("ioctl(SIOCZRLST)");
10080Sstevel@tonic-gate }
10090Sstevel@tonic-gate } else {
10100Sstevel@tonic-gate #ifdef USE_QUAD_T
10110Sstevel@tonic-gate /*
10120Sstevel@tonic-gate printf("hits %qd bytes %qd ",
10130Sstevel@tonic-gate (long long)fr->fr_hits,
10140Sstevel@tonic-gate (long long)fr->fr_bytes);
10150Sstevel@tonic-gate */
10160Sstevel@tonic-gate #else
10170Sstevel@tonic-gate /*
10180Sstevel@tonic-gate printf("hits %ld bytes %ld ",
10190Sstevel@tonic-gate fr->fr_hits, fr->fr_bytes);
10200Sstevel@tonic-gate */
10210Sstevel@tonic-gate #endif
10220Sstevel@tonic-gate printnat(ipn, opts);
10230Sstevel@tonic-gate }
10240Sstevel@tonic-gate } else if ((opts & OPT_REMOVE) != 0) {
10250Sstevel@tonic-gate if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
10260Sstevel@tonic-gate if ((opts & OPT_DONOTHING) == 0) {
10270Sstevel@tonic-gate fprintf(stderr, "%d:", yylineNum);
10280Sstevel@tonic-gate perror("ioctl(delete nat rule)");
10290Sstevel@tonic-gate }
10300Sstevel@tonic-gate }
10310Sstevel@tonic-gate } else {
10320Sstevel@tonic-gate if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
10330Sstevel@tonic-gate if ((opts & OPT_DONOTHING) == 0) {
10340Sstevel@tonic-gate fprintf(stderr, "%d:", yylineNum);
10350Sstevel@tonic-gate perror("ioctl(add/insert nat rule)");
10360Sstevel@tonic-gate }
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate }
10390Sstevel@tonic-gate }
10402609Sjojemann
1041