parse.y revision 1.102
1/*	$OpenBSD: parse.y,v 1.102 2006/06/08 21:15:21 naddy Exp $	*/
2
3/*
4 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier.  All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt.  All rights reserved.
8 * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
9 *
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23%{
24#include <sys/types.h>
25#include <sys/ioctl.h>
26#include <sys/queue.h>
27#include <sys/socket.h>
28#include <sys/stat.h>
29#include <net/if.h>
30#include <netinet/in.h>
31#include <netinet/ip_ipsp.h>
32#include <arpa/inet.h>
33
34#include <ctype.h>
35#include <err.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <ifaddrs.h>
39#include <limits.h>
40#include <netdb.h>
41#include <stdarg.h>
42#include <stdio.h>
43#include <string.h>
44#include <syslog.h>
45#include <unistd.h>
46#include <netdb.h>
47
48#include "ipsecctl.h"
49
50#define KEYSIZE_LIMIT	1024
51
52static struct ipsecctl	*ipsec = NULL;
53static FILE		*fin = NULL;
54static int		 lineno = 1;
55static int		 errors = 0;
56static int		 debug = 0;
57
58const struct ipsec_xf authxfs[] = {
59	{ "unknown",		AUTHXF_UNKNOWN,		0,	0 },
60	{ "none",		AUTHXF_NONE,		0,	0 },
61	{ "hmac-md5",		AUTHXF_HMAC_MD5,	16,	0 },
62	{ "hmac-ripemd160",	AUTHXF_HMAC_RIPEMD160,	20,	0 },
63	{ "hmac-sha1",		AUTHXF_HMAC_SHA1,	20,	0 },
64	{ "hmac-sha2-256",	AUTHXF_HMAC_SHA2_256,	32,	0 },
65	{ "hmac-sha2-384",	AUTHXF_HMAC_SHA2_384,	48,	0 },
66	{ "hmac-sha2-512",	AUTHXF_HMAC_SHA2_512,	64,	0 },
67	{ NULL,			0,			0,	0 },
68};
69
70const struct ipsec_xf encxfs[] = {
71	{ "unknown",		ENCXF_UNKNOWN,		0,	0 },
72	{ "none",		ENCXF_NONE,		0,	0 },
73	{ "3des-cbc",		ENCXF_3DES_CBC,		24,	24 },
74	{ "des-cbc",		ENCXF_DES_CBC,		8,	8 },
75	{ "aes",		ENCXF_AES,		16,	32 },
76	{ "aesctr",		ENCXF_AESCTR,		16+4,	32+4 },
77	{ "blowfish",		ENCXF_BLOWFISH,		5,	56 },
78	{ "cast128",		ENCXF_CAST128,		5,	16 },
79	{ "null",		ENCXF_NULL,		0,	0 },
80	{ "skipjack",		ENCXF_SKIPJACK,		10,	10 },
81	{ NULL,			0,			0,	0 },
82};
83
84const struct ipsec_xf compxfs[] = {
85	{ "unknown",		COMPXF_UNKNOWN,		0,	0 },
86	{ "deflate",		COMPXF_DEFLATE,		0,	0 },
87	{ "lzs",		COMPXF_LZS,		0,	0 },
88	{ NULL,			0,			0,	0 },
89};
90
91const struct ipsec_xf groupxfs[] = {
92	{ "unknown",		GROUPXF_UNKNOWN,	0,	0 },
93	{ "modp768",		GROUPXF_768,		768,	0 },
94	{ "grp1",		GROUPXF_768,		768,	0 },
95	{ "modp1024",		GROUPXF_1024,		1024,	0 },
96	{ "grp2",		GROUPXF_1024,		1024,	0 },
97	{ "modp1536",		GROUPXF_1536,		1536,	0 },
98	{ "grp5",		GROUPXF_1536,		1536,	0 },
99	{ "modp2048",		GROUPXF_2048,		2048,	0 },
100	{ "grp14",		GROUPXF_2048,		2048,	0 },
101	{ "modp3072",		GROUPXF_3072,		3072,	0 },
102	{ "grp15",		GROUPXF_3072,		3072,	0 },
103	{ "modp4096",		GROUPXF_4096,		4096,	0 },
104	{ "grp16",		GROUPXF_4096,		4096,	0 },
105	{ "modp6144",		GROUPXF_6144,		6144,	0 },
106	{ "grp18",		GROUPXF_6144,		6144,	0 },
107	{ "modp8192",		GROUPXF_8192,		8192,	0 },
108	{ "grp18",		GROUPXF_8192,		8192,	0 },
109	{ NULL,			0,			0,	0 },
110};
111
112int			 yyerror(const char *, ...);
113int			 yyparse(void);
114int			 kw_cmp(const void *, const void *);
115int			 lookup(char *);
116int			 lgetc(FILE *);
117int			 lungetc(int);
118int			 findeol(void);
119int			 yylex(void);
120
121TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
122struct sym {
123	TAILQ_ENTRY(sym)	 entries;
124	int		 used;
125	int		 persist;
126	char		*nam;
127	char		*val;
128};
129
130int			 symset(const char *, const char *, int);
131int			 cmdline_symset(char *);
132char			*symget(const char *);
133int			 atoul(char *, u_long *);
134int			 atospi(char *, u_int32_t *);
135u_int8_t		 x2i(unsigned char *);
136struct ipsec_key	*parsekey(unsigned char *, size_t);
137struct ipsec_key	*parsekeyfile(char *);
138struct ipsec_addr_wrap	*host(const char *);
139struct ipsec_addr_wrap	*host_v6(const char *, int);
140struct ipsec_addr_wrap	*host_v4(const char *, int);
141struct ipsec_addr_wrap	*host_dns(const char *, int, int);
142struct ipsec_addr_wrap	*host_if(const char *, int);
143void			 ifa_load(void);
144int			 ifa_exists(const char *);
145struct ipsec_addr_wrap	*ifa_lookup(const char *ifa_name);
146struct ipsec_addr_wrap	*ifa_grouplookup(const char *);
147void			 set_ipmask(struct ipsec_addr_wrap *, u_int8_t);
148const struct ipsec_xf	*parse_xf(const char *, const struct ipsec_xf *);
149struct ipsec_life	*parse_life(int);
150struct ipsec_transforms *copytransforms(const struct ipsec_transforms *);
151struct ipsec_life	*copylife(const struct ipsec_life *);
152struct ipsec_auth	*copyipsecauth(const struct ipsec_auth *);
153struct ike_auth		*copyikeauth(const struct ike_auth *);
154struct ipsec_key	*copykey(struct ipsec_key *);
155struct ipsec_addr_wrap	*copyhost(const struct ipsec_addr_wrap *);
156struct ipsec_rule	*copyrule(struct ipsec_rule *);
157int			 validate_sa(u_int32_t, u_int8_t,
158			     struct ipsec_transforms *, struct ipsec_key *,
159			     struct ipsec_key *, u_int8_t);
160struct ipsec_rule	*create_sa(u_int8_t, u_int8_t, struct ipsec_hosts *,
161			     u_int32_t, struct ipsec_transforms *,
162			     struct ipsec_key *, struct ipsec_key *);
163struct ipsec_rule	*reverse_sa(struct ipsec_rule *, u_int32_t,
164			     struct ipsec_key *, struct ipsec_key *);
165struct ipsec_rule	*create_sagroup(struct ipsec_addr_wrap *, u_int8_t,
166			     u_int32_t, struct ipsec_addr_wrap *, u_int8_t,
167			     u_int32_t);
168struct ipsec_rule	*create_flow(u_int8_t, u_int8_t, struct ipsec_hosts *,
169			     struct ipsec_hosts *, u_int8_t, char *, char *,
170			     u_int8_t);
171int			 expand_rule(struct ipsec_rule *, u_int8_t, u_int32_t,
172			     struct ipsec_key *, struct ipsec_key *, int);
173struct ipsec_rule	*reverse_rule(struct ipsec_rule *);
174struct ipsec_rule	*create_ike(u_int8_t, struct ipsec_hosts *,
175			     struct ipsec_hosts *, struct ike_mode *,
176			     struct ike_mode *, u_int8_t, u_int8_t, u_int8_t,
177			     char *, char *, struct ike_auth *);
178int			 add_sagroup(struct ipsec_rule *);
179
180struct ipsec_transforms *ipsec_transforms;
181
182typedef struct {
183	union {
184		u_int32_t	 number;
185		u_int8_t	 ikemode;
186		u_int8_t	 dir;
187		u_int8_t	 satype;	/* encapsulating prococol */
188		u_int8_t	 proto;		/* encapsulated protocol */
189		u_int8_t	 tmode;
190		char		*string;
191		u_int16_t	 port;
192		struct ipsec_hosts hosts;
193		struct ipsec_hosts peers;
194		struct ipsec_addr_wrap *singlehost;
195		struct ipsec_addr_wrap *host;
196		struct {
197			char *srcid;
198			char *dstid;
199		} ids;
200		char		*id;
201		u_int8_t	 type;
202		struct ike_auth	 ikeauth;
203		struct {
204			u_int32_t	spiout;
205			u_int32_t	spiin;
206		} spis;
207		struct {
208			struct ipsec_key *keyout;
209			struct ipsec_key *keyin;
210		} authkeys;
211		struct {
212			struct ipsec_key *keyout;
213			struct ipsec_key *keyin;
214		} enckeys;
215		struct {
216			struct ipsec_key *keyout;
217			struct ipsec_key *keyin;
218		} keys;
219		struct ipsec_transforms *transforms;
220		struct ipsec_life	*life;
221		struct ike_mode		*mainmode;
222		struct ike_mode		*quickmode;
223	} v;
224	int lineno;
225} YYSTYPE;
226
227%}
228
229%token	FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
230%token	AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
231%token	ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC LIFE
232%token	TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP PORT
233%token	<v.string>		STRING
234%type	<v.string>		string
235%type	<v.dir>			dir
236%type	<v.satype>		satype
237%type	<v.proto>		proto
238%type	<v.tmode>		tmode
239%type	<v.number>		number
240%type	<v.hosts>		hosts
241%type	<v.port>		port
242%type	<v.peers>		peers
243%type	<v.singlehost>		singlehost
244%type	<v.host>		host host_list
245%type	<v.ids>			ids
246%type	<v.id>			id
247%type	<v.spis>		spispec
248%type	<v.authkeys>		authkeyspec
249%type	<v.enckeys>		enckeyspec
250%type	<v.keys>		keyspec
251%type	<v.transforms>		transforms
252%type	<v.ikemode>		ikemode
253%type	<v.ikeauth>		ikeauth
254%type	<v.type>		type
255%type	<v.life>		life
256%type	<v.mainmode>		mainmode
257%type	<v.quickmode>		quickmode
258%%
259
260grammar		: /* empty */
261		| grammar '\n'
262		| grammar ikerule '\n'
263		| grammar flowrule '\n'
264		| grammar sarule '\n'
265		| grammar tcpmd5rule '\n'
266		| grammar varset '\n'
267		| grammar error '\n'		{ errors++; }
268		;
269
270number		: STRING			{
271			unsigned long	ulval;
272
273			if (atoul($1, &ulval) == -1) {
274				yyerror("%s is not a number", $1);
275				free($1);
276				YYERROR;
277			}
278			if (ulval > UINT_MAX) {
279				yyerror("0x%lx out of range", ulval);
280				free($1);
281				YYERROR;
282			}
283			$$ = (u_int32_t)ulval;
284			free($1);
285		}
286		;
287
288comma		: ','
289		| /* empty */
290		;
291
292tcpmd5rule	: TCPMD5 hosts spispec authkeyspec	{
293			struct ipsec_rule	*r;
294
295			r = create_sa(IPSEC_TCPMD5, IPSEC_TRANSPORT, &$2,
296			    $3.spiout, NULL, $4.keyout, NULL);
297			if (r == NULL)
298				YYERROR;
299			r->nr = ipsec->rule_nr++;
300
301			if (expand_rule(r, 0, $3.spiin, $4.keyin, NULL, 0))
302				errx(1, "tcpmd5rule: expand_rule");
303		}
304		;
305
306sarule		: satype tmode hosts spispec transforms authkeyspec
307		    enckeyspec {
308			struct ipsec_rule	*r;
309
310			r = create_sa($1, $2, &$3, $4.spiout, $5, $6.keyout,
311			    $7.keyout);
312			if (r == NULL)
313				YYERROR;
314			r->nr = ipsec->rule_nr++;
315
316			if (expand_rule(r, 0, $4.spiin, $6.keyin, $7.keyin, 1))
317				errx(1, "sarule: expand_rule");
318		}
319		;
320
321flowrule	: FLOW satype dir proto hosts peers ids type {
322			struct ipsec_rule	*r;
323
324			r = create_flow($3, $4, &$5, &$6, $2, $7.srcid,
325			    $7.dstid, $8);
326			if (r == NULL)
327				YYERROR;
328
329			if (expand_rule(r, $3, 0, NULL, NULL, 0))
330				errx(1, "flowrule: expand_rule");
331		}
332		;
333
334ikerule		: IKE ikemode satype tmode proto hosts peers mainmode quickmode
335		      ids ikeauth {
336			struct ipsec_rule	*r;
337
338			r = create_ike($5, &$6, &$7, $8, $9, $3, $4, $2,
339			    $10.srcid, $10.dstid, &$11);
340			if (r == NULL)
341				YYERROR;
342			r->nr = ipsec->rule_nr++;
343
344			if (expand_rule(r, 0, 0, NULL, NULL, 0))
345				errx(1, "ikerule: expand_rule");
346		}
347		;
348
349satype		: /* empty */			{ $$ = IPSEC_ESP; }
350		| ESP				{ $$ = IPSEC_ESP; }
351		| AH				{ $$ = IPSEC_AH; }
352		| IPCOMP			{ $$ = IPSEC_IPCOMP; }
353		| IPIP				{ $$ = IPSEC_IPIP; }
354		;
355
356proto		: /* empty */			{ $$ = 0; }
357		| PROTO STRING			{
358			struct protoent *p;
359			const char *errstr;
360			int proto;
361
362			if ((p = getprotobyname($2)) != NULL) {
363				$$ = p->p_proto;
364			} else {
365				errstr = NULL;
366				proto = strtonum($2, 0, 255, &errstr);
367				if (errstr)
368					errx(1, "unknown protocol: %s", $2);
369				$$ = proto;
370			}
371
372		}
373		;
374
375tmode		: /* empty */			{ $$ = IPSEC_TUNNEL; }
376		| TUNNEL			{ $$ = IPSEC_TUNNEL; }
377		| TRANSPORT			{ $$ = IPSEC_TRANSPORT; }
378		;
379
380dir		: /* empty */			{ $$ = IPSEC_INOUT; }
381		| IN				{ $$ = IPSEC_IN; }
382		| OUT				{ $$ = IPSEC_OUT; }
383		;
384
385hosts		: FROM host port TO host port		{
386			$$.src = $2;
387			$$.sport = $3;
388			$$.dst = $5;
389			$$.dport = $6;
390		}
391		| TO host port FROM host port		{
392			$$.src = $5;
393			$$.sport = $6;
394			$$.dst = $2;
395			$$.dport = $3;
396		}
397		;
398
399port		: /* empty */				{ $$ = 0; }
400		| PORT STRING				{
401			struct servent *s;
402			const char *errstr;
403			int port;
404
405			if ((s = getservbyname($2, "tcp")) != NULL ||
406			    (s = getservbyname($2, "udp")) != NULL) {
407				$$ = s->s_port;
408			} else {
409				errstr = NULL;
410				port = strtonum($2, 0, USHRT_MAX, &errstr);
411				if (errstr) {
412					yyerror("unknown port: %s", $2);
413					YYERROR;
414				}
415				$$ = htons(port);
416			}
417		}
418		;
419
420peers		: /* empty */				{
421			$$.dst = NULL;
422			$$.src = NULL;
423		}
424		| PEER singlehost LOCAL singlehost	{
425			$$.dst = $2;
426			$$.src = $4;
427		}
428		| LOCAL singlehost PEER singlehost	{
429			$$.dst = $4;
430			$$.src = $2;
431		}
432		| PEER singlehost			{
433			$$.dst = $2;
434			$$.src = NULL;
435		}
436		| LOCAL singlehost			{
437			$$.dst = NULL;
438			$$.src = $2;
439		}
440		;
441
442singlehost	: /* empty */			{ $$ = NULL; }
443		| STRING			{
444			if (($$ = host($1)) == NULL) {
445				free($1);
446				yyerror("could not parse host specification");
447				YYERROR;
448			}
449			free($1);
450		}
451		;
452
453host_list	: host				{ $$ = $1; }
454		| host_list comma host		{
455			if ($3 == NULL)
456				$$ = $1;
457			else if ($1 == NULL)
458				$$ = $3;
459			else {
460				$1->tail->next = $3;
461				$1->tail = $3->tail;
462				$$ = $1;
463			}
464		}
465		;
466
467host		: STRING			{
468			if (($$ = host($1)) == NULL) {
469				free($1);
470				yyerror("could not parse host specification");
471				YYERROR;
472			}
473			free($1);
474		}
475		| STRING '/' number		{
476			char	*buf;
477
478			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
479				err(1, "host: asprintf");
480			free($1);
481			if (($$ = host(buf)) == NULL)	{
482				free(buf);
483				yyerror("could not parse host specification");
484				YYERROR;
485			}
486			free(buf);
487		}
488		| ANY				{
489			struct ipsec_addr_wrap	*ipa;
490
491			ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
492			if (ipa == NULL)
493				err(1, "host: calloc");
494
495			ipa->af = AF_INET;
496			ipa->netaddress = 1;
497			if ((ipa->name = strdup("0.0.0.0/0")) == NULL)
498				err(1, "host: strdup");
499
500			ipa->next = calloc(1, sizeof(struct ipsec_addr_wrap));
501			if (ipa->next == NULL)
502				err(1, "host: calloc");
503
504			ipa->next->af = AF_INET6;
505			ipa->next->netaddress = 1;
506			if ((ipa->next->name = strdup("::/0")) == NULL)
507				err(1, "host: strdup");
508
509			$$ = ipa;
510		}
511		| '{' host_list '}'		{ $$ = $2; }
512		;
513
514ids		: /* empty */			{
515			$$.srcid = NULL;
516			$$.dstid = NULL;
517		}
518		| SRCID id DSTID id		{
519			$$.srcid = $2;
520			$$.dstid = $4;
521		}
522		| SRCID id			{
523			$$.srcid = $2;
524			$$.dstid = NULL;
525		}
526		| DSTID id			{
527			$$.srcid = NULL;
528			$$.dstid = $2;
529		}
530		;
531
532type		: /* empty */			{
533			$$ = TYPE_REQUIRE;
534		}
535		| TYPE USE			{
536			$$ = TYPE_USE;
537		}
538		| TYPE ACQUIRE			{
539			$$ = TYPE_ACQUIRE;
540		}
541		| TYPE REQUIRE			{
542			$$ = TYPE_REQUIRE;
543		}
544		| TYPE DENY			{
545			$$ = TYPE_DENY;
546		}
547		| TYPE BYPASS			{
548			$$ = TYPE_BYPASS;
549		}
550		| TYPE DONTACQ			{
551			$$ = TYPE_DONTACQ;
552		}
553		;
554
555id		: STRING			{ $$ = $1; }
556		;
557
558spispec		: SPI STRING			{
559			u_int32_t	 spi;
560			char		*p = strchr($2, ':');
561
562			if (p != NULL) {
563				*p++ = 0;
564
565				if (atospi(p, &spi) == -1) {
566					yyerror("%s is not a valid spi", p);
567					free($2);
568					YYERROR;
569				}
570				$$.spiin = spi;
571			} else
572				$$.spiin = 0;
573
574			if (atospi($2, &spi) == -1) {
575				yyerror("%s is not a valid spi", $2);
576				free($2);
577				YYERROR;
578			}
579			$$.spiout = spi;
580
581
582			free($2);
583		}
584		;
585
586transforms	:					{
587			if ((ipsec_transforms = calloc(1,
588			    sizeof(struct ipsec_transforms))) == NULL)
589				err(1, "transforms: calloc");
590		}
591		    transforms_l
592			{ $$ = ipsec_transforms; }
593		| /* empty */				{
594			if (($$ = calloc(1,
595			    sizeof(struct ipsec_transforms))) == NULL)
596				err(1, "transforms: calloc");
597		}
598		;
599
600transforms_l	: transforms_l transform
601		| transform
602		;
603
604transform	: AUTHXF STRING			{
605			if (ipsec_transforms->authxf)
606				yyerror("auth already set");
607			else {
608				ipsec_transforms->authxf = parse_xf($2,
609				    authxfs);
610				if (!ipsec_transforms->authxf)
611					yyerror("%s not a valid transform", $2);
612			}
613		}
614		| ENCXF STRING			{
615			if (ipsec_transforms->encxf)
616				yyerror("enc already set");
617			else {
618				ipsec_transforms->encxf = parse_xf($2, encxfs);
619				if (!ipsec_transforms->encxf)
620					yyerror("%s not a valid transform", $2);
621			}
622		}
623		| COMPXF STRING			{
624			if (ipsec_transforms->compxf)
625				yyerror("comp already set");
626			else {
627				ipsec_transforms->compxf = parse_xf($2,
628				    compxfs);
629				if (!ipsec_transforms->compxf)
630					yyerror("%s not a valid transform", $2);
631			}
632		}
633		| GROUP STRING			{
634			if (ipsec_transforms->groupxf)
635				yyerror("group already set");
636			else {
637				ipsec_transforms->groupxf = parse_xf($2,
638				    groupxfs);
639				if (!ipsec_transforms->groupxf)
640					yyerror("%s not a valid transform", $2);
641			}
642		}
643		;
644
645mainmode	: /* empty */			{
646			struct ike_mode		*mm;
647
648			/* We create just an empty mode */
649			if ((mm = calloc(1, sizeof(struct ike_mode))) == NULL)
650				err(1, "mainmode: calloc");
651			$$ = mm;
652		}
653		| MAIN transforms life		{
654			struct ike_mode	*mm;
655
656			if ((mm = calloc(1, sizeof(struct ike_mode))) == NULL)
657				err(1, "mainmode: calloc");
658			mm->xfs = $2;
659			mm->life = $3;
660			$$ = mm;
661		}
662		;
663
664quickmode	: /* empty */			{
665			struct ike_mode		*qm;
666
667			/* We create just an empty mode */
668			if ((qm = calloc(1, sizeof(struct ike_mode))) == NULL)
669				err(1, "quickmode: calloc");
670			$$ = qm;
671		}
672		| QUICK transforms life		{
673			struct ike_mode	*qm;
674
675			if ((qm = calloc(1, sizeof(struct ike_mode))) == NULL)
676				err(1, "quickmode: calloc");
677			qm->xfs = $2;
678			qm->life = $3;
679			$$ = qm;
680		}
681		;
682
683life		: /* empty */			{
684			struct ipsec_life *life;
685
686			/* We create just an empty transform */
687			if ((life = calloc(1, sizeof(struct ipsec_life)))
688			    == NULL)
689				err(1, "life: calloc");
690			life->lifetime = -1;
691			life->lifevolume = -1;
692			$$ = life;
693		}
694		| LIFE number			{
695			struct ipsec_life *life;
696
697			life = parse_life($2);
698			if (life == NULL)
699				yyerror("%s not a valid lifetime", $2);
700			$$ = life;
701		}
702		;
703
704authkeyspec	: /* empty */			{
705			$$.keyout = NULL;
706			$$.keyin = NULL;
707		}
708		| AUTHKEY keyspec		{
709			$$.keyout = $2.keyout;
710			$$.keyin = $2.keyin;
711		}
712		;
713
714enckeyspec	: /* empty */			{
715			$$.keyout = NULL;
716			$$.keyin = NULL;
717		}
718		| ENCKEY keyspec		{
719			$$.keyout = $2.keyout;
720			$$.keyin = $2.keyin;
721		}
722		;
723
724keyspec		: STRING			{
725			unsigned char	*hex;
726			unsigned char	*p = strchr($1, ':');
727
728			if (p != NULL ) {
729				*p++ = 0;
730
731				if (!strncmp(p, "0x", 2))
732					p += 2;
733				$$.keyin = parsekey(p, strlen(p));
734			} else
735				$$.keyin = NULL;
736
737			hex = $1;
738			if (!strncmp(hex, "0x", 2))
739				hex += 2;
740			$$.keyout = parsekey(hex, strlen(hex));
741
742			free($1);
743		}
744		| FILENAME STRING		{
745			unsigned char	*p = strchr($2, ':');
746
747			if (p != NULL) {
748				*p++ = 0;
749				$$.keyin = parsekeyfile(p);
750			}
751			$$.keyout = parsekeyfile($2);
752			free($2);
753		}
754		;
755
756ikemode		: /* empty */			{ $$ = IKE_ACTIVE; }
757		| PASSIVE			{ $$ = IKE_PASSIVE; }
758		| DYNAMIC			{ $$ = IKE_DYNAMIC; }
759		| ACTIVE			{ $$ = IKE_ACTIVE; }
760		;
761
762ikeauth		: /* empty */			{
763			$$.type = IKE_AUTH_RSA;
764			$$.string = NULL;
765		}
766		| RSA				{
767			$$.type = IKE_AUTH_RSA;
768			$$.string = NULL;
769		}
770		| PSK STRING			{
771			$$.type = IKE_AUTH_PSK;
772			if (($$.string = strdup($2)) == NULL)
773				err(1, "ikeauth: strdup");
774		}
775		;
776
777string		: string STRING
778		{
779			if (asprintf(&$$, "%s %s", $1, $2) == -1)
780				err(1, "string: asprintf");
781			free($1);
782			free($2);
783		}
784		| STRING
785		;
786
787varset		: STRING '=' string
788		{
789			if (ipsec->opts & IPSECCTL_OPT_VERBOSE)
790				printf("%s = \"%s\"\n", $1, $3);
791			if (symset($1, $3, 0) == -1)
792				err(1, "cannot store variable");
793			free($1);
794			free($3);
795		}
796		;
797
798%%
799
800struct keywords {
801	const char	*k_name;
802	int		 k_val;
803};
804
805int
806yyerror(const char *fmt, ...)
807{
808	va_list		 ap;
809	extern const char *infile;
810
811	errors = 1;
812	va_start(ap, fmt);
813	fprintf(stderr, "%s: %d: ", infile, yyval.lineno);
814	vfprintf(stderr, fmt, ap);
815	fprintf(stderr, "\n");
816	va_end(ap);
817	return (0);
818}
819
820int
821kw_cmp(const void *k, const void *e)
822{
823	return (strcmp(k, ((const struct keywords *)e)->k_name));
824}
825
826int
827lookup(char *s)
828{
829	/* this has to be sorted always */
830	static const struct keywords keywords[] = {
831		{ "acquire",		ACQUIRE },
832		{ "active",		ACTIVE },
833		{ "ah",			AH },
834		{ "any",		ANY },
835		{ "auth",		AUTHXF },
836		{ "authkey",		AUTHKEY },
837		{ "bypass",		BYPASS },
838		{ "comp",		COMPXF },
839		{ "deny",		DENY },
840		{ "dontacq",		DONTACQ },
841		{ "dstid",		DSTID },
842		{ "dynamic",		DYNAMIC },
843		{ "enc",		ENCXF },
844		{ "enckey",		ENCKEY },
845		{ "esp",		ESP },
846		{ "file",		FILENAME },
847		{ "flow",		FLOW },
848		{ "from",		FROM },
849		{ "group",		GROUP },
850		{ "ike",		IKE },
851		{ "in",			IN },
852		{ "ipcomp",		IPCOMP },
853		{ "ipip",		IPIP },
854		{ "life",		LIFE },
855		{ "local",		LOCAL },
856		{ "main",		MAIN },
857		{ "out",		OUT },
858		{ "passive",		PASSIVE },
859		{ "peer",		PEER },
860		{ "port",		PORT },
861		{ "proto",		PROTO },
862		{ "psk",		PSK },
863		{ "quick",		QUICK },
864		{ "require",		REQUIRE },
865		{ "rsa",		RSA },
866		{ "spi",		SPI },
867		{ "srcid",		SRCID },
868		{ "tcpmd5",		TCPMD5 },
869		{ "to",			TO },
870		{ "transport",		TRANSPORT },
871		{ "tunnel",		TUNNEL },
872		{ "type",		TYPE },
873		{ "use",		USE }
874	};
875	const struct keywords	*p;
876
877	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
878	    sizeof(keywords[0]), kw_cmp);
879
880	if (p) {
881		if (debug > 1)
882			fprintf(stderr, "%s: %d\n", s, p->k_val);
883		return (p->k_val);
884	} else {
885		if (debug > 1)
886			fprintf(stderr, "string: %s\n", s);
887		return (STRING);
888	}
889}
890
891#define MAXPUSHBACK	128
892
893char	*parsebuf;
894int	 parseindex;
895char	 pushback_buffer[MAXPUSHBACK];
896int	 pushback_index = 0;
897
898int
899lgetc(FILE *f)
900{
901	int	c, next;
902
903	if (parsebuf) {
904		/* Read character from the parsebuffer instead of input. */
905		if (parseindex >= 0) {
906			c = parsebuf[parseindex++];
907			if (c != '\0')
908				return (c);
909			parsebuf = NULL;
910		} else
911			parseindex++;
912	}
913
914	if (pushback_index)
915		return (pushback_buffer[--pushback_index]);
916
917	while ((c = getc(f)) == '\\') {
918		next = getc(f);
919		if (next != '\n') {
920			c = next;
921			break;
922		}
923		yylval.lineno = lineno;
924		lineno++;
925	}
926	if (c == '\t' || c == ' ') {
927		/* Compress blanks to a single space. */
928		do {
929			c = getc(f);
930		} while (c == '\t' || c == ' ');
931		ungetc(c, f);
932		c = ' ';
933	}
934
935	return (c);
936}
937
938int
939lungetc(int c)
940{
941	if (c == EOF)
942		return (EOF);
943	if (parsebuf) {
944		parseindex--;
945		if (parseindex >= 0)
946			return (c);
947	}
948	if (pushback_index < MAXPUSHBACK-1)
949		return (pushback_buffer[pushback_index++] = c);
950	else
951		return (EOF);
952}
953
954int
955findeol(void)
956{
957	int	c;
958
959	parsebuf = NULL;
960	pushback_index = 0;
961
962	/* skip to either EOF or the first real EOL */
963	while (1) {
964		c = lgetc(fin);
965		if (c == '\n') {
966			lineno++;
967			break;
968		}
969		if (c == EOF)
970			break;
971	}
972	return (ERROR);
973}
974
975int
976yylex(void)
977{
978	char	 buf[8096];
979	char	*p, *val;
980	int	 endc, c;
981	int	 token;
982
983top:
984	p = buf;
985	while ((c = lgetc(fin)) == ' ')
986		; /* nothing */
987
988	yylval.lineno = lineno;
989	if (c == '#')
990		while ((c = lgetc(fin)) != '\n' && c != EOF)
991			; /* nothing */
992	if (c == '$' && parsebuf == NULL) {
993		while (1) {
994			if ((c = lgetc(fin)) == EOF)
995				return (0);
996
997			if (p + 1 >= buf + sizeof(buf) - 1) {
998				yyerror("string too long");
999				return (findeol());
1000			}
1001			if (isalnum(c) || c == '_') {
1002				*p++ = (char)c;
1003				continue;
1004			}
1005			*p = '\0';
1006			lungetc(c);
1007			break;
1008		}
1009		val = symget(buf);
1010		if (val == NULL) {
1011			yyerror("macro \"%s\" not defined", buf);
1012			return (findeol());
1013		}
1014		parsebuf = val;
1015		parseindex = 0;
1016		goto top;
1017	}
1018
1019	switch (c) {
1020	case '\'':
1021	case '"':
1022		endc = c;
1023		while (1) {
1024			if ((c = lgetc(fin)) == EOF)
1025				return (0);
1026			if (c == endc) {
1027				*p = '\0';
1028				break;
1029			}
1030			if (c == '\n') {
1031				lineno++;
1032				continue;
1033			}
1034			if (p + 1 >= buf + sizeof(buf) - 1) {
1035				yyerror("string too long");
1036				return (findeol());
1037			}
1038			*p++ = (char)c;
1039		}
1040		yylval.v.string = strdup(buf);
1041		if (yylval.v.string == NULL)
1042			err(1, "yylex: strdup");
1043		return (STRING);
1044	}
1045
1046#define allowed_in_string(x) \
1047	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
1048	x != '{' && x != '}' && x != '<' && x != '>' && \
1049	x != '!' && x != '=' && x != '/' && x != '#' && \
1050	x != ','))
1051
1052	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
1053		do {
1054			*p++ = c;
1055			if ((unsigned)(p-buf) >= sizeof(buf)) {
1056				yyerror("string too long");
1057				return (findeol());
1058			}
1059		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
1060		lungetc(c);
1061		*p = '\0';
1062		if ((token = lookup(buf)) == STRING)
1063			if ((yylval.v.string = strdup(buf)) == NULL)
1064				err(1, "yylex: strdup");
1065		return (token);
1066	}
1067	if (c == '\n') {
1068		yylval.lineno = lineno;
1069		lineno++;
1070	}
1071	if (c == EOF)
1072		return (0);
1073	return (c);
1074}
1075
1076int
1077parse_rules(FILE *input, struct ipsecctl *ipsecx)
1078{
1079	struct sym	*sym;
1080
1081	ipsec = ipsecx;
1082	fin = input;
1083	lineno = 1;
1084	errors = 0;
1085
1086	yyparse();
1087
1088	/* Free macros and check which have not been used. */
1089	while ((sym = TAILQ_FIRST(&symhead))) {
1090		if ((ipsec->opts & IPSECCTL_OPT_VERBOSE2) && !sym->used)
1091			fprintf(stderr, "warning: macro '%s' not "
1092			    "used\n", sym->nam);
1093		TAILQ_REMOVE(&symhead, sym, entries);
1094		free(sym->nam);
1095		free(sym->val);
1096		free(sym);
1097	}
1098
1099	return (errors ? -1 : 0);
1100}
1101
1102int
1103symset(const char *nam, const char *val, int persist)
1104{
1105	struct sym	*sym;
1106
1107	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
1108	    sym = TAILQ_NEXT(sym, entries))
1109		;	/* nothing */
1110
1111	if (sym != NULL) {
1112		if (sym->persist == 1)
1113			return (0);
1114		else {
1115			TAILQ_REMOVE(&symhead, sym, entries);
1116			free(sym->nam);
1117			free(sym->val);
1118			free(sym);
1119		}
1120	}
1121	if ((sym = calloc(1, sizeof(*sym))) == NULL)
1122		return (-1);
1123
1124	sym->nam = strdup(nam);
1125	if (sym->nam == NULL) {
1126		free(sym);
1127		return (-1);
1128	}
1129	sym->val = strdup(val);
1130	if (sym->val == NULL) {
1131		free(sym->nam);
1132		free(sym);
1133		return (-1);
1134	}
1135	sym->used = 0;
1136	sym->persist = persist;
1137	TAILQ_INSERT_TAIL(&symhead, sym, entries);
1138	return (0);
1139}
1140
1141int
1142cmdline_symset(char *s)
1143{
1144	char	*sym, *val;
1145	int	ret;
1146	size_t	len;
1147
1148	if ((val = strrchr(s, '=')) == NULL)
1149		return (-1);
1150
1151	len = strlen(s) - strlen(val) + 1;
1152	if ((sym = malloc(len)) == NULL)
1153		err(1, "cmdline_symset: malloc");
1154
1155	strlcpy(sym, s, len);
1156
1157	ret = symset(sym, val + 1, 1);
1158	free(sym);
1159
1160	return (ret);
1161}
1162
1163char *
1164symget(const char *nam)
1165{
1166	struct sym	*sym;
1167
1168	TAILQ_FOREACH(sym, &symhead, entries)
1169		if (strcmp(nam, sym->nam) == 0) {
1170			sym->used = 1;
1171			return (sym->val);
1172		}
1173	return (NULL);
1174}
1175
1176int
1177atoul(char *s, u_long *ulvalp)
1178{
1179	u_long	 ulval;
1180	char	*ep;
1181
1182	errno = 0;
1183	ulval = strtoul(s, &ep, 0);
1184	if (s[0] == '\0' || *ep != '\0')
1185		return (-1);
1186	if (errno == ERANGE && ulval == ULONG_MAX)
1187		return (-1);
1188	*ulvalp = ulval;
1189	return (0);
1190}
1191
1192int
1193atospi(char *s, u_int32_t *spivalp)
1194{
1195	unsigned long	ulval;
1196
1197	if (atoul(s, &ulval) == -1)
1198		return (-1);
1199	if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) {
1200		yyerror("illegal SPI value");
1201		return (-1);
1202	}
1203	*spivalp = ulval;
1204	return (0);
1205}
1206
1207u_int8_t
1208x2i(unsigned char *s)
1209{
1210	char	ss[3];
1211
1212	ss[0] = s[0];
1213	ss[1] = s[1];
1214	ss[2] = 0;
1215
1216	if (!isxdigit(s[0]) || !isxdigit(s[1])) {
1217		yyerror("keys need to be specified in hex digits");
1218		return (-1);
1219	}
1220	return ((u_int8_t)strtoul(ss, NULL, 16));
1221}
1222
1223struct ipsec_key *
1224parsekey(unsigned char *hexkey, size_t len)
1225{
1226	struct ipsec_key *key;
1227	int		  i;
1228
1229	key = calloc(1, sizeof(struct ipsec_key));
1230	if (key == NULL)
1231		err(1, "parsekey: calloc");
1232
1233	key->len = len / 2;
1234	key->data = calloc(key->len, sizeof(u_int8_t));
1235	if (key->data == NULL)
1236		err(1, "parsekey: calloc");
1237
1238	for (i = 0; i < (int)key->len; i++)
1239		key->data[i] = x2i(hexkey + 2 * i);
1240
1241	return (key);
1242}
1243
1244struct ipsec_key *
1245parsekeyfile(char *filename)
1246{
1247	struct stat	 sb;
1248	int		 fd;
1249	unsigned char	*hex;
1250
1251	if ((fd = open(filename, O_RDONLY)) < 0)
1252		err(1, "parsekeyfile: open");
1253	if (fstat(fd, &sb) < 0)
1254		err(1, "parsekeyfile: stat %s", filename);
1255	if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0))
1256		errx(1, "parsekeyfile: key too %s", sb.st_size ? "large" :
1257		    "small");
1258	if ((hex = calloc(sb.st_size, sizeof(unsigned char))) == NULL)
1259		err(1, "parsekeyfile: calloc");
1260	if (read(fd, hex, sb.st_size) < sb.st_size)
1261		err(1, "parsekeyfile: read");
1262	close(fd);
1263	return (parsekey(hex, sb.st_size));
1264}
1265
1266struct ipsec_addr_wrap *
1267host(const char *s)
1268{
1269	struct ipsec_addr_wrap	*ipa = NULL;
1270	int			 mask, v4mask, cont = 1;
1271	char			*p, *q, *ps;
1272
1273	if ((p = strrchr(s, '/')) != NULL) {
1274		errno = 0;
1275		mask = strtol(p + 1, &q, 0);
1276		if (errno == ERANGE || !q || *q || mask > 128 || q == (p + 1))
1277			errx(1, "host: invalid netmask '%s'", p);
1278		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
1279			err(1, "host: calloc");
1280		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
1281		v4mask = mask;
1282	} else {
1283		if ((ps = strdup(s)) == NULL)
1284			err(1, "host: strdup");
1285		v4mask = 32;
1286		mask = -1;
1287	}
1288
1289	/* Does interface with this name exist? */
1290	if (cont && (ipa = host_if(ps, mask)) != NULL)
1291		cont = 0;
1292
1293	/* IPv4 address? */
1294	if (cont && (ipa = host_v4(s, v4mask)) != NULL)
1295		cont = 0;
1296
1297	/* IPv6 address? */
1298	if (cont && (ipa = host_v6(ps, mask == -1 ? 128 : mask)) != NULL)
1299		cont = 0;
1300
1301	/* dns lookup */
1302	if (cont && (ipa = host_dns(s, v4mask, 0)) != NULL)
1303		cont = 0;
1304	free(ps);
1305
1306	if (ipa == NULL || cont == 1) {
1307		fprintf(stderr, "no IP address found for %s\n", s);
1308		return (NULL);
1309	}
1310	return (ipa);
1311}
1312
1313struct ipsec_addr_wrap *
1314host_v6(const char *s, int prefixlen)
1315{
1316	struct ipsec_addr_wrap	*ipa = NULL;
1317	struct addrinfo		 hints, *res0, *res;
1318	char			 hbuf[NI_MAXHOST];
1319
1320	bzero(&hints, sizeof(struct addrinfo));
1321	hints.ai_family = PF_UNSPEC;
1322	hints.ai_socktype = SOCK_STREAM;
1323	hints.ai_flags = AI_NUMERICHOST;
1324	if (getaddrinfo(s, NULL, &hints, &res0))
1325		return (NULL);
1326
1327	for (res = res0; res; res = res->ai_next) {
1328		if (res->ai_family != AF_INET6)
1329			continue;
1330		break; /* found one */
1331	}
1332	ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1333	if (ipa == NULL)
1334		err(1, "host_addr: calloc");
1335	ipa->af = res->ai_family;
1336	memcpy(&ipa->address.v6,
1337	    &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr,
1338	    sizeof(struct in6_addr));
1339	if (prefixlen > 128)
1340		prefixlen = 128;
1341	ipa->next = NULL;
1342	ipa->tail = ipa;
1343
1344	set_ipmask(ipa, prefixlen);
1345	if (getnameinfo(res->ai_addr, res->ai_addrlen,
1346	    hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) {
1347		errx(1, "could not get a numeric hostname");
1348	}
1349
1350	if (prefixlen != 128) {
1351		ipa->netaddress = 1;
1352		asprintf(&ipa->name, "%s/%d", hbuf, prefixlen);
1353	} else
1354		ipa->name = strdup(hbuf);
1355	if (ipa->name == NULL)
1356		err(1, "host_dns: strdup");
1357
1358	freeaddrinfo(res0);
1359
1360	return (ipa);
1361}
1362
1363struct ipsec_addr_wrap *
1364host_v4(const char *s, int mask)
1365{
1366	struct ipsec_addr_wrap	*ipa = NULL;
1367	struct in_addr		 ina;
1368	int			 bits = 32;
1369
1370	bzero(&ina, sizeof(struct in_addr));
1371	if (strrchr(s, '/') != NULL) {
1372		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
1373			return (NULL);
1374	} else {
1375		if (inet_pton(AF_INET, s, &ina) != 1)
1376			return (NULL);
1377	}
1378
1379	ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1380	if (ipa == NULL)
1381		err(1, "host_v4: calloc");
1382
1383	ipa->address.v4 = ina;
1384	ipa->name = strdup(s);
1385	if (ipa->name == NULL)
1386		err(1, "host_v4: strdup");
1387	ipa->af = AF_INET;
1388	ipa->next = NULL;
1389	ipa->tail = ipa;
1390
1391	set_ipmask(ipa, bits);
1392	if (bits != (ipa->af == AF_INET ? 32 : 128))
1393		ipa->netaddress = 1;
1394
1395	return (ipa);
1396}
1397
1398struct ipsec_addr_wrap *
1399host_dns(const char *s, int v4mask, int v6mask)
1400{
1401	struct ipsec_addr_wrap	*ipa = NULL;
1402	struct addrinfo		 hints, *res0, *res;
1403	int			 error;
1404	int			 bits = 32;
1405
1406	bzero(&hints, sizeof(struct addrinfo));
1407	hints.ai_family = PF_UNSPEC;
1408	hints.ai_socktype = SOCK_STREAM;
1409	error = getaddrinfo(s, NULL, &hints, &res0);
1410	if (error)
1411		return (NULL);
1412
1413	for (res = res0; res; res = res->ai_next) {
1414		if (res->ai_family != AF_INET)
1415			continue;
1416		ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1417		if (ipa == NULL)
1418			err(1, "host_dns: calloc");
1419		memcpy(&ipa->address.v4,
1420		    &((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr,
1421		    sizeof(struct in_addr));
1422		ipa->name = strdup(inet_ntoa(ipa->address.v4));
1423		if (ipa->name == NULL)
1424			err(1, "host_dns: strdup");
1425		ipa->af = AF_INET;
1426		ipa->next = NULL;
1427		ipa->tail = ipa;
1428
1429		set_ipmask(ipa, bits);
1430		if (bits != (ipa->af == AF_INET ? 32 : 128))
1431			ipa->netaddress = 1;
1432		break;
1433	}
1434	freeaddrinfo(res0);
1435
1436	return (ipa);
1437}
1438
1439struct ipsec_addr_wrap *
1440host_if(const char *s, int mask)
1441{
1442	struct ipsec_addr_wrap *ipa = NULL;
1443
1444	if (ifa_exists(s))
1445		ipa = ifa_lookup(s);
1446
1447	return (ipa);
1448}
1449
1450/* interface lookup routintes */
1451
1452struct ipsec_addr_wrap	*iftab;
1453
1454void
1455ifa_load(void)
1456{
1457	struct ifaddrs		*ifap, *ifa;
1458	struct ipsec_addr_wrap	*n = NULL, *h = NULL;
1459
1460	if (getifaddrs(&ifap) < 0)
1461		err(1, "ifa_load: getiffaddrs");
1462
1463	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1464		if (!(ifa->ifa_addr->sa_family == AF_INET ||
1465		    ifa->ifa_addr->sa_family == AF_INET6 ||
1466		    ifa->ifa_addr->sa_family == AF_LINK))
1467			continue;
1468		n = calloc(1, sizeof(struct ipsec_addr_wrap));
1469		if (n == NULL)
1470			err(1, "ifa_load: calloc");
1471		n->af = ifa->ifa_addr->sa_family;
1472		if ((n->name = strdup(ifa->ifa_name)) == NULL)
1473			err(1, "ifa_load: strdup");
1474		if (n->af == AF_INET) {
1475			n->af = AF_INET;
1476			memcpy(&n->address.v4, &((struct sockaddr_in *)
1477			    ifa->ifa_addr)->sin_addr.s_addr,
1478			    sizeof(struct in_addr));
1479			memcpy(&n->mask.v4, &((struct sockaddr_in *)
1480			    ifa->ifa_netmask)->sin_addr.s_addr,
1481			    sizeof(struct in_addr));
1482		} else if (n->af == AF_INET6) {
1483			n->af = AF_INET6;
1484			memcpy(&n->address.v6, &((struct sockaddr_in6 *)
1485			    ifa->ifa_addr)->sin6_addr.s6_addr,
1486			    sizeof(struct in6_addr));
1487			memcpy(&n->mask.v6, &((struct sockaddr_in6 *)
1488			    ifa->ifa_netmask)->sin6_addr.s6_addr,
1489			    sizeof(struct in6_addr));
1490		}
1491		if ((n->name = strdup(ifa->ifa_name)) == NULL)
1492			err(1, "ifa_load: strdup");
1493		n->next = NULL;
1494		n->tail = n;
1495		if (h == NULL)
1496			h = n;
1497		else {
1498			h->tail->next = n;
1499			h->tail = n;
1500		}
1501	}
1502
1503	iftab = h;
1504	freeifaddrs(ifap);
1505}
1506
1507int
1508ifa_exists(const char *ifa_name)
1509{
1510	struct ipsec_addr_wrap	*n;
1511	struct ifgroupreq	 ifgr;
1512	int			 s;
1513
1514	if (iftab == NULL)
1515		ifa_load();
1516
1517	/* check wether this is a group */
1518	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1519		err(1, "ifa_exists: socket");
1520	bzero(&ifgr, sizeof(ifgr));
1521	strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1522	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == 0) {
1523		close(s);
1524		return (1);
1525	}
1526	close(s);
1527
1528	for (n = iftab; n; n = n->next) {
1529		if (n->af == AF_LINK && !strncmp(n->name, ifa_name,
1530		    IFNAMSIZ))
1531			return (1);
1532	}
1533
1534	return (0);
1535}
1536
1537struct ipsec_addr_wrap *
1538ifa_grouplookup(const char *ifa_name)
1539{
1540	struct ifg_req		*ifg;
1541	struct ifgroupreq	 ifgr;
1542	int			 s;
1543	size_t			 len;
1544	struct ipsec_addr_wrap	*n, *h = NULL, *hn;
1545
1546	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
1547		err(1, "socket");
1548	bzero(&ifgr, sizeof(ifgr));
1549	strlcpy(ifgr.ifgr_name, ifa_name, sizeof(ifgr.ifgr_name));
1550	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
1551		close(s);
1552		return (NULL);
1553	}
1554
1555	len = ifgr.ifgr_len;
1556	if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
1557		err(1, "calloc");
1558	if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
1559		err(1, "ioctl");
1560
1561	for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
1562	    ifg++) {
1563		len -= sizeof(struct ifg_req);
1564		if ((n = ifa_lookup(ifg->ifgrq_member)) == NULL)
1565			continue;
1566		if (h == NULL)
1567			h = n;
1568		else {
1569			for (hn = h; hn->next != NULL; hn = hn->next)
1570				;	/* nothing */
1571			hn->next = n;
1572			n->tail = hn;
1573		}
1574	}
1575	free(ifgr.ifgr_groups);
1576	close(s);
1577
1578	return (h);
1579}
1580
1581struct ipsec_addr_wrap *
1582ifa_lookup(const char *ifa_name)
1583{
1584	struct ipsec_addr_wrap	*p = NULL, *h = NULL, *n = NULL;
1585
1586	if (iftab == NULL)
1587		ifa_load();
1588
1589	if ((n = ifa_grouplookup(ifa_name)) != NULL)
1590		return (n);
1591
1592	for (p = iftab; p; p = p->next) {
1593		if (p->af != AF_INET && p->af != AF_INET6)
1594			continue;
1595		if (strncmp(p->name, ifa_name, IFNAMSIZ))
1596			continue;
1597		n = calloc(1, sizeof(struct ipsec_addr_wrap));
1598		if (n == NULL)
1599			err(1, "ifa_lookup: calloc");
1600		memcpy(n, p, sizeof(struct ipsec_addr_wrap));
1601		if ((n->name = strdup(p->name)) == NULL)
1602			err(1, "ifa_lookup: strdup");
1603		switch(n->af) {
1604		case AF_INET:
1605			set_ipmask(n, 32);
1606			break;
1607		case AF_INET6:
1608			/* route/show.c and bgpd/util.c give KAME credit */
1609			if (IN6_IS_ADDR_LINKLOCAL(&n->address.v6) ||
1610			    IN6_IS_ADDR_MC_LINKLOCAL(&n->address.v6)) {
1611				u_int16_t tmp16;
1612				/* for now we can not handle link local,
1613				 * therefore bail for now
1614				 */
1615				free(n);
1616				continue;
1617
1618				memcpy(&tmp16, &n->address.v6.s6_addr[2],
1619				    sizeof(tmp16));
1620				/* use this when we support link-local
1621				 * n->??.scopeid = ntohs(tmp16);
1622				 */
1623				n->address.v6.s6_addr[2] = 0;
1624				n->address.v6.s6_addr[3] = 0;
1625			}
1626			set_ipmask(n, 128);
1627			break;
1628		}
1629
1630		n->next = NULL;
1631		n->tail = n;
1632		if (h == NULL)
1633			h = n;
1634		else {
1635			h->tail->next = n;
1636			h->tail = n;
1637		}
1638	}
1639
1640	return (h);
1641}
1642
1643void
1644set_ipmask(struct ipsec_addr_wrap *address, u_int8_t b)
1645{
1646	struct ipsec_addr	*ipa;
1647	int			 i, j = 0;
1648
1649	ipa = &address->mask;
1650	bzero(ipa, sizeof(struct ipsec_addr));
1651
1652	while (b >= 32) {
1653		ipa->addr32[j++] = 0xffffffff;
1654		b -= 32;
1655	}
1656	for (i = 31; i > 31 - b; --i)
1657		ipa->addr32[j] |= (1 << i);
1658	if (b)
1659		ipa->addr32[j] = htonl(ipa->addr32[j]);
1660}
1661
1662const struct ipsec_xf *
1663parse_xf(const char *name, const struct ipsec_xf xfs[])
1664{
1665	int		i;
1666
1667	for (i = 0; xfs[i].name != NULL; i++) {
1668		if (strncmp(name, xfs[i].name, strlen(name)))
1669			continue;
1670		return &xfs[i];
1671	}
1672	return (NULL);
1673}
1674
1675struct ipsec_life *
1676parse_life(int value)
1677{
1678	struct ipsec_life	*life;
1679
1680	life = calloc(1, sizeof(struct ipsec_life));
1681	if (life == NULL)
1682		err(1, "calloc");
1683
1684	life->lifetime = value;
1685
1686	return (life);
1687}
1688
1689struct ipsec_transforms *
1690copytransforms(const struct ipsec_transforms *xfs)
1691{
1692	struct ipsec_transforms *newxfs;
1693
1694	if (xfs == NULL)
1695		return (NULL);
1696
1697	newxfs = calloc(1, sizeof(struct ipsec_transforms));
1698	if (newxfs == NULL)
1699		err(1, "copytransforms: calloc");
1700
1701	memcpy(newxfs, xfs, sizeof(struct ipsec_transforms));
1702	return (newxfs);
1703}
1704
1705struct ipsec_life *
1706copylife(const struct ipsec_life *life)
1707{
1708	struct ipsec_life *newlife;
1709
1710	if (life == NULL)
1711		return (NULL);
1712
1713	newlife = calloc(1, sizeof(struct ipsec_life));
1714	if (newlife == NULL)
1715		err(1, "copylife: calloc");
1716
1717	memcpy(newlife, life, sizeof(struct ipsec_life));
1718	return (newlife);
1719}
1720
1721struct ipsec_auth *
1722copyipsecauth(const struct ipsec_auth *auth)
1723{
1724	struct ipsec_auth	*newauth;
1725
1726	if (auth == NULL)
1727		return (NULL);
1728
1729	if ((newauth = calloc(1, sizeof(struct ipsec_auth))) == NULL)
1730		err(1, "calloc");
1731	if (auth->srcid &&
1732	    asprintf(&newauth->srcid, "%s", auth->srcid) == -1)
1733		err(1, "asprintf");
1734	if (auth->dstid &&
1735	    asprintf(&newauth->dstid, "%s", auth->dstid) == -1)
1736		err(1, "asprintf");
1737
1738	newauth->idtype = auth->idtype;
1739	newauth->type = auth->type;
1740
1741	return (newauth);
1742}
1743
1744struct ike_auth *
1745copyikeauth(const struct ike_auth *auth)
1746{
1747	struct ike_auth	*newauth;
1748
1749	if (auth == NULL)
1750		return (NULL);
1751
1752	if ((newauth = calloc(1, sizeof(struct ike_auth))) == NULL)
1753		err(1, "calloc");
1754	if (auth->string &&
1755	    asprintf(&newauth->string, "%s", auth->string) == -1)
1756		err(1, "asprintf");
1757
1758	newauth->type = auth->type;
1759
1760	return (newauth);
1761}
1762
1763struct ipsec_key *
1764copykey(struct ipsec_key *key)
1765{
1766	struct ipsec_key	*newkey;
1767
1768	if (key == NULL)
1769		return (NULL);
1770
1771	if ((newkey = calloc(1, sizeof(struct ipsec_key))) == NULL)
1772		err(1, "calloc");
1773	if ((newkey->data = calloc(key->len, sizeof(u_int8_t))) == NULL)
1774		err(1, "calloc");
1775	memcpy(newkey->data, key->data, key->len);
1776	newkey->len = key->len;
1777
1778	return (newkey);
1779}
1780
1781struct ipsec_addr_wrap *
1782copyhost(const struct ipsec_addr_wrap *src)
1783{
1784	struct ipsec_addr_wrap *dst;
1785
1786	if (src == NULL)
1787		return (NULL);
1788
1789	dst = calloc(1, sizeof(struct ipsec_addr_wrap));
1790	if (dst == NULL)
1791		err(1, "copyhost: calloc");
1792
1793	memcpy(dst, src, sizeof(struct ipsec_addr_wrap));
1794
1795	if ((dst->name = strdup(src->name)) == NULL)
1796		err(1, "copyhost: strdup");
1797
1798	return dst;
1799}
1800
1801struct ipsec_rule *
1802copyrule(struct ipsec_rule *rule)
1803{
1804	struct ipsec_rule	*r;
1805
1806	if ((r = calloc(1, sizeof(struct ipsec_rule))) == NULL)
1807		err(1, "calloc");
1808
1809	r->src = copyhost(rule->src);
1810	r->dst = copyhost(rule->dst);
1811	r->local = copyhost(rule->local);
1812	r->peer = copyhost(rule->peer);
1813	r->auth = copyipsecauth(rule->auth);
1814	r->ikeauth = copyikeauth(rule->ikeauth);
1815	r->xfs = copytransforms(rule->xfs);
1816	r->mmxfs = copytransforms(rule->mmxfs);
1817	r->qmxfs = copytransforms(rule->qmxfs);
1818	r->mmlife = copylife(rule->mmlife);
1819	r->qmlife = copylife(rule->qmlife);
1820	r->authkey = copykey(rule->authkey);
1821	r->enckey = copykey(rule->enckey);
1822
1823	r->type = rule->type;
1824	r->satype = rule->satype;
1825	r->proto = rule->proto;
1826	r->tmode = rule->tmode;
1827	r->direction = rule->direction;
1828	r->flowtype = rule->flowtype;
1829	r->sport = rule->sport;
1830	r->dport = rule->dport;
1831	r->ikemode = rule->ikemode;
1832	r->spi = rule->spi;
1833	r->nr = rule->nr;
1834
1835	return (r);
1836}
1837
1838int
1839validate_sa(u_int32_t spi, u_int8_t satype, struct ipsec_transforms *xfs,
1840    struct ipsec_key *authkey, struct ipsec_key *enckey, u_int8_t tmode)
1841{
1842	/* Sanity checks */
1843	if (spi == 0) {
1844		yyerror("no SPI specified");
1845		return (0);
1846	}
1847	if (satype == IPSEC_AH) {
1848		if (!xfs) {
1849			yyerror("no transforms specified");
1850			return (0);
1851		}
1852		if (!xfs->authxf)
1853			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1854		if (xfs->encxf) {
1855			yyerror("ah does not provide encryption");
1856			return (0);
1857		}
1858		if (xfs->compxf) {
1859			yyerror("ah does not provide compression");
1860			return (0);
1861		}
1862	}
1863	if (satype == IPSEC_ESP) {
1864		if (!xfs) {
1865			yyerror("no transforms specified");
1866			return (0);
1867		}
1868		if (xfs->compxf) {
1869			yyerror("esp does not provide compression");
1870			return (0);
1871		}
1872		if (!xfs->authxf)
1873			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1874		if (!xfs->encxf)
1875			xfs->encxf = &encxfs[ENCXF_AESCTR];
1876	}
1877	if (satype == IPSEC_IPCOMP) {
1878		if (!xfs) {
1879			yyerror("no transform specified");
1880			return (0);
1881		}
1882		if (xfs->authxf || xfs->encxf) {
1883			yyerror("no encryption or authentication with ipcomp");
1884			return (0);
1885		}
1886		if (!xfs->compxf)
1887			xfs->compxf = &compxfs[COMPXF_DEFLATE];
1888	}
1889	if (satype == IPSEC_IPIP) {
1890		if (!xfs) {
1891			yyerror("no transform specified");
1892			return (0);
1893		}
1894		if (xfs->authxf || xfs->encxf || xfs->compxf) {
1895			yyerror("no encryption, authentication or compression"
1896			    " with ipip");
1897			return (0);
1898		}
1899	}
1900	if (satype == IPSEC_TCPMD5 && authkey == NULL && tmode !=
1901	    IPSEC_TRANSPORT) {
1902		yyerror("authentication key needed for tcpmd5");
1903		return (0);
1904	}
1905	if (xfs && xfs->authxf) {
1906		if (!authkey) {
1907			yyerror("no authentication key specified");
1908			return (0);
1909		}
1910		if (authkey->len != xfs->authxf->keymin) {
1911			yyerror("wrong authentication key length, needs to be "
1912			    "%d bits", xfs->authxf->keymin * 8);
1913			return (0);
1914		}
1915	}
1916	if (xfs && xfs->encxf) {
1917		if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) {
1918			yyerror("no encryption key specified");
1919			return (0);
1920		}
1921		if (enckey) {
1922			if (enckey->len < xfs->encxf->keymin) {
1923				yyerror("encryption key too short (%d bits), "
1924				    "minimum %d bits", enckey->len * 8,
1925				     xfs->encxf->keymin * 8);
1926				return (0);
1927			}
1928			if (xfs->encxf->keymax < enckey->len) {
1929				yyerror("encryption key too long (%d bits), "
1930				    "maximum %d bits", enckey->len * 8,
1931				     xfs->encxf->keymax * 8);
1932				return (0);
1933			}
1934		}
1935	}
1936
1937	return 1;
1938}
1939
1940int
1941add_sagroup(struct ipsec_rule *r)
1942{
1943	struct ipsec_rule	*rp, *last, *group;
1944	int			 found = 0;
1945
1946	TAILQ_FOREACH(rp, &ipsec->group_queue, group_entry) {
1947		if (strcmp(rp->dst->name, r->dst->name) == 0) {
1948			found = 1;
1949			break;
1950		}
1951	}
1952	if (found) {
1953		last = TAILQ_LAST(&rp->dst_group_queue, dst_group_queue);
1954		TAILQ_INSERT_TAIL(&rp->dst_group_queue, r, dst_group_entry);
1955
1956		group = create_sagroup(last->dst, last->satype, last->spi,
1957		    r->dst, r->satype, r->spi);
1958		if (group == NULL)
1959			return (1);
1960		group->nr = ipsec->rule_nr++;
1961		if (ipsecctl_add_rule(ipsec, group))
1962			return (1);
1963	} else {
1964		TAILQ_INSERT_TAIL(&ipsec->group_queue, r, group_entry);
1965		TAILQ_INIT(&r->dst_group_queue);
1966		TAILQ_INSERT_TAIL(&r->dst_group_queue, r, dst_group_entry);
1967	}
1968
1969	return (0);
1970}
1971
1972struct ipsec_rule *
1973create_sa(u_int8_t satype, u_int8_t tmode, struct ipsec_hosts *hosts,
1974    u_int32_t spi, struct ipsec_transforms *xfs, struct ipsec_key *authkey,
1975    struct ipsec_key *enckey)
1976{
1977	struct ipsec_rule *r;
1978
1979	if (validate_sa(spi, satype, xfs, authkey, enckey, tmode) == 0)
1980		return (NULL);
1981
1982	r = calloc(1, sizeof(struct ipsec_rule));
1983	if (r == NULL)
1984		err(1, "create_sa: calloc");
1985
1986	r->type |= RULE_SA;
1987	r->satype = satype;
1988	r->tmode = tmode;
1989	r->src = hosts->src;
1990	r->dst = hosts->dst;
1991	r->spi = spi;
1992	r->xfs = xfs;
1993	r->authkey = authkey;
1994	r->enckey = enckey;
1995
1996	return r;
1997}
1998
1999struct ipsec_rule *
2000reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
2001    struct ipsec_key *enckey)
2002{
2003	struct ipsec_rule *reverse;
2004
2005	if (validate_sa(spi, rule->satype, rule->xfs, authkey, enckey,
2006	    rule->tmode) == 0)
2007		return (NULL);
2008
2009	reverse = calloc(1, sizeof(struct ipsec_rule));
2010	if (reverse == NULL)
2011		err(1, "reverse_sa: calloc");
2012
2013	reverse->type |= RULE_SA;
2014	reverse->satype = rule->satype;
2015	reverse->tmode = rule->tmode;
2016	reverse->src = copyhost(rule->dst);
2017	reverse->dst = copyhost(rule->src);
2018	reverse->spi = spi;
2019	reverse->xfs = copytransforms(rule->xfs);
2020	reverse->authkey = authkey;
2021	reverse->enckey = enckey;
2022
2023	return (reverse);
2024}
2025
2026struct ipsec_rule *
2027create_sagroup(struct ipsec_addr_wrap *dst, u_int8_t proto, u_int32_t spi,
2028    struct ipsec_addr_wrap *dst2, u_int8_t proto2, u_int32_t spi2)
2029{
2030	struct ipsec_rule *r;
2031
2032	r = calloc(1, sizeof(struct ipsec_rule));
2033	if (r == NULL)
2034		err(1, "create_sagroup: calloc");
2035
2036	r->type |= RULE_GROUP;
2037
2038	r->dst = copyhost(dst);
2039	r->dst2 = copyhost(dst2);
2040	r->proto = proto;
2041	r->proto2 = proto2;
2042	r->spi = spi;
2043	r->spi2 = spi2;
2044	r->satype = proto;
2045
2046	return (r);
2047}
2048
2049struct ipsec_rule *
2050create_flow(u_int8_t dir, u_int8_t proto, struct ipsec_hosts *hosts,
2051    struct ipsec_hosts *peers,
2052    u_int8_t satype, char *srcid, char *dstid, u_int8_t type)
2053{
2054	struct ipsec_rule *r;
2055
2056	r = calloc(1, sizeof(struct ipsec_rule));
2057	if (r == NULL)
2058		err(1, "create_flow: calloc");
2059
2060	r->type |= RULE_FLOW;
2061
2062	if (dir == IPSEC_INOUT)
2063		r->direction = IPSEC_OUT;
2064	else
2065		r->direction = dir;
2066
2067	r->satype = satype;
2068	r->proto = proto;
2069	r->src = hosts->src;
2070	r->sport = hosts->sport;
2071	r->dst = hosts->dst;
2072	r->dport = hosts->dport;
2073	if ((hosts->sport != 0 || hosts->dport != 0) &&
2074            (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) {
2075		yyerror("no protocol supplied with source/destination ports");
2076		goto errout;
2077	}
2078
2079	if (type == TYPE_DENY || type == TYPE_BYPASS) {
2080		r->flowtype = type;
2081		return (r);
2082	}
2083
2084	r->flowtype = type;
2085	r->local = peers->src;
2086	if (peers->dst == NULL) {
2087		/* Set peer to remote host.  Must be a host address. */
2088		if (r->direction == IPSEC_IN) {
2089			if (r->src->netaddress) {
2090				yyerror("no peer specified");
2091				goto errout;
2092			}
2093			r->peer = copyhost(r->src);
2094		} else {
2095			if (r->dst->netaddress) {
2096				yyerror("no peer specified");
2097				goto errout;
2098			}
2099			r->peer = copyhost(r->dst);
2100		}
2101	} else
2102		r->peer = peers->dst;
2103
2104	r->auth = calloc(1, sizeof(struct ipsec_auth));
2105	if (r->auth == NULL)
2106		err(1, "create_flow: calloc");
2107	r->auth->srcid = srcid;
2108	r->auth->dstid = dstid;
2109	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
2110
2111	return r;
2112
2113errout:
2114	free(r);
2115	if (srcid)
2116		free(srcid);
2117	if (dstid)
2118		free(dstid);
2119	free(hosts->src);
2120	free(hosts->dst);
2121
2122	return NULL;
2123}
2124
2125int
2126expand_rule(struct ipsec_rule *rule, u_int8_t direction, u_int32_t spi,
2127    struct ipsec_key *authkey, struct ipsec_key *enckey, int group)
2128{
2129	struct ipsec_rule	*r, *revr;
2130	struct ipsec_addr_wrap	*src, *dst;
2131	int added = 0;
2132
2133	for (src = rule->src; src; src = src->next) {
2134		for (dst = rule->dst; dst; dst = dst->next) {
2135			if (src->af != dst->af)
2136				continue;
2137			r = copyrule(rule);
2138
2139			r->src = copyhost(src);
2140			r->dst = copyhost(dst);
2141
2142			r->nr = ipsec->rule_nr++;
2143			if (ipsecctl_add_rule(ipsec, r))
2144				return (1);
2145			if (group && add_sagroup(r))
2146				return (1);
2147
2148			if (direction == IPSEC_INOUT) {
2149				/* Create and add reverse flow rule. */
2150				revr = reverse_rule(r);
2151				if (revr == NULL)
2152					return (1);
2153
2154				revr->nr = ipsec->rule_nr++;
2155				if (ipsecctl_add_rule(ipsec, revr))
2156					return (1);
2157				if (group && add_sagroup(revr))
2158					return (1);
2159			} else if (spi != 0 || authkey || enckey) {
2160				/* Create and add reverse sa rule. */
2161				revr = reverse_sa(r, spi, authkey, enckey);
2162				if (revr == NULL)
2163					return (1);
2164
2165				revr->nr = ipsec->rule_nr++;
2166				if (ipsecctl_add_rule(ipsec, revr))
2167					return (1);
2168				if (group && add_sagroup(revr))
2169					return (1);
2170			}
2171			added++;
2172		}
2173	}
2174	if (!added)
2175		yyerror("rule expands to no valid combination");
2176	ipsecctl_free_rule(rule);
2177	return (0);
2178}
2179
2180struct ipsec_rule *
2181reverse_rule(struct ipsec_rule *rule)
2182{
2183	struct ipsec_rule *reverse;
2184
2185	reverse = calloc(1, sizeof(struct ipsec_rule));
2186	if (reverse == NULL)
2187		err(1, "reverse_rule: calloc");
2188
2189	reverse->type |= RULE_FLOW;
2190
2191	/* Reverse direction */
2192	if (rule->direction == (u_int8_t)IPSEC_OUT)
2193		reverse->direction = (u_int8_t)IPSEC_IN;
2194	else
2195		reverse->direction = (u_int8_t)IPSEC_OUT;
2196
2197	reverse->flowtype = rule->flowtype;
2198	reverse->src = copyhost(rule->dst);
2199	reverse->dst = copyhost(rule->src);
2200	reverse->sport = rule->dport;
2201	reverse->dport = rule->sport;
2202	if (rule->local)
2203		reverse->local = copyhost(rule->local);
2204	if (rule->peer)
2205		reverse->peer = copyhost(rule->peer);
2206	reverse->satype = rule->satype;
2207	reverse->proto = rule->proto;
2208
2209	if (rule->auth) {
2210		reverse->auth = calloc(1, sizeof(struct ipsec_auth));
2211		if (reverse->auth == NULL)
2212			err(1, "reverse_rule: calloc");
2213		if (rule->auth->dstid && (reverse->auth->dstid =
2214		    strdup(rule->auth->dstid)) == NULL)
2215			err(1, "reverse_rule: strdup");
2216		if (rule->auth->srcid && (reverse->auth->srcid =
2217		    strdup(rule->auth->srcid)) == NULL)
2218			err(1, "reverse_rule: strdup");
2219		reverse->auth->idtype = rule->auth->idtype;
2220		reverse->auth->type = rule->auth->type;
2221	}
2222
2223	return reverse;
2224}
2225
2226struct ipsec_rule *
2227create_ike(u_int8_t proto, struct ipsec_hosts *hosts, struct ipsec_hosts *peers,
2228    struct ike_mode *mainmode, struct ike_mode *quickmode,
2229    u_int8_t satype, u_int8_t tmode, u_int8_t mode, char *srcid, char *dstid,
2230    struct ike_auth *authtype)
2231{
2232	struct ipsec_rule *r;
2233
2234	r = calloc(1, sizeof(struct ipsec_rule));
2235	if (r == NULL)
2236		err(1, "create_ike: calloc");
2237
2238	r->type = RULE_IKE;
2239
2240	r->proto = proto;
2241	r->src = hosts->src;
2242	r->sport = hosts->sport;
2243	r->dst = hosts->dst;
2244	r->dport = hosts->dport;
2245	if ((hosts->sport != 0 || hosts->dport != 0) &&
2246            (proto != IPPROTO_TCP && proto != IPPROTO_UDP)) {
2247		yyerror("no protocol supplied with source/destination ports");
2248		free(r);
2249		free(hosts->src);
2250		free(hosts->dst);
2251		if (mainmode) {
2252			free(mainmode->xfs);
2253			free(mainmode->life);
2254		}
2255		if (quickmode) {
2256			free(quickmode->xfs);
2257			free(quickmode->life);
2258		}
2259		if (srcid)
2260			free(srcid);
2261		if (dstid)
2262			free(dstid);
2263		return NULL;
2264	}
2265
2266	if (peers->dst == NULL) {
2267		/* Set peer to remote host.  Must be a host address. */
2268		if (r->direction == IPSEC_IN) {
2269			if (r->src->netaddress)
2270				r->peer = NULL;
2271			else
2272				r->peer = copyhost(r->src);
2273		} else {
2274			if (r->dst->netaddress)
2275				r->peer = NULL;
2276			else
2277				r->peer = copyhost(r->dst);
2278		}
2279	} else
2280		r->peer = peers->dst;
2281
2282	if (peers->src)
2283		r->local = peers->src;
2284
2285	r->satype = satype;
2286	r->tmode = tmode;
2287	r->ikemode = mode;
2288	if (mainmode) {
2289		r->mmxfs = mainmode->xfs;
2290		r->mmlife = mainmode->life;
2291	}
2292	if (quickmode) {
2293		r->qmxfs = quickmode->xfs;
2294		r->qmlife = quickmode->life;
2295	}
2296	r->auth = calloc(1, sizeof(struct ipsec_auth));
2297	if (r->auth == NULL)
2298		err(1, "create_ike: calloc");
2299	r->auth->srcid = srcid;
2300	r->auth->dstid = dstid;
2301	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
2302	r->ikeauth = calloc(1, sizeof(struct ike_auth));
2303	if (r->ikeauth == NULL)
2304		err(1, "create_ike: calloc");
2305	r->ikeauth->type = authtype->type;
2306	r->ikeauth->string = authtype->string;
2307
2308	return (r);
2309}
2310