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