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