]> git.ipfire.org Git - people/stevee/aiccu.git/blame - common/aiccu.c
Add setup script functionality to Linux client
[people/stevee/aiccu.git] / common / aiccu.c
CommitLineData
d98f6a46
SS
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**********************************************************/
12
13#include "aiccu.h"
14
15struct AICCU_conf *g_aiccu = NULL;
16
17/* Config */
18struct pl_rule aiccu_conf_rules[] =
19{
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)},
28
29 /* Post Setup script path */
30 {"setupscript", PLRT_STRING, offsetof(struct AICCU_conf, setupscript)},
31
32 /* Automatic */
33 {"automatic", PLRT_BOOL, offsetof(struct AICCU_conf, automatic)},
34
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},
45};
46
47#ifdef AICCU_GNUTLS
48void aiccu_tls_log(int level, const char *message);
49void aiccu_tls_log(int level, const char *message)
50{
51 dolog(level, "[GNUTLS] %s\n", message);
52}
53#endif
54
55bool aiccu_InitConfig()
56{
57#ifdef AICCU_GNUTLS
58 int ret;
59#define CAFILE "ca.pem"
28ad9c07
NR
60#endif
61#ifndef _WIN32
62 openlog(NULL, LOG_PID, LOG_DAEMON);
d98f6a46
SS
63#endif
64 /* Allocate & Initialize */
65 g_aiccu = (struct AICCU_conf *)malloc(sizeof(*g_aiccu));
66 if (!g_aiccu) return false;
67 memset(g_aiccu, 0, sizeof(*g_aiccu));
68 g_aiccu->tic = (struct TIC_conf *)malloc(sizeof(*g_aiccu->tic));
69 memset(g_aiccu->tic, 0, sizeof(*g_aiccu->tic));
70
71 /* Initialize config to defaults */
72 g_aiccu->running = true;
73 g_aiccu->tunrunning = false;
74 g_aiccu->daemonize = 0;
75 g_aiccu->verbose = false;
76 g_aiccu->requiretls = false; /* Not mandatory yet */
77 g_aiccu->noconfigure = false;
78 g_aiccu->makebeats = true;
79 g_aiccu->defaultroute = true;
80 g_aiccu->ipv6_interface = strdup("aiccu");
81 if (!g_aiccu->ipv6_interface) return false;
82 g_aiccu->protocol = strdup("tic");
83 if (!g_aiccu->protocol) return false;
84 g_aiccu->server = strdup("tic.sixxs.net");
85 if (!g_aiccu->server) return false;
86 g_aiccu->pidfile = strdup(AICCU_PID);
87 if (!g_aiccu->pidfile) return false;
88
89#ifdef AICCU_GNUTLS
90 /* Initialize GNUTLS */
91 ret = gnutls_global_init();
92 if (ret != 0)
93 {
94 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
95 return false;
96 }
97
98 /* X509 credentials */
99 ret = gnutls_certificate_allocate_credentials(&g_aiccu->tls_cred);
100 if (ret != 0)
101 {
102 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
103 return false;
104 }
105
106 /* For the time being don't load the PEM as it is not there... */
107
108#if 0
109 /* Sets the trusted cas file */
110 ret = gnutls_certificate_set_x509_trust_file(g_aiccu->tls_cred, CAFILE, GNUTLS_X509_FMT_PEM);
111 if (ret < 0)
112 {
113 dolog(LOG_ERR, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret), ret);
114 return false;
115 }
116#endif
117
118 /* Configure GNUTLS logging to happen using our own logging interface */
119 gnutls_global_set_log_function(aiccu_tls_log);
120
121#ifdef DEBUG
122 /* Show some GNUTLS debugging information */
123 gnutls_global_set_log_level(5);
124#endif
125
126#endif /* AICCU_GNUTLS */
127
128 return true;
129}
130
131/* Locate where the configfile is stored */
132void aiccu_LocateFile(const char *what, char *filename, unsigned int length);
133void aiccu_LocateFile(const char *what, char *filename, unsigned int length)
134{
135 memset(filename, 0, length);
136#ifdef _WIN32
137 /* Figure out the "C:\Windows" location */
138 /* as that is where we store our configuration */
139 GetWindowsDirectory(filename, length);
140 strncat(filename, "\\", length);
141 strncat(filename, what, length);
142#else
143 /* Use the default location */
144 strncat(filename, what, length);
145#endif
146}
147
148/* configure this client */
149bool aiccu_LoadConfig(const char *filename)
150{
151 FILE *f;
152 char buf[1000];
153 char filenames[256];
154 unsigned int line = 0;
155
156 if (!filename)
157 {
158 aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
159 filename = filenames;
160 }
161
162 f = fopen(filename, "r");
163 if (!f)
164 {
165 dolog(LOG_ERR, "Could not open config file \"%s\"\n", filename);
166 return false;
167 }
168
169 while (fgets(buf, sizeof(buf), f))
170 {
171 line++;
172 if (parseline(buf, " ", aiccu_conf_rules, g_aiccu)) continue;
173
174 dolog(LOG_WARNING, "Unknown configuration statement on line %u of %s: \"%s\"\n", line, filename, buf);
175 }
176 fclose(f);
177
178 return true;
179}
180
181/* Save the configuration */
182bool aiccu_SaveConfig(const char *filename)
183{
184 FILE *f;
185 char filenames[512];
186
187 if (!filename)
188 {
189 aiccu_LocateFile(AICCU_CONFIG, filenames, sizeof(filenames));
190 filename = filenames;
191 }
192
193 f = fopen(filename, "w");
194 if (!f)
195 {
196 dolog(LOG_ERR, "Could not open config file \"%s\" for writing\n", filename);
197 return false;
198 }
199
200 fprintf(f, "# AICCU Configuration (Saved by AICCU %s)\n", AICCU_VER);
201 fprintf(f, "\n");
202 fprintf(f, "# Login information\n");
203 fprintf(f, "username %s\n", g_aiccu->username);
204 fprintf(f, "password %s\n", g_aiccu->password);
205 fprintf(f, "protocol %s\n", g_aiccu->protocol);
206 fprintf(f, "server %s\n", g_aiccu->server);
207 fprintf(f, "\n");
208 fprintf(f, "# Interface names to use\n");
209 fprintf(f, "ipv6_interface %s\n", g_aiccu->ipv6_interface);
210 fprintf(f, "\n");
211 fprintf(f, "# The tunnel_id to use\n");
212 fprintf(f, "# (only required when there are multiple tunnels in the list)\n");
213 fprintf(f, "tunnel_id %s\n", g_aiccu->tunnel_id);
214 fprintf(f, "\n");
215 fprintf(f, "# Try to automatically login and setup the tunnel?\n");
216 fprintf(f, "automatic %s\n", g_aiccu->automatic ? "true" : "false");
217 fprintf(f, "\n");
5cb2a912
SS
218 fprintf(f, "# Script to run after setting up the interfaces (default: none)\n");
219 fprintf(f, "%ssetupscript %s\n", g_aiccu->setupscript ? "" : "#", g_aiccu->setupscript ? g_aiccu->setupscript : "<path>");
220 fprintf(f, "\n");
d98f6a46
SS
221 fprintf(f, "# TLS Required?\n");
222 fprintf(f, "requiretls %s\n", g_aiccu->requiretls ? "true" : "false");
223 fprintf(f, "\n");
224 fprintf(f, "# Be verbose?\n");
225 fprintf(f, "verbose %s\n", g_aiccu->verbose ? "true" : "false");
226 fprintf(f, "\n");
227 fprintf(f, "# Daemonize?\n");
228 fprintf(f, "daemonize %s\n", g_aiccu->daemonize ? "true" : "false");
229 fprintf(f, "\n");
230 fprintf(f, "# Behind NAT (default: false)\n");
231 fprintf(f, "# Notify the user that a NAT-kind network is detected\n");
232 fprintf(f, "behindnat %s\n", g_aiccu->behindnat ? "true" : "false");
233 fprintf(f, "\n");
234 fprintf(f, "# PID File\n");
235 fprintf(f, "pidfile %s\n", g_aiccu->pidfile);
236 fprintf(f, "\n");
237 fprintf(f, "# Make heartbeats (default true)\n");
238 fprintf(f, "# In general you don't want to turn this off\n");
239 fprintf(f, "# Of course only applies to AYIYA and heartbeat tunnels not to static ones\n");
240 fprintf(f, "makebeats %s\n", g_aiccu->makebeats ? "true" : "false");
241 fprintf(f, "\n");
242 fprintf(f, "# Add a default route (default: true)\n");
243 fprintf(f, "defaultroute %s\n", g_aiccu->defaultroute ? "true" : "false");
244 fprintf(f, "\n");
245 fprintf(f, "# Don't configure anything (default: false)\n");
246 fprintf(f, "noconfigure %s\n", g_aiccu->noconfigure ? "true" : "false");
247 fclose(f);
248 return true;
249}
250
251void aiccu_FreeConfig()
252{
253 if (!g_aiccu) return;
254
255#ifdef AICCU_GNUTLS
256 gnutls_certificate_free_credentials(g_aiccu->tls_cred);
257 gnutls_global_deinit();
258#endif
259
260 if (g_aiccu->username) { free(g_aiccu->username); g_aiccu->username = NULL; }
261 if (g_aiccu->password) { free(g_aiccu->password); g_aiccu->password = NULL; }
262 if (g_aiccu->ipv6_interface) { free(g_aiccu->ipv6_interface);g_aiccu->ipv6_interface = NULL; }
263 if (g_aiccu->tunnel_id) { free(g_aiccu->tunnel_id); g_aiccu->tunnel_id = NULL; }
264 if (g_aiccu->tic) { free(g_aiccu->tic); g_aiccu->tic = NULL; }
265 if (g_aiccu->setupscript) { free(g_aiccu->setupscript); g_aiccu->setupscript = NULL; }
266 if (g_aiccu->pidfile) { free(g_aiccu->pidfile); g_aiccu->pidfile = NULL; }
267
268 free(g_aiccu);
269 g_aiccu = NULL;
270}
271
272/* Make sure the OS understands IPv6 */
273void aiccu_install(void)
274{
275 D(dolog(LOG_DEBUG, "aiccu_install()\n");)
276 aiccu_os_install();
277}
278
279bool aiccu_setup(struct TIC_Tunnel *hTunnel, bool firstrun)
280{
281 bool ret = false;
282
283 D(dolog(LOG_DEBUG, "aiccu_setup(%s, %s)\n", hTunnel->sIPv6_Local, firstrun ? "first" : "other");)
284
285 /* AYIYA calls aiccu_setup(hTunnel,false) after preparing the tunnel interface */
286 if (firstrun && strcasecmp(hTunnel->sType, "ayiya") == 0)
287 {
288 ret = ayiya(hTunnel);
289 }
290#ifdef NEWSTUFF_TEEPEE
291 else if (firstrun && strcasecmp(hTunnel->sType, "l2tp") == 0)
292 {
293 ret = teepee(hTunnel);
294 }
295#endif
296 else
297 {
298 ret = aiccu_os_setup(hTunnel);
299 }
300
301 /* Beat for the first time */
302 if (ret) aiccu_beat(hTunnel);
303
304 return ret;
305}
306
307void aiccu_beat(struct TIC_Tunnel *hTunnel)
308{
309 if (!g_aiccu->makebeats)
310 {
311 D(dolog(LOG_DEBUG, "aiccu_beat() - Beating disabled\n"));
312 return;
313 }
314
315 D(dolog(LOG_DEBUG, "aiccu_beat() - Beating %s...\n", hTunnel->sType));
316
317 if (strcasecmp(hTunnel->sType, "6in4-heartbeat") == 0)
318 {
319 heartbeat_beat(hTunnel);
320 }
321 else if (strcasecmp(hTunnel->sType, "ayiya") == 0)
322 {
323 ayiya_beat();
324 }
325 else
326 {
327 D(dolog(LOG_DEBUG, "aiccu_beat() - No beat for %s!?\n", hTunnel->sType));
328 }
329
330 /* L2TP Hello's are handled inside TeePee */
331}
332
333void aiccu_reconfig(struct TIC_Tunnel *hTunnel)
334{
335 D(dolog(LOG_DEBUG, "aiccu_reconfig(%s)\n", hTunnel->sIPv6_Local);)
336 if (!g_aiccu->noconfigure) aiccu_os_reconfig(hTunnel);
337}
338
339void aiccu_delete(struct TIC_Tunnel *hTunnel)
340{
341 D(dolog(LOG_DEBUG, "aiccu_delete(%s)\n", hTunnel->sIPv6_Local);)
342 if (!g_aiccu->noconfigure) aiccu_os_delete(hTunnel);
343}
344
345void aiccu_test(struct TIC_Tunnel *hTunnel, bool automatic)
346{
347 D(dolog(LOG_DEBUG, "aiccu_test()\n"));
348 aiccu_os_test(hTunnel, automatic);
349}
350
351bool aiccu_exec(const char *fmt, ...)
352{
353#ifndef _WIN32
354 char buf[1024];
355 int ret;
356 va_list ap;
357
358 va_start(ap, fmt);
359 vsnprintf(buf,sizeof(buf),fmt,ap);
360 D(dolog(LOG_DEBUG, "aiccu_os_exec(\"%s\")\n", buf));
361 ret = system(buf);
362 if (ret == -1) dolog(LOG_WARNING, "Execution of \"%s\" failed!? (Please check if the command is available)\n", buf);
363 va_end(ap);
364#endif
365 return true;
366}
367
368#define SIXXS_LICENSE_PART1 "\
369The SixXS License - http://www.sixxs.net/\n\
370\n\
371Copyright (C) SixXS Staff <info@sixxs.net>\n\
372All rights reserved.\n\
373\n\
374Redistribution and use in source and binary forms, with or without\n\
375modification, are permitted provided that the following conditions\n\
376are met:\n\
3771. Redistributions of source code must retain the above copyright\n\
378 notice, this list of conditions and the following disclaimer.\n"
379
380#define SIXXS_LICENSE_PART2 "\
3812. Redistributions in binary form must reproduce the above copyright\n\
382 notice, this list of conditions and the following disclaimer in the\n\
383 documentation and/or other materials provided with the distribution.\n\
3843. Neither the name of SixXS nor the names of its contributors\n\
385 may be used to endorse or promote products derived from this software\n\
386 without specific prior permission.\n\
387\n\
388\n"
389
390#define SIXXS_LICENSE_PART3 "\
391THIS SOFTWARE IS PROVIDED BY SIXXS AND CONTRIBUTORS ``AS IS'' AND\n\
392ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\
393IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n\
394ARE DISCLAIMED. IN NO EVENT SHALL SIXXS OR CONTRIBUTORS BE LIABLE\n\
395FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n\
396DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
397
398#define SIXXS_LICENSE_PART4 "\
399OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\
400HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n\
401LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n\
402OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n\
403SUCH DAMAGE.\n"
404
405const char *aiccu_license()
406{
407#ifndef NOPEDANTIC
408 /*
409 * Pedantic doesn't allow this long strings, thus we will
410 * play nice and malloc it, copy them in separately and
411 * then return the buffer.
412 * What we don't do for compliancy....
413 */
414 static char *license = NULL;
415 if (!license)
416 {
417 /*
418 * Make one big block out of it
419 * too bad that the \0's get inserted,
420 * remove them and tada one big text...
421 */
422 static char
423 l1[] = SIXXS_LICENSE_PART1,
424 l2[] = SIXXS_LICENSE_PART2,
425 l3[] = SIXXS_LICENSE_PART3,
426 l4[] = SIXXS_LICENSE_PART4;
427 size_t
428 a = strlen(l1),
429 b = strlen(l2),
430 c = strlen(l3),
431 d = strlen(l4);
432
433 /* Create the 'long' string our selves then */
434 license = (char *)malloc(a+b+c+d+1);
435 if (!license) return NULL;
436
437 memset(license, 0, a+b+c+d+1);
438 memcpy(license , l1, a);
439 memcpy(license + a, l2, b);
440 memcpy(license + a + b, l3, c);
441 memcpy(license + a + b + c, l4, d);
442 }
443 return license;
444#else
445 return SIXXS_LICENSE_PART1 SIXXS_LICENSE_PART2 SIXXS_LICENSE_PART3 SIXXS_LICENSE_PART4;
446#endif
447}