aboutsummaryrefslogtreecommitdiff
path: root/src/events/route_up.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/events/route_up.c')
-rw-r--r--src/events/route_up.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/events/route_up.c b/src/events/route_up.c
new file mode 100644
index 0000000..0691cc7
--- /dev/null
+++ b/src/events/route_up.c
@@ -0,0 +1,93 @@
+/*
+ * 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;
+}