Scroll to navigation

IP(7) Руководство программиста Linux IP(7)

ИМЯ

ip - реализация протокола IPv4 в Linux

ОБЗОР

#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* включает предыдущий */

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 реализован Internet Protocol (IP) версии 4, описанный в RFC 791 и RFC 1122. В модуле ip содержится реализация второго уровня групповых сообщений, которая соответствует RFC 1112. Кроме того, в нём имеется маршрутизатор IP с фильтрацией пакетов.

Программный интерфейс совместим с интерфейсом сокетов BSD. Более подробную информацию смотрите в socket(7).

IP-сокет создаётся с помощью вызова socket(2) вида socket(AF_INET, socket_type, protocol). Значением типа сокета (socket_type) может быть: SOCK_STREAM (для открытия сокета tcp(7)), SOCK_DGRAM (для открытия сокета udp(7)), SOCK_RAW (для открытия сокета raw(7) с прямым доступом к протоколу IP). В protocol указывается значение протокола IP в IP-заголовке для принимаемых или отправляемых пакетов. Допустимые значения для параметра protocol: 0 и IPPROTO_TCP — для сокетов TCP, 0 и IPPROTO_UDP — для сокетов UDP. Для SOCK_RAW можно указать любой из IP-протоколов, описанных в RFC 1700 и зарегистрированных в IANA.

Если процесс хочет принимать новые входящие пакеты или соединения, то он должен связать сокет с адресом локального интерфейса с помощью bind(2). Каждый IP-сокет может быть связан только с одной задаваемой локальной парой (адрес, порт). Если в вызове bind(2) указать INADDR_ANY, то сокет будет связан со всеми локальными интерфейсами. При вызове listen(2) или connect(2) для несвязанного сокета происходит автоматическая привязка к произвольно выбранному свободному порту и локальному адресу INADDR_ANY.

После закрытия связанного локального TCP-сокета его адрес будет недоступен в течение некоторого времени, если только не был установлен флаг SO_REUSEADDR. Следует проявлять осторожность при использовании этого флага, поскольку это делает TCP менее надежным.

Формат адреса

Адрес IP-сокета определяется как комбинация IP-адреса интерфейса и номера порта. В самом протоколе IP нет номеров портов, они реализуются протоколами более высокого уровня, например udp(7) и tcp(7). У «сырых» (raw) сокетов номер протокола IP указывается в sin_port.


struct sockaddr_in {

sa_family_t sin_family; /* семейство адресов: AF_INET */
in_port_t sin_port; /* порт сокета в сетевом порядке
байт */
struct in_addr sin_addr; /* Интернет-адрес */ }; /* Интернет-адрес */ struct in_addr {
uint32_t s_addr; /* адрес в сетевом порядке байт */ };

Значение sin_family всегда устанавливается в AF_INET. Это обязательно; в Linux 2.2 большая часть сетевых функций возвращает код ошибки EINVAL, если это условие не выполняется. В sin_port указывается номер порта в сетевом порядке байт. Порты, номера которых меньше 1024, называются привилегированными портами (или, иногда, зарезервированными портами). Только привилегированные процессы (т.е., имеющие мандат CAP_NET_BIND_SERVICE) могут быть связаны с этими сокетами с помощью bind(2). Заметим, что у «сырого» протокола IPv4, как такового, нет понятия порта, они реализуются только протоколами более высокого уровня, типа tcp(7) и udp(7).

В sin_addr указывается IP-адрес узла. В поле s_addr структуры struct in_addr содержится адрес интерфейса узла в сетевом порядке байт. Значение in_addr должно быть одним из INADDR_* (например, INADDR_ANY) или устанавливаться с помощью библиотечных функций inet_aton(3), inet_addr(3), inet_makeaddr(3) или напрямую с помощью преобразователя имён (смотрите gethostbyname(3)).

Адреса IPv4 делятся на однозначные (unicast), широковещательные (broadcast) и групповые (multicast). Однозначный адрес указывает на один интерфейс узла, широковещательный адрес указывает на все узлы в сети, а групповой адрес указывает на все узлы определённой группы (multicast group). Дейтаграммы могут посылаться или приниматься по широковещательным адресам только, если для сокета установлен флаг SO_BROADCAST. В текущей реализации сокетам, ориентированным на соединения, разрешено иметь только однозначные адреса.

