ip(7) Miscellaneous Information Manual ip(7)

ip - Implementacja protokołu IPv4 dla systemu Linux

#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);

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.

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.


struct sockaddr_in {
    sa_family_t    sin_family; /* rodzina adresów: AF_INET */
    in_port_t      sin_port;   /* port - sieciowa kolejność bajtów */
    struct in_addr sin_addr;   /* adres internetowy */
};
/* adres internetowy */
struct in_addr {
    uint32_t       s_addr;     /* adres - sieciowa kolejność bajtów */
};

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 (maszyny). Pole s_addr struktury struct in_addr zawiera adres interfejsu maszyny w sieciowej kolejności bajtów. Polu in_addr 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ę.

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;
ma w przypadku bind(2), ze względów historycznych, taki sam skutek jak INADDR_ANY. 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).

IP wspiera niektóre opcje specyficzne dla protokołu, które mogą być ustawione przy użyciu setsockopt(2) i odczytane z pomocą getsockopt(2). Poziom opcji gniazda dla IP to IPPROTO_IP. Dla każdego ze znaczników logicznych wartość całkowita zero oznacza fałsz, a każda inna - prawdę.

Gdy poda się nieprawidłową opcję gniazda, getsockopt(2) i setsockopt(2) zwrócą błąd ENOPROTOOPT.

Przyłącza grupę adresów. Argumentem jest struktura ip_mreqn .

struct ip_mreqn {
    struct in_addr imr_multiaddr; /* grupowy adres IP */
    struct in_addr imr_address;   /* adres IP interfejsu
                                     lokalnego */
    int            imr_ifindex;   /* indeks interfejsu */
};

imr_multiaddr zawiera adres grupy, którą aplikacja chce podłączyć lub rozłączyć. Musi być to poprawny adres grupowy (multicast; w przeciwnym wypadku setsockopt(2) zwróci błąd EINVAL). imr_address jest to adres lokalnego interfejsu, przez który system powinien połączyć grupę; jeśli jest równy INADDR_ANY, to odpowiedni interfejs jest wybierany przez system. imr_ifindex jest indeksem interfejsu, który powinien być podłączony/odłączony do obsługi grupy imr_multiaddr lub 0, by wskazać na dowolny interfejs.
Struktura ip_mreqn jest dostępna tylko od wersji 2.2 Linuksa. Dla kompatybilności, stara struktura ip_mreq wciąż jest obsługiwana. Różni się wprawdzie od ip_mreqn, lecz tylko tym, że nie zawiera pola imr_ifindex (jądro określa którą strukturę zastosowano na podstawie rozmiaru podanego w optlen).
IP_ADD_MEMBERSHIP jest prawidłowe wyłącznie dla setsockopt(2).
Przyłącza adres grupowy (multicast) i zezwala na otrzymywanie danych jedynie z podanego źródła. Argumentem jest struktura ip_mreq_source.

struct ip_mreq_source {
    struct in_addr imr_multiaddr;  /* grupowy adres IP */
    struct in_addr imr_interface;  /* adres IP interfejsu
                                      lokalnego */
    struct in_addr imr_sourceaddr; /* adres IP
                                      grupowego źródła */
};

