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[MAX_PACKET_MANGLER];
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_DEFINE(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
230 if (packet_manglers[sac->sc_unit - 1] != NULL) {
231 PKT_MNGLR_LOG(LOG_ERR, "sc_unit %u in use", sac->sc_unit);
232 error = EADDRINUSE;
233 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
234 goto fail_free;
235 } else {
236 /*
237 * kernel control socket kcunit numbers start at 1
238 */
239 packet_manglers[sac->sc_unit - 1] = p_pkt_mnglr;
240
241 p_pkt_mnglr->pkt_mnglr_kcref = kctlref;
242 p_pkt_mnglr->pkt_mnglr_kcunit = sac->sc_unit;
243
244 pkt_mnglr_active_count++;
245 }
246
247 p_pkt_mnglr->pkt_mnglr_ipfilter.cookie = p_pkt_mnglr;
248 p_pkt_mnglr->pkt_mnglr_ipfilter.name = "com.apple.pktmnglripfilter";
249 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_input = pktmnglr_ipfilter_input;
250 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_output = pktmnglr_ipfilter_output;
251 p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_detach = pktmnglr_ipfilter_detach;
252 error = ipf_addv4(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfref));
253 if (error) {
254 PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv4 Filter");
255 goto fail_locked;
256 }
257 error = ipf_addv6(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfrefv6));
258 if (error) {
259 ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
260 PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv6 Filter");
261 goto fail_locked;
262 }
263
264 PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler's IP Filters");
265 p_pkt_mnglr->pkt_mnglr_flags |= PKT_MNGLR_FLG_IPFILTER_ATTACHED;
266 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
267
268 if (error) {
269 fail_locked:
270 pkt_mnglr_active_count--;
271
272 packet_manglers[sac->sc_unit - 1] = NULL;
273 *unitinfo = NULL;
274
275 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
276
277 fail_free:
278 zfree(packet_mangler_zone, p_pkt_mnglr);
279 }
280
281 fail:
282 *unitinfo = p_pkt_mnglr;
283
284 PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
285 error, pkt_mnglr_active_count, sac->sc_unit);
286
287 return error;
288 }
289
290 static errno_t
pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo)291 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo)
292 {
293 #pragma unused(kctlref)
294 errno_t error = 0;
295 struct packet_mangler *p_pkt_mnglr;
296
297 PKT_MNGLR_LOG(LOG_INFO, "Disconnecting packet mangler kernel control");
298
299 if (unitinfo == NULL) {
300 goto done;
301 }
302
303 if (kcunit > MAX_PACKET_MANGLER) {
304 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
305 kcunit, MAX_PACKET_MANGLER);
306 error = EINVAL;
307 goto done;
308 }
309
310 p_pkt_mnglr = (struct packet_mangler *)unitinfo;
311
312 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
313 if (packet_manglers[kcunit - 1] != p_pkt_mnglr || p_pkt_mnglr->pkt_mnglr_kcunit != kcunit) {
314 PKT_MNGLR_LOG(LOG_ERR, "bad unit info %u",
315 kcunit);
316 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
317 goto done;
318 }
319
320 /*
321 * Make filter inactive
322 */
323 packet_manglers[kcunit - 1] = NULL;
324 pkt_mnglr_active_count--;
325 if (p_pkt_mnglr->pkt_mnglr_flags & PKT_MNGLR_FLG_IPFILTER_ATTACHED) {
326 (void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
327 (void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfrefv6);
328 }
329 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
330 zfree(packet_mangler_zone, p_pkt_mnglr);
331 done:
332 PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
333 error, pkt_mnglr_active_count, kcunit);
334
335 return error;
336 }
337
338 static errno_t
pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t * len)339 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
340 int opt, void *data, size_t *len)
341 {
342 #pragma unused(kctlref, opt)
343 errno_t error = 0;
344 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
345
346 PKT_MNGLR_LOG(LOG_NOTICE, "");
347
348 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw);
349
350 if (kcunit > MAX_PACKET_MANGLER) {
351 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
352 kcunit, MAX_PACKET_MANGLER);
353 error = EINVAL;
354 goto done;
355 }
356 if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
357 PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
358 kcunit);
359 error = EINVAL;
360 goto done;
361 }
362 switch (opt) {
363 case PKT_MNGLR_OPT_PROTO_ACT_MASK:
364 if (*len < sizeof(uint32_t)) {
365 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
366 "len too small %lu", *len);
367 error = EINVAL;
368 goto done;
369 }
370
371 if (data != NULL) {
372 *(uint32_t *)data = p_pkt_mnglr->proto_action_mask;
373 }
374 break;
375 case PKT_MNGLR_OPT_IP_ACT_MASK:
376 if (*len < sizeof(uint32_t)) {
377 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
378 "len too small %lu", *len);
379 error = EINVAL;
380 goto done;
381 }
382
383 if (data != NULL) {
384 *(uint32_t *)data = p_pkt_mnglr->ip_action_mask;
385 }
386 break;
387 case PKT_MNGLR_OPT_LOCAL_IP:
388 if (*len < sizeof(struct sockaddr_storage)) {
389 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
390 "len too small %lu", *len);
391 error = EINVAL;
392 goto done;
393 }
394
395 if (data != NULL) {
396 *(struct sockaddr_storage *)data = p_pkt_mnglr->lsaddr;
397 }
398 break;
399 case PKT_MNGLR_OPT_REMOTE_IP:
400 if (*len < sizeof(struct sockaddr_storage)) {
401 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
402 "len too small %lu", *len);
403 error = EINVAL;
404 goto done;
405 }
406
407 if (data != NULL) {
408 *(struct sockaddr_storage *)data = p_pkt_mnglr->rsaddr;
409 }
410 break;
411 case PKT_MNGLR_OPT_LOCAL_PORT:
412 if (*len < sizeof(uint16_t)) {
413 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
414 "len too small %lu", *len);
415 error = EINVAL;
416 goto done;
417 }
418
419 if (data != NULL) {
420 *(uint16_t *)data = p_pkt_mnglr->lport;
421 }
422 break;
423 case PKT_MNGLR_OPT_REMOTE_PORT:
424 if (*len < sizeof(uint16_t)) {
425 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
426 "len too small %lu", *len);
427 error = EINVAL;
428 goto done;
429 }
430
431 if (data != NULL) {
432 *(uint16_t *)data = p_pkt_mnglr->rport;
433 }
434 break;
435 case PKT_MNGLR_OPT_DIRECTION:
436 if (*len < sizeof(uint32_t)) {
437 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
438 "len too small %lu", *len);
439 error = EINVAL;
440 goto done;
441 }
442 if (data != NULL) {
443 *(uint32_t *)data = p_pkt_mnglr->dir;
444 }
445 break;
446 case PKT_MNGLR_OPT_PROTOCOL:
447 if (*len < sizeof(uint32_t)) {
448 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
449 "len too small %lu", *len);
450 error = EINVAL;
451 goto done;
452 }
453 if (data != NULL) {
454 *(uint32_t *)data = p_pkt_mnglr->proto;
455 }
456 break;
457 case PKT_MNGLR_OPT_ACTIVATE:
458 if (*len < sizeof(uint8_t)) {
459 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
460 "len too small %lu", *len);
461 error = EINVAL;
462 goto done;
463 }
464
465 if (data != NULL) {
466 *(uint8_t *)data = p_pkt_mnglr->activate;
467 }
468 break;
469 default:
470 error = ENOPROTOOPT;
471 break;
472 }
473 done:
474 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw);
475
476 return error;
477 }
478
479 static errno_t
pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t len)480 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
481 int opt, void *data, size_t len)
482 {
483 #pragma unused(kctlref, opt)
484 errno_t error = 0;
485 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
486
487 PKT_MNGLR_LOG(LOG_NOTICE, "");
488
489 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
490
491 if (kcunit > MAX_PACKET_MANGLER) {
492 PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
493 kcunit, MAX_PACKET_MANGLER);
494 error = EINVAL;
495 goto done;
496 }
497 if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
498 PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
499 kcunit);
500 error = EINVAL;
501 goto done;
502 }
503 switch (opt) {
504 case PKT_MNGLR_OPT_PROTO_ACT_MASK:
505 if (len < sizeof(uint32_t)) {
506 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
507 "len too small %lu", len);
508 error = EINVAL;
509 goto done;
510 }
511 if (p_pkt_mnglr->proto_action_mask != 0) {
512 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
513 "already set %u",
514 p_pkt_mnglr->proto_action_mask);
515 error = EINVAL;
516 goto done;
517 }
518 p_pkt_mnglr->proto_action_mask = *(uint32_t *)data;
519 PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr->proto_action_mask);
520 break;
521 case PKT_MNGLR_OPT_IP_ACT_MASK:
522 if (len < sizeof(uint32_t)) {
523 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
524 "len too small %lu", len);
525 error = EINVAL;
526 goto done;
527 }
528 if (p_pkt_mnglr->ip_action_mask != 0) {
529 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
530 "already set %u",
531 p_pkt_mnglr->ip_action_mask);
532 error = EINVAL;
533 goto done;
534 }
535 p_pkt_mnglr->ip_action_mask = *(uint32_t *)data;
536 break;
537 case PKT_MNGLR_OPT_LOCAL_IP:
538 if (len < sizeof(struct sockaddr_storage)) {
539 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
540 "len too small %lu", len);
541 error = EINVAL;
542 goto done;
543 }
544 if (p_pkt_mnglr->lsaddr.ss_family) {
545 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
546 "already set");
547 error = EINVAL;
548 goto done;
549 }
550 p_pkt_mnglr->lsaddr = *(struct sockaddr_storage *)data;
551 break;
552 case PKT_MNGLR_OPT_REMOTE_IP:
553 if (len < sizeof(struct sockaddr_storage)) {
554 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
555 "len too small %lu", len);
556 error = EINVAL;
557 goto done;
558 }
559 if (p_pkt_mnglr->rsaddr.ss_family) {
560 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
561 "already set");
562 error = EINVAL;
563 goto done;
564 }
565
566 p_pkt_mnglr->rsaddr = *(struct sockaddr_storage *)data;
567 PKT_MNGLR_LOG(LOG_INFO,
568 "Remote IP registered for address family: %d",
569 p_pkt_mnglr->rsaddr.ss_family);
570 break;
571 case PKT_MNGLR_OPT_LOCAL_PORT:
572 if (len < sizeof(uint16_t)) {
573 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
574 "len too small %lu", len);
575 error = EINVAL;
576 goto done;
577 }
578 if (p_pkt_mnglr->lport != 0) {
579 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
580 "already set %d",
581 p_pkt_mnglr->lport);
582 error = EINVAL;
583 goto done;
584 }
585 p_pkt_mnglr->lport = *(uint16_t *)data;
586 break;
587 case PKT_MNGLR_OPT_REMOTE_PORT:
588 if (len < sizeof(uint16_t)) {
589 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
590 "len too small %lu", len);
591 error = EINVAL;
592 goto done;
593 }
594 if (p_pkt_mnglr->rport != 0) {
595 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
596 "already set %d",
597 p_pkt_mnglr->rport);
598 error = EINVAL;
599 goto done;
600 }
601 p_pkt_mnglr->rport = *(uint16_t *)data;
602 break;
603 case PKT_MNGLR_OPT_DIRECTION:
604 if (len < sizeof(uint32_t)) {
605 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
606 "len too small %lu", len);
607 error = EINVAL;
608 goto done;
609 }
610 if (p_pkt_mnglr->dir != 0) {
611 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
612 "already set %u",
613 p_pkt_mnglr->dir);
614 error = EINVAL;
615 goto done;
616 }
617 p_pkt_mnglr->dir = *(uint32_t *)data;
618 break;
619 case PKT_MNGLR_OPT_PROTOCOL:
620 if (len < sizeof(uint32_t)) {
621 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
622 "len too small %lu", len);
623 error = EINVAL;
624 goto done;
625 }
626 if (p_pkt_mnglr->proto != 0) {
627 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
628 "already set %u",
629 p_pkt_mnglr->proto);
630 error = EINVAL;
631 goto done;
632 }
633 p_pkt_mnglr->proto = *(uint32_t *)data;
634 break;
635 case PKT_MNGLR_OPT_ACTIVATE:
636 if (len < sizeof(uint8_t)) {
637 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
638 "len too small %lu", len);
639 error = EINVAL;
640 goto done;
641 }
642 if (p_pkt_mnglr->activate != 0) {
643 PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
644 "already set %u",
645 p_pkt_mnglr->activate);
646 error = EINVAL;
647 goto done;
648 }
649 p_pkt_mnglr->activate = *(uint8_t *)data;
650 PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr->activate set to :%d",
651 p_pkt_mnglr->activate);
652 break;
653 default:
654 error = ENOPROTOOPT;
655 break;
656 }
657 done:
658 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
659
660 return error;
661 }
662
663 void
pkt_mnglr_init(void)664 pkt_mnglr_init(void)
665 {
666 struct kern_ctl_reg kern_ctl;
667 errno_t error = 0;
668
669 PKT_MNGLR_LOG(LOG_NOTICE, "");
670
671 /*
672 * Compile time verifications
673 */
674 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT == MAX_PACKET_MANGLER);
675
676 /*
677 * Register kernel control
678 */
679 bzero(&kern_ctl, sizeof(kern_ctl));
680 strlcpy(kern_ctl.ctl_name, PACKET_MANGLER_CONTROL_NAME,
681 sizeof(kern_ctl.ctl_name));
682 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_EXTENDED;
683 kern_ctl.ctl_connect = pkt_mnglr_ctl_connect;
684 kern_ctl.ctl_disconnect = pkt_mnglr_ctl_disconnect;
685 kern_ctl.ctl_getopt = pkt_mnglr_ctl_getopt;
686 kern_ctl.ctl_setopt = pkt_mnglr_ctl_setopt;
687 error = ctl_register(&kern_ctl, &pkt_mnglr_kctlref);
688 if (error != 0) {
689 PKT_MNGLR_LOG(LOG_ERR, "ctl_register failed: %d", error);
690 } else {
691 PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler kernel control.");
692 }
693 }
694
695 static errno_t
pktmnglr_ipfilter_output(void * cookie,mbuf_t * data,ipf_pktopts_t options)696 pktmnglr_ipfilter_output(void *cookie, mbuf_t *data, ipf_pktopts_t options)
697 {
698 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
699 struct ip ip;
700 struct tcphdr tcp;
701 int optlen = 0;
702 errno_t error = 0;
703
704 #pragma unused(tcp, optlen, options)
705 if (p_pkt_mnglr == NULL) {
706 goto output_done;
707 }
708
709 if (!p_pkt_mnglr->activate) {
710 goto output_done;
711 }
712
713 if (p_pkt_mnglr->dir == IN) {
714 goto output_done;
715 }
716
717 if (data == NULL) {
718 PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
719 goto output_done;
720 }
721
722 /* Check for IP filter options */
723 error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
724 if (error) {
725 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
726 goto output_done;
727 }
728
729 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
730 goto output_done;
731 }
732
733 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
734 goto output_done;
735 }
736
737 if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
738 struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
739 if (ip.ip_src.s_addr != laddr.sin_addr.s_addr) {
740 goto output_done;
741 }
742 }
743
744 if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
745 struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
746 if (ip.ip_dst.s_addr != raddr.sin_addr.s_addr) {
747 goto output_done;
748 }
749 }
750
751 if (ip.ip_v != 4) {
752 PKT_MNGLR_LOG(LOG_INFO,
753 "%s:%d Not handling IP version %d\n",
754 __func__, __LINE__, ip.ip_v);
755 goto output_done;
756 }
757
758 output_done:
759 /* Not handling output flow */
760 return 0;
761 }
762
763 #define TCP_MAX_OPTLEN 40
764
765 static errno_t
pktmnglr_ipfilter_input(void * cookie,mbuf_t * data,int offset,u_int8_t protocol)766 pktmnglr_ipfilter_input(void *cookie, mbuf_t *data, int offset, u_int8_t protocol)
767 {
768 struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
769 struct ip6_hdr ip6;
770 struct ip ip;
771 struct tcphdr tcp;
772 size_t ip_pld_len;
773 errno_t error = 0;
774
775 if (p_pkt_mnglr == NULL) {
776 PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr is NULL");
777 goto input_done;
778 }
779
780 if (p_pkt_mnglr->activate == 0) {
781 PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr not yet activated");
782 goto input_done;
783 }
784
785 if (p_pkt_mnglr->dir == OUT) {
786 goto input_done;
787 }
788
789 if (data == NULL) {
790 PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
791 goto input_done;
792 }
793
794 /* Check for IP filter options */
795 error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
796 if (error) {
797 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
798 goto input_done;
799 }
800
801 if (ip.ip_v == 6) {
802 error = mbuf_copydata(*data, 0, sizeof(ip6), &ip6);
803 if (error) {
804 PKT_MNGLR_LOG(LOG_ERR, "Could not make local IPv6 header copy");
805 goto input_done;
806 }
807 }
808
809 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
810 PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family of packet is IPv4 but local "
811 "address is set to IPv6");
812 goto input_done;
813 }
814
815 if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
816 PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family "
817 "of packet is IPv6 but local address is set to IPv4");
818 goto input_done;
819 }
820
821 if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
822 struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
823 if (ip.ip_dst.s_addr != laddr.sin_addr.s_addr) {
824 goto input_done;
825 }
826 } else if (p_pkt_mnglr->lsaddr.ss_family == AF_INET6) {
827 struct sockaddr_in6 laddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->lsaddr));
828 if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_dst, &laddr.sin6_addr)) {
829 goto input_done;
830 }
831 }
832
833 if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
834 struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
835 if (ip.ip_src.s_addr != raddr.sin_addr.s_addr) {
836 goto input_done;
837 }
838 PKT_MNGLR_LOG(LOG_INFO, "Remote IP: %x Source IP: %x in input path",
839 raddr.sin_addr.s_addr,
840 ip.ip_src.s_addr);
841 } else if (p_pkt_mnglr->rsaddr.ss_family == AF_INET6) {
842 struct sockaddr_in6 raddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->rsaddr));
843 if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_src, &raddr.sin6_addr)) {
844 goto input_done;
845 }
846 }
847
848 if (ip.ip_v == 4) {
849 ip_pld_len = ntohs(ip.ip_len) - (ip.ip_hl << 2);
850 } else if (ip.ip_v == 6) {
851 if (ip6.ip6_nxt != p_pkt_mnglr->proto) {
852 /* Don't support IPv6 extension headers */
853 goto input_done;
854 }
855 ip_pld_len = ntohs(ip6.ip6_plen);
856 } else {
857 goto input_done;
858 }
859
860
861 if (protocol != p_pkt_mnglr->proto) {
862 PKT_MNGLR_LOG(LOG_INFO, "Skip: Protocol mismatch");
863 goto input_done;
864 }
865
866 switch (protocol) {
867 case IPPROTO_TCP:
868 if (ip_pld_len < sizeof(tcp)) {
869 PKT_MNGLR_LOG(LOG_ERR, "IP total len not big enough for TCP: %zu", ip_pld_len);
870 goto drop_it;
871 }
872
873 error = mbuf_copydata(*data, (size_t)offset, sizeof(tcp), &tcp);
874 if (error) {
875 PKT_MNGLR_LOG(LOG_ERR, "Could not make local TCP header copy");
876 goto input_done;
877 }
878
879 if (p_pkt_mnglr->lport && (p_pkt_mnglr->lport != tcp.th_dport)) {
880 PKT_MNGLR_LOG(LOG_INFO, "Local port and IP des port do not match");
881 goto input_done;
882 }
883
884 if (p_pkt_mnglr->rport && (p_pkt_mnglr->rport != tcp.th_sport)) {
885 PKT_MNGLR_LOG(LOG_INFO, "Remote port and IP src port do not match");
886 goto input_done;
887 }
888 break;
889 case IPPROTO_UDP:
890 goto input_done;
891 case IPPROTO_ICMP:
892 goto input_done;
893 case IPPROTO_ICMPV6:
894 goto input_done;
895 default:
896 goto input_done;
897 }
898
899 /* XXX Do IP actions here */
900 PKT_MNGLR_LOG(LOG_INFO, "Proceeding with packet mangler actions on the packet");
901
902 /* Protocol actions */
903 switch (protocol) {
904 case IPPROTO_TCP:
905 if (p_pkt_mnglr->proto_action_mask) {
906 unsigned char tcp_opt_buf[TCP_MAX_OPTLEN] = {0};
907 size_t orig_tcp_optlen;
908 size_t tcp_optlen = 0;
909 size_t i = 0, off;
910
911 off = (tcp.th_off << 2);
912
913 if (off < sizeof(struct tcphdr) || off > ip_pld_len) {
914 PKT_MNGLR_LOG(LOG_ERR, "TCP header offset is wrong: %zu", off);
915 goto drop_it;
916 }
917
918 tcp_optlen = off - sizeof(struct tcphdr);
919
920 PKT_MNGLR_LOG(LOG_INFO, "Packet from F5 is TCP\n");
921 PKT_MNGLR_LOG(LOG_INFO, "Optlen: %zu\n", tcp_optlen);
922 orig_tcp_optlen = tcp_optlen;
923 if (orig_tcp_optlen) {
924 error = mbuf_copydata(*data, (size_t)offset + sizeof(struct tcphdr), orig_tcp_optlen, tcp_opt_buf);
925 if (error) {
926 PKT_MNGLR_LOG(LOG_ERR, "Failed to copy tcp options: error %d offset %d optlen %zu", error, offset, orig_tcp_optlen);
927 goto input_done;
928 }
929 }
930
931 while (tcp_optlen > 0) {
932 if (tcp_opt_buf[i] == 0x1) {
933 PKT_MNGLR_LOG(LOG_INFO, "Skipping NOP\n");
934 tcp_optlen--;
935 i++;
936 continue;
937 } else if ((tcp_opt_buf[i] != 0) && (tcp_opt_buf[i] != TCP_OPT_MULTIPATH_TCP)) {
938 unsigned char optlen;
939
940 PKT_MNGLR_LOG(LOG_INFO, "Skipping option %x\n", tcp_opt_buf[i]);
941
942 if (tcp_optlen < 2) {
943 PKT_MNGLR_LOG(LOG_ERR, "Received short TCP option");
944 goto drop_it;
945 }
946
947 /* Minimum TCP option size is 2 */
948 optlen = tcp_opt_buf[i + 1];
949 if (optlen < 2 || optlen > tcp_optlen) {
950 PKT_MNGLR_LOG(LOG_ERR, "Received suspicious TCP option");
951 goto drop_it;
952 }
953 tcp_optlen -= optlen;
954 i += optlen;
955 continue;
956 } else if (tcp_opt_buf[i] == TCP_OPT_MULTIPATH_TCP) {
957 size_t j = 0;
958 unsigned char mptcpoptlen;
959 uint8_t sbtver;
960 uint8_t subtype;
961
962 if (tcp_optlen < 3) {
963 PKT_MNGLR_LOG(LOG_ERR, "Received short MPTCP option");
964 goto drop_it;
965 }
966
967 /* Minimum MPTCP option size is 3 */
968 mptcpoptlen = tcp_opt_buf[i + 1];
969 if (mptcpoptlen < 3 || mptcpoptlen > tcp_optlen) {
970 PKT_MNGLR_LOG(LOG_ERR, "Received suspicious MPTCP option");
971 goto drop_it;
972 }
973
974 sbtver = tcp_opt_buf[i + MPTCP_SBT_VER_OFFSET];
975 subtype = sbtver >> 4;
976
977 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
978 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP subtype %x\n", subtype);
979 if (subtype == MPTCP_SUBTYPE_DSS) {
980 PKT_MNGLR_LOG(LOG_INFO, "Got DSS option\n");
981 PKT_MNGLR_LOG(LOG_INFO, "Protocol option mask: %d\n", p_pkt_mnglr->proto_action_mask);
982 if (p_pkt_mnglr->proto_action_mask &
983 PKT_MNGLR_TCP_ACT_DSS_DROP) {
984 goto drop_it;
985 }
986 }
987
988 PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
989 for (; j < mptcpoptlen && j < tcp_optlen; j++) {
990 if (p_pkt_mnglr->proto_action_mask &
991 PKT_MNGLR_TCP_ACT_NOP_MPTCP) {
992 tcp_opt_buf[i + j] = 0x1;
993 }
994 }
995 tcp_optlen -= mptcpoptlen;
996 i += mptcpoptlen;
997 } else {
998 tcp_optlen--;
999 i++;
1000 }
1001 }
1002
1003 if (orig_tcp_optlen) {
1004 error = mbuf_copyback(*data,
1005 (size_t)offset + sizeof(struct tcphdr),
1006 orig_tcp_optlen, tcp_opt_buf, MBUF_WAITOK);
1007
1008 if (error) {
1009 PKT_MNGLR_LOG(LOG_ERR,
1010 "Failed to copy tcp options back: error %d offset %d optlen %zu",
1011 error, offset, orig_tcp_optlen);
1012 goto input_done;
1013 }
1014 }
1015 }
1016 break;
1017 case IPPROTO_UDP:
1018 /* Don't handle UDP */
1019 break;
1020 case IPPROTO_ICMP:
1021 break;
1022 case IPPROTO_ICMPV6:
1023 break;
1024 default:
1025 break;
1026 }
1027 chksm_update(*data);
1028 input_done:
1029 return 0;
1030
1031 drop_it:
1032 PKT_MNGLR_LOG(LOG_INFO, "Dropping packet\n");
1033 mbuf_freem(*data);
1034 return EJUSTRETURN;
1035 }
1036
1037 static void
pktmnglr_ipfilter_detach(void * cookie)1038 pktmnglr_ipfilter_detach(void *cookie)
1039 {
1040 #pragma unused(cookie)
1041 return;
1042 }
1043
1044 /* XXX Still need to modify this to use mbuf_copy* macros */
1045 static void
chksm_update(mbuf_t data)1046 chksm_update(mbuf_t data)
1047 {
1048 u_int16_t ip_sum;
1049 u_int16_t tsum;
1050 struct tcphdr *tcp;
1051 errno_t err;
1052
1053 unsigned char *ptr = (unsigned char *)mbuf_data(data);
1054 struct ip *ip = (struct ip *)(void *)ptr;
1055 if (ip->ip_v != 4) {
1056 return;
1057 }
1058
1059 ip->ip_sum = 0;
1060 err = mbuf_inet_cksum(data, 0, 0, ip->ip_hl << 2, &ip_sum); // ip sum
1061 if (err == 0) {
1062 ip->ip_sum = ip_sum;
1063 }
1064 switch (ip->ip_p) {
1065 case IPPROTO_TCP:
1066 tcp = (struct tcphdr *)(void *)(ptr + (ip->ip_hl << 2));
1067 tcp->th_sum = 0;
1068 err = mbuf_inet_cksum(data, IPPROTO_TCP, ip->ip_hl << 2,
1069 ntohs(ip->ip_len) - (ip->ip_hl << 2), &tsum);
1070 if (err == 0) {
1071 tcp->th_sum = tsum;
1072 }
1073 break;
1074 case IPPROTO_UDP:
1075 /* Don't handle UDP */
1076 break;
1077 case IPPROTO_ICMP:
1078 break;
1079 case IPPROTO_ICMPV6:
1080 break;
1081 default:
1082 break;
1083 }
1084
1085 mbuf_clear_csum_performed(data);
1086 return;
1087 }
1088