| /* |
| * route_up.c - wake events for route changes |
| * Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "config.h" |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <time.h> |
| #include <unistd.h> |
| |
| #include <event2/event.h> |
| |
| #include "src/conf.h" |
| #include "src/routeup.h" |
| #include "src/tlsdate.h" |
| #include "src/util.h" |
| |
| void action_stdin_wakeup (evutil_socket_t fd, short what, void *arg) |
| { |
| struct state *state = arg; |
| char buf[1]; |
| verb_debug ("[event:%s] fired", __func__); |
| if (what != EV_READ) |
| return; |
| if (IGNORE_EINTR (read (fd, buf, sizeof (buf))) != sizeof (buf)) |
| { |
| error ("[event:%s] unregistering stdin handler - it's broken!", |
| __func__); |
| event_del (state->events[E_ROUTEUP]); |
| return; |
| } |
| action_kickoff_time_sync (-1, EV_TIMEOUT, arg); |
| } |
| |
| void action_netlink_ready (evutil_socket_t fd, short what, void *arg) |
| { |
| struct routeup routeup_cfg; |
| verb_debug ("[event:%s] fired", __func__); |
| routeup_cfg.netlinkfd = fd; |
| if (what & EV_READ) |
| { |
| if (routeup_process (&routeup_cfg) == 0) |
| { |
| verb_debug ("[event:%s] routes changed", __func__); |
| /* Fire off a proxy resolution attempt and a new sync request */ |
| action_kickoff_time_sync (-1, EV_TIMEOUT, arg); |
| } |
| } |
| } |
| |
| int setup_event_route_up (struct state *state) |
| { |
| event_callback_fn handler; |
| int fd = -1; |
| struct routeup routeup_cfg; |
| if (state->opts.should_netlink) |
| { |
| if (routeup_setup (&routeup_cfg)) |
| { |
| error ("routeup_setup() failed"); |
| return 1; |
| } |
| fd = routeup_cfg.netlinkfd; |
| handler = action_netlink_ready; |
| } |
| else /* Listen for cues from stdin */ |
| { |
| fd = STDIN_FILENO; |
| if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) |
| { |
| perror ("stdin fcntl(O_NONBLOCK) failed"); |
| return 1; |
| } |
| handler = action_stdin_wakeup; |
| } |
| state->events[E_ROUTEUP] = event_new (state->base, fd, |
| EV_READ|EV_PERSIST, handler, state); |
| if (!state->events[E_ROUTEUP]) |
| { |
| if (state->opts.should_netlink) |
| { |
| routeup_teardown (&routeup_cfg); |
| } |
| return 1; |
| } |
| event_priority_set (state->events[E_ROUTEUP], PRI_WAKE); |
| event_add (state->events[E_ROUTEUP], NULL); |
| return 0; |
| } |