Struktura ip_mreq_source jest podobna do ip_mreqn opisanej pod hasłem IP_ADD_MEMBERSHIP. Pole imr_multiaddr zawiera adres grupowy do którego aplikacja ma zamiar dołączyć lub opuścić go. Pole imr_interface jest adresem interfejsu lokalnego z którego system powinien dołączyć do adresu grupowego. Pole imr_sourceaddr zawiera adres źródłowy, z którego aplikacja ma zamiar otrzymywać dane.
Opcja może być użyta kilkakrotnie aby otrzymywać dane z kilku źródeł.
Informuje jądro, aby nie rezerwować portu efemerycznego przy korzystaniu z bind(2) z numerem portu 0. Port będzie wybrany automatycznie później, w trakcie wykonywania connect(2), w sposób umożliwiający współdzielenie portu źródłowego tak długo, jak długo unikatowa jest czteroelementowa krotka.
Kończy otrzymywanie danych grupowych z podanego źródła i podanej grupy. Jest to odpowiednie jedynie po zapisaniu się do adresu grupowego za pomocą IP_ADD_MEMBERSHIP lub IP_ADD_SOURCE_MEMBERSHIP.
Argumentem jest struktura ip_mreq_source opisana w części dotyczącej IP_ADD_SOURCE_MEMBERSHIP.
Odłącza się od grupy adresów. Argumentem jest struktura ip_mreqn lub ip_mreq podobna do IP_ADD_MEMBERSHIP.
Odłącza się od grupy z podanego źródła — zaprzestaje otrzymywania danych z podanej grupy adresów pochodzącej z podanego źródła. Jeśli programy zostały przypisane do wielu źródeł z tej samej grupy, dane z pozostałych źródeł wciąż będą dostarczane. Aby zatrzymać otrzymywanie danych ze wszystkich źródeł na raz, należy użyć IP_DROP_MEMBERSHIP.
Argumentem jest struktura ip_mreq_source opisana w części dotyczącej IP_ADD_SOURCE_MEMBERSHIP.
Jeśli jest włączona, to ta opcja logiczna pozwala na przypisanie do adresu nielokalnego lub (jeszcze) nieistniejącego. Pozwala to na nasłuchiwanie na gnieździe bez wymagania, żeby interfejs sieciowy niższej warstwy lub podany dynamiczny adres IP były ustawione podczas próby przypisania gniazda przez aplikację. Ta opcja jest odpowiednikiem - dla pojedynczego gniazda - opisanego poniżej interfejsu /proc ip_nonlocal_bind.
Jeśli włączone, to dopuszczalne jest tworzenie przez użytkownika własnego nagłówka IP przed danymi użytkownika. Działa to jedynie dla gniazd SOCK_RAW, patrz raw(7), by uzyskać więcej informacji. Gdy ten znacznik jest włączony, to wartości ustawiane przez IP_OPTIONS, IP_TTL i IP_TOS są ignorowane.
Ustawia lub pobiera domyślny przedział lokalnych portów przypisany do gniazda. Opcji tej można użyć do zawężenia dla danego gniazda, globalnego przedziału lokalnych portów, zdefiniowanego w interfejsie /proc ip_local_port_range opisanym poniżej.
Opcja przyjmuje wartość uint32_t, gdzie wysokie 16 bitów ustawia górną granicę przedziału (włącznie), a niskie 16 bitów ustawia dolną granicę przedziału (włącznie). Wartości 16-bitowe powinny przestrzegać kolejności bajtów komputera.
Dolna granica przedziału musi być mniejsza od górnej granicy przedziału, a żadna nie może wynosić zero. Przy naruszeniu tych warunków, ustawienie opcji zawiedzie z błędem EINVAL.
Jeśli któraś z granic jest poza globalnym przedziałem portów lokalnych lub wynosi zero, to przedział nie ma zastosowania.
Aby zresetować ustawienie, należy podać zero jako zarówno górną jak i dolną granicę przedziału.
Opcja pozwala na uzyskanie dostępu do zaawansowanego interfejsu filtrowania pełnostanowego. Argumentem jest struktura ip_msfilter.

struct ip_msfilter {
    struct in_addr imsf_multiaddr; /* grupowy adres IP
    struct in_addr imsf_interface; /* adres IP interfejsu
                                      lokalnego */
    uint32_t       imsf_fmode;     /* Tryb filtrowania */
    uint32_t       imsf_numsrc;    /* Liczba źródeł
                                      w poniższej tablicy */
    struct in_addr imsf_slist[1];  /* Tablica źródeł
                                      adresów */
};

