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 ***********************************************************
9 $Id: aiccu.c,v 1.20 2007-01-15 12:02:10 jeroen Exp $
10 $Date: 2007-01-15 12:02:10 $
11 **********************************************************/
15 struct AICCU_conf
*g_aiccu
= NULL
;
18 struct pl_rule aiccu_conf_rules
[] =
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
)},
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
)},
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
);
55 bool aiccu_InitConfig()
59 #define CAFILE "ca.pem"
62 openlog(NULL
, LOG_PID
, LOG_DAEMON
);
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
));
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;
90 /* Initialize GNUTLS */
91 ret
= gnutls_global_init();
94 dolog(LOG_ERR
, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret
), ret
);
98 /* X509 credentials */
99 ret
= gnutls_certificate_allocate_credentials(&g_aiccu
->tls_cred
);
102 dolog(LOG_ERR
, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret
), ret
);
106 /* For the time being don't load the PEM as it is not there... */
109 /* Sets the trusted cas file */
110 ret
= gnutls_certificate_set_x509_trust_file(g_aiccu
->tls_cred
, CAFILE
, GNUTLS_X509_FMT_PEM
);
113 dolog(LOG_ERR
, "GNUTLS failed to initialize: %s (%d)\n", gnutls_strerror(ret
), ret
);
118 /* Configure GNUTLS logging to happen using our own logging interface */
119 gnutls_global_set_log_function(aiccu_tls_log
);
122 /* Show some GNUTLS debugging information */
123 gnutls_global_set_log_level(5);
126 #endif /* AICCU_GNUTLS */
131 /* Locate where the configfile is stored */
132 void aiccu_LocateFile(const char *what
, char *filename
, unsigned int length
);
133 void aiccu_LocateFile(const char *what
, char *filename
, unsigned int length
)
135 memset(filename
, 0, length
);
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
);
143 /* Use the default location */
144 strncat(filename
, what
, length
);
148 /* configure this client */
149 bool aiccu_LoadConfig(const char *filename
)
154 unsigned int line
= 0;
158 aiccu_LocateFile(AICCU_CONFIG
, filenames
, sizeof(filenames
));
159 filename
= filenames
;
162 f
= fopen(filename
, "r");
165 dolog(LOG_ERR
, "Could not open config file \"%s\"\n", filename
);
169 while (fgets(buf
, sizeof(buf
), f
))
172 if (parseline(buf
, " ", aiccu_conf_rules
, g_aiccu
)) continue;
174 dolog(LOG_WARNING
, "Unknown configuration statement on line %u of %s: \"%s\"\n", line
, filename
, buf
);
181 /* Save the configuration */
182 bool aiccu_SaveConfig(const char *filename
)
189 aiccu_LocateFile(AICCU_CONFIG
, filenames
, sizeof(filenames
));
190 filename
= filenames
;
193 f
= fopen(filename
, "w");
196 dolog(LOG_ERR
, "Could not open config file \"%s\" for writing\n", filename
);
200 fprintf(f
, "# AICCU Configuration (Saved by AICCU %s)\n", AICCU_VER
);
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
);
208 fprintf(f
, "# Interface names to use\n");
209 fprintf(f
, "ipv6_interface %s\n", g_aiccu
->ipv6_interface
);
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
);
215 fprintf(f
, "# Try to automatically login and setup the tunnel?\n");
216 fprintf(f
, "automatic %s\n", g_aiccu
->automatic
? "true" : "false");
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>");
221 fprintf(f
, "# TLS Required?\n");
222 fprintf(f
, "requiretls %s\n", g_aiccu
->requiretls
? "true" : "false");
224 fprintf(f
, "# Be verbose?\n");
225 fprintf(f
, "verbose %s\n", g_aiccu
->verbose
? "true" : "false");
227 fprintf(f
, "# Daemonize?\n");
228 fprintf(f
, "daemonize %s\n", g_aiccu
->daemonize
? "true" : "false");
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");
234 fprintf(f
, "# PID File\n");
235 fprintf(f
, "pidfile %s\n", g_aiccu
->pidfile
);
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");
242 fprintf(f
, "# Add a default route (default: true)\n");
243 fprintf(f
, "defaultroute %s\n", g_aiccu
->defaultroute
? "true" : "false");
245 fprintf(f
, "# Don't configure anything (default: false)\n");
246 fprintf(f
, "noconfigure %s\n", g_aiccu
->noconfigure
? "true" : "false");
251 void aiccu_FreeConfig()
253 if (!g_aiccu
) return;
256 gnutls_certificate_free_credentials(g_aiccu
->tls_cred
);
257 gnutls_global_deinit();
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
; }
272 /* Make sure the OS understands IPv6 */
273 void aiccu_install(void)
275 D(dolog(LOG_DEBUG
, "aiccu_install()\n");)
279 bool aiccu_setup(struct TIC_Tunnel
*hTunnel
, bool firstrun
)
283 D(dolog(LOG_DEBUG
, "aiccu_setup(%s, %s)\n", hTunnel
->sIPv6_Local
, firstrun
? "first" : "other");)
285 /* AYIYA calls aiccu_setup(hTunnel,false) after preparing the tunnel interface */
286 if (firstrun
&& strcasecmp(hTunnel
->sType
, "ayiya") == 0)
288 ret
= ayiya(hTunnel
);
290 #ifdef NEWSTUFF_TEEPEE
291 else if (firstrun
&& strcasecmp(hTunnel
->sType
, "l2tp") == 0)
293 ret
= teepee(hTunnel
);
298 ret
= aiccu_os_setup(hTunnel
);
301 /* Beat for the first time */
302 if (ret
) aiccu_beat(hTunnel
);
307 void aiccu_beat(struct TIC_Tunnel
*hTunnel
)
309 if (!g_aiccu
->makebeats
)
311 D(dolog(LOG_DEBUG
, "aiccu_beat() - Beating disabled\n"));
315 D(dolog(LOG_DEBUG
, "aiccu_beat() - Beating %s...\n", hTunnel
->sType
));
317 if (strcasecmp(hTunnel
->sType
, "6in4-heartbeat") == 0)
319 heartbeat_beat(hTunnel
);
321 else if (strcasecmp(hTunnel
->sType
, "ayiya") == 0)
327 D(dolog(LOG_DEBUG
, "aiccu_beat() - No beat for %s!?\n", hTunnel
->sType
));
330 /* L2TP Hello's are handled inside TeePee */
333 void aiccu_reconfig(struct TIC_Tunnel
*hTunnel
)
335 D(dolog(LOG_DEBUG
, "aiccu_reconfig(%s)\n", hTunnel
->sIPv6_Local
);)
336 if (!g_aiccu
->noconfigure
) aiccu_os_reconfig(hTunnel
);
339 void aiccu_delete(struct TIC_Tunnel
*hTunnel
)
341 D(dolog(LOG_DEBUG
, "aiccu_delete(%s)\n", hTunnel
->sIPv6_Local
);)
342 if (!g_aiccu
->noconfigure
) aiccu_os_delete(hTunnel
);
345 void aiccu_test(struct TIC_Tunnel
*hTunnel
, bool automatic
)
347 D(dolog(LOG_DEBUG
, "aiccu_test()\n"));
348 aiccu_os_test(hTunnel
, automatic
);
351 bool aiccu_exec(const char *fmt
, ...)
359 vsnprintf(buf
,sizeof(buf
),fmt
,ap
);
360 D(dolog(LOG_DEBUG
, "aiccu_os_exec(\"%s\")\n", buf
));
362 if (ret
== -1) dolog(LOG_WARNING
, "Execution of \"%s\" failed!? (Please check if the command is available)\n", buf
);
368 #define SIXXS_LICENSE_PART1 "\
369 The SixXS License - http://www.sixxs.net/\n\
371 Copyright (C) SixXS Staff <info@sixxs.net>\n\
372 All rights reserved.\n\
374 Redistribution and use in source and binary forms, with or without\n\
375 modification, are permitted provided that the following conditions\n\
377 1. Redistributions of source code must retain the above copyright\n\
378 notice, this list of conditions and the following disclaimer.\n"
380 #define SIXXS_LICENSE_PART2 "\
381 2. 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\
384 3. 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\
390 #define SIXXS_LICENSE_PART3 "\
391 THIS SOFTWARE IS PROVIDED BY SIXXS AND CONTRIBUTORS ``AS IS'' AND\n\
392 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n\
393 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n\
394 ARE DISCLAIMED. IN NO EVENT SHALL SIXXS OR CONTRIBUTORS BE LIABLE\n\
395 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n\
396 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n"
398 #define SIXXS_LICENSE_PART4 "\
399 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n\
400 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n\
401 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n\
402 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n\
405 const char *aiccu_license()
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....
414 static char *license
= NULL
;
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...
423 l1
[] = SIXXS_LICENSE_PART1
,
424 l2
[] = SIXXS_LICENSE_PART2
,
425 l3
[] = SIXXS_LICENSE_PART3
,
426 l4
[] = SIXXS_LICENSE_PART4
;
433 /* Create the 'long' string our selves then */
434 license
= (char *)malloc(a
+b
+c
+d
+1);
435 if (!license
) return NULL
;
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
);
445 return SIXXS_LICENSE_PART1 SIXXS_LICENSE_PART2 SIXXS_LICENSE_PART3 SIXXS_LICENSE_PART4
;