Заметим, что значения адреса и порта всегда хранятся в сетевом порядке байт. В частности, это означает, что требуется вызывать htons(3) для числа, обозначающего порт. Все функции из стандартной библиотеки, используемые для работы с адресами/портами, используют сетевой порядок байт.

Есть несколько специальных адресов: INADDR_LOOPBACK (127.0.0.1) всегда ссылается на локальный узел через интерфейс обратной петли; INADDR_ANY (0.0.0.0) означает любой адрес для связывания; INADDR_BROADCAST (255.255.255.255) означает любой узел и, по историческим причинам, при связывании подобен INADDR_ANY.

Параметры сокета

IP поддерживает некоторые параметры сокета, относящиеся к протоколу, которые могут быть установлены с помощью setsockopt(2) и прочитаны с помощью getsockopt(2). Значением уровня (level) параметров сокета для IP является IPPROTO_IP. Логический флаг в виде целого числа со значением ноль означает «ложь», другие значения — «истина».

Присоединиться к группе. В аргументе указывается структура ip_mreqn.


struct ip_mreqn {

struct in_addr imr_multiaddr; /* IP-адрес группы */
struct in_addr imr_address; /* IP- локального
интерфейса */
int imr_ifindex; /* индекс интерфейса */ };

В imr_multiaddr содержится адрес группы, в которую приложение хочет войти или выйти. Это должен быть правильный групповой адрес (иначе setsockopt(2) завершится с ошибкой EINVAL). В imr_address указывается адрес локального интерфейса, через который система должна войти в группу; если указано значение INADDR_ANY, то нужный интерфейса выбирается системой самостоятельно. В imr_ifindex указывается индекс интерфейса, через который нужно войти/выйти в группу imr_multiaddr, или 0, если интерфейс может быть любым.

Структура ip_mreqn появилась только с Linux 2.2. Для совместимости, старая структура ip_mreq (существует с Linux 1.2) всё ещё поддерживается; она отличается от ip_mreqn только отсутствующим полем imr_ifindex. Может использоваться только в setsockopt(2).
Выйти из группы. Аргументом является структура ip_mreqn или ip_mreq, описана в IP_ADD_MEMBERSHIP.
Этот логический параметр позволяет привязаться (если значение равно «истина») к IP-адресу, который не является локальным или (пока) не существует. Это позволяет прослушивать сокет, не имея нижележащего сетевого интерфейса или назначенного динамического IP-адреса, которых может ещё не быть, когда приложение пытается связаться с ним. На каждый сокет этот параметр имеет эквивалентный интерфейс в /procip_nonlocal_bind (описан далее).
Если значение равно «истина», то это означает, что пользователь добавил заголовок IP в начало своих данных. Допустим только для сокетов SOCK_RAW. Более подробную информацию смотрите в raw(7). Если этот флаг установлен, то значения, заданные параметрами IP_OPTIONS, IP_TTL и IP_TOS, игнорируются.
Возвращает известное в данный момент значение MTU маршрута текущего сокета. Допустим, только если сокет установил соединение. Возвращает целое число. Применяется только в getsockopt(2).
Устанавливает или возвращает значение Path MTU Discovery (обнаружение значения MTU маршрута) для сокета. Если он установлен, то Linux будет производить обнаружение значения MTU маршрута для сокетов SOCK_STREAM согласно RFC 1191. Для сокетов не SOCK_STREAM при значении IP_PMTUDISC_DO у всех исходящих пакетов будет устанавливаться флаг запрета фрагментации. Ответственность за разбивку данных на пакеты согласно размеру MTU, и за выполнение, по-необходимости, повторной передачи данных, лежит на пользователе. Ядро будет отвергать пакеты (с ошибкой EMSGSIZE), размер которых больше текущего значения MTU у маршрута. При значении IP_PMTUDISC_WANT дейтаграмма будет фрагментироваться по размеру MTU, если требуется, иначе устанавливается флаг запрета фрагментации.

