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