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) { \ 913 printf("%s: - ctl_enqueuembuf failed (rc %d) for %s:\n", __FUNCTION__, rc, (char *)errstr); \ 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); 968 utun_pkt_dtls_puntup(pcb, pkt, (char *)"unsupported proto", rc); 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 { 977 utun_pkt_dtls_puntup(pcb, pkt, (char *)"slowpath", rc); 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} 1046