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