Initial import of binutils 2.22 on the new vendor branch
[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 PR_TCP
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 PR_TCP
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         |       PR_TCP
234                 {
235                         p_satype = SADB_X_SATYPE_TCPSIGNATURE;
236                 }
237         ;
238         
239 spi
240         :       DECSTRING { p_spi = $1; }
241         |       HEXSTRING
242                 {
243                         caddr_t bp;
244                         caddr_t yp = $1.buf;
245                         char buf0[4], buf[4];
246                         int i, j;
247
248                         /* sanity check */
249                         if ($1.len > 4) {
250                                 yyerror("SPI too big.");
251                                 free($1.buf);
252                                 return -1;
253                         }
254
255                         bp = buf0;
256                         while (*yp) {
257                                 *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
258                                 yp += 2, bp++;
259                         }
260
261                         /* initialize */
262                         for (i = 0; i < 4; i++) buf[i] = 0;
263
264                         for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
265                                 buf[i] = buf0[j];
266
267                         /* XXX: endian */
268                         p_spi = ntohl(*(u_int32_t *)buf);
269
270                         free($1.buf);
271                 }
272         ;
273
274 algorithm_spec
275         :       esp_spec
276         |       ah_spec
277         |       ipcomp_spec
278         ;
279
280 esp_spec
281         :       F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
282         |       F_ENC enc_alg enc_key
283         ;
284
285 ah_spec
286         :       F_AUTH auth_alg auth_key
287         ;
288
289 ipcomp_spec
290         :       F_COMP ALG_COMP { p_alg_enc = $2; }
291         |       F_COMP ALG_COMP { p_alg_enc = $2; }
292                 F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
293         ;
294
295 enc_alg
296         :       ALG_ENC { p_alg_enc = $1; }
297         |       ALG_ENC_DESDERIV
298                 {
299                         p_alg_enc = $1;
300                         if (p_ext & SADB_X_EXT_OLD) {
301                                 yyerror("algorithm mismatched.");
302                                 return -1;
303                         }
304                         p_ext |= SADB_X_EXT_DERIV;
305                 }
306         |       ALG_ENC_DES32IV
307                 {
308                         p_alg_enc = $1;
309                         if (!(p_ext & SADB_X_EXT_OLD)) {
310                                 yyerror("algorithm mismatched.");
311                                 return -1;
312                         }
313                         p_ext |= SADB_X_EXT_IV4B;
314                 }
315         ;
316
317 enc_key
318         :       /*NOTHING*/
319                 {
320                         if (p_alg_enc != SADB_EALG_NULL) {
321                                 yyerror("no key found.");
322                                 return -1;
323                         }
324                 }
325         |       key_string
326                 {
327                         p_key_enc_len = $1.len;
328                         p_key_enc = pp_key;
329
330                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
331                                         p_alg_enc,
332                                         PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
333                                 yyerror(ipsec_strerror());
334                                 return -1;
335                         }
336                 }
337         ;
338
339 auth_alg
340         :       ALG_AUTH { p_alg_auth = $1; }
341         ;
342
343 auth_key
344         :       /*NOTHING*/
345                 {
346                         if (p_alg_auth != SADB_X_AALG_NULL) {
347                                 yyerror("no key found.");
348                                 return -1;
349                         }
350                 }
351         |       key_string
352                 {
353                         p_key_auth_len = $1.len;
354                         p_key_auth = pp_key;
355
356                         if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
357                                 if ((p_key_auth_len < 1) || (p_key_auth_len >
358                                         80))
359                                         return -1;
360                         } else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
361                                         p_alg_auth,
362                                         PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
363                                 yyerror(ipsec_strerror());
364                                 return -1;
365                         }
366                 }
367         ;
368
369 key_string
370         :       QUOTEDSTRING
371                 {
372                         pp_key = $1.buf;
373                         /* free pp_key later */
374                 }
375         |       HEXSTRING
376                 {
377                         caddr_t bp;
378                         caddr_t yp = $1.buf;
379
380                         if ((pp_key = malloc($1.len)) == 0) {
381                                 free($1.buf);
382                                 yyerror("not enough core");
383                                 return -1;
384                         }
385                         memset(pp_key, 0, $1.len);
386
387                         bp = pp_key;
388                         while (*yp) {
389                                 *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
390                                 yp += 2, bp++;
391                         }
392
393                         free($1.buf);
394                 }
395         ;
396
397 extension_spec
398         :       /*NOTHING*/
399         |       extension_spec extension
400         ;
401
402 extension
403         :       F_EXT EXTENSION { p_ext |= $2; }
404         |       F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
405         |       F_MODE MODE { p_mode = $2; }
406         |       F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
407         |       F_REQID DECSTRING { p_reqid = $2; }
408         |       F_REPLAY DECSTRING
409                 {
410                         if (p_ext & SADB_X_EXT_OLD) {
411                                 yyerror("replay prevention "
412                                         "only use on new spec.");
413                                 return -1;
414                         }
415                         p_replay = $2;
416                 }
417         |       F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
418         |       F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
419         ;
420
421         /* definition about command for SPD management */
422         /* spdadd */
423 spdadd_command
424         :       SPDADD
425                 {
426                         p_type = SADB_X_SPDADD;
427                         p_satype = SADB_SATYPE_UNSPEC;
428                 }
429                 sp_selector_spec policy_spec EOT
430         ;
431
432 spddelete_command:
433                 SPDDELETE
434                 {
435                         p_type = SADB_X_SPDDELETE;
436                         p_satype = SADB_SATYPE_UNSPEC;
437                 }
438                 sp_selector_spec policy_spec EOT
439         ;
440
441 spddump_command:
442                 SPDDUMP
443                 {
444                         p_type = SADB_X_SPDDUMP;
445                         p_satype = SADB_SATYPE_UNSPEC;
446                 }
447                 EOT
448         ;
449
450 spdflush_command:
451                 SPDFLUSH
452                 {
453                         p_type = SADB_X_SPDFLUSH;
454                         p_satype = SADB_SATYPE_UNSPEC;
455                 }
456                 EOT
457         ;
458
459         /* sp_selector_spec */
460 sp_selector_spec
461         :       ipaddress { p_src = pp_addr; }
462                 prefix { p_prefs = pp_prefix; }
463                 port
464                 {
465                         switch (p_src->sa_family) {
466                         case AF_INET:
467                                 ((struct sockaddr_in *)p_src)->sin_port =
468                                     htons(pp_port);
469                                 break;
470 #ifdef INET6
471                         case AF_INET6:
472                                 ((struct sockaddr_in6 *)p_src)->sin6_port =
473                                     htons(pp_port);
474                                 break;
475 #endif
476                         default:
477                                 exit(1); /*XXX*/
478                         }
479                 }
480                 ipaddress { p_dst = pp_addr; }
481                 prefix { p_prefd = pp_prefix; }
482                 port
483                 {
484                         switch (p_dst->sa_family) {
485                         case AF_INET:
486                                 ((struct sockaddr_in *)p_dst)->sin_port =
487                                     htons(pp_port);
488                                 break;
489 #ifdef INET6
490                         case AF_INET6:
491                                 ((struct sockaddr_in6 *)p_dst)->sin6_port =
492                                     htons(pp_port);
493                                 break;
494 #endif
495                         default:
496                                 exit(1); /*XXX*/
497                         }
498                 }
499                 upper_spec
500                 {
501                         /* XXX is it something userland should check? */
502 #if 0
503                         switch (p_upper) {
504                         case IPPROTO_ICMP:
505                         case IPPROTO_ICMPV6:
506                                 if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
507                                  || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
508                                         yyerror("port number must be \"any\".");
509                                         return -1;
510                                 }
511                                 if ((pp_addr->sa_family == AF_INET6
512                                   && p_upper == IPPROTO_ICMP)
513                                  || (pp_addr->sa_family == AF_INET
514                                   && p_upper == IPPROTO_ICMPV6)) {
515                                         yyerror("upper layer protocol "
516                                                 "mismatched.\n");
517                                         return -1;
518                                 }
519                                 break;
520                         default:
521                                 break;
522                         }
523 #endif
524                 }
525         ;
526
527 ipaddress
528         :       ADDRESS
529                 {
530                         struct addrinfo *res;
531
532                         res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
533                         if (res == NULL) {
534                                 free($1.buf);
535                                 return -1;
536                         }
537                         pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
538                         if (!pp_addr) {
539                                 yyerror("not enough core");
540                                 goto end;
541                         }
542
543                         memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
544                     end:
545                         freeaddrinfo(res);
546                         free($1.buf);
547                 }
548         ;
549
550 prefix
551         :       /*NOTHING*/ { pp_prefix = ~0; }
552         |       PREFIX { pp_prefix = $1; }
553         ;
554
555 port
556         :       /*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
557         |       PORT { pp_port = $1; }
558         |       PORTANY { pp_port = IPSEC_PORT_ANY; }
559         ;
560
561 upper_spec
562         :       DECSTRING { p_upper = $1; }
563         |       UP_PROTO { p_upper = $1; }
564         |       ANY { p_upper = IPSEC_ULPROTO_ANY; }
565         |       STRING
566                 {
567                         struct protoent *ent;
568
569                         ent = getprotobyname($1.buf);
570                         if (ent)
571                                 p_upper = ent->p_proto;
572                         else {
573                                 if (strcmp("icmp6", $1.buf) == 0) {
574                                         p_upper = IPPROTO_ICMPV6;
575                                 } else if(strcmp("ip4", $1.buf) == 0) {
576                                         p_upper = IPPROTO_IPV4;
577                                 } else {
578                                         yyerror("invalid upper layer protocol");
579                                         free($1.buf);
580                                         return -1;
581                                 }
582                         }
583                         free($1.buf);
584                 }
585         ;
586
587 policy_spec
588         :       F_POLICY policy_requests
589                 {
590                         p_policy = ipsec_set_policy($2.buf, $2.len);
591                         if (p_policy == NULL) {
592                                 free($2.buf);
593                                 p_policy = NULL;
594                                 yyerror(ipsec_strerror());
595                                 return -1;
596                         }
597
598                         p_policy_len = ipsec_get_policylen(p_policy);
599
600                         free($2.buf);
601                 }
602         ;
603
604 policy_requests
605         :       PL_REQUESTS { $$ = $1; }
606         ;
607
608 %%
609
610 int
611 setkeymsg(void)
612 {
613         struct sadb_msg m_msg;
614
615         m_msg.sadb_msg_version = PF_KEY_V2;
616         m_msg.sadb_msg_type = p_type;
617         m_msg.sadb_msg_errno = 0;
618         m_msg.sadb_msg_satype = p_satype;
619         m_msg.sadb_msg_reserved = 0;
620         m_msg.sadb_msg_seq = 0;
621         m_msg.sadb_msg_pid = getpid();
622
623         m_len = sizeof(struct sadb_msg);
624         memcpy(m_buf, &m_msg, m_len);
625
626         switch (p_type) {
627         case SADB_FLUSH:
628         case SADB_DUMP:
629                 break;
630
631         case SADB_ADD:
632                 /* set encryption algorithm, if present. */
633                 if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
634                         struct sadb_key m_key;
635
636                         m_key.sadb_key_len =
637                                 PFKEY_UNIT64(sizeof(m_key)
638                                            + PFKEY_ALIGN8(p_key_enc_len));
639                         m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
640                         m_key.sadb_key_bits = p_key_enc_len * 8;
641                         m_key.sadb_key_reserved = 0;
642
643                         setvarbuf(&m_len,
644                                 (struct sadb_ext *)&m_key, sizeof(m_key),
645                                 (caddr_t)p_key_enc, p_key_enc_len);
646                 }
647
648                 /* set authentication algorithm, if present. */
649                 if (p_alg_auth != SADB_AALG_NONE) {
650                         struct sadb_key m_key;
651
652                         m_key.sadb_key_len =
653                                 PFKEY_UNIT64(sizeof(m_key)
654                                            + PFKEY_ALIGN8(p_key_auth_len));
655                         m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
656                         m_key.sadb_key_bits = p_key_auth_len * 8;
657                         m_key.sadb_key_reserved = 0;
658
659                         setvarbuf(&m_len,
660                                 (struct sadb_ext *)&m_key, sizeof(m_key),
661                                 (caddr_t)p_key_auth, p_key_auth_len);
662                 }
663
664                 /* set lifetime for HARD */
665                 if (p_lt_hard != 0) {
666                         struct sadb_lifetime m_lt;
667                         u_int len = sizeof(struct sadb_lifetime);
668
669                         m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
670                         m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
671                         m_lt.sadb_lifetime_allocations = 0;
672                         m_lt.sadb_lifetime_bytes = 0;
673                         m_lt.sadb_lifetime_addtime = p_lt_hard;
674                         m_lt.sadb_lifetime_usetime = 0;
675
676                         memcpy(m_buf + m_len, &m_lt, len);
677                         m_len += len;
678                 }
679
680                 /* set lifetime for SOFT */
681                 if (p_lt_soft != 0) {
682                         struct sadb_lifetime m_lt;
683                         u_int len = sizeof(struct sadb_lifetime);
684
685                         m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
686                         m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
687                         m_lt.sadb_lifetime_allocations = 0;
688                         m_lt.sadb_lifetime_bytes = 0;
689                         m_lt.sadb_lifetime_addtime = p_lt_soft;
690                         m_lt.sadb_lifetime_usetime = 0;
691
692                         memcpy(m_buf + m_len, &m_lt, len);
693                         m_len += len;
694                 }
695                 /* FALLTHROUGH */
696
697         case SADB_DELETE:
698         case SADB_GET:
699             {
700                 struct sadb_sa m_sa;
701                 struct sadb_x_sa2 m_sa2;
702                 struct sadb_address m_addr;
703                 u_int len;
704
705                 if (p_no_spi == 0) {
706                         len = sizeof(struct sadb_sa);
707                         m_sa.sadb_sa_len = PFKEY_UNIT64(len);
708                         m_sa.sadb_sa_exttype = SADB_EXT_SA;
709                         m_sa.sadb_sa_spi = htonl(p_spi);
710                         m_sa.sadb_sa_replay = p_replay;
711                         m_sa.sadb_sa_state = 0;
712                         m_sa.sadb_sa_auth = p_alg_auth;
713                         m_sa.sadb_sa_encrypt = p_alg_enc;
714                         m_sa.sadb_sa_flags = p_ext;
715
716                         memcpy(m_buf + m_len, &m_sa, len);
717                         m_len += len;
718
719                         len = sizeof(struct sadb_x_sa2);
720                         m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
721                         m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
722                         m_sa2.sadb_x_sa2_mode = p_mode;
723                         m_sa2.sadb_x_sa2_reqid = p_reqid;
724
725                         memcpy(m_buf + m_len, &m_sa2, len);
726                         m_len += len;
727                 }
728
729                 /* set src */
730                 m_addr.sadb_address_len =
731                         PFKEY_UNIT64(sizeof(m_addr)
732                                    + PFKEY_ALIGN8(p_src->sa_len));
733                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
734                 m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
735                 switch (p_src->sa_family) {
736                 case AF_INET:
737                         m_addr.sadb_address_prefixlen =
738                             sizeof(struct in_addr) << 3;
739                         break;
740 #ifdef INET6
741                 case AF_INET6:
742                         m_addr.sadb_address_prefixlen =
743                             sizeof(struct in6_addr) << 3;
744                         break;
745 #endif
746                 default:
747                         yyerror("unsupported address family");
748                         exit(1);        /*XXX*/
749                 }
750                 m_addr.sadb_address_reserved = 0;
751
752                 setvarbuf(&m_len,
753                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
754                         (caddr_t)p_src, p_src->sa_len);
755
756                 /* set dst */
757                 m_addr.sadb_address_len =
758                         PFKEY_UNIT64(sizeof(m_addr)
759                                    + PFKEY_ALIGN8(p_dst->sa_len));
760                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
761                 m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
762                 switch (p_dst->sa_family) {
763                 case AF_INET:
764                         m_addr.sadb_address_prefixlen =
765                             sizeof(struct in_addr) << 3;
766                         break;
767 #ifdef INET6
768                 case AF_INET6:
769                         m_addr.sadb_address_prefixlen =
770                             sizeof(struct in6_addr) << 3;
771                         break;
772 #endif
773                 default:
774                         yyerror("unsupported address family");
775                         exit(1);        /*XXX*/
776                 }
777                 m_addr.sadb_address_reserved = 0;
778
779                 setvarbuf(&m_len,
780                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
781                         (caddr_t)p_dst, p_dst->sa_len);
782             }
783                 break;
784
785         /* for SPD management */
786         case SADB_X_SPDFLUSH:
787         case SADB_X_SPDDUMP:
788                 break;
789
790         case SADB_X_SPDADD:
791         case SADB_X_SPDDELETE:
792             {
793                 struct sadb_address m_addr;
794                 u_int8_t plen;
795
796                 memcpy(m_buf + m_len, p_policy, p_policy_len);
797                 m_len += p_policy_len;
798                 free(p_policy);
799                 p_policy = NULL;
800
801                 /* set src */
802                 m_addr.sadb_address_len =
803                         PFKEY_UNIT64(sizeof(m_addr)
804                                    + PFKEY_ALIGN8(p_src->sa_len));
805                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
806                 m_addr.sadb_address_proto = p_upper;
807                 switch (p_src->sa_family) {
808                 case AF_INET:
809                         plen = sizeof(struct in_addr) << 3;
810                         break;
811 #ifdef INET6
812                 case AF_INET6:
813                         plen = sizeof(struct in6_addr) << 3;
814                         break;
815 #endif
816                 default:
817                         yyerror("unsupported address family");
818                         exit(1);        /*XXX*/
819                 }
820                 m_addr.sadb_address_prefixlen =
821                     (p_prefs != ~0 ? p_prefs : plen);
822                 m_addr.sadb_address_reserved = 0;
823
824                 setvarbuf(&m_len,
825                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
826                         (caddr_t)p_src, p_src->sa_len);
827
828                 /* set dst */
829                 m_addr.sadb_address_len =
830                         PFKEY_UNIT64(sizeof(m_addr)
831                                    + PFKEY_ALIGN8(p_dst->sa_len));
832                 m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
833                 m_addr.sadb_address_proto = p_upper;
834                 switch (p_dst->sa_family) {
835                 case AF_INET:
836                         plen = sizeof(struct in_addr) << 3;
837                         break;
838 #ifdef INET6
839                 case AF_INET6:
840                         plen = sizeof(struct in6_addr) << 3;
841                         break;
842 #endif
843                 default:
844                         yyerror("unsupported address family");
845                         exit(1);        /*XXX*/
846                 }
847                 m_addr.sadb_address_prefixlen =
848                     (p_prefd != ~0 ? p_prefd : plen);
849                 m_addr.sadb_address_reserved = 0;
850
851                 setvarbuf(&m_len,
852                         (struct sadb_ext *)&m_addr, sizeof(m_addr),
853                         (caddr_t)p_dst, p_dst->sa_len);
854             }
855                 break;
856         }
857
858         ((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
859
860         return 0;
861 }
862
863 static struct addrinfo *
864 parse_addr(char *host, char *port, int flag)
865 {
866         struct addrinfo hints, *res = NULL;
867         int error;
868
869         memset(&hints, 0, sizeof(hints));
870         hints.ai_family = PF_UNSPEC;
871         hints.ai_socktype = SOCK_DGRAM;
872         hints.ai_flags = flag;
873         error = getaddrinfo(host, port, &hints, &res);
874         if (error != 0) {
875                 yyerror(gai_strerror(error));
876                 return NULL;
877         }
878         if (res->ai_next != NULL) {
879                 yyerror(gai_strerror(error));
880         }
881         return res;
882 }
883
884 static int
885 setvarbuf(int *off, struct sadb_ext *ebuf, int elen, caddr_t vbuf, int vlen)
886 {
887         memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
888         memcpy(m_buf + *off, (caddr_t)ebuf, elen);
889         memcpy(m_buf + *off + elen, vbuf, vlen);
890         (*off) += PFKEY_ALIGN8(elen + vlen);
891
892         return 0;
893 }
894
895 void
896 parse_init(void)
897 {
898         p_type = 0;
899         p_spi = 0;
900         p_no_spi = 0;
901
902         p_src = 0, p_dst = 0;
903         pp_prefix = p_prefs = p_prefd = ~0;
904         pp_port = IPSEC_PORT_ANY;
905         p_upper = 0;
906
907         p_satype = 0;
908         p_ext = SADB_X_EXT_CYCSEQ;
909         p_alg_enc = SADB_EALG_NONE;
910         p_alg_auth = SADB_AALG_NONE;
911         p_mode = IPSEC_MODE_ANY;
912         p_reqid = 0;
913         p_replay = 0;
914         p_key_enc_len = p_key_auth_len = 0;
915         p_key_enc = p_key_auth = 0;
916         p_lt_hard = p_lt_soft = 0;
917
918         p_policy_len = 0;
919         p_policy = NULL;
920
921         memset(cmdarg, 0, sizeof(cmdarg));
922
923         return;
924 }
925
926 void
927 free_buffer(void)
928 {
929         if (p_src) free(p_src);
930         if (p_dst) free(p_dst);
931         if (p_key_enc) free(p_key_enc);
932         if (p_key_auth) free(p_key_auth);
933
934         return;
935 }
936