]> git.saurik.com Git - apple/xnu.git/blob - bsd/net/if_ipsec.c
xnu-3789.41.3.tar.gz
[apple/xnu.git] / bsd / net / if_ipsec.c
1 /*
2 * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <sys/systm.h>
30 #include <sys/kern_control.h>
31 #include <net/kpi_protocol.h>
32 #include <net/kpi_interface.h>
33 #include <sys/socket.h>
34 #include <sys/socketvar.h>
35 #include <net/if.h>
36 #include <net/if_types.h>
37 #include <net/bpf.h>
38 #include <net/if_ipsec.h>
39 #include <sys/mbuf.h>
40 #include <sys/sockio.h>
41 #include <netinet/in.h>
42 #include <netinet/ip6.h>
43 #include <netinet6/in6_var.h>
44 #include <netinet6/ip6_var.h>
45 #include <sys/kauth.h>
46 #include <netinet6/ipsec.h>
47 #include <netinet6/ipsec6.h>
48 #include <netinet/ip.h>
49 #include <net/flowadv.h>
50 #include <net/necp.h>
51 #include <netkey/key.h>
52 #include <net/pktap.h>
53
54 extern int net_qos_policy_restricted;
55 extern int net_qos_policy_restrict_avapps;
56
57 /* Kernel Control functions */
58 static errno_t ipsec_ctl_connect(kern_ctl_ref kctlref, struct sockaddr_ctl *sac,
59 void **unitinfo);
60 static errno_t ipsec_ctl_disconnect(kern_ctl_ref kctlref, u_int32_t unit,
61 void *unitinfo);
62 static errno_t ipsec_ctl_send(kern_ctl_ref kctlref, u_int32_t unit,
63 void *unitinfo, mbuf_t m, int flags);
64 static errno_t ipsec_ctl_getopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
65 int opt, void *data, size_t *len);
66 static errno_t ipsec_ctl_setopt(kern_ctl_ref kctlref, u_int32_t unit, void *unitinfo,
67 int opt, void *data, size_t len);
68
69 /* Network Interface functions */
70 static void ipsec_start(ifnet_t interface);
71 static errno_t ipsec_output(ifnet_t interface, mbuf_t data);
72 static errno_t ipsec_demux(ifnet_t interface, mbuf_t data, char *frame_header,
73 protocol_family_t *protocol);
74 static errno_t ipsec_add_proto(ifnet_t interface, protocol_family_t protocol,
75 const struct ifnet_demux_desc *demux_array,
76 u_int32_t demux_count);
77 static errno_t ipsec_del_proto(ifnet_t interface, protocol_family_t protocol);
78 static errno_t ipsec_ioctl(ifnet_t interface, u_long cmd, void *data);
79 static void ipsec_detached(ifnet_t interface);
80
81 /* Protocol handlers */
82 static errno_t ipsec_attach_proto(ifnet_t interface, protocol_family_t proto);
83 static errno_t ipsec_proto_input(ifnet_t interface, protocol_family_t protocol,
84 mbuf_t m, char *frame_header);
85 static errno_t ipsec_proto_pre_output(ifnet_t interface, protocol_family_t protocol,
86 mbuf_t *packet, const struct sockaddr *dest, void *route,
87 char *frame_type, char *link_layer_dest);
88
89 static kern_ctl_ref ipsec_kctlref;
90 static u_int32_t ipsec_family;
91
92 #define IPSECQ_MAXLEN 256
93
94 errno_t
95 ipsec_register_control(void)
96 {
97 struct kern_ctl_reg kern_ctl;
98 errno_t result = 0;
99
100 /* Find a unique value for our interface family */
101 result = mbuf_tag_id_find(IPSEC_CONTROL_NAME, &ipsec_family);
102 if (result != 0) {
103 printf("ipsec_register_control - mbuf_tag_id_find_internal failed: %d\n", result);
104 return result;
105 }
106
107 bzero(&kern_ctl, sizeof(kern_ctl));
108 strlcpy(kern_ctl.ctl_name, IPSEC_CONTROL_NAME, sizeof(kern_ctl.ctl_name));
109 kern_ctl.ctl_name[sizeof(kern_ctl.ctl_name) - 1] = 0;
110 kern_ctl.ctl_flags = CTL_FLAG_PRIVILEGED; /* Require root */
111 kern_ctl.ctl_sendsize = 64 * 1024;
112 kern_ctl.ctl_recvsize = 64 * 1024;
113 kern_ctl.ctl_connect = ipsec_ctl_connect;
114 kern_ctl.ctl_disconnect = ipsec_ctl_disconnect;
115 kern_ctl.ctl_send = ipsec_ctl_send;
116 kern_ctl.ctl_setopt = ipsec_ctl_setopt;
117 kern_ctl.ctl_getopt = ipsec_ctl_getopt;
118
119 result = ctl_register(&kern_ctl, &ipsec_kctlref);
120 if (result != 0) {
121 printf("ipsec_register_control - ctl_register failed: %d\n", result);
122 return result;
123 }
124
125 /* Register the protocol plumbers */
126 if ((result = proto_register_plumber(PF_INET, ipsec_family,
127 ipsec_attach_proto, NULL)) != 0) {
128 printf("ipsec_register_control - proto_register_plumber(PF_INET, %d) failed: %d\n",
129 ipsec_family, result);
130 ctl_deregister(ipsec_kctlref);
131 return result;
132 }
133
134 /* Register the protocol plumbers */
135 if ((result = proto_register_plumber(PF_INET6, ipsec_family,
136 ipsec_attach_proto, NULL)) != 0) {
137 proto_unregister_plumber(PF_INET, ipsec_family);
138 ctl_deregister(ipsec_kctlref);
139 printf("ipsec_register_control - proto_register_plumber(PF_INET6, %d) failed: %d\n",
140 ipsec_family, result);
141 return result;
142 }
143
144 return 0;
145 }
146
147 /* Helpers */
148 int
149 ipsec_interface_isvalid (ifnet_t interface)
150 {
151 struct ipsec_pcb *pcb = NULL;
152
153 if (interface == NULL)
154 return 0;
155
156 pcb = ifnet_softc(interface);
157
158 if (pcb == NULL)
159 return 0;
160
161 /* When ctl disconnects, ipsec_unit is set to 0 */
162 if (pcb->ipsec_unit == 0)
163 return 0;
164
165 return 1;
166 }
167
168 /* Kernel control functions */
169
170 static errno_t
171 ipsec_ctl_connect(kern_ctl_ref kctlref,
172 struct sockaddr_ctl *sac,
173 void **unitinfo)
174 {
175 struct ifnet_init_eparams ipsec_init;
176 struct ipsec_pcb *pcb;
177 errno_t result;
178 struct ifnet_stats_param stats;
179
180 /* kernel control allocates, interface frees */
181 MALLOC(pcb, struct ipsec_pcb *, sizeof(*pcb), M_DEVBUF, M_WAITOK | M_ZERO);
182
183 /* Setup the protocol control block */
184 *unitinfo = pcb;
185 pcb->ipsec_ctlref = kctlref;
186 pcb->ipsec_unit = sac->sc_unit;
187 pcb->ipsec_output_service_class = MBUF_SC_OAM;
188
189 printf("ipsec_ctl_connect: creating interface ipsec%d\n", pcb->ipsec_unit - 1);
190
191 /* Create the interface */
192 bzero(&ipsec_init, sizeof(ipsec_init));
193 ipsec_init.ver = IFNET_INIT_CURRENT_VERSION;
194 ipsec_init.len = sizeof (ipsec_init);
195 ipsec_init.name = "ipsec";
196 ipsec_init.start = ipsec_start;
197 ipsec_init.unit = pcb->ipsec_unit - 1;
198 ipsec_init.family = ipsec_family;
199 ipsec_init.type = IFT_OTHER;
200 ipsec_init.demux = ipsec_demux;
201 ipsec_init.add_proto = ipsec_add_proto;
202 ipsec_init.del_proto = ipsec_del_proto;
203 ipsec_init.softc = pcb;
204 ipsec_init.ioctl = ipsec_ioctl;
205 ipsec_init.detach = ipsec_detached;
206
207 result = ifnet_allocate_extended(&ipsec_init, &pcb->ipsec_ifp);
208 if (result != 0) {
209 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result);
210 *unitinfo = NULL;
211 FREE(pcb, M_DEVBUF);
212 return result;
213 }
214
215 /* Set flags and additional information. */
216 ifnet_set_mtu(pcb->ipsec_ifp, 1500);
217 ifnet_set_flags(pcb->ipsec_ifp, IFF_UP | IFF_MULTICAST | IFF_POINTOPOINT, 0xffff);
218
219 /* The interface must generate its own IPv6 LinkLocal address,
220 * if possible following the recommendation of RFC2472 to the 64bit interface ID
221 */
222 ifnet_set_eflags(pcb->ipsec_ifp, IFEF_NOAUTOIPV6LL, IFEF_NOAUTOIPV6LL);
223
224 /* Reset the stats in case as the interface may have been recycled */
225 bzero(&stats, sizeof(struct ifnet_stats_param));
226 ifnet_set_stat(pcb->ipsec_ifp, &stats);
227
228 /* Attach the interface */
229 result = ifnet_attach(pcb->ipsec_ifp, NULL);
230 if (result != 0) {
231 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result);
232 ifnet_release(pcb->ipsec_ifp);
233 *unitinfo = NULL;
234 FREE(pcb, M_DEVBUF);
235 } else {
236 /* Attach to bpf */
237 bpfattach(pcb->ipsec_ifp, DLT_NULL, 4);
238
239 /* The interfaces resoures allocated, mark it as running */
240 ifnet_set_flags(pcb->ipsec_ifp, IFF_RUNNING, IFF_RUNNING);
241 }
242
243 return result;
244 }
245
246 static errno_t
247 ipsec_detach_ip(ifnet_t interface,
248 protocol_family_t protocol,
249 socket_t pf_socket)
250 {
251 errno_t result = EPROTONOSUPPORT;
252
253 /* Attempt a detach */
254 if (protocol == PF_INET) {
255 struct ifreq ifr;
256
257 bzero(&ifr, sizeof(ifr));
258 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
259 ifnet_name(interface), ifnet_unit(interface));
260
261 result = sock_ioctl(pf_socket, SIOCPROTODETACH, &ifr);
262 }
263 else if (protocol == PF_INET6) {
264 struct in6_ifreq ifr6;
265
266 bzero(&ifr6, sizeof(ifr6));
267 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
268 ifnet_name(interface), ifnet_unit(interface));
269
270 result = sock_ioctl(pf_socket, SIOCPROTODETACH_IN6, &ifr6);
271 }
272
273 return result;
274 }
275
276 static void
277 ipsec_remove_address(ifnet_t interface,
278 protocol_family_t protocol,
279 ifaddr_t address,
280 socket_t pf_socket)
281 {
282 errno_t result = 0;
283
284 /* Attempt a detach */
285 if (protocol == PF_INET) {
286 struct ifreq ifr;
287
288 bzero(&ifr, sizeof(ifr));
289 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d",
290 ifnet_name(interface), ifnet_unit(interface));
291 result = ifaddr_address(address, &ifr.ifr_addr, sizeof(ifr.ifr_addr));
292 if (result != 0) {
293 printf("ipsec_remove_address - ifaddr_address failed: %d", result);
294 }
295 else {
296 result = sock_ioctl(pf_socket, SIOCDIFADDR, &ifr);
297 if (result != 0) {
298 printf("ipsec_remove_address - SIOCDIFADDR failed: %d", result);
299 }
300 }
301 }
302 else if (protocol == PF_INET6) {
303 struct in6_ifreq ifr6;
304
305 bzero(&ifr6, sizeof(ifr6));
306 snprintf(ifr6.ifr_name, sizeof(ifr6.ifr_name), "%s%d",
307 ifnet_name(interface), ifnet_unit(interface));
308 result = ifaddr_address(address, (struct sockaddr*)&ifr6.ifr_addr,
309 sizeof(ifr6.ifr_addr));
310 if (result != 0) {
311 printf("ipsec_remove_address - ifaddr_address failed (v6): %d",
312 result);
313 }
314 else {
315 result = sock_ioctl(pf_socket, SIOCDIFADDR_IN6, &ifr6);
316 if (result != 0) {
317 printf("ipsec_remove_address - SIOCDIFADDR_IN6 failed: %d",
318 result);
319 }
320 }
321 }
322 }
323
324 static void
325 ipsec_cleanup_family(ifnet_t interface,
326 protocol_family_t protocol)
327 {
328 errno_t result = 0;
329 socket_t pf_socket = NULL;
330 ifaddr_t *addresses = NULL;
331 int i;
332
333 if (protocol != PF_INET && protocol != PF_INET6) {
334 printf("ipsec_cleanup_family - invalid protocol family %d\n", protocol);
335 return;
336 }
337
338 /* Create a socket for removing addresses and detaching the protocol */
339 result = sock_socket(protocol, SOCK_DGRAM, 0, NULL, NULL, &pf_socket);
340 if (result != 0) {
341 if (result != EAFNOSUPPORT)
342 printf("ipsec_cleanup_family - failed to create %s socket: %d\n",
343 protocol == PF_INET ? "IP" : "IPv6", result);
344 goto cleanup;
345 }
346
347 /* always set SS_PRIV, we want to close and detach regardless */
348 sock_setpriv(pf_socket, 1);
349
350 result = ipsec_detach_ip(interface, protocol, pf_socket);
351 if (result == 0 || result == ENXIO) {
352 /* We are done! We either detached or weren't attached. */
353 goto cleanup;
354 }
355 else if (result != EBUSY) {
356 /* Uh, not really sure what happened here... */
357 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result);
358 goto cleanup;
359 }
360
361 /*
362 * At this point, we received an EBUSY error. This means there are
363 * addresses attached. We should detach them and then try again.
364 */
365 result = ifnet_get_address_list_family(interface, &addresses, protocol);
366 if (result != 0) {
367 printf("fnet_get_address_list_family(%s%d, 0xblah, %s) - failed: %d\n",
368 ifnet_name(interface), ifnet_unit(interface),
369 protocol == PF_INET ? "PF_INET" : "PF_INET6", result);
370 goto cleanup;
371 }
372
373 for (i = 0; addresses[i] != 0; i++) {
374 ipsec_remove_address(interface, protocol, addresses[i], pf_socket);
375 }
376 ifnet_free_address_list(addresses);
377 addresses = NULL;
378
379 /*
380 * The addresses should be gone, we should try the remove again.
381 */
382 result = ipsec_detach_ip(interface, protocol, pf_socket);
383 if (result != 0 && result != ENXIO) {
384 printf("ipsec_cleanup_family - ipsec_detach_ip failed: %d\n", result);
385 }
386
387 cleanup:
388 if (pf_socket != NULL)
389 sock_close(pf_socket);
390
391 if (addresses != NULL)
392 ifnet_free_address_list(addresses);
393 }
394
395 static errno_t
396 ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref,
397 __unused u_int32_t unit,
398 void *unitinfo)
399 {
400 struct ipsec_pcb *pcb = unitinfo;
401 ifnet_t ifp = NULL;
402 errno_t result = 0;
403
404 if (pcb == NULL)
405 return EINVAL;
406
407 ifp = pcb->ipsec_ifp;
408 VERIFY(ifp != NULL);
409 pcb->ipsec_ctlref = NULL;
410 pcb->ipsec_unit = 0;
411
412 /*
413 * We want to do everything in our power to ensure that the interface
414 * really goes away when the socket is closed. We must remove IP/IPv6
415 * addresses and detach the protocols. Finally, we can remove and
416 * release the interface.
417 */
418 key_delsp_for_ipsec_if(ifp);
419
420 ipsec_cleanup_family(ifp, AF_INET);
421 ipsec_cleanup_family(ifp, AF_INET6);
422
423 if ((result = ifnet_detach(ifp)) != 0) {
424 printf("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result);
425 }
426
427 return 0;
428 }
429
430 static errno_t
431 ipsec_ctl_send(__unused kern_ctl_ref kctlref,
432 __unused u_int32_t unit,
433 __unused void *unitinfo,
434 mbuf_t m,
435 __unused int flags)
436 {
437 /* Receive messages from the control socket. Currently unused. */
438 mbuf_freem(m);
439 return 0;
440 }
441
442 static errno_t
443 ipsec_ctl_setopt(__unused kern_ctl_ref kctlref,
444 __unused u_int32_t unit,
445 void *unitinfo,
446 int opt,
447 void *data,
448 size_t len)
449 {
450 struct ipsec_pcb *pcb = unitinfo;
451 errno_t result = 0;
452
453 /* check for privileges for privileged options */
454 switch (opt) {
455 case IPSEC_OPT_FLAGS:
456 case IPSEC_OPT_EXT_IFDATA_STATS:
457 case IPSEC_OPT_SET_DELEGATE_INTERFACE:
458 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS:
459 if (kauth_cred_issuser(kauth_cred_get()) == 0) {
460 return EPERM;
461 }
462 break;
463 }
464
465 switch (opt) {
466 case IPSEC_OPT_FLAGS:
467 if (len != sizeof(u_int32_t))
468 result = EMSGSIZE;
469 else
470 pcb->ipsec_flags = *(u_int32_t *)data;
471 break;
472
473 case IPSEC_OPT_EXT_IFDATA_STATS:
474 if (len != sizeof(int)) {
475 result = EMSGSIZE;
476 break;
477 }
478 pcb->ipsec_ext_ifdata_stats = (*(int *)data) ? 1 : 0;
479 break;
480
481 case IPSEC_OPT_INC_IFDATA_STATS_IN:
482 case IPSEC_OPT_INC_IFDATA_STATS_OUT: {
483 struct ipsec_stats_param *utsp = (struct ipsec_stats_param *)data;
484
485 if (utsp == NULL || len < sizeof(struct ipsec_stats_param)) {
486 result = EINVAL;
487 break;
488 }
489 if (!pcb->ipsec_ext_ifdata_stats) {
490 result = EINVAL;
491 break;
492 }
493 if (opt == IPSEC_OPT_INC_IFDATA_STATS_IN)
494 ifnet_stat_increment_in(pcb->ipsec_ifp, utsp->utsp_packets,
495 utsp->utsp_bytes, utsp->utsp_errors);
496 else
497 ifnet_stat_increment_out(pcb->ipsec_ifp, utsp->utsp_packets,
498 utsp->utsp_bytes, utsp->utsp_errors);
499 break;
500 }
501
502 case IPSEC_OPT_SET_DELEGATE_INTERFACE: {
503 ifnet_t del_ifp = NULL;
504 char name[IFNAMSIZ];
505
506 if (len > IFNAMSIZ - 1) {
507 result = EMSGSIZE;
508 break;
509 }
510 if (len != 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
511 bcopy(data, name, len);
512 name[len] = 0;
513 result = ifnet_find_by_name(name, &del_ifp);
514 }
515 if (result == 0) {
516 printf("%s IPSEC_OPT_SET_DELEGATE_INTERFACE %s to %s\n",
517 __func__, pcb->ipsec_ifp->if_xname,
518 del_ifp->if_xname);
519
520 result = ifnet_set_delegate(pcb->ipsec_ifp, del_ifp);
521 if (del_ifp)
522 ifnet_release(del_ifp);
523 }
524 break;
525 }
526
527 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: {
528 if (len != sizeof(int)) {
529 result = EMSGSIZE;
530 break;
531 }
532 mbuf_svc_class_t output_service_class = so_tc2msc(*(int *)data);
533 if (output_service_class == MBUF_SC_UNSPEC) {
534 pcb->ipsec_output_service_class = MBUF_SC_OAM;
535 } else {
536 pcb->ipsec_output_service_class = output_service_class;
537 }
538 printf("%s IPSEC_OPT_OUTPUT_TRAFFIC_CLASS %s svc %d\n",
539 __func__, pcb->ipsec_ifp->if_xname,
540 pcb->ipsec_output_service_class);
541 break;
542 }
543
544 default:
545 result = ENOPROTOOPT;
546 break;
547 }
548
549 return result;
550 }
551
552 static errno_t
553 ipsec_ctl_getopt(__unused kern_ctl_ref kctlref,
554 __unused u_int32_t unit,
555 void *unitinfo,
556 int opt,
557 void *data,
558 size_t *len)
559 {
560 struct ipsec_pcb *pcb = unitinfo;
561 errno_t result = 0;
562
563 switch (opt) {
564 case IPSEC_OPT_FLAGS:
565 if (*len != sizeof(u_int32_t))
566 result = EMSGSIZE;
567 else
568 *(u_int32_t *)data = pcb->ipsec_flags;
569 break;
570
571 case IPSEC_OPT_EXT_IFDATA_STATS:
572 if (*len != sizeof(int))
573 result = EMSGSIZE;
574 else
575 *(int *)data = (pcb->ipsec_ext_ifdata_stats) ? 1 : 0;
576 break;
577
578 case IPSEC_OPT_IFNAME:
579 *len = snprintf(data, *len, "%s%d", ifnet_name(pcb->ipsec_ifp), ifnet_unit(pcb->ipsec_ifp)) + 1;
580 break;
581
582 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS: {
583 if (*len != sizeof(int)) {
584 result = EMSGSIZE;
585 break;
586 }
587 *(int *)data = so_svc2tc(pcb->ipsec_output_service_class);
588 break;
589 }
590 default:
591 result = ENOPROTOOPT;
592 break;
593 }
594
595 return result;
596 }
597
598 /* Network Interface functions */
599 static errno_t
600 ipsec_output(ifnet_t interface,
601 mbuf_t data)
602 {
603 struct ipsec_pcb *pcb = ifnet_softc(interface);
604 struct ipsec_output_state ipsec_state;
605 struct route ro;
606 struct route_in6 ro6;
607 int length;
608 struct ip *ip;
609 struct ip6_hdr *ip6;
610 struct ip_out_args ipoa;
611 struct ip6_out_args ip6oa;
612 int error = 0;
613 u_int ip_version = 0;
614 uint32_t af;
615 int flags = 0;
616 struct flowadv *adv = NULL;
617
618 // Make sure this packet isn't looping through the interface
619 if (necp_get_last_interface_index_from_packet(data) == interface->if_index) {
620 error = -1;
621 goto ipsec_output_err;
622 }
623
624 // Mark the interface so NECP can evaluate tunnel policy
625 necp_mark_packet_from_interface(data, interface);
626
627 ip = mtod(data, struct ip *);
628 ip_version = ip->ip_v;
629
630 switch (ip_version) {
631 case 4:
632 /* Tap */
633 af = AF_INET;
634 bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af));
635
636 /* Apply encryption */
637 bzero(&ipsec_state, sizeof(ipsec_state));
638 ipsec_state.m = data;
639 ipsec_state.dst = (struct sockaddr *)&ip->ip_dst;
640 bzero(&ipsec_state.ro, sizeof(ipsec_state.ro));
641
642 error = ipsec4_interface_output(&ipsec_state, interface);
643 /* Tunneled in IPv6 - packet is gone */
644 if (error == 0 && ipsec_state.tunneled == 6) {
645 goto done;
646 }
647
648 data = ipsec_state.m;
649 if (error || data == NULL) {
650 printf("ipsec_output: ipsec4_output error %d.\n", error);
651 goto ipsec_output_err;
652 }
653
654 /* Set traffic class, set flow */
655 m_set_service_class(data, pcb->ipsec_output_service_class);
656 data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
657 data->m_pkthdr.pkt_flowid = interface->if_flowhash;
658 data->m_pkthdr.pkt_proto = ip->ip_p;
659 data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
660
661 /* Flip endian-ness for ip_output */
662 ip = mtod(data, struct ip *);
663 NTOHS(ip->ip_len);
664 NTOHS(ip->ip_off);
665
666 /* Increment statistics */
667 length = mbuf_pkthdr_len(data);
668 ifnet_stat_increment_out(interface, 1, length, 0);
669
670 /* Send to ip_output */
671 bzero(&ro, sizeof(ro));
672
673 flags = IP_OUTARGS | /* Passing out args to specify interface */
674 IP_NOIPSEC; /* To ensure the packet doesn't go through ipsec twice */
675
676 bzero(&ipoa, sizeof(ipoa));
677 ipoa.ipoa_flowadv.code = 0;
678 ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR;
679 if (ipsec_state.outgoing_if) {
680 ipoa.ipoa_boundif = ipsec_state.outgoing_if;
681 ipoa.ipoa_flags |= IPOAF_BOUND_IF;
682 }
683 ipsec_set_ipoa_for_interface(pcb->ipsec_ifp, &ipoa);
684
685 adv = &ipoa.ipoa_flowadv;
686
687 (void) ip_output(data, NULL, &ro, flags, NULL, &ipoa);
688 data = NULL;
689
690 if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) {
691 error = ENOBUFS;
692 ifnet_disable_output(interface);
693 }
694
695 goto done;
696 case 6:
697 af = AF_INET6;
698 bpf_tap_out(pcb->ipsec_ifp, DLT_NULL, data, &af, sizeof(af));
699
700 data = ipsec6_splithdr(data);
701 if (data == NULL) {
702 printf("ipsec_output: ipsec6_splithdr returned NULL\n");
703 goto ipsec_output_err;
704 }
705
706 ip6 = mtod(data, struct ip6_hdr *);
707
708 bzero(&ipsec_state, sizeof(ipsec_state));
709 ipsec_state.m = data;
710 ipsec_state.dst = (struct sockaddr *)&ip6->ip6_dst;
711 bzero(&ipsec_state.ro, sizeof(ipsec_state.ro));
712
713 error = ipsec6_interface_output(&ipsec_state, interface, &ip6->ip6_nxt, ipsec_state.m);
714 if (error == 0 && ipsec_state.tunneled == 4) /* tunneled in IPv4 - packet is gone */
715 goto done;
716 data = ipsec_state.m;
717 if (error || data == NULL) {
718 printf("ipsec_output: ipsec6_output error %d.\n", error);
719 goto ipsec_output_err;
720 }
721
722 /* Set traffic class, set flow */
723 m_set_service_class(data, pcb->ipsec_output_service_class);
724 data->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
725 data->m_pkthdr.pkt_flowid = interface->if_flowhash;
726 data->m_pkthdr.pkt_proto = ip6->ip6_nxt;
727 data->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
728
729 /* Increment statistics */
730 length = mbuf_pkthdr_len(data);
731 ifnet_stat_increment_out(interface, 1, length, 0);
732
733 /* Send to ip6_output */
734 bzero(&ro6, sizeof(ro6));
735
736 flags = IPV6_OUTARGS;
737
738 bzero(&ip6oa, sizeof(ip6oa));
739 ip6oa.ip6oa_flowadv.code = 0;
740 ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR;
741 if (ipsec_state.outgoing_if) {
742 ip6oa.ip6oa_boundif = ipsec_state.outgoing_if;
743 ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF;
744 }
745 ipsec_set_ip6oa_for_interface(pcb->ipsec_ifp, &ip6oa);
746
747 adv = &ip6oa.ip6oa_flowadv;
748
749 (void) ip6_output(data, NULL, &ro6, flags, NULL, NULL, &ip6oa);
750 data = NULL;
751
752 if (adv->code == FADV_FLOW_CONTROLLED || adv->code == FADV_SUSPENDED) {
753 error = ENOBUFS;
754 ifnet_disable_output(interface);
755 }
756
757 goto done;
758 default:
759 printf("ipsec_output: Received unknown packet version %d.\n", ip_version);
760 error = -1;
761 goto ipsec_output_err;
762 }
763
764 done:
765 return error;
766
767 ipsec_output_err:
768 if (data)
769 mbuf_freem(data);
770 goto done;
771 }
772
773 static void
774 ipsec_start(ifnet_t interface)
775 {
776 mbuf_t data;
777
778 for (;;) {
779 if (ifnet_dequeue(interface, &data) != 0)
780 break;
781 if (ipsec_output(interface, data) != 0)
782 break;
783 }
784 }
785
786 /* Network Interface functions */
787 static errno_t
788 ipsec_demux(__unused ifnet_t interface,
789 mbuf_t data,
790 __unused char *frame_header,
791 protocol_family_t *protocol)
792 {
793 struct ip *ip;
794 u_int ip_version;
795
796 while (data != NULL && mbuf_len(data) < 1) {
797 data = mbuf_next(data);
798 }
799
800 if (data == NULL)
801 return ENOENT;
802
803 ip = mtod(data, struct ip *);
804 ip_version = ip->ip_v;
805
806 switch(ip_version) {
807 case 4:
808 *protocol = PF_INET;
809 return 0;
810 case 6:
811 *protocol = PF_INET6;
812 return 0;
813 default:
814 break;
815 }
816
817 return 0;
818 }
819
820 static errno_t
821 ipsec_add_proto(__unused ifnet_t interface,
822 protocol_family_t protocol,
823 __unused const struct ifnet_demux_desc *demux_array,
824 __unused u_int32_t demux_count)
825 {
826 switch(protocol) {
827 case PF_INET:
828 return 0;
829 case PF_INET6:
830 return 0;
831 default:
832 break;
833 }
834
835 return ENOPROTOOPT;
836 }
837
838 static errno_t
839 ipsec_del_proto(__unused ifnet_t interface,
840 __unused protocol_family_t protocol)
841 {
842 return 0;
843 }
844
845 static errno_t
846 ipsec_ioctl(ifnet_t interface,
847 u_long command,
848 void *data)
849 {
850 errno_t result = 0;
851
852 switch(command) {
853 case SIOCSIFMTU:
854 ifnet_set_mtu(interface, ((struct ifreq*)data)->ifr_mtu);
855 break;
856
857 case SIOCSIFFLAGS:
858 /* ifioctl() takes care of it */
859 break;
860
861 default:
862 result = EOPNOTSUPP;
863 }
864
865 return result;
866 }
867
868 static void
869 ipsec_detached(
870 ifnet_t interface)
871 {
872 struct ipsec_pcb *pcb = ifnet_softc(interface);
873
874 ifnet_release(pcb->ipsec_ifp);
875 }
876
877 /* Protocol Handlers */
878
879 static errno_t
880 ipsec_proto_input(ifnet_t interface,
881 protocol_family_t protocol,
882 mbuf_t m,
883 __unused char *frame_header)
884 {
885 struct ip *ip;
886 uint32_t af = 0;
887 ip = mtod(m, struct ip *);
888 if (ip->ip_v == 4)
889 af = AF_INET;
890 else if (ip->ip_v == 6)
891 af = AF_INET6;
892
893 mbuf_pkthdr_setrcvif(m, interface);
894 bpf_tap_in(interface, DLT_NULL, m, &af, sizeof(af));
895 pktap_input(interface, protocol, m, NULL);
896
897 if (proto_input(protocol, m) != 0) {
898 ifnet_stat_increment_in(interface, 0, 0, 1);
899 m_freem(m);
900 } else {
901 ifnet_stat_increment_in(interface, 1, m->m_pkthdr.len, 0);
902 }
903
904 return 0;
905 }
906
907 static errno_t
908 ipsec_proto_pre_output(__unused ifnet_t interface,
909 protocol_family_t protocol,
910 __unused mbuf_t *packet,
911 __unused const struct sockaddr *dest,
912 __unused void *route,
913 __unused char *frame_type,
914 __unused char *link_layer_dest)
915 {
916
917 *(protocol_family_t *)(void *)frame_type = protocol;
918 return 0;
919 }
920
921 static errno_t
922 ipsec_attach_proto(ifnet_t interface,
923 protocol_family_t protocol)
924 {
925 struct ifnet_attach_proto_param proto;
926 errno_t result;
927
928 bzero(&proto, sizeof(proto));
929 proto.input = ipsec_proto_input;
930 proto.pre_output = ipsec_proto_pre_output;
931
932 result = ifnet_attach_protocol(interface, protocol, &proto);
933 if (result != 0 && result != EEXIST) {
934 printf("ipsec_attach_inet - ifnet_attach_protocol %d failed: %d\n",
935 protocol, result);
936 }
937
938 return result;
939 }
940
941 errno_t
942 ipsec_inject_inbound_packet(ifnet_t interface,
943 mbuf_t packet)
944 {
945 errno_t error;
946 protocol_family_t protocol;
947 if ((error = ipsec_demux(interface, packet, NULL, &protocol)) != 0) {
948 return error;
949 }
950
951 return ipsec_proto_input(interface, protocol, packet, NULL);
952 }
953
954 void
955 ipsec_set_pkthdr_for_interface(ifnet_t interface, mbuf_t packet, int family)
956 {
957 if (packet != NULL && interface != NULL) {
958 struct ipsec_pcb *pcb = ifnet_softc(interface);
959 if (pcb != NULL) {
960 /* Set traffic class, set flow */
961 m_set_service_class(packet, pcb->ipsec_output_service_class);
962 packet->m_pkthdr.pkt_flowsrc = FLOWSRC_IFNET;
963 packet->m_pkthdr.pkt_flowid = interface->if_flowhash;
964 if (family == AF_INET) {
965 struct ip *ip = mtod(packet, struct ip *);
966 packet->m_pkthdr.pkt_proto = ip->ip_p;
967 } else if (family == AF_INET6) {
968 struct ip6_hdr *ip6 = mtod(packet, struct ip6_hdr *);
969 packet->m_pkthdr.pkt_proto = ip6->ip6_nxt;
970 }
971 packet->m_pkthdr.pkt_flags = (PKTF_FLOW_ID | PKTF_FLOW_ADV | PKTF_FLOW_LOCALSRC);
972 }
973 }
974 }
975
976 void
977 ipsec_set_ipoa_for_interface(ifnet_t interface, struct ip_out_args *ipoa)
978 {
979 struct ipsec_pcb *pcb;
980
981 if (interface == NULL || ipoa == NULL)
982 return;
983 pcb = ifnet_softc(interface);
984
985 if (net_qos_policy_restricted == 0) {
986 ipoa->ipoa_flags |= IPOAF_QOSMARKING_ALLOWED;
987 ipoa->ipoa_sotc = so_svc2tc(pcb->ipsec_output_service_class);
988 } else if (pcb->ipsec_output_service_class != MBUF_SC_VO ||
989 net_qos_policy_restrict_avapps != 0) {
990 ipoa->ipoa_flags &= ~IPOAF_QOSMARKING_ALLOWED;
991 } else {
992 ipoa->ipoa_flags |= IP6OAF_QOSMARKING_ALLOWED;
993 ipoa->ipoa_sotc = SO_TC_VO;
994 }
995 }
996
997 void
998 ipsec_set_ip6oa_for_interface(ifnet_t interface, struct ip6_out_args *ip6oa)
999 {
1000 struct ipsec_pcb *pcb;
1001
1002 if (interface == NULL || ip6oa == NULL)
1003 return;
1004 pcb = ifnet_softc(interface);
1005
1006 if (net_qos_policy_restricted == 0) {
1007 ip6oa->ip6oa_flags |= IPOAF_QOSMARKING_ALLOWED;
1008 ip6oa->ip6oa_sotc = so_svc2tc(pcb->ipsec_output_service_class);
1009 } else if (pcb->ipsec_output_service_class != MBUF_SC_VO ||
1010 net_qos_policy_restrict_avapps != 0) {
1011 ip6oa->ip6oa_flags &= ~IPOAF_QOSMARKING_ALLOWED;
1012 } else {
1013 ip6oa->ip6oa_flags |= IP6OAF_QOSMARKING_ALLOWED;
1014 ip6oa->ip6oa_sotc = SO_TC_VO;
1015 }
1016 }