1145519Sdarrenr/*	$FreeBSD: stable/11/contrib/ipfilter/tools/ippool_y.y 369245 2021-02-09 13:47:46Z git2svn $	*/
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# include <sys/cdefs.h>
14145510Sdarrenr#include <sys/ioctl.h>
15145510Sdarrenr
16145510Sdarrenr#include <net/if.h>
17145510Sdarrenr#include <netinet/in.h>
18145510Sdarrenr
19145510Sdarrenr#include <arpa/inet.h>
20145510Sdarrenr
21145510Sdarrenr#include <stdio.h>
22145510Sdarrenr#include <fcntl.h>
23145510Sdarrenr#include <stdlib.h>
24145510Sdarrenr#include <string.h>
25145510Sdarrenr#include <netdb.h>
26145510Sdarrenr#include <ctype.h>
27145510Sdarrenr#include <unistd.h>
28145510Sdarrenr
29145510Sdarrenr#include "ipf.h"
30145510Sdarrenr#include "netinet/ip_lookup.h"
31145510Sdarrenr#include "netinet/ip_pool.h"
32145510Sdarrenr#include "netinet/ip_htable.h"
33255332Scy#include "netinet/ip_dstlist.h"
34145510Sdarrenr#include "ippool_l.h"
35145510Sdarrenr#include "kmem.h"
36145510Sdarrenr
37145510Sdarrenr#define	YYDEBUG	1
38170268Sdarrenr#define	YYSTACKSIZE	0x00ffffff
39145510Sdarrenr
40369245Sgit2svnextern	int	yyparse(void);
41145510Sdarrenrextern	int	yydebug;
42145510Sdarrenrextern	FILE	*yyin;
43145510Sdarrenr
44145510Sdarrenrstatic	iphtable_t	ipht;
45145510Sdarrenrstatic	iphtent_t	iphte;
46145510Sdarrenrstatic	ip_pool_t	iplo;
47255332Scystatic	ippool_dst_t	ipld;
48145510Sdarrenrstatic	ioctlfunc_t	poolioctl = NULL;
49145510Sdarrenrstatic	char		poolname[FR_GROUPLEN];
50145510Sdarrenr
51369245Sgit2svnstatic iphtent_t *add_htablehosts(char *);
52369245Sgit2svnstatic ip_pool_node_t *add_poolhosts(char *);
53369245Sgit2svnstatic ip_pool_node_t *read_whoisfile(char *);
54369245Sgit2svnstatic void setadflen(addrfamily_t *);
55170268Sdarrenr
56145510Sdarrenr%}
57145510Sdarrenr
58145510Sdarrenr%union	{
59145510Sdarrenr	char	*str;
60145510Sdarrenr	u_32_t	num;
61255332Scy	struct	in_addr	ip4;
62145510Sdarrenr	struct	alist_s	*alist;
63255332Scy	addrfamily_t	adrmsk[2];
64145510Sdarrenr	iphtent_t	*ipe;
65145510Sdarrenr	ip_pool_node_t	*ipp;
66255332Scy	ipf_dstnode_t	*ipd;
67255332Scy	addrfamily_t	ipa;
68255332Scy	i6addr_t	ip6;
69145510Sdarrenr}
70145510Sdarrenr
71255332Scy%token  <num>	YY_NUMBER YY_HEX
72255332Scy%token  <str>	YY_STR
73255332Scy%token  <ip6>	YY_IPV6
74255332Scy%token	YY_COMMENT
75255332Scy%token	YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
76255332Scy%token	YY_RANGE_OUT YY_RANGE_IN
77255332Scy%token	IPT_IPF IPT_NAT IPT_COUNT IPT_AUTH IPT_IN IPT_OUT IPT_ALL
78255332Scy%token	IPT_TABLE IPT_GROUPMAP IPT_HASH IPT_SRCHASH IPT_DSTHASH
79145510Sdarrenr%token	IPT_ROLE IPT_TYPE IPT_TREE
80255332Scy%token	IPT_GROUP IPT_SIZE IPT_SEED IPT_NUM IPT_NAME IPT_POLICY
81255332Scy%token	IPT_POOL IPT_DSTLIST IPT_ROUNDROBIN
82255332Scy%token	IPT_WEIGHTED IPT_RANDOM IPT_CONNECTION
83255332Scy%token	IPT_WHOIS IPT_FILE
84255332Scy%type	<num> role table inout unit dstopts weighting
85145510Sdarrenr%type	<ipp> ipftree range addrlist
86145510Sdarrenr%type	<adrmsk> addrmask
87145510Sdarrenr%type	<ipe> ipfgroup ipfhash hashlist hashentry
88145510Sdarrenr%type	<ipe> groupentry setgrouplist grouplist
89255332Scy%type	<ipa> ipaddr mask
90255332Scy%type	<ip4> ipv4
91255332Scy%type	<str> number setgroup name
92255332Scy%type	<ipd> dstentry dstentries dstlist
93145510Sdarrenr
94145510Sdarrenr%%
95145510Sdarrenrfile:	line
96145510Sdarrenr	| assign
97145510Sdarrenr	| file line
98145510Sdarrenr	| file assign
99145510Sdarrenr	;
100145510Sdarrenr
101255332Scyline:	table role ipftree eol		{ ip_pool_node_t *n;
102255332Scy					  iplo.ipo_unit = $2;
103145510Sdarrenr					  iplo.ipo_list = $3;
104145510Sdarrenr					  load_pool(&iplo, poolioctl);
105255332Scy					  while ((n = $3) != NULL) {
106255332Scy						$3 = n->ipn_next;
107255332Scy						free(n);
108255332Scy					  }
109145510Sdarrenr					  resetlexer();
110255332Scy					  use_inet6 = 0;
111145510Sdarrenr					}
112255332Scy	| table role ipfhash eol	{ iphtent_t *h;
113255332Scy					  ipht.iph_unit = $2;
114145510Sdarrenr					  ipht.iph_type = IPHASH_LOOKUP;
115145510Sdarrenr					  load_hash(&ipht, $3, poolioctl);
116255332Scy					  while ((h = $3) != NULL) {
117255332Scy						$3 = h->ipe_next;
118255332Scy						free(h);
119255332Scy					  }
120145510Sdarrenr					  resetlexer();
121255332Scy					  use_inet6 = 0;
122145510Sdarrenr					}
123145510Sdarrenr	| groupmap role number ipfgroup eol
124255332Scy					{ iphtent_t *h;
125255332Scy					  ipht.iph_unit = $2;
126145510Sdarrenr					  strncpy(ipht.iph_name, $3,
127145510Sdarrenr						  sizeof(ipht.iph_name));
128145510Sdarrenr					  ipht.iph_type = IPHASH_GROUPMAP;
129145510Sdarrenr					  load_hash(&ipht, $4, poolioctl);
130255332Scy					  while ((h = $4) != NULL) {
131255332Scy						$4 = h->ipe_next;
132255332Scy						free(h);
133255332Scy					  }
134145510Sdarrenr					  resetlexer();
135255332Scy					  use_inet6 = 0;
136145510Sdarrenr					}
137145510Sdarrenr	| YY_COMMENT
138255332Scy	| poolline eol
139145510Sdarrenr	;
140145510Sdarrenr
141145510Sdarrenreol:	';'
142145510Sdarrenr	;
143145510Sdarrenr
144145510Sdarrenrassign:	YY_STR assigning YY_STR ';'	{ set_variable($1, $3);
145145510Sdarrenr					  resetlexer();
146145510Sdarrenr					  free($1);
147145510Sdarrenr					  free($3);
148170268Sdarrenr					  yyvarnext = 0;
149145510Sdarrenr					}
150145510Sdarrenr	;
151145510Sdarrenr
152145510Sdarrenrassigning:
153145510Sdarrenr	'='				{ yyvarnext = 1; }
154145510Sdarrenr	;
155145510Sdarrenr
156145510Sdarrenrtable:	IPT_TABLE		{ bzero((char *)&ipht, sizeof(ipht));
157145510Sdarrenr				  bzero((char *)&iphte, sizeof(iphte));
158145510Sdarrenr				  bzero((char *)&iplo, sizeof(iplo));
159255332Scy				  bzero((char *)&ipld, sizeof(ipld));
160145510Sdarrenr				  *ipht.iph_name = '\0';
161145510Sdarrenr				  iplo.ipo_flags = IPHASH_ANON;
162145510Sdarrenr				  iplo.ipo_name[0] = '\0';
163145510Sdarrenr				}
164145510Sdarrenr	;
165145510Sdarrenr
166145510Sdarrenrgroupmap:
167145510Sdarrenr	IPT_GROUPMAP inout	{ bzero((char *)&ipht, sizeof(ipht));
168145510Sdarrenr				  bzero((char *)&iphte, sizeof(iphte));
169145510Sdarrenr				  *ipht.iph_name = '\0';
170145510Sdarrenr				  ipht.iph_unit = IPHASH_GROUPMAP;
171145510Sdarrenr				  ipht.iph_flags = $2;
172145510Sdarrenr				}
173145510Sdarrenr	;
174145510Sdarrenr
175145510Sdarrenrinout:	IPT_IN				{ $$ = FR_INQUE; }
176145510Sdarrenr	| IPT_OUT			{ $$ = FR_OUTQUE; }
177145510Sdarrenr	;
178255332Scy
179255332Scyrole:	IPT_ROLE '=' unit		{ $$ = $3; }
180145510Sdarrenr	;
181145510Sdarrenr
182255332Scyunit:	IPT_IPF				{ $$ = IPL_LOGIPF; }
183255332Scy	| IPT_NAT			{ $$ = IPL_LOGNAT; }
184255332Scy	| IPT_AUTH			{ $$ = IPL_LOGAUTH; }
185255332Scy	| IPT_COUNT			{ $$ = IPL_LOGCOUNT; }
186255332Scy	| IPT_ALL			{ $$ = IPL_LOGALL; }
187255332Scy	;
188255332Scy
189145510Sdarrenripftree:
190145510Sdarrenr	IPT_TYPE '=' IPT_TREE number start addrlist end
191145510Sdarrenr					{ strncpy(iplo.ipo_name, $4,
192145510Sdarrenr						  sizeof(iplo.ipo_name));
193145510Sdarrenr					  $$ = $6;
194145510Sdarrenr					}
195145510Sdarrenr	;
196145510Sdarrenr
197145510Sdarrenripfhash:
198145510Sdarrenr	IPT_TYPE '=' IPT_HASH number hashopts start hashlist end
199145510Sdarrenr					{ strncpy(ipht.iph_name, $4,
200145510Sdarrenr						  sizeof(ipht.iph_name));
201145510Sdarrenr					  $$ = $7;
202145510Sdarrenr					}
203145510Sdarrenr	;
204145510Sdarrenr
205145510Sdarrenripfgroup:
206145510Sdarrenr	setgroup hashopts start grouplist end
207145510Sdarrenr					{ iphtent_t *e;
208145510Sdarrenr					  for (e = $4; e != NULL;
209145510Sdarrenr					       e = e->ipe_next)
210145510Sdarrenr						if (e->ipe_group[0] == '\0')
211145510Sdarrenr							strncpy(e->ipe_group,
212145510Sdarrenr								$1,
213145510Sdarrenr								FR_GROUPLEN);
214145510Sdarrenr					  $$ = $4;
215255332Scy					  free($1);
216145510Sdarrenr					}
217255332Scy	| hashopts start setgrouplist end
218255332Scy					{ $$ = $3; }
219145510Sdarrenr	;
220145510Sdarrenr
221145510Sdarrenrnumber:	IPT_NUM '=' YY_NUMBER			{ sprintf(poolname, "%u", $3);
222145510Sdarrenr						  $$ = poolname;
223145510Sdarrenr						}
224255332Scy	| IPT_NAME '=' YY_STR			{ strncpy(poolname, $3,
225255332Scy							  FR_GROUPLEN);
226255332Scy						  poolname[FR_GROUPLEN-1]='\0';
227255332Scy						  free($3);
228255332Scy						  $$ = poolname;
229255332Scy						}
230145510Sdarrenr	|					{ $$ = ""; }
231145510Sdarrenr	;
232145510Sdarrenr
233145510Sdarrenrsetgroup:
234145510Sdarrenr	IPT_GROUP '=' YY_STR		{ char tmp[FR_GROUPLEN+1];
235145510Sdarrenr					  strncpy(tmp, $3, FR_GROUPLEN);
236145510Sdarrenr					  $$ = strdup(tmp);
237255332Scy					  free($3);
238145510Sdarrenr					}
239145510Sdarrenr	| IPT_GROUP '=' YY_NUMBER	{ char tmp[FR_GROUPLEN+1];
240145510Sdarrenr					  sprintf(tmp, "%u", $3);
241145510Sdarrenr					  $$ = strdup(tmp);
242145510Sdarrenr					}
243145510Sdarrenr	;
244145510Sdarrenr
245145510Sdarrenrhashopts:
246145510Sdarrenr	| size
247145510Sdarrenr	| seed
248145510Sdarrenr	| size seed
249145510Sdarrenr	;
250145510Sdarrenr
251145510Sdarrenraddrlist:
252255332Scy	';'				{ $$ = NULL; }
253255332Scy	| range next addrlist		{ $$ = $1;
254255332Scy					  while ($1->ipn_next != NULL)
255255332Scy						$1 = $1->ipn_next;
256255332Scy					  $1->ipn_next = $3;
257255332Scy					}
258145510Sdarrenr	| range next			{ $$ = $1; }
259145510Sdarrenr	;
260145510Sdarrenr
261145510Sdarrenrgrouplist:
262255332Scy	';'				{ $$ = NULL; }
263145510Sdarrenr	| groupentry next grouplist	{ $$ = $1; $1->ipe_next = $3; }
264145510Sdarrenr	| addrmask next grouplist	{ $$ = calloc(1, sizeof(iphtent_t));
265255332Scy					  $$->ipe_addr = $1[0].adf_addr;
266255332Scy					  $$->ipe_mask = $1[1].adf_addr;
267255332Scy					  $$->ipe_family = $1[0].adf_family;
268145510Sdarrenr					  $$->ipe_next = $3;
269145510Sdarrenr					}
270145510Sdarrenr	| groupentry next		{ $$ = $1; }
271145510Sdarrenr	| addrmask next			{ $$ = calloc(1, sizeof(iphtent_t));
272255332Scy					  $$->ipe_addr = $1[0].adf_addr;
273255332Scy					  $$->ipe_mask = $1[1].adf_addr;
274255332Scy#ifdef AF_INET6
275255332Scy					  if (use_inet6)
276255332Scy						$$->ipe_family = AF_INET6;
277255332Scy					  else
278255332Scy#endif
279255332Scy						$$->ipe_family = AF_INET;
280145510Sdarrenr					}
281255332Scy	| YY_STR			{ $$ = add_htablehosts($1);
282255332Scy					  free($1);
283255332Scy					}
284145510Sdarrenr	;
285145510Sdarrenr
286145510Sdarrenrsetgrouplist:
287255332Scy	';'				{ $$ = NULL; }
288145510Sdarrenr	| groupentry next		{ $$ = $1; }
289145510Sdarrenr	| groupentry next setgrouplist	{ $1->ipe_next = $3; $$ = $1; }
290145510Sdarrenr	;
291145510Sdarrenr
292145510Sdarrenrgroupentry:
293145510Sdarrenr	addrmask ',' setgroup		{ $$ = calloc(1, sizeof(iphtent_t));
294255332Scy					  $$->ipe_addr = $1[0].adf_addr;
295255332Scy					  $$->ipe_mask = $1[1].adf_addr;
296145510Sdarrenr					  strncpy($$->ipe_group, $3,
297145510Sdarrenr						  FR_GROUPLEN);
298255332Scy#ifdef AF_INET6
299255332Scy					  if (use_inet6)
300255332Scy						$$->ipe_family = AF_INET6;
301255332Scy					  else
302255332Scy#endif
303255332Scy						$$->ipe_family = AF_INET;
304145510Sdarrenr					  free($3);
305145510Sdarrenr					}
306145510Sdarrenr	;
307145510Sdarrenr
308255332Scyrange:	addrmask			{ $$ = calloc(1, sizeof(*$$));
309255332Scy					  $$->ipn_info = 0;
310255332Scy					  $$->ipn_addr = $1[0];
311255332Scy					  $$->ipn_mask = $1[1];
312354111Scy#ifdef USE_INET6
313354111Scy					  if (use_inet6)
314354111Scy						$$->ipn_addr.adf_family =
315354111Scy							AF_INET6;
316354111Scy					  else
317354111Scy#endif
318354111Scy						$$->ipn_addr.adf_family =
319354111Scy							AF_INET;
320255332Scy					}
321255332Scy	| '!' addrmask			{ $$ = calloc(1, sizeof(*$$));
322255332Scy					  $$->ipn_info = 1;
323255332Scy					  $$->ipn_addr = $2[0];
324255332Scy					  $$->ipn_mask = $2[1];
325354111Scy#ifdef USE_INET6
326354111Scy					  if (use_inet6)
327354111Scy						$$->ipn_addr.adf_family =
328354111Scy							AF_INET6;
329354111Scy					  else
330354111Scy#endif
331354111Scy						$$->ipn_addr.adf_family =
332354111Scy							AF_INET;
333255332Scy					}
334255332Scy	| YY_STR			{ $$ = add_poolhosts($1);
335255332Scy					  free($1);
336255332Scy					}
337255332Scy	| IPT_WHOIS IPT_FILE YY_STR	{ $$ = read_whoisfile($3);
338255332Scy					  free($3);
339255332Scy					}
340255332Scy	;
341145510Sdarrenr
342145510Sdarrenrhashlist:
343255332Scy	';'				{ $$ = NULL; }
344145510Sdarrenr	| hashentry next		{ $$ = $1; }
345145510Sdarrenr	| hashentry next hashlist	{ $1->ipe_next = $3; $$ = $1; }
346145510Sdarrenr	;
347145510Sdarrenr
348145510Sdarrenrhashentry:
349255332Scy	addrmask 		{ $$ = calloc(1, sizeof(iphtent_t));
350255332Scy				  $$->ipe_addr = $1[0].adf_addr;
351255332Scy				  $$->ipe_mask = $1[1].adf_addr;
352255332Scy#ifdef USE_INET6
353255332Scy				  if (use_inet6)
354255332Scy					$$->ipe_family = AF_INET6;
355255332Scy				  else
356255332Scy#endif
357255332Scy					$$->ipe_family = AF_INET;
358255332Scy				}
359255332Scy	| YY_STR		{ $$ = add_htablehosts($1);
360255332Scy				  free($1);
361255332Scy				}
362145510Sdarrenr	;
363145510Sdarrenr
364145510Sdarrenraddrmask:
365255332Scy	ipaddr '/' mask		{ $$[0] = $1;
366255332Scy				  setadflen(&$$[0]);
367255332Scy				  $$[1] = $3;
368255332Scy				  $$[1].adf_len = $$[0].adf_len;
369145510Sdarrenr				}
370255332Scy	| ipaddr		{ $$[0] = $1;
371255332Scy				  setadflen(&$$[1]);
372255332Scy				  $$[1].adf_len = $$[0].adf_len;
373255332Scy#ifdef USE_INET6
374255332Scy				  if (use_inet6)
375255332Scy					memset(&$$[1].adf_addr, 0xff,
376255332Scy					       sizeof($$[1].adf_addr.in6));
377255332Scy				  else
378255332Scy#endif
379255332Scy					memset(&$$[1].adf_addr, 0xff,
380255332Scy					       sizeof($$[1].adf_addr.in4));
381145510Sdarrenr				}
382145510Sdarrenr	;
383145510Sdarrenr
384255332Scyipaddr:	ipv4			{ $$.adf_addr.in4 = $1;
385255332Scy				  $$.adf_family = AF_INET;
386255332Scy				  setadflen(&$$);
387255332Scy				  use_inet6 = 0;
388255332Scy				}
389255332Scy	| YY_NUMBER		{ $$.adf_addr.in4.s_addr = htonl($1);
390255332Scy				  $$.adf_family = AF_INET;
391255332Scy				  setadflen(&$$);
392255332Scy				  use_inet6 = 0;
393255332Scy				}
394255332Scy	| YY_IPV6		{ $$.adf_addr = $1;
395255332Scy				  $$.adf_family = AF_INET6;
396255332Scy				  setadflen(&$$);
397255332Scy				  use_inet6 = 1;
398255332Scy				}
399145510Sdarrenr	;
400145510Sdarrenr
401255332Scymask:	YY_NUMBER	{ bzero(&$$, sizeof($$));
402255332Scy			  if (use_inet6) {
403255332Scy				if (ntomask(AF_INET6, $1,
404255332Scy					    (u_32_t *)&$$.adf_addr) == -1)
405255332Scy					yyerror("bad bitmask");
406255332Scy			  } else {
407255332Scy				if (ntomask(AF_INET, $1,
408255332Scy					    (u_32_t *)&$$.adf_addr.in4) == -1)
409255332Scy					yyerror("bad bitmask");
410255332Scy			  }
411255332Scy			}
412255332Scy	| ipv4		{ bzero(&$$, sizeof($$));
413255332Scy			  $$.adf_addr.in4 = $1;
414255332Scy			}
415255332Scy	| YY_IPV6	{ bzero(&$$, sizeof($$));
416255332Scy			  $$.adf_addr = $1;
417255332Scy			}
418145510Sdarrenr	;
419145510Sdarrenr
420255332Scysize:	IPT_SIZE '=' YY_NUMBER		{ ipht.iph_size = $3; }
421145510Sdarrenr	;
422145510Sdarrenr
423255332Scyseed:	IPT_SEED '=' YY_NUMBER		{ ipht.iph_seed = $3; }
424145510Sdarrenr	;
425145510Sdarrenr
426145510Sdarrenripv4:	YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
427145510Sdarrenr		{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
428145510Sdarrenr			yyerror("Invalid octet string for IP address");
429145510Sdarrenr			return 0;
430145510Sdarrenr		  }
431145510Sdarrenr		  $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
432145510Sdarrenr		  $$.s_addr = htonl($$.s_addr);
433145510Sdarrenr		}
434145510Sdarrenr	;
435255332Scy
436255332Scynext:	';'				{ yyexpectaddr = 1; }
437255332Scy	;
438255332Scy
439255332Scystart:	'{'				{ yyexpectaddr = 1; }
440255332Scy	;
441255332Scy
442255332Scyend:	'}'				{ yyexpectaddr = 0; }
443255332Scy	;
444255332Scy
445255332Scypoolline:
446255332Scy	IPT_POOL unit '/' IPT_DSTLIST '(' name ';' dstopts ')'
447255332Scy	start dstlist end
448255332Scy					{ bzero((char *)&ipld, sizeof(ipld));
449255332Scy					  strncpy(ipld.ipld_name, $6,
450255332Scy						  sizeof(ipld.ipld_name));
451255332Scy					  ipld.ipld_unit = $2;
452255332Scy					  ipld.ipld_policy = $8;
453255332Scy					  load_dstlist(&ipld, poolioctl, $11);
454255332Scy					  resetlexer();
455255332Scy					  use_inet6 = 0;
456255332Scy					  free($6);
457255332Scy					}
458255332Scy	| IPT_POOL unit '/' IPT_TREE '(' name ';' ')'
459255332Scy	  start addrlist end
460255332Scy					{ bzero((char *)&iplo, sizeof(iplo));
461255332Scy					  strncpy(iplo.ipo_name, $6,
462255332Scy						  sizeof(iplo.ipo_name));
463255332Scy					  iplo.ipo_list = $10;
464255332Scy					  iplo.ipo_unit = $2;
465255332Scy					  load_pool(&iplo, poolioctl);
466255332Scy					  resetlexer();
467255332Scy					  use_inet6 = 0;
468255332Scy					  free($6);
469255332Scy					}
470255332Scy	| IPT_POOL '(' name ';' ')' start addrlist end
471255332Scy					{ bzero((char *)&iplo, sizeof(iplo));
472255332Scy					  strncpy(iplo.ipo_name, $3,
473255332Scy						  sizeof(iplo.ipo_name));
474255332Scy					  iplo.ipo_list = $7;
475255332Scy					  iplo.ipo_unit = IPL_LOGALL;
476255332Scy					  load_pool(&iplo, poolioctl);
477255332Scy					  resetlexer();
478255332Scy					  use_inet6 = 0;
479255332Scy					  free($3);
480255332Scy					}
481255332Scy	| IPT_POOL unit '/' IPT_HASH '(' name ';' hashoptlist ')'
482255332Scy	  start hashlist end
483255332Scy					{ iphtent_t *h;
484255332Scy					  bzero((char *)&ipht, sizeof(ipht));
485255332Scy					  strncpy(ipht.iph_name, $6,
486255332Scy						  sizeof(ipht.iph_name));
487255332Scy					  ipht.iph_unit = $2;
488255332Scy					  load_hash(&ipht, $11, poolioctl);
489255332Scy					  while ((h = ipht.iph_list) != NULL) {
490255332Scy						ipht.iph_list = h->ipe_next;
491255332Scy						free(h);
492255332Scy					  }
493255332Scy					  resetlexer();
494255332Scy					  use_inet6 = 0;
495255332Scy					  free($6);
496255332Scy					}
497255332Scy	| IPT_GROUPMAP '(' name ';' inout ';' ')'
498255332Scy	  start setgrouplist end
499255332Scy					{ iphtent_t *h;
500255332Scy					  bzero((char *)&ipht, sizeof(ipht));
501255332Scy					  strncpy(ipht.iph_name, $3,
502255332Scy						  sizeof(ipht.iph_name));
503255332Scy					  ipht.iph_type = IPHASH_GROUPMAP;
504255332Scy					  ipht.iph_unit = IPL_LOGIPF;
505255332Scy					  ipht.iph_flags = $5;
506255332Scy					  load_hash(&ipht, $9, poolioctl);
507255332Scy					  while ((h = ipht.iph_list) != NULL) {
508255332Scy						ipht.iph_list = h->ipe_next;
509255332Scy						free(h);
510255332Scy					  }
511255332Scy					  resetlexer();
512255332Scy					  use_inet6 = 0;
513255332Scy					  free($3);
514255332Scy					}
515255332Scy	;
516255332Scy
517255332Scyname:	IPT_NAME YY_STR			{ $$ = $2; }
518255332Scy	| IPT_NUM YY_NUMBER		{ char name[80];
519255332Scy					  sprintf(name, "%d", $2);
520255332Scy					  $$ = strdup(name);
521255332Scy					}
522255332Scy	;
523255332Scy
524255332Scyhashoptlist:
525255332Scy	| hashopt ';'
526255332Scy	| hashoptlist ';' hashopt ';'
527255332Scy	;
528255332Scyhashopt:
529255332Scy	IPT_SIZE YY_NUMBER
530255332Scy	| IPT_SEED YY_NUMBER
531255332Scy	;
532255332Scy
533255332Scydstlist:
534255332Scy	dstentries			{ $$ = $1; }
535255332Scy	| ';'				{ $$ = NULL; }
536255332Scy	;
537255332Scy
538255332Scydstentries:
539255332Scy	dstentry next			{ $$ = $1; }
540255332Scy	| dstentry next dstentries	{ $1->ipfd_next = $3; $$ = $1; }
541255332Scy	;
542255332Scy
543255332Scydstentry:
544255332Scy	YY_STR ':' ipaddr	{ int size = sizeof(*$$) + strlen($1) + 1;
545255332Scy				  $$ = calloc(1, size);
546255332Scy				  if ($$ != NULL) {
547255332Scy					$$->ipfd_dest.fd_name = strlen($1) + 1;
548255332Scy					bcopy($1, $$->ipfd_names,
549255332Scy					      $$->ipfd_dest.fd_name);
550255332Scy					$$->ipfd_dest.fd_addr = $3;
551255332Scy					$$->ipfd_size = size;
552255332Scy				  }
553255332Scy				  free($1);
554255332Scy				}
555255332Scy	| ipaddr		{ $$ = calloc(1, sizeof(*$$));
556255332Scy				  if ($$ != NULL) {
557255332Scy					$$->ipfd_dest.fd_name = -1;
558255332Scy					$$->ipfd_dest.fd_addr = $1;
559255332Scy					$$->ipfd_size = sizeof(*$$);
560255332Scy				  }
561255332Scy				}
562255332Scy	;
563255332Scy
564255332Scydstopts:
565255332Scy						{ $$ = IPLDP_NONE; }
566255332Scy	| IPT_POLICY IPT_ROUNDROBIN ';'		{ $$ = IPLDP_ROUNDROBIN; }
567255332Scy	| IPT_POLICY IPT_WEIGHTED weighting ';'	{ $$ = $3; }
568255332Scy	| IPT_POLICY IPT_RANDOM ';'		{ $$ = IPLDP_RANDOM; }
569255332Scy	| IPT_POLICY IPT_HASH ';'		{ $$ = IPLDP_HASHED; }
570255332Scy	| IPT_POLICY IPT_SRCHASH ';'		{ $$ = IPLDP_SRCHASH; }
571255332Scy	| IPT_POLICY IPT_DSTHASH ';'		{ $$ = IPLDP_DSTHASH; }
572255332Scy	;
573255332Scy
574255332Scyweighting:
575255332Scy	IPT_CONNECTION				{ $$ = IPLDP_CONNECTION; }
576255332Scy	;
577145510Sdarrenr%%
578145510Sdarrenrstatic	wordtab_t	yywords[] = {
579255332Scy	{ "all",		IPT_ALL },
580255332Scy	{ "auth",		IPT_AUTH },
581255332Scy	{ "connection",		IPT_CONNECTION },
582255332Scy	{ "count",		IPT_COUNT },
583255332Scy	{ "dst-hash",		IPT_DSTHASH },
584255332Scy	{ "dstlist",		IPT_DSTLIST },
585255332Scy	{ "file",		IPT_FILE },
586255332Scy	{ "group",		IPT_GROUP },
587255332Scy	{ "group-map",		IPT_GROUPMAP },
588255332Scy	{ "hash",		IPT_HASH },
589255332Scy	{ "in",			IPT_IN },
590255332Scy	{ "ipf",		IPT_IPF },
591255332Scy	{ "name",		IPT_NAME },
592255332Scy	{ "nat",		IPT_NAT },
593255332Scy	{ "number",		IPT_NUM },
594255332Scy	{ "out",		IPT_OUT },
595255332Scy	{ "policy",		IPT_POLICY },
596255332Scy	{ "pool",		IPT_POOL },
597255332Scy	{ "random",		IPT_RANDOM },
598255332Scy	{ "round-robin",	IPT_ROUNDROBIN },
599255332Scy	{ "role",		IPT_ROLE },
600255332Scy	{ "seed",		IPT_SEED },
601255332Scy	{ "size",		IPT_SIZE },
602255332Scy	{ "src-hash",		IPT_SRCHASH },
603255332Scy	{ "table",		IPT_TABLE },
604255332Scy	{ "tree",		IPT_TREE },
605255332Scy	{ "type",		IPT_TYPE },
606255332Scy	{ "weighted",		IPT_WEIGHTED },
607255332Scy	{ "whois",		IPT_WHOIS },
608255332Scy	{ NULL,			0 }
609145510Sdarrenr};
610145510Sdarrenr
611145510Sdarrenr
612145510Sdarrenrint ippool_parsefile(fd, filename, iocfunc)
613145510Sdarrenrint fd;
614145510Sdarrenrchar *filename;
615145510Sdarrenrioctlfunc_t iocfunc;
616145510Sdarrenr{
617145510Sdarrenr	FILE *fp = NULL;
618145510Sdarrenr	char *s;
619145510Sdarrenr
620145510Sdarrenr	yylineNum = 1;
621145510Sdarrenr	(void) yysettab(yywords);
622145510Sdarrenr
623145510Sdarrenr	s = getenv("YYDEBUG");
624145510Sdarrenr	if (s)
625145510Sdarrenr		yydebug = atoi(s);
626145510Sdarrenr	else
627145510Sdarrenr		yydebug = 0;
628145510Sdarrenr
629145510Sdarrenr	if (strcmp(filename, "-")) {
630145510Sdarrenr		fp = fopen(filename, "r");
631145510Sdarrenr		if (!fp) {
632145510Sdarrenr			fprintf(stderr, "fopen(%s) failed: %s\n", filename,
633145510Sdarrenr				STRERROR(errno));
634145510Sdarrenr			return -1;
635145510Sdarrenr		}
636145510Sdarrenr	} else
637145510Sdarrenr		fp = stdin;
638145510Sdarrenr
639145510Sdarrenr	while (ippool_parsesome(fd, fp, iocfunc) == 1)
640145510Sdarrenr		;
641145510Sdarrenr	if (fp != NULL)
642145510Sdarrenr		fclose(fp);
643145510Sdarrenr	return 0;
644145510Sdarrenr}
645145510Sdarrenr
646145510Sdarrenr
647145510Sdarrenrint ippool_parsesome(fd, fp, iocfunc)
648145510Sdarrenrint fd;
649145510SdarrenrFILE *fp;
650145510Sdarrenrioctlfunc_t iocfunc;
651145510Sdarrenr{
652145510Sdarrenr	char *s;
653145510Sdarrenr	int i;
654145510Sdarrenr
655145510Sdarrenr	poolioctl = iocfunc;
656145510Sdarrenr
657145510Sdarrenr	if (feof(fp))
658145510Sdarrenr		return 0;
659145510Sdarrenr	i = fgetc(fp);
660145510Sdarrenr	if (i == EOF)
661145510Sdarrenr		return 0;
662145510Sdarrenr	if (ungetc(i, fp) == EOF)
663145510Sdarrenr		return 0;
664145510Sdarrenr	if (feof(fp))
665145510Sdarrenr		return 0;
666145510Sdarrenr	s = getenv("YYDEBUG");
667145510Sdarrenr	if (s)
668145510Sdarrenr		yydebug = atoi(s);
669145510Sdarrenr	else
670145510Sdarrenr		yydebug = 0;
671145510Sdarrenr
672145510Sdarrenr	yyin = fp;
673145510Sdarrenr	yyparse();
674145510Sdarrenr	return 1;
675145510Sdarrenr}
676170268Sdarrenr
677170268Sdarrenr
678170268Sdarrenrstatic iphtent_t *
679170268Sdarrenradd_htablehosts(url)
680170268Sdarrenrchar *url;
681170268Sdarrenr{
682170268Sdarrenr	iphtent_t *htop, *hbot, *h;
683170268Sdarrenr	alist_t *a, *hlist;
684170268Sdarrenr
685170268Sdarrenr	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
686170268Sdarrenr		hlist = load_url(url);
687170268Sdarrenr	} else {
688170268Sdarrenr		use_inet6 = 0;
689170268Sdarrenr
690170268Sdarrenr		hlist = calloc(1, sizeof(*hlist));
691170268Sdarrenr		if (hlist == NULL)
692170268Sdarrenr			return NULL;
693170268Sdarrenr
694255332Scy		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
695170268Sdarrenr			yyerror("Unknown hostname");
696255332Scy		}
697170268Sdarrenr	}
698170268Sdarrenr
699170268Sdarrenr	hbot = NULL;
700170268Sdarrenr	htop = NULL;
701170268Sdarrenr
702170268Sdarrenr	for (a = hlist; a != NULL; a = a->al_next) {
703170268Sdarrenr		h = calloc(1, sizeof(*h));
704170268Sdarrenr		if (h == NULL)
705170268Sdarrenr			break;
706170268Sdarrenr
707255332Scy		h->ipe_family = a->al_family;
708255332Scy		h->ipe_addr = a->al_i6addr;
709255332Scy		h->ipe_mask = a->al_i6mask;
710170268Sdarrenr
711170268Sdarrenr		if (hbot != NULL)
712170268Sdarrenr			hbot->ipe_next = h;
713170268Sdarrenr		else
714170268Sdarrenr			htop = h;
715170268Sdarrenr		hbot = h;
716170268Sdarrenr	}
717170268Sdarrenr
718170268Sdarrenr	alist_free(hlist);
719170268Sdarrenr
720170268Sdarrenr	return htop;
721170268Sdarrenr}
722170268Sdarrenr
723170268Sdarrenr
724170268Sdarrenrstatic ip_pool_node_t *
725170268Sdarrenradd_poolhosts(url)
726170268Sdarrenrchar *url;
727170268Sdarrenr{
728170268Sdarrenr	ip_pool_node_t *ptop, *pbot, *p;
729170268Sdarrenr	alist_t *a, *hlist;
730170268Sdarrenr
731170268Sdarrenr	if (!strncmp(url, "file://", 7) || !strncmp(url, "http://", 7)) {
732170268Sdarrenr		hlist = load_url(url);
733170268Sdarrenr	} else {
734170268Sdarrenr		use_inet6 = 0;
735170268Sdarrenr
736170268Sdarrenr		hlist = calloc(1, sizeof(*hlist));
737170268Sdarrenr		if (hlist == NULL)
738170268Sdarrenr			return NULL;
739170268Sdarrenr
740255332Scy		if (gethost(hlist->al_family, url, &hlist->al_i6addr) == -1) {
741170268Sdarrenr			yyerror("Unknown hostname");
742255332Scy		}
743170268Sdarrenr	}
744170268Sdarrenr
745170268Sdarrenr	pbot = NULL;
746170268Sdarrenr	ptop = NULL;
747170268Sdarrenr
748170268Sdarrenr	for (a = hlist; a != NULL; a = a->al_next) {
749170268Sdarrenr		p = calloc(1, sizeof(*p));
750170268Sdarrenr		if (p == NULL)
751170268Sdarrenr			break;
752255332Scy		p->ipn_mask.adf_addr = a->al_i6mask;
753170268Sdarrenr
754255332Scy		if (a->al_family == AF_INET) {
755255332Scy			p->ipn_addr.adf_family = AF_INET;
756255332Scy#ifdef USE_INET6
757255332Scy		} else if (a->al_family == AF_INET6) {
758255332Scy			p->ipn_addr.adf_family = AF_INET6;
759255332Scy#endif
760255332Scy		}
761255332Scy		setadflen(&p->ipn_addr);
762255332Scy		p->ipn_addr.adf_addr = a->al_i6addr;
763170268Sdarrenr		p->ipn_info = a->al_not;
764255332Scy		p->ipn_mask.adf_len = p->ipn_addr.adf_len;
765170268Sdarrenr
766170268Sdarrenr		if (pbot != NULL)
767170268Sdarrenr			pbot->ipn_next = p;
768170268Sdarrenr		else
769170268Sdarrenr			ptop = p;
770170268Sdarrenr		pbot = p;
771170268Sdarrenr	}
772170268Sdarrenr
773170268Sdarrenr	alist_free(hlist);
774170268Sdarrenr
775170268Sdarrenr	return ptop;
776170268Sdarrenr}
777255332Scy
778255332Scy
779255332Scyip_pool_node_t *
780255332Scyread_whoisfile(file)
781255332Scy	char *file;
782255332Scy{
783255332Scy	ip_pool_node_t *ntop, *ipn, node, *last;
784255332Scy	char line[1024];
785255332Scy	FILE *fp;
786255332Scy
787255332Scy	fp = fopen(file, "r");
788255332Scy	if (fp == NULL)
789255332Scy		return NULL;
790255332Scy
791255332Scy	last = NULL;
792255332Scy	ntop = NULL;
793255332Scy	while (fgets(line, sizeof(line) - 1, fp) != NULL) {
794255332Scy		line[sizeof(line) - 1] = '\0';
795255332Scy
796255332Scy		if (parsewhoisline(line, &node.ipn_addr, &node.ipn_mask))
797255332Scy			continue;
798255332Scy		ipn = calloc(1, sizeof(*ipn));
799255332Scy		if (ipn == NULL)
800255332Scy			continue;
801255332Scy		ipn->ipn_addr = node.ipn_addr;
802255332Scy		ipn->ipn_mask = node.ipn_mask;
803255332Scy		if (last == NULL)
804255332Scy			ntop = ipn;
805255332Scy		else
806255332Scy			last->ipn_next = ipn;
807255332Scy		last = ipn;
808255332Scy	}
809255332Scy	fclose(fp);
810255332Scy	return ntop;
811255332Scy}
812255332Scy
813255332Scy
814255332Scystatic void
815255332Scysetadflen(afp)
816255332Scy	addrfamily_t *afp;
817255332Scy{
818255332Scy	afp->adf_len = offsetof(addrfamily_t, adf_addr);
819255332Scy	switch (afp->adf_family)
820255332Scy	{
821255332Scy	case AF_INET :
822255332Scy		afp->adf_len += sizeof(struct in_addr);
823255332Scy		break;
824255332Scy#ifdef USE_INET6
825255332Scy	case AF_INET6 :
826255332Scy		afp->adf_len += sizeof(struct in6_addr);
827255332Scy		break;
828255332Scy#endif
829255332Scy	default :
830255332Scy		break;
831255332Scy	}
832255332Scy}
833