1 /**********************************************************
2 SixXS - Automatic IPv6 Connectivity Configuration Utility
3 ***********************************************************
4 Copyright 2003-2005 SixXS - http://www.sixxs.net
5 ***********************************************************
6 common/tic.c - Tunnel Information & Control Protocol
7 ***********************************************************
9 $Id: tic.c,v 1.17 2007-01-11 13:41:31 jeroen Exp $
10 $Date: 2007-01-11 13:41:31 $
11 **********************************************************/
17 /* Specific includes only used here */
19 #include <sys/utsname.h>
24 unsigned int tic_filled
;
27 * epochtime = epochtime as received in the packet
28 * Don't forget to convert byteorder using ntohl()
30 int tic_checktime(time_t epochtime
)
32 /* Number of seconds we allow the clock to be off */
36 /* Get the current time */
37 time_t curr_time
= time(NULL
);
39 /* Is one of the times in the loop range? */
40 if ( (curr_time
>= -CLOCK_OFF
) ||
41 (epochtime
>= -CLOCK_OFF
))
43 /* Shift the times out of the loop range */
44 i
=(int)(((int)curr_time
) + (CLOCK_OFF
*2)) -
45 (((int)epochtime
) + (CLOCK_OFF
*2));
47 else i
= ((int)curr_time
) - ((int)epochtime
);
49 /* The clock may be faster, thus flip the sign */
52 /* Compare the clock offset */
59 /* Time is in the allowed range */
63 bool tic_Login(struct TIC_conf
*tic
, const char *username
, const char *password
, const char *server
)
65 char buf
[1024], sSignature
[33], sChallenge
[1024];
68 struct utsname uts_name
;
71 OSVERSIONINFOEX osvEx
;
72 char *platform
= NULL
;
76 D(dolog(LOG_DEBUG
, "Trying to connect to TIC server %s\n", server
));
78 /* Connect to the TIC server */
79 tic
->sock
= connect_client(server
, TIC_PORT
, AF_INET
, SOCK_STREAM
);
82 dolog(LOG_ERR
, "Couldn't connect to the TIC server %s\n", server
);
86 /* Fetch the welcome */
87 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
93 dolog(LOG_ERR
, "TIC Server is currently not available\n");
97 /* Send our client identification */
100 sock_printf(tic
->sock
, "client TIC/%s %s/%s %s/%s\n",
102 TIC_CLIENT_NAME
, TIC_CLIENT_VERSION
,
103 uts_name
.sysname
, uts_name
.release
);
105 osv
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
106 osvEx
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
108 if (!GetVersionEx(&osv
))
110 platform
= "Windows";
111 snprintf(version
, sizeof(version
), "%s", "Unknown");
116 platform
= (osv
.dwPlatformId
== VER_PLATFORM_WIN32s
) ? "Win32s" :
117 ((osv
.dwPlatformId
== VER_PLATFORM_WIN32_WINDOWS
) ? "Win9x" :
118 ((osv
.dwPlatformId
== VER_PLATFORM_WIN32_NT
) ? "WinNT" :
121 if ( osv
.dwMajorVersion
< 5 ||
122 !GetVersionEx((OSVERSIONINFO
*)&osvEx
) ||
123 osvEx
.wServicePackMajor
<= 0)
125 snprintf(version
, sizeof(version
), "%d.%d.%d",
126 osv
.dwMajorVersion
, osv
.dwMinorVersion
, osv
.dwBuildNumber
);
128 else if (osvEx
.wServicePackMinor
<= 0)
130 snprintf(version
, sizeof(version
), "%d.%d.%d-SP%d",
131 osv
.dwMajorVersion
, osv
.dwMinorVersion
, osv
.dwBuildNumber
,
132 osvEx
.wServicePackMajor
);
136 snprintf(version
, sizeof(version
), "%d.%d.%d-SP%d.%d",
137 osv
.dwMajorVersion
, osv
.dwMinorVersion
, osv
.dwBuildNumber
,
138 osvEx
.wServicePackMajor
, osvEx
.wServicePackMinor
);
141 sock_printf(tic
->sock
, "client TIC/%s %s/%s %s/%s\n",
143 TIC_CLIENT_NAME
, TIC_CLIENT_VERSION
,
147 /* Fetch the answer */
148 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
154 dolog(LOG_ERR
, "Couldn't pass client information: %s.\n", &buf
[4]);
158 /* Request current time */
159 sock_printf(tic
->sock
, "get unixtime\n");
161 /* Fetch the answer */
162 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
168 dolog(LOG_ERR
, "Time not available? %s\n", &buf
[4]);
172 /* Check if the time is correct */
173 i
= tic_checktime(atoi(&buf
[4]));
177 dolog(LOG_ERR
, "The clock is off by %d seconds, use NTP to sync it!\n", i
);
178 snprintf(quitmsg
, sizeof(quitmsg
), "Aborting: Clock is off by %d seconds\n", i
);
179 tic_Logout(tic
, quitmsg
);
185 sock_printf(tic
->sock
, "starttls\n");
187 /* Fetch the welcome */
188 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
195 if (!sock_gotls(tic
->sock
)) return false;
199 if (g_aiccu
->requiretls
)
201 dolog(LOG_ERR
, "TIC Server does not support TLS and TLS is required\n");
204 if (g_aiccu
->verbose
) dolog(LOG_WARNING
, "TIC Server does not support TLS but TLS is not required, continuing\n");
209 /* Send our username */
210 sock_printf(tic
->sock
, "username %s\n", username
);
212 /* Fetch the answer */
213 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
219 dolog(LOG_ERR
, "Username not accepted: %s.\n", &buf
[4]);
223 /* Pick a challenge */
224 sock_printf(tic
->sock
, "challenge md5\n");
226 /* Fetch the answer */
227 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
233 dolog(LOG_ERR
, "Challenge not correct: %s.\n", &buf
[4]);
237 /* Send the response */
238 /* sSignature = md5(challenge.md5(password)); */
239 MD5String(password
, sSignature
, sizeof(sSignature
));
240 snprintf(sChallenge
, sizeof(sChallenge
), "%s%s", &buf
[4], sSignature
);
241 MD5String(sChallenge
, sSignature
, sizeof(sSignature
));
243 sock_printf(tic
->sock
, "authenticate md5 %s\n", sSignature
);
245 /* Fetch the answer */
246 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
248 tic_Logout(tic
, NULL
);
253 tic_Logout(tic
, NULL
);
254 dolog(LOG_ERR
, "Response not accepted: %s.\n", &buf
[4]);
262 void tic_Logout(struct TIC_conf
*tic
, const char *quitmsg
)
264 /* A list of appropriate quit messages */
265 const char *byers
[] = {
266 /* Swiss-German form of "Ciao" */
269 /* Dutch for "they who are going, greet you" */
270 "Zij die gaan, groeten u",
271 "See you later alligator",
272 "A bitter thought, but I have to go",
274 /* Dutch for "see you later" */
276 "Thank you for the information",
277 "It was lovely talking to you again",
280 "I'll be back. Ha, you didn't know I was going to say that!",
281 "We will be the only two people left in the world, Yes--Adam and Evil!",
298 "The Trick Is To Keep Breathing",
301 "We just stopped breating",
302 "Even the spirits are afraid",
308 "The Last Thing I Need Is You",
309 "Every Time We Live Together",
310 "My Autumn's Done Come",
312 /* Infected Mushroom */
314 "None of this is real",
315 "Nothing Comes Easy",
318 /* Nine Inch Nails */
319 "Something I can never have",
320 "And All That Could Have Been...",
324 "Under the weeping moon",
325 "For Absent Friends",
331 /* Suicide Commando */
339 /* Within Temptation */
340 "This is not our farewell",
341 "Running Down That Hill",
344 "Schaltet den schmerz ab",
345 "Down where we belong",
348 /* Already disconnected? */
349 if (!tic
->sock
) return;
353 /* Stupid random quit messages, got to put some form of easteregg in it :) */
354 srand((unsigned)time(NULL
));
356 quitmsg
= (char *)byers
[rand()%(sizeof(byers
)/sizeof(char *))];
359 /* Send our bye bye */
360 sock_printf(tic
->sock
, "QUIT %s\n", quitmsg
);
363 sock_free(tic
->sock
);
367 struct TIC_sTunnel
*tic_ListTunnels(struct TIC_conf
*tic
)
369 char buf
[1024], buf2
[1024];
370 struct TIC_sTunnel
*start
= NULL
, *last
= NULL
, *tun
= NULL
;
373 /* Request a list of Tunnels */
374 sock_printf(tic
->sock
, "tunnel list\n");
376 /* Fetch the answer */
377 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
382 /* 201 (start of list) ? */
383 if (buf
[0] != '2' || buf
[1] != '0' || buf
[2] != '1')
385 dolog(LOG_ERR
, "Couldn't list tunnels: %s.\n", &buf
[4]);
389 /* Process all the lines */
390 while (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) != -1)
392 /* 202 (end of list) ? */
393 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2') break;
395 i
= countfields(buf
);
398 dolog(LOG_ERR
, "Wrong field format when listing tunnels\n");
402 /* Allocate a new struct */
403 tun
= (struct TIC_sTunnel
*)malloc(sizeof(*tun
));
406 dolog(LOG_ERR
, "Memory problem while listing tunnels\n");
409 memset(tun
, 0, sizeof(*tun
));
411 /* Copy the fields into the struct */
412 if (!copyfield(buf
, 1, buf2
, sizeof(buf2
))) break;
413 tun
->sId
= strdup(buf2
);
414 if (!copyfield(buf
, 2, buf2
, sizeof(buf2
))) break;
415 tun
->sIPv6
= strdup(buf2
);
416 if (!copyfield(buf
, 3, buf2
, sizeof(buf2
))) break;
417 tun
->sIPv4
= strdup(buf2
);
418 if (!copyfield(buf
, 4, buf2
, sizeof(buf2
))) break;
419 tun
->sPOPId
= strdup(buf2
);
421 /* Add it into the list */
434 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2')
439 /* Free the structure, it was broken anyway */
440 tic_Free_sTunnel(start
);
442 dolog(LOG_ERR
, "Tunnel list went wrong: %s\n", &buf
[4]);
446 struct TIC_sRoute
*tic_ListRoutes(struct TIC_conf
*tic
)
448 dolog(LOG_ERR
, "Not implemented - tic_ListRoutes(%x)\n", tic
);
452 struct TIC_sPOP
*tic_ListPOPs(struct TIC_conf
*tic
)
454 dolog(LOG_ERR
, "Not implemented - tic_ListPOPs(%x)\n", tic
);
458 struct pl_rule tunnel_rules
[] =
460 {"TunnelId", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sId
)},
461 {"Type", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sType
)},
462 {"IPv6 Endpoint", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sIPv6_Local
)},
463 {"IPv6 POP", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sIPv6_POP
)},
464 {"IPv6 PrefixLength", PLRT_INTEGER
, offsetof(struct TIC_Tunnel
, nIPv6_PrefixLength
)},
465 {"POP Id", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sPOP_Id
)},
466 {"IPv4 Endpoint", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sIPv4_Local
)},
467 {"IPv4 POP", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sIPv4_POP
)},
468 {"UserState", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sUserState
)},
469 {"AdminState", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sAdminState
)},
470 {"Password", PLRT_STRING
, offsetof(struct TIC_Tunnel
, sPassword
)},
471 {"Heartbeat_Interval", PLRT_INTEGER
, offsetof(struct TIC_Tunnel
, nHeartbeat_Interval
)},
472 {"Tunnel MTU", PLRT_INTEGER
, offsetof(struct TIC_Tunnel
, nMTU
)},
476 struct TIC_Tunnel
*tic_GetTunnel(struct TIC_conf
*tic
, const char *sId
)
479 struct TIC_Tunnel
*tun
;
482 sock_printf(tic
->sock
, "tunnel show %s\n", sId
);
484 /* Fetch the answer */
485 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
490 /* 201 (start of information) ? */
491 if (buf
[0] != '2' || buf
[1] != '0' || buf
[2] != '1')
493 dolog(LOG_ERR
, "Couldn't show tunnel %s: %s.\n", sId
, buf
);
497 /* Allocate a new struct */
498 tun
= (struct TIC_Tunnel
*)malloc(sizeof(*tun
));
501 dolog(LOG_ERR
, "Memory problem while getting tunnel %s\n", sId
);
504 memset(tun
, 0, sizeof(*tun
));
506 /* Gather the information */
507 while (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) != -1)
509 /* 202 (end of list) ? */
510 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2') break;
512 parseline(buf
, ": ", tunnel_rules
, tun
);
515 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2')
517 struct in6_addr ipv6_ll
, ipv6_local
;
520 /* Log that the fetch was succesful */
521 dolog(LOG_INFO
, "Succesfully retrieved tunnel information for %s\n", sId
);
524 * Some TUN/TAP devices don't have any
525 * link local addresses and we want multicast and MLD to work
526 * thus we invent one based on the following:
528 * ipv6_us = 2001:0db8:1234:5678: : : :0001
529 * ipv6_ll = fe80: : : :0db8:1234:5678:0001
531 * Thus we ignore the first 16bits, take the following 48 bits
532 * and then add the last 16bits.
534 * As we are not 100% sure that this LL is unique we clear that bit.
537 inet_pton(AF_INET6
, tun
->sIPv6_Local
, &ipv6_local
);
539 /* Link Local (fe80::/64) */
540 ipv6_ll
.s6_addr
[ 0] = 0xfe;
541 ipv6_ll
.s6_addr
[ 1] = 0x80;
542 ipv6_ll
.s6_addr
[ 2] = 0x00;
543 ipv6_ll
.s6_addr
[ 3] = 0x00;
544 ipv6_ll
.s6_addr
[ 4] = 0x00;
545 ipv6_ll
.s6_addr
[ 5] = 0x00;
546 ipv6_ll
.s6_addr
[ 6] = 0x00;
547 ipv6_ll
.s6_addr
[ 7] = 0x00;
548 ipv6_ll
.s6_addr
[ 8] = ipv6_local
.s6_addr
[ 2] & 0xfc; /* Clear the LL Unique Bit */
549 ipv6_ll
.s6_addr
[ 9] = ipv6_local
.s6_addr
[ 3];
550 ipv6_ll
.s6_addr
[10] = ipv6_local
.s6_addr
[ 4];
551 ipv6_ll
.s6_addr
[11] = ipv6_local
.s6_addr
[ 5];
552 ipv6_ll
.s6_addr
[12] = ipv6_local
.s6_addr
[ 6];
553 ipv6_ll
.s6_addr
[13] = ipv6_local
.s6_addr
[ 7];
554 ipv6_ll
.s6_addr
[14] = ipv6_local
.s6_addr
[14];
555 ipv6_ll
.s6_addr
[15] = ipv6_local
.s6_addr
[15];
557 inet_ntop(AF_INET6
, &ipv6_ll
, ll
, sizeof(ll
));
558 if (tun
->sIPv6_LinkLocal
) free(tun
->sIPv6_LinkLocal
);
559 tun
->sIPv6_LinkLocal
= strdup(ll
);
561 if ( strcmp(tun
->sType
, "ayiya") == 0 ||
562 strcmp(tun
->sType
, "l2tp") == 0)
564 tun
->uses_tundev
= 1;
566 dolog(LOG_ERR
, "This build doesn't support the Tun/TAP device and thus can't instantiate tunnels of type %s, please fix your OS and recompile\n", tun
->sType
);
567 tic_Free_Tunnel(tun
);
571 else tun
->uses_tundev
= 0;
573 /* Need to override the local IPv4 address? */
574 if (g_aiccu
->local_ipv4_override
)
576 dolog(LOG_INFO
, "Overriding Local IPv4 address from %s to %s\n", tun
->sIPv4_Local
, g_aiccu
->local_ipv4_override
);
577 free(tun
->sIPv4_Local
);
578 tun
->sIPv4_Local
= strdup(g_aiccu
->local_ipv4_override
);
584 /* Free the structure, it is broken anyway */
585 tic_Free_Tunnel(tun
);
587 dolog(LOG_ERR
, "Tunnel Get for %s went wrong: %s\n", sId
, buf
);
591 struct TIC_Route
*tic_GetRoute(struct TIC_conf
*tic
, const char *sId
)
593 dolog(LOG_ERR
, "Not implemented - tic_GetRoute(%x, \"%s\")\n", tic
, sId
);
597 struct pl_rule pop_rules
[] =
599 {"POPId", PLRT_STRING
, offsetof(struct TIC_POP
, sId
)},
600 {"City", PLRT_STRING
, offsetof(struct TIC_POP
, sCity
)},
601 {"Country", PLRT_STRING
, offsetof(struct TIC_POP
, sCountry
)},
602 {"IPv4", PLRT_STRING
, offsetof(struct TIC_POP
, sIPv4
)},
603 {"IPv6", PLRT_STRING
, offsetof(struct TIC_POP
, sIPv6
)},
605 {"ISP Short", PLRT_STRING
, offsetof(struct TIC_POP
, sISP_Short
)},
606 {"ISP Name", PLRT_STRING
, offsetof(struct TIC_POP
, sISP_Name
)},
607 {"ISP Website", PLRT_STRING
, offsetof(struct TIC_POP
, sISP_Website
)},
608 {"ISP ASN", PLRT_STRING
, offsetof(struct TIC_POP
, sISP_ASN
)},
609 {"ISP LIR", PLRT_STRING
, offsetof(struct TIC_POP
, sISP_LIR
)},
614 struct TIC_POP
*tic_GetPOP(struct TIC_conf
*tic
, const char *sId
)
620 sock_printf(tic
->sock
, "pop show %s\n", sId
);
622 /* Fetch the answer */
623 if (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) == -1)
628 /* 201 (start of info) ? */
629 if (buf
[0] != '2' || buf
[1] != '0' || buf
[2] != '1')
631 dolog(LOG_ERR
, "Couldn't show POP %s: %s.\n", sId
, buf
);
635 /* Allocate a new struct */
636 pop
= (struct TIC_POP
*)malloc(sizeof(*pop
));
639 dolog(LOG_ERR
, "Memory problem while getting POP\n");
642 memset(pop
, 0, sizeof(*pop
));
644 /* Gather the information */
645 while (sock_getline(tic
->sock
, tic_buf
, sizeof(tic_buf
), &tic_filled
, buf
, sizeof(buf
)) != -1)
647 /* 202 (end of list) ? */
648 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2') break;
650 parseline(buf
, ": ", pop_rules
, pop
);
653 if (buf
[0] == '2' && buf
[1] == '0' && buf
[2] == '2')
655 dolog(LOG_INFO
, "Succesfully retrieved POP information for %s\n", sId
);
659 /* Free the structure, it is broken anyway */
662 dolog(LOG_ERR
, "POP Get for %s went wrong: %s\n", sId
, buf
);
666 void tic_Free_sTunnel(struct TIC_sTunnel
*tun
)
668 struct TIC_sTunnel
*next
;
670 for (; tun
; tun
= next
)
673 if (tun
->sId
) free(tun
->sId
);
674 if (tun
->sIPv6
) free(tun
->sIPv6
);
675 if (tun
->sIPv4
) free(tun
->sIPv4
);
676 if (tun
->sPOPId
) free(tun
->sPOPId
);
681 void tic_Free_sRoute(struct TIC_sRoute
*rt
)
683 struct TIC_sRoute
*next
;
685 for (; rt
; rt
= next
)
688 if (rt
->sId
) free(rt
->sId
);
689 if (rt
->sTunnelId
) free(rt
->sTunnelId
);
690 if (rt
->sIPv6
) free(rt
->sIPv6
);
695 void tic_Free_sPOP(struct TIC_sPOP
*pop
)
697 struct TIC_sPOP
*next
;
699 for (; pop
; pop
= next
)
702 if (pop
->sId
) free(pop
->sId
);
707 void tic_Free_Tunnel(struct TIC_Tunnel
*tun
)
709 if (tun
->sId
) { free(tun
->sId
); tun
->sId
= NULL
; }
710 if (tun
->sType
) { free(tun
->sType
); tun
->sType
= NULL
; }
711 if (tun
->sPOP_Id
) { free(tun
->sPOP_Id
); tun
->sPOP_Id
= NULL
; }
712 if (tun
->sUserState
) { free(tun
->sUserState
); tun
->sUserState
= NULL
; }
713 if (tun
->sAdminState
) { free(tun
->sAdminState
); tun
->sAdminState
= NULL
; }
714 if (tun
->sPassword
) { free(tun
->sPassword
); tun
->sPassword
= NULL
; }
715 if (tun
->sIPv4_Local
) { free(tun
->sIPv4_Local
); tun
->sIPv4_Local
= NULL
; }
716 if (tun
->sIPv4_POP
) { free(tun
->sIPv4_POP
); tun
->sIPv4_POP
= NULL
; }
717 if (tun
->sIPv6_Local
) { free(tun
->sIPv6_Local
); tun
->sIPv6_Local
= NULL
; }
718 if (tun
->sIPv6_POP
) { free(tun
->sIPv6_POP
); tun
->sIPv6_POP
= NULL
; }
723 void tic_Free_Route(struct TIC_Route
*rt
)
725 if (rt
->sId
) free(rt
->sId
);
726 if (rt
->sTunnelId
) free(rt
->sTunnelId
);
730 void tic_Free_POP(struct TIC_POP
*pop
)
732 if (pop
->sId
) free(pop
->sId
);
733 if (pop
->sCity
) free(pop
->sCity
);
734 if (pop
->sCountry
) free(pop
->sCountry
);
735 if (pop
->sIPv4
) free(pop
->sIPv4
);
736 if (pop
->sIPv6
) free(pop
->sIPv6
);
737 if (pop
->sISP_Short
) free(pop
->sISP_Short
);
738 if (pop
->sISP_Name
) free(pop
->sISP_Name
);
739 if (pop
->sISP_Website
) free(pop
->sISP_Website
);
740 if (pop
->sISP_ASN
) free(pop
->sISP_ASN
);
741 if (pop
->sISP_LIR
) free(pop
->sISP_LIR
);