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