1145519Sdarrenr/*	$FreeBSD: releng/10.3/contrib/ipfilter/tools/ippool_y.y 255332 2013-09-06 23:11:19Z cy $	*/
2145510Sdarrenr
3170268Sdarrenr/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5170268Sdarrenr *
6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7170268Sdarrenr */
8145510Sdarrenr%{
9145510Sdarrenr#include <sys/types.h>
10145510Sdarrenr#include <sys/time.h>
11145510Sdarrenr#include <sys/param.h>
12145510Sdarrenr#include <sys/socket.h>
13145510Sdarrenr#if defined(BSD) && (BSD >= 199306)
14145510Sdarrenr# include <sys/cdefs.h>
15145510Sdarrenr#endif
16145510Sdarrenr#include <sys/ioctl.h>
17145510Sdarrenr
18145510Sdarrenr#include <net/if.h>
19145510Sdarrenr#if __FreeBSD_version >= 300000
20145510Sdarrenr# include <net/if_var.h>
21145510Sdarrenr#endif
22145510Sdarrenr#include <netinet/in.h>
23145510Sdarrenr
24145510Sdarrenr#include <arpa/inet.h>
25145510Sdarrenr
26145510Sdarrenr#include <stdio.h>
27145510Sdarrenr#include <fcntl.h>
28145510Sdarrenr#include <stdlib.h>
29145510Sdarrenr#include <string.h>
30145510Sdarrenr#include <netdb.h>
31145510Sdarrenr#include <ctype.h>
32145510Sdarrenr#include <unistd.h>
33145510Sdarrenr
34145510Sdarrenr#include "ipf.h"
35145510Sdarrenr#include "netinet/ip_lookup.h"
36145510Sdarrenr#include "netinet/ip_pool.h"
37145510Sdarrenr#include "netinet/ip_htable.h"
38255332Scy#include "netinet/ip_dstlist.h"
39145510Sdarrenr#include "ippool_l.h"
40145510Sdarrenr#include "kmem.h"
41145510Sdarrenr
42145510Sdarrenr#define	YYDEBUG	1
43170268Sdarrenr#define	YYSTACKSIZE	0x00ffffff
44145510Sdarrenr
45145510Sdarrenrextern	int	yyparse __P((void));
46145510Sdarrenrextern	int	yydebug;
47145510Sdarrenrextern	FILE	*yyin;
48145510Sdarrenr
49145510Sdarrenrstatic	iphtable_t	ipht;
50145510Sdarrenrstatic	iphtent_t	iphte;
51145510Sdarrenrstatic	ip_pool_t	iplo;
52255332Scystatic	ippool_dst_t	ipld;
53145510Sdarrenrstatic	ioctlfunc_t	poolioctl = NULL;
54145510Sdarrenrstatic	char		poolname[FR_GROUPLEN];
55145510Sdarrenr
56170268Sdarrenrstatic iphtent_t *add_htablehosts __P((char *));
57170268Sdarrenrstatic ip_pool_node_t *add_poolhosts __P((char *));
58255332Scystatic ip_pool_node_t *read_whoisfile __P((char *));
59255332Scystatic void setadflen __P((addrfamily_t *));
60170268Sdarrenr
61145510Sdarrenr%}
62145510Sdarrenr
63145510Sdarrenr%union	{
64145510Sdarrenr	char	*str;
65145510Sdarrenr	u_32_t	num;
66255332Scy	struct	in_addr	ip4;
67145510Sdarrenr	struct	alist_s	*alist;
68255332Scy	addrfamily_t	adrmsk[2];
69145510Sdarrenr	iphtent_t	*ipe;
70145510Sdarrenr	ip_pool_node_t	*ipp;
71255332Scy	ipf_dstnode_t	*ipd;
72255332Scy	addrfamily_t	ipa;
73255332Scy	i6addr_t	ip6;
74145510Sdarrenr}
75145510Sdarrenr
76255332Scy%token  <num>	YY_NUMBER YY_HEX
77255332Scy%token  <str>	YY_STR
78255332Scy%token  <ip6>	YY_IPV6
79255332Scy%token	YY_COMMENT
80255332Scy%token	YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
81255332Scy%token	YY_RANGE_OUT YY_RANGE_IN
82255332Scy%token	IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT IPT_ALL
83255332Scy%token	IPT_TABLE IPT_GROUPMAP IPT_HASH IPT_SRCHASH IPT_DSTHASH
84145510Sdarrenr%token	IPT_ROLE IPT_TYPE IPT_TREE
85255332Scy%token	IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME IPT_POLICY
86255332Scy%token	IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN
87255332Scy%token	IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION
88255332Scy%token	IPT_WHOIS IPT_FILE
89255332Scy%type	<num> role table inout unit dstopts weighting
90145510Sdarrenr%type	<ipp> ipftree range addrlist
91145510Sdarrenr%type	<adrmsk> addrmask
92145510Sdarrenr%type	<ipe> ipfgroup ipfhash hashlist hashentry
93145510Sdarrenr%type	<ipe> groupentry setgrouplist grouplist
94255332Scy%type	<ipa> ipaddr mask
95255332Scy%type	<ip4> ipv4
96255332Scy%type	<str> number setgroup name
97255332Scy%type	<ipd> dstentry dstentries dstlist
98145510Sdarrenr
99145510Sdarrenr%%
100145510Sdarrenrfile:	line
101145510Sdarrenr	| assign
102145510Sdarrenr	| file line
103145510Sdarrenr	| file assign
104145510Sdarrenr	;
105145510Sdarrenr
106255332Scyline:	table role ipftree eol		{ ip_pool_node_t *n;
107255332Scy					  iplo.ipo_unit = $2;
108145510Sdarrenr					  iplo.ipo_list = $3;
109145510Sdarrenr					  load_pool(&iplo, poolioctl);
110255332Scy					  while ((n = $3) != NULL) {
111255332Scy						$3 = n->ipn_next;
112255332Scy						free(n);
113255332Scy					  }
114145510Sdarrenr					  resetlexer();
115255332Scy					  use_inet6 = 0;
116145510Sdarrenr					}
117255332Scy	| table role ipfhash eol	{ iphtent_t *h;
118255332Scy					  ipht.iph_unit = $2;
119145510Sdarrenr					  ipht.iph_type = IPHASH_LOOKUP;
120145510Sdarrenr					  load_hash(&ipht, $3, poolioctl);
121255332Scy					  while ((h = $3) != NULL) {
122255332Scy						$3 = h->ipe_next;
123255332Scy						free(h);
124255332Scy					  }
125145510Sdarrenr					  resetlexer();
126255332Scy					  use_inet6 = 0;
127145510Sdarrenr					}
128145510Sdarrenr	| groupmap role number ipfgroup eol
129255332Scy					{ iphtent_t *h;
130255332Scy					  ipht.iph_unit = $2;
131145510Sdarrenr					  strncpy(ipht.iph_name, $3,
132145510Sdarrenr						  sizeof(ipht.iph_name));
133145510Sdarrenr					  ipht.iph_type = IPHASH_GROUPMAP;
134145510Sdarrenr					  load_hash(&ipht, $4, poolioctl);
135255332Scy					  while ((h = $4) != NULL) {
136255332Scy						$4 = h->ipe_next;
137255332Scy						free(h);
138255332Scy					  }
139145510Sdarrenr					  resetlexer();
140255332Scy					  use_inet6 = 0;
141145510Sdarrenr					}
142145510Sdarrenr	| YY_COMMENT
143255332Scy	| poolline eol
144145510Sdarrenr	;
145145510Sdarrenr
146145510Sdarrenreol:	';'
147145510Sdarrenr	;
148145510Sdarrenr
149145510Sdarrenrassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
150145510Sdarrenr					  resetlexer();
151145510Sdarrenr					  free($1);
152145510Sdarrenr					  free($3);
153170268Sdarrenr					  yyvarnext = 0;
154145510Sdarrenr					}
155145510Sdarrenr	;
156145510Sdarrenr
157145510Sdarrenrassigning:
158145510Sdarrenr	'='				{ yyvarnext = 1; }
159145510Sdarrenr	;
160145510Sdarrenr
161145510Sdarrenrtable:	IPT_TABLE		{ bzero((char *)&ipht, sizeof(ipht));
162145510Sdarrenr				  bzero((char *)&iphte, sizeof(iphte));
163145510Sdarrenr				  bzero((char *)&iplo, sizeof(iplo));
164255332Scy				  bzero((char *)&ipld, sizeof(ipld));
165145510Sdarrenr				  *ipht.iph_name = '\0';
166145510Sdarrenr				  iplo.ipo_flags = IPHASH_ANON;
167145510Sdarrenr				  iplo.ipo_name[0] = '\0';
168145510Sdarrenr				}
169145510Sdarrenr	;
170145510Sdarrenr
171145510Sdarrenrgroupmap:
172145510Sdarrenr	IPT_GROUPMAP inout	{ bzero((char *)&ipht, sizeof(ipht));
173145510Sdarrenr				  bzero((char *)&iphte, sizeof(iphte));
174145510Sdarrenr				  *ipht.iph_name = '\0';
175145510Sdarrenr				  ipht.iph_unit = IPHASH_GROUPMAP;
176145510Sdarrenr				  ipht.iph_flags = $2;
177145510Sdarrenr				}
178145510Sdarrenr	;
179145510Sdarrenr
180145510Sdarrenrinout:	IPT_IN				{ $$ = FR_INQUE; }
181145510Sdarrenr	| IPT_OUT			{ $$ = FR_OUTQUE; }
182145510Sdarrenr	;
183255332Scy
184255332Scyrole:	IPT_ROLE '=' unit		{ $$ = $3; }
185145510Sdarrenr	;
186145510Sdarrenr
187255332Scyunit:	IPT_IPF				{ $$ = IPL_LOGIPF; }
188255332Scy	| IPT_NAT			{ $$ = IPL_LOGNAT; }
189255332Scy	| IPT_AUTH			{ $$ = IPL_LOGAUTH; }
190255332Scy	| IPT_COUNT			{ $$ = IPL_LOGCOUNT; }
191255332Scy	| IPT_ALL			{ $$ = IPL_LOGALL; }
192255332Scy	;
193255332Scy
194145510Sdarrenripftree:
195145510Sdarrenr	IPT_TYPE '=' IPT_TREE number start addrlist end
196145510Sdarrenr					{ strncpy(iplo.ipo_name, $4,
197145510Sdarrenr						  sizeof(iplo.ipo_name));
198145510Sdarrenr					  $$ = $6;
199145510Sdarrenr					}
200145510Sdarrenr	;
201145510Sdarrenr
202145510Sdarrenripfhash:
203145510Sdarrenr	IPT_TYPE '=' IPT_HASH number hashopts start hashlist end
204145510Sdarrenr					{ strncpy(ipht.iph_name, $4,
205145510Sdarrenr						  sizeof(ipht.iph_name));
206145510Sdarrenr					  $$ = $7;
207145510Sdarrenr					}
208145510Sdarrenr	;
209145510Sdarrenr
210145510Sdarrenripfgroup:
211145510Sdarrenr	setgroup hashopts start grouplist end
212145510Sdarrenr					{ iphtent_t *e;
213145510Sdarrenr					  for (e = $4; e != NULL;
214145510Sdarrenr					       e = e->ipe_next)
215145510Sdarrenr						if (e->ipe_group[0] == '\0')
216145510Sdarrenr							strncpy(e->ipe_group,
217145510Sdarrenr								$1,
218145510Sdarrenr								FR_GROUPLEN);
219145510Sdarrenr					  $$ = $4;
220255332Scy					  free($1);
221145510Sdarrenr					}
222255332Scy	| hashopts start setgrouplist end
223255332Scy					{ $$ = $3; }
224145510Sdarrenr	;
225145510Sdarrenr
226145510Sdarrenrnumber:	IPT_NUM '=' YY_NUMBER			{ sprintf(poolname, "%u", $3);
227145510Sdarrenr						  $$ = poolname;
228145510Sdarrenr						}
229255332Scy	| IPT_NAME '=' YY_STR			{ strncpy(poolname, $3,
230255332Scy							  FR_GROUPLEN);
231255332Scy						  poolname[FR_GROUPLEN-1]='\0';
232255332Scy						  free($3);
233255332Scy						  $$ = poolname;
234255332Scy						}
235145510Sdarrenr	|					{ $$ = ""; }
236145510Sdarrenr	;
237145510Sdarrenr
238145510Sdarrenrsetgroup:
239145510Sdarrenr	IPT_GROUP '=' YY_STR		{ char tmp[FR_GROUPLEN+1];
240145510Sdarrenr					  strncpy(tmp, $3, FR_GROUPLEN);
241145510Sdarrenr					  $$ = strdup(tmp);
242255332Scy					  free($3);
243145510Sdarrenr					}
244145510Sdarrenr	| IPT_GROUP '=' YY_NUMBER	{ char tmp[FR_GROUPLEN+1];
245145510Sdarrenr					  sprintf(tmp, "%u", $3);
246145510Sdarrenr					  $$ = strdup(tmp);
247145510Sdarrenr					}
248145510Sdarrenr	;
249145510Sdarrenr
250145510Sdarrenrhashopts:
251145510Sdarrenr	| size
252145510Sdarrenr	| seed
253145510Sdarrenr	| size seed
254145510Sdarrenr	;
255145510Sdarrenr
256145510Sdarrenraddrlist:
257255332Scy	';'				{ $$ = NULL; }
258255332Scy	| range next addrlist		{ $$ = $1;
259255332Scy					  while ($1->ipn_next != NULL)
260255332Scy						$1 = $1->ipn_next;
261255332Scy					  $1->ipn_next = $3;
262255332Scy					}
263145510Sdarrenr	| range next			{ $$ = $1; }
264145510Sdarrenr	;
265145510Sdarrenr
266145510Sdarrenrgrouplist:
267255332Scy	';'				{ $$ = NULL; }
268145510Sdarrenr	| groupentry next grouplist	{ $$ = $1; $1->ipe_next = $3; }
269145510Sdarrenr	| addrmask next grouplist	{ $$ = calloc(1, sizeof(iphtent_t));
270255332Scy					  $$->ipe_addr = $1[0].adf_addr;
271255332Scy					  $$->ipe_mask = $1[1].adf_addr;
272255332Scy					  $$->ipe_family = $1[0].adf_family;
273145510Sdarrenr					  $$->ipe_next = $3;
274145510Sdarrenr					}
275145510Sdarrenr	| groupentry next		{ $$ = $1; }
276145510Sdarrenr	| addrmask next			{ $$ = calloc(1, sizeof(iphtent_t));
277255332Scy					  $$->ipe_addr = $1[0].adf_addr;
278255332Scy					  $$->ipe_mask = $1[1].adf_addr;
279255332Scy#ifdef AF_INET6
280255332Scy					  if (use_inet6)
281255332Scy						$$->ipe_family = AF_INET6;
282255332Scy					  else
283255332Scy#endif
284255332Scy						$$->ipe_family = AF_INET;
285145510Sdarrenr					}
286255332Scy	| YY_STR			{ $$ = add_htablehosts($1);
287255332Scy					  free($1);
288255332Scy					}
289145510Sdarrenr	;
290145510Sdarrenr
291145510Sdarrenrsetgrouplist:
292255332Scy	';'				{ $$ = NULL; }
293145510Sdarrenr	| groupentry next		{ $$ = $1; }
294145510Sdarrenr	| groupentry next setgrouplist	{ $1->ipe_next = $3; $$ = $1; }
295145510Sdarrenr	;
296145510Sdarrenr
297145510Sdarrenrgroupentry:
298145510Sdarrenr	addrmask ',' setgroup		{ $$ = calloc(1, sizeof(iphtent_t));
299255332Scy					  $$->ipe_addr = $1[0].adf_addr;
300255332Scy					  $$->ipe_mask = $1[1].adf_addr;
301145510Sdarrenr					  strncpy($$->ipe_group, $3,
302145510Sdarrenr						  FR_GROUPLEN);
303255332Scy#ifdef AF_INET6
304255332Scy					  if (use_inet6)
305255332Scy						$$->ipe_family = AF_INET6;
306255332Scy					  else
307255332Scy#endif
308255332Scy						$$->ipe_family = AF_INET;
309145510Sdarrenr					  free($3);
310145510Sdarrenr					}
311145510Sdarrenr	;
312145510Sdarrenr
313255332Scyrange:	addrmask			{ $$ = calloc(1, sizeof(*$$));
314255332Scy					  $$->ipn_info = 0;
315255332Scy					  $$->ipn_addr = $1[0];
316255332Scy					  $$->ipn_mask = $1[1];
317255332Scy					}
318255332Scy	| '!' addrmask			{ $$ = calloc(1, sizeof(*$$));
319255332Scy					  $$->ipn_info = 1;
320255332Scy					  $$->ipn_addr = $2[0];
321255332Scy					  $$->ipn_mask = $2[1];
322255332Scy					}
323255332Scy	| YY_STR			{ $$ = add_poolhosts($1);
324255332Scy					  free($1);
325255332Scy					}
326255332Scy	| IPT_WHOIS IPT_FILE YY_STR	{ $$ = read_whoisfile($3);
327255332Scy					  free($3);
328255332Scy					}
329255332Scy	;
330145510Sdarrenr
331145510Sdarrenrhashlist:
332255332Scy	';'				{ $$ = NULL; }
333145510Sdarrenr	| hashentry next		{ $$ = $1; }
334145510Sdarrenr	| hashentry next hashlist	{ $1->ipe_next = $3; $$ = $1; }
335145510Sdarrenr	;
336145510Sdarrenr
337145510Sdarrenrhashentry:
338255332Scy	addrmask 		{ $$ = calloc(1, sizeof(iphtent_t));
339255332Scy				  $$->ipe_addr = $1[0].adf_addr;
340255332Scy				  $$->ipe_mask = $1[1].adf_addr;
341255332Scy#ifdef USE_INET6
342255332Scy				  if (use_inet6)
343255332Scy					$$->ipe_family = AF_INET6;
344255332Scy				  else
345255332Scy#endif
346255332Scy					$$->ipe_family = AF_INET;
347255332Scy				}
348255332Scy	| YY_STR		{ $$ = add_htablehosts($1);
349255332Scy				  free($1);
350255332Scy				}
351145510Sdarrenr	;
352145510Sdarrenr
353145510Sdarrenraddrmask:
354255332Scy	ipaddr '/' mask		{ $$[0] = $1;
355255332Scy				  setadflen(&$$[0]);
356255332Scy				  $$[1] = $3;
357255332Scy				  $$[1].adf_len = $$[0].adf_len;
358145510Sdarrenr				}
359255332Scy	| ipaddr		{ $$[0] = $1;
360255332Scy				  setadflen(&$$[1]);
361255332Scy				  $$[1].adf_len = $$[0].adf_len;
362255332Scy#ifdef USE_INET6
363255332Scy				  if (use_inet6)
364255332Scy					memset(&$$[1].adf_addr, 0xff,
365255332Scy					       sizeof($$[1].adf_addr.in6));
366255332Scy				  else
367255332Scy#endif
368255332Scy					memset(&$$[1].adf_addr, 0xff,
369255332Scy					       sizeof($$[1].adf_addr.in4));
370145510Sdarrenr				}
371145510Sdarrenr	;
372145510Sdarrenr
373255332Scyipaddr:	ipv4			{ $$.adf_addr.in4 = $1;
374255332Scy				  $$.adf_family = AF_INET;
375255332Scy				  setadflen(&$$);
376255332Scy				  use_inet6 = 0;
377255332Scy				}
378255332Scy	| YY_NUMBER		{ $$.adf_addr.in4.s_addr = htonl($1);
379255332Scy				  $$.adf_family = AF_INET;
380255332Scy				  setadflen(&$$);
381255332Scy				  use_inet6 = 0;
382255332Scy				}
383255332Scy	| YY_IPV6		{ $$.adf_addr = $1;
384255332Scy				  $$.adf_family = AF_INET6;
385255332Scy				  setadflen(&$$);
386255332Scy				  use_inet6 = 1;
387255332Scy				}
388145510Sdarrenr	;
389145510Sdarrenr
390255332Scymask:	YY_NUMBER	{ bzero(&$$, sizeof($$));
391255332Scy			  if (use_inet6) {
392255332Scy				if (ntomask(AF_INET6, $1,
393255332Scy					    (u_32_t *)&$$.adf_addr) == -1)
394255332Scy					yyerror("bad bitmask");
395255332Scy			  } else {
396255332Scy				if (ntomask(AF_INET, $1,
397255332Scy					    (u_32_t *)&$$.adf_addr.in4) == -1)
398255332Scy					yyerror("bad bitmask");
399255332Scy			  }
400255332Scy			}
401255332Scy	| ipv4		{ bzero(&$$, sizeof($$));
402255332Scy			  $$.adf_addr.in4 = $1;
403255332Scy			}
404255332Scy	| YY_IPV6	{ bzero(&$$, sizeof($$));
405255332Scy			  $$.adf_addr = $1;
406255332Scy			}
407145510Sdarrenr	;
408145510Sdarrenr
409255332Scysize:	IPT_SIZE '=' YY_NUMBER		{ ipht.iph_size = $3; }
410145510Sdarrenr	;
411145510Sdarrenr
412255332Scyseed:	IPT_SEED '=' YY_NUMBER		{ ipht.iph_seed = $3; }
413145510Sdarrenr	;
414145510Sdarrenr
415145510Sdarrenripv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
416145510Sdarrenr		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
417145510Sdarrenr			yyerror("Invalid octet string for IP address");
418145510Sdarrenr			return 0;
419145510Sdarrenr		  }
420145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
421145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
422145510Sdarrenr		}
423145510Sdarrenr	;
424255332Scy
425255332Scynext:	';'				{ yyexpectaddr = 1; }
426255332Scy	;
427255332Scy
428255332Scystart:	'{'				{ yyexpectaddr = 1; }
429255332Scy	;
430255332Scy
431255332Scyend:	'}'				{ yyexpectaddr = 0; }
432255332Scy	;
433255332Scy
434255332Scypoolline:
435255332Scy	IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')'
436255332Scy	start dstlist end
437255332Scy					{ bzero((char *)&ipld, sizeof(ipld));
438255332Scy					  strncpy(ipld.ipld_name, $6,
439255332Scy						  sizeof(ipld.ipld_name));
440255332Scy					  ipld.ipld_unit = $2;
441255332Scy					  ipld.ipld_policy = $8;
442255332Scy					  load_dstlist(&ipld, poolioctl, $11);
443255332Scy					  resetlexer();
444255332Scy					  use_inet6 = 0;
445255332Scy					  free($6);
446255332Scy					}
447255332Scy	| IPT_POOL unit '/' IPT_TREE '(' name ';' ')'
448255332Scy	  start addrlist end
449255332Scy					{ bzero((char *)&iplo, sizeof(iplo));
450255332Scy					  strncpy(iplo.ipo_name, $6,
451255332Scy						  sizeof(iplo.ipo_name));
452255332Scy					  iplo.ipo_list = $10;
453255332Scy					  iplo.ipo_unit = $2;
454255332Scy					  load_pool(&iplo, poolioctl);
455255332Scy					  resetlexer();
456255332Scy					  use_inet6 = 0;
457255332Scy					  free($6);
458255332Scy					}
459255332Scy	| IPT_POOL '(' name ';' ')' start addrlist end
460255332Scy					{ bzero((char *)&iplo, sizeof(iplo));
461255332Scy					  strncpy(iplo.ipo_name, $3,
462255332Scy						  sizeof(iplo.ipo_name));
463255332Scy					  iplo.ipo_list = $7;
464255332Scy					  iplo.ipo_unit = IPL_LOGALL;
465255332Scy					  load_pool(&iplo, poolioctl);
466255332Scy					  resetlexer();
467255332Scy					  use_inet6 = 0;
468255332Scy					  free($3);
469255332Scy					}
470255332Scy	| IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')'
471255332Scy	  start hashlist end
472255332Scy					{ iphtent_t *h;
473255332Scy					  bzero((char *)&ipht, sizeof(ipht));
474255332Scy					  strncpy(ipht.iph_name, $6,
475255332Scy						  sizeof(ipht.iph_name));
476255332Scy					  ipht.iph_unit = $2;
477255332Scy					  load_hash(&ipht, $11, poolioctl);
478255332Scy					  while ((h = ipht.iph_list) != NULL) {
479255332Scy						ipht.iph_list = h->ipe_next;
480255332Scy						free(h);
481255332Scy					  }
482255332Scy					  resetlexer();
483255332Scy					  use_inet6 = 0;
484255332Scy					  free($6);
485255332Scy					}
486255332Scy	| IPT_GROUPMAP '(' name ';' inout ';' ')'
487255332Scy	  start setgrouplist end
488255332Scy					{ iphtent_t *h;
489255332Scy					  bzero((char *)&ipht, sizeof(ipht));
490255332Scy					  strncpy(ipht.iph_name, $3,
491255332Scy						  sizeof(ipht.iph_name));
492255332Scy					  ipht.iph_type = IPHASH_GROUPMAP;
493255332Scy					  ipht.iph_unit = IPL_LOGIPF;
494255332Scy					  ipht.iph_flags = $5;
495255332Scy					  load_hash(&ipht, $9, poolioctl);
496255332Scy					  while ((h = ipht.iph_list) != NULL) {
497255332Scy						ipht.iph_list = h->ipe_next;
498255332Scy						free(h);
499255332Scy					  }
500255332Scy					  resetlexer();
501255332Scy					  use_inet6 = 0;
502255332Scy					  free($3);
503255332Scy					}
504255332Scy	;
505255332Scy
506255332Scyname:	IPT_NAME YY_STR			{ $$ = $2; }
507255332Scy	| IPT_NUM YY_NUMBER		{ char name[80];
508255332Scy					  sprintf(name, "%d", $2);
509255332Scy					  $$ = strdup(name);
510255332Scy					}
511255332Scy	;
512255332Scy
513255332Scyhashoptlist:
514255332Scy	| hashopt ';'
515255332Scy	| hashoptlist ';' hashopt ';'
516255332Scy	;
517255332Scyhashopt:
518255332Scy	IPT_SIZE YY_NUMBER
519255332Scy	| IPT_SEED YY_NUMBER
520255332Scy	;
521255332Scy
522255332Scydstlist:
523255332Scy	dstentries			{ $$ = $1; }
524255332Scy	| ';'				{ $$ = NULL; }
525255332Scy	;
526255332Scy
527255332Scydstentries:
528255332Scy	dstentry next			{ $$ = $1; }
529255332Scy	| dstentry next dstentries	{ $1->ipfd_next = $3; $$ = $1; }
530255332Scy	;
531255332Scy
532255332Scydstentry:
533255332Scy	YY_STR ':' ipaddr	{ int size = sizeof(*$$) + strlen($1) + 1;
534255332Scy				  $$ = calloc(1, size);
535255332Scy				  if ($$ != NULL) {
536255332Scy					$$->ipfd_dest.fd_name = strlen($1) + 1;
537255332Scy					bcopy($1, $$->ipfd_names,
538255332Scy					      $$->ipfd_dest.fd_name);
539255332Scy					$$->ipfd_dest.fd_addr = $3;
540255332Scy					$$->ipfd_size = size;
541255332Scy				  }
542255332Scy				  free($1);
543255332Scy				}
544255332Scy	| ipaddr		{ $$ = calloc(1, sizeof(*$$));
545255332Scy				  if ($$ != NULL) {
546255332Scy					$$->ipfd_dest.fd_name = -1;
547255332Scy					$$->ipfd_dest.fd_addr = $1;
548255332Scy					$$->ipfd_size = sizeof(*$$);
549255332Scy				  }
550255332Scy				}
551255332Scy	;
552255332Scy
553255332Scydstopts:
554255332Scy						{ $$ = IPLDP_NONE; }
555255332Scy	| IPT_POLICY IPT_ROUNDROBIN ';'		{ $$ = IPLDP_ROUNDROBIN; }
556255332Scy	| IPT_POLICY IPT_WEIGHTED weighting ';'	{ $$ = $3; }
557255332Scy	| IPT_POLICY IPT_RANDOM ';'		{ $$ = IPLDP_RANDOM; }
558255332Scy	| IPT_POLICY IPT_HASH ';'		{ $$ = IPLDP_HASHED; }
559255332Scy	| IPT_POLICY IPT_SRCHASH ';'		{ $$ = IPLDP_SRCHASH; }
560255332Scy	| IPT_POLICY IPT_DSTHASH ';'		{ $$ = IPLDP_DSTHASH; }
561255332Scy	;
562255332Scy
563255332Scyweighting:
564255332Scy	IPT_CONNECTION				{ $$ = IPLDP_CONNECTION; }
565255332Scy	;
566145510Sdarrenr%%
567145510Sdarrenrstatic	wordtab_t	yywords[] = {
568255332Scy	{ "all",		IPT_ALL },
569255332Scy	{ "auth",		IPT_AUTH },
570255332Scy	{ "connection",		IPT_CONNECTION },
571255332Scy	{ "count",		IPT_COUNT },
572255332Scy	{ "dst-hash",		IPT_DSTHASH },
573255332Scy	{ "dstlist",		IPT_DSTLIST },
574255332Scy	{ "file",		IPT_FILE },
575255332Scy	{ "group",		IPT_GROUP },
576255332Scy	{ "group-map",		IPT_GROUPMAP },
577255332Scy	{ "hash",		IPT_HASH },
578255332Scy	{ "in",			IPT_IN },
579255332Scy	{ "ipf",		IPT_IPF },
580255332Scy	{ "name",		IPT_NAME },
581255332Scy	{ "nat",		IPT_NAT },
582255332Scy	{ "number",		IPT_NUM },
583255332Scy	{ "out",		IPT_OUT },
584255332Scy	{ "policy",		IPT_POLICY },
585255332Scy	{ "pool",		IPT_POOL },
586255332Scy	{ "random",		IPT_RANDOM },
587255332Scy	{ "round-robin",	IPT_ROUNDROBIN },
588255332Scy	{ "role",		IPT_ROLE },
589255332Scy	{ "seed",		IPT_SEED },
590255332Scy	{ "size",		IPT_SIZE },
591255332Scy	{ "src-hash",		IPT_SRCHASH },
592255332Scy	{ "table",		IPT_TABLE },
593255332Scy	{ "tree",		IPT_TREE },
594255332Scy	{ "type",		IPT_TYPE },
595255332Scy	{ "weighted",		IPT_WEIGHTED },
596255332Scy	{ "whois",		IPT_WHOIS },
597255332Scy	{ NULL,			0 }
598145510Sdarrenr};
599145510Sdarrenr
600145510Sdarrenr
601145510Sdarrenrint ippool_parsefile(fd, filename, iocfunc)
602145510Sdarrenrint fd;
603145510Sdarrenrchar *filename;
604145510Sdarrenrioctlfunc_t iocfunc;
605145510Sdarrenr{
606145510Sdarrenr	FILE *fp = NULL;
607145510Sdarrenr	char *s;
608145510Sdarrenr
609145510Sdarrenr	yylineNum = 1;
610145510Sdarrenr	(void) yysettab(yywords);
611145510Sdarrenr
612145510Sdarrenr	s = getenv("YYDEBUG");
613145510Sdarrenr	if (s)
614145510Sdarrenr		yydebug = atoi(s);
615145510Sdarrenr	else
616145510Sdarrenr		yydebug = 0;
617145510Sdarrenr
618145510Sdarrenr	if (strcmp(filename, "-")) {
619145510Sdarrenr		fp = fopen(filename, "r");
620145510Sdarrenr		if (!fp) {
621145510Sdarrenr			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
622145510Sdarrenr				STRERROR(errno));
623145510Sdarrenr			return -1;
624145510Sdarrenr		}
625145510Sdarrenr	} else
626145510Sdarrenr		fp = stdin;
627145510Sdarrenr
628145510Sdarrenr	while (ippool_parsesome(fd, fp, iocfunc) == 1)
629145510Sdarrenr		;
630145510Sdarrenr	if (fp != NULL)
631145510Sdarrenr		fclose(fp);
632145510Sdarrenr	return 0;
633145510Sdarrenr}
634145510Sdarrenr
635145510Sdarrenr
636145510Sdarrenrint ippool_parsesome(fd, fp, iocfunc)
637145510Sdarrenrint fd;
638145510SdarrenrFILE *fp;
639145510Sdarrenrioctlfunc_t iocfunc;
640145510Sdarrenr{
641145510Sdarrenr	char *s;
642145510Sdarrenr	int i;
643145510Sdarrenr
644145510Sdarrenr	poolioctl = iocfunc;
645145510Sdarrenr
646145510Sdarrenr	if (feof(fp))
647145510Sdarrenr		return 0;
648145510Sdarrenr	i = fgetc(fp);
649145510Sdarrenr	if (i == EOF)
650145510Sdarrenr		return 0;
651145510Sdarrenr	if (ungetc(i, fp) == EOF)
652145510Sdarrenr		return 0;
653145510Sdarrenr	if (feof(fp))
654145510Sdarrenr		return 0;
655145510Sdarrenr	s = getenv("YYDEBUG");
656145510Sdarrenr	if (s)
657145510Sdarrenr		yydebug = atoi(s);
658145510Sdarrenr	else
659145510Sdarrenr		yydebug = 0;
660145510Sdarrenr
661145510Sdarrenr	yyin = fp;
662145510Sdarrenr	yyparse();
663145510Sdarrenr	return 1;
664145510Sdarrenr}
665170268Sdarrenr
666170268Sdarrenr
667170268Sdarrenrstatic iphtent_t *
668170268Sdarrenradd_htablehosts(url)
669170268Sdarrenrchar *url;
670170268Sdarrenr{
671170268Sdarrenr	iphtent_t *htop, *hbot, *h;
672170268Sdarrenr	alist_t *a, *hlist;
673170268Sdarrenr
674170268Sdarrenr	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
675170268Sdarrenr		hlist = load_url(url);
676170268Sdarrenr	} else {
677170268Sdarrenr		use_inet6 = 0;
678170268Sdarrenr
679170268Sdarrenr		hlist = calloc(1, sizeof(*hlist));
680170268Sdarrenr		if (hlist == NULL)
681170268Sdarrenr			return NULL;
682170268Sdarrenr
683255332Scy		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
684170268Sdarrenr			yyerror("Unknown hostname");
685255332Scy		}
686170268Sdarrenr	}
687170268Sdarrenr
688170268Sdarrenr	hbot = NULL;
689170268Sdarrenr	htop = NULL;
690170268Sdarrenr
691170268Sdarrenr	for (a = hlist; a != NULL; a = a->al_next) {
692170268Sdarrenr		h = calloc(1, sizeof(*h));
693170268Sdarrenr		if (h == NULL)
694170268Sdarrenr			break;
695170268Sdarrenr
696255332Scy		h->ipe_family = a->al_family;
697255332Scy		h->ipe_addr = a->al_i6addr;
698255332Scy		h->ipe_mask = a->al_i6mask;
699170268Sdarrenr
700170268Sdarrenr		if (hbot != NULL)
701170268Sdarrenr			hbot->ipe_next = h;
702170268Sdarrenr		else
703170268Sdarrenr			htop = h;
704170268Sdarrenr		hbot = h;
705170268Sdarrenr	}
706170268Sdarrenr
707170268Sdarrenr	alist_free(hlist);
708170268Sdarrenr
709170268Sdarrenr	return htop;
710170268Sdarrenr}
711170268Sdarrenr
712170268Sdarrenr
713170268Sdarrenrstatic ip_pool_node_t *
714170268Sdarrenradd_poolhosts(url)
715170268Sdarrenrchar *url;
716170268Sdarrenr{
717170268Sdarrenr	ip_pool_node_t *ptop, *pbot, *p;
718170268Sdarrenr	alist_t *a, *hlist;
719170268Sdarrenr
720170268Sdarrenr	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
721170268Sdarrenr		hlist = load_url(url);
722170268Sdarrenr	} else {
723170268Sdarrenr		use_inet6 = 0;
724170268Sdarrenr
725170268Sdarrenr		hlist = calloc(1, sizeof(*hlist));
726170268Sdarrenr		if (hlist == NULL)
727170268Sdarrenr			return NULL;
728170268Sdarrenr
729255332Scy		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
730170268Sdarrenr			yyerror("Unknown hostname");
731255332Scy		}
732170268Sdarrenr	}
733170268Sdarrenr
734170268Sdarrenr	pbot = NULL;
735170268Sdarrenr	ptop = NULL;
736170268Sdarrenr
737170268Sdarrenr	for (a = hlist; a != NULL; a = a->al_next) {
738170268Sdarrenr		p = calloc(1, sizeof(*p));
739170268Sdarrenr		if (p == NULL)
740170268Sdarrenr			break;
741255332Scy		p->ipn_mask.adf_addr = a->al_i6mask;
742170268Sdarrenr
743255332Scy		if (a->al_family == AF_INET) {
744255332Scy			p->ipn_addr.adf_family = AF_INET;
745255332Scy#ifdef USE_INET6
746255332Scy		} else if (a->al_family == AF_INET6) {
747255332Scy			p->ipn_addr.adf_family = AF_INET6;
748255332Scy#endif
749255332Scy		}
750255332Scy		setadflen(&p->ipn_addr);
751255332Scy		p->ipn_addr.adf_addr = a->al_i6addr;
752170268Sdarrenr		p->ipn_info = a->al_not;
753255332Scy		p->ipn_mask.adf_len = p->ipn_addr.adf_len;
754170268Sdarrenr
755170268Sdarrenr		if (pbot != NULL)
756170268Sdarrenr			pbot->ipn_next = p;
757170268Sdarrenr		else
758170268Sdarrenr			ptop = p;
759170268Sdarrenr		pbot = p;
760170268Sdarrenr	}
761170268Sdarrenr
762170268Sdarrenr	alist_free(hlist);
763170268Sdarrenr
764170268Sdarrenr	return ptop;
765170268Sdarrenr}
766255332Scy
767255332Scy
768255332Scyip_pool_node_t *
769255332Scyread_whoisfile(file)
770255332Scy	char *file;
771255332Scy{
772255332Scy	ip_pool_node_t *ntop, *ipn, node, *last;
773255332Scy	char line[1024];
774255332Scy	FILE *fp;
775255332Scy
776255332Scy	fp = fopen(file, "r");
777255332Scy	if (fp == NULL)
778255332Scy		return NULL;
779255332Scy
780255332Scy	last = NULL;
781255332Scy	ntop = NULL;
782255332Scy	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
783255332Scy		line[sizeof(line) - 1] = '\0';
784255332Scy
785255332Scy		if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask))
786255332Scy			continue;
787255332Scy		ipn = calloc(1, sizeof(*ipn));
788255332Scy		if (ipn == NULL)
789255332Scy			continue;
790255332Scy		ipn->ipn_addr = node.ipn_addr;
791255332Scy		ipn->ipn_mask = node.ipn_mask;
792255332Scy		if (last == NULL)
793255332Scy			ntop = ipn;
794255332Scy		else
795255332Scy			last->ipn_next = ipn;
796255332Scy		last = ipn;
797255332Scy	}
798255332Scy	fclose(fp);
799255332Scy	return ntop;
800255332Scy}
801255332Scy
802255332Scy
803255332Scystatic void
804255332Scysetadflen(afp)
805255332Scy	addrfamily_t *afp;
806255332Scy{
807255332Scy	afp->adf_len = offsetof(addrfamily_t, adf_addr);
808255332Scy	switch (afp->adf_family)
809255332Scy	{
810255332Scy	case AF_INET :
811255332Scy		afp->adf_len += sizeof(struct in_addr);
812255332Scy		break;
813255332Scy#ifdef USE_INET6
814255332Scy	case AF_INET6 :
815255332Scy		afp->adf_len += sizeof(struct in6_addr);
816255332Scy		break;
817255332Scy#endif
818255332Scy	default :
819255332Scy		break;
820255332Scy	}
821255332Scy}
822