2 * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
27 * The packet mangler subsystem provides a limited way for user space
28 * applications to apply certain actions on certain flows.
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.
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>
44 #include <kern/locks.h>
45 #include <kern/zalloc.h>
46 #include <kern/debug.h>
48 #include <net/packet_mangler.h>
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>
56 #include <libkern/libkern.h>
58 #define MAX_PACKET_MANGLER 1
60 #define PKT_MNGLR_FLG_IPFILTER_ATTACHED 0x00000001
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, "");
66 * The structure packet_mangler represents a user space packet filter
67 * It's created and associated with a kernel control socket instance
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
;
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
;
89 uint32_t proto_action_mask
;
92 /* Array of all the packet mangler instancesi */
93 struct packet_mangler
**packet_manglers
= NULL
;
95 uint32_t pkt_mnglr_active_count
= 0; /* Number of active packet filters */
96 uint32_t pkt_mnglr_close_wait_timeout
= 1000; /* in milliseconds */
98 static kern_ctl_ref pkt_mnglr_kctlref
= NULL
;
100 static lck_grp_attr_t
*pkt_mnglr_lck_grp_attr
= NULL
;
101 static lck_attr_t
*pkt_mnglr_lck_attr
= NULL
;
102 static lck_grp_t
*pkt_mnglr_lck_grp
= NULL
;
104 /* The lock below protects packet_manglers DS, packet_mangler DS */
105 decl_lck_rw_data(static, pkt_mnglr_lck_rw
);
107 #define PKT_MNGLR_RW_LCK_MAX 8
109 int pkt_mnglr_rw_nxt_lck
= 0;
110 void* pkt_mnglr_rw_lock_history
[PKT_MNGLR_RW_LCK_MAX
];
112 int pkt_mnglr_rw_nxt_unlck
= 0;
113 void* pkt_mnglr_rw_unlock_history
[PKT_MNGLR_RW_LCK_MAX
];
115 static ZONE_DECLARE(packet_mangler_zone
, "packet_mangler",
116 sizeof(struct packet_mangler
), ZC_NONE
);
119 * For troubleshooting
121 int pkt_mnglr_log_level
= LOG_ERR
;
122 int pkt_mnglr_debug
= 1;
125 * Forward declaration to appease the compiler
127 static void pkt_mnglr_rw_lock_exclusive(lck_rw_t
*);
128 static void pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*);
129 static void pkt_mnglr_rw_lock_shared(lck_rw_t
*);
130 static void pkt_mnglr_rw_unlock_shared(lck_rw_t
*);
132 static errno_t
pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
,
133 ipf_pktopts_t options
);
134 static errno_t
pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
,
135 int offset
, u_int8_t protocol
);
136 static void pktmnglr_ipfilter_detach(void *cookie
);
138 static void chksm_update(mbuf_t data
);
140 #define TCP_OPT_MULTIPATH_TCP 30
141 #define MPTCP_SBT_VER_OFFSET 2
143 #define MPTCP_SUBTYPE_MPCAPABLE 0x0
144 #define MPTCP_SUBTYPE_MPJOIN 0x1
145 #define MPTCP_SUBTYPE_DSS 0x2
146 #define MPTCP_SUBTYPE_ADD_ADDR 0x3
147 #define MPTCP_SUBTYPE_REM_ADDR 0x4
148 #define MPTCP_SUBTYPE_MP_PRIO 0x5
149 #define MPTCP_SUBTYPE_MP_FAIL 0x6
150 #define MPTCP_SUBTYPE_MP_FASTCLOSE 0x7
153 * packet filter global read write lock
157 pkt_mnglr_rw_lock_exclusive(lck_rw_t
*lck
)
161 lr_saved
= __builtin_return_address(0);
163 lck_rw_lock_exclusive(lck
);
165 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
166 pkt_mnglr_rw_nxt_lck
=
167 (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
171 pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*lck
)
175 lr_saved
= __builtin_return_address(0);
177 lck_rw_unlock_exclusive(lck
);
179 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] =
181 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
185 pkt_mnglr_rw_lock_shared(lck_rw_t
*lck
)
189 lr_saved
= __builtin_return_address(0);
191 lck_rw_lock_shared(lck
);
193 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
194 pkt_mnglr_rw_nxt_lck
= (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
198 pkt_mnglr_rw_unlock_shared(lck_rw_t
*lck
)
202 lr_saved
= __builtin_return_address(0);
204 lck_rw_unlock_shared(lck
);
206 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] = lr_saved
;
207 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
211 * Packet Mangler's Kernel control socket callbacks
214 pkt_mnglr_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
218 struct packet_mangler
*p_pkt_mnglr
= NULL
;
220 PKT_MNGLR_LOG(LOG_NOTICE
, "Connecting packet mangler filter.");
222 p_pkt_mnglr
= zalloc(packet_mangler_zone
);
223 if (p_pkt_mnglr
== NULL
) {
224 PKT_MNGLR_LOG(LOG_ERR
, "zalloc failed");
229 bzero(p_pkt_mnglr
, sizeof(struct packet_mangler
));
231 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
232 if (packet_manglers
== NULL
) {
233 struct packet_mangler
**tmp
;
235 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
238 struct packet_mangler
**,
239 MAX_PACKET_MANGLER
* sizeof(struct packet_mangler
*),
243 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
245 if (tmp
== NULL
&& packet_manglers
== NULL
) {
247 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
250 /* Another thread may have won the race */
251 if (packet_manglers
!= NULL
) {
254 packet_manglers
= tmp
;
258 if (sac
->sc_unit
== 0 || sac
->sc_unit
> MAX_PACKET_MANGLER
) {
259 PKT_MNGLR_LOG(LOG_ERR
, "bad sc_unit %u", sac
->sc_unit
);
261 } else if (packet_manglers
[sac
->sc_unit
- 1] != NULL
) {
262 PKT_MNGLR_LOG(LOG_ERR
, "sc_unit %u in use", sac
->sc_unit
);
266 * kernel control socket kcunit numbers start at 1
268 packet_manglers
[sac
->sc_unit
- 1] = p_pkt_mnglr
;
270 p_pkt_mnglr
->pkt_mnglr_kcref
= kctlref
;
271 p_pkt_mnglr
->pkt_mnglr_kcunit
= sac
->sc_unit
;
273 *unitinfo
= p_pkt_mnglr
;
274 pkt_mnglr_active_count
++;
277 p_pkt_mnglr
->pkt_mnglr_ipfilter
.cookie
= p_pkt_mnglr
;
278 p_pkt_mnglr
->pkt_mnglr_ipfilter
.name
= "com.apple.pktmnglripfilter";
279 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_input
= pktmnglr_ipfilter_input
;
280 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_output
= pktmnglr_ipfilter_output
;
281 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_detach
= pktmnglr_ipfilter_detach
;
282 error
= ipf_addv4(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfref
));
284 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv4 Filter");
287 error
= ipf_addv6(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
));
289 ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
290 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv6 Filter");
294 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler's IP Filters");
295 p_pkt_mnglr
->pkt_mnglr_flags
|= PKT_MNGLR_FLG_IPFILTER_ATTACHED
;
296 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
299 if (error
!= 0 && p_pkt_mnglr
!= NULL
) {
300 zfree(packet_mangler_zone
, p_pkt_mnglr
);
303 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
304 error
, pkt_mnglr_active_count
, sac
->sc_unit
);
310 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
)
312 #pragma unused(kctlref)
314 struct packet_mangler
*p_pkt_mnglr
;
316 PKT_MNGLR_LOG(LOG_INFO
, "Disconnecting packet mangler kernel control");
318 if (packet_manglers
== NULL
) {
319 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
323 if (kcunit
> MAX_PACKET_MANGLER
) {
324 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
325 kcunit
, MAX_PACKET_MANGLER
);
330 p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
331 if (p_pkt_mnglr
== NULL
) {
332 PKT_MNGLR_LOG(LOG_ERR
, "Unit info is NULL");
336 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
337 if (packet_manglers
[kcunit
- 1] != p_pkt_mnglr
|| p_pkt_mnglr
->pkt_mnglr_kcunit
!= kcunit
) {
338 PKT_MNGLR_LOG(LOG_ERR
, "bad unit info %u)",
340 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
345 * Make filter inactive
347 packet_manglers
[kcunit
- 1] = NULL
;
348 pkt_mnglr_active_count
--;
349 if (p_pkt_mnglr
->pkt_mnglr_flags
& PKT_MNGLR_FLG_IPFILTER_ATTACHED
) {
350 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
351 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
);
353 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
354 zfree(packet_mangler_zone
, p_pkt_mnglr
);
356 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
357 error
, pkt_mnglr_active_count
, kcunit
);
363 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
364 int opt
, void *data
, size_t *len
)
366 #pragma unused(kctlref, opt)
368 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
370 PKT_MNGLR_LOG(LOG_NOTICE
, "");
372 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw
);
374 if (packet_manglers
== NULL
) {
375 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
379 if (kcunit
> MAX_PACKET_MANGLER
) {
380 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
381 kcunit
, MAX_PACKET_MANGLER
);
385 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
386 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
392 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
393 if (*len
< sizeof(uint32_t)) {
394 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
395 "len too small %lu", *len
);
401 *(uint32_t *)data
= p_pkt_mnglr
->proto_action_mask
;
404 case PKT_MNGLR_OPT_IP_ACT_MASK
:
405 if (*len
< sizeof(uint32_t)) {
406 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
407 "len too small %lu", *len
);
413 *(uint32_t *)data
= p_pkt_mnglr
->ip_action_mask
;
416 case PKT_MNGLR_OPT_LOCAL_IP
:
417 if (*len
< sizeof(struct sockaddr_storage
)) {
418 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
419 "len too small %lu", *len
);
425 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->lsaddr
;
428 case PKT_MNGLR_OPT_REMOTE_IP
:
429 if (*len
< sizeof(struct sockaddr_storage
)) {
430 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
431 "len too small %lu", *len
);
437 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->rsaddr
;
440 case PKT_MNGLR_OPT_LOCAL_PORT
:
441 if (*len
< sizeof(uint16_t)) {
442 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
443 "len too small %lu", *len
);
449 *(uint16_t *)data
= p_pkt_mnglr
->lport
;
452 case PKT_MNGLR_OPT_REMOTE_PORT
:
453 if (*len
< sizeof(uint16_t)) {
454 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
455 "len too small %lu", *len
);
461 *(uint16_t *)data
= p_pkt_mnglr
->rport
;
464 case PKT_MNGLR_OPT_DIRECTION
:
465 if (*len
< sizeof(uint32_t)) {
466 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
467 "len too small %lu", *len
);
472 *(uint32_t *)data
= p_pkt_mnglr
->dir
;
475 case PKT_MNGLR_OPT_PROTOCOL
:
476 if (*len
< sizeof(uint32_t)) {
477 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
478 "len too small %lu", *len
);
483 *(uint32_t *)data
= p_pkt_mnglr
->proto
;
486 case PKT_MNGLR_OPT_ACTIVATE
:
487 if (*len
< sizeof(uint8_t)) {
488 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
489 "len too small %lu", *len
);
495 *(uint8_t *)data
= p_pkt_mnglr
->activate
;
503 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw
);
509 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
510 int opt
, void *data
, size_t len
)
512 #pragma unused(kctlref, opt)
514 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
516 PKT_MNGLR_LOG(LOG_NOTICE
, "");
518 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
520 if (packet_manglers
== NULL
) {
521 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
525 if (kcunit
> MAX_PACKET_MANGLER
) {
526 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
527 kcunit
, MAX_PACKET_MANGLER
);
531 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
532 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
538 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
539 if (len
< sizeof(uint32_t)) {
540 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
541 "len too small %lu", len
);
545 if (p_pkt_mnglr
->proto_action_mask
!= 0) {
546 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
548 p_pkt_mnglr
->proto_action_mask
);
552 p_pkt_mnglr
->proto_action_mask
= *(uint32_t *)data
;
553 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr
->proto_action_mask
);
555 case PKT_MNGLR_OPT_IP_ACT_MASK
:
556 if (len
< sizeof(uint32_t)) {
557 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
558 "len too small %lu", len
);
562 if (p_pkt_mnglr
->ip_action_mask
!= 0) {
563 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
565 p_pkt_mnglr
->ip_action_mask
);
569 p_pkt_mnglr
->ip_action_mask
= *(uint32_t *)data
;
571 case PKT_MNGLR_OPT_LOCAL_IP
:
572 if (len
< sizeof(struct sockaddr_storage
)) {
573 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
574 "len too small %lu", len
);
578 if (p_pkt_mnglr
->lsaddr
.ss_family
) {
579 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
584 p_pkt_mnglr
->lsaddr
= *(struct sockaddr_storage
*)data
;
586 case PKT_MNGLR_OPT_REMOTE_IP
:
587 if (len
< sizeof(struct sockaddr_storage
)) {
588 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
589 "len too small %lu", len
);
593 if (p_pkt_mnglr
->rsaddr
.ss_family
) {
594 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
600 p_pkt_mnglr
->rsaddr
= *(struct sockaddr_storage
*)data
;
601 PKT_MNGLR_LOG(LOG_INFO
,
602 "Remote IP registered for address family: %d",
603 p_pkt_mnglr
->rsaddr
.ss_family
);
605 case PKT_MNGLR_OPT_LOCAL_PORT
:
606 if (len
< sizeof(uint16_t)) {
607 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
608 "len too small %lu", len
);
612 if (p_pkt_mnglr
->lport
!= 0) {
613 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
619 p_pkt_mnglr
->lport
= *(uint16_t *)data
;
621 case PKT_MNGLR_OPT_REMOTE_PORT
:
622 if (len
< sizeof(uint16_t)) {
623 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
624 "len too small %lu", len
);
628 if (p_pkt_mnglr
->rport
!= 0) {
629 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
635 p_pkt_mnglr
->rport
= *(uint16_t *)data
;
637 case PKT_MNGLR_OPT_DIRECTION
:
638 if (len
< sizeof(uint32_t)) {
639 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
640 "len too small %lu", len
);
644 if (p_pkt_mnglr
->dir
!= 0) {
645 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
651 p_pkt_mnglr
->dir
= *(uint32_t *)data
;
653 case PKT_MNGLR_OPT_PROTOCOL
:
654 if (len
< sizeof(uint32_t)) {
655 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
656 "len too small %lu", len
);
660 if (p_pkt_mnglr
->proto
!= 0) {
661 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
667 p_pkt_mnglr
->proto
= *(uint32_t *)data
;
669 case PKT_MNGLR_OPT_ACTIVATE
:
670 if (len
< sizeof(uint8_t)) {
671 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
672 "len too small %lu", len
);
676 if (p_pkt_mnglr
->activate
!= 0) {
677 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
679 p_pkt_mnglr
->activate
);
683 p_pkt_mnglr
->activate
= *(uint8_t *)data
;
684 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr->activate set to :%d",
685 p_pkt_mnglr
->activate
);
692 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
700 struct kern_ctl_reg kern_ctl
;
703 PKT_MNGLR_LOG(LOG_NOTICE
, "");
706 * Compile time verifications
708 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT
== MAX_PACKET_MANGLER
);
713 pkt_mnglr_lck_grp_attr
= lck_grp_attr_alloc_init();
714 if (pkt_mnglr_lck_grp_attr
== NULL
) {
715 panic("%s: lck_grp_attr_alloc_init failed", __func__
);
718 pkt_mnglr_lck_grp
= lck_grp_alloc_init("packet manglerr",
719 pkt_mnglr_lck_grp_attr
);
720 if (pkt_mnglr_lck_grp
== NULL
) {
721 panic("%s: lck_grp_alloc_init failed", __func__
);
724 pkt_mnglr_lck_attr
= lck_attr_alloc_init();
725 if (pkt_mnglr_lck_attr
== NULL
) {
726 panic("%s: lck_attr_alloc_init failed", __func__
);
729 lck_rw_init(&pkt_mnglr_lck_rw
, pkt_mnglr_lck_grp
, pkt_mnglr_lck_attr
);
732 * Register kernel control
734 bzero(&kern_ctl
, sizeof(kern_ctl
));
735 strlcpy(kern_ctl
.ctl_name
, PACKET_MANGLER_CONTROL_NAME
,
736 sizeof(kern_ctl
.ctl_name
));
737 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
;
738 kern_ctl
.ctl_connect
= pkt_mnglr_ctl_connect
;
739 kern_ctl
.ctl_disconnect
= pkt_mnglr_ctl_disconnect
;
740 kern_ctl
.ctl_getopt
= pkt_mnglr_ctl_getopt
;
741 kern_ctl
.ctl_setopt
= pkt_mnglr_ctl_setopt
;
742 error
= ctl_register(&kern_ctl
, &pkt_mnglr_kctlref
);
744 PKT_MNGLR_LOG(LOG_ERR
, "ctl_register failed: %d", error
);
746 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler kernel control.");
751 pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
, ipf_pktopts_t options
)
753 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
759 #pragma unused(tcp, optlen, options)
760 if (p_pkt_mnglr
== NULL
) {
764 if (!p_pkt_mnglr
->activate
) {
768 if (p_pkt_mnglr
->dir
== IN
) {
773 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
777 /* Check for IP filter options */
778 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
780 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
784 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
788 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
792 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
793 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
794 if (ip
.ip_src
.s_addr
!= laddr
.sin_addr
.s_addr
) {
799 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
800 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
801 if (ip
.ip_dst
.s_addr
!= raddr
.sin_addr
.s_addr
) {
807 PKT_MNGLR_LOG(LOG_INFO
,
808 "%s:%d Not handling IP version %d\n",
809 __func__
, __LINE__
, ip
.ip_v
);
814 /* Not handling output flow */
818 #define TCP_MAX_OPTLEN 40
821 pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
, int offset
, u_int8_t protocol
)
823 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
830 if (p_pkt_mnglr
== NULL
) {
831 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr is NULL");
835 if (p_pkt_mnglr
->activate
== 0) {
836 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr not yet activated");
840 if (p_pkt_mnglr
->dir
== OUT
) {
845 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
849 /* Check for IP filter options */
850 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
852 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
857 error
= mbuf_copydata(*data
, 0, sizeof(ip6
), &ip6
);
859 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IPv6 header copy");
864 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
865 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family of packet is IPv4 but local "
866 "address is set to IPv6");
870 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
871 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family "
872 "of packet is IPv6 but local address is set to IPv4");
876 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
877 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
878 if (ip
.ip_dst
.s_addr
!= laddr
.sin_addr
.s_addr
) {
881 } else if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) {
882 struct sockaddr_in6 laddr
= *(struct sockaddr_in6
*)(&(p_pkt_mnglr
->lsaddr
));
883 if (!IN6_ARE_ADDR_EQUAL(&ip6
.ip6_dst
, &laddr
.sin6_addr
)) {
888 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
889 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
890 if (ip
.ip_src
.s_addr
!= raddr
.sin_addr
.s_addr
) {
893 PKT_MNGLR_LOG(LOG_INFO
, "Remote IP: %x Source IP: %x in input path",
894 raddr
.sin_addr
.s_addr
,
896 } else if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET6
) {
897 struct sockaddr_in6 raddr
= *(struct sockaddr_in6
*)(&(p_pkt_mnglr
->rsaddr
));
898 if (!IN6_ARE_ADDR_EQUAL(&ip6
.ip6_src
, &raddr
.sin6_addr
)) {
904 ip_pld_len
= ntohs(ip
.ip_len
) - (ip
.ip_hl
<< 2);
905 } else if (ip
.ip_v
== 6) {
906 if (ip6
.ip6_nxt
!= p_pkt_mnglr
->proto
) {
907 /* Don't support IPv6 extension headers */
910 ip_pld_len
= ntohs(ip6
.ip6_plen
) + sizeof(struct ip6_hdr
);
916 if (protocol
!= p_pkt_mnglr
->proto
) {
917 PKT_MNGLR_LOG(LOG_INFO
, "Skip: Protocol mismatch");
923 if (ip_pld_len
< (int) sizeof(tcp
)) {
924 PKT_MNGLR_LOG(LOG_ERR
, "IP total len not big enough for TCP: %d", ip_pld_len
);
928 error
= mbuf_copydata(*data
, offset
, sizeof(tcp
), &tcp
);
930 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local TCP header copy");
934 if (p_pkt_mnglr
->lport
&& (p_pkt_mnglr
->lport
!= tcp
.th_dport
)) {
935 PKT_MNGLR_LOG(LOG_INFO
, "Local port and IP des port do not match");
939 if (p_pkt_mnglr
->rport
&& (p_pkt_mnglr
->rport
!= tcp
.th_sport
)) {
940 PKT_MNGLR_LOG(LOG_INFO
, "Remote port and IP src port do not match");
954 /* XXX Do IP actions here */
955 PKT_MNGLR_LOG(LOG_INFO
, "Proceeding with packet mangler actions on the packet");
957 /* Protocol actions */
960 if (p_pkt_mnglr
->proto_action_mask
) {
961 char tcp_opt_buf
[TCP_MAX_OPTLEN
] = {0};
966 off
= (tcp
.th_off
<< 2);
968 if (off
< (int) sizeof(struct tcphdr
) || off
> ip_pld_len
) {
969 PKT_MNGLR_LOG(LOG_ERR
, "TCP header offset is wrong: %d", off
);
974 tcp_optlen
= off
- sizeof(struct tcphdr
);
976 PKT_MNGLR_LOG(LOG_INFO
, "Packet from F5 is TCP\n");
977 PKT_MNGLR_LOG(LOG_INFO
, "Optlen: %d\n", tcp_optlen
);
978 orig_tcp_optlen
= tcp_optlen
;
979 if (orig_tcp_optlen
) {
980 error
= mbuf_copydata(*data
, offset
+ sizeof(struct tcphdr
), orig_tcp_optlen
, tcp_opt_buf
);
982 PKT_MNGLR_LOG(LOG_ERR
, "Failed to copy tcp options: error %d offset %d optlen %d", error
, offset
, orig_tcp_optlen
);
987 while (tcp_optlen
> 0) {
988 if (tcp_opt_buf
[i
] == 0x1) {
989 PKT_MNGLR_LOG(LOG_INFO
, "Skipping NOP\n");
993 } else if ((tcp_opt_buf
[i
] != 0) && (tcp_opt_buf
[i
] != TCP_OPT_MULTIPATH_TCP
)) {
994 PKT_MNGLR_LOG(LOG_INFO
, "Skipping option %x\n", tcp_opt_buf
[i
]);
996 /* Minimum TCP option size is 2 */
997 if (tcp_opt_buf
[i
+ 1] < 2) {
998 PKT_MNGLR_LOG(LOG_ERR
, "Received suspicious TCP option");
1001 tcp_optlen
-= tcp_opt_buf
[i
+ 1];
1002 i
+= tcp_opt_buf
[i
+ 1];
1004 } else if (tcp_opt_buf
[i
] == TCP_OPT_MULTIPATH_TCP
) {
1006 unsigned char mptcpoptlen
= tcp_opt_buf
[i
+ 1];
1007 uint8_t sbtver
= tcp_opt_buf
[i
+ MPTCP_SBT_VER_OFFSET
];
1008 uint8_t subtype
= sbtver
>> 4;
1010 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
1011 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP subtype %x\n", subtype
);
1012 if (subtype
== MPTCP_SUBTYPE_DSS
) {
1013 PKT_MNGLR_LOG(LOG_INFO
, "Got DSS option\n");
1014 PKT_MNGLR_LOG(LOG_INFO
, "Protocol option mask: %d\n", p_pkt_mnglr
->proto_action_mask
);
1015 if (p_pkt_mnglr
->proto_action_mask
&
1016 PKT_MNGLR_TCP_ACT_DSS_DROP
) {
1021 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
1022 for (; j
< mptcpoptlen
&& j
< tcp_optlen
; j
++) {
1023 if (p_pkt_mnglr
->proto_action_mask
&
1024 PKT_MNGLR_TCP_ACT_NOP_MPTCP
) {
1025 tcp_opt_buf
[i
+ j
] = 0x1;
1028 tcp_optlen
-= mptcpoptlen
;
1036 if (orig_tcp_optlen
) {
1037 error
= mbuf_copyback(*data
,
1038 offset
+ sizeof(struct tcphdr
),
1039 orig_tcp_optlen
, tcp_opt_buf
, MBUF_WAITOK
);
1042 PKT_MNGLR_LOG(LOG_ERR
,
1043 "Failed to copy tcp options back: error %d offset %d optlen %d",
1044 error
, offset
, orig_tcp_optlen
);
1051 /* Don't handle UDP */
1055 case IPPROTO_ICMPV6
:
1060 chksm_update(*data
);
1065 PKT_MNGLR_LOG(LOG_INFO
, "Dropping packet\n");
1071 pktmnglr_ipfilter_detach(void *cookie
)
1073 #pragma unused(cookie)
1077 /* XXX Still need to modify this to use mbuf_copy* macros */
1079 chksm_update(mbuf_t data
)
1086 unsigned char *ptr
= (unsigned char *)mbuf_data(data
);
1087 struct ip
*ip
= (struct ip
*)(void *)ptr
;
1088 if (ip
->ip_v
!= 4) {
1093 err
= mbuf_inet_cksum(data
, 0, 0, ip
->ip_hl
<< 2, &ip_sum
); // ip sum
1095 ip
->ip_sum
= ip_sum
;
1099 tcp
= (struct tcphdr
*)(void *)(ptr
+ (ip
->ip_hl
<< 2));
1101 err
= mbuf_inet_cksum(data
, IPPROTO_TCP
, ip
->ip_hl
<< 2,
1102 ntohs(ip
->ip_len
) - (ip
->ip_hl
<< 2), &tsum
);
1108 /* Don't handle UDP */
1112 case IPPROTO_ICMPV6
:
1118 mbuf_clear_csum_performed(data
);