Do określenia trybu filtrowania służą dwa makra - MCAST_INCLUDE i MCAST_EXCLUDE. Makro IP_MSFILTER_SIZE(n) służy natomiast do określenia wielkości pamięci potrzebnej do przechowania struktury ip_msfilter z n źródeł w liście źródeł.
Pełny opis filtrowania źródeł adresów zawiera dokument RFC 3376.
Pobiera bieżącą wartość MTU ścieżki obecnego gniazda. Zwraca liczbę całkowitą.
IP_MTU jest poprawne tylko do getsockopt(2) i można go użyć wyłącznie gdy gniazdo zostało połączone.
Ustawia lub pobiera opcję badania MTU ścieżki (ang. Path MTU Discovery) dla gniazda. Gdy opcja ta jest włączona, to Linux będzie przeprowadzał badanie MTU ścieżki dla gniazd SOCK_STREAM zgodnie z definicją zawartą w RFC 1191. W przypadku gniazd nie będących gniazdami SOCK_STREAM, IP_PMTUDISC_DO wymusza ustawienie we wszystkich pakietach wychodzących znacznika zakazu fragmentacji. Za poprawne zgodne z wartością MTU, podzielenie na pakiety i za wykonanie ewentualnych retransmisji jest odpowiedzialny program użytkownika. Jądro odrzuci (z błędem EMSGSIZE) pakiety większe niż znane MTU ścieżki. Ustawienie znacznika IP_PMTUDISC_WANT spowoduje sfragmentowanie datagramu, jeśli MTU ścieżki tego wymaga, albo - w przeciwnym wypadku - ustawienie znacznika zakazującego fragmentacji.
Domyślną dla systemu wartość można ustawić na IP_PMTUDISC_WANT lub na IP_PMTUDISC_DONT, wpisując odpowiednio - zero lub wartość niezerową - do pliku /proc/sys/net/ipv4/ip_no_pmtu_disc.
Wart. badan. MTU ścieżki Znaczenie
IP_PMTUDISC_WANT Używaj ustawień zależnych od trasy.
IP_PMTUDISC_DONT Nie badaj MTU ścieżki.
IP_PMTUDISC_DO Zawsze badaj MTU ścieżki.
IP_PMTUDISC_PROBE Ustawia bit DF, ale ignoruje MTU ścieżki.
Gdy włączone jest badanie MTU ścieżki, jądro automatycznie namierza wartości MTU ścieżki dla każdego komputera docelowego. Gdy aktywne jest połączenie z danym komputerem, można wygodnie odczytać aktualnie rozpoznaną wartość MTU ścieżki za pomocą connect(2) używając opcji gniazda IP_MTU (np. po wystąpieniu błędu EMSGSIZE). Wartość MTU ścieżki może się zmieniać z czasem. Dla gniazd bezpołączeniowych z wieloma komputerami docelowymi MTU dla danego, również nowego, komputera docelowego można uzyskać za pomocą kolejki błędów (zobacz IP_RECVERR). Po nadejściu każdej aktualizacji MTU zostanie skolejkowany nowy błąd.
W trakcie rozpoznawania MTU, pakiety inicjujące z gniazd datagramowych mogą zostać porzucone. Programy korzystające z UDP powinny być tego świadome i nie brać tego pod uwagę w swojej strategii retransmisji pakietów.
Aby zainicjować proces badania MTU ścieżki dla gniazd niepołączonych, można rozpocząć z dużym rozmiarem datagramu (nagłówek o długości do 64 kilobajtów) i pozwolić na jego zmniejszenie w wyniku aktualizacji MTU ścieżki.
Aby oszacować inicjalne MTU ścieżki, należy podłączyć gniazdo datagramowe do adresu docelowego za pomocą connect(2) i pobrać MTU, wołając getsockopt(2) z opcją IP_MTU.
Poprzez ustawienie wartości w IP_PMTUDISC_PROBE (dostępnej od Linuksa 2.6.22) możliwe jest zaimplementowanie opisanego w RFC 4821 próbkowania MTU dla gniazd SOCK_DGRAM lub SOCK_RAW. Jest to szczególnie użyteczne w narzędziach diagnostycznych typu tracepath(8), które w sposób zamierzony chcą wysyłać pakiety testowe większe niż zaobserwowane MTU ścieżki.
Tej opcji można użyć do modyfikacji zasad dostarczania wiadomości grupowych. Argument wynosi 0 lub 1 (domyślnie 1). Gdy jest ustawiony na 1, to gniazdo otrzyma wiadomości ze wszystkich grup, które dołączono globalnie z całego systemu. W przeciwnym razie dostarczone będą tylko wiadomości z grup dołączonych jawnie (np. opcją IP_ADD_MEMBERSHIP) do tego konkretnego gniazda.
Ustawia lokalne urządzenie dla gniazda grupowego. Argumentem do setsockopt(2) jest ip_mreqn lub (od Linuksa 3.5) ip_mreq, struktura podobna do IP_ADD_MEMBERSHIP; albo struktura in_addr (jądro określa którą strukturę się podało na podstawie rozmiaru przekazanego w optlen). Do getsockopt(2) argumentem jest struktura in_addr.
Ustawia lub pobiera logiczny argument typu całkowitego, określający, czy przesyłane pakiety grupowe powinny wracać do lokalnego gniazda.
Ustawia lub pobiera wartość czasu życia pakietu dla wychodzących z tego gniazda pakietów grupowych. Jest bardzo istotne w przypadku adresowania grupowego, by ustawić najmniejszą możliwą wartość TTL. Domyślnie jest to 1, co oznacza, że pakiety grupowe nie opuszczają sieci lokalnej, chyba że program użytkownika wyraźnie tego żąda. Argument jest liczbą całkowitą.
Jeśli włączone (argument jest niezerowy), łączenie pakietów wychodzących przez warstwę netfilter jest wyłączone. Argumentem jest liczba całkowita.
Ta opcja jest prawidłowa tylko dla gniazd SOCK_RAW.
Ustawia lub pobiera opcje IP, które będą wysyłane z każdym pakietem z danego gniazda. Argumenty są wskaźnikiem do bufora pamięci zawierającego opcje i ich długości. setsockopt(2) ustawia opcje IP skojarzone z gniazdem. Maksymalny rozmiar opcji dla IPv4 to 40 bajtów. Zobacz RFC 791, by poznać możliwe opcje. Gdy pakiet wstępnego potwierdzenia połączenia (ACK) dla gniazda typu SOCK_STREAM zawiera opcje IP, to opcje wychodzącego pakietu IP będą automatycznie pobrane z opcji IP pobranego pakietu z odwróconymi nagłówkami mówiącymi o trasie. Po ustanowieniu połączenia przychodzące pakiety nie są uprawnione do zmiany swoich opcji. Przetwarzanie wszystkich przychodzących opcji źródła jest domyślnie wyłączone, ale można je włączyć ustawiając accept_source_route w interfejsie /proc. W przypadku gniazd datagramowych opcje IP mogą być ustawione jedynie przez użytkownika lokalnego. Funkcja getsockopt(2) z argumentem IP_OPTIONS zwróci obecnie wysłane opcje przez umieszczenie ich w dostarczonym buforze.
Jeśli na stacjach wysyłających i przyjmujących skonfigurowano etykietowany IPSEC lub NetLabel, opcja ta włącza kontekst bezpieczeństwa drugiego gniazda, w komunikacie pomocniczym typu SCM_SECURITY, odbieranym za pomocą recvmsg(2). Opcja jest wspierana tylko dla gniazd UDP; w przypadku gniazd TCP lub SCTP proszę przeczytać opis opcji SO_PEERSEC poniżej.
Podana wartość jest argumentem do setsockopt(2), a zwracana jako wynik getsockopt(2) jest flaga logiczna będąca liczbą całkowitą.
Kontekst bezpieczeństwa zwrócony przez komunikat pomocniczy SCM_SECURITY ma ten sam format, jak opisany przy opcji SO_PEERSEC poniżej.
Uwaga: ponowne użycie typu komunikatu SCM_SECURITY dla opcji gniazda IP_PASSSEC było prawdopodobnie pomyłką, jako że pozostałe komunikaty kontrolne IP mają swój schemat numeracji w przestrzeni nazw IP i często używają wartości opcji gniazda jako typu komunikatu. Obecnie nie występuje konflikt, ponieważ opcją IP z taką samą wartością jak SCM_SECURITY jest IP_HDRINCL, a ona nigdy nie jest używana do typu komunikatów kontrolnych.
Przekazuje pomocniczy komunikat IP_PKTINFO zawierający strukturę pktinfo dostarczającą trochę informacji o przychodzącym pakiecie. Działa to jedynie dla gniazd datagramowych. Argument jest znacznikiem mówiącym gniazdu, czy należy przekazać komunikat IP_PKTINFO, czy też nie. Sam komunikat może zostać przesłany/otrzymany wraz z pakietem jedynie jako komunikat sterujący za pomocą recvmsg(2) lub sendmsg(2).

