1 /* $OpenBSD: sasyncd.c,v 1.18 2008/03/17 20:30:17 sobrado Exp $ */ 2 3 /* 4 * Copyright (c) 2005 H�kan Olsson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 /* 29 * This code was written under funding by Multicom Security AB. 30 */ 31 32 33 #include <sys/types.h> 34 #include <sys/time.h> 35 #include <errno.h> 36 #include <fcntl.h> 37 #include <pwd.h> 38 #include <signal.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <stdlib.h> 42 #include <unistd.h> 43 44 #include "sasyncd.h" 45 46 volatile sig_atomic_t daemon_shutdown = 0; 47 48 /* Called by signal handler for controlled daemon shutdown. */ 49 static void 50 sasyncd_stop(int s) 51 { 52 daemon_shutdown++; 53 } 54 55 static int 56 sasyncd_run(pid_t ppid) 57 { 58 struct timeval *timeout, tv; 59 fd_set *rfds, *wfds; 60 size_t fdsetsize; 61 int maxfd, n; 62 63 n = getdtablesize(); 64 fdsetsize = howmany(n, NFDBITS) * sizeof(fd_mask); 65 66 rfds = (fd_set *)malloc(fdsetsize); 67 if (!rfds) { 68 log_err("malloc(%lu) failed", (unsigned long)fdsetsize); 69 return -1; 70 } 71 72 wfds = (fd_set *)malloc(fdsetsize); 73 if (!wfds) { 74 log_err("malloc(%lu) failed", (unsigned long)fdsetsize); 75 return -1; 76 } 77 78 isakmpd_setrun(); 79 80 signal(SIGINT, sasyncd_stop); 81 signal(SIGTERM, sasyncd_stop); 82 83 timer_add("carp_undemote", CARP_DEMOTE_MAXTIME, 84 monitor_carpundemote, NULL); 85 86 while (!daemon_shutdown) { 87 memset(rfds, 0, fdsetsize); 88 memset(wfds, 0, fdsetsize); 89 maxfd = net_set_rfds(rfds); 90 n = net_set_pending_wfds(wfds); 91 if (n > maxfd) 92 maxfd = n; 93 94 pfkey_set_rfd(rfds); 95 pfkey_set_pending_wfd(wfds); 96 if (cfgstate.pfkey_socket + 1 > maxfd) 97 maxfd = cfgstate.pfkey_socket + 1; 98 99 carp_set_rfd(rfds); 100 if (cfgstate.route_socket + 1 > maxfd) 101 maxfd = cfgstate.route_socket + 1; 102 103 timeout = &tv; 104 timer_next_event(&tv); 105 106 n = select(maxfd, rfds, wfds, 0, timeout); 107 if (n == -1) { 108 if (errno != EINTR) { 109 log_err("select()"); 110 sleep(1); 111 } 112 } else if (n) { 113 net_handle_messages(rfds); 114 net_send_messages(wfds); 115 pfkey_read_message(rfds); 116 pfkey_send_message(wfds); 117 carp_read_message(rfds); 118 } 119 timer_run(); 120 121 /* Mostly for debugging. */ 122 if (getppid() != ppid) { 123 log_msg(0, "sasyncd: parent died"); 124 daemon_shutdown++; 125 } 126 } 127 free(rfds); 128 free(wfds); 129 return 0; 130 } 131 132 __dead static void 133 usage(void) 134 { 135 extern char *__progname; 136 137 fprintf(stderr, "usage: %s [-dv] [-c config-file]\n", __progname); 138 exit(1); 139 } 140 141 int 142 main(int argc, char **argv) 143 { 144 extern char *__progname; 145 char *cfgfile = 0; 146 int ch; 147 148 if (geteuid() != 0) { 149 /* No point in continuing. */ 150 fprintf(stderr, "%s: This daemon needs to be run as root.\n", 151 __progname); 152 return 1; 153 } 154 155 memset(&cfgstate, 0, sizeof cfgstate); 156 157 while ((ch = getopt(argc, argv, "c:dv")) != -1) { 158 switch (ch) { 159 case 'c': 160 if (cfgfile) 161 return 2; 162 cfgfile = optarg; 163 break; 164 case 'd': 165 cfgstate.debug++; 166 break; 167 case 'v': 168 cfgstate.verboselevel++; 169 break; 170 default: 171 usage(); 172 } 173 } 174 argc -= optind; 175 argv += optind; 176 177 if (argc > 0) 178 usage(); 179 180 log_init(__progname); 181 timer_init(); 182 183 cfgstate.runstate = INIT; 184 LIST_INIT(&cfgstate.peerlist); 185 186 cfgstate.listen_port = SASYNCD_DEFAULT_PORT; 187 188 if (!cfgfile) 189 cfgfile = SASYNCD_CFGFILE; 190 191 if (conf_parse_file(cfgfile) == 0 ) { 192 if (!cfgstate.sharedkey) { 193 fprintf(stderr, "config: " 194 "no shared key specified, cannot continue"); 195 exit(1); 196 } 197 } else { 198 exit(1); 199 } 200 201 carp_demote(CARP_INC, 0); 202 203 if (carp_init()) 204 return 1; 205 if (pfkey_init(0)) 206 return 1; 207 if (net_init()) 208 return 1; 209 210 if (!cfgstate.debug) 211 if (daemon(1, 0)) { 212 perror("daemon()"); 213 exit(1); 214 } 215 216 if (monitor_init()) { 217 /* Parent, with privileges. */ 218 monitor_loop(); 219 exit(0); 220 } 221 222 /* Child, no privileges left. Run main loop. */ 223 sasyncd_run(getppid()); 224 225 /* Shutdown. */ 226 log_msg(0, "shutting down..."); 227 228 net_shutdown(); 229 pfkey_shutdown(); 230 return 0; 231 } 232 233 /* Special for compiling with Boehms GC. See Makefile and sasyncd.h */ 234 #if defined (GC_DEBUG) 235 char * 236 gc_strdup(const char *x) 237 { 238 char *strcpy(char *,const char *); 239 char *y = malloc(strlen(x) + 1); 240 return strcpy(y,x); 241 } 242 #endif 243