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 *);
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
))))
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_malloc(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
;
278 /* get buffer length */
279 while ((len
= recv(elem
->sock
, (char *)&hdr
, sizeof(hdr
), MSG_PEEK
)) < 0) {
283 "failed to recv vpn_control command: %s\n", strerror(errno
));
287 plog(ASL_LEVEL_DEBUG
,
288 "vpn_control socket closed by peer.\n");
289 /* kill all related connections */
290 vpncontrol_disconnect_all(elem
, ike_session_stopped_by_controller_comm_lost
);
291 vpncontrol_close_comm(elem
);
292 return; // %%%%%% terminate
296 if (len
< sizeof(hdr
)) {
298 "invalid header length of vpn_control command - len=%ld - expected %ld\n", len
, sizeof(hdr
));
302 /* get buffer to receive */
303 if ((combuf
= racoon_malloc(ntohs(hdr
.len
) + sizeof(hdr
))) == 0) {
305 "failed to alloc buffer for vpn_control command\n");
310 while ((len
= recv(elem
->sock
, combuf
, ntohs(hdr
.len
) + sizeof(hdr
), 0)) < 0) {
314 "failed to recv vpn_control command: %s\n",
319 (void)vpncontrol_process(elem
, combuf
);
328 vpncontrol_process(struct vpnctl_socket_elem
*elem
, char *combuf
)
331 struct vpnctl_hdr
*hdr
= ALIGNED_CAST(struct vpnctl_hdr
*)combuf
;
333 switch (ntohs(hdr
->msg_type
)) {
335 case VPNCTL_CMD_BIND
:
337 struct vpnctl_cmd_bind
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_bind
*)combuf
;
338 struct bound_addr
*addr
;
340 plog(ASL_LEVEL_DEBUG
,
341 "received bind command on vpn control socket.\n");
342 addr
= racoon_calloc(1, sizeof(struct bound_addr
));
345 "memory error: %s\n", strerror(errno
));
349 if (ntohs(pkt
->vers_len
)) {
350 addr
->version
= vmalloc(ntohs(pkt
->vers_len
));
351 if (addr
->version
== NULL
) {
353 "memory error: %s\n", strerror(errno
));
357 memcpy(addr
->version
->v
, pkt
+ 1, ntohs(pkt
->vers_len
));
359 addr
->address
= pkt
->address
;
360 LIST_INSERT_HEAD(&elem
->bound_addresses
, addr
, chain
);
361 lcconf
->auto_exit_state
|= LC_AUTOEXITSTATE_CLIENT
; /* client side */
365 case VPNCTL_CMD_UNBIND
:
367 struct vpnctl_cmd_unbind
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_unbind
*)combuf
;
368 struct bound_addr
*addr
;
369 struct bound_addr
*t_addr
;
371 plog(ASL_LEVEL_DEBUG
,
372 "received unbind command on vpn control socket.\n");
373 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
374 if (pkt
->address
== 0xFFFFFFFF ||
375 pkt
->address
== addr
->address
) {
376 flushsainfo_dynamic(addr
->address
);
377 LIST_REMOVE(addr
, chain
);
379 vfree(addr
->version
);
386 case VPNCTL_CMD_REDIRECT
:
388 struct vpnctl_cmd_redirect
*redirect_msg
= ALIGNED_CAST(struct vpnctl_cmd_redirect
*)combuf
;
389 struct redirect
*raddr
;
390 struct redirect
*t_raddr
;
393 plog(ASL_LEVEL_DEBUG
,
394 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg
->redirect_address
));
396 LIST_FOREACH_SAFE(raddr
, &lcconf
->redirect_addresses
, chain
, t_raddr
) {
397 if (raddr
->cluster_address
== redirect_msg
->address
) {
398 if (redirect_msg
->redirect_address
== 0) {
399 LIST_REMOVE(raddr
, chain
);
402 raddr
->redirect_address
= redirect_msg
->redirect_address
;
403 raddr
->force
= ntohs(redirect_msg
->force
);
410 raddr
= racoon_malloc(sizeof(struct redirect
));
412 plog(ASL_LEVEL_DEBUG
,
413 "cannot allcoate memory for redirect address.\n");
417 raddr
->cluster_address
= redirect_msg
->address
;
418 raddr
->redirect_address
= redirect_msg
->redirect_address
;
419 raddr
->force
= ntohs(redirect_msg
->force
);
420 LIST_INSERT_HEAD(&lcconf
->redirect_addresses
, raddr
, chain
);
426 case VPNCTL_CMD_PING
:
427 break; /* just reply for now */
429 case VPNCTL_CMD_XAUTH_INFO
:
431 struct vpnctl_cmd_xauth_info
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_xauth_info
*)combuf
;
432 struct bound_addr
*addr
;
433 struct bound_addr
*t_addr
;
436 plog(ASL_LEVEL_DEBUG
,
437 "received xauth info command vpn control socket.\n");
438 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
439 if (pkt
->address
== addr
->address
) {
440 /* reply to the last xauth request */
442 error
= vpn_xauth_reply(pkt
->address
, attr_list
, ntohs(pkt
->hdr
.len
) - sizeof(u_int32_t
));
449 case VPNCTL_CMD_CONNECT
:
451 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
452 struct bound_addr
*addr
;
453 struct bound_addr
*t_addr
;
455 plog(ASL_LEVEL_DEBUG
,
456 "received connect command on vpn control socket.\n");
457 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
458 if (pkt
->address
== addr
->address
) {
459 /* start the connection */
460 error
= vpn_connect(addr
, VPN_STARTED_BY_API
);
467 case VPNCTL_CMD_DISCONNECT
:
469 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
470 struct bound_addr
*addr
;
471 struct bound_addr
*t_addr
;
473 plog(ASL_LEVEL_DEBUG
,
474 "received disconnect command on vpn control socket.\n");
475 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
476 if (pkt
->address
== addr
->address
) {
477 /* stop the connection */
478 error
= vpn_disconnect(addr
, ike_session_stopped_by_vpn_disconnect
);
485 case VPNCTL_CMD_START_PH2
:
487 struct vpnctl_cmd_start_ph2
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_start_ph2
*)combuf
;
488 struct bound_addr
*addr
;
489 struct bound_addr
*t_addr
;
491 plog(ASL_LEVEL_DEBUG
, "received start_ph2 command on vpn control socket.\n");
492 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
493 if (pkt
->address
== addr
->address
) {
494 /* start the connection */
495 error
= vpn_start_ph2(addr
, pkt
);
502 case VPNCTL_CMD_START_DPD
:
504 struct vpnctl_cmd_start_dpd
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_start_dpd
*)combuf
;
505 struct bound_addr
*srv
;
506 struct bound_addr
*t_addr
;
508 plog(ASL_LEVEL_DEBUG
,
509 "received start_dpd command on vpn control socket.\n");
510 LIST_FOREACH_SAFE(srv
, &elem
->bound_addresses
, chain
, t_addr
) {
511 if (pkt
->address
== srv
->address
) {
512 union { // Wcast-align fix - force alignment
513 struct sockaddr_storage ss
;
514 struct sockaddr_in addr_in
;
517 bzero(&daddr
, sizeof(struct sockaddr_in
));
518 daddr
.addr_in
.sin_len
= sizeof(struct sockaddr_in
);
519 daddr
.addr_in
.sin_addr
.s_addr
= srv
->address
;
520 daddr
.addr_in
.sin_port
= 0;
521 daddr
.addr_in
.sin_family
= AF_INET
;
524 error
= ike_session_ph1_force_dpd(&daddr
.ss
);
531 case VPNCTL_CMD_ASSERT
:
533 struct vpnctl_cmd_assert
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_assert
*)combuf
;
534 // struct bound_addr *addr;
535 // struct bound_addr *t_addr;
536 struct sockaddr_in saddr
;
537 struct sockaddr_in daddr
;
539 plogdump(ASL_LEVEL_DEBUG
, pkt
, ntohs(hdr
->len
) + sizeof(struct vpnctl_hdr
), "received assert command on vpn control socket.\n");
540 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
541 // if (pkt->dst_address == addr->address) {
542 bzero(&saddr
, sizeof(saddr
));
543 saddr
.sin_len
= sizeof(saddr
);
544 saddr
.sin_addr
.s_addr
= pkt
->src_address
;
546 saddr
.sin_family
= AF_INET
;
547 bzero(&daddr
, sizeof(daddr
));
548 daddr
.sin_len
= sizeof(daddr
);
549 daddr
.sin_addr
.s_addr
= pkt
->dst_address
;
551 daddr
.sin_family
= AF_INET
;
553 error
= vpn_assert((struct sockaddr_storage
*)&saddr
, (struct sockaddr_storage
*)&daddr
);
560 case VPNCTL_CMD_RECONNECT
:
562 struct vpnctl_cmd_connect
*pkt
= ALIGNED_CAST(struct vpnctl_cmd_connect
*)combuf
;
563 struct bound_addr
*addr
;
564 struct bound_addr
*t_addr
;
566 plog(ASL_LEVEL_DEBUG
,
567 "received reconnect command on vpn control socket.\n");
568 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
569 if (pkt
->address
== addr
->address
) {
570 /* start the connection */
571 error
= vpn_connect(addr
, VPN_RESTARTED_BY_API
);
580 "invalid command: %d\n", ntohs(hdr
->msg_type
));
581 error
= -1; // for now
586 hdr
->result
= htons(error
);
587 if (vpncontrol_reply(elem
->sock
, combuf
) < 0)
595 vpncontrol_reply(int so
, char *combuf
)
599 tlen
= send(so
, combuf
, sizeof(struct vpnctl_hdr
), 0);
602 "failed to send vpn_control message: %s\n", strerror(errno
));
610 vpncontrol_notify_need_authinfo(phase1_handle_t
*iph1
, void* attr_list
, size_t attr_len
)
612 struct vpnctl_status_need_authinfo
*msg
= NULL
;
613 struct vpnctl_socket_elem
*sock_elem
;
614 struct bound_addr
*bound_addr
;
623 plog(ASL_LEVEL_DEBUG
,
624 "sending vpn_control xauth need info status\n");
626 msg
= (struct vpnctl_status_need_authinfo
*)racoon_malloc(msg_size
= sizeof(struct vpnctl_status_need_authinfo
) + attr_len
);
629 "unable to allocate space for vpn control message.\n");
634 if (iph1
->remote
->ss_family
== AF_INET
)
635 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
639 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
640 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
641 if (!ike_session_is_client_ph1_rekey(iph1
)) {
642 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_AUTHINFO
);
644 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_REAUTHINFO
);
646 msg
->address
= address
;
648 memcpy(ptr
, attr_list
, attr_len
);
650 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
651 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
652 if (bound_addr
->address
== 0xFFFFFFFF ||
653 bound_addr
->address
== address
) {
654 plog(ASL_LEVEL_DEBUG
, "vpn control writing %zu bytes\n", msg_size
);
655 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
658 "failed to send vpn_control need authinfo status: %s\n", strerror(errno
));
672 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
)
674 struct vpnctl_status_failed
*msg
= NULL
;
675 struct vpnctl_socket_elem
*sock_elem
;
676 struct bound_addr
*bound_addr
;
680 len
= sizeof(struct vpnctl_status_failed
) + data_len
;
682 msg
= (struct vpnctl_status_failed
*)racoon_malloc(len
);
684 plog(ASL_LEVEL_DEBUG
,
685 "unable to allcate memory for vpn control status message.\n");
689 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_IKE_FAILED
);
690 msg
->hdr
.flags
= msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
691 msg
->hdr
.len
= htons(len
- sizeof(struct vpnctl_hdr
));
692 msg
->address
= address
;
693 msg
->ike_code
= htons(notify_code
);
694 msg
->from
= htons(from
);
696 memcpy(msg
->data
, data
, data_len
);
697 plog(ASL_LEVEL_DEBUG
,
698 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code
,
699 (from
== FROM_LOCAL
? "local" : "remote"));
701 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
702 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
703 if (bound_addr
->address
== 0xFFFFFFFF ||
704 bound_addr
->address
== address
) {
705 tlen
= send(sock_elem
->sock
, msg
, len
, 0);
708 "Unable to send vpn_control ike notify failed: %s\n", strerror(errno
));
721 vpncontrol_status_2_str(u_int16_t msg_type
)
724 case VPNCTL_STATUS_IKE_FAILED
:
726 case VPNCTL_STATUS_PH1_START_US
:
727 return "Phase 1 started by us";
728 case VPNCTL_STATUS_PH1_START_PEER
:
729 return "Phase 1 started by peer";
730 case VPNCTL_STATUS_PH1_ESTABLISHED
:
731 return "Phase 1 established";
732 case VPNCTL_STATUS_PH2_START
:
733 return "Phase 2 started";
734 case VPNCTL_STATUS_PH2_ESTABLISHED
:
735 return "Phase 2 established";
736 case VPNCTL_STATUS_NEED_AUTHINFO
:
737 return "Need authentication info";
738 case VPNCTL_STATUS_NEED_REAUTHINFO
:
739 return "Need re-authentication info";
747 vpncontrol_notify_phase_change(int start
, u_int16_t from
, phase1_handle_t
*iph1
, phase2_handle_t
*iph2
)
749 struct vpnctl_status_phase_change
*msg
;
750 struct vpnctl_socket_elem
*sock_elem
;
751 struct bound_addr
*bound_addr
;
756 if (iph1
&& !start
&& iph1
->mode_cfg
&& iph1
->mode_cfg
->xauth
.status
!= XAUTHST_OK
) {
757 if (vpn_get_config(iph1
, &msg
, &msg_size
) == 1)
758 return 0; /* mode config not finished yet */
760 msg
= racoon_malloc(msg_size
= sizeof(struct vpnctl_status_phase_change
));
766 "unable to allocate space for vpn control message.\n");
770 if (iph1
->remote
->ss_family
== AF_INET
)
771 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
774 msg
->hdr
.msg_type
= htons(start
?
775 (from
== FROM_LOCAL
? VPNCTL_STATUS_PH1_START_US
: VPNCTL_STATUS_PH1_START_PEER
)
776 : VPNCTL_STATUS_PH1_ESTABLISHED
);
777 // TODO: indicate version
779 if (iph2
->dst
->ss_family
== AF_INET
)
780 address
= ((struct sockaddr_in
*)iph2
->dst
)->sin_addr
.s_addr
;
783 msg
->hdr
.msg_type
= htons(start
? VPNCTL_STATUS_PH2_START
: VPNCTL_STATUS_PH2_ESTABLISHED
);
784 // TODO: indicate version
786 plog(ASL_LEVEL_NOTICE
,
787 ">>>>> phase change status = %s\n", vpncontrol_status_2_str(ntohs(msg
->hdr
.msg_type
)));
789 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
790 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
791 msg
->address
= address
;
793 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
794 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
795 if (bound_addr
->address
== 0xFFFFFFFF ||
796 bound_addr
->address
== address
) {
797 plog(ASL_LEVEL_DEBUG
, "vpn control writing %zu bytes\n", msg_size
);
798 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
801 "failed to send vpn_control phase change status: %s\n", strerror(errno
));
815 vpncontrol_notify_peer_resp (u_int16_t notify_code
, u_int32_t address
)
817 struct vpnctl_status_peer_resp msg
;
818 struct vpnctl_socket_elem
*sock_elem
;
819 struct bound_addr
*bound_addr
;
823 bzero(&msg
, sizeof(msg
));
824 msg
.hdr
.msg_type
= htons(VPNCTL_STATUS_PEER_RESP
);
825 msg
.hdr
.cookie
= msg
.hdr
.reserved
= msg
.hdr
.result
= 0;
826 msg
.hdr
.len
= htons(sizeof(msg
) - sizeof(msg
.hdr
));
827 msg
.address
= address
;
828 msg
.ike_code
= notify_code
;
829 plog(ASL_LEVEL_DEBUG
,
830 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code
, address
);
832 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
833 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
834 if (bound_addr
->address
== 0xFFFFFFFF ||
835 bound_addr
->address
== address
) {
836 tlen
= send(sock_elem
->sock
, &msg
, sizeof(msg
), 0);
839 "unable to send vpn_control status (peer response): %s\n", strerror(errno
));
852 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code
, phase1_handle_t
*iph1
)
857 if (iph1
&& iph1
->parent_session
&& iph1
->parent_session
->controller_awaiting_peer_resp
) {
858 if (iph1
->remote
->ss_family
== AF_INET
)
859 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
866 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, address
)) == 0) {
867 iph1
->parent_session
->controller_awaiting_peer_resp
= 0;
873 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code
, phase2_handle_t
*iph2
)
878 if (iph2
&& iph2
->parent_session
&& iph2
->parent_session
->controller_awaiting_peer_resp
) {
879 if (iph2
->dst
->ss_family
== AF_INET
)
880 address
= ((struct sockaddr_in
*)iph2
->dst
)->sin_addr
.s_addr
;
887 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, address
)) == 0) {
888 iph2
->parent_session
->controller_awaiting_peer_resp
= 0;
894 vpncontrol_init(void)
898 if (vpncontrolsock_path
== NULL
) {
899 lcconf
->sock_vpncontrol
= -1;
903 if ( (lcconf
->sock_vpncontrol
= checklaunchd()) == 0 ) {
904 memset(&sunaddr
, 0, sizeof(sunaddr
));
905 sunaddr
.sun_family
= AF_UNIX
;
906 snprintf(sunaddr
.sun_path
, sizeof(sunaddr
.sun_path
),
907 "%s", vpncontrolsock_path
);
909 lcconf
->sock_vpncontrol
= socket(AF_UNIX
, SOCK_STREAM
, 0);
910 if (lcconf
->sock_vpncontrol
== -1) {
912 "socket: %s\n", strerror(errno
));
916 if (fcntl(lcconf
->sock_vpncontrol
, F_SETFL
, O_NONBLOCK
) == -1) {
917 plog(ASL_LEVEL_ERR
, "failed to put VPN-Control socket in non-blocking mode\n");
920 unlink(sunaddr
.sun_path
);
921 if (bind(lcconf
->sock_vpncontrol
, (struct sockaddr
*)&sunaddr
,
922 sizeof(sunaddr
)) != 0) {
924 "bind(sockname:%s): %s\n",
925 sunaddr
.sun_path
, strerror(errno
));
926 (void)close(lcconf
->sock_vpncontrol
);
930 if (chown(sunaddr
.sun_path
, vpncontrolsock_owner
, vpncontrolsock_group
) != 0) {
932 "chown(%s, %d, %d): %s\n",
933 sunaddr
.sun_path
, vpncontrolsock_owner
,
934 vpncontrolsock_group
, strerror(errno
));
935 (void)close(lcconf
->sock_vpncontrol
);
939 if (chmod(sunaddr
.sun_path
, vpncontrolsock_mode
) != 0) {
941 "chmod(%s, 0%03o): %s\n",
942 sunaddr
.sun_path
, vpncontrolsock_mode
, strerror(errno
));
943 (void)close(lcconf
->sock_vpncontrol
);
947 if (listen(lcconf
->sock_vpncontrol
, 5) != 0) {
949 "listen(sockname:%s): %s\n",
950 sunaddr
.sun_path
, strerror(errno
));
951 (void)close(lcconf
->sock_vpncontrol
);
954 plog(ASL_LEVEL_DEBUG
,
955 "opened %s as racoon management.\n", sunaddr
.sun_path
);
957 lcconf
->vpncontrol_source
= dispatch_source_create(DISPATCH_SOURCE_TYPE_READ
, lcconf
->sock_vpncontrol
, 0, dispatch_get_main_queue());
958 if (lcconf
->vpncontrol_source
== NULL
) {
959 plog(ASL_LEVEL_ERR
, "could not create vpncontrol socket source.");
962 dispatch_source_set_event_handler_f(lcconf
->vpncontrol_source
, vpncontrol_handler
);
963 sock
= lcconf
->sock_vpncontrol
;
964 dispatch_source_set_cancel_handler(lcconf
->vpncontrol_source
,
968 dispatch_resume(lcconf
->vpncontrol_source
);
973 vpncontrol_disconnect_all(struct vpnctl_socket_elem
*elem
, const char *reason
)
975 struct bound_addr
*addr
;
976 struct bound_addr
*t_addr
;
978 plog(ASL_LEVEL_DEBUG
,
979 "received disconnect all command.\n");
981 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
982 /* stop any connections */
983 vpn_disconnect(addr
, reason
);
990 struct vpnctl_socket_elem
*elem
;
991 struct vpnctl_socket_elem
*t_elem
;
993 plog(ASL_LEVEL_DEBUG
,
994 "vpncontrol_close.\n");
996 dispatch_source_cancel(lcconf
->vpncontrol_source
);
997 lcconf
->vpncontrol_source
= NULL
;
999 lcconf
->sock_vpncontrol
= -1;
1000 LIST_FOREACH_SAFE(elem
, &lcconf
->vpnctl_comm_socks
, chain
, t_elem
)
1001 vpncontrol_close_comm(elem
);
1005 vpncontrol_close_comm(struct vpnctl_socket_elem
*elem
)
1007 struct bound_addr
*addr
;
1008 struct bound_addr
*t_addr
;
1010 plog(ASL_LEVEL_DEBUG
,
1011 "vpncontrol_close_comm.\n");
1013 LIST_REMOVE(elem
, chain
);
1014 if (elem
->sock
!= -1)
1015 dispatch_source_cancel(elem
->source
);
1016 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
1017 flushsainfo_dynamic(addr
->address
);
1018 LIST_REMOVE(addr
, chain
);
1020 vfree(addr
->version
);
1029 vpn_control_connected(void)
1031 if (LIST_EMPTY(&lcconf
->vpnctl_comm_socks
))