2 * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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>
36 #include <net/if_types.h>
38 #include <net/if_ipsec.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>
51 #include <netkey/key.h>
52 #include <net/pktap.h>
54 extern int net_qos_policy_restricted
;
55 extern int net_qos_policy_restrict_avapps
;
57 /* Kernel Control functions */
58 static errno_t
ipsec_ctl_connect(kern_ctl_ref kctlref
, struct sockaddr_ctl
*sac
,
60 static errno_t
ipsec_ctl_disconnect(kern_ctl_ref kctlref
, u_int32_t unit
,
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
);
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
);
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
);
89 static kern_ctl_ref ipsec_kctlref
;
90 static u_int32_t ipsec_family
;
92 #define IPSECQ_MAXLEN 256
95 ipsec_register_control(void)
97 struct kern_ctl_reg kern_ctl
;
100 /* Find a unique value for our interface family */
101 result
= mbuf_tag_id_find(IPSEC_CONTROL_NAME
, &ipsec_family
);
103 printf("ipsec_register_control - mbuf_tag_id_find_internal failed: %d\n", result
);
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
;
119 result
= ctl_register(&kern_ctl
, &ipsec_kctlref
);
121 printf("ipsec_register_control - ctl_register failed: %d\n", result
);
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
);
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
);
149 ipsec_interface_isvalid (ifnet_t interface
)
151 struct ipsec_pcb
*pcb
= NULL
;
153 if (interface
== NULL
)
156 pcb
= ifnet_softc(interface
);
161 /* When ctl disconnects, ipsec_unit is set to 0 */
162 if (pcb
->ipsec_unit
== 0)
168 /* Kernel control functions */
171 ipsec_ctl_connect(kern_ctl_ref kctlref
,
172 struct sockaddr_ctl
*sac
,
175 struct ifnet_init_eparams ipsec_init
;
176 struct ipsec_pcb
*pcb
;
178 struct ifnet_stats_param stats
;
180 /* kernel control allocates, interface frees */
181 MALLOC(pcb
, struct ipsec_pcb
*, sizeof(*pcb
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
183 /* Setup the protocol control block */
185 pcb
->ipsec_ctlref
= kctlref
;
186 pcb
->ipsec_unit
= sac
->sc_unit
;
187 pcb
->ipsec_output_service_class
= MBUF_SC_OAM
;
189 printf("ipsec_ctl_connect: creating interface ipsec%d\n", pcb
->ipsec_unit
- 1);
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
;
207 result
= ifnet_allocate_extended(&ipsec_init
, &pcb
->ipsec_ifp
);
209 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result
);
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);
219 /* The interface must generate its own IPv6 LinkLocal address,
220 * if possible following the recommendation of RFC2472 to the 64bit interface ID
222 ifnet_set_eflags(pcb
->ipsec_ifp
, IFEF_NOAUTOIPV6LL
, IFEF_NOAUTOIPV6LL
);
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
);
228 /* Attach the interface */
229 result
= ifnet_attach(pcb
->ipsec_ifp
, NULL
);
231 printf("ipsec_ctl_connect - ifnet_allocate failed: %d\n", result
);
232 ifnet_release(pcb
->ipsec_ifp
);
237 bpfattach(pcb
->ipsec_ifp
, DLT_NULL
, 4);
239 /* The interfaces resoures allocated, mark it as running */
240 ifnet_set_flags(pcb
->ipsec_ifp
, IFF_RUNNING
, IFF_RUNNING
);
247 ipsec_detach_ip(ifnet_t interface
,
248 protocol_family_t protocol
,
251 errno_t result
= EPROTONOSUPPORT
;
253 /* Attempt a detach */
254 if (protocol
== PF_INET
) {
257 bzero(&ifr
, sizeof(ifr
));
258 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s%d",
259 ifnet_name(interface
), ifnet_unit(interface
));
261 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH
, &ifr
);
263 else if (protocol
== PF_INET6
) {
264 struct in6_ifreq ifr6
;
266 bzero(&ifr6
, sizeof(ifr6
));
267 snprintf(ifr6
.ifr_name
, sizeof(ifr6
.ifr_name
), "%s%d",
268 ifnet_name(interface
), ifnet_unit(interface
));
270 result
= sock_ioctl(pf_socket
, SIOCPROTODETACH_IN6
, &ifr6
);
277 ipsec_remove_address(ifnet_t interface
,
278 protocol_family_t protocol
,
284 /* Attempt a detach */
285 if (protocol
== PF_INET
) {
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
));
293 printf("ipsec_remove_address - ifaddr_address failed: %d", result
);
296 result
= sock_ioctl(pf_socket
, SIOCDIFADDR
, &ifr
);
298 printf("ipsec_remove_address - SIOCDIFADDR failed: %d", result
);
302 else if (protocol
== PF_INET6
) {
303 struct in6_ifreq ifr6
;
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
));
311 printf("ipsec_remove_address - ifaddr_address failed (v6): %d",
315 result
= sock_ioctl(pf_socket
, SIOCDIFADDR_IN6
, &ifr6
);
317 printf("ipsec_remove_address - SIOCDIFADDR_IN6 failed: %d",
325 ipsec_cleanup_family(ifnet_t interface
,
326 protocol_family_t protocol
)
329 socket_t pf_socket
= NULL
;
330 ifaddr_t
*addresses
= NULL
;
333 if (protocol
!= PF_INET
&& protocol
!= PF_INET6
) {
334 printf("ipsec_cleanup_family - invalid protocol family %d\n", protocol
);
338 /* Create a socket for removing addresses and detaching the protocol */
339 result
= sock_socket(protocol
, SOCK_DGRAM
, 0, NULL
, NULL
, &pf_socket
);
341 if (result
!= EAFNOSUPPORT
)
342 printf("ipsec_cleanup_family - failed to create %s socket: %d\n",
343 protocol
== PF_INET
? "IP" : "IPv6", result
);
347 /* always set SS_PRIV, we want to close and detach regardless */
348 sock_setpriv(pf_socket
, 1);
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. */
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
);
362 * At this point, we received an EBUSY error. This means there are
363 * addresses attached. We should detach them and then try again.
365 result
= ifnet_get_address_list_family(interface
, &addresses
, protocol
);
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
);
373 for (i
= 0; addresses
[i
] != 0; i
++) {
374 ipsec_remove_address(interface
, protocol
, addresses
[i
], pf_socket
);
376 ifnet_free_address_list(addresses
);
380 * The addresses should be gone, we should try the remove again.
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
);
388 if (pf_socket
!= NULL
)
389 sock_close(pf_socket
);
391 if (addresses
!= NULL
)
392 ifnet_free_address_list(addresses
);
396 ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref
,
397 __unused u_int32_t unit
,
400 struct ipsec_pcb
*pcb
= unitinfo
;
407 ifp
= pcb
->ipsec_ifp
;
409 pcb
->ipsec_ctlref
= NULL
;
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.
418 key_delsp_for_ipsec_if(ifp
);
420 ipsec_cleanup_family(ifp
, AF_INET
);
421 ipsec_cleanup_family(ifp
, AF_INET6
);
423 if ((result
= ifnet_detach(ifp
)) != 0) {
424 printf("ipsec_ctl_disconnect - ifnet_detach failed: %d\n", result
);
431 ipsec_ctl_send(__unused kern_ctl_ref kctlref
,
432 __unused u_int32_t unit
,
433 __unused
void *unitinfo
,
437 /* Receive messages from the control socket. Currently unused. */
443 ipsec_ctl_setopt(__unused kern_ctl_ref kctlref
,
444 __unused u_int32_t unit
,
450 struct ipsec_pcb
*pcb
= unitinfo
;
453 /* check for privileges for privileged options */
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) {
466 case IPSEC_OPT_FLAGS
:
467 if (len
!= sizeof(u_int32_t
))
470 pcb
->ipsec_flags
= *(u_int32_t
*)data
;
473 case IPSEC_OPT_EXT_IFDATA_STATS
:
474 if (len
!= sizeof(int)) {
478 pcb
->ipsec_ext_ifdata_stats
= (*(int *)data
) ? 1 : 0;
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
;
485 if (utsp
== NULL
|| len
< sizeof(struct ipsec_stats_param
)) {
489 if (!pcb
->ipsec_ext_ifdata_stats
) {
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
);
497 ifnet_stat_increment_out(pcb
->ipsec_ifp
, utsp
->utsp_packets
,
498 utsp
->utsp_bytes
, utsp
->utsp_errors
);
502 case IPSEC_OPT_SET_DELEGATE_INTERFACE
: {
503 ifnet_t del_ifp
= NULL
;
506 if (len
> IFNAMSIZ
- 1) {
510 if (len
!= 0) { /* if len==0, del_ifp will be NULL causing the delegate to be removed */
511 bcopy(data
, name
, len
);
513 result
= ifnet_find_by_name(name
, &del_ifp
);
516 printf("%s IPSEC_OPT_SET_DELEGATE_INTERFACE %s to %s\n",
517 __func__
, pcb
->ipsec_ifp
->if_xname
,
520 result
= ifnet_set_delegate(pcb
->ipsec_ifp
, del_ifp
);
522 ifnet_release(del_ifp
);
527 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: {
528 if (len
!= sizeof(int)) {
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
;
536 pcb
->ipsec_output_service_class
= output_service_class
;
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
);
545 result
= ENOPROTOOPT
;
553 ipsec_ctl_getopt(__unused kern_ctl_ref kctlref
,
554 __unused u_int32_t unit
,
560 struct ipsec_pcb
*pcb
= unitinfo
;
564 case IPSEC_OPT_FLAGS
:
565 if (*len
!= sizeof(u_int32_t
))
568 *(u_int32_t
*)data
= pcb
->ipsec_flags
;
571 case IPSEC_OPT_EXT_IFDATA_STATS
:
572 if (*len
!= sizeof(int))
575 *(int *)data
= (pcb
->ipsec_ext_ifdata_stats
) ? 1 : 0;
578 case IPSEC_OPT_IFNAME
:
579 *len
= snprintf(data
, *len
, "%s%d", ifnet_name(pcb
->ipsec_ifp
), ifnet_unit(pcb
->ipsec_ifp
)) + 1;
582 case IPSEC_OPT_OUTPUT_TRAFFIC_CLASS
: {
583 if (*len
!= sizeof(int)) {
587 *(int *)data
= so_svc2tc(pcb
->ipsec_output_service_class
);
591 result
= ENOPROTOOPT
;
598 /* Network Interface functions */
600 ipsec_output(ifnet_t interface
,
603 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
604 struct ipsec_output_state ipsec_state
;
606 struct route_in6 ro6
;
610 struct ip_out_args ipoa
;
611 struct ip6_out_args ip6oa
;
613 u_int ip_version
= 0;
616 struct flowadv
*adv
= NULL
;
618 // Make sure this packet isn't looping through the interface
619 if (necp_get_last_interface_index_from_packet(data
) == interface
->if_index
) {
621 goto ipsec_output_err
;
624 // Mark the interface so NECP can evaluate tunnel policy
625 necp_mark_packet_from_interface(data
, interface
);
627 ip
= mtod(data
, struct ip
*);
628 ip_version
= ip
->ip_v
;
630 switch (ip_version
) {
634 bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
));
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
));
642 error
= ipsec4_interface_output(&ipsec_state
, interface
);
643 /* Tunneled in IPv6 - packet is gone */
644 if (error
== 0 && ipsec_state
.tunneled
== 6) {
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
;
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
);
661 /* Flip endian-ness for ip_output */
662 ip
= mtod(data
, struct ip
*);
666 /* Increment statistics */
667 length
= mbuf_pkthdr_len(data
);
668 ifnet_stat_increment_out(interface
, 1, length
, 0);
670 /* Send to ip_output */
671 bzero(&ro
, sizeof(ro
));
673 flags
= IP_OUTARGS
| /* Passing out args to specify interface */
674 IP_NOIPSEC
; /* To ensure the packet doesn't go through ipsec twice */
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
;
683 ipsec_set_ipoa_for_interface(pcb
->ipsec_ifp
, &ipoa
);
685 adv
= &ipoa
.ipoa_flowadv
;
687 (void) ip_output(data
, NULL
, &ro
, flags
, NULL
, &ipoa
);
690 if (adv
->code
== FADV_FLOW_CONTROLLED
|| adv
->code
== FADV_SUSPENDED
) {
692 ifnet_disable_output(interface
);
698 bpf_tap_out(pcb
->ipsec_ifp
, DLT_NULL
, data
, &af
, sizeof(af
));
700 data
= ipsec6_splithdr(data
);
702 printf("ipsec_output: ipsec6_splithdr returned NULL\n");
703 goto ipsec_output_err
;
706 ip6
= mtod(data
, struct ip6_hdr
*);
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
));
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 */
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
;
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
);
729 /* Increment statistics */
730 length
= mbuf_pkthdr_len(data
);
731 ifnet_stat_increment_out(interface
, 1, length
, 0);
733 /* Send to ip6_output */
734 bzero(&ro6
, sizeof(ro6
));
736 flags
= IPV6_OUTARGS
;
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
;
745 ipsec_set_ip6oa_for_interface(pcb
->ipsec_ifp
, &ip6oa
);
747 adv
= &ip6oa
.ip6oa_flowadv
;
749 (void) ip6_output(data
, NULL
, &ro6
, flags
, NULL
, NULL
, &ip6oa
);
752 if (adv
->code
== FADV_FLOW_CONTROLLED
|| adv
->code
== FADV_SUSPENDED
) {
754 ifnet_disable_output(interface
);
759 printf("ipsec_output: Received unknown packet version %d.\n", ip_version
);
761 goto ipsec_output_err
;
774 ipsec_start(ifnet_t interface
)
779 if (ifnet_dequeue(interface
, &data
) != 0)
781 if (ipsec_output(interface
, data
) != 0)
786 /* Network Interface functions */
788 ipsec_demux(__unused ifnet_t interface
,
790 __unused
char *frame_header
,
791 protocol_family_t
*protocol
)
796 while (data
!= NULL
&& mbuf_len(data
) < 1) {
797 data
= mbuf_next(data
);
803 ip
= mtod(data
, struct ip
*);
804 ip_version
= ip
->ip_v
;
811 *protocol
= PF_INET6
;
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
)
839 ipsec_del_proto(__unused ifnet_t interface
,
840 __unused protocol_family_t protocol
)
846 ipsec_ioctl(ifnet_t interface
,
854 ifnet_set_mtu(interface
, ((struct ifreq
*)data
)->ifr_mtu
);
858 /* ifioctl() takes care of it */
872 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
874 ifnet_release(pcb
->ipsec_ifp
);
877 /* Protocol Handlers */
880 ipsec_proto_input(ifnet_t interface
,
881 protocol_family_t protocol
,
883 __unused
char *frame_header
)
887 ip
= mtod(m
, struct ip
*);
890 else if (ip
->ip_v
== 6)
893 mbuf_pkthdr_setrcvif(m
, interface
);
894 bpf_tap_in(interface
, DLT_NULL
, m
, &af
, sizeof(af
));
895 pktap_input(interface
, protocol
, m
, NULL
);
897 if (proto_input(protocol
, m
) != 0) {
898 ifnet_stat_increment_in(interface
, 0, 0, 1);
901 ifnet_stat_increment_in(interface
, 1, m
->m_pkthdr
.len
, 0);
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
)
917 *(protocol_family_t
*)(void *)frame_type
= protocol
;
922 ipsec_attach_proto(ifnet_t interface
,
923 protocol_family_t protocol
)
925 struct ifnet_attach_proto_param proto
;
928 bzero(&proto
, sizeof(proto
));
929 proto
.input
= ipsec_proto_input
;
930 proto
.pre_output
= ipsec_proto_pre_output
;
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",
942 ipsec_inject_inbound_packet(ifnet_t interface
,
946 protocol_family_t protocol
;
947 if ((error
= ipsec_demux(interface
, packet
, NULL
, &protocol
)) != 0) {
951 return ipsec_proto_input(interface
, protocol
, packet
, NULL
);
955 ipsec_set_pkthdr_for_interface(ifnet_t interface
, mbuf_t packet
, int family
)
957 if (packet
!= NULL
&& interface
!= NULL
) {
958 struct ipsec_pcb
*pcb
= ifnet_softc(interface
);
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
;
971 packet
->m_pkthdr
.pkt_flags
= (PKTF_FLOW_ID
| PKTF_FLOW_ADV
| PKTF_FLOW_LOCALSRC
);
977 ipsec_set_ipoa_for_interface(ifnet_t interface
, struct ip_out_args
*ipoa
)
979 struct ipsec_pcb
*pcb
;
981 if (interface
== NULL
|| ipoa
== NULL
)
983 pcb
= ifnet_softc(interface
);
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
;
992 ipoa
->ipoa_flags
|= IP6OAF_QOSMARKING_ALLOWED
;
993 ipoa
->ipoa_sotc
= SO_TC_VO
;
998 ipsec_set_ip6oa_for_interface(ifnet_t interface
, struct ip6_out_args
*ip6oa
)
1000 struct ipsec_pcb
*pcb
;
1002 if (interface
== NULL
|| ip6oa
== NULL
)
1004 pcb
= ifnet_softc(interface
);
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
;
1013 ip6oa
->ip6oa_flags
|= IP6OAF_QOSMARKING_ALLOWED
;
1014 ip6oa
->ip6oa_sotc
= SO_TC_VO
;