struct in_pktinfo {
    unsigned int   ipi_ifindex;  /* Indeks interfejsu */
    struct in_addr ipi_spec_dst; /* Adres lokalny */
    struct in_addr ipi_addr;     /* Nagłówek adresu
                                    docelowego */
};

ipi_ifindex jest unikatowym indeksem interfejsu, przez który pakiet został odebrany. Adres ipi_spec_dst jest lokalnym adresem pakietu, a ipi_addr jest adresem docelowym wynikającym z nagłówka pakietu. Jeśli IP_PKTINFO jest przekazane do sendmsg(2), a ipi_spec_dst ma wartość niezerową, to zostanie użyte jako źródłowy adres lokalny podczas przeszukiwania tablicy trasowania i dla ustawienia opcji trasowania według adresu źródłowego. Gdy ipi_ifindex ma wartość niezerową, to podstawowy adres lokalny interfejsu wskazywanego przez ten indeks nadpisuje ipi_spec_dst podczas przeszukiwania tablicy trasowania.
Włącza przekazywanie dodatkowych komunikatów o błędach, zwiększając niezawodność połączenia. Gdy jest to ustawione w gnieździe datagramowym, to wszystkie generowane błędy będą zapamiętane w specjalnej kolejce błędów przypisanej do gniazda. Gdy użytkownik (proces użytkownika) otrzyma błąd (przez zwrócony kod błędu operacji na gnieździe), to może go odebrać, używając funkcji recvmsg(2) z ustawionym znacznikiem MSG_ERRQUEUE. Struktura opisująca błąd sock_extended_err zostanie przekazana w pomocniczym komunikacie o typie IP_RECVERR i poziomie IPPROTO_IP. Jest to niezwykle pomocne przy niezawodnym przechwytywaniu błędów niepołączonych gniazd. Odbierana z kolejki błędów porcja danych zawiera pakiet z informacją o błędzie.
Komunikat sterujący IP_RECVERR zawiera strukturę sock_extended_err zdefiniowaną następująco:

