]> git.saurik.com Git - apple/ipsec.git/blame - ipsec-tools/racoon/session.c
ipsec-317.tar.gz
[apple/ipsec.git] / ipsec-tools / racoon / session.c
CommitLineData
d1e348cf
A
1/* $NetBSD: session.c,v 1.7.6.2 2007/08/01 11:52:22 vanhu Exp $ */
2
52b7d2ce
A
3/* $KAME: session.c,v 1.32 2003/09/24 02:01:17 jinmei Exp $ */
4
5/*
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "config.h"
35
36#include <sys/types.h>
37#include <sys/param.h>
38#include <sys/time.h>
39#include <sys/socket.h>
40#if HAVE_SYS_WAIT_H
41# include <sys/wait.h>
42#endif
43#ifndef WEXITSTATUS
44# define WEXITSTATUS(s) ((unsigned)(s) >> 8)
45#endif
46#ifndef WIFEXITED
47# define WIFEXITED(s) (((s) & 255) == 0)
48#endif
49
50#ifndef HAVE_NETINET6_IPSEC
51#include <netinet/ipsec.h>
52#else
53#include <netinet6/ipsec.h>
54#endif
55
56#include <stdlib.h>
57#include <stdio.h>
58#include <string.h>
59#include <errno.h>
60#ifdef HAVE_UNISTD_H
61#include <unistd.h>
62#endif
63#include <signal.h>
64#include <sys/stat.h>
65#include <paths.h>
66
d1e348cf
A
67#include <netinet/in.h>
68#include <netinet/ip.h>
69#include <netinet/ip_icmp.h>
70
d1e348cf 71#include <TargetConditionals.h>
e97d2cf9 72#include <vproc_priv.h>
65c25746 73#include <dispatch/dispatch.h>
c8d8bee0 74#include <xpc/xpc.h>
d1e348cf 75
52b7d2ce
A
76#include "libpfkey.h"
77
78#include "var.h"
79#include "misc.h"
80#include "vmbuf.h"
81#include "plog.h"
82#include "debug.h"
65c25746 83#include "plog.h"
52b7d2ce
A
84
85#include "schedule.h"
86#include "session.h"
87#include "grabmyaddr.h"
52b7d2ce
A
88#include "cfparse_proto.h"
89#include "isakmp_var.h"
d1e348cf
A
90#include "isakmp_xauth.h"
91#include "isakmp_cfg.h"
52b7d2ce
A
92#include "oakley.h"
93#include "pfkey.h"
94#include "handler.h"
95#include "localconf.h"
96#include "remoteconf.h"
52b7d2ce
A
97#ifdef ENABLE_NATT
98#include "nattraversal.h"
99#endif
100#include "vpn_control_var.h"
101#include "policy.h"
d1e348cf
A
102#include "algorithm.h" /* XXX ??? */
103
104#include "sainfo.h"
e8d9021d 105#include "power_mgmt.h"
d1e348cf 106
d9c572c0
A
107#include <NetworkExtension/NEPolicy.h>
108#include <sys/proc_info.h>
109#include <libproc.h>
d1e348cf 110
52b7d2ce
A
111
112extern pid_t racoon_pid;
85f41bec 113extern int launchdlaunched;
65c25746
A
114static void close_session (int);
115static int init_signal (void);
116static int set_signal (int sig, RETSIGTYPE (*func) (int, siginfo_t *, void *));
65c25746
A
117static void check_flushsa_stub (void *);
118static void check_flushsa (void);
119static void auto_exit_do (void *);
120static int close_sockets (void);
121
52b7d2ce 122static volatile sig_atomic_t sigreq[NSIG + 1];
d1e348cf 123int terminated = 0;
886926c0 124int pending_signal_handle = 0;
52b7d2ce 125
e97d2cf9
A
126static int64_t racoon_keepalive = -1;
127
65c25746
A
128dispatch_queue_t main_queue;
129
d9c572c0
A
130static NEPolicySessionRef policySession = NULL;
131
e97d2cf9
A
132/*
133 * This is used to (manually) update racoon's launchd keepalive, which is needed because racoon is (mostly)
e8d9021d 134 * launched on demand and for <rdar://problem/8768510> requires a keepalive on dirty/failure exits.
e97d2cf9
A
135 * The launchd plist can't be used for this because RunOnLoad is required to have keepalive on a failure exit.
136 */
137int64_t
138launchd_update_racoon_keepalive (Boolean enabled)
139{
65c25746
A
140 if (launchdlaunched) {
141 int64_t val = (__typeof__(val))enabled;
142 /* Set our own KEEPALIVE value */
143 if (vproc_swap_integer(NULL,
144 VPROC_GSK_BASIC_KEEPALIVE,
145 &val,
146 &racoon_keepalive)) {
147 plog(ASL_LEVEL_ERR,
148 "failed to swap launchd keepalive integer %d\n", enabled);
e97d2cf9
A
149 }
150 }
151 return racoon_keepalive;
152}
e97d2cf9 153
d9c572c0
A
154static CFUUIDRef
155copy_racoon_proc_uuid(void)
156{
157 struct proc_uniqidentifierinfo procu;
158 CFUUIDBytes uuidBytes;
159 int size = 0;
160
161 memset(&procu, 0, sizeof(procu));
162 size = proc_pidinfo(getpid(), PROC_PIDUNIQIDENTIFIERINFO, 1, &procu, PROC_PIDUNIQIDENTIFIERINFO_SIZE);
163 if (size != PROC_PIDUNIQIDENTIFIERINFO_SIZE) {
164 return (NULL);
165 }
166
167 memcpy(&uuidBytes, procu.p_uuid, sizeof(CFUUIDBytes));
168 return CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, uuidBytes);
169}
170
171static bool
172policy_session_init(void)
173{
174 bool success = true;
175 policySession = NEPolicyCreateSession(kCFAllocatorDefault, CFSTR("racoon"), NULL, NULL);
176 if (policySession == NULL) {
177 return false;
178 }
179
180 CFUUIDRef proc_uuid = copy_racoon_proc_uuid();
181 if (proc_uuid == NULL) {
182 return false;
183 }
184
185 CFMutableArrayRef conditions = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
186 if (conditions) {
187 CFMutableDictionaryRef uuidCondition = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
188 if (uuidCondition) {
189 CFDictionarySetValue(uuidCondition, kNEPolicyConditionType, kNEPolicyValPolicyConditionTypeApplication);
190 CFDictionarySetValue(uuidCondition, kNEPolicyApplicationUUID, proc_uuid);
191 CFArrayAppendValue(conditions, uuidCondition);
192 CFRelease(uuidCondition);
193 } else {
194 success = false;
195 }
196
197 CFMutableDictionaryRef interfacesCondition = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
198 if (interfacesCondition) {
199 CFDictionarySetValue(interfacesCondition, kNEPolicyConditionType, kNEPolicyValPolicyConditionTypeAllInterfaces);
200 CFArrayAppendValue(conditions, interfacesCondition);
201 CFRelease(interfacesCondition);
202 } else {
203 success = false;
204 }
205 } else {
206 success = false;
207 }
208
209 CFMutableDictionaryRef result = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
210 if (result) {
211 CFDictionaryAddValue(result, kNEPolicyResult, kNEPolicyValPolicyResultPass);
212 } else {
213 success = false;
214 }
215
216 if (success) {
217 success = (NEPolicyAdd(policySession, 0, conditions, result, NULL) != kNEPolicyIDInvalid);
218 }
219
220 if (result) {
221 CFRelease(result);
222 }
223 if (conditions) {
224 CFRelease(conditions);
225 }
226 if (proc_uuid) {
227 CFRelease(proc_uuid);
228 }
229
230 return (success && NEPolicyApply(policySession));
231}
232
65c25746
A
233//
234// Session
235//
236// Initialize listening sockets, timers, vpn control etc.,
237// write the PID file and call dispatch_main.
238//
239void
52b7d2ce
A
240session(void)
241{
52b7d2ce
A
242 char pid_file[MAXPATHLEN];
243 FILE *fp;
65c25746
A
244 int i;
245
246 main_queue = dispatch_get_main_queue();
52b7d2ce
A
247
248 /* initialize schedular */
249 sched_init();
250
e8d9021d
A
251 /* needs to be called after schedular */
252 if (init_power_mgmt() < 0) {
65c25746
A
253 plog(ASL_LEVEL_ERR,
254 "failed to initialize power-mgmt.");
52b7d2ce
A
255 exit(1);
256 }
65c25746
A
257
258 if (lcconf->autograbaddr == 1)
259 if (pfroute_init()) {
260 plog(ASL_LEVEL_ERR, "failed to initialize route socket.\n");
261 exit(1);
262 }
d9c572c0
A
263
264 if (!policy_session_init()) {
265 plog(ASL_LEVEL_ERR, "failed to initialize NEPolicy session.\n");
266 }
267
65c25746
A
268 if (initmyaddr()) {
269 plog(ASL_LEVEL_ERR, "failed to initialize listening addresses.\n");
270 exit(1);
271 }
272 if (isakmp_init()) {
273 plog(ASL_LEVEL_ERR, "failed to initialize isakmp");
52b7d2ce 274 exit(1);
65c25746 275 }
52b7d2ce 276#ifdef ENABLE_VPNCONTROL_PORT
65c25746
A
277 if (vpncontrol_init()) {
278 plog(ASL_LEVEL_ERR, "failed to initialize vpn control port");
279 //exit(1);
52b7d2ce
A
280 }
281#endif
282
65c25746
A
283 if (init_signal()) {
284 plog(ASL_LEVEL_ERR, "failed to initialize signals.\n");
285 exit(1);
286 }
287
52b7d2ce
A
288 for (i = 0; i <= NSIG; i++)
289 sigreq[i] = 0;
290
291 /* write .pid file */
292 if (!f_foreground) {
293 racoon_pid = getpid();
294 if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE] == NULL)
d1e348cf 295 strlcpy(pid_file, _PATH_VARRUN "racoon.pid", sizeof(pid_file));
52b7d2ce 296 else if (lcconf->pathinfo[LC_PATHTYPE_PIDFILE][0] == '/')
d1e348cf 297 strlcpy(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce 298 else {
d1e348cf
A
299 strlcat(pid_file, _PATH_VARRUN, sizeof(pid_file));
300 strlcat(pid_file, lcconf->pathinfo[LC_PATHTYPE_PIDFILE], sizeof(pid_file));
52b7d2ce
A
301 }
302 fp = fopen(pid_file, "w");
303 if (fp) {
304 if (fchmod(fileno(fp),
305 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1) {
65c25746 306 plog(ASL_LEVEL_ERR, "%s", strerror(errno));
52b7d2ce
A
307 fclose(fp);
308 exit(1);
309 }
310 fprintf(fp, "%ld\n", (long)racoon_pid);
311 fclose(fp);
312 } else {
65c25746 313 plog(ASL_LEVEL_ERR,
52b7d2ce
A
314 "cannot open %s", pid_file);
315 }
316 }
c8d8bee0
A
317
318 xpc_transaction_begin();
319
e97d2cf9
A
320#if !TARGET_OS_EMBEDDED
321 // enable keepalive for recovery (from crashes and bad exits... after init)
322 (void)launchd_update_racoon_keepalive(true);
323#endif // !TARGET_OS_EMBEDDED
e97d2cf9 324
65c25746
A
325 // Off to the races!
326 if (!terminated) {
327 dispatch_main();
328 }
329
330 exit(1); // should not be reached!!!
52b7d2ce
A
331}
332
333
334/* clear all status and exit program. */
335static void
65c25746 336close_session(int error)
52b7d2ce 337{
65c25746
A
338 sched_killall();
339 cleanup_power_mgmt();
d1e348cf 340 if ( terminated )
65c25746
A
341 ike_session_flush_all_phase2(false);
342 ike_session_flush_all_phase1(false);
52b7d2ce 343 close_sockets();
52b7d2ce 344
c8d8bee0
A
345 xpc_transaction_end();
346
e97d2cf9
A
347#if !TARGET_OS_EMBEDDED
348 // a clean exit, so disable launchd keepalive
349 (void)launchd_update_racoon_keepalive(false);
350#endif // !TARGET_OS_EMBEDDED
e97d2cf9 351
7ebaebe2 352 plog(ASL_LEVEL_NOTICE, "racoon shutdown\n");
52b7d2ce
A
353 exit(0);
354}
355
52b7d2ce
A
356
357/*
358 * waiting the termination of processing until sending DELETE message
359 * for all inbound SA will complete.
360 */
361static void
362check_flushsa_stub(p)
363 void *p;
364{
52b7d2ce
A
365 check_flushsa();
366}
367
368static void
369check_flushsa()
370{
371 vchar_t *buf;
372 struct sadb_msg *msg, *end, *next;
373 struct sadb_sa *sa;
374 caddr_t mhp[SADB_EXT_MAX + 1];
375 int n;
376
377 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
378 if (buf == NULL) {
65c25746 379 plog(ASL_LEVEL_DEBUG,
52b7d2ce
A
380 "pfkey_dump_sadb: returned nothing.\n");
381 return;
382 }
383
85f41bec
A
384 msg = ALIGNED_CAST(struct sadb_msg *)buf->v;
385 end = ALIGNED_CAST(struct sadb_msg *)(buf->v + buf->l);
52b7d2ce
A
386
387 /* counting SA except of dead one. */
388 n = 0;
389 while (msg < end) {
390 if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
391 break;
85f41bec 392 next = ALIGNED_CAST(struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len)); // Wcast-align fix (void*) - aligned buffer + multiple of 64
52b7d2ce
A
393 if (msg->sadb_msg_type != SADB_DUMP) {
394 msg = next;
395 continue;
396 }
397
398 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
65c25746 399 plog(ASL_LEVEL_ERR,
52b7d2ce
A
400 "pfkey_check (%s)\n", ipsec_strerror());
401 msg = next;
402 continue;
403 }
404
85f41bec 405 sa = ALIGNED_CAST(struct sadb_sa *)(mhp[SADB_EXT_SA]); // Wcast-align fix (void*) - mhp contains pointers to aligned structs
52b7d2ce
A
406 if (!sa) {
407 msg = next;
408 continue;
409 }
410
411 if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
412 n++;
413 msg = next;
414 continue;
415 }
416
417 msg = next;
418 }
419
420 if (buf != NULL)
421 vfree(buf);
422
423 if (n) {
424 sched_new(1, check_flushsa_stub, NULL);
425 return;
426 }
427
d1e348cf
A
428#if !TARGET_OS_EMBEDDED
429 if (lcconf->vt)
430 vproc_transaction_end(NULL, lcconf->vt);
431#endif
65c25746 432 close_session(0);
52b7d2ce
A
433}
434
435void
436auto_exit_do(void *p)
437{
7ebaebe2 438 plog(ASL_LEVEL_NOTICE,
d1e348cf 439 "performing auto exit\n");
d9c572c0
A
440#if ENABLE_NO_SA_FLUSH
441 close_session(0);
442#else
52b7d2ce
A
443 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
444 sched_new(1, check_flushsa_stub, NULL);
65c25746 445 dying();
d9c572c0 446#endif /* ENABLE_NO_SA_FLUSH */
52b7d2ce
A
447}
448
449void
450check_auto_exit(void)
451{
65c25746 452 if (lcconf->auto_exit_sched) { /* exit scheduled? */
52b7d2ce 453 if (lcconf->auto_exit_state != LC_AUTOEXITSTATE_ENABLED
65c25746
A
454 || vpn_control_connected() /* vpn control connected */
455 || policies_installed() /* policies installed in kernel */
456 || !no_remote_configs(FALSE)) { /* remote or anonymous configs */
52b7d2ce 457 SCHED_KILL(lcconf->auto_exit_sched);
65c25746 458 }
52b7d2ce
A
459 } else { /* exit not scheduled */
460 if (lcconf->auto_exit_state == LC_AUTOEXITSTATE_ENABLED
65c25746 461 && !vpn_control_connected()
93762ec7 462 && !policies_installed()
65c25746
A
463 && no_remote_configs(FALSE)) {
464 if (lcconf->auto_exit_delay == 0) {
465 auto_exit_do(NULL); /* immediate exit */
466 } else {
467 lcconf->auto_exit_sched = sched_new(lcconf->auto_exit_delay, auto_exit_do, NULL);
468 }
469 }
52b7d2ce
A
470 }
471}
472
65c25746
A
473static int signals[] = {
474 SIGHUP,
475 SIGINT,
476 SIGTERM,
477 SIGUSR1,
478 SIGUSR2,
479 SIGPIPE,
480 0
481};
482
52b7d2ce 483
886926c0 484void
65c25746
A
485check_sigreq()
486{
487 int sig;
488
489 /*
490 * XXX We are not able to tell if we got
491 * several time the same signal. This is
492 * not a problem for the current code,
493 * but we shall remember this limitation.
494 */
495 for (sig = 0; sig <= NSIG; sig++) {
496 if (sigreq[sig] == 0)
497 continue;
498
499 sigreq[sig]--;
500 switch(sig) {
501 case 0:
502 return;
503
504 /* Catch up childs, mainly scripts.
505 */
506
507 case SIGUSR1:
508 case SIGHUP:
509#ifdef ENABLE_HYBRID
510 if ((isakmp_cfg_init(ISAKMP_CFG_INIT_WARM)) != 0) {
511 plog(ASL_LEVEL_ERR,
512 "ISAKMP mode config structure reset failed, "
513 "not reloading\n");
514 return;
515 }
516#endif
517 if ( terminated )
518 break;
519
520 /*
521 * if we got a HUP... try graceful teardown of sessions before we close and reopen sockets...
522 * so that info-deletes notifications can make it to the peer.
523 */
524 if (sig == SIGHUP) {
525 ike_session_flush_all_phase2(true);
526 ike_session_flush_all_phase1(true);
527 }
528
529 /* Save old configuration, load new one... */
530 if (cfreparse(sig)) {
531 plog(ASL_LEVEL_ERR,
532 "configuration read failed\n");
533 exit(1);
534 }
535 if (lcconf->logfile_param == NULL && logFileStr[0] == 0)
536 plogresetfile(lcconf->pathinfo[LC_PATHTYPE_LOGFILE]);
537
538#if TARGET_OS_EMBEDDED
539 if (no_remote_configs(TRUE)) {
d9c572c0
A
540#if ENABLE_NO_SA_FLUSH
541 close_session(0);
542#else
65c25746
A
543 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
544#ifdef ENABLE_FASTQUIT
545 close_session(0);
546#else
547 sched_new(1, check_flushsa_stub, NULL);
d9c572c0 548#endif /* ENABLE_FASTQUIT */
65c25746 549 dying();
d9c572c0 550#endif /* ENABLE_NO_SA_FLUSH */
65c25746
A
551 }
552#endif
553
554 break;
555
556 case SIGINT:
557 case SIGTERM:
7ebaebe2 558 plog(ASL_LEVEL_NOTICE,
65c25746 559 "caught signal %d\n", sig);
d9c572c0
A
560#if ENABLE_NO_SA_FLUSH
561 close_session(0);
562#else
563 pfkey_send_flush(lcconf->sock_pfkey,
65c25746
A
564 SADB_SATYPE_UNSPEC);
565 if ( sig == SIGTERM ){
566 terminated = 1; /* in case if it hasn't been set yet */
567 close_session(0);
568 }
569 else
570 sched_new(1, check_flushsa_stub, NULL);
571
572 dying();
d9c572c0 573#endif /* ENABLE_NO_SA_FLUSH */
65c25746
A
574 break;
575
576 default:
7ebaebe2 577 plog(ASL_LEVEL_NOTICE,
65c25746
A
578 "caught signal %d\n", sig);
579 break;
580 }
581 }
582}
583
584
585/*
586 * asynchronous requests will actually dispatched in the
587 * main loop in session().
588 */
589RETSIGTYPE
590signal_handler(int sig, siginfo_t *sigi, void *ctx)
591{
592#if 0
7ebaebe2 593 plog(ASL_LEVEL_NOTICE,
65c25746
A
594 "%s received signal %d from pid %d uid %d\n\n",
595 __FUNCTION__, sig, sigi->si_pid, sigi->si_uid);
596#endif
597
598 /* Do not just set it to 1, because we may miss some signals by just setting
599 * values to 0/1
600 */
601 sigreq[sig]++;
602 if ( sig == SIGTERM ){
603 terminated = 1;
604 }
886926c0
A
605
606 pending_signal_handle = 1;
65c25746
A
607 dispatch_async(main_queue,
608 ^{
886926c0
A
609 if (pending_signal_handle) {
610 check_sigreq();
611 pending_signal_handle = 0;
612 }
65c25746
A
613 });
614}
615
616
617static int
52b7d2ce
A
618init_signal()
619{
620 int i;
621
65c25746 622 for (i = 0; signals[i] != 0; i++) {
52b7d2ce 623 if (set_signal(signals[i], signal_handler) < 0) {
65c25746 624 plog(ASL_LEVEL_ERR,
52b7d2ce
A
625 "failed to set_signal (%s)\n",
626 strerror(errno));
65c25746 627 return (1);
52b7d2ce 628 }
65c25746
A
629 }
630 return 0;
52b7d2ce
A
631}
632
633static int
65c25746 634set_signal(int sig, RETSIGTYPE (*func) (int, siginfo_t *, void *))
52b7d2ce
A
635{
636 struct sigaction sa;
637
638 memset((caddr_t)&sa, 0, sizeof(sa));
65c25746 639 sa.sa_sigaction = func;
e8d9021d 640 sa.sa_flags = SA_RESTART | SA_SIGINFO;
52b7d2ce
A
641
642 if (sigemptyset(&sa.sa_mask) < 0)
643 return -1;
644
645 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
646 return(-1);
647
648 return 0;
649}
650
65c25746
A
651void
652fatal_error(int error)
653{
654 close_session(error == 0 ? -1 : error);
655}
656
657/* suspend all socket sources except pf_key */
658void
659dying(void)
660{
661 if (lcconf->rt_source)
662 dispatch_suspend(lcconf->rt_source);
663 if (lcconf->vpncontrol_source)
664 dispatch_suspend(lcconf->vpncontrol_source);
665 isakmp_suspend_sockets();
666}
667
52b7d2ce
A
668static int
669close_sockets()
670{
65c25746 671 pfroute_close();
52b7d2ce 672 isakmp_close();
65c25746 673 pfkey_close();
52b7d2ce
A
674#ifdef ENABLE_VPNCONTROL_PORT
675 vpncontrol_close();
676#endif
65c25746 677
52b7d2ce
A
678 return 0;
679}
680
d1e348cf 681