background image

Sieci komputerowe – Ćwiczenia projektowe Nr1  

za zajęcia można zdobyć 5 punktów (+ew 1 punkt) 

Adres IPv4

Adres składa się z 32 bitów, które są zwykle zapisywane jako 4 liczby oddzielone znakiem „.” . Liczby mogą 
być zapisywane w reprezentacji dziesiętnej (0-255 -  najpopularniejszy sposób), szesnastkowej lub binarnej.  
Przestrzeń adresowa to teoretycznie 2

32

=4 294 968 298 w praktyce jest znacznie mniejsza ze względu na 

sposób adresowania (np adresowanie klasowe tab 1), sposobu podziału na podsieci (jeden adres staje się 
adresem sieci a drugi adresem rozgłoszeniowym), wykluczenie lub ograniczenie pewnych grup adresów 
(tabela 2)

Zapis adresu IPv4 
dziesiętny

binarny 

szestnastkowy

10.0.2.1

00001010.00000000.00000010.00000001

0xA000201

Tabela 1 Podział na klasy

Sposób wyróżnienia

Klasa

Zakres adresów

Bity maski/uwagi

Najstarszy bit 0

 A

1.0.0.0 – 127.255.255.255

8

Najstarsze bity 10

B

128.0.0.0 – 191.255.255.255

16

Najstarsze bity 110

C

192.0.0.0 – 223.255.255.255

24

Najstarsze bity 1110

D

224.0.0.0 – 239.255.255.255

specjalne przeznaczenie

Najstarsze bity 1111

E

240.0.0.0 – 254.255.255.255

zarezerwowane

Tabela 2 Wykorzystanie adresów IP

Adresy

Obecne użycie

0.0.0.0/8

0.0.0.0 oznacza całą sieć poza lokalną

10.0.0.0/8

dawna sieć DARPA obecnie tylko dla sieci wewnętrznych

14.0.0.0/8

publiczne sieci danych

24.0.0.0/8

Telewizje kablowe

39.0.0.0/8

Zarezerwowane ale w trakcie podziału

127.0.0.0/8

localnet

128.0.0.0/16

Zarezerwowane ale w trakcie podziału

169.254.0.0/16

lokalne łącze

172.16.0.0/16

dla sieci wewnętrznych

191.255.0.0/16

Zarezerwowane ale w trakcie podziału

192.0.0.0/24

Zarezerwowane ale w trakcie podziału

192.0.2.0/24
192.88.99.0/24

Test-Net – Łączenie sieci IPv4 i IPv6

192.18.0.0/15

Połączenia międzysieciowe testowanie urządzeń

192.168.0.0-192.168.255.255

dla sieci wewnętrznych

223.255.255.0/24

Zarezerwowane, ale w trakcie podziału

224.0.0.0/4

Multicast

240.0.0.0/4

Zarezerwowane dla przyszłego użycia

background image

Do   działania   sieci   TCP/IP   wymagany   jest   adres   IP   oraz   maska,   adres   rozgłoszeniowy   (informacja 
przeznaczona dla wszystkich hostów w podsieci) może być wyliczony z adresu i maski podobnie jak numer 
sieci.

IP

10010101.10011100.1110000.00110111

149.156.112.55

maska 

11111111.11111111.1111111.00000000 

255.255.255.0

rozg .  

ł

10010101.10011100.1110000.11111111 

149.156.112.255

sie

ć

10010101.10011100.1110000.00000000

149.156.112.0

Adres bramy (gateway) jest konieczny tylko w wypadku połączeń międzysieciowych.

Adresy IP oraz adres portu mogą być zapisywane w pamięci hosta na różne sposoby zależnie od prządku  
procesora – bigindian/littleindian/middleindian. W sieci obowiązuje tzw porządek sieciowy (network order). 
Przenośność programu wymaga użycia funckcji konwertujących porządek sieciowy<->porządek hosta

UWAGA – szczególnie ważne dla architektury IA32 (x86,x86_64)

#include <arpa/inet.h>

uint32_t htonl(uint32_t hostlong); 

// z hosta na sieciowy long 

uint16_t htons(uint16_t hostshort);

// z hosta na sieciowy short 

uint32_t ntohl(uint32_t netlong);

// z sieciowego na hosta long 

uint16_t ntohs(uint16_t netshort);

// z sieciowego na hosta long

Tłumaczenie zapisu dziesiętnego na binarny i odwrotnie

#include <sys/socket.h>
#include <netinet/in.h>

#include <arpa/inet.h>

/* Adres internetowy. */
struct in_addr {

__be32

s_addr;

/* 32-bitowa liczba np long */

};

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);

Funkcja inet_ntop konwertuje adres binarny na typu af (AF_NET, AF_INET6) na adres dziesiętny i zapisuje 
pod wskaźnikiem dst

int inet_pton(int af, const char *src, void *dst); /

Funkcja   inet_pton   konwertuje   ciąg   znaków   src   (typu   149.156.112.55)   na   typ   af   (AF_NET,  AF_INET6)   i  
zapisuje pod wskaźnikiem dst

int inet_aton(const char *cp, struct in_addr *inp);

char *inet_ntoa(struct in_addr in);

