]> git.saurik.com Git - apple/network_cmds.git/blame - racoon.tproj/session.c
network_cmds-245.1.tar.gz
[apple/network_cmds.git] / racoon.tproj / session.c
CommitLineData
ac2f15b3 1/* $KAME: session.c,v 1.31 2002/11/20 02:06:18 itojun Exp $ */
7ba0088d
A
2
3/*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/types.h>
33#include <sys/param.h>
34#include <sys/time.h>
35#include <sys/socket.h>
36#if HAVE_SYS_WAIT_H
37# include <sys/wait.h>
38#endif
39#ifndef WEXITSTATUS
40# define WEXITSTATUS(s) ((unsigned)(s) >> 8)
41#endif
42#ifndef WIFEXITED
43# define WIFEXITED(s) (((s) & 255) == 0)
44#endif
45
46#ifdef IPV6_INRIA_VERSION
47#include <netinet/ipsec.h>
48#else
49#include <netinet6/ipsec.h>
50#endif
51
52#include <stdlib.h>
53#include <stdio.h>
54#include <string.h>
55#include <errno.h>
56#ifdef HAVE_UNISTD_H
57#include <unistd.h>
58#endif
59#include <signal.h>
07f47057 60#include <sys/stat.h>
7ba0088d
A
61
62#include "libpfkey.h"
63
64#include "var.h"
65#include "misc.h"
66#include "vmbuf.h"
67#include "plog.h"
68#include "debug.h"
69
70#include "schedule.h"
71#include "session.h"
72#include "grabmyaddr.h"
73#include "cfparse.h"
74#include "isakmp_var.h"
75#include "admin_var.h"
76#include "oakley.h"
77#include "pfkey.h"
78#include "handler.h"
79#include "localconf.h"
80#include "remoteconf.h"
81#include "backupsa.h"
82
83static void close_session __P((void));
84static void check_rtsock __P((void *));
85static void initfds __P((void));
86static void init_signal __P((void));
87static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
88static void check_sigreq __P((void));
89static void check_flushsa_stub __P((void *));
90static void check_flushsa __P((void));
91static int close_sockets __P((void));
92
93static fd_set mask0;
94static int nfds = 0;
95static int sigreq = 0;
96
97int
98session(void)
99{
100 fd_set rfds;
101 struct timeval *timeout;
102 int error;
103 struct myaddrs *p;
104
105 /* initialize schedular */
106 sched_init();
107
108 init_signal();
109
110#ifdef ENABLE_ADMINPORT
111 /* debug port has no authentication, do not open it */
112 if (admin_init() < 0)
113 exit(1);
114#endif
115
116 initmyaddr();
117
118 if (isakmp_init() < 0)
119 exit(1);
120
121 initfds();
122
123 sigreq = 0;
124 while (1) {
07f47057 125
7ba0088d
A
126 /*
127 * asynchronous requests via signal.
128 * make sure to reset sigreq to 0.
129 */
130 check_sigreq();
131
132 /* scheduling */
133 timeout = schedular();
07f47057 134 rfds = mask0;
7ba0088d
A
135 error = select(nfds, &rfds, (fd_set *)0, (fd_set *)0, timeout);
136 if (error < 0) {
137 switch (errno) {
138 case EINTR:
139 continue;
140 default:
141 plog(LLV_ERROR, LOCATION, NULL,
142 "failed to select (%s)\n",
143 strerror(errno));
144 return -1;
145 }
146 /*NOTREACHED*/
147 }
7ba0088d
A
148#ifdef ENABLE_ADMINPORT
149 if (FD_ISSET(lcconf->sock_admin, &rfds))
150 admin_handler();
151#endif
152
153 for (p = lcconf->myaddrs; p; p = p->next) {
154 if (!p->addr)
155 continue;
07f47057 156
7ba0088d 157 if (FD_ISSET(p->sock, &rfds))
2b484d24
A
158 if ((error = isakmp_handler(p->sock)) == -2)
159 break;
160
161
ac2f15b3
A
162#ifdef IKE_NAT_T
163 if (p->nattsock >= 0 && FD_ISSET(p->nattsock, &rfds))
2b484d24
A
164 if ((error = isakmp_natt_handler(p->nattsock)) == -2)
165 break;
ac2f15b3 166#endif
7ba0088d 167 }
2b484d24
A
168 if (error == -2) {
169 if (lcconf->autograbaddr) {
170 /* serious socket problem - close all listening sockets and re-open */
171 isakmp_close();
172 initfds();
173 sched_new(5, check_rtsock, NULL);
174 continue;
175 } else {
176 isakmp_close_sockets();
177 isakmp_open();
178 }
179
180 }
7ba0088d
A
181
182 if (FD_ISSET(lcconf->sock_pfkey, &rfds))
183 pfkey_handler();
184
07f47057 185 if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds))
7ba0088d
A
186 if (update_myaddrs() && lcconf->autograbaddr)
187 sched_new(5, check_rtsock, NULL);
7ba0088d
A
188 }
189}
190
191/* clear all status and exit program. */
192static void
193close_session()
194{
195 flushph1();
196 close_sockets();
197 backupsa_clean();
198
199 plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
200 exit(0);
201}
202
07f47057 203
7ba0088d
A
204static void
205check_rtsock(p)
206 void *p;
07f47057 207{
7ba0088d 208 grab_myaddrs();
07f47057 209 isakmp_close_unused();
7ba0088d 210 autoconf_myaddrsport();
07f47057 211 isakmp_open();
7ba0088d
A
212
213 /* initialize socket list again */
214 initfds();
215}
216
217static void
218initfds()
219{
220 struct myaddrs *p;
221
222 nfds = 0;
223
224 FD_ZERO(&mask0);
225
226#ifdef ENABLE_ADMINPORT
ac2f15b3
A
227 if (lcconf->sock_admin >= FD_SETSIZE) {
228 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
229 exit(1);
230 }
7ba0088d
A
231 FD_SET(lcconf->sock_admin, &mask0);
232 nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
233#endif
ac2f15b3
A
234 if (lcconf->sock_pfkey >= FD_SETSIZE) {
235 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
236 exit(1);
237 }
7ba0088d
A
238 FD_SET(lcconf->sock_pfkey, &mask0);
239 nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
ac2f15b3
A
240 if (lcconf->rtsock >= 0) {
241 if (lcconf->rtsock >= FD_SETSIZE) {
242 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
243 exit(1);
244 }
245 FD_SET(lcconf->rtsock, &mask0);
246 nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
247 }
7ba0088d
A
248
249 for (p = lcconf->myaddrs; p; p = p->next) {
250 if (!p->addr)
251 continue;
ac2f15b3
A
252 if (p->sock >= FD_SETSIZE) {
253 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
254 exit(1);
255 }
7ba0088d
A
256 FD_SET(p->sock, &mask0);
257 nfds = (nfds > p->sock ? nfds : p->sock);
ac2f15b3
A
258#ifdef IKE_NAT_T
259 if (p->nattsock >= 0) {
260 if (p-> nattsock >= FD_SETSIZE) {
261 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
262 exit(1);
263 }
264 FD_SET(p->nattsock, &mask0);
265 nfds = (nfds > p->nattsock ? nfds : p->nattsock);
266 }
267#endif
7ba0088d
A
268 }
269 nfds++;
270}
271
272static int signals[] = {
273 SIGHUP,
274 SIGINT,
275 SIGTERM,
276 SIGUSR1,
277 SIGUSR2,
278 SIGCHLD,
279 0
280};
281
282/*
283 * asynchronous requests will actually dispatched in the
284 * main loop in session().
285 */
286RETSIGTYPE
287signal_handler(sig)
288 int sig;
289{
290 switch (sig) {
291 case SIGCHLD:
292 {
293 pid_t pid;
294 int s;
295
296 pid = wait(&s);
297 }
298 break;
299
300#ifdef DEBUG_RECORD_MALLOCATION
301 case SIGUSR2:
302 DRM_dump();
303 break;
304#endif
305 default:
306 /* XXX should be blocked any signal ? */
307 sigreq = sig;
308 break;
309 }
310}
311
ac2f15b3
A
312extern int cfreparse(void);
313
7ba0088d
A
314static void
315check_sigreq()
316{
317 switch (sigreq) {
318 case 0:
319 return;
320
321 case SIGHUP:
322 if (cfreparse()) {
323 plog(LLV_ERROR, LOCATION, NULL,
324 "configuration read failed\n");
325 exit(1);
326 }
327 sigreq = 0;
328 break;
329
330 default:
331 plog(LLV_INFO, LOCATION, NULL, "caught signal %d\n", sigreq);
332 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
333 sched_new(1, check_flushsa_stub, NULL);
334 sigreq = 0;
335 break;
336 }
337}
338
339/*
340 * waiting the termination of processing until sending DELETE message
341 * for all inbound SA will complete.
342 */
343static void
344check_flushsa_stub(p)
345 void *p;
346{
347
348 check_flushsa();
349}
350
351static void
352check_flushsa()
353{
354 vchar_t *buf;
355 struct sadb_msg *msg, *end, *next;
356 struct sadb_sa *sa;
357 caddr_t mhp[SADB_EXT_MAX + 1];
358 int n;
359
360 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
361
362 msg = (struct sadb_msg *)buf->v;
363 end = (struct sadb_msg *)(buf->v + buf->l);
364
365 /* counting SA except of dead one. */
366 n = 0;
367 while (msg < end) {
368 if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
369 break;
370 next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
371 if (msg->sadb_msg_type != SADB_DUMP) {
372 msg = next;
373 continue;
374 }
375
376 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
377 plog(LLV_ERROR, LOCATION, NULL,
378 "pfkey_check (%s)\n", ipsec_strerror());
379 msg = next;
380 continue;
381 }
382
383 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
384 if (!sa) {
385 msg = next;
386 continue;
387 }
388
389 if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
390 n++;
391 msg = next;
392 continue;
393 }
394
395 msg = next;
396 }
ac2f15b3
A
397
398 if (buf) vfree(buf);
7ba0088d
A
399
400 if (n) {
401 sched_new(1, check_flushsa_stub, NULL);
402 return;
403 }
404
405 close_session();
406}
407
408static void
409init_signal()
410{
411 int i;
412
413 for (i = 0; signals[i] != 0; i++)
414 if (set_signal(signals[i], signal_handler) < 0) {
415 plog(LLV_ERROR, LOCATION, NULL,
416 "failed to set_signal (%s)\n",
417 strerror(errno));
418 exit(1);
419 }
420}
421
422static int
423set_signal(sig, func)
424 int sig;
425 RETSIGTYPE (*func) __P((int));
426{
427 struct sigaction sa;
428
429 memset((caddr_t)&sa, 0, sizeof(sa));
430 sa.sa_handler = func;
431 sa.sa_flags = SA_RESTART;
432
433 if (sigemptyset(&sa.sa_mask) < 0)
434 return -1;
435
436 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
437 return(-1);
438
439 return 0;
440}
441
442static int
443close_sockets()
444{
445 isakmp_close();
446 pfkey_close(lcconf->sock_pfkey);
447#ifdef ENABLE_ADMINPORT
448 (void)admin_close();
449#endif
450 return 0;
451}
452