Scroll to navigation

ip(7) Miscellaneous Information Manual ip(7)

NAZWA

ip - Implementacja protokołu IPv4 dla systemu Linux

SKŁADNIA

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>  /* nadzbiór poprzedniego */
tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
raw_socket = socket(AF_INET, SOCK_RAW, protocol);

OPIS

Linux implementuje protokół IPv4 opisany w RFC 791 i RFC 1122. ip zawiera drugi poziom implementacji adresowania grupowego (multicasting) zgodny z RFC 1112. Zawiera też router IP, włączając w to filtr pakietów.

Interfejs programistyczny jest zgodny z gniazdami BSD. Więcej informacji na temat gniazd można znaleźć, przeglądając socket(7).

Gniazdo IP jest tworzone za pomocą socket(2):


socket(AF_INET, typ_gniazda, protokół);

Prawidłowe typy gniazd obejmują SOCK_STREAM do otwarcia gniazda strumieniowego, SOCK_DGRAM do otwarcia gniazda datagramowego i SOCK_RAW do otwarcia gniazda raw(7) w celu bezpośredniego dostępu do protokołu IP.

protocol jest protokołem IP w nagłówku IP, który ma być otrzymany lub wysłany. Prawidłowe wartości protocol to:

0 i IPPROTO_TCP dla gniazd strumieniowych tcp(7);
0 i IPPROTO_UDP dla gniazd datagramowych udp(7);
IPPROTO_SCTP dla gniazd strumieniowych sctp(7); oraz
IPPROTO_UDPLITE dla gniazd datagramowych udplite(7).

W przypadku SOCK_RAW można podać prawidłowe liczby przypisane w RFC 1700 protokołowi IP IANA.

Kiedy proces chce odbierać nowe, nadchodzące pakiety lub połączenia, powinien podłączyć gniazdo do adresu lokalnego interfejsu za pomocą funkcji bind(2). W takim przypadku do dowolnej lokalnej pary (adres, port) można podłączyć tylko jedno gniazdo IP. Gdy w wywołaniu bind(2) podana jest wartość INADDR_ANY, to gniazdo zostanie dowiązane do wszystkich lokalnych interfejsów sieciowych. Gdy do niedowiązanego gniazda wywoływane jest listen(2), to gniazdo zostanie automatycznie dowiązane do losowo wybranego wolnego portu, przy czym adres lokalny zostanie ustawiony na INADDR_ANY. Gdy dla niedowiązanego gniazda zostanie wywołane connect(2), gniazdo to zostanie automatycznie dowiązane do losowo wybranego wolnego portu lub do używalnego portu dzielonego, przy czym adres lokalny zostanie ustawiony na INADDR_ANY.

Przypisywanie (często w literaturze: "nazywanie") lokalnego gniazda TCP jest niemożliwe przez pewien okres czasu po jego zamknięciu, chyba że zostanie dla tego gniazda ustawiony atrybut SO_REUSEADDR. Należy używać tego atrybutu z rozwagą, gdyż czyni on TCP mniej niezawodnym.

Format adresu

Adres gniazda IP jest przedstawiony za pomocą kombinacji adresu interfejsu IP i 16-bitowego numeru portu. Podstawowy protokół IP nie zawiera numerów portów, są one zaimplementowane w protokołach wyższej warstwy, takich jak udp(7) i tcp(7). Dla gniazd surowych .sin_port jest ustawione na protokół IP.

Patrz sockaddr_in(3type).

.sin_family ma zawsze wartość AF_INET. Jest to wymagane; w Linuksie 2.2 większość funkcji sieciowych zwraca EINVAL, jeśli brakuje tego ustawienia. .sin_port zawiera numer portu podany w sieciowej kolejności bajtów. Numery portów niższe niż 1024 są nazywane portami uprzywilejowanymi (lub czasem portami zarezerwowanymi). Tylko procesy uprzywilejowane (na Linuksie: proces z przywilejem CAP_NET_BIND_SERVICE w przestrzeni nazw użytkownika zarządzającą swoją sieciową przestrzenią nazw) mogą wywołać bind(2) dla tego rodzaju gniazd. Należy zauważyć, że surowy protokół IPv4 jako taki nie zawiera pojęcia portu (takie rozróżnienie jest dopiero w warstwie transportowej, a to jest warstwa sieciowa). Numery portów występują dopiero w protokołach wyższej warstwy, takich jak tcp(7) i udp(7).

.sin_addr to adres IP komputera (stacji). Pole s_addr struktury in_addr(3type) zawiera adres interfejsu stacji w sieciowej kolejności bajtów. in_addr(3type) należy albo przypisać jedną z wartości INADDR_* (np. INADDR_LOOPBACK) za pomocą htonl(3), albo użyć funkcji bibliotecznych inet_aton(3), inet_addr(3), inet_makeaddr(3) do ustawienia wartości, albo ustawić bezpośrednio przez funkcję obsługi nazw (patrz też gethostbyname(3)).

