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