parse.y revision 125681
1/*	$FreeBSD: head/sbin/setkey/parse.y 125681 2004-02-11 04:34:34Z 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	|	STRING
676		{
677			struct protoent *ent;
678
679			ent = getprotobyname($1.buf);
680			if (ent)
681				$$ = ent->p_proto;
682			else {
683				if (strcmp("icmp6", $1.buf) == 0) {
684					$$ = IPPROTO_ICMPV6;
685				} else if(strcmp("ip4", $1.buf) == 0) {
686					$$ = IPPROTO_IPV4;
687				} else {
688					yyerror("invalid upper layer protocol");
689					return -1;
690				}
691			}
692			endprotoent();
693		}
694	;
695
696upper_misc_spec
697	:	/*NOTHING*/
698		{
699			$$.buf = NULL;
700			$$.len = 0;
701		}
702	|	STRING
703		{
704			$$.buf = strdup($1.buf);
705			if (!$$.buf) {
706				yyerror("insufficient memory");
707				return -1;
708			}
709			$$.len = strlen($$.buf);
710		}
711	;
712
713policy_spec
714	:	F_POLICY policy_requests
715		{
716			char *policy;
717
718			policy = ipsec_set_policy($2.buf, $2.len);
719			if (policy == NULL) {
720				yyerror(ipsec_strerror());
721				return -1;
722			}
723
724			$$.buf = policy;
725			$$.len = ipsec_get_policylen(policy);
726		}
727	;
728
729policy_requests
730	:	PL_REQUESTS { $$ = $1; }
731	;
732
733%%
734
735int
736setkeymsg0(msg, type, satype, l)
737	struct sadb_msg *msg;
738	unsigned int type;
739	unsigned int satype;
740	size_t l;
741{
742
743	msg->sadb_msg_version = PF_KEY_V2;
744	msg->sadb_msg_type = type;
745	msg->sadb_msg_errno = 0;
746	msg->sadb_msg_satype = satype;
747	msg->sadb_msg_reserved = 0;
748	msg->sadb_msg_seq = 0;
749	msg->sadb_msg_pid = getpid();
750	msg->sadb_msg_len = PFKEY_UNIT64(l);
751	return 0;
752}
753
754/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
755static int
756setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
757	unsigned int type;
758	unsigned int upper;
759	vchar_t *policy;
760	struct addrinfo *srcs;
761	int splen;
762	struct addrinfo *dsts;
763	int dplen;
764{
765	struct sadb_msg *msg;
766	char buf[BUFSIZ];
767	int l, l0;
768	struct sadb_address m_addr;
769	struct addrinfo *s, *d;
770	int n;
771	int plen;
772	struct sockaddr *sa;
773	int salen;
774
775	msg = (struct sadb_msg *)buf;
776
777	if (!srcs || !dsts)
778		return -1;
779
780	/* fix up length afterwards */
781	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
782	l = sizeof(struct sadb_msg);
783
784	memcpy(buf + l, policy->buf, policy->len);
785	l += policy->len;
786
787	l0 = l;
788	n = 0;
789
790	/* do it for all src/dst pairs */
791	for (s = srcs; s; s = s->ai_next) {
792		for (d = dsts; d; d = d->ai_next) {
793			/* rewind pointer */
794			l = l0;
795
796			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
797				continue;
798			switch (s->ai_addr->sa_family) {
799			case AF_INET:
800				plen = sizeof(struct in_addr) << 3;
801				break;
802#ifdef INET6
803			case AF_INET6:
804				plen = sizeof(struct in6_addr) << 3;
805				break;
806#endif
807			default:
808				continue;
809			}
810
811			/* set src */
812			sa = s->ai_addr;
813			salen = s->ai_addr->sa_len;
814			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
815			    PFKEY_ALIGN8(salen));
816			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
817			m_addr.sadb_address_proto = upper;
818			m_addr.sadb_address_prefixlen =
819			    (splen >= 0 ? splen : plen);
820			m_addr.sadb_address_reserved = 0;
821
822			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
823			    sizeof(m_addr), (caddr_t)sa, salen);
824
825			/* set dst */
826			sa = d->ai_addr;
827			salen = d->ai_addr->sa_len;
828			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
829			    PFKEY_ALIGN8(salen));
830			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
831			m_addr.sadb_address_proto = upper;
832			m_addr.sadb_address_prefixlen =
833			    (dplen >= 0 ? dplen : plen);
834			m_addr.sadb_address_reserved = 0;
835
836			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
837			    sizeof(m_addr), (caddr_t)sa, salen);
838
839			msg->sadb_msg_len = PFKEY_UNIT64(l);
840
841			sendkeymsg(buf, l);
842
843			n++;
844		}
845	}
846
847	if (n == 0)
848		return -1;
849	else
850		return 0;
851}
852
853/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
854static int
855setkeymsg_addr(type, satype, srcs, dsts, no_spi)
856	unsigned int type;
857	unsigned int satype;
858	struct addrinfo *srcs;
859	struct addrinfo *dsts;
860	int no_spi;
861{
862	struct sadb_msg *msg;
863	char buf[BUFSIZ];
864	int l, l0, len;
865	struct sadb_sa m_sa;
866	struct sadb_x_sa2 m_sa2;
867	struct sadb_address m_addr;
868	struct addrinfo *s, *d;
869	int n;
870	int plen;
871	struct sockaddr *sa;
872	int salen;
873
874	msg = (struct sadb_msg *)buf;
875
876	if (!srcs || !dsts)
877		return -1;
878
879	/* fix up length afterwards */
880	setkeymsg0(msg, type, satype, 0);
881	l = sizeof(struct sadb_msg);
882
883	if (!no_spi) {
884		len = sizeof(struct sadb_sa);
885		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
886		m_sa.sadb_sa_exttype = SADB_EXT_SA;
887		m_sa.sadb_sa_spi = htonl(p_spi);
888		m_sa.sadb_sa_replay = p_replay;
889		m_sa.sadb_sa_state = 0;
890		m_sa.sadb_sa_auth = p_alg_auth;
891		m_sa.sadb_sa_encrypt = p_alg_enc;
892		m_sa.sadb_sa_flags = p_ext;
893
894		memcpy(buf + l, &m_sa, len);
895		l += len;
896
897		len = sizeof(struct sadb_x_sa2);
898		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
899		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
900		m_sa2.sadb_x_sa2_mode = p_mode;
901		m_sa2.sadb_x_sa2_reqid = p_reqid;
902
903		memcpy(buf + l, &m_sa2, len);
904		l += len;
905	}
906
907	l0 = l;
908	n = 0;
909
910	/* do it for all src/dst pairs */
911	for (s = srcs; s; s = s->ai_next) {
912		for (d = dsts; d; d = d->ai_next) {
913			/* rewind pointer */
914			l = l0;
915
916			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
917				continue;
918			switch (s->ai_addr->sa_family) {
919			case AF_INET:
920				plen = sizeof(struct in_addr) << 3;
921				break;
922#ifdef INET6
923			case AF_INET6:
924				plen = sizeof(struct in6_addr) << 3;
925				break;
926#endif
927			default:
928				continue;
929			}
930
931			/* set src */
932			sa = s->ai_addr;
933			salen = s->ai_addr->sa_len;
934			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
935			    PFKEY_ALIGN8(salen));
936			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
937			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
938			m_addr.sadb_address_prefixlen = plen;
939			m_addr.sadb_address_reserved = 0;
940
941			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
942			    sizeof(m_addr), (caddr_t)sa, salen);
943
944			/* set dst */
945			sa = d->ai_addr;
946			salen = d->ai_addr->sa_len;
947			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
948			    PFKEY_ALIGN8(salen));
949			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
950			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
951			m_addr.sadb_address_prefixlen = plen;
952			m_addr.sadb_address_reserved = 0;
953
954			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
955			    sizeof(m_addr), (caddr_t)sa, salen);
956
957			msg->sadb_msg_len = PFKEY_UNIT64(l);
958
959			sendkeymsg(buf, l);
960
961			n++;
962		}
963	}
964
965	if (n == 0)
966		return -1;
967	else
968		return 0;
969}
970
971/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
972static int
973setkeymsg_add(type, satype, srcs, dsts)
974	unsigned int type;
975	unsigned int satype;
976	struct addrinfo *srcs;
977	struct addrinfo *dsts;
978{
979	struct sadb_msg *msg;
980	char buf[BUFSIZ];
981	int l, l0, len;
982	struct sadb_sa m_sa;
983	struct sadb_x_sa2 m_sa2;
984	struct sadb_address m_addr;
985	struct addrinfo *s, *d;
986	int n;
987	int plen;
988	struct sockaddr *sa;
989	int salen;
990
991	msg = (struct sadb_msg *)buf;
992
993	if (!srcs || !dsts)
994		return -1;
995
996	/* fix up length afterwards */
997	setkeymsg0(msg, type, satype, 0);
998	l = sizeof(struct sadb_msg);
999
1000	/* set encryption algorithm, if present. */
1001	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1002		struct sadb_key m_key;
1003
1004		m_key.sadb_key_len =
1005			PFKEY_UNIT64(sizeof(m_key)
1006				   + PFKEY_ALIGN8(p_key_enc_len));
1007		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1008		m_key.sadb_key_bits = p_key_enc_len * 8;
1009		m_key.sadb_key_reserved = 0;
1010
1011		setvarbuf(buf, &l,
1012			(struct sadb_ext *)&m_key, sizeof(m_key),
1013			(caddr_t)p_key_enc, p_key_enc_len);
1014	}
1015
1016	/* set authentication algorithm, if present. */
1017	if (p_key_auth) {
1018		struct sadb_key m_key;
1019
1020		m_key.sadb_key_len =
1021			PFKEY_UNIT64(sizeof(m_key)
1022				   + PFKEY_ALIGN8(p_key_auth_len));
1023		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1024		m_key.sadb_key_bits = p_key_auth_len * 8;
1025		m_key.sadb_key_reserved = 0;
1026
1027		setvarbuf(buf, &l,
1028			(struct sadb_ext *)&m_key, sizeof(m_key),
1029			(caddr_t)p_key_auth, p_key_auth_len);
1030	}
1031
1032	/* set lifetime for HARD */
1033	if (p_lt_hard != 0) {
1034		struct sadb_lifetime m_lt;
1035		u_int slen = sizeof(struct sadb_lifetime);
1036
1037		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1038		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1039		m_lt.sadb_lifetime_allocations = 0;
1040		m_lt.sadb_lifetime_bytes = 0;
1041		m_lt.sadb_lifetime_addtime = p_lt_hard;
1042		m_lt.sadb_lifetime_usetime = 0;
1043
1044		memcpy(buf + l, &m_lt, slen);
1045		l += len;
1046	}
1047
1048	/* set lifetime for SOFT */
1049	if (p_lt_soft != 0) {
1050		struct sadb_lifetime m_lt;
1051		u_int slen = sizeof(struct sadb_lifetime);
1052
1053		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1054		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1055		m_lt.sadb_lifetime_allocations = 0;
1056		m_lt.sadb_lifetime_bytes = 0;
1057		m_lt.sadb_lifetime_addtime = p_lt_soft;
1058		m_lt.sadb_lifetime_usetime = 0;
1059
1060		memcpy(buf + l, &m_lt, slen);
1061		l += len;
1062	}
1063
1064	len = sizeof(struct sadb_sa);
1065	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1066	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1067	m_sa.sadb_sa_spi = htonl(p_spi);
1068	m_sa.sadb_sa_replay = p_replay;
1069	m_sa.sadb_sa_state = 0;
1070	m_sa.sadb_sa_auth = p_alg_auth;
1071	m_sa.sadb_sa_encrypt = p_alg_enc;
1072	m_sa.sadb_sa_flags = p_ext;
1073
1074	memcpy(buf + l, &m_sa, len);
1075	l += len;
1076
1077	len = sizeof(struct sadb_x_sa2);
1078	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1079	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1080	m_sa2.sadb_x_sa2_mode = p_mode;
1081	m_sa2.sadb_x_sa2_reqid = p_reqid;
1082
1083	memcpy(buf + l, &m_sa2, len);
1084	l += len;
1085
1086	l0 = l;
1087	n = 0;
1088
1089	/* do it for all src/dst pairs */
1090	for (s = srcs; s; s = s->ai_next) {
1091		for (d = dsts; d; d = d->ai_next) {
1092			/* rewind pointer */
1093			l = l0;
1094
1095			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1096				continue;
1097			switch (s->ai_addr->sa_family) {
1098			case AF_INET:
1099				plen = sizeof(struct in_addr) << 3;
1100				break;
1101#ifdef INET6
1102			case AF_INET6:
1103				plen = sizeof(struct in6_addr) << 3;
1104				break;
1105#endif
1106			default:
1107				continue;
1108			}
1109
1110			/* set src */
1111			sa = s->ai_addr;
1112			salen = s->ai_addr->sa_len;
1113			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1114			    PFKEY_ALIGN8(salen));
1115			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1116			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1117			m_addr.sadb_address_prefixlen = plen;
1118			m_addr.sadb_address_reserved = 0;
1119
1120			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1121			    sizeof(m_addr), (caddr_t)sa, salen);
1122
1123			/* set dst */
1124			sa = d->ai_addr;
1125			salen = d->ai_addr->sa_len;
1126			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1127			    PFKEY_ALIGN8(salen));
1128			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1129			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1130			m_addr.sadb_address_prefixlen = plen;
1131			m_addr.sadb_address_reserved = 0;
1132
1133			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1134			    sizeof(m_addr), (caddr_t)sa, salen);
1135
1136			msg->sadb_msg_len = PFKEY_UNIT64(l);
1137
1138			sendkeymsg(buf, l);
1139
1140			n++;
1141		}
1142	}
1143
1144	if (n == 0)
1145		return -1;
1146	else
1147		return 0;
1148}
1149
1150static struct addrinfo *
1151parse_addr(host, port)
1152	char *host;
1153	char *port;
1154{
1155	struct addrinfo hints, *res = NULL;
1156	int error;
1157
1158	memset(&hints, 0, sizeof(hints));
1159	hints.ai_family = p_aifamily;
1160	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1161	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1162	hints.ai_flags = p_aiflags;
1163	error = getaddrinfo(host, port, &hints, &res);
1164	if (error != 0) {
1165		yyerror(gai_strerror(error));
1166		return NULL;
1167	}
1168	return res;
1169}
1170
1171static int
1172fix_portstr(spec, sport, dport)
1173	vchar_t *spec, *sport, *dport;
1174{
1175	char *p, *p2;
1176	u_int l;
1177
1178	l = 0;
1179	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1180		;
1181	if (*p == '\0') {
1182		p2 = "0";
1183	} else {
1184		if (*p == ',') {
1185			*p = '\0';
1186			p2 = ++p;
1187		}
1188		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1189			;
1190		if (*p != '\0' || *p2 == '\0') {
1191			yyerror("invalid an upper layer protocol spec");
1192			return -1;
1193		}
1194	}
1195
1196	sport->buf = strdup(spec->buf);
1197	if (!sport->buf) {
1198		yyerror("insufficient memory");
1199		return -1;
1200	}
1201	sport->len = strlen(sport->buf);
1202	dport->buf = strdup(p2);
1203	if (!dport->buf) {
1204		yyerror("insufficient memory");
1205		return -1;
1206	}
1207	dport->len = strlen(dport->buf);
1208
1209	return 0;
1210}
1211
1212static int
1213setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1214	char *buf;
1215	int *off;
1216	struct sadb_ext *ebuf;
1217	int elen;
1218	caddr_t vbuf;
1219	int vlen;
1220{
1221	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1222	memcpy(buf + *off, (caddr_t)ebuf, elen);
1223	memcpy(buf + *off + elen, vbuf, vlen);
1224	(*off) += PFKEY_ALIGN8(elen + vlen);
1225
1226	return 0;
1227}
1228
1229void
1230parse_init()
1231{
1232	p_spi = 0;
1233
1234	p_ext = SADB_X_EXT_CYCSEQ;
1235	p_alg_enc = SADB_EALG_NONE;
1236	p_alg_auth = SADB_AALG_NONE;
1237	p_mode = IPSEC_MODE_ANY;
1238	p_reqid = 0;
1239	p_replay = 0;
1240	p_key_enc_len = p_key_auth_len = 0;
1241	p_key_enc = p_key_auth = 0;
1242	p_lt_hard = p_lt_soft = 0;
1243
1244	p_aiflags = 0;
1245	p_aifamily = PF_UNSPEC;
1246
1247	return;
1248}
1249
1250void
1251free_buffer()
1252{
1253	/* we got tons of memory leaks in the parser anyways, leave them */
1254
1255	return;
1256}
1257