Provided by: manpages-ru_4.18.1-1_all bug

ИМЯ

       packet - пакетный интерфейс на уровне устройства

СИНТАКСИС

       #include <sys/socket.h>
       #include <linux/if_packet.h>
       #include <net/ethernet.h> /* протоколы L2 */

       packet_socket = socket(AF_PACKET, int socket_type, int protocol);

ОПИСАНИЕ

       Пакетные  сокеты  используются для приёма и передачи неструктурированных пакетов на уровне
       драйвера устройства (второй уровень OSI). Они позволяют пользователю реализовывать  модули
       протоколов в пользовательском пространстве поверх физического уровня.

       The  socket_type  is  either  SOCK_RAW  for raw packets including the link-level header or
       SOCK_DGRAM for cooked packets with the link-level header removed.  The  link-level  header
       information  is  available in a common format in a sockaddr_ll structure.  protocol is the
       IEEE 802.3 protocol number in network byte order.  See the <linux/if_ether.h> include file
       for  a  list  of  allowed  protocols.   When protocol is set to htons(ETH_P_ALL), then all
       protocols are received.  All incoming packets of that protocol type will be passed to  the
       packet  socket  before  they  are  passed  to the protocols implemented in the kernel.  If
       protocol is set to zero, no packets are received.  bind(2) can optionally be called with a
       nonzero sll_protocol to start receiving packets for the protocols specified.

       Для  создания  пакетного сокета процесс должен иметь мандат CAP_NET_RAW в пользовательском
       пространстве имён, определяемом по его сетевому пространству имён.

       Пакеты SOCK_RAW передаются в и из драйвера устройства без каких-либо  изменений  в  данных
       пакета.  При  получении пакета, адрес по-прежнему анализируется и передаётся в стандартной
       адресной структуре sockaddr_ll. При отправке пакета, выделенный пользователем буфер должен
       содержать  заголовок физического уровня. Этот пакет затем ставится без изменений в очередь
       сетевого  драйвера  интерфейса,  определяемого  адресом  назначения.  Некоторые   драйверы
       устройств  всегда  добавляют  другой заголовок. Пакеты SOCK_RAW похожи, но не совместимы с
       устаревшими AF_INET/SOCK_PACKET из Linux 2.0.

       При типе  SOCK_DGRAM  обработка  происходит  на  чуть  более  высоком  уровне.  Физический
       заголовок удаляется перед передачей пакета пользователю. Пакеты, посылаемые через пакетный
       сокет SOCK_DGRAM, перед постановкой в очередь получают  подходящий  заголовок  физического
       уровня на основе информации из адреса назначения в sockaddr_ll.

       По  умолчанию,  все  пакеты  заданного  типа  протокола  передаются  в пакетный сокет. Для
       получения пакетов только из определённого интерфейса используйте bind(2),  задав  адрес  в
       struct  sockaddr_ll  для  привязки  пакетного  сокета к интерфейсу. Поля, используемые для
       привязывания: sll_family (должно быть равно AF_PACKET), sll_protocol и sll_ifindex.

       Операция connect(2) не поддерживается для пакетных сокетов.

       Если в recvmsg(2), recv(2) или recvfrom(2)  передаётся  флаг  MSG_TRUNC,  то  возвращается
       реальная длина пакета в канале, даже если значение длиннее буфера.

   Типы адресов
       Структура sockaddr_ll описывает независимый от устройства адрес на физическом уровне.

           struct sockaddr_ll {
               unsigned short sll_family;   /* всегда равно AF_PACKET */
               unsigned short sll_protocol; /* протокол физического уровня */
               int            sll_ifindex;  /* номер интерфейса */
               unsigned short sll_hatype;   /* тип аппаратного ARP */
               unsigned char  sll_pkttype;  /* тип пакета */
               unsigned char  sll_halen;    /* длина адреса */
               unsigned char  sll_addr[8];  /* адрес на физическом уровне */
           };

       Поля этой структуры имеют следующее назначение:

       sll_protocol
              is  the  standard  ethernet  protocol  type in network byte order as defined in the
              <linux/if_ether.h> include file.  It defaults to the socket's protocol.

       sll_ifindex
              is the interface index of the interface (see netdevice(7)); 0 matches any interface
              (only  permitted  for  binding).   sll_hatype  is  an  ARP  type  as defined in the
              <linux/if_arp.h> include file.

       sll_pkttype
              contains the packet type.  Valid types are PACKET_HOST for a  packet  addressed  to
              the   local   host,   PACKET_BROADCAST   for  a  physical-layer  broadcast  packet,
              PACKET_MULTICAST  for  a  packet  sent  to  a  physical-layer  multicast   address,
              PACKET_OTHERHOST  for  a packet to some other host that has been caught by a device
              driver in promiscuous mode, and PACKET_OUTGOING for a packet originating  from  the
              local host that is looped back to a packet socket.  These types make sense only for
              receiving.

       sll_addr
       sll_halen
              contain the physical-layer (e.g., IEEE 802.3) address and its  length.   The  exact
              interpretation depends on the device.

       Когда вы посылаете пакеты, достаточно указать sll_family, sll_addr, sll_halen, sll_ifindex
       и  sll_protocol.  Остальные  поля  должны  равняться  0.  Поля  sll_hatype  и  sll_pkttype
       заполняются в получаемых пакетах для вашей информированности.

   Параметры сокета
       Параметры пакетных сокетов настраиваются вызовом setsockopt(2) с уровнем SOL_PACKET.

       PACKET_ADD_MEMBERSHIP
       PACKET_DROP_MEMBERSHIP
              Пакетные  сокеты можно использовать для настройки неразборчивого режима и групповой
              рассылки на физическом уровне. Параметр PACKET_ADD_MEMBERSHIP  добавляет  привязку,
              PACKET_DROP_MEMBERSHIP  отменяет  её.  Для  обоих  в  качестве аргумента передаётся
              структура packet_mreq:

                  struct packet_mreq {
                      int            mr_ifindex;    /* индекс интерфейса */
                      unsigned short mr_type;       /* действие */
                      unsigned short mr_alen;       /* длина адреса */
                      unsigned char  mr_address[8]; /* адрес физ-кого уровня */
                  };

              В mr_ifindex содержится индекс интерфейса, состояние  которого  нужно  изменить.  В
              поле mr_type указывается какое действие нужно выполнить. Значение PACKET_MR_PROMISC
              включает приём всех пакетов из общего  носителя  (часто  называется  «неразборчивый
              режим»),  PACKET_MR_MULTICAST  привязывает  сокет  к групповой рассылке физического
              уровня, задаваемой в mr_address и mr_alen, а  PACKET_MR_ALLMULTI  заставляет  сокет
              принимать все пакеты групповых рассылок, поступающих на интерфейс.

              Также,   для   тех   же   целей  можно  использовать  обычные  ioctl  SIOCSIFFLAGS,
              SIOCADDMULTI, SIOCDELMULTI.

       PACKET_AUXDATA (начиная с Linux 2.6.21)
              Если  включён  этот  двоичный  параметр,  то  пакетный  сокет  передаёт   структуру
              метаданных  вместе  с каждым пакетом в управляющем поле recvmsg(2). Структуру можно
              прочитать с помощью cmsg(3). Она определена как:

                  struct tpacket_auxdata {
                      __u32 tp_status;
                      __u32 tp_len;      /* packet length */
                      __u32 tp_snaplen;  /* captured length */
                      __u16 tp_mac;
                      __u16 tp_net;
                      __u16 tp_vlan_tci;
                      __u16 tp_vlan_tpid; /* Since Linux 3.14; earlier, these
                                             were unused padding bytes */
                  };

       PACKET_FANOUT (начиная с Linux 3.1)
              To scale processing across threads, packet sockets can form  a  fanout  group.   In
              this  mode,  each matching packet is enqueued onto only one socket in the group.  A
              socket joins a fanout group by calling setsockopt(2)   with  level  SOL_PACKET  and
              option  PACKET_FANOUT.   Each  network  namespace  can have up to 65536 independent
              groups.  A socket selects a group by encoding the ID in the first 16  bits  of  the
              integer  option  value.  The first packet socket to join a group implicitly creates
              it.  To successfully join an existing group, subsequent packet  sockets  must  have
              the  same  protocol,  device  settings, fanout mode, and flags (see below).  Packet
              sockets can leave a fanout group only by closing the socket.  The group is  deleted
              when the last socket is closed.

              Для  разветвления  поддерживается  несколько  алгоритмов  распределения  трафика по
              сокетам:

              •  Режим по умолчанию PACKET_FANOUT_HASH посылает пакеты из одного потока в один  и
                 тот  же  сокет  для  обеспечения  упорядочивания  по  потоку. Для каждого пакета
                 выбирается  сокет,  получаемый  из  хэша  потока  пакетов,  взятого  по   модулю
                 количества  сокетов  в группе, где хэш потока — это хэш адреса сетевого уровня и
                 необязательных полей портов транспортного уровня.

              •  Режим балансировки нагрузки PACKET_FANOUT_LB реализует карусельный алгоритм.

              •  В режиме PACKET_FANOUT_CPU выбираются сокеты исходя из ЦП, на  который  поступил
                 пакет.

              •  В   режиме  PACKET_FANOUT_ROLLOVER  все  данные  обрабатываются  одним  сокетом,
                 следующий задействуется, если текущий занят (backlogged).

              •  В режиме PACKET_FANOUT_RND сокет выбирается согласно генератору  псевдослучайных
                 чисел.

              •  В  режиме  PACKET_FANOUT_QM (доступен, начиная с Linux 3.14)  сокет выбирается с
                 помощью записанного queue_mapping из полученной skb.

              Режимы разветвления  могут  учитывать  дополнительные  параметры.  Фрагментация  IP
              приводит  к  тому,  что  пакеты  одного  потока  имеют  разные  хэши  потоков. Если
              установлен флаг  PACKET_FANOUT_FLAG_DEFRAG,  то  пакеты  будут  дефрагментироваться
              перед  применением разветвления, что позволит сохранить порядок даже в этом случае.
              Параметры режима разветвления задаются во вторых 16 битах  целочисленного  значения
              параметра.  Флаг  PACKET_FANOUT_FLAG_ROLLOVER  включает  механизм  перекатывания  в
              качестве запасного: если первоначальный алгоритм разветвления выбрал занятый сокет,
              то пакет переходит на следующий доступный.

       PACKET_LOSSPACKET_TX_RING)
              Когда  в  кольце  передачи  обнаруживается  некорректный пакет, то по умолчанию его
              состояние  в  tp_status  сбрасывается   в   TP_STATUS_WRONG_FORMAT   и   происходит
              немедленная  отмена передачи. Некорректный пакет блокирует как свою отправку, так и
              всех следующих  пакетов  в  очереди.  Ошибка  в  формате  должна  быть  исправлена,
              соответствующий  tp_status  сброшен  в  значение TP_STATUS_SEND_REQUEST, а передача
              перезапущена с помощью send(2). Однако, если задан  параметр  PACKET_LOSS,  то  все
              некорректные    пакеты    будут   пропускаться,   их   tp_status   сбрасываться   в
              TP_STATUS_AVAILABLE и процесс передачи продолжаться.

       PACKET_RESERVEPACKET_RX_RING)
              По умолчанию, в кольцо приёма  пакетов  сразу  за  пакетом  записывается  структура
              метаданных  и заполнитель для выравнивания. Этот целочисленный параметр резервирует
              дополнительное свободное место.

       PACKET_RX_RING
              Включает создание отображаемого в  памяти  кольцевого  буфера  асинхронного  приёма
              пакетов.  Пакетный  сокет  резервирует  непрерывную область в адресном пространстве
              приложения, размечает её как массив  пакетных  слотов  и  последовательно  копирует
              пакеты  (не более tp_snaplen) в слоты. В начале каждого пакета помещается структура
              метаданных, похожая на tpacket_auxdata. В поле протокола кодируется смещение данных
              от  начала  заголовка  метаданных. В tp_net хранится смещение сетевого уровня. Если
              тип пакетного сокета — SOCK_DGRAM, то  это  делается  и  для  tp_mac.  Если  тип  —
              SOCK_RAW,  то  в  этом  поле  хранится смещение на кадр канального уровня. Пакетный
              сокет и приложение обмениваются началом  и  концом  кольца  через  поле  tp_status.
              Пакетному   сокету   принадлежат   все   слоты   со   значением   tp_status  равным
              TP_STATUS_KERNEL. После заполнения слота, изменяется состояние  слота  и  права  на
              него  передаются  приложению. При нормальной работе в новом значении tp_status, как
              минимум, установлен бит TP_STATUS_USER, что  показывает,  что  принятый  пакет  был
              сохранён. Когда приложение заканчивает обработку пакета, оно передаёт права на слот
              обратно сокету посредством установки tp_status в значение TP_STATUS_KERNEL.

              Packet sockets implement multiple variants of the packet ring.  The  implementation
              details  are  described  in  Documentation/networking/packet_mmap.rst  in the Linux
              kernel source tree.

       PACKET_STATISTICS
              Возвращает статистику по пакетному сокету в виде структуры

                  struct tpacket_stats {
                      unsigned int tp_packets;  /* общее количество пакетов */
                      unsigned int tp_drops;    /* кол-во отброшенных пакетов */
                  };

              При  получении  статистики  сбрасываются  внутренние  счётчики.  Если  используется
              вариант кольца TPACKET_V3, то статистика имеет другую структуру.

       PACKET_TIMESTAMPPACKET_RX_RING; начиная с Linux 2.6.36)
              The  packet  receive  ring  always  stores  a timestamp in the metadata header.  By
              default, this is a software generated timestamp generated when the packet is copied
              into  the  ring.   This  integer option selects the type of timestamp.  Besides the
              default,    it    support    the    two    hardware    formats     described     in
              Documentation/networking/timestamping.rst in the Linux kernel source tree.

       PACKET_TX_RING (начиная с Linux 2.6.31)
              Включает  создание  отображаемого в памяти кольцевого буфера передачи пакетов. Этот
              параметр подобен PACKET_RX_RING и имеет  те  же  аргументы.  Приложение  записывает
              пакеты в слоты со значением tp_status равным TP_STATUS_AVAILABLE и планирует их для
              передачи делая  значение  tp_status  равным  TP_STATUS_SEND_REQUEST.  Когда  пакеты
              готовы  к  передаче,  приложение вызывает send(2) или его вариант. Поля buf и len в
              этом вызове игнорируются. Если передаётся адрес с помощью sendto(2) или sendmsg(2),
              то  он  заменяет  сокетное  значение  по  умолчанию.  При  успешной  передаче сокет
              сбрасывает значение tp_status в TP_STATUS_AVAILABLE. При ошибке передача немедленно
              прерывается, если не задан PACKET_LOSS.

       PACKET_VERSIONPACKET_RX_RING; начиная с Linux 2.6.27)
              По  умолчанию, PACKET_RX_RING создаёт кольцо приёма пакетов по варианту TPACKET_V1.
              Для создания другого варианта, задайте желаемый, указав  целочисленное  значение  в
              этом параметре перед созданием кольца.

       PACKET_QDISC_BYPASS (начиная с Linux 3.14)
              By  default,  packets  sent  through packet sockets pass through the kernel's qdisc
              (traffic control) layer, which is fine for the vast majority  of  use  cases.   For
              traffic  generator appliances using packet sockets that intend to brute-force flood
              the network—for example, to test devices under load in a similar fashion to pktgen—
              this  layer  can be bypassed by setting this integer option to 1.  A side effect is
              that packet buffering in the qdisc layer is avoided, which will lead  to  increased
              drops  when  network  device  transmit  queues are busy; therefore, use at your own
              risk.

   Вызовы ioctl
       Вызов SIOCGSTAMP можно использовать для получения  метки  времени  последнего  полученного
       пакета. Аргументом является struct timeval.

       Также,  для пакетных сокетов работают все стандартные ioctl, определённые в netdevice(7) и
       socket(7).

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

