]> git.saurik.com Git - apple/ipsec.git/blob - ipsec-tools/racoon/vpn_control.c
da31d7678f327075ba9db1cda11812ebc70757e1
[apple/ipsec.git] / ipsec-tools / racoon / vpn_control.c
1 /* $Id: vpn_control.c,v 1.17.2.4 2005/07/12 11:49:44 manubsd Exp $ */
2
3 /*
4 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
5 *
6 * @APPLE_LICENSE_HEADER_START@
7 *
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.
13 *
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
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 /*
26 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
27 * All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
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.
40 *
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
51 * SUCH DAMAGE.
52 */
53
54 #include "config.h"
55
56 #include <sys/types.h>
57 #include <sys/param.h>
58 #include <sys/socket.h>
59 #include <sys/signal.h>
60 #include <sys/stat.h>
61 #include <sys/un.h>
62
63 #include <System/net/pfkeyv2.h>
64
65 #include <netinet/in.h>
66 #ifndef HAVE_NETINET6_IPSEC
67 #include <netinet/ipsec.h>
68 #else
69 #include <netinet6/ipsec.h>
70 #endif
71
72
73 #include <stdlib.h>
74 #include <stdio.h>
75 #include <string.h>
76 #include <errno.h>
77 #include <netdb.h>
78 #ifdef HAVE_UNISTD_H
79 #include <unistd.h>
80 #endif
81 #include <launch.h>
82 #include <launch_priv.h>
83 #include <fcntl.h>
84
85 #include "var.h"
86 #include "misc.h"
87 #include "vmbuf.h"
88 #include "plog.h"
89 #include "sockmisc.h"
90 #include "debug.h"
91
92 #include "schedule.h"
93 #include "localconf.h"
94 #include "remoteconf.h"
95 #include "grabmyaddr.h"
96 #include "isakmp_var.h"
97 #include "isakmp.h"
98 #include "oakley.h"
99 #include "handler.h"
100 #include "evt.h"
101 #include "pfkey.h"
102 #include "ipsec_doi.h"
103 #include "vpn_control.h"
104 #include "vpn_control_var.h"
105 #include "isakmp_inf.h"
106 #include "session.h"
107 #include "gcmalloc.h"
108 #include "isakmp_cfg.h"
109 #include "sainfo.h"
110
111 #ifdef ENABLE_VPNCONTROL_PORT
112 char *vpncontrolsock_path = VPNCONTROLSOCK_PATH;
113 uid_t vpncontrolsock_owner = 0;
114 gid_t vpncontrolsock_group = 0;
115 mode_t vpncontrolsock_mode = 0600;
116
117 static struct sockaddr_un sunaddr;
118 static int vpncontrol_process(struct vpnctl_socket_elem *, char *);
119 static int vpncontrol_reply(int, char *);
120 static void vpncontrol_close_comm(struct vpnctl_socket_elem *);
121 static int checklaunchd();
122 extern int vpn_get_config __P((struct ph1handle *, struct vpnctl_status_phase_change **, size_t *));
123 extern int vpn_xauth_reply __P((u_int32_t, void *, size_t));
124
125
126 int
127 checklaunchd()
128 {
129 launch_data_t checkin_response = NULL;
130 launch_data_t sockets_dict, listening_fd_array;
131 launch_data_t listening_fd;
132 struct sockaddr_storage fdsockaddr;
133 socklen_t fdsockaddrlen = sizeof(fdsockaddr);
134 int socketct;
135 int i;
136 int listenerct;
137 int returnval = 0;
138 int fd;
139
140 /* check in with launchd */
141 if ((checkin_response = launch_socket_service_check_in()) == NULL) {
142 plog(LLV_ERROR, LOCATION, NULL,
143 "failed to launch_socket_service_check_in.\n");
144 goto done;
145 }
146 if (LAUNCH_DATA_ERRNO == launch_data_get_type(checkin_response)) {
147 plog(LLV_ERROR, LOCATION, NULL,
148 "launch_data_get_type error %d\n",
149 launch_data_get_errno(checkin_response));
150 goto done;
151 }
152 if ( (sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS)) == NULL){
153 plog(LLV_ERROR, LOCATION, NULL,
154 "failed to launch_data_dict_lookup.\n");
155 goto done;
156 }
157 if ( !(socketct = launch_data_dict_get_count(sockets_dict))){
158 plog(LLV_ERROR, LOCATION, NULL,
159 "launch_data_dict_get_count returns no socket defined.\n");
160 goto done;
161 }
162
163 if ( (listening_fd_array = launch_data_dict_lookup(sockets_dict, "Listeners")) == NULL ){
164 plog(LLV_ERROR, LOCATION, NULL,
165 "failed to launch_data_dict_lookup.\n");
166 goto done;
167 }
168 listenerct = launch_data_array_get_count(listening_fd_array);
169 for (i = 0; i < listenerct; i++) {
170 listening_fd = launch_data_array_get_index(listening_fd_array, i);
171 fd = launch_data_get_fd( listening_fd );
172 if ( getsockname( fd , (struct sockaddr *)&fdsockaddr, &fdsockaddrlen)){
173 continue;
174 }
175
176 /* Is this the VPN control socket? */
177 if ( fdsockaddr.ss_family == AF_UNIX &&
178 (!(strcmp(vpncontrolsock_path, ((struct sockaddr_un *)&fdsockaddr)->sun_path))))
179 {
180 plog(LLV_INFO, LOCATION, NULL,
181 "found launchd socket.\n");
182 returnval = fd;
183 break;
184 }
185 }
186 // TODO: check if we have any leaked fd
187 if ( listenerct == i){
188 plog(LLV_ERROR, LOCATION, NULL,
189 "failed to find launchd socket\n");
190 returnval = 0;
191 }
192
193 done:
194 if (checkin_response)
195 launch_data_free(checkin_response);
196 return(returnval);
197 }
198
199
200 int
201 vpncontrol_handler()
202 {
203 struct sockaddr_storage from;
204 socklen_t fromlen = sizeof(from);
205
206 struct vpnctl_socket_elem *sock_elem;
207
208 sock_elem = racoon_malloc(sizeof(struct vpnctl_socket_elem));
209 if (sock_elem == NULL) {
210 plog(LLV_ERROR, LOCATION, NULL,
211 "memory error: %s\n", strerror(errno));
212 return -1;
213 }
214 LIST_INIT(&sock_elem->bound_addresses);
215
216 sock_elem->sock = accept(lcconf->sock_vpncontrol, (struct sockaddr *)&from, &fromlen);
217 if (sock_elem->sock < 0) {
218 plog(LLV_ERROR, LOCATION, NULL,
219 "failed to accept vpn_control command: %s\n", strerror(errno));
220 racoon_free(sock_elem);
221 return -1;
222 }
223 LIST_INSERT_HEAD(&lcconf->vpnctl_comm_socks, sock_elem, chain);
224 plog(LLV_NOTIFY, LOCATION, NULL,
225 "accepted connection on vpn control socket.\n");
226
227 check_auto_exit();
228
229 return 0;
230 }
231
232 int
233 vpncontrol_comm_handler(struct vpnctl_socket_elem *elem)
234 {
235 struct vpnctl_hdr hdr;
236 char *combuf = NULL;
237 ssize_t len;
238
239 /* get buffer length */
240 while ((len = recv(elem->sock, (char *)&hdr, sizeof(hdr), MSG_PEEK)) < 0) {
241 if (errno == EINTR)
242 continue;
243 plog(LLV_ERROR, LOCATION, NULL,
244 "failed to recv vpn_control command: %s\n", strerror(errno));
245 goto end;
246 }
247 if (len == 0) {
248 plog(LLV_DEBUG, LOCATION, NULL,
249 "vpn_control socket closed by peer.\n");
250 /* kill all related connections */
251 vpncontrol_disconnect_all(elem, ike_session_stopped_by_controller_comm_lost);
252 vpncontrol_close_comm(elem);
253 return -1;
254 }
255
256 /* sanity check */
257 if (len < sizeof(hdr)) {
258 plog(LLV_ERROR, LOCATION, NULL,
259 "invalid header length of vpn_control command - len=%d - expected %d\n", len, sizeof(hdr));
260 goto end;
261 }
262
263 /* get buffer to receive */
264 if ((combuf = racoon_malloc(ntohs(hdr.len) + sizeof(hdr))) == 0) {
265 plog(LLV_ERROR, LOCATION, NULL,
266 "failed to alloc buffer for vpn_control command\n");
267 goto end;
268 }
269
270 /* get real data */
271 while ((len = recv(elem->sock, combuf, ntohs(hdr.len) + sizeof(hdr), 0)) < 0) {
272 if (errno == EINTR)
273 continue;
274 plog(LLV_ERROR, LOCATION, NULL,
275 "failed to recv vpn_control command: %s\n",
276 strerror(errno));
277 goto end;
278 }
279
280 (void)vpncontrol_process(elem, combuf);
281
282 end:
283 if (combuf)
284 racoon_free(combuf);
285 return 0; // return -1 only if a socket is closed
286 }
287
288 static int
289 vpncontrol_process(struct vpnctl_socket_elem *elem, char *combuf)
290 {
291 u_int16_t error = 0;
292 struct vpnctl_hdr *hdr = ALIGNED_CAST(struct vpnctl_hdr *)combuf;
293
294 switch (ntohs(hdr->msg_type)) {
295
296 case VPNCTL_CMD_BIND:
297 {
298 struct vpnctl_cmd_bind *pkt = ALIGNED_CAST(struct vpnctl_cmd_bind *)combuf;
299 struct bound_addr *addr;
300
301 plog(LLV_DEBUG, LOCATION, NULL,
302 "received bind command on vpn control socket.\n");
303 addr = racoon_calloc(1, sizeof(struct bound_addr));
304 if (addr == NULL) {
305 plog(LLV_ERROR, LOCATION, NULL,
306 "memory error: %s\n", strerror(errno));
307 error = -1;
308 break;
309 }
310 if (ntohs(pkt->vers_len)) {
311 addr->version = vmalloc(ntohs(pkt->vers_len));
312 if (addr->version == NULL) {
313 plog(LLV_ERROR, LOCATION, NULL,
314 "memory error: %s\n", strerror(errno));
315 error = -1;
316 break;
317 }
318 memcpy(addr->version->v, pkt + 1, ntohs(pkt->vers_len));
319 }
320 addr->address = pkt->address;
321 LIST_INSERT_HEAD(&elem->bound_addresses, addr, chain);
322 lcconf->auto_exit_state |= LC_AUTOEXITSTATE_CLIENT; /* client side */
323 }
324 break;
325
326 case VPNCTL_CMD_UNBIND:
327 {
328 struct vpnctl_cmd_unbind *pkt = ALIGNED_CAST(struct vpnctl_cmd_unbind *)combuf;
329 struct bound_addr *addr;
330 struct bound_addr *t_addr;
331
332 plog(LLV_DEBUG, LOCATION, NULL,
333 "received unbind command on vpn control socket.\n");
334 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
335 if (pkt->address == 0xFFFFFFFF ||
336 pkt->address == addr->address) {
337 flushsainfo_dynamic(addr->address);
338 LIST_REMOVE(addr, chain);
339 if (addr->version)
340 vfree(addr->version);
341 racoon_free(addr);
342 }
343 }
344 }
345 break;
346
347 case VPNCTL_CMD_REDIRECT:
348 {
349 struct vpnctl_cmd_redirect *redirect_msg = ALIGNED_CAST(struct vpnctl_cmd_redirect *)combuf;
350 struct redirect *raddr;
351 struct redirect *t_raddr;
352 int found = 0;
353
354 plog(LLV_DEBUG, LOCATION, NULL,
355 "received redirect command on vpn control socket - address = %x.\n", ntohl(redirect_msg->redirect_address));
356
357 LIST_FOREACH_SAFE(raddr, &lcconf->redirect_addresses, chain, t_raddr) {
358 if (raddr->cluster_address == redirect_msg->address) {
359 if (redirect_msg->redirect_address == 0) {
360 LIST_REMOVE(raddr, chain);
361 racoon_free(raddr);
362 } else {
363 raddr->redirect_address = redirect_msg->redirect_address;
364 raddr->force = ntohs(redirect_msg->force);
365 }
366 found = 1;
367 break;
368 }
369 }
370 if (!found) {
371 raddr = racoon_malloc(sizeof(struct redirect));
372 if (raddr == NULL) {
373 plog(LLV_DEBUG, LOCATION, NULL,
374 "cannot allcoate memory for redirect address.\n");
375 error = -1;
376 break;
377 }
378 raddr->cluster_address = redirect_msg->address;
379 raddr->redirect_address = redirect_msg->redirect_address;
380 raddr->force = ntohs(redirect_msg->force);
381 LIST_INSERT_HEAD(&lcconf->redirect_addresses, raddr, chain);
382
383 }
384 }
385 break;
386
387 case VPNCTL_CMD_PING:
388 break; /* just reply for now */
389
390 case VPNCTL_CMD_XAUTH_INFO:
391 {
392 struct vpnctl_cmd_xauth_info *pkt = ALIGNED_CAST(struct vpnctl_cmd_xauth_info *)combuf;
393 struct bound_addr *addr;
394 struct bound_addr *t_addr;
395 void *attr_list;
396
397 plog(LLV_DEBUG, LOCATION, NULL,
398 "received xauth info command vpn control socket.\n");
399 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
400 if (pkt->address == addr->address) {
401 /* reply to the last xauth request */
402 attr_list = pkt + 1;
403 error = vpn_xauth_reply(pkt->address, attr_list, ntohs(pkt->hdr.len) - sizeof(u_int32_t));
404 break;
405 }
406 }
407 }
408 break;
409
410 case VPNCTL_CMD_CONNECT:
411 {
412 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
413 struct bound_addr *addr;
414 struct bound_addr *t_addr;
415
416 plog(LLV_DEBUG, LOCATION, NULL,
417 "received connect command on vpn control socket.\n");
418 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
419 if (pkt->address == addr->address) {
420 /* start the connection */
421 error = vpn_connect(addr, VPN_STARTED_BY_API);
422 break;
423 }
424 }
425 }
426 break;
427
428 case VPNCTL_CMD_DISCONNECT:
429 {
430 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
431 struct bound_addr *addr;
432 struct bound_addr *t_addr;
433
434 plog(LLV_DEBUG, LOCATION, NULL,
435 "received disconnect command on vpn control socket.\n");
436 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
437 if (pkt->address == addr->address) {
438 /* stop the connection */
439 error = vpn_disconnect(addr, ike_session_stopped_by_vpn_disconnect);
440 break;
441 }
442 }
443 }
444 break;
445
446 case VPNCTL_CMD_START_PH2:
447 {
448 struct vpnctl_cmd_start_ph2 *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_ph2 *)combuf;
449 struct bound_addr *addr;
450 struct bound_addr *t_addr;
451
452 plog(LLV_DEBUG, LOCATION, NULL,
453 "received start_ph2 command on vpn control socket.\n");
454 plogdump(LLV_DEBUG2, pkt, ntohs(hdr->len) + sizeof(struct vpnctl_hdr));
455 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
456 if (pkt->address == addr->address) {
457 /* start the connection */
458 error = vpn_start_ph2(addr, pkt);
459 break;
460 }
461 }
462 }
463 break;
464
465 case VPNCTL_CMD_START_DPD:
466 {
467 struct vpnctl_cmd_start_dpd *pkt = ALIGNED_CAST(struct vpnctl_cmd_start_dpd *)combuf;
468 struct bound_addr *srv;
469 struct bound_addr *t_addr;
470
471 plog(LLV_DEBUG, LOCATION, NULL,
472 "received start_dpd command on vpn control socket.\n");
473 LIST_FOREACH_SAFE(srv, &elem->bound_addresses, chain, t_addr) {
474 if (pkt->address == srv->address) {
475 union { // Wcast-align fix - force alignment
476 struct sockaddr_storage ss;
477 struct sockaddr_in addr_in;
478 } daddr;
479
480 bzero(&daddr, sizeof(struct sockaddr_in));
481 daddr.addr_in.sin_len = sizeof(struct sockaddr_in);
482 daddr.addr_in.sin_addr.s_addr = srv->address;
483 daddr.addr_in.sin_port = 0;
484 daddr.addr_in.sin_family = AF_INET;
485
486 /* start the dpd */
487 error = ph1_force_dpd(&daddr.ss);
488 break;
489 }
490 }
491 }
492 break;
493
494 case VPNCTL_CMD_ASSERT:
495 {
496 struct vpnctl_cmd_assert *pkt = ALIGNED_CAST(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;
501
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;
510 saddr.sin_port = 0;
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;
515 daddr.sin_port = 0;
516 daddr.sin_family = AF_INET;
517
518 error = vpn_assert((struct sockaddr_storage *)&saddr, (struct sockaddr_storage *)&daddr);
519 break;
520 // }
521 // }
522 }
523 break;
524
525 case VPNCTL_CMD_RECONNECT:
526 {
527 struct vpnctl_cmd_connect *pkt = ALIGNED_CAST(struct vpnctl_cmd_connect *)combuf;
528 struct bound_addr *addr;
529 struct bound_addr *t_addr;
530
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);
537 break;
538 }
539 }
540 }
541 break;
542
543 default:
544 plog(LLV_ERROR, LOCATION, NULL,
545 "invalid command: %d\n", ntohs(hdr->msg_type));
546 error = -1; // for now
547 break;
548 }
549
550 hdr->len = 0;
551 hdr->result = htons(error);
552 if (vpncontrol_reply(elem->sock, combuf) < 0)
553 return -1;
554
555 return 0;
556
557 }
558
559 static int
560 vpncontrol_reply(int so, char *combuf)
561 {
562 ssize_t tlen;
563
564 tlen = send(so, combuf, sizeof(struct vpnctl_hdr), 0);
565 if (tlen < 0) {
566 plog(LLV_ERROR, LOCATION, NULL,
567 "failed to send vpn_control message: %s\n", strerror(errno));
568 return -1;
569 }
570
571 return 0;
572 }
573
574 int
575 vpncontrol_notify_need_authinfo(struct ph1handle *iph1, void* attr_list, size_t attr_len)
576 {
577 struct vpnctl_status_need_authinfo *msg = NULL;
578 struct vpnctl_socket_elem *sock_elem;
579 struct bound_addr *bound_addr;
580 size_t msg_size;
581 ssize_t tlen;
582 u_int32_t address;
583 void *ptr;
584
585 if (!iph1)
586 goto end;
587
588 plog(LLV_DEBUG, LOCATION, NULL,
589 "sending vpn_control xauth need info status\n");
590
591 msg = (struct vpnctl_status_need_authinfo *)racoon_malloc(msg_size = sizeof(struct vpnctl_status_need_authinfo) + attr_len);
592 if (msg == NULL) {
593 plog(LLV_ERROR, LOCATION, NULL,
594 "unable to allocate space for vpn control message.\n");
595 return -1;
596 }
597 msg->hdr.flags = 0;
598
599 if (iph1->remote->ss_family == AF_INET)
600 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
601 else
602 goto end; // for now
603
604 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
605 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
606 if (!ike_session_is_client_ph1_rekey(iph1)) {
607 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_AUTHINFO);
608 } else {
609 msg->hdr.msg_type = htons(VPNCTL_STATUS_NEED_REAUTHINFO);
610 }
611 msg->address = address;
612 ptr = msg + 1;
613 memcpy(ptr, attr_list, attr_len);
614
615 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
616 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
617 if (bound_addr->address == 0xFFFFFFFF ||
618 bound_addr->address == address) {
619 plog(LLV_DEBUG, LOCATION, NULL,
620 "vpn control writing %d bytes\n", msg_size);
621 plogdump(LLV_DEBUG, msg, msg_size);
622 tlen = send(sock_elem->sock, msg, msg_size, 0);
623 if (tlen < 0) {
624 plog(LLV_ERROR, LOCATION, NULL,
625 "failed to send vpn_control need authinfo status: %s\n", strerror(errno));
626 }
627 break;
628 }
629 }
630 }
631
632 end:
633 if (msg)
634 racoon_free(msg);
635 return 0;
636 }
637
638 int
639 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 {
641 struct vpnctl_status_failed *msg = NULL;
642 struct vpnctl_socket_elem *sock_elem;
643 struct bound_addr *bound_addr;
644 size_t len;
645 ssize_t tlen;
646
647 len = sizeof(struct vpnctl_status_failed) + data_len;
648
649 msg = (struct vpnctl_status_failed *)racoon_malloc(len);
650 if (msg == NULL) {
651 plog(LLV_DEBUG, LOCATION, NULL,
652 "unable to allcate memory for vpn control status message.\n");
653 return -1;
654 }
655
656 msg->hdr.msg_type = htons(VPNCTL_STATUS_IKE_FAILED);
657 msg->hdr.flags = msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
658 msg->hdr.len = htons(len - sizeof(struct vpnctl_hdr));
659 msg->address = address;
660 msg->ike_code = htons(notify_code);
661 msg->from = htons(from);
662 if (data_len > 0)
663 memcpy(msg->data, data, data_len);
664 plog(LLV_DEBUG, LOCATION, NULL,
665 "sending vpn_control ike failed message - code=%d from=%s.\n", notify_code,
666 (from == FROM_LOCAL ? "local" : "remote"));
667
668 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
669 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
670 if (bound_addr->address == 0xFFFFFFFF ||
671 bound_addr->address == address) {
672 tlen = send(sock_elem->sock, msg, len, 0);
673 if (tlen < 0) {
674 plog(LLV_ERROR, LOCATION, NULL,
675 "unable to send vpn_control ike notify failed: %s\n", strerror(errno));
676 }
677 break;
678 }
679 }
680 }
681
682 if (msg)
683 racoon_free(msg);
684 return 0;
685 }
686
687
688 int
689 vpncontrol_notify_phase_change(int start, u_int16_t from, struct ph1handle *iph1, struct ph2handle *iph2)
690 {
691 struct vpnctl_status_phase_change *msg;
692 struct vpnctl_socket_elem *sock_elem;
693 struct bound_addr *bound_addr;
694 ssize_t tlen;
695 size_t msg_size;
696 u_int32_t address;
697
698 plog(LLV_DEBUG, LOCATION, NULL,
699 "sending vpn_control phase change status\n");
700
701 if (iph1 && !start && iph1->mode_cfg && iph1->mode_cfg->xauth.status != XAUTHST_OK) {
702 if (vpn_get_config(iph1, &msg, &msg_size) == 1)
703 return 0; /* mode config not finished yet */
704 } else {
705 msg = racoon_malloc(msg_size = sizeof(struct vpnctl_status_phase_change));
706 msg->hdr.flags = 0;
707 }
708
709 if (msg == NULL) {
710 plog(LLV_ERROR, LOCATION, NULL,
711 "unable to allocate space for vpn control message.\n");
712 return -1;
713 }
714 if (iph1) {
715 if (iph1->remote->ss_family == AF_INET)
716 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
717 else
718 goto end; // for now
719 msg->hdr.msg_type = htons(start ?
720 (from == FROM_LOCAL ? VPNCTL_STATUS_PH1_START_US : VPNCTL_STATUS_PH1_START_PEER)
721 : VPNCTL_STATUS_PH1_ESTABLISHED);
722 } else {
723 if (iph2->dst->ss_family == AF_INET)
724 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
725 else
726 goto end; // for now
727 msg->hdr.msg_type = htons(start ? VPNCTL_STATUS_PH2_START : VPNCTL_STATUS_PH2_ESTABLISHED);
728 }
729 msg->hdr.cookie = msg->hdr.reserved = msg->hdr.result = 0;
730 msg->hdr.len = htons((msg_size) - sizeof(struct vpnctl_hdr));
731 msg->address = address;
732
733 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
734 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
735 if (bound_addr->address == 0xFFFFFFFF ||
736 bound_addr->address == address) {
737 plog(LLV_DEBUG, LOCATION, NULL,
738 "vpn control writing %d bytes\n", msg_size);
739 plogdump(LLV_DEBUG, msg, msg_size);
740 tlen = send(sock_elem->sock, msg, msg_size, 0);
741 if (tlen < 0) {
742 plog(LLV_ERROR, LOCATION, NULL,
743 "failed to send vpn_control phase change status: %s\n", strerror(errno));
744 }
745 break;
746 }
747 }
748 }
749
750 end:
751 if (msg)
752 racoon_free(msg);
753 return 0;
754 }
755
756 static int
757 vpncontrol_notify_peer_resp (u_int16_t notify_code, u_int32_t address)
758 {
759 struct vpnctl_status_peer_resp msg;
760 struct vpnctl_socket_elem *sock_elem;
761 struct bound_addr *bound_addr;
762 ssize_t tlen;
763 int rc = -1;
764
765 bzero(&msg, sizeof(msg));
766 msg.hdr.msg_type = htons(VPNCTL_STATUS_PEER_RESP);
767 msg.hdr.cookie = msg.hdr.reserved = msg.hdr.result = 0;
768 msg.hdr.len = htons(sizeof(msg) - sizeof(msg.hdr));
769 msg.address = address;
770 msg.ike_code = notify_code;
771 plog(LLV_DEBUG, LOCATION, NULL,
772 "sending vpn_control status (peer response) message - code=%d addr=%x.\n", notify_code, address);
773
774 LIST_FOREACH(sock_elem, &lcconf->vpnctl_comm_socks, chain) {
775 LIST_FOREACH(bound_addr, &sock_elem->bound_addresses, chain) {
776 if (bound_addr->address == 0xFFFFFFFF ||
777 bound_addr->address == address) {
778 tlen = send(sock_elem->sock, &msg, sizeof(msg), 0);
779 if (tlen < 0) {
780 plog(LLV_ERROR, LOCATION, NULL,
781 "unable to send vpn_control status (peer response): %s\n", strerror(errno));
782 } else {
783 rc = 0;
784 }
785 break;
786 }
787 }
788 }
789
790 return rc;
791 }
792
793 int
794 vpncontrol_notify_peer_resp_ph1 (u_int16_t notify_code, struct ph1handle *iph1)
795 {
796 u_int32_t address;
797 int rc;
798
799 if (iph1 && iph1->parent_session && iph1->parent_session->controller_awaiting_peer_resp) {
800 if (iph1->remote->ss_family == AF_INET)
801 address = ((struct sockaddr_in *)iph1->remote)->sin_addr.s_addr;
802 else
803 address = 0;
804 } else {
805 return 0;
806 }
807
808 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) {
809 iph1->parent_session->controller_awaiting_peer_resp = 0;
810 }
811 return rc;
812 }
813
814 int
815 vpncontrol_notify_peer_resp_ph2 (u_int16_t notify_code, struct ph2handle *iph2)
816 {
817 u_int32_t address;
818 int rc;
819
820 if (iph2 && iph2->parent_session && iph2->parent_session->controller_awaiting_peer_resp) {
821 if (iph2->dst->ss_family == AF_INET)
822 address = ((struct sockaddr_in *)iph2->dst)->sin_addr.s_addr;
823 else
824 address = 0;
825 } else {
826 return 0;
827 }
828
829 if ((rc = vpncontrol_notify_peer_resp(notify_code, address)) == 0) {
830 iph2->parent_session->controller_awaiting_peer_resp = 0;
831 }
832 return rc;
833 }
834
835 int
836 vpncontrol_init()
837 {
838 if (vpncontrolsock_path == NULL) {
839 lcconf->sock_vpncontrol = -1;
840 return 0;
841 }
842
843 if ( (lcconf->sock_vpncontrol = checklaunchd()) ){
844 return 0;
845 }
846 else {
847
848 memset(&sunaddr, 0, sizeof(sunaddr));
849 sunaddr.sun_family = AF_UNIX;
850 snprintf(sunaddr.sun_path, sizeof(sunaddr.sun_path),
851 "%s", vpncontrolsock_path);
852
853 lcconf->sock_vpncontrol = socket(AF_UNIX, SOCK_STREAM, 0);
854 if (lcconf->sock_vpncontrol == -1) {
855 plog(LLV_ERROR, LOCATION, NULL,
856 "socket: %s\n", strerror(errno));
857 return -1;
858 }
859
860 if (fcntl(lcconf->sock_vpncontrol, F_SETFL, O_NONBLOCK) == -1) {
861 plog(LLV_ERROR, LOCATION, NULL,
862 "failed to put VPN-Control socket in non-blocking mode\n");
863 }
864
865 unlink(sunaddr.sun_path);
866 if (bind(lcconf->sock_vpncontrol, (struct sockaddr *)&sunaddr,
867 sizeof(sunaddr)) != 0) {
868 plog(LLV_ERROR, LOCATION, NULL,
869 "bind(sockname:%s): %s\n",
870 sunaddr.sun_path, strerror(errno));
871 (void)close(lcconf->sock_vpncontrol);
872 return -1;
873 }
874
875 if (chown(sunaddr.sun_path, vpncontrolsock_owner, vpncontrolsock_group) != 0) {
876 plog(LLV_ERROR, LOCATION, NULL,
877 "chown(%s, %d, %d): %s\n",
878 sunaddr.sun_path, vpncontrolsock_owner,
879 vpncontrolsock_group, strerror(errno));
880 (void)close(lcconf->sock_vpncontrol);
881 return -1;
882 }
883
884 if (chmod(sunaddr.sun_path, vpncontrolsock_mode) != 0) {
885 plog(LLV_ERROR, LOCATION, NULL,
886 "chmod(%s, 0%03o): %s\n",
887 sunaddr.sun_path, vpncontrolsock_mode, strerror(errno));
888 (void)close(lcconf->sock_vpncontrol);
889 return -1;
890 }
891
892 if (listen(lcconf->sock_vpncontrol, 5) != 0) {
893 plog(LLV_ERROR, LOCATION, NULL,
894 "listen(sockname:%s): %s\n",
895 sunaddr.sun_path, strerror(errno));
896 (void)close(lcconf->sock_vpncontrol);
897 return -1;
898 }
899 plog(LLV_DEBUG, LOCATION, NULL,
900 "opened %s as racoon management.\n", sunaddr.sun_path);
901
902 return 0;
903 }
904 }
905
906 void
907 vpncontrol_disconnect_all(struct vpnctl_socket_elem *elem, const char *reason)
908 {
909 struct bound_addr *addr;
910 struct bound_addr *t_addr;
911
912 plog(LLV_DEBUG, LOCATION, NULL,
913 "received disconnect all command.\n");
914
915 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
916 /* stop any connections */
917 vpn_disconnect(addr, reason);
918 }
919 }
920
921
922 void
923 vpncontrol_close()
924 {
925 struct vpnctl_socket_elem *elem;
926 struct vpnctl_socket_elem *t_elem;
927
928 plog(LLV_DEBUG, LOCATION, NULL,
929 "vpncontrol_close.\n");
930
931 if (lcconf->sock_vpncontrol != -1) {
932 close(lcconf->sock_vpncontrol);
933 lcconf->sock_vpncontrol = -1;
934 }
935 LIST_FOREACH_SAFE(elem, &lcconf->vpnctl_comm_socks, chain, t_elem)
936 vpncontrol_close_comm(elem);
937
938 }
939
940 static void
941 vpncontrol_close_comm(struct vpnctl_socket_elem *elem)
942 {
943 struct bound_addr *addr;
944 struct bound_addr *t_addr;
945
946 plog(LLV_DEBUG, LOCATION, NULL,
947 "vpncontrol_close_comm.\n");
948
949 LIST_REMOVE(elem, chain);
950 if (elem->sock != -1)
951 close(elem->sock);
952 LIST_FOREACH_SAFE(addr, &elem->bound_addresses, chain, t_addr) {
953 flushsainfo_dynamic(addr->address);
954 LIST_REMOVE(addr, chain);
955 if (addr->version)
956 vfree(addr->version);
957 racoon_free(addr);
958 }
959 racoon_free(elem);
960 check_auto_exit();
961 }
962
963 int
964 vpn_control_connected(void)
965 {
966 if (LIST_EMPTY(&lcconf->vpnctl_comm_socks))
967 return 0;
968 else
969 return 1;
970 }
971
972 #endif