// Stop all L3 switches in the Cedar void L3FreeAllSw(CEDAR *c) { LIST *o; UINT i; // Validate arguments if (c == NULL) { return; } o = NewListFast(NULL); LockList(c->L3SwList); { for (i = 0;i < LIST_NUM(c->L3SwList);i++) { L3SW *s = LIST_DATA(c->L3SwList, i); Insert(o, CopyStr(s->Name)); } for (i = 0;i < LIST_NUM(o);i++) { char *name = LIST_DATA(o, i); L3DelSw(c, name); Free(name); } ReleaseList(o); } UnlockList(c->L3SwList); }
// Read an INI file LIST *ReadIni(BUF *b) { LIST *o; // Validate arguments if (b == NULL) { return NULL; } o = NewListFast(NULL); SeekBuf(b, 0, 0); while (true) { char *line = CfgReadNextLine(b); if (line == NULL) { break; } Trim(line); if (IsEmptyStr(line) == false) { if (StartWith(line, "#") == false && StartWith(line, "//") == false && StartWith(line, ";") == false) { char *key, *value; UINT size = StrLen(line) + 1; key = ZeroMalloc(size); value = ZeroMalloc(size); if (GetKeyAndValue(line, key, size, value, size, NULL)) { UINT uni_size; INI_ENTRY *e = ZeroMalloc(sizeof(INI_ENTRY)); e->Key = CopyStr(key); e->Value = CopyStr(value); uni_size = CalcUtf8ToUni((BYTE *)value, StrLen(value)); e->UnicodeValue = ZeroMalloc(uni_size); Utf8ToUni(e->UnicodeValue, uni_size, (BYTE *)value, StrLen(value)); Add(o, e); } Free(key); Free(value); } } Free(line); } return o; }
// Delete old entries in Non-SSL connection list void DeleteOldNoSsl(CEDAR *c) { UINT i; LIST *o; // Validate arguments if (c == NULL) { return; } o = NewListFast(NULL); for (i = 0;i < LIST_NUM(c->NonSslList);i++) { NON_SSL *n = LIST_DATA(c->NonSslList, i); if (n->EntryExpires <= Tick64()) { Add(o, n); } } for (i = 0;i < LIST_NUM(o);i++) { NON_SSL *n = LIST_DATA(o, i); Delete(c->NonSslList, n); Free(n); } ReleaseList(o); }
// Get Ethernet device list on Solaris TOKEN_LIST *GetEthListSolaris() { TOKEN_LIST *t; int i, s; LIST *o; o = NewListFast(CompareStr); s = socket(AF_INET, SOCK_DGRAM, 0); if (s != INVALID_SOCKET) { struct lifnum lifn; lifn.lifn_family = AF_INET; lifn.lifn_flags = 0; if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) >= 0) { struct lifconf lifc; struct lifreq *buf; UINT numifs; UINT bufsize; numifs = lifn.lifn_count; Debug("NumIFs:%d\n",numifs); bufsize = numifs * sizeof(struct lifreq); buf = Malloc(bufsize); lifc.lifc_family = AF_INET; lifc.lifc_flags = 0; lifc.lifc_len = bufsize; lifc.lifc_buf = (char*) buf; if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) >= 0) { for (i = 0; i<numifs; i++) { if(StartWith(buf[i].lifr_name, "lo") == false){ Add(o, CopyStr(buf[i].lifr_name)); } } } Free(buf); } 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; }
// Cut out the token from the string (not ignore the blanks between delimiters) TOKEN_LIST *ParseTokenWithNullStr(char *str, char *split_chars) { LIST *o; UINT i, len; 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); 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 { WriteBuf(b, &zero, sizeof(char)); Insert(o, CopyStr((char *)b->Buf)); ClearBuf(b); } } 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; }
// Create a folder FOLDER *CfgCreateFolder(FOLDER *parent, char *name) { UINT size; FOLDER *f; // Validate arguments if (name == NULL) { return NULL; } size = StrLen(name) + 1; #ifdef CHECK_CFG_NAME_EXISTS // Check the name in the parent list if (parent != NULL) { FOLDER ff; ff.Name = ZeroMalloc(size); StrCpy(ff.Name, 0, name); f = Search(parent->Folders, &ff); Free(ff.Name); if (f != NULL) { // Folder with the same name already exists return NULL; } } #endif // CHECK_CFG_NAME_EXISTS f = ZeroMalloc(sizeof(FOLDER)); f->Items = NewListFast(CmpItemName); f->Folders = NewListFast(CmpFolderName); f->Name = ZeroMalloc(size); StrCpy(f->Name, 0, name); f->Parent = parent; // Add to parentlist if (f->Parent != NULL) { Insert(f->Parent->Folders, f); } return f; }
// Get the candidates list of of the real command name whose abbreviation matches to the command specified by the user TOKEN_LIST *GetRealnameCandidate(char *input_name, TOKEN_LIST *real_name_list) { TOKEN_LIST *ret; LIST *o; UINT i; bool ok = false; // Validate arguments if (input_name == NULL || real_name_list == NULL) { return NullToken(); } o = NewListFast(NULL); for (i = 0;i < real_name_list->NumTokens;i++) { char *name = real_name_list->Token[i]; // Search for an exact match with the highest priority first if (StrCmpi(name, input_name) == 0) { Insert(o, name); ok = true; break; } } if (ok == false) { // If there is no command to exact match, check whether it matches to a short form command for (i = 0;i < real_name_list->NumTokens;i++) { char *name = real_name_list->Token[i]; if (IsOmissionName(input_name, name) || IsNameInRealName(input_name, name)) { // A abbreviation is found Insert(o, name); ok = true; } } } if (ok) { // One or more candidate is found ret = ListToTokenList(o); } else { ret = NullToken(); } ReleaseList(o); return ret; }
// Parse the Attribute list LIST *SstpParseAttributeList(UCHAR *data, UINT size, SSTP_PACKET *p) { LIST *o; USHORT us; UINT num; // Validate arguments if (size == 0 || data == NULL || p == NULL) { return NULL; } if (size < 4) { return NULL; } // Message Type us = READ_USHORT(data); p->MessageType = us; data += sizeof(USHORT); size -= sizeof(USHORT); // Num Attributes num = READ_USHORT(data); data += sizeof(USHORT); size -= sizeof(USHORT); // Attibutes List o = NewListFast(NULL); while (LIST_NUM(o) < num) { SSTP_ATTRIBUTE *a = SstpParseAttribute(data, size); if (a == NULL) { SstpFreeAttributeList(o); return NULL; } if (a->TotalLength > size) { SstpFreeAttribute(a); SstpFreeAttributeList(o); return NULL; } Add(o, a); data += a->TotalLength; size -= a->TotalLength; } return o; }
// Create a new SSTP control packet SSTP_PACKET *SstpNewControlPacket(USHORT message_type) { SSTP_PACKET *p = ZeroMalloc(sizeof(SSTP_PACKET)); p->IsControl = true; p->MessageType = message_type; p->Version = SSTP_VERSION_1; p->AttibuteList = NewListFast(NULL); return p; }
// PACK オブジェクトの作成 PACK *NewPack() { PACK *p; // メモリ確保 p = MallocEx(sizeof(PACK), true); // リスト作成 p->elements = NewListFast(ComparePackName); return p; }
// Parse the data entry LIST *WpcParseDataEntry(BUF *b) { char entry_name[WPC_DATA_ENTRY_SIZE]; char size_str[11]; LIST *o; // Validate arguments if (b == NULL) { return NULL; } SeekBuf(b, 0, 0); o = NewListFast(NULL); while (true) { UINT size; WPC_ENTRY *e; if (ReadBuf(b, entry_name, WPC_DATA_ENTRY_SIZE) != WPC_DATA_ENTRY_SIZE) { break; } Zero(size_str, sizeof(size_str)); if (ReadBuf(b, size_str, 10) != 10) { break; } size = ToInt(size_str); if ((b->Size - b->Current) < size) { break; } e = ZeroMalloc(sizeof(WPC_ENTRY)); e->Data = (UCHAR *)b->Buf + b->Current; Copy(e->EntryName, entry_name, WPC_DATA_ENTRY_SIZE); e->Size = size; SeekBuf(b, size, 1); Add(o, e); } return o; }
// Get the string name that begins with the specified name TOKEN_LIST *GetTableNameStartWith(char *str) { UINT i; UINT len; LIST *o; TOKEN_LIST *t; char tmp[MAX_SIZE]; // Validate arguments if (str == NULL) { return NullToken(); } StrCpy(tmp, sizeof(tmp), str); StrUpper(tmp); len = StrLen(tmp); o = NewListFast(NULL); for (i = 0;i < LIST_NUM(TableList);i++) { TABLE *t = LIST_DATA(TableList, i); UINT len2 = StrLen(t->name); if (len2 >= len) { if (Cmp(t->name, tmp, len) == 0) { Insert(o, CopyStr(t->name)); } } } 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; }
// Polling for the ARP resolution waiting list void L3PollingArpWaitTable(L3IF *f) { UINT i; LIST *o = NULL; // Validate arguments if (f == NULL) { return; } for (i = 0;i < LIST_NUM(f->ArpWaitTable);i++) { L3ARPWAIT *w = LIST_DATA(f->ArpWaitTable, i); if (w->Expire <= Tick64()) { // The ARP request entry is expired if (o == NULL) { o = NewListFast(NULL); } Insert(o, w); } else if ((w->LastSentTime + ARP_REQUEST_TIMEOUT) <= Tick64()) { // Send a next ARP request packet w->LastSentTime = Tick64(); L3SendArpRequestNow(f, w->IpAddress); } } if (o != NULL) { for (i = 0;i < LIST_NUM(o);i++) { L3ARPWAIT *w = LIST_DATA(o, i); Delete(f->ArpWaitTable, w); Free(w); } ReleaseList(o); } }
// すべてのオブジェクトの表示 void DebugPrintAllObjects() { UINT i; LIST *view; // リスト作成 view = NewListFast(SortObjectView); LockTrackingList(); { for (i = 0; i < TRACKING_NUM_ARRAY; i++) { if (hashlist[i] != NULL) { TRACKING_LIST *t = hashlist[i]; while (true) { Add(view, t->Object); if (t->Next == NULL) { break; } t = t->Next; } } } } UnlockTrackingList(); // ソート Sort(view); // 描画 for (i = 0; i < LIST_NUM(view); i++) { TRACKING_OBJECT *o = (TRACKING_OBJECT *)LIST_DATA(view, i); PrintObjectList(o); } // リスト解放 ReleaseList(view); Print("\n"); }
// Clear old ARP table entries void L3DeleteOldArpTable(L3IF *f) { UINT i; LIST *o = NULL; // Validate arguments if (f == NULL) { return; } if ((f->LastDeleteOldArpTable + ARP_ENTRY_POLLING_TIME) > Tick64()) { return; } f->LastDeleteOldArpTable = Tick64(); for (i = 0;i < LIST_NUM(f->ArpTable);i++) { L3ARPENTRY *a = LIST_DATA(f->ArpTable, i); if (a->Expire <= Tick64()) { // Expired if (o == NULL) { o = NewListFast(NULL); } Insert(o, a); } } if (o != NULL) { for (i = 0;i < LIST_NUM(o);i++) { L3ARPENTRY *a = LIST_DATA(o, i); Delete(f->ArpTable, a); Free(a); } ReleaseList(o); } }
// トークンリストを文字列リストに変換する LIST *TokenListToList(TOKEN_LIST *t) { UINT i; LIST *o; // 引数チェック if (t == NULL) { return NULL; } o = NewListFast(NULL); for (i = 0;i < t->NumTokens;i++) { Insert(o, CopyStr(t->Token[i])); } return o; }
// Ethernet device list by Pcap API TOKEN_LIST *GetEthListPcap() { pcap_if_t *alldevs; char errbuf[PCAP_ERRBUF_SIZE]; LIST *o; TOKEN_LIST *t; int i; o = NewListFast(CompareStr); if( pcap_findalldevs(&alldevs,errbuf) != -1) { pcap_if_t *dev = alldevs; while(dev != NULL) { pcap_t *p; // Device type will be unknown until open the device? p = pcap_open_live(dev->name, 0, false, 0, errbuf); if(p != NULL) { int datalink = pcap_datalink(p); // Debug("type:%s\n",pcap_datalink_val_to_name(datalink)); pcap_close(p); if(datalink == DLT_EN10MB){ // Enumerate only Ethernet type device Add(o, CopyStr(dev->name)); } } dev = dev->next; } pcap_freealldevs(alldevs); } 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++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); return t; }
// アダプタ一覧を取得 (BPF) TOKEN_LIST *GetEthListBpf() { struct ifaddrs *ifadrs; struct sockaddr_dl *sockadr; LIST *o; TOKEN_LIST *t; int i; o = NewListFast(CompareStr); // ネットワークデバイスの一覧を取得 if(getifaddrs( &ifadrs ) == 0) { struct ifaddrs *ifadr = ifadrs; while(ifadr) { sockadr = (struct sockaddr_dl*)ifadr->ifa_addr; if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER) { // Ethernet デバイスか? if(!IsInListStr(o,ifadr->ifa_name)) { // 既存でなければ追加(複数のMACアドレスを持つインターフェースへの対策) Add(o, CopyStr(ifadr->ifa_name)); } } ifadr = ifadr -> ifa_next; } freeifaddrs(ifadrs); } 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++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); return t; }
// Send the waiting IP packets whose destination MAC address has been resolved void L3SendWaitingIp(L3IF *f, UCHAR *mac, UINT ip, L3ARPENTRY *a) { UINT i; LIST *o = NULL; // Validate arguments if (f == NULL || mac == NULL || a == NULL) { return; } for (i = 0;i < LIST_NUM(f->IpWaitList);i++) { L3PACKET *p = LIST_DATA(f->IpWaitList, i); if (p->NextHopIp == ip) { if (o == NULL) { o = NewListFast(NULL); } Add(o, p); } } if (o != NULL) { for (i = 0;i < LIST_NUM(o);i++) { L3PACKET *p = LIST_DATA(o, i); // Transmission L3SendIpNow(f, a, p); Delete(f->IpWaitList, p); Free(p->Packet->PacketData); FreePacket(p->Packet); Free(p); } ReleaseList(o); } }
// Ethernet device list by BPF API TOKEN_LIST *GetEthListBpf() { struct ifaddrs *ifadrs; struct sockaddr_dl *sockadr; LIST *o; TOKEN_LIST *t; int i; o = NewListFast(CompareStr); // Enumerate network devices if(getifaddrs( &ifadrs ) == 0) { struct ifaddrs *ifadr = ifadrs; while(ifadr) { sockadr = (struct sockaddr_dl*)ifadr->ifa_addr; if(sockadr->sdl_family == AF_LINK && sockadr->sdl_type == IFT_ETHER) { // Is this Ethernet device? if(!IsInListStr(o,ifadr->ifa_name)) { // Ignore the foregoing device (for device which have multiple MAC address) Add(o, CopyStr(ifadr->ifa_name)); } } ifadr = ifadr -> ifa_next; } freeifaddrs(ifadrs); } 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++) { t->Token[i] = LIST_DATA(o, i); } ReleaseList(o); return t; }
// Clone the secure object enumeration results LIST *CloneEnumSecObject(LIST *o) { LIST *ret; UINT i; // Validate arguments if (o == NULL) { return NULL; } ret = NewListFast(NULL); for (i = 0;i < LIST_NUM(o);i++) { SEC_OBJ *obj = LIST_DATA(o, i); Add(ret, CloneSecObject(obj)); } return ret; }
// Clear the IP waiting list void L3DeleteOldIpWaitList(L3IF *f) { UINT i; LIST *o = NULL; // Validate arguments if (f == NULL) { return; } for (i = 0;i < LIST_NUM(f->IpWaitList);i++) { L3PACKET *p = LIST_DATA(f->IpWaitList, i); if (p->Expire <= Tick64()) { if (o == NULL) { o = NewListFast(NULL); } Insert(o, p); } } if (o != NULL) { for (i = 0;i < LIST_NUM(o);i++) { L3PACKET *p = LIST_DATA(o, i); Delete(f->IpWaitList, p); Free(p->Packet->PacketData); FreePacket(p->Packet); Free(p); } ReleaseList(o); } }
// Convert a (NULL delimited) string to a list LIST *StrToStrList(char *str, UINT size) { LIST *o; char *tmp; UINT tmp_size; UINT i; // Validate arguments if (str == NULL) { return NULL; } o = NewListFast(NULL); i = 0; while (true) { if (i >= size) { break; } if (*str == 0) { break; } tmp_size = StrSize(str); tmp = ZeroMalloc(tmp_size); StrCpy(tmp, tmp_size, str); Add(o, tmp); str += StrLen(str) + 1; i++; } return o; }
// コマンドラインをパースする TOKEN_LIST *ParseCmdLine(char *str) { TOKEN_LIST *t; LIST *o; UINT i, len, wp, mode; char c; char *tmp; bool ignore_space = false; // 引数チェック if (str == NULL) { // トークン無し 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: // 次のトークンを発見するモード if (c == ' ' || c == '\t') { // 次の文字へ進める } else { // トークンの開始 if (c == '\"') { if (str[i + 1] == '\"') { // 2 重の " は 1 個の " 文字として見なす tmp[wp++] = '\"'; i++; } else { // 1 個の " はスペース無視フラグを有効にする ignore_space = true; } } else { tmp[wp++] = c; } mode = 1; } break; case 1: if (ignore_space == false && (c == ' ' || c == '\t')) { // トークンの終了 tmp[wp++] = 0; wp = 0; Insert(o, CopyStr(tmp)); mode = 0; } else { if (c == '\"') { if (str[i + 1] == '\"') { // 2 重の " は 1 個の " 文字として見なす tmp[wp++] = L'\"'; i++; } else { if (ignore_space == false) { // 1 個の " はスペース無視フラグを有効にする ignore_space = true; } else { // スペース無視フラグを無効にする 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; }
// 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; }
LIST *GetEthAdapterListInternal() { LIST *o; LIST *ret; UINT size; char *buf; UINT i, j; char *qos_tag = " (Microsoft's Packet Scheduler)"; SU *su = NULL; LIST *su_adapter_list = NULL; // Try to use SeLow if (enable_selow) { su = SuInit(); } o = NewListFast(CompareWpAdapter); size = 200000; buf = ZeroMalloc(size); // Try to enumerate with SeLow if (su != NULL) { su_adapter_list = SuGetAdapterList(su); if (su_adapter_list == NULL) { // Fail to enumerate SuFree(su); su = NULL; //WHERE; is_using_selow = false; } else { //WHERE; is_using_selow = true; } } else { is_using_selow = false; } if (su_adapter_list != NULL) { // If 1 or more adapters are enumerated by SeLow, create adapter list object UINT i; for (i = 0;i < LIST_NUM(su_adapter_list);i++) { SU_ADAPTER_LIST *t = LIST_DATA(su_adapter_list, i); WP_ADAPTER *a = ZeroMalloc(sizeof(WP_ADAPTER)); StrCpy(a->Name, sizeof(a->Name), t->Name); StrCpy(a->Guid, sizeof(a->Guid), t->Guid); StrCpy(a->Title, sizeof(a->Title), t->Info.FriendlyName); TrimCrlf(a->Title); Trim(a->Title); TrimCrlf(a->Title); Trim(a->Title); if (EndWith(a->Title, qos_tag)) { a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0; TrimCrlf(a->Title); Trim(a->Title); TrimCrlf(a->Title); Trim(a->Title); } Add(o, a); } } else { // When SeLow is not used, create adapter list with SEE or WinPcap if (wp->PacketGetAdapterNames(buf, &size) == false) { Free(buf); return o; } i = 0; if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType)) { // Windows NT if (size >= 2 && buf[0] != 0 && buf[1] != 0) { goto ANSI_STR; } while (true) { wchar_t tmp[MAX_SIZE]; WP_ADAPTER *a; UniStrCpy(tmp, sizeof(tmp), L""); if (*((wchar_t *)(&buf[i])) == 0) { i += sizeof(wchar_t); break; } for (;*((wchar_t *)(&buf[i])) != 0;i += sizeof(wchar_t)) { wchar_t str[2]; str[0] = *((wchar_t *)(&buf[i])); str[1] = 0; UniStrCat(tmp, sizeof(tmp), str); } i += sizeof(wchar_t); a = ZeroMalloc(sizeof(WP_ADAPTER)); UniToStr(a->Name, sizeof(a->Name), tmp); Add(o, a); } } else { // Windows 9x ANSI_STR: while (true) { char tmp[MAX_SIZE]; WP_ADAPTER *a; StrCpy(tmp, sizeof(tmp), ""); if (*((char *)(&buf[i])) == 0) { i += sizeof(char); break; } for (;*((char *)(&buf[i])) != 0;i += sizeof(char)) { char str[2]; str[0] = *((char *)(&buf[i])); str[1] = 0; StrCat(tmp, sizeof(tmp), str); } i += sizeof(char); a = ZeroMalloc(sizeof(WP_ADAPTER)); StrCpy(a->Name, sizeof(a->Name), tmp); Add(o, a); } } for (j = 0;j < LIST_NUM(o);j++) { WP_ADAPTER *a = LIST_DATA(o, j); StrCpy(a->Title, sizeof(a->Title), &buf[i]); i += StrSize(a->Title); // If device description is "Unknown" in Win9x, skip 1 byte if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType)) { if (StrCmp(a->Title, "Unknown") == 0) { if (buf[i] == 0) { i+=sizeof(char); } } } TrimCrlf(a->Title); Trim(a->Title); TrimCrlf(a->Title); Trim(a->Title); if (EndWith(a->Title, qos_tag)) { a->Title[StrLen(a->Title) - StrLen(qos_tag)] = 0; TrimCrlf(a->Title); Trim(a->Title); TrimCrlf(a->Title); Trim(a->Title); } } } for (j = 0;j < LIST_NUM(o);j++) { // Extract GUID WP_ADAPTER *a = LIST_DATA(o, j); if (IsEmptyStr(a->Guid)) { StrCpy(a->Guid, sizeof(a->Guid), a->Name); ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\SEE_", ""); ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\NPF_", ""); ReplaceStr(a->Guid, sizeof(a->Guid), a->Guid, "\\Device\\PCD_", ""); } } // Sort if (su_adapter_list != NULL) { // Since adapter list made by SeLow is already sorted, don't sort here Sort(o); } ret = NewListFast(CompareWpAdapter); for (i = 0;i < LIST_NUM(o);i++) { WP_ADAPTER *a = LIST_DATA(o, i); ADAPTER *ad; bool is_ethernet = false; bool ok = false; if (SearchStrEx(a->Title, "ppp", 0, false) != INFINITE || SearchStrEx(a->Title, "wan", 0, false) != INFINITE || SearchStrEx(a->Title, "dialup", 0, false) != INFINITE || SearchStrEx(a->Title, "pptp", 0, false) != INFINITE || SearchStrEx(a->Title, "telepho", 0, false) != INFINITE || SearchStrEx(a->Title, "modem", 0, false) != INFINITE || SearchStrEx(a->Title, "ras", 0, false) != INFINITE) { Free(a); continue; } // Determine whether the adapter type is Ethernet if (su == NULL) { // Determine with See ad = wp->PacketOpenAdapter(a->Name); if (ad != NULL) { NetType type; if (wp->PacketGetNetType(ad, &type)) { if (type.LinkType == 0) { is_ethernet = true; } } wp->PacketCloseAdapter(ad); } } else { // In using SeLow, all devices should be Ethernet device is_ethernet = true; } if (is_ethernet) { // Add only Ethernet device char tmp[MAX_SIZE]; UINT k; StrCpy(tmp, sizeof(tmp), a->Title); for (k = 0;;k++) { if (k == 0) { StrCpy(tmp, sizeof(tmp), a->Title); } else { Format(tmp, sizeof(tmp), "%s (%u)", a->Title, k + 1); } ok = true; for (j = 0;j < LIST_NUM(ret);j++) { WP_ADAPTER *aa = LIST_DATA(ret, j); if (StrCmpi(aa->Title, tmp) == 0) { ok = false; } } if (ok) { break; } } StrCpy(a->Title, sizeof(a->Title), tmp); a->Id = Win32EthGenIdFromGuid(a->Guid); Add(ret, a); } if (ok == false) { Free(a); } } Free(buf); Sort(ret); ReleaseList(o); if (su != NULL) { SuFreeAdapterList(su_adapter_list); SuFree(su); } return ret; }
// 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); }
// 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; }
// 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); }