main.c revision 8f3b38855d8849959825acc45dd11144adc7d862
1/*
2 * Copyright (C) 2011 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 <stdarg.h>
20#include <signal.h>
21#include <poll.h>
22
23#ifdef ANDROID_CHANGES
24#include <unistd.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <android/log.h>
28#include <cutils/sockets.h>
29#include <private/android_filesystem_config.h>
30#endif
31
32#include "config.h"
33#include "gcmalloc.h"
34#include "session.h"
35#include "schedule.h"
36#include "plog.h"
37
38#ifdef ANDROID_CHANGES
39
40static int get_control_and_arguments(int *argc, char ***argv)
41{
42    static char *args[32];
43    int control;
44    int i;
45
46    if ((i = android_get_control_socket("racoon")) == -1) {
47        return -1;
48    }
49    do_plog(LLV_DEBUG, "Waiting for control socket");
50    if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
51        do_plog(LLV_ERROR, "Cannot get control socket");
52        exit(1);
53    }
54    close(i);
55
56    args[0] = (*argv)[0];
57    for (i = 1; i < 32; ++i) {
58        unsigned char bytes[2];
59        if (recv(control, &bytes[0], 1, 0) != 1
60            || recv(control, &bytes[1], 1, 0) != 1) {
61            do_plog(LLV_ERROR, "Cannot get argument length");
62            exit(1);
63        } else {
64            int length = bytes[0] << 8 | bytes[1];
65            int offset = 0;
66
67            if (length == 0xFFFF) {
68                break;
69            }
70            args[i] = malloc(length + 1);
71            while (offset < length) {
72                int n = recv(control, &args[i][offset], length - offset, 0);
73                if (n > 0) {
74                    offset += n;
75                } else {
76                    do_plog(LLV_ERROR, "Cannot get argument value");
77                    exit(1);
78                }
79            }
80            args[i][length] = 0;
81        }
82    }
83    do_plog(LLV_DEBUG, "Received %d arguments", i - 1);
84
85    *argc = i;
86    *argv = args;
87    return control;
88}
89
90#endif
91
92extern void setup(int argc, char **argv);
93
94char *pname;
95
96static int monitor_count;
97static struct {
98    int (*callback)(void *ctx, int fd);
99    void *ctx;
100} monitors[10];
101static struct pollfd pollfds[10];
102
103static void terminate(int signal)
104{
105    exit(1);
106}
107
108static void terminated()
109{
110    do_plog(LLV_INFO, "Bye\n");
111}
112
113int main(int argc, char **argv)
114{
115#ifdef ANDROID_CHANGES
116    int control = get_control_and_arguments(&argc, &argv);
117    if (control != -1) {
118        pname = "%p";
119    }
120#endif
121
122    do_plog(LLV_INFO, "ipsec-tools 0.8.0 (http://ipsec-tools.sf.net)\n");
123    setup(argc, argv);
124
125    signal(SIGHUP, terminate);
126    signal(SIGINT, terminate);
127    signal(SIGTERM, terminate);
128    signal(SIGPIPE, SIG_IGN);
129    atexit(terminated);
130
131    while (1) {
132        struct timeval *tv = schedular();
133        int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
134
135        if (poll(pollfds, monitor_count, timeout) > 0) {
136            int i;
137            for (i = 0; i < monitor_count; ++i) {
138                if (pollfds[i].revents & POLLHUP) {
139                    do_plog(LLV_ERROR, "fd %d is closed\n", pollfds[i].fd);
140                    exit(1);
141                }
142                if (pollfds[i].revents & POLLIN) {
143                    monitors[i].callback(monitors[i].ctx, pollfds[i].fd);
144                }
145            }
146        }
147    }
148    return 0;
149}
150
151/* session.h */
152
153void monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
154{
155    if (fd < 0 || monitor_count == 10) {
156        do_plog(LLV_ERROR, "Cannot monitor fd");
157        exit(1);
158    }
159    monitors[monitor_count].callback = callback;
160    monitors[monitor_count].ctx = ctx;
161    pollfds[monitor_count].fd = fd;
162    pollfds[monitor_count].events = POLLIN;
163    ++monitor_count;
164}
165
166void unmonitor_fd(int fd)
167{
168    exit(1);
169}
170
171/* plog.h */
172
173void do_plog(int level, char *format, ...)
174{
175    if (level >= 0 && level <= 5) {
176#ifdef ANDROID_CHANGES
177        static int levels[6] = {
178            ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
179            ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
180        };
181        va_list ap;
182        va_start(ap, format);
183        __android_log_vprint(levels[level], "racoon", format, ap);
184        va_end(ap);
185#else
186        static char *levels = "EWNIDV";
187        fprintf(stderr, "%c: ", levels[level]);
188        va_list ap;
189        va_start(ap, format);
190        vfprintf(stderr, format, ap);
191        va_end(ap);
192#endif
193    }
194}
195
196char *binsanitize(char *data, size_t length)
197{
198    char *output = racoon_malloc(length + 1);
199    if (output) {
200        size_t i;
201        for (i = 0; i < length; ++i) {
202            output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
203        }
204        output[length] = '\0';
205    }
206    return output;
207}
208