main.c revision c454954382b81262dc81ac54e147f4dc7fc0af75
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20#include <stdarg.h>
21#include <signal.h>
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/socket.h>
25#include <sys/select.h>
26
27#ifdef ANDROID_CHANGES
28#include <sys/ioctl.h>
29#include <linux/if.h>
30#include <android/log.h>
31#include <cutils/sockets.h>
32#include <private/android_filesystem_config.h>
33#include "keystore_get.h"
34#endif
35
36#include "config.h"
37#include "libpfkey.h"
38#include "gcmalloc.h"
39#include "vmbuf.h"
40#include "crypto_openssl.h"
41#include "oakley.h"
42#include "pfkey.h"
43#include "schedule.h"
44#include "isakmp_var.h"
45#include "nattraversal.h"
46#include "localconf.h"
47#include "sockmisc.h"
48#include "grabmyaddr.h"
49#include "plog.h"
50#include "admin.h"
51#include "privsep.h"
52#include "misc.h"
53
54#ifdef ANDROID_CHANGES
55
56static int get_control_and_arguments(int *argc, char ***argv)
57{
58    static char *args[256];
59    int control;
60    int i;
61
62    if ((i = android_get_control_socket("racoon")) == -1) {
63        return -1;
64    }
65    do_plog(LLV_DEBUG, "Waiting for control socket");
66    if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
67        do_plog(LLV_ERROR, "Cannot get control socket");
68        exit(-1);
69    }
70    close(i);
71
72    args[0] = (*argv)[0];
73    for (i = 1; i < 256; ++i) {
74        unsigned char length;
75        if (recv(control, &length, 1, 0) != 1) {
76            do_plog(LLV_ERROR, "Cannot get argument length");
77            exit(-1);
78        }
79        if (length == 0xFF) {
80            break;
81        } else {
82            int offset = 0;
83            args[i] = malloc(length + 1);
84            while (offset < length) {
85                int n = recv(control, &args[i][offset], length - offset, 0);
86                if (n > 0) {
87                    offset += n;
88                } else {
89                    do_plog(LLV_ERROR, "Cannot get argument value");
90                    exit(-1);
91                }
92            }
93            args[i][length] = 0;
94        }
95    }
96    do_plog(LLV_DEBUG, "Received %d arguments", i - 1);
97
98    *argc = i;
99    *argv = args;
100    return control;
101}
102
103static void bind_interface()
104{
105    struct ifreq ifreqs[64];
106    struct ifconf ifconf = {.ifc_len = sizeof(ifreqs), .ifc_req = ifreqs};
107    struct myaddrs *p = lcconf->myaddrs;
108
109    if (ioctl(p->sock, SIOCGIFCONF, &ifconf) == -1) {
110        do_plog(LLV_WARNING, "Cannot list interfaces");
111        return;
112    }
113
114    while (p) {
115        int i = ifconf.ifc_len / sizeof(struct ifreq) - 1;
116        while (i >= 0 && cmpsaddrwop(p->addr, &ifreqs[i].ifr_addr)) {
117            --i;
118        }
119        if (i < 0 || setsockopt(p->sock, SOL_SOCKET, SO_BINDTODEVICE,
120                                ifreqs[i].ifr_name, IFNAMSIZ) == -1) {
121            do_plog(LLV_WARNING, "Cannot bind socket %d to proper interface",
122                    p->sock);
123        }
124        p = p->next;
125    }
126}
127
128#endif
129
130extern void setup(int argc, char **argv);
131int f_local = 0;
132
133static void terminate(int signal)
134{
135    exit(1);
136}
137
138static void terminated()
139{
140    do_plog(LLV_INFO, "Bye\n");
141}
142
143int main(int argc, char **argv)
144{
145    fd_set fdset;
146    int fdset_size;
147    struct myaddrs *p;
148#ifdef ANDROID_CHANGES
149    int control = get_control_and_arguments(&argc, &argv);
150    unsigned char code = argc - 1;
151#endif
152
153    do_plog(LLV_INFO, "ipsec-tools 0.7.2 (http://ipsec-tools.sf.net)\n");
154
155    atexit(terminated);
156    signal(SIGHUP, terminate);
157    signal(SIGINT, terminate);
158    signal(SIGTERM, terminate);
159    signal(SIGPIPE, SIG_IGN);
160
161    eay_init();
162    oakley_dhinit();
163    compute_vendorids();
164    sched_init();
165    setup(argc, argv);
166
167    if (pfkey_init() < 0 || isakmp_init() < 0) {
168        exit(1);
169    }
170
171#ifdef ANDROID_CHANGES
172    bind_interface();
173    send(control, &code, 1, 0);
174    setuid(AID_VPN);
175#endif
176
177#ifdef ENABLE_NATT
178    natt_keepalive_init();
179#endif
180
181    FD_ZERO(&fdset);
182    FD_SET(lcconf->sock_pfkey, &fdset);
183    fdset_size = lcconf->sock_pfkey;
184    for (p = lcconf->myaddrs; p; p = p->next) {
185        FD_SET(p->sock, &fdset);
186        if (fdset_size < p->sock) {
187            fdset_size = p->sock;
188        }
189    }
190    ++fdset_size;
191
192    while (1) {
193        fd_set readset = fdset;
194        struct timeval *timeout = schedular();
195        if (select(fdset_size, &readset, NULL, NULL, timeout) < 0) {
196            exit(1);
197        }
198        if (FD_ISSET(lcconf->sock_pfkey, &readset)) {
199            pfkey_handler();
200        }
201        for (p = lcconf->myaddrs; p; p = p->next) {
202            if (FD_ISSET(p->sock, &readset)) {
203                isakmp_handler(p->sock);
204            }
205        }
206    }
207    return 0;
208}
209
210/* plog.h */
211
212void do_plog(int level, char *format, ...)
213{
214    if (level >= 0 && level <= 5) {
215#ifdef ANDROID_CHANGES
216        static int levels[6] = {
217            ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
218            ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
219        };
220        va_list ap;
221        va_start(ap, format);
222        __android_log_vprint(levels[level], "racoon", format, ap);
223        va_end(ap);
224#else
225        static char *levels = "EWNIDV";
226        fprintf(stderr, "%c: ", levels[level]);
227        va_list ap;
228        va_start(ap, format);
229        vfprintf(stderr, format, ap);
230        va_end(ap);
231#endif
232    }
233}
234
235char *binsanitize(char *data, size_t length)
236{
237    char *output = racoon_malloc(length + 1);
238    if (output) {
239        size_t i;
240        for (i = 0; i < length; ++i) {
241            output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
242        }
243        output[length] = '\0';
244    }
245    return output;
246}
247
248/* privsep.h */
249
250int privsep_pfkey_open()
251{
252    return pfkey_open();
253}
254
255void privsep_pfkey_close(int key)
256{
257    pfkey_close(key);
258}
259
260vchar_t *privsep_eay_get_pkcs1privkey(char *file)
261{
262    return eay_get_pkcs1privkey(file);
263}
264
265vchar_t *privsep_getpsk(const char *key, int size)
266{
267    vchar_t *p = NULL;
268#ifdef ANDROID_CHANGES
269    char *value = keystore_get(key, &size);
270    if (value) {
271        if ((p = vmalloc(size)) != NULL) {
272            memcpy(p->v, value, p->l);
273        }
274        free(value);
275    }
276#else
277    if (key && (p = vmalloc(size)) != NULL) {
278        memcpy(p->v, key, p->l);
279    }
280#endif
281    return p;
282}
283
284int privsep_script_exec(char *script, int name, char * const *environ)
285{
286    return 0;
287}
288
289/* grabmyaddr.h */
290
291int getsockmyaddr(struct sockaddr *addr)
292{
293    struct myaddrs *p;
294    for (p = lcconf->myaddrs; p; p = p->next) {
295        if (cmpsaddrstrict(addr, p->addr) == 0) {
296            return p->sock;
297        }
298    }
299    return -1;
300}
301
302/* misc.h */
303
304int racoon_hexdump(void *data, size_t length)
305{
306    return 0;
307}
308