Komunikacja z serwerem uslugi DNS.

Transkrypt

Komunikacja z serwerem uslugi DNS.
Protokół DNS
Domain Name System
Aplikacja dnsquery
dr Zbigniew Lipiński
Instytut Matematyki i Informatyki
ul. Oleska 48
50-204 Opole
[email protected]
Protokół DNS
DNS, (ang.) Domain Name System.
Specyfikacje protokołu i usługi DNS:
RFC 1034, P.V. Mockapetris, Domain names - concepts and facilities.
RFC 1035, P.V. Mockapetris, Domain names - implementation and specification.
RFC 1995, M. Ohta, Incremental Zone Transfer in DNS.
RFC 2136, P. Vixie, Ed., S. Thomson, Y. Rekhter, Dynamic Updates in the Domain Name System (DNS UPDATE).
RFC 2181, R. Elz, R. Bush, Clarifications to the DNS Specification.
RFC 2308. M. Andrews, Negative Caching of DNS Queries (DNS NCACHE).
RFC 2537, D. Eastlake, RSA/MD5 KEYs and SIGs in the Domain Name System (DNS).
RFC 3596, S. Thomson, C. Huitema, V. Ksinant, M. Souissi, DNS Extensions to Support IP Version 6.
W warstwie transportowej modelu referencyjnego dla OSI protokół DNS wykorzystuje:
• protokół UDP, port serwera DNS 53,
• protokół TCP, port serwera DNS 53.
Wiadomości przesyłane w protokole UDP mogą mieć maks. wielkość 512 bajtów (bez nagłówka IP, UDP).
Protokół UDP stosowany jest do standardowych zapytań do serwera nazw.
Do transferu informacji o strafach serwery nazw powinny stosować protokół TCP.
2
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Protokół i usługa DNS
Protokół DNS wykorzystywany jest przez usługę DNS, (ang.) Domain Name System Service.
Domain Name System jest hierarchiczna, rozproszoną bazą danych.
System DNS definiuje:
•
schemat baz DNS,
•
mechanizm zapytań i uaktualniania danych w bazach DNS,
•
mechanizm replikacji danych między bazami.
Usługa DNS pozwala użytkownikom sieci na posługiwanie się do lokalizacji sieci, hostów, usług nazw dns’owych
('naturalnych’ nazw i adresów) zamiast adresów IP.
Usługa DNS służy do tłumaczenia nazw sieci (nazw domen), dns’owych nazw hostów, dns’owych adresów serwerów
usług, URL na ich adresy IP.
Usługa DNS została zaimplementowana po raz pierwszy:
•
w 1984 w systemie Windows NT Server 4,
•
w systemie UNIX BSD 4.3, jako BIND, (ang.) Berkeley Internet Name Domain (1986).
3
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Komponenty systemu DNS
Komponenty systemu DNS:
•
DOMAIN NAME SPACE - struktura (hierarchia) drzewa nazw w domenach.
•
RESOURCE RECORDS - struktura danych w bazach DNS.
•
NAME SERVERS -
serwery nazw, oprogramowanie służące do wykonywania operacji na bazach DNS.
•
RESOLVERS -
programy które pośredniczą w komunikacji między programem użytkownika a
serwerami nazw. Resolvery znajdują się po stronie klienta i serwera.
Zewnetrzny
serwer nazw
Baza DNS
Program
Uzytkownika
Pytanie
Pytanie
Resolver
Serwer nazw
Odpowiedz
Odpowiedz
Pytanie
Odpowiedz
cache
Baza DNS
Konfiguracja uslugi DNS
4
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Protokół i usługa DNS
Usługa DNS wprowadza hierarchie nazw dla sieci, podsieci w Internecie.
Hosty, podsieci, sieci grupowane są w domeny dn’sowe.
Domena -
jest zbiorem hostów, zbiorem sieci charakteryzujących się wspólnymi zasadami zarządzania, bezpieczeństwa,
wspólną nazwą.
Domeny, i ich nazwy, posiadają hierarchiczną strukturę.
Na szczycie hierarchii znajduje się domena główna (root domain).
Informacja o domenach jest zawarta w rozproszonej bazie, znajdujących się na serwerach nazw (name
servers).
Strefa
-
(ang.) zone, podzbiór obszaru nazw DNS zarządzany przez jeden serwer nazw.
Nazwa domeny - to ciąg nazw poszczególnych obszarów w hierarchii domeny oddzielonych kropkami.
Przykład:
Nazwa domeny.
math.uni.opole.pl
Przykład:
Nazwa hosta w domenie math.uni.opole.pl o netbiosowej nazwie host1.
host1.math.uni.opole.pl
5
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Narzędzie nslookup
RFC 2151, G. Kessler, S. Sheppard,'A Primer On Internet and TCP/IP Tools and Utilities', 1997.
Nslookup narzędzie umożliwiające wyszukiwanie danych na serwerach DNS, służące również do testowania połączeń z
serwerem DNS.
Składnia:
nslookup [-opcja] [nazwa_hosta] [serwer]
Wybrae opcje:
all
- drukuje opcje, informacje o bieżącym serwerze i hoście
[no]defname
- dołącza nazwę domeny do każdej kwerendy
[no]recurse
- prosi o rekurencyjną odpowiedź na kwerendę
[no]search
- używa listy przeszukiwania domen
domain=NAZWA
- ustawia domyślną nazwę domeny na NAZWA
srchlist=N1[/N2/.../N6] - ustawia domenę na N1, a listę przeszukiwania na N1, N2, itd.
root=NAZWA
- ustawia serwer główny na NAZWA
retry=X
- ustawia liczbę ponawianych prób na X
timeout=X
- ustawia początkowy limit czasu na X sekund
type=X
- ustawia typ kwerendy (np. A, ANY, CNAME, MX, NS, PTR, SOA, SRV)
class=X
- ustawia klasę zapytania (np. IN (Internet), ANY)
[no]msxfr
- używa szybkiego transferu strefy MS
ixfrver=X
- bieżąca wersja używana w żądaniu transferu IXFR
6
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury GUID
Nazwa struktury : GUID
Opis
Atrybuty
: Struktura GUID opisuje identyfikator obiektu ‘globally unique identifier’.
:
Data1 Data2 Data3 Data4 –
wartość unsigned long integer.
wartość unsigned short integer.
wartość unsigned short integer.
tablica unsigned characters.
Implementacja struktury GUID:
typedef struct _GUID
{
unsigned
unsigned
unsigned
unsigned
} GUID;
long
short
short
char
Data1;
Data2;
Data3;
Data4[8];
7
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury AFPROTOCOLS
Nazwa struktury : AFPROTOCOLS
Opis
Atrybuty
: Struktura AFPROTOCOLS dostarcza listę protokołów do jakich programiści mogą
ograniczyć zapytania.
:
iAddressFamily –
iProtocol –
Rodzina adresów do jakich zapytanie ma być ograniczone.
Protokół do jakiego zapytanie ma być ograniczone.
Implementacja struktury AFPROTOCOLS:
typedef struct _AFPROTOCOLS
{
INT iAddressFamily;
INT iProtocol;
} AFPROTOCOLS, *PAFPROTOCOLS, *LPAFPROTOCOLS;
8
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury AFPROTOCOLS
Tablica afproto[2]
Tablica afproto[2].
AFPROTOCOLS afproto[2] = { {AF_INET, IPPROTO_UDP}, {AF_INET, IPPROTO_TCP} };
AF_INET- oznacza rodzinę adresów TCP/IPv4, (inne wartości: AF_INET6, AF_UNSPEC).
Opcja gniazda: IPPROTO_UDP
Wartość: UDP_NOCHECKSUM
Typ: BOOL Jeżeli ta opcja jest ustawiona, datagramy UDP są wysyłane z zerową sumą kontrolną. Obsługa tej opcji jest
wymagana.
Jeżeli ‘service provider’ nie posiada mechanizmu blokowania liczenia sumy kontrolnej, może ignorować tą
opcję.
Opcja gniazda: IPPROTO_TCP Wartość: TCP_EXPEDITED_1122
RFC 11 22, R. Braden, Requirements for Internet Hosts - Communication Layers, 1989.
Typ: BOOL Jeżeli opcja jest ustawiona, ‘service provider’ implementuje format wysyłanych danych zgodnie ze
specyfikacją RFC-1222. W pozostałych przypadkach, jako format domyślny, używany jest format
‘Berkeley Software Distribution (BSD)’.
Opcja jest ustawiana dla połączenia tylko raz, tzn. nie może być zmieniana lub wyłączona w trakcie
połączenia. Opcja nie jest wymagana.
9
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury WSAQUERYSET
Nazwa struktury : WSAQUERYSET
Opis:
Struktura WSAQUERYSET dostarcza informacji o danej usłudze: ID klasy usługi (service class ID), nazwę
usługi, identyfikator obszaru nazw (name-space identifier), adresy IP z portami na których nasłuchuje
serwer usługi.
Atrybuty
:
dwSize –
Musi być wartość sizeof(WSAQuerySet). Parametr służy do określenia wersji.
lpszServiceInstanceName - Parametr opcjonalny. Wskaźnik do nazwy usługi.
lpServiceClassId Parametr wymagany. GUID dla danej klasy usługi.
lpVersion Parametr opcjonalny. Wskaźnik do zmiennej zawierającej wymaganą wersję.
lpszComment Parametr ignorowanych przy zapytaniach.
dwNameSpace Identyfikator obszaru nazw do którego ma być ograniczone przeszukiwane
informacji o usłudze (parametr NS_ALL oznacza przeszukiwanie wszystkich
obszarów nazw).
lpNSProviderId Parametr opcjonalny. Wskaźnik do GUID w określonym obszarze nazw ‘service
provider’, zapytania są ograniczane tylko do tego ‘sp’.
lpszContext Parametr opcjonalny. Wskaźnik określa początkowy obszar nazw do którego
będzie wysłane zapytanie.
dwNumberOfProtocols – Wielkość tablicy zawierającej listę protokołów do których ograniczone są
zapytania (w bajtach). Wartość może być zero.
lpafpProtocols Parametr opcjonalny. Wskazuje na tablice struktur AFPROTOCOLS. Only
services that utilize these protocols will be returned.
lpszQueryString Parametr opcjonalny. Pewne obszary nazw (jak Whois++) posiadają mechanizm
obsługi ‘enriched SQL-like queries’ które zawierają zapytania w formacie string txt.
Parametr służy do określania tego stringu.
dwNumberOfCsAddrs - Parametr ignorowanych przy zapytaniach.
lpcsaBuffer Parametr ignorowanych przy zapytaniach.
dwOutputFlags Parametr ignorowanych przy zapytaniach.
lpBlob Parametr opcjonalny. Wskaźnik do określonego ‘providera’ (pointer to a providerspecific entity).
10
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Implementacja struktury WSAQUERYSET
typedef struct _WSAQuerySet {
DWORD
dwSize;
LPTSTR
lpszServiceInstanceName;
LPGUID
lpServiceClassId;
LPWSAVERSION
lpVersion;
LPTSTR
lpszComment;
DWORD
dwNameSpace;
LPGUID
lpNSProviderId;
LPTSTR
lpszContext;
DWORD
dwNumberOfProtocols;
LPAFPROTOCOLS
lpafpProtocols;
LPTSTR
lpszQueryString;
DWORD
dwNumberOfCsAddrs;
LPCSADDR_INFO
pcsaBuffer;
DWORD
dwOutputFlags;
LPBLOB
pBlob;
} WSAQUERYSET, *PWSAQUERYSETW;
11
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury BLOB
Nazwa struktury : BLOB
Opis
:
Atrybuty :
Struktura BLOB, (wyznaczana z Binary Large Object) zawiera informację o bloku danych.
cbSize
pBlobData
- Wielkość bloku danych (w bajtach) wskazywany przez pBlobData.
- Wskaźnik do bloku danych.
Implementacja struktury BLOB:
typedef struct _BLOB {
ULONG
BYTE*
} BLOB;
cbSize;
pBlobData;
12
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja struktury hostent
Nazwa struktury : hostent
Opis
:
Struktura jest używana przez funkcje do przechowywania informacji o hoście.
Zadeklarowana w pliku Winsock2.h
Atrybuty
:
h_name –
Nazwa hosta. Jeżeli jest używany system DNS (lub podobny) zmienna zawiera pełną nazwę
DNS’ową hosta FQDN (ang. Fully Qualified Domain Name). W pliku hosts, wartość zmiennej jest
drugim wpisem po adresie IP.
h_aliases - Zerem zakończona tablica alternatywnych nazw hosta.
h_addrtype - Typ adresu.
h_length -
Długość w bajtach każdego adresu.
h_addr_list - Zerem zakończona lista adresów IP hosta. Adresy IP są zwracane w sieciowym
uporządkowaniu bajtów (Big Endian). Makro h_addr zastępuje h_addr_list[0] w celu
zgodności ze starszymi wersjami oprogramowania.
Przykład:
char *ServerName; LPHOSTENT hp;
SOCKADDR_IN AdresSerwera;
hp = gethostbyname(ServerName);
AdresSerwera.sin_addr.s_addr = hp->h_addr;
Implementacja struktury hostent:
typedef struct hostent
{
char FAR*
char FAR FAR**
short
short
char FAR FAR**
} hostent;
h_name;
h_aliases;
h_addrtype;
h_length;
h_addr_list;
13
Specyfikacja struktury sockaddr_in
Nazwa struktury: sockaddr_in
Opis
: Zawiera adres IP i numer portu odbiorcy danych.
Struktura zadeklarowana w pliku Winsock2.h (dla IPv4), ws2tcpip.h (dla IPv6).
Atrybuty
: short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8];
sin_family
Kod rodziny adresów TCP//IP (wartość musi być AF_INET).
sin_port
Numer portu (IP port).
sin_addr
Adres IP karty. Jeśli w polu jest wartość INADDR_ANY, to nasłuchiwanmnie
będzie prowadzone na wszystkich adresach, jakie posiada dany host.
sin_zero
Pole służy do uzupełniania tak, aby wielkość struktury była taka sama jak SOCKADDR.
Implementacja struktury sockaddr_in:
struct sockaddr_in {
short
unsigned short
struct in_addr
char
};
Przykład:
sin_family;
sin_port;
sin_addr;
sin_zero[8];
char *ServerName; LPHOSTENT hp;
SOCKADDR_IN AdresSerwera;
hp = gethostbyname(ServerName);
AdresSerwera.sin_addr.s_addr = hp->h_addr;
14
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 S_un_w S_addr -
adres hosta w formacie u_chars.
adres hosta w formacie dwóch u_shorts.
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;
};
15
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja funkcji FixList()
Nazwa funkcji
: FixList()
Zwracana wartość: void
Argumenty
: PCHAR ** , PCHAR
Opis
: Funkcja FixList() pobiera tablicę znaków zwróconą przez funkcję WSALookupServiceNext() modyfikuje
je poprzez dodanie znaku.
Implementacja funkcji FixList():
void FixList(PCHAR ** List, PCHAR Base)
{
if (*List)
{
PCHAR * Addr;
Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
while(*Addr)
{
*Addr = (PCHAR)(((DWORD)*Addr + Base));
Addr++;
}
}
}
16
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja funkcji UnpackHostEnt()
Nazwa funkcji
: UnpackHostEnt()
Zwracana wartość: void
Argumenty
Opis
: struct hostent *
: Funkcja UnpackHostEnt() dokleja do atrybutu h_name struktury hostent znak
pch = (PCHAR)hostent, jeżeli wartość atrybutu h_name jest zero wywołuje funkcję
FixList() (funkcja dołącza do atrybutu h_aliases, h_addr_list struktury hostent znak
pch = (PCHAR)hostent.
Implementacja funkcji UnpackHostEnt():
void UnpackHostEnt(struct hostent * hostent)
{
PCHAR pch;
pch = (PCHAR)hostent;
if(hostent->h_name)
{
hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
}
FixList(&hostent->h_aliases, pch);
FixList(&hostent->h_addr_list, pch);
}
17
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja funkcji WSALookupServiceBegin()
Nazwa funkcji : WSALookupServiceBegin()
Zwracana wartość: INT
Argumenty
:
lpqsRestrictions - [in] Wskaźnik od zmiennej zwierającej parametry wyszukiwania.
dwControlFlags - [in] Flaga służąca do kontroli ‘głębokości’ wyszukiwania:
LUP_DEEP, LUP_CONTAINERS, LUP_NOCONTAINERS, LUP_FLUSHCACHE,
LUP_FLUSHPREVIOUS, LUP_NEAREST, LUP_RES_SERVICE,
LUP_RETURN_ALIASES,LUP_RETURN_NAME, LUP_RETURN_TYPE,
LUP_RETURN_VERSION, LUP_RETURN_COMMENT, LUP_RETURN_ADDR,
LUP_RETURN_BLOB, LUP_RETURN_ALL
lphLookup - [out] Uchwyt do wywoływanej funkcji WSALookupServiceNext() w celu rozpoczęcia
uzyskiwania parametrów.
Opis
: Funkcja WSALookupServiceBegin() służy do inicjowania zapytań klienta o informacje dotyczące
graniczeń zapytań zawartych w strukturze WSAQUERYSET.
Funkcja WSALookupServiceBegin() tylko zwraca uchwyt który powinien być użyty przez kolejne zapytania
funkcją WSALookupServiceNext().
Nagłówek zadeklarowany w pliku Winsock2.h. Implementacja w pliku Use Ws2_32.lib.
18
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja funkcji WSALookupServiceNext()
Nazwa funkcji
: WSALookupServiceNext()
Zwracana wartość: INT
Funkcja zawraca zero gdy operacja zakończyła się sukcesem, jeśli nie to funkcja zwraca wartość
SOCKET_ERROR
Argumenty
:
hLookup - [in] Uchwyt zwrócony przez funkcje WSALookupServiceBegin().
dwControlFlags - [in] Flaga służąca do kontroli zapytania. Currently only LUP_FLUSHPREVIOUS is
defined as a means to cope with a result set which is too large. If an application does not (or cannot)
supply a large enough buffer, setting LUP_FLUSHPREVIOUS instructs the provider to discard the
last result set—which was too large—and move on to the next set for this call.
lpdwBufferLength - [in, out] Na wejściu, wskaźnik do zmiennej zawierającej liczbę bajtów w buforze
(wskazywanym przez lpqsResults. Na wyjściu, gdy funkcja nie zwróci kodu błędu WSAEFAULT,
wskaźnik wskazuje na minimalną liczbę bajtów jaką powinien zawierać bufor aby odebrać dane.
lpqsResults - [out] Wskaźnik do pamięci który zawiera strukturę WSAQUERYSET
Opis
:
Funkcja WSALookupServiceNext() jest wywoływana po uzyskaniu uchwytu od funkcji
WSALookupServiceBegin() w celu uzyskania informacji o usłudze.
‘Service provider’ zwraca dane w strukturze WSAQUERYSET do bufora wskazywanego przez lpqsResults.
Klient wywołuje tą funkcję tak długo aż funkcja nie zwróci WSA_E_NO_MORE (co oznacza, że wszystkie dane
WSAQUERYSET zostały zwrócone).
19
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja funkcji WSALookupServiceEnd()
Nazwa funkcji
: WSALookupServiceEnd()
Zwracana wartość: INT
Funkcja zawraca zero gdy operacja zakończyła się sukcesem, jeśli nie to funkcja zwraca wartość
SOCKET_ERROR
Argumenty
:
hLookup - [in] Uchwyt uzyskany przez wywołanie funkcji WSALookupServiceBegin().
Opis
:
Funkcja WSALookupServiceEnd() służy od zwalniania uchwytu utworzonego przez funkcję
WSALookupServiceBegin().
Wywołanie funkcji WSALookupServiceEnd() z innego wątku, gdy wątek funkcji WSALookupServiceNext()
jest zablokowany, kasuje zapytanie i powoduje, że funkcja WSALookupServiceNext() natychmiast
zwraca zapytanie.
20
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja projektu
Nazwa projektu: dnsquery
Typ projektu: Win32 console application
Lista plików: dnsquery.cpp
Metoda kompilacji: Microsoft Visual C++ 2008.
Utworzyć projekt typu 'Win32 console application‘ w menu
(-)File-> New -> Project-> Other languages-> Visual C++ -> win32 -> Win32 console application -> wpisać nazwę:
dnsquery -> przycisk (OK) -> Okno Win32 application wizard – dnsquery-> wybrać: Application settings -> wybrać:
Empty project-> Przycisk (Finish).
Konfiguracja projektu:
(-)Project-> nazwa_projektu Properies... -> Configuration Properies-> Linker-> Input -> Additional
Dependecies, wpisać: WS2_32.Lib.
W pliku dnsquery.vcproj, atrybutowi CharacterSet tagu Configuration przypisać wartość 2, tzn.
<Configuration CharacterSet="2”>
Funkcjonalność: (Run-> cmd) wpisać: \> dnsquery nazwa_hosta
21
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Specyfikacja projektu
Pliki nagłówkowe: winsock2.h, SvcGuid.h (VCID_INET_HOSTADDRBYNAME), iostream
Funkcje programu:
WSAStartup(), WSAGetLastError(), WSALookupServiceBegin(), WSALookupServiceNext(),
WSALookupServiceEnd(), WSACleanup(),
FixList(), UnpackHostEnt()
Struktury programu:
WSADATA, GUID, AFPROTOCOLS, WSAQUERYSET, BLOB, HOSTENT, SOCKADDR_IN
Zmienne programu:
WSADATA
WSAQUERYSET
char
wsd;
*qs=NULL;
buff[RNR_BUFFER_SIZE];
// specjalna wartość struktury GUID: SVCID_INET_HOSTADDRBYNAME dla rozwiązania nazwy hosta
GUID
HostnameGuid = SVCID_INET_HOSTADDRBYNAME;
HANDLE
AFPROTOCOLS
DWORD
int
LPBLOB
HOSTENT
SOCKADDR_IN
hRnr;
afproto[2] = { {AF_INET, IPPROTO_UDP}, {AF_INET, IPPROTO_TCP} };
dwLength = RNR_BUFFER_SIZE;
ret;
pvRet =
NULL;
*hp =
NULL;
addr;
22
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Struktura programu (struktura funkcji main())
1.Sprawdzenie listy argumentów.
2. Sprawdzenie wersji Winsock.
WSAStartup(MAKEWORD(2,2), &wsd) != 0 ?
3. Inicjowanie struktury WSAQUERYSET.
qs = (WSAQUERYSET *)buff; // qs wskaźnik do struktury WSAQUERYSET
qs->dwSize = sizeof(WSAQUERYSET);
qs->lpszServiceInstanceName = argv[1];
qs->lpServiceClassId = &HostnameGuid;
qs->dwNameSpace = NS_ALL;
qs->dwNumberOfProtocols = 2;
// TCP i UDP
qs->lpafpProtocols = afproto;
4. Początek sesji zapytań klienta do serwera DNS. Dane do inicjowania sesji pochodzą ze struktury WSAQUERYSET.
Utworzenie uchwytu do sesji, który następnie będzie wykorzystywany do zapytań przez funkcję
WSALookupServiceNext().
ret = WSALookupServiceBegin(qs, LUP_RETURN_BLOB | LUP_RETURN_NAME, &hRnr);
23
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Struktura funkcji main()
5. Sprawdzenie czy funkcja WSALookupServiceBegin() nie zwróciła błędu.
Czy ret == NO_ERROR ?
6. Wywołanie funkcji WSALookupServiceNext(), sprawdzenie czy funkcja nie zwróciła błędu.
ret = WSALookupServiceNext(hRnr, 0, &dwLength, qs);
Czy ret != NO_ERROR ?
7. Jeżeli funkcja WSALookupServiceNext() zwróciła błąd sprawdzenie numeru błędu i zakończenie sesji
Czy WSAGetLastError() == WSASERVICE_NOT_FOUND ?
WSALookupServiceEnd(hRnr);
8. Sprawdzenie czy serwer DNS zwrócił dane do struktury BLOB.
Czy qs->lpBlob == NULL ?
9. Utworzenie bufora na dane.
hp = new HOSTENT [qs->lpBlob->cbSize];
lub
hp = (HOSTENT *)LocalAlloc(LPTR, qs->lpBlob->cbSize);
10. Rozwinięcie listy hostów.
UnpackHostEnt(hp);
24
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
Struktura funkcji main()
11. Przekierowanie adresów na ekran.
for(register int i=0; hp->h_addr_list[i] ;i++)
{
memcpy(&addr.sin_addr, hp->h_addr_list[i], hp->h_length);
cout << argv[1] << " IP: " << inet_ntoa(addr.sin_addr) << endl;
}
for(i=0; hp->h_aliases[i] ;i++)
cout << "Alias: " << hp->h_aliases[i] << endl;
12. Zwolnienie pamięci i zamknięcie sesji.
delete [] hp; // lub LocalFree(hp);
WSACleanup();
25
Z. Lipiński, Instytut Matematyki i Informatyki, Uniwersytet Opolski, Podstawy programowania sieciowego
// dnsquery.cpp
#include <winsock2.h>
#include <SvcGuid.h> // VCID_INET_HOSTADDRBYNAME
#include <iostream>
using namespace std;
#define RNR_BUFFER_SIZE (sizeof(WSAQUERYSET) + sizeof(struct hostent) + 1024)
void FixList(PCHAR ** List, PCHAR Base)
{
if (*List)
{
PCHAR * Addr;
Addr = *List = (PCHAR *)( ((DWORD)*List + Base) );
while(*Addr)
{
*Addr = (PCHAR)(((DWORD)*Addr + Base));
Addr++;
}
}
} //koniec FixList()
void UnpackHostEnt(struct hostent * hostent)
{
PCHAR pch;
pch = (PCHAR)hostent;
if(hostent->h_name)
{
hostent->h_name = (PCHAR)((DWORD)hostent->h_name + pch);
}
FixList(&hostent->h_aliases, pch);
FixList(&hostent->h_addr_list, pch);
} //koniec UnpackHostEnt()
26
int main(int argc, char *argv[])
{
WSADATA
wsd;
WSAQUERYSET
*qs
= NULL;
char
buff[RNR_BUFFER_SIZE];
GUID
HostnameGuid = SVCID_INET_HOSTADDRBYNAME;
HANDLE
hRnr;
AFPROTOCOLS
afproto[2] = { {AF_INET, IPPROTO_UDP},
{AF_INET, IPPROTO_TCP} };
DWORD
dwLength = RNR_BUFFER_SIZE;
int
ret, i;
LPBLOB
pvRet
= NULL;
HOSTENT
*hp
= NULL;
SOCKADDR_IN
addr;
if (argc != 2)
{
cout << "wpisz: " << argv[0] << " nazwa_hosta " << endl;
return -1;
}
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
{
cerr << "WSAStartup() error no: " << WSAGetLastError() << endl;
return -1;
}
27
//qs = (WSAQUERYSET *)&buff;
qs = (WSAQUERYSET *)buff;
memset(qs, 0, sizeof(*qs));
// w pliku dnsquery.vcproj, atrybutowi CharacterSet w tagu Configuration przypisac
// wartosc 2, tzn. <Configurations> <Configuration CharacterSet="2” >
///////////////////////////////////////////////////////
qs->dwSize
= sizeof(WSAQUERYSET);
qs->lpszServiceInstanceName = argv[1];
qs->lpServiceClassId = &HostnameGuid;
qs->dwNameSpace
= NS_ALL;
qs->dwNumberOfProtocols = 2;
// TCP & UDP
qs->lpafpProtocols
= afproto;
ret = WSALookupServiceBegin(qs, LUP_RETURN_BLOB | LUP_RETURN_NAME, &hRnr);
if (ret == NO_ERROR)
{
ret = WSALookupServiceNext(hRnr, 0, &dwLength, qs);
if (ret != NO_ERROR)
{
if (WSAGetLastError() == WSASERVICE_NOT_FOUND)
{
cerr <<"No such name found!" << endl;
WSALookupServiceEnd(hRnr);
return 0;
}
cerr << "WSALookupServiceNext() error no: " << WSAGetLastError() << endl;
}
WSALookupServiceEnd(hRnr);
}
28
if (qs->lpBlob == NULL)
return -1;
hp = new HOSTENT [qs->lpBlob->cbSize];
if (!hp)
{
cerr << "hp on heap failed" << endl;
return -1;
}
//void * memcpy ( void * destination, const void * source, size_t num );
memcpy(hp, qs->lpBlob->pBlobData, qs->lpBlob->cbSize);
UnpackHostEnt(hp);
for(i=0; hp->h_addr_list[i] ;i++)
{
memcpy(&addr.sin_addr, hp->h_addr_list[i], hp->h_length);
cout << argv[1] << " IP: " << inet_ntoa(addr.sin_addr) << endl;
}
for(i=0; hp->h_aliases[i] ;i++)
cout << "Alias: " << hp->h_aliases[i] << endl;
delete [] hp;
WSACleanup();
return 0;
}//koniec main()
29

Podobne dokumenty