Coverage Report

Created: 2026-11-12 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/strongswan/src/libcharon/encoding/payloads/ts_payload.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2005-2010 Martin Willi
3
 * Copyright (C) 2005 Jan Hutter
4
 *
5
 * Copyright (C) secunet Security Networks AG
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by the
9
 * Free Software Foundation; either version 2 of the License, or (at your
10
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
11
 *
12
 * This program is distributed in the hope that it will be useful, but
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15
 * for more details.
16
 */
17
18
#include <stddef.h>
19
20
#include "ts_payload.h"
21
22
#include <encoding/payloads/encodings.h>
23
#include <collections/linked_list.h>
24
25
typedef struct private_ts_payload_t private_ts_payload_t;
26
27
/**
28
 * Private data of an ts_payload_t object.
29
 */
30
struct private_ts_payload_t {
31
32
  /**
33
   * Public ts_payload_t interface.
34
   */
35
  ts_payload_t public;
36
37
  /**
38
   * TRUE if this TS payload is of type TSi, FALSE for TSr.
39
   */
40
  bool is_initiator;
41
42
  /**
43
   * Next payload type.
44
   */
45
  uint8_t  next_payload;
46
47
  /**
48
   * Critical flag.
49
   */
50
  bool critical;
51
52
  /**
53
   * reserved bits
54
   */
55
  bool reserved_bit[7];
56
57
  /**
58
   * reserved bytes
59
   */
60
  bool reserved_byte[3];
61
62
  /**
63
   * Length of this payload.
64
   */
65
  uint16_t payload_length;
66
67
  /**
68
   * Number of traffic selectors
69
   */
70
  uint8_t ts_num;
71
72
  /**
73
   * Contains the traffic selectors of type traffic_selector_substructure_t.
74
   */
75
  linked_list_t *substrs;
76
};
77
78
/**
79
 * Encoding rules to parse or generate a TS payload
80
 *
81
 * The defined offsets are the positions in a object of type
82
 * private_ts_payload_t.
83
 */
84
static encoding_rule_t encodings[] = {
85
  /* 1 Byte next payload type, stored in the field next_payload */
86
  { U_INT_8,      offsetof(private_ts_payload_t, next_payload)  },
87
  /* the critical bit */
88
  { FLAG,       offsetof(private_ts_payload_t, critical)    },
89
  /* 7 Bit reserved bits */
90
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[0]) },
91
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[1]) },
92
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[2]) },
93
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[3]) },
94
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[4]) },
95
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[5]) },
96
  { RESERVED_BIT,   offsetof(private_ts_payload_t, reserved_bit[6]) },
97
  /* Length of the whole payload*/
98
  { PAYLOAD_LENGTH, offsetof(private_ts_payload_t, payload_length)  },
99
  /* 1 Byte TS type*/
100
  { U_INT_8,      offsetof(private_ts_payload_t, ts_num)      },
101
  /* 3 reserved bytes */
102
  { RESERVED_BYTE,  offsetof(private_ts_payload_t, reserved_byte[0])},
103
  { RESERVED_BYTE,  offsetof(private_ts_payload_t, reserved_byte[1])},
104
  { RESERVED_BYTE,  offsetof(private_ts_payload_t, reserved_byte[2])},
105
  /* wrapped list of traffic selectors substructures */
106
  { PAYLOAD_LIST + PLV2_TRAFFIC_SELECTOR_SUBSTRUCTURE,
107
            offsetof(private_ts_payload_t, substrs)     },
108
};
109
110
/*
111
                           1                   2                   3
112
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
113
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
114
      ! Next Payload  !C!  RESERVED   !         Payload Length        !
115
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
116
      ! Number of TSs !                 RESERVED                      !
117
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
118
      !                                                               !
119
      ~                       <Traffic Selectors>                     ~
120
      !                                                               !
121
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122
*/
123
124
METHOD(payload_t, verify, status_t,
125
  private_ts_payload_t *this)
126
2.07k
{
127
2.07k
  enumerator_t *enumerator;
128
2.07k
  payload_t *substr;
129
2.07k
  status_t status = SUCCESS;
130
131
2.07k
  if (this->ts_num != this->substrs->get_count(this->substrs))
132
27
  {
133
27
    return FAILED;
134
27
  }
135
2.04k
  enumerator = this->substrs->create_enumerator(this->substrs);
136
3.83k
  while (enumerator->enumerate(enumerator, &substr))
137
1.86k
  {
138
1.86k
    status = substr->verify(substr);
139
1.86k
    if (status != SUCCESS)
140
70
    {
141
70
      break;
142
70
    }
143
1.86k
  }
144
2.04k
  enumerator->destroy(enumerator);
145
146
2.04k
  return status;
147
2.07k
}
148
149
METHOD(payload_t, get_encoding_rules, int,
150
  private_ts_payload_t *this, encoding_rule_t **rules)
151
2.15k
{
152
2.15k
  *rules = encodings;
153
2.15k
  return countof(encodings);
154
2.15k
}
155
156
METHOD(payload_t, get_header_length, int,
157
  private_ts_payload_t *this)
158
33.6k
{
159
33.6k
  return 8;
160
33.6k
}
161
162
METHOD(payload_t, get_type, payload_type_t,
163
  private_ts_payload_t *this)
164
1.98k
{
165
1.98k
  if (this->is_initiator)
166
767
  {
167
767
    return PLV2_TS_INITIATOR;
168
767
  }
169
1.22k
  return PLV2_TS_RESPONDER;
170
1.98k
}
171
172
METHOD(payload_t, get_next_type, payload_type_t,
173
  private_ts_payload_t *this)
174
1.97k
{
175
1.97k
  return this->next_payload;
176
1.97k
}
177
178
METHOD(payload_t, set_next_type, void,
179
  private_ts_payload_t *this,payload_type_t type)
