// End the tracking of the routing table void RouteTrackingStop(SESSION *s, ROUTE_TRACKING *t) { ROUTE_ENTRY *e; ROUTE_TABLE *table; IP dns_ip; bool network_has_changed = false; bool do_not_delete_routing_entry = false; // Validate arguments if (s == NULL || t == NULL) { return; } Zero(&dns_ip, sizeof(dns_ip)); // Remove the default gateway added by the virtual LAN card if (MsIsVista() == false) { if (t->DefaultGatewayByVLan != NULL) { Debug("Default Gateway by VLAN was deleted.\n"); DeleteRouteEntry(t->DefaultGatewayByVLan); } if (t->VistaOldDefaultGatewayByVLan != NULL) { FreeRouteEntry(t->VistaOldDefaultGatewayByVLan); } } if (t->DefaultGatewayByVLan != NULL) { FreeRouteEntry(t->DefaultGatewayByVLan); t->DefaultGatewayByVLan = NULL; } if (t->VistaDefaultGateway1 != NULL) { Debug("Vista PPP Fix Route Table Deleted.\n"); DeleteRouteEntry(t->VistaDefaultGateway1); FreeRouteEntry(t->VistaDefaultGateway1); DeleteRouteEntry(t->VistaDefaultGateway2); FreeRouteEntry(t->VistaDefaultGateway2); } if (MsIsNt() == false) { // Only in the case of Windows 9x, release the DHCP address of the virtual LAN card Win32ReleaseDhcp9x(t->VLanInterfaceId, false); } // Clear the DNS cache Win32FlushDnsCache(); if (s->Cedar->Client != NULL && s->Account != NULL) { UINT i; ACCOUNT *a; for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++) { a = LIST_DATA(s->Cedar->Client->AccountList, i); Lock(a->lock); { SESSION *sess = a->ClientSession; if (sess != NULL && sess != s) { VLAN *v = sess->PacketAdapter->Param; if (v != NULL) { ROUTE_TRACKING *tr = v->RouteState; if (tr != NULL) { if (Cmp(tr->RouteToServer, t->RouteToServer, sizeof(ROUTE_ENTRY)) == 0) { do_not_delete_routing_entry = true; } } } } } Unlock(a->lock); } Lock(s->Account->lock); } if (do_not_delete_routing_entry == false) { // Delete the route that is added firstly if (t->RouteToServerAlreadyExists == false) { DeleteRouteEntry(t->RouteToServer); } DeleteRouteEntry(t->RouteToDefaultDns); DeleteRouteEntry(t->RouteToNatTServer); DeleteRouteEntry(t->RouteToRealServerGlobal); } FreeRouteEntry(t->RouteToDefaultDns); FreeRouteEntry(t->RouteToServer); FreeRouteEntry(t->RouteToEight); FreeRouteEntry(t->RouteToNatTServer); FreeRouteEntry(t->RouteToRealServerGlobal); t->RouteToDefaultDns = t->RouteToServer = t->RouteToEight = t->RouteToNatTServer = t->RouteToRealServerGlobal = NULL; if (s->Cedar->Client != NULL && s->Account != NULL) { Unlock(s->Account->lock); } #if 0 // Get the current DNS server if (GetDefaultDns(&dns_ip)) { if (IPToUINT(&t->OldDnsServer) != 0) { if (IPToUINT(&t->OldDnsServer) != IPToUINT(&dns_ip)) { char s1[MAX_SIZE], s2[MAX_SIZE]; network_has_changed = true; IPToStr(s1, sizeof(s1), &t->OldDnsServer); IPToStr(s2, sizeof(s2), &dns_ip); Debug("Old Dns: %s, New Dns: %s\n", s1, s2); } } } if (network_has_changed == false) { Debug("Network: not changed.\n"); } else { Debug("Network: Changed.\n"); } #endif // Get the current routing table table = GetRouteTable(); // Restore the routing table which has been removed so far while (e = GetNext(t->DeletedDefaultGateway)) { bool restore = true; UINT i; // If the restoring routing entry is a default gateway and // the existing routing table contains another default gateway // on the interface, give up restoring the entry if (IPToUINT(&e->DestIP) == 0 && IPToUINT(&e->DestMask) == 0) { for (i = 0;i < table->NumEntry;i++) { ROUTE_ENTRY *r = table->Entry[i]; if (IPToUINT(&r->DestIP) == 0 && IPToUINT(&r->DestMask) == 0) { if (r->InterfaceID == e->InterfaceID) { restore = false; } } } if (network_has_changed) { restore = false; } } if (restore) { // Routing table restoration AddRouteEntry(e); } // Memory release FreeRouteEntry(e); } // Release FreeRouteTable(table); ReleaseQueue(t->DeletedDefaultGateway); FreeRouteChange(t->RouteChange); Free(t); }
// DDNS client thread void DCThread(THREAD *thread, void *param) { DDNS_CLIENT *c; INTERRUPT_MANAGER *interrput; UINT last_ip_hash = 0; void *route_change_poller = NULL; bool last_time_ip_changed = false; UINT last_azure_ddns_trigger_int = 0; UINT last_vgs_ddns_trigger_int = 0; UINT n; INTERNET_SETTING last_t; // Validate arguments if (thread == NULL || param == NULL) { return; } c = (DDNS_CLIENT *)param; interrput = NewInterruptManager(); route_change_poller = NewRouteChange(); IsRouteChanged(route_change_poller); Zero(&last_t, sizeof(last_t)); n = 0; while (c->Halt == false) { UINT ip_hash = GetHostIPAddressHash32(); UINT interval; UINT64 now = Tick64(); bool ip_changed = false; bool azure_client_triggered = false; bool internet_setting_changed = false; bool vgs_server_triggered = false; if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL) { if (c->Cedar->Server->AzureClient->DDnsTriggerInt != last_azure_ddns_trigger_int) { azure_client_triggered = true; last_azure_ddns_trigger_int = c->Cedar->Server->AzureClient->DDnsTriggerInt; last_time_ip_changed = false; Debug("DDNS Thread Triggered by AzureClient.\n"); } } if (Cmp(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING)) != 0) { Copy(&last_t, &c->InternetSetting, sizeof(INTERNET_SETTING)); internet_setting_changed = true; last_time_ip_changed = false; } if (ip_hash != last_ip_hash) { last_time_ip_changed = false; Debug("DDNS Thread Triggered by IP Hash Changed.\n"); } if ((ip_hash != last_ip_hash) || (IsRouteChanged(route_change_poller)) || azure_client_triggered || internet_setting_changed || vgs_server_triggered) { if (last_time_ip_changed == false) { // Call all getting functions from the beginning if the routing // table or the IP address of this host has changed c->NextRegisterTick_IPv4 = 0; c->NextRegisterTick_IPv6 = 0; c->NextGetMyIpTick_IPv4 = 0; c->NextGetMyIpTick_IPv6 = 0; last_ip_hash = ip_hash; last_time_ip_changed = true; ip_changed = true; Debug("DDNS Internet Condition Changed.\n"); } } else { last_time_ip_changed = false; } if ((n++) >= 1) { // Self IPv4 address acquisition if (c->NextGetMyIpTick_IPv4 == 0 || now >= c->NextGetMyIpTick_IPv4) { UINT next_interval; char ip[MAX_SIZE]; Zero(ip, sizeof(ip)); c->Err_IPv4_GetMyIp = DCGetMyIp(c, false, ip, sizeof(ip), NULL); if (c->Err_IPv4_GetMyIp == ERR_NO_ERROR) { if (StrCmpi(c->LastMyIPv4, ip) != 0) { ip_changed = true; StrCpy(c->LastMyIPv4, sizeof(c->LastMyIPv4), ip); } next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX); } else { if (IsEmptyStr(c->LastMyIPv4) == false) { ip_changed = true; } Zero(c->LastMyIPv4, sizeof(c->LastMyIPv4)); next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX); } c->NextGetMyIpTick_IPv4 = Tick64() + (UINT64)next_interval; AddInterrupt(interrput, c->NextGetMyIpTick_IPv4); } // Self IPv6 address acquisition if (c->NextGetMyIpTick_IPv6 == 0 || now >= c->NextGetMyIpTick_IPv6) { UINT next_interval; char ip[MAX_SIZE]; Zero(ip, sizeof(ip)); c->Err_IPv6_GetMyIp = DCGetMyIp(c, true, ip, sizeof(ip), NULL); if (c->Err_IPv6_GetMyIp == ERR_NO_ERROR) { if (StrCmpi(c->LastMyIPv6, ip) != 0) { ip_changed = true; StrCpy(c->LastMyIPv6, sizeof(c->LastMyIPv6), ip); } next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_OK_MIN, DDNS_GETMYIP_INTERVAL_OK_MAX); } else { if (IsEmptyStr(c->LastMyIPv6) == false) { ip_changed = true; } Zero(c->LastMyIPv6, sizeof(c->LastMyIPv6)); next_interval = GenRandInterval(DDNS_GETMYIP_INTERVAL_NG_MIN, DDNS_GETMYIP_INTERVAL_NG_MAX); } c->NextGetMyIpTick_IPv6 = Tick64() + (UINT64)next_interval; AddInterrupt(interrput, c->NextGetMyIpTick_IPv6); } } if (ip_changed) { c->NextRegisterTick_IPv4 = 0; c->NextRegisterTick_IPv6 = 0; } // IPv4 host registration if (c->NextRegisterTick_IPv4 == 0 || now >= c->NextRegisterTick_IPv4) { UINT next_interval; c->Err_IPv4 = DCRegister(c, false, NULL, NULL); if (c->Err_IPv4 == ERR_NO_ERROR) { next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX); } else { next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX); } //next_interval = 0; c->NextRegisterTick_IPv4 = Tick64() + (UINT64)next_interval; if (true) { DDNS_CLIENT_STATUS st; DCGetStatus(c, &st); SiApplyAzureConfig(c->Cedar->Server, &st); } AddInterrupt(interrput, c->NextRegisterTick_IPv4); } if (c->Halt) { break; } // IPv6 host registration if (c->NextRegisterTick_IPv6 == 0 || now >= c->NextRegisterTick_IPv6) { UINT next_interval; c->Err_IPv6 = DCRegister(c, true, NULL, NULL); if (c->Err_IPv6 == ERR_NO_ERROR) { next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_OK_MIN, DDNS_REGISTER_INTERVAL_OK_MAX); } else { next_interval = GenRandInterval(DDNS_REGISTER_INTERVAL_NG_MIN, DDNS_REGISTER_INTERVAL_NG_MAX); } c->NextRegisterTick_IPv6 = Tick64() + (UINT64)next_interval; if (true) { DDNS_CLIENT_STATUS st; DCGetStatus(c, &st); SiApplyAzureConfig(c->Cedar->Server, &st); } AddInterrupt(interrput, c->NextRegisterTick_IPv6); } interval = GetNextIntervalForInterrupt(interrput); interval = MIN(interval, 1234); if (n == 1) { interval = MIN(interval, 0); } if (c->Halt) { break; } if (c->KeyChanged) { c->KeyChanged = false; c->NextRegisterTick_IPv4 = c->NextRegisterTick_IPv6 = 0; interval = 0; } if (last_time_ip_changed) { if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL) { c->Cedar->Server->AzureClient->IpStatusRevision++; } } Wait(c->Event, interval); } FreeRouteChange(route_change_poller); FreeInterruptManager(interrput); }