Funkcje inet_aton/ntoa działają podobnie do poprzednich, z tym że używają sieciowego porządku bajtów

Zadanie 1 (2p)

Napisać   program   obliczający:   adres   rozgłoszeniowy   oraz   numer   sieci   na   podstawie   adresu   i   maski  
zapisanego w następujący sposób xxx.yyy.zzz.xxx/m (m - ilość bitów maski)

Adresy IPv6

Opracowano aby wyeliminować pewne niedostatki poprzedniej wersji głównie:

Mała jak na obecne potrzeby liczba adresów (co prawda stosowanie sieci wewnętrznych ograniczyło 
te potrzeby) 

Brak zabezpieczeń transmisji przed zmianą czy przechwyceniem

 
Przestrzeń adresowa IPv6 to 2

128

 adresów. Adresy IPv4 są podgrupą adresów IPv6 . Stosuje się wyłącznie 

zapis heksadecymalny. Liczby dla ułatwienia są oddzielane są znakiem „:”. Zera mogą być pomijane w 
zapisie. „::” - oznacza dowolną liczbę zer, w szczególności: 

::1” oznacza localhost

background image

fe00::0         ipv6-localnet.

ff00::0         ipv6-mcastprefix.
ff02::1         ipv6-allnodes.
ff02::2         ipv6-allrouters.
ff02::3         ipv6-allhosts.

TCP/IP - resolver – rozwiązywanie nazw/DNS

Za tłumaczenie nazwy komputera na adres IP odpowiada tzw. resolver będący zestawem bibliotek oraz jego 
konfiguracja.

W systemach UNIX/Linux – stosuje się dwie funkcje: 
gethostbyname i gethostbyaddr są przestarzałe ale ciągle stosowane ich nowsze wersje to  getaddrinfo i 
getnameinfo

#include <netdb.h>

struct hostent *gethostbyname(const char *name);

#include <sys/socket.h> 

/* AF_INET */

struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);

struktura hostent

jest zdefiniowana w <netdb.h> następująco:

struct hostent {

char  *h_name;

/* oficialna nazwa hosta */

char **h_aliases;

/* lista aliasów - tablica */

int    h_addrtype;

/* typ adresu hosta AF_INET lub AF_INET6*/

int    h_length;

/* długość adresu w bajtach*/

char **h_addr_list;

/* lista adresów – sieciowy porządek bajtów*/

}

#define h_addr h_addr_list[0] 

/* zdefiniowane dla wstecznej kompatybilności */

Nowsze implementacje powinny używać getaddrinfo i  getnameinfo  

#include <sys/types.h>

#include <sys/socket.h>
#include <netdb.h>

void freeaddrinfo(struct addrinfo *ai);

int getaddrinfo( const char 

*restrict nodename,

const char 

*restrict servname,

const struct 

addrinfo *restrict hints,

struct addrinfo 

**restrict res);

zwracana wartość

0 – 

sukces

EAI_ADDRFAMILY 

host nie ma adresu internetowego w danej rodzinie adresów

EAI_AGAIN

chwilowa niedostępność – spróbować poźniej

EAI_BADFLAGS

złe flagi lub AI_CANONNAME jest NULL

EAI_FAIL 

permanentny błąd serwera nazw

EAI_FAMILY

rodzina adresów nie wspierana

EAI_MEMORY

przepełnienie pamięci

EAI_NODATA

host istnieje ale nie ma adresu

EAI_NONAME

węzeł lub serwis nie znany

EAI_SERVICE

usługa nie jest dostępna dla tego typu socketa

EAI_SOCKTYPE

ten typ socketa jest nie wspierany

EAI_SYSTEM

błąd systemowy

Argumenty

#include <sys/socket.h>
#include <netdb.h>

int getnameinfo(const struct sockaddr *sa, 

socklen_t 

salen,

char 

*host, 

background image

size_t 

hostlen,

char 

*serv, 

size_t 

servlen, 

int 

flags);

struct addrinfo {

int

ai_flags;

int

ai_family;

/* Rodzina adresów AF_INET, AF_INET6*/

int

ai_socktype;

/*SOCK_STREAM lub SOCK_DGRAM */

`

int

ai_protocol;

size_t

ai_addrlen;

struct sockaddr *ai_addr;
char

*ai_canonname;

struct addrinfo *ai_next;

};

#include <sys/socket.h>

struct sockaddr{

unsigned short sa_family;

/* Rodzina adresów AF_INET, AF_INET6 */

char

sa_data[14];

/* 14 bajtów danych protokołu*/

};

Bardziej użyteczna bywa struktura sockaddr_in gdzie sa_data jest rozbite na dwie pozycje

#include <netinet/in.h>

struct sockaddr_in {

short int

sin_family;

/* Rodzina adresów AF_INET, AF_INET6*/

unsigned short sin_port;

/* Numer portu */

struct in_addr sin_addr;

/* Adres internetowy */

char sin_zero[8]

/* Wypełnienie do rozmiaru `struct sockaddr'. */

};

Zadanie 2 (2p)

Napisać program odnajdujący nazwę hosta dla podanego jako argument  adresu IP dla IPv4

Zadanie 3(1p)

Napisać program odnajdujący adres IP hosta, którego nazwa podana jest jako argument dla IPv4