Системное значение по умолчанию можно переключать между IP_PMTUDISC_WANT и IP_PMTUDISC_DONT, записывая, соответственно, нулевое и ненулевое значение в файл /proc/sys/net/ipv4/ip_no_pmtu_disc.

Флаг Path MTU discovery Назначение
IP_PMTUDISC_WANT Использовать для каждого маршрута своё
значение.
IP_PMTUDISC_DONT Никогда не выполнять обнаружение
значения MTU маршрута.
IP_PMTUDISC_DO Всегда выполнять обнаружение
значения MTU маршрута.
IP_PMTUDISC_PROBE Установить DF, но игнорировать Path MTU.

Если значение Path MTU Discovery задано, то ядро автоматически следит за MTU маршрута для каждого удалённого узла. Когда с некоторым узлом установлено соединение с помощью connect(2), текущее значение MTU маршрута можно легко получить через параметр сокета IP_MTU (например, после возникновения ошибки EMSGSIZE). Значение MTU может со временем меняться. Для сокетов без установления соединения, которые имеют несколько узлов-получателей, новое значение MTU для заданного узла назначения может быть получено с помощью очереди ошибок (смотрите IP_RECVERR). При каждом входящем сообщении об обновлении MTU в очередь будет добавляться новая ошибка.

Во время процесса обнаружения MTU начальные пакеты от дейтаграмных сокетов могут быть отброшены. Приложения, использующие UDP, должны учитывать это и не думать, что эти пакеты будут переданы повторно.

Чтобы запустить процесс обнаружения MTU маршрута для сокетов без установления соединения можно сначала установить большой размер дейтаграммы (с размером заголовка до 64Кбайт) и сокращать его при изменении MTU маршрута.

Чтобы получить начальную оценку MTU маршрута, соедините дейтаграмный сокет с адресом назначения, используя connect(2), и узнайте значение MTU путем вызова getsockopt(2) с параметром IP_MTU.

Возможно реализовать исследование MTU согласно RFC 4821 с помощью сокетов типа SOCK_DGRAM или SOCK_RAW, установив значение IP_PMTUDISC_PROBE (доступно, начиная с Linux 2.6.22). В частности, это также полезно для инструментов диагностики, таких как tracepath(8), которым нужно умышленно посылать проверочные пакеты большего размера чем исследуемый Path MTU.

Назначает локальное устройство для группового сокета (multicast socket). Аргументом является структура ip_mreqn или ip_mreq, описана в IP_ADD_MEMBERSHIP.
Если сокету передается неправильный параметр, то возвращается ошибка ENOPROTOOPT.
Устанавливает или возвращает логический флаг в виде целого числа, в зависимости от того, будут ли пакеты, использующие групповую адресацию, закольцовываться на локальные сокеты.
Устанавливает или возвращает значение времени существования (time-to-live) для исходящих из этого сокета пакетов, использующих групповую адресацию. Для подобных пакетов очень важно установить наименьшее возможное значение TTL. По умолчанию оно равно 1, это значит, что групповые пакеты не выйдут за пределы локальной сети, если только пользовательская программа явно не попросит этого. Значением аргумента является целое число.
Если уставлен (аргумент не равен нулю), то уровне netfilter запрещается выполнять переборку (reassembly) исходящих пакетов. Этот параметр допускается только для сокетов с типом SOCK_RAW. sockets. Значением аргумента является целое число.
Устанавливает или возвращает параметры IP, которые посылаются с каждым пакетом из данного сокета. Аргументами являются указатель на буфер памяти с этими параметрами и размер параметра. Системный вызов setsockopt(2) устанавливает параметры IP, связанные с сокетом. Для IPv4 максимальный размер параметра IPv4 равен 40 байтам. Все возможные параметры перечислены в RFC 791. Если пакет, устанавливающий соединение с сокетом типа SOCK_STREAM, содержит параметры IP, то эти параметры IP (с инвертированными заголовками маршрутизации) будут использоваться в этом сокете. После установления соединения изменять параметрывходящими пакетами запрещено. По умолчанию, обработка всех параметров, связанных с маршрутизацией от источника, отключена, но её можно включить через интерфейс accept_source_route /proc. Другие параметры, например связанные с временными отметками (timestamp), продолжают обрабатываться. Для дейтаграмных сокетов параметры IP могут быть установлены только локальным пользователем. Вызов getsockopt(2) с параметром IP_OPTIONS помещает в указанный буфер текущие параметры IP, используемые при отправке.
Передает вспомогательное (ancillary) сообщение IP_PKTINFO с структурой pktinfo, которая содержит некоторую информацию о входящем пакете. Допускается только для сокетов, ориентированных на посылку дейтаграмм. Аргументом является флаг, который сообщает сокету, нужно ли посылать сообщение IP_PKTINFO или нет. Само сообщение может быть послано/получено только в виде управляющего сообщения с пакетом, используя recvmsg(2) или sendmsg(2).

