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