1 /*
2 * route_up.c - wake events for route changes
3 * Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "config.h"
9
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <time.h>
13 #include <unistd.h>
14
15 #include <event2/event.h>
16
17 #include "src/conf.h"
18 #include "src/routeup.h"
19 #include "src/tlsdate.h"
20 #include "src/util.h"
21
action_stdin_wakeup(evutil_socket_t fd,short what,void * arg)22 void action_stdin_wakeup (evutil_socket_t fd, short what, void *arg)
23 {
24 struct state *state = arg;
25 char buf[1];
26 verb_debug ("[event:%s] fired", __func__);
27 if (what != EV_READ)
28 return;
29 if (IGNORE_EINTR (read (fd, buf, sizeof (buf))) != sizeof (buf))
30 {
31 error ("[event:%s] unregistering stdin handler - it's broken!",
32 __func__);
33 event_del (state->events[E_ROUTEUP]);
34 return;
35 }
36 action_kickoff_time_sync (-1, EV_TIMEOUT, arg);
37 }
38
action_netlink_ready(evutil_socket_t fd,short what,void * arg)39 void action_netlink_ready (evutil_socket_t fd, short what, void *arg)
40 {
41 struct routeup routeup_cfg;
42 verb_debug ("[event:%s] fired", __func__);
43 routeup_cfg.netlinkfd = fd;
44 if (what & EV_READ)
45 {
46 if (routeup_process (&routeup_cfg) == 0)
47 {
48 verb_debug ("[event:%s] routes changed", __func__);
49 /* Fire off a proxy resolution attempt and a new sync request */
50 action_kickoff_time_sync (-1, EV_TIMEOUT, arg);
51 }
52 }
53 }
54
setup_event_route_up(struct state * state)55 int setup_event_route_up (struct state *state)
56 {
57 event_callback_fn handler;
58 int fd = -1;
59 struct routeup routeup_cfg;
60 if (state->opts.should_netlink)
61 {
62 if (routeup_setup (&routeup_cfg))
63 {
64 error ("routeup_setup() failed");
65 return 1;
66 }
67 fd = routeup_cfg.netlinkfd;
68 handler = action_netlink_ready;
69 }
70 else /* Listen for cues from stdin */
71 {
72 fd = STDIN_FILENO;
73 if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0)
74 {
75 perror ("stdin fcntl(O_NONBLOCK) failed");
76 return 1;
77 }
78 handler = action_stdin_wakeup;
79 }
80 state->events[E_ROUTEUP] = event_new (state->base, fd,
81 EV_READ|EV_PERSIST, handler, state);
82 if (!state->events[E_ROUTEUP])
83 {
84 if (state->opts.should_netlink)
85 {
86 routeup_teardown (&routeup_cfg);
87 }
88 return 1;
89 }
90 event_priority_set (state->events[E_ROUTEUP], PRI_WAKE);
91 event_add (state->events[E_ROUTEUP], NULL);
92 return 0;
93 }
94