2 * Copyright (c) 2014 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
);
142 * packet filter global read write lock
146 pkt_mnglr_rw_lock_exclusive(lck_rw_t
*lck
)
150 lr_saved
= __builtin_return_address(0);
152 lck_rw_lock_exclusive(lck
);
154 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
155 pkt_mnglr_rw_nxt_lck
=
156 (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
160 pkt_mnglr_rw_unlock_exclusive(lck_rw_t
*lck
)
164 lr_saved
= __builtin_return_address(0);
166 lck_rw_unlock_exclusive(lck
);
168 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] =
170 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
174 pkt_mnglr_rw_lock_shared(lck_rw_t
*lck
)
178 lr_saved
= __builtin_return_address(0);
180 lck_rw_lock_shared(lck
);
182 pkt_mnglr_rw_lock_history
[pkt_mnglr_rw_nxt_lck
] = lr_saved
;
183 pkt_mnglr_rw_nxt_lck
= (pkt_mnglr_rw_nxt_lck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
187 pkt_mnglr_rw_unlock_shared(lck_rw_t
*lck
)
191 lr_saved
= __builtin_return_address(0);
193 lck_rw_unlock_shared(lck
);
195 pkt_mnglr_rw_unlock_history
[pkt_mnglr_rw_nxt_unlck
] = lr_saved
;
196 pkt_mnglr_rw_nxt_unlck
= (pkt_mnglr_rw_nxt_unlck
+ 1) % PKT_MNGLR_RW_LCK_MAX
;
200 * Packet Mangler's Kernel control socket callbacks
203 pkt_mnglr_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
207 struct packet_mangler
*p_pkt_mnglr
= NULL
;
209 PKT_MNGLR_LOG(LOG_NOTICE
, "Connecting packet mangler filter.");
211 p_pkt_mnglr
= zalloc(packet_mangler_zone
);
212 if (p_pkt_mnglr
== NULL
) {
213 PKT_MNGLR_LOG(LOG_ERR
, "zalloc failed");
218 bzero(p_pkt_mnglr
, sizeof(struct packet_mangler
));
220 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
221 if (packet_manglers
== NULL
) {
222 struct packet_mangler
**tmp
;
224 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
227 struct packet_mangler
**,
228 MAX_PACKET_MANGLER
* sizeof(struct packet_mangler
*),
232 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
234 if (tmp
== NULL
&& packet_manglers
== NULL
) {
236 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
239 /* Another thread may have won the race */
240 if (packet_manglers
!= NULL
)
243 packet_manglers
= tmp
;
246 if (sac
->sc_unit
== 0 || sac
->sc_unit
> MAX_PACKET_MANGLER
) {
247 PKT_MNGLR_LOG(LOG_ERR
, "bad sc_unit %u", sac
->sc_unit
);
249 } else if (packet_manglers
[sac
->sc_unit
- 1] != NULL
) {
250 PKT_MNGLR_LOG(LOG_ERR
, "sc_unit %u in use", sac
->sc_unit
);
254 * kernel control socket kcunit numbers start at 1
256 packet_manglers
[sac
->sc_unit
- 1] = p_pkt_mnglr
;
258 p_pkt_mnglr
->pkt_mnglr_kcref
= kctlref
;
259 p_pkt_mnglr
->pkt_mnglr_kcunit
= sac
->sc_unit
;
261 *unitinfo
= p_pkt_mnglr
;
262 pkt_mnglr_active_count
++;
265 p_pkt_mnglr
->pkt_mnglr_ipfilter
.cookie
= p_pkt_mnglr
;
266 p_pkt_mnglr
->pkt_mnglr_ipfilter
.name
= "com.apple.pktmnglripfilter";
267 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_input
= pktmnglr_ipfilter_input
;
268 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_output
= pktmnglr_ipfilter_output
;
269 p_pkt_mnglr
->pkt_mnglr_ipfilter
.ipf_detach
= pktmnglr_ipfilter_detach
;
270 error
= ipf_addv4(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfref
));
272 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv4 Filter");
275 error
= ipf_addv6(&(p_pkt_mnglr
->pkt_mnglr_ipfilter
), &(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
));
277 ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
278 PKT_MNGLR_LOG(LOG_ERR
, "Could not register packet mangler's IPv6 Filter");
282 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler's IP Filters");
283 p_pkt_mnglr
->pkt_mnglr_flags
|= PKT_MNGLR_FLG_IPFILTER_ATTACHED
;
284 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
287 if (error
!= 0 && p_pkt_mnglr
!= NULL
)
288 zfree(packet_mangler_zone
, p_pkt_mnglr
);
290 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
291 error
, pkt_mnglr_active_count
, sac
->sc_unit
);
297 pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
)
299 #pragma unused(kctlref)
301 struct packet_mangler
*p_pkt_mnglr
;
303 PKT_MNGLR_LOG(LOG_INFO
, "Disconnecting packet mangler kernel control");
305 if (packet_manglers
== NULL
) {
306 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
310 if (kcunit
> MAX_PACKET_MANGLER
) {
311 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
312 kcunit
, MAX_PACKET_MANGLER
);
317 p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
318 if (p_pkt_mnglr
== NULL
) {
319 PKT_MNGLR_LOG(LOG_ERR
, "Unit info is NULL");
323 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
324 if (packet_manglers
[kcunit
- 1] != p_pkt_mnglr
|| p_pkt_mnglr
->pkt_mnglr_kcunit
!= kcunit
) {
325 PKT_MNGLR_LOG(LOG_ERR
, "bad unit info %u)",
327 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
332 * Make filter inactive
334 packet_manglers
[kcunit
- 1] = NULL
;
335 pkt_mnglr_active_count
--;
336 if (p_pkt_mnglr
->pkt_mnglr_flags
& PKT_MNGLR_FLG_IPFILTER_ATTACHED
) {
337 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfref
);
338 (void) ipf_remove(p_pkt_mnglr
->pkt_mnglr_ipfrefv6
);
340 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
341 zfree(packet_mangler_zone
, p_pkt_mnglr
);
343 PKT_MNGLR_LOG(LOG_INFO
, "return %d pkt_mnglr_active_count %u kcunit %u",
344 error
, pkt_mnglr_active_count
, kcunit
);
350 pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
351 int opt
, void *data
, size_t *len
)
353 #pragma unused(kctlref, opt)
355 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
357 PKT_MNGLR_LOG(LOG_NOTICE
, "");
359 pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw
);
361 if (packet_manglers
== NULL
) {
362 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
366 if (kcunit
> MAX_PACKET_MANGLER
) {
367 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
368 kcunit
, MAX_PACKET_MANGLER
);
372 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
373 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
379 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
380 if (*len
< sizeof(uint32_t)) {
381 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
382 "len too small %lu", *len
);
388 *(uint32_t *)data
= p_pkt_mnglr
->proto_action_mask
;
391 case PKT_MNGLR_OPT_IP_ACT_MASK
:
392 if (*len
< sizeof(uint32_t)) {
393 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
394 "len too small %lu", *len
);
400 *(uint32_t *)data
= p_pkt_mnglr
->ip_action_mask
;
403 case PKT_MNGLR_OPT_LOCAL_IP
:
404 if (*len
< sizeof(struct sockaddr_storage
)) {
405 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
406 "len too small %lu", *len
);
412 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->lsaddr
;
415 case PKT_MNGLR_OPT_REMOTE_IP
:
416 if (*len
< sizeof(struct sockaddr_storage
)) {
417 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
418 "len too small %lu", *len
);
424 *(struct sockaddr_storage
*)data
= p_pkt_mnglr
->rsaddr
;
427 case PKT_MNGLR_OPT_LOCAL_PORT
:
428 if (*len
< sizeof(uint16_t)) {
429 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
430 "len too small %lu", *len
);
436 *(uint16_t *)data
= p_pkt_mnglr
->lport
;
439 case PKT_MNGLR_OPT_REMOTE_PORT
:
440 if (*len
< sizeof(uint16_t)) {
441 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
442 "len too small %lu", *len
);
448 *(uint16_t *)data
= p_pkt_mnglr
->rport
;
451 case PKT_MNGLR_OPT_DIRECTION
:
452 if (*len
< sizeof(uint32_t)) {
453 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
454 "len too small %lu", *len
);
459 *(uint32_t *)data
= p_pkt_mnglr
->dir
;
462 case PKT_MNGLR_OPT_PROTOCOL
:
463 if (*len
< sizeof(uint32_t)) {
464 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
465 "len too small %lu", *len
);
470 *(uint32_t *)data
= p_pkt_mnglr
->proto
;
473 case PKT_MNGLR_OPT_ACTIVATE
:
474 if (*len
< sizeof(uint8_t)) {
475 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
476 "len too small %lu", *len
);
482 *(uint8_t *)data
= p_pkt_mnglr
->activate
;
490 pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw
);
496 pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref
, u_int32_t kcunit
, void *unitinfo
,
497 int opt
, void *data
, size_t len
)
499 #pragma unused(kctlref, opt)
501 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)unitinfo
;
503 PKT_MNGLR_LOG(LOG_NOTICE
, "");
505 pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw
);
507 if (packet_manglers
== NULL
) {
508 PKT_MNGLR_LOG(LOG_ERR
, "no packet filter");
512 if (kcunit
> MAX_PACKET_MANGLER
) {
513 PKT_MNGLR_LOG(LOG_ERR
, "kcunit %u > MAX_PACKET_MANGLER (%d)",
514 kcunit
, MAX_PACKET_MANGLER
);
518 if (p_pkt_mnglr
!= (void *)packet_manglers
[kcunit
- 1]) {
519 PKT_MNGLR_LOG(LOG_ERR
, "unitinfo does not match for kcunit %u",
525 case PKT_MNGLR_OPT_PROTO_ACT_MASK
:
526 if (len
< sizeof(uint32_t)) {
527 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
528 "len too small %lu", len
);
532 if (p_pkt_mnglr
->proto_action_mask
!= 0) {
533 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
535 p_pkt_mnglr
->proto_action_mask
);
539 p_pkt_mnglr
->proto_action_mask
= *(uint32_t *)data
;
540 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr
->proto_action_mask
);
542 case PKT_MNGLR_OPT_IP_ACT_MASK
:
543 if (len
< sizeof(uint32_t)) {
544 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
545 "len too small %lu", len
);
549 if (p_pkt_mnglr
->ip_action_mask
!= 0) {
550 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_IP_ACT_MASK "
552 p_pkt_mnglr
->ip_action_mask
);
556 p_pkt_mnglr
->ip_action_mask
= *(uint32_t *)data
;
558 case PKT_MNGLR_OPT_LOCAL_IP
:
559 if (len
< sizeof(struct sockaddr_storage
)) {
560 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
561 "len too small %lu", len
);
565 if (p_pkt_mnglr
->lsaddr
.ss_family
) {
566 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_IP "
571 p_pkt_mnglr
->lsaddr
= *(struct sockaddr_storage
*)data
;
573 case PKT_MNGLR_OPT_REMOTE_IP
:
574 if (len
< sizeof(struct sockaddr_storage
)) {
575 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
576 "len too small %lu", len
);
580 if (p_pkt_mnglr
->rsaddr
.ss_family
) {
581 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_IP "
587 p_pkt_mnglr
->rsaddr
= *(struct sockaddr_storage
*)data
;
588 PKT_MNGLR_LOG(LOG_INFO
,
589 "Remote IP registered for address family: %d",
590 p_pkt_mnglr
->rsaddr
.ss_family
);
592 case PKT_MNGLR_OPT_LOCAL_PORT
:
593 if (len
< sizeof(uint16_t)) {
594 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
595 "len too small %lu", len
);
599 if (p_pkt_mnglr
->lport
!= 0) {
600 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_LOCAL_PORT "
606 p_pkt_mnglr
->lport
= *(uint16_t *)data
;
608 case PKT_MNGLR_OPT_REMOTE_PORT
:
609 if (len
< sizeof(uint16_t)) {
610 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
611 "len too small %lu", len
);
615 if (p_pkt_mnglr
->rport
!= 0) {
616 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_REMOTE_PORT "
622 p_pkt_mnglr
->rport
= *(uint16_t *)data
;
624 case PKT_MNGLR_OPT_DIRECTION
:
625 if (len
< sizeof(uint32_t)) {
626 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
627 "len too small %lu", len
);
631 if (p_pkt_mnglr
->dir
!= 0) {
632 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_DIRECTION "
638 p_pkt_mnglr
->dir
= *(uint32_t *)data
;
640 case PKT_MNGLR_OPT_PROTOCOL
:
641 if (len
< sizeof(uint32_t)) {
642 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
643 "len too small %lu", len
);
647 if (p_pkt_mnglr
->proto
!= 0) {
648 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_PROTOCOL "
654 p_pkt_mnglr
->proto
= *(uint32_t *)data
;
656 case PKT_MNGLR_OPT_ACTIVATE
:
657 if (len
< sizeof(uint8_t)) {
658 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
659 "len too small %lu", len
);
663 if (p_pkt_mnglr
->activate
!= 0) {
664 PKT_MNGLR_LOG(LOG_ERR
, "PKT_MNGLR_OPT_ACTIVATE "
666 p_pkt_mnglr
->activate
);
670 p_pkt_mnglr
->activate
= *(uint8_t *)data
;
671 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr->activate set to :%d",
672 p_pkt_mnglr
->activate
);
679 pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw
);
687 struct kern_ctl_reg kern_ctl
;
689 vm_size_t pkt_mnglr_size
= 0;
691 PKT_MNGLR_LOG(LOG_NOTICE
, "");
694 * Compile time verifications
696 _CASSERT(PKT_MNGLR_MAX_FILTER_COUNT
== MAX_PACKET_MANGLER
);
699 * Zone for packet mangler kernel control sockets
701 pkt_mnglr_size
= sizeof(struct packet_mangler
);
702 packet_mangler_zone
= zinit(pkt_mnglr_size
,
703 PACKET_MANGLER_ZONE_MAX
* pkt_mnglr_size
,
705 PACKET_MANGLER_ZONE_NAME
);
707 if (packet_mangler_zone
== NULL
) {
708 panic("%s: zinit(%s) failed", __func__
,
709 PACKET_MANGLER_ZONE_NAME
);
712 zone_change(packet_mangler_zone
, Z_CALLERACCT
, FALSE
);
713 zone_change(packet_mangler_zone
, Z_EXPAND
, TRUE
);
718 pkt_mnglr_lck_grp_attr
= lck_grp_attr_alloc_init();
719 if (pkt_mnglr_lck_grp_attr
== NULL
) {
720 panic("%s: lck_grp_attr_alloc_init failed", __func__
);
723 pkt_mnglr_lck_grp
= lck_grp_alloc_init("packet manglerr",
724 pkt_mnglr_lck_grp_attr
);
725 if (pkt_mnglr_lck_grp
== NULL
) {
726 panic("%s: lck_grp_alloc_init failed", __func__
);
729 pkt_mnglr_lck_attr
= lck_attr_alloc_init();
730 if (pkt_mnglr_lck_attr
== NULL
) {
731 panic("%s: lck_attr_alloc_init failed", __func__
);
734 lck_rw_init(&pkt_mnglr_lck_rw
, pkt_mnglr_lck_grp
, pkt_mnglr_lck_attr
);
737 * Register kernel control
739 bzero(&kern_ctl
, sizeof(kern_ctl
));
740 strlcpy(kern_ctl
.ctl_name
, PACKET_MANGLER_CONTROL_NAME
,
741 sizeof(kern_ctl
.ctl_name
));
742 kern_ctl
.ctl_flags
= CTL_FLAG_PRIVILEGED
| CTL_FLAG_REG_EXTENDED
;
743 kern_ctl
.ctl_connect
= pkt_mnglr_ctl_connect
;
744 kern_ctl
.ctl_disconnect
= pkt_mnglr_ctl_disconnect
;
745 kern_ctl
.ctl_getopt
= pkt_mnglr_ctl_getopt
;
746 kern_ctl
.ctl_setopt
= pkt_mnglr_ctl_setopt
;
747 error
= ctl_register(&kern_ctl
, &pkt_mnglr_kctlref
);
749 PKT_MNGLR_LOG(LOG_ERR
, "ctl_register failed: %d", error
);
751 PKT_MNGLR_LOG(LOG_INFO
, "Registered packet mangler kernel control.");
755 static errno_t
pktmnglr_ipfilter_output(void *cookie
, mbuf_t
*data
, ipf_pktopts_t options
)
757 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
758 unsigned char *ptr
= (unsigned char *)mbuf_data(*data
);
759 struct ip
*ip
= (struct ip
*)(void *)ptr
;
763 #pragma unused(tcp, optlen, options)
765 if (p_pkt_mnglr
== NULL
) {
769 if (!p_pkt_mnglr
->activate
) {
774 PKT_MNGLR_LOG(LOG_INFO
, "%s:%d Data pointer is NULL\n", __FILE__
, __LINE__
);
778 if (p_pkt_mnglr
->dir
== IN
) {
782 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
->ip_v
== 4)) {
786 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
->ip_v
== 6)) {
790 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
791 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
792 if (ip
->ip_src
.s_addr
!= laddr
.sin_addr
.s_addr
) {
797 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
798 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
799 if (ip
->ip_dst
.s_addr
!= raddr
.sin_addr
.s_addr
) {
805 PKT_MNGLR_LOG(LOG_INFO
, "%s:%d Not handling IP version %d\n", __FILE__
, __LINE__
, ip
->ip_v
);
809 /* Not handling output flow */
813 #define TCP_MAX_OPTLEN 40
815 static errno_t
pktmnglr_ipfilter_input(void *cookie
, mbuf_t
*data
, int offset
, u_int8_t protocol
)
817 struct packet_mangler
*p_pkt_mnglr
= (struct packet_mangler
*)cookie
;
820 char tcp_opt_buf
[TCP_MAX_OPTLEN
] = {0};
825 if (p_pkt_mnglr
== NULL
) {
826 PKT_MNGLR_LOG(LOG_ERR
, "p_pkt_mnglr is NULL");
830 if (p_pkt_mnglr
->activate
== 0) {
831 PKT_MNGLR_LOG(LOG_INFO
, "p_pkt_mnglr not yet activated");
836 PKT_MNGLR_LOG(LOG_ERR
, "Data pointer is NULL");
840 if (p_pkt_mnglr
->dir
== OUT
) {
844 /* Check for IP filter options */
845 error
= mbuf_copydata(*data
, 0, sizeof(ip
), &ip
);
847 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local IP header copy");
851 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET6
) && (ip
.ip_v
== 4)) {
852 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family of packet is IPv4 but local "
853 "address is set to IPv6");
857 if ((p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) && (ip
.ip_v
== 6)) {
858 PKT_MNGLR_LOG(LOG_INFO
, "Skipping filtering as address family "
859 "of packet is IPv6 but local address is set to IPv4");
863 if (p_pkt_mnglr
->lsaddr
.ss_family
== AF_INET
) {
864 struct sockaddr_in laddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->lsaddr
));
865 if (ip
.ip_dst
.s_addr
!= laddr
.sin_addr
.s_addr
) {
870 if (p_pkt_mnglr
->rsaddr
.ss_family
== AF_INET
) {
871 struct sockaddr_in raddr
= *(struct sockaddr_in
*)(&(p_pkt_mnglr
->rsaddr
));
872 if (ip
.ip_src
.s_addr
!= raddr
.sin_addr
.s_addr
) {
875 PKT_MNGLR_LOG(LOG_INFO
, "Remote IP: %x Source IP: %x in input path",
876 raddr
.sin_addr
.s_addr
,
884 if (protocol
!= p_pkt_mnglr
->proto
) {
885 PKT_MNGLR_LOG(LOG_INFO
, "Skip: Protocol mismatch");
891 error
= mbuf_copydata(*data
, offset
, sizeof(tcp
), &tcp
);
893 PKT_MNGLR_LOG(LOG_ERR
, "Could not make local TCP header copy");
897 if (p_pkt_mnglr
->lport
&& (p_pkt_mnglr
->lport
!= tcp
.th_dport
)) {
898 PKT_MNGLR_LOG(LOG_INFO
, "Local port and IP des port do not match");
902 if (p_pkt_mnglr
->rport
&& (p_pkt_mnglr
->rport
!= tcp
.th_sport
)) {
903 PKT_MNGLR_LOG(LOG_INFO
, "Remote port and IP src port do not match");
921 /* XXX Do IP actions here */
922 PKT_MNGLR_LOG(LOG_INFO
, "Proceeding with packet mangler actions on the packet");
924 /* Protocol actions */
927 if (p_pkt_mnglr
->proto_action_mask
& PKT_MNGLR_TCP_ACT_NOP_MPTCP
) {
929 tcp_optlen
= (tcp
.th_off
<< 2)-sizeof(struct tcphdr
);
930 PKT_MNGLR_LOG(LOG_INFO
, "Packet from F5 is TCP\n");
931 PKT_MNGLR_LOG(LOG_INFO
, "Optlen: %d\n", tcp_optlen
);
932 orig_tcp_optlen
= tcp_optlen
;
933 if (orig_tcp_optlen
) {
934 error
= mbuf_copydata(*data
, offset
+sizeof(struct tcphdr
), orig_tcp_optlen
, tcp_opt_buf
);
936 PKT_MNGLR_LOG(LOG_ERR
, "Failed to copy tcp options");
942 if (tcp_opt_buf
[i
] == 0x1) {
943 PKT_MNGLR_LOG(LOG_INFO
, "Skipping NOP\n");
947 } else if ((tcp_opt_buf
[i
] != 0) && (tcp_opt_buf
[i
] != 0x1e)) {
948 PKT_MNGLR_LOG(LOG_INFO
, "Skipping option %x\n", tcp_opt_buf
[i
]);
949 tcp_optlen
-= tcp_opt_buf
[i
+1];
950 i
+= tcp_opt_buf
[i
+1];
952 } else if (tcp_opt_buf
[i
] == 0x1e) {
954 int mptcpoptlen
= tcp_opt_buf
[i
+1];
955 PKT_MNGLR_LOG(LOG_INFO
, "Got MPTCP option %x\n", tcp_opt_buf
[i
]);
956 PKT_MNGLR_LOG(LOG_INFO
, "Overwriting with NOP\n");
957 for (; j
< mptcpoptlen
; j
++) {
958 tcp_opt_buf
[i
+j
] = 0x1;
960 tcp_optlen
-= mptcpoptlen
;
967 error
= mbuf_copyback(*data
,
968 offset
+sizeof(struct tcphdr
),
969 orig_tcp_optlen
, tcp_opt_buf
, MBUF_WAITOK
);
972 PKT_MNGLR_LOG(LOG_ERR
,
973 "Failed to copy tcp options");
979 /* Don't handle UDP */
993 static void pktmnglr_ipfilter_detach(void *cookie
)
995 #pragma unused(cookie)
999 /* XXX Still need to modify this to use mbuf_copy* macros */
1000 static void chksm_update(mbuf_t data
)
1006 unsigned char *ptr
= (unsigned char *)mbuf_data(data
);
1007 struct ip
*ip
= (struct ip
*)(void *)ptr
;
1008 if (ip
->ip_v
!= 4) {
1013 mbuf_inet_cksum(data
, 0, 0, ip
->ip_hl
<< 2, &ip_sum
); // ip sum
1015 ip
->ip_sum
= ip_sum
;
1018 tcp
= (struct tcphdr
*)(void *)(ptr
+ (ip
->ip_hl
<< 2));
1020 mbuf_inet_cksum(data
, IPPROTO_TCP
, ip
->ip_hl
<< 2,
1021 ntohs(ip
->ip_len
) - (ip
->ip_hl
<< 2), &tsum
);
1025 /* Don't handle UDP */
1029 case IPPROTO_ICMPV6
:
1035 mbuf_clear_csum_performed(data
);