blob: 3aae6d3a1f4abdc3a04becf8626a9d9764649646 [file] [log] [blame]
Ed Warnickecb9cada2015-12-08 15:45:58 -07001/*
2 * Copyright (c) 2015 Cisco and/or its affiliates.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at:
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
Damjan Marione936bbe2016-02-25 23:17:38 +010016#include <ctype.h>
17
Ed Warnickecb9cada2015-12-08 15:45:58 -070018#include <vnet/vnet.h>
19#include <vnet/api_errno.h>
20#include <vnet/ip/ip.h>
21#include <vnet/interface.h>
22
23#include <vnet/ipsec/ipsec.h>
24#include <vnet/ipsec/ikev2.h>
25#include <vnet/ipsec/ikev2_priv.h>
26
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070027/* *INDENT-OFF* */
28typedef CLIB_PACKED (struct
29 {
30 u8 nextpayload;
31 u8 flags;
32 u16 length;
33 u8 protocol_id;
34 u8 spi_size;
35 u16 msg_type;
36 u8 payload[0];}) ike_notify_payload_header_t;
37/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070038
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070039/* *INDENT-OFF* */
40typedef CLIB_PACKED (struct
41 {
42 u8 ts_type;
43 u8 protocol_id;
44 u16 selector_len;
45 u16 start_port;
46 u16 end_port;
47 ip4_address_t start_addr;
48 ip4_address_t end_addr;}) ikev2_ts_payload_entry_t;
49/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070050
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070051/* *INDENT-OFF* */
52typedef CLIB_PACKED (struct
53 {
54 u8 nextpayload;
55 u8 flags;
56 u16 length;
57 u8 num_ts;
58 u8 reserved[3];
59 ikev2_ts_payload_entry_t ts[0];})
60 ike_ts_payload_header_t;
61/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070062
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070063/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070064typedef CLIB_PACKED (struct {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070065 u8 last_or_more;
66 u8 reserved;
67 u16 proposal_len;
68 u8 proposal_num;
69 u8 protocol_id;
70 u8 spi_size;
71 u8 num_transforms; u32 spi[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -070072}) ike_sa_proposal_data_t;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070073/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070074
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070075/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070076typedef CLIB_PACKED (struct {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070077 u8 last_or_more;
78 u8 reserved;
79 u16 transform_len;
80 u8 transform_type;
81 u8 reserved2;
82 u16 transform_id;
83 u8 attributes[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -070084}) ike_sa_transform_data_t;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070085/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070086
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070087/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070088typedef CLIB_PACKED (struct {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070089 u8 nextpayload;
90 u8 flags;
91 u16 length;
92 u8 protocol_id;
93 u8 spi_size;
94 u16 num_of_spi;
95 u32 spi[0];
Ed Warnickecb9cada2015-12-08 15:45:58 -070096}) ike_delete_payload_header_t;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -070097/* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070098
99static ike_payload_header_t *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700100ikev2_payload_add_hdr (ikev2_payload_chain_t * c, u8 payload_type, int len)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700101{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700102 ike_payload_header_t *hdr =
103 (ike_payload_header_t *) & c->data[c->last_hdr_off];
104 u8 *tmp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700105
106 if (c->data)
107 hdr->nextpayload = payload_type;
108 else
109 c->first_payload_type = payload_type;
110
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700111 c->last_hdr_off = vec_len (c->data);
112 vec_add2 (c->data, tmp, len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113 hdr = (ike_payload_header_t *) tmp;
Dave Barachb7b92992018-10-17 10:38:51 -0400114 clib_memset (hdr, 0, len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700115
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700116 hdr->length = clib_host_to_net_u16 (len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700117
118 return hdr;
119}
120
121static void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700122ikev2_payload_add_data (ikev2_payload_chain_t * c, u8 * data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700123{
124 u16 len;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700125 ike_payload_header_t *hdr;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700126
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700127 vec_append (c->data, data);
128 hdr = (ike_payload_header_t *) & c->data[c->last_hdr_off];
129 len = clib_net_to_host_u16 (hdr->length);
130 hdr->length = clib_host_to_net_u16 (len + vec_len (data));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700131}
132
133void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700134ikev2_payload_add_notify (ikev2_payload_chain_t * c, u16 msg_type, u8 * data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700135{
Radu Nicolaucb33dc22017-02-16 16:49:46 +0000136 ikev2_payload_add_notify_2(c, msg_type, data, 0);
137}
138
139void
140ikev2_payload_add_notify_2 (ikev2_payload_chain_t * c, u16 msg_type,
141 u8 * data, ikev2_notify_t * notify)
142{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700143 ike_notify_payload_header_t *n;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700144
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700145 n =
146 (ike_notify_payload_header_t *) ikev2_payload_add_hdr (c,
Radu Nicolaucb33dc22017-02-16 16:49:46 +0000147 IKEV2_PAYLOAD_NOTIFY,
148 sizeof (*n));
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700149 n->msg_type = clib_host_to_net_u16 (msg_type);
Radu Nicolaucb33dc22017-02-16 16:49:46 +0000150 if (notify)
151 {
152 n->protocol_id = notify->protocol_id;
153 if (notify->spi)
154 {
155 n->spi_size = 4;
156 }
157 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700158 ikev2_payload_add_data (c, data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700159}
160
161void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700162ikev2_payload_add_sa (ikev2_payload_chain_t * c,
163 ikev2_sa_proposal_t * proposals)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700164{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700165 ike_payload_header_t *ph;
166 ike_sa_proposal_data_t *prop;
167 ike_sa_transform_data_t *tr;
168 ikev2_sa_proposal_t *p;
169 ikev2_sa_transform_t *t;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700170
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700171 u8 *tmp;
172 u8 *pr_data = 0;
173 u8 *tr_data = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700174
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700175 ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_SA, sizeof (*ph));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700176
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700177 vec_foreach (p, proposals)
178 {
179 int spi_size = (p->protocol_id == IKEV2_PROTOCOL_ESP) ? 4 : 0;
180 pr_data = vec_new (u8, sizeof (ike_sa_proposal_data_t) + spi_size);
181 prop = (ike_sa_proposal_data_t *) pr_data;
182 prop->last_or_more = proposals - p + 1 < vec_len (proposals) ? 2 : 0;
183 prop->protocol_id = p->protocol_id;
184 prop->proposal_num = p->proposal_num;
185 prop->spi_size = spi_size;
186 prop->num_transforms = vec_len (p->transforms);
187
188 if (spi_size)
189 prop->spi[0] = clib_host_to_net_u32 (p->spi);
190
191 DBG_PLD ("proposal num %u protocol_id %u last_or_more %u spi_size %u%s%U",
192 prop->proposal_num, prop->protocol_id, prop->last_or_more,
193 prop->spi_size, prop->spi_size ? " spi_data " : "",
194 format_hex_bytes, prop->spi, prop->spi_size);
195
196 vec_foreach (t, p->transforms)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700197 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700198 vec_add2 (tr_data, tmp, sizeof (*tr) + vec_len (t->attrs));
199 tr = (ike_sa_transform_data_t *) tmp;
200 tr->last_or_more =
201 ((t - p->transforms) + 1 < vec_len (p->transforms)) ? 3 : 0;
202 tr->transform_type = t->type;
203 tr->transform_id = clib_host_to_net_u16 (t->transform_id);
204 tr->transform_len =
205 clib_host_to_net_u16 (sizeof (*tr) + vec_len (t->attrs));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700206
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700207 if (vec_len (t->attrs) > 0)
Dave Barach178cf492018-11-13 16:34:13 -0500208 clib_memcpy_fast (tr->attributes, t->attrs, vec_len (t->attrs));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700209
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700210 DBG_PLD
211 ("transform type %U transform_id %u last_or_more %u attr_size %u%s%U",
212 format_ikev2_transform_type, tr->transform_type, t->transform_id,
213 tr->last_or_more, vec_len (t->attrs),
214 vec_len (t->attrs) ? " attrs " : "", format_hex_bytes,
215 tr->attributes, vec_len (t->attrs));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700216 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700217
218 prop->proposal_len =
219 clib_host_to_net_u16 (vec_len (tr_data) + vec_len (pr_data));
220 ikev2_payload_add_data (c, pr_data);
221 ikev2_payload_add_data (c, tr_data);
222 vec_free (pr_data);
223 vec_free (tr_data);
224 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700225}
226
227void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700228ikev2_payload_add_ke (ikev2_payload_chain_t * c, u16 dh_group, u8 * dh_data)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700229{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700230 ike_ke_payload_header_t *ke;
231 ke = (ike_ke_payload_header_t *) ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_KE,
232 sizeof (*ke));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700233
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700234 ke->dh_group = clib_host_to_net_u16 (dh_group);
235 ikev2_payload_add_data (c, dh_data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700236}
237
238void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700239ikev2_payload_add_nonce (ikev2_payload_chain_t * c, u8 * nonce)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700240{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700241 ikev2_payload_add_hdr (c, IKEV2_PAYLOAD_NONCE,
242 sizeof (ike_payload_header_t));
243 ikev2_payload_add_data (c, nonce);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244}
245
246void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700247ikev2_payload_add_id (ikev2_payload_chain_t * c, ikev2_id_t * id, u8 type)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700248{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700249 ike_id_payload_header_t *idp;
250 idp =
251 (ike_id_payload_header_t *) ikev2_payload_add_hdr (c, type,
252 sizeof (*idp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700253
254 idp->id_type = id->type;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700255 ikev2_payload_add_data (c, id->data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256}
257
258void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700259ikev2_payload_add_delete (ikev2_payload_chain_t * c, ikev2_delete_t * d)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700260{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700261 ike_delete_payload_header_t *dp;
262 u16 num_of_spi = vec_len (d);
263 ikev2_delete_t *d2;
264 dp =
265 (ike_delete_payload_header_t *) ikev2_payload_add_hdr (c,
266 IKEV2_PAYLOAD_DELETE,
267 sizeof (*dp));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700268
269 if (d[0].protocol_id == IKEV2_PROTOCOL_IKE)
270 {
271 dp->protocol_id = 1;
272 }
273 else
274 {
275 dp->protocol_id = d[0].protocol_id;
276 dp->spi_size = 4;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700277 dp->num_of_spi = clib_host_to_net_u16 (num_of_spi);
278 vec_foreach (d2, d)
279 {
280 u8 *data = vec_new (u8, 4);
281 u32 spi = clib_host_to_net_u32 (d2->spi);
282 clib_memcpy (data, &spi, 4);
283 ikev2_payload_add_data (c, data);
284 vec_free (data);
285 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700286 }
287}
288
289void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700290ikev2_payload_add_auth (ikev2_payload_chain_t * c, ikev2_auth_t * auth)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700291{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700292 ike_auth_payload_header_t *ap;
293 ap =
294 (ike_auth_payload_header_t *) ikev2_payload_add_hdr (c,
295 IKEV2_PAYLOAD_AUTH,
296 sizeof (*ap));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700297
298 ap->auth_method = auth->method;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700299 ikev2_payload_add_data (c, auth->data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700300}
301
302void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700303ikev2_payload_add_ts (ikev2_payload_chain_t * c, ikev2_ts_t * ts, u8 type)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700304{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700305 ike_ts_payload_header_t *tsh;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700306 ikev2_ts_t *ts2;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700307 u8 *data = 0, *tmp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700308
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700309 tsh =
310 (ike_ts_payload_header_t *) ikev2_payload_add_hdr (c, type,
311 sizeof (*tsh));
312 tsh->num_ts = vec_len (ts);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700313
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700314 vec_foreach (ts2, ts)
315 {
316 ASSERT (ts2->ts_type == 7); /*TS_IPV4_ADDR_RANGE */
317 ikev2_ts_payload_entry_t *entry;
318 vec_add2 (data, tmp, sizeof (*entry));
319 entry = (ikev2_ts_payload_entry_t *) tmp;
320 entry->ts_type = ts2->ts_type;
321 entry->protocol_id = ts2->protocol_id;
322 entry->selector_len = clib_host_to_net_u16 (16);
323 entry->start_port = clib_host_to_net_u16 (ts2->start_port);
324 entry->end_port = clib_host_to_net_u16 (ts2->end_port);
325 entry->start_addr.as_u32 = ts2->start_addr.as_u32;
326 entry->end_addr.as_u32 = ts2->end_addr.as_u32;
327 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700328
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700329 ikev2_payload_add_data (c, data);
330 vec_free (data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700331}
332
333void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700334ikev2_payload_chain_add_padding (ikev2_payload_chain_t * c, int bs)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700335{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700336 u8 *tmp __attribute__ ((unused));
337 u8 pad_len = (vec_len (c->data) / bs + 1) * bs - vec_len (c->data);
338 vec_add2 (c->data, tmp, pad_len);
339 c->data[vec_len (c->data) - 1] = pad_len - 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700340}
341
342ikev2_sa_proposal_t *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700343ikev2_parse_sa_payload (ike_payload_header_t * ikep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700344{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700345 ikev2_sa_proposal_t *v = 0;
346 ikev2_sa_proposal_t *proposal;
347 ikev2_sa_transform_t *transform;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700348
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700349 u32 plen = clib_net_to_host_u16 (ikep->length);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700351 ike_sa_proposal_data_t *sap;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700352 int proposal_ptr = 0;
353
354 do
355 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700356 sap = (ike_sa_proposal_data_t *) & ikep->payload[proposal_ptr];
Ed Warnickecb9cada2015-12-08 15:45:58 -0700357 int i;
358 int transform_ptr;
359
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700360 DBG_PLD ("proposal num %u len %u last_or_more %u id %u "
361 "spi_size %u num_transforms %u",
362 sap->proposal_num, clib_net_to_host_u16 (sap->proposal_len),
363 sap->last_or_more, sap->protocol_id, sap->spi_size,
364 sap->num_transforms);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700365
366 /* IKE proposal should not have SPI */
367 if (sap->protocol_id == IKEV2_PROTOCOL_IKE && sap->spi_size != 0)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700368 goto data_corrupted;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700369
370 /* IKE proposal should not have SPI */
371 if (sap->protocol_id == IKEV2_PROTOCOL_ESP && sap->spi_size != 4)
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700372 goto data_corrupted;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700373
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700374 transform_ptr = proposal_ptr + sizeof (*sap) + sap->spi_size;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700375
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700376 vec_add2 (v, proposal, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700377 proposal->proposal_num = sap->proposal_num;
378 proposal->protocol_id = sap->protocol_id;
379
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700380 if (sap->spi_size == 4)
381 {
382 proposal->spi = clib_net_to_host_u32 (sap->spi[0]);
383 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700385 for (i = 0; i < sap->num_transforms; i++)
386 {
387 ike_sa_transform_data_t *tr =
388 (ike_sa_transform_data_t *) & ikep->payload[transform_ptr];
389 u16 tlen = clib_net_to_host_u16 (tr->transform_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700390
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700391 if (tlen < sizeof (*tr))
392 goto data_corrupted;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700394 vec_add2 (proposal->transforms, transform, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700396 transform->type = tr->transform_type;
397 transform->transform_id = clib_net_to_host_u16 (tr->transform_id);
398 if (tlen > sizeof (*tr))
399 vec_add (transform->attrs, tr->attributes, tlen - sizeof (*tr));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700400
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700401 DBG_PLD
402 ("transform num %u len %u last_or_more %u type %U id %u%s%U", i,
403 tlen, tr->last_or_more, format_ikev2_sa_transform, transform,
404 clib_net_to_host_u16 (tr->transform_id),
405 tlen > sizeof (*tr) ? " attrs " : "", format_hex_bytes,
406 tr->attributes, tlen - sizeof (*tr));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700407
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700408 transform_ptr += tlen;
409 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700410
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700411 proposal_ptr += clib_net_to_host_u16 (sap->proposal_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700412 }
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700413 while (proposal_ptr < (plen - sizeof (*ikep)) && sap->last_or_more == 2);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700414
415 /* data validation */
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700416 if (proposal_ptr != (plen - sizeof (*ikep)) || sap->last_or_more)
417 goto data_corrupted;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700418
419 return v;
420
421data_corrupted:
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700422 DBG_PLD ("SA payload data corrupted");
423 ikev2_sa_free_proposal_vector (&v);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700424 return 0;
425}
426
427ikev2_ts_t *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700428ikev2_parse_ts_payload (ike_payload_header_t * ikep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700429{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700430 ike_ts_payload_header_t *tsp = (ike_ts_payload_header_t *) ikep;
431 ikev2_ts_t *r = 0, *ts;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432 u8 i;
433
434 for (i = 0; i < tsp->num_ts; i++)
435 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700436 if (tsp->ts[i].ts_type != 7) /* TS_IPV4_ADDR_RANGE */
437 {
438 DBG_PLD ("unsupported TS type received (%u)", tsp->ts[i].ts_type);
439 continue;
440 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700441
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700442 vec_add2 (r, ts, 1);
443 ts->ts_type = tsp->ts[i].ts_type;
444 ts->protocol_id = tsp->ts[i].protocol_id;
445 ts->start_port = tsp->ts[i].start_port;
446 ts->end_port = tsp->ts[i].end_port;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700447 ts->start_addr.as_u32 = tsp->ts[i].start_addr.as_u32;
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700448 ts->end_addr.as_u32 = tsp->ts[i].end_addr.as_u32;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700449 }
450 return r;
451}
452
453ikev2_notify_t *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700454ikev2_parse_notify_payload (ike_payload_header_t * ikep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700455{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700456 ike_notify_payload_header_t *n = (ike_notify_payload_header_t *) ikep;
457 u32 plen = clib_net_to_host_u16 (ikep->length);
458 ikev2_notify_t *r = 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459 u32 spi;
460
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700461 DBG_PLD ("msg_type %U len %u%s%U",
462 format_ikev2_notify_msg_type, clib_net_to_host_u16 (n->msg_type),
463 plen, plen > sizeof (*n) ? " data " : "",
464 format_hex_bytes, n->payload, plen - sizeof (*n));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700465
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700466 r = vec_new (ikev2_notify_t, 1);
467 r->msg_type = clib_net_to_host_u16 (n->msg_type);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700468 r->protocol_id = n->protocol_id;
469
470 if (n->spi_size == 4)
471 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700472 clib_memcpy (&spi, n->payload, n->spi_size);
473 r->spi = clib_net_to_host_u32 (spi);
474 DBG_PLD ("spi %lx", r->spi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700475 }
476 else if (n->spi_size == 0)
477 {
478 r->spi = 0;
479 }
480 else
481 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700482 clib_warning ("invalid SPI Size %d", n->spi_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700483 }
484
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700485 if (plen > (sizeof (*n) + n->spi_size))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700486 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700487 vec_add (r->data, n->payload + n->spi_size,
488 plen - sizeof (*n) - n->spi_size);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700489 }
490
491 return r;
492}
493
494void
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700495ikev2_parse_vendor_payload (ike_payload_header_t * ikep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700496{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700497 u32 plen = clib_net_to_host_u16 (ikep->length);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700498 int i;
499 int is_string = 1;
500
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700501 for (i = 0; i < plen - 4; i++)
502 if (!isprint (ikep->payload[i]))
Ed Warnickecb9cada2015-12-08 15:45:58 -0700503 is_string = 0;
504
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700505 DBG_PLD ("len %u data %s:%U",
506 plen,
507 is_string ? "string" : "hex",
508 is_string ? format_ascii_bytes : format_hex_bytes,
509 ikep->payload, plen - sizeof (*ikep));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700510}
511
512ikev2_delete_t *
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700513ikev2_parse_delete_payload (ike_payload_header_t * ikep)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700514{
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700515 ike_delete_payload_header_t *d = (ike_delete_payload_header_t *) ikep;
516 u32 plen = clib_net_to_host_u16 (ikep->length);
517 ikev2_delete_t *r = 0, *del;
518 u16 num_of_spi = clib_net_to_host_u16 (d->num_of_spi);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700519 u16 i = 0;
520
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700521 DBG_PLD ("protocol_id %u spi_size %u num_of_spi %u len %u%s%U",
522 d->protocol_id, d->spi_size, num_of_spi,
523 plen, plen > sizeof (d) ? " data " : "",
524 format_hex_bytes, d->spi, plen - sizeof (*d));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525
526 if (d->protocol_id == IKEV2_PROTOCOL_IKE)
527 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700528 r = vec_new (ikev2_delete_t, 1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700529 r->protocol_id = 1;
530 }
531 else
532 {
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700533 r = vec_new (ikev2_delete_t, num_of_spi);
534 vec_foreach (del, r)
535 {
536 del->protocol_id = d->protocol_id;
537 del->spi = clib_net_to_host_u32 (d->spi[i++]);
538 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700539 }
540
541 return r;
542}
Keith Burns (alagalah)166a9d42016-08-06 11:00:56 -0700543
544/*
545 * fd.io coding-style-patch-verification: ON
546 *
547 * Local Variables:
548 * eval: (c-set-style "gnu")
549 * End:
550 */