2 * Copyright (c) 2015-2016 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/kpi_ipfilter.h>
55 #include <libkern/libkern.h>
57 #define MAX_PACKET_MANGLER 1
59 #define PKT_MNGLR_FLG_IPFILTER_ATTACHED 0x00000001
61 SYSCTL_NODE(_net
, OID_AUTO
, pktmnglr
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "pktmnglr");
62 SYSCTL_INT(_net_pktmnglr
, OID_AUTO
, log
, CTLFLAG_RW
|CTLFLAG_LOCKED
,
63 &pkt_mnglr_log_level
, 0, "");
65 * The structure packet_mangler represents a user space packet filter
66 * It's created and associated with a kernel control socket instance
68 struct packet_mangler
{
69 kern_ctl_ref pkt_mnglr_kcref
;
70 uint32_t pkt_mnglr_kcunit
;
71 uint32_t pkt_mnglr_flags
;
72 /* IP filter related params */
73 ipfilter_t pkt_mnglr_ipfref
;
74 ipfilter_t pkt_mnglr_ipfrefv6
;
75 struct ipf_filter pkt_mnglr_ipfilter
;
80 struct sockaddr_storage lsaddr
;
81 struct sockaddr_storage rsaddr
;
82 struct sockaddr_storage swap_lsaddr
;
83 struct sockaddr_storage swap_rsaddr
;
84 uint32_t ip_action_mask
;
88 uint32_t proto_action_mask
;
91 /* Array of all the packet mangler instancesi */
92 struct packet_mangler
**packet_manglers
= NULL
;
94 uint32_t pkt_mnglr_active_count
= 0; /* Number of active packet filters */
95 uint32_t pkt_mnglr_close_wait_timeout
= 1000; /* in milliseconds */
97 static kern_ctl_ref pkt_mnglr_kctlref
= NULL
;
99 static lck_grp_attr_t
*pkt_mnglr_lck_grp_attr
= NULL
;
100 static lck_attr_t
*pkt_mnglr_lck_attr
= NULL
;
101 static lck_grp_t
*pkt_mnglr_lck_grp
= NULL
;
103 /* The lock below protects packet_manglers DS, packet_mangler DS */
104 decl_lck_rw_data(static, pkt_mnglr_lck_rw
);
106 #define PKT_MNGLR_RW_LCK_MAX 8
108 int pkt_mnglr_rw_nxt_lck
= 0;
109 void* pkt_mnglr_rw_lock_history
[PKT_MNGLR_RW_LCK_MAX
];
111 int pkt_mnglr_rw_nxt_unlck
= 0;
112 void* pkt_mnglr_rw_unlock_history
[PKT_MNGLR_RW_LCK_MAX
];
115 #define PACKET_MANGLER_ZONE_NAME "packet_mangler"
116 #define PACKET_MANGLER_ZONE_MAX 10
117 static struct zone
*packet_mangler_zone
= NULL
; /* zone for packet_mangler */
120 * For troubleshooting
122 int pkt_mnglr_log_level
= LOG_ERR
;
123 int pkt_mnglr_debug
= 1;
126 * Forward declaration to appease the compiler
128 static void pkt_mnglr_rw_lock_exclusive(lck_rw_t
*);
129 static void pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*);
130 static void pkt_mnglr_rw_lock_shared(lck_rw_t
*);
131 static void pkt_mnglr_rw_unlock_shared(lck_rw_t
*);
133 static errno_t
pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
,
134 ipf_pktopts_t options
);
135 static errno_t
pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
,
136 int offset
, u_int8_t protocol
);
137 static void pktmnglr_ipfilter_detach(void *cookie
);
139 static void chksm_update(mbuf_t data
);
141 #define TCP_OPT_MULTIPATH_TCP 30
142 #define MPTCP_SBT_VER_OFFSET 2
144 #define MPTCP_SUBTYPE_MPCAPABLE 0x0
145 #define MPTCP_SUBTYPE_MPJOIN 0x1
146 #define MPTCP_SUBTYPE_DSS 0x2
147 #define MPTCP_SUBTYPE_ADD_ADDR 0x3
148 #define MPTCP_SUBTYPE_REM_ADDR 0x4
149 #define MPTCP_SUBTYPE_MP_PRIO 0x5
150 #define MPTCP_SUBTYPE_MP_FAIL 0x6
151 #define MPTCP_SUBTYPE_MP_FASTCLOSE 0x7
154 * packet filter global read write lock
158 pkt_mnglr_rw_lock_exclusive(lck_rw_t
*lck
)
162 lr_saved
= __builtin_return_address(0);
164 lck_rw_lock_exclusive(lck
);
166 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
167 pkt_mnglr_rw_nxt_lck
=
168 (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
172 pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*lck
)
176 lr_saved
= __builtin_return_address(0);
178 lck_rw_unlock_exclusive(lck
);
180 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] =
182 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
186 pkt_mnglr_rw_lock_shared(lck_rw_t
*lck
)
190 lr_saved
= __builtin_return_address(0);
192 lck_rw_lock_shared(lck
);
194 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
195 pkt_mnglr_rw_nxt_lck
= (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
199 pkt_mnglr_rw_unlock_shared(lck_rw_t
*lck
)
203 lr_saved
= __builtin_return_address(0);
205 lck_rw_unlock_shared(lck
);
207 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] = lr_saved
;
208 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
212 * Packet Mangler's Kernel control socket callbacks
215 pkt_mnglr_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
219 struct packet_mangler
*p_pkt_mnglr
= NULL
;
221 PKT_MNGLR_LOG(LOG_NOTICE
, "Connecting packet mangler filter.");
223 p_pkt_mnglr
= zalloc(packet_mangler_zone
);
224 if (p_pkt_mnglr
== NULL
) {
225 PKT_MNGLR_LOG(LOG_ERR
, "zalloc failed");
230 bzero(p_pkt_mnglr
, sizeof(struct packet_mangler
));
232 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
233 if (packet_manglers
== NULL
) {
234 struct packet_mangler
**tmp
;
236 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
239 struct packet_mangler
**,
240 MAX_PACKET_MANGLER
* sizeof(struct packet_mangler
*),
244 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
246 if (tmp
== NULL
&& packet_manglers
== NULL
) {
248 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
251 /* Another thread may have won the race */
252 if (packet_manglers
!= NULL
)
255 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
);
302 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
303 error
, pkt_mnglr_active_count
, sac
->sc_unit
);
309 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
)
311 #pragma unused(kctlref)
313 struct packet_mangler
*p_pkt_mnglr
;
315 PKT_MNGLR_LOG(LOG_INFO
, "Disconnecting packet mangler kernel control");
317 if (packet_manglers
== NULL
) {
318 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
322 if (kcunit
> MAX_PACKET_MANGLER
) {
323 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
324 kcunit
, MAX_PACKET_MANGLER
);
329 p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
330 if (p_pkt_mnglr
== NULL
) {
331 PKT_MNGLR_LOG(LOG_ERR
, "Unit info is NULL");
335 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
336 if (packet_manglers
[kcunit
- 1] != p_pkt_mnglr
|| p_pkt_mnglr
->pkt_mnglr_kcunit
!= kcunit
) {
337 PKT_MNGLR_LOG(LOG_ERR
, "bad unit info %u)",
339 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
344 * Make filter inactive
346 packet_manglers
[kcunit
- 1] = NULL
;
347 pkt_mnglr_active_count
--;
348 if (p_pkt_mnglr
->pkt_mnglr_flags
& PKT_MNGLR_FLG_IPFILTER_ATTACHED
) {
349 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
350 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
);
352 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
353 zfree(packet_mangler_zone
, p_pkt_mnglr
);
355 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
356 error
, pkt_mnglr_active_count
, kcunit
);
362 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
363 int opt
, void *data
, size_t *len
)
365 #pragma unused(kctlref, opt)
367 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
369 PKT_MNGLR_LOG(LOG_NOTICE
, "");
371 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw
);
373 if (packet_manglers
== NULL
) {
374 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
378 if (kcunit
> MAX_PACKET_MANGLER
) {
379 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
380 kcunit
, MAX_PACKET_MANGLER
);
384 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
385 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
391 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
392 if (*len
< sizeof(uint32_t)) {
393 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
394 "len too small %lu", *len
);
400 *(uint32_t *)data
= p_pkt_mnglr
->proto_action_mask
;
403 case PKT_MNGLR_OPT_IP_ACT_MASK
:
404 if (*len
< sizeof(uint32_t)) {
405 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
406 "len too small %lu", *len
);
412 *(uint32_t *)data
= p_pkt_mnglr
->ip_action_mask
;
415 case PKT_MNGLR_OPT_LOCAL_IP
:
416 if (*len
< sizeof(struct sockaddr_storage
)) {
417 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
418 "len too small %lu", *len
);
424 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->lsaddr
;
427 case PKT_MNGLR_OPT_REMOTE_IP
:
428 if (*len
< sizeof(struct sockaddr_storage
)) {
429 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
430 "len too small %lu", *len
);
436 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->rsaddr
;
439 case PKT_MNGLR_OPT_LOCAL_PORT
:
440 if (*len
< sizeof(uint16_t)) {
441 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
442 "len too small %lu", *len
);
448 *(uint16_t *)data
= p_pkt_mnglr
->lport
;
451 case PKT_MNGLR_OPT_REMOTE_PORT
:
452 if (*len
< sizeof(uint16_t)) {
453 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
454 "len too small %lu", *len
);
460 *(uint16_t *)data
= p_pkt_mnglr
->rport
;
463 case PKT_MNGLR_OPT_DIRECTION
:
464 if (*len
< sizeof(uint32_t)) {
465 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
466 "len too small %lu", *len
);
471 *(uint32_t *)data
= p_pkt_mnglr
->dir
;
474 case PKT_MNGLR_OPT_PROTOCOL
:
475 if (*len
< sizeof(uint32_t)) {
476 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
477 "len too small %lu", *len
);
482 *(uint32_t *)data
= p_pkt_mnglr
->proto
;
485 case PKT_MNGLR_OPT_ACTIVATE
:
486 if (*len
< sizeof(uint8_t)) {
487 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
488 "len too small %lu", *len
);
494 *(uint8_t *)data
= p_pkt_mnglr
->activate
;
502 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw
);
508 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
509 int opt
, void *data
, size_t len
)
511 #pragma unused(kctlref, opt)
513 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
515 PKT_MNGLR_LOG(LOG_NOTICE
, "");
517 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
519 if (packet_manglers
== NULL
) {
520 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
524 if (kcunit
> MAX_PACKET_MANGLER
) {
525 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
526 kcunit
, MAX_PACKET_MANGLER
);
530 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
531 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
537 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
538 if (len
< sizeof(uint32_t)) {
539 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
540 "len too small %lu", len
);
544 if (p_pkt_mnglr
->proto_action_mask
!= 0) {
545 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
547 p_pkt_mnglr
->proto_action_mask
);
551 p_pkt_mnglr
->proto_action_mask
= *(uint32_t *)data
;
552 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr
->proto_action_mask
);
554 case PKT_MNGLR_OPT_IP_ACT_MASK
:
555 if (len
< sizeof(uint32_t)) {
556 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
557 "len too small %lu", len
);
561 if (p_pkt_mnglr
->ip_action_mask
!= 0) {
562 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
564 p_pkt_mnglr
->ip_action_mask
);
568 p_pkt_mnglr
->ip_action_mask
= *(uint32_t *)data
;
570 case PKT_MNGLR_OPT_LOCAL_IP
:
571 if (len
< sizeof(struct sockaddr_storage
)) {
572 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
573 "len too small %lu", len
);
577 if (p_pkt_mnglr
->lsaddr
.ss_family
) {
578 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
583 p_pkt_mnglr
->lsaddr
= *(struct sockaddr_storage
*)data
;
585 case PKT_MNGLR_OPT_REMOTE_IP
:
586 if (len
< sizeof(struct sockaddr_storage
)) {
587 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
588 "len too small %lu", len
);
592 if (p_pkt_mnglr
->rsaddr
.ss_family
) {
593 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
599 p_pkt_mnglr
->rsaddr
= *(struct sockaddr_storage
*)data
;
600 PKT_MNGLR_LOG(LOG_INFO
,
601 "Remote IP registered for address family: %d",
602 p_pkt_mnglr
->rsaddr
.ss_family
);
604 case PKT_MNGLR_OPT_LOCAL_PORT
:
605 if (len
< sizeof(uint16_t)) {
606 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
607 "len too small %lu", len
);
611 if (p_pkt_mnglr
->lport
!= 0) {
612 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
618 p_pkt_mnglr
->lport
= *(uint16_t *)data
;
620 case PKT_MNGLR_OPT_REMOTE_PORT
:
621 if (len
< sizeof(uint16_t)) {
622 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
623 "len too small %lu", len
);
627 if (p_pkt_mnglr
->rport
!= 0) {
628 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
634 p_pkt_mnglr
->rport
= *(uint16_t *)data
;
636 case PKT_MNGLR_OPT_DIRECTION
:
637 if (len
< sizeof(uint32_t)) {
638 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
639 "len too small %lu", len
);
643 if (p_pkt_mnglr
->dir
!= 0) {
644 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
650 p_pkt_mnglr
->dir
= *(uint32_t *)data
;
652 case PKT_MNGLR_OPT_PROTOCOL
:
653 if (len
< sizeof(uint32_t)) {
654 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
655 "len too small %lu", len
);
659 if (p_pkt_mnglr
->proto
!= 0) {
660 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
666 p_pkt_mnglr
->proto
= *(uint32_t *)data
;
668 case PKT_MNGLR_OPT_ACTIVATE
:
669 if (len
< sizeof(uint8_t)) {
670 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
671 "len too small %lu", len
);
675 if (p_pkt_mnglr
->activate
!= 0) {
676 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
678 p_pkt_mnglr
->activate
);
682 p_pkt_mnglr
->activate
= *(uint8_t *)data
;
683 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr->activate set to :%d",
684 p_pkt_mnglr
->activate
);
691 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
699 struct kern_ctl_reg kern_ctl
;
701 vm_size_t pkt_mnglr_size
= 0;
703 PKT_MNGLR_LOG(LOG_NOTICE
, "");
706 * Compile time verifications
708 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT
== MAX_PACKET_MANGLER
);
711 * Zone for packet mangler kernel control sockets
713 pkt_mnglr_size
= sizeof(struct packet_mangler
);
714 packet_mangler_zone
= zinit(pkt_mnglr_size
,
715 PACKET_MANGLER_ZONE_MAX
* pkt_mnglr_size
,
717 PACKET_MANGLER_ZONE_NAME
);
719 if (packet_mangler_zone
== NULL
) {
720 panic("%s: zinit(%s) failed", __func__
,
721 PACKET_MANGLER_ZONE_NAME
);
724 zone_change(packet_mangler_zone
, Z_CALLERACCT
, FALSE
);
725 zone_change(packet_mangler_zone
, Z_EXPAND
, TRUE
);
730 pkt_mnglr_lck_grp_attr
= lck_grp_attr_alloc_init();
731 if (pkt_mnglr_lck_grp_attr
== NULL
) {
732 panic("%s: lck_grp_attr_alloc_init failed", __func__
);
735 pkt_mnglr_lck_grp
= lck_grp_alloc_init("packet manglerr",
736 pkt_mnglr_lck_grp_attr
);
737 if (pkt_mnglr_lck_grp
== NULL
) {
738 panic("%s: lck_grp_alloc_init failed", __func__
);
741 pkt_mnglr_lck_attr
= lck_attr_alloc_init();
742 if (pkt_mnglr_lck_attr
== NULL
) {
743 panic("%s: lck_attr_alloc_init failed", __func__
);
746 lck_rw_init(&pkt_mnglr_lck_rw
, pkt_mnglr_lck_grp
, pkt_mnglr_lck_attr
);
749 * Register kernel control
751 bzero(&kern_ctl
, sizeof(kern_ctl
));
752 strlcpy(kern_ctl
.ctl_name
, PACKET_MANGLER_CONTROL_NAME
,
753 sizeof(kern_ctl
.ctl_name
));
754 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
;
755 kern_ctl
.ctl_connect
= pkt_mnglr_ctl_connect
;
756 kern_ctl
.ctl_disconnect
= pkt_mnglr_ctl_disconnect
;
757 kern_ctl
.ctl_getopt
= pkt_mnglr_ctl_getopt
;
758 kern_ctl
.ctl_setopt
= pkt_mnglr_ctl_setopt
;
759 error
= ctl_register(&kern_ctl
, &pkt_mnglr_kctlref
);
761 PKT_MNGLR_LOG(LOG_ERR
, "ctl_register failed: %d", error
);
763 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler kernel control.");
767 static errno_t
pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
, ipf_pktopts_t options
)
769 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
775 #pragma unused(tcp, optlen, options)
776 if (p_pkt_mnglr
== NULL
) {
780 if (!p_pkt_mnglr
->activate
) {
784 if (p_pkt_mnglr
->dir
== IN
) {
789 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
793 /* Check for IP filter options */
794 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
796 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
800 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
804 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
808 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
809 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
810 if (ip
.ip_src
.s_addr
!= laddr
.sin_addr
.s_addr
) {
815 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
816 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
817 if (ip
.ip_dst
.s_addr
!= raddr
.sin_addr
.s_addr
) {
823 PKT_MNGLR_LOG(LOG_INFO
,
824 "%s:%d Not handling IP version %d\n",
825 __FILE__
, __LINE__
, ip
.ip_v
);
830 /* Not handling output flow */
834 #define TCP_MAX_OPTLEN 40
836 static errno_t
pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
, int offset
, u_int8_t protocol
)
838 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
841 char tcp_opt_buf
[TCP_MAX_OPTLEN
] = {0};
846 if (p_pkt_mnglr
== NULL
) {
847 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr is NULL");
851 if (p_pkt_mnglr
->activate
== 0) {
852 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr not yet activated");
856 if (p_pkt_mnglr
->dir
== OUT
) {
861 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
865 /* Check for IP filter options */
866 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
868 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
872 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
873 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family of packet is IPv4 but local "
874 "address is set to IPv6");
878 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
879 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family "
880 "of packet is IPv6 but local address is set to IPv4");
884 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
885 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
886 if (ip
.ip_dst
.s_addr
!= laddr
.sin_addr
.s_addr
) {
891 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
892 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
893 if (ip
.ip_src
.s_addr
!= raddr
.sin_addr
.s_addr
) {
896 PKT_MNGLR_LOG(LOG_INFO
, "Remote IP: %x Source IP: %x in input path",
897 raddr
.sin_addr
.s_addr
,
905 if (protocol
!= p_pkt_mnglr
->proto
) {
906 PKT_MNGLR_LOG(LOG_INFO
, "Skip: Protocol mismatch");
912 error
= mbuf_copydata(*data
, offset
, sizeof(tcp
), &tcp
);
914 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local TCP header copy");
918 if (p_pkt_mnglr
->lport
&& (p_pkt_mnglr
->lport
!= tcp
.th_dport
)) {
919 PKT_MNGLR_LOG(LOG_INFO
, "Local port and IP des port do not match");
923 if (p_pkt_mnglr
->rport
&& (p_pkt_mnglr
->rport
!= tcp
.th_sport
)) {
924 PKT_MNGLR_LOG(LOG_INFO
, "Remote port and IP src port do not match");
938 /* XXX Do IP actions here */
939 PKT_MNGLR_LOG(LOG_INFO
, "Proceeding with packet mangler actions on the packet");
941 /* Protocol actions */
944 if (p_pkt_mnglr
->proto_action_mask
) {
946 tcp_optlen
= (tcp
.th_off
<< 2)-sizeof(struct tcphdr
);
947 PKT_MNGLR_LOG(LOG_INFO
, "Packet from F5 is TCP\n");
948 PKT_MNGLR_LOG(LOG_INFO
, "Optlen: %d\n", tcp_optlen
);
949 orig_tcp_optlen
= tcp_optlen
;
950 if (orig_tcp_optlen
) {
951 error
= mbuf_copydata(*data
, offset
+sizeof(struct tcphdr
), orig_tcp_optlen
, tcp_opt_buf
);
953 PKT_MNGLR_LOG(LOG_ERR
, "Failed to copy tcp options");
959 if (tcp_opt_buf
[i
] == 0x1) {
960 PKT_MNGLR_LOG(LOG_INFO
, "Skipping NOP\n");
964 } else if ((tcp_opt_buf
[i
] != 0) && (tcp_opt_buf
[i
] != TCP_OPT_MULTIPATH_TCP
)) {
965 PKT_MNGLR_LOG(LOG_INFO
, "Skipping option %x\n", tcp_opt_buf
[i
]);
966 tcp_optlen
-= tcp_opt_buf
[i
+1];
967 i
+= tcp_opt_buf
[i
+1];
969 } else if (tcp_opt_buf
[i
] == TCP_OPT_MULTIPATH_TCP
) {
971 int mptcpoptlen
= tcp_opt_buf
[i
+1];
972 uint8_t sbtver
= tcp_opt_buf
[i
+MPTCP_SBT_VER_OFFSET
];
973 uint8_t subtype
= sbtver
>> 4;
975 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
976 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP subtype %x\n", subtype
);
977 if (subtype
== MPTCP_SUBTYPE_DSS
) {
978 PKT_MNGLR_LOG(LOG_INFO
, "Got DSS option\n");
979 PKT_MNGLR_LOG(LOG_INFO
, "Protocol option mask: %d\n", p_pkt_mnglr
->proto_action_mask
);
980 if (p_pkt_mnglr
->proto_action_mask
&
981 PKT_MNGLR_TCP_ACT_DSS_DROP
) {
986 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
987 for (; j
< mptcpoptlen
; j
++) {
988 if (p_pkt_mnglr
->proto_action_mask
&
989 PKT_MNGLR_TCP_ACT_NOP_MPTCP
) {
990 tcp_opt_buf
[i
+j
] = 0x1;
993 tcp_optlen
-= mptcpoptlen
;
1000 error
= mbuf_copyback(*data
,
1001 offset
+sizeof(struct tcphdr
),
1002 orig_tcp_optlen
, tcp_opt_buf
, MBUF_WAITOK
);
1005 PKT_MNGLR_LOG(LOG_ERR
,
1006 "Failed to copy tcp options");
1012 /* Don't handle UDP */
1016 case IPPROTO_ICMPV6
:
1021 chksm_update(*data
);
1026 PKT_MNGLR_LOG(LOG_INFO
, "Dropping packet\n");
1031 static void pktmnglr_ipfilter_detach(void *cookie
)
1033 #pragma unused(cookie)
1037 /* XXX Still need to modify this to use mbuf_copy* macros */
1038 static void chksm_update(mbuf_t data
)
1044 unsigned char *ptr
= (unsigned char *)mbuf_data(data
);
1045 struct ip
*ip
= (struct ip
*)(void *)ptr
;
1046 if (ip
->ip_v
!= 4) {
1051 mbuf_inet_cksum(data
, 0, 0, ip
->ip_hl
<< 2, &ip_sum
); // ip sum
1053 ip
->ip_sum
= ip_sum
;
1056 tcp
= (struct tcphdr
*)(void *)(ptr
+ (ip
->ip_hl
<< 2));
1058 mbuf_inet_cksum(data
, IPPROTO_TCP
, ip
->ip_hl
<< 2,
1059 ntohs(ip
->ip_len
) - (ip
->ip_hl
<< 2), &tsum
);
1063 /* Don't handle UDP */
1067 case IPPROTO_ICMPV6
:
1073 mbuf_clear_csum_performed(data
);