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