Adresy IPv4 dzielimy na pojedyncze (unicast), rozgłoszeniowe (broadcast) i grupowe (multicast). Adresy pojedyncze określają pojedynczy interfejs maszyny, adresy rozgłoszeniowe określają wszystkie maszyny w obrębie jakiejś sieci (podsieci), a adresy grupowe wszystkie maszyny w obrębie jakiejś grupy odbiorców. Datagramy kierowane do adresów rozgłoszeniowych trafiają do odbiorcy tylko wtedy, gdy jego gniazdo ma ustawiony atrybut rozgłoszenia SO_BROADCAST. Ten sam atrybut musi być też ustawiony, gdy zachodzi potrzeba wysłania datagramów rozgłoszenia. W obecnej implementacji gniazda połączeniowe mogą używać wyłącznie adresów pojedynczych.

Należy zauważyć, że dla adresu i portu zawsze jest używana sieciowa kolejność bajtów. W szczególności oznacza to, że trzeba używać funkcji htons(3) dla numeru przypisanego do portu. Wszystkie funkcje standardowej biblioteki manipulujące adresem/portem automatycznie przekształcają podaną wartość na jej sieciową reprezentację.

Adresy specjalne i zarezerwowane

Istnieje wiele adresów specjalnych:

zawsze odnosi się do komputera lokalnego za pośrednictwem urządzenia pętli zwrotnej (loopback);
oznacza każdy adres, do kojarzenia gniazd;
Pakiet zaadresowany do INADDR_BROADCAST za pośrednictwem gniazda z ustawionym SO_BROADCAST będzie rozgłaszał do wszystkich stacji w segmencie sieci lokalnej, tak długo, jak połączenie ma możliwość rozgłaszania.
W każdej podsieci lokalnej, innej niż punkt do punktu, z połączeniem obsługującym rozgłaszanie, adres o najwyższym możliwym numerze (np. adres .255 w podsieci z maską sieciową 255.255.255.0) służy jako adres rozgłoszeniowy. Nie można go użytecznie przypisać do indywidualnego interfejsu i można go zaadresować jedynie gniazdem z ustawioną opcją SO_BROADCAST. Standardy internetowe historycznie rezerwowały również adres o najniższym możliwym numerze (np. adres .0 w podsieci z maską sieciową 255.255.255.0) do rozgłaszania, choć nazywały go „przestarzałym” do tego celu (część źródeł odnosi się do niego również jako do „adresu sieci”). Od Linuksa 5.14 jest on traktowany jako standardowy adres pojedynczy i może być przypisany do interfejsu.

Standardy internetowe tradycyjnie rezerwowały również różne adresy do określonych celów, choć Linux części z nich nie traktuje już w specjalny sposób.

[0.0.0.1, 0.255.255.255]
[240.0.0.0, 255.255.255.254]
Adresy w tych zakresach (0/8 i 240/4) są zarezerwowane globalnie. Od Linuksa 5.3 i Linuksa 2.6.25 adresy, odpowiednio, 0/8 i 240/4, inne niż INADDR_ANY i INADDR_BROADCAST są traktowane jako zwykłe adresy pojedyncze. Systemy przestrzegające tradycyjnego zachowania mogą nie współpracować z tymi zakresami historycznie zarezerwowanych adresów.
[127.0.0.1, 127.255.255.254]
Adresy w tym zakresie (127/8) są traktowane jako adresy pętli zwrotnej, podobnie do standardowego adresu pętli zwrotnej INADDR_LOOPBACK (127.0.0.1);
[224.0.0.0, 239.255.255.255]
Adresy w tym zakresie (224/4) są przeznaczone do użycia grupowego (multicast).

Opcje gniazda

Patrz IPPROTO_IP(2const).

Interfejsy /proc

Patrz proc_sys_net_ipv4(5).

Kontrolki systemowe (ioctl)

Do protokołu ip mają zastosowanie wszystkie kontrolki wejścia/wyjścia opisane w socket(7).

Kontrolki konfigurowania ogólnych parametrów urządzenia są opisane w netdevice(7).

BŁĘDY

