parse.y revision 1.41
1/*	$OpenBSD: parse.y,v 1.41 2005/11/24 11:52:07 hshoexer 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 <stdarg.h>
41#include <stdio.h>
42#include <string.h>
43#include <syslog.h>
44#include <unistd.h>
45
46#include "ipsecctl.h"
47
48#define KEYSIZE_LIMIT	1024
49
50static struct ipsecctl	*ipsec = NULL;
51static FILE		*fin = NULL;
52static int		 lineno = 1;
53static int		 errors = 0;
54static int		 debug = 0;
55
56const struct ipsec_xf authxfs[] = {
57	{ "unknown",		AUTHXF_UNKNOWN,		0,	0 },
58	{ "none",		AUTHXF_NONE,		0,	0 },
59	{ "hmac-md5",		AUTHXF_HMAC_MD5,	16,	0 },
60	{ "hmac-ripemd160",	AUTHXF_HMAC_RIPEMD160,	20,	0 },
61	{ "hmac-sha1",		AUTHXF_HMAC_SHA1,	20,	0 },
62	{ "hmac-sha2-256",	AUTHXF_HMAC_SHA2_256,	32,	0 },
63	{ "hmac-sha2-384",	AUTHXF_HMAC_SHA2_384,	48,	0 },
64	{ "hmac-sha2-512",	AUTHXF_HMAC_SHA2_512,	64,	0 },
65	{ NULL,			0,			0,	0 },
66};
67
68const struct ipsec_xf encxfs[] = {
69	{ "unknown",		ENCXF_UNKNOWN,		0,	0 },
70	{ "none",		ENCXF_NONE,		0,	0 },
71	{ "3des-cbc",		ENCXF_3DES_CBC,		24,	24 },
72	{ "des-cbc",		ENCXF_DES_CBC,		8,	8 },
73	{ "aes",		ENCXF_AES,		16,	32 },
74	{ "aesctr",		ENCXF_AESCTR,		16+4,	32+4 },
75	{ "blowfish",		ENCXF_BLOWFISH,		5,	56 },
76	{ "cast128",		ENCXF_CAST128,		5,	16 },
77	{ "null",		ENCXF_NULL,		0,	0 },
78	{ "skipjack",		ENCXF_SKIPJACK,		10,	10 },
79	{ NULL,			0,			0,	0 },
80};
81
82const struct ipsec_xf compxfs[] = {
83	{ "unknown",		COMPXF_UNKNOWN,		0,	0 },
84	{ "deflate",		COMPXF_DEFLATE,		0,	0 },
85	{ "lzs",		COMPXF_LZS,		0,	0 },
86	{ NULL,			0,			0,	0 },
87};
88
89int			 yyerror(const char *, ...);
90int			 yyparse(void);
91int			 kw_cmp(const void *, const void *);
92int			 lookup(char *);
93int			 lgetc(FILE *);
94int			 lungetc(int);
95int			 findeol(void);
96int			 yylex(void);
97
98TAILQ_HEAD(symhead, sym)	 symhead = TAILQ_HEAD_INITIALIZER(symhead);
99struct sym {
100	TAILQ_ENTRY(sym)	 entries;
101	int		 used;
102	int		 persist;
103	char		*nam;
104	char		*val;
105};
106
107int			 symset(const char *, const char *, int);
108int			 cmdline_symset(char *);
109char			*symget(const char *);
110int			 atoul(char *, u_long *);
111int			 atospi(char *, u_int32_t *);
112u_int8_t		 x2i(unsigned char *);
113struct ipsec_key	*parsekey(unsigned char *, size_t);
114struct ipsec_key	*parsekeyfile(char *);
115struct ipsec_addr_wrap	*host(const char *);
116struct ipsec_addr_wrap	*host_v4(const char *, int);
117struct ipsec_addr_wrap	*host_if(const char *, int);
118void			 ifa_load(void);
119int			 ifa_exists(const char *);
120struct ipsec_addr_wrap	*ifa_lookup(const char *ifa_name);
121void			 set_ipmask(struct ipsec_addr_wrap *, u_int8_t);
122struct ipsec_addr_wrap	*copyhost(const struct ipsec_addr_wrap *);
123const struct ipsec_xf	*parse_xf(const char *, const struct ipsec_xf *);
124struct ipsec_transforms *transforms(const char *, const char *, const char *);
125struct ipsec_transforms *copytransforms(const struct ipsec_transforms *);
126int			 validate_sa(u_int32_t, u_int8_t,
127			     struct ipsec_transforms *, struct ipsec_key *,
128			     struct ipsec_key *, u_int8_t);
129struct ipsec_rule	*create_sa(u_int8_t, u_int8_t, struct ipsec_addr_wrap *,
130			     struct ipsec_addr_wrap *, u_int32_t,
131			     struct ipsec_transforms *, struct ipsec_key *,
132			     struct ipsec_key *);
133struct ipsec_rule	*reverse_sa(struct ipsec_rule *, u_int32_t,
134			     struct ipsec_key *, struct ipsec_key *);
135struct ipsec_rule	*create_flow(u_int8_t, struct ipsec_addr_wrap *, struct
136			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
137			     u_int8_t, char *, char *, u_int16_t);
138struct ipsec_rule	*reverse_rule(struct ipsec_rule *);
139struct ipsec_rule	*create_ike(struct ipsec_addr_wrap *, struct
140			     ipsec_addr_wrap *, struct ipsec_addr_wrap *,
141			     struct ipsec_transforms *, struct
142			     ipsec_transforms *, u_int8_t, u_int8_t, char *,
143			     char *);
144
145typedef struct {
146	union {
147		u_int32_t	 number;
148		u_int8_t	 ikemode;
149		u_int8_t	 dir;
150		u_int8_t	 protocol;
151		u_int8_t	 tmode;
152		char		*string;
153		struct {
154			struct ipsec_addr_wrap *src;
155			struct ipsec_addr_wrap *dst;
156		} hosts;
157		struct ipsec_addr_wrap *peer;
158		struct ipsec_addr_wrap *host;
159		struct {
160			char *srcid;
161			char *dstid;
162		} ids;
163		char		*id;
164		u_int16_t	 authtype;
165		struct {
166			u_int32_t	spiout;
167			u_int32_t	spiin;
168		} spis;
169		struct {
170			struct ipsec_key *keyout;
171			struct ipsec_key *keyin;
172		} authkeys;
173		struct {
174			struct ipsec_key *keyout;
175			struct ipsec_key *keyin;
176		} enckeys;
177		struct {
178			struct ipsec_key *keyout;
179			struct ipsec_key *keyin;
180		} keys;
181		struct ipsec_transforms *transforms;
182		struct ipsec_transforms *mmxfs;
183		struct ipsec_transforms *qmxfs;
184	} v;
185	int lineno;
186} YYSTYPE;
187
188%}
189
190%token	FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI
191%token	AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK PASSIVE
192%token	ACTIVE ANY IPCOMP COMPXF TUNNEL TRANSPORT
193%token	<v.string>		STRING
194%type	<v.dir>			dir
195%type	<v.protocol>		protocol
196%type	<v.tmode>		tmode
197%type	<v.number>		number
198%type	<v.hosts>		hosts
199%type	<v.peer>		peer
200%type	<v.host>		host
201%type	<v.ids>			ids
202%type	<v.id>			id
203%type	<v.authtype>		authtype
204%type	<v.spis>		spispec
205%type	<v.authkeys>		authkeyspec
206%type	<v.enckeys>		enckeyspec
207%type	<v.keys>		keyspec
208%type	<v.transforms>		transforms
209%type	<v.mmxfs>		mmxfs
210%type	<v.qmxfs>		qmxfs
211%type	<v.ikemode>		ikemode
212%%
213
214grammar		: /* empty */
215		| grammar '\n'
216		| grammar ikerule '\n'
217		| grammar flowrule '\n'
218		| grammar sarule '\n'
219		| grammar tcpmd5rule '\n'
220		| grammar error '\n'		{ errors++; }
221		;
222
223number		: STRING			{
224			unsigned long	ulval;
225
226			if (atoul($1, &ulval) == -1) {
227				yyerror("%s is not a number", $1);
228				free($1);
229				YYERROR;
230			}
231			if (ulval > UINT_MAX) {
232				yyerror("0x%lx out of range", ulval);
233				free($1);
234				YYERROR;
235			}
236			$$ = (u_int32_t)ulval;
237			free($1);
238		}
239		;
240
241tcpmd5rule	: TCPMD5 hosts spispec authkeyspec	{
242			struct ipsec_rule	*r;
243
244			r = create_sa(IPSEC_TCPMD5, IPSEC_TRANSPORT, $2.src,
245			    $2.dst, $3.spiout, NULL, $4.keyout, NULL);
246			if (r == NULL)
247				YYERROR;
248			r->nr = ipsec->rule_nr++;
249
250			if (ipsecctl_add_rule(ipsec, r))
251				errx(1, "tcpmd5rule: ipsecctl_add_rule");
252
253			/* Create and add reverse SA rule. */
254			if ($3.spiin != 0 || $4.keyin != NULL) {
255				r = reverse_sa(r, $3.spiin, $4.keyin, NULL);
256				if (r == NULL)
257					YYERROR;
258				r->nr = ipsec->rule_nr++;
259
260				if (ipsecctl_add_rule(ipsec, r))
261					errx(1, "tcpmd5rule: ipsecctl_add_rule");
262			}
263		}
264		;
265
266sarule		: protocol tmode hosts spispec transforms authkeyspec
267		    enckeyspec {
268			struct ipsec_rule	*r;
269
270			r = create_sa($1, $2, $3.src, $3.dst, $4.spiout, $5,
271			    $6.keyout, $7.keyout);
272			if (r == NULL)
273				YYERROR;
274			r->nr = ipsec->rule_nr++;
275
276			if (ipsecctl_add_rule(ipsec, r))
277				errx(1, "sarule: ipsecctl_add_rule");
278
279			/* Create and add reverse SA rule. */
280			if ($4.spiin != 0 || $6.keyin || $7.keyin) {
281				r = reverse_sa(r, $4.spiin, $6.keyin,
282				    $7.keyin);
283				if (r == NULL)
284					YYERROR;
285				r->nr = ipsec->rule_nr++;
286
287				if (ipsecctl_add_rule(ipsec, r))
288					errx(1, "sarule: ipsecctl_add_rule");
289			}
290		}
291		;
292
293flowrule	: FLOW protocol dir hosts peer ids authtype	{
294			struct ipsec_rule	*r;
295
296			r = create_flow($3, $4.src, $4.dst, $5, $2, $6.srcid,
297			    $6.dstid, $7);
298			if (r == NULL)
299				YYERROR;
300			r->nr = ipsec->rule_nr++;
301
302			if (ipsecctl_add_rule(ipsec, r))
303				errx(1, "flowrule: ipsecctl_add_rule");
304
305			/* Create and add reverse flow rule. */
306			if ($3 == IPSEC_INOUT) {
307				r = reverse_rule(r);
308				r->nr = ipsec->rule_nr++;
309
310				if (ipsecctl_add_rule(ipsec, r))
311					errx(1, "flowrule: ipsecctl_add_rule");
312			}
313		}
314		;
315
316ikerule		: IKE ikemode protocol hosts peer mmxfs qmxfs ids {
317			struct ipsec_rule	*r;
318
319			r = create_ike($4.src, $4.dst, $5, $6, $7, $3, $2,
320			    $8.srcid, $8.dstid);
321			if (r == NULL)
322				YYERROR;
323			r->nr = ipsec->rule_nr++;
324
325			if (ipsecctl_add_rule(ipsec, r))
326				errx(1, "ikerule: ipsecctl_add_rule");
327		}
328		;
329
330protocol	: /* empty */			{ $$ = IPSEC_ESP; }
331		| ESP				{ $$ = IPSEC_ESP; }
332		| AH				{ $$ = IPSEC_AH; }
333		| IPCOMP			{ $$ = IPSEC_IPCOMP; }
334		;
335
336tmode		: /* empty */			{ $$ = IPSEC_TUNNEL; }
337		| TUNNEL			{ $$ = IPSEC_TUNNEL; }
338		| TRANSPORT			{ $$ = IPSEC_TRANSPORT; }
339		;
340
341dir		: /* empty */			{ $$ = IPSEC_INOUT; }
342		| IN				{ $$ = IPSEC_IN; }
343		| OUT				{ $$ = IPSEC_OUT; }
344		;
345
346hosts		: FROM host TO host		{
347			$$.src = $2;
348			$$.dst = $4;
349		}
350		| TO host FROM host		{
351			$$.src = $4;
352			$$.dst = $2;
353		}
354		;
355
356peer		: /* empty */			{ $$ = NULL; }
357		| PEER STRING			{
358			if (($$ = host($2)) == NULL) {
359				free($2);
360				yyerror("could not parse host specification");
361				YYERROR;
362			}
363			free($2);
364		}
365		;
366
367host		: STRING			{
368			if (($$ = host($1)) == NULL) {
369				free($1);
370				yyerror("could not parse host specification");
371				YYERROR;
372			}
373			free($1);
374		}
375		| STRING '/' number		{
376			char	*buf;
377
378			if (asprintf(&buf, "%s/%u", $1, $3) == -1)
379				err(1, "host: asprintf");
380			free($1);
381			if (($$ = host(buf)) == NULL)	{
382				free(buf);
383				yyerror("could not parse host specification");
384				YYERROR;
385			}
386			free(buf);
387		}
388		| ANY				{
389			struct ipsec_addr_wrap	*ipa;
390
391			ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
392			if (ipa == NULL)
393				err(1, "host: calloc");
394
395			ipa->af = AF_INET;
396			ipa->netaddress = 1;
397			if ((ipa->name = strdup("0.0.0.0/0")) == NULL)
398				err(1, "host: strdup");
399			$$ = ipa;
400		}
401		;
402
403ids		: /* empty */			{
404			$$.srcid = NULL;
405			$$.dstid = NULL;
406		}
407		| SRCID id DSTID id		{
408			$$.srcid = $2;
409			$$.dstid = $4;
410		}
411		| SRCID id			{
412			$$.srcid = $2;
413			$$.dstid = NULL;
414		}
415		| DSTID id			{
416			$$.srcid = NULL;
417			$$.dstid = $2;
418		}
419		;
420
421id		: STRING			{ $$ = $1; }
422		;
423
424authtype	: /* empty */			{ $$ = 0; }
425		| RSA				{ $$ = AUTH_RSA; }
426		| PSK				{ $$ = AUTH_PSK; }
427		;
428
429spispec		: SPI STRING			{
430			u_int32_t	 spi;
431			char		*p = strchr($2, ':');
432
433			if (p != NULL) {
434				*p++ = 0;
435
436				if (atospi(p, &spi) == -1) {
437					yyerror("%s is not a valid spi", p);
438					free($2);
439					YYERROR;
440				}
441				$$.spiin = spi;
442			}
443			if (atospi($2, &spi) == -1) {
444				yyerror("%s is not a valid spi", $2);
445				free($2);
446				YYERROR;
447			}
448			$$.spiout = spi;
449
450
451			free($2);
452		}
453		;
454
455transforms	: /* empty */			{
456			struct ipsec_transforms *xfs;
457
458			/* We create just an empty transform */
459			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
460			    == NULL)
461				err(1, "transforms: calloc");
462			$$ = xfs;
463		}
464		| AUTHXF STRING ENCXF STRING	{
465			if (($$ = transforms($2, $4, NULL)) == NULL) {
466				free($2);
467				free($4);
468				yyerror("could not parse transforms");
469				YYERROR;
470			}
471			free($2);
472			free($4);
473		}
474		| AUTHXF STRING			{
475			if (($$ = transforms($2, NULL, NULL)) == NULL) {
476				free($2);
477				yyerror("could not parse transforms");
478				YYERROR;
479			}
480			free($2);
481		}
482		| ENCXF STRING			{
483			if (($$ = transforms(NULL, $2, NULL)) == NULL) {
484				free($2);
485				yyerror("could not parse transforms");
486				YYERROR;
487			}
488			free($2);
489		}
490		| COMPXF STRING			{
491			if (($$ = transforms(NULL, NULL, $2)) == NULL) {
492				free($2);
493				yyerror("could not parse transforms");
494				YYERROR;
495			}
496			free($2);
497		}
498		;
499
500mmxfs		: /* empty */			{
501			struct ipsec_transforms *xfs;
502
503			/* We create just an empty transform */
504			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
505			    == NULL)
506				err(1, "mmxfs: calloc");
507			$$ = xfs;
508		}
509		| MAIN transforms		{ $$ = $2; }
510		;
511
512qmxfs		: /* empty */			{
513			struct ipsec_transforms *xfs;
514
515			/* We create just an empty transform */
516			if ((xfs = calloc(1, sizeof(struct ipsec_transforms)))
517			    == NULL)
518				err(1, "qmxfs: calloc");
519			$$ = xfs;
520		}
521		| QUICK transforms		{ $$ = $2; }
522		;
523
524authkeyspec	: /* empty */			{
525			$$.keyout = NULL;
526			$$.keyin = NULL;
527		}
528		| AUTHKEY keyspec		{
529			$$.keyout = $2.keyout;
530			$$.keyin = $2.keyin;
531		}
532		;
533
534enckeyspec	: /* empty */			{
535			$$.keyout = NULL;
536			$$.keyin = NULL;
537		}
538		| ENCKEY keyspec		{
539			$$.keyout = $2.keyout;
540			$$.keyin = $2.keyin;
541		}
542		;
543
544keyspec		: STRING			{
545			unsigned char	*hex;
546			unsigned char	*p = strchr($1, ':');
547
548			if (p != NULL ) {
549				*p++ = 0;
550
551				if (!strncmp(p, "0x", 2))
552					p += 2;
553				$$.keyin = parsekey(p, strlen(p));
554			}
555
556			hex = $1;
557			if (!strncmp(hex, "0x", 2))
558				hex += 2;
559			$$.keyout = parsekey(hex, strlen(hex));
560
561			free($1);
562		}
563		| FILENAME STRING		{
564			unsigned char	*p = strchr($2, ':');
565
566			if (p != NULL) {
567				*p++ = 0;
568				$$.keyin = parsekeyfile(p);
569			}
570			$$.keyout = parsekeyfile($2);
571			free($2);
572		}
573		;
574ikemode		: /* empty */			{ $$ = IKE_ACTIVE; }
575		| PASSIVE			{ $$ = IKE_PASSIVE; }
576		| ACTIVE			{ $$ = IKE_ACTIVE; }
577		;
578%%
579
580struct keywords {
581	const char	*k_name;
582	int		 k_val;
583};
584
585int
586yyerror(const char *fmt, ...)
587{
588	va_list		 ap;
589	extern char	*infile;
590
591	errors = 1;
592	va_start(ap, fmt);
593	fprintf(stderr, "%s: %d: ", infile, yyval.lineno);
594	vfprintf(stderr, fmt, ap);
595	fprintf(stderr, "\n");
596	va_end(ap);
597	return (0);
598}
599
600int
601kw_cmp(const void *k, const void *e)
602{
603	return (strcmp(k, ((const struct keywords *)e)->k_name));
604}
605
606int
607lookup(char *s)
608{
609	/* this has to be sorted always */
610	static const struct keywords keywords[] = {
611		{ "active",		ACTIVE },
612		{ "ah",			AH },
613		{ "any",		ANY },
614		{ "auth",		AUTHXF },
615		{ "authkey",		AUTHKEY },
616		{ "comp",		COMPXF },
617		{ "dstid",		DSTID },
618		{ "enc",		ENCXF },
619		{ "enckey",		ENCKEY },
620		{ "esp",		ESP },
621		{ "file",		FILENAME },
622		{ "flow",		FLOW },
623		{ "from",		FROM },
624		{ "ike",		IKE },
625		{ "in",			IN },
626		{ "ipcomp",		IPCOMP },
627		{ "main",		MAIN },
628		{ "out",		OUT },
629		{ "passive",		PASSIVE },
630		{ "peer",		PEER },
631		{ "psk",		PSK },
632		{ "quick",		QUICK },
633		{ "rsa",		RSA },
634		{ "spi",		SPI },
635		{ "srcid",		SRCID },
636		{ "tcpmd5",		TCPMD5 },
637		{ "to",			TO },
638		{ "transport",		TRANSPORT },
639		{ "tunnel",		TUNNEL },
640	};
641	const struct keywords	*p;
642
643	p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
644	    sizeof(keywords[0]), kw_cmp);
645
646	if (p) {
647		if (debug > 1)
648			fprintf(stderr, "%s: %d\n", s, p->k_val);
649		return (p->k_val);
650	} else {
651		if (debug > 1)
652			fprintf(stderr, "string: %s\n", s);
653		return (STRING);
654	}
655}
656
657#define MAXPUSHBACK	128
658
659char	*parsebuf;
660int	 parseindex;
661char	 pushback_buffer[MAXPUSHBACK];
662int	 pushback_index = 0;
663
664int
665lgetc(FILE *f)
666{
667	int	c, next;
668
669	if (parsebuf) {
670		/* Read character from the parsebuffer instead of input. */
671		if (parseindex >= 0) {
672			c = parsebuf[parseindex++];
673			if (c != '\0')
674				return (c);
675			parsebuf = NULL;
676		} else
677			parseindex++;
678	}
679
680	if (pushback_index)
681		return (pushback_buffer[--pushback_index]);
682
683	while ((c = getc(f)) == '\\') {
684		next = getc(f);
685		if (next != '\n') {
686			if (isspace(next))
687				yyerror("whitespace after \\");
688			ungetc(next, f);
689			break;
690		}
691		yylval.lineno = lineno;
692		lineno++;
693	}
694	if (c == '\t' || c == ' ') {
695		/* Compress blanks to a single space. */
696		do {
697			c = getc(f);
698		} while (c == '\t' || c == ' ');
699		ungetc(c, f);
700		c = ' ';
701	}
702
703	return (c);
704}
705
706int
707lungetc(int c)
708{
709	if (c == EOF)
710		return (EOF);
711	if (parsebuf) {
712		parseindex--;
713		if (parseindex >= 0)
714			return (c);
715	}
716	if (pushback_index < MAXPUSHBACK-1)
717		return (pushback_buffer[pushback_index++] = c);
718	else
719		return (EOF);
720}
721
722int
723findeol(void)
724{
725	int	c;
726
727	parsebuf = NULL;
728	pushback_index = 0;
729
730	/* skip to either EOF or the first real EOL */
731	while (1) {
732		c = lgetc(fin);
733		if (c == '\n') {
734			lineno++;
735			break;
736		}
737		if (c == EOF)
738			break;
739	}
740	return (ERROR);
741}
742
743int
744yylex(void)
745{
746	char	 buf[8096];
747	char	*p, *val;
748	int	 endc, c;
749	int	 token;
750
751top:
752	p = buf;
753	while ((c = lgetc(fin)) == ' ')
754		; /* nothing */
755
756	yylval.lineno = lineno;
757	if (c == '#')
758		while ((c = lgetc(fin)) != '\n' && c != EOF)
759			; /* nothing */
760	if (c == '$' && parsebuf == NULL) {
761		while (1) {
762			if ((c = lgetc(fin)) == EOF)
763				return (0);
764
765			if (p + 1 >= buf + sizeof(buf) - 1) {
766				yyerror("string too long");
767				return (findeol());
768			}
769			if (isalnum(c) || c == '_') {
770				*p++ = (char)c;
771				continue;
772			}
773			*p = '\0';
774			lungetc(c);
775			break;
776		}
777		val = symget(buf);
778		if (val == NULL) {
779			yyerror("macro \"%s\" not defined", buf);
780			return (findeol());
781		}
782		parsebuf = val;
783		parseindex = 0;
784		goto top;
785	}
786
787	switch (c) {
788	case '\'':
789	case '"':
790		endc = c;
791		while (1) {
792			if ((c = lgetc(fin)) == EOF)
793				return (0);
794			if (c == endc) {
795				*p = '\0';
796				break;
797			}
798			if (c == '\n') {
799				lineno++;
800				continue;
801			}
802			if (p + 1 >= buf + sizeof(buf) - 1) {
803				yyerror("string too long");
804				return (findeol());
805			}
806			*p++ = (char)c;
807		}
808		yylval.v.string = strdup(buf);
809		if (yylval.v.string == NULL)
810			err(1, "yylex: strdup");
811		return (STRING);
812	}
813
814#define allowed_in_string(x) \
815	(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
816	x != '{' && x != '}' && x != '<' && x != '>' && \
817	x != '!' && x != '=' && x != '/' && x != '#' && \
818	x != ','))
819
820	if (isalnum(c) || c == ':' || c == '_' || c == '*') {
821		do {
822			*p++ = c;
823			if ((unsigned)(p-buf) >= sizeof(buf)) {
824				yyerror("string too long");
825				return (findeol());
826			}
827		} while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
828		lungetc(c);
829		*p = '\0';
830		if ((token = lookup(buf)) == STRING)
831			if ((yylval.v.string = strdup(buf)) == NULL)
832				err(1, "yylex: strdup");
833		return (token);
834	}
835	if (c == '\n') {
836		yylval.lineno = lineno;
837		lineno++;
838	}
839	if (c == EOF)
840		return (0);
841	return (c);
842}
843
844int
845parse_rules(FILE *input, struct ipsecctl *ipsecx)
846{
847	struct sym	*sym;
848
849	ipsec = ipsecx;
850	fin = input;
851	lineno = 1;
852	errors = 0;
853
854	yyparse();
855
856	/* Free macros and check which have not been used. */
857	while ((sym = TAILQ_FIRST(&symhead))) {
858		TAILQ_REMOVE(&symhead, sym, entries);
859		free(sym->nam);
860		free(sym->val);
861		free(sym);
862	}
863
864	return (errors ? -1 : 0);
865}
866
867int
868symset(const char *nam, const char *val, int persist)
869{
870	struct sym	*sym;
871
872	for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
873	    sym = TAILQ_NEXT(sym, entries))
874		;	/* nothing */
875
876	if (sym != NULL) {
877		if (sym->persist == 1)
878			return (0);
879		else {
880			TAILQ_REMOVE(&symhead, sym, entries);
881			free(sym->nam);
882			free(sym->val);
883			free(sym);
884		}
885	}
886	if ((sym = calloc(1, sizeof(*sym))) == NULL)
887		return (-1);
888
889	sym->nam = strdup(nam);
890	if (sym->nam == NULL) {
891		free(sym);
892		return (-1);
893	}
894	sym->val = strdup(val);
895	if (sym->val == NULL) {
896		free(sym->nam);
897		free(sym);
898		return (-1);
899	}
900	sym->used = 0;
901	sym->persist = persist;
902	TAILQ_INSERT_TAIL(&symhead, sym, entries);
903	return (0);
904}
905
906int
907cmdline_symset(char *s)
908{
909	char	*sym, *val;
910	int	ret;
911	size_t	len;
912
913	if ((val = strrchr(s, '=')) == NULL)
914		return (-1);
915
916	len = strlen(s) - strlen(val) + 1;
917	if ((sym = malloc(len)) == NULL)
918		err(1, "cmdline_symset: malloc");
919
920	strlcpy(sym, s, len);
921
922	ret = symset(sym, val + 1, 1);
923	free(sym);
924
925	return (ret);
926}
927
928char *
929symget(const char *nam)
930{
931	struct sym	*sym;
932
933	TAILQ_FOREACH(sym, &symhead, entries)
934		if (strcmp(nam, sym->nam) == 0) {
935			sym->used = 1;
936			return (sym->val);
937		}
938	return (NULL);
939}
940
941int
942atoul(char *s, u_long *ulvalp)
943{
944	u_long	 ulval;
945	char	*ep;
946
947	errno = 0;
948	ulval = strtoul(s, &ep, 0);
949	if (s[0] == '\0' || *ep != '\0')
950		return (-1);
951	if (errno == ERANGE && ulval == ULONG_MAX)
952		return (-1);
953	*ulvalp = ulval;
954	return (0);
955}
956
957int
958atospi(char *s, u_int32_t *spivalp)
959{
960	unsigned long	ulval;
961
962	if (atoul(s, &ulval) == -1)
963		return (-1);
964	if (ulval >= SPI_RESERVED_MIN && ulval <= SPI_RESERVED_MAX) {
965		yyerror("illegal SPI value");
966		return (-1);
967	}
968	*spivalp = ulval;
969	return (0);
970}
971
972u_int8_t
973x2i(unsigned char *s)
974{
975	char	ss[3];
976
977	ss[0] = s[0];
978	ss[1] = s[1];
979	ss[2] = 0;
980
981	if (!isxdigit(s[0]) || !isxdigit(s[1])) {
982		yyerror("keys need to be specified in hex digits");
983		return (-1);
984	}
985	return ((u_int8_t)strtoul(ss, NULL, 16));
986}
987
988struct ipsec_key *
989parsekey(unsigned char *hexkey, size_t len)
990{
991	struct ipsec_key *key;
992	int		  i;
993
994	key = calloc(1, sizeof(struct ipsec_key));
995	if (key == NULL)
996		err(1, "parsekey: calloc");
997
998	key->len = len / 2;
999	key->data = calloc(key->len, sizeof(u_int8_t));
1000	if (key->data == NULL)
1001		err(1, "parsekey: calloc");
1002
1003	for (i = 0; i < (int)key->len; i++)
1004		key->data[i] = x2i(hexkey + 2 * i);
1005
1006	return (key);
1007}
1008
1009struct ipsec_key *
1010parsekeyfile(char *filename)
1011{
1012	struct stat	 sb;
1013	int		 fd;
1014	unsigned char	*hex;
1015
1016	if ((fd = open(filename, O_RDONLY)) < 0)
1017		err(1, "parsekeyfile: open");
1018	if (fstat(fd, &sb) < 0)
1019		err(1, "parsekeyfile: stat %s", filename);
1020	if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0))
1021		errx(1, "parsekeyfile: key too %s", sb.st_size ? "large" :
1022		    "small");
1023	if ((hex = calloc(sb.st_size, sizeof(unsigned char))) == NULL)
1024		err(1, "parsekeyfile: calloc");
1025	if (read(fd, hex, sb.st_size) < sb.st_size)
1026		err(1, "parsekeyfile: read");
1027	close(fd);
1028	return (parsekey(hex, sb.st_size));
1029}
1030
1031struct ipsec_addr_wrap *
1032host(const char *s)
1033{
1034	struct ipsec_addr_wrap	*ipa = NULL;
1035	int			 mask, v4mask, cont = 1;
1036	char			*p, *q, *ps;
1037
1038	if ((p = strrchr(s, '/')) != NULL) {
1039		mask = strtol(p + 1, &q, 0);
1040		if (!q || *q || mask > 32 || q == (p + 1))
1041			errx(1, "host: invalid netmask '%s'", p);
1042		if ((ps = malloc(strlen(s) - strlen(p) + 1)) == NULL)
1043			err(1, "host: calloc");
1044		strlcpy(ps, s, strlen(s) - strlen(p) + 1);
1045		v4mask = mask;
1046	} else {
1047		if ((ps = strdup(s)) == NULL)
1048			err(1, "host: strdup");
1049		v4mask = 32;
1050		mask = -1;
1051	}
1052
1053	/* Does interface with this name exist? */
1054	if (cont && (ipa = host_if(ps, mask)) != NULL)
1055		cont = 0;
1056
1057	/* IPv4 address? */
1058	if (cont && (ipa = host_v4(s, mask)) != NULL)
1059		cont = 0;
1060
1061#if notyet
1062	/* IPv6 address? */
1063	if (cont && (ipa = host_dns(ps, v4mask, 0)) != NULL)
1064		cont = 0;
1065#endif
1066	free(ps);
1067
1068	if (ipa == NULL || cont == 1) {
1069		fprintf(stderr, "no IP address found for %s\n", s);
1070		return (NULL);
1071	}
1072	return (ipa);
1073}
1074
1075struct ipsec_addr_wrap *
1076host_v4(const char *s, int mask)
1077{
1078	struct ipsec_addr_wrap	*ipa = NULL;
1079	struct in_addr		 ina;
1080	int			 bits = 32;
1081
1082	bzero(&ina, sizeof(struct in_addr));
1083	if (strrchr(s, '/') != NULL) {
1084		if ((bits = inet_net_pton(AF_INET, s, &ina, sizeof(ina))) == -1)
1085			return (NULL);
1086	} else {
1087		if (inet_pton(AF_INET, s, &ina) != 1)
1088			return (NULL);
1089	}
1090
1091	ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1092	if (ipa == NULL)
1093		err(1, "host_v4: calloc");
1094
1095	ipa->address.v4 = ina;
1096	ipa->name = strdup(s);
1097	if (ipa->name == NULL)
1098		err(1, "host_v4: strdup");
1099	ipa->af = AF_INET;
1100
1101	set_ipmask(ipa, bits);
1102	if (bits != (ipa->af == AF_INET ? 32 : 128))
1103		ipa->netaddress = 1;
1104
1105	return (ipa);
1106}
1107
1108struct ipsec_addr_wrap *
1109host_if(const char *s, int mask)
1110{
1111	struct ipsec_addr_wrap *ipa = NULL;
1112	char			*ps;
1113
1114	if ((ps = strdup(s)) == NULL)
1115		err(1, "host_if: strdup");
1116
1117	if (ifa_exists(ps))
1118		ipa = ifa_lookup(ps);
1119
1120	free(ps);
1121	return (ipa);
1122}
1123
1124/* interface lookup routintes */
1125
1126struct addr_node	*iftab;
1127
1128void
1129ifa_load(void)
1130{
1131	struct ifaddrs		*ifap, *ifa;
1132	struct addr_node	*n = NULL, *h = NULL;
1133
1134	if (getifaddrs(&ifap) < 0)
1135		err(1, "ifa_load: getiffaddrs");
1136
1137	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1138		if (!(ifa->ifa_addr->sa_family == AF_INET ||
1139		    ifa->ifa_addr->sa_family == AF_INET6 ||
1140		    ifa->ifa_addr->sa_family == AF_LINK))
1141			continue;
1142		n = calloc(1, sizeof(struct addr_node));
1143		if (n == NULL)
1144			err(1, "ifa_load: calloc");
1145		n->af = ifa->ifa_addr->sa_family;
1146		if ((n->addr.name = strdup(ifa->ifa_name)) == NULL)
1147			err(1, "ifa_load: strdup");
1148		if (n->af == AF_INET) {
1149			n->addr.af = AF_INET;
1150			memcpy(&n->addr.address.v4, &((struct sockaddr_in *)
1151			    ifa->ifa_addr)->sin_addr.s_addr,
1152			    sizeof(struct in_addr));
1153			memcpy(&n->addr.mask.v4, &((struct sockaddr_in *)
1154			    ifa->ifa_netmask)->sin_addr.s_addr,
1155			    sizeof(struct in_addr));
1156		} else if (n->af == AF_INET6) {
1157			n->addr.af = AF_INET6;
1158			memcpy(&n->addr.address.v6, &((struct sockaddr_in6 *)
1159			    ifa->ifa_addr)->sin6_addr.s6_addr,
1160			    sizeof(struct in6_addr));
1161			memcpy(&n->addr.mask.v6, &((struct sockaddr_in6 *)
1162			    ifa->ifa_netmask)->sin6_addr.s6_addr,
1163			    sizeof(struct in6_addr));
1164		}
1165		if ((n->addr.name = strdup(ifa->ifa_name)) == NULL)
1166			err(1, "ifa_load: strdup");
1167		n->next = NULL;
1168		n->tail = n;
1169		if (h == NULL)
1170			h = n;
1171		else {
1172			h->tail->next = n;
1173			h->tail = n;
1174		}
1175	}
1176
1177	iftab = h;
1178	freeifaddrs(ifap);
1179}
1180
1181int
1182ifa_exists(const char *ifa_name)
1183{
1184	struct addr_node	*n;
1185
1186	if (iftab == NULL)
1187		ifa_load();
1188
1189	for (n = iftab; n; n = n->next) {
1190		if (n->af == AF_LINK && !strncmp(n->addr.name, ifa_name,
1191		    IFNAMSIZ))
1192			return (1);
1193	}
1194
1195	return (0);
1196}
1197
1198struct ipsec_addr_wrap *
1199ifa_lookup(const char *ifa_name)
1200{
1201	struct addr_node	*p = NULL;
1202	struct ipsec_addr_wrap	*ipa = NULL;
1203
1204	if (iftab == NULL)
1205		ifa_load();
1206
1207	for (p = iftab; p; p = p->next) {
1208		if (p->af != AF_INET)
1209			continue;
1210		if (strncmp(p->addr.name, ifa_name, IFNAMSIZ))
1211			continue;
1212		ipa = calloc(1, sizeof(struct ipsec_addr_wrap));
1213		if (ipa == NULL)
1214			err(1, "ifa_lookup: calloc");
1215		memcpy(ipa, &p->addr, sizeof(struct ipsec_addr_wrap));
1216		break;
1217	}
1218
1219	return (ipa);
1220}
1221
1222void
1223set_ipmask(struct ipsec_addr_wrap *address, u_int8_t b)
1224{
1225	struct ipsec_addr	*ipa;
1226	int			 i, j = 0;
1227
1228	ipa = &address->mask;
1229	bzero(ipa, sizeof(struct ipsec_addr));
1230
1231	while (b >= 32) {
1232		ipa->addr32[j++] = 0xffffffff;
1233		b -= 32;
1234	}
1235	for (i = 31; i > 31 - b; --i)
1236		ipa->addr32[j] |= (1 << i);
1237	if (b)
1238		ipa->addr32[j] = htonl(ipa->addr32[j]);
1239}
1240
1241struct ipsec_addr_wrap *
1242copyhost(const struct ipsec_addr_wrap *src)
1243{
1244	struct ipsec_addr_wrap *dst;
1245
1246	dst = calloc(1, sizeof(struct ipsec_addr_wrap));
1247	if (dst == NULL)
1248		err(1, "copyhost: calloc");
1249
1250	memcpy(dst, src, sizeof(struct ipsec_addr_wrap));
1251
1252	if ((dst->name = strdup(src->name)) == NULL)
1253		err(1, "copyhost: strdup");
1254
1255	return dst;
1256}
1257
1258const struct ipsec_xf *
1259parse_xf(const char *name, const struct ipsec_xf xfs[])
1260{
1261	int		i;
1262
1263	for (i = 0; xfs[i].name != NULL; i++) {
1264		if (strncmp(name, xfs[i].name, strlen(name)))
1265			continue;
1266		return &xfs[i];
1267	}
1268	return (NULL);
1269}
1270
1271struct ipsec_transforms *
1272transforms(const char *authname, const char *encname, const char *compname)
1273{
1274	struct ipsec_transforms *xfs;
1275
1276	xfs = calloc(1, sizeof(struct ipsec_transforms));
1277	if (xfs == NULL)
1278		err(1, "transforms: calloc");
1279
1280	if (authname) {
1281		xfs->authxf = parse_xf(authname, authxfs);
1282		if (xfs->authxf == NULL)
1283			yyerror("%s not a valid transform", authname);
1284	}
1285	if (encname) {
1286		xfs->encxf = parse_xf(encname, encxfs);
1287		if (xfs->encxf == NULL)
1288			yyerror("%s not a valid transform", encname);
1289	}
1290	if (compname) {
1291		xfs->compxf = parse_xf(compname, compxfs);
1292		if (xfs->compxf == NULL)
1293			yyerror("%s not a valid transform", compname);
1294	}
1295
1296	return (xfs);
1297}
1298
1299struct ipsec_transforms *
1300copytransforms(const struct ipsec_transforms *xfs)
1301{
1302	struct ipsec_transforms *newxfs;
1303
1304	if (xfs == NULL)
1305		return (NULL);
1306
1307	newxfs = calloc(1, sizeof(struct ipsec_transforms));
1308	if (newxfs == NULL)
1309		err(1, "copytransforms: calloc");
1310
1311	memcpy(newxfs, xfs, sizeof(struct ipsec_transforms));
1312	return (newxfs);
1313}
1314
1315int
1316validate_sa(u_int32_t spi, u_int8_t protocol, struct ipsec_transforms *xfs,
1317    struct ipsec_key *authkey, struct ipsec_key *enckey, u_int8_t tmode)
1318{
1319	/* Sanity checks */
1320	if (spi == 0) {
1321		yyerror("no SPI specified");
1322		return (0);
1323	}
1324	if (protocol == IPSEC_AH) {
1325		if (!xfs) {
1326			yyerror("no transforms specified");
1327			return (0);
1328		}
1329		if (!xfs->authxf)
1330			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1331		if (xfs->encxf) {
1332			yyerror("ah does not provide encryption");
1333			return (0);
1334		}
1335	}
1336	if (protocol == IPSEC_ESP) {
1337		if (!xfs) {
1338			yyerror("no transforms specified");
1339			return (0);
1340		}
1341		if (!xfs->authxf)
1342			xfs->authxf = &authxfs[AUTHXF_HMAC_SHA2_256];
1343		if (!xfs->encxf)
1344			xfs->encxf = &encxfs[ENCXF_AESCTR];
1345	}
1346	if (protocol == IPSEC_IPCOMP) {
1347		if (!xfs) {
1348			yyerror("no transform specified");
1349			return (0);
1350		}
1351		if (!xfs->compxf)
1352			xfs->compxf = &compxfs[COMPXF_DEFLATE];
1353	}
1354	if (protocol == IPSEC_TCPMD5 && authkey == NULL && tmode !=
1355	    IPSEC_TRANSPORT) {
1356		yyerror("authentication key needed for tcpmd5");
1357		return (0);
1358	}
1359	if (xfs && xfs->authxf) {
1360		if (!authkey) {
1361			yyerror("no authentication key specified");
1362			return (0);
1363		}
1364		if (authkey->len != xfs->authxf->keymin) {
1365			yyerror("wrong authentication key length, needs to be "
1366			    "%d bits", xfs->authxf->keymin * 8);
1367			return (0);
1368		}
1369	}
1370	if (xfs && xfs->encxf) {
1371		if (!enckey && xfs->encxf != &encxfs[ENCXF_NULL]) {
1372			yyerror("no encryption key specified");
1373			return (0);
1374		}
1375		if (enckey) {
1376			if (enckey->len < xfs->encxf->keymin) {
1377				yyerror("encryption key too short, minimum %d bits",
1378				    xfs->encxf->keymin * 8);
1379				return (0);
1380			}
1381			if (xfs->encxf->keymax < enckey->len) {
1382				yyerror("encryption key too long, maximum %d bits",
1383				    xfs->encxf->keymax * 8);
1384				return (0);
1385			}
1386		}
1387	}
1388
1389	return 1;
1390}
1391
1392struct ipsec_rule *
1393create_sa(u_int8_t protocol, u_int8_t tmode, struct ipsec_addr_wrap *src, struct
1394    ipsec_addr_wrap *dst, u_int32_t spi, struct ipsec_transforms *xfs,
1395    struct ipsec_key *authkey, struct ipsec_key *enckey)
1396{
1397	struct ipsec_rule *r;
1398
1399	if (validate_sa(spi, protocol, xfs, authkey, enckey, tmode) == 0)
1400		return (NULL);
1401
1402	r = calloc(1, sizeof(struct ipsec_rule));
1403	if (r == NULL)
1404		err(1, "create_sa: calloc");
1405
1406	r->type |= RULE_SA;
1407	r->proto = protocol;
1408	r->tmode = tmode;
1409	r->src = src;
1410	r->dst = dst;
1411	r->spi = spi;
1412	r->xfs = xfs;
1413	r->authkey = authkey;
1414	r->enckey = enckey;
1415
1416	return r;
1417}
1418
1419struct ipsec_rule *
1420reverse_sa(struct ipsec_rule *rule, u_int32_t spi, struct ipsec_key *authkey,
1421    struct ipsec_key *enckey)
1422{
1423	struct ipsec_rule *reverse;
1424
1425	if (validate_sa(spi, rule->proto, rule->xfs, authkey, enckey,
1426	    rule->tmode) == 0)
1427		return (NULL);
1428
1429	reverse = calloc(1, sizeof(struct ipsec_rule));
1430	if (reverse == NULL)
1431		err(1, "reverse_sa: calloc");
1432
1433	reverse->type |= RULE_SA;
1434	reverse->proto = rule->proto;
1435	reverse->tmode = rule->tmode;
1436	reverse->src = copyhost(rule->dst);
1437	reverse->dst = copyhost(rule->src);
1438	reverse->spi = spi;
1439	reverse->xfs = copytransforms(rule->xfs);
1440	reverse->authkey = authkey;
1441	reverse->enckey = enckey;
1442
1443	return (reverse);
1444}
1445
1446struct ipsec_rule *
1447create_flow(u_int8_t dir, struct ipsec_addr_wrap *src, struct ipsec_addr_wrap
1448    *dst, struct ipsec_addr_wrap *peer, u_int8_t proto, char *srcid, char
1449    *dstid, u_int16_t authtype)
1450{
1451	struct ipsec_rule *r;
1452
1453	r = calloc(1, sizeof(struct ipsec_rule));
1454	if (r == NULL)
1455		err(1, "create_flow: calloc");
1456
1457	r->type |= RULE_FLOW;
1458
1459	if (dir == IPSEC_INOUT)
1460		r->direction = IPSEC_OUT;
1461	else
1462		r->direction = dir;
1463
1464	if (r->direction == IPSEC_IN)
1465		r->flowtype = TYPE_USE;
1466	else
1467		r->flowtype = TYPE_REQUIRE;
1468
1469	r->src = src;
1470	r->dst = dst;
1471
1472	if (peer == NULL) {
1473		/* Set peer to remote host.  Must be a host address. */
1474		if (r->direction == IPSEC_IN) {
1475			if (r->src->netaddress) {
1476				yyerror("no peer specified");
1477				goto errout;
1478			}
1479			r->peer = copyhost(r->src);
1480		} else {
1481			if (r->dst->netaddress) {
1482				yyerror("no peer specified");
1483				goto errout;
1484			}
1485			r->peer = copyhost(r->dst);
1486		}
1487	} else
1488		r->peer = peer;
1489
1490	r->proto = proto;
1491	r->auth = calloc(1, sizeof(struct ipsec_auth));
1492	if (r->auth == NULL)
1493		err(1, "create_flow: calloc");
1494	r->auth->srcid = srcid;
1495	r->auth->dstid = dstid;
1496	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1497#ifdef notyet
1498	r->auth->type = authtype;
1499#endif
1500
1501	return r;
1502
1503errout:
1504	free(r);
1505	if (srcid)
1506		free(srcid);
1507	if (dstid)
1508		free(dstid);
1509	free(src);
1510	free(dst);
1511
1512	return NULL;
1513}
1514
1515struct ipsec_rule *
1516reverse_rule(struct ipsec_rule *rule)
1517{
1518	struct ipsec_rule *reverse;
1519
1520	reverse = calloc(1, sizeof(struct ipsec_rule));
1521	if (reverse == NULL)
1522		err(1, "reverse_rule: calloc");
1523
1524	reverse->type |= RULE_FLOW;
1525
1526	if (rule->direction == (u_int8_t)IPSEC_OUT) {
1527		reverse->direction = (u_int8_t)IPSEC_IN;
1528		reverse->flowtype = TYPE_USE;
1529	} else {
1530		reverse->direction = (u_int8_t)IPSEC_OUT;
1531		reverse->flowtype = TYPE_REQUIRE;
1532	}
1533
1534	reverse->src = copyhost(rule->dst);
1535	reverse->dst = copyhost(rule->src);
1536	reverse->peer = copyhost(rule->peer);
1537	reverse->proto = (u_int8_t)rule->proto;
1538
1539	reverse->auth = calloc(1, sizeof(struct ipsec_auth));
1540	if (reverse->auth == NULL)
1541		err(1, "reverse_rule: calloc");
1542	if (rule->auth->dstid && (reverse->auth->dstid =
1543	    strdup(rule->auth->dstid)) == NULL)
1544		err(1, "reverse_rule: strdup");
1545	if (rule->auth->srcid && (reverse->auth->srcid =
1546	    strdup(rule->auth->srcid)) == NULL)
1547		err(1, "reverse_rule: strdup");
1548	reverse->auth->idtype = rule->auth->idtype;
1549	reverse->auth->type = rule->auth->type;
1550
1551	return reverse;
1552}
1553
1554struct ipsec_rule *
1555create_ike(struct ipsec_addr_wrap *src, struct ipsec_addr_wrap *dst, struct
1556    ipsec_addr_wrap * peer, struct ipsec_transforms *mmxfs, struct
1557    ipsec_transforms *qmxfs, u_int8_t proto, u_int8_t mode, char *srcid, char
1558    *dstid)
1559{
1560	struct ipsec_rule *r;
1561
1562	r = calloc(1, sizeof(struct ipsec_rule));
1563	if (r == NULL)
1564		err(1, "create_ike: calloc");
1565
1566	r->type = RULE_IKE;
1567
1568	r->src = src;
1569	r->dst = dst;
1570
1571	if (peer == NULL) {
1572		/* Set peer to remote host.  Must be a host address. */
1573		if (r->direction == IPSEC_IN) {
1574			if (r->src->netaddress) {
1575				yyerror("no peer specified");
1576				goto errout;
1577			}
1578			r->peer = copyhost(r->src);
1579		} else {
1580			if (r->dst->netaddress) {
1581				yyerror("no peer specified");
1582				goto errout;
1583			}
1584			r->peer = copyhost(r->dst);
1585		}
1586	} else
1587		r->peer = peer;
1588
1589	r->proto = proto;
1590	r->ikemode = mode;
1591	r->mmxfs = mmxfs;
1592	r->qmxfs = qmxfs;
1593	r->auth = calloc(1, sizeof(struct ipsec_auth));
1594	if (r->auth == NULL)
1595		err(1, "create_ike: calloc");
1596	r->auth->srcid = srcid;
1597	r->auth->dstid = dstid;
1598	r->auth->idtype = ID_FQDN;	/* XXX For now only FQDN. */
1599
1600	return (r);
1601
1602errout:
1603	free(r);
1604	if (srcid)
1605		free(srcid);
1606	if (dstid)
1607		free(dstid);
1608	free(src);
1609	free(dst);
1610
1611	return (NULL);
1612}
1613