• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/netifd/main.c

  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
 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         if (priority > log_level)
125                 return;
126 
127         va_start(vl, format);
128         netifd_udebug_vprintf(format, vl);
129         va_end(vl);
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