Imported Upstream version 20070115
[aiccu.git] / common / aiccu.c
blob9abb3344feed29e3cf8ac78367c264e66dc78d10
1 /**********************************************************
2 SixXS - Automatic IPv6 Connectivity Configuration Utility
3 ***********************************************************
4 Copyright 2003-2005 SixXS - http://www.sixxs.net
5 ***********************************************************
6 common/aiccu.c - AICCU Abstracted functions
7 ***********************************************************
8 $Author: jeroen $
9 $Id: aiccu.c,v 1.20 2007-01-15 12:02:10 jeroen Exp $
10 $Date: 2007-01-15 12:02:10 $
11 **********************************************************/
13 #include "aiccu.h"
15 struct AICCU_conf *g_aiccu = NULL;
17 /* Config */
18 struct pl_rule aiccu_conf_rules[] =
20 /* Configuration */
21 {"username", PLRT_STRING, offsetof(struct AICCU_conf, username)},
22 {"password", PLRT_STRING, offsetof(struct AICCU_conf, password)},
23 {"protocol", PLRT_STRING, offsetof(struct AICCU_conf, protocol)},
24 {"server", PLRT_STRING, offsetof(struct AICCU_conf, server)},
25 {"ipv6_interface", PLRT_STRING, offsetof(struct AICCU_conf, ipv6_interface)},
26 {"tunnel_id", PLRT_STRING, offsetof(struct AICCU_conf, tunnel_id)},
27 {"local_ipv4_override", PLRT_STRING, offsetof(struct AICCU_conf, local_ipv4_override)},
29 /* Post Setup script path */
30 {"setupscript", PLRT_STRING, offsetof(struct AICCU_conf, setupscript)},
32 /* Automatic */
33 {"automatic", PLRT_BOOL, offsetof(struct AICCU_conf, automatic)},
35 /* Operational options */
36 {"daemonize", PLRT_BOOL, offsetof(struct AICCU_conf, daemonize)},
37 {"verbose", PLRT_BOOL, offsetof(struct AICCU_conf, verbose)},
38 {"behindnat", PLRT_BOOL, offsetof(struct AICCU_conf, behindnat)},
39 {"requiretls", PLRT_BOOL, offsetof(struct AICCU_conf, requiretls)},
40 {"noconfigure", PLRT_BOOL, offsetof(struct AICCU_conf, noconfigure)},
41 {"makebeats", PLRT_BOOL, offsetof(struct AICCU_conf, makebeats)},
42 {"defaultroute", PLRT_BOOL, offsetof(struct AICCU_conf, defaultroute)},
43 {"pidfile", PLRT_STRING, offsetof(struct AICCU_conf, pidfile)},
44 {NULL, PLRT_END, 0},
47 #ifdef AICCU_GNUTLS
48 void aiccu_tls_log(int level, const char *message);
49 void aiccu_tls_log(int level, const char *message)
51 dolog(level, "[GNUTLS] %s\n", message);
53 #endif
55 bool aiccu_InitConfig()
57 #ifdef AICCU_GNUTLS
58 int ret;
59 #define CAFILE "ca.pem"
60 #endif
61 /* Allocate & Initialize */
62 g_aiccu = (struct AICCU_conf *)malloc(sizeof(*g_aiccu));
63 if (!g_aiccu) return false;
64 memset(g_aiccu, 0, sizeof(*g_aiccu));
65 g_aiccu->tic = (struct TIC_conf *)malloc(sizeof(*g_aiccu->tic));
66 memset(g_aiccu->tic, 0, sizeof(*g_aiccu->tic));
68 /* Initialize config to defaults */
69 g_aiccu->running = true;
70 g_aiccu->tunrunning = false;
71 g_aiccu->daemonize = 0;
72 g_aiccu->verbose = false;
73 g_aiccu->requiretls = false; /* Not mandatory yet */
74 g_aiccu->noconfigure = false;
75 g_aiccu->makebeats = true;
76 g_aiccu->defaultroute = true;
77 g_aiccu->ipv6_interface = strdup("aiccu");
78 if (!g_aiccu->ipv6_interface) return false;
79 g_aiccu->protocol = strdup("tic");
80 if (!g_aiccu->protocol) return false;
81 g_aiccu->server = strdup("tic.sixxs.net");
82 if (!g_aiccu->server) return false;
83 g_aiccu->pidfile = strdup(AICCU_PID);
84 if (!g_aiccu->pidfile) return false;
86 #ifdef AICCU_GNUTLS
87 /* Initialize GNUTLS */
88 ret = gnutls_global_init();
89 if (ret != 0)
91 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
92 return false;
95 /* X509 credentials */
96 ret = gnutls_certificate_allocate_credentials(&g_aiccu->tls_cred);
97 if (ret != 0)
99 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
100 return false;
103 /* For the time being don't load the PEM as it is not there... */
105 #if 0
106 /* Sets the trusted cas file */
107 ret = gnutls_certificate_set_x509_trust_file(g_aiccu->tls_cred, CAFILE, GNUTLS_X509_FMT_PEM);
108 if (ret < 0)
110 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
111 return false;
113 #endif
115 /* Configure GNUTLS logging to happen using our own logging interface */
116 gnutls_global_set_log_function(aiccu_tls_log);
118 #ifdef DEBUG
119 /* Show some GNUTLS debugging information */
120 gnutls_global_set_log_level(5);
121 #endif
123 #endif /* AICCU_GNUTLS */
125 return true;
128 /* Locate where the configfile is stored */
129 void aiccu_LocateFile(const char *what, char *filename, unsigned int length);
130 void aiccu_LocateFile(const char *what, char *filename, unsigned int length)
132 memset(filename, 0, length);
133 #ifdef _WIN32
134 /* Figure out the "C:\Windows" location */
135 /* as that is where we store our configuration */
136 GetWindowsDirectory(filename, length);
137 strncat(filename, "\\", length);
138 strncat(filename, what, length);
139 #else
140 /* Use the default location */
141 strncat(filename, what, length);
142 #endif
145 /* configure this client */
146 bool aiccu_LoadConfig(const char *filename)
148 FILE *f;
149 char buf[1000];
150 char filenames[256];
151 unsigned int line = 0;
153 if (!filename)
155 aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
156 filename = filenames;
159 f = fopen(filename, "r");
160 if (!f)
162 dolog(LOG_ERR, "Could not open config file \"%s\"\n", filename);
163 return false;
166 while (fgets(buf, sizeof(buf), f))
168 line++;
169 if (parseline(buf, " ", aiccu_conf_rules, g_aiccu)) continue;
171 dolog(LOG_WARNING, "Unknown configuration statement on line %u of %s: \"%s\"\n", line, filename, buf);
173 fclose(f);
175 return true;
178 /* Save the configuration */
179 bool aiccu_SaveConfig(const char *filename)
181 FILE *f;
182 char filenames[512];
184 if (!filename)
186 aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
187 filename = filenames;
190 f = fopen(filename, "w");
191 if (!f)
193 dolog(LOG_ERR, "Could not open config file \"%s\" for writing\n", filename);
194 return false;
197 fprintf(f, "# AICCU Configuration (Saved by AICCU %s)\n", AICCU_VER);
198 fprintf(f, "\n");
199 fprintf(f, "# Login information\n");
200 fprintf(f, "username %s\n", g_aiccu->username);
201 fprintf(f, "password %s\n", g_aiccu->password);
202 fprintf(f, "protocol %s\n", g_aiccu->protocol);
203 fprintf(f, "server %s\n", g_aiccu->server);
204 fprintf(f, "\n");
205 fprintf(f, "# Interface names to use\n");
206 fprintf(f, "ipv6_interface %s\n", g_aiccu->ipv6_interface);
207 fprintf(f, "\n");
208 fprintf(f, "# The tunnel_id to use\n");
209 fprintf(f, "# (only required when there are multiple tunnels in the list)\n");
210 fprintf(f, "tunnel_id %s\n", g_aiccu->tunnel_id);
211 fprintf(f, "\n");
212 fprintf(f, "# Try to automatically login and setup the tunnel?\n");
213 fprintf(f, "automatic %s\n", g_aiccu->automatic ? "true" : "false");
214 fprintf(f, "\n");
215 fprintf(f, "# Script to run after setting up the interfaces (default: none)\n");
216 fprintf(f, "%ssetupscript %s\n", g_aiccu->setupscript ? "" : "#", g_aiccu->setupscript ? g_aiccu->setupscript : "<path>");
217 fprintf(f, "\n");
218 fprintf(f, "# TLS Required?\n");
219 fprintf(f, "requiretls %s\n", g_aiccu->requiretls ? "true" : "false");
220 fprintf(f, "\n");
221 fprintf(f, "# Be verbose?\n");
222 fprintf(f, "verbose %s\n", g_aiccu->verbose ? "true" : "false");
223 fprintf(f, "\n");
224 fprintf(f, "# Daemonize?\n");
225 fprintf(f, "daemonize %s\n", g_aiccu->daemonize ? "true" : "false");
226 fprintf(f, "\n");
227 fprintf(f, "# Behind NAT (default: false)\n");
228 fprintf(f, "# Notify the user that a NAT-kind network is detected\n");
229 fprintf(f, "behindnat %s\n", g_aiccu->behindnat ? "true" : "false");
230 fprintf(f, "\n");
231 fprintf(f, "# PID File\n");
232 fprintf(f, "pidfile %s\n", g_aiccu->pidfile);
233 fprintf(f, "\n");
234 fprintf(f, "# Make heartbeats (default true)\n");
235 fprintf(f, "# In general you don't want to turn this off\n");
236 fprintf(f, "# Of course only applies to AYIYA and heartbeat tunnels not to static ones\n");
237 fprintf(f, "makebeats %s\n", g_aiccu->makebeats ? "true" : "false");
238 fprintf(f, "\n");
239 fprintf(f, "# Add a default route (default: true)\n");
240 fprintf(f, "defaultroute %s\n", g_aiccu->defaultroute ? "true" : "false");
241 fprintf(f, "\n");
242 fprintf(f, "# Don't configure anything (default: false)\n");
243 fprintf(f, "noconfigure %s\n", g_aiccu->noconfigure ? "true" : "false");
244 fclose(f);
245 return true;
248 void aiccu_FreeConfig()
250 if (!g_aiccu) return;
252 #ifdef AICCU_GNUTLS
253 gnutls_certificate_free_credentials(g_aiccu->tls_cred);
254 gnutls_global_deinit();
255 #endif
257 if (g_aiccu->username) { free(g_aiccu->username); g_aiccu->username = NULL; }
258 if (g_aiccu->password) { free(g_aiccu->password); g_aiccu->password = NULL; }
259 if (g_aiccu->ipv6_interface) { free(g_aiccu->ipv6_interface);g_aiccu->ipv6_interface = NULL; }
260 if (g_aiccu->tunnel_id) { free(g_aiccu->tunnel_id); g_aiccu->tunnel_id = NULL; }
261 if (g_aiccu->tic) { free(g_aiccu->tic); g_aiccu->tic = NULL; }
262 if (g_aiccu->setupscript) { free(g_aiccu->setupscript); g_aiccu->setupscript = NULL; }
263 if (g_aiccu->pidfile) { free(g_aiccu->pidfile); g_aiccu->pidfile = NULL; }
265 free(g_aiccu);
266 g_aiccu = NULL;
269 /* Make sure the OS understands IPv6 */
270 void aiccu_install(void)
272 D(dolog(LOG_DEBUG, "aiccu_install()\n");)
273 aiccu_os_install();
276 bool aiccu_setup(struct TIC_Tunnel *hTunnel, bool firstrun)
278 bool ret = false;
280 D(dolog(LOG_DEBUG, "aiccu_setup(%s, %s)\n", hTunnel->sIPv6_Local, firstrun ? "first" : "other");)
282 /* AYIYA calls aiccu_setup(hTunnel,false) after preparing the tunnel interface */
283 if (firstrun && strcasecmp(hTunnel->sType, "ayiya") == 0)
285 ret = ayiya(hTunnel);
287 #ifdef NEWSTUFF_TEEPEE
288 else if (firstrun && strcasecmp(hTunnel->sType, "l2tp") == 0)
290 ret = teepee(hTunnel);
292 #endif
293 else
295 ret = aiccu_os_setup(hTunnel);
298 /* Beat for the first time */
299 if (ret) aiccu_beat(hTunnel);
301 return ret;
304 void aiccu_beat(struct TIC_Tunnel *hTunnel)
306 if (!g_aiccu->makebeats)
308 D(dolog(LOG_DEBUG, "aiccu_beat() - Beating disabled\n"));
309 return;
312 D(dolog(LOG_DEBUG, "aiccu_beat() - Beating %s...\n", hTunnel->sType));
314 if (strcasecmp(hTunnel->sType, "6in4-heartbeat") == 0)
316 heartbeat_beat(hTunnel);
318 else if (strcasecmp(hTunnel->sType, "ayiya") == 0)
320 ayiya_beat();
322 else
324 D(dolog(LOG_DEBUG, "aiccu_beat() - No beat for %s!?\n", hTunnel->sType));
327 /* L2TP Hello's are handled inside TeePee */
330 void aiccu_reconfig(struct TIC_Tunnel *hTunnel)
332 D(dolog(LOG_DEBUG, "aiccu_reconfig(%s)\n", hTunnel->sIPv6_Local);)
333 if (!g_aiccu->noconfigure) aiccu_os_reconfig(hTunnel);
336 void aiccu_delete(struct TIC_Tunnel *hTunnel)
338 D(dolog(LOG_DEBUG, "aiccu_delete(%s)\n", hTunnel->sIPv6_Local);)
339 if (!g_aiccu->noconfigure) aiccu_os_delete(hTunnel);
342 void aiccu_test(struct TIC_Tunnel *hTunnel, bool automatic)
344 D(dolog(LOG_DEBUG, "aiccu_test()\n"));
345 aiccu_os_test(hTunnel, automatic);
348 bool aiccu_exec(const char *fmt, ...)
350 #ifndef _WIN32
351 char buf[1024];
352 int ret;
353 va_list ap;
355 va_start(ap, fmt);
356 vsnprintf(buf,sizeof(buf),fmt,ap);
357 D(dolog(LOG_DEBUG, "aiccu_os_exec(\"%s\")\n", buf));
358 ret = system(buf);
359 if (ret == -1) dolog(LOG_WARNING, "Execution of \"%s\" failed!? (Please check if the command is available)\n", buf);
360 va_end(ap);
361 #endif
362 return true;
365 #define SIXXS_LICENSE_PART1 "\
366 The SixXS License - http://www.sixxs.net/\n\
368 Copyright (C) SixXS Staff <info@sixxs.net>\n\
369 All rights reserved.\n\
371 Redistribution and use in source and binary forms, with or without\n\
372 modification, are permitted provided that the following conditions\n\
373 are met:\n\
374 1. Redistributions of source code must retain the above copyright\n\
375 notice, this list of conditions and the following disclaimer.\n"
377 #define SIXXS_LICENSE_PART2 "\
378 2. Redistributions in binary form must reproduce the above copyright\n\
379 notice, this list of conditions and the following disclaimer in the\n\
380 documentation and/or other materials provided with the distribution.\n\
381 3. Neither the name of SixXS nor the names of its contributors\n\
382 may be used to endorse or promote products derived from this software\n\
383 without specific prior permission.\n\
387 #define SIXXS_LICENSE_PART3 "\
388 THIS SOFTWARE IS PROVIDED BY SIXXS AND CONTRIBUTORS ``AS IS'' AND\n\
389 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\
390 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n\
391 ARE DISCLAIMED. IN NO EVENT SHALL SIXXS OR CONTRIBUTORS BE LIABLE\n\
392 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n\
393 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
395 #define SIXXS_LICENSE_PART4 "\
396 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\
397 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n\
398 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n\
399 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n\
400 SUCH DAMAGE.\n"
402 const char *aiccu_license()
404 #ifndef NOPEDANTIC
406 * Pedantic doesn't allow this long strings, thus we will
407 * play nice and malloc it, copy them in separately and
408 * then return the buffer.
409 * What we don't do for compliancy....
411 static char *license = NULL;
412 if (!license)
415 * Make one big block out of it
416 * too bad that the \0's get inserted,
417 * remove them and tada one big text...
419 static char
420 l1[] = SIXXS_LICENSE_PART1,
421 l2[] = SIXXS_LICENSE_PART2,
422 l3[] = SIXXS_LICENSE_PART3,
423 l4[] = SIXXS_LICENSE_PART4;
424 size_t
425 a = strlen(l1),
426 b = strlen(l2),
427 c = strlen(l3),
428 d = strlen(l4);
430 /* Create the 'long' string our selves then */
431 license = (char *)malloc(a+b+c+d+1);
432 if (!license) return NULL;
434 memset(license, 0, a+b+c+d+1);
435 memcpy(license , l1, a);
436 memcpy(license + a, l2, b);
437 memcpy(license + a + b, l3, c);
438 memcpy(license + a + b + c, l4, d);
440 return license;
441 #else
442 return SIXXS_LICENSE_PART1 SIXXS_LICENSE_PART2 SIXXS_LICENSE_PART3 SIXXS_LICENSE_PART4;
443 #endif