#include #include "debug.h" #include "stringutils.h" #include #include // z:\home\sources\wince500\PUBLIC\COMMON\SDK\INC\iprtrmib.h // z:\home\sources\wince500\PUBLIC\COMMON\SDK\INC\iphlpapi.h // z:\home\sources\wince500\PUBLIC\COMMON\SDK\INC\iptypes.h std::string physaddrstring(const BYTE *p, DWORD size) { std::string str; while (size--) { if (!str.empty()) str += ":"; str += stringformat("%02x", *p++); } return "["+str+"]"; } void dumpNumberOfIf() { DWORD n=0; DWORD rc= GetNumberOfInterfaces(&n); if (rc!=NO_ERROR) { debug("GetNumberOfInterfaces: error %08lx\n", rc); return; } debugt("GetNumberOfInterfaces: %d\n", n); } void dumpAdaptersAddresses() { ByteVector bv(sizeof(IP_ADAPTER_ADDRESSES)*4); DWORD dwLen=bv.size(); IP_ADAPTER_ADDRESSES *p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetAdaptersAddresses(AF_UNSPEC, 0, 0, p, &dwLen); } while (rc==ERROR_BUFFER_OVERFLOW); if (rc!=NO_ERROR) { debug("GetAdaptersAddresses: error %08lx\n", rc); return; } debugt("GetAdaptersAddresses\n"); while (p) { debug("'%s': dns:%s, desc:%s, name:%s, f:%x,mtu:%d,type:%d, addr=%s\n", ToString(p->AdapterName).c_str(), ToString(p->DnsSuffix).c_str(), ToString(p->Description).c_str(), ToString(p->FriendlyName).c_str(), p->Flags, p->Mtu, p->IfType, physaddrstring(p->PhysicalAddress, p->PhysicalAddressLength).c_str()); p= p->Next; } } std::string ipaddrstring(IP_ADDR_STRING *p) { if (p==NULL) return "-"; return stringformat("[%d]%s%s%s", p->Context, p->IpAddress.String, p->IpMask.String[0]?":":"", p->IpMask.String); } std::string ipaddrlist(IP_ADDR_STRING *p) { std::string str; while (p) { if (!str.empty()) str += ", "; str += ipaddrstring(p); p=p->Next; } return str; } void dumpAdaptersInfo() { ByteVector bv(sizeof(IP_ADAPTER_INFO)*4); DWORD dwLen=bv.size(); IP_ADAPTER_INFO * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetAdaptersInfo(p, &dwLen); } while (rc==ERROR_BUFFER_OVERFLOW); if (rc!=NO_ERROR) { debug("GetAdaptersInfo: error %08lx\n", rc); return; } debugt("GetAdaptersInfo\n"); while (p) { debug("%08x i:%d, name:'%s', desc:'%s', addr:%s, type:%x, dhcp:%x\n", p->Index, p->ComboIndex, p->AdapterName, p->Description, physaddrstring(p->Address, p->AddressLength).c_str(), p->Type, p->DhcpEnabled); debug("cur: %s\n", ipaddrstring(p->CurrentIpAddress).c_str()); debug("ip: %s\n", ipaddrlist(&p->IpAddressList).c_str()); debug("gate: %s\n", ipaddrlist(&p->GatewayList).c_str()); debug("dhcp: %s\n", ipaddrlist(&p->DhcpServer).c_str()); debug("1st: %s\n", ipaddrlist(&p->PrimaryWinsServer).c_str()); debug("2nd: %s\n", ipaddrlist(&p->SecondaryWinsServer).c_str()); p= p->Next; } } const char*icmp6type(int type) { switch(type) { case ICMP6_DST_UNREACH: return "DST_UNREACH"; case ICMP6_PACKET_TOO_BIG: return "PACKET_TOO_BIG"; case ICMP6_TIME_EXCEEDED: return "TIME_EXCEEDED"; case ICMP6_PARAM_PROB: return "PARAM_PROB"; case ICMP6_ECHO_REQUEST: return "ECHO_REQUEST"; case ICMP6_ECHO_REPLY: return "ECHO_REPLY"; case ICMP6_MEMBERSHIP_QUERY: return "MEMBERSHIP_QUERY"; case ICMP6_MEMBERSHIP_REPORT: return "MEMBERSHIP_REPORT"; case ICMP6_MEMBERSHIP_REDUCTION: return "MEMBERSHIP_REDUCTION"; case ND_ROUTER_SOLICIT: return "ND_ROUTER_SOLICIT"; case ND_ROUTER_ADVERT: return "ND_ROUTER_ADVERT"; case ND_NEIGHBOR_SOLICIT: return "ND_NEIGHBOR_SOLICIT"; case ND_NEIGHBOR_ADVERT: return "ND_NEIGHBOR_ADVERT"; case ND_REDIRECT: return "ND_REDIRECT"; default: return NULL; } } const char*icmp4type(int type) { switch(type) { case ICMP4_ECHO_REPLY: return "ECHO_REPLY"; case ICMP4_DST_UNREACH: return "DST_UNREACH"; case ICMP4_SOURCE_QUENCH: return "SOURCE_QUENCH"; case ICMP4_REDIRECT: return "REDIRECT"; case ICMP4_ECHO_REQUEST: return "ECHO_REQUEST"; case ICMP4_ROUTER_ADVERT: return "ROUTER_ADVERT"; case ICMP4_ROUTER_SOLICIT: return "ROUTER_SOLICIT"; case ICMP4_TIME_EXCEEDED: return "TIME_EXCEEDED"; case ICMP4_PARAM_PROB: return "PARAM_PROB"; case ICMP4_TIMESTAMP_REQUEST: return "TIMESTAMP_REQUEST"; case ICMP4_TIMESTAMP_REPLY: return "TIMESTAMP_REPLY"; case ICMP4_MASK_REQUEST: return "MASK_REQUEST"; case ICMP4_MASK_REPLY: return "MASK_REPLY"; default: return NULL; } } void dumpIcmpStats(const MIBICMPSTATS_EX& s, bool isipv4) { debug("msgs=%d, errors=%d\n", s.dwMsgs, s.dwErrors); for (int i=0 ; i<256 ; i++) { if (s.rgdwTypeCount[i]) { const char *desc= isipv4 ? icmp4type(i) : icmp6type(i); debug("type %d : %10d %s\n", i, s.rgdwTypeCount[i], desc?desc:""); } } } void dumpIcmpStats() { MIB_ICMP_EX mib; DWORD rc; rc= GetIcmpStatisticsEx(&mib, AF_INET); if (rc!=NO_ERROR) { debug("icmpstats: error %08lx\n", rc); } else { debugt("GetIcmpStatisticsEx\n"); debug("\nicmp in stats\n"); dumpIcmpStats(mib.icmpInStats, true); debug("\nicmp out stats\n"); dumpIcmpStats(mib.icmpOutStats, true); } debugt("\n"); rc= GetIcmpStatisticsEx(&mib, AF_INET6); if (rc!=NO_ERROR) { debug("icmp6stats: error %08lx\n"); } else { debugt("GetIcmpStatisticsEx\n"); debug("\nicmp6 in stats\n"); dumpIcmpStats(mib.icmpInStats, false); debug("\nicmp6 out stats\n"); dumpIcmpStats(mib.icmpOutStats, false); } } void dumpIpStats(const MIB_IPSTATS&s) { debug("fw:%d ttl:%d inrec=%d inherr=%d, inaerr=%d fwddgm=%d inunkn=%d indisc=%d indeliv=%d\n" "outreq=%d routdisc=%d outdisc=%d outnort=%d\n" "reasmto=%d reasmreq=%d reasmok=%d reasmfail=%d\n" "fragok=%d fragfail=%d fragcreat=%d\n" "nrif=%d nraddr=%d nrrt=%d\n", s.dwForwarding, s.dwDefaultTTL, s.dwInReceives, s.dwInHdrErrors, s.dwInAddrErrors, s.dwForwDatagrams, s.dwInUnknownProtos, s.dwInDiscards, s.dwInDelivers, s.dwOutRequests, s.dwRoutingDiscards, s.dwOutDiscards, s.dwOutNoRoutes, s.dwReasmTimeout, s.dwReasmReqds, s.dwReasmOks, s.dwReasmFails, s.dwFragOks, s.dwFragFails, s.dwFragCreates, s.dwNumIf, s.dwNumAddr, s.dwNumRoutes); } void dumpIpStats() { MIB_IPSTATS mib; DWORD rc; rc= GetIpStatisticsEx(&mib, AF_INET); if (rc!=NO_ERROR) { debug("icmpstats: error %08lx\n", rc); } else { debugt("GetIpStatisticsEx\n"); debug("\nipv4 stats\n"); dumpIpStats(mib); } rc= GetIpStatisticsEx(&mib, AF_INET6); if (rc!=NO_ERROR) { debug("icmp6stats: error %08lx\n"); } else { debugt("GetIpStatisticsEx\n"); debug("\nipv6 stats\n"); dumpIpStats(mib); } } void dumpUdpStats(const MIB_UDPSTATS&s) { debug("indg=%d noport=%d inerr=%d outdg=%d nraddr=%d\n", s.dwInDatagrams, s.dwNoPorts, s.dwInErrors, s.dwOutDatagrams, s.dwNumAddrs); } void dumpUdpStats() { MIB_UDPSTATS mib; DWORD rc; rc= GetUdpStatisticsEx(&mib, AF_INET); if (rc!=NO_ERROR) { debug("icmpstats: error %08lx\n", rc); } else { debugt("GetUdpStatisticsEx\n"); debug("\nipv4 udp stats\n"); dumpUdpStats(mib); } debugt("\n"); rc= GetUdpStatisticsEx(&mib, AF_INET6); if (rc!=NO_ERROR) { debug("icmp6stats: error %08lx\n"); } else { debugt("GetUdpStatisticsEx\n"); debug("\nipv6 udp stats\n"); dumpUdpStats(mib); } } void dumpTcpStats(const MIB_TCPSTATS&s) { debug("rtoalg=%d rto=%d..%d maxcon=%d active=%d passive=%d fails=%d\n" "estreq=%d currest=%d inseg=%d outseg=%d retr=%d inerr=%d outrsts=%d nrconns=%d\n", s.dwRtoAlgorithm, s.dwRtoMin, s.dwRtoMax, s.dwMaxConn, s.dwActiveOpens, s.dwPassiveOpens, s.dwAttemptFails, s.dwEstabResets, s.dwCurrEstab, s.dwInSegs, s.dwOutSegs, s.dwRetransSegs, s.dwInErrs, s.dwOutRsts, s.dwNumConns); } void dumpTcpStats() { MIB_TCPSTATS mib; DWORD rc; rc= GetTcpStatisticsEx(&mib, AF_INET); if (rc!=NO_ERROR) { debug("icmpstats: error %08lx\n", rc); } else { debugt("GetTcpStatisticsEx\n"); debug("\nipv4 tcp stats\n"); dumpTcpStats(mib); } debugt("\n"); rc= GetTcpStatisticsEx(&mib, AF_INET6); if (rc!=NO_ERROR) { debug("icmp6stats: error %08lx\n"); } else { debugt("GetTcpStatisticsEx\n"); debug("\nipv6 tcp stats\n"); dumpTcpStats(mib); } } const char*addrs[]= { "127.0.0.1", "192.168.9.1", "213.73.91.193", "194.109.6.66" }; #define NADDRS (sizeof(addrs)/sizeof(*addrs)) void dumpBest() { for (unsigned i=0 ; i(ToTString(addrs[i]).c_str()), sa.sin_family, NULL, (SOCKADDR*)&sa, &size); rc= GetBestInterfaceEx((SOCKADDR*)&sa, &idx); debugt("%-20s : %08lx %08x\n", addrs[i], rc, idx); } } void dumpIfRow(const MIB_IFROW& row) { debug("%08x %d %5d %10d %-20s %x %x %x '%s'\n" "in: %10d %10d %10d %10d %10d %10d\n" "out:%10d %10d %10d %10d %10d %10d\n" "desc:%s\n", row.dwIndex, row.dwType, row.dwMtu, row.dwSpeed, physaddrstring(row.bPhysAddr, row.dwPhysAddrLen).c_str(), row.dwAdminStatus, row.dwOperStatus, row.dwLastChange, ToString(row.wszName).c_str(), row.dwInOctets, row.dwInUcastPkts, row.dwInNUcastPkts, row.dwInDiscards, row.dwInErrors, row.dwInUnknownProtos, row.dwOutOctets, row.dwOutUcastPkts, row.dwOutNUcastPkts, row.dwOutDiscards, row.dwOutErrors, row.dwOutQLen, row.bDescr); } void dumpIfTable() { ByteVector bv(sizeof(MIB_IFTABLE)*4); DWORD dwLen=bv.size(); MIB_IFTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetIfTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetIfTable: error %08lx\n", rc); return; } debugt("GetIfTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpIfRow(p->table[i]); } } std::string ipaddr(DWORD addr, DWORD port=0xFFFFFFFF) { if (port==0xFFFFFFFF) return stringformat("%d.%d.%d.%d", (addr>>0)&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff); else return stringformat("%d.%d.%d.%d:%d", (addr>>0)&0xff, (addr>>8)&0xff, (addr>>16)&0xff, (addr>>24)&0xff, htons(port)); } void dumpTcpRow(const MIB_TCPROW& row) { debug("%02x %-21s - %-21s\n", row.dwState, ipaddr(row.dwLocalAddr, row.dwLocalPort).c_str(), ipaddr(row.dwRemoteAddr, row.dwRemotePort).c_str()); } void dumpTcpTable() { ByteVector bv(sizeof(MIB_TCPTABLE)*4); DWORD dwLen=bv.size(); MIB_TCPTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetTcpTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetTcpTable: error %08lx\n", rc); return; } debugt("GetTcpTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpTcpRow(p->table[i]); } } void dumpUdpRow(const MIB_UDPROW& row) { debug("%s\n", ipaddr(row.dwLocalAddr, row.dwLocalPort).c_str()); } void dumpUdpTable() { ByteVector bv(sizeof(MIB_UDPTABLE)*4); DWORD dwLen=bv.size(); MIB_UDPTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetUdpTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetUdpTable: error %08lx\n", rc); return; } debugt("GetUdpTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpUdpRow(p->table[i]); } } void dumpIpRow(const MIB_IPADDRROW& row) { debug("%08x: %s/%s %s\n", row.dwIndex, ipaddr(row.dwAddr).c_str(), ipaddr(row.dwMask).c_str(), ipaddr(row.dwBCastAddr).c_str()); } void dumpIpAddrTable() { ByteVector bv(sizeof(MIB_IPADDRTABLE)*4); DWORD dwLen=bv.size(); MIB_IPADDRTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetIpAddrTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetIpAddrTable: error %08lx\n", rc); return; } debugt("GetIpAddrTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpIpRow(p->table[i]); } } void dumpIpNetRow(const MIB_IPNETROW& row) { debug("%08x: %s %04x %s\n", row.dwIndex, ipaddr(row.dwAddr).c_str(), row.dwType, physaddrstring(row.bPhysAddr, row.dwPhysAddrLen).c_str()); } void dumpIpNetTable() { ByteVector bv(sizeof(MIB_IPNETTABLE)*4); DWORD dwLen=bv.size(); MIB_IPNETTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetIpNetTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetIpNetTable: error %08lx\n", rc); return; } debugt("GetIpNetTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpIpNetRow(p->table[i]); } } void dumpIpForwardRow(const MIB_IPFORWARDROW& row) { debug("%08x: %s/%s -> %s %d %d %d [%d,%d,%d,%d,%d]\n", row.dwForwardIfIndex, ipaddr(row.dwForwardDest).c_str(), ipaddr(row.dwForwardMask).c_str(), ipaddr(row.dwForwardNextHop).c_str(), row.dwForwardType, row.dwForwardProto, row.dwForwardNextHopAS, row.dwForwardMetric1, row.dwForwardMetric2, row.dwForwardMetric3, row.dwForwardMetric4, row.dwForwardMetric5); } void dumpIpForwardTable() { ByteVector bv(sizeof(MIB_IPFORWARDTABLE)*4); DWORD dwLen=bv.size(); MIB_IPFORWARDTABLE * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetIpForwardTable(p, &dwLen, FALSE); } while (rc==ERROR_INSUFFICIENT_BUFFER); if (rc!=NO_ERROR) { debug("GetIpForwardTable: error %08lx\n", rc); return; } debugt("GetIpForwardTable\n"); for (unsigned i=0 ; idwNumEntries ; i++) { dumpIpForwardRow(p->table[i]); } } void dumpNetworkParams() { ByteVector bv(sizeof(FIXED_INFO)*4); DWORD dwLen=bv.size(); FIXED_INFO * p=NULL; DWORD rc; do { bv.resize(dwLen); p= reinterpret_cast(&bv.front()); rc= GetNetworkParams(p, &dwLen); } while (rc==ERROR_BUFFER_OVERFLOW); if (rc!=NO_ERROR) { debug("GetNetworkParams: error %08lx\n", rc); return; } debug("host:%s dom:%s, type=%d routing=%d proxy=%d dns=%d curdns=%s\n" "dnslist: %s\n" "scope: %s\n", p->HostName, p->DomainName, p->NodeType, p->EnableRouting, p->EnableProxy, p->EnableDns, ipaddrstring(p->CurrentDnsServer).c_str(), ipaddrlist(&p->DnsServerList).c_str(), p->ScopeId); } /* GetNumberOfInterfaces(PDWORD) <<< done -> count GetAdaptersAddresses(af, 0,0,buf,len) <<< done -> list {name,dns, desc,name,flag,mtu,type,addr} GetAdaptersInfo(buf,len) <<< done -> list {idx,name,desc,addr,ipaddr,ipgw,dhcp} // handled by GetIfTable: GetIfEntry(IN OUT MIB_IFROW *pIfRow); GetIpAddrTable(OUT MIB_IPADDRTABLE *pIpAddrTable, IN OUT ULONG *pdwSize, IN BOOL bOrder); <<< done -> list {addr+ix+mask+bcast+reasmsize+type} GetIpNetTable(OUT MIB_IPNETTABLE *pIpNetTable, IN OUT ULONG *pdwSize, IN BOOL bOrder); <<< done -> list { ix+phys+addr+type } GetIpForwardTable(OUT MIB_IPFORWARDTABLE *pIpForwardTable, IN OUT ULONG *pdwSize, IN BOOL bOrder); <<< done -> list { dest+mask+policy+next+ix+type+proto+age+...} GetInterfaceInfo(IN IP_INTERFACE_INFO *pIfTable, OUT PULONG dwOutBufLen); -> list { index+name } GetUniDirectionalAdapterInfo(OUT IP_UNIDIRECTIONAL_ADAPTER_ADDRESS *pIPIfInfo, OUT PULONG dwOutBufLen); -> nr + address GetBestRoute(IN DWORD dwDestAddr, IN DWORD dwSourceAddr, OPTIONAL OUT PMIB_IPFORWARDROW pBestRoute); GetAdapterIndex(IN LPWSTR AdapterName, OUT PULONG IfIndex); -> same as GetInterfaceInfo but per interface GetPerAdapterInfo(ULONG IfIndex, IP_PER_ADAPTER_INFO *pPerAdapterInfo, ULONG *pOutBufLen); -> autocfg + dnsserver GetFriendlyIfIndex(DWORD IfIndex); GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount, ULONG MaxHops, PULONG RTT); GetIpErrorString(IN IP_STATUS ErrorCode, OUT PWCHAR Buffer, IN OUT PDWORD Size); */ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { DebugSetLogfile("netstat.log"); WSADATA wsa; DWORD err= WSAStartup(WINSOCK_VERSION, &wsa); if (err!=NO_ERROR) { debug("startip: %08lx\n", err); } else { debug("wsa: v=%04x high=%04x\n", wsa.wVersion, wsa.wHighVersion); debug("desc:'%s' stat:%s\n", wsa.szDescription, wsa.szSystemStatus); debug("maxsock=%d, maxudpdg=%d vendor:%p\n", wsa.iMaxSockets, wsa.iMaxUdpDg, wsa.lpVendorInfo); } dumpNumberOfIf(); debugt("\nadapter addresses\n"); dumpAdaptersAddresses(); debugt("\nadapter info\n"); dumpAdaptersInfo(); debugt("\n"); dumpIcmpStats(); debugt("\n"); dumpIpStats(); debugt("\n"); dumpUdpStats(); debugt("\n"); dumpTcpStats(); debugt("\nbestif\n"); dumpBest(); debugt("\niftable\n"); dumpIfTable(); debugt("\ntcptable\n"); dumpTcpTable(); debugt("\nudptable\n"); dumpUdpTable(); debugt("\nnetparams\n"); dumpNetworkParams(); debugt("\nipaddrtable\n"); dumpIpAddrTable(); debugt("\nipnettable\n"); dumpIpNetTable(); debugt("\nipforwardtable\n"); dumpIpForwardTable(); debugt("\ndone\n"); return 0; }