1 /*
2 * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_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. Please obtain a copy of the License at
10 * http: www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * THEORY OF OPERATION
26 *
27 * The packet mangler subsystem provides a limited way for user space
28 * applications to apply certain actions on certain flows.
29 *
30 * A user space applications opens a kernel control socket with the name
31 * PACKET_MANGLER_CONTROL_NAME to attach to the packet mangler subsystem.
32 * When connected, a "struct packet_mangler" is created and set as the
33 * "unitinfo" of the corresponding kernel control socket instance.
34 * Connect call for packet mangler's kernel control socket also registers
35 * ip filers with cookie set to the packet_mangler instance.
36 * The ip filters are removed when control socket is disconnected.
37 */
38 #include <sys/types.h>
39 #include <sys/kern_control.h>
40 #include <sys/domain.h>
41 #include <sys/protosw.h>
42 #include <sys/syslog.h>
43
44 #include <kern/locks.h>
45 #include <kern/zalloc.h>
46 #include <kern/debug.h>
47
48 #include <net/packet_mangler.h>
49
50 #include <netinet/tcp.h>
51 #include <netinet/tcp_var.h>
52 #include <netinet/ip.h>
53 #include <netinet/ip6.h>
54 #include <netinet/kpi_ipfilter.h>
55 #include <string.h>
56 #include <libkern/libkern.h>
57
58 #define MAX_PACKET_MANGLER 1
59
60 #define PKT_MNGLR_FLG_IPFILTER_ATTACHED 0x00000001
61
62 SYSCTL_NODE(_net, OID_AUTO, pktmnglr, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "pktmnglr");
63 SYSCTL_INT(_net_pktmnglr, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED,
64 &pkt_mnglr_log_level, 0, "");
65 /*
66 * The structure packet_mangler represents a user space packet filter
67 * It's created and associated with a kernel control socket instance
68 */
69 struct packet_mangler {
70 kern_ctl_ref pkt_mnglr_kcref;
71 uint32_t pkt_mnglr_kcunit;
72 uint32_t pkt_mnglr_flags;
73 /* IP filter related params */
74 ipfilter_t pkt_mnglr_ipfref;
75 ipfilter_t pkt_mnglr_ipfrefv6;
76 struct ipf_filter pkt_mnglr_ipfilter;
77
78 /* Options */
79 uint8_t activate;
80 Pkt_Mnglr_Flow dir;
81 struct sockaddr_storage lsaddr;
82 struct sockaddr_storage rsaddr;
83 struct sockaddr_storage swap_lsaddr;
84 struct sockaddr_storage swap_rsaddr;
85 uint32_t ip_action_mask;
86 uint16_t lport;
87 uint16_t rport;
88 uint32_t proto;
89 uint32_t proto_action_mask;
90 };
91
92 /* Array of all the packet mangler instancesi */
93 struct packet_mangler **packet_manglers = NULL;
94
95 uint32_t pkt_mnglr_active_count = 0; /* Number of active packet filters */
96 uint32_t pkt_mnglr_close_wait_timeout = 1000; /* in milliseconds */
97
98 static kern_ctl_ref pkt_mnglr_kctlref = NULL;
99
100 /* The lock below protects packet_manglers DS, packet_mangler DS */
101 static LCK_GRP_DECLARE(pkt_mnglr_lck_grp, "packet mangler");
102 static LCK_RW_DECLARE(pkt_mnglr_lck_rw, &pkt_mnglr_lck_grp);
103
104 #define PKT_MNGLR_RW_LCK_MAX 8
105
106 int pkt_mnglr_rw_nxt_lck = 0;
107 void* pkt_mnglr_rw_lock_history[PKT_MNGLR_RW_LCK_MAX];
108
109 int pkt_mnglr_rw_nxt_unlck = 0;
110 void* pkt_mnglr_rw_unlock_history[PKT_MNGLR_RW_LCK_MAX];
111
112 static ZONE_DECLARE(packet_mangler_zone, "packet_mangler",
113 sizeof(struct packet_mangler), ZC_NONE);
114
115 /*
116 * For troubleshooting
117 */
118 int pkt_mnglr_log_level = LOG_ERR;
119 int pkt_mnglr_debug = 1;
120
121 /*
122 * Forward declaration to appease the compiler
123 */
124 static void pkt_mnglr_rw_lock_exclusive(lck_rw_t *);
125 static void pkt_mnglr_rw_unlock_exclusive(lck_rw_t *);
126 static void pkt_mnglr_rw_lock_shared(lck_rw_t *);
127 static void pkt_mnglr_rw_unlock_shared(lck_rw_t *);
128
129 static errno_t pktmnglr_ipfilter_output(void *cookie, mbuf_t *data,
130 ipf_pktopts_t options);
131 static errno_t pktmnglr_ipfilter_input(void *cookie, mbuf_t *data,
132 int offset, u_int8_t protocol);
133 static void pktmnglr_ipfilter_detach(void *cookie);
134
135 static void chksm_update(mbuf_t data);
136
137 #define TCP_OPT_MULTIPATH_TCP 30
138 #define MPTCP_SBT_VER_OFFSET 2
139
140 #define MPTCP_SUBTYPE_MPCAPABLE 0x0
141 #define MPTCP_SUBTYPE_MPJOIN 0x1
142 #define MPTCP_SUBTYPE_DSS 0x2
143 #define MPTCP_SUBTYPE_ADD_ADDR 0x3
144 #define MPTCP_SUBTYPE_REM_ADDR 0x4
145 #define MPTCP_SUBTYPE_MP_PRIO 0x5
146 #define MPTCP_SUBTYPE_MP_FAIL 0x6
147 #define MPTCP_SUBTYPE_MP_FASTCLOSE 0x7
148
149 /*
150 * packet filter global read write lock
151 */
152
153 static void
pkt_mnglr_rw_lock_exclusive(lck_rw_t * lck)154 pkt_mnglr_rw_lock_exclusive(lck_rw_t *lck)
155 {
156 void *lr_saved;
157
158 lr_saved = __builtin_return_address(0);
159
160 lck_rw_lock_exclusive(lck);
161
162 pkt_mnglr_rw_lock_history[pkt_mnglr_rw_nxt_lck] = lr_saved;
163 pkt_mnglr_rw_nxt_lck =
164 (pkt_mnglr_rw_nxt_lck + 1) % PKT_MNGLR_RW_LCK_MAX;
165 }
166
167 static void
pkt_mnglr_rw_unlock_exclusive(lck_rw_t * lck)168 pkt_mnglr_rw_unlock_exclusive(lck_rw_t *lck)
169 {
170 void *lr_saved;
171
172 lr_saved = __builtin_return_address(0);
173
174 lck_rw_unlock_exclusive(lck);
175
176 pkt_mnglr_rw_unlock_history[pkt_mnglr_rw_nxt_unlck] =
177 lr_saved;
178 pkt_mnglr_rw_nxt_unlck = (pkt_mnglr_rw_nxt_unlck + 1) % PKT_MNGLR_RW_LCK_MAX;
179 }
180
181 static void
pkt_mnglr_rw_lock_shared(lck_rw_t * lck)182 pkt_mnglr_rw_lock_shared(lck_rw_t *lck)
183 {
184 void *lr_saved;
185
186 lr_saved = __builtin_return_address(0);
187
188 lck_rw_lock_shared(lck);
189
190 pkt_mnglr_rw_lock_history[pkt_mnglr_rw_nxt_lck] = lr_saved;
191 pkt_mnglr_rw_nxt_lck = (pkt_mnglr_rw_nxt_lck + 1) % PKT_MNGLR_RW_LCK_MAX;
192 }
193
194 static void
pkt_mnglr_rw_unlock_shared(lck_rw_t * lck)195 pkt_mnglr_rw_unlock_shared(lck_rw_t *lck)
196 {
197 void *lr_saved;
198
199 lr_saved = __builtin_return_address(0);
200
201 lck_rw_unlock_shared(lck);
202
203 pkt_mnglr_rw_unlock_history[pkt_mnglr_rw_nxt_unlck] = lr_saved;
204 pkt_mnglr_rw_nxt_unlck = (pkt_mnglr_rw_nxt_unlck + 1) % PKT_MNGLR_RW_LCK_MAX;
205 }
206
207 /*
208 * Packet Mangler's Kernel control socket callbacks
209 */
210 static errno_t
pkt_mnglr_ctl_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)211 pkt_mnglr_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
212 void **unitinfo)
213 {
214 errno_t error = 0;
215 struct packet_mangler *p_pkt_mnglr = NULL;
216
217 PKT_MNGLR_LOG(LOG_NOTICE, "Connecting packet mangler filter.");
218
219 if (sac->sc_unit == 0 || sac->sc_unit > MAX_PACKET_MANGLER) {
220 PKT_MNGLR_LOG(LOG_ERR, "bad sc_unit %u", sac->sc_unit);
221 error = EINVAL;
222 goto fail;
223 }
224
225 p_pkt_mnglr = zalloc_flags(packet_mangler_zone,
226 Z_WAITOK | Z_ZERO | Z_NOFAIL);
227
228 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
229 if (packet_manglers == NULL) {
230 struct packet_mangler **tmp;
231
232 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
233
234 MALLOC(tmp,
235 struct packet_mangler **,
236 MAX_PACKET_MANGLER * sizeof(struct packet_mangler *),
237 M_TEMP,
238 M_WAITOK | M_ZERO);
239
240 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
241
242 if (tmp == NULL && packet_manglers == NULL) {
243 error = ENOMEM;
244 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
245 goto fail_free;
246 }
247 /* Another thread may have won the race */
248 if (packet_manglers != NULL) {
249 FREE(tmp, M_TEMP);
250 } else {
251 packet_manglers = tmp;
252 }
253 }
254
255 if (packet_manglers[sac->sc_unit - 1] != NULL) {
256 PKT_MNGLR_LOG(LOG_ERR, "sc_unit %u in use", sac->sc_unit);
257 error = EADDRINUSE;
258 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
259 goto fail_free;
260 } else {
261 /*
262 * kernel control socket kcunit numbers start at 1
263 */
264 packet_manglers[sac->sc_unit - 1] = p_pkt_mnglr;
265
266 p_pkt_mnglr->pkt_mnglr_kcref = kctlref;
267 p_pkt_mnglr->pkt_mnglr_kcunit = sac->sc_unit;
268
269 pkt_mnglr_active_count++;
270 }
271
272 p_pkt_mnglr->pkt_mnglr_ipfilter.cookie = p_pkt_mnglr;
273 p_pkt_mnglr->pkt_mnglr_ipfilter.name = "com.apple.pktmnglripfilter";
274 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_input = pktmnglr_ipfilter_input;
275 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_output = pktmnglr_ipfilter_output;
276 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_detach = pktmnglr_ipfilter_detach;
277 error = ipf_addv4(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfref));
278 if (error) {
279 PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv4 Filter");
280 goto fail_locked;
281 }
282 error = ipf_addv6(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfrefv6));
283 if (error) {
284 ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
285 PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv6 Filter");
286 goto fail_locked;
287 }
288
289 PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler's IP Filters");
290 p_pkt_mnglr->pkt_mnglr_flags |= PKT_MNGLR_FLG_IPFILTER_ATTACHED;
291 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
292
293 if (error) {
294 fail_locked:
295 pkt_mnglr_active_count--;
296
297 packet_manglers[sac->sc_unit - 1] = NULL;
298 *unitinfo = NULL;
299
300 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
301
302 fail_free:
303 zfree(packet_mangler_zone, p_pkt_mnglr);
304 }
305
306 fail:
307 *unitinfo = p_pkt_mnglr;
308
309 PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
310 error, pkt_mnglr_active_count, sac->sc_unit);
311
312 return error;
313 }
314
315 static errno_t
pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo)316 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo)
317 {
318 #pragma unused(kctlref)
319 errno_t error = 0;
320 struct packet_mangler *p_pkt_mnglr;
321
322 PKT_MNGLR_LOG(LOG_INFO, "Disconnecting packet mangler kernel control");
323
324 if (unitinfo == NULL) {
325 goto done;
326 }
327
328 if (packet_manglers == NULL) {
329 PKT_MNGLR_LOG(LOG_ERR, "no packet filter");
330 error = EINVAL;
331 goto done;
332 }
333 if (kcunit > MAX_PACKET_MANGLER) {
334 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
335 kcunit, MAX_PACKET_MANGLER);
336 error = EINVAL;
337 goto done;
338 }
339
340 p_pkt_mnglr = (struct packet_mangler *)unitinfo;
341
342 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
343 if (packet_manglers[kcunit - 1] != p_pkt_mnglr || p_pkt_mnglr->pkt_mnglr_kcunit != kcunit) {
344 PKT_MNGLR_LOG(LOG_ERR, "bad unit info %u",
345 kcunit);
346 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
347 goto done;
348 }
349
350 /*
351 * Make filter inactive
352 */
353 packet_manglers[kcunit - 1] = NULL;
354 pkt_mnglr_active_count--;
355 if (p_pkt_mnglr->pkt_mnglr_flags & PKT_MNGLR_FLG_IPFILTER_ATTACHED) {
356 (void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
357 (void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfrefv6);
358 }
359 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
360 zfree(packet_mangler_zone, p_pkt_mnglr);
361 done:
362 PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
363 error, pkt_mnglr_active_count, kcunit);
364
365 return error;
366 }
367
368 static errno_t
pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t * len)369 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
370 int opt, void *data, size_t *len)
371 {
372 #pragma unused(kctlref, opt)
373 errno_t error = 0;
374 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
375
376 PKT_MNGLR_LOG(LOG_NOTICE, "");
377
378 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw);
379
380 if (packet_manglers == NULL) {
381 PKT_MNGLR_LOG(LOG_ERR, "no packet filter");
382 error = EINVAL;
383 goto done;
384 }
385 if (kcunit > MAX_PACKET_MANGLER) {
386 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
387 kcunit, MAX_PACKET_MANGLER);
388 error = EINVAL;
389 goto done;
390 }
391 if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
392 PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
393 kcunit);
394 error = EINVAL;
395 goto done;
396 }
397 switch (opt) {
398 case PKT_MNGLR_OPT_PROTO_ACT_MASK:
399 if (*len < sizeof(uint32_t)) {
400 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
401 "len too small %lu", *len);
402 error = EINVAL;
403 goto done;
404 }
405
406 if (data != NULL) {
407 *(uint32_t *)data = p_pkt_mnglr->proto_action_mask;
408 }
409 break;
410 case PKT_MNGLR_OPT_IP_ACT_MASK:
411 if (*len < sizeof(uint32_t)) {
412 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
413 "len too small %lu", *len);
414 error = EINVAL;
415 goto done;
416 }
417
418 if (data != NULL) {
419 *(uint32_t *)data = p_pkt_mnglr->ip_action_mask;
420 }
421 break;
422 case PKT_MNGLR_OPT_LOCAL_IP:
423 if (*len < sizeof(struct sockaddr_storage)) {
424 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
425 "len too small %lu", *len);
426 error = EINVAL;
427 goto done;
428 }
429
430 if (data != NULL) {
431 *(struct sockaddr_storage *)data = p_pkt_mnglr->lsaddr;
432 }
433 break;
434 case PKT_MNGLR_OPT_REMOTE_IP:
435 if (*len < sizeof(struct sockaddr_storage)) {
436 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
437 "len too small %lu", *len);
438 error = EINVAL;
439 goto done;
440 }
441
442 if (data != NULL) {
443 *(struct sockaddr_storage *)data = p_pkt_mnglr->rsaddr;
444 }
445 break;
446 case PKT_MNGLR_OPT_LOCAL_PORT:
447 if (*len < sizeof(uint16_t)) {
448 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
449 "len too small %lu", *len);
450 error = EINVAL;
451 goto done;
452 }
453
454 if (data != NULL) {
455 *(uint16_t *)data = p_pkt_mnglr->lport;
456 }
457 break;
458 case PKT_MNGLR_OPT_REMOTE_PORT:
459 if (*len < sizeof(uint16_t)) {
460 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
461 "len too small %lu", *len);
462 error = EINVAL;
463 goto done;
464 }
465
466 if (data != NULL) {
467 *(uint16_t *)data = p_pkt_mnglr->rport;
468 }
469 break;
470 case PKT_MNGLR_OPT_DIRECTION:
471 if (*len < sizeof(uint32_t)) {
472 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
473 "len too small %lu", *len);
474 error = EINVAL;
475 goto done;
476 }
477 if (data != NULL) {
478 *(uint32_t *)data = p_pkt_mnglr->dir;
479 }
480 break;
481 case PKT_MNGLR_OPT_PROTOCOL:
482 if (*len < sizeof(uint32_t)) {
483 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
484 "len too small %lu", *len);
485 error = EINVAL;
486 goto done;
487 }
488 if (data != NULL) {
489 *(uint32_t *)data = p_pkt_mnglr->proto;
490 }
491 break;
492 case PKT_MNGLR_OPT_ACTIVATE:
493 if (*len < sizeof(uint8_t)) {
494 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
495 "len too small %lu", *len);
496 error = EINVAL;
497 goto done;
498 }
499
500 if (data != NULL) {
501 *(uint8_t *)data = p_pkt_mnglr->activate;
502 }
503 break;
504 default:
505 error = ENOPROTOOPT;
506 break;
507 }
508 done:
509 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw);
510
511 return error;
512 }
513
514 static errno_t
pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t len)515 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
516 int opt, void *data, size_t len)
517 {
518 #pragma unused(kctlref, opt)
519 errno_t error = 0;
520 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
521
522 PKT_MNGLR_LOG(LOG_NOTICE, "");
523
524 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
525
526 if (packet_manglers == NULL) {
527 PKT_MNGLR_LOG(LOG_ERR, "no packet filter");
528 error = EINVAL;
529 goto done;
530 }
531 if (kcunit > MAX_PACKET_MANGLER) {
532 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
533 kcunit, MAX_PACKET_MANGLER);
534 error = EINVAL;
535 goto done;
536 }
537 if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
538 PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
539 kcunit);
540 error = EINVAL;
541 goto done;
542 }
543 switch (opt) {
544 case PKT_MNGLR_OPT_PROTO_ACT_MASK:
545 if (len < sizeof(uint32_t)) {
546 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
547 "len too small %lu", len);
548 error = EINVAL;
549 goto done;
550 }
551 if (p_pkt_mnglr->proto_action_mask != 0) {
552 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
553 "already set %u",
554 p_pkt_mnglr->proto_action_mask);
555 error = EINVAL;
556 goto done;
557 }
558 p_pkt_mnglr->proto_action_mask = *(uint32_t *)data;
559 PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr->proto_action_mask);
560 break;
561 case PKT_MNGLR_OPT_IP_ACT_MASK:
562 if (len < sizeof(uint32_t)) {
563 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
564 "len too small %lu", len);
565 error = EINVAL;
566 goto done;
567 }
568 if (p_pkt_mnglr->ip_action_mask != 0) {
569 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
570 "already set %u",
571 p_pkt_mnglr->ip_action_mask);
572 error = EINVAL;
573 goto done;
574 }
575 p_pkt_mnglr->ip_action_mask = *(uint32_t *)data;
576 break;
577 case PKT_MNGLR_OPT_LOCAL_IP:
578 if (len < sizeof(struct sockaddr_storage)) {
579 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
580 "len too small %lu", len);
581 error = EINVAL;
582 goto done;
583 }
584 if (p_pkt_mnglr->lsaddr.ss_family) {
585 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
586 "already set");
587 error = EINVAL;
588 goto done;
589 }
590 p_pkt_mnglr->lsaddr = *(struct sockaddr_storage *)data;
591 break;
592 case PKT_MNGLR_OPT_REMOTE_IP:
593 if (len < sizeof(struct sockaddr_storage)) {
594 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
595 "len too small %lu", len);
596 error = EINVAL;
597 goto done;
598 }
599 if (p_pkt_mnglr->rsaddr.ss_family) {
600 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
601 "already set");
602 error = EINVAL;
603 goto done;
604 }
605
606 p_pkt_mnglr->rsaddr = *(struct sockaddr_storage *)data;
607 PKT_MNGLR_LOG(LOG_INFO,
608 "Remote IP registered for address family: %d",
609 p_pkt_mnglr->rsaddr.ss_family);
610 break;
611 case PKT_MNGLR_OPT_LOCAL_PORT:
612 if (len < sizeof(uint16_t)) {
613 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
614 "len too small %lu", len);
615 error = EINVAL;
616 goto done;
617 }
618 if (p_pkt_mnglr->lport != 0) {
619 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
620 "already set %d",
621 p_pkt_mnglr->lport);
622 error = EINVAL;
623 goto done;
624 }
625 p_pkt_mnglr->lport = *(uint16_t *)data;
626 break;
627 case PKT_MNGLR_OPT_REMOTE_PORT:
628 if (len < sizeof(uint16_t)) {
629 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
630 "len too small %lu", len);
631 error = EINVAL;
632 goto done;
633 }
634 if (p_pkt_mnglr->rport != 0) {
635 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
636 "already set %d",
637 p_pkt_mnglr->rport);
638 error = EINVAL;
639 goto done;
640 }
641 p_pkt_mnglr->rport = *(uint16_t *)data;
642 break;
643 case PKT_MNGLR_OPT_DIRECTION:
644 if (len < sizeof(uint32_t)) {
645 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
646 "len too small %lu", len);
647 error = EINVAL;
648 goto done;
649 }
650 if (p_pkt_mnglr->dir != 0) {
651 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
652 "already set %u",
653 p_pkt_mnglr->dir);
654 error = EINVAL;
655 goto done;
656 }
657 p_pkt_mnglr->dir = *(uint32_t *)data;
658 break;
659 case PKT_MNGLR_OPT_PROTOCOL:
660 if (len < sizeof(uint32_t)) {
661 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
662 "len too small %lu", len);
663 error = EINVAL;
664 goto done;
665 }
666 if (p_pkt_mnglr->proto != 0) {
667 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
668 "already set %u",
669 p_pkt_mnglr->proto);
670 error = EINVAL;
671 goto done;
672 }
673 p_pkt_mnglr->proto = *(uint32_t *)data;
674 break;
675 case PKT_MNGLR_OPT_ACTIVATE:
676 if (len < sizeof(uint8_t)) {
677 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
678 "len too small %lu", len);
679 error = EINVAL;
680 goto done;
681 }
682 if (p_pkt_mnglr->activate != 0) {
683 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
684 "already set %u",
685 p_pkt_mnglr->activate);
686 error = EINVAL;
687 goto done;
688 }
689 p_pkt_mnglr->activate = *(uint8_t *)data;
690 PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr->activate set to :%d",
691 p_pkt_mnglr->activate);
692 break;
693 default:
694 error = ENOPROTOOPT;
695 break;
696 }
697 done:
698 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
699
700 return error;
701 }
702
703 void
pkt_mnglr_init(void)704 pkt_mnglr_init(void)
705 {
706 struct kern_ctl_reg kern_ctl;
707 errno_t error = 0;
708
709 PKT_MNGLR_LOG(LOG_NOTICE, "");
710
711 /*
712 * Compile time verifications
713 */
714 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT == MAX_PACKET_MANGLER);
715
716 /*
717 * Register kernel control
718 */
719 bzero(&kern_ctl, sizeof(kern_ctl));
720 strlcpy(kern_ctl.ctl_name, PACKET_MANGLER_CONTROL_NAME,
721 sizeof(kern_ctl.ctl_name));
722 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_EXTENDED;
723 kern_ctl.ctl_connect = pkt_mnglr_ctl_connect;
724 kern_ctl.ctl_disconnect = pkt_mnglr_ctl_disconnect;
725 kern_ctl.ctl_getopt = pkt_mnglr_ctl_getopt;
726 kern_ctl.ctl_setopt = pkt_mnglr_ctl_setopt;
727 error = ctl_register(&kern_ctl, &pkt_mnglr_kctlref);
728 if (error != 0) {
729 PKT_MNGLR_LOG(LOG_ERR, "ctl_register failed: %d", error);
730 } else {
731 PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler kernel control.");
732 }
733 }
734
735 static errno_t
pktmnglr_ipfilter_output(void * cookie,mbuf_t * data,ipf_pktopts_t options)736 pktmnglr_ipfilter_output(void *cookie, mbuf_t *data, ipf_pktopts_t options)
737 {
738 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
739 struct ip ip;
740 struct tcphdr tcp;
741 int optlen = 0;
742 errno_t error = 0;
743
744 #pragma unused(tcp, optlen, options)
745 if (p_pkt_mnglr == NULL) {
746 goto output_done;
747 }
748
749 if (!p_pkt_mnglr->activate) {
750 goto output_done;
751 }
752
753 if (p_pkt_mnglr->dir == IN) {
754 goto output_done;
755 }
756
757 if (data == NULL) {
758 PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
759 goto output_done;
760 }
761
762 /* Check for IP filter options */
763 error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
764 if (error) {
765 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
766 goto output_done;
767 }
768
769 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
770 goto output_done;
771 }
772
773 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
774 goto output_done;
775 }
776
777 if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
778 struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
779 if (ip.ip_src.s_addr != laddr.sin_addr.s_addr) {
780 goto output_done;
781 }
782 }
783
784 if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
785 struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
786 if (ip.ip_dst.s_addr != raddr.sin_addr.s_addr) {
787 goto output_done;
788 }
789 }
790
791 if (ip.ip_v != 4) {
792 PKT_MNGLR_LOG(LOG_INFO,
793 "%s:%d Not handling IP version %d\n",
794 __func__, __LINE__, ip.ip_v);
795 goto output_done;
796 }
797
798 output_done:
799 /* Not handling output flow */
800 return 0;
801 }
802
803 #define TCP_MAX_OPTLEN 40
804
805 static errno_t
pktmnglr_ipfilter_input(void * cookie,mbuf_t * data,int offset,u_int8_t protocol)806 pktmnglr_ipfilter_input(void *cookie, mbuf_t *data, int offset, u_int8_t protocol)
807 {
808 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
809 struct ip6_hdr ip6;
810 struct ip ip;
811 struct tcphdr tcp;
812 size_t ip_pld_len;
813 errno_t error = 0;
814
815 if (p_pkt_mnglr == NULL) {
816 PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr is NULL");
817 goto input_done;
818 }
819
820 if (p_pkt_mnglr->activate == 0) {
821 PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr not yet activated");
822 goto input_done;
823 }
824
825 if (p_pkt_mnglr->dir == OUT) {
826 goto input_done;
827 }
828
829 if (data == NULL) {
830 PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
831 goto input_done;
832 }
833
834 /* Check for IP filter options */
835 error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
836 if (error) {
837 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
838 goto input_done;
839 }
840
841 if (ip.ip_v == 6) {
842 error = mbuf_copydata(*data, 0, sizeof(ip6), &ip6);
843 if (error) {
844 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IPv6 header copy");
845 goto input_done;
846 }
847 }
848
849 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
850 PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family of packet is IPv4 but local "
851 "address is set to IPv6");
852 goto input_done;
853 }
854
855 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
856 PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family "
857 "of packet is IPv6 but local address is set to IPv4");
858 goto input_done;
859 }
860
861 if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
862 struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
863 if (ip.ip_dst.s_addr != laddr.sin_addr.s_addr) {
864 goto input_done;
865 }
866 } else if (p_pkt_mnglr->lsaddr.ss_family == AF_INET6) {
867 struct sockaddr_in6 laddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->lsaddr));
868 if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_dst, &laddr.sin6_addr)) {
869 goto input_done;
870 }
871 }
872
873 if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
874 struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
875 if (ip.ip_src.s_addr != raddr.sin_addr.s_addr) {
876 goto input_done;
877 }
878 PKT_MNGLR_LOG(LOG_INFO, "Remote IP: %x Source IP: %x in input path",
879 raddr.sin_addr.s_addr,
880 ip.ip_src.s_addr);
881 } else if (p_pkt_mnglr->rsaddr.ss_family == AF_INET6) {
882 struct sockaddr_in6 raddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->rsaddr));
883 if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_src, &raddr.sin6_addr)) {
884 goto input_done;
885 }
886 }
887
888 if (ip.ip_v == 4) {
889 ip_pld_len = ntohs(ip.ip_len) - (ip.ip_hl << 2);
890 } else if (ip.ip_v == 6) {
891 if (ip6.ip6_nxt != p_pkt_mnglr->proto) {
892 /* Don't support IPv6 extension headers */
893 goto input_done;
894 }
895 ip_pld_len = ntohs(ip6.ip6_plen);
896 } else {
897 goto input_done;
898 }
899
900
901 if (protocol != p_pkt_mnglr->proto) {
902 PKT_MNGLR_LOG(LOG_INFO, "Skip: Protocol mismatch");
903 goto input_done;
904 }
905
906 switch (protocol) {
907 case IPPROTO_TCP:
908 if (ip_pld_len < sizeof(tcp)) {
909 PKT_MNGLR_LOG(LOG_ERR, "IP total len not big enough for TCP: %zu", ip_pld_len);
910 goto drop_it;
911 }
912
913 error = mbuf_copydata(*data, (size_t)offset, sizeof(tcp), &tcp);
914 if (error) {
915 PKT_MNGLR_LOG(LOG_ERR, "Could not make local TCP header copy");
916 goto input_done;
917 }
918
919 if (p_pkt_mnglr->lport && (p_pkt_mnglr->lport != tcp.th_dport)) {
920 PKT_MNGLR_LOG(LOG_INFO, "Local port and IP des port do not match");
921 goto input_done;
922 }
923
924 if (p_pkt_mnglr->rport && (p_pkt_mnglr->rport != tcp.th_sport)) {
925 PKT_MNGLR_LOG(LOG_INFO, "Remote port and IP src port do not match");
926 goto input_done;
927 }
928 break;
929 case IPPROTO_UDP:
930 goto input_done;
931 case IPPROTO_ICMP:
932 goto input_done;
933 case IPPROTO_ICMPV6:
934 goto input_done;
935 default:
936 goto input_done;
937 }
938
939 /* XXX Do IP actions here */
940 PKT_MNGLR_LOG(LOG_INFO, "Proceeding with packet mangler actions on the packet");
941
942 /* Protocol actions */
943 switch (protocol) {
944 case IPPROTO_TCP:
945 if (p_pkt_mnglr->proto_action_mask) {
946 unsigned char tcp_opt_buf[TCP_MAX_OPTLEN] = {0};
947 size_t orig_tcp_optlen;
948 size_t tcp_optlen = 0;
949 size_t i = 0, off;
950
951 off = (tcp.th_off << 2);
952
953 if (off < sizeof(struct tcphdr) || off > ip_pld_len) {
954 PKT_MNGLR_LOG(LOG_ERR, "TCP header offset is wrong: %zu", off);
955 goto drop_it;
956 }
957
958 tcp_optlen = off - sizeof(struct tcphdr);
959
960 PKT_MNGLR_LOG(LOG_INFO, "Packet from F5 is TCP\n");
961 PKT_MNGLR_LOG(LOG_INFO, "Optlen: %zu\n", tcp_optlen);
962 orig_tcp_optlen = tcp_optlen;
963 if (orig_tcp_optlen) {
964 error = mbuf_copydata(*data, (size_t)offset + sizeof(struct tcphdr), orig_tcp_optlen, tcp_opt_buf);
965 if (error) {
966 PKT_MNGLR_LOG(LOG_ERR, "Failed to copy tcp options: error %d offset %d optlen %zu", error, offset, orig_tcp_optlen);
967 goto input_done;
968 }
969 }
970
971 while (tcp_optlen > 0) {
972 if (tcp_opt_buf[i] == 0x1) {
973 PKT_MNGLR_LOG(LOG_INFO, "Skipping NOP\n");
974 tcp_optlen--;
975 i++;
976 continue;
977 } else if ((tcp_opt_buf[i] != 0) && (tcp_opt_buf[i] != TCP_OPT_MULTIPATH_TCP)) {
978 unsigned char optlen;
979
980 PKT_MNGLR_LOG(LOG_INFO, "Skipping option %x\n", tcp_opt_buf[i]);
981
982 if (tcp_optlen < 2) {
983 PKT_MNGLR_LOG(LOG_ERR, "Received short TCP option");
984 goto drop_it;
985 }
986
987 /* Minimum TCP option size is 2 */
988 optlen = tcp_opt_buf[i + 1];
989 if (optlen < 2 || optlen > tcp_optlen) {
990 PKT_MNGLR_LOG(LOG_ERR, "Received suspicious TCP option");
991 goto drop_it;
992 }
993 tcp_optlen -= optlen;
994 i += optlen;
995 continue;
996 } else if (tcp_opt_buf[i] == TCP_OPT_MULTIPATH_TCP) {
997 size_t j = 0;
998 unsigned char mptcpoptlen;
999 uint8_t sbtver;
1000 uint8_t subtype;
1001
1002 if (tcp_optlen < 3) {
1003 PKT_MNGLR_LOG(LOG_ERR, "Received short MPTCP option");
1004 goto drop_it;
1005 }
1006
1007 /* Minimum MPTCP option size is 3 */
1008 mptcpoptlen = tcp_opt_buf[i + 1];
1009 if (mptcpoptlen < 3 || mptcpoptlen > tcp_optlen) {
1010 PKT_MNGLR_LOG(LOG_ERR, "Received suspicious MPTCP option");
1011 goto drop_it;
1012 }
1013
1014 sbtver = tcp_opt_buf[i + MPTCP_SBT_VER_OFFSET];
1015 subtype = sbtver >> 4;
1016
1017 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
1018 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP subtype %x\n", subtype);
1019 if (subtype == MPTCP_SUBTYPE_DSS) {
1020 PKT_MNGLR_LOG(LOG_INFO, "Got DSS option\n");
1021 PKT_MNGLR_LOG(LOG_INFO, "Protocol option mask: %d\n", p_pkt_mnglr->proto_action_mask);
1022 if (p_pkt_mnglr->proto_action_mask &
1023 PKT_MNGLR_TCP_ACT_DSS_DROP) {
1024 goto drop_it;
1025 }
1026 }
1027
1028 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
1029 for (; j < mptcpoptlen && j < tcp_optlen; j++) {
1030 if (p_pkt_mnglr->proto_action_mask &
1031 PKT_MNGLR_TCP_ACT_NOP_MPTCP) {
1032 tcp_opt_buf[i + j] = 0x1;
1033 }
1034 }
1035 tcp_optlen -= mptcpoptlen;
1036 i += mptcpoptlen;
1037 } else {
1038 tcp_optlen--;
1039 i++;
1040 }
1041 }
1042
1043 if (orig_tcp_optlen) {
1044 error = mbuf_copyback(*data,
1045 (size_t)offset + sizeof(struct tcphdr),
1046 orig_tcp_optlen, tcp_opt_buf, MBUF_WAITOK);
1047
1048 if (error) {
1049 PKT_MNGLR_LOG(LOG_ERR,
1050 "Failed to copy tcp options back: error %d offset %d optlen %zu",
1051 error, offset, orig_tcp_optlen);
1052 goto input_done;
1053 }
1054 }
1055 }
1056 break;
1057 case IPPROTO_UDP:
1058 /* Don't handle UDP */
1059 break;
1060 case IPPROTO_ICMP:
1061 break;
1062 case IPPROTO_ICMPV6:
1063 break;
1064 default:
1065 break;
1066 }
1067 chksm_update(*data);
1068 input_done:
1069 return 0;
1070
1071 drop_it:
1072 PKT_MNGLR_LOG(LOG_INFO, "Dropping packet\n");
1073 mbuf_freem(*data);
1074 return EJUSTRETURN;
1075 }
1076
1077 static void
pktmnglr_ipfilter_detach(void * cookie)1078 pktmnglr_ipfilter_detach(void *cookie)
1079 {
1080 #pragma unused(cookie)
1081 return;
1082 }
1083
1084 /* XXX Still need to modify this to use mbuf_copy* macros */
1085 static void
chksm_update(mbuf_t data)1086 chksm_update(mbuf_t data)
1087 {
1088 u_int16_t ip_sum;
1089 u_int16_t tsum;
1090 struct tcphdr *tcp;
1091 errno_t err;
1092
1093 unsigned char *ptr = (unsigned char *)mbuf_data(data);
1094 struct ip *ip = (struct ip *)(void *)ptr;
1095 if (ip->ip_v != 4) {
1096 return;
1097 }
1098
1099 ip->ip_sum = 0;
1100 err = mbuf_inet_cksum(data, 0, 0, ip->ip_hl << 2, &ip_sum); // ip sum
1101 if (err == 0) {
1102 ip->ip_sum = ip_sum;
1103 }
1104 switch (ip->ip_p) {
1105 case IPPROTO_TCP:
1106 tcp = (struct tcphdr *)(void *)(ptr + (ip->ip_hl << 2));
1107 tcp->th_sum = 0;
1108 err = mbuf_inet_cksum(data, IPPROTO_TCP, ip->ip_hl << 2,
1109 ntohs(ip->ip_len) - (ip->ip_hl << 2), &tsum);
1110 if (err == 0) {
1111 tcp->th_sum = tsum;
1112 }
1113 break;
1114 case IPPROTO_UDP:
1115 /* Don't handle UDP */
1116 break;
1117 case IPPROTO_ICMP:
1118 break;
1119 case IPPROTO_ICMPV6:
1120 break;
1121 default:
1122 break;
1123 }
1124
1125 mbuf_clear_csum_performed(data);
1126 return;
1127 }
1128