141edb306SCy Schubert
241edb306SCy Schubert /*
341edb306SCy Schubert * Copyright (C) 2012 by Darren Reed.
441edb306SCy Schubert *
541edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing.
641edb306SCy Schubert */
741edb306SCy Schubert %{
841edb306SCy Schubert #include <stdio.h>
941edb306SCy Schubert #include <unistd.h>
1041edb306SCy Schubert #include <string.h>
1141edb306SCy Schubert #include <fcntl.h>
1241edb306SCy Schubert #include <errno.h>
1341edb306SCy Schubert #if !defined(__SVR4) && !defined(__GNUC__)
1441edb306SCy Schubert #include <strings.h>
1541edb306SCy Schubert #endif
1641edb306SCy Schubert #include <sys/types.h>
1741edb306SCy Schubert #include <sys/param.h>
1841edb306SCy Schubert #include <sys/file.h>
1941edb306SCy Schubert #include <stdlib.h>
2041edb306SCy Schubert #include <stddef.h>
2141edb306SCy Schubert #include <sys/socket.h>
2241edb306SCy Schubert #include <sys/ioctl.h>
2341edb306SCy Schubert #include <netinet/in.h>
2441edb306SCy Schubert #include <netinet/in_systm.h>
2541edb306SCy Schubert #include <sys/time.h>
2641edb306SCy Schubert #include <syslog.h>
2741edb306SCy Schubert #include <net/if.h>
2841edb306SCy Schubert #include <netdb.h>
2941edb306SCy Schubert #include <arpa/nameser.h>
3041edb306SCy Schubert #include <resolv.h>
3141edb306SCy Schubert #include "ipf.h"
3241edb306SCy Schubert #include "netinet/ipl.h"
3341edb306SCy Schubert #include "ipnat_l.h"
3441edb306SCy Schubert
3541edb306SCy Schubert #define YYDEBUG 1
3641edb306SCy Schubert
3741edb306SCy Schubert extern void yyerror(char *);
3841edb306SCy Schubert extern int yyparse(void);
3941edb306SCy Schubert extern int yylex(void);
4041edb306SCy Schubert extern int yydebug;
4141edb306SCy Schubert extern FILE *yyin;
4241edb306SCy Schubert extern int yylineNum;
4341edb306SCy Schubert
4441edb306SCy Schubert static ipnat_t *nattop = NULL;
4541edb306SCy Schubert static ipnat_t *nat = NULL;
4641edb306SCy Schubert static int natfd = -1;
4741edb306SCy Schubert static ioctlfunc_t natioctlfunc = NULL;
4841edb306SCy Schubert static addfunc_t nataddfunc = NULL;
4941edb306SCy Schubert static int suggest_port = 0;
5041edb306SCy Schubert static proxyrule_t *prules = NULL;
5141edb306SCy Schubert static int parser_error = 0;
5241edb306SCy Schubert
5341edb306SCy Schubert static void newnatrule(void);
5441edb306SCy Schubert static void setnatproto(int);
5541edb306SCy Schubert static void setmapifnames(void);
5641edb306SCy Schubert static void setrdrifnames(void);
5741edb306SCy Schubert static void proxy_setconfig(int);
5841edb306SCy Schubert static void proxy_unsetconfig(void);
5941edb306SCy Schubert static namelist_t *proxy_dns_add_pass(char *, char *);
6041edb306SCy Schubert static namelist_t *proxy_dns_add_block(char *, char *);
6141edb306SCy Schubert static void proxy_addconfig(char *, int, char *, namelist_t *);
6241edb306SCy Schubert static void proxy_loadconfig(int, ioctlfunc_t, char *, int,
6341edb306SCy Schubert char *, namelist_t *);
6441edb306SCy Schubert static void proxy_loadrules(int, ioctlfunc_t, proxyrule_t *);
6541edb306SCy Schubert static void setmapifnames(void);
6641edb306SCy Schubert static void setrdrifnames(void);
6741edb306SCy Schubert static void setifname(ipnat_t **, int, char *);
6841edb306SCy Schubert static int addname(ipnat_t **, char *);
6941edb306SCy Schubert %}
7041edb306SCy Schubert %union {
7141edb306SCy Schubert char *str;
7241edb306SCy Schubert u_32_t num;
7341edb306SCy Schubert struct {
7441edb306SCy Schubert i6addr_t a;
7541edb306SCy Schubert int f;
7641edb306SCy Schubert } ipa;
7741edb306SCy Schubert frentry_t fr;
7841edb306SCy Schubert frtuc_t *frt;
7941edb306SCy Schubert u_short port;
8041edb306SCy Schubert struct {
8141edb306SCy Schubert int p1;
8241edb306SCy Schubert int p2;
8341edb306SCy Schubert int pc;
8441edb306SCy Schubert } pc;
8541edb306SCy Schubert struct {
8641edb306SCy Schubert i6addr_t a;
8741edb306SCy Schubert i6addr_t m;
8841edb306SCy Schubert int t; /* Address type */
8941edb306SCy Schubert int u;
9041edb306SCy Schubert int f; /* Family */
9141edb306SCy Schubert int v; /* IP version */
9241edb306SCy Schubert int s; /* 0 = number, 1 = text */
9341edb306SCy Schubert int n; /* number */
9441edb306SCy Schubert } ipp;
9541edb306SCy Schubert union i6addr ip6;
9641edb306SCy Schubert namelist_t *names;
9741edb306SCy Schubert };
9841edb306SCy Schubert
9941edb306SCy Schubert %token <num> YY_NUMBER YY_HEX
10041edb306SCy Schubert %token <str> YY_STR
10141edb306SCy Schubert %token YY_COMMENT
10241edb306SCy Schubert %token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
10341edb306SCy Schubert %token YY_RANGE_OUT YY_RANGE_IN
10441edb306SCy Schubert %token <ip6> YY_IPV6
10541edb306SCy Schubert
10641edb306SCy Schubert %token IPNY_MAPBLOCK IPNY_RDR IPNY_PORT IPNY_PORTS IPNY_AUTO IPNY_RANGE
10741edb306SCy Schubert %token IPNY_MAP IPNY_BIMAP IPNY_FROM IPNY_TO IPNY_MASK IPNY_PORTMAP IPNY_ANY
10841edb306SCy Schubert %token IPNY_ROUNDROBIN IPNY_FRAG IPNY_AGE IPNY_ICMPIDMAP IPNY_PROXY
10941edb306SCy Schubert %token IPNY_TCP IPNY_UDP IPNY_TCPUDP IPNY_STICKY IPNY_MSSCLAMP IPNY_TAG
11041edb306SCy Schubert %token IPNY_TLATE IPNY_POOL IPNY_HASH IPNY_NO IPNY_REWRITE IPNY_PROTO
11141edb306SCy Schubert %token IPNY_ON IPNY_SRC IPNY_DST IPNY_IN IPNY_OUT IPNY_DIVERT
11241edb306SCy Schubert %token IPNY_CONFIG IPNY_ALLOW IPNY_DENY IPNY_DNS IPNY_INET IPNY_INET6
11341edb306SCy Schubert %token IPNY_SEQUENTIAL IPNY_DSTLIST IPNY_PURGE
11441edb306SCy Schubert %type <port> portspec
11541edb306SCy Schubert %type <num> hexnumber compare range proto
11641edb306SCy Schubert %type <num> saddr daddr sobject dobject mapfrom rdrfrom dip
11741edb306SCy Schubert %type <ipa> hostname ipv4 ipaddr
11841edb306SCy Schubert %type <ipp> addr rhsaddr rhdaddr erhdaddr
11941edb306SCy Schubert %type <pc> portstuff portpair comaports srcports dstports
12041edb306SCy Schubert %type <names> dnslines dnsline
12141edb306SCy Schubert %%
12241edb306SCy Schubert file: line
12341edb306SCy Schubert | assign
12441edb306SCy Schubert | file line
12541edb306SCy Schubert | file assign
12641edb306SCy Schubert | file pconf ';'
12741edb306SCy Schubert ;
12841edb306SCy Schubert
12941edb306SCy Schubert line: xx rule { int err;
13041edb306SCy Schubert while ((nat = nattop) != NULL) {
13141edb306SCy Schubert if (nat->in_v[0] == 0)
13241edb306SCy Schubert nat->in_v[0] = 4;
13341edb306SCy Schubert if (nat->in_v[1] == 0)
13441edb306SCy Schubert nat->in_v[1] = nat->in_v[0];
13541edb306SCy Schubert nattop = nat->in_next;
13641edb306SCy Schubert err = (*nataddfunc)(natfd, natioctlfunc, nat);
13741edb306SCy Schubert free(nat);
13841edb306SCy Schubert if (err != 0) {
13941edb306SCy Schubert parser_error = err;
14041edb306SCy Schubert break;
14141edb306SCy Schubert }
14241edb306SCy Schubert }
14341edb306SCy Schubert if (parser_error == 0 && prules != NULL) {
14441edb306SCy Schubert proxy_loadrules(natfd, natioctlfunc, prules);
14541edb306SCy Schubert prules = NULL;
14641edb306SCy Schubert }
14741edb306SCy Schubert resetlexer();
14841edb306SCy Schubert }
14941edb306SCy Schubert | YY_COMMENT
15041edb306SCy Schubert ;
15141edb306SCy Schubert
15241edb306SCy Schubert assign: YY_STR assigning YY_STR ';' { set_variable($1, $3);
15341edb306SCy Schubert resetlexer();
15441edb306SCy Schubert free($1);
15541edb306SCy Schubert free($3);
15641edb306SCy Schubert yyvarnext = 0;
15741edb306SCy Schubert }
15841edb306SCy Schubert ;
15941edb306SCy Schubert
16041edb306SCy Schubert assigning:
16141edb306SCy Schubert '=' { yyvarnext = 1; }
16241edb306SCy Schubert ;
16341edb306SCy Schubert
16441edb306SCy Schubert xx: { newnatrule(); }
16541edb306SCy Schubert ;
16641edb306SCy Schubert
16741edb306SCy Schubert rule: map eol
16841edb306SCy Schubert | mapblock eol
16941edb306SCy Schubert | redir eol
17041edb306SCy Schubert | rewrite ';'
17141edb306SCy Schubert | divert ';'
17241edb306SCy Schubert ;
17341edb306SCy Schubert
17441edb306SCy Schubert no: IPNY_NO { nat->in_flags |= IPN_NO; }
17541edb306SCy Schubert ;
17641edb306SCy Schubert
17741edb306SCy Schubert eol: | ';'
17841edb306SCy Schubert ;
17941edb306SCy Schubert
18041edb306SCy Schubert map: mapit ifnames addr tlate rhsaddr proxy mapoptions
18141edb306SCy Schubert { if ($3.f != 0 && $3.f != $5.f && $5.f != 0)
18241edb306SCy Schubert yyerror("3.address family mismatch");
18341edb306SCy Schubert if (nat->in_v[0] == 0 && $5.v != 0)
18441edb306SCy Schubert nat->in_v[0] = $5.v;
18541edb306SCy Schubert else if (nat->in_v[0] == 0 && $3.v != 0)
18641edb306SCy Schubert nat->in_v[0] = $3.v;
18741edb306SCy Schubert if (nat->in_v[1] == 0 && $5.v != 0)
18841edb306SCy Schubert nat->in_v[1] = $5.v;
18941edb306SCy Schubert else if (nat->in_v[1] == 0 && $3.v != 0)
19041edb306SCy Schubert nat->in_v[1] = $3.v;
19141edb306SCy Schubert nat->in_osrcatype = $3.t;
19241edb306SCy Schubert bcopy(&$3.a, &nat->in_osrc.na_addr[0],
19341edb306SCy Schubert sizeof($3.a));
19441edb306SCy Schubert bcopy(&$3.m, &nat->in_osrc.na_addr[1],
19541edb306SCy Schubert sizeof($3.a));
19641edb306SCy Schubert nat->in_nsrcatype = $5.t;
19741edb306SCy Schubert nat->in_nsrcafunc = $5.u;
19841edb306SCy Schubert bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
19941edb306SCy Schubert sizeof($5.a));
20041edb306SCy Schubert bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
20141edb306SCy Schubert sizeof($5.a));
20241edb306SCy Schubert
20341edb306SCy Schubert setmapifnames();
20441edb306SCy Schubert }
20541edb306SCy Schubert | mapit ifnames addr tlate rhsaddr mapport mapoptions
20641edb306SCy Schubert { if ($3.f != $5.f && $3.f != 0 && $5.f != 0)
20741edb306SCy Schubert yyerror("4.address family mismatch");
20841edb306SCy Schubert if (nat->in_v[1] == 0 && $5.v != 0)
20941edb306SCy Schubert nat->in_v[1] = $5.v;
21041edb306SCy Schubert else if (nat->in_v[0] == 0 && $3.v != 0)
21141edb306SCy Schubert nat->in_v[0] = $3.v;
21241edb306SCy Schubert if (nat->in_v[0] == 0 && $5.v != 0)
21341edb306SCy Schubert nat->in_v[0] = $5.v;
21441edb306SCy Schubert else if (nat->in_v[1] == 0 && $3.v != 0)
21541edb306SCy Schubert nat->in_v[1] = $3.v;
21641edb306SCy Schubert nat->in_osrcatype = $3.t;
21741edb306SCy Schubert bcopy(&$3.a, &nat->in_osrc.na_addr[0],
21841edb306SCy Schubert sizeof($3.a));
21941edb306SCy Schubert bcopy(&$3.m, &nat->in_osrc.na_addr[1],
22041edb306SCy Schubert sizeof($3.a));
22141edb306SCy Schubert nat->in_nsrcatype = $5.t;
22241edb306SCy Schubert nat->in_nsrcafunc = $5.u;
22341edb306SCy Schubert bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
22441edb306SCy Schubert sizeof($5.a));
22541edb306SCy Schubert bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
22641edb306SCy Schubert sizeof($5.a));
22741edb306SCy Schubert
22841edb306SCy Schubert setmapifnames();
22941edb306SCy Schubert }
23041edb306SCy Schubert | no mapit ifnames addr setproto ';'
23141edb306SCy Schubert { if (nat->in_v[0] == 0)
23241edb306SCy Schubert nat->in_v[0] = $4.v;
23341edb306SCy Schubert nat->in_osrcatype = $4.t;
23441edb306SCy Schubert bcopy(&$4.a, &nat->in_osrc.na_addr[0],
23541edb306SCy Schubert sizeof($4.a));
23641edb306SCy Schubert bcopy(&$4.m, &nat->in_osrc.na_addr[1],
23741edb306SCy Schubert sizeof($4.a));
23841edb306SCy Schubert
23941edb306SCy Schubert setmapifnames();
24041edb306SCy Schubert }
24141edb306SCy Schubert | mapit ifnames mapfrom tlate rhsaddr proxy mapoptions
24241edb306SCy Schubert { if ($3 != 0 && $5.f != 0 && $3 != $5.f)
24341edb306SCy Schubert yyerror("5.address family mismatch");
24441edb306SCy Schubert if (nat->in_v[0] == 0 && $5.v != 0)
24541edb306SCy Schubert nat->in_v[0] = $5.v;
24641edb306SCy Schubert else if (nat->in_v[0] == 0 && $3 != 0)
24741edb306SCy Schubert nat->in_v[0] = ftov($3);
24841edb306SCy Schubert if (nat->in_v[1] == 0 && $5.v != 0)
24941edb306SCy Schubert nat->in_v[1] = $5.v;
25041edb306SCy Schubert else if (nat->in_v[1] == 0 && $3 != 0)
25141edb306SCy Schubert nat->in_v[1] = ftov($3);
25241edb306SCy Schubert nat->in_nsrcatype = $5.t;
25341edb306SCy Schubert nat->in_nsrcafunc = $5.u;
25441edb306SCy Schubert bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
25541edb306SCy Schubert sizeof($5.a));
25641edb306SCy Schubert bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
25741edb306SCy Schubert sizeof($5.a));
25841edb306SCy Schubert
25941edb306SCy Schubert setmapifnames();
26041edb306SCy Schubert }
26141edb306SCy Schubert | no mapit ifnames mapfrom setproto ';'
26241edb306SCy Schubert { nat->in_v[0] = ftov($4);
26341edb306SCy Schubert setmapifnames();
26441edb306SCy Schubert }
26541edb306SCy Schubert | mapit ifnames mapfrom tlate rhsaddr mapport mapoptions
26641edb306SCy Schubert { if ($3 != 0 && $5.f != 0 && $3 != $5.f)
26741edb306SCy Schubert yyerror("6.address family mismatch");
26841edb306SCy Schubert if (nat->in_v[0] == 0 && $5.v != 0)
26941edb306SCy Schubert nat->in_v[0] = $5.v;
27041edb306SCy Schubert else if (nat->in_v[0] == 0 && $3 != 0)
27141edb306SCy Schubert nat->in_v[0] = ftov($3);
27241edb306SCy Schubert if (nat->in_v[1] == 0 && $5.v != 0)
27341edb306SCy Schubert nat->in_v[1] = $5.v;
27441edb306SCy Schubert else if (nat->in_v[1] == 0 && $3 != 0)
27541edb306SCy Schubert nat->in_v[1] = ftov($3);
27641edb306SCy Schubert nat->in_nsrcatype = $5.t;
27741edb306SCy Schubert nat->in_nsrcafunc = $5.u;
27841edb306SCy Schubert bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
27941edb306SCy Schubert sizeof($5.a));
28041edb306SCy Schubert bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
28141edb306SCy Schubert sizeof($5.a));
28241edb306SCy Schubert
28341edb306SCy Schubert setmapifnames();
28441edb306SCy Schubert }
28541edb306SCy Schubert ;
28641edb306SCy Schubert
28741edb306SCy Schubert mapblock:
28841edb306SCy Schubert mapblockit ifnames addr tlate addr ports mapoptions
28941edb306SCy Schubert { if ($3.f != 0 && $5.f != 0 && $3.f != $5.f)
29041edb306SCy Schubert yyerror("7.address family mismatch");
29141edb306SCy Schubert if (nat->in_v[0] == 0 && $5.v != 0)
29241edb306SCy Schubert nat->in_v[0] = $5.v;
29341edb306SCy Schubert else if (nat->in_v[0] == 0 && $3.v != 0)
29441edb306SCy Schubert nat->in_v[0] = $3.v;
29541edb306SCy Schubert if (nat->in_v[1] == 0 && $5.v != 0)
29641edb306SCy Schubert nat->in_v[1] = $5.v;
29741edb306SCy Schubert else if (nat->in_v[1] == 0 && $3.v != 0)
29841edb306SCy Schubert nat->in_v[1] = $3.v;
29941edb306SCy Schubert nat->in_osrcatype = $3.t;
30041edb306SCy Schubert bcopy(&$3.a, &nat->in_osrc.na_addr[0],
30141edb306SCy Schubert sizeof($3.a));
30241edb306SCy Schubert bcopy(&$3.m, &nat->in_osrc.na_addr[1],
30341edb306SCy Schubert sizeof($3.a));
30441edb306SCy Schubert nat->in_nsrcatype = $5.t;
30541edb306SCy Schubert nat->in_nsrcafunc = $5.u;
30641edb306SCy Schubert bcopy(&$5.a, &nat->in_nsrc.na_addr[0],
30741edb306SCy Schubert sizeof($5.a));
30841edb306SCy Schubert bcopy(&$5.m, &nat->in_nsrc.na_addr[1],
30941edb306SCy Schubert sizeof($5.a));
31041edb306SCy Schubert
31141edb306SCy Schubert setmapifnames();
31241edb306SCy Schubert }
31341edb306SCy Schubert | no mapblockit ifnames { yyexpectaddr = 1; } addr setproto ';'
31441edb306SCy Schubert { if (nat->in_v[0] == 0)
31541edb306SCy Schubert nat->in_v[0] = $5.v;
31641edb306SCy Schubert if (nat->in_v[1] == 0)
31741edb306SCy Schubert nat->in_v[1] = $5.v;
31841edb306SCy Schubert nat->in_osrcatype = $5.t;
31941edb306SCy Schubert bcopy(&$5.a, &nat->in_osrc.na_addr[0],
32041edb306SCy Schubert sizeof($5.a));
32141edb306SCy Schubert bcopy(&$5.m, &nat->in_osrc.na_addr[1],
32241edb306SCy Schubert sizeof($5.a));
32341edb306SCy Schubert
32441edb306SCy Schubert setmapifnames();
32541edb306SCy Schubert }
32641edb306SCy Schubert ;
32741edb306SCy Schubert
32841edb306SCy Schubert redir: rdrit ifnames addr dport tlate dip nport setproto rdroptions
32941edb306SCy Schubert { if ($6 != 0 && $3.f != 0 && $6 != $3.f)
33041edb306SCy Schubert yyerror("21.address family mismatch");
33141edb306SCy Schubert if (nat->in_v[0] == 0) {
33241edb306SCy Schubert if ($3.v != AF_UNSPEC)
33341edb306SCy Schubert nat->in_v[0] = ftov($3.f);
33441edb306SCy Schubert else
33541edb306SCy Schubert nat->in_v[0] = ftov($6);
33641edb306SCy Schubert }
33741edb306SCy Schubert nat->in_odstatype = $3.t;
33841edb306SCy Schubert bcopy(&$3.a, &nat->in_odst.na_addr[0],
33941edb306SCy Schubert sizeof($3.a));
34041edb306SCy Schubert bcopy(&$3.m, &nat->in_odst.na_addr[1],
34141edb306SCy Schubert sizeof($3.a));
34241edb306SCy Schubert
34341edb306SCy Schubert setrdrifnames();
34441edb306SCy Schubert }
34541edb306SCy Schubert | no rdrit ifnames addr dport setproto ';'
34641edb306SCy Schubert { if (nat->in_v[0] == 0)
34741edb306SCy Schubert nat->in_v[0] = ftov($4.f);
34841edb306SCy Schubert nat->in_odstatype = $4.t;
34941edb306SCy Schubert bcopy(&$4.a, &nat->in_odst.na_addr[0],
35041edb306SCy Schubert sizeof($4.a));
35141edb306SCy Schubert bcopy(&$4.m, &nat->in_odst.na_addr[1],
35241edb306SCy Schubert sizeof($4.a));
35341edb306SCy Schubert
35441edb306SCy Schubert setrdrifnames();
35541edb306SCy Schubert }
35641edb306SCy Schubert | rdrit ifnames rdrfrom tlate dip nport setproto rdroptions
35741edb306SCy Schubert { if ($5 != 0 && $3 != 0 && $5 != $3)
35841edb306SCy Schubert yyerror("20.address family mismatch");
35941edb306SCy Schubert if (nat->in_v[0] == 0) {
36041edb306SCy Schubert if ($3 != AF_UNSPEC)
36141edb306SCy Schubert nat->in_v[0] = ftov($3);
36241edb306SCy Schubert else
36341edb306SCy Schubert nat->in_v[0] = ftov($5);
36441edb306SCy Schubert }
36541edb306SCy Schubert setrdrifnames();
36641edb306SCy Schubert }
36741edb306SCy Schubert | no rdrit ifnames rdrfrom setproto ';'
36841edb306SCy Schubert { nat->in_v[0] = ftov($4);
36941edb306SCy Schubert
37041edb306SCy Schubert setrdrifnames();
37141edb306SCy Schubert }
37241edb306SCy Schubert ;
37341edb306SCy Schubert
37441edb306SCy Schubert rewrite:
37541edb306SCy Schubert IPNY_REWRITE oninout rwrproto mapfrom tlate newdst newopts
37641edb306SCy Schubert { if (nat->in_v[0] == 0)
37741edb306SCy Schubert nat->in_v[0] = ftov($4);
37841edb306SCy Schubert if (nat->in_redir & NAT_MAP)
37941edb306SCy Schubert setmapifnames();
38041edb306SCy Schubert else
38141edb306SCy Schubert setrdrifnames();
38241edb306SCy Schubert nat->in_redir |= NAT_REWRITE;
38341edb306SCy Schubert }
38441edb306SCy Schubert ;
38541edb306SCy Schubert
38641edb306SCy Schubert divert: IPNY_DIVERT oninout rwrproto mapfrom tlate divdst newopts
38741edb306SCy Schubert { if (nat->in_v[0] == 0)
38841edb306SCy Schubert nat->in_v[0] = ftov($4);
38941edb306SCy Schubert if (nat->in_redir & NAT_MAP) {
39041edb306SCy Schubert setmapifnames();
39141edb306SCy Schubert nat->in_pr[0] = IPPROTO_UDP;
39241edb306SCy Schubert } else {
39341edb306SCy Schubert setrdrifnames();
39441edb306SCy Schubert nat->in_pr[1] = IPPROTO_UDP;
39541edb306SCy Schubert }
39641edb306SCy Schubert nat->in_flags &= ~IPN_TCP;
39741edb306SCy Schubert }
39841edb306SCy Schubert ;
39941edb306SCy Schubert
40041edb306SCy Schubert tlate: IPNY_TLATE { yyexpectaddr = 1; }
40141edb306SCy Schubert ;
40241edb306SCy Schubert
40341edb306SCy Schubert pconf: IPNY_PROXY { yysetdict(proxies); }
40441edb306SCy Schubert IPNY_DNS '/' proto IPNY_CONFIG YY_STR '{'
40541edb306SCy Schubert { proxy_setconfig(IPNY_DNS); }
40641edb306SCy Schubert dnslines ';' '}'
40741edb306SCy Schubert { proxy_addconfig("dns", $5, $7, $10);
40841edb306SCy Schubert proxy_unsetconfig();
40941edb306SCy Schubert }
41041edb306SCy Schubert ;
41141edb306SCy Schubert
41241edb306SCy Schubert dnslines:
41341edb306SCy Schubert dnsline { $$ = $1; }
41441edb306SCy Schubert | dnslines ';' dnsline { $$ = $1; $1->na_next = $3; }
41541edb306SCy Schubert ;
41641edb306SCy Schubert
41741edb306SCy Schubert dnsline:
41841edb306SCy Schubert IPNY_ALLOW YY_STR { $$ = proxy_dns_add_pass(NULL, $2); }
41941edb306SCy Schubert | IPNY_DENY YY_STR { $$ = proxy_dns_add_block(NULL, $2); }
42041edb306SCy Schubert | IPNY_ALLOW '.' YY_STR { $$ = proxy_dns_add_pass(".", $3); }
42141edb306SCy Schubert | IPNY_DENY '.' YY_STR { $$ = proxy_dns_add_block(".", $3); }
42241edb306SCy Schubert ;
42341edb306SCy Schubert
42441edb306SCy Schubert oninout:
42541edb306SCy Schubert inout IPNY_ON ifnames { ; }
42641edb306SCy Schubert ;
42741edb306SCy Schubert
42841edb306SCy Schubert inout: IPNY_IN { nat->in_redir = NAT_REDIRECT; }
42941edb306SCy Schubert | IPNY_OUT { nat->in_redir = NAT_MAP; }
43041edb306SCy Schubert ;
43141edb306SCy Schubert
43241edb306SCy Schubert rwrproto:
43341edb306SCy Schubert | IPNY_PROTO setproto
43441edb306SCy Schubert ;
43541edb306SCy Schubert
43641edb306SCy Schubert newdst: src rhsaddr srcports dst erhdaddr dstports
43741edb306SCy Schubert { nat->in_nsrc.na_addr[0] = $2.a;
43841edb306SCy Schubert nat->in_nsrc.na_addr[1] = $2.m;
43941edb306SCy Schubert nat->in_nsrc.na_atype = $2.t;
44041edb306SCy Schubert if ($2.t == FRI_LOOKUP) {
44141edb306SCy Schubert nat->in_nsrc.na_type = $2.u;
44241edb306SCy Schubert nat->in_nsrc.na_subtype = $2.s;
44341edb306SCy Schubert nat->in_nsrc.na_num = $2.n;
44441edb306SCy Schubert }
44541edb306SCy Schubert nat->in_nsports[0] = $3.p1;
44641edb306SCy Schubert nat->in_nsports[1] = $3.p2;
44741edb306SCy Schubert nat->in_ndst.na_addr[0] = $5.a;
44841edb306SCy Schubert nat->in_ndst.na_addr[1] = $5.m;
44941edb306SCy Schubert nat->in_ndst.na_atype = $5.t;
45041edb306SCy Schubert if ($5.t == FRI_LOOKUP) {
45141edb306SCy Schubert nat->in_ndst.na_type = $5.u;
45241edb306SCy Schubert nat->in_ndst.na_subtype = $5.s;
45341edb306SCy Schubert nat->in_ndst.na_num = $5.n;
45441edb306SCy Schubert }
45541edb306SCy Schubert nat->in_ndports[0] = $6.p1;
45641edb306SCy Schubert nat->in_ndports[1] = $6.p2;
45741edb306SCy Schubert }
45841edb306SCy Schubert ;
45941edb306SCy Schubert
46041edb306SCy Schubert divdst: src addr ',' portspec dst addr ',' portspec IPNY_UDP
46141edb306SCy Schubert { nat->in_nsrc.na_addr[0] = $2.a;
46241edb306SCy Schubert if ($2.m.in4.s_addr != 0xffffffff)
46341edb306SCy Schubert yyerror("divert must have /32 dest");
46441edb306SCy Schubert nat->in_nsrc.na_addr[1] = $2.m;
46541edb306SCy Schubert nat->in_nsports[0] = $4;
46641edb306SCy Schubert nat->in_nsports[1] = $4;
46741edb306SCy Schubert
46841edb306SCy Schubert nat->in_ndst.na_addr[0] = $6.a;
46941edb306SCy Schubert nat->in_ndst.na_addr[1] = $6.m;
47041edb306SCy Schubert if ($6.m.in4.s_addr != 0xffffffff)
47141edb306SCy Schubert yyerror("divert must have /32 dest");
47241edb306SCy Schubert nat->in_ndports[0] = $8;
47341edb306SCy Schubert nat->in_ndports[1] = $8;
47441edb306SCy Schubert
47541edb306SCy Schubert nat->in_redir |= NAT_DIVERTUDP;
47641edb306SCy Schubert }
47741edb306SCy Schubert ;
47841edb306SCy Schubert
47941edb306SCy Schubert src: IPNY_SRC { yyexpectaddr = 1; }
48041edb306SCy Schubert ;
48141edb306SCy Schubert
48241edb306SCy Schubert dst: IPNY_DST { yyexpectaddr = 1; }
48341edb306SCy Schubert ;
48441edb306SCy Schubert
48541edb306SCy Schubert srcports:
48641edb306SCy Schubert comaports { $$.p1 = $1.p1;
48741edb306SCy Schubert $$.p2 = $1.p2;
48841edb306SCy Schubert }
48941edb306SCy Schubert | IPNY_PORT '=' portspec
49041edb306SCy Schubert { $$.p1 = $3;
49141edb306SCy Schubert $$.p2 = $3;
49241edb306SCy Schubert nat->in_flags |= IPN_FIXEDSPORT;
49341edb306SCy Schubert }
49441edb306SCy Schubert ;
49541edb306SCy Schubert
49641edb306SCy Schubert dstports:
49741edb306SCy Schubert comaports { $$.p1 = $1.p1;
49841edb306SCy Schubert $$.p2 = $1.p2;
49941edb306SCy Schubert }
50041edb306SCy Schubert | IPNY_PORT '=' portspec
50141edb306SCy Schubert { $$.p1 = $3;
50241edb306SCy Schubert $$.p2 = $3;
50341edb306SCy Schubert nat->in_flags |= IPN_FIXEDDPORT;
50441edb306SCy Schubert }
50541edb306SCy Schubert ;
50641edb306SCy Schubert
50741edb306SCy Schubert comaports:
50841edb306SCy Schubert { $$.p1 = 0;
50941edb306SCy Schubert $$.p2 = 0;
51041edb306SCy Schubert }
51141edb306SCy Schubert | ',' { if (!(nat->in_flags & IPN_TCPUDP))
51241edb306SCy Schubert yyerror("must be TCP/UDP for ports");
51341edb306SCy Schubert }
51441edb306SCy Schubert portpair { $$.p1 = $3.p1;
51541edb306SCy Schubert $$.p2 = $3.p2;
51641edb306SCy Schubert }
51741edb306SCy Schubert ;
51841edb306SCy Schubert
51941edb306SCy Schubert proxy: | IPNY_PROXY port portspec YY_STR '/' proto
52041edb306SCy Schubert { int pos;
52141edb306SCy Schubert pos = addname(&nat, $4);
52241edb306SCy Schubert nat->in_plabel = pos;
52341edb306SCy Schubert if (nat->in_dcmp == 0) {
52441edb306SCy Schubert nat->in_odport = $3;
52541edb306SCy Schubert } else if ($3 != nat->in_odport) {
52641edb306SCy Schubert yyerror("proxy port numbers not consistant");
52741edb306SCy Schubert }
52841edb306SCy Schubert nat->in_ndport = $3;
52941edb306SCy Schubert setnatproto($6);
53041edb306SCy Schubert free($4);
53141edb306SCy Schubert }
53241edb306SCy Schubert | IPNY_PROXY port YY_STR YY_STR '/' proto
53341edb306SCy Schubert { int pnum, pos;
53441edb306SCy Schubert pos = addname(&nat, $4);
53541edb306SCy Schubert nat->in_plabel = pos;
53641edb306SCy Schubert pnum = getportproto($3, $6);
53741edb306SCy Schubert if (pnum == -1)
53841edb306SCy Schubert yyerror("invalid port number");
53941edb306SCy Schubert nat->in_odport = ntohs(pnum);
54041edb306SCy Schubert nat->in_ndport = ntohs(pnum);
54141edb306SCy Schubert setnatproto($6);
54241edb306SCy Schubert free($3);
54341edb306SCy Schubert free($4);
54441edb306SCy Schubert }
54541edb306SCy Schubert | IPNY_PROXY port portspec YY_STR '/' proto IPNY_CONFIG YY_STR
54641edb306SCy Schubert { int pos;
54741edb306SCy Schubert pos = addname(&nat, $4);
54841edb306SCy Schubert nat->in_plabel = pos;
54941edb306SCy Schubert if (nat->in_dcmp == 0) {
55041edb306SCy Schubert nat->in_odport = $3;
55141edb306SCy Schubert } else if ($3 != nat->in_odport) {
55241edb306SCy Schubert yyerror("proxy port numbers not consistant");
55341edb306SCy Schubert }
55441edb306SCy Schubert nat->in_ndport = $3;
55541edb306SCy Schubert setnatproto($6);
55641edb306SCy Schubert nat->in_pconfig = addname(&nat, $8);
55741edb306SCy Schubert free($4);
55841edb306SCy Schubert free($8);
55941edb306SCy Schubert }
56041edb306SCy Schubert | IPNY_PROXY port YY_STR YY_STR '/' proto IPNY_CONFIG YY_STR
56141edb306SCy Schubert { int pnum, pos;
56241edb306SCy Schubert pos = addname(&nat, $4);
56341edb306SCy Schubert nat->in_plabel = pos;
56441edb306SCy Schubert pnum = getportproto($3, $6);
56541edb306SCy Schubert if (pnum == -1)
56641edb306SCy Schubert yyerror("invalid port number");
56741edb306SCy Schubert nat->in_odport = ntohs(pnum);
56841edb306SCy Schubert nat->in_ndport = ntohs(pnum);
56941edb306SCy Schubert setnatproto($6);
57041edb306SCy Schubert pos = addname(&nat, $8);
57141edb306SCy Schubert nat->in_pconfig = pos;
57241edb306SCy Schubert free($3);
57341edb306SCy Schubert free($4);
57441edb306SCy Schubert free($8);
57541edb306SCy Schubert }
57641edb306SCy Schubert ;
57741edb306SCy Schubert setproto:
57841edb306SCy Schubert | proto { if (nat->in_pr[0] != 0 ||
57941edb306SCy Schubert nat->in_pr[1] != 0 ||
58041edb306SCy Schubert nat->in_flags & IPN_TCPUDP)
58141edb306SCy Schubert yyerror("protocol set twice");
58241edb306SCy Schubert setnatproto($1);
58341edb306SCy Schubert }
58441edb306SCy Schubert | IPNY_TCPUDP { if (nat->in_pr[0] != 0 ||
58541edb306SCy Schubert nat->in_pr[1] != 0 ||
58641edb306SCy Schubert nat->in_flags & IPN_TCPUDP)
58741edb306SCy Schubert yyerror("protocol set twice");
58841edb306SCy Schubert nat->in_flags |= IPN_TCPUDP;
58941edb306SCy Schubert nat->in_pr[0] = 0;
59041edb306SCy Schubert nat->in_pr[1] = 0;
59141edb306SCy Schubert }
59241edb306SCy Schubert | IPNY_TCP '/' IPNY_UDP { if (nat->in_pr[0] != 0 ||
59341edb306SCy Schubert nat->in_pr[1] != 0 ||
59441edb306SCy Schubert nat->in_flags & IPN_TCPUDP)
59541edb306SCy Schubert yyerror("protocol set twice");
59641edb306SCy Schubert nat->in_flags |= IPN_TCPUDP;
59741edb306SCy Schubert nat->in_pr[0] = 0;
59841edb306SCy Schubert nat->in_pr[1] = 0;
59941edb306SCy Schubert }
60041edb306SCy Schubert ;
60141edb306SCy Schubert
60241edb306SCy Schubert rhsaddr:
60341edb306SCy Schubert addr { $$ = $1;
60441edb306SCy Schubert yyexpectaddr = 0;
60541edb306SCy Schubert }
60641edb306SCy Schubert | hostname '-' { yyexpectaddr = 1; } hostname
60741edb306SCy Schubert { $$.t = FRI_RANGE;
60841edb306SCy Schubert if ($1.f != $4.f)
60941edb306SCy Schubert yyerror("8.address family "
61041edb306SCy Schubert "mismatch");
61141edb306SCy Schubert $$.f = $1.f;
61241edb306SCy Schubert $$.v = ftov($1.f);
61341edb306SCy Schubert $$.a = $1.a;
61441edb306SCy Schubert $$.m = $4.a;
61541edb306SCy Schubert nat->in_flags |= IPN_SIPRANGE;
61641edb306SCy Schubert yyexpectaddr = 0;
61741edb306SCy Schubert }
61841edb306SCy Schubert | IPNY_RANGE hostname '-' { yyexpectaddr = 1; } hostname
61941edb306SCy Schubert { $$.t = FRI_RANGE;
62041edb306SCy Schubert if ($2.f != $5.f)
62141edb306SCy Schubert yyerror("9.address family "
62241edb306SCy Schubert "mismatch");
62341edb306SCy Schubert $$.f = $2.f;
62441edb306SCy Schubert $$.v = ftov($2.f);
62541edb306SCy Schubert $$.a = $2.a;
62641edb306SCy Schubert $$.m = $5.a;
62741edb306SCy Schubert nat->in_flags |= IPN_SIPRANGE;
62841edb306SCy Schubert yyexpectaddr = 0;
62941edb306SCy Schubert }
63041edb306SCy Schubert ;
63141edb306SCy Schubert
63241edb306SCy Schubert dip:
63341edb306SCy Schubert hostname ',' { yyexpectaddr = 1; } hostname
63441edb306SCy Schubert { nat->in_flags |= IPN_SPLIT;
63541edb306SCy Schubert if ($1.f != $4.f)
63641edb306SCy Schubert yyerror("10.address family "
63741edb306SCy Schubert "mismatch");
63841edb306SCy Schubert $$ = $1.f;
63941edb306SCy Schubert nat->in_ndstip6 = $1.a;
64041edb306SCy Schubert nat->in_ndstmsk6 = $4.a;
64141edb306SCy Schubert nat->in_ndstatype = FRI_SPLIT;
64241edb306SCy Schubert yyexpectaddr = 0;
64341edb306SCy Schubert }
64441edb306SCy Schubert | rhdaddr { int bits;
64541edb306SCy Schubert nat->in_ndstip6 = $1.a;
64641edb306SCy Schubert nat->in_ndstmsk6 = $1.m;
64741edb306SCy Schubert nat->in_ndst.na_atype = $1.t;
64841edb306SCy Schubert yyexpectaddr = 0;
64941edb306SCy Schubert if ($1.f == AF_INET)
65041edb306SCy Schubert bits = count4bits($1.m.in4.s_addr);
65141edb306SCy Schubert else
65241edb306SCy Schubert bits = count6bits($1.m.i6);
65341edb306SCy Schubert if (($1.f == AF_INET) && (bits != 0) &&
65441edb306SCy Schubert (bits != 32)) {
65541edb306SCy Schubert yyerror("dest ip bitmask not /32");
65641edb306SCy Schubert } else if (($1.f == AF_INET6) &&
65741edb306SCy Schubert (bits != 0) && (bits != 128)) {
65841edb306SCy Schubert yyerror("dest ip bitmask not /128");
65941edb306SCy Schubert }
66041edb306SCy Schubert $$ = $1.f;
66141edb306SCy Schubert }
66241edb306SCy Schubert ;
66341edb306SCy Schubert
66441edb306SCy Schubert rhdaddr:
66541edb306SCy Schubert addr { $$ = $1;
66641edb306SCy Schubert yyexpectaddr = 0;
66741edb306SCy Schubert }
66841edb306SCy Schubert | hostname '-' hostname { bzero(&$$, sizeof($$));
66941edb306SCy Schubert $$.t = FRI_RANGE;
67041edb306SCy Schubert if ($1.f != 0 && $3.f != 0 &&
67141edb306SCy Schubert $1.f != $3.f)
67241edb306SCy Schubert yyerror("11.address family "
67341edb306SCy Schubert "mismatch");
67441edb306SCy Schubert $$.a = $1.a;
67541edb306SCy Schubert $$.m = $3.a;
67641edb306SCy Schubert nat->in_flags |= IPN_DIPRANGE;
67741edb306SCy Schubert yyexpectaddr = 0;
67841edb306SCy Schubert }
67941edb306SCy Schubert | IPNY_RANGE hostname '-' hostname
68041edb306SCy Schubert { bzero(&$$, sizeof($$));
68141edb306SCy Schubert $$.t = FRI_RANGE;
68241edb306SCy Schubert if ($2.f != 0 && $4.f != 0 &&
68341edb306SCy Schubert $2.f != $4.f)
68441edb306SCy Schubert yyerror("12.address family "
68541edb306SCy Schubert "mismatch");
68641edb306SCy Schubert $$.a = $2.a;
68741edb306SCy Schubert $$.m = $4.a;
68841edb306SCy Schubert nat->in_flags |= IPN_DIPRANGE;
68941edb306SCy Schubert yyexpectaddr = 0;
69041edb306SCy Schubert }
69141edb306SCy Schubert ;
69241edb306SCy Schubert
69341edb306SCy Schubert erhdaddr:
69441edb306SCy Schubert rhdaddr { $$ = $1; }
69541edb306SCy Schubert | IPNY_DSTLIST '/' YY_NUMBER { $$.t = FRI_LOOKUP;
69641edb306SCy Schubert $$.u = IPLT_DSTLIST;
69741edb306SCy Schubert $$.s = 0;
69841edb306SCy Schubert $$.n = $3;
69941edb306SCy Schubert }
70041edb306SCy Schubert | IPNY_DSTLIST '/' YY_STR { $$.t = FRI_LOOKUP;
70141edb306SCy Schubert $$.u = IPLT_DSTLIST;
70241edb306SCy Schubert $$.s = 1;
70341edb306SCy Schubert $$.n = addname(&nat, $3);
70441edb306SCy Schubert }
70541edb306SCy Schubert ;
70641edb306SCy Schubert
70741edb306SCy Schubert port: IPNY_PORT { suggest_port = 1; }
70841edb306SCy Schubert ;
70941edb306SCy Schubert
71041edb306SCy Schubert portspec:
71141edb306SCy Schubert YY_NUMBER { if ($1 > 65535) /* Unsigned */
71241edb306SCy Schubert yyerror("invalid port number");
71341edb306SCy Schubert else
71441edb306SCy Schubert $$ = $1;
71541edb306SCy Schubert }
71641edb306SCy Schubert | YY_STR { if (getport(NULL, $1,
71741edb306SCy Schubert &($$), NULL) == -1)
71841edb306SCy Schubert yyerror("invalid port number");
71941edb306SCy Schubert $$ = ntohs($$);
72041edb306SCy Schubert }
72141edb306SCy Schubert ;
72241edb306SCy Schubert
72341edb306SCy Schubert portpair:
72441edb306SCy Schubert portspec { $$.p1 = $1; $$.p2 = $1; }
72541edb306SCy Schubert | portspec '-' portspec { $$.p1 = $1; $$.p2 = $3; }
72641edb306SCy Schubert | portspec ':' portspec { $$.p1 = $1; $$.p2 = $3; }
72741edb306SCy Schubert ;
72841edb306SCy Schubert
72941edb306SCy Schubert dport: | port portpair { nat->in_odport = $2.p1;
73041edb306SCy Schubert if ($2.p2 == 0)
73141edb306SCy Schubert nat->in_dtop = $2.p1;
73241edb306SCy Schubert else
73341edb306SCy Schubert nat->in_dtop = $2.p2;
73441edb306SCy Schubert }
73541edb306SCy Schubert ;
73641edb306SCy Schubert
73741edb306SCy Schubert nport: | port portpair { nat->in_dpmin = $2.p1;
73841edb306SCy Schubert nat->in_dpnext = $2.p1;
73941edb306SCy Schubert nat->in_dpmax = $2.p2;
74041edb306SCy Schubert nat->in_ndport = $2.p1;
74141edb306SCy Schubert if (nat->in_dtop == 0)
74241edb306SCy Schubert nat->in_dtop = $2.p2;
74341edb306SCy Schubert }
74441edb306SCy Schubert | port '=' portspec { nat->in_dpmin = $3;
74541edb306SCy Schubert nat->in_dpnext = $3;
74641edb306SCy Schubert nat->in_ndport = $3;
74741edb306SCy Schubert if (nat->in_dtop == 0)
74841edb306SCy Schubert nat->in_dtop = nat->in_odport;
74941edb306SCy Schubert nat->in_flags |= IPN_FIXEDDPORT;
75041edb306SCy Schubert }
75141edb306SCy Schubert ;
75241edb306SCy Schubert
75341edb306SCy Schubert ports: | IPNY_PORTS YY_NUMBER { nat->in_spmin = $2; }
75441edb306SCy Schubert | IPNY_PORTS IPNY_AUTO { nat->in_flags |= IPN_AUTOPORTMAP; }
75541edb306SCy Schubert ;
75641edb306SCy Schubert
75741edb306SCy Schubert mapit: IPNY_MAP { nat->in_redir = NAT_MAP; }
75841edb306SCy Schubert | IPNY_BIMAP { nat->in_redir = NAT_BIMAP; }
75941edb306SCy Schubert ;
76041edb306SCy Schubert
76141edb306SCy Schubert rdrit: IPNY_RDR { nat->in_redir = NAT_REDIRECT; }
76241edb306SCy Schubert ;
76341edb306SCy Schubert
76441edb306SCy Schubert mapblockit:
76541edb306SCy Schubert IPNY_MAPBLOCK { nat->in_redir = NAT_MAPBLK; }
76641edb306SCy Schubert ;
76741edb306SCy Schubert
76841edb306SCy Schubert mapfrom:
76941edb306SCy Schubert from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
77041edb306SCy Schubert yyerror("13.address family "
77141edb306SCy Schubert "mismatch");
77241edb306SCy Schubert $$ = $2;
77341edb306SCy Schubert }
77441edb306SCy Schubert | from sobject '!' to dobject
77541edb306SCy Schubert { if ($2 != 0 && $5 != 0 && $2 != $5)
77641edb306SCy Schubert yyerror("14.address family "
77741edb306SCy Schubert "mismatch");
77841edb306SCy Schubert nat->in_flags |= IPN_NOTDST;
77941edb306SCy Schubert $$ = $2;
78041edb306SCy Schubert }
78141edb306SCy Schubert | from sobject to '!' dobject
78241edb306SCy Schubert { if ($2 != 0 && $5 != 0 && $2 != $5)
78341edb306SCy Schubert yyerror("15.address family "
78441edb306SCy Schubert "mismatch");
78541edb306SCy Schubert nat->in_flags |= IPN_NOTDST;
78641edb306SCy Schubert $$ = $2;
78741edb306SCy Schubert }
78841edb306SCy Schubert ;
78941edb306SCy Schubert
79041edb306SCy Schubert rdrfrom:
79141edb306SCy Schubert from sobject to dobject { if ($2 != 0 && $4 != 0 && $2 != $4)
79241edb306SCy Schubert yyerror("16.address family "
79341edb306SCy Schubert "mismatch");
79441edb306SCy Schubert $$ = $2;
79541edb306SCy Schubert }
79641edb306SCy Schubert | '!' from sobject to dobject
79741edb306SCy Schubert { if ($3 != 0 && $5 != 0 && $3 != $5)
79841edb306SCy Schubert yyerror("17.address family "
79941edb306SCy Schubert "mismatch");
80041edb306SCy Schubert nat->in_flags |= IPN_NOTSRC;
80141edb306SCy Schubert $$ = $3;
80241edb306SCy Schubert }
80341edb306SCy Schubert | from '!' sobject to dobject
80441edb306SCy Schubert { if ($3 != 0 && $5 != 0 && $3 != $5)
80541edb306SCy Schubert yyerror("18.address family "
80641edb306SCy Schubert "mismatch");
80741edb306SCy Schubert nat->in_flags |= IPN_NOTSRC;
80841edb306SCy Schubert $$ = $3;
80941edb306SCy Schubert }
81041edb306SCy Schubert ;
81141edb306SCy Schubert
81241edb306SCy Schubert from: IPNY_FROM { nat->in_flags |= IPN_FILTER;
81341edb306SCy Schubert yyexpectaddr = 1;
81441edb306SCy Schubert }
81541edb306SCy Schubert ;
81641edb306SCy Schubert
81741edb306SCy Schubert to: IPNY_TO { yyexpectaddr = 1; }
81841edb306SCy Schubert ;
81941edb306SCy Schubert
82041edb306SCy Schubert ifnames:
82141edb306SCy Schubert ifname family { yyexpectaddr = 1; }
82241edb306SCy Schubert | ifname ',' otherifname family { yyexpectaddr = 1; }
82341edb306SCy Schubert ;
82441edb306SCy Schubert
82541edb306SCy Schubert ifname: YY_STR { setifname(&nat, 0, $1);
82641edb306SCy Schubert free($1);
82741edb306SCy Schubert }
82841edb306SCy Schubert ;
82941edb306SCy Schubert
83041edb306SCy Schubert family: | IPNY_INET { nat->in_v[0] = 4; nat->in_v[1] = 4; }
83141edb306SCy Schubert | IPNY_INET6 { nat->in_v[0] = 6; nat->in_v[1] = 6; }
83241edb306SCy Schubert ;
83341edb306SCy Schubert
83441edb306SCy Schubert otherifname:
83541edb306SCy Schubert YY_STR { setifname(&nat, 1, $1);
83641edb306SCy Schubert free($1);
83741edb306SCy Schubert }
83841edb306SCy Schubert ;
83941edb306SCy Schubert
84041edb306SCy Schubert mapport:
84141edb306SCy Schubert IPNY_PORTMAP tcpudp portpair sequential
84241edb306SCy Schubert { nat->in_spmin = $3.p1;
84341edb306SCy Schubert nat->in_spmax = $3.p2;
84441edb306SCy Schubert }
84541edb306SCy Schubert | IPNY_PORTMAP portpair tcpudp sequential
84641edb306SCy Schubert { nat->in_spmin = $2.p1;
84741edb306SCy Schubert nat->in_spmax = $2.p2;
84841edb306SCy Schubert }
84941edb306SCy Schubert | IPNY_PORTMAP tcpudp IPNY_AUTO sequential
85041edb306SCy Schubert { nat->in_flags |= IPN_AUTOPORTMAP;
85141edb306SCy Schubert nat->in_spmin = 1024;
85241edb306SCy Schubert nat->in_spmax = 65535;
85341edb306SCy Schubert }
85441edb306SCy Schubert | IPNY_ICMPIDMAP YY_STR portpair sequential
85541edb306SCy Schubert { if (strcmp($2, "icmp") != 0 &&
85641edb306SCy Schubert strcmp($2, "ipv6-icmp") != 0) {
85741edb306SCy Schubert yyerror("icmpidmap not followed by icmp");
85841edb306SCy Schubert }
85941edb306SCy Schubert free($2);
86041edb306SCy Schubert if ($3.p1 < 0 || $3.p1 > 65535)
86141edb306SCy Schubert yyerror("invalid 1st ICMP Id number");
86241edb306SCy Schubert if ($3.p2 < 0 || $3.p2 > 65535)
86341edb306SCy Schubert yyerror("invalid 2nd ICMP Id number");
86441edb306SCy Schubert if (strcmp($2, "ipv6-icmp") == 0) {
86541edb306SCy Schubert nat->in_pr[0] = IPPROTO_ICMPV6;
86641edb306SCy Schubert nat->in_pr[1] = IPPROTO_ICMPV6;
86741edb306SCy Schubert } else {
86841edb306SCy Schubert nat->in_pr[0] = IPPROTO_ICMP;
86941edb306SCy Schubert nat->in_pr[1] = IPPROTO_ICMP;
87041edb306SCy Schubert }
87141edb306SCy Schubert nat->in_flags = IPN_ICMPQUERY;
87241edb306SCy Schubert nat->in_spmin = $3.p1;
87341edb306SCy Schubert nat->in_spmax = $3.p2;
87441edb306SCy Schubert }
87541edb306SCy Schubert ;
87641edb306SCy Schubert
87741edb306SCy Schubert sobject:
87841edb306SCy Schubert saddr { $$ = $1; }
87941edb306SCy Schubert | saddr port portstuff { nat->in_osport = $3.p1;
88041edb306SCy Schubert nat->in_stop = $3.p2;
88141edb306SCy Schubert nat->in_scmp = $3.pc;
88241edb306SCy Schubert $$ = $1;
88341edb306SCy Schubert }
88441edb306SCy Schubert ;
88541edb306SCy Schubert
88641edb306SCy Schubert saddr: addr { nat->in_osrcatype = $1.t;
88741edb306SCy Schubert bcopy(&$1.a,
88841edb306SCy Schubert &nat->in_osrc.na_addr[0],
88941edb306SCy Schubert sizeof($1.a));
89041edb306SCy Schubert bcopy(&$1.m,
89141edb306SCy Schubert &nat->in_osrc.na_addr[1],
89241edb306SCy Schubert sizeof($1.m));
89341edb306SCy Schubert $$ = $1.f;
89441edb306SCy Schubert }
89541edb306SCy Schubert ;
89641edb306SCy Schubert
89741edb306SCy Schubert dobject:
89841edb306SCy Schubert daddr { $$ = $1; }
89941edb306SCy Schubert | daddr port portstuff { nat->in_odport = $3.p1;
90041edb306SCy Schubert nat->in_dtop = $3.p2;
90141edb306SCy Schubert nat->in_dcmp = $3.pc;
90241edb306SCy Schubert $$ = $1;
90341edb306SCy Schubert }
90441edb306SCy Schubert ;
90541edb306SCy Schubert
90641edb306SCy Schubert daddr: addr { nat->in_odstatype = $1.t;
90741edb306SCy Schubert bcopy(&$1.a,
90841edb306SCy Schubert &nat->in_odst.na_addr[0],
90941edb306SCy Schubert sizeof($1.a));
91041edb306SCy Schubert bcopy(&$1.m,
91141edb306SCy Schubert &nat->in_odst.na_addr[1],
91241edb306SCy Schubert sizeof($1.m));
91341edb306SCy Schubert $$ = $1.f;
91441edb306SCy Schubert }
91541edb306SCy Schubert ;
91641edb306SCy Schubert
91741edb306SCy Schubert addr: IPNY_ANY { yyexpectaddr = 0;
91841edb306SCy Schubert bzero(&$$, sizeof($$));
91941edb306SCy Schubert $$.t = FRI_NORMAL;
92041edb306SCy Schubert }
92141edb306SCy Schubert | hostname { bzero(&$$, sizeof($$));
92241edb306SCy Schubert $$.a = $1.a;
92341edb306SCy Schubert $$.t = FRI_NORMAL;
92441edb306SCy Schubert $$.v = ftov($1.f);
92541edb306SCy Schubert $$.f = $1.f;
92641edb306SCy Schubert if ($$.f == AF_INET) {
92741edb306SCy Schubert $$.m.in4.s_addr = 0xffffffff;
92841edb306SCy Schubert } else if ($$.f == AF_INET6) {
92941edb306SCy Schubert $$.m.i6[0] = 0xffffffff;
93041edb306SCy Schubert $$.m.i6[1] = 0xffffffff;
93141edb306SCy Schubert $$.m.i6[2] = 0xffffffff;
93241edb306SCy Schubert $$.m.i6[3] = 0xffffffff;
93341edb306SCy Schubert }
93441edb306SCy Schubert yyexpectaddr = 0;
93541edb306SCy Schubert }
93641edb306SCy Schubert | hostname slash YY_NUMBER
93741edb306SCy Schubert { bzero(&$$, sizeof($$));
93841edb306SCy Schubert $$.a = $1.a;
93941edb306SCy Schubert $$.f = $1.f;
94041edb306SCy Schubert $$.v = ftov($1.f);
94141edb306SCy Schubert $$.t = FRI_NORMAL;
94241edb306SCy Schubert ntomask($$.f, $3, (u_32_t *)&$$.m);
94341edb306SCy Schubert $$.a.i6[0] &= $$.m.i6[0];
94441edb306SCy Schubert $$.a.i6[1] &= $$.m.i6[1];
94541edb306SCy Schubert $$.a.i6[2] &= $$.m.i6[2];
94641edb306SCy Schubert $$.a.i6[3] &= $$.m.i6[3];
94741edb306SCy Schubert yyexpectaddr = 0;
94841edb306SCy Schubert }
94941edb306SCy Schubert | hostname slash ipaddr { bzero(&$$, sizeof($$));
95041edb306SCy Schubert if ($1.f != $3.f) {
95141edb306SCy Schubert yyerror("1.address family "
95241edb306SCy Schubert "mismatch");
95341edb306SCy Schubert }
95441edb306SCy Schubert $$.a = $1.a;
95541edb306SCy Schubert $$.m = $3.a;
95641edb306SCy Schubert $$.t = FRI_NORMAL;
95741edb306SCy Schubert $$.a.i6[0] &= $$.m.i6[0];
95841edb306SCy Schubert $$.a.i6[1] &= $$.m.i6[1];
95941edb306SCy Schubert $$.a.i6[2] &= $$.m.i6[2];
96041edb306SCy Schubert $$.a.i6[3] &= $$.m.i6[3];
96141edb306SCy Schubert $$.f = $1.f;
96241edb306SCy Schubert $$.v = ftov($1.f);
96341edb306SCy Schubert yyexpectaddr = 0;
96441edb306SCy Schubert }
96541edb306SCy Schubert | hostname slash hexnumber { bzero(&$$, sizeof($$));
96641edb306SCy Schubert $$.a = $1.a;
96741edb306SCy Schubert $$.m.in4.s_addr = htonl($3);
96841edb306SCy Schubert $$.t = FRI_NORMAL;
96941edb306SCy Schubert $$.a.in4.s_addr &= $$.m.in4.s_addr;
97041edb306SCy Schubert $$.f = $1.f;
97141edb306SCy Schubert $$.v = ftov($1.f);
97241edb306SCy Schubert if ($$.f == AF_INET6)
97341edb306SCy Schubert yyerror("incorrect inet6 mask");
97441edb306SCy Schubert }
97541edb306SCy Schubert | hostname mask ipaddr { bzero(&$$, sizeof($$));
97641edb306SCy Schubert if ($1.f != $3.f) {
97741edb306SCy Schubert yyerror("2.address family "
97841edb306SCy Schubert "mismatch");
97941edb306SCy Schubert }
98041edb306SCy Schubert $$.a = $1.a;
98141edb306SCy Schubert $$.m = $3.a;
98241edb306SCy Schubert $$.t = FRI_NORMAL;
98341edb306SCy Schubert $$.a.i6[0] &= $$.m.i6[0];
98441edb306SCy Schubert $$.a.i6[1] &= $$.m.i6[1];
98541edb306SCy Schubert $$.a.i6[2] &= $$.m.i6[2];
98641edb306SCy Schubert $$.a.i6[3] &= $$.m.i6[3];
98741edb306SCy Schubert $$.f = $1.f;
98841edb306SCy Schubert $$.v = ftov($1.f);
98941edb306SCy Schubert yyexpectaddr = 0;
99041edb306SCy Schubert }
99141edb306SCy Schubert | hostname mask hexnumber { bzero(&$$, sizeof($$));
99241edb306SCy Schubert $$.a = $1.a;
99341edb306SCy Schubert $$.m.in4.s_addr = htonl($3);
99441edb306SCy Schubert $$.t = FRI_NORMAL;
99541edb306SCy Schubert $$.a.in4.s_addr &= $$.m.in4.s_addr;
99641edb306SCy Schubert $$.f = AF_INET;
99741edb306SCy Schubert $$.v = 4;
99841edb306SCy Schubert }
99941edb306SCy Schubert | pool slash YY_NUMBER { bzero(&$$, sizeof($$));
100041edb306SCy Schubert $$.a.iplookupnum = $3;
100141edb306SCy Schubert $$.a.iplookuptype = IPLT_POOL;
100241edb306SCy Schubert $$.a.iplookupsubtype = 0;
100341edb306SCy Schubert $$.t = FRI_LOOKUP;
100441edb306SCy Schubert }
100541edb306SCy Schubert | pool slash YY_STR { bzero(&$$, sizeof($$));
100641edb306SCy Schubert $$.a.iplookupname = addname(&nat,$3);
100741edb306SCy Schubert $$.a.iplookuptype = IPLT_POOL;
100841edb306SCy Schubert $$.a.iplookupsubtype = 1;
100941edb306SCy Schubert $$.t = FRI_LOOKUP;
101041edb306SCy Schubert }
101141edb306SCy Schubert | hash slash YY_NUMBER { bzero(&$$, sizeof($$));
101241edb306SCy Schubert $$.a.iplookupnum = $3;
101341edb306SCy Schubert $$.a.iplookuptype = IPLT_HASH;
101441edb306SCy Schubert $$.a.iplookupsubtype = 0;
101541edb306SCy Schubert $$.t = FRI_LOOKUP;
101641edb306SCy Schubert }
101741edb306SCy Schubert | hash slash YY_STR { bzero(&$$, sizeof($$));
101841edb306SCy Schubert $$.a.iplookupname = addname(&nat,$3);
101941edb306SCy Schubert $$.a.iplookuptype = IPLT_HASH;
102041edb306SCy Schubert $$.a.iplookupsubtype = 1;
102141edb306SCy Schubert $$.t = FRI_LOOKUP;
102241edb306SCy Schubert }
102341edb306SCy Schubert ;
102441edb306SCy Schubert
102541edb306SCy Schubert slash: '/' { yyexpectaddr = 0; }
102641edb306SCy Schubert ;
102741edb306SCy Schubert
102841edb306SCy Schubert mask: IPNY_MASK { yyexpectaddr = 0; }
102941edb306SCy Schubert ;
103041edb306SCy Schubert
103141edb306SCy Schubert pool: IPNY_POOL { if (!(nat->in_flags & IPN_FILTER)) {
103241edb306SCy Schubert yyerror("Can only use pool with from/to rules\n");
103341edb306SCy Schubert }
103441edb306SCy Schubert yyexpectaddr = 0;
103541edb306SCy Schubert yyresetdict();
103641edb306SCy Schubert }
103741edb306SCy Schubert ;
103841edb306SCy Schubert
103941edb306SCy Schubert hash: IPNY_HASH { if (!(nat->in_flags & IPN_FILTER)) {
104041edb306SCy Schubert yyerror("Can only use hash with from/to rules\n");
104141edb306SCy Schubert }
104241edb306SCy Schubert yyexpectaddr = 0;
104341edb306SCy Schubert yyresetdict();
104441edb306SCy Schubert }
104541edb306SCy Schubert ;
104641edb306SCy Schubert
104741edb306SCy Schubert portstuff:
104841edb306SCy Schubert compare portspec { $$.pc = $1; $$.p1 = $2; $$.p2 = 0; }
104941edb306SCy Schubert | portspec range portspec { $$.pc = $2; $$.p1 = $1; $$.p2 = $3; }
105041edb306SCy Schubert ;
105141edb306SCy Schubert
105241edb306SCy Schubert mapoptions:
105341edb306SCy Schubert rr frag age mssclamp nattag setproto purge
105441edb306SCy Schubert ;
105541edb306SCy Schubert
105641edb306SCy Schubert rdroptions:
105741edb306SCy Schubert rr frag age sticky mssclamp rdrproxy nattag purge
105841edb306SCy Schubert ;
105941edb306SCy Schubert
106041edb306SCy Schubert nattag: | IPNY_TAG YY_STR { strncpy(nat->in_tag.ipt_tag, $2,
106141edb306SCy Schubert sizeof(nat->in_tag.ipt_tag));
106241edb306SCy Schubert }
106341edb306SCy Schubert rr: | IPNY_ROUNDROBIN { nat->in_flags |= IPN_ROUNDR; }
106441edb306SCy Schubert ;
106541edb306SCy Schubert
106641edb306SCy Schubert frag: | IPNY_FRAG { nat->in_flags |= IPN_FRAG; }
106741edb306SCy Schubert ;
106841edb306SCy Schubert
106941edb306SCy Schubert age: | IPNY_AGE YY_NUMBER { nat->in_age[0] = $2;
107041edb306SCy Schubert nat->in_age[1] = $2; }
107141edb306SCy Schubert | IPNY_AGE YY_NUMBER '/' YY_NUMBER { nat->in_age[0] = $2;
107241edb306SCy Schubert nat->in_age[1] = $4; }
107341edb306SCy Schubert ;
107441edb306SCy Schubert
107541edb306SCy Schubert sticky: | IPNY_STICKY { if (!(nat->in_flags & IPN_ROUNDR) &&
107641edb306SCy Schubert !(nat->in_flags & IPN_SPLIT)) {
107741edb306SCy Schubert FPRINTF(stderr,
107841edb306SCy Schubert "'sticky' for use with round-robin/IP splitting only\n");
107941edb306SCy Schubert } else
108041edb306SCy Schubert nat->in_flags |= IPN_STICKY;
108141edb306SCy Schubert }
108241edb306SCy Schubert ;
108341edb306SCy Schubert
108441edb306SCy Schubert mssclamp:
108541edb306SCy Schubert | IPNY_MSSCLAMP YY_NUMBER { nat->in_mssclamp = $2; }
108641edb306SCy Schubert ;
108741edb306SCy Schubert
108841edb306SCy Schubert tcpudp: IPNY_TCP { setnatproto(IPPROTO_TCP); }
108941edb306SCy Schubert | IPNY_UDP { setnatproto(IPPROTO_UDP); }
109041edb306SCy Schubert | IPNY_TCPUDP { nat->in_flags |= IPN_TCPUDP;
109141edb306SCy Schubert nat->in_pr[0] = 0;
109241edb306SCy Schubert nat->in_pr[1] = 0;
109341edb306SCy Schubert }
109441edb306SCy Schubert | IPNY_TCP '/' IPNY_UDP { nat->in_flags |= IPN_TCPUDP;
109541edb306SCy Schubert nat->in_pr[0] = 0;
109641edb306SCy Schubert nat->in_pr[1] = 0;
109741edb306SCy Schubert }
109841edb306SCy Schubert ;
109941edb306SCy Schubert
110041edb306SCy Schubert sequential:
110141edb306SCy Schubert | IPNY_SEQUENTIAL { nat->in_flags |= IPN_SEQUENTIAL; }
110241edb306SCy Schubert ;
110341edb306SCy Schubert
110441edb306SCy Schubert purge:
110541edb306SCy Schubert | IPNY_PURGE { nat->in_flags |= IPN_PURGE; }
110641edb306SCy Schubert ;
110741edb306SCy Schubert
110841edb306SCy Schubert rdrproxy:
110941edb306SCy Schubert IPNY_PROXY YY_STR
111041edb306SCy Schubert { int pos;
111141edb306SCy Schubert pos = addname(&nat, $2);
111241edb306SCy Schubert nat->in_plabel = pos;
111341edb306SCy Schubert nat->in_odport = nat->in_dpnext;
111441edb306SCy Schubert nat->in_dtop = nat->in_odport;
111541edb306SCy Schubert free($2);
111641edb306SCy Schubert }
111741edb306SCy Schubert | proxy { if (nat->in_plabel != -1) {
111841edb306SCy Schubert nat->in_ndport = nat->in_odport;
111941edb306SCy Schubert nat->in_dpmin = nat->in_odport;
112041edb306SCy Schubert nat->in_dpmax = nat->in_dpmin;
112141edb306SCy Schubert nat->in_dtop = nat->in_dpmin;
112241edb306SCy Schubert nat->in_dpnext = nat->in_dpmin;
112341edb306SCy Schubert }
112441edb306SCy Schubert }
112541edb306SCy Schubert ;
112641edb306SCy Schubert
112741edb306SCy Schubert newopts:
112841edb306SCy Schubert | IPNY_PURGE { nat->in_flags |= IPN_PURGE; }
112941edb306SCy Schubert ;
113041edb306SCy Schubert
113141edb306SCy Schubert proto: YY_NUMBER { $$ = $1;
113241edb306SCy Schubert if ($$ != IPPROTO_TCP &&
113341edb306SCy Schubert $$ != IPPROTO_UDP)
113441edb306SCy Schubert suggest_port = 0;
113541edb306SCy Schubert }
113641edb306SCy Schubert | IPNY_TCP { $$ = IPPROTO_TCP; }
113741edb306SCy Schubert | IPNY_UDP { $$ = IPPROTO_UDP; }
113841edb306SCy Schubert | YY_STR { $$ = getproto($1);
113941edb306SCy Schubert free($1);
114041edb306SCy Schubert if ($$ == -1)
114141edb306SCy Schubert yyerror("unknown protocol");
114241edb306SCy Schubert if ($$ != IPPROTO_TCP &&
114341edb306SCy Schubert $$ != IPPROTO_UDP)
114441edb306SCy Schubert suggest_port = 0;
114541edb306SCy Schubert }
114641edb306SCy Schubert ;
114741edb306SCy Schubert
114841edb306SCy Schubert hexnumber:
114941edb306SCy Schubert YY_HEX { $$ = $1; }
115041edb306SCy Schubert ;
115141edb306SCy Schubert
115241edb306SCy Schubert hostname:
115341edb306SCy Schubert YY_STR { i6addr_t addr;
115441edb306SCy Schubert int family;
115541edb306SCy Schubert
115641edb306SCy Schubert #ifdef USE_INET6
115741edb306SCy Schubert if (nat->in_v[0] == 6)
115841edb306SCy Schubert family = AF_INET6;
115941edb306SCy Schubert else
116041edb306SCy Schubert #endif
116141edb306SCy Schubert family = AF_INET;
116241edb306SCy Schubert memset(&($$), 0, sizeof($$));
116341edb306SCy Schubert memset(&addr, 0, sizeof(addr));
116441edb306SCy Schubert $$.f = family;
116541edb306SCy Schubert if (gethost(family, $1,
116641edb306SCy Schubert &addr) == 0) {
116741edb306SCy Schubert $$.a = addr;
116841edb306SCy Schubert } else {
116941edb306SCy Schubert FPRINTF(stderr,
117041edb306SCy Schubert "Unknown host '%s'\n",
117141edb306SCy Schubert $1);
117241edb306SCy Schubert }
117341edb306SCy Schubert free($1);
117441edb306SCy Schubert }
117541edb306SCy Schubert | YY_NUMBER { memset(&($$), 0, sizeof($$));
117641edb306SCy Schubert $$.a.in4.s_addr = htonl($1);
117741edb306SCy Schubert if ($$.a.in4.s_addr != 0)
117841edb306SCy Schubert $$.f = AF_INET;
117941edb306SCy Schubert }
118041edb306SCy Schubert | ipv4 { $$ = $1; }
118141edb306SCy Schubert | YY_IPV6 { memset(&($$), 0, sizeof($$));
118241edb306SCy Schubert $$.a = $1;
118341edb306SCy Schubert $$.f = AF_INET6;
118441edb306SCy Schubert }
118541edb306SCy Schubert | YY_NUMBER YY_IPV6 { memset(&($$), 0, sizeof($$));
118641edb306SCy Schubert $$.a = $2;
118741edb306SCy Schubert $$.f = AF_INET6;
118841edb306SCy Schubert }
118941edb306SCy Schubert ;
119041edb306SCy Schubert
119141edb306SCy Schubert compare:
119241edb306SCy Schubert '=' { $$ = FR_EQUAL; }
119341edb306SCy Schubert | YY_CMP_EQ { $$ = FR_EQUAL; }
119441edb306SCy Schubert | YY_CMP_NE { $$ = FR_NEQUAL; }
119541edb306SCy Schubert | YY_CMP_LT { $$ = FR_LESST; }
119641edb306SCy Schubert | YY_CMP_LE { $$ = FR_LESSTE; }
119741edb306SCy Schubert | YY_CMP_GT { $$ = FR_GREATERT; }
119841edb306SCy Schubert | YY_CMP_GE { $$ = FR_GREATERTE; }
119941edb306SCy Schubert
120041edb306SCy Schubert range:
120141edb306SCy Schubert YY_RANGE_OUT { $$ = FR_OUTRANGE; }
120241edb306SCy Schubert | YY_RANGE_IN { $$ = FR_INRANGE; }
120341edb306SCy Schubert | ':' { $$ = FR_INCRANGE; }
120441edb306SCy Schubert ;
120541edb306SCy Schubert
120641edb306SCy Schubert ipaddr: ipv4 { $$ = $1; }
120741edb306SCy Schubert | YY_IPV6 { $$.a = $1;
120841edb306SCy Schubert $$.f = AF_INET6;
120941edb306SCy Schubert }
121041edb306SCy Schubert ;
121141edb306SCy Schubert
121241edb306SCy Schubert ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
121341edb306SCy Schubert { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
121441edb306SCy Schubert yyerror("Invalid octet string for IP address");
1215*2582ae57SCy Schubert return(0);
121641edb306SCy Schubert }
121741edb306SCy Schubert bzero((char *)&$$, sizeof($$));
121841edb306SCy Schubert $$.a.in4.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
121941edb306SCy Schubert $$.a.in4.s_addr = htonl($$.a.in4.s_addr);
122041edb306SCy Schubert $$.f = AF_INET;
122141edb306SCy Schubert }
122241edb306SCy Schubert ;
122341edb306SCy Schubert
122441edb306SCy Schubert %%
122541edb306SCy Schubert
122641edb306SCy Schubert
122741edb306SCy Schubert static wordtab_t proxies[] = {
122841edb306SCy Schubert { "dns", IPNY_DNS }
122941edb306SCy Schubert };
123041edb306SCy Schubert
123141edb306SCy Schubert static wordtab_t dnswords[] = {
123241edb306SCy Schubert { "allow", IPNY_ALLOW },
123341edb306SCy Schubert { "block", IPNY_DENY },
123441edb306SCy Schubert { "deny", IPNY_DENY },
123541edb306SCy Schubert { "drop", IPNY_DENY },
123641edb306SCy Schubert { "pass", IPNY_ALLOW },
123741edb306SCy Schubert
123841edb306SCy Schubert };
123941edb306SCy Schubert
124041edb306SCy Schubert static wordtab_t yywords[] = {
124141edb306SCy Schubert { "age", IPNY_AGE },
124241edb306SCy Schubert { "any", IPNY_ANY },
124341edb306SCy Schubert { "auto", IPNY_AUTO },
124441edb306SCy Schubert { "bimap", IPNY_BIMAP },
124541edb306SCy Schubert { "config", IPNY_CONFIG },
124641edb306SCy Schubert { "divert", IPNY_DIVERT },
124741edb306SCy Schubert { "dst", IPNY_DST },
124841edb306SCy Schubert { "dstlist", IPNY_DSTLIST },
124941edb306SCy Schubert { "frag", IPNY_FRAG },
125041edb306SCy Schubert { "from", IPNY_FROM },
125141edb306SCy Schubert { "hash", IPNY_HASH },
125241edb306SCy Schubert { "icmpidmap", IPNY_ICMPIDMAP },
125341edb306SCy Schubert { "in", IPNY_IN },
125441edb306SCy Schubert { "inet", IPNY_INET },
125541edb306SCy Schubert { "inet6", IPNY_INET6 },
125641edb306SCy Schubert { "mask", IPNY_MASK },
125741edb306SCy Schubert { "map", IPNY_MAP },
125841edb306SCy Schubert { "map-block", IPNY_MAPBLOCK },
125941edb306SCy Schubert { "mssclamp", IPNY_MSSCLAMP },
126041edb306SCy Schubert { "netmask", IPNY_MASK },
126141edb306SCy Schubert { "no", IPNY_NO },
126241edb306SCy Schubert { "on", IPNY_ON },
126341edb306SCy Schubert { "out", IPNY_OUT },
126441edb306SCy Schubert { "pool", IPNY_POOL },
126541edb306SCy Schubert { "port", IPNY_PORT },
126641edb306SCy Schubert { "portmap", IPNY_PORTMAP },
126741edb306SCy Schubert { "ports", IPNY_PORTS },
126841edb306SCy Schubert { "proto", IPNY_PROTO },
126941edb306SCy Schubert { "proxy", IPNY_PROXY },
127041edb306SCy Schubert { "purge", IPNY_PURGE },
127141edb306SCy Schubert { "range", IPNY_RANGE },
127241edb306SCy Schubert { "rewrite", IPNY_REWRITE },
127341edb306SCy Schubert { "rdr", IPNY_RDR },
127441edb306SCy Schubert { "round-robin",IPNY_ROUNDROBIN },
127541edb306SCy Schubert { "sequential", IPNY_SEQUENTIAL },
127641edb306SCy Schubert { "src", IPNY_SRC },
127741edb306SCy Schubert { "sticky", IPNY_STICKY },
127841edb306SCy Schubert { "tag", IPNY_TAG },
127941edb306SCy Schubert { "tcp", IPNY_TCP },
128041edb306SCy Schubert { "tcpudp", IPNY_TCPUDP },
128141edb306SCy Schubert { "to", IPNY_TO },
128241edb306SCy Schubert { "udp", IPNY_UDP },
128341edb306SCy Schubert { "-", '-' },
128441edb306SCy Schubert { "->", IPNY_TLATE },
128541edb306SCy Schubert { "eq", YY_CMP_EQ },
128641edb306SCy Schubert { "ne", YY_CMP_NE },
128741edb306SCy Schubert { "lt", YY_CMP_LT },
128841edb306SCy Schubert { "gt", YY_CMP_GT },
128941edb306SCy Schubert { "le", YY_CMP_LE },
129041edb306SCy Schubert { "ge", YY_CMP_GE },
129141edb306SCy Schubert { NULL, 0 }
129241edb306SCy Schubert };
129341edb306SCy Schubert
129441edb306SCy Schubert
129541edb306SCy Schubert int
ipnat_parsefile(int fd,addfunc_t addfunc,ioctlfunc_t ioctlfunc,char * filename)1296efeb8bffSCy Schubert ipnat_parsefile(int fd, addfunc_t addfunc, ioctlfunc_t ioctlfunc,
1297efeb8bffSCy Schubert char *filename)
129841edb306SCy Schubert {
129941edb306SCy Schubert FILE *fp = NULL;
130041edb306SCy Schubert int rval;
130141edb306SCy Schubert char *s;
130241edb306SCy Schubert
130341edb306SCy Schubert yylineNum = 1;
130441edb306SCy Schubert
130541edb306SCy Schubert (void) yysettab(yywords);
130641edb306SCy Schubert
130741edb306SCy Schubert s = getenv("YYDEBUG");
130841edb306SCy Schubert if (s)
130941edb306SCy Schubert yydebug = atoi(s);
131041edb306SCy Schubert else
131141edb306SCy Schubert yydebug = 0;
131241edb306SCy Schubert
131341edb306SCy Schubert if (strcmp(filename, "-")) {
131441edb306SCy Schubert fp = fopen(filename, "r");
131541edb306SCy Schubert if (!fp) {
131641edb306SCy Schubert FPRINTF(stderr, "fopen(%s) failed: %s\n", filename,
131741edb306SCy Schubert STRERROR(errno));
1318*2582ae57SCy Schubert return(-1);
131941edb306SCy Schubert }
132041edb306SCy Schubert } else
132141edb306SCy Schubert fp = stdin;
132241edb306SCy Schubert
132341edb306SCy Schubert while ((rval = ipnat_parsesome(fd, addfunc, ioctlfunc, fp)) == 0)
132441edb306SCy Schubert ;
132541edb306SCy Schubert if (fp != NULL)
132641edb306SCy Schubert fclose(fp);
132741edb306SCy Schubert if (rval == -1)
132841edb306SCy Schubert rval = 0;
132941edb306SCy Schubert else if (rval != 0)
133041edb306SCy Schubert rval = 1;
1331*2582ae57SCy Schubert return(rval);
133241edb306SCy Schubert }
133341edb306SCy Schubert
133441edb306SCy Schubert
133541edb306SCy Schubert int
ipnat_parsesome(int fd,addfunc_t addfunc,ioctlfunc_t ioctlfunc,FILE * fp)1336efeb8bffSCy Schubert ipnat_parsesome(int fd, addfunc_t addfunc, ioctlfunc_t ioctlfunc,
1337efeb8bffSCy Schubert FILE *fp)
133841edb306SCy Schubert {
133941edb306SCy Schubert char *s;
134041edb306SCy Schubert int i;
134141edb306SCy Schubert
134241edb306SCy Schubert natfd = fd;
134341edb306SCy Schubert parser_error = 0;
134441edb306SCy Schubert nataddfunc = addfunc;
134541edb306SCy Schubert natioctlfunc = ioctlfunc;
134641edb306SCy Schubert
134741edb306SCy Schubert if (feof(fp))
1348*2582ae57SCy Schubert return(-1);
134941edb306SCy Schubert i = fgetc(fp);
135041edb306SCy Schubert if (i == EOF)
1351*2582ae57SCy Schubert return(-1);
135241edb306SCy Schubert if (ungetc(i, fp) == EOF)
1353*2582ae57SCy Schubert return(-1);
135441edb306SCy Schubert if (feof(fp))
1355*2582ae57SCy Schubert return(-1);
135641edb306SCy Schubert s = getenv("YYDEBUG");
135741edb306SCy Schubert if (s)
135841edb306SCy Schubert yydebug = atoi(s);
135941edb306SCy Schubert else
136041edb306SCy Schubert yydebug = 0;
136141edb306SCy Schubert
136241edb306SCy Schubert yyin = fp;
136341edb306SCy Schubert yyparse();
1364*2582ae57SCy Schubert return(parser_error);
136541edb306SCy Schubert }
136641edb306SCy Schubert
136741edb306SCy Schubert
136841edb306SCy Schubert static void
newnatrule(void)1369efeb8bffSCy Schubert newnatrule(void)
137041edb306SCy Schubert {
137141edb306SCy Schubert ipnat_t *n;
137241edb306SCy Schubert
137341edb306SCy Schubert n = calloc(1, sizeof(*n));
137441edb306SCy Schubert if (n == NULL)
137541edb306SCy Schubert return;
137641edb306SCy Schubert
137741edb306SCy Schubert if (nat == NULL) {
137841edb306SCy Schubert nattop = nat = n;
137941edb306SCy Schubert n->in_pnext = &nattop;
138041edb306SCy Schubert } else {
138141edb306SCy Schubert nat->in_next = n;
138241edb306SCy Schubert n->in_pnext = &nat->in_next;
138341edb306SCy Schubert nat = n;
138441edb306SCy Schubert }
138541edb306SCy Schubert
138641edb306SCy Schubert n->in_flineno = yylineNum;
138741edb306SCy Schubert n->in_ifnames[0] = -1;
138841edb306SCy Schubert n->in_ifnames[1] = -1;
138941edb306SCy Schubert n->in_plabel = -1;
139041edb306SCy Schubert n->in_pconfig = -1;
139141edb306SCy Schubert n->in_size = sizeof(*n);
139241edb306SCy Schubert
139341edb306SCy Schubert suggest_port = 0;
139441edb306SCy Schubert }
139541edb306SCy Schubert
139641edb306SCy Schubert
139741edb306SCy Schubert static void
setnatproto(int p)1398efeb8bffSCy Schubert setnatproto(int p)
139941edb306SCy Schubert {
140041edb306SCy Schubert nat->in_pr[0] = p;
140141edb306SCy Schubert nat->in_pr[1] = p;
140241edb306SCy Schubert
140341edb306SCy Schubert switch (p)
140441edb306SCy Schubert {
140541edb306SCy Schubert case IPPROTO_TCP :
140641edb306SCy Schubert nat->in_flags |= IPN_TCP;
140741edb306SCy Schubert nat->in_flags &= ~IPN_UDP;
140841edb306SCy Schubert break;
140941edb306SCy Schubert case IPPROTO_UDP :
141041edb306SCy Schubert nat->in_flags |= IPN_UDP;
141141edb306SCy Schubert nat->in_flags &= ~IPN_TCP;
141241edb306SCy Schubert break;
141341edb306SCy Schubert #ifdef USE_INET6
141441edb306SCy Schubert case IPPROTO_ICMPV6 :
141541edb306SCy Schubert #endif
141641edb306SCy Schubert case IPPROTO_ICMP :
141741edb306SCy Schubert nat->in_flags &= ~IPN_TCPUDP;
141841edb306SCy Schubert if (!(nat->in_flags & IPN_ICMPQUERY) &&
141941edb306SCy Schubert !(nat->in_redir & NAT_DIVERTUDP)) {
142041edb306SCy Schubert nat->in_dcmp = 0;
142141edb306SCy Schubert nat->in_scmp = 0;
142241edb306SCy Schubert nat->in_dpmin = 0;
142341edb306SCy Schubert nat->in_dpmax = 0;
142441edb306SCy Schubert nat->in_dpnext = 0;
142541edb306SCy Schubert nat->in_spmin = 0;
142641edb306SCy Schubert nat->in_spmax = 0;
142741edb306SCy Schubert nat->in_spnext = 0;
142841edb306SCy Schubert }
142941edb306SCy Schubert break;
143041edb306SCy Schubert default :
143141edb306SCy Schubert if ((nat->in_redir & NAT_MAPBLK) == 0) {
143241edb306SCy Schubert nat->in_flags &= ~IPN_TCPUDP;
143341edb306SCy Schubert nat->in_dcmp = 0;
143441edb306SCy Schubert nat->in_scmp = 0;
143541edb306SCy Schubert nat->in_dpmin = 0;
143641edb306SCy Schubert nat->in_dpmax = 0;
143741edb306SCy Schubert nat->in_dpnext = 0;
143841edb306SCy Schubert nat->in_spmin = 0;
143941edb306SCy Schubert nat->in_spmax = 0;
144041edb306SCy Schubert nat->in_spnext = 0;
144141edb306SCy Schubert }
144241edb306SCy Schubert break;
144341edb306SCy Schubert }
144441edb306SCy Schubert
144541edb306SCy Schubert if ((nat->in_flags & (IPN_TCP|IPN_UDP)) == 0) {
144641edb306SCy Schubert nat->in_stop = 0;
144741edb306SCy Schubert nat->in_dtop = 0;
144841edb306SCy Schubert nat->in_osport = 0;
144941edb306SCy Schubert nat->in_odport = 0;
145041edb306SCy Schubert nat->in_stop = 0;
145141edb306SCy Schubert nat->in_osport = 0;
145241edb306SCy Schubert nat->in_dtop = 0;
145341edb306SCy Schubert nat->in_odport = 0;
145441edb306SCy Schubert }
145541edb306SCy Schubert if ((nat->in_flags & (IPN_TCPUDP|IPN_FIXEDDPORT)) == IPN_FIXEDDPORT)
145641edb306SCy Schubert nat->in_flags &= ~IPN_FIXEDDPORT;
145741edb306SCy Schubert }
145841edb306SCy Schubert
145941edb306SCy Schubert
146041edb306SCy Schubert int
ipnat_addrule(int fd,ioctlfunc_t ioctlfunc,void * ptr)1461efeb8bffSCy Schubert ipnat_addrule(int fd, ioctlfunc_t ioctlfunc, void *ptr)
146241edb306SCy Schubert {
146341edb306SCy Schubert ioctlcmd_t add, del;
146441edb306SCy Schubert ipfobj_t obj;
146541edb306SCy Schubert ipnat_t *ipn;
146641edb306SCy Schubert
146741edb306SCy Schubert ipn = ptr;
146841edb306SCy Schubert bzero((char *)&obj, sizeof(obj));
146941edb306SCy Schubert obj.ipfo_rev = IPFILTER_VERSION;
147041edb306SCy Schubert obj.ipfo_size = ipn->in_size;
147141edb306SCy Schubert obj.ipfo_type = IPFOBJ_IPNAT;
147241edb306SCy Schubert obj.ipfo_ptr = ptr;
147341edb306SCy Schubert
147441edb306SCy Schubert if ((opts & OPT_DONOTHING) != 0)
147541edb306SCy Schubert fd = -1;
147641edb306SCy Schubert
147741edb306SCy Schubert if (opts & OPT_ZERORULEST) {
147841edb306SCy Schubert add = SIOCZRLST;
147941edb306SCy Schubert del = 0;
148041edb306SCy Schubert } else if (opts & OPT_PURGE) {
148141edb306SCy Schubert add = 0;
148241edb306SCy Schubert del = SIOCPURGENAT;
148341edb306SCy Schubert } else {
148441edb306SCy Schubert add = SIOCADNAT;
148541edb306SCy Schubert del = SIOCRMNAT;
148641edb306SCy Schubert }
148741edb306SCy Schubert
148841edb306SCy Schubert if ((opts & OPT_VERBOSE) != 0)
148941edb306SCy Schubert printnat(ipn, opts);
149041edb306SCy Schubert
149141edb306SCy Schubert if (opts & OPT_DEBUG)
149241edb306SCy Schubert binprint(ipn, ipn->in_size);
149341edb306SCy Schubert
149441edb306SCy Schubert if ((opts & OPT_ZERORULEST) != 0) {
149541edb306SCy Schubert if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
149641edb306SCy Schubert if ((opts & OPT_DONOTHING) == 0) {
149741edb306SCy Schubert char msg[80];
149841edb306SCy Schubert
149941edb306SCy Schubert snprintf(msg, sizeof(msg), "%d:ioctl(zero nat rule)",
150041edb306SCy Schubert ipn->in_flineno);
1501*2582ae57SCy Schubert return(ipf_perror_fd(fd, ioctlfunc, msg));
150241edb306SCy Schubert }
150341edb306SCy Schubert } else {
150441edb306SCy Schubert PRINTF("hits %lu ", ipn->in_hits);
150541edb306SCy Schubert #ifdef USE_QUAD_T
150641edb306SCy Schubert PRINTF("bytes %"PRIu64" ",
150741edb306SCy Schubert ipn->in_bytes[0] + ipn->in_bytes[1]);
150841edb306SCy Schubert #else
150941edb306SCy Schubert PRINTF("bytes %lu ",
151041edb306SCy Schubert ipn->in_bytes[0] + ipn->in_bytes[1]);
151141edb306SCy Schubert #endif
151241edb306SCy Schubert printnat(ipn, opts);
151341edb306SCy Schubert }
151441edb306SCy Schubert } else if ((opts & OPT_REMOVE) != 0) {
151541edb306SCy Schubert if ((*ioctlfunc)(fd, del, (void *)&obj) == -1) {
151641edb306SCy Schubert if ((opts & OPT_DONOTHING) == 0) {
151741edb306SCy Schubert char msg[80];
151841edb306SCy Schubert
151941edb306SCy Schubert snprintf(msg, sizeof(msg), "%d:ioctl(delete nat rule)",
152041edb306SCy Schubert ipn->in_flineno);
1521*2582ae57SCy Schubert return(ipf_perror_fd(fd, ioctlfunc, msg));
152241edb306SCy Schubert }
152341edb306SCy Schubert }
152441edb306SCy Schubert } else {
152541edb306SCy Schubert if ((*ioctlfunc)(fd, add, (void *)&obj) == -1) {
152641edb306SCy Schubert if ((opts & OPT_DONOTHING) == 0) {
152741edb306SCy Schubert char msg[80];
152841edb306SCy Schubert
152941edb306SCy Schubert snprintf(msg, sizeof(msg), "%d:ioctl(add/insert nat rule)",
153041edb306SCy Schubert ipn->in_flineno);
153141edb306SCy Schubert if (errno == EEXIST) {
153241edb306SCy Schubert int strlen_msg = strlen(msg);
153341edb306SCy Schubert snprintf(msg + strlen_msg, sizeof(msg) -strlen_msg, "(line %d)",
153441edb306SCy Schubert ipn->in_flineno);
153541edb306SCy Schubert }
1536*2582ae57SCy Schubert return(ipf_perror_fd(fd, ioctlfunc, msg));
153741edb306SCy Schubert }
153841edb306SCy Schubert }
153941edb306SCy Schubert }
1540*2582ae57SCy Schubert return(0);
154141edb306SCy Schubert }
154241edb306SCy Schubert
154341edb306SCy Schubert
154441edb306SCy Schubert static void
setmapifnames()154541edb306SCy Schubert setmapifnames()
154641edb306SCy Schubert {
154741edb306SCy Schubert if (nat->in_ifnames[1] == -1)
154841edb306SCy Schubert nat->in_ifnames[1] = nat->in_ifnames[0];
154941edb306SCy Schubert
155041edb306SCy Schubert if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0)
155141edb306SCy Schubert nat->in_flags |= IPN_TCPUDP;
155241edb306SCy Schubert
155341edb306SCy Schubert if ((nat->in_flags & IPN_TCPUDP) == 0)
155441edb306SCy Schubert setnatproto(nat->in_pr[1]);
155541edb306SCy Schubert
155641edb306SCy Schubert if (((nat->in_redir & NAT_MAPBLK) != 0) ||
155741edb306SCy Schubert ((nat->in_flags & IPN_AUTOPORTMAP) != 0))
155841edb306SCy Schubert nat_setgroupmap(nat);
155941edb306SCy Schubert }
156041edb306SCy Schubert
156141edb306SCy Schubert
156241edb306SCy Schubert static void
setrdrifnames(void)1563efeb8bffSCy Schubert setrdrifnames(void)
156441edb306SCy Schubert {
156541edb306SCy Schubert if ((suggest_port == 1) && (nat->in_flags & IPN_TCPUDP) == 0)
156641edb306SCy Schubert nat->in_flags |= IPN_TCPUDP;
156741edb306SCy Schubert
156841edb306SCy Schubert if ((nat->in_pr[0] == 0) && ((nat->in_flags & IPN_TCPUDP) == 0) &&
156941edb306SCy Schubert (nat->in_dpmin != 0 || nat->in_dpmax != 0 || nat->in_dpnext != 0))
157041edb306SCy Schubert setnatproto(IPPROTO_TCP);
157141edb306SCy Schubert
157241edb306SCy Schubert if (nat->in_ifnames[1] == -1)
157341edb306SCy Schubert nat->in_ifnames[1] = nat->in_ifnames[0];
157441edb306SCy Schubert }
157541edb306SCy Schubert
157641edb306SCy Schubert
157741edb306SCy Schubert static void
proxy_setconfig(int proxy)1578efeb8bffSCy Schubert proxy_setconfig(int proxy)
157941edb306SCy Schubert {
158041edb306SCy Schubert if (proxy == IPNY_DNS) {
158141edb306SCy Schubert yysetfixeddict(dnswords);
158241edb306SCy Schubert }
158341edb306SCy Schubert }
158441edb306SCy Schubert
158541edb306SCy Schubert
158641edb306SCy Schubert static void
proxy_unsetconfig(void)1587efeb8bffSCy Schubert proxy_unsetconfig(void)
158841edb306SCy Schubert {
158941edb306SCy Schubert yyresetdict();
159041edb306SCy Schubert }
159141edb306SCy Schubert
159241edb306SCy Schubert
159341edb306SCy Schubert static namelist_t *
proxy_dns_add_pass(char * prefix,char * name)1594efeb8bffSCy Schubert proxy_dns_add_pass(char *prefix, char *name)
159541edb306SCy Schubert {
159641edb306SCy Schubert namelist_t *n;
159741edb306SCy Schubert
159841edb306SCy Schubert n = calloc(1, sizeof(*n));
159941edb306SCy Schubert if (n != NULL) {
160041edb306SCy Schubert if (prefix == NULL || *prefix == '\0') {
160141edb306SCy Schubert n->na_name = strdup(name);
160241edb306SCy Schubert } else {
160341edb306SCy Schubert n->na_name = malloc(strlen(name) + strlen(prefix) + 1);
160441edb306SCy Schubert strcpy(n->na_name, prefix);
160541edb306SCy Schubert strcat(n->na_name, name);
160641edb306SCy Schubert }
160741edb306SCy Schubert }
1608*2582ae57SCy Schubert return(n);
160941edb306SCy Schubert }
161041edb306SCy Schubert
161141edb306SCy Schubert
161241edb306SCy Schubert static namelist_t *
proxy_dns_add_block(char * prefix,char * name)1613efeb8bffSCy Schubert proxy_dns_add_block(char *prefix, char *name)
161441edb306SCy Schubert {
161541edb306SCy Schubert namelist_t *n;
161641edb306SCy Schubert
161741edb306SCy Schubert n = calloc(1, sizeof(*n));
161841edb306SCy Schubert if (n != NULL) {
161941edb306SCy Schubert if (prefix == NULL || *prefix == '\0') {
162041edb306SCy Schubert n->na_name = strdup(name);
162141edb306SCy Schubert } else {
162241edb306SCy Schubert n->na_name = malloc(strlen(name) + strlen(prefix) + 1);
162341edb306SCy Schubert strcpy(n->na_name, prefix);
162441edb306SCy Schubert strcat(n->na_name, name);
162541edb306SCy Schubert }
162641edb306SCy Schubert n->na_value = 1;
162741edb306SCy Schubert }
1628*2582ae57SCy Schubert return(n);
162941edb306SCy Schubert }
163041edb306SCy Schubert
163141edb306SCy Schubert
163241edb306SCy Schubert static void
proxy_addconfig(char * proxy,int proto,char * conf,namelist_t * list)1633efeb8bffSCy Schubert proxy_addconfig(char *proxy, int proto, char *conf, namelist_t *list)
163441edb306SCy Schubert {
163541edb306SCy Schubert proxyrule_t *pr;
163641edb306SCy Schubert
163741edb306SCy Schubert pr = calloc(1, sizeof(*pr));
163841edb306SCy Schubert if (pr != NULL) {
163941edb306SCy Schubert pr->pr_proto = proto;
164041edb306SCy Schubert pr->pr_proxy = proxy;
164141edb306SCy Schubert pr->pr_conf = conf;
164241edb306SCy Schubert pr->pr_names = list;
164341edb306SCy Schubert pr->pr_next = prules;
164441edb306SCy Schubert prules = pr;
164541edb306SCy Schubert }
164641edb306SCy Schubert }
164741edb306SCy Schubert
164841edb306SCy Schubert
164941edb306SCy Schubert static void
proxy_loadrules(int fd,ioctlfunc_t ioctlfunc,proxyrule_t * rules)1650efeb8bffSCy Schubert proxy_loadrules(int fd, ioctlfunc_t ioctlfunc, proxyrule_t *rules)
165141edb306SCy Schubert {
165241edb306SCy Schubert proxyrule_t *pr;
165341edb306SCy Schubert
165441edb306SCy Schubert while ((pr = rules) != NULL) {
165541edb306SCy Schubert proxy_loadconfig(fd, ioctlfunc, pr->pr_proxy, pr->pr_proto,
165641edb306SCy Schubert pr->pr_conf, pr->pr_names);
165741edb306SCy Schubert rules = pr->pr_next;
165841edb306SCy Schubert free(pr->pr_conf);
165941edb306SCy Schubert free(pr);
166041edb306SCy Schubert }
166141edb306SCy Schubert }
166241edb306SCy Schubert
166341edb306SCy Schubert
166441edb306SCy Schubert static void
proxy_loadconfig(int fd,ioctlfunc_t ioctlfunc,char * proxy,int proto,char * conf,namelist_t * list)1665efeb8bffSCy Schubert proxy_loadconfig(int fd, ioctlfunc_t ioctlfunc, char *proxy, int proto,
1666efeb8bffSCy Schubert char *conf, namelist_t *list)
166741edb306SCy Schubert {
166841edb306SCy Schubert namelist_t *na;
166941edb306SCy Schubert ipfobj_t obj;
167041edb306SCy Schubert ap_ctl_t pcmd;
167141edb306SCy Schubert
167241edb306SCy Schubert obj.ipfo_rev = IPFILTER_VERSION;
167341edb306SCy Schubert obj.ipfo_type = IPFOBJ_PROXYCTL;
167441edb306SCy Schubert obj.ipfo_size = sizeof(pcmd);
167541edb306SCy Schubert obj.ipfo_ptr = &pcmd;
167641edb306SCy Schubert
167741edb306SCy Schubert while ((na = list) != NULL) {
167841edb306SCy Schubert if ((opts & OPT_REMOVE) != 0)
167941edb306SCy Schubert pcmd.apc_cmd = APC_CMD_DEL;
168041edb306SCy Schubert else
168141edb306SCy Schubert pcmd.apc_cmd = APC_CMD_ADD;
168241edb306SCy Schubert pcmd.apc_dsize = strlen(na->na_name) + 1;
168341edb306SCy Schubert pcmd.apc_data = na->na_name;
168441edb306SCy Schubert pcmd.apc_arg = na->na_value;
168541edb306SCy Schubert pcmd.apc_p = proto;
168641edb306SCy Schubert
168741edb306SCy Schubert strncpy(pcmd.apc_label, proxy, APR_LABELLEN);
168841edb306SCy Schubert pcmd.apc_label[APR_LABELLEN - 1] = '\0';
168941edb306SCy Schubert
169041edb306SCy Schubert strncpy(pcmd.apc_config, conf, APR_LABELLEN);
169141edb306SCy Schubert pcmd.apc_config[APR_LABELLEN - 1] = '\0';
169241edb306SCy Schubert
169341edb306SCy Schubert if ((*ioctlfunc)(fd, SIOCPROXY, (void *)&obj) == -1) {
169441edb306SCy Schubert if ((opts & OPT_DONOTHING) == 0) {
169541edb306SCy Schubert char msg[80];
169641edb306SCy Schubert
169741edb306SCy Schubert snprintf(msg, sizeof(msg), "%d:ioctl(add/remove proxy rule)",
169841edb306SCy Schubert yylineNum);
169941edb306SCy Schubert ipf_perror_fd(fd, ioctlfunc, msg);
170041edb306SCy Schubert return;
170141edb306SCy Schubert }
170241edb306SCy Schubert }
170341edb306SCy Schubert
170441edb306SCy Schubert list = na->na_next;
170541edb306SCy Schubert free(na->na_name);
170641edb306SCy Schubert free(na);
170741edb306SCy Schubert }
170841edb306SCy Schubert }
170941edb306SCy Schubert
171041edb306SCy Schubert
171141edb306SCy Schubert static void
setifname(ipnat_t ** np,int idx,char * name)1712efeb8bffSCy Schubert setifname(ipnat_t **np, int idx, char *name)
171341edb306SCy Schubert {
171441edb306SCy Schubert int pos;
171541edb306SCy Schubert
171641edb306SCy Schubert pos = addname(np, name);
171741edb306SCy Schubert if (pos == -1)
171841edb306SCy Schubert return;
171941edb306SCy Schubert (*np)->in_ifnames[idx] = pos;
172041edb306SCy Schubert }
172141edb306SCy Schubert
172241edb306SCy Schubert
172341edb306SCy Schubert static int
addname(ipnat_t ** np,char * name)1724efeb8bffSCy Schubert addname(ipnat_t **np, char *name)
172541edb306SCy Schubert {
172641edb306SCy Schubert ipnat_t *n;
172741edb306SCy Schubert int nlen;
172841edb306SCy Schubert int pos;
172941edb306SCy Schubert
173041edb306SCy Schubert nlen = strlen(name) + 1;
173141edb306SCy Schubert n = realloc(*np, (*np)->in_size + nlen);
173241edb306SCy Schubert if (*np == nattop)
173341edb306SCy Schubert nattop = n;
173441edb306SCy Schubert *np = n;
173541edb306SCy Schubert if (n == NULL)
1736*2582ae57SCy Schubert return(-1);
173741edb306SCy Schubert if (n->in_pnext != NULL)
173841edb306SCy Schubert *n->in_pnext = n;
173941edb306SCy Schubert n->in_size += nlen;
174041edb306SCy Schubert pos = n->in_namelen;
174141edb306SCy Schubert n->in_namelen += nlen;
174241edb306SCy Schubert strcpy(n->in_names + pos, name);
174341edb306SCy Schubert n->in_names[n->in_namelen] = '\0';
1744*2582ae57SCy Schubert return(pos);
174541edb306SCy Schubert }
1746