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 232=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

Test-Net – Łączenie sieci IPv4 i IPv6

192.88.99.0/24

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

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 2128 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

fe00::0 ipv6-localnet.

ff00::0 ipv6-mcastprefix.

ff02::1 ipv6-al nodes.

ff02::2 ipv6-al routers.

ff02::3 ipv6-al hosts.

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,

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 */

ìnt

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 rozmiarù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