// Release of the parameter value list void FreeParamValueList(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { PARAM_VALUE *v = LIST_DATA(o, i); Free(v->StrValue); Free(v->UniStrValue); Free(v->Name); Free(v); } ReleaseList(o); }
// Get the Attibute with the specified ID from SSTP packet SSTP_ATTRIBUTE *SstpFindAttribute(SSTP_PACKET *p, UCHAR attribute_id) { UINT i; // Validate arguments if (p == NULL) { return NULL; } for (i = 0;i < LIST_NUM(p->AttibuteList);i++) { SSTP_ATTRIBUTE *a = LIST_DATA(p->AttibuteList, i); if (a->AttributeId == attribute_id) { return a; } } return NULL; }
// Release the language list void FreeLangList(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { LANGLIST *e = LIST_DATA(o, i); FreeStrList(e->LangList); ReleaseIntList(e->LcidList); Free(e); } ReleaseList(o); }
// Choose the language from the ID LANGLIST *GetLangById(LIST *o, UINT id) { UINT i; // Validate arguments if (o == NULL) { return NULL; } for (i = 0;i < LIST_NUM(o);i++) { LANGLIST *e = LIST_DATA(o, i); if (e->Id == id) { return e; } } return NULL; }
// Get a secure device SECURE_DEVICE *GetSecureDevice(UINT id) { UINT i; if (id == 0) { return NULL; } for (i = 0;i < LIST_NUM(SecureDeviceList);i++) { SECURE_DEVICE *dev = LIST_DATA(SecureDeviceList, i); if (dev->Id == id) { return dev; } } return NULL; }
// Initialize all Layer-3 interfaces void L3InitAllInterfaces(L3SW *s) { UINT i; // Validate arguments if (s == NULL) { return; } for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); THREAD *t; L3InitInterface(f); f->Hub = GetHub(s->Cedar, f->HubName); t = NewThread(L3IfThread, f); WaitThreadInit(t); ReleaseThread(t); } }
// Release the INI void FreeIni(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { INI_ENTRY *e = LIST_DATA(o, i); Free(e->Key); Free(e->Value); Free(e->UnicodeValue); Free(e); } ReleaseList(o); }
// Get the number of unestablished connections UINT GetUnestablishedConnections(CEDAR *cedar) { UINT i, ret; // Validate arguments if (cedar == NULL) { return 0; } ret = 0; LockList(cedar->ConnectionList); { for (i = 0;i < LIST_NUM(cedar->ConnectionList);i++) { CONNECTION *c = LIST_DATA(cedar->ConnectionList, i); switch (c->Type) { case CONNECTION_TYPE_CLIENT: case CONNECTION_TYPE_INIT: case CONNECTION_TYPE_LOGIN: case CONNECTION_TYPE_ADDITIONAL: switch (c->Status) { case CONNECTION_STATUS_ACCEPTED: case CONNECTION_STATUS_NEGOTIATION: case CONNECTION_STATUS_USERAUTH: ret++; break; } break; } } } UnlockList(cedar->ConnectionList); return ret + Count(cedar->AcceptingSockets); }
void CleanupEtherIPServer(ETHERIP_SERVER *s) { UINT i; // Validate arguments if (s == NULL) { return; } EtherIPLog(s, "LE_STOP"); if (s->IpcConnectThread != NULL) { ReleaseThread(s->IpcConnectThread); } if (s->Ipc != NULL) { FreeIPC(s->Ipc); } for (i = 0;i < LIST_NUM(s->SendPacketList);i++) { BLOCK *b = LIST_DATA(s->SendPacketList, i); FreeBlock(b); } ReleaseList(s->SendPacketList); ReleaseSockEvent(s->SockEvent); ReleaseCedar(s->Cedar); DeleteLock(s->Lock); Free(s); }
// Delete the group bool AcDeleteGroup(HUB *h, char *name) { USERGROUP *g; UINT i; // Validate arguments if (h == NULL || name == NULL) { return false; } g = AcGetGroup(h, name); if (g == NULL) { return false; } if (Delete(h->HubDb->GroupList, g)) { ReleaseGroup(g); } for (i = 0;i < LIST_NUM(h->HubDb->UserList);i++) { USER *u = LIST_DATA(h->HubDb->UserList, i); Lock(u->lock); { if (u->Group == g) { JoinUserToGroup(u, NULL); } } Unlock(u->lock); } ReleaseGroup(g); return true; }
// Add new user in the hub bool AcAddUser(HUB *h, USER *u) { // Validate arguments if (h == NULL || u == NULL || NO_ACCOUNT_DB(h)) { return false; } if (LIST_NUM(h->HubDb->UserList) >= MAX_USERS) { return false; } if (AcIsUser(h, u->Name) != false) { return false; } Insert(h->HubDb->UserList, u); AddRef(u->ref); return true; }
// Add new group to the hub bool AcAddGroup(HUB *h, USERGROUP *g) { // Validate arguments if (h == NULL || g == NULL || NO_ACCOUNT_DB(h)) { return false; } if (LIST_NUM(h->HubDb->GroupList) >= MAX_GROUPS) { return false; } if (AcIsGroup(h, g->Name) != false) { return false; } Insert(h->HubDb->GroupList, g); AddRef(g->ref); return true; }
// Start all links void StartAllLink(HUB *h) { // Validate arguments if (h == NULL) { return; } LockList(h->LinkList); { UINT i; for (i = 0;i < LIST_NUM(h->LinkList);i++) { LINK *k = (LINK *)LIST_DATA(h->LinkList, i); if (k->Offline == false) { StartLink(k); } } } UnlockList(h->LinkList); }
// Folder enumeration void CfgEnumFolder(FOLDER *f, ENUM_FOLDER proc, void *param) { UINT i; // Validate arguments if (f == NULL || proc == NULL) { return; } for (i = 0;i < LIST_NUM(f->Folders);i++) { FOLDER *ff = LIST_DATA(f->Folders, i); if (proc(ff, param) == false) { break; } if ((i % 100) == 99) { YieldCpu(); } } }
// Write the configuration to the folder void ElSaveConfigToFolder(EL *e, FOLDER *root) { UINT i; FOLDER *devices; // Validate arguments if (e == NULL || root == NULL) { return; } CfgAddInt64(root, "AutoDeleteCheckDiskFreeSpaceMin", e->AutoDeleteCheckDiskFreeSpaceMin); CfgAddInt(root, "AdminPort", e->Port); CfgAddByte(root, "AdminPassword", e->HashedPassword, sizeof(e->HashedPassword)); if (ELOG_IS_BETA == false) { EiWriteLicenseManager(CfgCreateFolder(root, "LicenseManager"), e); } devices = CfgCreateFolder(root,"Devices"); LockList(e->DeviceList); { for (i = 0;i < LIST_NUM(e->DeviceList);i++) { FOLDER *f; EL_DEVICE *d = LIST_DATA(e->DeviceList, i); f = CfgCreateFolder(devices, d->DeviceName); SiWriteHubLogCfgEx(f, &d->LogSetting, true); CfgAddBool(f, "NoPromiscusMode", d->NoPromiscus); } } UnlockList(e->DeviceList); }
// Search for the data entry WPC_ENTRY *WpcFindDataEntry(LIST *o, char *name) { UINT i; char name_str[WPC_DATA_ENTRY_SIZE]; // Validate arguments if (o == NULL || name == NULL) { return NULL; } WpcFillEntryName(name_str, name); for (i = 0;i < LIST_NUM(o);i++) { WPC_ENTRY *e = LIST_DATA(o, i); if (Cmp(e->EntryName, name_str, WPC_DATA_ENTRY_SIZE) == 0) { return e; } } return NULL; }
// Search for the best language from LCID LANGLIST *GetBestLangByLcid(LIST *o, UINT lcid) { LANGLIST *ret; UINT i; // Validate arguments if (o == NULL) { return NULL; } for (i = 0;i < LIST_NUM(o);i++) { LANGLIST *e = LIST_DATA(o, i); if (IsIntInList(e->LcidList, lcid)) { return e; } } ret = GetBestLangByName(o, "en"); return ret; }
// Remove the object which have the specified name from the cache void DeleteSecObjFromEnumCache(SECURE *sec, char *name, UINT type) { UINT i; // Validate arguments if (sec == NULL || name == NULL || sec->EnumCache == NULL) { return; } for (i = 0;i < LIST_NUM(sec->EnumCache);i++) { SEC_OBJ *obj = LIST_DATA(sec->EnumCache, i); if (StrCmpi(obj->Name, name) == 0) { if (obj->Type == type) { Delete(sec->EnumCache, obj); FreeSecObject(obj); break; } } } }
// Get in-process listener socket in Cedar SOCK *GetInProcListeningSock(CEDAR *c) { SOCK *s = NULL; // Validate arguments if (c == NULL) { return NULL; } LockList(c->ListenerList); { UINT i; for (i = 0;i < LIST_NUM(c->ListenerList);i++) { LISTENER *r = LIST_DATA(c->ListenerList, i); if (r->Protocol == LISTENER_INPROC) { Lock(r->lock); { s = r->Sock; if (s != NULL) { AddRef(s->ref); } } Unlock(r->lock); break; } } } UnlockList(c->ListenerList); return s; }
// Cut out the token from string (Ignore blanks between delimiters) TOKEN_LIST *ParseTokenWithoutNullStr(char *str, char *split_chars) { LIST *o; UINT i, len; bool last_flag; BUF *b; char zero = 0; TOKEN_LIST *t; // Validate arguments if (str == NULL) { return NullToken(); } if (split_chars == NULL) { split_chars = DefaultTokenSplitChars(); } b = NewBuf(); o = NewListFast(NULL); len = StrLen(str); last_flag = false; for (i = 0;i < (len + 1);i++) { char c = str[i]; bool flag = IsCharInStr(split_chars, c); if (c == '\0') { flag = true; } if (flag == false) { WriteBuf(b, &c, sizeof(char)); } else { if (last_flag == false) { WriteBuf(b, &zero, sizeof(char)); if ((StrLen((char *)b->Buf)) != 0) { Insert(o, CopyStr((char *)b->Buf)); } ClearBuf(b); } } last_flag = flag; } t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < t->NumTokens;i++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); FreeBuf(b); return t; }
// Parse the command line TOKEN_LIST *ParseCmdLine(char *str) { TOKEN_LIST *t; LIST *o; UINT i, len, wp, mode; char c; char *tmp; bool ignore_space = false; // Validate arguments if (str == NULL) { // There is no token return NullToken(); } o = NewListFast(NULL); tmp = Malloc(StrSize(str) + 32); wp = 0; mode = 0; len = StrLen(str); for (i = 0;i < len;i++) { c = str[i]; switch (mode) { case 0: // Mode to discover the next token if (c == ' ' || c == '\t') { // Advance to the next character } else { // Start of the token if (c == '\"') { if (str[i + 1] == '\"') { // Regard "" as a single " tmp[wp++] = '\"'; i++; } else { // Enable the ignoring space flag for a single " ignore_space = true; } } else { tmp[wp++] = c; } mode = 1; } break; case 1: if (ignore_space == false && (c == ' ' || c == '\t')) { // End of the token tmp[wp++] = 0; wp = 0; Insert(o, CopyStr(tmp)); mode = 0; } else { if (c == '\"') { if (str[i + 1] == '\"') { // Regard "" as a single " tmp[wp++] = L'\"'; i++; } else { if (ignore_space == false) { // Enable the ignoring space flag for a single " ignore_space = true; } else { // Disable the space ignore flag ignore_space = false; } } } else { tmp[wp++] = c; } } break; } } if (wp != 0) { tmp[wp++] = 0; Insert(o, CopyStr(tmp)); } Free(tmp); t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < t->NumTokens;i++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); return t; }
// 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); }
// Start tracking of the routing table void RouteTrackingStart(SESSION *s) { VLAN *v; ROUTE_TRACKING *t; UINT if_id = 0; ROUTE_ENTRY *e; ROUTE_ENTRY *dns = NULL; ROUTE_ENTRY *route_to_real_server_global = NULL; char tmp[64]; UINT exclude_if_id = 0; bool already_exists = false; bool already_exists_by_other_account = false; IP eight; // Validate arguments if (s == NULL) { return; } v = (VLAN *)s->PacketAdapter->Param; if (v->RouteState != NULL) { return; } // Get the interface ID of the virtual LAN card if_id = GetInstanceId(v->InstanceName); Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id); if (MsIsVista()) { // The routing table by the virtual LAN card body should be // excluded explicitly in Windows Vista exclude_if_id = if_id; } // Get the route to the server e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id); if (e == NULL) { // Acquisition failure Debug("Failed to get GetBestRouteEntry().\n"); return; } IPToStr(tmp, sizeof(tmp), &e->GatewayIP); Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp); // Add a route if (MsIsVista()) { e->Metric = e->OldIfMetric; } if (AddRouteEntryEx(e, &already_exists) == false) { FreeRouteEntry(e); e = NULL; } Debug("already_exists: %u\n", already_exists); if (already_exists) { 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 && e != NULL) { if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0) { already_exists_by_other_account = true; } } } } } Unlock(a->lock); } } if (already_exists_by_other_account) { Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account); already_exists = false; } } // Get the routing table to the DNS server // (If the DNS server is this PC itself, there's no need to get) if (IsZeroIP(&s->DefaultDns) == false) { if (IsMyIPAddress(&s->DefaultDns) == false) { dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id); if (dns == NULL) { // Getting failure Debug("Failed to get GetBestRouteEntry DNS.\n"); } else { // Add a route if (MsIsVista()) { dns->Metric = dns->OldIfMetric; if (AddRouteEntry(dns) == false) { FreeRouteEntry(dns); dns = NULL; } } } } } if (s->IsAzureSession && IsZeroIP(&s->AzureRealServerGlobalIp) == false) { // Add also a static route to the real server in the case of via VPN Azure if (IsMyIPAddress(&s->AzureRealServerGlobalIp) == false) { route_to_real_server_global = GetBestRouteEntryEx(&s->AzureRealServerGlobalIp, exclude_if_id); if (route_to_real_server_global != NULL) { if (MsIsVista()) { route_to_real_server_global->Metric = route_to_real_server_global->OldIfMetric; } if (AddRouteEntry(route_to_real_server_global) == false) { FreeRouteEntry(route_to_real_server_global); route_to_real_server_global = NULL; } } } } // Initialize if (s->Cedar->Client != NULL && s->Account != NULL) { Lock(s->Account->lock); } t = ZeroMalloc(sizeof(ROUTE_TRACKING)); v->RouteState = t; t->RouteToServerAlreadyExists = already_exists; t->RouteToServer = e; t->RouteToDefaultDns = dns; t->RouteToRealServerGlobal = route_to_real_server_global; t->VLanInterfaceId = if_id; t->NextTrackingTime = 0; t->DeletedDefaultGateway = NewQueue(); t->OldDefaultGatewayMetric = 0x7fffffff; if (s->Cedar->Client != NULL && s->Account != NULL) { Unlock(s->Account->lock); } // Get the route to 8.8.8.8 SetIP(&eight, 8, 8, 8, 8); t->RouteToEight = GetBestRouteEntryEx(&eight, exclude_if_id); // Get the current default DNS server to detect network changes GetDefaultDns(&t->OldDnsServer); // Get as soon as releasing the IP address in the case of using DHCP if (IsNt()) { char tmp[MAX_SIZE]; MS_ADAPTER *a; Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName); a = MsGetAdapter(tmp); if (a != NULL) { if (a->UseDhcp) { bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100); Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret); ret = Win32RenewAddressByGuidEx(a->Guid, 100); Debug("*** Win32RenewAddressByGuidEx = %u\n", ret); } MsFreeAdapter(a); } } else { // For Win9x Win32RenewDhcp9x(if_id); } // Clear the DNS cache Win32FlushDnsCache(); // Detect a change in the routing table (for only supported OS) t->RouteChange = NewRouteChange(); Debug("t->RouteChange = 0x%p\n", t->RouteChange); }
// Real-time clock measuring thread void Tick64Thread(THREAD *thread, void *param) { UINT n = 0; bool first = false; bool create_first_entry = true; UINT tick_span; // Validate arguments if (thread == NULL) { return; } #ifdef OS_WIN32 // Raise the priority of the Win32 thread MsSetThreadPriorityRealtime(); tick_span = TICK64_SPAN_WIN32; #else // OS_WIN32 // Raise the priority of a POSIX threads UnixSetThreadPriorityRealtime(); tick_span = TICK64_SPAN; #endif // OS_WIN32 while (true) { UINT tick; UINT64 tick64; #ifndef OS_WIN32 tick = TickRealtime(); // Get the current system clock if (tk64->LastTick > tick) { if ((tk64->LastTick - tick) >= (UINT64)0x0fffffff) { // The Tick has gone lap around tk64->RoundCount++; } else { // tick skewed (System administrator might change hardware clock) // Normally, the clock skew appears as sub-seconds error tick = tk64->LastTick; } } tk64->LastTick = tick; tick64 = (UINT64)tk64->RoundCount * (UINT64)4294967296LL + (UINT64)tick; Lock(tk64->TickLock); { if (tk64->TickStart == 0) { tk64->TickStart = tick64; } tick64 = tk64->Tick = tick64 - tk64->TickStart + (UINT64)1; } Unlock(tk64->TickLock); #else // OS_WIN32 tick64 = Win32FastTick64(); tick = (UINT)tick64; #endif // OS_WIN32 if (create_first_entry) { ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME)); t->Tick = tick64; t->Time = SystemTime64(); tk64->Tick64WithTime64 = tick64; tk64->Time64 = t->Time; Add(tk64->AdjustTime, t); // Notify the completion of the initialization NoticeThreadInit(thread); create_first_entry = false; } // Time correction n += tick_span; if (n >= 1000 || first == false) { UINT64 now = SystemTime64(); if (now < tk64->Time64 || Diff64((now - tk64->Time64) + tk64->Tick64WithTime64, tick64) >= tick_span) { ADJUST_TIME *t = ZeroMalloc(sizeof(ADJUST_TIME)); LockList(tk64->AdjustTime); { t->Tick = tick64; t->Time = now; Add(tk64->AdjustTime, t); Debug("Adjust Time: Tick = %I64u, Time = %I64u\n", t->Tick, t->Time); // To prevent consuming memory infinite on a system that clock is skewd if (LIST_NUM(tk64->AdjustTime) > MAX_ADJUST_TIME) { // Remove the second ADJUST_TIME *t2 = LIST_DATA(tk64->AdjustTime, 1); Delete(tk64->AdjustTime, t2); Debug("NUM_ADJUST TIME: %u\n", LIST_NUM(tk64->AdjustTime)); Free(t2); } } UnlockList(tk64->AdjustTime); tk64->Time64 = now; tk64->Tick64WithTime64 = tick64; } first = true; n = 0; } if (tk64->Halt) { break; } #ifdef OS_WIN32 Wait(halt_tick_event, tick_span); #else // OS_WIN32 SleepThread(tick_span); #endif // OS_WIN32 } }
// Stack main thread void NsMainThread(THREAD *thread, void *param) { NATIVE_STACK *a = (NATIVE_STACK *)param; // Validate arguments if (thread == NULL || param == NULL) { return; } while (true) { SOCKSET set; bool err = false; bool flush_tube; LIST *recv_packets; bool state_changed = false; InitSockSet(&set); AddSockSet(&set, a->Sock1); if (a->Halt) { break; } // Pass to the IPC by receiving from the bridge LABEL_RESTART: state_changed = false; flush_tube = false; while (true) { void *data; UINT size; size = EthGetPacket(a->Eth, &data); if (size == INFINITE) { // Device error err = true; break; } else if (size == 0) { // Can not get any more break; } else { // Pass the IPC socket TubeSendEx(a->Sock1->SendTube, data, size, NULL, true); Free(data); flush_tube = true; state_changed = true; } } if (flush_tube) { TubeFlush(a->Sock1->SendTube); } // Pass to the bridge by receiving from IPC recv_packets = NULL; while (true) { TUBEDATA *d = TubeRecvAsync(a->Sock1->RecvTube); if (d == NULL) { break; } if (recv_packets == NULL) { recv_packets = NewListFast(NULL); } Add(recv_packets, d); state_changed = true; } if (recv_packets != NULL) { UINT i; UINT num = LIST_NUM(recv_packets); void **data_array; UINT *size_array; data_array = Malloc(sizeof(void *) * num); size_array = Malloc(sizeof(UINT) * num); for (i = 0;i < num;i++) { TUBEDATA *d = LIST_DATA(recv_packets, i); data_array[i] = d->Data; size_array[i] = d->DataSize; } EthPutPackets(a->Eth, num, data_array, size_array); for (i = 0;i < num;i++) { TUBEDATA *d = LIST_DATA(recv_packets, i); // Because the data buffer has been already released, not to release twice d->Data = NULL; FreeTubeData(d); } Free(data_array); Free(size_array); ReleaseList(recv_packets); } if (IsTubeConnected(a->Sock1->SendTube) == false || IsTubeConnected(a->Sock1->RecvTube) == false) { err = true; } if (err) { // An error has occured Debug("Native Stack: Error !\n"); a->Halt = true; continue; } if (state_changed) { goto LABEL_RESTART; } Select(&set, 1234, a->Cancel, NULL); } Disconnect(a->Sock1); Disconnect(a->Sock2); }
// main function int main(int argc, char *argv[]) { wchar_t *s; UINT ret = 0; #ifdef OS_WIN32 SetConsoleTitleA(CEDAR_PRODUCT_STR " VPN Command Line Utility"); #endif // OS_WIN32 InitMayaqua(false, false, argc, argv); InitCedar(); s = GetCommandLineUniStr(); if (s == NULL) { s = CopyUniStr(L""); } if (UniStrCmpi(s, L"exit") != 0) { UINT size = UniStrSize(s) + 64; wchar_t *tmp; tmp = Malloc(size); UniFormat(tmp, size, L"vpncmd %s", s); ret = CommandMain(tmp); Free(tmp); } #ifdef OS_WIN32 { UINT i; LIST *o = MsGetProcessList(); bool b = false; for (i = 0;i < LIST_NUM(o);i++) { MS_PROCESS *p = LIST_DATA(o, i); if (EndWith(p->ExeFilename, "\\cmd.exe") || EndWith(p->ExeFilename, "\\command.com")) { b = true; break; } } MsFreeProcessList(o); if (b == false) { if (ret != ERR_NO_ERROR) { SleepThread(1000); } } } #endif // OS_WIN32 Free(s); FreeCedar(); FreeMayaqua(); return ret; }
// Get Ethernet device list on Linux TOKEN_LIST *GetEthListLinux() { struct ifreq ifr; TOKEN_LIST *t; UINT i, n; int s; LIST *o; char name[MAX_SIZE]; o = NewListFast(CompareStr); s = UnixEthOpenRawSocket(); if (s != INVALID_SOCKET) { n = 0; for (i = 0;;i++) { Zero(&ifr, sizeof(ifr)); ifr.ifr_ifindex = i; if (ioctl(s, SIOCGIFNAME, &ifr) >= 0) { n = 0; StrCpy(name, sizeof(name), ifr.ifr_name); Zero(&ifr, sizeof(ifr)); StrCpy(ifr.ifr_name, sizeof(ifr.ifr_name), name); if (ioctl(s, SIOCGIFHWADDR, &ifr) >= 0) { UINT type = ifr.ifr_hwaddr.sa_family; if (type == 1 || type == 2 || type == 6 || type == 800 || type == 801) { if (IsInListStr(o, name) == false) { if (StartWith(name, "tap_") == false) { Add(o, CopyStr(name)); } } } } } else { n++; if (n >= 64) { break; } } } closesocket(s); } Sort(o); t = ZeroMalloc(sizeof(TOKEN_LIST)); t->NumTokens = LIST_NUM(o); t->Token = ZeroMalloc(sizeof(char *) * t->NumTokens); for (i = 0;i < LIST_NUM(o);i++) { char *name = LIST_DATA(o, i); t->Token[i] = name; } ReleaseList(o); return t; }
// Layer-3 switch thread void L3SwThread(THREAD *t, void *param) { L3SW *s; bool shutdown_now = false; // Validate arguments if (t == NULL || param == NULL) { return; } s = (L3SW *)param; s->Active = true; NoticeThreadInit(t); // Operation start SLog(s->Cedar, "L3_SWITCH_START", s->Name); while (s->Halt == false) { if (s->Online == false) { // Because the L3 switch is off-line now, // attempt to make it on-line periodically LockList(s->Cedar->HubList); { Lock(s->lock); { UINT i; UINT n = 0; bool all_exists = true; if (LIST_NUM(s->IfList) == 0) { // Don't operate if there is no interface all_exists = false; } for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); HUB *h = GetHub(s->Cedar, f->HubName); if (h != NULL) { if (h->Offline || h->Type == HUB_TYPE_FARM_DYNAMIC) { all_exists = false; } else { n++; } ReleaseHub(h); } else { all_exists = false; } } if (all_exists && n >= 1) { // Start the operation because all Virtual HUBs for // interfaces are enabled SLog(s->Cedar, "L3_SWITCH_ONLINE", s->Name); L3InitAllInterfaces(s); s->Online = true; } } Unlock(s->lock); } UnlockList(s->Cedar->HubList); } else { // Examine periodically whether all sessions terminated UINT i; bool any_halted = false; LIST *o = NULL; SHUTDOWN: Lock(s->lock); { for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); if (f->Session->Halt || f->Hub->Offline != false) { any_halted = true; break; } } if (shutdown_now) { any_halted = true; } if (any_halted) { SLog(s->Cedar, "L3_SWITCH_OFFLINE", s->Name); o = NewListFast(NULL); // If there is any terminated session, terminate all sessions for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *f = LIST_DATA(s->IfList, i); Insert(o, f->Session); } // Restore to the offline s->Online = false; } } Unlock(s->lock); if (o != NULL) { UINT i; for (i = 0;i < LIST_NUM(o);i++) { SESSION *s = LIST_DATA(o, i); StopSession(s); } L3FreeAllInterfaces(s); ReleaseList(o); o = NULL; } } SleepThread(50); } if (s->Online != false) { shutdown_now = true; goto SHUTDOWN; } // Stop the operation SLog(s->Cedar, "L3_SWITCH_STOP", s->Name); }
// Determine the packet destined for the specified IP address should be sent to which interface L3IF *L3GetNextIf(L3SW *s, UINT ip, UINT *next_hop) { UINT i; L3IF *f; UINT next_hop_ip = 0; // Validate arguments if (s == NULL || ip == 0 || ip == 0xffffffff) { return NULL; } f = NULL; // Examine whether the specified IP address is contained // in the networks which each interfaces belong to for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *ff = LIST_DATA(s->IfList, i); if ((ff->IpAddress & ff->SubnetMask) == (ip & ff->SubnetMask)) { f = ff; next_hop_ip = ip; break; } } if (f == NULL) { // Find the routing table if it's not found L3TABLE *t = L3GetBestRoute(s, ip); if (t == NULL) { // Still not found return NULL; } else { // Find the interface with the IP address of the router of // NextHop of the found route for (i = 0;i < LIST_NUM(s->IfList);i++) { L3IF *ff = LIST_DATA(s->IfList, i); if ((ff->IpAddress & ff->SubnetMask) == (t->GatewayAddress & ff->SubnetMask)) { f = ff; next_hop_ip = t->GatewayAddress; break; } } } } if (f == NULL) { // Destination interface was unknown after all return NULL; } if (next_hop != NULL) { *next_hop = next_hop_ip; } return f; }
// Get VLAN tag pass-through availability of all devices bool EnumEthVLanWin32(RPC_ENUM_ETH_VLAN *t) { UINT i; LIST *o; // Validate arguments if (t == NULL) { return false; } Zero(t, sizeof(RPC_ENUM_ETH_VLAN)); if (MsIsWin2000OrGreater() == false) { return false; } if (IsEthSupported() == false) { return false; } // Get device list Lock(eth_list_lock); InitEthAdaptersList(); o = NewListFast(CmpRpcEnumEthVLan); for (i = 0;i < LIST_NUM(eth_list);i++) { WP_ADAPTER *a = LIST_DATA(eth_list, i); if (IsEmptyStr(a->Guid) == false) { char class_key[MAX_SIZE]; char short_key[MAX_SIZE]; if (GetClassRegKeyWin32(class_key, sizeof(class_key), short_key, sizeof(short_key), a->Guid)) { char *device_instance_id = MsRegReadStr(REG_LOCAL_MACHINE, class_key, "DeviceInstanceID"); if (IsEmptyStr(device_instance_id)) { Free(device_instance_id); device_instance_id = SearchDeviceInstanceIdFromShortKey(short_key); } if (IsEmptyStr(device_instance_id) == false) { char device_key[MAX_SIZE]; char *service_name; Format(device_key, sizeof(device_key), "SYSTEM\\CurrentControlSet\\Enum\\%s", device_instance_id); service_name = MsRegReadStr(REG_LOCAL_MACHINE, device_key, "Service"); if (IsEmptyStr(service_name) == false) { char service_key[MAX_SIZE]; char *sys; Format(service_key, sizeof(service_key), "SYSTEM\\CurrentControlSet\\services\\%s", service_name); sys = MsRegReadStr(REG_LOCAL_MACHINE, service_key, "ImagePath"); if (IsEmptyStr(sys) == false) { char sysname[MAX_PATH]; GetFileNameFromFilePath(sysname, sizeof(sysname), sys); Trim(sysname); if (EndWith(sysname, ".sys")) { // device found RPC_ENUM_ETH_VLAN_ITEM *e = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM)); StrCpy(e->DeviceName, sizeof(e->DeviceName), a->Title); StrCpy(e->Guid, sizeof(e->Guid), a->Guid); StrCpy(e->DeviceInstanceId, sizeof(e->DeviceInstanceId), device_instance_id); StrCpy(e->DriverName, sizeof(e->DriverName), sysname); // Get VLAN tag pass-through availability of the device GetVLanSupportStatus(e); // Get current pass-through setting of the device GetVLanEnableStatus(e); Insert(o, e); } } Free(sys); } Free(service_name); } Free(device_instance_id); } } } t->NumItem = LIST_NUM(o); t->Items = ZeroMalloc(sizeof(RPC_ENUM_ETH_VLAN_ITEM) * i); for (i = 0;i < LIST_NUM(o);i++) { RPC_ENUM_ETH_VLAN_ITEM *e = LIST_DATA(o, i); Copy(&t->Items[i], e, sizeof(RPC_ENUM_ETH_VLAN_ITEM)); Free(e); } ReleaseList(o); Unlock(eth_list_lock); return true; }