Do spisu treści tematu 8
8.2.2 Protokół komunikacyjny IP (2)
Spis treści
8.2.2.1 Interfejs wyjściowy
protokołu IP
Interfejs wyjściowy protokołu IP w Linuxie zdefiniowany jest w plikach
net/ipv4/ip_output.c oraz
(częściowo) net/ipv4/ip_forward.c.
Najważniejsze zdefiniowane w nich funkcje to:
DEFINICJA: int ip_build_header(struct sk_buff *skb, __u32 saddr,
__u32 daddr, struct device **dev, int type,
struct options *opt, int len, int tos,
int ttl, struct rtable ** rp)
WYNIK: Długość zbudowanego nagłówka
budująca nagłówek IP dla pakietu IP przechowywanego
w przekazywanej strukturze typu sk_buff i dodająca ewentualnie
na koniec rekord opcji (woła ip_options_build()),
DEFINICJA: static inline void add_to_send_queue(
struct sock * sk, struct sk_buff * skb)
WYNIK: -
przeznaczająca strukturę sk_buff do kolejki pakietów do wysłania
związanej z podanym gniazdem sk,
DEFINICJA: void ip_queue_xmit(struct sock *sk,
struct device *dev, struct sk_buff *skb, int free)
WYNIK: -
dodająca podany pakiet (skb) do kolejki do wysłania na dane
gniazdo (sk) i uruchamiająca wysyłanie (wywołując dev_queue_xmit())
DEFINICJA: int ip_build_xmit(struct sock *sk,
void getfrag (const void *, __u32,
char *, unsigned int, unsigned int),
const void *frag,
unsigned short int length,
__u32 daddr,
__u32 user_saddr,
struct options * opt,
int flags,
int type,
int noblock)
WYNIK: 0 jeśli wszystko poszło dobrze,
kod błędu: ENODEV jeśli nie ma urządzenia,
ENETUNREACH jeśli odbiorca jest niedostępny,
EPERM jeśli pakiet nie może przedostać się przez
zabezpieczenia dostepu (ang. firewall),
EMSGSIZE jeśli pakiet musi być sfragmentowany
lub kod błędu specyficzny dla protokołu wyższego poziomu
Robi to, co wszystkie wcześniejsze funkcje razem: buduje nagłówek, inicjuje
sk_buff, wkłada do kolejki i wysyła.
DEFINICJA: int ip_forward(struct sk_buff *skb, struct device *dev,
int is_frag, __u32 target_addr)
WYNIK: -1 w przypadku mogących wystąpić błędów (opisanych poniżej)
1 w przypadku sukcesu
Po sprawdzeniu, że pakiet nie jest przeterminowany, odwołuje się do
bramy (wywołując ip_rt_route())
aby pobrać adres najbliższego "skoku". Wreszcie sprawdza, czy
pakiet nie powinien zostać poddany fragmentacji
przed posłaniem go na urządzenie wyjściowe.
8.2.2.2 Adresowanie cz.2
Budowa adresu IP omówiona jest w części
1 tego dokumentu.
Wymienimy tutaj jedynie specjalne przypadki adresów, które były używane
do realizacji takich funkcji jak np. rozgłaszanie (ang. broadcasting)
- patrz Interfejs wyjściowy protokołu IP -
używając następującej notacji, zależnie od klasy adresu:
{ <Numer sieci>, <Numer stacji> }
lub
{ <Numer sieci>, <Numer podsieci>, <Numer stacji>
}
realizując minus jedynkę (-1) poprzez pole z wszystkimi bitami ustawionymi.
- { 0, 0 }
- Oznacza "ta stacja w tej sieci". Taki adres jest używany
tylko jako adres nadawcy w przypadku pewnych procedur inicjujących, za
pomocą których stacje dowiadują się o swoich adresach IP.
- { 0, <Numer stacji> }
- Oznacza daną stację tej sieci, z zastrzeżeniami jak wyżej.
- { -1, -1 }
- Ograniczone rozgłaszanie; może być używany tylko jako adres odbiorcy.
Datagram zaadresowany w ten sposób zostanie odebrany przez każdą maszynę
w macierzystej sieci, ale nie zostanie rozesłany dalej.
- { <Numer sieci>, -1 }
- Rozgłaszanie skierowane do podanej sieci, również tylko jako adres
odbiorcy.
- { <Numer sieci>, <Numer podsieci>, -1 }
- Rozgłaszanie skierowane do podanej podsieci, tylko jako adres odbiorcy.
- { <Numer sieci>, -1, -1 }
- Rozgłaszanie skierowane do podanej sieci (w przypadku sieci z podsieciami),
tylko jako adres odbiorcy.
- { 127, <cokolwiek> }
- Adres - pętla wewnątrz naszej stacji. Nie powinien nigdy być wysyłany
poza tę stację.
Unikatowe numery sieci przyznawane są administracyjnie.
Należy nadmienić, że początkowo wszystkie adresy IP miały być amorficznymi
32-bitowymi liczbami i właściwie takie arbitralne dzielenie adresu na sekcje
sieci, podsieci i stacji jest złamaniem tej reguły; np. przypadek 6 w znacznej
ilości sieci nie jest rozpoznawany.
8.2.2.3 Routing - przekazywanie
datagramów przez bramy
8.2.2.3.1 Zasady ogólne
Warstwa IP odpowiada za wybranie następnego poprawnego "skoku"
dla każdego datagramu, który wysyła. Jeśli odbiorca jest w tej samej sieci,
pakiet będzie wysłany bezpośrednio do niego; w przeciwnym przypadku musi
być przekazany dalej, do bramy łączącej sieci.
Decyzję, czy adres przeznaczenia leży na przyłączonej do danej stacji
sieci, podejmuje się w oparciu o maskę adresów (ang. address mask),
sprawdzając zgodność adresów odbiorcy i nadawcy po przefiltrowaniu przez
tę maskę. Jeśli wyniki nie są zgodne, należy wybrać bramę, przez którą
komunikaty przejdą do docelowej sieci. Ewentualnie, jeśli adres odbiorcy
oznacza rozgłaszanie do aktualnej sieci lub podsieci (patrz
wyżej), to adres taki jest przekazany do interfejsu sieciowego niższej
warstwy.
Aby efektywnie przekazywać pakiety dalej, każda stacja trzyma tzw.
route cache - pamięć podręczną adresów bram, do których bezpośrednio
można posyłać datagramy o danych adresach przeznaczenia. Każda pozycja
w tabeli adresów bram zawerać musi przynajmniej:
- Adres przeznaczenia (stacji lub sieci)
- Maska adresów (jeśli pakiet nie pasuje do żadnej maski w całej route
cache, jest zapominany, a nadawca otrzymuje komunikat ICMP:
Destination Unreachable)
- Następny "skok", który jest zawsze adresem IP stacji lub
bramy (routera lub gateway; rozróżnienie jest płynne i zależy
od tego, jak różne kawałki sieci łączy brama) dostępnej bezpośrednio poprzez
Ethernet, połączenie satelitarne lub inne fizyczne połączenie.
Algorytm wykonywany przez stację (zaprojektowany tak, aby główny ciężar
wyboru trasy spoczywał na urządzeniu spełniającym funkcję bramy) jest następujący:
- Jeśli adres przeznaczenia nie występuje w podręcznej tabeli bram, stacja
wybiera domyślną bramę i posyła do niej datagram; adres ten jest też dodawany
do route cache;
- Jeśli ta brama nie jest [już dłużej] najlepszym punktem "skoku"
do celu, przekaże ona datagram do sobie z kolei znanej kolejnej bramy i
powiadomi o tym stację nadawcy komunikatem protokołu
ICMP - Redirect
- Stacja otrzymująca komunikat Redirect uaktualnia w pamięci podręcznej
bramę dla danego adresu przeznaczenia, tak, że następne datagramy dla tego
adresu pójdą bezpośrednio do tej właśnie bramy, poleconej przez tę poprzednio
wywołaną.
Dzięki temu rozwiązaniu, w połączeniu z różnymi mechanizmami wykrywania
"martwych bram" (ang. dead gateway detection) i wybierania
bram nowych, których w tym miejscu nie omawiamy, protokół IP może spełniać
funkcję, do której był oryginalnie zaprojektowany - utrzymania przy życiu
sieci, której infrastruktura została w znacznej części zniszczona lub przeciążona.
Dodatkowo, istnieje możliwośc implementowania tras statycznych (ang.
static routes) czyli specjalnie ustawionych pozycji w route cache,
które nie muszą być uaktualniane komunikatami Redirect. Mogą też
one mieć znaczenie jako mechanizm obsługujący pole Type of Service
nagłówka IP (patrz budowa nagłówka IP),
np. pakiety o wysokim priorytecie mogą iść do szczególnie szybkiej bramy.
Stacja nie będąca fizycznie bramą między dwiema odmiennymi sieciami
może również służyć jako brama (tutaj: router) - pośredni "skok"
w trasie pakietu - jeśli spełnia następujące warunki:
- Zmniejsza wartość pola TTL (Time To Live) i ewentualnie usuwa
przeterminowany pakiet
- Potrafi generować komunikat protokołu ICMP -
Destination Unreachable - jeśli pakiet nie może być przekazany do
następnej sieci z powodu np. niemożliwości fragmentacji lub niemożliwości
zrealizowania żądanej trasy pakietu (ang. strict source route) w przypadku,
gdy następny adres nie znajduje się na przyłączonej sieci.
- Nie traktuje każdego pakietu jak wysyłany przez siebie, tzn. zachowuje
adres nadawcy w wysyłanych pakietach IP
- Jeśli jest na to miejsce w polu opcji nagłówka IP, dopisuje się jako
kolejny skok na trasie
- Uaktualnia opcję Timestamp w nagłówku IP
Bramy decydujące o dynamicznym wyborze trasy między sieciami działają
na zasadzie minimalizacji kosztu przesyłu pakietu, wymieniając między sobą
informacje o obciążeniu poszczególnych połączeń. Protokoły używane w takim
"równoważeniu" sieci to np.
- Distance-Vector Routing (RFC 1058)
- wymienianie się tablicami tras (ang. routing tables)
- Link State Routing (RFC
1583) - wymiana komunikatów o stanie dostępnych połączeń
- BGP-4 Exterior Routing (RFC
1771) - mieszanka obydwu powyższych metod, zarządzająca trasowaniem
w sieci szkieletowej (ang. backbone network) Internetu.
8.2.2.3.2 Implementacja w Linuxie
Najważniejszą strukturą danych odpowiadającą za wybór trasy pakietu
w Linuxie jest lista łączona ip_rt_hash_table, zdefiniowana w
net/ipv4/route.c. Aby przyspieszyć
operacje na tej liście, która może być dość pokaźnych rozmiarów, jest ona
haszowana (domyślnie po kluczu 8-bitowym). Element takiej listy wygląda
następująco:
struct rtable
{
struct rtable *rt_next;
__u32 rt_dst;
__u32 rt_src;
__u32 rt_gateway;
atomic_t rt_refcnt;
atomic_t rt_use;
unsigned long rt_window;
atomic_t rt_lastuse;
struct hh_cache *rt_hh;
struct device *rt_dev;
unsigned short rt_flags;
unsigned short rt_mtu;
unsigned short rt_irtt;
unsigned char rt_tos;
};
Składowe tej struktury to:
rt_next
|
Wskaźnik do następnego elementu listy
|
rt_dst
|
Adres odbiorcy (stacji lub sieci)
|
rt_src
|
Adres nadawcy (używany w przypadku stacji o wielu numerach IP)
|
rt_gateway
|
Adres bramy używanej do przesłania pakietu do odbiorcy; adres ten może
się zmienić po odebraniu komunikatu ICMP - Redirect
|
rt_refcnt
|
Licznik odniesień (wykorzystanie danej pozycji)
|
rt_use
|
Czy trasa wykorzystywana?
|
rt_window
|
Pole pomocnicze w obsłudze protokołu TCP
|
rt_lastuse
|
Wskazuje, kiedy ostatnio ta pozycja była używana
|
rt_hh
|
Pole związane z obsługą wysyłania pakietów IP do wielu stacji identyfikowanych
tym samym numerem IP (IP Multicasting).
|
rt_dev
|
Urządzenie przez które pakiet będzie wysyłany
|
rt_flags
|
Miejsce na opcje, zdefiniowane w include/linux/route.h.
Ciekawsze z nich to:
- RTF_GATEWAY oznacza, że odbiorca (rt_dst) jest bramą
- RTF_REINSTATE powoduje, że trasa zostanie ponownie sprawdzona
(i ewentualnie ustawiona inna wartość rt_gateway lub rt_irtt)
po zadanym czasie
- RTF_DYNAMIC oznacza, że trasa może być modyfikowana komunikatem
Redirect
- RTF_MODIFIED oznacza trasę właśnie w taki sposób zmodyfikowaną
|
rt_mtu
|
Maksymalna jednostka transmisji (ang. Maximum Transmission Unit) dla sieci na tej trasie
|
rt_irtt
|
Czas połączenia na danej trasie (ang. initial round trip time);
może być używany w algorytmach dynamicznego wyboru trasy.
|
rt_tos
|
Znacznik trasy specjalnie zaprojektowanej do przesyłania pakietów IP
o danej zawartości pola nagłówka Type of Service.
|
Znajdowanie trasy dla pakietu IP realizowane jest za pomocą fukcji ip_build_header
(patrz interfejs wyjściowy IP), która wywołuje:
DEFINICJA: struct rtable * ip_rt_route(__u32 daddr, int local)
WYNIK: pozycja w tabeli tras
Funkcja ta dla podanego adresu odbiorcy zwraca pozycję tablicy rt_ip_hash_table,
która będzie użyta do wysłania danego pakietu IP dalej.
Inne funkcje realizujące operacje na tej tabeli zgodnie z podanymi wcześniej
zasadami to:
DEFINICJA: static void rt_redirect(__u32 dst, __u32 gw, struct
device *dev)
WYNIK: -
dokonująca odpowiednich zmian w tabeli rt_ip_hash_table po
otrzymaniu żądania zmiany bramy dla trasy (ICMP Redirect),
DEFINICJA: int ip_rt_new(struct rtentry *r)
WYNIK: -
dodająca nową pozycję w tablicy rt_ip_hash_table po próbie wysłania
do adresu jeszcze w niej nie istniejącego.
8.2.2.4 Błędy i zapytania: Protokół
ICMP
Protokół ICMP (Internet Control Message Protocol) jest protokołem
pomocniczym współpracującym z IP, opisanym w dokumencie RFC
792. Przekazuje on komunikaty związane z:
- obsługą błędów IP
- "zapytaniami" wykonywanymi w celu rekonfiguracji urządzeń
obsługujących IP
Komunikaty obsługi błędów to:
- Odbiorca niedostępny (Destination Unreachable), wysyłany
w przypadku niemożności dotarcia pakietu do punktu przeznaczenia z powodu
np. braku fizycznego połączenia, nie wynegocjowanego protokołu, nieobsługiwanego
portu, niewykonanej fragmentacji. Objawia
się dla użytkownika komunikatami takimi jak np. "no route to host"
- Trasa zmieniona (Redirect), wysyłany przez bramę jeśli
jakieś inne połączenie (nie przez tę właśnie bramę) jest najlepszym połączeniem
od nadawcy pakietu do odbiorcy.
- Przeciążenie bramy (Source Quench), wysyłany przez bramę
do nadawcy w przypadku zbyt dużej ilości pakietów do obsłużenia.
- Przeterminowanie pakietu (Time Exceeded), wysyłany przez
bramę jeśli po zmniejszeniu pola ttl (Time To Live) nagłówka
IP jego wartość jest mniejsza od zera
- Zły parametr (Parameter Problem), wysyłany przez bramę w przypadku
zauważenia niezgodności w nagłówku IP pakietu,
takiej jak zła suma kontrolna lub niepoprawna opcja.
Komunikaty zapytań to:
- Echo (Echo) - sprawdzający istnieje i poprawne działanie
urządzenia o zadanym adresie; musi ono odesłać dokładnie te same dane,
jakie dostaje komunikatem Echo. Dla użytkownika dostępny jest poprzez
polecenie ping.
- Informacja o sieci (Information) - używany w inicjalizacji
stacji, służy do dowiadywania się w jakiej sieci znajduje się stacja.
- Czas wysłania (Timestamp) - używany do wymiany informacji
o ostatnim momencie przetwarzania pakietu IP, która może być potem używana
np. do stwierdzenia przeterminowania pakietu lub obliczenia obciążenia
trasy.
W Linuxie obsługa protokołu ICMP zaimplementowana jest w pliku net/ipv4/icmp.c.
Najważniejszą funkcją jest
DEFINICJA: void icmp_send(struct sk_buff *skb_in, int type, int
code,
unsigned long info, struct device *dev)
WYNIK: -
jako parametry przyjmująca pakiet IP, którego będzie dotyczył komunikat
ICMP, typ i kod komunikatu do wysłania i ewentualnie inne potrzebne informacje
(jak zwracany adres, informacje z ping itp.)
8.2.2.5 Bibliografia
- Pliki źródłowe Linuxa:
- W.Richard Stevens: Programowanie zastosowań sieciowych w systemie
Unix. WNT 1995
- Dokumenty RFC (Requests For Comments) w Internet
Encyclopedia.