parse.y revision 171135
1/*	$FreeBSD: head/sbin/setkey/parse.y 171135 2007-07-01 12:08:08Z gnn $	*/
2/*	$KAME: parse.y,v 1.83 2004/05/18 08:48:23 sakane 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 <netipsec/key_var.h>
42#include <netipsec/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			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
327			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
328				yyerror(ipsec_strerror());
329				return -1;
330			}
331		}
332	|	ALG_ENC key_string {
333			if ($1 < 0) {
334				yyerror("unsupported algorithm");
335				return -1;
336			}
337			p_alg_enc = $1;
338
339			p_key_enc_len = $2.len;
340			p_key_enc = $2.buf;
341			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
342			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
343				yyerror(ipsec_strerror());
344				return -1;
345			}
346		}
347	|	ALG_ENC_OLD {
348			if ($1 < 0) {
349				yyerror("unsupported algorithm");
350				return -1;
351			}
352			yyerror("WARNING: obsolete algorithm");
353			p_alg_enc = $1;
354
355			p_key_enc_len = 0;
356			p_key_enc = NULL;
357			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
358			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
359				yyerror(ipsec_strerror());
360				return -1;
361			}
362		}
363	|	ALG_ENC_DESDERIV key_string
364		{
365			if ($1 < 0) {
366				yyerror("unsupported algorithm");
367				return -1;
368			}
369			p_alg_enc = $1;
370			if (p_ext & SADB_X_EXT_OLD) {
371				yyerror("algorithm mismatched");
372				return -1;
373			}
374			p_ext |= SADB_X_EXT_DERIV;
375
376			p_key_enc_len = $2.len;
377			p_key_enc = $2.buf;
378			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
379			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
380				yyerror(ipsec_strerror());
381				return -1;
382			}
383		}
384	|	ALG_ENC_DES32IV key_string
385		{
386			if ($1 < 0) {
387				yyerror("unsupported algorithm");
388				return -1;
389			}
390			p_alg_enc = $1;
391			if (!(p_ext & SADB_X_EXT_OLD)) {
392				yyerror("algorithm mismatched");
393				return -1;
394			}
395			p_ext |= SADB_X_EXT_IV4B;
396
397			p_key_enc_len = $2.len;
398			p_key_enc = $2.buf;
399			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
400			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
401				yyerror(ipsec_strerror());
402				return -1;
403			}
404		}
405	;
406
407auth_alg
408	:	ALG_AUTH key_string {
409			if ($1 < 0) {
410				yyerror("unsupported algorithm");
411				return -1;
412			}
413			p_alg_auth = $1;
414
415			p_key_auth_len = $2.len;
416			p_key_auth = $2.buf;
417
418			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
419				if ((p_key_auth_len < 1) || (p_key_auth_len >
420				    80))
421					return -1;
422			} else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
423			    p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
424				yyerror(ipsec_strerror());
425				return -1;
426			}
427		}
428	|	ALG_AUTH_NOKEY {
429			if ($1 < 0) {
430				yyerror("unsupported algorithm");
431				return -1;
432			}
433			p_alg_auth = $1;
434
435			p_key_auth_len = 0;
436			p_key_auth = NULL;
437		}
438	;
439
440key_string
441	:	QUOTEDSTRING
442		{
443			$$ = $1;
444		}
445	|	HEXSTRING
446		{
447			caddr_t pp_key;
448			caddr_t bp;
449			caddr_t yp = $1.buf;
450			int l;
451
452			l = strlen(yp) % 2 + strlen(yp) / 2;
453			if ((pp_key = malloc(l)) == 0) {
454				yyerror("not enough core");
455				return -1;
456			}
457			memset(pp_key, 0, l);
458
459			bp = pp_key;
460			if (strlen(yp) % 2) {
461				*bp = ATOX(yp[0]);
462				yp++, bp++;
463			}
464			while (*yp) {
465				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
466				yp += 2, bp++;
467			}
468
469			$$.len = l;
470			$$.buf = pp_key;
471		}
472	;
473
474extension_spec
475	:	/*NOTHING*/
476	|	extension_spec extension
477	;
478
479extension
480	:	F_EXT EXTENSION { p_ext |= $2; }
481	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
482	|	F_MODE MODE { p_mode = $2; }
483	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
484	|	F_REQID DECSTRING { p_reqid = $2; }
485	|	F_REPLAY DECSTRING
486		{
487			if ((p_ext & SADB_X_EXT_OLD) != 0) {
488				yyerror("replay prevention cannot be used with "
489				    "ah/esp-old");
490				return -1;
491			}
492			p_replay = $2;
493		}
494	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
495	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
496	;
497
498	/* definition about command for SPD management */
499	/* spdadd */
500spdadd_command
501	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
502		{
503			int status;
504			struct addrinfo *src, *dst;
505
506			/* fixed port fields if ulp is icmpv6 */
507			if ($10.buf != NULL) {
508				if ($9 != IPPROTO_ICMPV6)
509					return -1;
510				free($5.buf);
511				free($8.buf);
512				if (fix_portstr(&$10, &$5, &$8))
513					return -1;
514			}
515
516			src = parse_addr($3.buf, $5.buf);
517			dst = parse_addr($6.buf, $8.buf);
518			if (!src || !dst) {
519				/* yyerror is already called */
520				return -1;
521			}
522			if (src->ai_next || dst->ai_next) {
523				yyerror("multiple address specified");
524				freeaddrinfo(src);
525				freeaddrinfo(dst);
526				return -1;
527			}
528
529			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
530			    src, $4, dst, $7);
531			freeaddrinfo(src);
532			freeaddrinfo(dst);
533			if (status < 0)
534				return -1;
535		}
536	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
537		{
538			return -1;
539		}
540	;
541
542spddelete_command
543	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
544		{
545			int status;
546			struct addrinfo *src, *dst;
547
548			/* fixed port fields if ulp is icmpv6 */
549			if ($10.buf != NULL) {
550				if ($9 != IPPROTO_ICMPV6)
551					return -1;
552				free($5.buf);
553				free($8.buf);
554				if (fix_portstr(&$10, &$5, &$8))
555					return -1;
556			}
557
558			src = parse_addr($3.buf, $5.buf);
559			dst = parse_addr($6.buf, $8.buf);
560			if (!src || !dst) {
561				/* yyerror is already called */
562				return -1;
563			}
564			if (src->ai_next || dst->ai_next) {
565				yyerror("multiple address specified");
566				freeaddrinfo(src);
567				freeaddrinfo(dst);
568				return -1;
569			}
570
571			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
572			    src, $4, dst, $7);
573			freeaddrinfo(src);
574			freeaddrinfo(dst);
575			if (status < 0)
576				return -1;
577		}
578	;
579
580spddump_command:
581		SPDDUMP EOT
582		{
583			struct sadb_msg msg;
584			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
585			    sizeof(msg));
586			sendkeymsg((char *)&msg, sizeof(msg));
587		}
588	;
589
590spdflush_command:
591		SPDFLUSH EOT
592		{
593			struct sadb_msg msg;
594			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
595			    sizeof(msg));
596			sendkeymsg((char *)&msg, sizeof(msg));
597		}
598	;
599
600ipaddropts
601	:	/* nothing */
602	|	ipaddropts ipaddropt
603	;
604
605ipaddropt
606	:	F_AIFLAGS
607		{
608			char *p;
609
610			for (p = $1.buf + 1; *p; p++)
611				switch (*p) {
612				case '4':
613					p_aifamily = AF_INET;
614					break;
615#ifdef INET6
616				case '6':
617					p_aifamily = AF_INET6;
618					break;
619#endif
620				case 'n':
621					p_aiflags = AI_NUMERICHOST;
622					break;
623				default:
624					yyerror("invalid flag");
625					return -1;
626				}
627		}
628	;
629
630ipaddr
631	:	STRING
632		{
633			$$ = parse_addr($1.buf, NULL);
634			if ($$ == NULL) {
635				/* yyerror already called by parse_addr */
636				return -1;
637			}
638		}
639	;
640
641prefix
642	:	/*NOTHING*/ { $$ = -1; }
643	|	SLASH DECSTRING { $$ = $2; }
644	;
645
646portstr
647	:	/*NOTHING*/
648		{
649			$$.buf = strdup("0");
650			if (!$$.buf) {
651				yyerror("insufficient memory");
652				return -1;
653			}
654			$$.len = strlen($$.buf);
655		}
656	|	BLCL ANY ELCL
657		{
658			$$.buf = strdup("0");
659			if (!$$.buf) {
660				yyerror("insufficient memory");
661				return -1;
662			}
663			$$.len = strlen($$.buf);
664		}
665	|	BLCL DECSTRING ELCL
666		{
667			char buf[20];
668			snprintf(buf, sizeof(buf), "%lu", $2);
669			$$.buf = strdup(buf);
670			if (!$$.buf) {
671				yyerror("insufficient memory");
672				return -1;
673			}
674			$$.len = strlen($$.buf);
675		}
676	|	BLCL STRING ELCL
677		{
678			$$ = $2;
679		}
680	;
681
682upper_spec
683	:	DECSTRING { $$ = $1; }
684	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
685	|	PR_TCP { $$ = IPPROTO_TCP; }
686	|	STRING
687		{
688			struct protoent *ent;
689
690			ent = getprotobyname($1.buf);
691			if (ent)
692				$$ = ent->p_proto;
693			else {
694				if (strcmp("icmp6", $1.buf) == 0) {
695					$$ = IPPROTO_ICMPV6;
696				} else if(strcmp("ip4", $1.buf) == 0) {
697					$$ = IPPROTO_IPV4;
698				} else {
699					yyerror("invalid upper layer protocol");
700					return -1;
701				}
702			}
703			endprotoent();
704		}
705	;
706
707upper_misc_spec
708	:	/*NOTHING*/
709		{
710			$$.buf = NULL;
711			$$.len = 0;
712		}
713	|	STRING
714		{
715			$$.buf = strdup($1.buf);
716			if (!$$.buf) {
717				yyerror("insufficient memory");
718				return -1;
719			}
720			$$.len = strlen($$.buf);
721		}
722	;
723
724policy_spec
725	:	F_POLICY policy_requests
726		{
727			char *policy;
728
729			policy = ipsec_set_policy($2.buf, $2.len);
730			if (policy == NULL) {
731				yyerror(ipsec_strerror());
732				return -1;
733			}
734
735			$$.buf = policy;
736			$$.len = ipsec_get_policylen(policy);
737		}
738	;
739
740policy_requests
741	:	PL_REQUESTS { $$ = $1; }
742	;
743
744%%
745
746int
747setkeymsg0(msg, type, satype, l)
748	struct sadb_msg *msg;
749	unsigned int type;
750	unsigned int satype;
751	size_t l;
752{
753
754	msg->sadb_msg_version = PF_KEY_V2;
755	msg->sadb_msg_type = type;
756	msg->sadb_msg_errno = 0;
757	msg->sadb_msg_satype = satype;
758	msg->sadb_msg_reserved = 0;
759	msg->sadb_msg_seq = 0;
760	msg->sadb_msg_pid = getpid();
761	msg->sadb_msg_len = PFKEY_UNIT64(l);
762	return 0;
763}
764
765/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
766static int
767setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
768	unsigned int type;
769	unsigned int upper;
770	vchar_t *policy;
771	struct addrinfo *srcs;
772	int splen;
773	struct addrinfo *dsts;
774	int dplen;
775{
776	struct sadb_msg *msg;
777	char buf[BUFSIZ];
778	int l, l0;
779	struct sadb_address m_addr;
780	struct addrinfo *s, *d;
781	int n;
782	int plen;
783	struct sockaddr *sa;
784	int salen;
785
786	msg = (struct sadb_msg *)buf;
787
788	if (!srcs || !dsts)
789		return -1;
790
791	/* fix up length afterwards */
792	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
793	l = sizeof(struct sadb_msg);
794
795	memcpy(buf + l, policy->buf, policy->len);
796	l += policy->len;
797
798	l0 = l;
799	n = 0;
800
801	/* do it for all src/dst pairs */
802	for (s = srcs; s; s = s->ai_next) {
803		for (d = dsts; d; d = d->ai_next) {
804			/* rewind pointer */
805			l = l0;
806
807			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
808				continue;
809			switch (s->ai_addr->sa_family) {
810			case AF_INET:
811				plen = sizeof(struct in_addr) << 3;
812				break;
813#ifdef INET6
814			case AF_INET6:
815				plen = sizeof(struct in6_addr) << 3;
816				break;
817#endif
818			default:
819				continue;
820			}
821
822			/* set src */
823			sa = s->ai_addr;
824			salen = s->ai_addr->sa_len;
825			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
826			    PFKEY_ALIGN8(salen));
827			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
828			m_addr.sadb_address_proto = upper;
829			m_addr.sadb_address_prefixlen =
830			    (splen >= 0 ? splen : plen);
831			m_addr.sadb_address_reserved = 0;
832
833			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
834			    sizeof(m_addr), (caddr_t)sa, salen);
835
836			/* set dst */
837			sa = d->ai_addr;
838			salen = d->ai_addr->sa_len;
839			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
840			    PFKEY_ALIGN8(salen));
841			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
842			m_addr.sadb_address_proto = upper;
843			m_addr.sadb_address_prefixlen =
844			    (dplen >= 0 ? dplen : plen);
845			m_addr.sadb_address_reserved = 0;
846
847			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
848			    sizeof(m_addr), (caddr_t)sa, salen);
849
850			msg->sadb_msg_len = PFKEY_UNIT64(l);
851
852			sendkeymsg(buf, l);
853
854			n++;
855		}
856	}
857
858	if (n == 0)
859		return -1;
860	else
861		return 0;
862}
863
864/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
865static int
866setkeymsg_addr(type, satype, srcs, dsts, no_spi)
867	unsigned int type;
868	unsigned int satype;
869	struct addrinfo *srcs;
870	struct addrinfo *dsts;
871	int no_spi;
872{
873	struct sadb_msg *msg;
874	char buf[BUFSIZ];
875	int l, l0, len;
876	struct sadb_sa m_sa;
877	struct sadb_x_sa2 m_sa2;
878	struct sadb_address m_addr;
879	struct addrinfo *s, *d;
880	int n;
881	int plen;
882	struct sockaddr *sa;
883	int salen;
884
885	msg = (struct sadb_msg *)buf;
886
887	if (!srcs || !dsts)
888		return -1;
889
890	/* fix up length afterwards */
891	setkeymsg0(msg, type, satype, 0);
892	l = sizeof(struct sadb_msg);
893
894	if (!no_spi) {
895		len = sizeof(struct sadb_sa);
896		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
897		m_sa.sadb_sa_exttype = SADB_EXT_SA;
898		m_sa.sadb_sa_spi = htonl(p_spi);
899		m_sa.sadb_sa_replay = p_replay;
900		m_sa.sadb_sa_state = 0;
901		m_sa.sadb_sa_auth = p_alg_auth;
902		m_sa.sadb_sa_encrypt = p_alg_enc;
903		m_sa.sadb_sa_flags = p_ext;
904
905		memcpy(buf + l, &m_sa, len);
906		l += len;
907
908		len = sizeof(struct sadb_x_sa2);
909		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
910		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
911		m_sa2.sadb_x_sa2_mode = p_mode;
912		m_sa2.sadb_x_sa2_reqid = p_reqid;
913
914		memcpy(buf + l, &m_sa2, len);
915		l += len;
916	}
917
918	l0 = l;
919	n = 0;
920
921	/* do it for all src/dst pairs */
922	for (s = srcs; s; s = s->ai_next) {
923		for (d = dsts; d; d = d->ai_next) {
924			/* rewind pointer */
925			l = l0;
926
927			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
928				continue;
929			switch (s->ai_addr->sa_family) {
930			case AF_INET:
931				plen = sizeof(struct in_addr) << 3;
932				break;
933#ifdef INET6
934			case AF_INET6:
935				plen = sizeof(struct in6_addr) << 3;
936				break;
937#endif
938			default:
939				continue;
940			}
941
942			/* set src */
943			sa = s->ai_addr;
944			salen = s->ai_addr->sa_len;
945			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
946			    PFKEY_ALIGN8(salen));
947			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
948			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
949			m_addr.sadb_address_prefixlen = plen;
950			m_addr.sadb_address_reserved = 0;
951
952			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
953			    sizeof(m_addr), (caddr_t)sa, salen);
954
955			/* set dst */
956			sa = d->ai_addr;
957			salen = d->ai_addr->sa_len;
958			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
959			    PFKEY_ALIGN8(salen));
960			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
961			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
962			m_addr.sadb_address_prefixlen = plen;
963			m_addr.sadb_address_reserved = 0;
964
965			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
966			    sizeof(m_addr), (caddr_t)sa, salen);
967
968			msg->sadb_msg_len = PFKEY_UNIT64(l);
969
970			sendkeymsg(buf, l);
971
972			n++;
973		}
974	}
975
976	if (n == 0)
977		return -1;
978	else
979		return 0;
980}
981
982/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
983static int
984setkeymsg_add(type, satype, srcs, dsts)
985	unsigned int type;
986	unsigned int satype;
987	struct addrinfo *srcs;
988	struct addrinfo *dsts;
989{
990	struct sadb_msg *msg;
991	char buf[BUFSIZ];
992	int l, l0, len;
993	struct sadb_sa m_sa;
994	struct sadb_x_sa2 m_sa2;
995	struct sadb_address m_addr;
996	struct addrinfo *s, *d;
997	int n;
998	int plen;
999	struct sockaddr *sa;
1000	int salen;
1001
1002	msg = (struct sadb_msg *)buf;
1003
1004	if (!srcs || !dsts)
1005		return -1;
1006
1007	/* fix up length afterwards */
1008	setkeymsg0(msg, type, satype, 0);
1009	l = sizeof(struct sadb_msg);
1010
1011	/* set encryption algorithm, if present. */
1012	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1013		struct sadb_key m_key;
1014
1015		m_key.sadb_key_len =
1016			PFKEY_UNIT64(sizeof(m_key)
1017				   + PFKEY_ALIGN8(p_key_enc_len));
1018		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1019		m_key.sadb_key_bits = p_key_enc_len * 8;
1020		m_key.sadb_key_reserved = 0;
1021
1022		setvarbuf(buf, &l,
1023			(struct sadb_ext *)&m_key, sizeof(m_key),
1024			(caddr_t)p_key_enc, p_key_enc_len);
1025	}
1026
1027	/* set authentication algorithm, if present. */
1028	if (p_key_auth) {
1029		struct sadb_key m_key;
1030
1031		m_key.sadb_key_len =
1032			PFKEY_UNIT64(sizeof(m_key)
1033				   + PFKEY_ALIGN8(p_key_auth_len));
1034		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1035		m_key.sadb_key_bits = p_key_auth_len * 8;
1036		m_key.sadb_key_reserved = 0;
1037
1038		setvarbuf(buf, &l,
1039			(struct sadb_ext *)&m_key, sizeof(m_key),
1040			(caddr_t)p_key_auth, p_key_auth_len);
1041	}
1042
1043	/* set lifetime for HARD */
1044	if (p_lt_hard != 0) {
1045		struct sadb_lifetime m_lt;
1046		u_int slen = sizeof(struct sadb_lifetime);
1047
1048		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1049		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1050		m_lt.sadb_lifetime_allocations = 0;
1051		m_lt.sadb_lifetime_bytes = 0;
1052		m_lt.sadb_lifetime_addtime = p_lt_hard;
1053		m_lt.sadb_lifetime_usetime = 0;
1054
1055		memcpy(buf + l, &m_lt, slen);
1056		l += slen;
1057	}
1058
1059	/* set lifetime for SOFT */
1060	if (p_lt_soft != 0) {
1061		struct sadb_lifetime m_lt;
1062		u_int slen = sizeof(struct sadb_lifetime);
1063
1064		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1065		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1066		m_lt.sadb_lifetime_allocations = 0;
1067		m_lt.sadb_lifetime_bytes = 0;
1068		m_lt.sadb_lifetime_addtime = p_lt_soft;
1069		m_lt.sadb_lifetime_usetime = 0;
1070
1071		memcpy(buf + l, &m_lt, slen);
1072		l += slen;
1073	}
1074
1075	len = sizeof(struct sadb_sa);
1076	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1077	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1078	m_sa.sadb_sa_spi = htonl(p_spi);
1079	m_sa.sadb_sa_replay = p_replay;
1080	m_sa.sadb_sa_state = 0;
1081	m_sa.sadb_sa_auth = p_alg_auth;
1082	m_sa.sadb_sa_encrypt = p_alg_enc;
1083	m_sa.sadb_sa_flags = p_ext;
1084
1085	memcpy(buf + l, &m_sa, len);
1086	l += len;
1087
1088	len = sizeof(struct sadb_x_sa2);
1089	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1090	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1091	m_sa2.sadb_x_sa2_mode = p_mode;
1092	m_sa2.sadb_x_sa2_reqid = p_reqid;
1093
1094	memcpy(buf + l, &m_sa2, len);
1095	l += len;
1096
1097	l0 = l;
1098	n = 0;
1099
1100	/* do it for all src/dst pairs */
1101	for (s = srcs; s; s = s->ai_next) {
1102		for (d = dsts; d; d = d->ai_next) {
1103			/* rewind pointer */
1104			l = l0;
1105
1106			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1107				continue;
1108			switch (s->ai_addr->sa_family) {
1109			case AF_INET:
1110				plen = sizeof(struct in_addr) << 3;
1111				break;
1112#ifdef INET6
1113			case AF_INET6:
1114				plen = sizeof(struct in6_addr) << 3;
1115				break;
1116#endif
1117			default:
1118				continue;
1119			}
1120
1121			/* set src */
1122			sa = s->ai_addr;
1123			salen = s->ai_addr->sa_len;
1124			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1125			    PFKEY_ALIGN8(salen));
1126			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1127			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1128			m_addr.sadb_address_prefixlen = plen;
1129			m_addr.sadb_address_reserved = 0;
1130
1131			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1132			    sizeof(m_addr), (caddr_t)sa, salen);
1133
1134			/* set dst */
1135			sa = d->ai_addr;
1136			salen = d->ai_addr->sa_len;
1137			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1138			    PFKEY_ALIGN8(salen));
1139			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1140			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1141			m_addr.sadb_address_prefixlen = plen;
1142			m_addr.sadb_address_reserved = 0;
1143
1144			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1145			    sizeof(m_addr), (caddr_t)sa, salen);
1146
1147			msg->sadb_msg_len = PFKEY_UNIT64(l);
1148
1149			sendkeymsg(buf, l);
1150
1151			n++;
1152		}
1153	}
1154
1155	if (n == 0)
1156		return -1;
1157	else
1158		return 0;
1159}
1160
1161static struct addrinfo *
1162parse_addr(host, port)
1163	char *host;
1164	char *port;
1165{
1166	struct addrinfo hints, *res = NULL;
1167	int error;
1168
1169	memset(&hints, 0, sizeof(hints));
1170	hints.ai_family = p_aifamily;
1171	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1172	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1173	hints.ai_flags = p_aiflags;
1174	error = getaddrinfo(host, port, &hints, &res);
1175	if (error != 0) {
1176		yyerror(gai_strerror(error));
1177		return NULL;
1178	}
1179	return res;
1180}
1181
1182static int
1183fix_portstr(spec, sport, dport)
1184	vchar_t *spec, *sport, *dport;
1185{
1186	char *p, *p2;
1187	u_int l;
1188
1189	l = 0;
1190	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1191		;
1192	if (*p == '\0') {
1193		p2 = "0";
1194	} else {
1195		if (*p == ',') {
1196			*p = '\0';
1197			p2 = ++p;
1198		}
1199		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1200			;
1201		if (*p != '\0' || *p2 == '\0') {
1202			yyerror("invalid an upper layer protocol spec");
1203			return -1;
1204		}
1205	}
1206
1207	sport->buf = strdup(spec->buf);
1208	if (!sport->buf) {
1209		yyerror("insufficient memory");
1210		return -1;
1211	}
1212	sport->len = strlen(sport->buf);
1213	dport->buf = strdup(p2);
1214	if (!dport->buf) {
1215		yyerror("insufficient memory");
1216		return -1;
1217	}
1218	dport->len = strlen(dport->buf);
1219
1220	return 0;
1221}
1222
1223static int
1224setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1225	char *buf;
1226	int *off;
1227	struct sadb_ext *ebuf;
1228	int elen;
1229	caddr_t vbuf;
1230	int vlen;
1231{
1232	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1233	memcpy(buf + *off, (caddr_t)ebuf, elen);
1234	memcpy(buf + *off + elen, vbuf, vlen);
1235	(*off) += PFKEY_ALIGN8(elen + vlen);
1236
1237	return 0;
1238}
1239
1240void
1241parse_init()
1242{
1243	p_spi = 0;
1244
1245	p_ext = SADB_X_EXT_CYCSEQ;
1246	p_alg_enc = SADB_EALG_NONE;
1247	p_alg_auth = SADB_AALG_NONE;
1248	p_mode = IPSEC_MODE_ANY;
1249	p_reqid = 0;
1250	p_replay = 0;
1251	p_key_enc_len = p_key_auth_len = 0;
1252	p_key_enc = p_key_auth = 0;
1253	p_lt_hard = p_lt_soft = 0;
1254
1255	p_aiflags = 0;
1256	p_aifamily = PF_UNSPEC;
1257
1258	return;
1259}
1260
1261void
1262free_buffer()
1263{
1264	/* we got tons of memory leaks in the parser anyways, leave them */
1265
1266	return;
1267}
1268