#include <sys/socket.h>
#include <features.h> /* for the glibc version number */
#if __GLIBC__ >= 2 && __GLIBC_MINOR >= 1
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h> /* The L2 protocols */
#endif packet_socket = socket(PF_PACKET, int socket_type, int protocol);
socket_type равен либо SOCK_RAW для raw-пакетов (включая заголовок установки соединения), либо SOCK_DGRAM для подготовленных пакетов без заголовка уровня соединения. Информация заголовка уровня соединения в общем формате предоставлена в sockaddr_ll. protocol - номер протокола в соответствии с IEEE 802.3 в сетевом порядке байтов. Список возможных протоколов приведен в файле <linux/if_ether.h> Если protocol содержит значение htons(ETH_P_ALL), то программой будут приниматься все протоколы. Все входящие пакеты этого типа протокола будут передаваться пакетному сокету до того, как они будут переданы протоколам, реализованным в ядре.
Открывать пакетные сокеты могут лишь процессы с идентификатором эффективного пользователя, равным нулю, или имеющие возможность CAP_NET_RAW.
Пакеты SOCK_RAW передаются драйверу устройства и принимаются от него без всяких изменений данных пакета. При получении пакета адрес обрабатывается и передается в стандартной структуре адреса sockaddr_ll. При передаче пакета буфер пользователя должен содержать заголовок физического уровня. Пакет передается без изменений драйверу сетевого интерфейса, указанному в адресе назначения. Hекоторые драйверы устройств всегда добавляют к заголовку и другие заголовки. SOCK_RAW похож, но не совместим с устаревшим SOCK_PACKET для Linux 2.0.
SOCK_DGRAM работает на несколько более высоком уровне. Физический заголовок удаляется перед тем, как пакет отправляется пользователю. Пакеты, посылаемые через пакетный сокет SOCK_DGRAM, получают перед постановкой в очередь подходящий заголовок физического уровня в соответствии с информацией об адресе назначения из sockaddr_ll.
По умолчанию, все пакеты указанного типа протокола передаются пакетному сокету. Для получения пакетов только определенного интерфейса используйте bind(2): это соединит пакетный сокет с интерфейсом, адрес которого указывается в структуре struct sockaddr_ll. Для соединения используются только поля адреса sll_protocol и sll_ifindex.
Операция connect(2) с пакетными сокетами не поддерживается.
Когда флаг MSG_TRUNC передается recvmsg(2), recv(2), recvfrom(2), то всегда возвращается действительная текущая длина пакета, даже если она больше, чем буфер.
struct sockaddr_ll {
unsigned short sll_family; /* Всегда AF_PACKET */
unsigned short sll_protocol; /* Протокол физического уровня */
int sll_ifindex; /* Hомер интерфейса */
unsigned short sll_hatype; /* Тип заголовка */
unsigned char sll_pkttype; /* Тип пакета */
unsigned char sll_halen; /* Длина адреса */
unsigned char sll_addr[8]; /* Адрес физического уровня */
};
struct packet_mreq
{
int mr_ifindex; /* индекс интерфейса */
unsigned short mr_type; /* действие */
unsigned short mr_alen; /* длина адреса */
unsigned char mr_address[8]; /* адрес физического уровня */
};
В дополнение ко всему, для этих целей могут быть использованы традиционные ioctl-вызовы: SIOCSIFFLAGS, SIOCADDMULTI, SIOCDELMULTI.
Кроме того, возможно использование всех стандартынх вызовов ioctl, определенных в netdevice(7) и socket(7).
struct sockaddr_pkt
{
unsigned short spkt_family;
unsigned char spkt_device[14];
unsigned short spkt_protocol;
};
Эта структура устарела и не должна быть указана в новом коде.
Пакетные сокеты 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. Поэтому подключиться (to bind) к ETH_P_802_3 невозможно; вместо этого подключайтесь к ETH_P_802_2 и выполняйте мультиплексирование протокола сами. По умолчанию для отправки используется стандартная инкапсуляция Ethernet DIX со вставленным протоколом.
Пакетные сокеты не обрабатываются входящими и исходящими правилами сетевого экрана.
Дополнительные ошибки могут генерироваться низкоуровенвым драйвером.
#ifndef SOL_PACKET #define SOL_PACKET 263 #endif
Обработка IEEE 802.2/803.3 LLC должна считаться ошибкой.
Фильтры сокетов не описаны. Расширение MSG_TRUNC для recvmsg является очень плохо сделанной правкой и должна быть заменена на управляющее сообщение. На данный момент нет иного выхода, кроме как определение настоящего адреса назначения пакета по SOCK_DGRAM.
RFC 894 создана для стандарта инкапсуляции IP Ethernet.
RFC 1700 создана для инкапсуляци IEEE 802.3 IP.
Файл linux/if_ether.h создан для протоколов физического уровня.
|
Закладки на сайте Проследить за страницей |
Created 1996-2025 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |