Revert "Added upstream changelog"
[aiccu.git] / common / tic.c
blobe0d70fefe36579c112cac2903ef32d293647a037
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 ***********************************************************
8 $Author: jeroen $
9 $Id: tic.c,v 1.17 2007-01-11 13:41:31 jeroen Exp $
10 $Date: 2007-01-11 13:41:31 $
11 **********************************************************/
13 #include "common.h"
14 #include "aiccu.h"
15 #include "tic.h"
17 /* Specific includes only used here */
18 #ifndef _WIN32
19 #include <sys/utsname.h>
20 #endif
22 /* getline vars */
23 char tic_buf[2048];
24 unsigned int tic_filled;
26 /*
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 */
33 #define CLOCK_OFF 120
34 int i;
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 */
50 if (i < 0) i = -i;
52 /* Compare the clock offset */
53 if (i > CLOCK_OFF)
55 /* Time is off */
56 return i;
59 /* Time is in the allowed range */
60 return 0;
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];
66 int i;
67 #ifndef _WIN32
68 struct utsname uts_name;
69 #else
70 OSVERSIONINFO osv;
71 OSVERSIONINFOEX osvEx;
72 char *platform = NULL;
73 char version[100];
74 #endif
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);
80 if (!tic->sock)
82 dolog(LOG_ERR, "Couldn't connect to the TIC server %s\n", server);
83 return false;
86 /* Fetch the welcome */
87 if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
89 return false;
91 if (buf[0] != '2')
93 dolog(LOG_ERR, "TIC Server is currently not available\n");
94 return false;
97 /* Send our client identification */
98 #ifndef _WIN32
99 uname(&uts_name);
100 sock_printf(tic->sock, "client TIC/%s %s/%s %s/%s\n",
101 TIC_VERSION,
102 TIC_CLIENT_NAME, TIC_CLIENT_VERSION,
103 uts_name.sysname, uts_name.release);
104 #else
105 osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
106 osvEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
108 if (!GetVersionEx(&osv))
110 platform = "Windows";
111 snprintf(version, sizeof(version), "%s", "Unknown");
113 else
116 platform = (osv.dwPlatformId == VER_PLATFORM_WIN32s) ? "Win32s" :
117 ((osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ? "Win9x" :
118 ((osv.dwPlatformId == VER_PLATFORM_WIN32_NT) ? "WinNT" :
119 "Windows"));
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);
134 else
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",
142 TIC_VERSION,
143 TIC_CLIENT_NAME, TIC_CLIENT_VERSION,
144 platform, version);
145 #endif
147 /* Fetch the answer */
148 if (sock_getline(tic->sock, tic_buf, sizeof(tic_buf), &tic_filled, buf, sizeof(buf)) == -1)
150 return false;
152 if (buf[0] != '2')
154 dolog(LOG_ERR, "Couldn't pass client information: %s.\n", &buf[4]);
155 return false;
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)
164 return false;
166 if (buf[0] != '2')
168 dolog(LOG_ERR, "Time not available? %s\n", &buf[4]);
169 return false;
172 /* Check if the time is correct */
173 i = tic_checktime(atoi(&buf[4]));
174 if (i != 0)
176 char quitmsg[100];
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);
180 return false;
183 #ifdef AICCU_GNUTLS
184 /* Upgrade to TLS */
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)
190 return false;
192 if (buf[0] == '2')
194 /* Go to TLS mode */
195 if (!sock_gotls(tic->sock)) return false;
197 else
199 if (g_aiccu->requiretls)
201 dolog(LOG_ERR, "TIC Server does not support TLS and TLS is required\n");
202 return false;
204 if (g_aiccu->verbose) dolog(LOG_WARNING, "TIC Server does not support TLS but TLS is not required, continuing\n");
207 #endif
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)
215 return false;
217 if (buf[0] != '2')
219 dolog(LOG_ERR, "Username not accepted: %s.\n", &buf[4]);
220 return false;
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)
229 return false;
231 if (buf[0] != '2')
233 dolog(LOG_ERR, "Challenge not correct: %s.\n", &buf[4]);
234 return false;
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);
249 return false;
251 if (buf[0] != '2')
253 tic_Logout(tic, NULL);
254 dolog(LOG_ERR, "Response not accepted: %s.\n", &buf[4]);
255 return false;
258 /* Connect OK */
259 return true;
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" */
267 "Tschau!",
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" */
275 "Ajuuu paraplu",
276 "Thank you for the information",
277 "It was lovely talking to you again",
278 "Tschussss...",
279 "Aufwiedersehen",
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!",
283 /* Blutengel */
284 "Stranded",
285 "Die With You",
286 "The End Of Love",
288 /* Chamber */
289 "In My Garden",
290 "Set Me Free",
292 /* Faithless */
293 "Don't Leave",
294 "Insomnia",
295 "Why Go",
297 /* Garbage */
298 "The Trick Is To Keep Breathing",
300 /* The Gathering */
301 "We just stopped breating",
302 "Even the spirits are afraid",
304 /* Goldfrapp */
305 "Deer Stop",
307 /* Hooverphonic */
308 "The Last Thing I Need Is You",
309 "Every Time We Live Together",
310 "My Autumn's Done Come",
312 /* Infected Mushroom */
313 "Never Ever Land",
314 "None of this is real",
315 "Nothing Comes Easy",
316 "Illuminaughty",
318 /* Nine Inch Nails */
319 "Something I can never have",
320 "And All That Could Have Been...",
321 "That's what I get",
323 /* Opeth */
324 "Under the weeping moon",
325 "For Absent Friends",
327 /* Portishead */
328 "It Could Be Sweet",
329 "Half Day Closing",
331 /* Suicide Commando */
332 "Better Off Dead",
334 /* VNV Nation */
335 "Solitary",
336 "Forsaken",
337 "Holding On",
339 /* Within Temptation */
340 "This is not our farewell",
341 "Running Down That Hill",
343 /* Wumpscut */
344 "Schaltet den schmerz ab",
345 "Down where we belong",
348 /* Already disconnected? */
349 if (!tic->sock) return;
351 if (!quitmsg)
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);
362 /* Disconnect */
363 sock_free(tic->sock);
364 tic->sock = NULL;
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;
371 int i;
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)
379 return NULL;
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]);
386 return NULL;
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);
396 if (i != 4)
398 dolog(LOG_ERR, "Wrong field format when listing tunnels\n");
399 break;
402 /* Allocate a new struct */
403 tun = (struct TIC_sTunnel *)malloc(sizeof(*tun));
404 if (!tun)
406 dolog(LOG_ERR, "Memory problem while listing tunnels\n");
407 break;
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 */
422 if (last)
424 last->next = tun;
425 last = tun;
427 else
429 start = last = tun;
433 /* All went okay? */
434 if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
436 return start;
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]);
443 return NULL;
446 struct TIC_sRoute *tic_ListRoutes(struct TIC_conf *tic)
448 dolog(LOG_ERR, "Not implemented - tic_ListRoutes(%x)\n", tic);
449 return NULL;
452 struct TIC_sPOP *tic_ListPOPs(struct TIC_conf *tic)
454 dolog(LOG_ERR, "Not implemented - tic_ListPOPs(%x)\n", tic);
455 return NULL;
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)},
473 {NULL, PLRT_END, 0},
476 struct TIC_Tunnel *tic_GetTunnel(struct TIC_conf *tic, const char *sId)
478 char buf[1024];
479 struct TIC_Tunnel *tun;
481 /* Get a Tunnel */
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)
487 return NULL;
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);
494 return NULL;
497 /* Allocate a new struct */
498 tun = (struct TIC_Tunnel *)malloc(sizeof(*tun));
499 if (!tun)
501 dolog(LOG_ERR, "Memory problem while getting tunnel %s\n", sId);
502 return NULL;
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);
514 /* All went okay? */
515 if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
517 struct in6_addr ipv6_ll, ipv6_local;
518 char ll[100];
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;
565 #ifdef NO_IFHEAD
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);
568 return NULL;
569 #endif
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);
581 return tun;
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);
588 return NULL;
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);
594 return NULL;
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)},
611 {NULL, PLRT_END, 0},
614 struct TIC_POP *tic_GetPOP(struct TIC_conf *tic, const char *sId)
616 char buf[1024];
617 struct TIC_POP *pop;
619 /* Get a Tunnel */
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)
625 return NULL;
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);
632 return NULL;
635 /* Allocate a new struct */
636 pop = (struct TIC_POP *)malloc(sizeof(*pop));
637 if (!pop)
639 dolog(LOG_ERR, "Memory problem while getting POP\n");
640 return NULL;
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);
652 /* All went okay? */
653 if (buf[0] == '2' && buf[1] == '0' && buf[2] == '2')
655 dolog(LOG_INFO, "Succesfully retrieved POP information for %s\n", sId);
656 return pop;
659 /* Free the structure, it is broken anyway */
660 tic_Free_POP(pop);
662 dolog(LOG_ERR, "POP Get for %s went wrong: %s\n", sId, buf);
663 return NULL;
666 void tic_Free_sTunnel(struct TIC_sTunnel *tun)
668 struct TIC_sTunnel *next;
670 for (; tun; tun = next)
672 next = 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);
677 free(tun);
681 void tic_Free_sRoute(struct TIC_sRoute *rt)
683 struct TIC_sRoute *next;
685 for (; rt; rt = next)
687 next = rt->next;
688 if (rt->sId) free(rt->sId);
689 if (rt->sTunnelId) free(rt->sTunnelId);
690 if (rt->sIPv6) free(rt->sIPv6);
691 free(rt);
695 void tic_Free_sPOP(struct TIC_sPOP *pop)
697 struct TIC_sPOP *next;
699 for (; pop; pop = next)
701 next = pop->next;
702 if (pop->sId) free(pop->sId);
703 free(pop);
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; }
719 free(tun);
720 tun = NULL;
723 void tic_Free_Route(struct TIC_Route *rt)
725 if (rt->sId) free(rt->sId);
726 if (rt->sTunnelId) free(rt->sTunnelId);
727 free(rt);
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);
743 free(pop);