/* * Program for obtaining adapter information using the GetAdaptersAddresses() function * * How to compile * * C:\>cl GetAdaptersAddresses.c ws2_32.lib iphlpapi.lib * */ #include #include #include #include #include /* for IP Helper API */ #include /* Convert IP_PREFIX_ORIGIN enum value, which specifies */ /* the origin of the IP address prefix (network part), into a character string. */ const char *getString_IP_PREFIX_ORIGIN(IP_PREFIX_ORIGIN ipo) { const char *szOriginString[] = { "Other", "Manual", "WellKnown", "Dhcp", "RouterAdvertisement" }; return szOriginString[ipo]; } /* Convert IP_SUFFIX_ORIGIN enum value, which specifies */ /* the origin of the IP address interface ID (host part), into a character string. */ const char *getString_IP_SUFFIX_ORIGIN(IP_SUFFIX_ORIGIN iso) { const char *szOriginString[] = { "Other", "Manual", "WellKnown", "Dhcp", "LinkLayerAddress", "Random" }; return szOriginString[iso]; } /* Show IP address DAD status. */ /* Convert IP_DAD_STATE enum value into a character string. */ const char *getString_IP_DAD_STATE(IP_DAD_STATE ids) { const char *szDADstate[] = { "Invalid", "Tentative", "Duplicate", "Deprecated", "Preferred" }; return szDADstate[ids]; } /* Show adapter status. */ /* Convert IF_OPER_STATUS enum value into a character string. */ const char *getString_IF_OPER_STATUS(IF_OPER_STATUS ios) { const char *szOperationalStatus[] = { "", /* According to the IF_OPER_STATUS enum definition, 0 is skipped. */ "Up", "Down", "Testing", "Unknown", "Dormant", "NotPresent", "LowerLayerDown" }; return szOperationalStatus[ios]; } /* Show adapter type (media type). */ /* Convert value (dwIfType) into a character string. */ const char *getString_IfType(DWORD dwIfType) { switch(dwIfType) { case IF_TYPE_ETHERNET_CSMACD: /* 6 */ return "Ethernet"; case IF_TYPE_SOFTWARE_LOOPBACK: /* 24 */ return "Loopback"; case IF_TYPE_TUNNEL: /* 131 */ return "Tunnel"; default: return "Other Adapter Type"; } } /* Convert the ULONG value (lt), which specifies the life span, into a character string and write it to szBuf. */ /* When the life span value. lt, is equal to ULONG_MAX, return the character string ginfiniteh. */ /* When enough size is not allocated in szBuf */ /* it returns NULL. */ const char *getString_Lifetime(char *szBuf, size_t size, ULONG lt) { if (lt == ULONG_MAX) { if (_snprintf(szBuf, size, "%s", "infinite") < 0) return NULL; } else { if (_snprintf(szBuf, size, "%u", lt) < 0) return NULL; } return szBuf; } /* Convert the flag information that specifies adapter attributes into a character string. */ /* The names of the flags are output separated by commas. */ /* When enough size is not allocated in szBuf, it returns NULL. */ char *getString_AdapterFlags(char *szBuf, size_t size, DWORD dwFlags) { char *p = szBuf; int len; struct _FlagList { DWORD Flag; const char *szFlagName; } FlagList[] = { { IP_ADAPTER_DDNS_ENABLED, "DDNS_ENABLED" }, { IP_ADAPTER_REGISTER_ADAPTER_SUFFIX, "REGISTER_ADAPTER_SUFFIX" }, { IP_ADAPTER_DHCP_ENABLED, "DHCP_ENABLED" }, { IP_ADAPTER_RECEIVE_ONLY, "RECEIVE_ONLY" }, { IP_ADAPTER_NO_MULTICAST, "NO_MULTICAST" }, { IP_ADAPTER_IPV6_OTHER_STATEFUL_CONFIG, "OTHER_STATEFUL_CONFIG"} }; int i; for (i = 0; i < sizeof(FlagList) / sizeof(struct _FlagList); ++i) { if (dwFlags & FlagList[i].Flag) { if ((len = _snprintf(p, size, "%s", FlagList[i].szFlagName)) < 0) return NULL; p+= len; size -= len; break; } } for (i++; i < sizeof(FlagList) / sizeof(struct _FlagList); ++i) { if (dwFlags & FlagList[i].Flag) { if ((len = _snprintf(p, size, ",%s", FlagList[i].szFlagName)) < 0) return NULL; p+= len; size -= len; } } return szBuf; } /* Convert SCOPE_LEVEL enum value, which specifies the scope, into a character string. */ const char *getString_SCOPE_LEVEL(SCOPE_LEVEL sl) { const char *szScopeLevel[] = { "", /* According to the SCOPE_LEVEL enum definition, 0 is skipped. */ "Interface", "Link", "Subnet", "Admin", "Site", "Origanization", "Global" }; return szScopeLevel[sl]; } int main(int argc, char *argv[]) { WSADATA wsaData; PIP_ADAPTER_ADDRESSES pAdapterAddresses, pAA; DWORD dwRet, dwSize; /* * Initialize WinSock */ if (WSAStartup(MAKEWORD(2, 2), &wsaData)) { fprintf(stderr, "cannot initilize WinSock\n"); exit(1); } /* * dwSize, which requests the buffer size necessary to store the return value, obtains that value. * In order to obtain the prefix information in the FirstPrefix member, * specify GAA_FLAG_INCLUDE_PREFIX in the second argument flag. */ dwRet = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, NULL, &dwSize); if (dwRet != ERROR_BUFFER_OVERFLOW) { fprintf(stderr, "no enough buffer\n"); exit(1); } /* * Allocate a buffer of size dwSize in pAdapterAddresses. */ pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(dwSize); if (pAdapterAddresses == NULL) { fprintf(stderr, "no enough buffer\n"); exit(1); } /* * Call the GetAdaptersAddresses() function again and obtain the adapter information * in pAdapterAddresses. In order to obtain prefix information in the FirstPrefix member, * specify GAA_FLAG_INCLUDE_PREFIX in the second argument flag. */ dwRet = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, pAdapterAddresses, &dwSize); if (dwRet != ERROR_SUCCESS) { fprintf(stderr, "GetAdaptersAddresses() failed\n"); exit(1); } /* * For each adapter, the variable pAA, * which shows adapter information, is set to point to * an IP_ADAPTER_ADDRESSES instance. */ for (pAA = pAdapterAddresses; pAA; pAA = pAA->Next) { char szAdapterName[BUFSIZ]; char szAdapterDescription[BUFSIZ]; char szDnsSuffix[BUFSIZ]; int len; PIP_ADAPTER_UNICAST_ADDRESS pUnicastAddress; PIP_ADAPTER_ANYCAST_ADDRESS pAnycastAddress; PIP_ADAPTER_MULTICAST_ADDRESS pMulticastAddress; PIP_ADAPTER_DNS_SERVER_ADDRESS pDnsServerAddress; char szFlagsString[BUFSIZ]; PIP_ADAPTER_PREFIX pIpAdapterPrefix; int i; /* * Display the human-readable adapter name using the FriendlyName member. */ /* Since FriendlyName is encoded in Unicode, */ /* convert it into multi-byte characters (Shift JIS). */ len = WideCharToMultiByte(CP_ACP, 0, pAA->FriendlyName, wcslen(pAA->FriendlyName), szAdapterName, sizeof(szAdapterName), NULL, NULL); if (len == 0) { fprintf(stderr, "cannot convert adapter name\n"); exit(1); } szAdapterName[len] = '\0'; printf("Adapter Name : %s\n", szAdapterName); /* * * Display the adapter name (UID format) using the AdapterName member. */ printf(" Adapter UID = %s\n", pAA->AdapterName); /* * Display the adapter description from the Description member. */ /* Since Description is encoded in Unicode, */ /* convert it into multi-byte characters (Shift JIS). */ len = WideCharToMultiByte(CP_ACP, 0, pAA->Description, wcslen(pAA->Description), szAdapterDescription, sizeof(szAdapterDescription), NULL, NULL); if (len == 0) { fprintf(stderr, "cannot convert adapter description\n"); exit(1); } szAdapterDescription[len] = '\0'; printf(" Description : %s\n", szAdapterDescription); /* * Display the adapterfs media type using IfType member. */ printf(" Type : %s\n", getString_IfType(pAA->IfType)); /* * Display the adapterfs status using the OperStatus member. */ printf(" Operational Status : %s\n", getString_IF_OPER_STATUS(pAA->OperStatus)); /* * Display the unicast address given to the adapter * using the FirstUnicastAddress member. */ for (i = 0, pUnicastAddress = pAA->FirstUnicastAddress; pUnicastAddress; i++, pUnicastAddress = pUnicastAddress->Next) { char szAddress[NI_MAXHOST]; char szValidLifetime[BUFSIZ]; char szPreferredLifetime[BUFSIZ]; char szLeaseLifetime[BUFSIZ]; /* * Process for displaying unicast address */ /* Convert the address stored in network format (binary) */ /* into a human-readable character string (presentation format). */ if (getnameinfo(pUnicastAddress->Address.lpSockaddr, pUnicastAddress->Address.iSockaddrLength, szAddress, sizeof(szAddress), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "can't convert network format to presentation format"); exit(1); } /* Display the unicast address character string. */ printf(" Unicast Address#%d\n", i); printf(" Family=%s, Addr=%s\n", ((pUnicastAddress->Address.lpSockaddr)->sa_family == AF_INET) ? "IPv4" : "IPv6", szAddress); /* Convert life span into a character string and display it. */ if (getString_Lifetime(szValidLifetime, sizeof(szValidLifetime), pUnicastAddress->ValidLifetime) == NULL) { fprintf(stderr, "cannot convert to string\n"); exit(1); } if (getString_Lifetime(szPreferredLifetime, sizeof(szPreferredLifetime), pUnicastAddress->PreferredLifetime) == NULL) { fprintf(stderr, "cannot convert to string\n"); exit(1); } if (getString_Lifetime(szLeaseLifetime, sizeof(szLeaseLifetime), pUnicastAddress->LeaseLifetime) == NULL) { fprintf(stderr, "cannot convert to string\n"); exit(1); } printf(" ValidLifetime=%s, " "PreferredLifetime=%s, " "LeaseLifetime=%s\n", szValidLifetime, szPreferredLifetime, szLeaseLifetime); /* * Display the IP address origin (PREFIX, SUFFIX). */ printf(" prefix origin : %s\n", getString_IP_PREFIX_ORIGIN(pUnicastAddress->PrefixOrigin)); printf(" suffix origin : %s\n", getString_IP_SUFFIX_ORIGIN(pUnicastAddress->SuffixOrigin)); /* * Display the DAD status for IPv6 addresses. */ if ((pUnicastAddress->Address.lpSockaddr)->sa_family == AF_INET6) { printf(" DAD state : %s\n", getString_IP_DAD_STATE(pUnicastAddress->DadState)); } } /* * Display anycast address using the FirstAnycastAddress member. */ for (i = 0, pAnycastAddress = pAA->FirstAnycastAddress; pAnycastAddress; i++, pAnycastAddress = pAnycastAddress->Next) { char szAddress[NI_MAXHOST]; /* * Process for displaying anycast address */ /* Convert the address stored in network format (binary) */ /* into a human-readable character string (presentation format). */ if (getnameinfo(pAnycastAddress->Address.lpSockaddr, pAnycastAddress->Address.iSockaddrLength, szAddress, sizeof(szAddress), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "can't convert network format to presentation format"); exit(1); } /* Display anycast address character string. */ printf(" Anycast Address#%d\n", i); printf(" Family=%s, Addr=%s\n", ((pAnycastAddress->Address.lpSockaddr)->sa_family == AF_INET) ? "IPv4" : "IPv6", szAddress); } /* * Display multicast address using the FirstMulticastAddress member. */ for (i = 0, pMulticastAddress = pAA->FirstMulticastAddress; pMulticastAddress; i++, pMulticastAddress = pMulticastAddress->Next) { char szAddress[NI_MAXHOST]; /* * Process for displaying multicast address */ /* Convert the address stored in network format (binary) */ /* into a human-readable character string (presentation format). */ if (getnameinfo(pMulticastAddress->Address.lpSockaddr, pMulticastAddress->Address.iSockaddrLength, szAddress, sizeof(szAddress), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "can't convert network format to presentation format"); exit(1); } /* Display the multicast address character string. */ printf(" Multicast Address#%d\n", i); printf(" Family=%s, Addr=%s\n", ((pMulticastAddress->Address.lpSockaddr)->sa_family == AF_INET) ? "IPv4" : "IPv6", szAddress); } /* * Display DNS server address using the FirstDnsServerAddress member. */ for (i = 0, pDnsServerAddress = pAA->FirstDnsServerAddress; pDnsServerAddress; i++, pDnsServerAddress = pDnsServerAddress->Next) { char szAddress[NI_MAXHOST]; /* * Process for displaying DNS server address */ /* Convert the address stored in network format (binary) */ /* into a human-readable character string (presentation format). */ if (getnameinfo(pDnsServerAddress->Address.lpSockaddr, pDnsServerAddress->Address.iSockaddrLength, szAddress, sizeof(szAddress), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "can't convert network format to presentation format"); exit(1); } /* Display DNS server address character string. */ printf(" DNS Server Address#%d\n", i); printf(" Family=%s, Addr=%s\n", ((pDnsServerAddress->Address.lpSockaddr)->sa_family == AF_INET) ? "IPv4" : "IPv6", szAddress); } /* * Display DNS suffix (domain name) using the DnsSuffix member. */ /* Since DnsSuffix is encoded in Unicode, */ /* convert it to multi-byte characters (Shift JIS). */ if (wcslen(pAA->DnsSuffix) != 0) { len = WideCharToMultiByte(CP_ACP, 0, pAA->DnsSuffix, wcslen(pAA->DnsSuffix), szDnsSuffix, sizeof(szDnsSuffix), NULL, NULL); if (len == 0) { fprintf(stderr, "cannot convert DNS suffix\n"); exit(1); } szDnsSuffix[len] = '\0'; printf(" DNS suffix : %s\n", szDnsSuffix); } /* * Display the adapterfs physical address (MAC address) * using the PhysicalAddress and PhysicalAddressLength members. */ if (pAA->PhysicalAddressLength != 0) { printf(" PhysicalAddress : "); for (i = 0; i < pAA->PhysicalAddressLength - 1; ++i) printf("%02X:", pAA->PhysicalAddress[i]); printf("%02X\n", pAA->PhysicalAddress[pAA->PhysicalAddressLength - 1]); } /* * Display the adapterfs MTU value using the Mtu member. */ printf(" MTU : %d\n", pAA->Mtu); /* * Display the interface index using the Ipv6IfIndex member. * fe80::1%6 --- The number written after % matches the number that indicates the adapter. */ printf(" IPv6 Interface Index : %d\n", pAA->Ipv6IfIndex); /* * Display the adapterfs attributes using the Flags member. */ if (getString_AdapterFlags(szFlagsString, sizeof(szFlagsString), pAA->Flags) == NULL) { fprintf(stderr, "cannot convert to string\n"); exit(1); } printf(" Flags: %s\n", szFlagsString); /* * Display zone information using the ZoneIndices member. */ printf(" Zone Info: if %d, link %d, subnet %d, admin %d, site %d, " "org %d, global %d\n", pAA->ZoneIndices[ScopeLevelInterface], pAA->ZoneIndices[ScopeLevelLink], pAA->ZoneIndices[ScopeLevelSubnet], pAA->ZoneIndices[ScopeLevelAdmin], pAA->ZoneIndices[ScopeLevelSite], pAA->ZoneIndices[ScopeLevelOrganization], pAA->ZoneIndices[ScopeLevelGlobal]); /* * Display the adapterfs prefix using the FirstPrefix member. */ for (i = 0, pIpAdapterPrefix= pAA->FirstPrefix; pIpAdapterPrefix; i++, pIpAdapterPrefix = pIpAdapterPrefix->Next) { char szAddress[NI_MAXHOST]; if (getnameinfo(pIpAdapterPrefix->Address.lpSockaddr, pIpAdapterPrefix->Address.iSockaddrLength, szAddress, sizeof(szAddress), NULL, 0, NI_NUMERICHOST)) { fprintf(stderr, "can't convert network format to presentation format"); exit(1); } printf(" Prefix#%d\n", i); switch((pIpAdapterPrefix->Address.lpSockaddr)->sa_family) { case AF_INET: printf(" Family=IPv4, Addr=%s\n", szAddress); break; case AF_INET6: printf(" Family=IPv6, Addr=%s/64\n", szAddress); break; default: printf(" Family=Unknown, Addr=%s\n", szAddress); } } putchar('\n'); } /* * Free the space that was used to store the adapter information. */ free(pAdapterAddresses); /* * Clean up WinSock. */ WSACleanup(); exit(0); }