1 /* $Id: ike_pfkey.c,v 1.79 2008/02/06 08:08:59 mk Exp $ */
2
3 /*
4 * Copyright (C) 2004 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 /*
33 * IKE-PFKEY interface bridge
34 */
35
36 #include <config.h>
37
38 #include <stdio.h>
39 #include <string.h>
40 #ifdef HAVE_INTTYPES_H
41 # include <inttypes.h>
42 #endif
43 #include <sys/types.h>
44 #if TIME_WITH_SYS_TIME
45 # include <sys/time.h>
46 # include <time.h>
47 #else
48 # if HAVE_SYS_TIME_H
49 # include <sys/time.h>
50 # else
51 # include <time.h>
52 # endif
53 #endif
54 #include <arpa/inet.h>
55
56 #include "racoon.h"
57 #include "ike_pfkey.h"
58 #include "isakmp_impl.h"
59 #include "ikev2_impl.h"
60 #include "debug.h"
61 #ifdef IKEV1
62 # include "oakley.h"
63 # include "ikev1_impl.h"
64 # include "ikev1/handler.h"
65 #endif
66
67 extern int debug_pfkey;
68 static void dump_param(char *, struct rcpfk_msg *);
69
70 static int sadb_getspi(struct rcpfk_msg *);
71 static int sadb_acquire_error(struct rcpfk_msg *);
72 static int sadb_update(struct rcpfk_msg *);
73 static int sadb_get(struct rcpfk_msg *);
74 static int sadb_add(struct rcpfk_msg *);
75 static int sadb_responder_error(struct rcpfk_msg *);
76 static int sadb_delete(struct rcpfk_msg *);
77
78 static int
79 null_proc()
80 {
81 return 0;
82 }
83
84 /* sadb_initiator_request_method used in response to SADB_ACQUIRE */
85 struct sadb_request_method sadb_initiator_request_method = {
86 sadb_getspi,
87 sadb_acquire_error,
88 sadb_update,
89 sadb_add,
90 sadb_delete,
91 sadb_get,
92 };
93
94 /* sadb_responder_request_method for use when receiving IKE_SA_INIT packet */
95 struct sadb_request_method sadb_responder_request_method = {
96 sadb_getspi,
97 sadb_responder_error,
98 sadb_update,
99 sadb_add,
100 sadb_delete,
101 sadb_get,
102 };
103
104 /* sadb_rekey_request_method for use when rekeying soft-expired IPsec SA */
105 struct sadb_request_method sadb_rekey_request_method = {
106 sadb_getspi,
107 sadb_responder_error,
108 sadb_update,
109 sadb_add,
110 sadb_delete,
111 sadb_get,
112 };
113
114 /* sadb_null_method for informational exchange SA */
115 struct sadb_request_method sadb_null_method = {
116 null_proc, null_proc, null_proc, null_proc, null_proc, null_proc
117 };
118
119 /* sadb_force_initiate_method for use with isakmp_force_initiate() */
120 struct sadb_request_method sadb_force_initiate_method = {
121 sadb_getspi,
122 sadb_responder_error, /* to ignore error */
123 sadb_update,
124 sadb_add,
125 sadb_delete,
126 sadb_get,
127 };
128
129 static SADB_LIST_HEAD(sadb_request_list_head, sadb_request) sadb_request_list_head;
130
131 static int pfkey_socket;
132 static uint32_t sadb_msg_seq;
133
134 static int sadb_getspi_callback(struct rcpfk_msg *param);
135 static int sadb_update_callback(struct rcpfk_msg *param);
136 static int sadb_get_callback(struct rcpfk_msg *param);
137 static int sadb_expire_callback(struct rcpfk_msg *param);
138 static int sadb_acquire_callback(struct rcpfk_msg *param);
139 static int sadb_delete_callback(struct rcpfk_msg *param);
140 #ifdef SADB_X_MIGRATE
141 static int sadb_x_migrate_callback(struct rcpfk_msg *param);
142 #endif
143
144 static struct rcpfk_cb ike_rcpfk_callback = {
145 sadb_getspi_callback,
146 sadb_update_callback,
147 0, /* sadb_add_callback, */
148 sadb_expire_callback,
149 sadb_acquire_callback,
150 sadb_delete_callback,
151 sadb_get_callback,
152 0, /* sadb_spdupdate_callback, */
153 0, /* sadb_spdadd_callback, */
154 0, /* sadb_spddelete_callback, */
155 0, /* sadb_spddelete2_callback, */
156 0, /* sadb_spdexpire_callbcak, */
157 0, /* sadb_spdget_callback */
158 0, /* sadb_spddump_callback */
159 #ifdef SADB_X_MIGRATE
160 sadb_x_migrate_callback,
161 #endif
162 };
163
164 int
165 sadb_init(void)
166 {
167 struct rcpfk_msg param;
168
169 SADB_LIST_INIT(&sadb_request_list_head);
170 if (debug_pfkey)
171 return 0;
172
173 param.flags = 0;
174
175 if (rcpfk_init(¶m, &ike_rcpfk_callback) != 0)
176 return -1;
177 pfkey_socket = param.so;
178 TRACE((PLOGLOC, "pfkey_socket: %d\n", pfkey_socket));
179 return 0;
180 }
181
182 #ifdef DEBUG
183 void
184 sadb_list_dump(void)
185 {
186 struct sadb_request *req;
187
188 plog(PLOG_DEBUG, PLOGLOC, 0, "sadb request list:\n");
189 for (req = SADB_LIST_FIRST(&sadb_request_list_head);
190 !SADB_LIST_END(req);
191 req = SADB_LIST_NEXT(req)) {
192 plog(PLOG_DEBUG, PLOGLOC, 0,
193 "req %p method:%p seqno:%lx sa:%p\n",
194 req, req->method, (unsigned long)req->seqno,
195 req->sa);
196 }
197 plog(PLOG_DEBUG, PLOGLOC, 0, "end\n");
198 }
199 #endif
200
201 int
202 sadb_socket(void)
203 {
204 return pfkey_socket;
205 }
206
207 uint32_t
208 sadb_new_seq(void)
209 {
210 return ++sadb_msg_seq;
211 }
212
213 static void
214 log_rcpfk_error(const char *msg, struct rcpfk_msg *param)
215 {
216 if (param->eno) {
217 isakmp_log(0, 0, 0, 0,
218 PLOG_INTERR, PLOGLOC,
219 "%s: %s\n", msg, param->estr);
220 } else {
221 isakmp_log(0, 0, 0, 0,
222 PLOG_INTERR, PLOGLOC,
223 "%s: unknown error\n", msg);
224 }
225 }
226
227 void
228 sadb_poll(void)
229 {
230 struct rcpfk_msg rcpfk_param;
231
232 rcpfk_param.so = pfkey_socket;
233 rcpfk_param.flags = 0;
234 if (rcpfk_handler(&rcpfk_param) != 0) {
235 log_rcpfk_error("sadb_poll", &rcpfk_param);
236 }
237 }
238
239 void
240 sadb_request_initialize(struct sadb_request *req,
241 struct sadb_request_method *m,
242 struct sadb_response_method *r,
243 uint32_t seqno, void *sa)
244 {
245 req->method = m;
246 req->callback = r;
247 req->seqno = seqno;
248 req->sa = sa;
249 SADB_LIST_LINK(&sadb_request_list_head, req);
250 }
251
252 void
253 sadb_request_finish(struct sadb_request *req)
254 {
255 TRACE((PLOGLOC, "%p\n", req));
256 if (req->link.tqe_prev != 0) /* initialized? */
257 SADB_LIST_REMOVE(&sadb_request_list_head, req);
258 }
259
260 /*
261 * Send a SADB_GETSPI message
262 */
263 static int
264 sadb_getspi(struct rcpfk_msg *param)
265 {
266 int err;
267
268 TRACE((PLOGLOC, "sadb_getspi: seq=%d, satype=%d\n",
269 param->seq, param->satype));
270
271 param->so = pfkey_socket;
272 param->eno = 0;
273 param->flags = 0;
274 err = rcpfk_send_getspi(param);
275 if (err)
276 log_rcpfk_error("sadb_getspi", param);
277 return err;
278 }
279
280 /*
281 * send SADB_ACQUIRE with error to inform kernel of SA creation failure
282 */
283 static int
284 sadb_acquire_error(struct rcpfk_msg *param)
285 {
286 int err;
287
288 TRACE((PLOGLOC,
289 "sadb_acquire_error: seq=%d, satype=%d, errno=%d\n",
290 param->seq, param->satype, param->eno));
291
292 /* param: so, satype, seq, eno */
293 param->so = pfkey_socket;
294 param->flags = 0;
295 err = rcpfk_send_acquire(param);
296 if (err)
297 log_rcpfk_error("sadb_acquire_error", param);
298 return err;
299 }
300
301 static void
302 sadb_log_add(char *op, struct rcpfk_msg *param)
303 {
304 if (param->satype == RCT_SATYPE_ESP) {
305 INFO((PLOGLOC,
306 "%s ul_proto=%d src=%s dst=%s satype=%s samode=%s spi=0x%08x authtype=%s enctype=%s lifetime soft time=%"
307 PRIu64 " bytes=%" PRIu64 " hard time=%" PRIu64 " bytes=%" PRIu64 "\n",
308 op, param->ul_proto, rcs_sa2str(param->sa_src),
309 rcs_sa2str(param->sa_dst), rct2str(param->satype),
310 rct2str(param->samode), ntohl(param->spi),
311 rct2str(param->authtype), rct2str(param->enctype),
312 param->lft_soft_time, param->lft_soft_bytes,
313 param->lft_hard_time, param->lft_hard_bytes));
314 } else {
315 INFO((PLOGLOC,
316 "%s ul_proto=%d src=%s dst=%s satype=%s samode=%s spi=0x%08x authtype=%s lifetime soft time=%"
317 PRIu64 " bytes=%" PRIu64 " hard time=%" PRIu64 " bytes=%" PRIu64 "\n",
318 op, param->ul_proto, rcs_sa2str(param->sa_src),
319 rcs_sa2str(param->sa_dst), rct2str(param->satype),
320 rct2str(param->samode), ntohl(param->spi),
321 rct2str(param->authtype), param->lft_soft_time,
322 param->lft_soft_bytes, param->lft_hard_time,
323 param->lft_hard_bytes));
324 }
325 }
326
327 /* send SADB_UPDATE */
328 static int
329 sadb_update(struct rcpfk_msg *param)
330 {
331 int err;
332
333 sadb_log_add("SADB_UPDATE", param);
334 IF_TRACE(dump_param("sadb_update", param));
335
336 /* param:
337 * so, satype, seq, spi, wsize, authtype, [enctype,] saflags, samode, reqid,
338 * lft_hard_time, lft_hard_bytes, lft_soft_time, lft_soft_bytes,
339 * sa_src, pref_src, sa_dst, pref_dst, ul_proto,
340 * [enckey, enckeylen], authkey, authkeylen
341 */
342 param->so = pfkey_socket;
343 param->eno = 0;
344 err = rcpfk_send_update(param);
345 if (err)
346 log_rcpfk_error("sadb_update", param);
347 return err;
348 }
349
350 /* send SADB_ADD */
351 static int
352 sadb_add(struct rcpfk_msg *param)
353 {
354 int err;
355
356 sadb_log_add("SADB_ADD", param);
357 IF_TRACE(dump_param("sadb_add", param));
358
359 param->so = pfkey_socket;
360 param->eno = 0;
361 err = rcpfk_send_add(param);
362 if (err)
363 log_rcpfk_error("sadb_add", param);
364 return err;
365 }
366
367 /* send SADB_GET */
368 static int
369 sadb_get(struct rcpfk_msg *param)
370 {
371 int err;
372
373 IF_TRACE(dump_param("sadb_get", param));
374
375 param->so = pfkey_socket;
376 param->eno = 0;
377 err = rcpfk_send_get(param);
378 if (err)
379 log_rcpfk_error("sadb_get", param);
380 return err;
381 }
382
383 /*
384 * acquire_error for responder
385 */
386 static int
387 sadb_responder_error(struct rcpfk_msg *param)
388 {
389 /* just ignore since there's no corresponding SADB_ACQUIRE */
390 TRACE((PLOGLOC,
391 "sadb_responder_error: seq=%d, satype=%d, spi=0x%08x, errno=%d\n",
392 param->seq, param->satype, ntohl(param->spi), param->eno));
393 return 0;
394 }
395
396 /*
397 * send SADB_DELETE
398 */
399 static int
400 sadb_delete(struct rcpfk_msg *rc)
401 {
402 int err;
403
404 INFO((PLOGLOC,
405 "SADB_DELETE ul_proto=%d src=%s dst=%s satype=%s spi=0x%08x\n",
406 rc->ul_proto, rcs_sa2str(rc->sa_src), rcs_sa2str(rc->sa_dst),
407 rct2str(rc->satype), ntohl(rc->spi)));
408 TRACE((PLOGLOC,
409 "sadb_delete: sa_src=%s, sa_dst=%s, satype=%d (%s), spi=0x%08x\n",
410 rcs_sa2str(rc->sa_src), rcs_sa2str(rc->sa_dst), rc->satype,
411 rct2str(rc->satype), ntohl(rc->spi)));
412
413 /* param: so, satype, spi, sa_src, sa_dst, ul_proto */
414 /* XXX
415 * pref_dst,pref_src must be <= addrlen, eventhough the values aren't used
416 */
417 rc->so = pfkey_socket;
418 rc->eno = 0;
419 rc->seq = 0;
420 rc->pref_src = rc->pref_dst = 0; /* ??? */
421 rc->flags = 0;
422 err = rcpfk_send_delete(rc);
423 if (err)
424 log_rcpfk_error("sadb_delete", rc);
425 return err;
426 }
427
428 /*
429 * find sadb_request by seq
430 */
431 static struct sadb_request *
432 sadb_find_by_seq(uint32_t seq)
433 {
434 struct sadb_request *req;
435
436 for (req = SADB_LIST_FIRST(&sadb_request_list_head);
437 !SADB_LIST_END(req);
438 req = SADB_LIST_NEXT(req)) {
439 if (req->seqno == seq)
440 return req;
441 }
442 return 0;
443 }
444
445
446 /*
447 * receive SADB_GETSPI message from kernel
448 */
449 static int
450 sadb_getspi_callback(struct rcpfk_msg *param)
451 {
452 /* param: seq, satype, spi, sa_src, sa_dst */
453
454 struct sadb_request *req;
455
456 TRACE((PLOGLOC,
457 "sadb_getspi_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s, sa_dst=%s\n",
458 param->seq, ntohl(param->spi), param->satype,
459 rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst)));
460
461 /* find sadb_request by param->seq */
462 req = sadb_find_by_seq(param->seq);
463 if (!req) {
464
465 /* couldn't find corresponding SA */
466 isakmp_log(0, 0, 0, 0,
467 PLOG_INTWARN, PLOGLOC,
468 "received PF_KEY SADB_GETSPI message (seq %u) does not have corresponding request. (ignored)\n",
469 param->seq);
470 return -1;
471 }
472
473 (*req->callback->getspi_response)(req, param->sa_src,
474 param->sa_dst,
475 (unsigned int)param->satype,
476 ntohl(param->spi));
477 return 0;
478 }
479
480
481 /* called when other KMd issued SADB_UPDATE */
482 static int
483 sadb_update_callback(struct rcpfk_msg *param)
484 {
485 /* param: seq, satype, spi, sa_src, sa_dst, samode */
486 /* lifetime??? address(P)??? identity??? */
487
488 struct sadb_request *req;
489
490 TRACE((PLOGLOC,
491 "sadb_update_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s,"
492 " sa_dst=%s, samode=%d\n",
493 param->seq, ntohl(param->spi), param->satype,
494 rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
495 param->samode));
496
497 req = sadb_find_by_seq(param->seq);
498 if (!req) {
499
500 /* couldn't find corresponding SA */
501 isakmp_log(0, 0, 0, 0,
502 PLOG_INTWARN, PLOGLOC,
503 "received PF_KEY SADB_UPDATE message (seq %u) does not have corresponding request. (ignored)\n",
504 param->seq);
505 return -1;
506 }
507
508 req->callback->update_response(req,
509 param->sa_src, param->sa_dst,
510 (unsigned int)param->satype,
511 (unsigned int)param->samode,
512 ntohl(param->spi));
513 return 0;
514 }
515
516 /* called when other KMd issued SADB_GET */
517 static int
518 sadb_get_callback(struct rcpfk_msg *param)
519 {
520 /* param: seq, satype, spi, sa_src, sa_dst, samode */
521 /* lifetime address(P) identity */
522
523 struct sadb_request *req;
524
525 TRACE((PLOGLOC,
526 "sadb_get_callback: seq=%d, spi=0x%08x, satype=%d, sa_src=%s,"
527 " sa_dst=%s, samode=%d\n",
528 param->seq, ntohl(param->spi), param->satype,
529 rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
530 param->samode));
531
532 req = sadb_find_by_seq(param->seq);
533 if (!req) {
534 /* couldn't find corresponding SA */
535 isakmp_log(0, 0, 0, 0,
536 PLOG_INTWARN, PLOGLOC,
537 "received PF_KEY SADB_GET message (seq %u) does not have corresponding request. (ignored)\n",
538 param->seq);
539 return -1;
540 }
541
542 req->callback->get_response(req,
543 param->sa_src,
544 param->sa_dst,
545 (unsigned int)param->satype,
546 ntohl(param->spi),
547 ¶m->lft_current_bytes);
548
549 return 0;
550 }
551
552
553 #if 0
554 /* not used */
555 /* called when other KMd issued SADB_UDPATE */
556 static int
557 sadb_add_callback(struct rcpfk_msg *param)
558 {
559 /* param: seq, satype, spi, sa_src, sa_dst, samode */
560 /* lifetime??? identity?? sensitivity?? */
561
562 return 0;
563 }
564 #endif
565
566 /*
567 * called when kernel SA expires
568 */
569 static int
570 sadb_expire_callback(struct rcpfk_msg *param)
571 {
572 /* param: seq, satype, spi, sa_src, sa_dst, samode, expired(hard?2:1) */
573 /* lifetime(C)??? */
574
575 struct sadb_request *req;
576
577 plog(PLOG_INFO, PLOGLOC, 0,
578 "received PFKEY_EXPIRE seq=%d sa_dst=%s spi=0x%08x satype=%s samode=%s expired=%d\n",
579 param->seq, rcs_sa2str(param->sa_dst), ntohl(param->spi),
580 rct2str(param->satype), rct2str(param->samode), param->expired);
581
582 /* #ifdef __linux__ ??? */
583 /* Linux/USAGI generates soft-expire regardless it was used or not */
584 TRACE((PLOGLOC, "allocated: %" PRIu64 "\n", param->lft_current_alloc));
585 if (param->expired == 1 && param->lft_current_alloc == 0) {
586 TRACE((PLOGLOC, "ignoring soft expire\n"));
587 return 0;
588 }
589 /* #endif */
590
591 /* start rekeying */
592 /* find sadb_request by spi, sa_dst */
593 for (req = SADB_LIST_FIRST(&sadb_request_list_head);
594 !SADB_LIST_END(req); req = SADB_LIST_NEXT(req)) {
595 if (req->callback->expired(req, param))
596 goto done;
597 }
598
599 /* couldn't find corresponding SA */
600 isakmp_log(0, 0, 0, 0, PLOG_INTWARN, PLOGLOC,
601 "PF_KEY SADB_EXPIRE message does not have corresponding request. (ignored)\n");
602
603 done:
604 TRACE((PLOGLOC, "done.\n"));
605 return 0;
606 }
607
608
609 /*
610 * called when the kernel generates SADB_ACQUIRE message
611 */
612 static int
613 sadb_acquire_callback(struct rcpfk_msg *param)
614 {
615 /* param: seq, satype, sa_src, sa_dst, samode, selid */
616 /* address(P)??? pid?? identity??? proposal??? */
617
618 TRACE((PLOGLOC,
619 "sadb_acquire_callback: seq=%d satype=%d sa_src=%s sa_dst=%s samode=%d selid=%d\n",
620 param->seq, param->satype, rcs_sa2str(param->sa_src),
621 rcs_sa2str(param->sa_dst), param->samode, param->slid));
622
623 if (sadb_find_by_seq(param->seq)) {
624 TRACE((PLOGLOC, "duplicate seq %u\n", param->seq));
625 return 0;
626 }
627
628 isakmp_initiate(&sadb_initiator_request_method,
629 param->slid,
630 param->seq, param->satype,
631 param->sa_src, param->sa_dst,
632 param->sa2_src);
633 return 0;
634 }
635
636 /*
637 * called when the kernel generates SADB_DELETE message
638 */
639 static int
640 sadb_delete_callback(struct rcpfk_msg *param)
641 {
642 /* param: seq, satype, spi, sa_src, sa_dst, samode */
643
644 /* similar to expire ? */
645
646 plog(PLOG_INFO, PLOGLOC, 0,
647 "received PFKEY_DELETE seq=%d satype=%s spi=0x%08x\n",
648 param->seq, rct2str(param->satype), ntohl(param->spi));
649 return 0;
650 }
651
652 #if 0
653 /* not used */
654 /* called when other KMd issued SADB_X_SPDUPDATE */
655 static int
656 sadb_spdupdate_callback(struct rcpfk_msg *param)
657 {
658 /* param: selid */
659
660 return 0;
661 }
662 #endif
663
664 #if 0
665 /* not used */
666 /* called when other KMd issued SADB_X_SPDADD */
667 static int
668 sadb_spdadd_callback(struct rcpfk_msg *param)
669 {
670 /* param: selid */
671 return 0;
672 }
673 #endif
674
675 #if 0
676 /* called when other KMd issued SADB_X_SPDDELETE */
677 static int
678 sadb_spddelete_callback(struct rcpfk_msg *param)
679 {
680 /* param: selid */
681 return 0;
682 }
683 #endif
684
685 #if 0
686 /* called when kernel SP expires */
687 static int
688 sadb_spdexpire_callback(struct rcpfk_msg *param)
689 {
690 /* param: selid */
691 /* address(SD)? lifetime(CH)? */
692
693 return 0;
694 }
695 #endif
696
697 #ifdef SADB_X_MIGRATE
698 #include <netinet/in.h>
699 /* called when kernel issued SADB_X_MIGRATE */
700 static int
701 sadb_x_migrate_callback(struct rcpfk_msg *param)
702 {
703 struct rcf_selector *selector;
704 struct rcf_policy *policy;
705 struct ikev2_sa *ike_sa;
706 struct ikev2_child_sa *child_sa;
707 #ifdef IKEV1
708 struct ph1handle *iph1;
709 struct ph2handle *iph2;
710 extern struct ph1handle *getph1bydstaddrwop(struct sockaddr *);
711 #endif
712 extern struct rcf_selector *rcf_selector_head;
713
714 TRACE((PLOGLOC,
715 "sadb_x_migrate_callback: dir=%s, sa_src=%s, sa_dst=%s, sa2_src=%s, sa2_dst=%s\n",
716 rct2str(param->dir),
717 rcs_sa2str(param->sa_src), rcs_sa2str(param->sa_dst),
718 rcs_sa2str(param->sa2_src), rcs_sa2str(param->sa2_dst)));
719
720 if ((rcs_cmpsa(param->sa_src, param->sa2_src) == 0) &&
721 (rcs_cmpsa(param->sa_dst, param->sa2_dst) == 0))
722 return 0;
723 if (param->dir != RCT_DIR_OUTBOUND)
724 return 0;
725
726 /* migrate the primary selector */
727
728 for (selector = rcf_selector_head;
729 selector != 0;
730 selector = selector->next) {
731 if (selector->direction != RCT_DIR_OUTBOUND)
732 continue;
733 /* XXX match only on the reqid! */
734 if (param->reqid != selector->reqid)
735 continue;
736 policy = selector->pl;
737 if (policy->my_sa_ipaddr)
738 switch (param->sa_src->sa_family) {
739 case AF_INET:
740 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET)
741 break;
742 ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
743 ((struct sockaddr_in *)param->sa2_src)->sin_addr;
744 break;
745 #ifdef INET6
746 case AF_INET6:
747 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET)
748 break;
749 memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr,
750 &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
751 sizeof(struct in6_addr));
752 break;
753 #endif
754 default:
755 return -1;
756 }
757 if (policy->peers_sa_ipaddr)
758 switch (param->sa_dst->sa_family) {
759 case AF_INET:
760 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET)
761 break;
762 ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
763 ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
764 break;
765 #ifdef INET6
766 case AF_INET6:
767 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET)
768 break;
769 memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
770 &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
771 sizeof(struct in6_addr));
772 break;
773 #endif
774 default:
775 return -1;
776 }
777 plog(PLOG_INFO, PLOGLOC, 0,
778 "move selector(%p) with sl_index(%s)\n",
779 selector, rc_vmem2str(selector->sl_index));
780 }
781
782 /* migrate the IKE SA */
783
784 ike_sa = ikev2_find_sa_by_addr(param->sa_dst);
785 if (ike_sa == NULL)
786 goto v1;
787 plog(PLOG_INFO, PLOGLOC, 0, "move ikev2_sa(%p): from %s -> %s\n",
788 ike_sa, rcs_sa2str(ike_sa->local), rcs_sa2str(ike_sa->remote));
789
790 switch (ike_sa->remote->sa_family) {
791 case AF_INET:
792 ((struct sockaddr_in *)ike_sa->local)->sin_addr =
793 ((struct sockaddr_in *)param->sa2_src)->sin_addr;
794 ((struct sockaddr_in *)ike_sa->remote)->sin_addr =
795 ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
796 #ifdef INET6
797 case AF_INET6:
798 memcpy(&((struct sockaddr_in6 *)ike_sa->local)->sin6_addr,
799 &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
800 sizeof(struct in6_addr));
801 memcpy(&((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
802 &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
803 sizeof(struct in6_addr));
804 break;
805 #endif
806 default:
807 return -1;
808 }
809 plog(PLOG_INFO, PLOGLOC, 0, "move ikev2_sa(%p): to %s -> %s\n",
810 ike_sa, rcs_sa2str(ike_sa->local), rcs_sa2str(ike_sa->remote));
811
812 /* migrate children */
813
814 for (child_sa = IKEV2_CHILD_LIST_FIRST(&ike_sa->children);
815 !IKEV2_CHILD_LIST_END(child_sa);
816 child_sa = IKEV2_CHILD_LIST_NEXT(child_sa)) {
817 if (!child_sa->selector)
818 continue;
819 if (param->reqid != child_sa->selector->reqid)
820 continue;
821 switch (ike_sa->remote->sa_family) {
822 case AF_INET:
823 if (child_sa->local)
824 ((struct sockaddr_in *)child_sa->local)->sin_addr =
825 ((struct sockaddr_in *)ike_sa->local)->sin_addr;
826 if (child_sa->remote)
827 ((struct sockaddr_in *)child_sa->remote)->sin_addr =
828 ((struct sockaddr_in *)ike_sa->remote)->sin_addr;
829
830 policy = child_sa->selector->pl;
831 if (policy->my_sa_ipaddr) {
832 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
833 TRACE((PLOGLOC, "unexpected type\n"));
834 continue;
835 }
836 ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
837 ((struct sockaddr_in *)ike_sa->local)->sin_addr;
838 }
839 if (policy->peers_sa_ipaddr) {
840 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
841 TRACE((PLOGLOC, "unexpected type\n"));
842 continue;
843 }
844 ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
845 ((struct sockaddr_in *)ike_sa->local)->sin_addr;
846 }
847 break;
848 #ifdef INET6
849 case AF_INET6:
850 if (child_sa->local)
851 memcpy(&((struct sockaddr_in6 *)child_sa->local)->sin6_addr,
852 &((struct sockaddr_in6 *)ike_sa->local)->sin6_addr,
853 sizeof(struct in6_addr));
854 if (child_sa->remote)
855 memcpy(&((struct sockaddr_in6 *)child_sa->remote)->sin6_addr,
856 &((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
857 sizeof(struct in6_addr));
858
859 policy = child_sa->selector->pl;
860 if (policy->my_sa_ipaddr) {
861 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
862 TRACE((PLOGLOC, "unexpected type\n"));
863 continue;
864 }
865 memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr,
866 &((struct sockaddr_in6 *)ike_sa->local)->sin6_addr,
867 sizeof(struct in6_addr));
868 }
869 if (policy->peers_sa_ipaddr) {
870 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
871 TRACE((PLOGLOC, "unexpected type\n"));
872 continue;
873 }
874 memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
875 &((struct sockaddr_in6 *)ike_sa->remote)->sin6_addr,
876 sizeof(struct in6_addr));
877 }
878 break;
879 #endif
880 }
881 plog(PLOG_INFO, PLOGLOC, 0, "move child_sa(%p)\n", child_sa);
882 }
883
884 ikev2_migrate_script_hook(ike_sa, param->sa_src, param->sa_dst,
885 param->sa2_src, param->sa2_dst);
886
887 v1:
888 #ifdef IKEV1
889 /* migrate the ISAKMP SA (aka phase 1) */
890
891 iph1 = getph1bydstaddrwop(param->sa_dst);
892 if (iph1 == NULL)
893 return 0;
894 plog(PLOG_INFO, PLOGLOC, 0, "move ikev1_ph1(%p): from %s -> %s\n",
895 iph1, rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
896
897 switch (iph1->remote->sa_family) {
898 case AF_INET:
899 ((struct sockaddr_in *)iph1->local)->sin_addr =
900 ((struct sockaddr_in *)param->sa2_src)->sin_addr;
901 ((struct sockaddr_in *)iph1->remote)->sin_addr =
902 ((struct sockaddr_in *)param->sa2_dst)->sin_addr;
903 #ifdef INET6
904 case AF_INET6:
905 memcpy(&((struct sockaddr_in6 *)iph1->local)->sin6_addr,
906 &((struct sockaddr_in6 *)param->sa2_src)->sin6_addr,
907 sizeof(struct in6_addr));
908 memcpy(&((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
909 &((struct sockaddr_in6 *)param->sa2_dst)->sin6_addr,
910 sizeof(struct in6_addr));
911 break;
912 #endif
913 default:
914 return -1;
915 }
916 plog(PLOG_INFO, PLOGLOC, 0, "move ikev1_ph1(%p): to %s -> %s\n",
917 iph1, rcs_sa2str(iph1->local), rcs_sa2str(iph1->remote));
918
919 /* migrate children aka phases 2 */
920
921 LIST_FOREACH(iph2, &iph1->ph2tree, ph1bind) {
922 if (!iph2->selector)
923 continue;
924 if (param->reqid != iph2->selector->reqid)
925 continue;
926 switch (iph1->remote->sa_family) {
927 case AF_INET:
928 if (iph2->src)
929 ((struct sockaddr_in *)iph2->src)->sin_addr =
930 ((struct sockaddr_in *)iph1->local)->sin_addr;
931 if (iph2->dst)
932 ((struct sockaddr_in *)iph2->dst)->sin_addr =
933 ((struct sockaddr_in *)iph1->remote)->sin_addr;
934
935 policy = iph2->selector->pl;
936 if (policy->my_sa_ipaddr) {
937 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
938 TRACE((PLOGLOC, "unexpected type\n"));
939 continue;
940 }
941 ((struct sockaddr_in *)policy->my_sa_ipaddr->a.ipaddr)->sin_addr =
942 ((struct sockaddr_in *)iph1->local)->sin_addr;
943 }
944 if (policy->peers_sa_ipaddr) {
945 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
946 TRACE((PLOGLOC, "unexpected type\n"));
947 continue;
948 }
949 ((struct sockaddr_in *)policy->peers_sa_ipaddr->a.ipaddr)->sin_addr =
950 ((struct sockaddr_in *)iph1->local)->sin_addr;
951 }
952 break;
953 #ifdef INET6
954 case AF_INET6:
955 if (iph2->src)
956 memcpy(&((struct sockaddr_in6 *)iph2->src)->sin6_addr,
957 &((struct sockaddr_in6 *)iph1->local)->sin6_addr,
958 sizeof(struct in6_addr));
959 if (iph2->dst)
960 memcpy(&((struct sockaddr_in6 *)iph2->dst)->sin6_addr,
961 &((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
962 sizeof(struct in6_addr));
963
964 policy = iph2->selector->pl;
965 if (policy->my_sa_ipaddr) {
966 if (policy->my_sa_ipaddr->type != RCT_ADDR_INET) {
967 TRACE((PLOGLOC, "unexpected type\n"));
968 continue;
969 }
970 memcpy(&((struct sockaddr_in6 *)policy->my_sa_ipaddr->a.ipaddr)->sin6_addr,
971 &((struct sockaddr_in6 *)iph1->local)->sin6_addr,
972 sizeof(struct in6_addr));
973 }
974 if (policy->peers_sa_ipaddr) {
975 if (policy->peers_sa_ipaddr->type != RCT_ADDR_INET) {
976 TRACE((PLOGLOC, "unexpected type\n"));
977 continue;
978 }
979 memcpy(&((struct sockaddr_in6 *)policy->peers_sa_ipaddr->a.ipaddr)->sin6_addr,
980 &((struct sockaddr_in6 *)iph1->remote)->sin6_addr,
981 sizeof(struct in6_addr));
982 }
983 break;
984 #endif
985 }
986 plog(PLOG_INFO, PLOGLOC, 0, "move iph2(%p)\n", iph2);
987 }
988
989 ikev1_migrate_script_hook(iph1, param->sa_src, param->sa_dst,
990 param->sa2_src, param->sa2_dst);
991
992 #endif
993 return 0;
994 }
995 #endif
996
997 /* #ifdef DEBUG */
998 static int sadb_debug_getspi(struct rcpfk_msg *param);
999 static int sadb_debug_acquire_error(struct rcpfk_msg *param);
1000 static int sadb_debug_update(struct rcpfk_msg *param);
1001 static int sadb_debug_add(struct rcpfk_msg *param);
1002 static int sadb_debug_delete(struct rcpfk_msg *param);
1003
1004 struct sadb_request_method sadb_debug_method = {
1005 sadb_debug_getspi,
1006 sadb_debug_acquire_error,
1007 sadb_debug_update,
1008 sadb_debug_add,
1009 sadb_debug_delete,
1010 };
1011
1012 uint32_t debug_spi = 0x10000;
1013
1014 static int
1015 sadb_debug_getspi(struct rcpfk_msg *param)
1016 {
1017 int err;
1018
1019 TRACE((PLOGLOC, "sadb_debug_getspi: seq=%d, satype=%d\n",
1020 param->seq, param->satype));
1021
1022 param->spi = htonl(debug_spi++);
1023 err = sadb_getspi_callback(param);
1024 TRACE((PLOGLOC, "sadb_getspi_callback retval %d\n", err));
1025 return 0;
1026 }
1027
1028 static int
1029 sadb_debug_acquire_error(struct rcpfk_msg *param)
1030 {
1031 TRACE((PLOGLOC,
1032 "sadb_debug_acquire_error: seq=%d, satype=%d, spi=0x%08x, errno=%d\n",
1033 param->seq, param->satype, ntohl(param->spi), param->eno));
1034 return 0;
1035 }
1036
1037 static int
1038 sadb_debug_update(struct rcpfk_msg *param)
1039 {
1040 dump_param("sadb_debug_update", param);
1041 return 0;
1042 }
1043
1044 static int
1045 sadb_debug_add(struct rcpfk_msg *param)
1046 {
1047 dump_param("sadb_debug_add", param);
1048 return 0;
1049 }
1050
1051 static int
1052 sadb_debug_delete(struct rcpfk_msg *param)
1053 {
1054 dump_param("sadb_debug_delete", param);
1055 return 0;
1056 }
1057
1058 /*
1059 * dump add/update parameters
1060 */
1061 static void
1062 dump_param(char *msg, struct rcpfk_msg *param)
1063 {
1064 int i;
1065 char buf[BUFSIZ];
1066 char *bufp;
1067 ssize_t buflen;
1068
1069 #define DUMP(x_) do { \
1070 buflen -= strlen(bufp); \
1071 bufp += strlen(bufp); \
1072 if (buflen > 0) { \
1073 x_; \
1074 } \
1075 } while (0)
1076
1077 buf[0] = '\0';
1078 bufp = &buf[0];
1079 buflen = sizeof(buf) - 1;
1080 DUMP(snprintf(bufp, buflen,
1081 "%s: seq=%d, ul_proto=%d sa_src=%s/%d, sa_dst=%s/%d, "
1082 "satype=%d (%s), spi=0x%08x, wsize=%d, "
1083 "authtype=%d (%s), enctype=%d (%s), saflags=0x%x, "
1084 "samode=%d (%s), reqid=%d, "
1085 "lifetime hard time %" PRIu64 ", bytes %" PRIu64 ", "
1086 "lifetime soft time %" PRIu64 ", bytes %" PRIu64 ", "
1087 "enckey len=%lu [",
1088 msg,
1089 param->seq, param->ul_proto,
1090 rcs_sa2str(param->sa_src), param->pref_src,
1091 rcs_sa2str(param->sa_dst), param->pref_dst,
1092 param->satype, rct2str(param->satype),
1093 ntohl(param->spi), param->wsize,
1094 param->authtype, rct2str(param->authtype),
1095 param->enctype, rct2str(param->enctype),
1096 param->saflags,
1097 param->samode, rct2str(param->samode),
1098 param->reqid,
1099 param->lft_hard_time, param->lft_hard_bytes,
1100 param->lft_soft_time, param->lft_soft_bytes,
1101 (unsigned long)param->enckeylen));
1102 for (i = 0; i < (int)param->enckeylen; ++i) {
1103 DUMP(snprintf(bufp, buflen,
1104 "%02x", ((uint8_t *)param->enckey)[i]));
1105 }
1106 DUMP(snprintf(bufp, buflen, "], authkey len=%lu [",
1107 (unsigned long)param->authkeylen));
1108 for (i = 0; i < (int)param->authkeylen; ++i) {
1109 DUMP(snprintf(bufp, buflen,
1110 "%02x", ((uint8_t *)param->authkey)[i]));
1111 }
1112 DUMP(snprintf(bufp, buflen, "]\n"));
1113
1114 TRACE((PLOGLOC, "%s", buf));
1115 }
1116
1117 #ifdef DEBUG
1118 #include <sys/socket.h>
1119 #include <netdb.h>
1120
1121 void
1122 debug_initiate(char *addr, const char *selector_index)
1123 {
1124 struct isakmp_acquire_request *req;
1125 struct addrinfo *res;
1126 int err;
1127
1128 req = racoon_calloc(1, sizeof(*req));
1129
1130 err = getaddrinfo(addr, 0, 0, &res);
1131 if (err) {
1132 fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
1133 return;
1134 }
1135 if (!res) {
1136 fprintf(stderr, "res is null\n");
1137 return;
1138 }
1139 if (!res->ai_addr) {
1140 fprintf(stderr, "res->ai_addr is null\n");
1141 return;
1142 }
1143
1144 req->callback_method = &sadb_debug_method;
1145 req->request_msg_seq = 1;
1146 req->dst = rcs_sadup(res->ai_addr);
1147 isakmp_initiate_cont(req, selector_index);
1148
1149 freeaddrinfo(res);
1150 }
1151 #endif
1152 /* #endif */