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