]> git.saurik.com Git - apple/network_cmds.git/blame - racoon.tproj/session.c
network_cmds-201.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
A
157 if (FD_ISSET(p->sock, &rfds))
158 isakmp_handler(p->sock);
ac2f15b3
A
159#ifdef IKE_NAT_T
160 if (p->nattsock >= 0 && FD_ISSET(p->nattsock, &rfds))
161 isakmp_natt_handler(p->nattsock);
162#endif
7ba0088d
A
163 }
164
165 if (FD_ISSET(lcconf->sock_pfkey, &rfds))
166 pfkey_handler();
167
07f47057 168 if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds))
7ba0088d
A
169 if (update_myaddrs() && lcconf->autograbaddr)
170 sched_new(5, check_rtsock, NULL);
7ba0088d
A
171 }
172}
173
174/* clear all status and exit program. */
175static void
176close_session()
177{
178 flushph1();
179 close_sockets();
180 backupsa_clean();
181
182 plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
183 exit(0);
184}
185
07f47057 186
7ba0088d
A
187static void
188check_rtsock(p)
189 void *p;
07f47057 190{
7ba0088d 191 grab_myaddrs();
07f47057 192 isakmp_close_unused();
7ba0088d 193 autoconf_myaddrsport();
07f47057 194 isakmp_open();
7ba0088d
A
195
196 /* initialize socket list again */
197 initfds();
198}
199
200static void
201initfds()
202{
203 struct myaddrs *p;
204
205 nfds = 0;
206
207 FD_ZERO(&mask0);
208
209#ifdef ENABLE_ADMINPORT
ac2f15b3
A
210 if (lcconf->sock_admin >= FD_SETSIZE) {
211 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
212 exit(1);
213 }
7ba0088d
A
214 FD_SET(lcconf->sock_admin, &mask0);
215 nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
216#endif
ac2f15b3
A
217 if (lcconf->sock_pfkey >= FD_SETSIZE) {
218 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
219 exit(1);
220 }
7ba0088d
A
221 FD_SET(lcconf->sock_pfkey, &mask0);
222 nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
ac2f15b3
A
223 if (lcconf->rtsock >= 0) {
224 if (lcconf->rtsock >= FD_SETSIZE) {
225 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
226 exit(1);
227 }
228 FD_SET(lcconf->rtsock, &mask0);
229 nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
230 }
7ba0088d
A
231
232 for (p = lcconf->myaddrs; p; p = p->next) {
233 if (!p->addr)
234 continue;
ac2f15b3
A
235 if (p->sock >= FD_SETSIZE) {
236 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
237 exit(1);
238 }
7ba0088d
A
239 FD_SET(p->sock, &mask0);
240 nfds = (nfds > p->sock ? nfds : p->sock);
ac2f15b3
A
241#ifdef IKE_NAT_T
242 if (p->nattsock >= 0) {
243 if (p-> nattsock >= FD_SETSIZE) {
244 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
245 exit(1);
246 }
247 FD_SET(p->nattsock, &mask0);
248 nfds = (nfds > p->nattsock ? nfds : p->nattsock);
249 }
250#endif
7ba0088d
A
251 }
252 nfds++;
253}
254
255static int signals[] = {
256 SIGHUP,
257 SIGINT,
258 SIGTERM,
259 SIGUSR1,
260 SIGUSR2,
261 SIGCHLD,
262 0
263};
264
265/*
266 * asynchronous requests will actually dispatched in the
267 * main loop in session().
268 */
269RETSIGTYPE
270signal_handler(sig)
271 int sig;
272{
273 switch (sig) {
274 case SIGCHLD:
275 {
276 pid_t pid;
277 int s;
278
279 pid = wait(&s);
280 }
281 break;
282
283#ifdef DEBUG_RECORD_MALLOCATION
284 case SIGUSR2:
285 DRM_dump();
286 break;
287#endif
288 default:
289 /* XXX should be blocked any signal ? */
290 sigreq = sig;
291 break;
292 }
293}
294
ac2f15b3
A
295extern int cfreparse(void);
296
7ba0088d
A
297static void
298check_sigreq()
299{
300 switch (sigreq) {
301 case 0:
302 return;
303
304 case SIGHUP:
305 if (cfreparse()) {
306 plog(LLV_ERROR, LOCATION, NULL,
307 "configuration read failed\n");
308 exit(1);
309 }
310 sigreq = 0;
311 break;
312
313 default:
314 plog(LLV_INFO, LOCATION, NULL, "caught signal %d\n", sigreq);
315 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
316 sched_new(1, check_flushsa_stub, NULL);
317 sigreq = 0;
318 break;
319 }
320}
321
322/*
323 * waiting the termination of processing until sending DELETE message
324 * for all inbound SA will complete.
325 */
326static void
327check_flushsa_stub(p)
328 void *p;
329{
330
331 check_flushsa();
332}
333
334static void
335check_flushsa()
336{
337 vchar_t *buf;
338 struct sadb_msg *msg, *end, *next;
339 struct sadb_sa *sa;
340 caddr_t mhp[SADB_EXT_MAX + 1];
341 int n;
342
343 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
344
345 msg = (struct sadb_msg *)buf->v;
346 end = (struct sadb_msg *)(buf->v + buf->l);
347
348 /* counting SA except of dead one. */
349 n = 0;
350 while (msg < end) {
351 if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
352 break;
353 next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
354 if (msg->sadb_msg_type != SADB_DUMP) {
355 msg = next;
356 continue;
357 }
358
359 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
360 plog(LLV_ERROR, LOCATION, NULL,
361 "pfkey_check (%s)\n", ipsec_strerror());
362 msg = next;
363 continue;
364 }
365
366 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
367 if (!sa) {
368 msg = next;
369 continue;
370 }
371
372 if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
373 n++;
374 msg = next;
375 continue;
376 }
377
378 msg = next;
379 }
ac2f15b3
A
380
381 if (buf) vfree(buf);
7ba0088d
A
382
383 if (n) {
384 sched_new(1, check_flushsa_stub, NULL);
385 return;
386 }
387
388 close_session();
389}
390
391static void
392init_signal()
393{
394 int i;
395
396 for (i = 0; signals[i] != 0; i++)
397 if (set_signal(signals[i], signal_handler) < 0) {
398 plog(LLV_ERROR, LOCATION, NULL,
399 "failed to set_signal (%s)\n",
400 strerror(errno));
401 exit(1);
402 }
403}
404
405static int
406set_signal(sig, func)
407 int sig;
408 RETSIGTYPE (*func) __P((int));
409{
410 struct sigaction sa;
411
412 memset((caddr_t)&sa, 0, sizeof(sa));
413 sa.sa_handler = func;
414 sa.sa_flags = SA_RESTART;
415
416 if (sigemptyset(&sa.sa_mask) < 0)
417 return -1;
418
419 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
420 return(-1);
421
422 return 0;
423}
424
425static int
426close_sockets()
427{
428 isakmp_close();
429 pfkey_close(lcconf->sock_pfkey);
430#ifdef ENABLE_ADMINPORT
431 (void)admin_close();
432#endif
433 return 0;
434}
435