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