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/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
];
116 #define PACKET_MANGLER_ZONE_NAME "packet_mangler"
117 #define PACKET_MANGLER_ZONE_MAX 10
118 static struct zone
*packet_mangler_zone
= NULL
; /* zone for packet_mangler */
121 * For troubleshooting
123 int pkt_mnglr_log_level
= LOG_ERR
;
124 int pkt_mnglr_debug
= 1;
127 * Forward declaration to appease the compiler
129 static void pkt_mnglr_rw_lock_exclusive(lck_rw_t
*);
130 static void pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*);
131 static void pkt_mnglr_rw_lock_shared(lck_rw_t
*);
132 static void pkt_mnglr_rw_unlock_shared(lck_rw_t
*);
134 static errno_t
pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
,
135 ipf_pktopts_t options
);
136 static errno_t
pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
,
137 int offset
, u_int8_t protocol
);
138 static void pktmnglr_ipfilter_detach(void *cookie
);
140 static void chksm_update(mbuf_t data
);
142 #define TCP_OPT_MULTIPATH_TCP 30
143 #define MPTCP_SBT_VER_OFFSET 2
145 #define MPTCP_SUBTYPE_MPCAPABLE 0x0
146 #define MPTCP_SUBTYPE_MPJOIN 0x1
147 #define MPTCP_SUBTYPE_DSS 0x2
148 #define MPTCP_SUBTYPE_ADD_ADDR 0x3
149 #define MPTCP_SUBTYPE_REM_ADDR 0x4
150 #define MPTCP_SUBTYPE_MP_PRIO 0x5
151 #define MPTCP_SUBTYPE_MP_FAIL 0x6
152 #define MPTCP_SUBTYPE_MP_FASTCLOSE 0x7
155 * packet filter global read write lock
159 pkt_mnglr_rw_lock_exclusive(lck_rw_t
*lck
)
163 lr_saved
= __builtin_return_address(0);
165 lck_rw_lock_exclusive(lck
);
167 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
168 pkt_mnglr_rw_nxt_lck
=
169 (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
173 pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*lck
)
177 lr_saved
= __builtin_return_address(0);
179 lck_rw_unlock_exclusive(lck
);
181 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] =
183 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
187 pkt_mnglr_rw_lock_shared(lck_rw_t
*lck
)
191 lr_saved
= __builtin_return_address(0);
193 lck_rw_lock_shared(lck
);
195 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
196 pkt_mnglr_rw_nxt_lck
= (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
200 pkt_mnglr_rw_unlock_shared(lck_rw_t
*lck
)
204 lr_saved
= __builtin_return_address(0);
206 lck_rw_unlock_shared(lck
);
208 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] = lr_saved
;
209 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
213 * Packet Mangler's Kernel control socket callbacks
216 pkt_mnglr_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
220 struct packet_mangler
*p_pkt_mnglr
= NULL
;
222 PKT_MNGLR_LOG(LOG_NOTICE
, "Connecting packet mangler filter.");
224 p_pkt_mnglr
= zalloc(packet_mangler_zone
);
225 if (p_pkt_mnglr
== NULL
) {
226 PKT_MNGLR_LOG(LOG_ERR
, "zalloc failed");
231 bzero(p_pkt_mnglr
, sizeof(struct packet_mangler
));
233 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
234 if (packet_manglers
== NULL
) {
235 struct packet_mangler
**tmp
;
237 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
240 struct packet_mangler
**,
241 MAX_PACKET_MANGLER
* sizeof(struct packet_mangler
*),
245 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
247 if (tmp
== NULL
&& packet_manglers
== NULL
) {
249 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
252 /* Another thread may have won the race */
253 if (packet_manglers
!= NULL
) {
256 packet_manglers
= tmp
;
260 if (sac
->sc_unit
== 0 || sac
->sc_unit
> MAX_PACKET_MANGLER
) {
261 PKT_MNGLR_LOG(LOG_ERR
, "bad sc_unit %u", sac
->sc_unit
);
263 } else if (packet_manglers
[sac
->sc_unit
- 1] != NULL
) {
264 PKT_MNGLR_LOG(LOG_ERR
, "sc_unit %u in use", sac
->sc_unit
);
268 * kernel control socket kcunit numbers start at 1
270 packet_manglers
[sac
->sc_unit
- 1] = p_pkt_mnglr
;
272 p_pkt_mnglr
->pkt_mnglr_kcref
= kctlref
;
273 p_pkt_mnglr
->pkt_mnglr_kcunit
= sac
->sc_unit
;
275 *unitinfo
= p_pkt_mnglr
;
276 pkt_mnglr_active_count
++;
279 p_pkt_mnglr
->pkt_mnglr_ipfilter
.cookie
= p_pkt_mnglr
;
280 p_pkt_mnglr
->pkt_mnglr_ipfilter
.name
= "com.apple.pktmnglripfilter";
281 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_input
= pktmnglr_ipfilter_input
;
282 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_output
= pktmnglr_ipfilter_output
;
283 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_detach
= pktmnglr_ipfilter_detach
;
284 error
= ipf_addv4(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfref
));
286 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv4 Filter");
289 error
= ipf_addv6(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
));
291 ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
292 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv6 Filter");
296 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler's IP Filters");
297 p_pkt_mnglr
->pkt_mnglr_flags
|= PKT_MNGLR_FLG_IPFILTER_ATTACHED
;
298 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
301 if (error
!= 0 && p_pkt_mnglr
!= NULL
) {
302 zfree(packet_mangler_zone
, p_pkt_mnglr
);
305 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
306 error
, pkt_mnglr_active_count
, sac
->sc_unit
);
312 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
)
314 #pragma unused(kctlref)
316 struct packet_mangler
*p_pkt_mnglr
;
318 PKT_MNGLR_LOG(LOG_INFO
, "Disconnecting packet mangler kernel control");
320 if (packet_manglers
== NULL
) {
321 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
325 if (kcunit
> MAX_PACKET_MANGLER
) {
326 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
327 kcunit
, MAX_PACKET_MANGLER
);
332 p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
333 if (p_pkt_mnglr
== NULL
) {
334 PKT_MNGLR_LOG(LOG_ERR
, "Unit info is NULL");
338 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
339 if (packet_manglers
[kcunit
- 1] != p_pkt_mnglr
|| p_pkt_mnglr
->pkt_mnglr_kcunit
!= kcunit
) {
340 PKT_MNGLR_LOG(LOG_ERR
, "bad unit info %u)",
342 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
347 * Make filter inactive
349 packet_manglers
[kcunit
- 1] = NULL
;
350 pkt_mnglr_active_count
--;
351 if (p_pkt_mnglr
->pkt_mnglr_flags
& PKT_MNGLR_FLG_IPFILTER_ATTACHED
) {
352 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
353 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
);
355 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
356 zfree(packet_mangler_zone
, p_pkt_mnglr
);
358 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
359 error
, pkt_mnglr_active_count
, kcunit
);
365 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
366 int opt
, void *data
, size_t *len
)
368 #pragma unused(kctlref, opt)
370 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
372 PKT_MNGLR_LOG(LOG_NOTICE
, "");
374 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw
);
376 if (packet_manglers
== NULL
) {
377 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
381 if (kcunit
> MAX_PACKET_MANGLER
) {
382 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
383 kcunit
, MAX_PACKET_MANGLER
);
387 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
388 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
394 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
395 if (*len
< sizeof(uint32_t)) {
396 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
397 "len too small %lu", *len
);
403 *(uint32_t *)data
= p_pkt_mnglr
->proto_action_mask
;
406 case PKT_MNGLR_OPT_IP_ACT_MASK
:
407 if (*len
< sizeof(uint32_t)) {
408 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
409 "len too small %lu", *len
);
415 *(uint32_t *)data
= p_pkt_mnglr
->ip_action_mask
;
418 case PKT_MNGLR_OPT_LOCAL_IP
:
419 if (*len
< sizeof(struct sockaddr_storage
)) {
420 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
421 "len too small %lu", *len
);
427 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->lsaddr
;
430 case PKT_MNGLR_OPT_REMOTE_IP
:
431 if (*len
< sizeof(struct sockaddr_storage
)) {
432 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
433 "len too small %lu", *len
);
439 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->rsaddr
;
442 case PKT_MNGLR_OPT_LOCAL_PORT
:
443 if (*len
< sizeof(uint16_t)) {
444 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
445 "len too small %lu", *len
);
451 *(uint16_t *)data
= p_pkt_mnglr
->lport
;
454 case PKT_MNGLR_OPT_REMOTE_PORT
:
455 if (*len
< sizeof(uint16_t)) {
456 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
457 "len too small %lu", *len
);
463 *(uint16_t *)data
= p_pkt_mnglr
->rport
;
466 case PKT_MNGLR_OPT_DIRECTION
:
467 if (*len
< sizeof(uint32_t)) {
468 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
469 "len too small %lu", *len
);
474 *(uint32_t *)data
= p_pkt_mnglr
->dir
;
477 case PKT_MNGLR_OPT_PROTOCOL
:
478 if (*len
< sizeof(uint32_t)) {
479 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
480 "len too small %lu", *len
);
485 *(uint32_t *)data
= p_pkt_mnglr
->proto
;
488 case PKT_MNGLR_OPT_ACTIVATE
:
489 if (*len
< sizeof(uint8_t)) {
490 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
491 "len too small %lu", *len
);
497 *(uint8_t *)data
= p_pkt_mnglr
->activate
;
505 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw
);
511 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
512 int opt
, void *data
, size_t len
)
514 #pragma unused(kctlref, opt)
516 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
518 PKT_MNGLR_LOG(LOG_NOTICE
, "");
520 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
522 if (packet_manglers
== NULL
) {
523 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
527 if (kcunit
> MAX_PACKET_MANGLER
) {
528 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
529 kcunit
, MAX_PACKET_MANGLER
);
533 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
534 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
540 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
541 if (len
< sizeof(uint32_t)) {
542 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
543 "len too small %lu", len
);
547 if (p_pkt_mnglr
->proto_action_mask
!= 0) {
548 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
550 p_pkt_mnglr
->proto_action_mask
);
554 p_pkt_mnglr
->proto_action_mask
= *(uint32_t *)data
;
555 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr
->proto_action_mask
);
557 case PKT_MNGLR_OPT_IP_ACT_MASK
:
558 if (len
< sizeof(uint32_t)) {
559 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
560 "len too small %lu", len
);
564 if (p_pkt_mnglr
->ip_action_mask
!= 0) {
565 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
567 p_pkt_mnglr
->ip_action_mask
);
571 p_pkt_mnglr
->ip_action_mask
= *(uint32_t *)data
;
573 case PKT_MNGLR_OPT_LOCAL_IP
:
574 if (len
< sizeof(struct sockaddr_storage
)) {
575 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
576 "len too small %lu", len
);
580 if (p_pkt_mnglr
->lsaddr
.ss_family
) {
581 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
586 p_pkt_mnglr
->lsaddr
= *(struct sockaddr_storage
*)data
;
588 case PKT_MNGLR_OPT_REMOTE_IP
:
589 if (len
< sizeof(struct sockaddr_storage
)) {
590 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
591 "len too small %lu", len
);
595 if (p_pkt_mnglr
->rsaddr
.ss_family
) {
596 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
602 p_pkt_mnglr
->rsaddr
= *(struct sockaddr_storage
*)data
;
603 PKT_MNGLR_LOG(LOG_INFO
,
604 "Remote IP registered for address family: %d",
605 p_pkt_mnglr
->rsaddr
.ss_family
);
607 case PKT_MNGLR_OPT_LOCAL_PORT
:
608 if (len
< sizeof(uint16_t)) {
609 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
610 "len too small %lu", len
);
614 if (p_pkt_mnglr
->lport
!= 0) {
615 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
621 p_pkt_mnglr
->lport
= *(uint16_t *)data
;
623 case PKT_MNGLR_OPT_REMOTE_PORT
:
624 if (len
< sizeof(uint16_t)) {
625 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
626 "len too small %lu", len
);
630 if (p_pkt_mnglr
->rport
!= 0) {
631 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
637 p_pkt_mnglr
->rport
= *(uint16_t *)data
;
639 case PKT_MNGLR_OPT_DIRECTION
:
640 if (len
< sizeof(uint32_t)) {
641 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
642 "len too small %lu", len
);
646 if (p_pkt_mnglr
->dir
!= 0) {
647 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
653 p_pkt_mnglr
->dir
= *(uint32_t *)data
;
655 case PKT_MNGLR_OPT_PROTOCOL
:
656 if (len
< sizeof(uint32_t)) {
657 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
658 "len too small %lu", len
);
662 if (p_pkt_mnglr
->proto
!= 0) {
663 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
669 p_pkt_mnglr
->proto
= *(uint32_t *)data
;
671 case PKT_MNGLR_OPT_ACTIVATE
:
672 if (len
< sizeof(uint8_t)) {
673 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
674 "len too small %lu", len
);
678 if (p_pkt_mnglr
->activate
!= 0) {
679 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
681 p_pkt_mnglr
->activate
);
685 p_pkt_mnglr
->activate
= *(uint8_t *)data
;
686 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr->activate set to :%d",
687 p_pkt_mnglr
->activate
);
694 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
702 struct kern_ctl_reg kern_ctl
;
704 vm_size_t pkt_mnglr_size
= 0;
706 PKT_MNGLR_LOG(LOG_NOTICE
, "");
709 * Compile time verifications
711 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT
== MAX_PACKET_MANGLER
);
714 * Zone for packet mangler kernel control sockets
716 pkt_mnglr_size
= sizeof(struct packet_mangler
);
717 packet_mangler_zone
= zinit(pkt_mnglr_size
,
718 PACKET_MANGLER_ZONE_MAX
* pkt_mnglr_size
,
720 PACKET_MANGLER_ZONE_NAME
);
722 if (packet_mangler_zone
== NULL
) {
723 panic("%s: zinit(%s) failed", __func__
,
724 PACKET_MANGLER_ZONE_NAME
);
727 zone_change(packet_mangler_zone
, Z_CALLERACCT
, FALSE
);
728 zone_change(packet_mangler_zone
, Z_EXPAND
, TRUE
);
733 pkt_mnglr_lck_grp_attr
= lck_grp_attr_alloc_init();
734 if (pkt_mnglr_lck_grp_attr
== NULL
) {
735 panic("%s: lck_grp_attr_alloc_init failed", __func__
);
738 pkt_mnglr_lck_grp
= lck_grp_alloc_init("packet manglerr",
739 pkt_mnglr_lck_grp_attr
);
740 if (pkt_mnglr_lck_grp
== NULL
) {
741 panic("%s: lck_grp_alloc_init failed", __func__
);
744 pkt_mnglr_lck_attr
= lck_attr_alloc_init();
745 if (pkt_mnglr_lck_attr
== NULL
) {
746 panic("%s: lck_attr_alloc_init failed", __func__
);
749 lck_rw_init(&pkt_mnglr_lck_rw
, pkt_mnglr_lck_grp
, pkt_mnglr_lck_attr
);
752 * Register kernel control
754 bzero(&kern_ctl
, sizeof(kern_ctl
));
755 strlcpy(kern_ctl
.ctl_name
, PACKET_MANGLER_CONTROL_NAME
,
756 sizeof(kern_ctl
.ctl_name
));
757 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
;
758 kern_ctl
.ctl_connect
= pkt_mnglr_ctl_connect
;
759 kern_ctl
.ctl_disconnect
= pkt_mnglr_ctl_disconnect
;
760 kern_ctl
.ctl_getopt
= pkt_mnglr_ctl_getopt
;
761 kern_ctl
.ctl_setopt
= pkt_mnglr_ctl_setopt
;
762 error
= ctl_register(&kern_ctl
, &pkt_mnglr_kctlref
);
764 PKT_MNGLR_LOG(LOG_ERR
, "ctl_register failed: %d", error
);
766 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler kernel control.");
771 pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
, ipf_pktopts_t options
)
773 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
779 #pragma unused(tcp, optlen, options)
780 if (p_pkt_mnglr
== NULL
) {
784 if (!p_pkt_mnglr
->activate
) {
788 if (p_pkt_mnglr
->dir
== IN
) {
793 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
797 /* Check for IP filter options */
798 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
800 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
804 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
808 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
812 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
813 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
814 if (ip
.ip_src
.s_addr
!= laddr
.sin_addr
.s_addr
) {
819 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
820 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
821 if (ip
.ip_dst
.s_addr
!= raddr
.sin_addr
.s_addr
) {
827 PKT_MNGLR_LOG(LOG_INFO
,
828 "%s:%d Not handling IP version %d\n",
829 __func__
, __LINE__
, ip
.ip_v
);
834 /* Not handling output flow */
838 #define TCP_MAX_OPTLEN 40
841 pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
, int offset
, u_int8_t protocol
)
843 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
850 if (p_pkt_mnglr
== NULL
) {
851 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr is NULL");
855 if (p_pkt_mnglr
->activate
== 0) {
856 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr not yet activated");
860 if (p_pkt_mnglr
->dir
== OUT
) {
865 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
869 /* Check for IP filter options */
870 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
872 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
877 error
= mbuf_copydata(*data
, 0, sizeof(ip6
), &ip6
);
879 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IPv6 header copy");
884 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
885 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family of packet is IPv4 but local "
886 "address is set to IPv6");
890 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
891 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family "
892 "of packet is IPv6 but local address is set to IPv4");
896 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
897 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
898 if (ip
.ip_dst
.s_addr
!= laddr
.sin_addr
.s_addr
) {
901 } else if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) {
902 struct sockaddr_in6 laddr
= *(struct sockaddr_in6
*)(&(p_pkt_mnglr
->lsaddr
));
903 if (!IN6_ARE_ADDR_EQUAL(&ip6
.ip6_dst
, &laddr
.sin6_addr
)) {
908 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
909 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
910 if (ip
.ip_src
.s_addr
!= raddr
.sin_addr
.s_addr
) {
913 PKT_MNGLR_LOG(LOG_INFO
, "Remote IP: %x Source IP: %x in input path",
914 raddr
.sin_addr
.s_addr
,
916 } else if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET6
) {
917 struct sockaddr_in6 raddr
= *(struct sockaddr_in6
*)(&(p_pkt_mnglr
->rsaddr
));
918 if (!IN6_ARE_ADDR_EQUAL(&ip6
.ip6_src
, &raddr
.sin6_addr
)) {
924 ip_pld_len
= ntohs(ip
.ip_len
) - (ip
.ip_hl
<< 2);
925 } else if (ip
.ip_v
== 6) {
926 if (ip6
.ip6_nxt
!= p_pkt_mnglr
->proto
) {
927 /* Don't support IPv6 extension headers */
930 ip_pld_len
= ntohs(ip6
.ip6_plen
) + sizeof(struct ip6_hdr
);
936 if (protocol
!= p_pkt_mnglr
->proto
) {
937 PKT_MNGLR_LOG(LOG_INFO
, "Skip: Protocol mismatch");
943 if (ip_pld_len
< (int) sizeof(tcp
)) {
944 PKT_MNGLR_LOG(LOG_ERR
, "IP total len not big enough for TCP: %d", ip_pld_len
);
948 error
= mbuf_copydata(*data
, offset
, sizeof(tcp
), &tcp
);
950 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local TCP header copy");
954 if (p_pkt_mnglr
->lport
&& (p_pkt_mnglr
->lport
!= tcp
.th_dport
)) {
955 PKT_MNGLR_LOG(LOG_INFO
, "Local port and IP des port do not match");
959 if (p_pkt_mnglr
->rport
&& (p_pkt_mnglr
->rport
!= tcp
.th_sport
)) {
960 PKT_MNGLR_LOG(LOG_INFO
, "Remote port and IP src port do not match");
974 /* XXX Do IP actions here */
975 PKT_MNGLR_LOG(LOG_INFO
, "Proceeding with packet mangler actions on the packet");
977 /* Protocol actions */
980 if (p_pkt_mnglr
->proto_action_mask
) {
981 char tcp_opt_buf
[TCP_MAX_OPTLEN
] = {0};
986 off
= (tcp
.th_off
<< 2);
988 if (off
< (int) sizeof(struct tcphdr
) || off
> ip_pld_len
) {
989 PKT_MNGLR_LOG(LOG_ERR
, "TCP header offset is wrong: %d", off
);
994 tcp_optlen
= off
- sizeof(struct tcphdr
);
996 PKT_MNGLR_LOG(LOG_INFO
, "Packet from F5 is TCP\n");
997 PKT_MNGLR_LOG(LOG_INFO
, "Optlen: %d\n", tcp_optlen
);
998 orig_tcp_optlen
= tcp_optlen
;
999 if (orig_tcp_optlen
) {
1000 error
= mbuf_copydata(*data
, offset
+ sizeof(struct tcphdr
), orig_tcp_optlen
, tcp_opt_buf
);
1002 PKT_MNGLR_LOG(LOG_ERR
, "Failed to copy tcp options: error %d offset %d optlen %d", error
, offset
, orig_tcp_optlen
);
1007 while (tcp_optlen
> 0) {
1008 if (tcp_opt_buf
[i
] == 0x1) {
1009 PKT_MNGLR_LOG(LOG_INFO
, "Skipping NOP\n");
1013 } else if ((tcp_opt_buf
[i
] != 0) && (tcp_opt_buf
[i
] != TCP_OPT_MULTIPATH_TCP
)) {
1014 PKT_MNGLR_LOG(LOG_INFO
, "Skipping option %x\n", tcp_opt_buf
[i
]);
1016 /* Minimum TCP option size is 2 */
1017 if (tcp_opt_buf
[i
+ 1] < 2) {
1018 PKT_MNGLR_LOG(LOG_ERR
, "Received suspicious TCP option");
1021 tcp_optlen
-= tcp_opt_buf
[i
+ 1];
1022 i
+= tcp_opt_buf
[i
+ 1];
1024 } else if (tcp_opt_buf
[i
] == TCP_OPT_MULTIPATH_TCP
) {
1026 unsigned char mptcpoptlen
= tcp_opt_buf
[i
+ 1];
1027 uint8_t sbtver
= tcp_opt_buf
[i
+ MPTCP_SBT_VER_OFFSET
];
1028 uint8_t subtype
= sbtver
>> 4;
1030 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
1031 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP subtype %x\n", subtype
);
1032 if (subtype
== MPTCP_SUBTYPE_DSS
) {
1033 PKT_MNGLR_LOG(LOG_INFO
, "Got DSS option\n");
1034 PKT_MNGLR_LOG(LOG_INFO
, "Protocol option mask: %d\n", p_pkt_mnglr
->proto_action_mask
);
1035 if (p_pkt_mnglr
->proto_action_mask
&
1036 PKT_MNGLR_TCP_ACT_DSS_DROP
) {
1041 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
1042 for (; j
< mptcpoptlen
&& j
< tcp_optlen
; j
++) {
1043 if (p_pkt_mnglr
->proto_action_mask
&
1044 PKT_MNGLR_TCP_ACT_NOP_MPTCP
) {
1045 tcp_opt_buf
[i
+ j
] = 0x1;
1048 tcp_optlen
-= mptcpoptlen
;
1056 if (orig_tcp_optlen
) {
1057 error
= mbuf_copyback(*data
,
1058 offset
+ sizeof(struct tcphdr
),
1059 orig_tcp_optlen
, tcp_opt_buf
, MBUF_WAITOK
);
1062 PKT_MNGLR_LOG(LOG_ERR
,
1063 "Failed to copy tcp options back: error %d offset %d optlen %d",
1064 error
, offset
, orig_tcp_optlen
);
1071 /* Don't handle UDP */
1075 case IPPROTO_ICMPV6
:
1080 chksm_update(*data
);
1085 PKT_MNGLR_LOG(LOG_INFO
, "Dropping packet\n");
1091 pktmnglr_ipfilter_detach(void *cookie
)
1093 #pragma unused(cookie)
1097 /* XXX Still need to modify this to use mbuf_copy* macros */
1099 chksm_update(mbuf_t data
)
1106 unsigned char *ptr
= (unsigned char *)mbuf_data(data
);
1107 struct ip
*ip
= (struct ip
*)(void *)ptr
;
1108 if (ip
->ip_v
!= 4) {
1113 err
= mbuf_inet_cksum(data
, 0, 0, ip
->ip_hl
<< 2, &ip_sum
); // ip sum
1115 ip
->ip_sum
= ip_sum
;
1119 tcp
= (struct tcphdr
*)(void *)(ptr
+ (ip
->ip_hl
<< 2));
1121 err
= mbuf_inet_cksum(data
, IPPROTO_TCP
, ip
->ip_hl
<< 2,
1122 ntohs(ip
->ip_len
) - (ip
->ip_hl
<< 2), &tsum
);
1128 /* Don't handle UDP */
1132 case IPPROTO_ICMPV6
:
1138 mbuf_clear_csum_performed(data
);