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 static struct udebug ud; 39 static struct udebug_buf udb_log; 40 struct udebug_buf udb_nl; 41 static const struct udebug_buf_meta meta_log = { 42 .name = "netifd_log", 43 .format = UDEBUG_FORMAT_STRING, 44 }; 45 static const struct udebug_buf_meta meta_nl = { 46 .name = "netifd_nl", 47 .format = UDEBUG_FORMAT_PACKET, 48 .sub_format = UDEBUG_DLT_NETLINK, 49 }; 50 static struct udebug_ubus_ring rings[] = { 51 { 52 .buf = &udb_log, 53 .meta = &meta_log, 54 .default_entries = 1024, 55 .default_size = 64 * 1024, 56 }, 57 { 58 .buf = &udb_nl, 59 .meta = &meta_nl, 60 .default_entries = 1024, 61 .default_size = 64 * 1024, 62 }, 63 }; 64 65 #define DEFAULT_LOG_LEVEL L_NOTICE 66 67 static int log_level = DEFAULT_LOG_LEVEL; 68 static const int log_class[] = { 69 [L_CRIT] = LOG_CRIT, 70 [L_WARNING] = LOG_WARNING, 71 [L_NOTICE] = LOG_NOTICE, 72 [L_INFO] = LOG_INFO, 73 [L_DEBUG] = LOG_DEBUG 74 }; 75 76 #ifdef DUMMY_MODE 77 #define use_syslog false 78 #else 79 static bool use_syslog = true; 80 #endif 81 82 83 static void 84 netifd_delete_process(struct netifd_process *proc) 85 { 86 while (ustream_poll(&proc->log.stream)); 87 list_del(&proc->list); 88 ustream_free(&proc->log.stream); 89 close(proc->log.fd.fd); 90 } 91 92 static void __attribute__((format (printf, 1, 0))) 93 netifd_udebug_vprintf(const char *format, va_list ap) 94 { 95 if (!udebug_buf_valid(&udb_log)) 96 return; 97 98 udebug_entry_init(&udb_log); 99 udebug_entry_vprintf(&udb_log, format, ap); 100 udebug_entry_add(&udb_log); 101 } 102 103 void netifd_udebug_printf(const char *format, ...) 104 { 105 va_list ap; 106 107 va_start(ap, format); 108 netifd_udebug_vprintf(format, ap); 109 va_end(ap); 110 } 111 112 void netifd_udebug_config(struct udebug_ubus *ctx, struct blob_attr *data, 113 bool enabled) 114 { 115 udebug_ubus_apply_config(&ud, rings, ARRAY_SIZE(rings), data, enabled); 116 } 117 118 void 119 __attribute__((format(printf, 2, 0))) 120 netifd_log_message(int priority, const char *format, ...) 121 { 122 va_list vl; 123 124 va_start(vl, format); 125 netifd_udebug_vprintf(format, vl); 126 va_end(vl); 127 128 if (priority > log_level) 129 return; 130 131 va_start(vl, format); 132 if (use_syslog) 133 vsyslog(log_class[priority], format, vl); 134 else 135 vfprintf(stderr, format, vl); 136 va_end(vl); 137 } 138 139 static void 140 netifd_process_log_read_cb(struct ustream *s, int bytes) 141 { 142 struct netifd_process *proc; 143 const char *log_prefix; 144 char *data; 145 int len = 0; 146 147 proc = container_of(s, struct netifd_process, log.stream); 148 log_prefix = proc->log_prefix; 149 if (!log_prefix) 150 log_prefix = "process"; 151 152 do { 153 char *newline; 154 155 data = ustream_get_read_buf(s, &len); 156 if (!len) 157 break; 158 159 newline = strchr(data, '\n'); 160 161 if (proc->log_overflow) { 162 if (newline) { 163 len = newline + 1 - data; 164 proc->log_overflow = false; 165 } 166 } else if (newline) { 167 *newline = 0; 168 len = newline + 1 - data; 169 netifd_log_message(L_NOTICE, "%s (%d): %s\n", 170 log_prefix, proc->uloop.pid, data); 171 } else if (len == s->r.buffer_len) { 172 netifd_log_message(L_NOTICE, "%s (%d): %s [...]\n", 173 log_prefix, proc->uloop.pid, data); 174 proc->log_overflow = true; 175 } else 176 break; 177 178 ustream_consume(s, len); 179 } while (1); 180 } 181 182 static void 183 netifd_process_cb(struct uloop_process *proc, int ret) 184 { 185 struct netifd_process *np; 186 np = container_of(proc, struct netifd_process, uloop); 187 188 netifd_delete_process(np); 189 np->cb(np, ret); 190 return; 191 } 192 193 int 194 netifd_start_process(const char **argv, char **env, struct netifd_process *proc) 195 { 196 int pfds[2]; 197 int pid; 198 199 netifd_kill_process(proc); 200 201 if (pipe(pfds) < 0) 202 return -1; 203 204 if ((pid = fork()) < 0) 205 goto error; 206 207 if (!pid) { 208 int i; 209 210 if (env) { 211 while (*env) { 212 putenv(*env); 213 env++; 214 } 215 } 216 if (proc->dir_fd >= 0) 217 if (fchdir(proc->dir_fd)) {} 218 219 close(pfds[0]); 220 221 for (i = 0; i <= 2; i++) { 222 if (pfds[1] == i) 223 continue; 224 225 dup2(pfds[1], i); 226 } 227 228 if (pfds[1] > 2) 229 close(pfds[1]); 230 231 execvp(argv[0], (char **) argv); 232 exit(127); 233 } 234 235 close(pfds[1]); 236 proc->uloop.cb = netifd_process_cb; 237 proc->uloop.pid = pid; 238 uloop_process_add(&proc->uloop); 239 list_add_tail(&proc->list, &process_list); 240 241 system_fd_set_cloexec(pfds[0]); 242 proc->log.stream.string_data = true; 243 proc->log.stream.notify_read = netifd_process_log_read_cb; 244 ustream_fd_init(&proc->log, pfds[0]); 245 246 return 0; 247 248 error: 249 close(pfds[0]); 250 close(pfds[1]); 251 return -1; 252 } 253 254 void 255 netifd_kill_process(struct netifd_process *proc) 256 { 257 if (!proc->uloop.pending) 258 return; 259 260 kill(proc->uloop.pid, SIGKILL); 261 uloop_process_delete(&proc->uloop); 262 netifd_delete_process(proc); 263 } 264 265 static void netifd_do_restart(struct uloop_timeout *timeout) 266 { 267 execvp(global_argv[0], global_argv); 268 } 269 270 int netifd_reload(void) 271 { 272 return config_init_all(); 273 } 274 275 void netifd_restart(void) 276 { 277 static struct uloop_timeout main_timer = { 278 .cb = netifd_do_restart 279 }; 280 281 interface_set_down(NULL); 282 uloop_timeout_set(&main_timer, 1000); 283 } 284 285 static int usage(const char *progname) 286 { 287 fprintf(stderr, "Usage: %s [options]\n" 288 "Options:\n" 289 " -d <mask>: Mask for debug messages\n" 290 " -s <path>: Path to the ubus socket\n" 291 " -p <path>: Path to netifd addons (default: %s)\n" 292 " -c <path>: Path to UCI configuration\n" 293 " -h <path>: Path to the hotplug script\n" 294 " (default: "DEFAULT_HOTPLUG_PATH")\n" 295 " -r <path>: Path to resolv.conf\n" 296 " -l <level>: Log output level (default: %d)\n" 297 " -S: Use stderr instead of syslog for log messages\n" 298 "\n", progname, main_path, DEFAULT_LOG_LEVEL); 299 300 return 1; 301 } 302 303 static void 304 netifd_handle_signal(int signo) 305 { 306 uloop_end(); 307 } 308 309 static void 310 netifd_setup_signals(void) 311 { 312 struct sigaction s; 313 314 memset(&s, 0, sizeof(s)); 315 s.sa_handler = netifd_handle_signal; 316 s.sa_flags = 0; 317 sigaction(SIGINT, &s, NULL); 318 sigaction(SIGTERM, &s, NULL); 319 sigaction(SIGUSR1, &s, NULL); 320 sigaction(SIGUSR2, &s, NULL); 321 322 s.sa_handler = SIG_IGN; 323 sigaction(SIGPIPE, &s, NULL); 324 } 325 326 static void 327 netifd_kill_processes(void) 328 { 329 struct netifd_process *proc, *tmp; 330 331 list_for_each_entry_safe(proc, tmp, &process_list, list) 332 netifd_kill_process(proc); 333 } 334 335 int main(int argc, char **argv) 336 { 337 const char *socket = NULL; 338 int ch; 339 340 global_argv = argv; 341 342 while ((ch = getopt(argc, argv, "d:s:p:c:h:r:l:S")) != -1) { 343 switch(ch) { 344 case 'd': 345 debug_mask = strtoul(optarg, NULL, 0); 346 break; 347 case 's': 348 socket = optarg; 349 break; 350 case 'p': 351 main_path = optarg; 352 break; 353 case 'c': 354 config_path = optarg; 355 break; 356 case 'h': 357 hotplug_cmd_path = optarg; 358 break; 359 case 'r': 360 resolv_conf = optarg; 361 break; 362 case 'l': 363 log_level = atoi(optarg); 364 if (log_level >= (int)ARRAY_SIZE(log_class)) 365 log_level = (int)ARRAY_SIZE(log_class) - 1; 366 break; 367 #ifndef DUMMY_MODE 368 case 'S': 369 use_syslog = false; 370 break; 371 #endif 372 default: 373 return usage(argv[0]); 374 } 375 } 376 377 if (use_syslog) 378 openlog("netifd", 0, LOG_DAEMON); 379 380 netifd_setup_signals(); 381 uloop_init(); 382 udebug_init(&ud); 383 udebug_auto_connect(&ud, NULL); 384 for (size_t i = 0; i < ARRAY_SIZE(rings); i++) 385 udebug_ubus_ring_init(&ud, &rings[i]); 386 387 if (netifd_ubus_init(socket) < 0) { 388 fprintf(stderr, "Failed to connect to ubus\n"); 389 return 1; 390 } 391 392 proto_shell_init(); 393 extdev_init(); 394 wireless_init(); 395 396 if (system_init()) { 397 fprintf(stderr, "Failed to initialize system control\n"); 398 return 1; 399 } 400 401 config_init_all(); 402 403 uloop_run(); 404 netifd_kill_processes(); 405 406 netifd_ubus_done(); 407 408 if (use_syslog) 409 closelog(); 410 411 return 0; 412 } 413
This page was automatically generated by LXR 0.3.1. • OpenWrt