Initial import from FreeBSD RELENG_4:
[dragonfly.git] / usr.sbin / setkey / parse.y
1 /*      $FreeBSD: src/usr.sbin/setkey/parse.y,v 1.1.2.2 2001/07/03 11:02:17 ume Exp $   */
2 /*      $KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 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 <netkey/key_var.h>
42 #include <netinet6/ipsec.h>
43 #include <arpa/inet.h>
44
45 #include <string.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <netdb.h>
49 #include <ctype.h>
50 #include <errno.h>
51
52 #include "libpfkey.h"
53 #include "vchar.h"
54
55 #define ATOX(c) \
56   (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
57
58 u_int p_type;
59 u_int32_t p_spi;
60 int p_no_spi;
61 struct sockaddr *p_src, *p_dst;
62 u_int p_prefs, p_prefd, p_upper;
63 u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
64 u_int32_t p_reqid;
65 u_int p_key_enc_len, p_key_auth_len;
66 caddr_t p_key_enc, p_key_auth;
67 time_t p_lt_hard, p_lt_soft;
68
69 u_int p_policy_len;
70 char *p_policy;
71
72 /* temporary buffer */
73 static struct sockaddr *pp_addr;
74 static u_int pp_prefix;
75 static u_int pp_port;
76 static caddr_t pp_key;
77
78 extern u_char m_buf[BUFSIZ];
79 extern int m_len;
80 extern char cmdarg[8192];
81 extern int f_debug;
82
83 static struct addrinfo *parse_addr __P((char *, char *, int));
84 static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
85 void parse_init __P((void));
86 void free_buffer __P((void));
87
88 extern int setkeymsg __P((void));
89 extern int sendkeymsg __P((void));
90
91 extern int yylex __P((void));
92 extern void yyfatal __P((const char *));
93 extern void yyerror __P((const char *));
94 %}
95
96 %union {
97         unsigned long num;
98         vchar_t val;
99 }
100
101 %token EOT
102 %token ADD GET DELETE FLUSH DUMP
103 %token ADDRESS PREFIX PORT PORTANY
104 %token UP_PROTO PR_ESP PR_AH PR_IPCOMP
105 %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
106 %token F_MODE MODE F_REQID
107 %token F_EXT EXTENSION NOCYCLICSEQ
108 %token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
109 %token F_LIFETIME_HARD F_LIFETIME_SOFT
110 %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
111         /* SPD management */
112 %token SPDADD SPDDELETE SPDDUMP SPDFLUSH
113 %token F_POLICY PL_REQUESTS
114
115 %type <num> PORT PREFIX EXTENSION MODE
116 %type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP
117 %type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
118 %type <num> DECSTRING
119 %type <val> ADDRESS PL_REQUESTS
120 %type <val> key_string policy_requests
121 %type <val> QUOTEDSTRING HEXSTRING STRING
122
123 %%
124 commands
125         :       /*NOTHING*/
126         |       commands command
127                 {
128                         if (f_debug) {
129                                 printf("cmdarg:\n%s\n", cmdarg);
130                         } else {
131                                 setkeymsg();
132                                 sendkeymsg();
133                         }
134                         free_buffer();
135                         parse_init();
136                 }
137         ;
138
139 command
140         :       add_command
141         |       get_command
142         |       delete_command
143         |       deleteall_command
144         |       flush_command
145         |       dump_command
146         |       spdadd_command
147         |       spddelete_command
148         |       spddump_command
149         |       spdflush_command
150         ;
151         /* commands concerned with management, there is in tail of this file. */
152
153         /* add command */
154 add_command
155         :       ADD { p_type = SADB_ADD; }
156                 sa_selector_spec extension_spec algorithm_spec EOT
157         ;
158
159         /* delete */
160 delete_command
161         :       DELETE { p_type = SADB_DELETE; }
162                 sa_selector_spec extension_spec
163                 {
164                         if (p_mode != IPSEC_MODE_ANY)
165                                 yyerror("WARNING: mode is obsoleted.");
166                 }
167                 EOT
168         ;
169
170         /* deleteall command */
171 deleteall_command
172         :       DELETEALL { p_type = SADB_DELETE; }
173                 ipaddress { p_src = pp_addr; }
174                 ipaddress { p_dst = pp_addr; }
175                 protocol_spec 
176                 { p_no_spi = 1; }
177                 EOT
178         ;
179
180         /* get command */
181 get_command
182         :       GET { p_type = SADB_GET; }
183                 sa_selector_spec extension_spec
184                 {
185                         if (p_mode != IPSEC_MODE_ANY)
186                                 yyerror("WARNING: mode is obsoleted.");
187                 }
188                 EOT
189         ;
190
191         /* flush */
192 flush_command
193         :       FLUSH { p_type = SADB_FLUSH; }
194                 protocol_spec EOT
195         ;
196
197         /* dump */
198 dump_command
199         :       DUMP { p_type = SADB_DUMP; }
200                 protocol_spec EOT
201         ;
202
203         /* sa_selector_spec */
204 sa_selector_spec
205         :       ipaddress { p_src = pp_addr; }
206                 ipaddress { p_dst = pp_addr; }
207                 protocol_spec spi
208         ;
209
210 protocol_spec
211         :       /*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
212         |       PR_ESP
213                 {
214                         p_satype = SADB_SATYPE_ESP;
215                         if ($1 == 1)
216                                 p_ext |= SADB_X_EXT_OLD;
217                         else
218                                 p_ext &= ~SADB_X_EXT_OLD;
219                 }
220         |       PR_AH
221                 {
222                         p_satype = SADB_SATYPE_AH;
223                         if ($1 == 1)
224                                 p_ext |= SADB_X_EXT_OLD;
225                         else
226                                 p_ext &= ~SADB_X_EXT_OLD;
227                 }
228         |       PR_IPCOMP
229                 {
230                         p_satype = SADB_X_SATYPE_IPCOMP;
231                 }
232         ;
233         
234 spi
235         :       DECSTRING { p_spi = $1; }
236         |       HEXSTRING
237                 {
238                         caddr_t bp;
239                         caddr_t yp = $1.buf;
240                         char buf0[4], buf[4];
241                         int i, j;
242
243                         /* sanity check */
244                         if ($1.len > 4) {
245                                 yyerror("SPI too big.");
246                                 free($1.buf);
247                                 return -1;
248                         }
249
250                         bp = buf0;
251                         while (*yp) {
252                                 *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
253                                 yp += 2, bp++;
254                         }
255
256                         /* initialize */
257                         for (i = 0; i < 4; i++) buf[i] = 0;
258
259                         for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
260                                 buf[i] = buf0[j];
261
262                         /* XXX: endian */
263                         p_spi = ntohl(*(u_int32_t *)buf);
264
265                         free($1.buf);
266                 }
267         ;
268
269 algorithm_spec
270         :       esp_spec
271         |       ah_spec
272         |       ipcomp_spec
273         ;
274
275 esp_spec
276         :       F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
277         |       F_ENC enc_alg enc_key
278         ;
279
280 ah_spec
281         :       F_AUTH auth_alg auth_key
282         ;
283
284 ipcomp_spec
285         :       F_COMP ALG_COMP { p_alg_enc = $2; }
286         |       F_COMP ALG_COMP { p_alg_enc = $2; }
287                 F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
288         ;
289
290 enc_alg
291         :       ALG_ENC { p_alg_enc = $1; }
292         |       ALG_ENC_DESDERIV
293                 {
294                         p_alg_enc = $1;
295                         if (p_ext & SADB_X_EXT_OLD) {
296                                 yyerror("algorithm mismatched.");
297                                 return -1;
298                         }
299                         p_ext |= SADB_X_EXT_DERIV;
300                 }
301         |       ALG_ENC_DES32IV
302                 {
303                         p_alg_enc = $1;
304                         if (!(p_ext & SADB_X_EXT_OLD)) {
305                                 yyerror("algorithm mismatched.");
306                                 return -1;
307                         }
308                         p_ext |= SADB_X_EXT_IV4B;
309                 }
310         ;
311
312 enc_key
313         :       /*NOTHING*/
314                 {
315                         if (p_alg_enc != SADB_EALG_NULL) {
316                                 yyerror("no key found.");
317                                 return -1;
318                         }
319                 }
320         |       key_string
321                 {
322                         p_key_enc_len = $1.len;
323                         p_key_enc = pp_key;
324
325                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
326                                         p_alg_enc,
327                                         PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
328                                 yyerror(ipsec_strerror());
329                                 return -1;
330                         }
331                 }
332         ;
333
334 auth_alg
335         :       ALG_AUTH { p_alg_auth = $1; }
336         ;
337
338 auth_key
339         :       /*NOTHING*/
340                 {
341                         if (p_alg_auth != SADB_X_AALG_NULL) {
342                                 yyerror("no key found.");
343                                 return -1;
344                         }
345                 }
346         |       key_string
347                 {
348                         p_key_auth_len = $1.len;
349                         p_key_auth = pp_key;
350
351                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
352                                         p_alg_auth,
353                                         PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
354                                 yyerror(ipsec_strerror());
355                                 return -1;
356                         }
357                 }
358         ;
359
360 key_string
361         :       QUOTEDSTRING
362                 {
363                         pp_key = $1.buf;
364                         /* free pp_key later */
365                 }
366         |       HEXSTRING
367                 {
368                         caddr_t bp;
369                         caddr_t yp = $1.buf;
370
371                         if ((pp_key = malloc($1.len)) == 0) {
372                                 free($1.buf);
373                                 yyerror("not enough core");
374                                 return -1;
375                         }
376                         memset(pp_key, 0, $1.len);
377
378                         bp = pp_key;
379                         while (*yp) {
380                                 *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
381                                 yp += 2, bp++;
382                         }
383
384                         free($1.buf);
385                 }
386         ;
387
388 extension_spec
389         :       /*NOTHING*/
390         |       extension_spec extension
391         ;
392
393 extension
394         :       F_EXT EXTENSION { p_ext |= $2; }
395         |       F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
396         |       F_MODE MODE { p_mode = $2; }
397         |       F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
398         |       F_REQID DECSTRING { p_reqid = $2; }
399         |       F_REPLAY DECSTRING
400                 {
401                         if (p_ext & SADB_X_EXT_OLD) {
402                                 yyerror("replay prevention "
403                                         "only use on new spec.");
404                                 return -1;
405                         }
406                         p_replay = $2;
407                 }
408         |       F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
409         |       F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
410         ;
411
412         /* definition about command for SPD management */
413         /* spdadd */
414 spdadd_command
415         :       SPDADD
416                 {
417                         p_type = SADB_X_SPDADD;
418                         p_satype = SADB_SATYPE_UNSPEC;
419                 }
420                 sp_selector_spec policy_spec EOT
421         ;
422
423 spddelete_command:
424                 SPDDELETE
425                 {
426                         p_type = SADB_X_SPDDELETE;
427                         p_satype = SADB_SATYPE_UNSPEC;
428                 }
429                 sp_selector_spec policy_spec EOT
430         ;
431
432 spddump_command:
433                 SPDDUMP
434                 {
435                         p_type = SADB_X_SPDDUMP;
436                         p_satype = SADB_SATYPE_UNSPEC;
437                 }
438                 EOT
439         ;
440
441 spdflush_command:
442                 SPDFLUSH
443                 {
444                         p_type = SADB_X_SPDFLUSH;
445                         p_satype = SADB_SATYPE_UNSPEC;
446                 }
447                 EOT
448         ;
449
450         /* sp_selector_spec */
451 sp_selector_spec
452         :       ipaddress { p_src = pp_addr; }
453                 prefix { p_prefs = pp_prefix; }
454                 port
455                 {
456                         switch (p_src->sa_family) {
457                         case AF_INET:
458                                 ((struct sockaddr_in *)p_src)->sin_port =
459                                     htons(pp_port);
460                                 break;
461 #ifdef INET6
462                         case AF_INET6:
463                                 ((struct sockaddr_in6 *)p_src)->sin6_port =
464                                     htons(pp_port);
465                                 break;
466 #endif
467                         default:
468                                 exit(1); /*XXX*/
469                         }
470                 }
471                 ipaddress { p_dst = pp_addr; }
472                 prefix { p_prefd = pp_prefix; }
473                 port
474                 {
475                         switch (p_dst->sa_family) {
476                         case AF_INET:
477                                 ((struct sockaddr_in *)p_dst)->sin_port =
478                                     htons(pp_port);
479                                 break;
480 #ifdef INET6
481                         case AF_INET6:
482                                 ((struct sockaddr_in6 *)p_dst)->sin6_port =
483                                     htons(pp_port);
484                                 break;
485 #endif
486                         default:
487                                 exit(1); /*XXX*/
488                         }
489                 }
490                 upper_spec
491                 {
492                         /* XXX is it something userland should check? */
493 #if 0
494                         switch (p_upper) {
495                         case IPPROTO_ICMP:
496                         case IPPROTO_ICMPV6:
497                                 if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
498                                  || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
499                                         yyerror("port number must be \"any\".");
500                                         return -1;
501                                 }
502                                 if ((pp_addr->sa_family == AF_INET6
503                                   && p_upper == IPPROTO_ICMP)
504                                  || (pp_addr->sa_family == AF_INET
505                                   && p_upper == IPPROTO_ICMPV6)) {
506                                         yyerror("upper layer protocol "
507                                                 "mismatched.\n");
508                                         return -1;
509                                 }
510                                 break;
511                         default:
512                                 break;
513                         }
514 #endif
515                 }
516         ;
517
518 ipaddress
519         :       ADDRESS
520                 {
521                         struct addrinfo *res;
522
523                         res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
524                         if (res == NULL) {
525                                 free($1.buf);
526                                 return -1;
527                         }
528                         pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
529                         if (!pp_addr) {
530                                 yyerror("not enough core");
531                                 goto end;
532                         }
533
534                         memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
535                     end:
536                         freeaddrinfo(res);
537                         free($1.buf);
538                 }
539         ;
540
541 prefix
542         :       /*NOTHING*/ { pp_prefix = ~0; }
543         |       PREFIX { pp_prefix = $1; }
544         ;
545
546 port
547         :       /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
548         |       PORT { pp_port = $1; }
549         |       PORTANY { pp_port = IPSEC_PORT_ANY; }
550         ;
551
552 upper_spec
553         :       DECSTRING { p_upper = $1; }
554         |       UP_PROTO { p_upper = $1; }
555         |       ANY { p_upper = IPSEC_ULPROTO_ANY; }
556         |       STRING
557                 {
558                         struct protoent *ent;
559
560                         ent = getprotobyname($1.buf);
561                         if (ent)
562                                 p_upper = ent->p_proto;
563                         else {
564                                 if (strcmp("icmp6", $1.buf) == 0) {
565                                         p_upper = IPPROTO_ICMPV6;
566                                 } else if(strcmp("ip4", $1.buf) == 0) {
567                                         p_upper = IPPROTO_IPV4;
568                                 } else {
569                                         yyerror("invalid upper layer protocol");
570                                         free($1.buf);
571                                         return -1;
572                                 }
573                         }
574                         free($1.buf);
575                 }
576         ;
577
578 policy_spec
579         :       F_POLICY policy_requests
580                 {
581                         p_policy = ipsec_set_policy($2.buf, $2.len);
582                         if (p_policy == NULL) {
583                                 free($2.buf);
584                                 p_policy = NULL;
585                                 yyerror(ipsec_strerror());
586                                 return -1;
587                         }
588
589                         p_policy_len = ipsec_get_policylen(p_policy);
590
591                         free($2.buf);
592                 }
593         ;
594
595 policy_requests
596         :       PL_REQUESTS { $$ = $1; }
597         ;
598
599 %%
600
601 int
602 setkeymsg()
603 {
604         struct sadb_msg m_msg;
605
606         m_msg.sadb_msg_version = PF_KEY_V2;
607         m_msg.sadb_msg_type = p_type;
608         m_msg.sadb_msg_errno = 0;
609         m_msg.sadb_msg_satype = p_satype;
610         m_msg.sadb_msg_reserved = 0;
611         m_msg.sadb_msg_seq = 0;
612         m_msg.sadb_msg_pid = getpid();
613
614         m_len = sizeof(struct sadb_msg);
615         memcpy(m_buf, &m_msg, m_len);
616
617         switch (p_type) {
618         case SADB_FLUSH:
619         case SADB_DUMP:
620                 break;
621
622         case SADB_ADD:
623                 /* set encryption algorithm, if present. */
624                 if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
625                         struct sadb_key m_key;
626
627                         m_key.sadb_key_len =
628                                 PFKEY_UNIT64(sizeof(m_key)
629                                            + PFKEY_ALIGN8(p_key_enc_len));
630                         m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
631                         m_key.sadb_key_bits = p_key_enc_len * 8;
632                         m_key.sadb_key_reserved = 0;
633
634                         setvarbuf(&m_len,
635                                 (struct sadb_ext *)&m_key, sizeof(m_key),
636                                 (caddr_t)p_key_enc, p_key_enc_len);
637                 }
638
639                 /* set authentication algorithm, if present. */
640                 if (p_alg_auth != SADB_AALG_NONE) {
641                         struct sadb_key m_key;
642
643                         m_key.sadb_key_len =
644                                 PFKEY_UNIT64(sizeof(m_key)
645                                            + PFKEY_ALIGN8(p_key_auth_len));
646                         m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
647                         m_key.sadb_key_bits = p_key_auth_len * 8;
648                         m_key.sadb_key_reserved = 0;
649
650                         setvarbuf(&m_len,
651                                 (struct sadb_ext *)&m_key, sizeof(m_key),
652                                 (caddr_t)p_key_auth, p_key_auth_len);
653                 }
654
655                 /* set lifetime for HARD */
656                 if (p_lt_hard != 0) {
657                         struct sadb_lifetime m_lt;
658                         u_int len = sizeof(struct sadb_lifetime);
659
660                         m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
661                         m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
662                         m_lt.sadb_lifetime_allocations = 0;
663                         m_lt.sadb_lifetime_bytes = 0;
664                         m_lt.sadb_lifetime_addtime = p_lt_hard;
665                         m_lt.sadb_lifetime_usetime = 0;
666
667                         memcpy(m_buf + m_len, &m_lt, len);
668                         m_len += len;
669                 }
670
671                 /* set lifetime for SOFT */
672                 if (p_lt_soft != 0) {
673                         struct sadb_lifetime m_lt;
674                         u_int len = sizeof(struct sadb_lifetime);
675
676                         m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
677                         m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
678                         m_lt.sadb_lifetime_allocations = 0;
679                         m_lt.sadb_lifetime_bytes = 0;
680                         m_lt.sadb_lifetime_addtime = p_lt_soft;
681                         m_lt.sadb_lifetime_usetime = 0;
682
683                         memcpy(m_buf + m_len, &m_lt, len);
684                         m_len += len;
685                 }
686                 /* FALLTHROUGH */
687
688         case SADB_DELETE:
689         case SADB_GET:
690             {
691                 struct sadb_sa m_sa;
692                 struct sadb_x_sa2 m_sa2;
693                 struct sadb_address m_addr;
694                 u_int len;
695
696                 if (p_no_spi == 0) {
697                         len = sizeof(struct sadb_sa);
698                         m_sa.sadb_sa_len = PFKEY_UNIT64(len);
699                         m_sa.sadb_sa_exttype = SADB_EXT_SA;
700                         m_sa.sadb_sa_spi = htonl(p_spi);
701                         m_sa.sadb_sa_replay = p_replay;
702                         m_sa.sadb_sa_state = 0;
703                         m_sa.sadb_sa_auth = p_alg_auth;
704                         m_sa.sadb_sa_encrypt = p_alg_enc;
705                         m_sa.sadb_sa_flags = p_ext;
706
707                         memcpy(m_buf + m_len, &m_sa, len);
708                         m_len += len;
709
710                         len = sizeof(struct sadb_x_sa2);
711                         m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
712                         m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
713                         m_sa2.sadb_x_sa2_mode = p_mode;
714                         m_sa2.sadb_x_sa2_reqid = p_reqid;
715
716                         memcpy(m_buf + m_len, &m_sa2, len);
717                         m_len += len;
718                 }
719
720                 /* set src */
721                 m_addr.sadb_address_len =
722                         PFKEY_UNIT64(sizeof(m_addr)
723                                    + PFKEY_ALIGN8(p_src->sa_len));
724                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
725                 m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
726                 switch (p_src->sa_family) {
727                 case AF_INET:
728                         m_addr.sadb_address_prefixlen =
729                             sizeof(struct in_addr) << 3;
730                         break;
731 #ifdef INET6
732                 case AF_INET6:
733                         m_addr.sadb_address_prefixlen =
734                             sizeof(struct in6_addr) << 3;
735                         break;
736 #endif
737                 default:
738                         yyerror("unsupported address family");
739                         exit(1);        /*XXX*/
740                 }
741                 m_addr.sadb_address_reserved = 0;
742
743                 setvarbuf(&m_len,
744                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
745                         (caddr_t)p_src, p_src->sa_len);
746
747                 /* set dst */
748                 m_addr.sadb_address_len =
749                         PFKEY_UNIT64(sizeof(m_addr)
750                                    + PFKEY_ALIGN8(p_dst->sa_len));
751                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
752                 m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
753                 switch (p_dst->sa_family) {
754                 case AF_INET:
755                         m_addr.sadb_address_prefixlen =
756                             sizeof(struct in_addr) << 3;
757                         break;
758 #ifdef INET6
759                 case AF_INET6:
760                         m_addr.sadb_address_prefixlen =
761                             sizeof(struct in6_addr) << 3;
762                         break;
763 #endif
764                 default:
765                         yyerror("unsupported address family");
766                         exit(1);        /*XXX*/
767                 }
768                 m_addr.sadb_address_reserved = 0;
769
770                 setvarbuf(&m_len,
771                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
772                         (caddr_t)p_dst, p_dst->sa_len);
773             }
774                 break;
775
776         /* for SPD management */
777         case SADB_X_SPDFLUSH:
778         case SADB_X_SPDDUMP:
779                 break;
780
781         case SADB_X_SPDADD:
782         case SADB_X_SPDDELETE:
783             {
784                 struct sadb_address m_addr;
785                 u_int8_t plen;
786
787                 memcpy(m_buf + m_len, p_policy, p_policy_len);
788                 m_len += p_policy_len;
789                 free(p_policy);
790                 p_policy = NULL;
791
792                 /* set src */
793                 m_addr.sadb_address_len =
794                         PFKEY_UNIT64(sizeof(m_addr)
795                                    + PFKEY_ALIGN8(p_src->sa_len));
796                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
797                 m_addr.sadb_address_proto = p_upper;
798                 switch (p_src->sa_family) {
799                 case AF_INET:
800                         plen = sizeof(struct in_addr) << 3;
801                         break;
802 #ifdef INET6
803                 case AF_INET6:
804                         plen = sizeof(struct in6_addr) << 3;
805                         break;
806 #endif
807                 default:
808                         yyerror("unsupported address family");
809                         exit(1);        /*XXX*/
810                 }
811                 m_addr.sadb_address_prefixlen =
812                     (p_prefs != ~0 ? p_prefs : plen);
813                 m_addr.sadb_address_reserved = 0;
814
815                 setvarbuf(&m_len,
816                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
817                         (caddr_t)p_src, p_src->sa_len);
818
819                 /* set dst */
820                 m_addr.sadb_address_len =
821                         PFKEY_UNIT64(sizeof(m_addr)
822                                    + PFKEY_ALIGN8(p_dst->sa_len));
823                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
824                 m_addr.sadb_address_proto = p_upper;
825                 switch (p_dst->sa_family) {
826                 case AF_INET:
827                         plen = sizeof(struct in_addr) << 3;
828                         break;
829 #ifdef INET6
830                 case AF_INET6:
831                         plen = sizeof(struct in6_addr) << 3;
832                         break;
833 #endif
834                 default:
835                         yyerror("unsupported address family");
836                         exit(1);        /*XXX*/
837                 }
838                 m_addr.sadb_address_prefixlen =
839                     (p_prefd != ~0 ? p_prefd : plen);
840                 m_addr.sadb_address_reserved = 0;
841
842                 setvarbuf(&m_len,
843                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
844                         (caddr_t)p_dst, p_dst->sa_len);
845             }
846                 break;
847         }
848
849         ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
850
851         return 0;
852 }
853
854 static struct addrinfo *
855 parse_addr(host, port, flag)
856         char *host;
857         char *port;
858         int flag;
859 {
860         struct addrinfo hints, *res = NULL;
861         int error;
862
863         memset(&hints, 0, sizeof(hints));
864         hints.ai_family = PF_UNSPEC;
865         hints.ai_socktype = SOCK_DGRAM;
866         hints.ai_flags = flag;
867         error = getaddrinfo(host, port, &hints, &res);
868         if (error != 0) {
869                 yyerror(gai_strerror(error));
870                 return NULL;
871         }
872         if (res->ai_next != NULL) {
873                 yyerror(gai_strerror(error));
874         }
875         return res;
876 }
877
878 static int
879 setvarbuf(off, ebuf, elen, vbuf, vlen)
880         caddr_t vbuf;
881         struct sadb_ext *ebuf;
882         int *off, elen, vlen;
883 {
884         memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
885         memcpy(m_buf + *off, (caddr_t)ebuf, elen);
886         memcpy(m_buf + *off + elen, vbuf, vlen);
887         (*off) += PFKEY_ALIGN8(elen + vlen);
888
889         return 0;
890 }
891
892 void
893 parse_init()
894 {
895         p_type = 0;
896         p_spi = 0;
897         p_no_spi = 0;
898
899         p_src = 0, p_dst = 0;
900         pp_prefix = p_prefs = p_prefd = ~0;
901         pp_port = IPSEC_PORT_ANY;
902         p_upper = 0;
903
904         p_satype = 0;
905         p_ext = SADB_X_EXT_CYCSEQ;
906         p_alg_enc = SADB_EALG_NONE;
907         p_alg_auth = SADB_AALG_NONE;
908         p_mode = IPSEC_MODE_ANY;
909         p_reqid = 0;
910         p_replay = 0;
911         p_key_enc_len = p_key_auth_len = 0;
912         p_key_enc = p_key_auth = 0;
913         p_lt_hard = p_lt_soft = 0;
914
915         p_policy_len = 0;
916         p_policy = NULL;
917
918         memset(cmdarg, 0, sizeof(cmdarg));
919
920         return;
921 }
922
923 void
924 free_buffer()
925 {
926         if (p_src) free(p_src);
927         if (p_dst) free(p_dst);
928         if (p_key_enc) free(p_key_enc);
929         if (p_key_auth) free(p_key_auth);
930
931         return;
932 }
933