#define SO_EE_ORIGIN_NONE    0
#define SO_EE_ORIGIN_LOCAL   1
#define SO_EE_ORIGIN_ICMP    2
#define SO_EE_ORIGIN_ICMP6   3
struct sock_extended_err {
    uint32_t ee_errno;   /* numer błędu */
    uint8_t  ee_origin;  /* źródło błędu */
    uint8_t  ee_type;    /* typ */
    uint8_t  ee_code;    /* kod */
    uint8_t  ee_pad;
    uint32_t ee_info;    /* informacje dodatkowe */
    uint32_t ee_data;    /* inne dane */ 
    /* Dalej mogą wystąpić dodatkowe dane */
};
struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

ee_errno zawiera numer errno błędu kolejki. ee_origin jest kodem miejsca pochodzenia błędu. Pozostałe pola są zależne od protokołu. Makro SO_EE_OFFENDER zwraca wskaźnik do adresu obiektu sieciowego, z którego pochodził błąd o zadanym wskaźniku do komunikatu pomocniczego. Gdy ten adres nie jest znany, pole sa_family struktury sockaddr zawiera wartość AF_UNSPEC a pozostałe pola tej struktury sockaddr są niezdefiniowane.
IP używa struktury sock_extended_err w następujący sposób: ee_origin ustawione na SO_EE_ORIGIN_ICMP dla błędów odbieranych jako pakiet ICMP albo też SO_EE_ORIGIN_LOCAL dla błędów generowanych lokalnie. Nieznane wartości należy ignorować. ee_type i ee_code są ustawiane zgodnie z typem i kodem pól w nagłówku ICMP. ee_info zawiera rozpoznaną wartość MTU dla błędów EMSGSIZE. Komunikat zawiera również sockaddr_in węzła, który spowodował błąd, a do którego można uzyskać dostęp za pomocą makra SO_EE_OFFENDER. Pole sin_family adresu SO_EE_OFFENDER ma wartość AF_UNSPEC, gdy źródło błędu nie jest znane. Gdy błąd pochodzi z sieci, wszystkie opcje IP (IP_OPTIONS, IP_TTL itd.) włączone w gnieździe i zawarte w pakiecie błędu są przekazywane jako komunikaty kontrolne. Właściwe dane pakietu, który spowodował błąd są zwracane jako normalne dane. Należy zauważyć, że TCP nie ma kolejki błędów; MSG_ERRQUEUE jest nielegalne w przypadku gniazd SOCK_STREAM. IP_RECVERR jest poprawne dla TCP, ale wszystkie błędy są przekazywane przez zwracaną wartość funkcji albo przez SO_ERROR.
Dla gniazd surowych, IP_RECVERR włącza przepuszczanie do aplikacji wszystkich odebranych komunikatów ICMP o błędach. W przeciwnym przypadku błędy są zgłaszane tylko dla gniazd połączonych.
Ustawia lub pobiera znacznik logiczny zapisany za pomocą liczby całkowitej. IP_RECVERR jest domyślnie wyłączone.
Przekazuje użytkownikowi wszystkie nadchodzące opcje IP z komunikatu sterującego IP_OPTIONS. Nagłówek wyboru trasy i inne opcje są już wstępnie wypełnione informacjami o lokalnej maszynie. Nieobsługiwane w przypadku gniazd typu SOCK_STREAM.
Ta opcja logiczna włącza komunikat pomocniczy IP_ORIGDSTADDR w recvmsg(2), w którym jądro zwraca oryginalny adres docelowy otrzymywanego właśnie datagramu. Ten komunikat pomocniczy zawiera strukturę struct sockaddr_in.
Jeśli jest ustawione, to pomocniczy komunikat IP_TOS jest przepuszczany razem z nadchodzącymi pakietami. Zawiera on bajt, który określa pole zdefiniowane także jako bajt znajdujące się w nagłówku pakietu, a zwane Typ Usługi/Pierwszeństwa. Wymaga logicznego znacznika w postaci liczby całkowitej.
Gdy ten znacznik jest ustawiony, przepuszczany jest komunikat pomocniczy IP_TTL, zawierający pole określane mianem „czas życia” odbieranego pakietu w postaci 32-bitowej liczby. Nie jest to wspierane w przypadku strumieniowych gniazd typu SOCK_STREAM.
Działanie identyczne do IP_RECVOPTS, ale zwraca surowe, nieprzetworzone opcje, włącznie z rekordem opcji, mówiącym o znaczniku czasowym i trasie, niewypełnionym wartościami w tym przejściu pakietu.
Przekazuje wszystkie pakiety z opcją alarmu rutera IP, które miałyby być przekazywane (ang. forwarded) do tego gniazda. Działa tylko dla gniazd surowych. Jest to przydatne na przykład dla demonów RSVP działających w przestrzeni użytkownika. Wykorzystane pakiety nie są przekazywane (ang. forwarded) przez jądro. Ponowne ich wysłanie należy do obowiązków programu użytkownika. Dowiązywanie gniazda jest w tym przypadku ignorowane, pakiety te są filtrowane jedynie na podstawie protokołu. Wymaga liczby całkowitej jako argumentu.
Ustawia lub pobiera pole znacznika Typ-Usługi (ang. Type-Of-Service, w skrócie TOS), które jest przesyłane z każdym pakietem IP pochodzącym z danego gniazda. Służy do ustalenia priorytetów pakietów w sieci. TOS jest bajtem. Oto definicje niektórych standardowych znaczników TOS: IPTOS_LOWDELAY - minimalizacja opóźnienia we wzajemnym ruchu, IPTOS_THROUGHPUT - optymalizacja wyjścia, IPTOS_RELIABILITY - optymalizacja pod kątem niezawodności, a IPTOS_MINCOST powinna być używana jako „dane wypełniające” tam, gdzie szybkość transmisji nie ma większego znaczenia. Można podać najwyżej jedną z powyższych wartości TOS. Inne bity są niepoprawne i powinny być wyzerowane. Linux domyślnie wysyła najpierw datagram IPTOS_LOWDELAY, ale dokładne zachowanie zależy od konfiguracji właściwości szeregowania. Niektóre poziomy o wysokim priorytecie mogą wymagać uprawnień administratora (ustawionego atrybutu CAP_NET_ADMIN).
Ustawienie tej opcji logicznej włącza przezroczyste (ang. „transparent”) proxy dla tego gniazda. Ta opcja gniazda pozwala wywołującej aplikacji przypisanie gniazda do nielokalnego adresu IP i operowanie jako zarówno klient, jak i serwer z zewnętrznym adresem IP dla lokalnego punktu docelowego. UWAGA: wymaga to takiego ustawienia reguł trasowania, żeby pakiety wysyłane na ten adres zewnętrzny były przekazywane przez TProxy (tj. system na którym działa aplikacja korzysta z opcji gniazda IP_TRANSPARENT). Włączenie tej opcji wymaga uprawnień administratora (przywilej CAP_NET_ADMIN).
Przekierowanie TProxy używające celu TPROXY z iptables(8) także wymagają włączenia tej opcji w przekierowywanym gnieździe.
Ustawia lub pobiera pole „czas życia” (ang. Time-To-Live, w skrócie TTL) dla każdego wychodzącego z danego gniazda pakietu IP.
Odblokowuje zablokowaną uprzednio grupę adresów. Zwraca EADDRNOTAVAIL gdy podane źródło nie było zablokowane.
Argumentem jest struktura ip_mreq_source opisana w części dotyczącej IP_ADD_SOURCE_MEMBERSHIP.
Jeśli na stacjach wysyłających i przyjmujących skonfigurowano etykietowany IPSEC lub NetLabel, ta opcja gniazda tylko do odczytu zwraca kontekst bezpieczeństwa drugiego gniazda połączonego z tym gniazdem. Domyślnie będzie to taka sama wartość jak wartość kontekstu procesu tworzącego drugie gniazdo, chyba że zostanie przesłoniona zasadami lub procesem z wymaganymi uprawnieniami.
Argumentem do getsockopt(2) jest wskaźnik do bufora określonej długości w bajtach, którego łańcuch kontekstu bezpieczeństwa ma zostać skopiowany. Jeśli długość bufora jest mniejsza niż długość łańcucha kontekstu bezpieczeństwa, to getsockopt(2) zwróci -1, ustawi errno na ERANGE i zwróci wymaganą długość za pomocą optlen. Wywołujący powinien początkowo przydzielić co najmniej NAME_MAX bajtów dla bufora, choć nie ma gwarancji, że będzie to wielkość wystarczająca. Może zajść konieczność dostosowania wielkości bufora do zwróconej długości i wykonanie drugiego podejścia.
Łańcuch kontekstu bezpieczeństwa może zawierać kończący znak null w zwracanej długości, ale nie jest to gwarantowane. Kontekst bezpieczeństwa "foo" może być reprezentowany jako {'f','o','o'} o długości 3 lub {'f','o','o','\0'} o długości 4, oba te warianty są uważane za równorzędne. Łańcuch jest drukowalny, nie zawiera znaków null innych niż kończące łańcuch oraz ma nieokreślone kodowanie (w szczególności, nie gwarantuje się kodowania ASCII lub UTF-8).
Użycie tej opcji do gniazd w rodzinie adresowej AF_INET jest obsługiwane od Linuksa 2.6.17 w przypadku gniazd TCP, a od Linuksa 4.17 w przypadku gniazd SCTP.
W przypadku SELinuksa, NetLabel przenosi jedynie część MLS kontekstu bezpieczeństwa partnera poprzez łącze, pozostała część kontekstu bezpieczeństwa uzyskuje wartości domyślne, zdefiniowane w początkowym identyfikatorze bezpieczeństwa (SID) netmsg. NetLabel można jednak skonfigurować, w celu przesyłania pełnego kontekstu bezpieczeństwa pętlą zwrotną. Etykietowany IPSEC zawsze przekazuje pełny kontekst bezpieczeństwa, jako część ustanawiania powiązania bezpieczeństwa (ang. security association – SA) i sprawdza je w zależności od powiązania dla każdego pakietu.

