Protokoł ARP. - Uniwersytet Opolski
Transkrypt
Protokoł ARP. - Uniwersytet Opolski
Protokół ARP Aplikacja printarp dr Zbigniew Lipiński Instytut Matematyki i Informatyki ul. Oleska 48 50-204 Opole [email protected] Address Resolution Protocol ARP, (ang.) Address Resolution Protocol. RFC 826. Protokół ARP jest protokołem warstwy Sieci modelu referencyjnego OSI. Protokół ARP należy do rodziny protokołów TCP/IP. Protokół ARP służy do znajdowania adresów fizycznych kart sieciowych (adresów MAC) na podstawie adresów IP. Protokół ARP służy do: • wysyłania zapytań do sieci o adres MAC, • uaktualniania tablic arp. 2 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura nagłówka komunikatu ARP Bity 4 1 1 2 8 12 16 20 Typ adresu nadawcy Dl. adresu MAC 24 28 32 Typ adresu odbiorcy Dl. adresu protokolu Operacja Pierwsze 32 bity adresu MAC nadawcy 3 Ostanie 16 bitow adresu MAC nadawcy Pierwsze 16 bitow adresu protokolu nadawcy 4 Ostatnie16 bitow adresu protokolu nadawcy Pierwsze 16 bitow adresu MAC odbiorcy 5 Ostatnie 32 bity adresu MAC odbiorcy 6 Ostatnie32 bity adresu protokolu odbiorcy Struktura komunikatu ARP 3 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura nagłówka komunikatu ARP Pole: Typ adresu fizycznego, (Hardware Type). Wielkość: 16 bitów. Pole określa typ adresu MAC (typ karty sieciowej). Typy adresów. Wartość: 1 (Ethernet), 2 (Experimental Ethernet), 3 (X.25), 4 (Proteon ProNET - Token Ring), 5 (Chaos), 6 (IEEE 802.X), 7 (ARCnet). Pole: Typ adresu protokołu, (Protocol Type). Wielkość: 16 bitów. Pole określa typ protokołu jakiego użył host wysyłający zapytanie. Dla rodziny TCP/IP użyty protokół jest typu 'Ethernet'. Pole: Dł. adresu MAC, (Hardware Address Length). Wielkość: 8 bitów. Długość (wyrażona w bajtach) adresu fizycznego w datagramie. Dla adresu MAC wartość = 6 bajtów. Pole: Dł. adresu protokołu, (Protocol Address Length). Wielkość: 8 bitów. Długość (wyrażona w bajtach) adresu protokołu. Dla adresu IP wartość pola = 4 bajty. Pole: Operacja, (Operation Code, Opcode). Wielkość: 16 bitów. Wartość kodu 1 dla wiadomości typu 'ARP reply' (odpowiedz), Wartość kodu 2 dla wiadomości typu 'ARP request' (zapytanie). Pole: Adres MAC nadawcy, (Sender Hardware Address). Wielkość: wartość z pola 'Hardware Address Length'. Adres MAC hosta wysyłającego ARP request. Pole: Adres nadawcy, (Sender Protocol Address). Wielkość: wartość z pola 'Protocol Address Length'. Adres IP hosta wysyłającego ARP request. Pole: Adres MAC odbiorcy, (Target Hardware Address). Wielkość: wartość z pola 'Hardware Address Length'. Adres MAC hosta odbierającego wiadomość. Pole: Adres odbiorcy, (Target Protocol Address). Wielkość: wartość z pola 'Protocol Address Length'. Adres IP hosta odbierającego wiadomość. 4 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura adresu MAC karty sieciowej Przykład: Adres fizyczny 00-B0-D0-2C-FC-B6 Pole I/G. Wartości: 0/1. 1 bit. Znaczenie: adres Indywidualny/Grupowy. Pole U/L. Wartości: 0/1. 1 bit. Znaczenie: adres Uniwersalny/Lokalny. Adres Univerwersaly: Karty sieciowe uniwersalne są zgodne ze standardem IEEE. Adres Lokalny: Karty z takim adresem mogą nie być zgodne ze standardem IEEE. Pole OUI (Organization Unique Identifier). 22 bity. Część adresu MAC określająca producenta karty sieciowej. Pole 24 bity. Znaczenie: numer karty sieciowej. Numer karty sieciowej przydzielany przez producenta karty. Przykłady kodów producentów kart: 00000C Cisco 0000D8 3Com, Novell PS/2 0080C2 IEEE 802.1 Committee 00AA00 Intel 02608C 3Com IBM PC; Imagen; Valid; Cisco 080020 Sun machines Przykład: Karta o adresie 08:00:20:00:70:DF została wyprodukowana przez Sun Microsystems. 5 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja projektu Nazwa projektu: IpArp Typ projektu : Win32 console application Lista plików : IpArp.cpp Kompilacja : Microsoft Visual C++ 2008. Wkopiować pliki svcrt.lib iphlpapi.lib WS2_32.Lib do katalog projektu. W Project-> Setings-> Link-> Object/Library Modules-> Dodać: WS2_32.Lib iphlpapi.lib Funkcjonalność: \> printarp // kieruje na ekran zawartość tablicy arp. Przykład: \>printarp \> Interfejs: 10.60.17.94 --- 0x2 Adres internetowy Adres fizyczny Typ 10.60.17.5 00-02-a5-cd-37-c4 dynamiczne 6 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura progamu Pliki nagłówkowe: windows.h, iphlpapi.h, iptypes.h, iostream. Funkcje programu: WSAStartup(), WSACleanup(), inet_ntoa(), GetIpNetTable(), GetIpAddrTable() PrintIpNetTable(), MyGetIpNetTable(), MyGetIpAddrTable(), PhysAddrToString(), StringToPhysAddr(), InterfaceIdxToInterfaceIp(), Struktury programu: WSADATA, MIB_IPNETTABLE, MIB_IPADDRTABLE, in_addr, MIB_IPNETROW Zmienne programu: WORD wVersionRequested = MAKEWORD(1,1); WSADATA wsaData; int nRet; DWORD dwStatus; PMIB_IPNETTABLE pIpArpTab = NULL; 7 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja Struktury WSADATA Nazwa struktury : WSADATA Opis : Struktura WSADATA zawiera informacje o implementacji gniazd (Windows Sockets). Struktura WSADATA jest zadeklarowana w pliku Winsock2.h. Aplikacja nie powinna używać atrybutów iMaxsockets, iMaxUdpDg, i lpVendorInfo struktury WSAData gdy wartość atrybutu wVersion, po wywołaniu WSAStartup jest co najmniej 2. Wyjaśnienie: This is because the architecture of Windows Sockets has been changed in version 2 to support multiple providers, and WSAData no longer applies to a single vendor's stack. Two new socket options are introduced to supply provider- specific information: SO_MAX_MSG_SIZE (replaces the iMaxUdpDg element) and PVD_CONFIG (allows any other provider-specific configuration to occur). Atrybuty : wVersion - Wersja gniazd WinSock którą ma używać biblioteka Ws2_32.dll. wHighVersion - Najwyższa wersja WinSock jaką może używać biblioteka .dll. Standardowo, wartość taka sama, jak wVersion. szDescription - Zerem zakończony string znaków ASCI (null-terminated ASCII string) do którego Ws2_32.dll kopiuje opis implementacji gniazd. Tekst (do 256 znaków) może być używany do opisów wiadomości. szSystemStatus - Zakończony zerem string znaków ASCI do którego WSs2_32.dll kopiuje informacje o statusie lub konfiguracji. Ws2_32.dll powinna używać tego atrybutu do tylko gdy informacje mogą być ważne dla użytkowników, atrybut nie powinien być traktowany jako rozszerzenie zmiennej szDescription. iMaxSockets - Pozostawiony dla zgodności poprzednimi wersjami gniazd. Parametr powinien być ignorowany przez Windows Socketsv.2 i wersje późniejsze (nie ma już jednej wartości dla wszystkich dostarczycieli usług). iMaxUdpDg - Atrybut ignorowany przez gniazda wersji 2 i następne. iMaxUdpDg pozostawiony dla zgodności z wersją gniazd Windows Sockets 1.1. Nie powinien być używany przy budowaniu nowych aplikacji. Dla określenia wielkości wiadomości dostarczyciela usług dla gniazda i typu gniazda aplikacje powinny używać getsockopt aby uzyskać wartość opcji SO_MAX_MSG_SIZE. lpVendorInfo - Atrybut ignorowany przez Windows Sockets v.2 i następne. lpVendorInfo pozostawiono dla zgodności z wersją gniazd Windows Sockets 1.1. Dla określenia konfiguracji dostarczyciela usług dla gniazda powinny używać getsockopt aby uzyskać wartość opcji PVD_CONFIG. 8 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja struktury MIB_IPNETTABLE Nazwa struktury : MIB_IPNETTABLE Opis Atrybuty : Struktura MIB_IPNETTABLE zawiera tablicę z danymi ARP. : dwNumEntries – Liczba rekordów w tabeli ARP. table - Wskaźnik do tablicy ARP implementowanej jako tablica struktur MIB_IPNETROW. Implementacja struktury MIB_IPNETTABLE: typedef struct _MIB_IPNETTABLE { DWORD dwNumEntries; MIB_IPNETROW table[ANY_SIZE]; } MIB_IPNETTABLE, *PMIB_IPNETTABLE; 9 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja struktury MIB_IPNETROW Nazwa struktury: MIB_IPNETROW Opis Atrybuty : Struktura MIB_IPNETROW zawiera dane do rekordów tablicy ARP. : dwIndex - Indeks karty sieciowej. dwPhysAddrLen - Długość adresu fizycznego karty sieciowej. bPhysAddr - Określa adres fizyczny karty sieciowej. dwAddr - Określa adres IP karty sieciowej. dwType - Określa typ rekordu ARP. Możliwe typy rekordów ARP: 4 Static, 3 Dynamic, 2 Invalid, 1 inne. Implementacja struktury MIB_IPNETROW: typedef struct _MIB_IPNETROW { DWORD dwIndex; DWORD dwPhysAddrLen; BYTE bPhysAddr[MAXLEN_PHYSADDR]; DWORD dwAddr; DWORD dwType; } MIB_IPNETROW, *PMIB_IPNETROW; 10 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja struktury MIB_IPADDRTABLE Nazwa struktury: MIB_IPADDRTABLE Opis Atrybuty : Struktura MIB_IPADDRTABLE zawiera tablicę adresów IP. : dwNumEntries – table – Określa numer adresu IP w tablicy. Wskaźnik do rekordu w tablicy implementowanej jako tablica struktur MIB_IPADDRROW. Implementacja struktury PMIB_IPADDRTABLE: typedef struct _MIB_IPADDRTABLE { DWORD dwNumEntries; MIB_IPADDRROW table[ANY_SIZE]; } MIB_IPADDRTABLE, *PMIB_IPADDRTABLE; typedef struct _MIB_IPADDRROW { DWORD dwAddr; //The IPv4 address in network byte order. DWORD dwIndex; // Index of nterface associated with this IPv4 address. DWORD dwMask; // Subnet mask for the IPv4 address in network byte order. DWORD dwBCastAddr; // The broadcast address in network byte order. DWORD dwReasmSize; // Maximum re-assembly size for received datagrams. unsigned short unused1; unsigned short wType; // The address type or state. } MIB_IPADDRROW, *PMIB_IPADDRROW; 11 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja struktury in_addr Nazwa struktury : in_addr Opis: Struktura in_addr adres IP hosta. Struktura zdefiniowana w WINSOCK.H Atrybuty : S_un_b - adres hosta w formacie u_chars. S_un_w adres hosta w formacie dwóch u_shorts. S_addr adres hosta w formacie u_long. Implementacja struktury in_addr: struct { in_addr union { struct { unsigned char s_b1, s_b2, s_b3, s_b4; } S_un_b; struct { unsigned short s_w1, s_w2; } S_un_w; unsigned long S_addr; } S_un; }; 12 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji WSAStartup() Nazwa funkcji : WSAStartup() Zwracana wartość: int WSAStartup() zwraca zero gdy wywołanie funkcji zakończyło się sukcesem. W innym przypadku zwraca następujące kody błędów: WSASYSNOTREADY – Wskazuje, że sieć lub podsieć nie jest przygotowana do transmisji danych. WSAVERNOTSUPPORTED – Żądana wersja WinSock nie jest obsługiwana przez implementację WinSock. WSAEINPROGRESS – Trwa operacja blokowania WinSock 1.1 WSAEPROCLIM Osiągnięto granicę liczby zadań dopuszczalną przez WinSock. WSAEFAULT Błędna wartość wskaźnika lpWSAData (not a valid pointer). Argumenty: WORD wVersionRequested - LPWSADATA lpWSAData Opis: [in] Najwyższa obsługiwana wersja WinSock, którą nadawca (caler) może użyć. Bajt najwyższy określa minimalną wersję, najniższy bajt określa maksymalna wersję. [out] Wskaźnik do struktury WSADATA. Funkcja WSAStartup() inicjuje użycie przez proces biblioteki WS2_32.DLL. Funkcja WSAStartup() musi być pierwszą funkcja Windows Sockets wywołana przez aplikacje. 13 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji WSACleanup() Nazwa funkcji: WSACleanup() Zwracana wartość: int WSACleanup() zwraca zero gdy wywołanie funkcji zakończyło się sukcesem. W innym przypadku zwraca SOCKET_ERROR, i określony kod błędu może być uzyskany poprzez wywołanie finkcji WSAGetLastError(): WSANOTINITIALISED - Przed wywołaniem tej funkcji WSACleanup() musi być wywołana z sukcesem funkcja WSAStartup(). WSAENETDOWN Awaria sieci (network subsystem has failed). WSAEINPROGRESS Trwa operacja blokowania WinSock 1.1 lub dostarczyciel usługi (service provider) obsługuje komunikat zwrotny (a callback function). Argumenty: brak Opis: Funkcja WSACleanup() kończy użycie biblioteki WS2_32.DLL. 14 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji inet_ntoa() Nazwa funkcji: inet_ntoa() Zwracana wartość: char* FAR Jeżeli nie ma błędów inet_ntoa() zwraca wskaźnik char* do statycznego bufora zawierającego adres w standardzie kropkowanym. W pozostałych przypadkach funkcja zwraca NULL. Argumenty Opis : : struct in_addr in in - [in] Wskaźnik do struktury in_addr reprezentującej adres IP hosta. Funkcja inet_ntoa() konwertuje adres IPv4 na adres w formacie kropkowanym (dotted format). 15 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji inet_addr() Nazwa funkcji : inet_addr() Zwracana wartość: unsigned long Argumenty Opis : const char* cp cp - [in] Zerem zakończony string znaków reprezentujący adres IP zapisany w notacji kropkowanej (np. 127.0.0.1). : Funkcja inet_addr() konwertuje string zawierający adres IPv4 w wersji kropkowanej na odpowiedni adres w strukturze IN_ADDR. 16 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji GetIpNetTable() Nazwa funkcji : GetIpNetTable() Zwracana wartość: DWORD Argumenty : pIpNetTable - [out] Wskaźnik do bufora który przechowuje adres tablicę danych ‘adres IP- adres MAC’ w strukturze MIB_IPNETTABLE. pdwSize - [in, out] Na wejściu wskaźnik do zmiennej przechowującej wielkość bufora (zmiennej wskazywanej przez pIpNetTable). Na wyjściu, jeżeli bufor jest za mały na zwracaną tablicę danych, funkcja ustawia wartość tego parametru na wielkość wymaganą. bOrder - [in] Argument określa czy zwracana tablica ma być uporządkowana według rosnących adresów IP (tablica jest uporządkowana gdy parametr ma wartość TRUE. Opis : Funkcja pobiera dane zawierające przyporządkowanie adres ‘IP adres MAC’ (tablica ARP). Deklaracja funkcji w pliku iphlpapi.h. 17 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Specyfikacja funkcji GetIpAddrTable() Nazwa funkcji : GetIpAddrTable() Zwracana wartość: DWORD Argumenty : pIpAddrTable - [out] Wskaźnik do bufora który przechowuje adres tablicę danych ‘karta - adres IP’ w strukturze MIB_IPADDRTABLE. pdwSize - [in, out] Na wejściu wskaźnik do zmiennej przechowującej wielkość bufora (zmiennej wskazywanej przez pIpAddrTable). Na wyjściu, jeżeli bufor jest za mały na zwracaną tablicę danych, funkcja ustawia wartość tego parametru na wielkość wymaganą. bOrder - [in] Argument określa czy zwracana tablica ma być uporządkowana według rosnących adresów IP (tablica jest uporządkowana gdy parametr ma wartość TRUE. Opis : Funkcja GetIpAddrTable() pobiera dane o przyporządkowaniu karty sieciowej do adresu IP. 18 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Implementacja funkcji InterfaceIdxToInterfaceIp() bool InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[]) { struct in_addr inadTmp; char *szIpAddr; if (pIpAddrTable == NULL || str == NULL) return FALSE; str[0] = '\0'; for (DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++) { if (dwIndex == pIpAddrTable->table[dwIdx].dwIndex) { inadTmp.s_addr = pIpAddrTable->table[dwIdx].dwAddr; szIpAddr = inet_ntoa(inadTmp); if (szIpAddr) { strcpy(str, szIpAddr); return TRUE; } else return FALSE; } } return FALSE; } 19 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Implementacja funkcji StringToPhysAddr() int StringToPhysAddr(char* szInEther, char* szOutEther) { const char DASH = '-'; register char c; register int val; if (strlen(szInEther) != 17) return (-1); if (szInEther[2] != DASH || szInEther[5] != DASH || szInEther[8] != DASH || szInEther[8] != DASH || szInEther[14] != DASH) return (-1); if (!isxdigit(szInEther[0]) || !isxdigit(szInEther[1]) || !isxdigit(szInEther[3]) || !isxdigit(szInEther[4]) || !isxdigit(szInEther[6]) || !isxdigit(szInEther[7]) || !isxdigit(szInEther[9]) || !isxdigit(szInEther[10]) || !isxdigit(szInEther[12]) || !isxdigit(szInEther[13]) || !isxdigit(szInEther[15]) || !isxdigit(szInEther[16])) return (-1); for (int i = 0; i < 6; i++) { val = 0; c = toupper(szInEther[i*3]); c = c - (isdigit(c) ? '0' : ('A' - 10)); val += c; val = (val << 4); c = toupper(szInEther[i*3 + 1]); c = c - (isdigit(c) ? '0' : ('A' - 10)); val += c; szOutEther[i] = val; } return 0; 20 } Implementacja funkcji PhysAddrToString() bool PhysAddrToString(BYTE PhysAddr[], DWORD PhysAddrLen, char str[]) { if (PhysAddr == NULL || PhysAddrLen == 0 || str == NULL) return FALSE; str[0] = '\0'; for (DWORD dwIdx = 0; dwIdx < PhysAddrLen; dwIdx++) { if (dwIdx == PhysAddrLen-1) sprintf(str+(dwIdx*3), "%02X", ((int)PhysAddr[dwIdx])&0xff); else sprintf(str+(dwIdx*3), "%02X-", ((int)PhysAddr[dwIdx])&0xff); } return TRUE; } 21 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Implementacja funkcji PrintIpNetTable() void PrintIpNetTable(PMIB_IPNETTABLE pIpNetTable) { DWORD i, dwStatus, dwCurrIndex; struct in_addr inadTmp; char szPrintablePhysAddr[256]; char szType[128]; char szIpAddr[128]; PMIB_IPADDRTABLE pIpAddrTable = NULL; if (pIpNetTable == NULL) { printf( "pIpNetTable == NULL in line %d\n", __LINE__); return; } if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR) { printf("GetIpAddrTable returned 0x%x\n", dwStatus); if (pIpAddrTable) delete [] pIpAddrTable; return; } dwCurrIndex = pIpNetTable->table[0].dwIndex; if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr)) { printf("\nInterface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex); printf(" Internet Address Physical Address Type\n"); } else { printf("Error: Could not convert Interface number 0x%X to IP address.\n", pIpNetTable->table[0].dwIndex); return; } Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego 22 Implementacja funkcji PrintIpNetTable() for (i = 0; i < pIpNetTable->dwNumEntries; ++i) { if (pIpNetTable->table[i].dwIndex != dwCurrIndex) { dwCurrIndex = pIpNetTable->table[i].dwIndex; if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr)) { printf("Interface: %s on Interface 0x%X\n", szIpAddr, dwCurrIndex); Physical Address Type\n"); printf(" Internet Address } else { printf("Error: Could not convert Interface number 0x%X to IP address.\n", pIpNetTable->table[0].dwIndex); return; } } PhysAddrToString(pIpNetTable->table[i].bPhysAddr, pIpNetTable->table[i].dwPhysAddrLen, szPrintablePhysAddr); inadTmp.s_addr = pIpNetTable->table[i].dwAddr; switch (pIpNetTable->table[i].dwType) { case 1: strcpy(szType,"other"); break; case 2: strcpy(szType,"invalidated"); break; case 3: strcpy(szType,"dynamic"); break; case 4: strcpy(szType,"static"); break; default: strcpy(szType,"invalidType"); } printf(" %-16s %-17s %-11s\n", inet_ntoa(inadTmp), szPrintablePhysAddr, szType); } if (pIpAddrTable) delete [] pIpAddrTable; } 23 Implementacja funkcji MyGetIpNetTable() DWORD MyGetIpNetTable(PMIB_IPNETTABLE& pIpNetTable, bool fOrder) { DWORD status = NO_ERROR; DWORD statusRetry = NO_ERROR; DWORD dwActualSize = 0; dwActualSize = 0; status = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder); if (status == NO_ERROR) { return status; } else if (status == ERROR_INSUFFICIENT_BUFFER) { pIpNetTable = new MIB_IPNETTABLE [dwActualSize]; statusRetry = GetIpNetTable(pIpNetTable, &dwActualSize, fOrder); 24 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Implementacja funkcji MyGetIpNetTable() if (statusRetry != NO_ERROR) { #ifdef _DEBUG printf("Retry failed.\n"); #endif return statusRetry; } else { return statusRetry; } } else { #ifdef _DEBUG printf("first getipnettable call failed\n"); #endif return status; } } 25 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Implementacja funkcji MyGetIpAddrTable() DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE& pIpAddrTable, bool fOrder) { DWORD status = NO_ERROR; DWORD statusRetry = NO_ERROR; DWORD dwActualSize = 0; // query for buffer size needed status = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder); if (status == NO_ERROR) { printf("No error\n"); return status; } else if (status == ERROR_INSUFFICIENT_BUFFER) { pIpAddrTable = new MIB_IPADDRTABLE [dwActualSize]; statusRetry = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder); return statusRetry; } else { return status; } } 26 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura programu 1. Sprawdzenie wersji winsock. nRet = WSAStartup(wVersionRequested, &wsaData); Czy wsaData.wVersion != wVersionRequested ? 2. Pobranie danych z tablic arp dwStatus = MyGetIpNetTable(pIpArpTab, TRUE)) == NO_ERROR 3. Przekazanie na ekran dnaych o tablicy arp. PrintIpNetTable(pIpArpTab); 4. Zakończenie użycia biblioteki winsock WS2_32.DLL. WSACleanup(); 27 Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego Struktura funkcji main() int main(int argc, char **argv) { WORD wVersionRequested = MAKEWORD(1,1); WSADATA wsaData; int nRet; nRet = WSAStartup(wVersionRequested, &wsaData); if (wsaData.wVersion != wVersionRequested) { cerr << "WinSock version: " << LOBYTE(wVersionRequested) <<"." << HIBYTE(wVersionRequested) << " not supported" << endl; WSACleanup(); return 1; } DWORD dwStatus; PMIB_IPNETTABLE pIpArpTab = NULL; if ( (dwStatus = MyGetIpNetTable(pIpArpTab, TRUE)) == NO_ERROR) { PrintIpNetTable(pIpArpTab); delete [] pIpArpTab; return 1; } else if ( dwStatus == ERROR_NO_DATA) { cerr << "No entries in arp cache." <<endl; return 1; } else { if (pIpArpTab) delete [] pIpArpTab; cout <<"IpArp returned: " << dwStatus << endl; return 1; } WSACleanup(); return 0; } 28