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