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
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/socket.h>
59 #include <sys/signal.h>
63 #include <System/net/pfkeyv2.h>
65 #include <netinet/in.h>
66 #ifndef HAVE_NETINET6_IPSEC
67 #include <netinet/ipsec.h>
69 #include <netinet6/ipsec.h>
91 #include "localconf.h"
92 #include "remoteconf.h"
93 #include "grabmyaddr.h"
94 #include "isakmp_var.h"
100 #include "ipsec_doi.h"
101 #include "vpn_control.h"
102 #include "vpn_control_var.h"
103 #include "isakmp_inf.h"
105 #include "gcmalloc.h"
106 #include "isakmp_cfg.h"
108 #ifdef ENABLE_VPNCONTROL_PORT
109 char *vpncontrolsock_path
= VPNCONTROLSOCK_PATH
;
110 uid_t vpncontrolsock_owner
= 0;
111 gid_t vpncontrolsock_group
= 0;
112 mode_t vpncontrolsock_mode
= 0600;
114 static struct sockaddr_un sunaddr
;
115 static int vpncontrol_process(struct vpnctl_socket_elem
*, char *);
116 static int vpncontrol_reply(int, char *);
117 static void vpncontrol_close_comm(struct vpnctl_socket_elem
*);
118 static int checklaunchd();
119 extern int vpn_get_config
__P((struct ph1handle
*, struct vpnctl_status_phase_change
**, size_t *));
120 extern int vpn_xauth_reply
__P((u_int32_t
, void *, size_t));
126 launch_data_t checkin_response
= NULL
;
127 launch_data_t checkin_request
= NULL
;
128 launch_data_t sockets_dict
, listening_fd_array
;
129 launch_data_t listening_fd
;
130 struct sockaddr_storage fdsockaddr
;
131 socklen_t fdsockaddrlen
= sizeof(fdsockaddr
);
138 /* check in with launchd */
139 if ((checkin_request
= launch_data_new_string(LAUNCH_KEY_CHECKIN
)) == NULL
) {
140 plog(LLV_ERROR
, LOCATION
, NULL
,
141 "failed to launch_data_new_string.\n");
144 if ((checkin_response
= launch_msg(checkin_request
)) == NULL
) {
145 plog(LLV_ERROR
, LOCATION
, NULL
,
146 "failed to launch_msg.\n");
149 if (LAUNCH_DATA_ERRNO
== launch_data_get_type(checkin_response
)) {
150 plog(LLV_ERROR
, LOCATION
, NULL
,
151 "launch_data_get_type error %d\n",
152 launch_data_get_errno(checkin_response
));
155 if ( (sockets_dict
= launch_data_dict_lookup(checkin_response
, LAUNCH_JOBKEY_SOCKETS
)) == NULL
){
156 plog(LLV_ERROR
, LOCATION
, NULL
,
157 "failed to launch_data_dict_lookup.\n");
160 if ( !(socketct
= launch_data_dict_get_count(sockets_dict
))){
161 plog(LLV_ERROR
, LOCATION
, NULL
,
162 "launch_data_dict_get_count returns no socket defined.\n");
166 if ( (listening_fd_array
= launch_data_dict_lookup(sockets_dict
, "Listeners")) == NULL
){
167 plog(LLV_ERROR
, LOCATION
, NULL
,
168 "failed to launch_data_dict_lookup.\n");
171 listenerct
= launch_data_array_get_count(listening_fd_array
);
172 for (i
= 0; i
< listenerct
; i
++) {
173 listening_fd
= launch_data_array_get_index(listening_fd_array
, i
);
174 fd
= launch_data_get_fd( listening_fd
);
175 if ( getsockname( fd
, (struct sockaddr
*)&fdsockaddr
, &fdsockaddrlen
)){
179 /* Is this the VPN control socket? */
180 if ( (((struct sockaddr
*)&fdsockaddr
)->sa_family
) == AF_UNIX
&&
181 (!(strcmp(vpncontrolsock_path
, ((struct sockaddr_un
*)&fdsockaddr
)->sun_path
))))
183 plog(LLV_INFO
, LOCATION
, NULL
,
184 "found launchd socket.\n");
189 // TODO: check if we have any leaked fd
190 if ( listenerct
== i
){
191 plog(LLV_ERROR
, LOCATION
, NULL
,
192 "failed to find launchd socket\n");
198 launch_data_free(checkin_request
);
199 if (checkin_response
)
200 launch_data_free(checkin_response
);
208 struct sockaddr_storage from
;
209 socklen_t fromlen
= sizeof(from
);
211 struct vpnctl_socket_elem
*sock_elem
;
213 sock_elem
= racoon_malloc(sizeof(struct vpnctl_socket_elem
));
214 if (sock_elem
== NULL
) {
215 plog(LLV_ERROR
, LOCATION
, NULL
,
216 "memory error: %s\n", strerror(errno
));
219 LIST_INIT(&sock_elem
->bound_addresses
);
221 sock_elem
->sock
= accept(lcconf
->sock_vpncontrol
, (struct sockaddr
*)&from
, &fromlen
);
222 if (sock_elem
->sock
< 0) {
223 plog(LLV_ERROR
, LOCATION
, NULL
,
224 "failed to accept vpn_control command: %s\n", strerror(errno
));
225 racoon_free(sock_elem
);
228 LIST_INSERT_HEAD(&lcconf
->vpnctl_comm_socks
, sock_elem
, chain
);
229 plog(LLV_NOTIFY
, LOCATION
, NULL
,
230 "accepted connection on vpn control socket.\n");
238 vpncontrol_comm_handler(struct vpnctl_socket_elem
*elem
)
240 struct vpnctl_hdr hdr
;
244 /* get buffer length */
245 while ((len
= recv(elem
->sock
, (char *)&hdr
, sizeof(hdr
), MSG_PEEK
)) < 0) {
248 plog(LLV_ERROR
, LOCATION
, NULL
,
249 "failed to recv vpn_control command: %s\n", strerror(errno
));
253 plog(LLV_DEBUG
, LOCATION
, NULL
,
254 "vpn_control socket closed by peer.\n");
255 vpncontrol_close_comm(elem
);
260 if (len
< sizeof(hdr
)) {
261 plog(LLV_ERROR
, LOCATION
, NULL
,
262 "invalid header length of vpn_control command - len=%d - expected %d\n", len
, sizeof(hdr
));
266 /* get buffer to receive */
267 if ((combuf
= racoon_malloc(ntohs(hdr
.len
) + sizeof(hdr
))) == 0) {
268 plog(LLV_ERROR
, LOCATION
, NULL
,
269 "failed to alloc buffer for vpn_control command\n");
274 while ((len
= recv(elem
->sock
, combuf
, ntohs(hdr
.len
) + sizeof(hdr
), 0)) < 0) {
277 plog(LLV_ERROR
, LOCATION
, NULL
,
278 "failed to recv vpn_control command: %s\n",
283 (void)vpncontrol_process(elem
, combuf
);
288 return 0; // return -1 only if a socket is closed
292 vpncontrol_process(struct vpnctl_socket_elem
*elem
, char *combuf
)
295 struct vpnctl_hdr
*hdr
= (struct vpnctl_hdr
*)combuf
;
297 switch (ntohs(hdr
->msg_type
)) {
299 case VPNCTL_CMD_BIND
:
301 struct vpnctl_cmd_bind
*pkt
= (struct vpnctl_cmd_bind
*)combuf
;
302 struct bound_addr
*addr
;
304 plog(LLV_DEBUG
, LOCATION
, NULL
,
305 "received bind command on vpn control socket.\n");
306 addr
= racoon_calloc(1, sizeof(struct bound_addr
));
308 plog(LLV_ERROR
, LOCATION
, NULL
,
309 "memory error: %s\n", strerror(errno
));
313 if (ntohs(pkt
->vers_len
)) {
314 addr
->version
= vmalloc(ntohs(pkt
->vers_len
));
315 if (addr
->version
== NULL
) {
316 plog(LLV_ERROR
, LOCATION
, NULL
,
317 "memory error: %s\n", strerror(errno
));
321 memcpy(addr
->version
->v
, pkt
+ 1, ntohs(pkt
->vers_len
));
323 addr
->address
= pkt
->address
;
324 LIST_INSERT_HEAD(&elem
->bound_addresses
, addr
, chain
);
325 lcconf
->auto_exit_state
|= LC_AUTOEXITSTATE_CLIENT
; /* client side */
329 case VPNCTL_CMD_UNBIND
:
331 struct vpnctl_cmd_unbind
*pkt
= (struct vpnctl_cmd_unbind
*)combuf
;
332 struct bound_addr
*addr
;
333 struct bound_addr
*t_addr
;
335 plog(LLV_DEBUG
, LOCATION
, NULL
,
336 "received unbind command on vpn control socket.\n");
337 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
338 if (pkt
->address
== 0xFFFFFFFF ||
339 pkt
->address
== addr
->address
) {
340 flushsainfo_dynamic(addr
->address
);
341 LIST_REMOVE(addr
, chain
);
343 vfree(addr
->version
);
350 case VPNCTL_CMD_REDIRECT
:
352 struct vpnctl_cmd_redirect
*redirect_msg
= (struct vpnctl_cmd_redirect
*)combuf
;
353 struct redirect
*raddr
;
354 struct redirect
*t_raddr
;
357 plog(LLV_DEBUG
, LOCATION
, NULL
,
358 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg
->redirect_address
));
360 LIST_FOREACH_SAFE(raddr
, &lcconf
->redirect_addresses
, chain
, t_raddr
) {
361 if (raddr
->cluster_address
== redirect_msg
->address
) {
362 if (redirect_msg
->redirect_address
== 0) {
363 LIST_REMOVE(raddr
, chain
);
366 raddr
->redirect_address
= redirect_msg
->redirect_address
;
367 raddr
->force
= ntohs(redirect_msg
->force
);
374 raddr
= racoon_malloc(sizeof(struct redirect
));
376 plog(LLV_DEBUG
, LOCATION
, NULL
,
377 "cannot allcoate memory for redirect address.\n");
381 raddr
->cluster_address
= redirect_msg
->address
;
382 raddr
->redirect_address
= redirect_msg
->redirect_address
;
383 raddr
->force
= ntohs(redirect_msg
->force
);
384 LIST_INSERT_HEAD(&lcconf
->redirect_addresses
, raddr
, chain
);
390 case VPNCTL_CMD_PING
:
391 break; /* just reply for now */
393 case VPNCTL_CMD_XAUTH_INFO
:
395 struct vpnctl_cmd_xauth_info
*pkt
= (struct vpnctl_cmd_xauth_info
*)combuf
;
396 struct bound_addr
*addr
;
397 struct bound_addr
*t_addr
;
400 plog(LLV_DEBUG
, LOCATION
, NULL
,
401 "received xauth info command vpn control socket.\n");
402 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
403 if (pkt
->address
== addr
->address
) {
404 /* reply to the last xauth request */
406 error
= vpn_xauth_reply(pkt
->address
, attr_list
, ntohs(pkt
->hdr
.len
) - sizeof(u_int32_t
));
413 case VPNCTL_CMD_CONNECT
:
415 struct vpnctl_cmd_connect
*pkt
= (struct vpnctl_cmd_connect
*)combuf
;
416 struct bound_addr
*addr
;
417 struct bound_addr
*t_addr
;
419 plog(LLV_DEBUG
, LOCATION
, NULL
,
420 "received connect command on vpn control socket.\n");
421 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
422 if (pkt
->address
== addr
->address
) {
423 /* start the connection */
424 error
= vpn_connect(addr
, VPN_STARTED_BY_API
);
431 case VPNCTL_CMD_DISCONNECT
:
433 struct vpnctl_cmd_connect
*pkt
= (struct vpnctl_cmd_connect
*)combuf
;
434 struct bound_addr
*addr
;
435 struct bound_addr
*t_addr
;
437 plog(LLV_DEBUG
, LOCATION
, NULL
,
438 "received disconnect command on vpn control socket.\n");
439 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
440 if (pkt
->address
== addr
->address
) {
441 /* stop the connection */
442 error
= vpn_disconnect(addr
);
449 case VPNCTL_CMD_START_PH2
:
451 struct vpnctl_cmd_start_ph2
*pkt
= (struct vpnctl_cmd_start_ph2
*)combuf
;
452 struct bound_addr
*addr
;
453 struct bound_addr
*t_addr
;
455 plog(LLV_DEBUG
, LOCATION
, NULL
,
456 "received start_ph2 command on vpn control socket.\n");
457 plogdump(LLV_DEBUG2
, pkt
, ntohs(hdr
->len
) + sizeof(struct vpnctl_hdr
));
458 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
459 if (pkt
->address
== addr
->address
) {
460 /* start the connection */
461 error
= vpn_start_ph2(addr
, pkt
);
468 case VPNCTL_CMD_START_DPD
:
470 struct vpnctl_cmd_start_dpd
*pkt
= (struct vpnctl_cmd_start_dpd
*)combuf
;
471 struct bound_addr
*srv
;
472 struct bound_addr
*t_addr
;
474 plog(LLV_DEBUG
, LOCATION
, NULL
,
475 "received start_dpd command on vpn control socket.\n");
476 LIST_FOREACH_SAFE(srv
, &elem
->bound_addresses
, chain
, t_addr
) {
477 if (pkt
->address
== srv
->address
) {
478 struct sockaddr_in daddr
;
480 bzero(&daddr
, sizeof(daddr
));
481 daddr
.sin_len
= sizeof(daddr
);
482 daddr
.sin_addr
.s_addr
= srv
->address
;
484 daddr
.sin_family
= AF_INET
;
487 error
= ph1_force_dpd(&daddr
);
494 case VPNCTL_CMD_ASSERT
:
496 struct vpnctl_cmd_assert
*pkt
= (struct vpnctl_cmd_assert
*)combuf
;
497 // struct bound_addr *addr;
498 // struct bound_addr *t_addr;
499 struct sockaddr_in saddr
;
500 struct sockaddr_in daddr
;
502 plog(LLV_DEBUG
, LOCATION
, NULL
,
503 "received assert command on vpn control socket.\n");
504 plogdump(LLV_DEBUG2
, pkt
, ntohs(hdr
->len
) + sizeof(struct vpnctl_hdr
));
505 // LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
506 // if (pkt->dst_address == addr->address) {
507 bzero(&saddr
, sizeof(saddr
));
508 saddr
.sin_len
= sizeof(saddr
);
509 saddr
.sin_addr
.s_addr
= pkt
->src_address
;
511 saddr
.sin_family
= AF_INET
;
512 bzero(&daddr
, sizeof(daddr
));
513 daddr
.sin_len
= sizeof(daddr
);
514 daddr
.sin_addr
.s_addr
= pkt
->dst_address
;
516 daddr
.sin_family
= AF_INET
;
518 error
= vpn_assert((struct sockaddr
*)&saddr
, (struct sockaddr
*)&daddr
);
525 case VPNCTL_CMD_RECONNECT
:
527 struct vpnctl_cmd_connect
*pkt
= (struct vpnctl_cmd_connect
*)combuf
;
528 struct bound_addr
*addr
;
529 struct bound_addr
*t_addr
;
531 plog(LLV_DEBUG
, LOCATION
, NULL
,
532 "received reconnect command on vpn control socket.\n");
533 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
534 if (pkt
->address
== addr
->address
) {
535 /* start the connection */
536 error
= vpn_connect(addr
, VPN_RESTARTED_BY_API
);
544 plog(LLV_ERROR
, LOCATION
, NULL
,
545 "invalid command: %d\n", ntohs(hdr
->msg_type
));
546 error
= -1; // for now
551 hdr
->result
= htons(error
);
552 if (vpncontrol_reply(elem
->sock
, combuf
) < 0)
560 vpncontrol_reply(int so
, char *combuf
)
564 tlen
= send(so
, combuf
, sizeof(struct vpnctl_hdr
), 0);
566 plog(LLV_ERROR
, LOCATION
, NULL
,
567 "failed to send vpn_control message: %s\n", strerror(errno
));
575 vpncontrol_notify_need_authinfo(struct ph1handle
*iph1
, void* attr_list
, size_t attr_len
)
577 struct vpnctl_status_need_authinfo
*msg
= NULL
;
578 struct vpnctl_socket_elem
*sock_elem
;
579 struct bound_addr
*bound_addr
;
580 size_t tlen
, msg_size
;
587 plog(LLV_DEBUG
, LOCATION
, NULL
,
588 "sending vpn_control xauth need info status\n");
590 msg
= (struct vpnctl_status_need_authinfo
*)racoon_malloc(msg_size
= sizeof(struct vpnctl_status_need_authinfo
) + attr_len
);
592 plog(LLV_ERROR
, LOCATION
, NULL
,
593 "unable to allocate space for vpn control message.\n");
598 if (iph1
->remote
->sa_family
== AF_INET
)
599 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
603 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
604 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
605 if (!ike_session_is_client_ph1_rekey(iph1
)) {
606 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_AUTHINFO
);
608 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_NEED_REAUTHINFO
);
610 msg
->address
= address
;
612 memcpy(ptr
, attr_list
, attr_len
);
614 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
615 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
616 if (bound_addr
->address
== 0xFFFFFFFF ||
617 bound_addr
->address
== address
) {
618 plog(LLV_DEBUG
, LOCATION
, NULL
,
619 "vpn control writing %d bytes\n", msg_size
);
620 plogdump(LLV_DEBUG
, msg
, msg_size
);
621 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
623 plog(LLV_ERROR
, LOCATION
, NULL
,
624 "failed to send vpn_control need authinfo status: %s\n", strerror(errno
));
638 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
)
640 struct vpnctl_status_failed
*msg
= NULL
;
641 struct vpnctl_socket_elem
*sock_elem
;
642 struct bound_addr
*bound_addr
;
645 len
= sizeof(struct vpnctl_status_failed
) + data_len
;
647 msg
= (struct vpnctl_status_failed
*)racoon_malloc(len
);
649 plog(LLV_DEBUG
, LOCATION
, NULL
,
650 "unable to allcate memory for vpn control status message.\n");
654 msg
->hdr
.msg_type
= htons(VPNCTL_STATUS_IKE_FAILED
);
655 msg
->hdr
.flags
= msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
656 msg
->hdr
.len
= htons(len
- sizeof(struct vpnctl_hdr
));
657 msg
->address
= address
;
658 msg
->ike_code
= htons(notify_code
);
659 msg
->from
= htons(from
);
661 memcpy(msg
->data
, data
, data_len
);
662 plog(LLV_DEBUG
, LOCATION
, NULL
,
663 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code
,
664 (from
== FROM_LOCAL
? "local" : "remote"));
666 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
667 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
668 if (bound_addr
->address
== 0xFFFFFFFF ||
669 bound_addr
->address
== address
) {
670 tlen
= send(sock_elem
->sock
, msg
, len
, 0);
672 plog(LLV_ERROR
, LOCATION
, NULL
,
673 "unable to send vpn_control ike notify failed: %s\n", strerror(errno
));
687 vpncontrol_notify_phase_change(int start
, u_int16_t from
, struct ph1handle
*iph1
, struct ph2handle
*iph2
)
689 struct vpnctl_status_phase_change
*msg
;
690 struct vpnctl_socket_elem
*sock_elem
;
691 struct bound_addr
*bound_addr
;
692 size_t tlen
, msg_size
;
695 plog(LLV_DEBUG
, LOCATION
, NULL
,
696 "sending vpn_control phase change status\n");
698 if (iph1
&& !start
&& iph1
->mode_cfg
&& iph1
->mode_cfg
->xauth
.status
!= XAUTHST_OK
) {
699 if (vpn_get_config(iph1
, &msg
, &msg_size
) == 1)
700 return 0; /* mode config not finished yet */
702 msg
= racoon_malloc(msg_size
= sizeof(struct vpnctl_status_phase_change
));
707 plog(LLV_ERROR
, LOCATION
, NULL
,
708 "unable to allocate space for vpn control message.\n");
712 if (iph1
->remote
->sa_family
== AF_INET
)
713 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
716 msg
->hdr
.msg_type
= htons(start
?
717 (from
== FROM_LOCAL
? VPNCTL_STATUS_PH1_START_US
: VPNCTL_STATUS_PH1_START_PEER
)
718 : VPNCTL_STATUS_PH1_ESTABLISHED
);
720 if (iph2
->dst
->sa_family
== AF_INET
)
721 address
= ((struct sockaddr_in
*)iph2
->dst
)->sin_addr
.s_addr
;
724 msg
->hdr
.msg_type
= htons(start
? VPNCTL_STATUS_PH2_START
: VPNCTL_STATUS_PH2_ESTABLISHED
);
726 msg
->hdr
.cookie
= msg
->hdr
.reserved
= msg
->hdr
.result
= 0;
727 msg
->hdr
.len
= htons((msg_size
) - sizeof(struct vpnctl_hdr
));
728 msg
->address
= address
;
730 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
731 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
732 if (bound_addr
->address
== 0xFFFFFFFF ||
733 bound_addr
->address
== address
) {
734 plog(LLV_DEBUG
, LOCATION
, NULL
,
735 "vpn control writing %d bytes\n", msg_size
);
736 plogdump(LLV_DEBUG
, msg
, msg_size
);
737 tlen
= send(sock_elem
->sock
, msg
, msg_size
, 0);
739 plog(LLV_ERROR
, LOCATION
, NULL
,
740 "failed to send vpn_control phase change status: %s\n", strerror(errno
));
754 vpncontrol_notify_peer_resp (u_int16_t notify_code
, u_int32_t address
)
756 struct vpnctl_status_peer_resp msg
;
757 struct vpnctl_socket_elem
*sock_elem
;
758 struct bound_addr
*bound_addr
;
762 bzero(&msg
, sizeof(msg
));
763 msg
.hdr
.msg_type
= htons(VPNCTL_STATUS_PEER_RESP
);
764 msg
.hdr
.cookie
= msg
.hdr
.reserved
= msg
.hdr
.result
= 0;
765 msg
.hdr
.len
= htons(sizeof(msg
) - sizeof(msg
.hdr
));
766 msg
.address
= address
;
767 msg
.ike_code
= notify_code
;
768 plog(LLV_DEBUG
, LOCATION
, NULL
,
769 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code
, address
);
771 LIST_FOREACH(sock_elem
, &lcconf
->vpnctl_comm_socks
, chain
) {
772 LIST_FOREACH(bound_addr
, &sock_elem
->bound_addresses
, chain
) {
773 if (bound_addr
->address
== 0xFFFFFFFF ||
774 bound_addr
->address
== address
) {
775 tlen
= send(sock_elem
->sock
, &msg
, sizeof(msg
), 0);
777 plog(LLV_ERROR
, LOCATION
, NULL
,
778 "unable to send vpn_control status (peer response): %s\n", strerror(errno
));
791 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code
, struct ph1handle
*iph1
)
796 if (iph1
&& iph1
->parent_session
&& iph1
->parent_session
->controller_awaiting_peer_resp
) {
797 if (iph1
->remote
->sa_family
== AF_INET
)
798 address
= ((struct sockaddr_in
*)iph1
->remote
)->sin_addr
.s_addr
;
805 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, address
)) == 0) {
806 iph1
->parent_session
->controller_awaiting_peer_resp
= 0;
812 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code
, struct ph2handle
*iph2
)
817 if (iph2
&& iph2
->parent_session
&& iph2
->parent_session
->controller_awaiting_peer_resp
) {
818 if (iph2
->dst
->sa_family
== AF_INET
)
819 address
= ((struct sockaddr_in
*)iph2
->dst
)->sin_addr
.s_addr
;
826 if ((rc
= vpncontrol_notify_peer_resp(notify_code
, address
)) == 0) {
827 iph2
->parent_session
->controller_awaiting_peer_resp
= 0;
835 if (vpncontrolsock_path
== NULL
) {
836 lcconf
->sock_vpncontrol
= -1;
840 if ( (lcconf
->sock_vpncontrol
= checklaunchd()) ){
845 memset(&sunaddr
, 0, sizeof(sunaddr
));
846 sunaddr
.sun_family
= AF_UNIX
;
847 snprintf(sunaddr
.sun_path
, sizeof(sunaddr
.sun_path
),
848 "%s", vpncontrolsock_path
);
850 lcconf
->sock_vpncontrol
= socket(AF_UNIX
, SOCK_STREAM
, 0);
851 if (lcconf
->sock_vpncontrol
== -1) {
852 plog(LLV_ERROR
, LOCATION
, NULL
,
853 "socket: %s\n", strerror(errno
));
857 unlink(sunaddr
.sun_path
);
858 if (bind(lcconf
->sock_vpncontrol
, (struct sockaddr
*)&sunaddr
,
859 sizeof(sunaddr
)) != 0) {
860 plog(LLV_ERROR
, LOCATION
, NULL
,
861 "bind(sockname:%s): %s\n",
862 sunaddr
.sun_path
, strerror(errno
));
863 (void)close(lcconf
->sock_vpncontrol
);
867 if (chown(sunaddr
.sun_path
, vpncontrolsock_owner
, vpncontrolsock_group
) != 0) {
868 plog(LLV_ERROR
, LOCATION
, NULL
,
869 "chown(%s, %d, %d): %s\n",
870 sunaddr
.sun_path
, vpncontrolsock_owner
,
871 vpncontrolsock_group
, strerror(errno
));
872 (void)close(lcconf
->sock_vpncontrol
);
876 if (chmod(sunaddr
.sun_path
, vpncontrolsock_mode
) != 0) {
877 plog(LLV_ERROR
, LOCATION
, NULL
,
878 "chmod(%s, 0%03o): %s\n",
879 sunaddr
.sun_path
, vpncontrolsock_mode
, strerror(errno
));
880 (void)close(lcconf
->sock_vpncontrol
);
884 if (listen(lcconf
->sock_vpncontrol
, 5) != 0) {
885 plog(LLV_ERROR
, LOCATION
, NULL
,
886 "listen(sockname:%s): %s\n",
887 sunaddr
.sun_path
, strerror(errno
));
888 (void)close(lcconf
->sock_vpncontrol
);
891 plog(LLV_DEBUG
, LOCATION
, NULL
,
892 "opened %s as racoon management.\n", sunaddr
.sun_path
);
902 struct vpnctl_socket_elem
*elem
;
903 struct vpnctl_socket_elem
*t_elem
;
905 plog(LLV_DEBUG
, LOCATION
, NULL
,
906 "vpncontrol_close.\n");
908 if (lcconf
->sock_vpncontrol
!= -1) {
909 close(lcconf
->sock_vpncontrol
);
910 lcconf
->sock_vpncontrol
= -1;
912 LIST_FOREACH_SAFE(elem
, &lcconf
->vpnctl_comm_socks
, chain
, t_elem
)
913 vpncontrol_close_comm(elem
);
918 vpncontrol_close_comm(struct vpnctl_socket_elem
*elem
)
920 struct bound_addr
*addr
;
921 struct bound_addr
*t_addr
;
923 plog(LLV_DEBUG
, LOCATION
, NULL
,
924 "vpncontrol_close_comm.\n");
926 LIST_REMOVE(elem
, chain
);
927 if (elem
->sock
!= -1)
929 LIST_FOREACH_SAFE(addr
, &elem
->bound_addresses
, chain
, t_addr
) {
930 flushsainfo_dynamic(addr
->address
);
931 LIST_REMOVE(addr
, chain
);
933 vfree(addr
->version
);
941 vpn_control_connected(void)
943 if (LIST_EMPTY(&lcconf
->vpnctl_comm_socks
))