struct in_pktinfo {

unsigned int ipi_ifindex; /* индекс интерфейса */
struct in_addr ipi_spec_dst; /* локальный адрес */
struct in_addr ipi_addr; /* заголовок адреса
назначения */ };

ipi_ifindex это уникальный индекс интерфейса, из которого был получен этот пакет. ipi_spec_dst это локальный адрес пакета, а ipi_addr это адрес назначения, указанный в заголовке пакета. Если параметр IP_PKTINFO передаётся в sendmsg(2) и ipi_spec_dst не равно нулю, то ipi_spec_dst будет использован как локальный адрес источника при просмотре таблицы маршрутизации и для установки IP-параметров маршрутизации от источника. Если значение ipi_ifindex не равно нулю, то при поиске в таблице маршрутизации вместо значения ipi_spec_dst используется первичный локальный адрес интерфейса с указанным индексом.
Делает передачу сообщений об ошибках более надёжной. Если этот параметр установлен для дейтаграмного сокета, то все возникающие ошибки будут поставлены в очередь ошибок, свою для каждого сокета. Для получения ошибки при операции с сокетом пользователь может воспользоваться вызовом recvmsg(2) с установленным флагом MSG_ERRQUEUE. Структура sock_extended_err, описывающая ошибку, будет передана в вспомогательном сообщении с типом IP_RECVERR и уровнем IPPROTO_IP. Этот параметр полезен для надежной обработки ошибок для сокетов без установления соединения. В пакете с ошибкой из очереди ошибок, также содержится порция полученных данных.
Управляющее сообщение типа IP_RECVERR содержит структуру sock_extended_err:

#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; /* номер ошибки */
uint8_t ee_origin; /* где возникла ошибка */
uint8_t ee_type; /* тип */
uint8_t ee_code; /* код */
uint8_t ee_pad;
uint32_t ee_info; /* дополнительная информация */
uint32_t ee_data; /* другие данные */
/* Дальше могут следовать данные */ }; struct sockaddr *SO_EE_OFFENDER(struct sock_extended_err *);

