]> git.saurik.com Git - apple/network_cmds.git/blame_incremental - racoon.tproj/session.c
network_cmds-176.tar.gz
[apple/network_cmds.git] / racoon.tproj / session.c
... / ...
CommitLineData
1/* $KAME: session.c,v 1.31 2002/11/20 02:06:18 itojun Exp $ */
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>
60
61#include "libpfkey.h"
62
63#include "var.h"
64#include "misc.h"
65#include "vmbuf.h"
66#include "plog.h"
67#include "debug.h"
68
69#include "schedule.h"
70#include "session.h"
71#include "grabmyaddr.h"
72#include "cfparse.h"
73#include "isakmp_var.h"
74#include "admin_var.h"
75#include "oakley.h"
76#include "pfkey.h"
77#include "handler.h"
78#include "localconf.h"
79#include "remoteconf.h"
80#include "backupsa.h"
81
82static void close_session __P((void));
83static void check_rtsock __P((void *));
84static void initfds __P((void));
85static void init_signal __P((void));
86static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
87static void check_sigreq __P((void));
88static void check_flushsa_stub __P((void *));
89static void check_flushsa __P((void));
90static int close_sockets __P((void));
91
92static fd_set mask0;
93static int nfds = 0;
94static int sigreq = 0;
95
96int
97session(void)
98{
99 fd_set rfds;
100 struct timeval *timeout;
101 int error;
102 struct myaddrs *p;
103
104 /* initialize schedular */
105 sched_init();
106
107 init_signal();
108
109#ifdef ENABLE_ADMINPORT
110 /* debug port has no authentication, do not open it */
111 if (admin_init() < 0)
112 exit(1);
113#endif
114
115 initmyaddr();
116
117 if (isakmp_init() < 0)
118 exit(1);
119
120 initfds();
121
122 sigreq = 0;
123 while (1) {
124 rfds = mask0;
125
126 /*
127 * asynchronous requests via signal.
128 * make sure to reset sigreq to 0.
129 */
130 check_sigreq();
131
132 /* scheduling */
133 timeout = schedular();
134
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 }
148
149#ifdef ENABLE_ADMINPORT
150 if (FD_ISSET(lcconf->sock_admin, &rfds))
151 admin_handler();
152#endif
153
154 for (p = lcconf->myaddrs; p; p = p->next) {
155 if (!p->addr)
156 continue;
157 if (FD_ISSET(p->sock, &rfds))
158 isakmp_handler(p->sock);
159#ifdef IKE_NAT_T
160 if (p->nattsock >= 0 && FD_ISSET(p->nattsock, &rfds))
161 isakmp_natt_handler(p->nattsock);
162#endif
163 }
164
165 if (FD_ISSET(lcconf->sock_pfkey, &rfds))
166 pfkey_handler();
167
168 if (lcconf->rtsock >= 0 && FD_ISSET(lcconf->rtsock, &rfds)) {
169 if (update_myaddrs() && lcconf->autograbaddr)
170 sched_new(5, check_rtsock, NULL);
171 initfds();
172 }
173 }
174}
175
176/* clear all status and exit program. */
177static void
178close_session()
179{
180 flushph1();
181 close_sockets();
182 backupsa_clean();
183
184 plog(LLV_INFO, LOCATION, NULL, "racoon shutdown\n");
185 exit(0);
186}
187
188static void
189check_rtsock(p)
190 void *p;
191{
192 isakmp_close();
193 grab_myaddrs();
194 autoconf_myaddrsport();
195 isakmp_open();
196
197 /* initialize socket list again */
198 initfds();
199}
200
201static void
202initfds()
203{
204 struct myaddrs *p;
205
206 nfds = 0;
207
208 FD_ZERO(&mask0);
209
210#ifdef ENABLE_ADMINPORT
211 if (lcconf->sock_admin >= FD_SETSIZE) {
212 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
213 exit(1);
214 }
215 FD_SET(lcconf->sock_admin, &mask0);
216 nfds = (nfds > lcconf->sock_admin ? nfds : lcconf->sock_admin);
217#endif
218 if (lcconf->sock_pfkey >= FD_SETSIZE) {
219 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
220 exit(1);
221 }
222 FD_SET(lcconf->sock_pfkey, &mask0);
223 nfds = (nfds > lcconf->sock_pfkey ? nfds : lcconf->sock_pfkey);
224 if (lcconf->rtsock >= 0) {
225 if (lcconf->rtsock >= FD_SETSIZE) {
226 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
227 exit(1);
228 }
229 FD_SET(lcconf->rtsock, &mask0);
230 nfds = (nfds > lcconf->rtsock ? nfds : lcconf->rtsock);
231 }
232
233 for (p = lcconf->myaddrs; p; p = p->next) {
234 if (!p->addr)
235 continue;
236 if (p->sock >= FD_SETSIZE) {
237 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
238 exit(1);
239 }
240 FD_SET(p->sock, &mask0);
241 nfds = (nfds > p->sock ? nfds : p->sock);
242#ifdef IKE_NAT_T
243 if (p->nattsock >= 0) {
244 if (p-> nattsock >= FD_SETSIZE) {
245 plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun\n");
246 exit(1);
247 }
248 FD_SET(p->nattsock, &mask0);
249 nfds = (nfds > p->nattsock ? nfds : p->nattsock);
250 }
251#endif
252 }
253 nfds++;
254}
255
256static int signals[] = {
257 SIGHUP,
258 SIGINT,
259 SIGTERM,
260 SIGUSR1,
261 SIGUSR2,
262 SIGCHLD,
263 0
264};
265
266/*
267 * asynchronous requests will actually dispatched in the
268 * main loop in session().
269 */
270RETSIGTYPE
271signal_handler(sig)
272 int sig;
273{
274 switch (sig) {
275 case SIGCHLD:
276 {
277 pid_t pid;
278 int s;
279
280 pid = wait(&s);
281 }
282 break;
283
284#ifdef DEBUG_RECORD_MALLOCATION
285 case SIGUSR2:
286 DRM_dump();
287 break;
288#endif
289 default:
290 /* XXX should be blocked any signal ? */
291 sigreq = sig;
292 break;
293 }
294}
295
296extern int cfreparse(void);
297
298static void
299check_sigreq()
300{
301 switch (sigreq) {
302 case 0:
303 return;
304
305 case SIGHUP:
306 if (cfreparse()) {
307 plog(LLV_ERROR, LOCATION, NULL,
308 "configuration read failed\n");
309 exit(1);
310 }
311 sigreq = 0;
312 break;
313
314 default:
315 plog(LLV_INFO, LOCATION, NULL, "caught signal %d\n", sigreq);
316 pfkey_send_flush(lcconf->sock_pfkey, SADB_SATYPE_UNSPEC);
317 sched_new(1, check_flushsa_stub, NULL);
318 sigreq = 0;
319 break;
320 }
321}
322
323/*
324 * waiting the termination of processing until sending DELETE message
325 * for all inbound SA will complete.
326 */
327static void
328check_flushsa_stub(p)
329 void *p;
330{
331
332 check_flushsa();
333}
334
335static void
336check_flushsa()
337{
338 vchar_t *buf;
339 struct sadb_msg *msg, *end, *next;
340 struct sadb_sa *sa;
341 caddr_t mhp[SADB_EXT_MAX + 1];
342 int n;
343
344 buf = pfkey_dump_sadb(SADB_SATYPE_UNSPEC);
345
346 msg = (struct sadb_msg *)buf->v;
347 end = (struct sadb_msg *)(buf->v + buf->l);
348
349 /* counting SA except of dead one. */
350 n = 0;
351 while (msg < end) {
352 if (PFKEY_UNUNIT64(msg->sadb_msg_len) < sizeof(*msg))
353 break;
354 next = (struct sadb_msg *)((caddr_t)msg + PFKEY_UNUNIT64(msg->sadb_msg_len));
355 if (msg->sadb_msg_type != SADB_DUMP) {
356 msg = next;
357 continue;
358 }
359
360 if (pfkey_align(msg, mhp) || pfkey_check(mhp)) {
361 plog(LLV_ERROR, LOCATION, NULL,
362 "pfkey_check (%s)\n", ipsec_strerror());
363 msg = next;
364 continue;
365 }
366
367 sa = (struct sadb_sa *)(mhp[SADB_EXT_SA]);
368 if (!sa) {
369 msg = next;
370 continue;
371 }
372
373 if (sa->sadb_sa_state != SADB_SASTATE_DEAD) {
374 n++;
375 msg = next;
376 continue;
377 }
378
379 msg = next;
380 }
381
382 if (buf) vfree(buf);
383
384 if (n) {
385 sched_new(1, check_flushsa_stub, NULL);
386 return;
387 }
388
389 close_session();
390}
391
392static void
393init_signal()
394{
395 int i;
396
397 for (i = 0; signals[i] != 0; i++)
398 if (set_signal(signals[i], signal_handler) < 0) {
399 plog(LLV_ERROR, LOCATION, NULL,
400 "failed to set_signal (%s)\n",
401 strerror(errno));
402 exit(1);
403 }
404}
405
406static int
407set_signal(sig, func)
408 int sig;
409 RETSIGTYPE (*func) __P((int));
410{
411 struct sigaction sa;
412
413 memset((caddr_t)&sa, 0, sizeof(sa));
414 sa.sa_handler = func;
415 sa.sa_flags = SA_RESTART;
416
417 if (sigemptyset(&sa.sa_mask) < 0)
418 return -1;
419
420 if (sigaction(sig, &sa, (struct sigaction *)0) < 0)
421 return(-1);
422
423 return 0;
424}
425
426static int
427close_sockets()
428{
429 isakmp_close();
430 pfkey_close(lcconf->sock_pfkey);
431#ifdef ENABLE_ADMINPORT
432 (void)admin_close();
433#endif
434 return 0;
435}
436