Skip to content

Latest commit

 

History

History
220 lines (176 loc) · 5.1 KB

mainloop.c

File metadata and controls

220 lines (176 loc) · 5.1 KB
 
Sep 22, 2008
Sep 22, 2008
1
/*
Nov 20, 2008
Nov 20, 2008
2
* OpenConnect (SSL + DTLS) VPN client
Sep 22, 2008
Sep 22, 2008
3
*
May 13, 2012
May 13, 2012
4
* Copyright © 2008-2011 Intel Corporation.
Sep 22, 2008
Sep 22, 2008
5
*
Nov 20, 2008
Nov 20, 2008
6
7
8
* Author: David Woodhouse <dwmw2@infradead.org>
*
* This program is free software; you can redistribute it and/or
Oct 4, 2008
Oct 4, 2008
9
* modify it under the terms of the GNU Lesser General Public License
Nov 20, 2008
Nov 20, 2008
10
* version 2.1, as published by the Free Software Foundation.
Sep 22, 2008
Sep 22, 2008
11
*
Nov 20, 2008
Nov 20, 2008
12
* This program is distributed in the hope that it will be useful, but
Oct 4, 2008
Oct 4, 2008
13
14
15
16
17
18
19
20
21
22
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to:
*
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
Sep 22, 2008
Sep 22, 2008
23
24
25
26
27
28
*/
#include <errno.h>
#include <poll.h>
#include <limits.h>
#include <sys/select.h>
Jul 8, 2012
Jul 8, 2012
29
#include <stdlib.h>
Sep 22, 2008
Sep 22, 2008
30
#include <signal.h>
Oct 6, 2008
Oct 6, 2008
31
#include <unistd.h>
Jun 1, 2009
Jun 1, 2009
32
#include <string.h>
Sep 22, 2008
Sep 22, 2008
33
Mar 9, 2011
Mar 9, 2011
34
#include "openconnect-internal.h"
Sep 22, 2008
Sep 22, 2008
35
Sep 22, 2008
Sep 22, 2008
36
void queue_packet(struct pkt **q, struct pkt *new)
Sep 22, 2008
Sep 22, 2008
37
38
39
40
{
while (*q)
q = &(*q)->next;
Sep 22, 2008
Sep 22, 2008
41
42
43
44
new->next = NULL;
*q = new;
}
Nov 2, 2009
Nov 2, 2009
45
int queue_new_packet(struct pkt **q, void *buf, int len)
Sep 22, 2008
Sep 22, 2008
46
{
Sep 22, 2008
Sep 22, 2008
47
48
struct pkt *new = malloc(sizeof(struct pkt) + len);
if (!new)
Sep 22, 2008
Sep 22, 2008
49
50
return -ENOMEM;
Sep 22, 2008
Sep 22, 2008
51
52
53
54
new->len = len;
new->next = NULL;
memcpy(new->data, buf, len);
queue_packet(q, new);
Sep 22, 2008
Sep 22, 2008
55
56
57
return 0;
}
Dec 12, 2008
Dec 12, 2008
58
int killed;
Sep 22, 2008
Sep 22, 2008
59
60
61
static void handle_sigint(int sig)
{
Sep 30, 2008
Sep 30, 2008
62
killed = sig;
Sep 22, 2008
Sep 22, 2008
63
64
}
Oct 5, 2008
Oct 5, 2008
65
int vpn_mainloop(struct openconnect_info *vpninfo)
Sep 22, 2008
Sep 22, 2008
66
{
Sep 22, 2008
Sep 22, 2008
67
68
69
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handle_sigint;
Apr 9, 2009
Apr 9, 2009
70
Oct 8, 2009
Oct 8, 2009
71
sigaction(SIGTERM, &sa, NULL);
Sep 22, 2008
Sep 22, 2008
72
sigaction(SIGINT, &sa, NULL);
Sep 30, 2008
Sep 30, 2008
73
74
sigaction(SIGHUP, &sa, NULL);
Sep 30, 2008
Sep 30, 2008
75
while (!vpninfo->quit_reason) {
Sep 22, 2008
Sep 22, 2008
76
77
int did_work = 0;
int timeout = INT_MAX;
Oct 15, 2008
Oct 15, 2008
78
79
struct timeval tv;
fd_set rfds, wfds, efds;
Sep 22, 2008
Sep 22, 2008
80
Jun 7, 2012
Jun 7, 2012
81
#ifdef HAVE_DTLS
Oct 2, 2008
Oct 2, 2008
82
83
84
if (vpninfo->new_dtls_ssl)
dtls_try_handshake(vpninfo);
Oct 7, 2008
Oct 7, 2008
85
if (vpninfo->dtls_attempt_period && !vpninfo->dtls_ssl && !vpninfo->new_dtls_ssl &&
Oct 2, 2008
Oct 2, 2008
86
vpninfo->new_dtls_started + vpninfo->dtls_attempt_period < time(NULL)) {
Sep 22, 2011
Sep 22, 2011
87
vpn_progress(vpninfo, PRG_TRACE, _("Attempt new DTLS connection\n"));
Oct 2, 2008
Oct 2, 2008
88
89
90
connect_dtls_socket(vpninfo);
}
if (vpninfo->dtls_ssl)
Sep 22, 2008
Sep 22, 2008
91
did_work += dtls_mainloop(vpninfo, &timeout);
Jun 2, 2009
Jun 2, 2009
92
#endif
Sep 30, 2008
Sep 30, 2008
93
94
95
if (vpninfo->quit_reason)
break;
Oct 4, 2008
Oct 4, 2008
96
did_work += cstp_mainloop(vpninfo, &timeout);
Sep 30, 2008
Sep 30, 2008
97
98
if (vpninfo->quit_reason)
break;
Oct 26, 2008
Oct 26, 2008
99
100
101
/* Tun must be last because it will set/clear its bit
in the select_rfds according to the queue length */
Sep 30, 2008
Sep 30, 2008
102
103
104
105
106
107
108
109
110
111
112
113
114
115
did_work += tun_mainloop(vpninfo, &timeout);
if (vpninfo->quit_reason)
break;
if (killed) {
if (killed == SIGHUP)
vpninfo->quit_reason = "Client received SIGHUP";
else if (killed == SIGINT)
vpninfo->quit_reason = "Client received SIGINT";
else
vpninfo->quit_reason = "Client killed";
break;
}
Sep 30, 2008
Sep 30, 2008
116
117
118
if (did_work)
continue;
Jun 27, 2011
Jun 27, 2011
119
vpn_progress(vpninfo, PRG_TRACE,
Sep 22, 2011
Sep 22, 2011
120
_("No work to do; sleeping for %d ms...\n"), timeout);
Oct 15, 2008
Oct 15, 2008
121
122
123
124
125
memcpy(&rfds, &vpninfo->select_rfds, sizeof(rfds));
memcpy(&wfds, &vpninfo->select_wfds, sizeof(wfds));
memcpy(&efds, &vpninfo->select_efds, sizeof(efds));
tv.tv_sec = timeout / 1000;
Dec 6, 2008
Dec 6, 2008
126
tv.tv_usec = (timeout % 1000) * 1000;
Oct 19, 2009
Oct 19, 2009
127
128
select(vpninfo->select_nfds, &rfds, &wfds, &efds, &tv);
Sep 22, 2008
Sep 22, 2008
129
}
Sep 22, 2008
Sep 22, 2008
130
Oct 4, 2008
Oct 4, 2008
131
cstp_bye(vpninfo, vpninfo->quit_reason);
Sep 22, 2008
Sep 22, 2008
132
Nov 3, 2009
Nov 3, 2009
133
shutdown_tun(vpninfo);
Sep 22, 2008
Sep 22, 2008
134
135
return 0;
}
Oct 2, 2008
Oct 2, 2008
136
Oct 2, 2008
Oct 2, 2008
137
138
/* Called when the socket is unwritable, to get the deadline for DPD.
Returns 1 if DPD deadline has already arrived. */
Aug 3, 2012
Aug 3, 2012
139
int ka_stalled_action(struct keepalive_info *ka, int *timeout)
Oct 2, 2008
Oct 2, 2008
140
{
Aug 3, 2012
Aug 3, 2012
141
142
143
144
145
146
147
148
149
150
151
time_t due, now = time(NULL);
if (ka->rekey) {
due = ka->last_rekey + ka->rekey;
if (now >= due)
return KA_REKEY;
if (*timeout > (due - now) * 1000)
*timeout = (due - now) * 1000;
}
Oct 2, 2008
Oct 2, 2008
152
Oct 5, 2008
Oct 5, 2008
153
if (!ka->dpd)
Aug 3, 2012
Aug 3, 2012
154
return KA_NONE;
Oct 2, 2008
Oct 2, 2008
155
156
157
158
due = ka->last_rx + (2 * ka->dpd);
if (now > due)
Aug 3, 2012
Aug 3, 2012
159
return KA_DPD_DEAD;
Oct 2, 2008
Oct 2, 2008
160
161
162
163
if (*timeout > (due - now) * 1000)
*timeout = (due - now) * 1000;
Aug 3, 2012
Aug 3, 2012
164
return KA_NONE;
Oct 2, 2008
Oct 2, 2008
165
166
167
}
Oct 2, 2008
Oct 2, 2008
168
int keepalive_action(struct keepalive_info *ka, int *timeout)
Oct 2, 2008
Oct 2, 2008
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
{
time_t now = time(NULL);
if (ka->rekey) {
time_t due = ka->last_rekey + ka->rekey;
if (now >= due)
return KA_REKEY;
if (*timeout > (due - now) * 1000)
*timeout = (due - now) * 1000;
}
/* DPD is bidirectional -- PKT 3 out, PKT 4 back */
if (ka->dpd) {
time_t due = ka->last_rx + ka->dpd;
time_t overdue = ka->last_rx + (2 * ka->dpd);
/* Peer didn't respond */
if (now > overdue)
return KA_DPD_DEAD;
/* If we already have DPD outstanding, don't flood. Repeat by
all means, but only after half the DPD period. */
if (ka->last_dpd > ka->last_rx)
due = ka->last_dpd + ka->dpd / 2;
/* We haven't seen a packet from this host for $DPD seconds.
Prod it to see if it's still alive */
if (now >= due) {
ka->last_dpd = now;
return KA_DPD;
}
if (*timeout > (due - now) * 1000)
*timeout = (due - now) * 1000;
}
/* Keepalive is just client -> server */
if (ka->keepalive) {
time_t due = ka->last_tx + ka->keepalive;
/* If we haven't sent anything for $KEEPALIVE seconds, send a
dummy packet (which the server will discard) */
if (now >= due)
return KA_KEEPALIVE;
if (*timeout > (due - now) * 1000)
*timeout = (due - now) * 1000;
}
return KA_NONE;
}