actually send BYE packet on exit
[platform/upstream/openconnect.git] / mainloop.c
1 /*
2  * Open AnyConnect (SSL + DTLS) client
3  *
4  * © 2008 David Woodhouse <dwmw2@infradead.org>
5  *
6  * Permission to use, copy, modify, and/or distribute this software
7  * for any purpose with or without fee is hereby granted, provided
8  * that the above copyright notice and this permission notice appear
9  * in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
15  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
16  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
17  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
18  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20
21 #include <errno.h>
22 #include <poll.h>
23 #include <limits.h>
24 #include <sys/select.h>
25 #include <signal.h>
26
27 #include "anyconnect.h"
28
29 int queue_new_packet(struct pkt **q, int type, void *buf, int len)
30 {
31         while (*q)
32                 q = &(*q)->next;
33
34         *q = malloc(sizeof(struct pkt) + len);
35         if (!*q)
36                 return -ENOMEM;
37
38         (*q)->type = type;
39         (*q)->len = len;
40         (*q)->next = NULL;
41         memcpy((*q)->data, buf, len);
42         return 0;
43 }
44
45 int vpn_add_pollfd(struct anyconnect_info *vpninfo, int fd, short events)
46 {
47         vpninfo->nfds++;
48         vpninfo->pfds = realloc(vpninfo->pfds, sizeof(struct pollfd) * vpninfo->nfds);
49         if (!vpninfo->pfds) {
50                 fprintf(stderr, "Failed to reallocate pfds\n");
51                 exit(1);
52         }
53         vpninfo->pfds[vpninfo->nfds - 1].fd = fd;
54         vpninfo->pfds[vpninfo->nfds - 1].events = events;
55
56         return vpninfo->nfds - 1;
57 }
58
59 static int killed;
60
61 static void handle_sigint(int sig)
62 {
63         killed = 1;
64 }
65
66 int vpn_mainloop(struct anyconnect_info *vpninfo)
67 {
68         struct sigaction sa;
69         memset(&sa, 0, sizeof(sa));
70         sa.sa_handler = handle_sigint;
71         
72         sigaction(SIGINT, &sa, NULL);
73         while (!killed) {
74                 int did_work = 0;
75                 int timeout = INT_MAX;
76
77                 if (vpninfo->dtls_fd != -1)
78                         did_work += dtls_mainloop(vpninfo, &timeout);
79
80                 did_work += ssl_mainloop(vpninfo, &timeout);
81                 did_work += tun_mainloop(vpninfo, &timeout);
82                 
83                 if (did_work)
84                         continue;
85                 
86                 if (verbose)
87                         printf("Did no work; sleeping for %d ms...\n", timeout);
88
89                 poll(vpninfo->pfds, vpninfo->nfds, timeout);
90         }
91         ssl_bye(vpninfo, "Client received SIGINT\n");
92
93         return 0;
94 }