]> git.saurik.com Git - apple/network_cmds.git/blob - racoon.tproj/session.c
network_cmds-176.4.1.tar.gz
[apple/network_cmds.git] / racoon.tproj / session.c
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
82 static void close_session __P((void));
83 static void check_rtsock __P((void *));
84 static void initfds __P((void));
85 static void init_signal __P((void));
86 static int set_signal __P((int sig, RETSIGTYPE (*func) __P((int))));
87 static void check_sigreq __P((void));
88 static void check_flushsa_stub __P((void *));
89 static void check_flushsa __P((void));
90 static int close_sockets __P((void));
91
92 static fd_set mask0;
93 static int nfds = 0;
94 static int sigreq = 0;
95
96 int
97 session(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. */
177 static void
178 close_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
188 static void
189 check_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
201 static void
202 initfds()
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
256 static 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 */
270 RETSIGTYPE
271 signal_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
296 extern int cfreparse(void);
297
298 static void
299 check_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 */
327 static void
328 check_flushsa_stub(p)
329 void *p;
330 {
331
332 check_flushsa();
333 }
334
335 static void
336 check_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
392 static void
393 init_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
406 static int
407 set_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
426 static int
427 close_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