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