Интернет-протокол
#include <sys/socket.h>#include <netinet/in.h>int socket( AF_INET,SOCK_RAW,proto );
IP - это протокол транспортного уровня, используемый семейством Интернет-протоколов. Можно установить параметры на уровне IP при использовании протоколов более высокого уровня, основанных на IP, таких как TCP и UDP. Также можно получить доступ к IP через «сырой сокет» (при разработке новых протоколов или специальных приложений).
Существует множество опций IP-уровня setsockopt() и getsockopt(). Можно использовать IP_OPTIONS
для предоставления параметров IP, которые должны передаваться в IP-заголовке каждого исходящего пакета, или для проверки параметров заголовка для входящих пакетов. Параметры IP могут использоваться с любым типом сокета в семействе Internet. Формат передаваемых параметров IP соответствует формату, указанному в спецификации протокола IP (RFC 791), с одним исключением: список адресов для параметров исходного маршрута должен включать шлюз первого перехода в начале списка шлюзов. Адрес шлюза первого перехода извлекается из списка опций, и его размер соответствующим образом корректируется перед использованием. Чтобы отключить ранее указанные параметры, следует использовать буфер нулевой длины:
setsockopt( s, IPPROTO_IP, IP_OPTIONS, NULL, 0 );
Можно использовать IP_TOS
и IP_TTL
для установки полей типа обслуживания и "времени жизни" в IP-заголовке для сокетов SOCK_STREAM
и SOCK_DGRAM
. Например:
int tos = IPTOS_LOWDELAY; /* см. <netinet/ip.h> */setsockopt( s, IPPROTO_IP, IP_TOS, &tos, sizeof( tos ) );int ttl = 60; /* max = 255 */setsockopt( s, IPPROTO_IP, IP_TTL, &ttl, sizeof( ttl ) );
Если опция IP_RECVDSTADDR
включена на сокете SOCK_DGRAM
или SOCK_RAW
, вызов recvmsg() вернет адрес назначения для датаграммы UDP. Поле msg_control структуры msghdr указывает на буфер, содержащий структуру cmsghdr
, за которой следует IP адрес. Поля cmsghdr имеют следующие значения:
cmsg_len = sizeof( struct cmsghdr ) + sizeof( struct in_addr )cmsg_level = IPPROTO_IPcmsg_type = IP_RECVDSTADDR
Если опция IP_RECVIF
включена на сокете SOCK_DGRAM
или SOCK_RAW
, вызов recvmsg() возвращает структуру sockaddr_dl
соответствующий интерфейсу, на котором был получен пакет. Поле msg_control в структуре msghdr
указывает на буфер, который содержит структуру cmsghdr
, за которой следует структура sockaddr_dl
. Поля cmsghdr имеют следующие значения:
cmsg_len = sizeof( struct cmsghdr ) + sizeof( struct sockaddr_dl )cmsg_level = IPPROTO_IPcmsg_type = IP_RECVIF
Сырые сокеты IP не требуют установления соединения и обычно используются с вызовами sendto() и recvfrom(), хотя также можно использовать connect() чтобы исправить место назначения для будущих пакетов (в этом случае следует использовать системные вызовы read() или recv() и write() или send()).
Если параметр proto функции socket() равен 0
, используется протокол по умолчанию IPPROTO_RAW
для исходящих пакетов, и принимаются только входящие пакеты, предназначенные для этого протокола. Если proto не равен нулю, этот номер протокола будет использоваться для исходящих пакетов и для фильтрации входящих пакетов.
К исходящим пакетам автоматически добавляется IP-заголовок (на основе адреса назначения и номера протокола, с которым создается сокет), если не была установлена опция IP_HDRINCL
. Входящие пакеты принимаются без изменений IP-заголовка и параметров.
IP_HDRINCL
указывает, что полный заголовок IP включен в данные и может использоваться только с типом SOCK_RAW
.
#include <netinet/ip.h>int hincl = 1; /* 1 = on, 0 = off */setsockopt( s, IPPROTO_IP, IP_HDRINCL, &hincl, sizeof( hincl ) );
Программа должна установить все поля заголовка IP, включая следующие:
ip->ip_v = IPVERSION;ip->ip_hl = hlen >> 2;ip->ip_id = 0; /* 0 означает, что ядро установило соответствующее значение */ip->ip_off = offset;
Если адрес источника заголовка установлен на INADDR_ANY
, ядро выбирает соответствующий адрес.
Многоадресная рассылка
Многоадресная IP-рассылка поддерживается только на сокетах AF_INET
типа SOCK_DGRAM
и SOCK_RAW
и только в сетях, где драйвер интерфейса поддерживает многоадресную рассылку.
Опции многоадресной рассылки
u_char ttl; /* range: 0 to 255, default = 1 */setsockopt( s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof( ttl ) );
Датаграммы с TTL 1
не пересылаются за пределы локальной сети. Многоадресные датаграммы с TTL равным 0
не передаются ни в какую сеть, но могут быть доставлены локально, если отправляющий хост принадлежит к группе назначения и если кольцевой контроль многоадресной рассылки не отключен на отправляющем сокете (см. ниже). Многоадресные датаграммы с TTL больше 1
могут быть перенаправлены в другие сети, если к локальной сети подключен многоадресный маршрутизатор.
IP_MULTICAST_IF
отменяет значение по умолчанию для последующих передач из данного сокета: struct in_addr addr;setsockopt( s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof( addr ) );
где addr - это локальный IP-адрес желаемого интерфейса или INADDR_ANY
чтобы указать интерфейс по умолчанию. Можно получить локальный IP-адрес интерфейса и возможность многоадресной рассылки, отправив запросы SIOCGIFCONF
и SIOCGIFFLAGS
в ioctl(). Обычные приложения не должны использовать эту опцию.
IP_MULTICAST_LOOP
дает отправителю явный контроль над тем, возвращаются ли последующие датаграммы обратно: u_char loop; /* 0 = disable, 1 = enable (default) */setsockopt( s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof( loop ) );
Этот параметр повышает производительность приложений, которые могут иметь не более одного экземпляра на одном хосте (например, демон маршрутизатора), за счет устранения накладных расходов на получение собственных передач. Обычно его не следует использовать приложениями, для которых может быть более одного экземпляра на одном хосте (например, программа конференц-связи) или для которых отправитель не принадлежит к группе назначения (например, программа запросов времени). Многоадресная датаграмма, отправленная с начальным TTL, превышающим 1
, может быть доставлена на хост-отправитель на другом интерфейсе, чем тот, на котором она была отправлена, если хост принадлежит к группе назначения на этом другом интерфейсе. Опция управления закольцовыванием не влияет на такую доставку.
IP_ADD_MEMBERSHIP:
struct ip_mreq mreq;setsockopt( s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof( mreq ) );
где mreq является следующей структурой:
struct ip_mreq {struct in_addr imr_multiaddr; /* multicast group to join */struct in_addr imr_interface; /* interface to join on */}
Установите imr_interface в значение INADDR_ANY
для выбора интерфейса многоадресной рассылки по умолчанию или на IP-адрес конкретного интерфейса с поддержкой многоадресной рассылки, если хост является многосетевым. Членство связано с единым интерфейсом; программам, работающим на многосетевых хостах, может потребоваться присоединение к одной группе на более чем одном интерфейсе. Для одного сокета можно добавить до IP_MAX_MEMBERSHIPS
членов (в настоящее время 20
).
struct ip_mreq mreq;setsockopt( s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof( mreq ) );
где mreq содержит те же значения, которые использовались для добавления членства. Членство сбрасывается при закрытии сокета или выходе из процесса.
Дескриптор сокета. Если возникла ошибка функция возвращает -1
, код ошибки записывается в errno.
Следующая ошибка, специфичная для IP, может возникнуть при установке или получении параметров IP:
|
ICMP протокол
connect(), getsockopt(), ioctl(), read(), recv(), recvfrom(), recvmsg(), send(), sendto(), setsockopt(), socket(), write()
Основано на RFC 791
Предыдущий раздел: Описание API сетевой библиотеки