]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/if_utun_crypto_dtls.c
xnu-3248.60.10.tar.gz
[apple/xnu.git] / bsd / net / if_utun_crypto_dtls.c
CommitLineData
39236c6e
A
1/*
2 * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29#include <sys/systm.h>
30#include <sys/socket.h>
31#include <net/if.h>
32#include <net/if_types.h>
33#include <net/if_utun.h>
34#include <sys/mbuf.h>
35#include <netinet/in.h>
36#include <netinet6/in6_var.h>
37#include <netinet6/in6_var.h>
38#include <netinet/ip.h>
39#include <netinet/ip6.h>
40#include <netinet/ip_var.h>
41#include <net/if_utun.h>
42#include <net/if_utun_crypto_dtls.h>
43#include <net/bpf.h>
44
45extern errno_t utun_pkt_input (struct utun_pcb *pcb, mbuf_t m);
46
47static UInt32 dtls_kpi_callbacks_inited = FALSE;
48static unsigned int dtls_kpi_flags = 0;
49static utun_crypto_kpi_connect_func dtls_kpi_connect = (__typeof__(dtls_kpi_connect))NULL;
50static utun_crypto_kpi_send_func dtls_kpi_send = (__typeof__(dtls_kpi_send))NULL;
51
52// convert this mutex to shared lock
53static UInt32 dtls_ctl_mutex_inited = FALSE;
54static lck_grp_t *dtls_ctl_mutex_grp = NULL;
55static lck_grp_attr_t *dtls_ctl_mutex_grp_attr = NULL;
56static lck_attr_t *dtls_ctl_mutex_attr = NULL;
57static lck_mtx_t dtls_ctl_mutex;
58
59#define utun_ctl_get_first_framer(ctx, inner_type) (utun_crypto_framer_t *)LIST_FIRST(&ctx->framer_listheads[UTUN_CRYPTO_INNER_TYPE_TO_IDX(inner_type)])
60#define utun_get_framer_listhead(ctx, inner_type) &ctx->framer_listheads[UTUN_CRYPTO_INNER_TYPE_TO_IDX(inner_type)]
61
62static void
63utun_ctl_clr_dtls_framer (utun_crypto_framer_t *rem_framer)
64{
65 if (!rem_framer) return;
66
67 // TOFIX: switch to BPF
68 LIST_REMOVE(rem_framer, framer_chain); // unchain the framer
69 if (rem_framer->dir == UTUN_CRYPTO_DIR_IN) {
70 if (utun_crypto_framer_state_dtls_in(rem_framer).in_pattern) {
71 utun_free(utun_crypto_framer_state_dtls_in(rem_framer).in_pattern);
72 }
73 if (utun_crypto_framer_state_dtls_in(rem_framer).in_pattern_mask) {
74 utun_free(utun_crypto_framer_state_dtls_in(rem_framer).in_pattern_mask);
75 }
76 if (utun_crypto_framer_state_dtls_in(rem_framer).in_pattern_masked) {
77 utun_free(utun_crypto_framer_state_dtls_in(rem_framer).in_pattern_masked);
78 }
79 } else {
80 if (utun_crypto_framer_state_dtls_out(rem_framer).out_pattern) {
81 utun_free(utun_crypto_framer_state_dtls_out(rem_framer).out_pattern);
82 }
83 }
84 utun_free(rem_framer);
85
86 return;
87}
88
89static void
90utun_ctl_clr_dtls_framers (utun_crypto_framer_t *first_framer)
91{
92 utun_crypto_framer_t *cur_framer, *nxt_framer;
93
94 // check framer->state.u.dtls.u.in.listhead for duplicates;
95 for (cur_framer = first_framer;
96 cur_framer != NULL;
97 cur_framer = nxt_framer) {
98 nxt_framer = (__typeof__(nxt_framer))LIST_NEXT(cur_framer, framer_chain);
99 utun_ctl_clr_dtls_framer(cur_framer);
100 }
101
102 return;
103}
104
105static void
106utun_ctl_clr_dtls_all_framers (utun_crypto_ctx_t *crypto_ctx)
107{
108 utun_ctl_clr_dtls_framers(utun_ctl_get_first_framer(crypto_ctx, UTUN_CRYPTO_INNER_TYPE_IPv4));
109 utun_ctl_clr_dtls_framers(utun_ctl_get_first_framer(crypto_ctx, UTUN_CRYPTO_INNER_TYPE_IPv6));
110 crypto_ctx->num_framers = 0;
111}
112
113static void
114utun_ctl_restart_dtls_framers (utun_crypto_framer_t *first_framer)
115{
116 utun_crypto_framer_t *cur_framer;
117
118 // check framer->state.u.dtls.u.in.listhead for duplicates;
119 for (cur_framer = first_framer;
120 cur_framer != NULL;
121 cur_framer = (__typeof__(cur_framer))LIST_NEXT(cur_framer, framer_chain)) {
122 utun_crypto_framer_state_dtls_out(cur_framer).sequence_field = utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_initval;
123 }
124
125 return;
126}
127
128static void
129utun_ctl_restart_dtls_all_framers (utun_crypto_ctx_t *crypto_ctx)
130{
131 utun_ctl_restart_dtls_framers(utun_ctl_get_first_framer(crypto_ctx, UTUN_CRYPTO_INNER_TYPE_IPv4));
132 utun_ctl_restart_dtls_framers(utun_ctl_get_first_framer(crypto_ctx, UTUN_CRYPTO_INNER_TYPE_IPv6));
133}
134
135static int
136is_pattern_all_zeroes (u_int8_t *pattern,
137 int pattern_len)
138{
139 int i;
140
141 if (!pattern || !pattern_len) return FALSE; // false if args are NULL
142
143 for (i = 0; i < pattern_len; i++) {
144 if (pattern[i] != 0) return FALSE;
145 }
146 return TRUE;
147}
148
149static int
150is_pattern_masked_all_zeroes (u_int8_t *pattern,
151 u_int8_t *pattern_mask,
152 int pattern_len)
153{
154 int i;
155
156 if (!pattern || !pattern_mask || !pattern_len) return FALSE; // false if args are NULL
157
158 for (i = 0; i < pattern_len; i++) {
159 if ((pattern[i] & pattern_mask[i])) return FALSE;
160 }
161 return TRUE;
162}
163
164static void
165utun_ctl_calc_dtls_framer_pattern_and_mask (u_int8_t *pattern_masked, u_int8_t *pattern, u_int8_t *mask, int len)
166{
167 int i;
168 for (i = 0; i < len; i++) {
169 pattern_masked[i] = (pattern[i] & mask[i]);
170 }
171}
172
173static Boolean
174utun_ctl_did_dtls_framer_pattern_match (u_int8_t *input, u_int8_t *pattern_masked, int len)
175{
176 int i;
177 for (i = 0; i < len; i++) {
178 if ((input[i] & pattern_masked[i]) != pattern_masked[i]) return FALSE;
179 }
180 return TRUE;
181}
182
183static Boolean
184utun_pkt_dtls_input_frame_is_data(utun_crypto_ctx_t *crypto_ctx,
185 mbuf_t *pkt,
186 protocol_family_t family,
187 int *striplen)
188{
189 u_int8_t *p;
190 utun_crypto_framer_t *cur_framer;
191
192 p = mtod(*pkt, __typeof__(p));
193 for (cur_framer = utun_ctl_get_first_framer(crypto_ctx, utun_crypto_framer_protocol_family_to_inner_type(family));
194 cur_framer != NULL;
195 cur_framer = (__typeof__(cur_framer))LIST_NEXT(cur_framer, framer_chain)) {
196 if (m_pktlen(*pkt) < utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len) {
197 continue;
198 }
199 if ((*pkt)->m_len < utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len) {
200 *pkt = m_pullup(*pkt, utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len);
201 if (!*pkt ||
202 (*pkt)->m_len < utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len) {
203 return FALSE;
204 }
205 p = mtod(*pkt, __typeof__(p));
206 }
207 // TOFIX: switch to BPF
208 if (utun_ctl_did_dtls_framer_pattern_match(p,
209 utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_masked,
210 utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len)) {
211 *striplen = utun_crypto_framer_state_dtls_in(cur_framer).in_data_offset;
212 return TRUE;
213 }
214 }
215 return FALSE;
216}
217
218#define GETLONG(l, cp) { \
219 (l) = *(cp)++ << 8; \
220 (l) |= *(cp)++; (l) <<= 8; \
221 (l) |= *(cp)++; (l) <<= 8; \
222 (l) |= *(cp)++; \
223 }
224#define PUTLONG(l, cp) { \
225 *(cp)++ = (u_char) ((l) >> 24); \
226 *(cp)++ = (u_char) ((l) >> 16); \
227 *(cp)++ = (u_char) ((l) >> 8); \
228 *(cp)++ = (u_char) (l); \
229 }
230
231static int
232utun_pkt_dtls_output_frame_encapsulate (utun_crypto_ctx_t *crypto_ctx,
233 mbuf_t *pkt,
234 protocol_family_t proto)
235{
236 u_int8_t *p;
237 utun_crypto_framer_t *cur_framer;
238 u_int32_t pkt_len;
239
240 // TOFIX: switch to BPF
241
242 if (!crypto_ctx->num_framers) {
243 return 0;
244 }
245 if (proto != AF_INET && proto != AF_INET6) {
246 printf("%s: unsupported proto %d\n", __FUNCTION__, proto);
247 return EINVAL;
248 }
249
250 for (cur_framer = utun_ctl_get_first_framer(crypto_ctx, utun_crypto_framer_protocol_family_to_inner_type(proto));
251 cur_framer != NULL && !utun_crypto_framer_state_dtls_out(cur_framer).out_pattern;
252 cur_framer = (__typeof__(cur_framer))LIST_NEXT(cur_framer, framer_chain));
253 if (!cur_framer ||
254 !utun_crypto_framer_state_dtls_out(cur_framer).out_pattern_len) {
255 return 0;
256 }
257
258 pkt_len = m_pktlen(*pkt);
259
260 // prepend/encapsulate the output pattern
261 if (mbuf_prepend(pkt, utun_crypto_framer_state_dtls_out(cur_framer).out_pattern_len, MBUF_DONTWAIT) != 0) {
262 printf("%s - ifnet_output prepend failed\n", __FUNCTION__);
263 return ENOBUFS;
264 }
265
266 p = mtod(*pkt, __typeof__(p));
267 memcpy(p,
268 utun_crypto_framer_state_dtls_out(cur_framer).out_pattern,
269 utun_crypto_framer_state_dtls_out(cur_framer).out_pattern_len);
270 // fill a "length" field... if configured
271 if (utun_crypto_framer_state_dtls_out(cur_framer).len_field_mask) {
272 u_int32_t tmp;
273 u_int8_t *q = p + utun_crypto_framer_state_dtls_out(cur_framer).len_field_offset;
274 GETLONG(tmp, q);
275 tmp &= ((pkt_len + utun_crypto_framer_state_dtls_out(cur_framer).len_field_extra) & utun_crypto_framer_state_dtls_out(cur_framer).len_field_mask);
276 q = p + utun_crypto_framer_state_dtls_out(cur_framer).len_field_offset;
277 PUTLONG(tmp, q);
278 }
279 // fill a "sequence" field... if configured
280 if (utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_mask) {
281 u_int32_t tmp = (utun_crypto_framer_state_dtls_out(cur_framer).sequence_field & utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_mask);
282 u_int8_t *q = p + utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_offset;
283 GETLONG(tmp, q);
284 tmp &= (utun_crypto_framer_state_dtls_out(cur_framer).sequence_field & utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_mask);
285 q = p + utun_crypto_framer_state_dtls_out(cur_framer).sequence_field_offset;
286 PUTLONG(tmp, q);
287 utun_crypto_framer_state_dtls_out(cur_framer).sequence_field++;
288 }
289 return 0;
290}
291
292void
293utun_ctl_init_crypto_dtls (void)
294{
295 if (OSCompareAndSwap(FALSE, TRUE, &dtls_ctl_mutex_inited)) {
296 if (!dtls_ctl_mutex_grp_attr)
297 dtls_ctl_mutex_grp_attr = lck_grp_attr_alloc_init();
298 if (!dtls_ctl_mutex_grp)
299 dtls_ctl_mutex_grp = lck_grp_alloc_init("utun-crypto", dtls_ctl_mutex_grp_attr);
300 if (!dtls_ctl_mutex_attr)
301 dtls_ctl_mutex_attr = lck_attr_alloc_init();
302
303 lck_mtx_init(&dtls_ctl_mutex, dtls_ctl_mutex_grp, dtls_ctl_mutex_attr);
304 }
305}
306
307/*
308 * Summary: registers the DTLS Kext routines with UTUN... so that UTUN can make calls into DTLS
309 */
310errno_t
311utun_ctl_register_dtls (utun_crypto_kpi_reg_t *reg)
312{
313 //printf("%s: entering\n", __FUNCTION__);
314 if (!reg) return EINVAL;
315
316 //printf("%s: type %d\n", __FUNCTION__, reg->crypto_kpi_type);
317 if (reg->crypto_kpi_type != UTUN_CRYPTO_TYPE_DTLS) {
318 return EINVAL;
319 }
320
321 if (!reg->crypto_kpi_connect) {
322 return EINVAL;
323 }
324
325 if (!reg->crypto_kpi_send) {
326 return EINVAL;
327 }
328
329 // printf("%s: pre-value of dtls_kpi_callbacks_inited %lu\n", __FUNCTION__,
330 // dtls_kpi_callbacks_inited);
331 if (OSCompareAndSwap(FALSE, TRUE, &dtls_kpi_callbacks_inited)) {
332 dtls_kpi_flags = reg->crypto_kpi_flags;
333 dtls_kpi_connect = reg->crypto_kpi_connect;
334 dtls_kpi_send = reg->crypto_kpi_send;
335 }
336 //printf("%s: post-value of dtls_kpi_callbacks_inited %lu\n", __FUNCTION__,
337 // dtls_kpi_callbacks_inited);
338 return 0;
339}
340
341/*
342 * Summary: enables dtls crypto info for the specified utun. dtls ref is passed into args.
343 */
344void
345utun_ctl_enable_crypto_dtls(struct utun_pcb *pcb, utun_crypto_args_t *args)
346{
347 utun_crypto_ctx_t *crypto_ctx;
348
349 lck_mtx_lock(&dtls_ctl_mutex);
350
351 //printf("%s: entering, flags %x, kpi-handle %x, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, pcb->utun_flags, crypto_ctx->kpi_handle, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
352
353 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_IN)];
354 if (crypto_ctx->valid) {
355 printf("%s: dtls already enabled (prev %u, now %u)\n", __FUNCTION__,
356 crypto_ctx->kpi_handle, args->u.dtls_v1.kpi_handle);
357 lck_mtx_unlock(&dtls_ctl_mutex);
358 return;
359 }
360
361 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT)];
362 if (!crypto_ctx->valid) {
363 crypto_ctx->kpi_handle = args->u.dtls_v1.kpi_handle;
364 } else {
365 printf("%s: dtls already enabled for egress (prev %u, now %u)\n", __FUNCTION__,
366 crypto_ctx->kpi_handle, args->u.dtls_v1.kpi_handle);
367 lck_mtx_unlock(&dtls_ctl_mutex);
368 return;
369 }
370 // crypto_ctx->valid will be set in utun_ctl_enable_crypto
371 lck_mtx_unlock(&dtls_ctl_mutex);
372 return;
373}
374
375/*
376 * Summary: disables dtls crypto info for the specified utun.
377 */
378void
379utun_ctl_disable_crypto_dtls(struct utun_pcb *pcb)
380{
381 utun_crypto_ctx_t *crypto_ctx;
382
383 lck_mtx_lock(&dtls_ctl_mutex);
384
385 //printf("%s: entering, flags %x, kpi-handle %d, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, pcb->utun_flags, crypto_ctx->kpi_handle, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
386
387 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_IN)];
388 if (crypto_ctx->valid &&
389 crypto_ctx->type == UTUN_CRYPTO_TYPE_DTLS) {
390 utun_ctl_clr_dtls_all_framers(crypto_ctx);
391 }
392
393 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT)];
394 if (!crypto_ctx->valid ||
395 crypto_ctx->type != UTUN_CRYPTO_TYPE_DTLS) {
396 lck_mtx_unlock(&dtls_ctl_mutex);
397 return;
398 }
399 if (crypto_ctx->kpi_ref) {
400 if (dtls_kpi_connect) {
401 (void)dtls_kpi_connect(crypto_ctx->kpi_handle, NULL);
402 if (--crypto_ctx->kpi_refcnt == 0) {
403 crypto_ctx->kpi_ref = (__typeof__(crypto_ctx->kpi_ref))NULL;
404 crypto_ctx->kpi_handle = UTUN_CRYPTO_DTLS_HANDLE_INVALID;
405 } else {
406 // printf("%s: ### dtls_kpi_refcnt %d not yet zero\n",
407 // __FUNCTION__, crypto_ctx->kpi_refcnt);
408 }
409 } else {
410 printf("%s: ### dtls_ctl_connect unavailable\n", __FUNCTION__);
411 lck_mtx_unlock(&dtls_ctl_mutex);
412 return;
413 }
414 } else {
415 if (crypto_ctx->kpi_handle < 0) {
416 printf("%s: dtls already disabled\n", __FUNCTION__);
417 lck_mtx_unlock(&dtls_ctl_mutex);
418 return;
419 }
420 crypto_ctx->kpi_handle = UTUN_CRYPTO_DTLS_HANDLE_INVALID;
421 }
422 utun_ctl_clr_dtls_all_framers(crypto_ctx);
423 lck_mtx_unlock(&dtls_ctl_mutex);
424 return;
425}
426
427static utun_crypto_framer_t *
428utun_ctl_get_dtls_in_framer (utun_crypto_framer_t *first_framer,
429 u_int8_t *in_pattern,
430 int in_pattern_len,
431 u_int8_t *in_pattern_mask,
432 int in_pattern_mask_len)
433{
434 utun_crypto_framer_t *cur_framer;
435
436 // check framer->u.listhead for duplicates;
437 for (cur_framer = first_framer;
438 cur_framer != NULL;
439 cur_framer = (__typeof__(cur_framer))LIST_NEXT(cur_framer, framer_chain)) {
440 // TOFIX: use in_pattern_masked
441 if (utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len == in_pattern_len &&
442 memcmp(utun_crypto_framer_state_dtls_in(cur_framer).in_pattern,
443 in_pattern,
444 in_pattern_len) == 0 &&
445 utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_len == in_pattern_mask_len &&
446 memcmp(utun_crypto_framer_state_dtls_in(cur_framer).in_pattern_mask,
447 in_pattern_mask,
448 in_pattern_mask_len) == 0) {
449 // found
450 return cur_framer;
451 }
452 }
453
454 return NULL;
455}
456
457errno_t
458utun_ctl_config_crypto_dtls_framer (utun_crypto_ctx_t *crypto_ctx,
459 utun_crypto_framer_args_t *args)
460{
461 utun_crypto_framer_t *framer, *new_framer = NULL, *dup_framer;
462
463 if (args->ver != UTUN_CRYPTO_DTLS_VER_1) {
464 return EINVAL;
465 }
466 if (!args->type || args->type >= UTUN_CRYPTO_INNER_TYPE_MAX) {
467 return EINVAL;
468 }
469
470 lck_mtx_lock(&dtls_ctl_mutex);
471
472 if (args->dir == UTUN_CRYPTO_DIR_IN) {
473 // Input framer (for tunnel hdr detection and decapsulation). there can be several pattern that identify data (vs. control) packets.
474
475 // First, the args need to be verified for errors/inconsistencies
476 // pattern and mask have to be configured
477 if (!utun_crypto_framer_args_dtls_in(args).in_pattern_len ||
478 !utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len) {
479 lck_mtx_unlock(&dtls_ctl_mutex);
480 printf("%s: invalid dtls in-pattern %d mask %d\n", __FUNCTION__,
481 utun_crypto_framer_args_dtls_in(args).in_pattern_len,
482 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len);
483 return EINVAL;
484 }
485 // pattern and mask lengths have to match
486 if (utun_crypto_framer_args_dtls_in(args).in_pattern_len != utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len) {
487 lck_mtx_unlock(&dtls_ctl_mutex);
488 printf("%s: inconsistent dtls in-pattern %d mask %d\n",__FUNCTION__,
489 utun_crypto_framer_args_dtls_in(args).in_pattern_len,
490 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len);
491 return EINVAL;
492 }
493 // check for len inconsistencies
494 if ((u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_len + (u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len != args->varargs_buflen) {
495 lck_mtx_unlock(&dtls_ctl_mutex);
496 printf("%s: inconsistent dtls in-pattern %d mask %d, total %d\n",__FUNCTION__,
497 utun_crypto_framer_args_dtls_in(args).in_pattern_len,
498 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len,
499 args->varargs_buflen);
500 return EINVAL;
501 }
502 // utun_crypto_framer_args_dtls_in(args).in_pattern should not be all zeros
503 if (is_pattern_all_zeroes(&args->varargs_buf[0],
504 utun_crypto_framer_args_dtls_in(args).in_pattern_len)) {
505 lck_mtx_unlock(&dtls_ctl_mutex);
506 printf("%s: in-pattern is all zeros, len %d\n",__FUNCTION__,
507 utun_crypto_framer_args_dtls_in(args).in_pattern_len);
508 return EINVAL;
509 }
510 // utun_crypto_framer_args_dtls_in(args).in_pattern_mask should not be all zeros
511 if (is_pattern_all_zeroes(&args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
512 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len)) {
513 lck_mtx_unlock(&dtls_ctl_mutex);
514 printf("%s: in-pattern-mask is all zeros, len %d\n",__FUNCTION__,
515 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len);
516 return EINVAL;
517 }
518 // utun_crypto_framer_args_dtls_in(args).in_pattern & utun_crypto_framer_args_dtls_in(args).in_pattern_mask should not be zeros
519 if (is_pattern_masked_all_zeroes(&args->varargs_buf[0],
520 &args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
521 utun_crypto_framer_args_dtls_in(args).in_pattern_len)) {
522 lck_mtx_unlock(&dtls_ctl_mutex);
523 printf("%s: in-pattern-masked is all zeros, len %d\n",__FUNCTION__,
524 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len);
525 return EINVAL;
526 }
527
528 // Secondly, we need to be careful about existing framer configs
529 if (!(framer = utun_ctl_get_first_framer(crypto_ctx, args->inner_type))) {
530 // no framers configured
531 if (!(framer = utun_alloc(sizeof(*framer)))) {
532 lck_mtx_unlock(&dtls_ctl_mutex);
533 return ENOBUFS;
534 }
535 bzero(framer, sizeof(*framer));
536 // fall through to fill-in the 1st framer
537 } else {
538 // at least one framer configured... check framer->u.listhead for duplicates;
539 if ((dup_framer = utun_ctl_get_dtls_in_framer(framer /* could be a list */,
540 &args->varargs_buf[0],
541 utun_crypto_framer_args_dtls_in(args).in_pattern_len,
542 &args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
543 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len))) {
544 // duplicate
545 lck_mtx_unlock(&dtls_ctl_mutex);
546 printf("%s: ignoring duplicate framer for type %d\n",__FUNCTION__,
547 args->inner_type);
548 return 0;
549 }
550
551 if (!(new_framer = utun_alloc(sizeof(*new_framer)))) {
552 lck_mtx_unlock(&dtls_ctl_mutex);
553 return ENOBUFS;
554 }
555 bzero(new_framer, sizeof(*new_framer));
556 framer = new_framer;
557 // fall through to fill-in additional framer
558 }
559 LIST_INSERT_HEAD(utun_get_framer_listhead(crypto_ctx, args->inner_type),
560 new_framer,
561 framer_chain);
562
563 framer->inner_type = args->inner_type;
564 framer->inner_protocol_family = utun_crypto_framer_inner_type_to_protocol_family(args->inner_type);
565 // allocate and fill the pattern
566 if (!(utun_crypto_framer_state_dtls_in(framer).in_pattern = utun_alloc(utun_crypto_framer_args_dtls_in(args).in_pattern_len))) {
567 utun_ctl_clr_dtls_framer(framer);
568 lck_mtx_unlock(&dtls_ctl_mutex);
569 return ENOBUFS;
570 }
571 memcpy(utun_crypto_framer_state_dtls_in(framer).in_pattern,
572 &args->varargs_buf[0],
573 utun_crypto_framer_args_dtls_in(args).in_pattern_len);
574 utun_crypto_framer_state_dtls_in(framer).in_pattern_len = utun_crypto_framer_args_dtls_in(args).in_pattern_len;
575
576 // allocate and fill the pattern-mask
577 if (!(utun_crypto_framer_state_dtls_in(framer).in_pattern_mask = utun_alloc(utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len))) {
578 utun_ctl_clr_dtls_framer(framer);
579 lck_mtx_unlock(&dtls_ctl_mutex);
580 return ENOBUFS;
581 }
582 memcpy(utun_crypto_framer_state_dtls_in(framer).in_pattern_mask,
583 &args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
584 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len);
585 utun_crypto_framer_state_dtls_in(framer).in_data_offset = utun_crypto_framer_args_dtls_in(args).in_data_offset;
586
587 if (!(utun_crypto_framer_state_dtls_in(framer).in_pattern_masked = utun_alloc(utun_crypto_framer_args_dtls_in(args).in_pattern_len))) {
588 utun_ctl_clr_dtls_framer(framer);
589 lck_mtx_unlock(&dtls_ctl_mutex);
590 return ENOBUFS;
591 }
592 utun_ctl_calc_dtls_framer_pattern_and_mask(utun_crypto_framer_state_dtls_in(framer).in_pattern_masked,
593 utun_crypto_framer_state_dtls_in(framer).in_pattern,
594 utun_crypto_framer_state_dtls_in(framer).in_pattern_mask,
595 utun_crypto_framer_state_dtls_in(framer).in_pattern_len);
596 // TOFIX: switch to BPF
597 crypto_ctx->num_framers++;
598 } else {
599 // Output Framer (for tunnel hdr encapsulation)... there can only be one for each type of traffic (see caller of this function)
600
601 // pattern and mask have to be configured
602 if (!utun_crypto_framer_args_dtls_out(args).out_pattern_len) {
603 lck_mtx_unlock(&dtls_ctl_mutex);
604 printf("%s: invalid output framer, len %d\n",__FUNCTION__,
605 utun_crypto_framer_args_dtls_out(args).out_pattern_len);
606 return EINVAL;
607 }
608 // utun_crypto_framer_args_dtls_out(args).out_pattern should not be all zeros;
609 if (is_pattern_all_zeroes(&args->varargs_buf[0],
610 utun_crypto_framer_args_dtls_out(args).out_pattern_len)) {
611 lck_mtx_unlock(&dtls_ctl_mutex);
612 printf("%s: zeroed output framer, len %d\n",__FUNCTION__,
613 utun_crypto_framer_args_dtls_out(args).out_pattern_len);
614 return EINVAL;
615 }
616
617 // can't have the offset/extra configured while the mask is cleared
618 if ((utun_crypto_framer_args_dtls_out(args).len_field_offset || utun_crypto_framer_args_dtls_out(args).len_field_extra) && !utun_crypto_framer_args_dtls_out(args).len_field_mask) {
619 lck_mtx_unlock(&dtls_ctl_mutex);
620 printf("%s: output framer has invalid length-field %d,%d,%x\n",__FUNCTION__,
621 (int)utun_crypto_framer_args_dtls_out(args).len_field_offset,
622 (int)utun_crypto_framer_args_dtls_out(args).len_field_extra,
623 utun_crypto_framer_args_dtls_out(args).len_field_mask);
624 return EINVAL;
625 }
626 // any length field should be within the bounds of the out-pattern
627 if (utun_crypto_framer_args_dtls_out(args).len_field_offset >= utun_crypto_framer_args_dtls_out(args).out_pattern_len) {
628 lck_mtx_unlock(&dtls_ctl_mutex);
629 return EINVAL;
630 }
631
632 // can't have the offset configured while the mask is cleared
633 if ((utun_crypto_framer_args_dtls_out(args).sequence_field || utun_crypto_framer_args_dtls_out(args).sequence_field_offset) && !utun_crypto_framer_args_dtls_out(args).sequence_field_mask) {
634 lck_mtx_unlock(&dtls_ctl_mutex);
635 printf("%s: output framer has invalid sequence-field %d,%d,%x\n",__FUNCTION__,
636 (int)utun_crypto_framer_args_dtls_out(args).sequence_field,
637 (int)utun_crypto_framer_args_dtls_out(args).sequence_field_offset,
638 utun_crypto_framer_args_dtls_out(args).sequence_field_mask);
639 return EINVAL;
640 }
641 // any sequence field should be within the bounds of the out-pattern
642 if (utun_crypto_framer_args_dtls_out(args).sequence_field_offset >= utun_crypto_framer_args_dtls_out(args).out_pattern_len) {
643 lck_mtx_unlock(&dtls_ctl_mutex);
644 return EINVAL;
645 }
646
647 // check for len inconsistencies
648 if ((u_int32_t)utun_crypto_framer_args_dtls_out(args).out_pattern_len != args->varargs_buflen) {
649 lck_mtx_unlock(&dtls_ctl_mutex);
650 return EINVAL;
651 }
652
653 if (!(framer = utun_ctl_get_first_framer(crypto_ctx, args->inner_type))) {
654 if (!(framer = utun_alloc(sizeof(*framer)))) {
655 lck_mtx_unlock(&dtls_ctl_mutex);
656 return ENOBUFS;
657 }
658 bzero(framer, sizeof(*framer));
659 LIST_INSERT_HEAD(utun_get_framer_listhead(crypto_ctx, args->inner_type),
660 new_framer,
661 framer_chain);
662 // fall through to fill-in 1st framer
663 } else {
664 // only one outbound framer may be configured.. is it a dup?
665 if (framer->inner_type == args->inner_type &&
666 utun_crypto_framer_state_dtls_out(framer).out_pattern_len == utun_crypto_framer_args_dtls_out(args).out_pattern_len &&
667 utun_crypto_framer_state_dtls_out(framer).out_pattern &&
668 memcmp(utun_crypto_framer_state_dtls_out(framer).out_pattern,
669 &args->varargs_buf[0],
670 utun_crypto_framer_args_dtls_out(args).out_pattern_len) == 0) {
671 // found
672 lck_mtx_unlock(&dtls_ctl_mutex);
673 return 0;
674 }
675
676 // overwrite the previous one
677 if (utun_crypto_framer_state_dtls_out(framer).out_pattern) {
678 utun_free(utun_crypto_framer_state_dtls_out(framer).out_pattern);
679 }
680 // fall through to fill-in additional framer
681 }
682
683 framer->inner_type = args->inner_type;
684 framer->inner_protocol_family = utun_crypto_framer_inner_type_to_protocol_family(args->inner_type);
685
686 // alloc and fill in the out-pattern
687 if (!(utun_crypto_framer_state_dtls_out(framer).out_pattern = utun_alloc(utun_crypto_framer_args_dtls_out(args).out_pattern_len))) {
688 utun_ctl_clr_dtls_framer(framer);
689 lck_mtx_unlock(&dtls_ctl_mutex);
690 return ENOBUFS;
691 }
692 memcpy(utun_crypto_framer_state_dtls_out(framer).out_pattern,
693 &args->varargs_buf[0],
694 utun_crypto_framer_args_dtls_out(args).out_pattern_len);
695 utun_crypto_framer_state_dtls_out(framer).out_pattern_len = utun_crypto_framer_args_dtls_out(args).out_pattern_len;
696
697 utun_crypto_framer_state_dtls_out(framer).len_field_mask = utun_crypto_framer_args_dtls_out(args).len_field_mask;
698 utun_crypto_framer_state_dtls_out(framer).len_field_offset = utun_crypto_framer_args_dtls_out(args).len_field_offset;
699 utun_crypto_framer_state_dtls_out(framer).len_field_extra = utun_crypto_framer_args_dtls_out(args).len_field_extra;
700 utun_crypto_framer_state_dtls_out(framer).sequence_field_initval = utun_crypto_framer_args_dtls_out(args).sequence_field;
701 utun_crypto_framer_state_dtls_out(framer).sequence_field_mask = utun_crypto_framer_args_dtls_out(args).sequence_field_mask;
702 utun_crypto_framer_state_dtls_out(framer).sequence_field_offset = utun_crypto_framer_args_dtls_out(args).sequence_field_offset;
703 crypto_ctx->num_framers = 1;
704 }
705 framer->type = args->type;
706 framer->dir = args->dir;
707 framer->valid = 1;
708
709 lck_mtx_unlock(&dtls_ctl_mutex);
710 return 0;
711}
712
713int
714utun_ctl_unconfig_crypto_dtls_framer (utun_crypto_ctx_t *crypto_ctx,
715 utun_crypto_framer_args_t *args)
716{
717 utun_crypto_framer_t *framer, *rem_framer;
718
719 if (args->ver != UTUN_CRYPTO_DTLS_VER_1) {
720 return EINVAL;
721 }
722 if (!args->type || args->type >= UTUN_CRYPTO_INNER_TYPE_MAX) {
723 return EINVAL;
724 }
725
726 lck_mtx_lock(&dtls_ctl_mutex);
727
728 if (args->dir == UTUN_CRYPTO_DIR_IN) {
729 if (!utun_crypto_framer_args_dtls_in(args).in_pattern_len) {
730 // no pattern means... clear all
731 utun_ctl_clr_dtls_framers(utun_ctl_get_first_framer(crypto_ctx, args->inner_type));
732 lck_mtx_unlock(&dtls_ctl_mutex);
733 return 0;
734 }
735
736 // when both specified, pattern and mask lengths have to match
737 if (utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len &&
738 utun_crypto_framer_args_dtls_in(args).in_pattern_len != utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len) {
739 lck_mtx_unlock(&dtls_ctl_mutex);
740 return EINVAL;
741 }
742 // check for len inconsistencies
743 if ((u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_len + (u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len != args->varargs_buflen) {
744 lck_mtx_unlock(&dtls_ctl_mutex);
745 return EINVAL;
746 }
747 // utun_crypto_framer_args_dtls_in(args).in_pattern should not be all zeros
748 if (is_pattern_all_zeroes(&args->varargs_buf[0],
749 utun_crypto_framer_args_dtls_in(args).in_pattern_len)) {
750 lck_mtx_unlock(&dtls_ctl_mutex);
751 return EINVAL;
752 }
753 // when specified, utun_crypto_framer_args_dtls_in(args).in_pattern_mask should not be all zeros
754 if (utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len &&
755 is_pattern_all_zeroes(&args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
756 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len)) {
757 lck_mtx_unlock(&dtls_ctl_mutex);
758 return EINVAL;
759 }
760 // utun_crypto_framer_args_dtls_in(args).in_pattern & utun_crypto_framer_args_dtls_in(args).in_pattern_mask should not be zeros
761 if (is_pattern_masked_all_zeroes(&args->varargs_buf[0],
762 &args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
763 utun_crypto_framer_args_dtls_in(args).in_pattern_len)) {
764 lck_mtx_unlock(&dtls_ctl_mutex);
765 return EINVAL;
766 }
767
768 if ((u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_len + (u_int32_t)utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len != args->varargs_buflen) {
769 lck_mtx_unlock(&dtls_ctl_mutex);
770 return EINVAL;
771 }
772
773 if (!(framer = utun_ctl_get_first_framer(crypto_ctx, args->inner_type))) {
774 // no framers
775 printf("%s: no framers configured\n", __FUNCTION__);
776 lck_mtx_unlock(&dtls_ctl_mutex);
777 return 0;
778 } else {
779 if ((rem_framer = utun_ctl_get_dtls_in_framer(framer,
780 &args->varargs_buf[0],
781 utun_crypto_framer_args_dtls_in(args).in_pattern_len,
782 &args->varargs_buf[utun_crypto_framer_args_dtls_in(args).in_pattern_len],
783 utun_crypto_framer_args_dtls_in(args).in_pattern_mask_len))) {
784 utun_ctl_clr_dtls_framer(rem_framer);
785 if (crypto_ctx->num_framers) crypto_ctx->num_framers--;
786 } else {
787 printf("%s: no matching ingress framer\n", __FUNCTION__);
788 }
789 lck_mtx_unlock(&dtls_ctl_mutex);
790 return 0;
791 }
792 } else {
793 framer = utun_ctl_get_first_framer(crypto_ctx, args->inner_type);
794 // overwrite the previous one
795 if (framer) {
796 if (framer->inner_type != args->inner_type ||
797 (utun_crypto_framer_args_dtls_out(args).out_pattern_len &&
798 utun_crypto_framer_state_dtls_out(framer).out_pattern_len != utun_crypto_framer_args_dtls_out(args).out_pattern_len) ||
799 (utun_crypto_framer_args_dtls_out(args).out_pattern_len &&
800 memcmp(utun_crypto_framer_state_dtls_out(framer).out_pattern,
801 &args->varargs_buf[0],
802 utun_crypto_framer_args_dtls_out(args).out_pattern_len))) {
803 printf("%s: no matching egress framer\n", __FUNCTION__);
804 lck_mtx_unlock(&dtls_ctl_mutex);
805 return EBADF;
806 }
807 utun_ctl_clr_dtls_framer(framer);
808 if (crypto_ctx->num_framers) crypto_ctx->num_framers--;
809 }
810 }
811
812 lck_mtx_unlock(&dtls_ctl_mutex);
813 return 0;
814}
815
816/*
817 * Summary: enables handling of data traffic
818 */
819void
820utun_ctl_start_datatraffic_crypto_dtls(struct utun_pcb *pcb)
821{
822 utun_crypto_ctx_t *crypto_ctx;
823
824 lck_mtx_lock(&dtls_ctl_mutex);
825
826 //printf("%s: entering, flags %x, kpi-handle %d, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, pcb->utun_flags, crypto_ctx->kpi_handle, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
827
828 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT)];
829
830 if (crypto_ctx->kpi_handle < 0) {
831 printf("%s: dtls disabled\n", __FUNCTION__);
832 lck_mtx_unlock(&dtls_ctl_mutex);
833 return;
834 }
835
836 if (!crypto_ctx->kpi_ref) {
837 if (dtls_kpi_connect) {
838 crypto_ctx->kpi_ref = dtls_kpi_connect(crypto_ctx->kpi_handle, pcb);
839 if (!crypto_ctx->kpi_ref) {
840 printf("%s: ### dtls_kpi_connect failed\n", __FUNCTION__);
841 lck_mtx_unlock(&dtls_ctl_mutex);
842 return;
843 }
844 crypto_ctx->kpi_refcnt++;
845 } else {
846 printf("%s: ### dtls_kpi_connect unavailable\n", __FUNCTION__);
847 lck_mtx_unlock(&dtls_ctl_mutex);
848 return;
849 }
850 } else {
851 printf("%s: dtls already stitched\n", __FUNCTION__);
852 lck_mtx_unlock(&dtls_ctl_mutex);
853 return;
854 }
855 utun_ctl_restart_dtls_all_framers(crypto_ctx); // for dynamic egress hdrs
856
857 //printf("%s: leaving, flags %x, kpi-handle %d, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, pcb->utun_flags, crypto_ctx->kpi_handle, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
858 lck_mtx_unlock(&dtls_ctl_mutex);
859 return;
860}
861
862/*
863 * Summary: disables handling of data traffic
864 */
865void
866utun_ctl_stop_datatraffic_crypto_dtls(struct utun_pcb *pcb)
867{
868 utun_crypto_ctx_t *crypto_ctx;
869
870 lck_mtx_lock(&dtls_ctl_mutex);
871
872 //printf("%s: entering, flags %x, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, pcb->utun_flags, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
873
874 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT)];
875
876 if (crypto_ctx->kpi_ref) {
877 if (dtls_kpi_connect) {
878 (void)dtls_kpi_connect(crypto_ctx->kpi_handle, NULL);
879 if (--crypto_ctx->kpi_refcnt == 0) {
880 crypto_ctx->kpi_ref = (__typeof__(crypto_ctx->kpi_ref))NULL;
881 crypto_ctx->kpi_handle = UTUN_CRYPTO_DTLS_HANDLE_INVALID;
882 } else {
883 // printf("%s: ### dtls_kpi_refcnt %d not yet zero\n",
884 // __FUNCTION__, crypto_ctx->kpi_refcnt);
885 }
886 } else {
887 printf("%s: dtls_kpi_connect unavailable\n", __FUNCTION__);
888 lck_mtx_unlock(&dtls_ctl_mutex);
889 return;
890 }
891 } else {
892 printf("%s: dtls already not-stitched\n", __FUNCTION__);
893 lck_mtx_unlock(&dtls_ctl_mutex);
894 return;
895 }
896 lck_mtx_unlock(&dtls_ctl_mutex);
897 return;
898}
899
900#define utun_pkt_dtls_prepend_proto(pkt, pf) do { \
901 if (mbuf_prepend(pkt, sizeof(protocol_family_t), MBUF_DONTWAIT) != 0) { \
902 printf("%s - ifnet_output prepend failed\n", __FUNCTION__); \
903 lck_mtx_unlock(&dtls_ctl_mutex); \
904 return EBADF; \
905 } \
906 *(protocol_family_t *)mbuf_data(*pkt) = pf; \
907 } while(0);
908
909#define utun_pkt_dtls_puntup(pcb, pkt, errstr, rc) do { \
910 *(protocol_family_t *)mbuf_data(*pkt) = htonl(*(protocol_family_t *)mbuf_data(*pkt)); \
911 rc = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, *pkt, CTL_DATA_EOR); \
912 if (rc != 0) { \
3e170ce0 913 printf("%s: - ctl_enqueuembuf failed (rc %d) for %s:\n", __FUNCTION__, rc, errstr); \
39236c6e
A
914 mbuf_freem(*pkt); \
915 ifnet_stat_increment_out(pcb->utun_ifp, 0, 0, 1); \
916 lck_mtx_unlock(&dtls_ctl_mutex); \
917 return 0; \
918 } \
919 *pkt = NULL; \
920 } while(0);
921
922int
923utun_pkt_dtls_output(struct utun_pcb *pcb, mbuf_t *pkt)
924{
925 errno_t rc = ENETUNREACH;
926 int len;
927 utun_crypto_ctx_t *crypto_ctx;
928 protocol_family_t proto;
929
930 //printf("%s: entering, flags %x, ifp %p\n", __FUNCTION__, pcb->utun_flags, pcb->utun_ifp);
931
932 if (!(pcb->utun_flags & UTUN_FLAGS_CRYPTO)) {
933 printf("%s - crypto disabled\n", __FUNCTION__);
934 return EINVAL;
935 }
936
937 if (!pcb->utun_ifp) {
938 printf("%s - utun ifp cleared\n", __FUNCTION__);
939 return EINVAL;
940 }
941
942 proto = *(mtod(*pkt, protocol_family_t *));
943
944 lck_mtx_lock(&dtls_ctl_mutex);
945
946 len = mbuf_pkthdr_len(*pkt);
947
948 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_OUT)];
949
950 //printf("%s: entering, kpi-handle %d, kpi-ref %p, kpi-refcnt %d\n", __FUNCTION__, crypto_ctx->kpi_handle, crypto_ctx->kpi_ref, crypto_ctx->kpi_refcnt);
951
952 if (dtls_kpi_send && (crypto_ctx->kpi_handle >= 0) && crypto_ctx->kpi_ref) {
953 m_adj(*pkt, sizeof(protocol_family_t));
954
955 if (!(rc = utun_pkt_dtls_output_frame_encapsulate(crypto_ctx, pkt, proto))) {
956 rc = dtls_kpi_send(crypto_ctx->kpi_ref, pkt);
957 if (rc) {
958 printf("%s: DTLS failed to send pkt %d\n", __FUNCTION__, rc);
959 // <rdar://problem/11385397>
960 // dtls_kpi_send (by way of so_inject_data_out) frees mbuf during certain error cases,
961 ifnet_stat_increment_out(pcb->utun_ifp, 0, 0, 1); // increment errors
962 lck_mtx_unlock(&dtls_ctl_mutex);
963 return 0; // and drop packet
964 }
965 } else if (rc == EINVAL) {
966 // unsupported proto... fall through and punt (but 1st undo the protocol strip)
967 utun_pkt_dtls_prepend_proto(pkt, proto);
3e170ce0 968 utun_pkt_dtls_puntup(pcb, pkt, "unsupported proto", rc);
39236c6e
A
969 } else {
970 // mbuf_prepend failure... mbuf will be already freed
971 printf("%s: failed to encrypsulate and send pkt %d\n", __FUNCTION__,rc);
972 ifnet_stat_increment_out(pcb->utun_ifp, 0, 0, 1); // increment errors
973 lck_mtx_unlock(&dtls_ctl_mutex);
974 return 0; // and drop packet
975 }
976 } else {
3e170ce0 977 utun_pkt_dtls_puntup(pcb, pkt, "slowpath", rc);
39236c6e
A
978 }
979
980 if (!rc)
981 ifnet_stat_increment_out(pcb->utun_ifp, 1, len, 0);
982
983 lck_mtx_unlock(&dtls_ctl_mutex);
984 return rc;
985}
986
987int
988utun_pkt_dtls_input(struct utun_pcb *pcb, mbuf_t *pkt, __unused protocol_family_t family)
989{
990 utun_crypto_ctx_t *crypto_ctx;
991 int striplen = 0;
992
993 //printf("%s: got pkt %d\n", __FUNCTION__,family);
994 if (!(pcb->utun_flags & UTUN_FLAGS_CRYPTO)) {
995 printf("%s - crypto disabled\n", __FUNCTION__);
996 return EINVAL;
997 }
998
999 if (!pcb->utun_ifp) {
1000 printf("%s - utun ifp cleared\n", __FUNCTION__);
1001 return EINVAL;
1002 }
1003
1004 lck_mtx_lock(&dtls_ctl_mutex);
1005
1006 /*
1007 * make sure that family matches what the UTUN was configured for (punt those that don't... along with all that fail to match the data pattern.
1008 */
1009 crypto_ctx = &pcb->utun_crypto_ctx[UTUN_CRYPTO_DIR_TO_IDX(UTUN_CRYPTO_DIR_IN)];
1010 if (crypto_ctx->num_framers &&
1011 !utun_pkt_dtls_input_frame_is_data(crypto_ctx, pkt, AF_INET, &striplen) &&
1012 !utun_pkt_dtls_input_frame_is_data(crypto_ctx, pkt, AF_INET6, &striplen)) {
1013 // control or unknown traffic, so punt up to the plugin
1014 errno_t rc;
1015
1016 utun_pkt_dtls_prepend_proto(pkt, family);
1017 *(protocol_family_t *)mbuf_data(*pkt) = htonl(*(protocol_family_t *)mbuf_data(*pkt));
1018 rc = ctl_enqueuembuf(pcb->utun_ctlref, pcb->utun_unit, *pkt, CTL_DATA_EOR);
1019 if (rc != 0) {
1020 // drop packet
1021 printf("%s: - ctl_enqueuembuf failed: %d\n", __FUNCTION__, rc);
1022 mbuf_freem(*pkt);
1023 lck_mtx_unlock(&dtls_ctl_mutex);
1024 return rc;
1025 }
1026 printf("%s: - ctl_enqueuembuf punted a packet up to UTUN ctrl sock: %d\n", __FUNCTION__, rc);
1027 ifnet_stat_increment_in(pcb->utun_ifp, 1, mbuf_pkthdr_len(*pkt), 0);
1028
1029 *pkt = NULL;
1030 lck_mtx_unlock(&dtls_ctl_mutex);
1031 return 0;
1032 }
1033 if (striplen) {
1034 //printf("%s: - about to strip tunneled hdr of len %d\n", __FUNCTION__, striplen);
1035 m_adj(*pkt, striplen);
1036 }
1037
1038 utun_pkt_dtls_prepend_proto(pkt, family);
1039
1040 ifnet_stat_increment_in(pcb->utun_ifp, 1, mbuf_pkthdr_len(*pkt), 0);
1041
1042 (void)utun_pkt_input(pcb, *pkt);
1043 lck_mtx_unlock(&dtls_ctl_mutex);
1044 return 0;
1045}