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