В ee_errno содержится номер ошибки в очереди. В ee_origin содержится код источника ошибки. Значение остальных полей зависит от протокола. Макрос SO_EE_OFFENDER возвращает указатель на адрес сетевого объекта, в котором возникла ошибка, согласно указанному указателю на вспомогательное сообщение. Если адрес неизвестен, то поле sa_family структуры sockaddr содержит AF_UNSPEC, и остальные поля sockaddr не определены.
Для IP структура sock_extended_err используется следующим образом: значение поля ee_origin устанавливается в SO_EE_ORIGIN_ICMP, если ошибка получена из пакета ICMP, или в SO_EE_ORIGIN_LOCAL, если возникла локальная ошибка. Неизвестные значения следует игнорировать. Значения полей ee_type и ee_code устанавливаются исходя из значений полей типа и кода заголовка ICMP. При ошибках EMSGSIZE поле ee_info содержит обнаруженную величину MTU. Сообщение также содержит структуру sockaddr_in для узла, вызвавшего ошибку, к которой доступна через макрос SO_EE_OFFENDER. Если источник неизвестен, то поле sin_family адреса, возвращённого макросом SO_EE_OFFENDER, содержит значение AF_UNSPEC. Если ошибка возникла в сети, то все параметры IP (IP_OPTIONS, IP_TTL и т.д.), которые используются сокетом и содержатся в пакете с описанием ошибки, передаются в управляющих сообщениях. Данные пакета, вызвавшего ошибку, возвращаются как нормальные данные. Заметьте, что у TCP нет очереди ошибок; флаг MSG_ERRQUEUE нельзя использовать для сокетов типа SOCK_STREAM. Параметр IP_RECVERR допустим для TCP, но все ошибки возвращаются только через функцию сокета или через параметр SO_ERROR.
Для «сырых» сокетов, параметр IP_RECVERR включает передачу в приложение всех получаемых ошибок ICMP, иначе сообщается только об ошибках в сокетах ориентированных на соединение.
Этот параметр устанавливается или возвращается как логический флаг в виде целого числа. По умолчанию, параметр IP_RECVERR выключен.
Передает пользователю все входящие параметры IP с помощью управляющего сообщения IP_OPTIONS. Для локального узла заполняется заголовок маршрутизации и другие параметры. Не поддерживается сокетами типа SOCK_STREAM.
Данный логический параметр включает вспомогательное сообщение IP_ORIGDSTADDR в recvmsg(2), в котором ядро возвращает первоначальный адрес назначения полученной дейтаграммы. Вспомогательное сообщение содержит структуру struct sockaddr_in.
Если включён, то вместе с входящими пакетами передаётся вспомогательное сообщение IP_TOS. В нём содержится байт, в котором указано поле типа сервиса/приоритета из заголовка пакета. Ожидается логическое значение в виде целого числа.
Если этот флаг установлен, то передаётся управляющее сообщение IP_TTL с байтом значения поля времени существования из полученного пакета. Не поддерживается сокетами типа SOCK_STREAM.
Идентичен параметру IP_RECVOPTS, но возвращает необработанные параметры, при чём без заполненных временных меток и записи о маршрутизации до этой точки (hop).
Передаёт этому сокету все пересылаемые (forwarded) пакеты с установленным параметром IP Router Alert. Этот параметр используется для «сырых» сокетов. Он может быть полезен, например, для служб RSVP, запущенных в пространстве пользователя. Перехваченные пакеты дальше ядром не пересылаются: ответственность за их отсылку лежит на пользователе. Связывание сокета игнорируется, так как пакеты фильтруются по протоколу. Ожидается логическое значение в виде целого числа.
Устанавливает или получает значение поля Type-Of-Service (TOS, тип сервиса) каждого IP-пакета, который отсылается с этого сокета. Это поле используется для указания приоритета пакета в сети. Значение TOS хранится в одном байте. Существует несколько стандартных флагов TOS: IPTOS_LOWDELAY — для минимизации задержки передаваемого трафика, IPTOS_THROUGHPUT — для оптимизации пропускной способности, IPTOS_RELIABILITY — для увеличения надёжности, IPTOS_MINCOST — для пересылки данных, которым неважна скорость передачи. Может быть указано не более одного из этих значений TOS. Все другие биты являются недействительными и должны быть обнулены. По умолчанию, Linux посылает дейтаграммы с IPTOS_LOWDELAY первыми, но точное поведение зависит от настроенного порядка очередности (queueing discipline). Для установки некоторых высокоприоритетных типов сервиса могут потребоваться права суперпользователя (мандат CAP_NET_ADMIN). Приоритет также можно указать не зависящим от типа протокола способом через параметр сокета (SOL_SOCKET, SO_PRIORITY, см. socket(7)).
Установка этого логического параметра включает прозрачное проксирование на заданный сокет. Данный параметр сокета позволяет вызвавшему приложению привязаться к нелокальному IP-адресу и работать клиентом и сервером с внешним адресом как с локальной конечной точкой. ЗАМЕЧАНИЕ: требуется настройка маршрутизации пакетов для внешнего адреса через TProxy. Для установки данного параметра сокета требуются права суперпользователя (мандат CAP_NET_ADMIN).
Также, для установки данного параметра на перенаправляемый сокет требуется перенаправление TProxy с помощью цели TPROXY в iptables.
Устанавливает или получает текущее значение поля времени существования (time to live), которое указывается в каждом пакете, который отсылается с этого сокета.

Интерфейсы в /proc

Настройку глобальных параметров протокола IP можно осуществлять через интерфейс /proc. Все параметры доступны посредством чтения или записи файлов из каталога /proc/sys/net/ipv4/. Для логических (Boolean) параметров значения указываются в виде целых чисел: ненулевое значение («истина») означает включает параметра, а нулевое значение («ложь») — выключение.

