xref: /xnu-8796.101.5/bsd/net/packet_mangler.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1*aca3beaaSApple OSS Distributions /*
2*aca3beaaSApple OSS Distributions  * Copyright (c) 2015-2020 Apple Inc. All rights reserved.
3*aca3beaaSApple OSS Distributions  *
4*aca3beaaSApple OSS Distributions  * @APPLE_LICENSE_HEADER_START@
5*aca3beaaSApple OSS Distributions  *
6*aca3beaaSApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*aca3beaaSApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*aca3beaaSApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*aca3beaaSApple OSS Distributions  * compliance with the License. Please obtain a copy of the License at
10*aca3beaaSApple OSS Distributions  * http: www.opensource.apple.com/apsl/ and read it before using this
11*aca3beaaSApple OSS Distributions  * file.
12*aca3beaaSApple OSS Distributions  *
13*aca3beaaSApple OSS Distributions  * The Original Code and all software distributed under the License are
14*aca3beaaSApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15*aca3beaaSApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16*aca3beaaSApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17*aca3beaaSApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18*aca3beaaSApple OSS Distributions  * Please see the License for the specific language governing rights and
19*aca3beaaSApple OSS Distributions  * limitations under the License.
20*aca3beaaSApple OSS Distributions  *
21*aca3beaaSApple OSS Distributions  * @APPLE_LICENSE_HEADER_END@
22*aca3beaaSApple OSS Distributions  */
23*aca3beaaSApple OSS Distributions 
24*aca3beaaSApple OSS Distributions /*
25*aca3beaaSApple OSS Distributions  * THEORY OF OPERATION
26*aca3beaaSApple OSS Distributions  *
27*aca3beaaSApple OSS Distributions  * The packet mangler subsystem provides a limited way for user space
28*aca3beaaSApple OSS Distributions  * applications to apply certain actions on certain flows.
29*aca3beaaSApple OSS Distributions  *
30*aca3beaaSApple OSS Distributions  * A user space applications opens a kernel control socket with the name
31*aca3beaaSApple OSS Distributions  * PACKET_MANGLER_CONTROL_NAME to attach to the packet mangler subsystem.
32*aca3beaaSApple OSS Distributions  * When connected, a "struct packet_mangler" is created and set as the
33*aca3beaaSApple OSS Distributions  * "unitinfo" of the corresponding kernel control socket instance.
34*aca3beaaSApple OSS Distributions  * Connect call for packet mangler's kernel control socket also registers
35*aca3beaaSApple OSS Distributions  * ip filers with cookie set to the packet_mangler instance.
36*aca3beaaSApple OSS Distributions  * The ip filters are removed when control socket is disconnected.
37*aca3beaaSApple OSS Distributions  */
38*aca3beaaSApple OSS Distributions #include <sys/types.h>
39*aca3beaaSApple OSS Distributions #include <sys/kern_control.h>
40*aca3beaaSApple OSS Distributions #include <sys/domain.h>
41*aca3beaaSApple OSS Distributions #include <sys/protosw.h>
42*aca3beaaSApple OSS Distributions #include <sys/syslog.h>
43*aca3beaaSApple OSS Distributions 
44*aca3beaaSApple OSS Distributions #include <kern/locks.h>
45*aca3beaaSApple OSS Distributions #include <kern/zalloc.h>
46*aca3beaaSApple OSS Distributions #include <kern/debug.h>
47*aca3beaaSApple OSS Distributions 
48*aca3beaaSApple OSS Distributions #include <net/packet_mangler.h>
49*aca3beaaSApple OSS Distributions 
50*aca3beaaSApple OSS Distributions #include <netinet/mptcp.h>
51*aca3beaaSApple OSS Distributions #include <netinet/tcp.h>
52*aca3beaaSApple OSS Distributions #include <netinet/tcp_var.h>
53*aca3beaaSApple OSS Distributions #include <netinet/ip.h>
54*aca3beaaSApple OSS Distributions #include <netinet/ip6.h>
55*aca3beaaSApple OSS Distributions #include <netinet/kpi_ipfilter.h>
56*aca3beaaSApple OSS Distributions #include <string.h>
57*aca3beaaSApple OSS Distributions #include <libkern/libkern.h>
58*aca3beaaSApple OSS Distributions 
59*aca3beaaSApple OSS Distributions #define MAX_PACKET_MANGLER                      1
60*aca3beaaSApple OSS Distributions 
61*aca3beaaSApple OSS Distributions #define PKT_MNGLR_FLG_IPFILTER_ATTACHED         0x00000001
62*aca3beaaSApple OSS Distributions 
63*aca3beaaSApple OSS Distributions SYSCTL_NODE(_net, OID_AUTO, pktmnglr, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "pktmnglr");
64*aca3beaaSApple OSS Distributions SYSCTL_INT(_net_pktmnglr, OID_AUTO, log, CTLFLAG_RW | CTLFLAG_LOCKED,
65*aca3beaaSApple OSS Distributions     &pkt_mnglr_log_level, 0, "");
66*aca3beaaSApple OSS Distributions /*
67*aca3beaaSApple OSS Distributions  * The structure packet_mangler represents a user space packet filter
68*aca3beaaSApple OSS Distributions  * It's created and associated with a kernel control socket instance
69*aca3beaaSApple OSS Distributions  */
70*aca3beaaSApple OSS Distributions struct packet_mangler {
71*aca3beaaSApple OSS Distributions 	kern_ctl_ref                    pkt_mnglr_kcref;
72*aca3beaaSApple OSS Distributions 	uint32_t                        pkt_mnglr_kcunit;
73*aca3beaaSApple OSS Distributions 	uint32_t                        pkt_mnglr_flags;
74*aca3beaaSApple OSS Distributions 	/* IP filter related params */
75*aca3beaaSApple OSS Distributions 	ipfilter_t                      pkt_mnglr_ipfref;
76*aca3beaaSApple OSS Distributions 	ipfilter_t                      pkt_mnglr_ipfrefv6;
77*aca3beaaSApple OSS Distributions 	struct ipf_filter               pkt_mnglr_ipfilter;
78*aca3beaaSApple OSS Distributions 
79*aca3beaaSApple OSS Distributions 	/* Options */
80*aca3beaaSApple OSS Distributions 	uint8_t                         activate;
81*aca3beaaSApple OSS Distributions 	Pkt_Mnglr_Flow                  dir;
82*aca3beaaSApple OSS Distributions 	struct sockaddr_storage         lsaddr;
83*aca3beaaSApple OSS Distributions 	struct sockaddr_storage         rsaddr;
84*aca3beaaSApple OSS Distributions 	struct sockaddr_storage         swap_lsaddr;
85*aca3beaaSApple OSS Distributions 	struct sockaddr_storage         swap_rsaddr;
86*aca3beaaSApple OSS Distributions 	uint32_t                        ip_action_mask;
87*aca3beaaSApple OSS Distributions 	uint16_t                        lport;
88*aca3beaaSApple OSS Distributions 	uint16_t                        rport;
89*aca3beaaSApple OSS Distributions 	uint32_t                        proto;
90*aca3beaaSApple OSS Distributions 	uint32_t                        proto_action_mask;
91*aca3beaaSApple OSS Distributions };
92*aca3beaaSApple OSS Distributions 
93*aca3beaaSApple OSS Distributions /* Array of all the packet mangler instancesi */
94*aca3beaaSApple OSS Distributions struct packet_mangler *packet_manglers[MAX_PACKET_MANGLER];
95*aca3beaaSApple OSS Distributions 
96*aca3beaaSApple OSS Distributions uint32_t pkt_mnglr_active_count = 0;    /* Number of active packet filters */
97*aca3beaaSApple OSS Distributions uint32_t pkt_mnglr_close_wait_timeout = 1000; /* in milliseconds */
98*aca3beaaSApple OSS Distributions 
99*aca3beaaSApple OSS Distributions static kern_ctl_ref pkt_mnglr_kctlref = NULL;
100*aca3beaaSApple OSS Distributions 
101*aca3beaaSApple OSS Distributions /* The lock below protects packet_manglers DS, packet_mangler DS */
102*aca3beaaSApple OSS Distributions static LCK_GRP_DECLARE(pkt_mnglr_lck_grp, "packet mangler");
103*aca3beaaSApple OSS Distributions static LCK_RW_DECLARE(pkt_mnglr_lck_rw, &pkt_mnglr_lck_grp);
104*aca3beaaSApple OSS Distributions 
105*aca3beaaSApple OSS Distributions #define PKT_MNGLR_RW_LCK_MAX    8
106*aca3beaaSApple OSS Distributions 
107*aca3beaaSApple OSS Distributions int pkt_mnglr_rw_nxt_lck = 0;
108*aca3beaaSApple OSS Distributions void* pkt_mnglr_rw_lock_history[PKT_MNGLR_RW_LCK_MAX];
109*aca3beaaSApple OSS Distributions 
110*aca3beaaSApple OSS Distributions int pkt_mnglr_rw_nxt_unlck = 0;
111*aca3beaaSApple OSS Distributions void* pkt_mnglr_rw_unlock_history[PKT_MNGLR_RW_LCK_MAX];
112*aca3beaaSApple OSS Distributions 
113*aca3beaaSApple OSS Distributions static KALLOC_TYPE_DEFINE(packet_mangler_zone, struct packet_mangler, NET_KT_DEFAULT);
114*aca3beaaSApple OSS Distributions 
115*aca3beaaSApple OSS Distributions /*
116*aca3beaaSApple OSS Distributions  * For troubleshooting
117*aca3beaaSApple OSS Distributions  */
118*aca3beaaSApple OSS Distributions int pkt_mnglr_log_level = LOG_ERR;
119*aca3beaaSApple OSS Distributions int pkt_mnglr_debug = 1;
120*aca3beaaSApple OSS Distributions 
121*aca3beaaSApple OSS Distributions /*
122*aca3beaaSApple OSS Distributions  * Forward declaration to appease the compiler
123*aca3beaaSApple OSS Distributions  */
124*aca3beaaSApple OSS Distributions static void pkt_mnglr_rw_lock_exclusive(lck_rw_t *);
125*aca3beaaSApple OSS Distributions static void pkt_mnglr_rw_unlock_exclusive(lck_rw_t *);
126*aca3beaaSApple OSS Distributions static void pkt_mnglr_rw_lock_shared(lck_rw_t *);
127*aca3beaaSApple OSS Distributions static void pkt_mnglr_rw_unlock_shared(lck_rw_t *);
128*aca3beaaSApple OSS Distributions 
129*aca3beaaSApple OSS Distributions static errno_t pktmnglr_ipfilter_output(void *cookie, mbuf_t *data,
130*aca3beaaSApple OSS Distributions     ipf_pktopts_t options);
131*aca3beaaSApple OSS Distributions static errno_t pktmnglr_ipfilter_input(void *cookie, mbuf_t *data,
132*aca3beaaSApple OSS Distributions     int offset, u_int8_t protocol);
133*aca3beaaSApple OSS Distributions static void pktmnglr_ipfilter_detach(void *cookie);
134*aca3beaaSApple OSS Distributions 
135*aca3beaaSApple OSS Distributions static void chksm_update(mbuf_t data);
136*aca3beaaSApple OSS Distributions 
137*aca3beaaSApple OSS Distributions #define TCP_OPT_MULTIPATH_TCP   30
138*aca3beaaSApple OSS Distributions #define MPTCP_SBT_VER_OFFSET    2
139*aca3beaaSApple OSS Distributions 
140*aca3beaaSApple OSS Distributions /*
141*aca3beaaSApple OSS Distributions  * packet filter global read write lock
142*aca3beaaSApple OSS Distributions  */
143*aca3beaaSApple OSS Distributions 
144*aca3beaaSApple OSS Distributions static void
pkt_mnglr_rw_lock_exclusive(lck_rw_t * lck)145*aca3beaaSApple OSS Distributions pkt_mnglr_rw_lock_exclusive(lck_rw_t *lck)
146*aca3beaaSApple OSS Distributions {
147*aca3beaaSApple OSS Distributions 	void *lr_saved;
148*aca3beaaSApple OSS Distributions 
149*aca3beaaSApple OSS Distributions 	lr_saved = __builtin_return_address(0);
150*aca3beaaSApple OSS Distributions 
151*aca3beaaSApple OSS Distributions 	lck_rw_lock_exclusive(lck);
152*aca3beaaSApple OSS Distributions 
153*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_history[pkt_mnglr_rw_nxt_lck] = lr_saved;
154*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_nxt_lck =
155*aca3beaaSApple OSS Distributions 	    (pkt_mnglr_rw_nxt_lck + 1) % PKT_MNGLR_RW_LCK_MAX;
156*aca3beaaSApple OSS Distributions }
157*aca3beaaSApple OSS Distributions 
158*aca3beaaSApple OSS Distributions static void
pkt_mnglr_rw_unlock_exclusive(lck_rw_t * lck)159*aca3beaaSApple OSS Distributions pkt_mnglr_rw_unlock_exclusive(lck_rw_t *lck)
160*aca3beaaSApple OSS Distributions {
161*aca3beaaSApple OSS Distributions 	void *lr_saved;
162*aca3beaaSApple OSS Distributions 
163*aca3beaaSApple OSS Distributions 	lr_saved = __builtin_return_address(0);
164*aca3beaaSApple OSS Distributions 
165*aca3beaaSApple OSS Distributions 	lck_rw_unlock_exclusive(lck);
166*aca3beaaSApple OSS Distributions 
167*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_history[pkt_mnglr_rw_nxt_unlck] =
168*aca3beaaSApple OSS Distributions 	    lr_saved;
169*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_nxt_unlck = (pkt_mnglr_rw_nxt_unlck + 1) % PKT_MNGLR_RW_LCK_MAX;
170*aca3beaaSApple OSS Distributions }
171*aca3beaaSApple OSS Distributions 
172*aca3beaaSApple OSS Distributions static void
pkt_mnglr_rw_lock_shared(lck_rw_t * lck)173*aca3beaaSApple OSS Distributions pkt_mnglr_rw_lock_shared(lck_rw_t *lck)
174*aca3beaaSApple OSS Distributions {
175*aca3beaaSApple OSS Distributions 	void *lr_saved;
176*aca3beaaSApple OSS Distributions 
177*aca3beaaSApple OSS Distributions 	lr_saved = __builtin_return_address(0);
178*aca3beaaSApple OSS Distributions 
179*aca3beaaSApple OSS Distributions 	lck_rw_lock_shared(lck);
180*aca3beaaSApple OSS Distributions 
181*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_history[pkt_mnglr_rw_nxt_lck] = lr_saved;
182*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_nxt_lck = (pkt_mnglr_rw_nxt_lck + 1) % PKT_MNGLR_RW_LCK_MAX;
183*aca3beaaSApple OSS Distributions }
184*aca3beaaSApple OSS Distributions 
185*aca3beaaSApple OSS Distributions static void
pkt_mnglr_rw_unlock_shared(lck_rw_t * lck)186*aca3beaaSApple OSS Distributions pkt_mnglr_rw_unlock_shared(lck_rw_t *lck)
187*aca3beaaSApple OSS Distributions {
188*aca3beaaSApple OSS Distributions 	void *lr_saved;
189*aca3beaaSApple OSS Distributions 
190*aca3beaaSApple OSS Distributions 	lr_saved = __builtin_return_address(0);
191*aca3beaaSApple OSS Distributions 
192*aca3beaaSApple OSS Distributions 	lck_rw_unlock_shared(lck);
193*aca3beaaSApple OSS Distributions 
194*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_history[pkt_mnglr_rw_nxt_unlck] = lr_saved;
195*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_nxt_unlck = (pkt_mnglr_rw_nxt_unlck + 1) % PKT_MNGLR_RW_LCK_MAX;
196*aca3beaaSApple OSS Distributions }
197*aca3beaaSApple OSS Distributions 
198*aca3beaaSApple OSS Distributions /*
199*aca3beaaSApple OSS Distributions  * Packet Mangler's Kernel control socket callbacks
200*aca3beaaSApple OSS Distributions  */
201*aca3beaaSApple OSS Distributions static errno_t
pkt_mnglr_ctl_connect(kern_ctl_ref kctlref,struct sockaddr_ctl * sac,void ** unitinfo)202*aca3beaaSApple OSS Distributions pkt_mnglr_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
203*aca3beaaSApple OSS Distributions     void **unitinfo)
204*aca3beaaSApple OSS Distributions {
205*aca3beaaSApple OSS Distributions 	errno_t error = 0;
206*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr = NULL;
207*aca3beaaSApple OSS Distributions 
208*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_NOTICE, "Connecting packet mangler filter.");
209*aca3beaaSApple OSS Distributions 
210*aca3beaaSApple OSS Distributions 	if (sac->sc_unit == 0 || sac->sc_unit > MAX_PACKET_MANGLER) {
211*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "bad sc_unit %u", sac->sc_unit);
212*aca3beaaSApple OSS Distributions 		error = EINVAL;
213*aca3beaaSApple OSS Distributions 		goto fail;
214*aca3beaaSApple OSS Distributions 	}
215*aca3beaaSApple OSS Distributions 
216*aca3beaaSApple OSS Distributions 	p_pkt_mnglr = zalloc_flags(packet_mangler_zone,
217*aca3beaaSApple OSS Distributions 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
218*aca3beaaSApple OSS Distributions 
219*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
220*aca3beaaSApple OSS Distributions 
221*aca3beaaSApple OSS Distributions 	if (packet_manglers[sac->sc_unit - 1] != NULL) {
222*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "sc_unit %u in use", sac->sc_unit);
223*aca3beaaSApple OSS Distributions 		error = EADDRINUSE;
224*aca3beaaSApple OSS Distributions 		pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
225*aca3beaaSApple OSS Distributions 		goto fail_free;
226*aca3beaaSApple OSS Distributions 	} else {
227*aca3beaaSApple OSS Distributions 		/*
228*aca3beaaSApple OSS Distributions 		 * kernel control socket kcunit numbers start at 1
229*aca3beaaSApple OSS Distributions 		 */
230*aca3beaaSApple OSS Distributions 		packet_manglers[sac->sc_unit - 1] = p_pkt_mnglr;
231*aca3beaaSApple OSS Distributions 
232*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->pkt_mnglr_kcref = kctlref;
233*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->pkt_mnglr_kcunit = sac->sc_unit;
234*aca3beaaSApple OSS Distributions 
235*aca3beaaSApple OSS Distributions 		pkt_mnglr_active_count++;
236*aca3beaaSApple OSS Distributions 	}
237*aca3beaaSApple OSS Distributions 
238*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_ipfilter.cookie = p_pkt_mnglr;
239*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_ipfilter.name = "com.apple.pktmnglripfilter";
240*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_input = pktmnglr_ipfilter_input;
241*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_output = pktmnglr_ipfilter_output;
242*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_ipfilter.ipf_detach = pktmnglr_ipfilter_detach;
243*aca3beaaSApple OSS Distributions 	error = ipf_addv4(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfref));
244*aca3beaaSApple OSS Distributions 	if (error) {
245*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv4 Filter");
246*aca3beaaSApple OSS Distributions 		goto fail_locked;
247*aca3beaaSApple OSS Distributions 	}
248*aca3beaaSApple OSS Distributions 	error = ipf_addv6(&(p_pkt_mnglr->pkt_mnglr_ipfilter), &(p_pkt_mnglr->pkt_mnglr_ipfrefv6));
249*aca3beaaSApple OSS Distributions 	if (error) {
250*aca3beaaSApple OSS Distributions 		ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
251*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Could not register packet mangler's IPv6 Filter");
252*aca3beaaSApple OSS Distributions 		goto fail_locked;
253*aca3beaaSApple OSS Distributions 	}
254*aca3beaaSApple OSS Distributions 
255*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler's IP Filters");
256*aca3beaaSApple OSS Distributions 	p_pkt_mnglr->pkt_mnglr_flags |= PKT_MNGLR_FLG_IPFILTER_ATTACHED;
257*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
258*aca3beaaSApple OSS Distributions 
259*aca3beaaSApple OSS Distributions 	if (error) {
260*aca3beaaSApple OSS Distributions fail_locked:
261*aca3beaaSApple OSS Distributions 		pkt_mnglr_active_count--;
262*aca3beaaSApple OSS Distributions 
263*aca3beaaSApple OSS Distributions 		packet_manglers[sac->sc_unit - 1] = NULL;
264*aca3beaaSApple OSS Distributions 		*unitinfo = NULL;
265*aca3beaaSApple OSS Distributions 
266*aca3beaaSApple OSS Distributions 		pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
267*aca3beaaSApple OSS Distributions 
268*aca3beaaSApple OSS Distributions fail_free:
269*aca3beaaSApple OSS Distributions 		zfree(packet_mangler_zone, p_pkt_mnglr);
270*aca3beaaSApple OSS Distributions 	}
271*aca3beaaSApple OSS Distributions 
272*aca3beaaSApple OSS Distributions fail:
273*aca3beaaSApple OSS Distributions 	*unitinfo = p_pkt_mnglr;
274*aca3beaaSApple OSS Distributions 
275*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
276*aca3beaaSApple OSS Distributions 	    error, pkt_mnglr_active_count, sac->sc_unit);
277*aca3beaaSApple OSS Distributions 
278*aca3beaaSApple OSS Distributions 	return error;
279*aca3beaaSApple OSS Distributions }
280*aca3beaaSApple OSS Distributions 
281*aca3beaaSApple OSS Distributions static errno_t
pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo)282*aca3beaaSApple OSS Distributions pkt_mnglr_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo)
283*aca3beaaSApple OSS Distributions {
284*aca3beaaSApple OSS Distributions #pragma unused(kctlref)
285*aca3beaaSApple OSS Distributions 	errno_t error = 0;
286*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr;
287*aca3beaaSApple OSS Distributions 
288*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "Disconnecting packet mangler kernel control");
289*aca3beaaSApple OSS Distributions 
290*aca3beaaSApple OSS Distributions 	if (unitinfo == NULL) {
291*aca3beaaSApple OSS Distributions 		goto done;
292*aca3beaaSApple OSS Distributions 	}
293*aca3beaaSApple OSS Distributions 
294*aca3beaaSApple OSS Distributions 	if (kcunit > MAX_PACKET_MANGLER) {
295*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
296*aca3beaaSApple OSS Distributions 		    kcunit, MAX_PACKET_MANGLER);
297*aca3beaaSApple OSS Distributions 		error = EINVAL;
298*aca3beaaSApple OSS Distributions 		goto done;
299*aca3beaaSApple OSS Distributions 	}
300*aca3beaaSApple OSS Distributions 
301*aca3beaaSApple OSS Distributions 	p_pkt_mnglr = (struct packet_mangler *)unitinfo;
302*aca3beaaSApple OSS Distributions 
303*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
304*aca3beaaSApple OSS Distributions 	if (packet_manglers[kcunit - 1] != p_pkt_mnglr || p_pkt_mnglr->pkt_mnglr_kcunit != kcunit) {
305*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "bad unit info %u",
306*aca3beaaSApple OSS Distributions 		    kcunit);
307*aca3beaaSApple OSS Distributions 		pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
308*aca3beaaSApple OSS Distributions 		goto done;
309*aca3beaaSApple OSS Distributions 	}
310*aca3beaaSApple OSS Distributions 
311*aca3beaaSApple OSS Distributions 	/*
312*aca3beaaSApple OSS Distributions 	 * Make filter inactive
313*aca3beaaSApple OSS Distributions 	 */
314*aca3beaaSApple OSS Distributions 	packet_manglers[kcunit - 1] = NULL;
315*aca3beaaSApple OSS Distributions 	pkt_mnglr_active_count--;
316*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->pkt_mnglr_flags & PKT_MNGLR_FLG_IPFILTER_ATTACHED) {
317*aca3beaaSApple OSS Distributions 		(void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfref);
318*aca3beaaSApple OSS Distributions 		(void) ipf_remove(p_pkt_mnglr->pkt_mnglr_ipfrefv6);
319*aca3beaaSApple OSS Distributions 	}
320*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
321*aca3beaaSApple OSS Distributions 	zfree(packet_mangler_zone, p_pkt_mnglr);
322*aca3beaaSApple OSS Distributions done:
323*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "return %d pkt_mnglr_active_count %u kcunit %u",
324*aca3beaaSApple OSS Distributions 	    error, pkt_mnglr_active_count, kcunit);
325*aca3beaaSApple OSS Distributions 
326*aca3beaaSApple OSS Distributions 	return error;
327*aca3beaaSApple OSS Distributions }
328*aca3beaaSApple OSS Distributions 
329*aca3beaaSApple OSS Distributions static errno_t
pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t * len)330*aca3beaaSApple OSS Distributions pkt_mnglr_ctl_getopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
331*aca3beaaSApple OSS Distributions     int opt, void *data, size_t *len)
332*aca3beaaSApple OSS Distributions {
333*aca3beaaSApple OSS Distributions #pragma unused(kctlref, opt)
334*aca3beaaSApple OSS Distributions 	errno_t error = 0;
335*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
336*aca3beaaSApple OSS Distributions 
337*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_NOTICE, "");
338*aca3beaaSApple OSS Distributions 
339*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_shared(&pkt_mnglr_lck_rw);
340*aca3beaaSApple OSS Distributions 
341*aca3beaaSApple OSS Distributions 	if (kcunit > MAX_PACKET_MANGLER) {
342*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
343*aca3beaaSApple OSS Distributions 		    kcunit, MAX_PACKET_MANGLER);
344*aca3beaaSApple OSS Distributions 		error = EINVAL;
345*aca3beaaSApple OSS Distributions 		goto done;
346*aca3beaaSApple OSS Distributions 	}
347*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
348*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
349*aca3beaaSApple OSS Distributions 		    kcunit);
350*aca3beaaSApple OSS Distributions 		error = EINVAL;
351*aca3beaaSApple OSS Distributions 		goto done;
352*aca3beaaSApple OSS Distributions 	}
353*aca3beaaSApple OSS Distributions 	switch (opt) {
354*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_PROTO_ACT_MASK:
355*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint32_t)) {
356*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
357*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
358*aca3beaaSApple OSS Distributions 			error = EINVAL;
359*aca3beaaSApple OSS Distributions 			goto done;
360*aca3beaaSApple OSS Distributions 		}
361*aca3beaaSApple OSS Distributions 
362*aca3beaaSApple OSS Distributions 		if (data != NULL) {
363*aca3beaaSApple OSS Distributions 			*(uint32_t *)data = p_pkt_mnglr->proto_action_mask;
364*aca3beaaSApple OSS Distributions 		}
365*aca3beaaSApple OSS Distributions 		break;
366*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_IP_ACT_MASK:
367*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint32_t)) {
368*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
369*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
370*aca3beaaSApple OSS Distributions 			error = EINVAL;
371*aca3beaaSApple OSS Distributions 			goto done;
372*aca3beaaSApple OSS Distributions 		}
373*aca3beaaSApple OSS Distributions 
374*aca3beaaSApple OSS Distributions 		if (data != NULL) {
375*aca3beaaSApple OSS Distributions 			*(uint32_t *)data = p_pkt_mnglr->ip_action_mask;
376*aca3beaaSApple OSS Distributions 		}
377*aca3beaaSApple OSS Distributions 		break;
378*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_LOCAL_IP:
379*aca3beaaSApple OSS Distributions 		if (*len < sizeof(struct sockaddr_storage)) {
380*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
381*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
382*aca3beaaSApple OSS Distributions 			error = EINVAL;
383*aca3beaaSApple OSS Distributions 			goto done;
384*aca3beaaSApple OSS Distributions 		}
385*aca3beaaSApple OSS Distributions 
386*aca3beaaSApple OSS Distributions 		if (data != NULL) {
387*aca3beaaSApple OSS Distributions 			*(struct sockaddr_storage *)data = p_pkt_mnglr->lsaddr;
388*aca3beaaSApple OSS Distributions 		}
389*aca3beaaSApple OSS Distributions 		break;
390*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_REMOTE_IP:
391*aca3beaaSApple OSS Distributions 		if (*len < sizeof(struct sockaddr_storage)) {
392*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
393*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
394*aca3beaaSApple OSS Distributions 			error = EINVAL;
395*aca3beaaSApple OSS Distributions 			goto done;
396*aca3beaaSApple OSS Distributions 		}
397*aca3beaaSApple OSS Distributions 
398*aca3beaaSApple OSS Distributions 		if (data != NULL) {
399*aca3beaaSApple OSS Distributions 			*(struct sockaddr_storage *)data = p_pkt_mnglr->rsaddr;
400*aca3beaaSApple OSS Distributions 		}
401*aca3beaaSApple OSS Distributions 		break;
402*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_LOCAL_PORT:
403*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint16_t)) {
404*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
405*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
406*aca3beaaSApple OSS Distributions 			error = EINVAL;
407*aca3beaaSApple OSS Distributions 			goto done;
408*aca3beaaSApple OSS Distributions 		}
409*aca3beaaSApple OSS Distributions 
410*aca3beaaSApple OSS Distributions 		if (data != NULL) {
411*aca3beaaSApple OSS Distributions 			*(uint16_t *)data = p_pkt_mnglr->lport;
412*aca3beaaSApple OSS Distributions 		}
413*aca3beaaSApple OSS Distributions 		break;
414*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_REMOTE_PORT:
415*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint16_t)) {
416*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
417*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
418*aca3beaaSApple OSS Distributions 			error = EINVAL;
419*aca3beaaSApple OSS Distributions 			goto done;
420*aca3beaaSApple OSS Distributions 		}
421*aca3beaaSApple OSS Distributions 
422*aca3beaaSApple OSS Distributions 		if (data != NULL) {
423*aca3beaaSApple OSS Distributions 			*(uint16_t *)data = p_pkt_mnglr->rport;
424*aca3beaaSApple OSS Distributions 		}
425*aca3beaaSApple OSS Distributions 		break;
426*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_DIRECTION:
427*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint32_t)) {
428*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
429*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
430*aca3beaaSApple OSS Distributions 			error = EINVAL;
431*aca3beaaSApple OSS Distributions 			goto done;
432*aca3beaaSApple OSS Distributions 		}
433*aca3beaaSApple OSS Distributions 		if (data != NULL) {
434*aca3beaaSApple OSS Distributions 			*(uint32_t *)data = p_pkt_mnglr->dir;
435*aca3beaaSApple OSS Distributions 		}
436*aca3beaaSApple OSS Distributions 		break;
437*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_PROTOCOL:
438*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint32_t)) {
439*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
440*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
441*aca3beaaSApple OSS Distributions 			error = EINVAL;
442*aca3beaaSApple OSS Distributions 			goto done;
443*aca3beaaSApple OSS Distributions 		}
444*aca3beaaSApple OSS Distributions 		if (data != NULL) {
445*aca3beaaSApple OSS Distributions 			*(uint32_t *)data = p_pkt_mnglr->proto;
446*aca3beaaSApple OSS Distributions 		}
447*aca3beaaSApple OSS Distributions 		break;
448*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_ACTIVATE:
449*aca3beaaSApple OSS Distributions 		if (*len < sizeof(uint8_t)) {
450*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
451*aca3beaaSApple OSS Distributions 			    "len too small %lu", *len);
452*aca3beaaSApple OSS Distributions 			error = EINVAL;
453*aca3beaaSApple OSS Distributions 			goto done;
454*aca3beaaSApple OSS Distributions 		}
455*aca3beaaSApple OSS Distributions 
456*aca3beaaSApple OSS Distributions 		if (data != NULL) {
457*aca3beaaSApple OSS Distributions 			*(uint8_t *)data = p_pkt_mnglr->activate;
458*aca3beaaSApple OSS Distributions 		}
459*aca3beaaSApple OSS Distributions 		break;
460*aca3beaaSApple OSS Distributions 	default:
461*aca3beaaSApple OSS Distributions 		error = ENOPROTOOPT;
462*aca3beaaSApple OSS Distributions 		break;
463*aca3beaaSApple OSS Distributions 	}
464*aca3beaaSApple OSS Distributions done:
465*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_shared(&pkt_mnglr_lck_rw);
466*aca3beaaSApple OSS Distributions 
467*aca3beaaSApple OSS Distributions 	return error;
468*aca3beaaSApple OSS Distributions }
469*aca3beaaSApple OSS Distributions 
470*aca3beaaSApple OSS Distributions static errno_t
pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref,u_int32_t kcunit,void * unitinfo,int opt,void * data,size_t len)471*aca3beaaSApple OSS Distributions pkt_mnglr_ctl_setopt(kern_ctl_ref kctlref, u_int32_t kcunit, void *unitinfo,
472*aca3beaaSApple OSS Distributions     int opt, void *data, size_t len)
473*aca3beaaSApple OSS Distributions {
474*aca3beaaSApple OSS Distributions #pragma unused(kctlref, opt)
475*aca3beaaSApple OSS Distributions 	errno_t error = 0;
476*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)unitinfo;
477*aca3beaaSApple OSS Distributions 
478*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_NOTICE, "");
479*aca3beaaSApple OSS Distributions 
480*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_lock_exclusive(&pkt_mnglr_lck_rw);
481*aca3beaaSApple OSS Distributions 
482*aca3beaaSApple OSS Distributions 	if (kcunit > MAX_PACKET_MANGLER) {
483*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "kcunit %u > MAX_PACKET_MANGLER (%d)",
484*aca3beaaSApple OSS Distributions 		    kcunit, MAX_PACKET_MANGLER);
485*aca3beaaSApple OSS Distributions 		error = EINVAL;
486*aca3beaaSApple OSS Distributions 		goto done;
487*aca3beaaSApple OSS Distributions 	}
488*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr != (void *)packet_manglers[kcunit - 1]) {
489*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "unitinfo does not match for kcunit %u",
490*aca3beaaSApple OSS Distributions 		    kcunit);
491*aca3beaaSApple OSS Distributions 		error = EINVAL;
492*aca3beaaSApple OSS Distributions 		goto done;
493*aca3beaaSApple OSS Distributions 	}
494*aca3beaaSApple OSS Distributions 	switch (opt) {
495*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_PROTO_ACT_MASK:
496*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint32_t)) {
497*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
498*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
499*aca3beaaSApple OSS Distributions 			error = EINVAL;
500*aca3beaaSApple OSS Distributions 			goto done;
501*aca3beaaSApple OSS Distributions 		}
502*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->proto_action_mask != 0) {
503*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTO_ACT_MASK "
504*aca3beaaSApple OSS Distributions 			    "already set %u",
505*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->proto_action_mask);
506*aca3beaaSApple OSS Distributions 			error = EINVAL;
507*aca3beaaSApple OSS Distributions 			goto done;
508*aca3beaaSApple OSS Distributions 		}
509*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->proto_action_mask = *(uint32_t *)data;
510*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr->proto_action_mask set to :%d", p_pkt_mnglr->proto_action_mask);
511*aca3beaaSApple OSS Distributions 		break;
512*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_IP_ACT_MASK:
513*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint32_t)) {
514*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
515*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
516*aca3beaaSApple OSS Distributions 			error = EINVAL;
517*aca3beaaSApple OSS Distributions 			goto done;
518*aca3beaaSApple OSS Distributions 		}
519*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->ip_action_mask != 0) {
520*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_IP_ACT_MASK "
521*aca3beaaSApple OSS Distributions 			    "already set %u",
522*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->ip_action_mask);
523*aca3beaaSApple OSS Distributions 			error = EINVAL;
524*aca3beaaSApple OSS Distributions 			goto done;
525*aca3beaaSApple OSS Distributions 		}
526*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->ip_action_mask = *(uint32_t *)data;
527*aca3beaaSApple OSS Distributions 		break;
528*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_LOCAL_IP:
529*aca3beaaSApple OSS Distributions 		if (len < sizeof(struct sockaddr_storage)) {
530*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
531*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
532*aca3beaaSApple OSS Distributions 			error = EINVAL;
533*aca3beaaSApple OSS Distributions 			goto done;
534*aca3beaaSApple OSS Distributions 		}
535*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->lsaddr.ss_family) {
536*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_IP "
537*aca3beaaSApple OSS Distributions 			    "already set");
538*aca3beaaSApple OSS Distributions 			error = EINVAL;
539*aca3beaaSApple OSS Distributions 			goto done;
540*aca3beaaSApple OSS Distributions 		}
541*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->lsaddr = *(struct sockaddr_storage *)data;
542*aca3beaaSApple OSS Distributions 		break;
543*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_REMOTE_IP:
544*aca3beaaSApple OSS Distributions 		if (len < sizeof(struct sockaddr_storage)) {
545*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
546*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
547*aca3beaaSApple OSS Distributions 			error = EINVAL;
548*aca3beaaSApple OSS Distributions 			goto done;
549*aca3beaaSApple OSS Distributions 		}
550*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->rsaddr.ss_family) {
551*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_IP "
552*aca3beaaSApple OSS Distributions 			    "already set");
553*aca3beaaSApple OSS Distributions 			error = EINVAL;
554*aca3beaaSApple OSS Distributions 			goto done;
555*aca3beaaSApple OSS Distributions 		}
556*aca3beaaSApple OSS Distributions 
557*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->rsaddr = *(struct sockaddr_storage *)data;
558*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO,
559*aca3beaaSApple OSS Distributions 		    "Remote IP registered for address family: %d",
560*aca3beaaSApple OSS Distributions 		    p_pkt_mnglr->rsaddr.ss_family);
561*aca3beaaSApple OSS Distributions 		break;
562*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_LOCAL_PORT:
563*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint16_t)) {
564*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
565*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
566*aca3beaaSApple OSS Distributions 			error = EINVAL;
567*aca3beaaSApple OSS Distributions 			goto done;
568*aca3beaaSApple OSS Distributions 		}
569*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->lport != 0) {
570*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_LOCAL_PORT "
571*aca3beaaSApple OSS Distributions 			    "already set %d",
572*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->lport);
573*aca3beaaSApple OSS Distributions 			error = EINVAL;
574*aca3beaaSApple OSS Distributions 			goto done;
575*aca3beaaSApple OSS Distributions 		}
576*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->lport = *(uint16_t *)data;
577*aca3beaaSApple OSS Distributions 		break;
578*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_REMOTE_PORT:
579*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint16_t)) {
580*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
581*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
582*aca3beaaSApple OSS Distributions 			error = EINVAL;
583*aca3beaaSApple OSS Distributions 			goto done;
584*aca3beaaSApple OSS Distributions 		}
585*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->rport != 0) {
586*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_REMOTE_PORT "
587*aca3beaaSApple OSS Distributions 			    "already set %d",
588*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->rport);
589*aca3beaaSApple OSS Distributions 			error = EINVAL;
590*aca3beaaSApple OSS Distributions 			goto done;
591*aca3beaaSApple OSS Distributions 		}
592*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->rport = *(uint16_t *)data;
593*aca3beaaSApple OSS Distributions 		break;
594*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_DIRECTION:
595*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint32_t)) {
596*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
597*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
598*aca3beaaSApple OSS Distributions 			error = EINVAL;
599*aca3beaaSApple OSS Distributions 			goto done;
600*aca3beaaSApple OSS Distributions 		}
601*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->dir != 0) {
602*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_DIRECTION "
603*aca3beaaSApple OSS Distributions 			    "already set %u",
604*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->dir);
605*aca3beaaSApple OSS Distributions 			error = EINVAL;
606*aca3beaaSApple OSS Distributions 			goto done;
607*aca3beaaSApple OSS Distributions 		}
608*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->dir = *(uint32_t *)data;
609*aca3beaaSApple OSS Distributions 		break;
610*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_PROTOCOL:
611*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint32_t)) {
612*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
613*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
614*aca3beaaSApple OSS Distributions 			error = EINVAL;
615*aca3beaaSApple OSS Distributions 			goto done;
616*aca3beaaSApple OSS Distributions 		}
617*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->proto != 0) {
618*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_PROTOCOL "
619*aca3beaaSApple OSS Distributions 			    "already set %u",
620*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->proto);
621*aca3beaaSApple OSS Distributions 			error = EINVAL;
622*aca3beaaSApple OSS Distributions 			goto done;
623*aca3beaaSApple OSS Distributions 		}
624*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->proto = *(uint32_t *)data;
625*aca3beaaSApple OSS Distributions 		break;
626*aca3beaaSApple OSS Distributions 	case PKT_MNGLR_OPT_ACTIVATE:
627*aca3beaaSApple OSS Distributions 		if (len < sizeof(uint8_t)) {
628*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
629*aca3beaaSApple OSS Distributions 			    "len too small %lu", len);
630*aca3beaaSApple OSS Distributions 			error = EINVAL;
631*aca3beaaSApple OSS Distributions 			goto done;
632*aca3beaaSApple OSS Distributions 		}
633*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->activate != 0) {
634*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "PKT_MNGLR_OPT_ACTIVATE "
635*aca3beaaSApple OSS Distributions 			    "already set %u",
636*aca3beaaSApple OSS Distributions 			    p_pkt_mnglr->activate);
637*aca3beaaSApple OSS Distributions 			error = EINVAL;
638*aca3beaaSApple OSS Distributions 			goto done;
639*aca3beaaSApple OSS Distributions 		}
640*aca3beaaSApple OSS Distributions 		p_pkt_mnglr->activate = *(uint8_t *)data;
641*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr->activate set to :%d",
642*aca3beaaSApple OSS Distributions 		    p_pkt_mnglr->activate);
643*aca3beaaSApple OSS Distributions 		break;
644*aca3beaaSApple OSS Distributions 	default:
645*aca3beaaSApple OSS Distributions 		error = ENOPROTOOPT;
646*aca3beaaSApple OSS Distributions 		break;
647*aca3beaaSApple OSS Distributions 	}
648*aca3beaaSApple OSS Distributions done:
649*aca3beaaSApple OSS Distributions 	pkt_mnglr_rw_unlock_exclusive(&pkt_mnglr_lck_rw);
650*aca3beaaSApple OSS Distributions 
651*aca3beaaSApple OSS Distributions 	return error;
652*aca3beaaSApple OSS Distributions }
653*aca3beaaSApple OSS Distributions 
654*aca3beaaSApple OSS Distributions void
pkt_mnglr_init(void)655*aca3beaaSApple OSS Distributions pkt_mnglr_init(void)
656*aca3beaaSApple OSS Distributions {
657*aca3beaaSApple OSS Distributions 	struct kern_ctl_reg kern_ctl;
658*aca3beaaSApple OSS Distributions 	errno_t error = 0;
659*aca3beaaSApple OSS Distributions 
660*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_NOTICE, "");
661*aca3beaaSApple OSS Distributions 
662*aca3beaaSApple OSS Distributions 	/*
663*aca3beaaSApple OSS Distributions 	 * Compile time verifications
664*aca3beaaSApple OSS Distributions 	 */
665*aca3beaaSApple OSS Distributions 	_CASSERT(PKT_MNGLR_MAX_FILTER_COUNT == MAX_PACKET_MANGLER);
666*aca3beaaSApple OSS Distributions 
667*aca3beaaSApple OSS Distributions 	/*
668*aca3beaaSApple OSS Distributions 	 * Register kernel control
669*aca3beaaSApple OSS Distributions 	 */
670*aca3beaaSApple OSS Distributions 	bzero(&kern_ctl, sizeof(kern_ctl));
671*aca3beaaSApple OSS Distributions 	strlcpy(kern_ctl.ctl_name, PACKET_MANGLER_CONTROL_NAME,
672*aca3beaaSApple OSS Distributions 	    sizeof(kern_ctl.ctl_name));
673*aca3beaaSApple OSS Distributions 	kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED | CTL_FLAG_REG_EXTENDED;
674*aca3beaaSApple OSS Distributions 	kern_ctl.ctl_connect = pkt_mnglr_ctl_connect;
675*aca3beaaSApple OSS Distributions 	kern_ctl.ctl_disconnect = pkt_mnglr_ctl_disconnect;
676*aca3beaaSApple OSS Distributions 	kern_ctl.ctl_getopt = pkt_mnglr_ctl_getopt;
677*aca3beaaSApple OSS Distributions 	kern_ctl.ctl_setopt = pkt_mnglr_ctl_setopt;
678*aca3beaaSApple OSS Distributions 	error = ctl_register(&kern_ctl, &pkt_mnglr_kctlref);
679*aca3beaaSApple OSS Distributions 	if (error != 0) {
680*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "ctl_register failed: %d", error);
681*aca3beaaSApple OSS Distributions 	} else {
682*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "Registered packet mangler kernel control.");
683*aca3beaaSApple OSS Distributions 	}
684*aca3beaaSApple OSS Distributions }
685*aca3beaaSApple OSS Distributions 
686*aca3beaaSApple OSS Distributions static errno_t
pktmnglr_ipfilter_output(void * cookie,mbuf_t * data,ipf_pktopts_t options)687*aca3beaaSApple OSS Distributions pktmnglr_ipfilter_output(void *cookie, mbuf_t *data, ipf_pktopts_t options)
688*aca3beaaSApple OSS Distributions {
689*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
690*aca3beaaSApple OSS Distributions 	struct ip ip;
691*aca3beaaSApple OSS Distributions 	struct tcphdr tcp;
692*aca3beaaSApple OSS Distributions 	int optlen = 0;
693*aca3beaaSApple OSS Distributions 	errno_t error = 0;
694*aca3beaaSApple OSS Distributions 
695*aca3beaaSApple OSS Distributions #pragma unused(tcp, optlen, options)
696*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr == NULL) {
697*aca3beaaSApple OSS Distributions 		goto output_done;
698*aca3beaaSApple OSS Distributions 	}
699*aca3beaaSApple OSS Distributions 
700*aca3beaaSApple OSS Distributions 	if (!p_pkt_mnglr->activate) {
701*aca3beaaSApple OSS Distributions 		goto output_done;
702*aca3beaaSApple OSS Distributions 	}
703*aca3beaaSApple OSS Distributions 
704*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->dir == IN) {
705*aca3beaaSApple OSS Distributions 		goto output_done;
706*aca3beaaSApple OSS Distributions 	}
707*aca3beaaSApple OSS Distributions 
708*aca3beaaSApple OSS Distributions 	if (data == NULL) {
709*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
710*aca3beaaSApple OSS Distributions 		goto output_done;
711*aca3beaaSApple OSS Distributions 	}
712*aca3beaaSApple OSS Distributions 
713*aca3beaaSApple OSS Distributions 	/* Check for IP filter options */
714*aca3beaaSApple OSS Distributions 	error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
715*aca3beaaSApple OSS Distributions 	if (error) {
716*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
717*aca3beaaSApple OSS Distributions 		goto output_done;
718*aca3beaaSApple OSS Distributions 	}
719*aca3beaaSApple OSS Distributions 
720*aca3beaaSApple OSS Distributions 	if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
721*aca3beaaSApple OSS Distributions 		goto output_done;
722*aca3beaaSApple OSS Distributions 	}
723*aca3beaaSApple OSS Distributions 
724*aca3beaaSApple OSS Distributions 	if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
725*aca3beaaSApple OSS Distributions 		goto output_done;
726*aca3beaaSApple OSS Distributions 	}
727*aca3beaaSApple OSS Distributions 
728*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
729*aca3beaaSApple OSS Distributions 		struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
730*aca3beaaSApple OSS Distributions 		if (ip.ip_src.s_addr != laddr.sin_addr.s_addr) {
731*aca3beaaSApple OSS Distributions 			goto output_done;
732*aca3beaaSApple OSS Distributions 		}
733*aca3beaaSApple OSS Distributions 	}
734*aca3beaaSApple OSS Distributions 
735*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
736*aca3beaaSApple OSS Distributions 		struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
737*aca3beaaSApple OSS Distributions 		if (ip.ip_dst.s_addr != raddr.sin_addr.s_addr) {
738*aca3beaaSApple OSS Distributions 			goto output_done;
739*aca3beaaSApple OSS Distributions 		}
740*aca3beaaSApple OSS Distributions 	}
741*aca3beaaSApple OSS Distributions 
742*aca3beaaSApple OSS Distributions 	if (ip.ip_v != 4) {
743*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO,
744*aca3beaaSApple OSS Distributions 		    "%s:%d Not handling IP version %d\n",
745*aca3beaaSApple OSS Distributions 		    __func__, __LINE__, ip.ip_v);
746*aca3beaaSApple OSS Distributions 		goto output_done;
747*aca3beaaSApple OSS Distributions 	}
748*aca3beaaSApple OSS Distributions 
749*aca3beaaSApple OSS Distributions output_done:
750*aca3beaaSApple OSS Distributions 	/* Not handling output flow */
751*aca3beaaSApple OSS Distributions 	return 0;
752*aca3beaaSApple OSS Distributions }
753*aca3beaaSApple OSS Distributions 
754*aca3beaaSApple OSS Distributions #define TCP_MAX_OPTLEN  40
755*aca3beaaSApple OSS Distributions 
756*aca3beaaSApple OSS Distributions static errno_t
pktmnglr_ipfilter_input(void * cookie,mbuf_t * data,int offset,u_int8_t protocol)757*aca3beaaSApple OSS Distributions pktmnglr_ipfilter_input(void *cookie, mbuf_t *data, int offset, u_int8_t protocol)
758*aca3beaaSApple OSS Distributions {
759*aca3beaaSApple OSS Distributions 	struct packet_mangler *p_pkt_mnglr = (struct packet_mangler *)cookie;
760*aca3beaaSApple OSS Distributions 	struct ip6_hdr ip6;
761*aca3beaaSApple OSS Distributions 	struct ip ip;
762*aca3beaaSApple OSS Distributions 	struct tcphdr tcp;
763*aca3beaaSApple OSS Distributions 	size_t ip_pld_len;
764*aca3beaaSApple OSS Distributions 	errno_t error = 0;
765*aca3beaaSApple OSS Distributions 
766*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr == NULL) {
767*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "p_pkt_mnglr is NULL");
768*aca3beaaSApple OSS Distributions 		goto input_done;
769*aca3beaaSApple OSS Distributions 	}
770*aca3beaaSApple OSS Distributions 
771*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->activate == 0) {
772*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "p_pkt_mnglr not yet activated");
773*aca3beaaSApple OSS Distributions 		goto input_done;
774*aca3beaaSApple OSS Distributions 	}
775*aca3beaaSApple OSS Distributions 
776*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->dir == OUT) {
777*aca3beaaSApple OSS Distributions 		goto input_done;
778*aca3beaaSApple OSS Distributions 	}
779*aca3beaaSApple OSS Distributions 
780*aca3beaaSApple OSS Distributions 	if (data == NULL) {
781*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Data pointer is NULL");
782*aca3beaaSApple OSS Distributions 		goto input_done;
783*aca3beaaSApple OSS Distributions 	}
784*aca3beaaSApple OSS Distributions 
785*aca3beaaSApple OSS Distributions 	/* Check for IP filter options */
786*aca3beaaSApple OSS Distributions 	error = mbuf_copydata(*data, 0, sizeof(ip), &ip);
787*aca3beaaSApple OSS Distributions 	if (error) {
788*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_ERR, "Could not make local IP header copy");
789*aca3beaaSApple OSS Distributions 		goto input_done;
790*aca3beaaSApple OSS Distributions 	}
791*aca3beaaSApple OSS Distributions 
792*aca3beaaSApple OSS Distributions 	if (ip.ip_v == 6) {
793*aca3beaaSApple OSS Distributions 		error = mbuf_copydata(*data, 0, sizeof(ip6), &ip6);
794*aca3beaaSApple OSS Distributions 		if (error) {
795*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "Could not make local IPv6 header copy");
796*aca3beaaSApple OSS Distributions 			goto input_done;
797*aca3beaaSApple OSS Distributions 		}
798*aca3beaaSApple OSS Distributions 	}
799*aca3beaaSApple OSS Distributions 
800*aca3beaaSApple OSS Distributions 	if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET6) && (ip.ip_v == 4)) {
801*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family of packet is IPv4 but local "
802*aca3beaaSApple OSS Distributions 		    "address is set to IPv6");
803*aca3beaaSApple OSS Distributions 		goto input_done;
804*aca3beaaSApple OSS Distributions 	}
805*aca3beaaSApple OSS Distributions 
806*aca3beaaSApple OSS Distributions 	if ((p_pkt_mnglr->lsaddr.ss_family == AF_INET) && (ip.ip_v == 6)) {
807*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "Skipping filtering as address family "
808*aca3beaaSApple OSS Distributions 		    "of packet is IPv6 but local address is set to IPv4");
809*aca3beaaSApple OSS Distributions 		goto input_done;
810*aca3beaaSApple OSS Distributions 	}
811*aca3beaaSApple OSS Distributions 
812*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->lsaddr.ss_family == AF_INET) {
813*aca3beaaSApple OSS Distributions 		struct sockaddr_in laddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->lsaddr));
814*aca3beaaSApple OSS Distributions 		if (ip.ip_dst.s_addr != laddr.sin_addr.s_addr) {
815*aca3beaaSApple OSS Distributions 			goto input_done;
816*aca3beaaSApple OSS Distributions 		}
817*aca3beaaSApple OSS Distributions 	} else if (p_pkt_mnglr->lsaddr.ss_family == AF_INET6) {
818*aca3beaaSApple OSS Distributions 		struct sockaddr_in6 laddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->lsaddr));
819*aca3beaaSApple OSS Distributions 		if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_dst, &laddr.sin6_addr)) {
820*aca3beaaSApple OSS Distributions 			goto input_done;
821*aca3beaaSApple OSS Distributions 		}
822*aca3beaaSApple OSS Distributions 	}
823*aca3beaaSApple OSS Distributions 
824*aca3beaaSApple OSS Distributions 	if (p_pkt_mnglr->rsaddr.ss_family == AF_INET) {
825*aca3beaaSApple OSS Distributions 		struct sockaddr_in raddr = *(struct sockaddr_in *)(&(p_pkt_mnglr->rsaddr));
826*aca3beaaSApple OSS Distributions 		if (ip.ip_src.s_addr != raddr.sin_addr.s_addr) {
827*aca3beaaSApple OSS Distributions 			goto input_done;
828*aca3beaaSApple OSS Distributions 		}
829*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "Remote IP: %x Source IP: %x in input path",
830*aca3beaaSApple OSS Distributions 		    raddr.sin_addr.s_addr,
831*aca3beaaSApple OSS Distributions 		    ip.ip_src.s_addr);
832*aca3beaaSApple OSS Distributions 	} else if (p_pkt_mnglr->rsaddr.ss_family == AF_INET6) {
833*aca3beaaSApple OSS Distributions 		struct sockaddr_in6 raddr = *(struct sockaddr_in6 *)(&(p_pkt_mnglr->rsaddr));
834*aca3beaaSApple OSS Distributions 		if (!IN6_ARE_ADDR_EQUAL(&ip6.ip6_src, &raddr.sin6_addr)) {
835*aca3beaaSApple OSS Distributions 			goto input_done;
836*aca3beaaSApple OSS Distributions 		}
837*aca3beaaSApple OSS Distributions 	}
838*aca3beaaSApple OSS Distributions 
839*aca3beaaSApple OSS Distributions 	if (ip.ip_v == 4) {
840*aca3beaaSApple OSS Distributions 		ip_pld_len = ntohs(ip.ip_len) - (ip.ip_hl << 2);
841*aca3beaaSApple OSS Distributions 	} else if (ip.ip_v == 6) {
842*aca3beaaSApple OSS Distributions 		if (ip6.ip6_nxt != p_pkt_mnglr->proto) {
843*aca3beaaSApple OSS Distributions 			/* Don't support IPv6 extension headers */
844*aca3beaaSApple OSS Distributions 			goto input_done;
845*aca3beaaSApple OSS Distributions 		}
846*aca3beaaSApple OSS Distributions 		ip_pld_len = ntohs(ip6.ip6_plen);
847*aca3beaaSApple OSS Distributions 	} else {
848*aca3beaaSApple OSS Distributions 		goto input_done;
849*aca3beaaSApple OSS Distributions 	}
850*aca3beaaSApple OSS Distributions 
851*aca3beaaSApple OSS Distributions 
852*aca3beaaSApple OSS Distributions 	if (protocol != p_pkt_mnglr->proto) {
853*aca3beaaSApple OSS Distributions 		PKT_MNGLR_LOG(LOG_INFO, "Skip: Protocol mismatch");
854*aca3beaaSApple OSS Distributions 		goto input_done;
855*aca3beaaSApple OSS Distributions 	}
856*aca3beaaSApple OSS Distributions 
857*aca3beaaSApple OSS Distributions 	switch (protocol) {
858*aca3beaaSApple OSS Distributions 	case IPPROTO_TCP:
859*aca3beaaSApple OSS Distributions 		if (ip_pld_len < sizeof(tcp)) {
860*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "IP total len not big enough for TCP: %zu", ip_pld_len);
861*aca3beaaSApple OSS Distributions 			goto drop_it;
862*aca3beaaSApple OSS Distributions 		}
863*aca3beaaSApple OSS Distributions 
864*aca3beaaSApple OSS Distributions 		error = mbuf_copydata(*data, (size_t)offset, sizeof(tcp), &tcp);
865*aca3beaaSApple OSS Distributions 		if (error) {
866*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_ERR, "Could not make local TCP header copy");
867*aca3beaaSApple OSS Distributions 			goto input_done;
868*aca3beaaSApple OSS Distributions 		}
869*aca3beaaSApple OSS Distributions 
870*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->lport && (p_pkt_mnglr->lport != tcp.th_dport)) {
871*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_INFO, "Local port and IP des port do not match");
872*aca3beaaSApple OSS Distributions 			goto input_done;
873*aca3beaaSApple OSS Distributions 		}
874*aca3beaaSApple OSS Distributions 
875*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->rport && (p_pkt_mnglr->rport != tcp.th_sport)) {
876*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_INFO, "Remote port and IP src port do not match");
877*aca3beaaSApple OSS Distributions 			goto input_done;
878*aca3beaaSApple OSS Distributions 		}
879*aca3beaaSApple OSS Distributions 		break;
880*aca3beaaSApple OSS Distributions 	case IPPROTO_UDP:
881*aca3beaaSApple OSS Distributions 		goto input_done;
882*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMP:
883*aca3beaaSApple OSS Distributions 		goto input_done;
884*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMPV6:
885*aca3beaaSApple OSS Distributions 		goto input_done;
886*aca3beaaSApple OSS Distributions 	default:
887*aca3beaaSApple OSS Distributions 		goto input_done;
888*aca3beaaSApple OSS Distributions 	}
889*aca3beaaSApple OSS Distributions 
890*aca3beaaSApple OSS Distributions 	/* XXX Do IP actions here */
891*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "Proceeding with packet mangler actions on the packet");
892*aca3beaaSApple OSS Distributions 
893*aca3beaaSApple OSS Distributions 	/* Protocol actions */
894*aca3beaaSApple OSS Distributions 	switch (protocol) {
895*aca3beaaSApple OSS Distributions 	case IPPROTO_TCP:
896*aca3beaaSApple OSS Distributions 		if (p_pkt_mnglr->proto_action_mask) {
897*aca3beaaSApple OSS Distributions 			unsigned char tcp_opt_buf[TCP_MAX_OPTLEN] = {0};
898*aca3beaaSApple OSS Distributions 			size_t orig_tcp_optlen;
899*aca3beaaSApple OSS Distributions 			size_t tcp_optlen = 0;
900*aca3beaaSApple OSS Distributions 			size_t i = 0, off;
901*aca3beaaSApple OSS Distributions 
902*aca3beaaSApple OSS Distributions 			off = (tcp.th_off << 2);
903*aca3beaaSApple OSS Distributions 
904*aca3beaaSApple OSS Distributions 			if (off < sizeof(struct tcphdr) || off > ip_pld_len) {
905*aca3beaaSApple OSS Distributions 				PKT_MNGLR_LOG(LOG_ERR, "TCP header offset is wrong: %zu", off);
906*aca3beaaSApple OSS Distributions 				goto drop_it;
907*aca3beaaSApple OSS Distributions 			}
908*aca3beaaSApple OSS Distributions 
909*aca3beaaSApple OSS Distributions 			tcp_optlen = off - sizeof(struct tcphdr);
910*aca3beaaSApple OSS Distributions 
911*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_INFO, "Packet from F5 is TCP\n");
912*aca3beaaSApple OSS Distributions 			PKT_MNGLR_LOG(LOG_INFO, "Optlen: %zu\n", tcp_optlen);
913*aca3beaaSApple OSS Distributions 			orig_tcp_optlen = tcp_optlen;
914*aca3beaaSApple OSS Distributions 			if (orig_tcp_optlen) {
915*aca3beaaSApple OSS Distributions 				error = mbuf_copydata(*data, (size_t)offset + sizeof(struct tcphdr), orig_tcp_optlen, tcp_opt_buf);
916*aca3beaaSApple OSS Distributions 				if (error) {
917*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_ERR, "Failed to copy tcp options: error %d offset %d optlen %zu", error, offset, orig_tcp_optlen);
918*aca3beaaSApple OSS Distributions 					goto input_done;
919*aca3beaaSApple OSS Distributions 				}
920*aca3beaaSApple OSS Distributions 			}
921*aca3beaaSApple OSS Distributions 
922*aca3beaaSApple OSS Distributions 			while (tcp_optlen > 0) {
923*aca3beaaSApple OSS Distributions 				if (tcp_opt_buf[i] == 0x1) {
924*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_INFO, "Skipping NOP\n");
925*aca3beaaSApple OSS Distributions 					tcp_optlen--;
926*aca3beaaSApple OSS Distributions 					i++;
927*aca3beaaSApple OSS Distributions 					continue;
928*aca3beaaSApple OSS Distributions 				} else if ((tcp_opt_buf[i] != 0) && (tcp_opt_buf[i] != TCP_OPT_MULTIPATH_TCP)) {
929*aca3beaaSApple OSS Distributions 					unsigned char optlen;
930*aca3beaaSApple OSS Distributions 
931*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_INFO, "Skipping option %x\n", tcp_opt_buf[i]);
932*aca3beaaSApple OSS Distributions 
933*aca3beaaSApple OSS Distributions 					if (tcp_optlen < 2) {
934*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_ERR, "Received short TCP option");
935*aca3beaaSApple OSS Distributions 						goto drop_it;
936*aca3beaaSApple OSS Distributions 					}
937*aca3beaaSApple OSS Distributions 
938*aca3beaaSApple OSS Distributions 					/* Minimum TCP option size is 2 */
939*aca3beaaSApple OSS Distributions 					optlen = tcp_opt_buf[i + 1];
940*aca3beaaSApple OSS Distributions 					if (optlen < 2 || optlen > tcp_optlen) {
941*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_ERR, "Received suspicious TCP option");
942*aca3beaaSApple OSS Distributions 						goto drop_it;
943*aca3beaaSApple OSS Distributions 					}
944*aca3beaaSApple OSS Distributions 					tcp_optlen -= optlen;
945*aca3beaaSApple OSS Distributions 					i += optlen;
946*aca3beaaSApple OSS Distributions 					continue;
947*aca3beaaSApple OSS Distributions 				} else if (tcp_opt_buf[i] == TCP_OPT_MULTIPATH_TCP) {
948*aca3beaaSApple OSS Distributions 					size_t j = 0;
949*aca3beaaSApple OSS Distributions 					unsigned char mptcpoptlen;
950*aca3beaaSApple OSS Distributions 					uint8_t sbtver;
951*aca3beaaSApple OSS Distributions 					uint8_t subtype;
952*aca3beaaSApple OSS Distributions 
953*aca3beaaSApple OSS Distributions 					if (tcp_optlen < 3) {
954*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_ERR, "Received short MPTCP option");
955*aca3beaaSApple OSS Distributions 						goto drop_it;
956*aca3beaaSApple OSS Distributions 					}
957*aca3beaaSApple OSS Distributions 
958*aca3beaaSApple OSS Distributions 					/* Minimum MPTCP option size is 3 */
959*aca3beaaSApple OSS Distributions 					mptcpoptlen = tcp_opt_buf[i + 1];
960*aca3beaaSApple OSS Distributions 					if (mptcpoptlen < 3 || mptcpoptlen > tcp_optlen) {
961*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_ERR, "Received suspicious MPTCP option");
962*aca3beaaSApple OSS Distributions 						goto drop_it;
963*aca3beaaSApple OSS Distributions 					}
964*aca3beaaSApple OSS Distributions 
965*aca3beaaSApple OSS Distributions 					sbtver = tcp_opt_buf[i + MPTCP_SBT_VER_OFFSET];
966*aca3beaaSApple OSS Distributions 					subtype = sbtver >> 4;
967*aca3beaaSApple OSS Distributions 
968*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
969*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP subtype %x\n", subtype);
970*aca3beaaSApple OSS Distributions 					if (subtype == MPO_DSS) {
971*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_INFO, "Got DSS option\n");
972*aca3beaaSApple OSS Distributions 						PKT_MNGLR_LOG(LOG_INFO, "Protocol option mask: %d\n", p_pkt_mnglr->proto_action_mask);
973*aca3beaaSApple OSS Distributions 						if (p_pkt_mnglr->proto_action_mask &
974*aca3beaaSApple OSS Distributions 						    PKT_MNGLR_TCP_ACT_DSS_DROP) {
975*aca3beaaSApple OSS Distributions 							goto drop_it;
976*aca3beaaSApple OSS Distributions 						}
977*aca3beaaSApple OSS Distributions 					}
978*aca3beaaSApple OSS Distributions 
979*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_INFO, "Got MPTCP option %x\n", tcp_opt_buf[i]);
980*aca3beaaSApple OSS Distributions 					for (; j < mptcpoptlen && j < tcp_optlen; j++) {
981*aca3beaaSApple OSS Distributions 						if (p_pkt_mnglr->proto_action_mask &
982*aca3beaaSApple OSS Distributions 						    PKT_MNGLR_TCP_ACT_NOP_MPTCP) {
983*aca3beaaSApple OSS Distributions 							tcp_opt_buf[i + j] = 0x1;
984*aca3beaaSApple OSS Distributions 						}
985*aca3beaaSApple OSS Distributions 					}
986*aca3beaaSApple OSS Distributions 					tcp_optlen -= mptcpoptlen;
987*aca3beaaSApple OSS Distributions 					i += mptcpoptlen;
988*aca3beaaSApple OSS Distributions 				} else {
989*aca3beaaSApple OSS Distributions 					tcp_optlen--;
990*aca3beaaSApple OSS Distributions 					i++;
991*aca3beaaSApple OSS Distributions 				}
992*aca3beaaSApple OSS Distributions 			}
993*aca3beaaSApple OSS Distributions 
994*aca3beaaSApple OSS Distributions 			if (orig_tcp_optlen) {
995*aca3beaaSApple OSS Distributions 				error = mbuf_copyback(*data,
996*aca3beaaSApple OSS Distributions 				    (size_t)offset + sizeof(struct tcphdr),
997*aca3beaaSApple OSS Distributions 				    orig_tcp_optlen, tcp_opt_buf, MBUF_WAITOK);
998*aca3beaaSApple OSS Distributions 
999*aca3beaaSApple OSS Distributions 				if (error) {
1000*aca3beaaSApple OSS Distributions 					PKT_MNGLR_LOG(LOG_ERR,
1001*aca3beaaSApple OSS Distributions 					    "Failed to copy tcp options back: error %d offset %d optlen %zu",
1002*aca3beaaSApple OSS Distributions 					    error, offset, orig_tcp_optlen);
1003*aca3beaaSApple OSS Distributions 					goto input_done;
1004*aca3beaaSApple OSS Distributions 				}
1005*aca3beaaSApple OSS Distributions 			}
1006*aca3beaaSApple OSS Distributions 		}
1007*aca3beaaSApple OSS Distributions 		break;
1008*aca3beaaSApple OSS Distributions 	case IPPROTO_UDP:
1009*aca3beaaSApple OSS Distributions 		/* Don't handle UDP */
1010*aca3beaaSApple OSS Distributions 		break;
1011*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMP:
1012*aca3beaaSApple OSS Distributions 		break;
1013*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMPV6:
1014*aca3beaaSApple OSS Distributions 		break;
1015*aca3beaaSApple OSS Distributions 	default:
1016*aca3beaaSApple OSS Distributions 		break;
1017*aca3beaaSApple OSS Distributions 	}
1018*aca3beaaSApple OSS Distributions 	chksm_update(*data);
1019*aca3beaaSApple OSS Distributions input_done:
1020*aca3beaaSApple OSS Distributions 	return 0;
1021*aca3beaaSApple OSS Distributions 
1022*aca3beaaSApple OSS Distributions drop_it:
1023*aca3beaaSApple OSS Distributions 	PKT_MNGLR_LOG(LOG_INFO, "Dropping packet\n");
1024*aca3beaaSApple OSS Distributions 	mbuf_freem(*data);
1025*aca3beaaSApple OSS Distributions 	return EJUSTRETURN;
1026*aca3beaaSApple OSS Distributions }
1027*aca3beaaSApple OSS Distributions 
1028*aca3beaaSApple OSS Distributions static void
pktmnglr_ipfilter_detach(void * cookie)1029*aca3beaaSApple OSS Distributions pktmnglr_ipfilter_detach(void *cookie)
1030*aca3beaaSApple OSS Distributions {
1031*aca3beaaSApple OSS Distributions #pragma unused(cookie)
1032*aca3beaaSApple OSS Distributions 	return;
1033*aca3beaaSApple OSS Distributions }
1034*aca3beaaSApple OSS Distributions 
1035*aca3beaaSApple OSS Distributions /* XXX Still need to modify this to use mbuf_copy* macros */
1036*aca3beaaSApple OSS Distributions static void
chksm_update(mbuf_t data)1037*aca3beaaSApple OSS Distributions chksm_update(mbuf_t data)
1038*aca3beaaSApple OSS Distributions {
1039*aca3beaaSApple OSS Distributions 	u_int16_t ip_sum;
1040*aca3beaaSApple OSS Distributions 	u_int16_t tsum;
1041*aca3beaaSApple OSS Distributions 	struct tcphdr *tcp;
1042*aca3beaaSApple OSS Distributions 	errno_t err;
1043*aca3beaaSApple OSS Distributions 
1044*aca3beaaSApple OSS Distributions 	unsigned char *ptr = (unsigned char *)mbuf_data(data);
1045*aca3beaaSApple OSS Distributions 	struct ip *ip = (struct ip *)(void *)ptr;
1046*aca3beaaSApple OSS Distributions 	if (ip->ip_v != 4) {
1047*aca3beaaSApple OSS Distributions 		return;
1048*aca3beaaSApple OSS Distributions 	}
1049*aca3beaaSApple OSS Distributions 
1050*aca3beaaSApple OSS Distributions 	ip->ip_sum = 0;
1051*aca3beaaSApple OSS Distributions 	err = mbuf_inet_cksum(data, 0, 0, ip->ip_hl << 2, &ip_sum); // ip sum
1052*aca3beaaSApple OSS Distributions 	if (err == 0) {
1053*aca3beaaSApple OSS Distributions 		ip->ip_sum = ip_sum;
1054*aca3beaaSApple OSS Distributions 	}
1055*aca3beaaSApple OSS Distributions 	switch (ip->ip_p) {
1056*aca3beaaSApple OSS Distributions 	case IPPROTO_TCP:
1057*aca3beaaSApple OSS Distributions 		tcp = (struct tcphdr *)(void *)(ptr + (ip->ip_hl << 2));
1058*aca3beaaSApple OSS Distributions 		tcp->th_sum = 0;
1059*aca3beaaSApple OSS Distributions 		err = mbuf_inet_cksum(data, IPPROTO_TCP, ip->ip_hl << 2,
1060*aca3beaaSApple OSS Distributions 		        ntohs(ip->ip_len) - (ip->ip_hl << 2), &tsum);
1061*aca3beaaSApple OSS Distributions 		if (err == 0) {
1062*aca3beaaSApple OSS Distributions 			tcp->th_sum = tsum;
1063*aca3beaaSApple OSS Distributions 		}
1064*aca3beaaSApple OSS Distributions 		break;
1065*aca3beaaSApple OSS Distributions 	case IPPROTO_UDP:
1066*aca3beaaSApple OSS Distributions 		/* Don't handle UDP */
1067*aca3beaaSApple OSS Distributions 		break;
1068*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMP:
1069*aca3beaaSApple OSS Distributions 		break;
1070*aca3beaaSApple OSS Distributions 	case IPPROTO_ICMPV6:
1071*aca3beaaSApple OSS Distributions 		break;
1072*aca3beaaSApple OSS Distributions 	default:
1073*aca3beaaSApple OSS Distributions 		break;
1074*aca3beaaSApple OSS Distributions 	}
1075*aca3beaaSApple OSS Distributions 
1076*aca3beaaSApple OSS Distributions 	mbuf_clear_csum_performed(data);
1077*aca3beaaSApple OSS Distributions 	return;
1078*aca3beaaSApple OSS Distributions }
1079