Coverage Report

Created: 2026-02-26 07:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libcharon/kernel/kernel_handler.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2010 Tobias Brunner
3
 *
4
 * Copyright (C) secunet Security Networks AG
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU General Public License as published by the
8
 * Free Software Foundation; either version 2 of the License, or (at your
9
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
10
 *
11
 * This program is distributed in the hope that it will be useful, but
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14
 * for more details.
15
 */
16
17
#include "kernel_handler.h"
18
19
#include <daemon.h>
20
#include <processing/jobs/acquire_job.h>
21
#include <processing/jobs/delete_child_sa_job.h>
22
#include <processing/jobs/migrate_job.h>
23
#include <processing/jobs/rekey_child_sa_job.h>
24
#include <processing/jobs/roam_job.h>
25
#include <processing/jobs/update_sa_job.h>
26
27
typedef struct private_kernel_handler_t private_kernel_handler_t;
28
29
/**
30
 * Private data of a kernel_handler_t object.
31
 */
32
struct private_kernel_handler_t {
33
34
  /**
35
   * Public part of kernel_handler_t object.
36
   */
37
  kernel_handler_t public;
38
};
39
40
/**
41
 * convert an IP protocol identifier to the IKEv2 specific protocol identifier.
42
 */
43
static inline protocol_id_t proto_ip2ike(uint8_t protocol)
44
0
{
45
0
  switch (protocol)
46
0
  {
47
0
    case IPPROTO_ESP:
48
0
      return PROTO_ESP;
49
0
    case IPPROTO_AH:
50
0
      return PROTO_AH;
51
0
    default:
52
0
      return protocol;
53
0
  }
54
0
}
55
56
METHOD(kernel_listener_t, acquire, bool,
57
  private_kernel_handler_t *this, uint32_t reqid, kernel_acquire_data_t *data)
58
0
{
59
0
  char lbuf[BUF_LEN] = "", cbuf[32] = "", sbuf[32] = "";
60
61
0
  if (data->label)
62
0
  {
63
0
    snprintf(lbuf, sizeof(lbuf), ", label {%s}",
64
0
         data->label->get_string(data->label));
65
0
  }
66
0
  if (data->cpu != CPU_ID_MAX)
67
0
  {
68
0
    snprintf(cbuf, sizeof(cbuf), ", cpu {%u}", data->cpu);
69
0
  }
70
0
  if (data->seq)
71
0
  {
72
0
    snprintf(sbuf, sizeof(sbuf), ", seq {%u}", data->seq);
73
0
  }
74
0
  if (data->src && data->dst)
75
0
  {
76
0
    DBG1(DBG_KNL, "creating acquire job for policy %R === %R with "
77
0
       "reqid {%u}%s%s%s", data->src, data->dst, reqid, lbuf, cbuf, sbuf);
78
0
  }
79
0
  else
80
0
  {
81
0
    DBG1(DBG_KNL, "creating acquire job for policy with reqid {%u}%s%s%s",
82
0
       reqid, lbuf, cbuf, sbuf);
83
0
  }
84
0
  lib->processor->queue_job(lib->processor,
85
0
                (job_t*)acquire_job_create(reqid, data));
86
0
  return TRUE;
87
0
}
88
89
METHOD(kernel_listener_t, expire, bool,
90
  private_kernel_handler_t *this, uint8_t protocol, uint32_t spi,
91
  host_t *dst, bool hard)
92
0
{
93
0
  protocol_id_t proto = proto_ip2ike(protocol);
94
95
0
  DBG1(DBG_KNL, "creating %s job for CHILD_SA %N/0x%08x/%H",
96
0
     hard ? "delete" : "rekey", protocol_id_names, proto, ntohl(spi), dst);
97
98
0
  if (hard)
99
0
  {
100
0
    lib->processor->queue_job(lib->processor,
101
0
        (job_t*)delete_child_sa_job_create(proto, spi, dst, hard));
102
0
  }
103
0
  else
104
0
  {
105
0
    lib->processor->queue_job(lib->processor,
106
0
        (job_t*)rekey_child_sa_job_create(proto, spi, dst));
107
0
  }
108
0
  return TRUE;
109
0
}
110
111
METHOD(kernel_listener_t, mapping, bool,
112
  private_kernel_handler_t *this, uint8_t protocol, uint32_t spi,
113
  host_t *dst, host_t *remote)
114
0
{
115
0
  protocol_id_t proto = proto_ip2ike(protocol);
116
117
0
  DBG1(DBG_KNL, "NAT mappings of CHILD_SA %N/0x%08x/%H changed to %#H, "
118
0
     "queuing update job", protocol_id_names, proto, ntohl(spi), dst,
119
0
     remote);
120
121
0
  lib->processor->queue_job(lib->processor,
122
0
            (job_t*)update_sa_job_create(proto, spi, dst, remote));
123
0
  return TRUE;
124
0
}
125
126
METHOD(kernel_listener_t, migrate, bool,
127
  private_kernel_handler_t *this, uint32_t reqid,
128
  traffic_selector_t *src_ts, traffic_selector_t *dst_ts,
129
  policy_dir_t direction, host_t *local, host_t *remote)
130
0
{
131
0
  DBG1(DBG_KNL, "creating migrate job for policy %R === %R %N with reqid {%u}",
132
0
     src_ts, dst_ts, policy_dir_names, direction, reqid, local);
133
134
0
  lib->processor->queue_job(lib->processor,
135
0
            (job_t*)migrate_job_create(reqid, src_ts, dst_ts,
136
0
                           direction, local, remote));
137
0
  return TRUE;
138
0
}
139
140
METHOD(kernel_listener_t, roam, bool,
141
  private_kernel_handler_t *this, bool address)
142
0
{
143
0
  DBG2(DBG_KNL, "creating roam job %s",
144
0
     address ? "due to address/link change" : "due to route change");
145
146
0
  lib->processor->queue_job(lib->processor, (job_t*)roam_job_create(address));
147
0
  return TRUE;
148
0
}
149
150
METHOD(kernel_handler_t, destroy, void,
151
  private_kernel_handler_t *this)
152
0
{
153
0
  charon->kernel->remove_listener(charon->kernel, &this->public.listener);
154
0
  free(this);
155
0
}
156
157
kernel_handler_t *kernel_handler_create()
158
2
{
159
2
  private_kernel_handler_t *this;
160
161
2
  INIT(this,
162
2
    .public = {
163
2
      .listener = {
164
2
        .acquire = _acquire,
165
2
        .expire = _expire,
166
2
        .mapping = _mapping,
167
2
        .migrate = _migrate,
168
2
        .roam = _roam,
169
2
      },
170
2
      .destroy = _destroy,
171
2
    },
172
2
  );
173
174
2
  charon->kernel->add_listener(charon->kernel, &this->public.listener);
175
176
2
  return &this->public;
177
2
}