[Появилось в ядре версии 2.2.13; в ранних версиях это свойство контролировалось с помощью флага CONFIG_IP_ALWAYS_DEFRAG во время компиляции; данный параметр убран в 2.4.x]

Если этот флаг включен (не равен 0), то входящие фрагменты (части IP-пакетов, которые образуются, если некоторый узел, находящийся между отправителем и получателем, решает, что пакеты слишком велики и разделяет их на кусочки) будут снова собраны (дефрагментированы) перед дальнейшей обработкой, даже если они должны быть пересланы дальше.

Включайте этот параметр только на межсетевом экране, который является единственной связью с вашей сетью, или на прозрачном прокси; никогда не включайте его на обычном маршрутизаторе или узле. В противном случае, соединение может быть нарушено, если фрагменты передаются по различным линиям. Дефрагментация также требует много памяти и процессорного времени.

Этот параметр включается автоматически при настройки маскарадинга или прозрачного проксирования.

Не описан.
Устанавливает значение time-to-live по умолчанию для исходящих пакетов. Это значение может быть изменено для каждого отдельного сокета с помощью параметра IP_TTL.
Включает динамическую адресацию сокета и подмену (masquerading) при изменении адреса интерфейса. Это полезно для интерфейсов коммутируемых соединений (dialup) с изменяющимися IP-адресами. Значение 0 означает не подменять, 1 включает подмену и 2 включает режим подробностей работы.
Включает/выключает пересылку (forwarding) IP-пакетов. Пересылка IP также может быть включена для каждого интерфейса в отдельности.
Содержит два целых числа, определяющих диапазон локальных портов по умолчанию, которые зарезервированы для сокетов. Резервирование начинается с первого числа и оканчивается вторым. Заметим, что эти порты не должны конфликтовать с портами, которые используются для маскарадинга (хотя это тоже обрабатывается). Кроме того, произвольный выбор диапазона может привести к проблемам с некоторыми фильтрами пакетов на межсетевом экране, которые делают предположение об используемых локальных портах. Первое число должно быть, по крайней мере больше 1024, а лучше более 4096, чтобы избежать конфликтов с известными портами и минимизировать проблемы с межсетевыми экранами.
Если включен, то, по умолчанию, не производится обнаружение значения MTU у маршрута для TCP сокетов. Обнаружение MTU маршрута может завершиться с ошибкой из-за встретившихся на пути неверно настроенных межсетевых экранов (которые отбрасывают все пакеты ICMP) или из-за неверно настроенных интерфейсов (например, соединение точка-точка, у которого оба конца не договорились о MTU). Лучше исправить встреченные на пути неисправные маршрутизаторы, чем глобально отключать обнаружение MTU маршрута, потому что это отключение приведет к высокой нагрузке на сеть.
Если установлен, то это позволяет процессам привязываться (bind(2)) к нелокальным IP-адресам, что полезно, но может привести к неработоспособности некоторых приложений.
Время в секундах, на которое фрагмент IPv6 остаётся в памяти.
Интервал регенерации (в секундах) контрольной суммы секрета (hash secret) (или время существования контрольной суммы секрета) фрагментов IPv6.
Если количество фрагментов IP, стоящих в очереди, достигает значения ipfrag_high_thresh, то очередь укорачивается до значения ipfrag_low_thresh. Содержит целое число, означающее количество байт.
Смотрите в arp(7).

Вызовы ioctl

Все вызовы ioctl, описанные в socket(7), применимы к ip.

Вызовы ioctl для настройки общих параметров устройств описаны в netdevice(7).

ОШИБКИ

