1 /* $OpenBSD: sasyncd.c,v 1.24 2015/08/20 22:39:29 deraadt 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 = malloc(fdsetsize); 67 if (!rfds) { 68 log_err("malloc(%lu) failed", (unsigned long)fdsetsize); 69 return -1; 70 } 71 72 wfds = malloc(fdsetsize); 73 if (!wfds) { 74 log_err("malloc(%lu) failed", (unsigned long)fdsetsize); 75 free(rfds); 76 return -1; 77 } 78 79 control_setrun(); 80 81 signal(SIGINT, sasyncd_stop); 82 signal(SIGTERM, sasyncd_stop); 83 84 timer_add("carp_undemote", CARP_DEMOTE_MAXTIME, 85 monitor_carpundemote, NULL); 86 87 while (!daemon_shutdown) { 88 memset(rfds, 0, fdsetsize); 89 memset(wfds, 0, fdsetsize); 90 maxfd = net_set_rfds(rfds); 91 n = net_set_pending_wfds(wfds); 92 if (n > maxfd) 93 maxfd = n; 94 95 pfkey_set_rfd(rfds); 96 pfkey_set_pending_wfd(wfds); 97 if (cfgstate.pfkey_socket + 1 > maxfd) 98 maxfd = cfgstate.pfkey_socket + 1; 99 100 carp_set_rfd(rfds); 101 if (cfgstate.route_socket + 1 > maxfd) 102 maxfd = cfgstate.route_socket + 1; 103 104 timeout = &tv; 105 timer_next_event(&tv); 106 107 n = select(maxfd, rfds, wfds, 0, timeout); 108 if (n == -1) { 109 if (errno != EINTR) { 110 log_err("select()"); 111 sleep(1); 112 } 113 } else if (n) { 114 net_handle_messages(rfds); 115 net_send_messages(wfds); 116 pfkey_read_message(rfds); 117 pfkey_send_message(wfds); 118 carp_read_message(rfds); 119 } 120 timer_run(); 121 122 /* Mostly for debugging. */ 123 if (getppid() != ppid) { 124 log_msg(0, "sasyncd: parent died"); 125 daemon_shutdown++; 126 } 127 } 128 free(rfds); 129 free(wfds); 130 return 0; 131 } 132 133 __dead static void 134 usage(void) 135 { 136 extern char *__progname; 137 138 fprintf(stderr, "usage: %s [-dv] [-c config-file]\n", __progname); 139 exit(1); 140 } 141 142 int 143 main(int argc, char **argv) 144 { 145 extern char *__progname; 146 char *cfgfile = 0; 147 int ch; 148 149 if (geteuid() != 0) { 150 /* No point in continuing. */ 151 fprintf(stderr, "%s: This daemon needs to be run as root.\n", 152 __progname); 153 return 1; 154 } 155 156 while ((ch = getopt(argc, argv, "c:dv")) != -1) { 157 switch (ch) { 158 case 'c': 159 if (cfgfile) 160 usage(); 161 cfgfile = optarg; 162 break; 163 case 'd': 164 cfgstate.debug++; 165 break; 166 case 'v': 167 cfgstate.verboselevel++; 168 break; 169 default: 170 usage(); 171 } 172 } 173 argc -= optind; 174 argv += optind; 175 176 if (argc > 0) 177 usage(); 178 179 log_init(__progname); 180 timer_init(); 181 182 cfgstate.runstate = INIT; 183 LIST_INIT(&cfgstate.peerlist); 184 185 cfgstate.listen_port = SASYNCD_DEFAULT_PORT; 186 cfgstate.flags |= CTL_DEFAULT; 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