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