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 "proto.h" 28 #include "extdev.h" 29 #include "ucode.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 void 194 netifd_add_process(struct netifd_process *proc, int fd, int pid) 195 { 196 proc->uloop.cb = netifd_process_cb; 197 proc->uloop.pid = pid; 198 uloop_process_add(&proc->uloop); 199 list_add_tail(&proc->list, &process_list); 200 201 system_fd_set_cloexec(fd); 202 proc->log.stream.string_data = true; 203 proc->log.stream.notify_read = netifd_process_log_read_cb; 204 ustream_fd_init(&proc->log, fd); 205 } 206 207 int 208 netifd_start_process(const char **argv, char **env, struct netifd_process *proc) 209 { 210 int pfds[2]; 211 int pid; 212 213 netifd_kill_process(proc); 214 215 if (pipe(pfds) < 0) 216 return -1; 217 218 if ((pid = fork()) < 0) 219 goto error; 220 221 if (!pid) { 222 int i; 223 224 if (env) { 225 while (*env) { 226 putenv(*env); 227 env++; 228 } 229 } 230 if (proc->dir_fd >= 0) 231 if (fchdir(proc->dir_fd)) {} 232 233 close(pfds[0]); 234 235 for (i = 0; i <= 2; i++) { 236 if (pfds[1] == i) 237 continue; 238 239 dup2(pfds[1], i); 240 } 241 242 if (pfds[1] > 2) 243 close(pfds[1]); 244 245 execvp(argv[0], (char **) argv); 246 exit(127); 247 } 248 249 close(pfds[1]); 250 netifd_add_process(proc, pfds[0], pid); 251 252 return 0; 253 254 error: 255 close(pfds[0]); 256 close(pfds[1]); 257 return -1; 258 } 259 260 void 261 netifd_kill_process(struct netifd_process *proc) 262 { 263 if (!proc->uloop.pending) 264 return; 265 266 kill(proc->uloop.pid, SIGKILL); 267 uloop_process_delete(&proc->uloop); 268 netifd_delete_process(proc); 269 } 270 271 static void netifd_do_restart(struct uloop_timeout *timeout) 272 { 273 execvp(global_argv[0], global_argv); 274 } 275 276 int netifd_reload(void) 277 { 278 return config_init_all(); 279 } 280 281 void netifd_restart(void) 282 { 283 static struct uloop_timeout main_timer = { 284 .cb = netifd_do_restart 285 }; 286 287 interface_set_down(NULL); 288 uloop_timeout_set(&main_timer, 1000); 289 } 290 291 static int usage(const char *progname) 292 { 293 fprintf(stderr, "Usage: %s [options]\n" 294 "Options:\n" 295 " -d <mask>: Mask for debug messages\n" 296 " -s <path>: Path to the ubus socket\n" 297 " -p <path>: Path to netifd addons (default: %s)\n" 298 " -c <path>: Path to UCI configuration\n" 299 " -h <path>: Path to the hotplug script\n" 300 " (default: "DEFAULT_HOTPLUG_PATH")\n" 301 " -r <path>: Path to resolv.conf\n" 302 " -l <level>: Log output level (default: %d)\n" 303 " -S: Use stderr instead of syslog for log messages\n" 304 "\n", progname, main_path, DEFAULT_LOG_LEVEL); 305 306 return 1; 307 } 308 309 static void 310 netifd_handle_signal(int signo) 311 { 312 uloop_end(); 313 } 314 315 static void 316 netifd_setup_signals(void) 317 { 318 struct sigaction s; 319 320 memset(&s, 0, sizeof(s)); 321 s.sa_handler = netifd_handle_signal; 322 s.sa_flags = 0; 323 sigaction(SIGINT, &s, NULL); 324 sigaction(SIGTERM, &s, NULL); 325 sigaction(SIGUSR1, &s, NULL); 326 sigaction(SIGUSR2, &s, NULL); 327 328 s.sa_handler = SIG_IGN; 329 sigaction(SIGPIPE, &s, NULL); 330 } 331 332 static void 333 netifd_kill_processes(void) 334 { 335 struct netifd_process *proc, *tmp; 336 337 list_for_each_entry_safe(proc, tmp, &process_list, list) 338 netifd_kill_process(proc); 339 } 340 341 int main(int argc, char **argv) 342 { 343 const char *socket = NULL; 344 int ch; 345 346 global_argv = argv; 347 348 while ((ch = getopt(argc, argv, "d:s:p:c:h:r:l:S")) != -1) { 349 switch(ch) { 350 case 'd': 351 debug_mask = strtoul(optarg, NULL, 0); 352 break; 353 case 's': 354 socket = optarg; 355 break; 356 case 'p': 357 main_path = optarg; 358 break; 359 case 'c': 360 config_path = optarg; 361 break; 362 case 'h': 363 hotplug_cmd_path = optarg; 364 break; 365 case 'r': 366 resolv_conf = optarg; 367 break; 368 case 'l': 369 log_level = atoi(optarg); 370 if (log_level >= (int)ARRAY_SIZE(log_class)) 371 log_level = (int)ARRAY_SIZE(log_class) - 1; 372 break; 373 #ifndef DUMMY_MODE 374 case 'S': 375 use_syslog = false; 376 break; 377 #endif 378 default: 379 return usage(argv[0]); 380 } 381 } 382 383 if (use_syslog) 384 openlog("netifd", 0, LOG_DAEMON); 385 386 netifd_setup_signals(); 387 uloop_init(); 388 udebug_init(&ud); 389 udebug_auto_connect(&ud, NULL); 390 for (size_t i = 0; i < ARRAY_SIZE(rings); i++) 391 udebug_ubus_ring_init(&ud, &rings[i]); 392 393 if (netifd_ubus_init(socket) < 0) { 394 fprintf(stderr, "Failed to connect to ubus\n"); 395 return 1; 396 } 397 398 proto_shell_init(); 399 extdev_init(); 400 netifd_ucode_init(); 401 402 if (system_init()) { 403 fprintf(stderr, "Failed to initialize system control\n"); 404 return 1; 405 } 406 407 config_init_all(); 408 409 uloop_run(); 410 netifd_kill_processes(); 411 412 netifd_ubus_done(); 413 netifd_ucode_free(); 414 415 if (use_syslog) 416 closelog(); 417 418 return 0; 419 } 420
This page was automatically generated by LXR 0.3.1. • OpenWrt