ОШИБКИ

       EADDRNOTAVAIL
              Передан неизвестный адрес групповой рассылки.

       EFAULT Пользователь передал неправильный адрес памяти.

       EINVAL Неверный аргумент.

       EMSGSIZE
              Пакет больше, чем интерфейс MTU.

       ENETDOWN
              Интерфейс не поднят.

       ENOBUFS
              Недостаточно памяти для размещения пакета.

       ENODEV В адресе интерфейса указано неизвестное имя устройства или индекс интерфейса.

       ENOENT Пакет не принят.

       ENOTCONN
              Не передан адрес интерфейса.

       ENXIO  В адресе интерфейса содержится некорректный индекс интерфейса.

       EPERM  У пользователя недостаточно прав для выполнения этой операции.

       Также, драйвером низкого уровня могут генерироваться другие ошибки.

ВЕРСИИ

       AF_PACKET появился в Linux 2.2. В ранних версиях Linux поддерживался только SOCK_PACKET.

ЗАМЕЧАНИЯ

       Для переносимых программ предлагается использовать AF_PACKET в pcap(3), хотя это покрывает
       не весь набор возможностей AF_PACKET.

       Пакетные сокеты SOCK_DGRAM не пытаются создать или разобрать заголовок IEEE 802.2  LLC  из
       кадров  IEEE  802.3.  Если  для  отправки в качестве протокола указан ETH_P_802_3, то ядро
       создаёт кадр 802.3 и заполняет поле длины; пользователь передаёт заголовок  LLC  в  пакете
       уже  полностью  заполненным.  Входящие  пакеты  802.3  не  уплотняются  по полям протокола
       DSAP/SSAP; вместо этого они передаются пользователю как протокол ETH_P_802_2  с  начальным
       заголовком  LLC.  То  есть  невозможно  выполнить  привязку  к  ETH_P_802_3;  вместо этого
       выполняйте привязку к ETH_P_802_2 и выполняйте протокольное  уплотнение самостоятельно. По
       умолчанию,  отправка  происходит  в  стандартной упаковке Ethernet DIX с заполненным полем
       протокола.

       Пакетные сокеты недоступны (not  subject)  во  входной  и  выходной  цепочках  межсетевого
       экрана.

   Совместимость
       В Linux 2.0 единственным способом получить пакетный сокет является вызов:

           socket(AF_INET, SOCK_PACKET, protocol)

       Он  всё  ещё поддерживается, но устарел и настоятельно не рекомендуется. Основным отличием
       между методами — для указания интерфейса  через  SOCK_PACKET  используется  старая  struct
       sockaddr_pkt, которая не предоставляет независимого физического уровня.

           struct sockaddr_pkt {
               unsigned short spkt_family;
               unsigned char  spkt_device[14];
               unsigned short spkt_protocol;
           };

       В  spkt_family  содержится  тип  устройства,  в  spkt_protocol — тип протокола IEEE 802.3,
       определённый в <sys/if_ether.h>, а в spkt_device — имя устройства в виде строки с  null  в
       конце, например, eth0.

       Эта структура устарела и не должна использоваться в новом коде.