180
0
{
181
0
  this->next_payload = type;
182
0
}
183
184
/**
185
 * recompute the length of the payload.
186
 */
187
static void compute_length(private_ts_payload_t *this)
188
0
{
189
0
  enumerator_t *enumerator;
190
0
  payload_t *subst;
191
192
0
  this->payload_length = get_header_length(this);
193
0
  this->ts_num = 0;
194
0
  enumerator = this->substrs->create_enumerator(this->substrs);
195
0
  while (enumerator->enumerate(enumerator, &subst))
196
0
  {
197
0
    this->payload_length += subst->get_length(subst);
198
0
    this->ts_num++;
199
0
  }
200
0
  enumerator->destroy(enumerator);
201
0
}
202
203
METHOD(payload_t, get_length, size_t,
204
  private_ts_payload_t *this)
205
0
{
206
0
  return this->payload_length;
207
0
}
208
209
METHOD(ts_payload_t, get_initiator, bool,
210
  private_ts_payload_t *this)
211
0
{
212
0
  return this->is_initiator;
213
0
}
214
215
METHOD(ts_payload_t, set_initiator, void,
216
  private_ts_payload_t *this,bool is_initiator)
217
0
{
218
0
  this->is_initiator = is_initiator;
219
0
}
220
221
/**
222
 * Get a list of either traffic selectors or labels
223
 */
224
static linked_list_t *get_list(private_ts_payload_t *this, bool labels)
225
0
{
226
0
  enumerator_t *enumerator;
227
0
  traffic_selector_substructure_t *subst;
228
0
  linked_list_t *list;
229
230
0
  list = linked_list_create();
231
0
  enumerator = this->substrs->create_enumerator(this->substrs);
232
0
  while (enumerator->enumerate(enumerator, &subst))
233
0
  {
234
0
    if (labels)
235
0
    {
236
0
      sec_label_t *label = subst->get_sec_label(subst);
237
238
0
      if (label)
239
0
      {
240
0
        list->insert_last(list, label);
241
0
      }
242
0
    }
243
0
    else
244
0
    {
245
0
      traffic_selector_t *ts = subst->get_traffic_selector(subst);
246
247
0
      if (ts)
248
0
      {
249
0
        list->insert_last(list, ts);
250
0
      }
251
0
    }
252
0
  }
253
0
  enumerator->destroy(enumerator);
254
255
0
  return list;
256
0
}
257
258
METHOD(ts_payload_t, get_traffic_selectors, linked_list_t*,
259
  private_ts_payload_t *this)
260
0
{
261
0
  return get_list(this, FALSE);
262
0
}
263
264
METHOD(ts_payload_t, get_sec_labels, linked_list_t*,
265
  private_ts_payload_t *this)
266
0
{
267
0
  return get_list(this, TRUE);
268
0
}
269
270
METHOD2(payload_t, ts_payload_t, destroy, void,
271
  private_ts_payload_t *this)
272
2.15k
{
273
2.15k
  this->substrs->destroy_offset(this->substrs, offsetof(payload_t, destroy));
274
2.15k
  free(this);
275
2.15k
}
276
277
/*
278
 * Described in header
279
 */
280
ts_payload_t *ts_payload_create(bool is_initiator)
281
2.15k
{
282
2.15k
  private_ts_payload_t *this;
283
284
2.15k
  INIT(this,
285
2.15k
    .public = {
286
2.15k
      .payload_interface = {
287
2.15k
        .verify = _verify,
288
2.15k
        .get_encoding_rules = _get_encoding_rules,
289
2.15k
        .get_header_length = _get_header_length,
290
2.15k
        .get_length = _get_length,
291
2.15k
        .get_next_type = _get_next_type,
292
2.15k
        .set_next_type = _set_next_type,
293
2.15k
        .get_type = _get_type,
294
2.15k
        .destroy = _destroy,
295
2.15k
      },
296
2.15k
      .get_initiator = _get_initiator,
297
2.15k
      .set_initiator = _set_initiator,
298
2.15k
      .get_traffic_selectors = _get_traffic_selectors,
299
2.15k
      .get_sec_labels = _get_sec_labels,
300
2.15k
      .destroy = _destroy,
301
2.15k
    },
302
2.15k
    .next_payload = PL_NONE,
303
2.15k
    .payload_length = get_header_length(this),
304
2.15k
    .is_initiator = is_initiator,
305
2.15k
    .substrs = linked_list_create(),
306
2.15k
  );
307
2.15k
  return &this->public;
308
2.15k
}
309
310
/*
311
 * Described in header
312
 */
313
ts_payload_t *ts_payload_create_from_traffic_selectors(bool is_initiator,
314
                      linked_list_t *traffic_selectors,
315
                      sec_label_t *label)
316
0
{
317
0
  enumerator_t *enumerator;
318
0
  traffic_selector_t *ts;
319
0
  traffic_selector_substructure_t *subst;
320
0
  private_ts_payload_t *this;
321
322
0
  this = (private_ts_payload_t*)ts_payload_create(is_initiator);
323
324
0
  enumerator = traffic_selectors->create_enumerator(traffic_selectors);
325
0
  while (enumerator->enumerate(enumerator, &ts))
326
0
  {
327
0
    subst = traffic_selector_substructure_create_from_traffic_selector(ts);
328
0
    this->substrs->insert_last(this->substrs, subst);
329
0
  }
330
0
  enumerator->destroy(enumerator);
331
332
0
  if (label)
333
0
  {
334
0
    subst = traffic_selector_substructure_create_from_sec_label(label);
335
0
    this->substrs->insert_last(this->substrs, subst);
336
0
  }
337
0
  compute_length(this);
338
339
0
  return &this->public;
340
0
}