]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/pfkey_racoon.c
ipsec-93.15.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / pfkey_racoon.c
CommitLineData
52b7d2ce
A
1/* $Id: pfkey.c,v 1.31.2.10 2005/10/03 14:52:19 manubsd Exp $ */
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include "config.h"
33
34#include <stdlib.h>
35#include <string.h>
36#include <stdio.h>
37#include <netdb.h>
38#include <errno.h>
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42#include <netdb.h>
43#include <netinet/in.h>
44#include <arpa/inet.h>
45
46#ifdef ENABLE_NATT
47# ifdef __linux__
48# include <linux/udp.h>
49# endif
50# if defined(__NetBSD__) || defined(__FreeBSD__)
51# include <netinet/udp.h>
52# endif
53#endif
54
55#include <sys/types.h>
56#include <sys/param.h>
57#include <sys/socket.h>
58#include <sys/queue.h>
59#include <sys/sysctl.h>
60
61#include <net/route.h>
62#ifdef __APPLE__
63#include <System/net/pfkeyv2.h>
64#else
65#include <net/pfkeyv2.h>
66#endif
67
68#include <netinet/in.h>
69#ifndef HAVE_NETINET6_IPSEC
70#include <netinet/ipsec.h>
71#else
72#include <netinet6/ipsec.h>
73#endif
74
75#include "libpfkey.h"
76
77#include "var.h"
78#include "misc.h"
79#include "vmbuf.h"
80#include "plog.h"
81#include "sockmisc.h"
82#include "debug.h"
83
84#include "schedule.h"
85#include "localconf.h"
86#include "remoteconf.h"
87#include "isakmp_var.h"
88#include "isakmp.h"
89#include "isakmp_inf.h"
90#include "ipsec_doi.h"
91#include "oakley.h"
92#include "pfkey.h"
93#include "handler.h"
94#include "policy.h"
95#include "algorithm.h"
96#include "sainfo.h"
97#include "proposal.h"
98#include "admin.h"
99#include "privsep.h"
100#include "strnames.h"
101#include "backupsa.h"
102#include "gcmalloc.h"
103#include "nattraversal.h"
104#include "crypto_openssl.h"
105#include "grabmyaddr.h"
106#include "vpn_control.h"
107#include "vpn_control_var.h"
d1e348cf
A
108#include "ike_session.h"
109#include "ipsecSessionTracer.h"
110#include "ipsecMessageTracer.h"
52b7d2ce
A
111
112#if defined(SADB_X_EALG_RIJNDAELCBC) && !defined(SADB_X_EALG_AESCBC)
113#define SADB_X_EALG_AESCBC SADB_X_EALG_RIJNDAELCBC
114#endif
115
116/* prototype */
117static u_int ipsecdoi2pfkey_aalg __P((u_int));
118static u_int ipsecdoi2pfkey_ealg __P((u_int));
119static u_int ipsecdoi2pfkey_calg __P((u_int));
120static u_int ipsecdoi2pfkey_alg __P((u_int, u_int));
121static u_int keylen_aalg __P((u_int));
122static u_int keylen_ealg __P((u_int, int));
123
124static int pk_recvgetspi __P((caddr_t *));
125static int pk_recvupdate __P((caddr_t *));
126static int pk_recvadd __P((caddr_t *));
127static int pk_recvdelete __P((caddr_t *));
128static int pk_recvacquire __P((caddr_t *));
129static int pk_recvexpire __P((caddr_t *));
130static int pk_recvflush __P((caddr_t *));
131static int getsadbpolicy __P((caddr_t *, int *, int, struct ph2handle *));
132static int pk_recvspdupdate __P((caddr_t *));
133static int pk_recvspdadd __P((caddr_t *));
134static int pk_recvspddelete __P((caddr_t *));
135static int pk_recvspdexpire __P((caddr_t *));
136static int pk_recvspdget __P((caddr_t *));
137static int pk_recvspddump __P((caddr_t *));
138static int pk_recvspdflush __P((caddr_t *));
d1e348cf 139static int pk_recvgetsastat __P((caddr_t *));
52b7d2ce
A
140static struct sadb_msg *pk_recv __P((int, int *));
141
142static int (*pkrecvf[]) __P((caddr_t *)) = {
143NULL,
144pk_recvgetspi,
145pk_recvupdate,
146pk_recvadd,
147pk_recvdelete,
148NULL, /* SADB_GET */
149pk_recvacquire,
150NULL, /* SABD_REGISTER */
151pk_recvexpire,
152pk_recvflush,
153NULL, /* SADB_DUMP */
154NULL, /* SADB_X_PROMISC */
155NULL, /* SADB_X_PCHANGE */
156pk_recvspdupdate,
157pk_recvspdadd,
158pk_recvspddelete,
159pk_recvspdget,
160NULL, /* SADB_X_SPDACQUIRE */
161pk_recvspddump,
162pk_recvspdflush,
163NULL, /* SADB_X_SPDSETIDX */
164pk_recvspdexpire,
165NULL, /* SADB_X_SPDDELETE2 */
d1e348cf 166pk_recvgetsastat, /* SADB_GETSASTAT */
52b7d2ce
A
167NULL, /* SADB_X_NAT_T_NEW_MAPPING */
168NULL, /* SADB_X_MIGRATE */
d1e348cf 169#if (SADB_MAX > 25)
52b7d2ce
A
170#error "SADB extra message?"
171#endif
172};
173
174static int addnewsp __P((caddr_t *));
175
176/* cope with old kame headers - ugly */
177#ifndef SADB_X_AALG_MD5
178#define SADB_X_AALG_MD5 SADB_AALG_MD5
179#endif
180#ifndef SADB_X_AALG_SHA
181#define SADB_X_AALG_SHA SADB_AALG_SHA
182#endif
183#ifndef SADB_X_AALG_NULL
184#define SADB_X_AALG_NULL SADB_AALG_NULL
185#endif
186
187#ifndef SADB_X_EALG_BLOWFISHCBC
188#define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC
189#endif
190#ifndef SADB_X_EALG_CAST128CBC
191#define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC
192#endif
193#ifndef SADB_X_EALG_RC5CBC
194#ifdef SADB_EALG_RC5CBC
195#define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC
196#endif
197#endif
198
52b7d2ce 199int
fd507379 200pfkey_process(msg)
52b7d2ce 201 struct sadb_msg *msg;
fd507379 202{
52b7d2ce
A
203 caddr_t mhp[SADB_EXT_MAX + 1];
204 int error = -1;
fd507379 205
52b7d2ce
A
206 plog(LLV_DEBUG, LOCATION, NULL, "get pfkey %s message\n",
207 s_pfkey_type(msg->sadb_msg_type));
208 plogdump(LLV_DEBUG2, msg, msg->sadb_msg_len << 3);
209
210 /* validity check */
211 if (msg->sadb_msg_errno) {
212 int pri;
213
214 /* when SPD is empty, treat the state as no error. */
215 if (msg->sadb_msg_type == SADB_X_SPDDUMP &&
216 msg->sadb_msg_errno == ENOENT)
217 pri = LLV_DEBUG;
218 else
219 pri = LLV_ERROR;
220
221 plog(pri, LOCATION, NULL,
222 "pfkey %s failed: %s\n",
223 s_pfkey_type(msg->sadb_msg_type),
224 strerror(msg->sadb_msg_errno));
225
226 goto end;
227 }
228
229 /* check pfkey message. */
230 if (pfkey_align(msg, mhp)) {
231 plog(LLV_ERROR, LOCATION, NULL,
232 "libipsec failed pfkey align (%s)\n",
233 ipsec_strerror());
234 goto end;
235 }
236 if (pfkey_check(mhp)) {
237 plog(LLV_ERROR, LOCATION, NULL,
238 "libipsec failed pfkey check (%s)\n",
239 ipsec_strerror());
240 goto end;
241 }
242 msg = (struct sadb_msg *)mhp[0];
243
244 /* safety check */
245 if (msg->sadb_msg_type >= ARRAYLEN(pkrecvf)) {
246 plog(LLV_ERROR, LOCATION, NULL,
247 "unknown PF_KEY message type=%u\n",
248 msg->sadb_msg_type);
249 goto end;
250 }
251
252 if (pkrecvf[msg->sadb_msg_type] == NULL) {
253 plog(LLV_INFO, LOCATION, NULL,
254 "unsupported PF_KEY message %s\n",
255 s_pfkey_type(msg->sadb_msg_type));
256 goto end;
257 }
258
259 if ((pkrecvf[msg->sadb_msg_type])(mhp) < 0)
260 goto end;
261
262 error = 0;
263end:
264 if (msg)
265 racoon_free(msg);
266 return(error);
267}
268
fd507379
A
269/*
270 * PF_KEY packet handler
271 * 0: success
272 * -1: fail
273 */
274int
275pfkey_handler()
276{
277 struct sadb_msg *msg;
278 int len;
279
280 /* receive pfkey message. */
281 len = 0;
282 msg = (struct sadb_msg *)pk_recv(lcconf->sock_pfkey, &len);
283 if (msg == NULL) {
284 if (len < 0) {
285 plog(LLV_ERROR, LOCATION, NULL,
286 "failed to recv from pfkey (%s)\n",
287 strerror(errno));
288 return -1;
289 } else {
290 /* short message - msg not ready */
291 return 0;
292 }
293 }
294 return pfkey_process(msg);
295}
296
297void
298pfkey_post_handler()
299{
300 struct saved_msg_elem *elem;
301 struct saved_msg_elem *elem_tmp = NULL;
302
303 TAILQ_FOREACH_SAFE(elem, &lcconf->saved_msg_queue, chain, elem_tmp) {
304 pfkey_process((struct sadb_msg *)elem->msg);
305 TAILQ_REMOVE(&lcconf->saved_msg_queue, elem, chain);
306 racoon_free(elem);
307
308 }
309}
310
311int
312pfkey_save_msg(msg)
313 struct sadb_msg *msg;
314{
315 struct saved_msg_elem *elem;
316
317 elem = (struct saved_msg_elem *)racoon_calloc(sizeof(struct saved_msg_elem), 1);
318 if (elem == NULL)
319 return -1;
320 elem->msg = msg;
321 TAILQ_INSERT_TAIL(&lcconf->saved_msg_queue, elem, chain);
322 return 0;
323}
324
52b7d2ce
A
325/*
326 * dump SADB
327 */
328vchar_t *
329pfkey_dump_sadb(satype)
330 int satype;
331{
332 int s = -1;
333 vchar_t *buf = NULL;
334 pid_t pid = getpid();
335 struct sadb_msg *msg = NULL;
336 size_t bl, ml;
337 int len;
338
339 if ((s = privsep_pfkey_open()) < 0) {
340 plog(LLV_ERROR, LOCATION, NULL,
341 "libipsec failed pfkey open: %s\n",
342 ipsec_strerror());
343 return NULL;
344 }
345
346 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_dump\n");
347 if (pfkey_send_dump(s, satype) < 0) {
348 plog(LLV_ERROR, LOCATION, NULL,
349 "libipsec failed dump: %s\n", ipsec_strerror());
350 goto fail;
351 }
352
353 while (1) {
354 if (msg)
355 racoon_free(msg);
356 msg = pk_recv(s, &len);
357 if (msg == NULL) {
358 if (len < 0)
359 goto done;
360 else
361 continue;
362 }
363
fd507379
A
364 if (msg->sadb_msg_pid != pid)
365 continue;
366
367 /*
368 * for multi-processor system this had to be added because the messages can
369 * be interleaved - they won't all be dump messages
370 */
371 if (msg->sadb_msg_type != SADB_DUMP) { /* save for later processing */
372 pfkey_save_msg(msg);
373 msg = NULL;
52b7d2ce 374 continue;
fd507379 375 }
52b7d2ce
A
376
377 ml = msg->sadb_msg_len << 3;
378 bl = buf ? buf->l : 0;
379 buf = vrealloc(buf, bl + ml);
380 if (buf == NULL) {
381 plog(LLV_ERROR, LOCATION, NULL,
382 "failed to reallocate buffer to dump.\n");
383 goto fail;
384 }
385 memcpy(buf->v + bl, msg, ml);
386
387 if (msg->sadb_msg_seq == 0)
388 break;
389 }
390 goto done;
391
392fail:
393 if (buf)
394 vfree(buf);
395 buf = NULL;
396done:
397 if (msg)
398 racoon_free(msg);
399 if (s >= 0)
400 privsep_pfkey_close(s);
401 return buf;
402}
403
404#ifdef ENABLE_ADMINPORT
405/*
406 * flush SADB
407 */
408void
409pfkey_flush_sadb(proto)
410 u_int proto;
411{
412 int satype;
413
414 /* convert to SADB_SATYPE */
415 if ((satype = admin2pfkey_proto(proto)) < 0)
416 return;
417
418 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_flush\n");
419 if (pfkey_send_flush(lcconf->sock_pfkey, satype) < 0) {
420 plog(LLV_ERROR, LOCATION, NULL,
421 "libipsec failed send flush (%s)\n", ipsec_strerror());
422 return;
423 }
424
425 return;
426}
427#endif
428
429/*
430 * These are the SATYPEs that we manage. We register to get
431 * PF_KEY messages related to these SATYPEs, and we also use
432 * this list to determine which SATYPEs to delete SAs for when
433 * we receive an INITIAL-CONTACT.
434 */
435const struct pfkey_satype pfkey_satypes[] = {
436 { SADB_SATYPE_AH, "AH" },
437 { SADB_SATYPE_ESP, "ESP" },
438 { SADB_X_SATYPE_IPCOMP, "IPCOMP" },
439};
440const int pfkey_nsatypes =
441 sizeof(pfkey_satypes) / sizeof(pfkey_satypes[0]);
442
443/*
444 * PF_KEY initialization
445 */
446int
447pfkey_init()
448{
449 int i, reg_fail;
450
451 if ((lcconf->sock_pfkey = privsep_pfkey_open()) < 0) {
452 plog(LLV_ERROR, LOCATION, NULL,
453 "libipsec failed pfkey open (%s)\n", ipsec_strerror());
454 return -1;
455 }
456
457 for (i = 0, reg_fail = 0; i < pfkey_nsatypes; i++) {
458 plog(LLV_DEBUG, LOCATION, NULL,
459 "call pfkey_send_register for %s\n",
460 pfkey_satypes[i].ps_name);
461 if (pfkey_send_register(lcconf->sock_pfkey,
462 pfkey_satypes[i].ps_satype) < 0 ||
463 pfkey_recv_register(lcconf->sock_pfkey) < 0) {
464 plog(LLV_WARNING, LOCATION, NULL,
465 "failed to register %s (%s)\n",
466 pfkey_satypes[i].ps_name,
467 ipsec_strerror());
468 reg_fail++;
469 }
470 }
471
472 if (reg_fail == pfkey_nsatypes) {
473 plog(LLV_ERROR, LOCATION, NULL,
474 "failed to regist any protocol.\n");
475 pfkey_close(lcconf->sock_pfkey);
476 return -1;
477 }
478
479 initsp();
480
481 if (pfkey_send_spddump(lcconf->sock_pfkey) < 0) {
482 plog(LLV_ERROR, LOCATION, NULL,
483 "libipsec sending spddump failed: %s\n",
484 ipsec_strerror());
485 pfkey_close(lcconf->sock_pfkey);
486 return -1;
487 }
488#if 0
489 if (pfkey_promisc_toggle(1) < 0) {
490 pfkey_close(lcconf->sock_pfkey);
491 return -1;
492 }
493#endif
494 return 0;
495}
496
497/* %%% for conversion */
498/* IPSECDOI_ATTR_AUTH -> SADB_AALG */
499static u_int
500ipsecdoi2pfkey_aalg(hashtype)
501 u_int hashtype;
502{
503 switch (hashtype) {
504 case IPSECDOI_ATTR_AUTH_HMAC_MD5:
505 return SADB_AALG_MD5HMAC;
506 case IPSECDOI_ATTR_AUTH_HMAC_SHA1:
507 return SADB_AALG_SHA1HMAC;
508 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_256:
509#if (defined SADB_X_AALG_SHA2_256) && !defined(SADB_X_AALG_SHA2_256HMAC)
510 return SADB_X_AALG_SHA2_256;
511#else
512 return SADB_X_AALG_SHA2_256HMAC;
513#endif
514 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_384:
515#if (defined SADB_X_AALG_SHA2_384) && !defined(SADB_X_AALG_SHA2_384HMAC)
516 return SADB_X_AALG_SHA2_384;
517#else
518 return SADB_X_AALG_SHA2_384HMAC;
519#endif
520 case IPSECDOI_ATTR_AUTH_HMAC_SHA2_512:
521#if (defined SADB_X_AALG_SHA2_512) && !defined(SADB_X_AALG_SHA2_512HMAC)
522 return SADB_X_AALG_SHA2_512;
523#else
524 return SADB_X_AALG_SHA2_512HMAC;
525#endif
526 case IPSECDOI_ATTR_AUTH_KPDK: /* need special care */
527 return SADB_AALG_NONE;
528
529 /* not supported */
530 case IPSECDOI_ATTR_AUTH_DES_MAC:
531 plog(LLV_ERROR, LOCATION, NULL,
532 "Not supported hash type: %u\n", hashtype);
533 return ~0;
534
535 case 0: /* reserved */
536 default:
537 return SADB_AALG_NONE;
538
539 plog(LLV_ERROR, LOCATION, NULL,
540 "Invalid hash type: %u\n", hashtype);
541 return ~0;
542 }
543 /*NOTREACHED*/
544}
545
546/* IPSECDOI_ESP -> SADB_EALG */
547static u_int
548ipsecdoi2pfkey_ealg(t_id)
549 u_int t_id;
550{
551 switch (t_id) {
552 case IPSECDOI_ESP_DES_IV64: /* sa_flags |= SADB_X_EXT_OLD */
553 return SADB_EALG_DESCBC;
554 case IPSECDOI_ESP_DES:
555 return SADB_EALG_DESCBC;
556 case IPSECDOI_ESP_3DES:
557 return SADB_EALG_3DESCBC;
558#ifdef SADB_X_EALG_RC5CBC
559 case IPSECDOI_ESP_RC5:
560 return SADB_X_EALG_RC5CBC;
561#endif
562 case IPSECDOI_ESP_CAST:
563 return SADB_X_EALG_CAST128CBC;
564 case IPSECDOI_ESP_BLOWFISH:
565 return SADB_X_EALG_BLOWFISHCBC;
566 case IPSECDOI_ESP_DES_IV32: /* flags |= (SADB_X_EXT_OLD|
567 SADB_X_EXT_IV4B)*/
568 return SADB_EALG_DESCBC;
569 case IPSECDOI_ESP_NULL:
570 return SADB_EALG_NULL;
571#ifdef SADB_X_EALG_AESCBC
572 case IPSECDOI_ESP_AES:
573 return SADB_X_EALG_AESCBC;
574#endif
575#ifdef SADB_X_EALG_TWOFISHCBC
576 case IPSECDOI_ESP_TWOFISH:
577 return SADB_X_EALG_TWOFISHCBC;
578#endif
579
580 /* not supported */
581 case IPSECDOI_ESP_3IDEA:
582 case IPSECDOI_ESP_IDEA:
583 case IPSECDOI_ESP_RC4:
584 plog(LLV_ERROR, LOCATION, NULL,
585 "Not supported transform: %u\n", t_id);
586 return ~0;
587
588 case 0: /* reserved */
589 default:
590 plog(LLV_ERROR, LOCATION, NULL,
591 "Invalid transform id: %u\n", t_id);
592 return ~0;
593 }
594 /*NOTREACHED*/
595}
596
597/* IPCOMP -> SADB_CALG */
598static u_int
599ipsecdoi2pfkey_calg(t_id)
600 u_int t_id;
601{
602 switch (t_id) {
603 case IPSECDOI_IPCOMP_OUI:
604 return SADB_X_CALG_OUI;
605 case IPSECDOI_IPCOMP_DEFLATE:
606 return SADB_X_CALG_DEFLATE;
607 case IPSECDOI_IPCOMP_LZS:
608 return SADB_X_CALG_LZS;
609
610 case 0: /* reserved */
611 default:
612 plog(LLV_ERROR, LOCATION, NULL,
613 "Invalid transform id: %u\n", t_id);
614 return ~0;
615 }
616 /*NOTREACHED*/
617}
618
619/* IPSECDOI_PROTO -> SADB_SATYPE */
620u_int
621ipsecdoi2pfkey_proto(proto)
622 u_int proto;
623{
624 switch (proto) {
625 case IPSECDOI_PROTO_IPSEC_AH:
626 return SADB_SATYPE_AH;
627 case IPSECDOI_PROTO_IPSEC_ESP:
628 return SADB_SATYPE_ESP;
629 case IPSECDOI_PROTO_IPCOMP:
630 return SADB_X_SATYPE_IPCOMP;
631
632 default:
633 plog(LLV_ERROR, LOCATION, NULL,
634 "Invalid ipsec_doi proto: %u\n", proto);
635 return ~0;
636 }
637 /*NOTREACHED*/
638}
639
640static u_int
641ipsecdoi2pfkey_alg(algclass, type)
642 u_int algclass, type;
643{
644 switch (algclass) {
645 case IPSECDOI_ATTR_AUTH:
646 return ipsecdoi2pfkey_aalg(type);
647 case IPSECDOI_PROTO_IPSEC_ESP:
648 return ipsecdoi2pfkey_ealg(type);
649 case IPSECDOI_PROTO_IPCOMP:
650 return ipsecdoi2pfkey_calg(type);
651 default:
652 plog(LLV_ERROR, LOCATION, NULL,
653 "Invalid ipsec_doi algclass: %u\n", algclass);
654 return ~0;
655 }
656 /*NOTREACHED*/
657}
658
659/* SADB_SATYPE -> IPSECDOI_PROTO */
660u_int
661pfkey2ipsecdoi_proto(satype)
662 u_int satype;
663{
664 switch (satype) {
665 case SADB_SATYPE_AH:
666 return IPSECDOI_PROTO_IPSEC_AH;
667 case SADB_SATYPE_ESP:
668 return IPSECDOI_PROTO_IPSEC_ESP;
669 case SADB_X_SATYPE_IPCOMP:
670 return IPSECDOI_PROTO_IPCOMP;
671
672 default:
673 plog(LLV_ERROR, LOCATION, NULL,
674 "Invalid pfkey proto: %u\n", satype);
675 return ~0;
676 }
677 /*NOTREACHED*/
678}
679
680/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
681u_int
682ipsecdoi2pfkey_mode(mode)
683 u_int mode;
684{
685 switch (mode) {
686 case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
687#ifdef ENABLE_NATT
688 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
689 case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
690#endif
691 return IPSEC_MODE_TUNNEL;
692 case IPSECDOI_ATTR_ENC_MODE_TRNS:
693#ifdef ENABLE_NATT
694 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
695 case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
696#endif
697 return IPSEC_MODE_TRANSPORT;
698 default:
699 plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
700 return ~0;
701 }
702 /*NOTREACHED*/
703}
704
705/* IPSECDOI_ATTR_ENC_MODE -> IPSEC_MODE */
706u_int
707pfkey2ipsecdoi_mode(mode)
708 u_int mode;
709{
710 switch (mode) {
711 case IPSEC_MODE_TUNNEL:
712 return IPSECDOI_ATTR_ENC_MODE_TUNNEL;
713 case IPSEC_MODE_TRANSPORT:
714 return IPSECDOI_ATTR_ENC_MODE_TRNS;
715 case IPSEC_MODE_ANY:
716 return IPSECDOI_ATTR_ENC_MODE_ANY;
717 default:
718 plog(LLV_ERROR, LOCATION, NULL, "Invalid mode type: %u\n", mode);
719 return ~0;
720 }
721 /*NOTREACHED*/
722}
723
724/* default key length for encryption algorithm */
725static u_int
726keylen_aalg(hashtype)
727 u_int hashtype;
728{
729 int res;
730
731 if (hashtype == 0)
732 return SADB_AALG_NONE;
733
734 res = alg_ipsec_hmacdef_hashlen(hashtype);
735 if (res == -1) {
736 plog(LLV_ERROR, LOCATION, NULL,
737 "invalid hmac algorithm %u.\n", hashtype);
738 return ~0;
739 }
740 return res;
741}
742
743/* default key length for encryption algorithm */
744static u_int
745keylen_ealg(enctype, encklen)
746 u_int enctype;
747 int encklen;
748{
749 int res;
750
751 res = alg_ipsec_encdef_keylen(enctype, encklen);
752 if (res == -1) {
753 plog(LLV_ERROR, LOCATION, NULL,
754 "invalid encryption algorithm %u.\n", enctype);
755 return ~0;
756 }
757 return res;
758}
759
760int
761pfkey_convertfromipsecdoi(proto_id, t_id, hashtype,
762 e_type, e_keylen, a_type, a_keylen, flags)
763 u_int proto_id;
764 u_int t_id;
765 u_int hashtype;
766 u_int *e_type;
767 u_int *e_keylen;
768 u_int *a_type;
769 u_int *a_keylen;
770 u_int *flags;
771{
772 *flags = 0;
773 switch (proto_id) {
774 case IPSECDOI_PROTO_IPSEC_ESP:
775 if ((*e_type = ipsecdoi2pfkey_ealg(t_id)) == ~0)
776 goto bad;
777 if ((*e_keylen = keylen_ealg(t_id, *e_keylen)) == ~0)
778 goto bad;
779 *e_keylen >>= 3;
780
781 if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
782 goto bad;
783 if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
784 goto bad;
785 *a_keylen >>= 3;
786
787 if (*e_type == SADB_EALG_NONE) {
788 plog(LLV_ERROR, LOCATION, NULL, "no ESP algorithm.\n");
789 goto bad;
790 }
791 break;
792
793 case IPSECDOI_PROTO_IPSEC_AH:
794 if ((*a_type = ipsecdoi2pfkey_aalg(hashtype)) == ~0)
795 goto bad;
796 if ((*a_keylen = keylen_aalg(hashtype)) == ~0)
797 goto bad;
798 *a_keylen >>= 3;
799
800 if (t_id == IPSECDOI_ATTR_AUTH_HMAC_MD5
801 && hashtype == IPSECDOI_ATTR_AUTH_KPDK) {
802 /* AH_MD5 + Auth(KPDK) = RFC1826 keyed-MD5 */
803 *a_type = SADB_X_AALG_MD5;
804 *flags |= SADB_X_EXT_OLD;
805 }
806 *e_type = SADB_EALG_NONE;
807 *e_keylen = 0;
808 if (*a_type == SADB_AALG_NONE) {
809 plog(LLV_ERROR, LOCATION, NULL, "no AH algorithm.\n");
810 goto bad;
811 }
812 break;
813
814 case IPSECDOI_PROTO_IPCOMP:
815 if ((*e_type = ipsecdoi2pfkey_calg(t_id)) == ~0)
816 goto bad;
817 *e_keylen = 0;
818
819 *flags = SADB_X_EXT_RAWCPI;
820
821 *a_type = SADB_AALG_NONE;
822 *a_keylen = 0;
823 if (*e_type == SADB_X_CALG_NONE) {
824 plog(LLV_ERROR, LOCATION, NULL, "no IPCOMP algorithm.\n");
825 goto bad;
826 }
827 break;
828
829 default:
830 plog(LLV_ERROR, LOCATION, NULL, "unknown IPsec protocol.\n");
831 goto bad;
832 }
833
834 return 0;
835
836 bad:
837 errno = EINVAL;
838 return -1;
839}
840
841/* called from scheduler */
842void
843pfkey_timeover_stub(p)
844 void *p;
845{
846
847 pfkey_timeover((struct ph2handle *)p);
848}
849
850void
851pfkey_timeover(iph2)
852 struct ph2handle *iph2;
853{
854 plog(LLV_ERROR, LOCATION, NULL,
855 "%s give up to get IPsec-SA due to time up to wait.\n",
856 saddrwop2str(iph2->dst));
857 SCHED_KILL(iph2->sce);
858
859 /* If initiator side, send error to kernel by SADB_ACQUIRE. */
860 if (iph2->side == INITIATOR)
861 pk_sendeacquire(iph2);
862
863 unbindph12(iph2);
864 remph2(iph2);
865 delph2(iph2);
866
867 return;
868}
869
870/*%%%*/
871/* send getspi message per ipsec protocol per remote address */
872/*
873 * the local address and remote address in ph1handle are dealed
874 * with destination address and source address respectively.
875 * Because SPI is decided by responder.
876 */
877int
878pk_sendgetspi(iph2)
879 struct ph2handle *iph2;
880{
881 struct sockaddr *src = NULL, *dst = NULL;
882 u_int satype, mode;
883 struct saprop *pp;
884 struct saproto *pr;
885 u_int32_t minspi, maxspi;
886 int proxy = 0;
887
888 if (iph2->side == INITIATOR) {
889 pp = iph2->proposal;
890 proxy = iph2->ph1->rmconf->support_proxy;
891 } else {
892 pp = iph2->approval;
893 if (iph2->sainfo && iph2->sainfo->id_i)
894 proxy = 1;
895 }
896
897 /* for mobile IPv6 */
898 if (proxy && iph2->src_id && iph2->dst_id &&
899 ipsecdoi_transportmode(pp)) {
900 src = iph2->src_id;
901 dst = iph2->dst_id;
902 } else {
903 src = iph2->src;
904 dst = iph2->dst;
905 }
906
907 for (pr = pp->head; pr != NULL; pr = pr->next) {
908
909 /* validity check */
910 satype = ipsecdoi2pfkey_proto(pr->proto_id);
911 if (satype == ~0) {
912 plog(LLV_ERROR, LOCATION, NULL,
913 "invalid proto_id %d\n", pr->proto_id);
914 return -1;
915 }
916 /* this works around a bug in Linux kernel where it allocates 4 byte
917 spi's for IPCOMP */
918 else if (satype == SADB_X_SATYPE_IPCOMP) {
919 minspi = 0x100;
920 maxspi = 0xffff;
921 }
922 else {
923 minspi = 0;
924 maxspi = 0;
925 }
926 mode = ipsecdoi2pfkey_mode(pr->encmode);
927 if (mode == ~0) {
928 plog(LLV_ERROR, LOCATION, NULL,
929 "invalid encmode %d\n", pr->encmode);
930 return -1;
931 }
932
933 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_getspi\n");
934 if (pfkey_send_getspi(
935 lcconf->sock_pfkey,
936 satype,
937 mode,
938 dst, /* src of SA */
939 src, /* dst of SA */
940 minspi, maxspi,
941 pr->reqid_in, iph2->seq) < 0) {
942 plog(LLV_ERROR, LOCATION, NULL,
943 "ipseclib failed send getspi (%s)\n",
944 ipsec_strerror());
945 return -1;
946 }
947 plog(LLV_DEBUG, LOCATION, NULL,
948 "pfkey GETSPI sent: %s\n",
949 sadbsecas2str(dst, src, satype, 0, mode));
950 }
951
952 return 0;
953}
954
955/*
956 * receive GETSPI from kernel.
957 */
958static int
959pk_recvgetspi(mhp)
960 caddr_t *mhp;
961{
962 struct sadb_msg *msg;
963 struct sadb_sa *sa;
964 struct ph2handle *iph2;
965 struct sockaddr *dst;
966 int proto_id;
967 int allspiok, notfound;
968 struct saprop *pp;
969 struct saproto *pr;
970
971 /* validity check */
972 if (mhp[SADB_EXT_SA] == NULL
973 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
974 plog(LLV_ERROR, LOCATION, NULL,
975 "inappropriate sadb getspi message passed.\n");
976 return -1;
977 }
978 msg = (struct sadb_msg *)mhp[0];
979 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
980 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]); /* note SA dir */
981
982 /* the message has to be processed or not ? */
983 if (msg->sadb_msg_pid != getpid()) {
984 plog(LLV_DEBUG, LOCATION, NULL,
985 "%s message is not interesting "
986 "because pid %d is not mine.\n",
987 s_pfkey_type(msg->sadb_msg_type),
988 msg->sadb_msg_pid);
989 return -1;
990 }
991
992 iph2 = getph2byseq(msg->sadb_msg_seq);
993 if (iph2 == NULL) {
994 plog(LLV_DEBUG, LOCATION, NULL,
995 "seq %d of %s message not interesting.\n",
996 msg->sadb_msg_seq,
997 s_pfkey_type(msg->sadb_msg_type));
998 return -1;
999 }
1000
80318cb7
A
1001 if (iph2->is_dying) {
1002 plog(LLV_ERROR, LOCATION, NULL,
1003 "status mismatch phase2 dying (db:%d msg:%d)\n",
1004 iph2->status, PHASE2ST_GETSPISENT);
1005 return -1;
1006 }
1007
52b7d2ce
A
1008 if (iph2->status != PHASE2ST_GETSPISENT) {
1009 plog(LLV_ERROR, LOCATION, NULL,
1010 "status mismatch (db:%d msg:%d)\n",
1011 iph2->status, PHASE2ST_GETSPISENT);
1012 return -1;
1013 }
1014
d1e348cf
A
1015 // check the underlying iph2->ph1
1016 if (!iph2->ph1) {
1017 if (!ike_session_update_ph2_ph1bind(iph2)) {
1018 plog(LLV_ERROR, LOCATION, NULL,
1019 "can't proceed with getspi for %s. no suitable ISAKMP-SA found \n",
1020 saddrwop2str(iph2->dst));
1021 unbindph12(iph2);
1022 remph2(iph2);
1023 delph2(iph2);
1024 return -1;
1025 }
1026 }
1027
52b7d2ce
A
1028 /* set SPI, and check to get all spi whether or not */
1029 allspiok = 1;
1030 notfound = 1;
1031 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1032 pp = iph2->side == INITIATOR ? iph2->proposal : iph2->approval;
1033
1034 for (pr = pp->head; pr != NULL; pr = pr->next) {
1035 if (pr->proto_id == proto_id && pr->spi == 0) {
1036 pr->spi = sa->sadb_sa_spi;
1037 notfound = 0;
1038 plog(LLV_DEBUG, LOCATION, NULL,
1039 "pfkey GETSPI succeeded: %s\n",
1040 sadbsecas2str(iph2->dst, iph2->src,
1041 msg->sadb_msg_satype,
1042 sa->sadb_sa_spi,
1043 ipsecdoi2pfkey_mode(pr->encmode)));
1044 }
1045 if (pr->spi == 0)
1046 allspiok = 0; /* not get all spi */
1047 }
1048
1049 if (notfound) {
1050 plog(LLV_ERROR, LOCATION, NULL,
1051 "get spi for unknown address %s\n",
1052 saddrwop2str(iph2->dst));
d1e348cf
A
1053 unbindph12(iph2);
1054 remph2(iph2);
1055 delph2(iph2);
52b7d2ce
A
1056 return -1;
1057 }
1058
1059 if (allspiok) {
1060 /* update status */
1061 iph2->status = PHASE2ST_GETSPIDONE;
1062 if (isakmp_post_getspi(iph2) < 0) {
1063 plog(LLV_ERROR, LOCATION, NULL,
1064 "failed to start post getspi.\n");
1065 unbindph12(iph2);
1066 remph2(iph2);
1067 delph2(iph2);
1068 iph2 = NULL;
1069 return -1;
1070 }
1071 }
1072
1073 return 0;
1074}
1075
1076/*
1077 * set inbound SA
1078 */
1079int
1080pk_sendupdate(iph2)
1081 struct ph2handle *iph2;
1082{
1083 struct saproto *pr;
1084 struct sockaddr *src = NULL, *dst = NULL;
1085 u_int e_type, e_keylen, a_type, a_keylen, flags;
1086 u_int satype, mode;
1087 u_int64_t lifebyte = 0;
1088 u_int wsize = 4; /* XXX static size of window */
1089 int proxy = 0;
1090 struct ph2natt natt;
1091
1092 /* sanity check */
1093 if (iph2->approval == NULL) {
1094 plog(LLV_ERROR, LOCATION, NULL,
1095 "no approvaled SAs found.\n");
1096 }
1097
1098 if (iph2->side == INITIATOR)
1099 proxy = iph2->ph1->rmconf->support_proxy;
1100 else if (iph2->sainfo && iph2->sainfo->id_i)
1101 proxy = 1;
1102
1103 /* for mobile IPv6 */
1104 if (proxy && iph2->src_id && iph2->dst_id &&
1105 ipsecdoi_transportmode(iph2->approval)) {
1106 src = iph2->src_id;
1107 dst = iph2->dst_id;
1108 } else {
1109 src = iph2->src;
1110 dst = iph2->dst;
1111 }
1112
1113 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1114 /* validity check */
1115 satype = ipsecdoi2pfkey_proto(pr->proto_id);
1116 if (satype == ~0) {
1117 plog(LLV_ERROR, LOCATION, NULL,
1118 "invalid proto_id %d\n", pr->proto_id);
1119 return -1;
1120 }
1121 else if (satype == SADB_X_SATYPE_IPCOMP) {
1122 /* IPCOMP has no replay window */
1123 wsize = 0;
1124 }
1125#ifdef ENABLE_SAMODE_UNSPECIFIED
1126 mode = IPSEC_MODE_ANY;
1127#else
1128 mode = ipsecdoi2pfkey_mode(pr->encmode);
1129 if (mode == ~0) {
1130 plog(LLV_ERROR, LOCATION, NULL,
1131 "invalid encmode %d\n", pr->encmode);
1132 return -1;
1133 }
1134#endif
1135
1136 /* set algorithm type and key length */
1137 e_keylen = pr->head->encklen;
1138 if (pfkey_convertfromipsecdoi(
1139 pr->proto_id,
1140 pr->head->trns_id,
1141 pr->head->authtype,
1142 &e_type, &e_keylen,
1143 &a_type, &a_keylen, &flags) < 0)
1144 return -1;
1145
1146#if 0
1147 lifebyte = iph2->approval->lifebyte * 1024,
1148#else
1149 lifebyte = 0;
1150#endif
1151
1152#ifdef __APPLE__
1153#ifdef ENABLE_NATT
1154 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
1155 if (pr->udp_encap) {
1156 memset (&natt, 0, sizeof (natt));
1157 natt.sport = extract_port (iph2->ph1->remote);
1158 flags |= SADB_X_EXT_NATT;
d1e348cf
A
1159 if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
1160 if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1161 flags |= SADB_X_EXT_NATT_KEEPALIVE;
1162 }
52b7d2ce
A
1163 else if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1164 mode == IPSEC_MODE_TRANSPORT &&
1165 src->sa_family == AF_INET)
1166 flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1167 } else {
1168 memset (&natt, 0, sizeof (natt));
1169 }
1170
1171 if (pfkey_send_update(
1172 lcconf->sock_pfkey,
1173 satype,
1174 mode,
1175 dst,
1176 src,
1177 pr->spi,
1178 pr->reqid_in,
1179 wsize,
1180 pr->keymat->v,
1181 e_type, e_keylen, a_type, a_keylen, flags,
1182 0, lifebyte, iph2->approval->lifetime, 0,
1183 iph2->seq, natt.sport) < 0) {
1184 plog(LLV_ERROR, LOCATION, NULL,
1185 "libipsec failed send update (%s)\n",
1186 ipsec_strerror());
1187 return -1;
1188 }
1189#else
1190 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
1191 if (pfkey_send_update(
1192 lcconf->sock_pfkey,
1193 satype,
1194 mode,
1195 dst,
1196 src,
1197 pr->spi,
1198 pr->reqid_in,
1199 wsize,
1200 pr->keymat->v,
1201 e_type, e_keylen, a_type, a_keylen, flags,
1202 0, lifebyte, iph2->approval->lifetime, 0,
1203 iph2->seq, 0) < 0) {
1204 plog(LLV_ERROR, LOCATION, NULL,
1205 "libipsec failed send update (%s)\n",
1206 ipsec_strerror());
1207 return -1;
1208 }
1209#endif /* ENABLE_NATT */
1210#else
1211#ifdef ENABLE_NATT
1212 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update_nat\n");
1213 if (pr->udp_encap) {
1214 memset (&natt, 0, sizeof (natt));
1215 natt.type = iph2->ph1->natt_options->encaps_type;
1216 natt.sport = extract_port (iph2->ph1->remote);
1217 natt.dport = extract_port (iph2->ph1->local);
1218 natt.oa = NULL; // FIXME: Here comes OA!!!
1219 natt.frag = iph2->ph1->rmconf->esp_frag;
1220 } else {
1221 memset (&natt, 0, sizeof (natt));
1222 }
1223
1224 if (pfkey_send_update_nat(
1225 lcconf->sock_pfkey,
1226 satype,
1227 mode,
1228 dst,
1229 src,
1230 pr->spi,
1231 pr->reqid_in,
1232 wsize,
1233 pr->keymat->v,
1234 e_type, e_keylen, a_type, a_keylen, flags,
1235 0, lifebyte, iph2->approval->lifetime, 0,
1236 iph2->seq,
1237 natt.type, natt.sport, natt.dport, natt.oa,
1238 natt.frag) < 0) {
1239 plog(LLV_ERROR, LOCATION, NULL,
1240 "libipsec failed send update_nat (%s)\n",
1241 ipsec_strerror());
1242 return -1;
1243 }
1244#else
1245 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_update\n");
1246 if (pfkey_send_update(
1247 lcconf->sock_pfkey,
1248 satype,
1249 mode,
1250 dst,
1251 src,
1252 pr->spi,
1253 pr->reqid_in,
1254 wsize,
1255 pr->keymat->v,
1256 e_type, e_keylen, a_type, a_keylen, flags,
1257 0, lifebyte, iph2->approval->lifetime, 0,
1258 iph2->seq) < 0) {
1259 plog(LLV_ERROR, LOCATION, NULL,
1260 "libipsec failed send update (%s)\n",
1261 ipsec_strerror());
1262 return -1;
1263 }
1264#endif /* ENABLE_NATT */
1265#endif /* __APPLE__ */
1266
1267 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
1268 continue;
1269
1270 /*
1271 * It maybe good idea to call backupsa_to_file() after
1272 * racoon will receive the sadb_update messages.
1273 * But it is impossible because there is not key in the
1274 * information from the kernel.
1275 */
1276 if (backupsa_to_file(satype, mode, dst, src,
1277 pr->spi, pr->reqid_in, 4,
1278 pr->keymat->v,
1279 e_type, e_keylen, a_type, a_keylen, flags,
1280 0, iph2->approval->lifebyte * 1024,
1281 iph2->approval->lifetime, 0,
1282 iph2->seq) < 0) {
1283 plog(LLV_ERROR, LOCATION, NULL,
1284 "backuped SA failed: %s\n",
1285 sadbsecas2str(dst, src,
1286 satype, pr->spi, mode));
1287 }
1288 plog(LLV_DEBUG, LOCATION, NULL,
1289 "backuped SA: %s\n",
1290 sadbsecas2str(dst, src,
1291 satype, pr->spi, mode));
1292 }
1293
1294 return 0;
1295}
1296
1297static int
1298pk_recvupdate(mhp)
1299 caddr_t *mhp;
1300{
1301 struct sadb_msg *msg;
1302 struct sadb_sa *sa;
1303 struct sockaddr *src, *dst;
1304 struct ph2handle *iph2;
1305 u_int proto_id, encmode, sa_mode;
1306 int incomplete = 0;
1307 struct saproto *pr;
1308
1309 /* ignore this message because of local test mode. */
1310 if (f_local)
1311 return 0;
1312
1313 /* sanity check */
1314 if (mhp[0] == NULL
1315 || mhp[SADB_EXT_SA] == NULL
1316 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1317 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1318 plog(LLV_ERROR, LOCATION, NULL,
1319 "inappropriate sadb update message passed.\n");
1320 return -1;
1321 }
1322 msg = (struct sadb_msg *)mhp[0];
1323 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1324 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1325 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
1326
1327 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1328 ? IPSEC_MODE_ANY
1329 : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1330
1331 /* the message has to be processed or not ? */
1332 if (msg->sadb_msg_pid != getpid()) {
1333 plog(LLV_DEBUG, LOCATION, NULL,
1334 "%s message is not interesting "
1335 "because pid %d is not mine.\n",
1336 s_pfkey_type(msg->sadb_msg_type),
1337 msg->sadb_msg_pid);
1338 return -1;
1339 }
1340
1341 iph2 = getph2byseq(msg->sadb_msg_seq);
1342 if (iph2 == NULL) {
1343 plog(LLV_DEBUG, LOCATION, NULL,
1344 "seq %d of %s message not interesting.\n",
1345 msg->sadb_msg_seq,
1346 s_pfkey_type(msg->sadb_msg_type));
1347 return -1;
1348 }
1349
80318cb7
A
1350 if (iph2->is_dying) {
1351 plog(LLV_ERROR, LOCATION, NULL,
1352 "status mismatch phase2 dying (db:%d msg:%d)\n",
1353 iph2->status, PHASE2ST_ADDSA);
1354 return -1;
1355 }
1356
52b7d2ce
A
1357 if (iph2->status != PHASE2ST_ADDSA) {
1358 plog(LLV_ERROR, LOCATION, NULL,
1359 "status mismatch (db:%d msg:%d)\n",
1360 iph2->status, PHASE2ST_ADDSA);
1361 return -1;
1362 }
1363
1364 /* check to complete all keys ? */
1365 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1366 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1367 if (proto_id == ~0) {
1368 plog(LLV_ERROR, LOCATION, NULL,
1369 "invalid proto_id %d\n", msg->sadb_msg_satype);
1370 return -1;
1371 }
1372 encmode = pfkey2ipsecdoi_mode(sa_mode);
1373 if (encmode == ~0) {
1374 plog(LLV_ERROR, LOCATION, NULL,
1375 "invalid encmode %d\n", sa_mode);
1376 return -1;
1377 }
1378
1379 if (pr->proto_id == proto_id
1380 && pr->spi == sa->sadb_sa_spi) {
1381 pr->ok = 1;
1382 plog(LLV_DEBUG, LOCATION, NULL,
1383 "pfkey UPDATE succeeded: %s\n",
1384 sadbsecas2str(iph2->dst, iph2->src,
1385 msg->sadb_msg_satype,
1386 sa->sadb_sa_spi,
1387 sa_mode));
1388
1389 plog(LLV_INFO, LOCATION, NULL,
1390 "IPsec-SA established: %s\n",
1391 sadbsecas2str(iph2->dst, iph2->src,
1392 msg->sadb_msg_satype, sa->sadb_sa_spi,
1393 sa_mode));
1394 }
1395
1396 if (pr->ok == 0)
1397 incomplete = 1;
1398 }
1399
1400 if (incomplete)
1401 return 0;
1402
1403 /* turn off the timer for calling pfkey_timeover() */
1404 SCHED_KILL(iph2->sce);
1405
1406 /* update status */
1407 iph2->status = PHASE2ST_ESTABLISHED;
1408
d1e348cf
A
1409 if (iph2->side == INITIATOR) {
1410 IPSECSESSIONTRACEREVENT(iph2->parent_session,
1411 IPSECSESSIONEVENTCODE_IKEV1_PH2_INIT_SUCC,
1412 CONSTSTR("Initiator, Quick-Mode"),
1413 CONSTSTR(NULL));
1414 } else {
1415 IPSECSESSIONTRACEREVENT(iph2->parent_session,
1416 IPSECSESSIONEVENTCODE_IKEV1_PH2_RESP_SUCC,
1417 CONSTSTR("Responder, Quick-Mode"),
1418 CONSTSTR(NULL));
1419 }
1420
1421 ike_session_ph2_established(iph2);
1422
52b7d2ce
A
1423#ifdef ENABLE_STATS
1424 gettimeofday(&iph2->end, NULL);
1425 syslog(LOG_NOTICE, "%s(%s): %8.6f",
1426 "phase2", "quick", timedelta(&iph2->start, &iph2->end));
1427#endif
1428
1429 /* count up */
fce29cd9
A
1430 if (iph2->ph1)
1431 iph2->ph1->ph2cnt++;
52b7d2ce
A
1432
1433 /* turn off schedule */
1434 if (iph2->scr)
1435 SCHED_KILL(iph2->scr);
1436
1437 /*
1438 * since we are going to reuse the phase2 handler, we need to
1439 * remain it and refresh all the references between ph1 and ph2 to use.
1440 */
1441 unbindph12(iph2);
1442
1443 iph2->sce = sched_new(iph2->approval->lifetime,
1444 isakmp_ph2expire_stub, iph2);
1445
1446 plog(LLV_DEBUG, LOCATION, NULL, "===\n");
1447 return 0;
1448}
1449
1450/*
1451 * set outbound SA
1452 */
1453int
1454pk_sendadd(iph2)
1455 struct ph2handle *iph2;
1456{
1457 struct saproto *pr;
1458 struct sockaddr *src = NULL, *dst = NULL;
1459 u_int e_type, e_keylen, a_type, a_keylen, flags;
1460 u_int satype, mode;
1461 u_int64_t lifebyte = 0;
1462 u_int wsize = 4; /* XXX static size of window */
1463 int proxy = 0;
1464 struct ph2natt natt;
1465
1466 /* sanity check */
1467 if (iph2->approval == NULL) {
1468 plog(LLV_ERROR, LOCATION, NULL,
1469 "no approvaled SAs found.\n");
1470 }
1471
1472 if (iph2->side == INITIATOR)
1473 proxy = iph2->ph1->rmconf->support_proxy;
1474 else if (iph2->sainfo && iph2->sainfo->id_i)
1475 proxy = 1;
1476
1477 /* for mobile IPv6 */
1478 if (proxy && iph2->src_id && iph2->dst_id &&
1479 ipsecdoi_transportmode(iph2->approval)) {
1480 src = iph2->src_id;
1481 dst = iph2->dst_id;
1482 } else {
1483 src = iph2->src;
1484 dst = iph2->dst;
1485 }
1486
1487 for (pr = iph2->approval->head; pr != NULL; pr = pr->next) {
1488 /* validity check */
1489 satype = ipsecdoi2pfkey_proto(pr->proto_id);
1490 if (satype == ~0) {
1491 plog(LLV_ERROR, LOCATION, NULL,
1492 "invalid proto_id %d\n", pr->proto_id);
1493 return -1;
1494 }
1495 else if (satype == SADB_X_SATYPE_IPCOMP) {
1496 /* no replay window for IPCOMP */
1497 wsize = 0;
1498 }
1499#ifdef ENABLE_SAMODE_UNSPECIFIED
1500 mode = IPSEC_MODE_ANY;
1501#else
1502 mode = ipsecdoi2pfkey_mode(pr->encmode);
1503 if (mode == ~0) {
1504 plog(LLV_ERROR, LOCATION, NULL,
1505 "invalid encmode %d\n", pr->encmode);
1506 return -1;
1507 }
1508#endif
1509
1510 /* set algorithm type and key length */
1511 e_keylen = pr->head->encklen;
1512 if (pfkey_convertfromipsecdoi(
1513 pr->proto_id,
1514 pr->head->trns_id,
1515 pr->head->authtype,
1516 &e_type, &e_keylen,
1517 &a_type, &a_keylen, &flags) < 0)
1518 return -1;
1519
1520#if 0
1521 lifebyte = iph2->approval->lifebyte * 1024,
1522#else
1523 lifebyte = 0;
1524#endif
1525
1526#ifdef __APPLE__
1527#ifdef ENABLE_NATT
1528 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
1529
1530 if (pr->udp_encap) {
1531 memset (&natt, 0, sizeof (natt));
1532 natt.dport = extract_port (iph2->ph1->remote);
1533 flags |= SADB_X_EXT_NATT;
d1e348cf
A
1534 if (iph2->ph1->natt_flags & NAT_DETECTED_ME) {
1535 if (iph2->ph1->rmconf->natt_keepalive == TRUE)
1536 flags |= SADB_X_EXT_NATT_KEEPALIVE;
1537 }
52b7d2ce
A
1538 else if (iph2->ph1->rmconf->natt_multiple_user == TRUE &&
1539 mode == IPSEC_MODE_TRANSPORT &&
1540 dst->sa_family == AF_INET)
1541 flags |= SADB_X_EXT_NATT_MULTIPLEUSERS;
1542 } else {
1543 memset (&natt, 0, sizeof (natt));
1544
1545 /* Remove port information, that SA doesn't use it */
1546 //set_port(src, 0);
1547 //set_port(dst, 0);
1548 }
1549
1550 if (pfkey_send_add(
1551 lcconf->sock_pfkey,
1552 satype,
1553 mode,
1554 src,
1555 dst,
1556 pr->spi_p,
1557 pr->reqid_out,
1558 wsize,
1559 pr->keymat_p->v,
1560 e_type, e_keylen, a_type, a_keylen, flags,
1561 0, lifebyte, iph2->approval->lifetime, 0,
1562 iph2->seq,natt.dport) < 0) {
1563 plog(LLV_ERROR, LOCATION, NULL,
1564 "libipsec failed send add (%s)\n",
1565 ipsec_strerror());
1566 return -1;
1567 }
1568#else
1569 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
1570
1571 /* Remove port information, it is not used without NAT-T */
1572 //set_port(src, 0);
1573 //set_port(dst, 0);
1574
1575 if (pfkey_send_add(
1576 lcconf->sock_pfkey,
1577 satype,
1578 mode,
1579 src,
1580 dst,
1581 pr->spi_p,
1582 pr->reqid_out,
1583 wsize,
1584 pr->keymat_p->v,
1585 e_type, e_keylen, a_type, a_keylen, flags,
1586 0, lifebyte, iph2->approval->lifetime, 0,
1587 iph2->seq, 0) < 0) {
1588 plog(LLV_ERROR, LOCATION, NULL,
1589 "libipsec failed send add (%s)\n",
1590 ipsec_strerror());
1591 return -1;
1592 }
1593#endif /* ENABLE_NATT */
1594#else /* __APPLE__ */
1595#ifdef ENABLE_NATT
1596 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add_nat\n");
1597
1598 if (pr->udp_encap) {
1599 memset (&natt, 0, sizeof (natt));
1600 natt.type = UDP_ENCAP_ESPINUDP;
1601 natt.sport = extract_port (iph2->ph1->local);
1602 natt.dport = extract_port (iph2->ph1->remote);
1603 natt.oa = NULL; // FIXME: Here comes OA!!!
1604 natt.frag = iph2->ph1->rmconf->esp_frag;
1605 } else {
1606 memset (&natt, 0, sizeof (natt));
1607
1608 /* Remove port information, that SA doesn't use it */
1609 set_port(src, 0);
1610 set_port(dst, 0);
1611 }
1612
1613 if (pfkey_send_add_nat(
1614 lcconf->sock_pfkey,
1615 satype,
1616 mode,
1617 src,
1618 dst,
1619 pr->spi_p,
1620 pr->reqid_out,
1621 wsize,
1622 pr->keymat_p->v,
1623 e_type, e_keylen, a_type, a_keylen, flags,
1624 0, lifebyte, iph2->approval->lifetime, 0,
1625 iph2->seq,
1626 natt.type, natt.sport, natt.dport, natt.oa,
1627 natt.frag) < 0) {
1628 plog(LLV_ERROR, LOCATION, NULL,
1629 "libipsec failed send add_nat (%s)\n",
1630 ipsec_strerror());
1631 return -1;
1632 }
1633#else
1634 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_add\n");
1635
1636 /* Remove port information, it is not used without NAT-T */
1637 set_port(src, 0);
1638 set_port(dst, 0);
1639
1640 if (pfkey_send_add(
1641 lcconf->sock_pfkey,
1642 satype,
1643 mode,
1644 src,
1645 dst,
1646 pr->spi_p,
1647 pr->reqid_out,
1648 wsize,
1649 pr->keymat_p->v,
1650 e_type, e_keylen, a_type, a_keylen, flags,
1651 0, lifebyte, iph2->approval->lifetime, 0,
1652 iph2->seq) < 0) {
1653 plog(LLV_ERROR, LOCATION, NULL,
1654 "libipsec failed send add (%s)\n",
1655 ipsec_strerror());
1656 return -1;
1657 }
1658#endif /* ENABLE_NATT */
1659#endif /* __APPLE__ */
1660
1661 if (!lcconf->pathinfo[LC_PATHTYPE_BACKUPSA])
1662 continue;
1663
1664 /*
1665 * It maybe good idea to call backupsa_to_file() after
1666 * racoon will receive the sadb_update messages.
1667 * But it is impossible because there is not key in the
1668 * information from the kernel.
1669 */
1670 if (backupsa_to_file(satype, mode, src, dst,
1671 pr->spi_p, pr->reqid_out, 4,
1672 pr->keymat_p->v,
1673 e_type, e_keylen, a_type, a_keylen, flags,
1674 0, iph2->approval->lifebyte * 1024,
1675 iph2->approval->lifetime, 0,
1676 iph2->seq) < 0) {
1677 plog(LLV_ERROR, LOCATION, NULL,
1678 "backuped SA failed: %s\n",
1679 sadbsecas2str(src, dst,
1680 satype, pr->spi_p, mode));
1681 }
1682 plog(LLV_DEBUG, LOCATION, NULL,
1683 "backuped SA: %s\n",
1684 sadbsecas2str(src, dst,
1685 satype, pr->spi_p, mode));
1686 }
1687
1688 return 0;
1689}
1690
1691static int
1692pk_recvadd(mhp)
1693 caddr_t *mhp;
1694{
1695 struct sadb_msg *msg;
1696 struct sadb_sa *sa;
1697 struct sockaddr *src, *dst;
1698 struct ph2handle *iph2;
1699 u_int sa_mode;
1700
1701 /* ignore this message because of local test mode. */
1702 if (f_local)
1703 return 0;
1704
1705 /* sanity check */
1706 if (mhp[0] == NULL
1707 || mhp[SADB_EXT_SA] == NULL
1708 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1709 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
1710 plog(LLV_ERROR, LOCATION, NULL,
1711 "inappropriate sadb add message passed.\n");
1712 return -1;
1713 }
1714 msg = (struct sadb_msg *)mhp[0];
1715 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1716 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1717 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
1718
1719 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1720 ? IPSEC_MODE_ANY
1721 : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1722
1723 /* the message has to be processed or not ? */
1724 if (msg->sadb_msg_pid != getpid()) {
1725 plog(LLV_DEBUG, LOCATION, NULL,
1726 "%s message is not interesting "
1727 "because pid %d is not mine.\n",
1728 s_pfkey_type(msg->sadb_msg_type),
1729 msg->sadb_msg_pid);
1730 return -1;
1731 }
1732
1733 iph2 = getph2byseq(msg->sadb_msg_seq);
1734 if (iph2 == NULL) {
1735 plog(LLV_DEBUG, LOCATION, NULL,
1736 "seq %d of %s message not interesting.\n",
1737 msg->sadb_msg_seq,
1738 s_pfkey_type(msg->sadb_msg_type));
1739 return -1;
1740 }
1741
1742 /*
1743 * NOTE don't update any status of phase2 handle
1744 * because they must be updated by SADB_UPDATE message
1745 */
1746
1747 plog(LLV_INFO, LOCATION, NULL,
1748 "IPsec-SA established: %s\n",
1749 sadbsecas2str(iph2->src, iph2->dst,
1750 msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1751
d1e348cf
A
1752 ike_session_cleanup_other_established_ph2s(iph2->parent_session, iph2);
1753
52b7d2ce
A
1754#ifdef ENABLE_VPNCONTROL_PORT
1755 {
1756 u_int32_t address;
1757
1758 if (iph2->dst->sa_family == AF_INET)
1759 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
1760 else
1761 address = 0;
1762 vpncontrol_notify_phase_change(0, FROM_LOCAL, NULL, iph2);
1763 }
1764#endif
1765
1766 plog(LLV_DEBUG, LOCATION, NULL, "===\n");
1767 return 0;
1768}
1769
1770static int
1771pk_recvexpire(mhp)
1772 caddr_t *mhp;
1773{
1774 struct sadb_msg *msg;
1775 struct sadb_sa *sa;
1776 struct sockaddr *src, *dst;
1777 struct ph2handle *iph2;
1778 u_int proto_id, sa_mode;
1779
1780 /* sanity check */
1781 if (mhp[0] == NULL
1782 || mhp[SADB_EXT_SA] == NULL
1783 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1784 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1785 || (mhp[SADB_EXT_LIFETIME_HARD] != NULL
1786 && mhp[SADB_EXT_LIFETIME_SOFT] != NULL)) {
1787 plog(LLV_ERROR, LOCATION, NULL,
1788 "inappropriate sadb expire message passed.\n");
1789 return -1;
1790 }
1791 msg = (struct sadb_msg *)mhp[0];
1792 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
1793 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1794 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1795
1796 sa_mode = mhp[SADB_X_EXT_SA2] == NULL
1797 ? IPSEC_MODE_ANY
1798 : ((struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2])->sadb_x_sa2_mode;
1799
1800 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
1801 if (proto_id == ~0) {
1802 plog(LLV_ERROR, LOCATION, NULL,
1803 "invalid proto_id %d\n", msg->sadb_msg_satype);
1804 return -1;
1805 }
1806
1807 plog(LLV_INFO, LOCATION, NULL,
1808 "IPsec-SA expired: %s\n",
1809 sadbsecas2str(src, dst,
1810 msg->sadb_msg_satype, sa->sadb_sa_spi, sa_mode));
1811
1812 iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
1813 if (iph2 == NULL) {
1814 /*
1815 * Ignore it because two expire messages are come up.
1816 * phase2 handler has been deleted already when 2nd message
1817 * is received.
1818 */
1819 plog(LLV_DEBUG, LOCATION, NULL,
1820 "no such a SA found: %s\n",
1821 sadbsecas2str(src, dst,
1822 msg->sadb_msg_satype, sa->sadb_sa_spi,
1823 sa_mode));
1824 return 0;
1825 }
80318cb7 1826 if (iph2->is_dying || iph2->status != PHASE2ST_ESTABLISHED) {
52b7d2ce
A
1827 /*
1828 * If the status is not equal to PHASE2ST_ESTABLISHED,
1829 * racoon ignores this expire message. There are two reason.
1830 * One is that the phase 2 probably starts because there is
1831 * a potential that racoon receives the acquire message
1832 * without receiving a expire message. Another is that racoon
1833 * may receive the multiple expire messages from the kernel.
1834 */
1835 plog(LLV_WARNING, LOCATION, NULL,
1836 "the expire message is received "
80318cb7 1837 "but the handler is dying or has not been established.\n");
52b7d2ce
A
1838 return 0;
1839 }
1840
1841 /* turn off the timer for calling isakmp_ph2expire() */
1842 SCHED_KILL(iph2->sce);
1843
1844 iph2->status = PHASE2ST_EXPIRED;
1845
d1e348cf 1846 /* INITIATOR, begin phase 2 exchange only if there's no other established ph2. */
52b7d2ce 1847 /* allocate buffer for status management of pfkey message */
d1e348cf 1848 if (iph2->side == INITIATOR &&
fce29cd9
A
1849 !ike_session_has_other_established_ph2(iph2->parent_session, iph2) &&
1850 !ike_session_drop_rekey(iph2->parent_session)) {
52b7d2ce
A
1851
1852 initph2(iph2);
1853
1854 /* update status for re-use */
1855 iph2->status = PHASE2ST_STATUS2;
1856
1857 /* start isakmp initiation by using ident exchange */
1858 if (isakmp_post_acquire(iph2) < 0) {
1859 plog(LLV_ERROR, LOCATION, iph2->dst,
1860 "failed to begin ipsec sa "
d1e348cf 1861 "re-negotiation.\n");
52b7d2ce
A
1862 unbindph12(iph2);
1863 remph2(iph2);
1864 delph2(iph2);
1865 return -1;
1866 }
1867
1868 return 0;
1869 /*NOTREACHED*/
1870 }
1871
1872 /* If not received SADB_EXPIRE, INITIATOR delete ph2handle. */
1873 /* RESPONDER always delete ph2handle, keep silent. RESPONDER doesn't
1874 * manage IPsec SA, so delete the list */
1875 unbindph12(iph2);
1876 remph2(iph2);
1877 delph2(iph2);
1878
1879 return 0;
1880}
1881
1882static int
1883pk_recvacquire(mhp)
1884 caddr_t *mhp;
1885{
1886 struct sadb_msg *msg;
1887 struct sadb_x_policy *xpl;
1888 struct secpolicy *sp_out = NULL, *sp_in = NULL;
1889#define MAXNESTEDSA 5 /* XXX */
1890 struct ph2handle *iph2[MAXNESTEDSA];
1891 struct sockaddr *src, *dst;
1892 int n; /* # of phase 2 handler */
1893
1894 /* ignore this message because of local test mode. */
1895 if (f_local)
1896 return 0;
1897
1898 /* sanity check */
1899 if (mhp[0] == NULL
1900 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
1901 || mhp[SADB_EXT_ADDRESS_DST] == NULL
1902 || mhp[SADB_X_EXT_POLICY] == NULL) {
1903 plog(LLV_ERROR, LOCATION, NULL,
1904 "inappropriate sadb acquire message passed.\n");
1905 return -1;
1906 }
1907 msg = (struct sadb_msg *)mhp[0];
1908 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
1909 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1910 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1911
1912 /* ignore if type is not IPSEC_POLICY_IPSEC */
1913 if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
1914 plog(LLV_DEBUG, LOCATION, NULL,
1915 "ignore ACQUIRE message. type is not IPsec.\n");
1916 return 0;
1917 }
1918
1919 /* ignore it if src is multicast address */
1920 {
1921 struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
1922
1923 if ((sa->sa_family == AF_INET
1924 && IN_MULTICAST(ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr)))
1925#ifdef INET6
1926 || (sa->sa_family == AF_INET6
1927 && IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)sa)->sin6_addr))
1928#endif
1929 ) {
1930 plog(LLV_DEBUG, LOCATION, NULL,
1931 "ignore due to multicast address: %s.\n",
1932 saddrwop2str(sa));
1933 return 0;
1934 }
1935 }
1936
1937 /* ignore, if we do not listen on source address */
1938 {
1939 /* reasons behind:
1940 * - if we'll contact peer from address we do not listen -
1941 * we will be unable to complete negotiation;
1942 * - if we'll negotiate using address we're listening -
1943 * remote peer will send packets to address different
1944 * than one in the policy, so kernel will drop them;
1945 * => therefore this acquire is not for us! --Aidas
1946 */
1947 struct sockaddr *sa = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
1948 struct myaddrs *p;
1949 int do_listen = 0;
1950 for (p = lcconf->myaddrs; p; p = p->next) {
1951 if (!cmpsaddrwop(p->addr, sa)) {
1952 do_listen = 1;
1953 break;
1954 }
1955 }
1956
1957 if (!do_listen) {
1958 plog(LLV_DEBUG, LOCATION, NULL,
1959 "ignore because do not listen on source address : %s.\n",
1960 saddrwop2str(sa));
1961 return 0;
1962 }
1963 }
1964
1965 /*
1966 * If there is a phase 2 handler against the policy identifier in
1967 * the acquire message, and if
1968 * 1. its state is less than PHASE2ST_ESTABLISHED, then racoon
1969 * should ignore such a acquire message because the phase 2
1970 * is just negotiating.
1971 * 2. its state is equal to PHASE2ST_ESTABLISHED, then racoon
d1e348cf
A
1972 * has to process such a acquire message because racoon may
1973 * have lost the expire message.
52b7d2ce
A
1974 */
1975 iph2[0] = getph2byid(src, dst, xpl->sadb_x_policy_id);
1976 if (iph2[0] != NULL) {
1977 if (iph2[0]->status < PHASE2ST_ESTABLISHED) {
1978 plog(LLV_DEBUG, LOCATION, NULL,
1979 "ignore the acquire because ph2 found\n");
1980 return -1;
1981 }
1982 if (iph2[0]->status == PHASE2ST_EXPIRED)
1983 iph2[0] = NULL;
1984 /*FALLTHROUGH*/
1985 }
1986
1987 /* search for proper policyindex */
1988 sp_out = getspbyspid(xpl->sadb_x_policy_id);
1989 if (sp_out == NULL) {
1990 plog(LLV_ERROR, LOCATION, NULL, "no policy found: id:%d.\n",
1991 xpl->sadb_x_policy_id);
1992 return -1;
1993 }
1994 plog(LLV_DEBUG, LOCATION, NULL,
1995 "suitable outbound SP found: %s.\n", spidx2str(&sp_out->spidx));
1996
1997 /* get inbound policy */
1998 {
1999 struct policyindex spidx;
2000
2001 spidx.dir = IPSEC_DIR_INBOUND;
2002 memcpy(&spidx.src, &sp_out->spidx.dst, sizeof(spidx.src));
2003 memcpy(&spidx.dst, &sp_out->spidx.src, sizeof(spidx.dst));
2004 spidx.prefs = sp_out->spidx.prefd;
2005 spidx.prefd = sp_out->spidx.prefs;
2006 spidx.ul_proto = sp_out->spidx.ul_proto;
2007
2008 sp_in = getsp(&spidx);
2009 if (sp_in) {
2010 plog(LLV_DEBUG, LOCATION, NULL,
2011 "suitable inbound SP found: %s.\n",
2012 spidx2str(&sp_in->spidx));
2013 } else {
2014 plog(LLV_NOTIFY, LOCATION, NULL,
2015 "no in-bound policy found: %s\n",
2016 spidx2str(&spidx));
2017 }
2018 }
2019
2020 memset(iph2, 0, MAXNESTEDSA);
2021
2022 n = 0;
2023
2024 /* allocate a phase 2 */
2025 iph2[n] = newph2();
2026 if (iph2[n] == NULL) {
2027 plog(LLV_ERROR, LOCATION, NULL,
2028 "failed to allocate phase2 entry.\n");
2029 return -1;
2030 }
2031 iph2[n]->side = INITIATOR;
2032 iph2[n]->spid = xpl->sadb_x_policy_id;
2033 iph2[n]->satype = msg->sadb_msg_satype;
2034 iph2[n]->seq = msg->sadb_msg_seq;
2035 iph2[n]->status = PHASE2ST_STATUS2;
2036
2037 /* set end addresses of SA */
2038 iph2[n]->dst = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]));
2039 if (iph2[n]->dst == NULL) {
2040 delph2(iph2[n]);
2041 return -1;
2042 }
2043 iph2[n]->src = dupsaddr(PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]));
2044 if (iph2[n]->src == NULL) {
2045 delph2(iph2[n]);
2046 return -1;
2047 }
2048
2049 plog(LLV_DEBUG, LOCATION, NULL,
2050 "new acquire %s\n", spidx2str(&sp_out->spidx));
2051
2052 /* get sainfo */
2053 {
2054 vchar_t *idsrc, *iddst;
2055
2056 idsrc = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.src,
2057 sp_out->spidx.prefs, sp_out->spidx.ul_proto);
2058 if (idsrc == NULL) {
2059 plog(LLV_ERROR, LOCATION, NULL,
2060 "failed to get ID for %s\n",
2061 spidx2str(&sp_out->spidx));
2062 delph2(iph2[n]);
2063 return -1;
2064 }
2065 iddst = ipsecdoi_sockaddr2id((struct sockaddr *)&sp_out->spidx.dst,
2066 sp_out->spidx.prefd, sp_out->spidx.ul_proto);
2067 if (iddst == NULL) {
2068 plog(LLV_ERROR, LOCATION, NULL,
2069 "failed to get ID for %s\n",
2070 spidx2str(&sp_out->spidx));
2071 vfree(idsrc);
2072 delph2(iph2[n]);
2073 return -1;
2074 }
05434fec 2075 iph2[n]->sainfo = getsainfo(idsrc, iddst, NULL, 0);
52b7d2ce
A
2076 vfree(idsrc);
2077 vfree(iddst);
2078 if (iph2[n]->sainfo == NULL) {
2079 plog(LLV_ERROR, LOCATION, NULL,
2080 "failed to get sainfo.\n");
2081 delph2(iph2[n]);
2082 return -1;
2083 /* XXX should use the algorithm list from register message */
2084 }
d1e348cf
A
2085#ifdef __APPLE__
2086 if (link_sainfo_to_ph2(iph2[n]->sainfo) != 0) {
2087 plog(LLV_ERROR, LOCATION, NULL,
2088 "failed to link sainfo\n");
2089 iph2[n]->sainfo = NULL;
2090 delph2(iph2[n]);
2091 return -1;
2092 }
2093#endif
52b7d2ce
A
2094 }
2095
2096 if (set_proposal_from_policy(iph2[n], sp_out, sp_in) < 0) {
2097 plog(LLV_ERROR, LOCATION, NULL,
2098 "failed to create saprop.\n");
2099 delph2(iph2[n]);
2100 return -1;
2101 }
2102 insph2(iph2[n]);
2103
2104 /* start isakmp initiation by using ident exchange */
2105 /* XXX should be looped if there are multiple phase 2 handler. */
2106 if (isakmp_post_acquire(iph2[n]) < 0) {
2107 plog(LLV_ERROR, LOCATION, NULL,
d1e348cf 2108 "failed to begin ipsec sa negotiation.\n");
52b7d2ce
A
2109 goto err;
2110 }
d1e348cf
A
2111
2112#if !TARGET_OS_EMBEDDED
2113 if ( lcconf->vt == NULL){
2114 if (!(lcconf->vt = vproc_transaction_begin(NULL)))
2115 plog(LLV_ERROR, LOCATION, NULL,
2116 "vproc_transaction_begin returns NULL.\n");
2117 }
2118#endif
52b7d2ce 2119
d1e348cf 2120
52b7d2ce
A
2121 return 0;
2122
2123err:
2124 while (n >= 0) {
2125 unbindph12(iph2[n]);
2126 remph2(iph2[n]);
2127 delph2(iph2[n]);
2128 iph2[n] = NULL;
2129 n--;
2130 }
2131 return -1;
2132}
2133
2134static int
2135pk_recvdelete(mhp)
2136 caddr_t *mhp;
2137{
2138 struct sadb_msg *msg;
2139 struct sadb_sa *sa;
2140 struct sockaddr *src, *dst;
2141 struct ph2handle *iph2 = NULL;
2142 u_int proto_id;
2143
2144 /* ignore this message because of local test mode. */
2145 if (f_local)
2146 return 0;
2147
2148 /* sanity check */
2149 if (mhp[0] == NULL
52b7d2ce
A
2150 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2151 || mhp[SADB_EXT_ADDRESS_DST] == NULL) {
2152 plog(LLV_ERROR, LOCATION, NULL,
2153 "inappropriate sadb delete message passed.\n");
2154 return -1;
2155 }
2156 msg = (struct sadb_msg *)mhp[0];
2157 sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
2158 src = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_SRC]);
2159 dst = PFKEY_ADDR_SADDR(mhp[SADB_EXT_ADDRESS_DST]);
2160
2161 /* the message has to be processed or not ? */
2162 if (msg->sadb_msg_pid == getpid()) {
2163 plog(LLV_DEBUG, LOCATION, NULL,
2164 "%s message is not interesting "
2165 "because the message was originated by me.\n",
2166 s_pfkey_type(msg->sadb_msg_type));
2167 return -1;
2168 }
2169
2170 proto_id = pfkey2ipsecdoi_proto(msg->sadb_msg_satype);
2171 if (proto_id == ~0) {
2172 plog(LLV_ERROR, LOCATION, NULL,
2173 "invalid proto_id %d\n", msg->sadb_msg_satype);
2174 return -1;
2175 }
2176
d1e348cf
A
2177 plog(LLV_DEBUG2, LOCATION, NULL, "SADB delete message: proto-id %d\n", proto_id);
2178 plog(LLV_DEBUG2, LOCATION, NULL, "src: %s\n", saddr2str(src));
2179 plog(LLV_DEBUG2, LOCATION, NULL, "dst: %s\n", saddr2str(dst));
2180
2181 if (!sa) {
2182 deleteallph2(src, dst, proto_id);
2183 deleteallph1(src, dst);
2184 return 0;
2185 }
2186
52b7d2ce
A
2187 iph2 = getph2bysaidx(src, dst, proto_id, sa->sadb_sa_spi);
2188 if (iph2 == NULL) {
2189 /* ignore */
2190 plog(LLV_ERROR, LOCATION, NULL,
2191 "no iph2 found: %s\n",
2192 sadbsecas2str(src, dst, msg->sadb_msg_satype,
2193 sa->sadb_sa_spi, IPSEC_MODE_ANY));
2194 return 0;
2195 }
2196
2197 plog(LLV_ERROR, LOCATION, NULL,
2198 "pfkey DELETE received: %s\n",
2199 sadbsecas2str(iph2->src, iph2->dst,
2200 msg->sadb_msg_satype, sa->sadb_sa_spi, IPSEC_MODE_ANY));
2201
2202 /* send delete information */
2203 if (iph2->status == PHASE2ST_ESTABLISHED)
2204 isakmp_info_send_d2(iph2);
2205
d1e348cf 2206 ike_session_cleanup_ph1s_by_ph2(iph2);
52b7d2ce
A
2207 unbindph12(iph2);
2208 remph2(iph2);
2209 delph2(iph2);
2210
2211 return 0;
2212}
2213
2214static int
2215pk_recvflush(mhp)
2216 caddr_t *mhp;
2217{
2218 /* ignore this message because of local test mode. */
2219 if (f_local)
2220 return 0;
2221
2222 /* sanity check */
2223 if (mhp[0] == NULL) {
2224 plog(LLV_ERROR, LOCATION, NULL,
2225 "inappropriate sadb flush message passed.\n");
2226 return -1;
2227 }
2228
d1e348cf
A
2229 flushph2(false);
2230 flushph1(false);
52b7d2ce
A
2231
2232 return 0;
2233}
2234
2235static int
2236getsadbpolicy(policy0, policylen0, type, iph2)
2237 caddr_t *policy0;
2238 int *policylen0, type;
2239 struct ph2handle *iph2;
2240{
2241 struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
2242 struct sadb_x_policy *xpl;
2243 struct sadb_x_ipsecrequest *xisr;
2244 struct saproto *pr;
2245 caddr_t policy, p;
2246 int policylen;
2247 int xisrlen;
2248 u_int satype, mode;
2249
2250 /* get policy buffer size */
2251 policylen = sizeof(struct sadb_x_policy);
2252 if (type != SADB_X_SPDDELETE) {
2253 for (pr = iph2->approval->head; pr; pr = pr->next) {
2254 xisrlen = sizeof(*xisr);
2255 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
2256 xisrlen += (sysdep_sa_len(iph2->src)
2257 + sysdep_sa_len(iph2->dst));
2258 }
2259
2260 policylen += PFKEY_ALIGN8(xisrlen);
2261 }
2262 }
2263
2264 /* make policy structure */
2265 policy = racoon_malloc(policylen);
2266 if (!policy) {
2267 plog(LLV_ERROR, LOCATION, NULL,
2268 "buffer allocation failed.\n");
2269 return -1;
2270 }
2271
2272 xpl = (struct sadb_x_policy *)policy;
2273 xpl->sadb_x_policy_len = PFKEY_UNIT64(policylen);
2274 xpl->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
2275 xpl->sadb_x_policy_type = IPSEC_POLICY_IPSEC;
2276 xpl->sadb_x_policy_dir = spidx->dir;
2277 xpl->sadb_x_policy_id = 0;
2278#ifdef HAVE_PFKEY_POLICY_PRIORITY
2279 xpl->sadb_x_policy_priority = PRIORITY_DEFAULT;
2280#endif
2281
2282 /* no need to append policy information any more if type is SPDDELETE */
2283 if (type == SADB_X_SPDDELETE)
2284 goto end;
2285
2286 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
2287
2288 for (pr = iph2->approval->head; pr; pr = pr->next) {
2289
2290 satype = doi2ipproto(pr->proto_id);
2291 if (satype == ~0) {
2292 plog(LLV_ERROR, LOCATION, NULL,
2293 "invalid proto_id %d\n", pr->proto_id);
2294 goto err;
2295 }
2296 mode = ipsecdoi2pfkey_mode(pr->encmode);
2297 if (mode == ~0) {
2298 plog(LLV_ERROR, LOCATION, NULL,
2299 "invalid encmode %d\n", pr->encmode);
2300 goto err;
2301 }
2302
2303 /*
2304 * the policy level cannot be unique because the policy
2305 * is defined later than SA, so req_id cannot be bound to SA.
2306 */
2307 xisr->sadb_x_ipsecrequest_proto = satype;
2308 xisr->sadb_x_ipsecrequest_mode = mode;
2309 xisr->sadb_x_ipsecrequest_level = IPSEC_LEVEL_REQUIRE;
2310 xisr->sadb_x_ipsecrequest_reqid = 0;
2311 p = (caddr_t)(xisr + 1);
2312
2313 xisrlen = sizeof(*xisr);
2314
2315 if (pr->encmode == IPSECDOI_ATTR_ENC_MODE_TUNNEL) {
2316 int src_len, dst_len;
2317
2318 src_len = sysdep_sa_len(iph2->src);
2319 dst_len = sysdep_sa_len(iph2->dst);
2320 xisrlen += src_len + dst_len;
2321
2322 memcpy(p, iph2->src, src_len);
2323 p += src_len;
2324
2325 memcpy(p, iph2->dst, dst_len);
2326 p += dst_len;
2327 }
2328
2329 xisr->sadb_x_ipsecrequest_len = PFKEY_ALIGN8(xisrlen);
2330 }
2331
2332end:
2333 *policy0 = policy;
2334 *policylen0 = policylen;
2335
2336 return 0;
2337
2338err:
2339 if (policy)
2340 racoon_free(policy);
2341
2342 return -1;
2343}
2344
2345int
2346pk_sendspdupdate2(iph2)
2347 struct ph2handle *iph2;
2348{
2349 struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
2350 caddr_t policy = NULL;
2351 int policylen = 0;
2352 u_int64_t ltime, vtime;
2353
2354 ltime = iph2->approval->lifetime;
2355 vtime = 0;
2356
2357 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDUPDATE, iph2)) {
2358 plog(LLV_ERROR, LOCATION, NULL,
2359 "getting sadb policy failed.\n");
2360 return -1;
2361 }
2362
2363 if (pfkey_send_spdupdate2(
2364 lcconf->sock_pfkey,
2365 (struct sockaddr *)&spidx->src,
2366 spidx->prefs,
2367 (struct sockaddr *)&spidx->dst,
2368 spidx->prefd,
2369 spidx->ul_proto,
2370 ltime, vtime,
2371 policy, policylen, 0) < 0) {
2372 plog(LLV_ERROR, LOCATION, NULL,
2373 "libipsec failed send spdupdate2 (%s)\n",
2374 ipsec_strerror());
2375 goto end;
2376 }
2377 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdupdate2\n");
2378
2379end:
2380 if (policy)
2381 racoon_free(policy);
2382
2383 return 0;
2384}
2385
2386static int
2387pk_recvspdupdate(mhp)
2388 caddr_t *mhp;
2389{
2390 struct sadb_address *saddr, *daddr;
2391 struct sadb_x_policy *xpl;
2392 struct policyindex spidx;
2393 struct secpolicy *sp;
2394
2395 /* sanity check */
2396 if (mhp[0] == NULL
2397 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2398 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2399 || mhp[SADB_X_EXT_POLICY] == NULL) {
2400 plog(LLV_ERROR, LOCATION, NULL,
2401 "inappropriate sadb spdupdate message passed.\n");
2402 return -1;
2403 }
2404 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2405 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2406 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2407
2408#ifdef HAVE_PFKEY_POLICY_PRIORITY
2409 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2410 saddr + 1,
2411 daddr + 1,
2412 saddr->sadb_address_prefixlen,
2413 daddr->sadb_address_prefixlen,
2414 saddr->sadb_address_proto,
2415 xpl->sadb_x_policy_priority,
2416 &spidx);
2417#else
2418 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2419 saddr + 1,
2420 daddr + 1,
2421 saddr->sadb_address_prefixlen,
2422 daddr->sadb_address_prefixlen,
2423 saddr->sadb_address_proto,
2424 &spidx);
2425#endif
2426
2427 sp = getsp(&spidx);
2428 if (sp == NULL) {
2429 plog(LLV_ERROR, LOCATION, NULL,
2430 "such policy does not already exist: \"%s\"\n",
2431 spidx2str(&spidx));
2432 } else {
2433 remsp(sp);
2434 delsp(sp);
2435 }
2436
2437 if (addnewsp(mhp) < 0)
2438 return -1;
2439
2440 return 0;
2441}
2442
2443/*
2444 * this function has to be used by responder side.
2445 */
2446int
2447pk_sendspdadd2(iph2)
2448 struct ph2handle *iph2;
2449{
2450 struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
2451 caddr_t policy = NULL;
2452 int policylen = 0;
2453 u_int64_t ltime, vtime;
2454
2455 ltime = iph2->approval->lifetime;
2456 vtime = 0;
2457
2458 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDADD, iph2)) {
2459 plog(LLV_ERROR, LOCATION, NULL,
2460 "getting sadb policy failed.\n");
2461 return -1;
2462 }
2463
2464 if (pfkey_send_spdadd2(
2465 lcconf->sock_pfkey,
2466 (struct sockaddr *)&spidx->src,
2467 spidx->prefs,
2468 (struct sockaddr *)&spidx->dst,
2469 spidx->prefd,
2470 spidx->ul_proto,
2471 ltime, vtime,
2472 policy, policylen, 0) < 0) {
2473 plog(LLV_ERROR, LOCATION, NULL,
2474 "libipsec failed send spdadd2 (%s)\n",
2475 ipsec_strerror());
2476 goto end;
2477 }
2478 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spdadd2\n");
2479
2480end:
2481 if (policy)
2482 racoon_free(policy);
2483
2484 return 0;
2485}
2486
2487static int
2488pk_recvspdadd(mhp)
2489 caddr_t *mhp;
2490{
2491 struct sadb_address *saddr, *daddr;
2492 struct sadb_x_policy *xpl;
2493 struct policyindex spidx;
2494 struct secpolicy *sp;
2495
2496 /* sanity check */
2497 if (mhp[0] == NULL
2498 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2499 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2500 || mhp[SADB_X_EXT_POLICY] == NULL) {
2501 plog(LLV_ERROR, LOCATION, NULL,
2502 "inappropriate sadb spdadd message passed.\n");
2503 return -1;
2504 }
2505 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2506 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2507 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2508
2509#ifdef HAVE_PFKEY_POLICY_PRIORITY
2510 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2511 saddr + 1,
2512 daddr + 1,
2513 saddr->sadb_address_prefixlen,
2514 daddr->sadb_address_prefixlen,
2515 saddr->sadb_address_proto,
2516 xpl->sadb_x_policy_priority,
2517 &spidx);
2518#else
2519 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2520 saddr + 1,
2521 daddr + 1,
2522 saddr->sadb_address_prefixlen,
2523 daddr->sadb_address_prefixlen,
2524 saddr->sadb_address_proto,
2525 &spidx);
2526#endif
2527
2528 sp = getsp(&spidx);
2529 if (sp != NULL) {
2530 plog(LLV_ERROR, LOCATION, NULL,
2531 "such policy already exists. "
2532 "anyway replace it: %s\n",
2533 spidx2str(&spidx));
2534 remsp(sp);
2535 delsp(sp);
2536 }
2537
2538 if (addnewsp(mhp) < 0)
2539 return -1;
2540
2541 return 0;
2542}
2543
2544/*
2545 * this function has to be used by responder side.
2546 */
2547int
2548pk_sendspddelete(iph2)
2549 struct ph2handle *iph2;
2550{
2551 struct policyindex *spidx = (struct policyindex *)iph2->spidx_gen;
2552 caddr_t policy = NULL;
2553 int policylen;
2554
2555 if (getsadbpolicy(&policy, &policylen, SADB_X_SPDDELETE, iph2)) {
2556 plog(LLV_ERROR, LOCATION, NULL,
2557 "getting sadb policy failed.\n");
2558 return -1;
2559 }
2560
2561 if (pfkey_send_spddelete(
2562 lcconf->sock_pfkey,
2563 (struct sockaddr *)&spidx->src,
2564 spidx->prefs,
2565 (struct sockaddr *)&spidx->dst,
2566 spidx->prefd,
2567 spidx->ul_proto,
2568 policy, policylen, 0) < 0) {
2569 plog(LLV_ERROR, LOCATION, NULL,
2570 "libipsec failed send spddelete (%s)\n",
2571 ipsec_strerror());
2572 goto end;
2573 }
2574 plog(LLV_DEBUG, LOCATION, NULL, "call pfkey_send_spddelete\n");
2575
2576end:
2577 if (policy)
2578 racoon_free(policy);
2579
2580 return 0;
2581}
2582
2583static int
2584pk_recvspddelete(mhp)
2585 caddr_t *mhp;
2586{
2587 struct sadb_address *saddr, *daddr;
2588 struct sadb_x_policy *xpl;
2589 struct policyindex spidx;
2590 struct secpolicy *sp;
2591
2592 /* sanity check */
2593 if (mhp[0] == NULL
2594 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2595 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2596 || mhp[SADB_X_EXT_POLICY] == NULL) {
2597 plog(LLV_ERROR, LOCATION, NULL,
2598 "inappropriate sadb spddelete message passed.\n");
2599 return -1;
2600 }
2601 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2602 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2603 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2604
2605#ifdef HAVE_PFKEY_POLICY_PRIORITY
2606 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2607 saddr + 1,
2608 daddr + 1,
2609 saddr->sadb_address_prefixlen,
2610 daddr->sadb_address_prefixlen,
2611 saddr->sadb_address_proto,
2612 xpl->sadb_x_policy_priority,
2613 &spidx);
2614#else
2615 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2616 saddr + 1,
2617 daddr + 1,
2618 saddr->sadb_address_prefixlen,
2619 daddr->sadb_address_prefixlen,
2620 saddr->sadb_address_proto,
2621 &spidx);
2622#endif
2623
2624 sp = getsp(&spidx);
2625 if (sp == NULL) {
2626 plog(LLV_ERROR, LOCATION, NULL,
2627 "no policy found: %s\n",
2628 spidx2str(&spidx));
2629 return -1;
2630 }
2631
d1e348cf
A
2632 purgephXbyspid(xpl->sadb_x_policy_id, true);
2633
52b7d2ce
A
2634 remsp(sp);
2635 delsp(sp);
2636
2637 return 0;
2638}
2639
2640static int
2641pk_recvspdexpire(mhp)
2642 caddr_t *mhp;
2643{
2644 struct sadb_address *saddr, *daddr;
2645 struct sadb_x_policy *xpl;
2646 struct policyindex spidx;
2647 struct secpolicy *sp;
2648
2649 /* sanity check */
2650 if (mhp[0] == NULL
2651 || mhp[SADB_EXT_ADDRESS_SRC] == NULL
2652 || mhp[SADB_EXT_ADDRESS_DST] == NULL
2653 || mhp[SADB_X_EXT_POLICY] == NULL) {
2654 plog(LLV_ERROR, LOCATION, NULL,
2655 "inappropriate sadb spdexpire message passed.\n");
2656 return -1;
2657 }
2658 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2659 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2660 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2661
2662#ifdef HAVE_PFKEY_POLICY_PRIORITY
2663 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2664 saddr + 1,
2665 daddr + 1,
2666 saddr->sadb_address_prefixlen,
2667 daddr->sadb_address_prefixlen,
2668 saddr->sadb_address_proto,
2669 xpl->sadb_x_policy_priority,
2670 &spidx);
2671#else
2672 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2673 saddr + 1,
2674 daddr + 1,
2675 saddr->sadb_address_prefixlen,
2676 daddr->sadb_address_prefixlen,
2677 saddr->sadb_address_proto,
2678 &spidx);
2679#endif
2680
2681 sp = getsp(&spidx);
2682 if (sp == NULL) {
2683 plog(LLV_ERROR, LOCATION, NULL,
2684 "no policy found: %s\n",
2685 spidx2str(&spidx));
2686 return -1;
2687 }
2688
d1e348cf
A
2689 purgephXbyspid(xpl->sadb_x_policy_id, false);
2690
52b7d2ce
A
2691 remsp(sp);
2692 delsp(sp);
2693
2694 return 0;
2695}
2696
2697static int
2698pk_recvspdget(mhp)
2699 caddr_t *mhp;
2700{
2701 /* sanity check */
2702 if (mhp[0] == NULL) {
2703 plog(LLV_ERROR, LOCATION, NULL,
2704 "inappropriate sadb spdget message passed.\n");
2705 return -1;
2706 }
2707
2708 return 0;
2709}
2710
2711static int
2712pk_recvspddump(mhp)
2713 caddr_t *mhp;
2714{
2715 struct sadb_msg *msg;
2716 struct sadb_address *saddr, *daddr;
2717 struct sadb_x_policy *xpl;
2718 struct policyindex spidx;
2719 struct secpolicy *sp;
2720
2721 /* sanity check */
2722 if (mhp[0] == NULL) {
2723 plog(LLV_ERROR, LOCATION, NULL,
2724 "inappropriate sadb spddump message passed.\n");
2725 return -1;
2726 }
2727 msg = (struct sadb_msg *)mhp[0];
2728
2729 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
2730 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
2731 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
2732
2733 if (saddr == NULL || daddr == NULL || xpl == NULL) {
2734 plog(LLV_ERROR, LOCATION, NULL,
2735 "inappropriate sadb spddump message passed.\n");
2736 return -1;
2737 }
2738
2739#ifdef HAVE_PFKEY_POLICY_PRIORITY
2740 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2741 saddr + 1,
2742 daddr + 1,
2743 saddr->sadb_address_prefixlen,
2744 daddr->sadb_address_prefixlen,
2745 saddr->sadb_address_proto,
2746 xpl->sadb_x_policy_priority,
2747 &spidx);
2748#else
2749 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
2750 saddr + 1,
2751 daddr + 1,
2752 saddr->sadb_address_prefixlen,
2753 daddr->sadb_address_prefixlen,
2754 saddr->sadb_address_proto,
2755 &spidx);
2756#endif
2757
2758 sp = getsp(&spidx);
2759 if (sp != NULL) {
2760 plog(LLV_ERROR, LOCATION, NULL,
2761 "such policy already exists. "
2762 "anyway replace it: %s\n",
2763 spidx2str(&spidx));
2764 remsp(sp);
2765 delsp(sp);
2766 }
2767
2768 if (addnewsp(mhp) < 0)
2769 return -1;
2770
2771 return 0;
2772}
2773
2774static int
2775pk_recvspdflush(mhp)
2776 caddr_t *mhp;
2777{
2778 /* sanity check */
2779 if (mhp[0] == NULL) {
2780 plog(LLV_ERROR, LOCATION, NULL,
2781 "inappropriate sadb spdflush message passed.\n");
2782 return -1;
2783 }
2784
d1e348cf
A
2785 flushph2(false);
2786 flushph1(false);
52b7d2ce
A
2787 flushsp();
2788
2789 return 0;
2790}
2791
2792/*
2793 * send error against acquire message to kenrel.
2794 */
2795int
2796pk_sendeacquire(iph2)
2797 struct ph2handle *iph2;
2798{
2799 struct sadb_msg *newmsg;
2800 int len;
2801
2802 len = sizeof(struct sadb_msg);
2803 newmsg = racoon_calloc(1, len);
2804 if (newmsg == NULL) {
2805 plog(LLV_ERROR, LOCATION, NULL,
2806 "failed to get buffer to send acquire.\n");
2807 return -1;
2808 }
2809
2810 memset(newmsg, 0, len);
2811 newmsg->sadb_msg_version = PF_KEY_V2;
2812 newmsg->sadb_msg_type = SADB_ACQUIRE;
2813 newmsg->sadb_msg_errno = ENOENT; /* XXX */
2814 newmsg->sadb_msg_satype = iph2->satype;
2815 newmsg->sadb_msg_len = PFKEY_UNIT64(len);
2816 newmsg->sadb_msg_reserved = 0;
2817 newmsg->sadb_msg_seq = iph2->seq;
2818 newmsg->sadb_msg_pid = (u_int32_t)getpid();
2819
2820 /* send message */
2821 len = pfkey_send(lcconf->sock_pfkey, newmsg, len);
2822
2823 racoon_free(newmsg);
2824
2825 return 0;
2826}
2827
d1e348cf
A
2828int
2829pk_sendget_inbound_sastats(ike_session_t *session)
2830{
2831 u_int32_t max_stats;
2832 u_int32_t seq;
2833
2834 if (!session) {
2835 plog(LLV_DEBUG, LOCATION, NULL, "invalid args in %s \n", __FUNCTION__);
2836 return -1;
2837 }
2838
2839 session->traffic_monitor.num_in_curr_req = 0;
2840 bzero(session->traffic_monitor.in_curr_req, sizeof(session->traffic_monitor.in_curr_req));
2841 max_stats = (sizeof(session->traffic_monitor.in_curr_req) / sizeof(session->traffic_monitor.in_curr_req[0]));
2842
2843 // get list of SAs
2844 if ((session->traffic_monitor.num_in_curr_req = ike_session_get_sas_for_stats(session,
2845 IPSEC_DIR_INBOUND,
2846 &seq,
2847 session->traffic_monitor.in_curr_req,
2848 max_stats))) {
2849 u_int64_t session_ids[] = {(u_int64_t)session, 0};
2850
2851 plog(LLV_DEBUG, LOCATION, NULL, "about to call %s\n", __FUNCTION__);
2852
2853 if (pfkey_send_getsastats(lcconf->sock_pfkey,
2854 seq,
2855 session_ids,
2856 1,
2857 IPSEC_DIR_INBOUND,
2858 session->traffic_monitor.in_curr_req,
2859 session->traffic_monitor.num_in_curr_req) < 0) {
2860 return -1;
2861 }
2862 plog(LLV_DEBUG, LOCATION, NULL, "%s successful\n", __FUNCTION__);
2863
2864 return session->traffic_monitor.num_in_curr_req;
2865 }
2866 return 0;
2867}
2868
2869int
2870pk_sendget_outbound_sastats(ike_session_t *session)
2871{
2872 u_int32_t max_stats;
2873 u_int32_t seq;
2874
2875 if (!session) {
2876 plog(LLV_DEBUG, LOCATION, NULL, "invalid args in %s \n", __FUNCTION__);
2877 return -1;
2878 }
2879
2880 session->traffic_monitor.num_out_curr_req = 0;
2881 bzero(session->traffic_monitor.out_curr_req, sizeof(session->traffic_monitor.out_curr_req));
2882 max_stats = (sizeof(session->traffic_monitor.out_curr_req) / sizeof(session->traffic_monitor.out_curr_req[0]));
2883
2884 // get list of SAs
2885 if ((session->traffic_monitor.num_out_curr_req = ike_session_get_sas_for_stats(session,
2886 IPSEC_DIR_OUTBOUND,
2887 &seq,
2888 session->traffic_monitor.out_curr_req,
2889 max_stats))) {
2890 u_int64_t session_ids[] = {(u_int64_t)session, 0};
2891
2892 plog(LLV_DEBUG, LOCATION, NULL, "about to call %s\n", __FUNCTION__);
2893
2894 if (pfkey_send_getsastats(lcconf->sock_pfkey,
2895 seq,
2896 session_ids,
2897 1,
2898 IPSEC_DIR_OUTBOUND,
2899 session->traffic_monitor.out_curr_req,
2900 session->traffic_monitor.num_out_curr_req) < 0) {
2901 return -1;
2902 }
2903 plog(LLV_DEBUG, LOCATION, NULL, "%s successful\n", __FUNCTION__);
2904
2905 return session->traffic_monitor.num_out_curr_req;
2906 }
2907 return 0;
2908}
2909
2910/*
2911 * receive GETSPDSTAT from kernel.
2912 */
2913static int
2914pk_recvgetsastat(mhp)
2915caddr_t *mhp;
2916{
2917 struct sadb_msg *msg;
2918 struct sadb_session_id *session_id;
2919 struct sadb_sastat *stat_resp;
2920 ike_session_t *session;
2921
2922 /* validity check */
2923 if (mhp[0] == NULL ||
2924 mhp[SADB_EXT_SESSION_ID] == NULL ||
2925 mhp[SADB_EXT_SASTAT] == NULL) {
2926 plog(LLV_ERROR, LOCATION, NULL,
2927 "inappropriate sadb getsastat response.\n");
2928 return -1;
2929 }
2930 msg = (struct sadb_msg *)mhp[0];
2931 session_id = (ike_session_t *)mhp[SADB_EXT_SESSION_ID];
2932 stat_resp = (struct sadb_sastat *)mhp[SADB_EXT_SASTAT];
2933
2934 /* the message has to be processed or not ? */
2935 if (msg->sadb_msg_pid != getpid()) {
2936 plog(LLV_DEBUG, LOCATION, NULL,
2937 "%s message is not interesting "
2938 "because pid %d is not mine.\n",
2939 s_pfkey_type(msg->sadb_msg_type),
2940 msg->sadb_msg_pid);
2941 return -1;
2942 }
2943 if (!session_id->sadb_session_id_v[0]) {
2944 plog(LLV_DEBUG, LOCATION, NULL,
2945 "%s message is bad "
2946 "because session-id[0] is invalid.\n",
2947 s_pfkey_type(msg->sadb_msg_type));
2948 return -1;
2949 }
2950 session = (__typeof__(session))session_id->sadb_session_id_v[0];
2951
2952 if (!stat_resp->sadb_sastat_list_len) {
2953 plog(LLV_DEBUG, LOCATION, NULL,
2954 "%s message is bad "
2955 "because it has no sastats.\n",
2956 s_pfkey_type(msg->sadb_msg_type));
2957 return -1;
2958 }
2959
2960 ike_session_update_traffic_idle_status(session,
2961 stat_resp->sadb_sastat_dir,
2962 (struct sastat *)(stat_resp + 1),
2963 stat_resp->sadb_sastat_list_len);
2964 return 0;
2965}
2966
52b7d2ce
A
2967/*
2968 * check if the algorithm is supported or not.
2969 * OUT 0: ok
2970 * -1: ng
2971 */
2972int
2973pk_checkalg(class, calg, keylen)
2974 int class, calg, keylen;
2975{
2976 int sup, error;
2977 u_int alg;
2978 struct sadb_alg alg0;
2979
2980 switch (algclass2doi(class)) {
2981 case IPSECDOI_PROTO_IPSEC_ESP:
2982 sup = SADB_EXT_SUPPORTED_ENCRYPT;
2983 break;
2984 case IPSECDOI_ATTR_AUTH:
2985 sup = SADB_EXT_SUPPORTED_AUTH;
2986 break;
2987 case IPSECDOI_PROTO_IPCOMP:
2988 plog(LLV_DEBUG, LOCATION, NULL,
2989 "compression algorithm can not be checked "
2990 "because sadb message doesn't support it.\n");
2991 return 0;
2992 default:
2993 plog(LLV_ERROR, LOCATION, NULL,
2994 "invalid algorithm class.\n");
2995 return -1;
2996 }
2997 alg = ipsecdoi2pfkey_alg(algclass2doi(class), algtype2doi(class, calg));
2998 if (alg == ~0)
2999 return -1;
3000
3001 if (keylen == 0) {
3002 if (ipsec_get_keylen(sup, alg, &alg0)) {
3003 plog(LLV_ERROR, LOCATION, NULL,
3004 "%s.\n", ipsec_strerror());
3005 return -1;
3006 }
3007 keylen = alg0.sadb_alg_minbits;
3008 }
3009
3010 error = ipsec_check_keylen(sup, alg, keylen);
3011 if (error)
3012 plog(LLV_ERROR, LOCATION, NULL,
3013 "%s.\n", ipsec_strerror());
3014
3015 return error;
3016}
3017
3018/*
3019 * differences with pfkey_recv() in libipsec/pfkey.c:
3020 * - never performs busy wait loop.
3021 * - returns NULL and set *lenp to negative on fatal failures
3022 * - returns NULL and set *lenp to non-negative on non-fatal failures
3023 * - returns non-NULL on success
3024 */
3025static struct sadb_msg *
3026pk_recv(so, lenp)
d1e348cf
A
3027 int so;
3028 int *lenp;
52b7d2ce 3029{
05434fec
A
3030 struct sadb_msg *newmsg;
3031 int reallen = 0;
3032 socklen_t optlen = sizeof(reallen);
3033
3034 if (getsockopt(so, SOL_SOCKET, SO_NREAD, &reallen, &optlen) < 0)
52b7d2ce 3035 return NULL; /*fatal*/
05434fec
A
3036
3037 if (reallen == 0)
52b7d2ce 3038 return NULL;
d1e348cf 3039
52b7d2ce
A
3040 if ((newmsg = racoon_calloc(1, reallen)) == NULL)
3041 return NULL;
d1e348cf 3042
52b7d2ce
A
3043 *lenp = recv(so, (caddr_t)newmsg, reallen, 0);
3044 if (*lenp < 0) {
3045 racoon_free(newmsg);
3046 return NULL; /*fatal*/
05434fec 3047 } else if (*lenp != reallen || *lenp < sizeof(struct sadb_msg)) {
52b7d2ce
A
3048 racoon_free(newmsg);
3049 return NULL;
3050 }
d1e348cf 3051
52b7d2ce
A
3052 return newmsg;
3053}
3054
3055/* see handler.h */
3056u_int32_t
3057pk_getseq()
3058{
3059 return eay_random();
3060}
3061
3062static int
3063addnewsp(mhp)
3064 caddr_t *mhp;
3065{
3066 struct secpolicy *new;
3067 struct sadb_address *saddr, *daddr;
3068 struct sadb_x_policy *xpl;
3069
3070 /* sanity check */
3071 if (mhp[SADB_EXT_ADDRESS_SRC] == NULL
3072 || mhp[SADB_EXT_ADDRESS_DST] == NULL
3073 || mhp[SADB_X_EXT_POLICY] == NULL) {
3074 plog(LLV_ERROR, LOCATION, NULL,
3075 "inappropriate sadb spd management message passed.\n");
3076 return -1;
3077 }
3078
3079 saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
3080 daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
3081 xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
3082
3083#ifdef __linux__
3084 /* bsd skips over per-socket policies because there will be no
3085 * src and dst extensions in spddump messages. On Linux the only
3086 * way to achieve the same is check for policy id.
3087 */
3088 if (xpl->sadb_x_policy_id % 8 >= 3) return 0;
3089#endif
3090
3091 new = newsp();
3092 if (new == NULL) {
3093 plog(LLV_ERROR, LOCATION, NULL,
3094 "failed to allocate buffer\n");
3095 return -1;
3096 }
3097
3098 new->spidx.dir = xpl->sadb_x_policy_dir;
3099 new->id = xpl->sadb_x_policy_id;
3100 new->policy = xpl->sadb_x_policy_type;
3101 new->req = NULL;
3102
3103 /* check policy */
3104 switch (xpl->sadb_x_policy_type) {
3105 case IPSEC_POLICY_DISCARD:
3106 case IPSEC_POLICY_GENERATE:
3107 case IPSEC_POLICY_NONE:
3108 case IPSEC_POLICY_ENTRUST:
3109 case IPSEC_POLICY_BYPASS:
3110 break;
3111
3112 case IPSEC_POLICY_IPSEC:
3113 {
3114 int tlen;
3115 struct sadb_x_ipsecrequest *xisr;
3116 struct ipsecrequest **p_isr = &new->req;
3117
3118 /* validity check */
3119 if (PFKEY_EXTLEN(xpl) < sizeof(*xpl)) {
3120 plog(LLV_ERROR, LOCATION, NULL,
3121 "invalid msg length.\n");
3122 return -1;
3123 }
3124
3125 tlen = PFKEY_EXTLEN(xpl) - sizeof(*xpl);
3126 xisr = (struct sadb_x_ipsecrequest *)(xpl + 1);
3127
3128 while (tlen > 0) {
3129
3130 /* length check */
3131 if (xisr->sadb_x_ipsecrequest_len < sizeof(*xisr)) {
3132 plog(LLV_ERROR, LOCATION, NULL,
3133 "invalid msg length.\n");
3134 return -1;
3135 }
3136
3137 /* allocate request buffer */
3138 *p_isr = newipsecreq();
3139 if (*p_isr == NULL) {
3140 plog(LLV_ERROR, LOCATION, NULL,
3141 "failed to get new ipsecreq.\n");
3142 return -1;
3143 }
3144
3145 /* set values */
3146 (*p_isr)->next = NULL;
3147
3148 switch (xisr->sadb_x_ipsecrequest_proto) {
3149 case IPPROTO_ESP:
3150 case IPPROTO_AH:
3151 case IPPROTO_IPCOMP:
3152 break;
3153 default:
3154 plog(LLV_ERROR, LOCATION, NULL,
3155 "invalid proto type: %u\n",
3156 xisr->sadb_x_ipsecrequest_proto);
3157 return -1;
3158 }
3159 (*p_isr)->saidx.proto = xisr->sadb_x_ipsecrequest_proto;
3160
3161 switch (xisr->sadb_x_ipsecrequest_mode) {
3162 case IPSEC_MODE_TRANSPORT:
3163 case IPSEC_MODE_TUNNEL:
3164 break;
3165 case IPSEC_MODE_ANY:
3166 default:
3167 plog(LLV_ERROR, LOCATION, NULL,
3168 "invalid mode: %u\n",
3169 xisr->sadb_x_ipsecrequest_mode);
3170 return -1;
3171 }
3172 (*p_isr)->saidx.mode = xisr->sadb_x_ipsecrequest_mode;
3173
3174 switch (xisr->sadb_x_ipsecrequest_level) {
3175 case IPSEC_LEVEL_DEFAULT:
3176 case IPSEC_LEVEL_USE:
3177 case IPSEC_LEVEL_REQUIRE:
3178 break;
3179 case IPSEC_LEVEL_UNIQUE:
3180 (*p_isr)->saidx.reqid =
3181 xisr->sadb_x_ipsecrequest_reqid;
3182 break;
3183
3184 default:
3185 plog(LLV_ERROR, LOCATION, NULL,
3186 "invalid level: %u\n",
3187 xisr->sadb_x_ipsecrequest_level);
3188 return -1;
3189 }
3190 (*p_isr)->level = xisr->sadb_x_ipsecrequest_level;
3191
3192 /* set IP addresses if there */
3193 if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
3194 struct sockaddr *paddr;
3195
3196 paddr = (struct sockaddr *)(xisr + 1);
3197 bcopy(paddr, &(*p_isr)->saidx.src,
3198 sysdep_sa_len(paddr));
3199
3200 paddr = (struct sockaddr *)((caddr_t)paddr
3201 + sysdep_sa_len(paddr));
3202 bcopy(paddr, &(*p_isr)->saidx.dst,
3203 sysdep_sa_len(paddr));
3204 }
3205
3206 (*p_isr)->sp = new;
3207
3208 /* initialization for the next. */
3209 p_isr = &(*p_isr)->next;
3210 tlen -= xisr->sadb_x_ipsecrequest_len;
3211
3212 /* validity check */
3213 if (tlen < 0) {
3214 plog(LLV_ERROR, LOCATION, NULL,
3215 "becoming tlen < 0\n");
3216 }
3217
3218 xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xisr
3219 + xisr->sadb_x_ipsecrequest_len);
3220 }
3221 }
3222 break;
3223 default:
3224 plog(LLV_ERROR, LOCATION, NULL,
3225 "invalid policy type.\n");
3226 return -1;
3227 }
3228
3229#ifdef HAVE_PFKEY_POLICY_PRIORITY
3230 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3231 saddr + 1,
3232 daddr + 1,
3233 saddr->sadb_address_prefixlen,
3234 daddr->sadb_address_prefixlen,
3235 saddr->sadb_address_proto,
3236 xpl->sadb_x_policy_priority,
3237 &new->spidx);
3238#else
3239 KEY_SETSECSPIDX(xpl->sadb_x_policy_dir,
3240 saddr + 1,
3241 daddr + 1,
3242 saddr->sadb_address_prefixlen,
3243 daddr->sadb_address_prefixlen,
3244 saddr->sadb_address_proto,
3245 &new->spidx);
3246#endif
3247
3248 inssp(new);
3249
3250 return 0;
3251}
3252
3253/* proto/mode/src->dst spi */
3254const char *
3255sadbsecas2str(src, dst, proto, spi, mode)
3256 struct sockaddr *src, *dst;
3257 int proto;
3258 u_int32_t spi;
3259 int mode;
3260{
3261 static char buf[256];
3262 u_int doi_proto, doi_mode = 0;
3263 char *p;
3264 int blen, i;
3265
3266 doi_proto = pfkey2ipsecdoi_proto(proto);
3267 if (doi_proto == ~0)
3268 return NULL;
3269 if (mode) {
3270 doi_mode = pfkey2ipsecdoi_mode(mode);
3271 if (doi_mode == ~0)
3272 return NULL;
3273 }
3274
3275 blen = sizeof(buf) - 1;
3276 p = buf;
3277
3278 i = snprintf(p, blen, "%s%s%s ",
3279 s_ipsecdoi_proto(doi_proto),
3280 mode ? "/" : "",
3281 mode ? s_ipsecdoi_encmode(doi_mode) : "");
3282 if (i < 0 || i >= blen)
3283 return NULL;
3284 p += i;
3285 blen -= i;
3286
3287 i = snprintf(p, blen, "%s->", saddr2str(src));
3288 if (i < 0 || i >= blen)
3289 return NULL;
3290 p += i;
3291 blen -= i;
3292
3293 i = snprintf(p, blen, "%s ", saddr2str(dst));
3294 if (i < 0 || i >= blen)
3295 return NULL;
3296 p += i;
3297 blen -= i;
3298
3299 if (spi) {
3300 snprintf(p, blen, "spi=%lu(0x%lx)", (unsigned long)ntohl(spi),
3301 (unsigned long)ntohl(spi));
3302 }
3303
3304 return buf;
3305}