1 /* $Id: vpn_control.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */
4 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
6 * @APPLE_LICENSE_HEADER_START@
8 * The contents of this file constitute Original Code as defined in and
9 * are subject to the Apple Public Source License Version 1.1 (the
10 * "License"). You may not use this file except in compliance with the
11 * License. Please obtain a copy of the License at
12 * http://www.apple.com/publicsource and read it before using this file.
14 * This Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
27 * All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. Neither the name of the project nor the names of its contributors
38 * may be used to endorse or promote products derived from this software
39 * without specific prior written permission.
41 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 #include <sys/types.h>
60 #include <sys/param.h>
61 #include <sys/socket.h>
62 #include <sys/signal.h>
66 #include <net/pfkeyv2.h>
68 #include <netinet/in.h>
69 #ifndef HAVE_NETINET6_IPSEC
70 #include <netinet/ipsec.h>
72 #include <netinet6/ipsec.h>
86 #include <launch_priv.h>
98 #include "localconf.h"
99 #include "remoteconf.h"
100 #include "grabmyaddr.h"
101 #include "isakmp_var.h"
106 #include "ipsec_doi.h"
107 #include "vpn_control.h"
108 #include "vpn_control_var.h"
109 #include "isakmp_inf.h"
111 #include "gcmalloc.h"
112 #include "isakmp_cfg.h"
115 #ifdef ENABLE_VPNCONTROL_PORT
116 char *vpncontrolsock_path
= VPNCONTROLSOCK_PATH
;
117 uid_t vpncontrolsock_owner
= 0;
118 gid_t vpncontrolsock_group
= 0;
119 mode_t vpncontrolsock_mode
= 0600;
121 static struct sockaddr_un sunaddr
;
122 static int vpncontrol_process (struct vpnctl_socket_elem
*, char *, size_t);
123 static int vpncontrol_reply (int, char *);
124 static void vpncontrol_close_comm (struct vpnctl_socket_elem
*);
125 static int checklaunchd (void);
126 extern int vpn_get_config (phase1_handle_t
*, struct vpnctl_status_phase_change
**, size_t *);
127 extern int vpn_xauth_reply (u_int32_t
, void *, size_t);
133 launch_data_t checkin_response
= NULL
;
135 launch_data_t checkin_request
= NULL
;
137 launch_data_t sockets_dict
, listening_fd_array
;
138 launch_data_t listening_fd
;
139 struct sockaddr_storage fdsockaddr
;
140 socklen_t fdsockaddrlen
= sizeof(fdsockaddr
);
147 /* check in with launchd */
149 if ((checkin_request
= launch_data_new_string(LAUNCH_KEY_CHECKIN
)) == NULL
) {
151 if ((checkin_response
= launch_socket_service_check_in()) == NULL
) {
154 "failed to launch_socket_service_check_in.\n");
158 if ((checkin_response
= launch_msg(checkin_request
)) == NULL
) {
159 plog(ASL_LEVEL_ERR
, "failed to launch_msg.\n");
163 if (LAUNCH_DATA_ERRNO
== launch_data_get_type(checkin_response
)) {
165 "launch_data_get_type error %d\n",
166 launch_data_get_errno(checkin_response
));
169 if ( (sockets_dict
= launch_data_dict_lookup(checkin_response
, LAUNCH_JOBKEY_SOCKETS
)) == NULL
){
171 "failed to launch_data_dict_lookup.\n");
174 if ( !(socketct
= launch_data_dict_get_count(sockets_dict
))){
176 "launch_data_dict_get_count returns no socket defined.\n");
180 if ( (listening_fd_array
= launch_data_dict_lookup(sockets_dict
, "Listeners")) == NULL
){
182 "failed to launch_data_dict_lookup.\n");
185 listenerct
= launch_data_array_get_count(listening_fd_array
);
186 for (i
= 0; i
< listenerct
; i
++) {
187 listening_fd
= launch_data_array_get_index(listening_fd_array
, i
);
188 fd
= launch_data_get_fd( listening_fd
);
189 if ( getsockname( fd
, (struct sockaddr
*)&fdsockaddr
, &fdsockaddrlen
)){
193 /* Is this the VPN control socket? */
194 if ( fdsockaddr
.ss_family
== AF_UNIX
&&
195 (!(strcmp(vpncontrolsock_path
, ((struct sockaddr_un
*)&fdsockaddr
)->sun_path
))))
197 plog(ASL_LEVEL_NOTICE
,
198 "found launchd socket.\n");
203 // TODO: check if we have any leaked fd
204 if ( listenerct
== i
){
206 "failed to find launchd socket\n");
211 if (checkin_response
)
212 launch_data_free(checkin_response
);
218 vpncontrol_handler(void *unused
)
220 struct sockaddr_storage from
;
221 socklen_t fromlen
= sizeof(from
);
224 struct vpnctl_socket_elem
*sock_elem
;
227 sock_elem
= racoon_calloc(1, sizeof(struct vpnctl_socket_elem
));
228 if (sock_elem
== NULL
) {
230 "memory error: %s\n", strerror(errno
));
231 return; //%%%%%% terminate
233 LIST_INIT(&sock_elem
->bound_addresses
);
235 sock_elem
->sock
= accept(lcconf
->sock_vpncontrol
, (struct sockaddr
*)&from
, &fromlen
);
236 if (sock_elem
->sock
< 0) {
238 "failed to accept vpn_control command: %s\n", strerror(errno
));
239 racoon_free(sock_elem
);
240 return; //%%%%% terminate
242 LIST_INSERT_HEAD(&lcconf
->vpnctl_comm_socks
, sock_elem
, chain
);
244 sock_elem
->source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_READ
, sock_elem
->sock
, 0, dispatch_get_main_queue());
245 if (sock_elem
->source
== NULL
) {
246 plog(ASL_LEVEL_ERR
, "could not create comm socket source.");
247 racoon_free(sock_elem
);
248 return; //%%%%% terminate
250 dispatch_source_set_event_handler(sock_elem
->source
,
252 vpncontrol_comm_handler(sock_elem
);
254 sock
= sock_elem
->sock
;
256 dispatch_source_t the_source
= sock_elem
->source
;
257 dispatch_source_set_cancel_handler(sock_elem
->source
,
260 dispatch_release(the_source
); /* Release the source on cancel */
262 dispatch_resume(sock_elem
->source
);
264 plog(ASL_LEVEL_NOTICE
,
265 "accepted connection on vpn control socket.\n");
272 vpncontrol_comm_handler(struct vpnctl_socket_elem
*elem
)
274 struct vpnctl_hdr hdr
;
277 /* get buffer length */
278 if (elem
->buffer
== NULL
) {
279 while ((len
= recv(elem
->sock
, (char *)&hdr
, sizeof(hdr
), MSG_PEEK
)) < 0) {
282 plog(ASL_LEVEL_ERR
, "failed to recv vpn_control command: %s\n", strerror(errno
));
286 plog(ASL_LEVEL_NOTICE
, "vpn_control socket closed by peer.\n");
287 /* kill all related connections */
288 vpncontrol_disconnect_all(elem
, ike_session_stopped_by_controller_comm_lost
);
289 vpncontrol_close_comm(elem
);
290 return; // %%%%%% terminate
294 if (len
< sizeof(hdr
)) {
296 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len
, sizeof(hdr
));
300 elem
->read_bytes_len
= 0; // Sanity
301 elem
->pending_bytes_len
= ntohs(hdr
.len
) + sizeof(hdr
);
303 /* get buffer to receive */
304 elem
->buffer
= racoon_malloc(elem
->pending_bytes_len
);
305 if (elem
->buffer
== NULL
) {
307 "failed to alloc buffer for vpn_control command\n");
313 while ((len
= recv(elem
->sock
, elem
->buffer
+ elem
->read_bytes_len
, elem
->pending_bytes_len
, 0)) < 0) {
316 plog(ASL_LEVEL_ERR
, "failed to recv vpn_control command: %s\n",
322 plog(ASL_LEVEL_NOTICE
, "vpn_control socket closed by peer while reading packet\n");
323 /* kill all related connections */
324 vpncontrol_disconnect_all(elem
, ike_session_stopped_by_controller_comm_lost
);
325 vpncontrol_close_comm(elem
);
329 elem
->read_bytes_len
+= len
;
331 if (len
< elem
->pending_bytes_len
) {
332 plog(ASL_LEVEL_NOTICE
,
333 "received partial vpn_control command - len=%ld - expected %u\n", len
, elem
->pending_bytes_len
);
334 elem
->pending_bytes_len
-= len
;
337 (void)vpncontrol_process(elem
, elem
->buffer
, elem
->read_bytes_len
);
340 elem
->read_bytes_len
= 0;
341 elem
->pending_bytes_len
= 0;
346 vpncontrol_process(struct vpnctl_socket_elem
*elem
, char *combuf
, size_t combuf_len
)
349 struct vpnctl_hdr
*hdr
= ALIGNED_CAST(struct vpnctl_hdr
*)combuf
;
351 switch (ntohs(hdr
->msg_type
)) {
353 case VPNCTL_CMD_BIND
:
355 if (combuf_len
< sizeof(struct vpnctl_cmd_bind
)) {
356 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl bind cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_bind
));
361 struct vpnctl_cmd_bind
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_bind
*)combuf
;
362 struct bound_addr
*addr
;
364 if (combuf_len
< (sizeof(struct vpnctl_cmd_bind
) + ntohs(pkt
->vers_len
))) {
365 plog(ASL_LEVEL_ERR
, "invalid length for vpnctl bind cmd - len=%ld - expected %ld\n", combuf_len
, (sizeof(struct vpnctl_cmd_bind
) + ntohs(pkt
->vers_len
)));
370 plog(ASL_LEVEL_NOTICE
,
371 "received bind command on vpn control socket.\n");
372 addr
= racoon_calloc(1, sizeof(struct bound_addr
));
375 "memory error: %s\n", strerror(errno
));
379 if (ntohs(pkt
->vers_len
)) {
380 addr
->version
= vmalloc(ntohs(pkt
->vers_len
));
381 if (addr
->version
== NULL
) {
383 "memory error: %s\n", strerror(errno
));
388 memcpy(addr
->version
->v
, pkt
+ 1, ntohs(pkt
->vers_len
));
390 addr
->address
= pkt
->address
;
391 LIST_INSERT_HEAD(&elem
->bound_addresses
, addr
, chain
);
392 lcconf
->auto_exit_state
|= LC_AUTOEXITSTATE_CLIENT
; /* client side */
396 case VPNCTL_CMD_UNBIND
:
398 if (combuf_len
< sizeof(struct vpnctl_cmd_unbind
)) {
399 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl unbind cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_unbind
));
404 struct vpnctl_cmd_unbind
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_unbind
*)combuf
;
405 struct bound_addr
*addr
;
406 struct bound_addr
*t_addr
;
408 plog(ASL_LEVEL_NOTICE
,
409 "received unbind command on vpn control socket.\n");
410 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
411 if (pkt
->address
== 0xFFFFFFFF ||
412 pkt
->address
== addr
->address
) {
413 flushsainfo_dynamic(addr
->address
);
414 LIST_REMOVE(addr
, chain
);
416 vfree(addr
->version
);
423 case VPNCTL_CMD_REDIRECT
:
425 if (combuf_len
< sizeof(struct vpnctl_cmd_redirect
)) {
426 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl redirect cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_redirect
));
431 struct vpnctl_cmd_redirect
*redirect_msg
= ALIGNED_CAST(struct vpnctl_cmd_redirect
*)combuf
;
432 struct redirect
*raddr
;
433 struct redirect
*t_raddr
;
436 plog(ASL_LEVEL_NOTICE
,
437 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg
->redirect_address
));
439 LIST_FOREACH_SAFE(raddr
, &lcconf
->redirect_addresses
, chain
, t_raddr
) {
440 if (raddr
->cluster_address
== redirect_msg
->address
) {
441 if (redirect_msg
->redirect_address
== 0) {
442 LIST_REMOVE(raddr
, chain
);
445 raddr
->redirect_address
= redirect_msg
->redirect_address
;
446 raddr
->force
= ntohs(redirect_msg
->force
);
453 raddr
= racoon_malloc(sizeof(struct redirect
));
456 "cannot allcoate memory for redirect address.\n");
460 raddr
->cluster_address
= redirect_msg
->address
;
461 raddr
->redirect_address
= redirect_msg
->redirect_address
;
462 raddr
->force
= ntohs(redirect_msg
->force
);
463 LIST_INSERT_HEAD(&lcconf
->redirect_addresses
, raddr
, chain
);
469 case VPNCTL_CMD_PING
:
470 break; /* just reply for now */
472 case VPNCTL_CMD_XAUTH_INFO
:
474 if (combuf_len
< sizeof(struct vpnctl_cmd_xauth_info
)) {
475 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl xauth info cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_xauth_info
));
480 struct vpnctl_cmd_xauth_info
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_xauth_info
*)combuf
;
481 struct bound_addr
*addr
;
482 struct bound_addr
*t_addr
;
485 if (combuf_len
< (sizeof(struct vpnctl_cmd_xauth_info
) + ntohs(pkt
->hdr
.len
) - sizeof(u_int32_t
))) {
486 plog(ASL_LEVEL_ERR
, "invalid length for vpnctl xauth info cmd - len=%ld - expected %ld\n", combuf_len
, (sizeof(struct vpnctl_cmd_xauth_info
) + ntohs(pkt
->hdr
.len
) - sizeof(u_int32_t
)));
491 plog(ASL_LEVEL_NOTICE
,
492 "received xauth info command vpn control socket.\n");
493 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
494 if (pkt
->address
== addr
->address
) {
495 /* reply to the last xauth request */
497 error
= vpn_xauth_reply(pkt
->address
, attr_list
, ntohs(pkt
->hdr
.len
) - sizeof(u_int32_t
));
504 case VPNCTL_CMD_SET_NAT64_PREFIX
:
506 if (combuf_len
< sizeof(struct vpnctl_cmd_set_nat64_prefix
)) {
507 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl nat64 prefix cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_set_nat64_prefix
));
512 struct vpnctl_cmd_set_nat64_prefix
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_set_nat64_prefix
*)combuf
;
513 struct bound_addr
*addr
;
514 struct bound_addr
*t_addr
;
516 plog(ASL_LEVEL_NOTICE
,
517 "received set v6 prefix of len %u command on vpn control socket, adding to all addresses.\n", pkt
->nat64_prefix
.length
);
518 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
519 memcpy(&addr
->nat64_prefix
, &pkt
->nat64_prefix
, sizeof(addr
->nat64_prefix
));
524 case VPNCTL_CMD_CONNECT
:
526 if (combuf_len
< sizeof(struct vpnctl_cmd_connect
)) {
527 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl connect cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_connect
));
532 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
533 struct bound_addr
*addr
;
534 struct bound_addr
*t_addr
;
536 if (pending_signal_handle
) {
538 * This check is done to ensure that a SIGUSR1 signal to re-read the configuration file
539 * is completed before calling a connect. This is to fix the issue seen in (rdar://problem/25641686)
542 pending_signal_handle
= 0;
545 plog(ASL_LEVEL_NOTICE
,
546 "received connect command on vpn control socket.\n");
547 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
548 if (pkt
->address
== addr
->address
) {
549 /* start the connection */
550 error
= vpn_connect(addr
, VPN_STARTED_BY_API
);
557 case VPNCTL_CMD_DISCONNECT
:
559 if (combuf_len
< sizeof(struct vpnctl_cmd_connect
)) {
560 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl disconnect cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_connect
));
565 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
566 struct bound_addr
*addr
;
567 struct bound_addr
*t_addr
;
569 plog(ASL_LEVEL_NOTICE
,
570 "received disconnect command on vpn control socket.\n");
571 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
572 if (pkt
->address
== addr
->address
) {
573 /* stop the connection */
574 error
= vpn_disconnect(addr
, ike_session_stopped_by_vpn_disconnect
);
581 case VPNCTL_CMD_START_PH2
:
583 if (combuf_len
< sizeof(struct vpnctl_cmd_start_ph2
)) {
584 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl start ph2 cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_start_ph2
));
589 struct vpnctl_cmd_start_ph2
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_start_ph2
*)combuf
;
590 struct bound_addr
*addr
;
591 struct bound_addr
*t_addr
;
593 plog(ASL_LEVEL_NOTICE
, "received start_ph2 command on vpn control socket.\n");
594 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
595 if (pkt
->address
== addr
->address
) {
596 /* start the connection */
597 error
= vpn_start_ph2(addr
, pkt
, combuf_len
);
604 case VPNCTL_CMD_START_DPD
:
606 if (combuf_len
< sizeof(struct vpnctl_cmd_start_dpd
)) {
607 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl start dpd cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_start_dpd
));
612 struct vpnctl_cmd_start_dpd
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_start_dpd
*)combuf
;
613 struct bound_addr
*srv
;
614 struct bound_addr
*t_addr
;
616 plog(ASL_LEVEL_NOTICE
,
617 "received start_dpd command on vpn control socket.\n");
618 LIST_FOREACH_SAFE(srv
, &elem
->bound_addresses
, chain
, t_addr
) {
619 if (pkt
->address
== srv
->address
) {
620 union { // Wcast-align fix - force alignment
621 struct sockaddr_storage ss
;
622 struct sockaddr_in addr_in
;
625 bzero(&daddr
, sizeof(struct sockaddr_in
));
626 daddr
.addr_in
.sin_len
= sizeof(struct sockaddr_in
);
627 daddr
.addr_in
.sin_addr
.s_addr
= srv
->address
;
628 daddr
.addr_in
.sin_port
= 0;
629 daddr
.addr_in
.sin_family
= AF_INET
;
632 error
= ike_session_ph1_force_dpd(&daddr
.ss
);
639 case VPNCTL_CMD_ASSERT
:
641 if (combuf_len
< sizeof(struct vpnctl_cmd_assert
)) {
642 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl assert cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_assert
));
647 struct vpnctl_cmd_assert
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_assert
*)combuf
;
648 // struct bound_addr *addr;
649 // struct bound_addr *t_addr;
650 struct sockaddr_in saddr
;
651 struct sockaddr_in daddr
;
653 plogdump(ASL_LEVEL_NOTICE
, pkt
, ntohs(hdr
->len
) + sizeof(struct vpnctl_hdr
), "received assert command on vpn control socket.\n");
654 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
655 // if (pkt->dst_address == addr->address) {
656 bzero(&saddr
, sizeof(saddr
));
657 saddr
.sin_len
= sizeof(saddr
);
658 saddr
.sin_addr
.s_addr
= pkt
->src_address
;
660 saddr
.sin_family
= AF_INET
;
661 bzero(&daddr
, sizeof(daddr
));
662 daddr
.sin_len
= sizeof(daddr
);
663 daddr
.sin_addr
.s_addr
= pkt
->dst_address
;
665 daddr
.sin_family
= AF_INET
;
667 error
= vpn_assert(ALIGNED_CAST(struct sockaddr_storage
*)&saddr
, ALIGNED_CAST(struct sockaddr_storage
*)&daddr
);
674 case VPNCTL_CMD_RECONNECT
:
676 if (combuf_len
< sizeof(struct vpnctl_cmd_connect
)) {
677 plog(ASL_LEVEL_ERR
, "invalid header length for vpnctl reconnect cmd - len=%ld - expected %ld\n", combuf_len
, sizeof(struct vpnctl_cmd_connect
));
682 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
683 struct bound_addr
*addr
;
684 struct bound_addr
*t_addr
;
686 plog(ASL_LEVEL_NOTICE
,
687 "received reconnect command on vpn control socket.\n");
688 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
689 if (pkt
->address
== addr
->address
) {
690 /* start the connection */
691 error
= vpn_connect(addr
, VPN_RESTARTED_BY_API
);
700 "invalid command: %d\n", ntohs(hdr
->msg_type
));
701 error
= -1; // for now
706 hdr
->result
= htons(error
);
707 if (vpncontrol_reply(elem
->sock
, combuf
) < 0)
715 vpncontrol_reply(int so
, char *combuf
)
719 tlen
= send(so
, combuf
, sizeof(struct vpnctl_hdr
), 0);
722 "failed to send vpn_control message: %s\n", strerror(errno
));
730 vpncontrol_set_nat64_prefix(nw_nat64_prefix_t
*prefix
)
732 struct vpnctl_socket_elem
*sock_elem
;
733 struct bound_addr
*bound_addr
;
735 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
736 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
737 if (bound_addr
->nat64_prefix
.length
!= 0) {
738 memcpy(prefix
, &bound_addr
->nat64_prefix
, sizeof(*prefix
));
747 vpncontrol_notify_need_authinfo(phase1_handle_t
*iph1
, void* attr_list
, size_t attr_len
)
749 struct vpnctl_status_need_authinfo
*msg
= NULL
;
750 struct vpnctl_socket_elem
*sock_elem
;
751 struct bound_addr
*bound_addr
;
760 plog(ASL_LEVEL_NOTICE
,
761 "sending vpn_control xauth need info status\n");
763 msg
= (struct vpnctl_status_need_authinfo
*)racoon_malloc(msg_size
= sizeof(struct vpnctl_status_need_authinfo
) + attr_len
);
766 "unable to allocate space for vpn control message.\n");
771 address
= iph1_get_remote_v4_address(iph1
);
776 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
777 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
778 if (!ike_session_is_client_ph1_rekey(iph1
)) {
779 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_AUTHINFO
);
781 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_REAUTHINFO
);
783 msg
->address
= iph1_get_remote_v4_address(iph1
);
785 memcpy(ptr
, attr_list
, attr_len
);
787 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
788 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
789 if (bound_addr
->address
== 0xFFFFFFFF ||
790 bound_addr
->address
== address
) {
791 plog(ASL_LEVEL_DEBUG
, "vpn control writing %zu bytes\n", msg_size
);
792 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
795 "failed to send vpn_control need authinfo status: %s\n", strerror(errno
));
809 vpncontrol_notify_ike_failed(u_int16_t notify_code
, u_int16_t from
, u_int32_t address
, u_int16_t data_len
, u_int8_t
*data
)
811 struct vpnctl_status_failed
*msg
= NULL
;
812 struct vpnctl_socket_elem
*sock_elem
;
813 struct bound_addr
*bound_addr
;
817 len
= sizeof(struct vpnctl_status_failed
) + data_len
;
819 msg
= (struct vpnctl_status_failed
*)racoon_malloc(len
);
822 "unable to allcate memory for vpn control status message.\n");
826 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_IKE_FAILED
);
827 msg
->hdr
.flags
= msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
828 msg
->hdr
.len
= htons(len
- sizeof(struct vpnctl_hdr
));
829 msg
->address
= address
;
830 msg
->ike_code
= htons(notify_code
);
831 msg
->from
= htons(from
);
833 memcpy(msg
->data
, data
, data_len
);
835 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code
,
836 (from
== FROM_LOCAL
? "local" : "remote"));
838 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
839 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
840 if (bound_addr
->address
== 0xFFFFFFFF ||
841 bound_addr
->address
== address
) {
842 tlen
= send(sock_elem
->sock
, msg
, len
, 0);
845 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno
));
847 plog(ASL_LEVEL_DEBUG
,
848 "Sent %zd/%zu bytes\n", tlen
, len
);
861 vpncontrol_status_2_str(u_int16_t msg_type
)
864 case VPNCTL_STATUS_IKE_FAILED
:
866 case VPNCTL_STATUS_PH1_START_US
:
867 return "Phase 1 started by us";
868 case VPNCTL_STATUS_PH1_START_PEER
:
869 return "Phase 1 started by peer";
870 case VPNCTL_STATUS_PH1_ESTABLISHED
:
871 return "Phase 1 established";
872 case VPNCTL_STATUS_PH2_START
:
873 return "Phase 2 started";
874 case VPNCTL_STATUS_PH2_ESTABLISHED
:
875 return "Phase 2 established";
876 case VPNCTL_STATUS_NEED_AUTHINFO
:
877 return "Need authentication info";
878 case VPNCTL_STATUS_NEED_REAUTHINFO
:
879 return "Need re-authentication info";
887 vpncontrol_notify_phase_change(int start
, u_int16_t from
, phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
889 struct vpnctl_status_phase_change
*msg
;
890 struct vpnctl_socket_elem
*sock_elem
;
891 struct bound_addr
*bound_addr
;
896 if (iph1
&& !start
&& iph1
->mode_cfg
&& iph1
->mode_cfg
->xauth
.status
!= XAUTHST_OK
) {
897 if (vpn_get_config(iph1
, &msg
, &msg_size
) == 1)
898 return 0; /* mode config not finished yet */
900 msg
= racoon_malloc(msg_size
= sizeof(struct vpnctl_status_phase_change
));
906 "unable to allocate space for vpn control message.\n");
910 address
= iph1_get_remote_v4_address(iph1
);
912 plog(ASL_LEVEL_ERR
, "bad address for ph1 status change.\n");
915 msg
->hdr
.msg_type
= htons(start
?
916 (from
== FROM_LOCAL
? VPNCTL_STATUS_PH1_START_US
: VPNCTL_STATUS_PH1_START_PEER
)
917 : VPNCTL_STATUS_PH1_ESTABLISHED
);
918 // TODO: indicate version
920 address
= iph2_get_remote_v4_address(iph2
);
922 plog(ASL_LEVEL_ERR
, "bad address for ph2 status change.\n");
925 msg
->hdr
.msg_type
= htons(start
? VPNCTL_STATUS_PH2_START
: VPNCTL_STATUS_PH2_ESTABLISHED
);
926 // TODO: indicate version
928 plog(ASL_LEVEL_NOTICE
,
929 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg
->hdr
.msg_type
)));
931 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
932 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
933 msg
->address
= address
;
935 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
936 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
937 if (bound_addr
->address
== 0xFFFFFFFF ||
938 bound_addr
->address
== address
) {
939 plog(ASL_LEVEL_DEBUG
, "vpn control writing %zu bytes\n", msg_size
);
940 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
943 "failed to send vpn_control phase change status: %s\n", strerror(errno
));
957 vpncontrol_notify_peer_resp (u_int16_t notify_code
, u_int32_t address
)
959 struct vpnctl_status_peer_resp msg
;
960 struct vpnctl_socket_elem
*sock_elem
;
961 struct bound_addr
*bound_addr
;
965 bzero(&msg
, sizeof(msg
));
966 msg
.hdr
.msg_type
= htons(VPNCTL_STATUS_PEER_RESP
);
967 msg
.hdr
.cookie
= msg
.hdr
.reserved
= msg
.hdr
.result
= 0;
968 msg
.hdr
.len
= htons(sizeof(msg
) - sizeof(msg
.hdr
));
969 msg
.address
= address
;
970 msg
.ike_code
= notify_code
;
971 plog(ASL_LEVEL_NOTICE
,
972 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code
, address
);
974 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
975 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
976 if (bound_addr
->address
== 0xFFFFFFFF ||
977 bound_addr
->address
== address
) {
978 tlen
= send(sock_elem
->sock
, &msg
, sizeof(msg
), 0);
981 "unable to send vpn_control status (peer response): %s\n", strerror(errno
));
994 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code
, phase1_handle_t
*iph1
)
996 if (iph1
&& iph1
->parent_session
&& iph1
->parent_session
->controller_awaiting_peer_resp
) {
998 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, iph1_get_remote_v4_address(iph1
))) == 0) {
999 iph1
->parent_session
->controller_awaiting_peer_resp
= 0;
1008 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code
, phase2_handle_t
*iph2
)
1010 if (iph2
&& iph2
->parent_session
&& iph2
->parent_session
->controller_awaiting_peer_resp
) {
1012 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, iph2_get_remote_v4_address(iph2
))) == 0) {
1013 iph2
->parent_session
->controller_awaiting_peer_resp
= 0;
1022 vpncontrol_init(void)
1026 if (vpncontrolsock_path
== NULL
) {
1027 lcconf
->sock_vpncontrol
= -1;
1031 if ( (lcconf
->sock_vpncontrol
= checklaunchd()) == 0 ) {
1032 memset(&sunaddr
, 0, sizeof(sunaddr
));
1033 sunaddr
.sun_family
= AF_UNIX
;
1034 snprintf(sunaddr
.sun_path
, sizeof(sunaddr
.sun_path
),
1035 "%s", vpncontrolsock_path
);
1037 lcconf
->sock_vpncontrol
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1038 if (lcconf
->sock_vpncontrol
== -1) {
1040 "socket: %s\n", strerror(errno
));
1044 if (fcntl(lcconf
->sock_vpncontrol
, F_SETFL
, O_NONBLOCK
) == -1) {
1045 plog(ASL_LEVEL_ERR
, "failed to put VPN-Control socket in non-blocking mode\n");
1048 unlink(sunaddr
.sun_path
);
1049 if (bind(lcconf
->sock_vpncontrol
, (struct sockaddr
*)&sunaddr
,
1050 sizeof(sunaddr
)) != 0) {
1052 "bind(sockname:%s): %s\n",
1053 sunaddr
.sun_path
, strerror(errno
));
1054 (void)close(lcconf
->sock_vpncontrol
);
1058 if (chown(sunaddr
.sun_path
, vpncontrolsock_owner
, vpncontrolsock_group
) != 0) {
1060 "chown(%s, %d, %d): %s\n",
1061 sunaddr
.sun_path
, vpncontrolsock_owner
,
1062 vpncontrolsock_group
, strerror(errno
));
1063 (void)close(lcconf
->sock_vpncontrol
);
1067 if (chmod(sunaddr
.sun_path
, vpncontrolsock_mode
) != 0) {
1069 "chmod(%s, 0%03o): %s\n",
1070 sunaddr
.sun_path
, vpncontrolsock_mode
, strerror(errno
));
1071 (void)close(lcconf
->sock_vpncontrol
);
1075 if (listen(lcconf
->sock_vpncontrol
, 5) != 0) {
1077 "listen(sockname:%s): %s\n",
1078 sunaddr
.sun_path
, strerror(errno
));
1079 (void)close(lcconf
->sock_vpncontrol
);
1082 plog(ASL_LEVEL_NOTICE
,
1083 "opened %s as racoon management.\n", sunaddr
.sun_path
);
1085 lcconf
->vpncontrol_source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_READ
, lcconf
->sock_vpncontrol
, 0, dispatch_get_main_queue());
1086 if (lcconf
->vpncontrol_source
== NULL
) {
1087 plog(ASL_LEVEL_ERR
, "could not create vpncontrol socket source.");
1090 dispatch_source_set_event_handler_f(lcconf
->vpncontrol_source
, vpncontrol_handler
);
1091 sock
= lcconf
->sock_vpncontrol
;
1092 dispatch_source_set_cancel_handler(lcconf
->vpncontrol_source
,
1096 dispatch_resume(lcconf
->vpncontrol_source
);
1101 vpncontrol_disconnect_all(struct vpnctl_socket_elem
*elem
, const char *reason
)
1103 struct bound_addr
*addr
;
1104 struct bound_addr
*t_addr
;
1106 plog(ASL_LEVEL_NOTICE
,
1107 "received disconnect all command.\n");
1109 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
1110 /* stop any connections */
1111 vpn_disconnect(addr
, reason
);
1118 struct vpnctl_socket_elem
*elem
;
1119 struct vpnctl_socket_elem
*t_elem
;
1121 plog(ASL_LEVEL_NOTICE
,
1122 "vpncontrol_close.\n");
1124 dispatch_source_cancel(lcconf
->vpncontrol_source
);
1125 lcconf
->vpncontrol_source
= NULL
;
1127 lcconf
->sock_vpncontrol
= -1;
1128 LIST_FOREACH_SAFE(elem
, &lcconf
->vpnctl_comm_socks
, chain
, t_elem
)
1129 vpncontrol_close_comm(elem
);
1133 vpncontrol_close_comm(struct vpnctl_socket_elem
*elem
)
1135 struct bound_addr
*addr
;
1136 struct bound_addr
*t_addr
;
1138 plog(ASL_LEVEL_NOTICE
,
1139 "vpncontrol_close_comm.\n");
1141 LIST_REMOVE(elem
, chain
);
1142 if (elem
->sock
!= -1) {
1143 dispatch_source_cancel(elem
->source
);
1146 if (elem
->buffer
!= NULL
) {
1148 elem
->buffer
= NULL
;
1149 elem
->pending_bytes_len
= 0;
1150 elem
->read_bytes_len
= 0;
1152 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
1153 flushsainfo_dynamic(addr
->address
);
1154 LIST_REMOVE(addr
, chain
);
1156 vfree(addr
->version
);
1165 vpn_control_connected(void)
1167 if (LIST_EMPTY(&lcconf
->vpnctl_comm_socks
))