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