1 /* 2 * netifd - network interface daemon 3 * Copyright (C) 2012 Felix Fietkau <nbd@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 #include <getopt.h> 18 #include <signal.h> 19 #include <stdarg.h> 20 #include <syslog.h> 21 22 #include "netifd.h" 23 #include "ubus.h" 24 #include "config.h" 25 #include "system.h" 26 #include "interface.h" 27 #include "wireless.h" 28 #include "proto.h" 29 #include "extdev.h" 30 31 unsigned int debug_mask = 0; 32 const char *main_path = DEFAULT_MAIN_PATH; 33 const char *config_path = DEFAULT_CONFIG_PATH; 34 const char *resolv_conf = DEFAULT_RESOLV_CONF; 35 static char **global_argv; 36 37 static struct list_head process_list = LIST_HEAD_INIT(process_list); 38 39 #define DEFAULT_LOG_LEVEL L_NOTICE 40 41 static int log_level = DEFAULT_LOG_LEVEL; 42 static const int log_class[] = { 43 [L_CRIT] = LOG_CRIT, 44 [L_WARNING] = LOG_WARNING, 45 [L_NOTICE] = LOG_NOTICE, 46 [L_INFO] = LOG_INFO, 47 [L_DEBUG] = LOG_DEBUG 48 }; 49 50 #ifdef DUMMY_MODE 51 #define use_syslog false 52 #else 53 static bool use_syslog = true; 54 #endif 55 56 57 static void 58 netifd_delete_process(struct netifd_process *proc) 59 { 60 while (ustream_poll(&proc->log.stream)); 61 list_del(&proc->list); 62 ustream_free(&proc->log.stream); 63 close(proc->log.fd.fd); 64 } 65 66 void 67 netifd_log_message(int priority, const char *format, ...) 68 { 69 va_list vl; 70 71 if (priority > log_level) 72 return; 73 74 va_start(vl, format); 75 if (use_syslog) 76 vsyslog(log_class[priority], format, vl); 77 else 78 vfprintf(stderr, format, vl); 79 va_end(vl); 80 } 81 82 static void 83 netifd_process_log_read_cb(struct ustream *s, int bytes) 84 { 85 struct netifd_process *proc; 86 const char *log_prefix; 87 char *data; 88 int len = 0; 89 90 proc = container_of(s, struct netifd_process, log.stream); 91 log_prefix = proc->log_prefix; 92 if (!log_prefix) 93 log_prefix = "process"; 94 95 do { 96 char *newline; 97 98 data = ustream_get_read_buf(s, &len); 99 if (!len) 100 break; 101 102 newline = strchr(data, '\n'); 103 104 if (proc->log_overflow) { 105 if (newline) { 106 len = newline + 1 - data; 107 proc->log_overflow = false; 108 } 109 } else if (newline) { 110 *newline = 0; 111 len = newline + 1 - data; 112 netifd_log_message(L_NOTICE, "%s (%d): %s\n", 113 log_prefix, proc->uloop.pid, data); 114 } else if (len == s->r.buffer_len) { 115 netifd_log_message(L_NOTICE, "%s (%d): %s [...]\n", 116 log_prefix, proc->uloop.pid, data); 117 proc->log_overflow = true; 118 } else 119 break; 120 121 ustream_consume(s, len); 122 } while (1); 123 } 124 125 static void 126 netifd_process_cb(struct uloop_process *proc, int ret) 127 { 128 struct netifd_process *np; 129 np = container_of(proc, struct netifd_process, uloop); 130 131 netifd_delete_process(np); 132 return np->cb(np, ret); 133 } 134 135 int 136 netifd_start_process(const char **argv, char **env, struct netifd_process *proc) 137 { 138 int pfds[2]; 139 int pid; 140 141 netifd_kill_process(proc); 142 143 if (pipe(pfds) < 0) 144 return -1; 145 146 if ((pid = fork()) < 0) 147 goto error; 148 149 if (!pid) { 150 int i; 151 152 if (env) { 153 while (*env) { 154 putenv(*env); 155 env++; 156 } 157 } 158 if (proc->dir_fd >= 0) 159 if (fchdir(proc->dir_fd)) {} 160 161 close(pfds[0]); 162 163 for (i = 0; i <= 2; i++) { 164 if (pfds[1] == i) 165 continue; 166 167 dup2(pfds[1], i); 168 } 169 170 if (pfds[1] > 2) 171 close(pfds[1]); 172 173 execvp(argv[0], (char **) argv); 174 exit(127); 175 } 176 177 close(pfds[1]); 178 proc->uloop.cb = netifd_process_cb; 179 proc->uloop.pid = pid; 180 uloop_process_add(&proc->uloop); 181 list_add_tail(&proc->list, &process_list); 182 183 system_fd_set_cloexec(pfds[0]); 184 proc->log.stream.string_data = true; 185 proc->log.stream.notify_read = netifd_process_log_read_cb; 186 ustream_fd_init(&proc->log, pfds[0]); 187 188 return 0; 189 190 error: 191 close(pfds[0]); 192 close(pfds[1]); 193 return -1; 194 } 195 196 void 197 netifd_kill_process(struct netifd_process *proc) 198 { 199 if (!proc->uloop.pending) 200 return; 201 202 kill(proc->uloop.pid, SIGKILL); 203 uloop_process_delete(&proc->uloop); 204 netifd_delete_process(proc); 205 } 206 207 static void netifd_do_restart(struct uloop_timeout *timeout) 208 { 209 execvp(global_argv[0], global_argv); 210 } 211 212 int netifd_reload(void) 213 { 214 return config_init_all(); 215 } 216 217 void netifd_restart(void) 218 { 219 static struct uloop_timeout main_timer = { 220 .cb = netifd_do_restart 221 }; 222 223 interface_set_down(NULL); 224 uloop_timeout_set(&main_timer, 1000); 225 } 226 227 static int usage(const char *progname) 228 { 229 fprintf(stderr, "Usage: %s [options]\n" 230 "Options:\n" 231 " -d <mask>: Mask for debug messages\n" 232 " -s <path>: Path to the ubus socket\n" 233 " -p <path>: Path to netifd addons (default: %s)\n" 234 " -c <path>: Path to UCI configuration\n" 235 " -h <path>: Path to the hotplug script\n" 236 " (default: "DEFAULT_HOTPLUG_PATH")\n" 237 " -r <path>: Path to resolv.conf\n" 238 " -l <level>: Log output level (default: %d)\n" 239 " -S: Use stderr instead of syslog for log messages\n" 240 "\n", progname, main_path, DEFAULT_LOG_LEVEL); 241 242 return 1; 243 } 244 245 static void 246 netifd_handle_signal(int signo) 247 { 248 uloop_end(); 249 } 250 251 static void 252 netifd_setup_signals(void) 253 { 254 struct sigaction s; 255 256 memset(&s, 0, sizeof(s)); 257 s.sa_handler = netifd_handle_signal; 258 s.sa_flags = 0; 259 sigaction(SIGINT, &s, NULL); 260 sigaction(SIGTERM, &s, NULL); 261 sigaction(SIGUSR1, &s, NULL); 262 sigaction(SIGUSR2, &s, NULL); 263 264 s.sa_handler = SIG_IGN; 265 sigaction(SIGPIPE, &s, NULL); 266 } 267 268 static void 269 netifd_kill_processes(void) 270 { 271 struct netifd_process *proc, *tmp; 272 273 list_for_each_entry_safe(proc, tmp, &process_list, list) 274 netifd_kill_process(proc); 275 } 276 277 int main(int argc, char **argv) 278 { 279 const char *socket = NULL; 280 int ch; 281 282 global_argv = argv; 283 284 while ((ch = getopt(argc, argv, "d:s:p:c:h:r:l:S")) != -1) { 285 switch(ch) { 286 case 'd': 287 debug_mask = strtoul(optarg, NULL, 0); 288 break; 289 case 's': 290 socket = optarg; 291 break; 292 case 'p': 293 main_path = optarg; 294 break; 295 case 'c': 296 config_path = optarg; 297 break; 298 case 'h': 299 hotplug_cmd_path = optarg; 300 break; 301 case 'r': 302 resolv_conf = optarg; 303 break; 304 case 'l': 305 log_level = atoi(optarg); 306 if (log_level >= ARRAY_SIZE(log_class)) 307 log_level = ARRAY_SIZE(log_class) - 1; 308 break; 309 #ifndef DUMMY_MODE 310 case 'S': 311 use_syslog = false; 312 break; 313 #endif 314 default: 315 return usage(argv[0]); 316 } 317 } 318 319 if (use_syslog) 320 openlog("netifd", 0, LOG_DAEMON); 321 322 netifd_setup_signals(); 323 if (netifd_ubus_init(socket) < 0) { 324 fprintf(stderr, "Failed to connect to ubus\n"); 325 return 1; 326 } 327 328 proto_shell_init(); 329 extdev_init(); 330 wireless_init(); 331 332 if (system_init()) { 333 fprintf(stderr, "Failed to initialize system control\n"); 334 return 1; 335 } 336 337 config_init_all(); 338 339 uloop_run(); 340 netifd_kill_processes(); 341 342 netifd_ubus_done(); 343 344 if (use_syslog) 345 closelog(); 346 347 return 0; 348 } 349
This page was automatically generated by LXR 0.3.1. • OpenWrt