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