Protokół IP obsługuje zbiór interfejsów /proc i korzysta z niech do ustawiania niektórych parametrów globalnych. Parametry są dostępne przez zapis lub odczyt plików z katalogu /proc/sys/net/ipv4/. Interfejsy opisane jako logiczne pobierają liczbę całkowitą, której wartość niezerowa („prawda”) oznacza, że dana opcja jest włączona, a zero („fałsz”), oznacza, że opcja jest wyłączona.

[Nowa w Linuksie 2.2.13; we wcześniejszych wersjach jądra funkcją tą sterowało się w czasie kompilacji za pomocą opcji CONFIG_IP_ALWAYS_DEFRAG, która nie jest już obecna w Linuksie 2.4.x i kolejnych]
Gdy ten znacznik logiczny jest włączony (różny od 0), przychodzące fragmenty (części pakietów IP, które się pojawiają, gdy pewien komputer pomiędzy komputerem źródłowym a docelowym zdecyduje, że pakiety były za duże i podzieli je na kawałki) będą ponownie złożone (zdefragmentowane) przed ich przetworzeniem, nawet jeśli mają być przekazane dalej (and. forwarded).
Należy włączać jedynie przy działającej zaporze sieciowej, stanowiącej główne wejście do danej sieci lub działającym przezroczystym proxy; nigdy nie należy tego włączać na zwykłym routerze lub komputerze. W przeciwnym przypadku łączność może zostać zakłócona, gdy fragmenty będą podróżować innymi łączami. Defragmentacja powoduje również znaczne wykorzystanie pamięci i czasu procesora.
Jest to włączane automagicznie, gdy skonfigurowane jest maskowanie lub przezroczyste proxy.
Nie udokumentowane.
Ustawia domyślną wartość „czasu życia” (ang. time-to-live) wychodzących pakietów. Może być ona zmieniona dla gniazda za pomocą opcji IP_TTL.
Włącza dynamiczne adresowanie gniazda oraz przepisywanie adresu dla maskowania przy zmianie adresu interfejsu. Jest to bardzo przydatne w przypadku korzystania z interfejsu sprzęgniętego z linią telefoniczną, którego adres IP może się zmieniać. 0 oznacza brak przepisywania, 1 włącza przepisywanie, a 2 włącza tryb rozwlekły (ang. verbose).
Włącza przekazywanie (ang. forwarding) pakietów przy użyciu logicznego znacznika. Może być ustawione także na podstawie interfejsu.
Plik zawierający dwa liczby całkowite określające domyślny zakres lokalnych portów przypisanych do gniazd niebędących bezpośrednio przydzielonych do portu — tj. zakres ten jest używany do portów efemerycznych (portów przypisywanych dynamicznie). Port efemeryczny jest przydzielany do gniazda w następujących sytuacjach:
numer portu w adresie gniazda jest określony jako 0 w trakcie wywoływania bind(2);
listen(2) jest wywoływane na gnieździe strumieniowym, które nie było wcześniej przydzielone;
connect(2) była wywołana na gnieździe, które nie było wcześniej przydzielone;
sendto(2) jest wywoływane na gnieździe datagramowym, które nie było wcześniej przydzielone.
Przypisywanie portów efemerycznych rozpoczyna się od pierwszego numeru w ip_local_port_range i kończy się na drugim numerze. Jeśli wyczerpie się zakres portów efemerycznych, to odpowiednie wywołanie systemowe zwróci błąd (ale proszę sprawdzić rozdział USTERKI!).
Proszę zauważyć, że zakres portów w ip_local_port_range nie powinien pokrywać się z zakresem portów wykorzystywanym do maskowania (chociaż taka sytuacja jest obsługiwana). Dowolny wybór może również powodować problemy z niektórymi zaporami sieciowymi, które robią pewne założenia odnośnie do portów używanych lokalnie. Pierwsza liczba powinna być większa niż 1024, albo - co byłoby lepsze - większa niż 4096, aby uniknąć konfliktów z dobrze znanymi portami i zminimalizować problemy z zaporami sieciowymi.
Jeśli jest to włączone, to domyślnie nie będzie wykonywane badanie MTU ścieżki dla gniazd TCP. Badanie MTU może się nie sprawdzać w przypadku źle skonfigurowanych zapór sieciowych (odrzucających wszelkie pakiety ICMP) lub źle skonfigurowanych interfejsów (np. połączenie typu point-to-point, gdzie oba końce nie zgadzają się na MTU). Lepiej poprawić wszelkie wadliwie skonfigurowane rutery po drodze niż całkowicie wyłączyć badanie MTU ścieżki, ponieważ niewykonywanie tej operacji pociąga za sobą duże straty w obrębie sieci.
Jeżeli ustawione, pozwala procesowi na wywołanie funkcji bind() z nielokalnym adresem IP, co może być całkiem przydatne, ale może popsuć niektóre aplikacje.
Czas w sekundach przetrzymywania w pamięci fragmentu IPv6.
Interwał (w sekundach) odświeżania sekretnego klucza funkcji mieszającej (lub czasu życia tego klucza) dla fragmentów IPv6.
Jeśli liczba zebranych w kolejce fragmentów IP osiągnie wartość określoną przez ipfrag_high_thresh, wtedy kolejka jest opróżniana do ilości określonej w ipfrag_low_thresh. Zawiera ona liczbę całkowitą z podaną liczbą bajtów.
Patrz arp(7).

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).

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).

IP_FREEBIND, IP_MSFILTER, IP_MTU, IP_MTU_DISCOVER, IP_RECVORIGDSTADDR, IP_PASSSEC, IP_PKTINFO, IP_RECVERR, IP_ROUTER_ALERT, and IP_TRANSPARENT są typowo Linuksowe.

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.

Niektóre inne implementacje gniazd BSD dopuszczają dla gniazd opcje IP_RCVDSTADDR i IP_RECVIF używane do pobierania adresu przeznaczenia i interfejsu odbieranych datagramów. Linux udostępnia bardziej ogólną opcję IP_PKTINFO, robiącą to samo.

Niektóre implementacja gniazd BSD także udostępniają opcję IP_RECVTTL, ale łącznie z przychodzącym pakietem jest przekazywany pomocniczy komunikat o typie IP_RECVTTL. W tym właśnie różni się to od opcji IP_TTL, używanej w Linuksie.

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).

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.

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.

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.txt.

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

Autorami polskiego tłumaczenia niniejszej strony podręcznika są: 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.

31 października 2023 r. Linux man-pages 6.06