parse.y revision 127684
1/*	$FreeBSD: head/sbin/setkey/parse.y 127684 2004-03-31 18:38:02Z bms $	*/
2/*	$KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $	*/
3
4/*
5 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the project nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33%{
34#include <sys/types.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37
38#include <net/route.h>
39#include <netinet/in.h>
40#include <net/pfkeyv2.h>
41#include <netkey/key_var.h>
42#include <netinet6/ipsec.h>
43#include <arpa/inet.h>
44
45#include <string.h>
46#include <unistd.h>
47#include <stdio.h>
48#include <netdb.h>
49#include <ctype.h>
50#include <errno.h>
51
52#include "libpfkey.h"
53#include "vchar.h"
54
55#define ATOX(c) \
56  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10)))
57
58u_int32_t p_spi;
59u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
60u_int32_t p_reqid;
61u_int p_key_enc_len, p_key_auth_len;
62caddr_t p_key_enc, p_key_auth;
63time_t p_lt_hard, p_lt_soft;
64
65static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
66
67static struct addrinfo *parse_addr __P((char *, char *));
68static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *));
69static int setvarbuf __P((char *, int *, struct sadb_ext *, int, caddr_t, int));
70void parse_init __P((void));
71void free_buffer __P((void));
72
73int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
74static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
75	struct addrinfo *, int, struct addrinfo *, int));
76static int setkeymsg_addr __P((unsigned int, unsigned int,
77	struct addrinfo *, struct addrinfo *, int));
78static int setkeymsg_add __P((unsigned int, unsigned int,
79	struct addrinfo *, struct addrinfo *));
80extern int setkeymsg __P((char *, size_t *));
81extern int sendkeymsg __P((char *, size_t));
82
83extern int yylex __P((void));
84extern void yyfatal __P((const char *));
85extern void yyerror __P((const char *));
86%}
87
88%union {
89	int num;
90	unsigned long ulnum;
91	vchar_t val;
92	struct addrinfo *res;
93}
94
95%token EOT SLASH BLCL ELCL
96%token ADD GET DELETE DELETEALL FLUSH DUMP
97%token PR_ESP PR_AH PR_IPCOMP PR_TCP
98%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
99%token F_MODE MODE F_REQID
100%token F_EXT EXTENSION NOCYCLICSEQ
101%token ALG_AUTH ALG_AUTH_NOKEY
102%token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
103%token ALG_COMP
104%token F_LIFETIME_HARD F_LIFETIME_SOFT
105%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
106	/* SPD management */
107%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
108%token F_POLICY PL_REQUESTS
109%token F_AIFLAGS
110%token TAGGED
111
112%type <num> prefix protocol_spec upper_spec
113%type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
114%type <num> ALG_AUTH ALG_AUTH_NOKEY
115%type <num> ALG_COMP
116%type <num> PR_ESP PR_AH PR_IPCOMP PR_TCP
117%type <num> EXTENSION MODE
118%type <ulnum> DECSTRING
119%type <val> PL_REQUESTS portstr key_string
120%type <val> policy_requests
121%type <val> QUOTEDSTRING HEXSTRING STRING
122%type <val> F_AIFLAGS
123%type <val> upper_misc_spec policy_spec
124%type <res> ipaddr
125
126%%
127commands
128	:	/*NOTHING*/
129	|	commands command
130		{
131			free_buffer();
132			parse_init();
133		}
134	;
135
136command
137	:	add_command
138	|	get_command
139	|	delete_command
140	|	deleteall_command
141	|	flush_command
142	|	dump_command
143	|	spdadd_command
144	|	spddelete_command
145	|	spddump_command
146	|	spdflush_command
147	;
148	/* commands concerned with management, there is in tail of this file. */
149
150	/* add command */
151add_command
152	:	ADD ipaddropts ipaddr ipaddr protocol_spec spi extension_spec algorithm_spec EOT
153		{
154			int status;
155
156			status = setkeymsg_add(SADB_ADD, $5, $3, $4);
157			if (status < 0)
158				return -1;
159		}
160	;
161
162	/* delete */
163delete_command
164	:	DELETE ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
165		{
166			int status;
167
168			if ($3->ai_next || $4->ai_next) {
169				yyerror("multiple address specified");
170				return -1;
171			}
172			if (p_mode != IPSEC_MODE_ANY)
173				yyerror("WARNING: mode is obsolete");
174
175			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
176			if (status < 0)
177				return -1;
178		}
179	;
180
181	/* deleteall command */
182deleteall_command
183	:	DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
184		{
185			int status;
186
187			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
188			if (status < 0)
189				return -1;
190		}
191	;
192
193	/* get command */
194get_command
195	:	GET ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
196		{
197			int status;
198
199			if (p_mode != IPSEC_MODE_ANY)
200				yyerror("WARNING: mode is obsolete");
201
202			status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
203			if (status < 0)
204				return -1;
205		}
206	;
207
208	/* flush */
209flush_command
210	:	FLUSH protocol_spec EOT
211		{
212			struct sadb_msg msg;
213			setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
214			sendkeymsg((char *)&msg, sizeof(msg));
215		}
216	;
217
218	/* dump */
219dump_command
220	:	DUMP protocol_spec EOT
221		{
222			struct sadb_msg msg;
223			setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
224			sendkeymsg((char *)&msg, sizeof(msg));
225		}
226	;
227
228protocol_spec
229	:	/*NOTHING*/
230		{
231			$$ = SADB_SATYPE_UNSPEC;
232		}
233	|	PR_ESP
234		{
235			$$ = SADB_SATYPE_ESP;
236			if ($1 == 1)
237				p_ext |= SADB_X_EXT_OLD;
238			else
239				p_ext &= ~SADB_X_EXT_OLD;
240		}
241	|	PR_AH
242		{
243			$$ = SADB_SATYPE_AH;
244			if ($1 == 1)
245				p_ext |= SADB_X_EXT_OLD;
246			else
247				p_ext &= ~SADB_X_EXT_OLD;
248		}
249	|	PR_IPCOMP
250		{
251			$$ = SADB_X_SATYPE_IPCOMP;
252		}
253	|	PR_TCP
254		{
255			$$ = SADB_X_SATYPE_TCPSIGNATURE;
256		}
257	;
258
259spi
260	:	DECSTRING { p_spi = $1; }
261	|	HEXSTRING
262		{
263			char *ep;
264			unsigned long v;
265
266			ep = NULL;
267			v = strtoul($1.buf, &ep, 16);
268			if (!ep || *ep) {
269				yyerror("invalid SPI");
270				return -1;
271			}
272			if (v & ~0xffffffff) {
273				yyerror("SPI too big.");
274				return -1;
275			}
276
277			p_spi = v;
278		}
279	;
280
281algorithm_spec
282	:	esp_spec
283	|	ah_spec
284	|	ipcomp_spec
285	;
286
287esp_spec
288	:	F_ENC enc_alg F_AUTH auth_alg
289	|	F_ENC enc_alg
290	;
291
292ah_spec
293	:	F_AUTH auth_alg
294	;
295
296ipcomp_spec
297	:	F_COMP ALG_COMP
298		{
299			if ($2 < 0) {
300				yyerror("unsupported algorithm");
301				return -1;
302			}
303			p_alg_enc = $2;
304		}
305	|	F_COMP ALG_COMP F_RAWCPI
306		{
307			if ($2 < 0) {
308				yyerror("unsupported algorithm");
309				return -1;
310			}
311			p_alg_enc = $2;
312			p_ext |= SADB_X_EXT_RAWCPI;
313		}
314	;
315
316enc_alg
317	:	ALG_ENC_NOKEY {
318			if ($1 < 0) {
319				yyerror("unsupported algorithm");
320				return -1;
321			}
322			p_alg_enc = $1;
323
324			p_key_enc_len = 0;
325			p_key_enc = NULL;
326		}
327	|	ALG_ENC key_string {
328			if ($1 < 0) {
329				yyerror("unsupported algorithm");
330				return -1;
331			}
332			p_alg_enc = $1;
333
334			p_key_enc_len = $2.len;
335			p_key_enc = $2.buf;
336			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
337			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
338				yyerror(ipsec_strerror());
339				return -1;
340			}
341		}
342	|	ALG_ENC_OLD {
343			if ($1 < 0) {
344				yyerror("unsupported algorithm");
345				return -1;
346			}
347			yyerror("WARNING: obsolete algorithm");
348			p_alg_enc = $1;
349
350			p_key_enc_len = 0;
351			p_key_enc = NULL;
352		}
353	|	ALG_ENC_DESDERIV key_string
354		{
355			if ($1 < 0) {
356				yyerror("unsupported algorithm");
357				return -1;
358			}
359			p_alg_enc = $1;
360			if (p_ext & SADB_X_EXT_OLD) {
361				yyerror("algorithm mismatched");
362				return -1;
363			}
364			p_ext |= SADB_X_EXT_DERIV;
365
366			p_key_enc_len = $2.len;
367			p_key_enc = $2.buf;
368			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
369			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
370				yyerror(ipsec_strerror());
371				return -1;
372			}
373		}
374	|	ALG_ENC_DES32IV key_string
375		{
376			if ($1 < 0) {
377				yyerror("unsupported algorithm");
378				return -1;
379			}
380			p_alg_enc = $1;
381			if (!(p_ext & SADB_X_EXT_OLD)) {
382				yyerror("algorithm mismatched");
383				return -1;
384			}
385			p_ext |= SADB_X_EXT_IV4B;
386
387			p_key_enc_len = $2.len;
388			p_key_enc = $2.buf;
389			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
390			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
391				yyerror(ipsec_strerror());
392				return -1;
393			}
394		}
395	;
396
397auth_alg
398	:	ALG_AUTH key_string {
399			if ($1 < 0) {
400				yyerror("unsupported algorithm");
401				return -1;
402			}
403			p_alg_auth = $1;
404
405			p_key_auth_len = $2.len;
406			p_key_auth = $2.buf;
407
408			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
409				if ((p_key_auth_len < 1) || (p_key_auth_len >
410				    80))
411					return -1;
412			} else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
413			    p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
414				yyerror(ipsec_strerror());
415				return -1;
416			}
417		}
418	|	ALG_AUTH_NOKEY {
419			if ($1 < 0) {
420				yyerror("unsupported algorithm");
421				return -1;
422			}
423			p_alg_auth = $1;
424
425			p_key_auth_len = 0;
426			p_key_auth = NULL;
427		}
428	;
429
430key_string
431	:	QUOTEDSTRING
432		{
433			$$ = $1;
434		}
435	|	HEXSTRING
436		{
437			caddr_t pp_key;
438			caddr_t bp;
439			caddr_t yp = $1.buf;
440			int l;
441
442			l = strlen(yp) % 2 + strlen(yp) / 2;
443			if ((pp_key = malloc(l)) == 0) {
444				yyerror("not enough core");
445				return -1;
446			}
447			memset(pp_key, 0, l);
448
449			bp = pp_key;
450			if (strlen(yp) % 2) {
451				*bp = ATOX(yp[0]);
452				yp++, bp++;
453			}
454			while (*yp) {
455				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
456				yp += 2, bp++;
457			}
458
459			$$.len = l;
460			$$.buf = pp_key;
461		}
462	;
463
464extension_spec
465	:	/*NOTHING*/
466	|	extension_spec extension
467	;
468
469extension
470	:	F_EXT EXTENSION { p_ext |= $2; }
471	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
472	|	F_MODE MODE { p_mode = $2; }
473	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
474	|	F_REQID DECSTRING { p_reqid = $2; }
475	|	F_REPLAY DECSTRING
476		{
477			if ((p_ext & SADB_X_EXT_OLD) != 0) {
478				yyerror("replay prevention cannot be used with "
479				    "ah/esp-old");
480				return -1;
481			}
482			p_replay = $2;
483		}
484	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
485	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
486	;
487
488	/* definition about command for SPD management */
489	/* spdadd */
490spdadd_command
491	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
492		{
493			int status;
494			struct addrinfo *src, *dst;
495
496			/* fixed port fields if ulp is icmpv6 */
497			if ($10.buf != NULL) {
498				if ($9 != IPPROTO_ICMPV6)
499					return -1;
500				free($5.buf);
501				free($8.buf);
502				if (fix_portstr(&$10, &$5, &$8))
503					return -1;
504			}
505
506			src = parse_addr($3.buf, $5.buf);
507			dst = parse_addr($6.buf, $8.buf);
508			if (!src || !dst) {
509				/* yyerror is already called */
510				return -1;
511			}
512			if (src->ai_next || dst->ai_next) {
513				yyerror("multiple address specified");
514				freeaddrinfo(src);
515				freeaddrinfo(dst);
516				return -1;
517			}
518
519			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
520			    src, $4, dst, $7);
521			freeaddrinfo(src);
522			freeaddrinfo(dst);
523			if (status < 0)
524				return -1;
525		}
526	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
527		{
528			return -1;
529		}
530	;
531
532spddelete_command
533	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
534		{
535			int status;
536			struct addrinfo *src, *dst;
537
538			/* fixed port fields if ulp is icmpv6 */
539			if ($10.buf != NULL) {
540				if ($9 != IPPROTO_ICMPV6)
541					return -1;
542				free($5.buf);
543				free($8.buf);
544				if (fix_portstr(&$10, &$5, &$8))
545					return -1;
546			}
547
548			src = parse_addr($3.buf, $5.buf);
549			dst = parse_addr($6.buf, $8.buf);
550			if (!src || !dst) {
551				/* yyerror is already called */
552				return -1;
553			}
554			if (src->ai_next || dst->ai_next) {
555				yyerror("multiple address specified");
556				freeaddrinfo(src);
557				freeaddrinfo(dst);
558				return -1;
559			}
560
561			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
562			    src, $4, dst, $7);
563			freeaddrinfo(src);
564			freeaddrinfo(dst);
565			if (status < 0)
566				return -1;
567		}
568	;
569
570spddump_command:
571		SPDDUMP EOT
572		{
573			struct sadb_msg msg;
574			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
575			    sizeof(msg));
576			sendkeymsg((char *)&msg, sizeof(msg));
577		}
578	;
579
580spdflush_command:
581		SPDFLUSH EOT
582		{
583			struct sadb_msg msg;
584			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
585			    sizeof(msg));
586			sendkeymsg((char *)&msg, sizeof(msg));
587		}
588	;
589
590ipaddropts
591	:	/* nothing */
592	|	ipaddropts ipaddropt
593	;
594
595ipaddropt
596	:	F_AIFLAGS
597		{
598			char *p;
599
600			for (p = $1.buf + 1; *p; p++)
601				switch (*p) {
602				case '4':
603					p_aifamily = AF_INET;
604					break;
605#ifdef INET6
606				case '6':
607					p_aifamily = AF_INET6;
608					break;
609#endif
610				case 'n':
611					p_aiflags = AI_NUMERICHOST;
612					break;
613				default:
614					yyerror("invalid flag");
615					return -1;
616				}
617		}
618	;
619
620ipaddr
621	:	STRING
622		{
623			$$ = parse_addr($1.buf, NULL);
624			if ($$ == NULL) {
625				/* yyerror already called by parse_addr */
626				return -1;
627			}
628		}
629	;
630
631prefix
632	:	/*NOTHING*/ { $$ = -1; }
633	|	SLASH DECSTRING { $$ = $2; }
634	;
635
636portstr
637	:	/*NOTHING*/
638		{
639			$$.buf = strdup("0");
640			if (!$$.buf) {
641				yyerror("insufficient memory");
642				return -1;
643			}
644			$$.len = strlen($$.buf);
645		}
646	|	BLCL ANY ELCL
647		{
648			$$.buf = strdup("0");
649			if (!$$.buf) {
650				yyerror("insufficient memory");
651				return -1;
652			}
653			$$.len = strlen($$.buf);
654		}
655	|	BLCL DECSTRING ELCL
656		{
657			char buf[20];
658			snprintf(buf, sizeof(buf), "%lu", $2);
659			$$.buf = strdup(buf);
660			if (!$$.buf) {
661				yyerror("insufficient memory");
662				return -1;
663			}
664			$$.len = strlen($$.buf);
665		}
666	|	BLCL STRING ELCL
667		{
668			$$ = $2;
669		}
670	;
671
672upper_spec
673	:	DECSTRING { $$ = $1; }
674	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
675	|	PR_TCP { $$ = IPPROTO_TCP; }
676	|	STRING
677		{
678			struct protoent *ent;
679
680			ent = getprotobyname($1.buf);
681			if (ent)
682				$$ = ent->p_proto;
683			else {
684				if (strcmp("icmp6", $1.buf) == 0) {
685					$$ = IPPROTO_ICMPV6;
686				} else if(strcmp("ip4", $1.buf) == 0) {
687					$$ = IPPROTO_IPV4;
688				} else {
689					yyerror("invalid upper layer protocol");
690					return -1;
691				}
692			}
693			endprotoent();
694		}
695	;
696
697upper_misc_spec
698	:	/*NOTHING*/
699		{
700			$$.buf = NULL;
701			$$.len = 0;
702		}
703	|	STRING
704		{
705			$$.buf = strdup($1.buf);
706			if (!$$.buf) {
707				yyerror("insufficient memory");
708				return -1;
709			}
710			$$.len = strlen($$.buf);
711		}
712	;
713
714policy_spec
715	:	F_POLICY policy_requests
716		{
717			char *policy;
718
719			policy = ipsec_set_policy($2.buf, $2.len);
720			if (policy == NULL) {
721				yyerror(ipsec_strerror());
722				return -1;
723			}
724
725			$$.buf = policy;
726			$$.len = ipsec_get_policylen(policy);
727		}
728	;
729
730policy_requests
731	:	PL_REQUESTS { $$ = $1; }
732	;
733
734%%
735
736int
737setkeymsg0(msg, type, satype, l)
738	struct sadb_msg *msg;
739	unsigned int type;
740	unsigned int satype;
741	size_t l;
742{
743
744	msg->sadb_msg_version = PF_KEY_V2;
745	msg->sadb_msg_type = type;
746	msg->sadb_msg_errno = 0;
747	msg->sadb_msg_satype = satype;
748	msg->sadb_msg_reserved = 0;
749	msg->sadb_msg_seq = 0;
750	msg->sadb_msg_pid = getpid();
751	msg->sadb_msg_len = PFKEY_UNIT64(l);
752	return 0;
753}
754
755/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
756static int
757setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
758	unsigned int type;
759	unsigned int upper;
760	vchar_t *policy;
761	struct addrinfo *srcs;
762	int splen;
763	struct addrinfo *dsts;
764	int dplen;
765{
766	struct sadb_msg *msg;
767	char buf[BUFSIZ];
768	int l, l0;
769	struct sadb_address m_addr;
770	struct addrinfo *s, *d;
771	int n;
772	int plen;
773	struct sockaddr *sa;
774	int salen;
775
776	msg = (struct sadb_msg *)buf;
777
778	if (!srcs || !dsts)
779		return -1;
780
781	/* fix up length afterwards */
782	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
783	l = sizeof(struct sadb_msg);
784
785	memcpy(buf + l, policy->buf, policy->len);
786	l += policy->len;
787
788	l0 = l;
789	n = 0;
790
791	/* do it for all src/dst pairs */
792	for (s = srcs; s; s = s->ai_next) {
793		for (d = dsts; d; d = d->ai_next) {
794			/* rewind pointer */
795			l = l0;
796
797			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
798				continue;
799			switch (s->ai_addr->sa_family) {
800			case AF_INET:
801				plen = sizeof(struct in_addr) << 3;
802				break;
803#ifdef INET6
804			case AF_INET6:
805				plen = sizeof(struct in6_addr) << 3;
806				break;
807#endif
808			default:
809				continue;
810			}
811
812			/* set src */
813			sa = s->ai_addr;
814			salen = s->ai_addr->sa_len;
815			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
816			    PFKEY_ALIGN8(salen));
817			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
818			m_addr.sadb_address_proto = upper;
819			m_addr.sadb_address_prefixlen =
820			    (splen >= 0 ? splen : plen);
821			m_addr.sadb_address_reserved = 0;
822
823			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
824			    sizeof(m_addr), (caddr_t)sa, salen);
825
826			/* set dst */
827			sa = d->ai_addr;
828			salen = d->ai_addr->sa_len;
829			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
830			    PFKEY_ALIGN8(salen));
831			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
832			m_addr.sadb_address_proto = upper;
833			m_addr.sadb_address_prefixlen =
834			    (dplen >= 0 ? dplen : plen);
835			m_addr.sadb_address_reserved = 0;
836
837			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
838			    sizeof(m_addr), (caddr_t)sa, salen);
839
840			msg->sadb_msg_len = PFKEY_UNIT64(l);
841
842			sendkeymsg(buf, l);
843
844			n++;
845		}
846	}
847
848	if (n == 0)
849		return -1;
850	else
851		return 0;
852}
853
854/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
855static int
856setkeymsg_addr(type, satype, srcs, dsts, no_spi)
857	unsigned int type;
858	unsigned int satype;
859	struct addrinfo *srcs;
860	struct addrinfo *dsts;
861	int no_spi;
862{
863	struct sadb_msg *msg;
864	char buf[BUFSIZ];
865	int l, l0, len;
866	struct sadb_sa m_sa;
867	struct sadb_x_sa2 m_sa2;
868	struct sadb_address m_addr;
869	struct addrinfo *s, *d;
870	int n;
871	int plen;
872	struct sockaddr *sa;
873	int salen;
874
875	msg = (struct sadb_msg *)buf;
876
877	if (!srcs || !dsts)
878		return -1;
879
880	/* fix up length afterwards */
881	setkeymsg0(msg, type, satype, 0);
882	l = sizeof(struct sadb_msg);
883
884	if (!no_spi) {
885		len = sizeof(struct sadb_sa);
886		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
887		m_sa.sadb_sa_exttype = SADB_EXT_SA;
888		m_sa.sadb_sa_spi = htonl(p_spi);
889		m_sa.sadb_sa_replay = p_replay;
890		m_sa.sadb_sa_state = 0;
891		m_sa.sadb_sa_auth = p_alg_auth;
892		m_sa.sadb_sa_encrypt = p_alg_enc;
893		m_sa.sadb_sa_flags = p_ext;
894
895		memcpy(buf + l, &m_sa, len);
896		l += len;
897
898		len = sizeof(struct sadb_x_sa2);
899		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
900		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
901		m_sa2.sadb_x_sa2_mode = p_mode;
902		m_sa2.sadb_x_sa2_reqid = p_reqid;
903
904		memcpy(buf + l, &m_sa2, len);
905		l += len;
906	}
907
908	l0 = l;
909	n = 0;
910
911	/* do it for all src/dst pairs */
912	for (s = srcs; s; s = s->ai_next) {
913		for (d = dsts; d; d = d->ai_next) {
914			/* rewind pointer */
915			l = l0;
916
917			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
918				continue;
919			switch (s->ai_addr->sa_family) {
920			case AF_INET:
921				plen = sizeof(struct in_addr) << 3;
922				break;
923#ifdef INET6
924			case AF_INET6:
925				plen = sizeof(struct in6_addr) << 3;
926				break;
927#endif
928			default:
929				continue;
930			}
931
932			/* set src */
933			sa = s->ai_addr;
934			salen = s->ai_addr->sa_len;
935			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
936			    PFKEY_ALIGN8(salen));
937			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
938			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
939			m_addr.sadb_address_prefixlen = plen;
940			m_addr.sadb_address_reserved = 0;
941
942			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
943			    sizeof(m_addr), (caddr_t)sa, salen);
944
945			/* set dst */
946			sa = d->ai_addr;
947			salen = d->ai_addr->sa_len;
948			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
949			    PFKEY_ALIGN8(salen));
950			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
951			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
952			m_addr.sadb_address_prefixlen = plen;
953			m_addr.sadb_address_reserved = 0;
954
955			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
956			    sizeof(m_addr), (caddr_t)sa, salen);
957
958			msg->sadb_msg_len = PFKEY_UNIT64(l);
959
960			sendkeymsg(buf, l);
961
962			n++;
963		}
964	}
965
966	if (n == 0)
967		return -1;
968	else
969		return 0;
970}
971
972/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
973static int
974setkeymsg_add(type, satype, srcs, dsts)
975	unsigned int type;
976	unsigned int satype;
977	struct addrinfo *srcs;
978	struct addrinfo *dsts;
979{
980	struct sadb_msg *msg;
981	char buf[BUFSIZ];
982	int l, l0, len;
983	struct sadb_sa m_sa;
984	struct sadb_x_sa2 m_sa2;
985	struct sadb_address m_addr;
986	struct addrinfo *s, *d;
987	int n;
988	int plen;
989	struct sockaddr *sa;
990	int salen;
991
992	msg = (struct sadb_msg *)buf;
993
994	if (!srcs || !dsts)
995		return -1;
996
997	/* fix up length afterwards */
998	setkeymsg0(msg, type, satype, 0);
999	l = sizeof(struct sadb_msg);
1000
1001	/* set encryption algorithm, if present. */
1002	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1003		struct sadb_key m_key;
1004
1005		m_key.sadb_key_len =
1006			PFKEY_UNIT64(sizeof(m_key)
1007				   + PFKEY_ALIGN8(p_key_enc_len));
1008		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1009		m_key.sadb_key_bits = p_key_enc_len * 8;
1010		m_key.sadb_key_reserved = 0;
1011
1012		setvarbuf(buf, &l,
1013			(struct sadb_ext *)&m_key, sizeof(m_key),
1014			(caddr_t)p_key_enc, p_key_enc_len);
1015	}
1016
1017	/* set authentication algorithm, if present. */
1018	if (p_key_auth) {
1019		struct sadb_key m_key;
1020
1021		m_key.sadb_key_len =
1022			PFKEY_UNIT64(sizeof(m_key)
1023				   + PFKEY_ALIGN8(p_key_auth_len));
1024		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1025		m_key.sadb_key_bits = p_key_auth_len * 8;
1026		m_key.sadb_key_reserved = 0;
1027
1028		setvarbuf(buf, &l,
1029			(struct sadb_ext *)&m_key, sizeof(m_key),
1030			(caddr_t)p_key_auth, p_key_auth_len);
1031	}
1032
1033	/* set lifetime for HARD */
1034	if (p_lt_hard != 0) {
1035		struct sadb_lifetime m_lt;
1036		u_int slen = sizeof(struct sadb_lifetime);
1037
1038		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1039		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1040		m_lt.sadb_lifetime_allocations = 0;
1041		m_lt.sadb_lifetime_bytes = 0;
1042		m_lt.sadb_lifetime_addtime = p_lt_hard;
1043		m_lt.sadb_lifetime_usetime = 0;
1044
1045		memcpy(buf + l, &m_lt, slen);
1046		l += len;
1047	}
1048
1049	/* set lifetime for SOFT */
1050	if (p_lt_soft != 0) {
1051		struct sadb_lifetime m_lt;
1052		u_int slen = sizeof(struct sadb_lifetime);
1053
1054		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1055		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1056		m_lt.sadb_lifetime_allocations = 0;
1057		m_lt.sadb_lifetime_bytes = 0;
1058		m_lt.sadb_lifetime_addtime = p_lt_soft;
1059		m_lt.sadb_lifetime_usetime = 0;
1060
1061		memcpy(buf + l, &m_lt, slen);
1062		l += len;
1063	}
1064
1065	len = sizeof(struct sadb_sa);
1066	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1067	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1068	m_sa.sadb_sa_spi = htonl(p_spi);
1069	m_sa.sadb_sa_replay = p_replay;
1070	m_sa.sadb_sa_state = 0;
1071	m_sa.sadb_sa_auth = p_alg_auth;
1072	m_sa.sadb_sa_encrypt = p_alg_enc;
1073	m_sa.sadb_sa_flags = p_ext;
1074
1075	memcpy(buf + l, &m_sa, len);
1076	l += len;
1077
1078	len = sizeof(struct sadb_x_sa2);
1079	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1080	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1081	m_sa2.sadb_x_sa2_mode = p_mode;
1082	m_sa2.sadb_x_sa2_reqid = p_reqid;
1083
1084	memcpy(buf + l, &m_sa2, len);
1085	l += len;
1086
1087	l0 = l;
1088	n = 0;
1089
1090	/* do it for all src/dst pairs */
1091	for (s = srcs; s; s = s->ai_next) {
1092		for (d = dsts; d; d = d->ai_next) {
1093			/* rewind pointer */
1094			l = l0;
1095
1096			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1097				continue;
1098			switch (s->ai_addr->sa_family) {
1099			case AF_INET:
1100				plen = sizeof(struct in_addr) << 3;
1101				break;
1102#ifdef INET6
1103			case AF_INET6:
1104				plen = sizeof(struct in6_addr) << 3;
1105				break;
1106#endif
1107			default:
1108				continue;
1109			}
1110
1111			/* set src */
1112			sa = s->ai_addr;
1113			salen = s->ai_addr->sa_len;
1114			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1115			    PFKEY_ALIGN8(salen));
1116			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1117			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1118			m_addr.sadb_address_prefixlen = plen;
1119			m_addr.sadb_address_reserved = 0;
1120
1121			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1122			    sizeof(m_addr), (caddr_t)sa, salen);
1123
1124			/* set dst */
1125			sa = d->ai_addr;
1126			salen = d->ai_addr->sa_len;
1127			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1128			    PFKEY_ALIGN8(salen));
1129			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1130			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1131			m_addr.sadb_address_prefixlen = plen;
1132			m_addr.sadb_address_reserved = 0;
1133
1134			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1135			    sizeof(m_addr), (caddr_t)sa, salen);
1136
1137			msg->sadb_msg_len = PFKEY_UNIT64(l);
1138
1139			sendkeymsg(buf, l);
1140
1141			n++;
1142		}
1143	}
1144
1145	if (n == 0)
1146		return -1;
1147	else
1148		return 0;
1149}
1150
1151static struct addrinfo *
1152parse_addr(host, port)
1153	char *host;
1154	char *port;
1155{
1156	struct addrinfo hints, *res = NULL;
1157	int error;
1158
1159	memset(&hints, 0, sizeof(hints));
1160	hints.ai_family = p_aifamily;
1161	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1162	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1163	hints.ai_flags = p_aiflags;
1164	error = getaddrinfo(host, port, &hints, &res);
1165	if (error != 0) {
1166		yyerror(gai_strerror(error));
1167		return NULL;
1168	}
1169	return res;
1170}
1171
1172static int
1173fix_portstr(spec, sport, dport)
1174	vchar_t *spec, *sport, *dport;
1175{
1176	char *p, *p2;
1177	u_int l;
1178
1179	l = 0;
1180	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1181		;
1182	if (*p == '\0') {
1183		p2 = "0";
1184	} else {
1185		if (*p == ',') {
1186			*p = '\0';
1187			p2 = ++p;
1188		}
1189		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1190			;
1191		if (*p != '\0' || *p2 == '\0') {
1192			yyerror("invalid an upper layer protocol spec");
1193			return -1;
1194		}
1195	}
1196
1197	sport->buf = strdup(spec->buf);
1198	if (!sport->buf) {
1199		yyerror("insufficient memory");
1200		return -1;
1201	}
1202	sport->len = strlen(sport->buf);
1203	dport->buf = strdup(p2);
1204	if (!dport->buf) {
1205		yyerror("insufficient memory");
1206		return -1;
1207	}
1208	dport->len = strlen(dport->buf);
1209
1210	return 0;
1211}
1212
1213static int
1214setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1215	char *buf;
1216	int *off;
1217	struct sadb_ext *ebuf;
1218	int elen;
1219	caddr_t vbuf;
1220	int vlen;
1221{
1222	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1223	memcpy(buf + *off, (caddr_t)ebuf, elen);
1224	memcpy(buf + *off + elen, vbuf, vlen);
1225	(*off) += PFKEY_ALIGN8(elen + vlen);
1226
1227	return 0;
1228}
1229
1230void
1231parse_init()
1232{
1233	p_spi = 0;
1234
1235	p_ext = SADB_X_EXT_CYCSEQ;
1236	p_alg_enc = SADB_EALG_NONE;
1237	p_alg_auth = SADB_AALG_NONE;
1238	p_mode = IPSEC_MODE_ANY;
1239	p_reqid = 0;
1240	p_replay = 0;
1241	p_key_enc_len = p_key_auth_len = 0;
1242	p_key_enc = p_key_auth = 0;
1243	p_lt_hard = p_lt_soft = 0;
1244
1245	p_aiflags = 0;
1246	p_aifamily = PF_UNSPEC;
1247
1248	return;
1249}
1250
1251void
1252free_buffer()
1253{
1254	/* we got tons of memory leaks in the parser anyways, leave them */
1255
1256	return;
1257}
1258