ДЕФЕКТЫ

   LLC header handling
       Способ обработки IEEE 802.2/803.3 LLC не считается за дефектный.

   MSG_TRUNC issues
       Расширение  MSG_TRUNC  recvmsg(2)  является  неудачным  решением и должно быть заменено на
       управляющее сообщение. Пока нет способа получить первоначальный адрес  назначения  пакетов
       через SOCK_DGRAM.

   spkt_device device name truncation
       The  spkt_device  field  of  sockaddr_pkt  has  a size of 14 bytes, which is less than the
       constant IFNAMSIZ defined in <net/if.h> which is 16 bytes and describes the  system  limit
       for  a  network  interface  name.   This means the names of network devices longer than 14
       bytes will  be  truncated  to  fit  into  spkt_device.   All  these  lengths  include  the
       terminating null byte ('\0')).

       Issues  from  this  with old code typically show up with very long interface names used by
       the Predictable Network Interface Names feature enabled by default in  many  modern  Linux
       distributions.

       The  preferred  solution is to rewrite code to avoid SOCK_PACKET.  Possible user solutions
       are to disable Predictable Network Interface Names or to rename the interface to a name of
       at most 13 bytes, for example using the ip(8)  tool.

   Documentation issues
       Не описаны сокетные фильтры.

СМ. ТАКЖЕ

       socket(2), pcap(3), capabilities(7), ip(7), raw(7), socket(7), ip(8),

       В  RFC 894  описана упаковка стандартного IP Ethernet. В RFC 1700 описана упаковка IP IEEE
       802.3.

       Заголовочный файл <linux/if_ether.h> содержит протоколы физического уровня.

       The Linux kernel source tree.  Documentation/networking/filter.rst describes how to  apply
       Berkeley  Packet  Filters  to packet sockets.  tools/testing/selftests/net/psock_tpacket.c
       contains  example  source  code  for  all  available  versions   of   PACKET_RX_RING   and
       PACKET_TX_RING.

ПЕРЕВОД

       Русский   перевод   этой   страницы   руководства   был  сделан  Alexey,  Azamat  Hackimov
       <azamat.hackimov@gmail.com>,  kogamatranslator49  <r.podarov@yandex.ru>,  Kogan,  Max   Is
       <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru> и Иван Павлов <pavia00@gmail.com>

       Этот  перевод  является  бесплатной  документацией;  прочитайте  Стандартную  общественную
       лицензию GNU версии 3 ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩ или более позднюю, чтобы
       узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

       Если  вы  обнаружите  ошибки  в  переводе этой страницы руководства, пожалуйста, отправьте
       электронное письмо на ⟨man-pages-ru-talks@lists.sourceforge.net⟩.