]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sbin/setkey/parse.y
This commit was generated by cvs2svn to compensate for changes in r161653,
[FreeBSD/FreeBSD.git] / sbin / setkey / parse.y
1 /*      $FreeBSD$       */
2 /*      $KAME: parse.y,v 1.83 2004/05/18 08:48:23 sakane Exp $  */
3
4 /*
5  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 %{
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37
38 #include <net/route.h>
39 #include <netinet/in.h>
40 #include <net/pfkeyv2.h>
41 #include <netkey/key_var.h>
42 #include <netinet6/ipsec.h>
43 #include <arpa/inet.h>
44
45 #include <string.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <netdb.h>
49 #include <ctype.h>
50 #include <errno.h>
51
52 #include "libpfkey.h"
53 #include "vchar.h"
54
55 #define ATOX(c) \
56   (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10)))
57
58 u_int32_t p_spi;
59 u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
60 u_int32_t p_reqid;
61 u_int p_key_enc_len, p_key_auth_len;
62 caddr_t p_key_enc, p_key_auth;
63 time_t p_lt_hard, p_lt_soft;
64
65 static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
66
67 static struct addrinfo *parse_addr __P((char *, char *));
68 static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *));
69 static int setvarbuf __P((char *, int *, struct sadb_ext *, int, caddr_t, int));
70 void parse_init __P((void));
71 void free_buffer __P((void));
72
73 int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
74 static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
75         struct addrinfo *, int, struct addrinfo *, int));
76 static int setkeymsg_addr __P((unsigned int, unsigned int,
77         struct addrinfo *, struct addrinfo *, int));
78 static int setkeymsg_add __P((unsigned int, unsigned int,
79         struct addrinfo *, struct addrinfo *));
80 extern int setkeymsg __P((char *, size_t *));
81 extern int sendkeymsg __P((char *, size_t));
82
83 extern int yylex __P((void));
84 extern void yyfatal __P((const char *));
85 extern void yyerror __P((const char *));
86 %}
87
88 %union {
89         int num;
90         unsigned long ulnum;
91         vchar_t val;
92         struct addrinfo *res;
93 }
94
95 %token EOT SLASH BLCL ELCL
96 %token ADD GET DELETE DELETEALL FLUSH DUMP
97 %token PR_ESP PR_AH PR_IPCOMP PR_TCP
98 %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
99 %token F_MODE MODE F_REQID
100 %token F_EXT EXTENSION NOCYCLICSEQ
101 %token ALG_AUTH ALG_AUTH_NOKEY
102 %token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
103 %token ALG_COMP
104 %token F_LIFETIME_HARD F_LIFETIME_SOFT
105 %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
106         /* SPD management */
107 %token SPDADD SPDDELETE SPDDUMP SPDFLUSH
108 %token F_POLICY PL_REQUESTS
109 %token F_AIFLAGS
110 %token TAGGED
111
112 %type <num> prefix protocol_spec upper_spec
113 %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
114 %type <num> ALG_AUTH ALG_AUTH_NOKEY
115 %type <num> ALG_COMP
116 %type <num> PR_ESP PR_AH PR_IPCOMP PR_TCP
117 %type <num> EXTENSION MODE
118 %type <ulnum> DECSTRING
119 %type <val> PL_REQUESTS portstr key_string
120 %type <val> policy_requests
121 %type <val> QUOTEDSTRING HEXSTRING STRING
122 %type <val> F_AIFLAGS
123 %type <val> upper_misc_spec policy_spec
124 %type <res> ipaddr
125
126 %%
127 commands
128         :       /*NOTHING*/
129         |       commands command
130                 {
131                         free_buffer();
132                         parse_init();
133                 }
134         ;
135
136 command
137         :       add_command
138         |       get_command
139         |       delete_command
140         |       deleteall_command
141         |       flush_command
142         |       dump_command
143         |       spdadd_command
144         |       spddelete_command
145         |       spddump_command
146         |       spdflush_command
147         ;
148         /* commands concerned with management, there is in tail of this file. */
149
150         /* add command */
151 add_command
152         :       ADD ipaddropts ipaddr ipaddr protocol_spec spi extension_spec algorithm_spec EOT
153                 {
154                         int status;
155
156                         status = setkeymsg_add(SADB_ADD, $5, $3, $4);
157                         if (status < 0)
158                                 return -1;
159                 }
160         ;
161
162         /* delete */
163 delete_command
164         :       DELETE ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
165                 {
166                         int status;
167
168                         if ($3->ai_next || $4->ai_next) {
169                                 yyerror("multiple address specified");
170                                 return -1;
171                         }
172                         if (p_mode != IPSEC_MODE_ANY)
173                                 yyerror("WARNING: mode is obsolete");
174
175                         status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
176                         if (status < 0)
177                                 return -1;
178                 }
179         ;
180
181         /* deleteall command */
182 deleteall_command
183         :       DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
184                 {
185                         int status;
186
187                         status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
188                         if (status < 0)
189                                 return -1;
190                 }
191         ;
192
193         /* get command */
194 get_command
195         :       GET ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
196                 {
197                         int status;
198
199                         if (p_mode != IPSEC_MODE_ANY)
200                                 yyerror("WARNING: mode is obsolete");
201
202                         status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
203                         if (status < 0)
204                                 return -1;
205                 }
206         ;
207
208         /* flush */
209 flush_command
210         :       FLUSH protocol_spec EOT
211                 {
212                         struct sadb_msg msg;
213                         setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
214                         sendkeymsg((char *)&msg, sizeof(msg));
215                 }
216         ;
217
218         /* dump */
219 dump_command
220         :       DUMP protocol_spec EOT
221                 {
222                         struct sadb_msg msg;
223                         setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
224                         sendkeymsg((char *)&msg, sizeof(msg));
225                 }
226         ;
227
228 protocol_spec
229         :       /*NOTHING*/
230                 {
231                         $$ = SADB_SATYPE_UNSPEC;
232                 }
233         |       PR_ESP
234                 {
235                         $$ = SADB_SATYPE_ESP;
236                         if ($1 == 1)
237                                 p_ext |= SADB_X_EXT_OLD;
238                         else
239                                 p_ext &= ~SADB_X_EXT_OLD;
240                 }
241         |       PR_AH
242                 {
243                         $$ = SADB_SATYPE_AH;
244                         if ($1 == 1)
245                                 p_ext |= SADB_X_EXT_OLD;
246                         else
247                                 p_ext &= ~SADB_X_EXT_OLD;
248                 }
249         |       PR_IPCOMP
250                 {
251                         $$ = SADB_X_SATYPE_IPCOMP;
252                 }
253         |       PR_TCP
254                 {
255                         $$ = SADB_X_SATYPE_TCPSIGNATURE;
256                 }
257         ;
258
259 spi
260         :       DECSTRING { p_spi = $1; }
261         |       HEXSTRING
262                 {
263                         char *ep;
264                         unsigned long v;
265
266                         ep = NULL;
267                         v = strtoul($1.buf, &ep, 16);
268                         if (!ep || *ep) {
269                                 yyerror("invalid SPI");
270                                 return -1;
271                         }
272                         if (v & ~0xffffffff) {
273                                 yyerror("SPI too big.");
274                                 return -1;
275                         }
276
277                         p_spi = v;
278                 }
279         ;
280
281 algorithm_spec
282         :       esp_spec
283         |       ah_spec
284         |       ipcomp_spec
285         ;
286
287 esp_spec
288         :       F_ENC enc_alg F_AUTH auth_alg
289         |       F_ENC enc_alg
290         ;
291
292 ah_spec
293         :       F_AUTH auth_alg
294         ;
295
296 ipcomp_spec
297         :       F_COMP ALG_COMP
298                 {
299                         if ($2 < 0) {
300                                 yyerror("unsupported algorithm");
301                                 return -1;
302                         }
303                         p_alg_enc = $2;
304                 }
305         |       F_COMP ALG_COMP F_RAWCPI
306                 {
307                         if ($2 < 0) {
308                                 yyerror("unsupported algorithm");
309                                 return -1;
310                         }
311                         p_alg_enc = $2;
312                         p_ext |= SADB_X_EXT_RAWCPI;
313                 }
314         ;
315
316 enc_alg
317         :       ALG_ENC_NOKEY {
318                         if ($1 < 0) {
319                                 yyerror("unsupported algorithm");
320                                 return -1;
321                         }
322                         p_alg_enc = $1;
323
324                         p_key_enc_len = 0;
325                         p_key_enc = NULL;
326                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
327                             p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
328                                 yyerror(ipsec_strerror());
329                                 return -1;
330                         }
331                 }
332         |       ALG_ENC key_string {
333                         if ($1 < 0) {
334                                 yyerror("unsupported algorithm");
335                                 return -1;
336                         }
337                         p_alg_enc = $1;
338
339                         p_key_enc_len = $2.len;
340                         p_key_enc = $2.buf;
341                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
342                             p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
343                                 yyerror(ipsec_strerror());
344                                 return -1;
345                         }
346                 }
347         |       ALG_ENC_OLD {
348                         if ($1 < 0) {
349                                 yyerror("unsupported algorithm");
350                                 return -1;
351                         }
352                         yyerror("WARNING: obsolete algorithm");
353                         p_alg_enc = $1;
354
355                         p_key_enc_len = 0;
356                         p_key_enc = NULL;
357                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
358                             p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
359                                 yyerror(ipsec_strerror());
360                                 return -1;
361                         }
362                 }
363         |       ALG_ENC_DESDERIV key_string
364                 {
365                         if ($1 < 0) {
366                                 yyerror("unsupported algorithm");
367                                 return -1;
368                         }
369                         p_alg_enc = $1;
370                         if (p_ext & SADB_X_EXT_OLD) {
371                                 yyerror("algorithm mismatched");
372                                 return -1;
373                         }
374                         p_ext |= SADB_X_EXT_DERIV;
375
376                         p_key_enc_len = $2.len;
377                         p_key_enc = $2.buf;
378                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
379                             p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
380                                 yyerror(ipsec_strerror());
381                                 return -1;
382                         }
383                 }
384         |       ALG_ENC_DES32IV key_string
385                 {
386                         if ($1 < 0) {
387                                 yyerror("unsupported algorithm");
388                                 return -1;
389                         }
390                         p_alg_enc = $1;
391                         if (!(p_ext & SADB_X_EXT_OLD)) {
392                                 yyerror("algorithm mismatched");
393                                 return -1;
394                         }
395                         p_ext |= SADB_X_EXT_IV4B;
396
397                         p_key_enc_len = $2.len;
398                         p_key_enc = $2.buf;
399                         if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
400                             p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
401                                 yyerror(ipsec_strerror());
402                                 return -1;
403                         }
404                 }
405         ;
406
407 auth_alg
408         :       ALG_AUTH key_string {
409                         if ($1 < 0) {
410                                 yyerror("unsupported algorithm");
411                                 return -1;
412                         }
413                         p_alg_auth = $1;
414
415                         p_key_auth_len = $2.len;
416                         p_key_auth = $2.buf;
417
418                         if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
419                                 if ((p_key_auth_len < 1) || (p_key_auth_len >
420                                     80))
421                                         return -1;
422                         } else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
423                             p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
424                                 yyerror(ipsec_strerror());
425                                 return -1;
426                         }
427                 }
428         |       ALG_AUTH_NOKEY {
429                         if ($1 < 0) {
430                                 yyerror("unsupported algorithm");
431                                 return -1;
432                         }
433                         p_alg_auth = $1;
434
435                         p_key_auth_len = 0;
436                         p_key_auth = NULL;
437                 }
438         ;
439
440 key_string
441         :       QUOTEDSTRING
442                 {
443                         $$ = $1;
444                 }
445         |       HEXSTRING
446                 {
447                         caddr_t pp_key;
448                         caddr_t bp;
449                         caddr_t yp = $1.buf;
450                         int l;
451
452                         l = strlen(yp) % 2 + strlen(yp) / 2;
453                         if ((pp_key = malloc(l)) == 0) {
454                                 yyerror("not enough core");
455                                 return -1;
456                         }
457                         memset(pp_key, 0, l);
458
459                         bp = pp_key;
460                         if (strlen(yp) % 2) {
461                                 *bp = ATOX(yp[0]);
462                                 yp++, bp++;
463                         }
464                         while (*yp) {
465                                 *bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
466                                 yp += 2, bp++;
467                         }
468
469                         $$.len = l;
470                         $$.buf = pp_key;
471                 }
472         ;
473
474 extension_spec
475         :       /*NOTHING*/
476         |       extension_spec extension
477         ;
478
479 extension
480         :       F_EXT EXTENSION { p_ext |= $2; }
481         |       F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
482         |       F_MODE MODE { p_mode = $2; }
483         |       F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
484         |       F_REQID DECSTRING { p_reqid = $2; }
485         |       F_REPLAY DECSTRING
486                 {
487                         if ((p_ext & SADB_X_EXT_OLD) != 0) {
488                                 yyerror("replay prevention cannot be used with "
489                                     "ah/esp-old");
490                                 return -1;
491                         }
492                         p_replay = $2;
493                 }
494         |       F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
495         |       F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
496         ;
497
498         /* definition about command for SPD management */
499         /* spdadd */
500 spdadd_command
501         :       SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
502                 {
503                         int status;
504                         struct addrinfo *src, *dst;
505
506                         /* fixed port fields if ulp is icmpv6 */
507                         if ($10.buf != NULL) {
508                                 if ($9 != IPPROTO_ICMPV6)
509                                         return -1;
510                                 free($5.buf);
511                                 free($8.buf);
512                                 if (fix_portstr(&$10, &$5, &$8))
513                                         return -1;
514                         }
515
516                         src = parse_addr($3.buf, $5.buf);
517                         dst = parse_addr($6.buf, $8.buf);
518                         if (!src || !dst) {
519                                 /* yyerror is already called */
520                                 return -1;
521                         }
522                         if (src->ai_next || dst->ai_next) {
523                                 yyerror("multiple address specified");
524                                 freeaddrinfo(src);
525                                 freeaddrinfo(dst);
526                                 return -1;
527                         }
528
529                         status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
530                             src, $4, dst, $7);
531                         freeaddrinfo(src);
532                         freeaddrinfo(dst);
533                         if (status < 0)
534                                 return -1;
535                 }
536         |       SPDADD TAGGED QUOTEDSTRING policy_spec EOT
537                 {
538                         return -1;
539                 }
540         ;
541
542 spddelete_command
543         :       SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
544                 {
545                         int status;
546                         struct addrinfo *src, *dst;
547
548                         /* fixed port fields if ulp is icmpv6 */
549                         if ($10.buf != NULL) {
550                                 if ($9 != IPPROTO_ICMPV6)
551                                         return -1;
552                                 free($5.buf);
553                                 free($8.buf);
554                                 if (fix_portstr(&$10, &$5, &$8))
555                                         return -1;
556                         }
557
558                         src = parse_addr($3.buf, $5.buf);
559                         dst = parse_addr($6.buf, $8.buf);
560                         if (!src || !dst) {
561                                 /* yyerror is already called */
562                                 return -1;
563                         }
564                         if (src->ai_next || dst->ai_next) {
565                                 yyerror("multiple address specified");
566                                 freeaddrinfo(src);
567                                 freeaddrinfo(dst);
568                                 return -1;
569                         }
570
571                         status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
572                             src, $4, dst, $7);
573                         freeaddrinfo(src);
574                         freeaddrinfo(dst);
575                         if (status < 0)
576                                 return -1;
577                 }
578         ;
579
580 spddump_command:
581                 SPDDUMP EOT
582                 {
583                         struct sadb_msg msg;
584                         setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
585                             sizeof(msg));
586                         sendkeymsg((char *)&msg, sizeof(msg));
587                 }
588         ;
589
590 spdflush_command:
591                 SPDFLUSH EOT
592                 {
593                         struct sadb_msg msg;
594                         setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
595                             sizeof(msg));
596                         sendkeymsg((char *)&msg, sizeof(msg));
597                 }
598         ;
599
600 ipaddropts
601         :       /* nothing */
602         |       ipaddropts ipaddropt
603         ;
604
605 ipaddropt
606         :       F_AIFLAGS
607                 {
608                         char *p;
609
610                         for (p = $1.buf + 1; *p; p++)
611                                 switch (*p) {
612                                 case '4':
613                                         p_aifamily = AF_INET;
614                                         break;
615 #ifdef INET6
616                                 case '6':
617                                         p_aifamily = AF_INET6;
618                                         break;
619 #endif
620                                 case 'n':
621                                         p_aiflags = AI_NUMERICHOST;
622                                         break;
623                                 default:
624                                         yyerror("invalid flag");
625                                         return -1;
626                                 }
627                 }
628         ;
629
630 ipaddr
631         :       STRING
632                 {
633                         $$ = parse_addr($1.buf, NULL);
634                         if ($$ == NULL) {
635                                 /* yyerror already called by parse_addr */
636                                 return -1;
637                         }
638                 }
639         ;
640
641 prefix
642         :       /*NOTHING*/ { $$ = -1; }
643         |       SLASH DECSTRING { $$ = $2; }
644         ;
645
646 portstr
647         :       /*NOTHING*/
648                 {
649                         $$.buf = strdup("0");
650                         if (!$$.buf) {
651                                 yyerror("insufficient memory");
652                                 return -1;
653                         }
654                         $$.len = strlen($$.buf);
655                 }
656         |       BLCL ANY ELCL
657                 {
658                         $$.buf = strdup("0");
659                         if (!$$.buf) {
660                                 yyerror("insufficient memory");
661                                 return -1;
662                         }
663                         $$.len = strlen($$.buf);
664                 }
665         |       BLCL DECSTRING ELCL
666                 {
667                         char buf[20];
668                         snprintf(buf, sizeof(buf), "%lu", $2);
669                         $$.buf = strdup(buf);
670                         if (!$$.buf) {
671                                 yyerror("insufficient memory");
672                                 return -1;
673                         }
674                         $$.len = strlen($$.buf);
675                 }
676         |       BLCL STRING ELCL
677                 {
678                         $$ = $2;
679                 }
680         ;
681
682 upper_spec
683         :       DECSTRING { $$ = $1; }
684         |       ANY { $$ = IPSEC_ULPROTO_ANY; }
685         |       PR_TCP { $$ = IPPROTO_TCP; }
686         |       STRING
687                 {
688                         struct protoent *ent;
689
690                         ent = getprotobyname($1.buf);
691                         if (ent)
692                                 $$ = ent->p_proto;
693                         else {
694                                 if (strcmp("icmp6", $1.buf) == 0) {
695                                         $$ = IPPROTO_ICMPV6;
696                                 } else if(strcmp("ip4", $1.buf) == 0) {
697                                         $$ = IPPROTO_IPV4;
698                                 } else {
699                                         yyerror("invalid upper layer protocol");
700                                         return -1;
701                                 }
702                         }
703                         endprotoent();
704                 }
705         ;
706
707 upper_misc_spec
708         :       /*NOTHING*/
709                 {
710                         $$.buf = NULL;
711                         $$.len = 0;
712                 }
713         |       STRING
714                 {
715                         $$.buf = strdup($1.buf);
716                         if (!$$.buf) {
717                                 yyerror("insufficient memory");
718                                 return -1;
719                         }
720                         $$.len = strlen($$.buf);
721                 }
722         ;
723
724 policy_spec
725         :       F_POLICY policy_requests
726                 {
727                         char *policy;
728
729                         policy = ipsec_set_policy($2.buf, $2.len);
730                         if (policy == NULL) {
731                                 yyerror(ipsec_strerror());
732                                 return -1;
733                         }
734
735                         $$.buf = policy;
736                         $$.len = ipsec_get_policylen(policy);
737                 }
738         ;
739
740 policy_requests
741         :       PL_REQUESTS { $$ = $1; }
742         ;
743
744 %%
745
746 int
747 setkeymsg0(msg, type, satype, l)
748         struct sadb_msg *msg;
749         unsigned int type;
750         unsigned int satype;
751         size_t l;
752 {
753
754         msg->sadb_msg_version = PF_KEY_V2;
755         msg->sadb_msg_type = type;
756         msg->sadb_msg_errno = 0;
757         msg->sadb_msg_satype = satype;
758         msg->sadb_msg_reserved = 0;
759         msg->sadb_msg_seq = 0;
760         msg->sadb_msg_pid = getpid();
761         msg->sadb_msg_len = PFKEY_UNIT64(l);
762         return 0;
763 }
764
765 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
766 static int
767 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
768         unsigned int type;
769         unsigned int upper;
770         vchar_t *policy;
771         struct addrinfo *srcs;
772         int splen;
773         struct addrinfo *dsts;
774         int dplen;
775 {
776         struct sadb_msg *msg;
777         char buf[BUFSIZ];
778         int l, l0;
779         struct sadb_address m_addr;
780         struct addrinfo *s, *d;
781         int n;
782         int plen;
783         struct sockaddr *sa;
784         int salen;
785
786         msg = (struct sadb_msg *)buf;
787
788         if (!srcs || !dsts)
789                 return -1;
790
791         /* fix up length afterwards */
792         setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
793         l = sizeof(struct sadb_msg);
794
795         memcpy(buf + l, policy->buf, policy->len);
796         l += policy->len;
797
798         l0 = l;
799         n = 0;
800
801         /* do it for all src/dst pairs */
802         for (s = srcs; s; s = s->ai_next) {
803                 for (d = dsts; d; d = d->ai_next) {
804                         /* rewind pointer */
805                         l = l0;
806
807                         if (s->ai_addr->sa_family != d->ai_addr->sa_family)
808                                 continue;
809                         switch (s->ai_addr->sa_family) {
810                         case AF_INET:
811                                 plen = sizeof(struct in_addr) << 3;
812                                 break;
813 #ifdef INET6
814                         case AF_INET6:
815                                 plen = sizeof(struct in6_addr) << 3;
816                                 break;
817 #endif
818                         default:
819                                 continue;
820                         }
821
822                         /* set src */
823                         sa = s->ai_addr;
824                         salen = s->ai_addr->sa_len;
825                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
826                             PFKEY_ALIGN8(salen));
827                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
828                         m_addr.sadb_address_proto = upper;
829                         m_addr.sadb_address_prefixlen =
830                             (splen >= 0 ? splen : plen);
831                         m_addr.sadb_address_reserved = 0;
832
833                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
834                             sizeof(m_addr), (caddr_t)sa, salen);
835
836                         /* set dst */
837                         sa = d->ai_addr;
838                         salen = d->ai_addr->sa_len;
839                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
840                             PFKEY_ALIGN8(salen));
841                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
842                         m_addr.sadb_address_proto = upper;
843                         m_addr.sadb_address_prefixlen =
844                             (dplen >= 0 ? dplen : plen);
845                         m_addr.sadb_address_reserved = 0;
846
847                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
848                             sizeof(m_addr), (caddr_t)sa, salen);
849
850                         msg->sadb_msg_len = PFKEY_UNIT64(l);
851
852                         sendkeymsg(buf, l);
853
854                         n++;
855                 }
856         }
857
858         if (n == 0)
859                 return -1;
860         else
861                 return 0;
862 }
863
864 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
865 static int
866 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
867         unsigned int type;
868         unsigned int satype;
869         struct addrinfo *srcs;
870         struct addrinfo *dsts;
871         int no_spi;
872 {
873         struct sadb_msg *msg;
874         char buf[BUFSIZ];
875         int l, l0, len;
876         struct sadb_sa m_sa;
877         struct sadb_x_sa2 m_sa2;
878         struct sadb_address m_addr;
879         struct addrinfo *s, *d;
880         int n;
881         int plen;
882         struct sockaddr *sa;
883         int salen;
884
885         msg = (struct sadb_msg *)buf;
886
887         if (!srcs || !dsts)
888                 return -1;
889
890         /* fix up length afterwards */
891         setkeymsg0(msg, type, satype, 0);
892         l = sizeof(struct sadb_msg);
893
894         if (!no_spi) {
895                 len = sizeof(struct sadb_sa);
896                 m_sa.sadb_sa_len = PFKEY_UNIT64(len);
897                 m_sa.sadb_sa_exttype = SADB_EXT_SA;
898                 m_sa.sadb_sa_spi = htonl(p_spi);
899                 m_sa.sadb_sa_replay = p_replay;
900                 m_sa.sadb_sa_state = 0;
901                 m_sa.sadb_sa_auth = p_alg_auth;
902                 m_sa.sadb_sa_encrypt = p_alg_enc;
903                 m_sa.sadb_sa_flags = p_ext;
904
905                 memcpy(buf + l, &m_sa, len);
906                 l += len;
907
908                 len = sizeof(struct sadb_x_sa2);
909                 m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
910                 m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
911                 m_sa2.sadb_x_sa2_mode = p_mode;
912                 m_sa2.sadb_x_sa2_reqid = p_reqid;
913
914                 memcpy(buf + l, &m_sa2, len);
915                 l += len;
916         }
917
918         l0 = l;
919         n = 0;
920
921         /* do it for all src/dst pairs */
922         for (s = srcs; s; s = s->ai_next) {
923                 for (d = dsts; d; d = d->ai_next) {
924                         /* rewind pointer */
925                         l = l0;
926
927                         if (s->ai_addr->sa_family != d->ai_addr->sa_family)
928                                 continue;
929                         switch (s->ai_addr->sa_family) {
930                         case AF_INET:
931                                 plen = sizeof(struct in_addr) << 3;
932                                 break;
933 #ifdef INET6
934                         case AF_INET6:
935                                 plen = sizeof(struct in6_addr) << 3;
936                                 break;
937 #endif
938                         default:
939                                 continue;
940                         }
941
942                         /* set src */
943                         sa = s->ai_addr;
944                         salen = s->ai_addr->sa_len;
945                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
946                             PFKEY_ALIGN8(salen));
947                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
948                         m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
949                         m_addr.sadb_address_prefixlen = plen;
950                         m_addr.sadb_address_reserved = 0;
951
952                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
953                             sizeof(m_addr), (caddr_t)sa, salen);
954
955                         /* set dst */
956                         sa = d->ai_addr;
957                         salen = d->ai_addr->sa_len;
958                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
959                             PFKEY_ALIGN8(salen));
960                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
961                         m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
962                         m_addr.sadb_address_prefixlen = plen;
963                         m_addr.sadb_address_reserved = 0;
964
965                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
966                             sizeof(m_addr), (caddr_t)sa, salen);
967
968                         msg->sadb_msg_len = PFKEY_UNIT64(l);
969
970                         sendkeymsg(buf, l);
971
972                         n++;
973                 }
974         }
975
976         if (n == 0)
977                 return -1;
978         else
979                 return 0;
980 }
981
982 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
983 static int
984 setkeymsg_add(type, satype, srcs, dsts)
985         unsigned int type;
986         unsigned int satype;
987         struct addrinfo *srcs;
988         struct addrinfo *dsts;
989 {
990         struct sadb_msg *msg;
991         char buf[BUFSIZ];
992         int l, l0, len;
993         struct sadb_sa m_sa;
994         struct sadb_x_sa2 m_sa2;
995         struct sadb_address m_addr;
996         struct addrinfo *s, *d;
997         int n;
998         int plen;
999         struct sockaddr *sa;
1000         int salen;
1001
1002         msg = (struct sadb_msg *)buf;
1003
1004         if (!srcs || !dsts)
1005                 return -1;
1006
1007         /* fix up length afterwards */
1008         setkeymsg0(msg, type, satype, 0);
1009         l = sizeof(struct sadb_msg);
1010
1011         /* set encryption algorithm, if present. */
1012         if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1013                 struct sadb_key m_key;
1014
1015                 m_key.sadb_key_len =
1016                         PFKEY_UNIT64(sizeof(m_key)
1017                                    + PFKEY_ALIGN8(p_key_enc_len));
1018                 m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1019                 m_key.sadb_key_bits = p_key_enc_len * 8;
1020                 m_key.sadb_key_reserved = 0;
1021
1022                 setvarbuf(buf, &l,
1023                         (struct sadb_ext *)&m_key, sizeof(m_key),
1024                         (caddr_t)p_key_enc, p_key_enc_len);
1025         }
1026
1027         /* set authentication algorithm, if present. */
1028         if (p_key_auth) {
1029                 struct sadb_key m_key;
1030
1031                 m_key.sadb_key_len =
1032                         PFKEY_UNIT64(sizeof(m_key)
1033                                    + PFKEY_ALIGN8(p_key_auth_len));
1034                 m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1035                 m_key.sadb_key_bits = p_key_auth_len * 8;
1036                 m_key.sadb_key_reserved = 0;
1037
1038                 setvarbuf(buf, &l,
1039                         (struct sadb_ext *)&m_key, sizeof(m_key),
1040                         (caddr_t)p_key_auth, p_key_auth_len);
1041         }
1042
1043         /* set lifetime for HARD */
1044         if (p_lt_hard != 0) {
1045                 struct sadb_lifetime m_lt;
1046                 u_int slen = sizeof(struct sadb_lifetime);
1047
1048                 m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1049                 m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1050                 m_lt.sadb_lifetime_allocations = 0;
1051                 m_lt.sadb_lifetime_bytes = 0;
1052                 m_lt.sadb_lifetime_addtime = p_lt_hard;
1053                 m_lt.sadb_lifetime_usetime = 0;
1054
1055                 memcpy(buf + l, &m_lt, slen);
1056                 l += slen;
1057         }
1058
1059         /* set lifetime for SOFT */
1060         if (p_lt_soft != 0) {
1061                 struct sadb_lifetime m_lt;
1062                 u_int slen = sizeof(struct sadb_lifetime);
1063
1064                 m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1065                 m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1066                 m_lt.sadb_lifetime_allocations = 0;
1067                 m_lt.sadb_lifetime_bytes = 0;
1068                 m_lt.sadb_lifetime_addtime = p_lt_soft;
1069                 m_lt.sadb_lifetime_usetime = 0;
1070
1071                 memcpy(buf + l, &m_lt, slen);
1072                 l += slen;
1073         }
1074
1075         len = sizeof(struct sadb_sa);
1076         m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1077         m_sa.sadb_sa_exttype = SADB_EXT_SA;
1078         m_sa.sadb_sa_spi = htonl(p_spi);
1079         m_sa.sadb_sa_replay = p_replay;
1080         m_sa.sadb_sa_state = 0;
1081         m_sa.sadb_sa_auth = p_alg_auth;
1082         m_sa.sadb_sa_encrypt = p_alg_enc;
1083         m_sa.sadb_sa_flags = p_ext;
1084
1085         memcpy(buf + l, &m_sa, len);
1086         l += len;
1087
1088         len = sizeof(struct sadb_x_sa2);
1089         m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1090         m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1091         m_sa2.sadb_x_sa2_mode = p_mode;
1092         m_sa2.sadb_x_sa2_reqid = p_reqid;
1093
1094         memcpy(buf + l, &m_sa2, len);
1095         l += len;
1096
1097         l0 = l;
1098         n = 0;
1099
1100         /* do it for all src/dst pairs */
1101         for (s = srcs; s; s = s->ai_next) {
1102                 for (d = dsts; d; d = d->ai_next) {
1103                         /* rewind pointer */
1104                         l = l0;
1105
1106                         if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1107                                 continue;
1108                         switch (s->ai_addr->sa_family) {
1109                         case AF_INET:
1110                                 plen = sizeof(struct in_addr) << 3;
1111                                 break;
1112 #ifdef INET6
1113                         case AF_INET6:
1114                                 plen = sizeof(struct in6_addr) << 3;
1115                                 break;
1116 #endif
1117                         default:
1118                                 continue;
1119                         }
1120
1121                         /* set src */
1122                         sa = s->ai_addr;
1123                         salen = s->ai_addr->sa_len;
1124                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1125                             PFKEY_ALIGN8(salen));
1126                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1127                         m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1128                         m_addr.sadb_address_prefixlen = plen;
1129                         m_addr.sadb_address_reserved = 0;
1130
1131                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1132                             sizeof(m_addr), (caddr_t)sa, salen);
1133
1134                         /* set dst */
1135                         sa = d->ai_addr;
1136                         salen = d->ai_addr->sa_len;
1137                         m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1138                             PFKEY_ALIGN8(salen));
1139                         m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1140                         m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1141                         m_addr.sadb_address_prefixlen = plen;
1142                         m_addr.sadb_address_reserved = 0;
1143
1144                         setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1145                             sizeof(m_addr), (caddr_t)sa, salen);
1146
1147                         msg->sadb_msg_len = PFKEY_UNIT64(l);
1148
1149                         sendkeymsg(buf, l);
1150
1151                         n++;
1152                 }
1153         }
1154
1155         if (n == 0)
1156                 return -1;
1157         else
1158                 return 0;
1159 }
1160
1161 static struct addrinfo *
1162 parse_addr(host, port)
1163         char *host;
1164         char *port;
1165 {
1166         struct addrinfo hints, *res = NULL;
1167         int error;
1168
1169         memset(&hints, 0, sizeof(hints));
1170         hints.ai_family = p_aifamily;
1171         hints.ai_socktype = SOCK_DGRAM;         /*dummy*/
1172         hints.ai_protocol = IPPROTO_UDP;        /*dummy*/
1173         hints.ai_flags = p_aiflags;
1174         error = getaddrinfo(host, port, &hints, &res);
1175         if (error != 0) {
1176                 yyerror(gai_strerror(error));
1177                 return NULL;
1178         }
1179         return res;
1180 }
1181
1182 static int
1183 fix_portstr(spec, sport, dport)
1184         vchar_t *spec, *sport, *dport;
1185 {
1186         char *p, *p2;
1187         u_int l;
1188
1189         l = 0;
1190         for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1191                 ;
1192         if (*p == '\0') {
1193                 p2 = "0";
1194         } else {
1195                 if (*p == ',') {
1196                         *p = '\0';
1197                         p2 = ++p;
1198                 }
1199                 for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1200                         ;
1201                 if (*p != '\0' || *p2 == '\0') {
1202                         yyerror("invalid an upper layer protocol spec");
1203                         return -1;
1204                 }
1205         }
1206
1207         sport->buf = strdup(spec->buf);
1208         if (!sport->buf) {
1209                 yyerror("insufficient memory");
1210                 return -1;
1211         }
1212         sport->len = strlen(sport->buf);
1213         dport->buf = strdup(p2);
1214         if (!dport->buf) {
1215                 yyerror("insufficient memory");
1216                 return -1;
1217         }
1218         dport->len = strlen(dport->buf);
1219
1220         return 0;
1221 }
1222
1223 static int
1224 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1225         char *buf;
1226         int *off;
1227         struct sadb_ext *ebuf;
1228         int elen;
1229         caddr_t vbuf;
1230         int vlen;
1231 {
1232         memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1233         memcpy(buf + *off, (caddr_t)ebuf, elen);
1234         memcpy(buf + *off + elen, vbuf, vlen);
1235         (*off) += PFKEY_ALIGN8(elen + vlen);
1236
1237         return 0;
1238 }
1239
1240 void
1241 parse_init()
1242 {
1243         p_spi = 0;
1244
1245         p_ext = SADB_X_EXT_CYCSEQ;
1246         p_alg_enc = SADB_EALG_NONE;
1247         p_alg_auth = SADB_AALG_NONE;
1248         p_mode = IPSEC_MODE_ANY;
1249         p_reqid = 0;
1250         p_replay = 0;
1251         p_key_enc_len = p_key_auth_len = 0;
1252         p_key_enc = p_key_auth = 0;
1253         p_lt_hard = p_lt_soft = 0;
1254
1255         p_aiflags = 0;
1256         p_aifamily = PF_UNSPEC;
1257
1258         return;
1259 }
1260
1261 void
1262 free_buffer()
1263 {
1264         /* we got tons of memory leaks in the parser anyways, leave them */
1265
1266         return;
1267 }