Пользователь попытался выполнить действие, не имея на это необходимых полномочий. Примеры таких действий: посылка пакета по широковещательному адресу без предварительной установки флага SO_BROADCAST; посылка пакета по запрещенному маршруту; изменение настроек межсетевого экрана не имея прав суперпользователя (мандата CAP_NET_ADMIN); связывание сокета с зарезервированным портом, не имея прав суперпользователя (мандата CAP_NET_BIND_SERVICE).
Попытка связать сокет с уже используемым адресом.
Был запрошен несуществующий интерфейс или запрошенный исходящий адрес не является локальным.
Действие над неблокирующим сокетом привело бы к его блокировке.
Операция соединения на неблокирующем сокете уже находится в процессе выполнения.
Соединение закрыто во время accept(2).
В таблице маршрутизации нет допустимых записей, соответствующих адресу назначения. Эта ошибка может возникнуть из-за ICMP-сообщения от удалённого маршрутизатора или из-за локальной таблицы маршрутизации.
Передан недопустимый аргумент. При операциях отправки эта ошибка может возникнуть из-за передачи по маршруту чёрная дыра (blackhole).
Вызов connect(2) запущен для сокета, уже установившего соединение.
Дейтаграмма больше значения MTU на маршруте, и она не может быть фрагментирована.
Недостаточно свободной памяти. Часто это означает, что выделение памяти ограничено не размером системной памяти, а границами буфера сокета, но это не всегда так.
SIOCGSTAMP вызван для сокета, который ещё не получил ни одного пакета.
Не настроена подсистема ядра.
Передана недопустимый параметр сокета.
Операция определена только для сокета, установившего соединение, а этот сокет не соединён.
У пользователя нет достаточных полномочий, чтобы повысить приоритет, изменить настройку или послать сигнал запрашиваемому процессу или группе процессов.
Соединение неожиданно закрылось или завершено (shut down) другой стороной.
Сокет не настроен или запрошен неизвестный тип сокета.

Протоколами более высокого уровня могут генерироваться другие ошибки; смотрите tcp(7), raw(7), udp(7) и socket(7).

ЗАМЕЧАНИЯ

Значения IP_FREEBIND, IP_MTU, IP_MTU_DISCOVER, IP_RECVORIGDSTADDR, IP_PKTINFO, IP_RECVERR, IP_ROUTER_ALERT и IP_TRANSPARENT есть только в Linux.

Будьте осторожны при использовании параметра SO_BROADCAST — в Linux он не является привилегированным. Если небрежно относиться к широковещательным сообщениям, то можно легко перегрузить сеть. В новых протоколах для приложений лучше использовать групповое вещание вместо широковещательного. Не используйте широковещание.

Для определения адреса назначения и интерфейса полученных дейтаграмм в некоторые реализациях BSD сокетов введены параметры сокетов IP_RCVDSTADDR и IP_RECVIF. В Linux для этой цели есть общий параметр IP_PKTINFO.

В некоторые реализациях BSD сокетов также есть параметр IP_RECVTTL, но вспомогательное сообщение с типом IP_RECVTTL передаётся с входным пакетом. В этом отличие от параметра IP_TTL, используемого в Linux.

Использование уровня параметров сокета SOL_IP непереносимо — в BSD-стеках используется уровень IPPROTO_IP.

Совместимость

Для совместимости с Linux 2.0 устаревший синтаксис socket(AF_INET, SOCK_PACKET, protocol) всё ещё поддерживается для открытия сокетов типа packet(7). Такое использование не поощряется и должно быть заменено на socket(AF_PACKET, SOCK_RAW, protocol). Основное различие между ними в новой адресной структуре sockaddr_ll (вместо старой структуры sockaddr_pkt.), хранящей информацию обобщённого уровня соединения,

ДЕФЕКТЫ

Слишком много противоречий в значениях ошибок.

Не описаны ioctl для настройки специальных параметров IP для интерфейса и таблиц ARP.

В некоторых версиях glibc не объявлена структура in_pktinfo. Это можно обойти, скопировав объявление этой структуры из этой справочной страницы.

Получение исходного адреса назначения в msg_name с помощью MSG_ERRQUEUE вызовом recvmsg(2) не работает в некоторых ядрах 2.2.

СМОТРИТЕ ТАКЖЕ

recvmsg(2), sendmsg(2), byteorder(3), ipfw(4), capabilities(7), netlink(7), raw(7), socket(7), tcp(7), udp(7)

Первоначальная спецификация IP описана в RFC 791.
Требования к узлу IPv4 приведены в RFC 1122.
Требования к маршрутизатору IPv4 приведены в RFC 1812.

2011-09-22 Linux