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