Użytkownik próbował wykonać operację, nie mając potrzebnych praw. Obejmuje to: wysyłanie pakietu na adres rozgłoszeniowy bez ustawionego znacznika SO_BROADCAST, wysyłanie pakietu zakazaną drogą, próbę modyfikacji ustawień zapory sieciowej, nie mając uprawnień administratora (ustawionego przywileju CAP_NET_ADMIN), próbę przypisania uprzywilejowanego portu, nie mając uprawnień administratora (ustawionego przywileju CAP_NET_BIND_SERVICE).
Próbowano przypisać port do adresu będącego już w użyciu.
Zażądano nieistniejącego interfejsu lub żądany adres źródłowy nie jest adresem lokalnym.
Operacja na gnieździe z wyłączonym blokowaniem spowodowałaby zablokowanie.
Operacja łączenia na gnieździe nieblokującym już trwa.
Połączenie zostało zamknięte podczas accept(2).
Brak wpisu określającego adres docelowy w tabeli trasowania. Błąd ten może być wywołany przez komunikat ICMP od zdalnego routera lub dla lokalnej tabeli trasowania.
Przypisano niewłaściwy argument. W przypadku operacji wysyłania może to być spowodowane przez wysyłanie drogą przypisaną do czarnej dziury.
connect(2) była wywołana na już połączonym gnieździe.
Datagram jest większy niż wartość MTU po drodze do celu i nie może być podzielony.
Niewystarczająca ilość dostępnej pamięci. Często oznacza to, że przydzielanie pamięci jest ograniczone przez ograniczenia bufora gniazda, a nie przez ograniczenia pamięci systemowej. Jednak nie jest to pewne na 100%.
SIOCGSTAMP było wywołane na gnieździe, do którego nie dotarł żaden pakiet.
Podsystem jądra nie był konfigurowany.
Przypisano niewłaściwą opcję gniazda.
Operacja może być wykonana tylko na połączonym gnieździe, a gniazdo nie zostało połączone.
Użytkownik nie ma praw do ustawiania wysokiego priorytetu, zmiany konfiguracji lub wysyłania sygnałów do żądanych procesów lub grup procesów.
Połączenie zostało nieoczekiwanie zamknięte lub wyłączył się drugi koniec.
Gniazdo nie jest skonfigurowane lub zażądano nieznanego typu gniazda.

Inne błędy mogą być generowane przez protokoły wyższych warstw; obejrzyj tcp(7), raw(7), udp(7) i socket(7).

UWAGI

Należy być bardzo ostrożnym przy stosowaniu opcji SO_BROADCAST - nie jest ona w systemie Linux uprzywilejowana, jest więc łatwo przeciążyć sieć za pomocą niedbale użytych rozgłoszeń. W przypadku protokołów nowych aplikacji lepiej używać grupy adresowej zamiast rozgłoszeń. Stosowanie adresów rozgłoszeniowych jest niezalecane. W RFC 6762 pokazany jest przykład protokołu (mDNS) korzystającego z nowocześniejszego podejścia do komunikacji z otwartą grupą stacji w sieci lokalnej.

Używanie poziomu opcji gniazd SOL_IP jest nieprzenośne; gniazda oparte na BSD używają poziomu IPPROTO_IP.

INADDR_ANY (0.0.0.0) i INADDR_BROADCAST (255.255.255.255) są neutralne pod kątem kolejności bajtów. Oznacza to, że nie wpływa na nie htonl(3).

Zgodność

Dla zgodności z Linuksem 2.0, wciąż jest dopuszczalna przestarzała składnia socket(AF_INET, SOCK_PACKET, protokół), by stworzyć gniazdo typu packet(7). Nie jest to zbyt poprawne i powinno być zastępowane przez socket(AF_PACKET, SOCK_RAW, protokół). Głównym powodem jest różnica w strukturze adresowej sockaddr_ll przechowującej informacje dla warstwy łącza (dokładniej: warstwy kanałowej), które kiedyś przechowywane były w sockaddr_pkt.

USTERKI

Jest zbyt wiele nieokreślonych wartości błędów.

Błąd używany do zdiagnozowania wyczerpania się zakresu portów efemerycznych różni się między poszczególnymi wywołaniami systemowymi (connect(2), bind(2), listen(2), sendto(2)), które przypisują porty efemeryczne.

Nie są opisane kontrolki wejścia/wyjścia do konfigurowania specyficznych dla IP opcji interfejsu i tabele ARP.

Pobieranie pierwotnego adresu docelowego za pomocą wywołania recvmsg(2) z MSG_ERRQUEUE w msg_name nie działa w niektórych jądrach Linux 2.2.

ZOBACZ TAKŻE

IPPROTO_IP(2const), recvmsg(2), sendmsg(2), byteorder(3), capabilities(7), icmp(7), ipv6(7), netdevice(7), netlink(7), raw(7), socket(7), tcp(7), udp(7), ip(8)

Plik źródeł jądra Documentation/networking/ip-sysctl.rst.

RFC 791 - oryginalny opis IP. RFC 1122 - wymagania stacji IPv4. RFC 1812 - wymagania rutera IPv4.

TŁUMACZENIE

Tłumaczenie niniejszej strony podręcznika: Paweł Wilk <siefca@pl.qmail.org>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.

8 lutego 2026 r. Linux man-pages 6.18