unsigned int csum; /* Контрольная сумма */
unsigned char __unused, /* He используется */
cloned, /* Заголовок должен клонироваться */
pkt_type, /* Класс пакета */
ip_summed; /* контрольная сумма IP */
__u32 priority; /* Приоритет пакета */
atomic_t users; /* Счетчик пользователей — см.
datagram.c, tcp.c */
unsigned short protocol; /* Протокол пакета */
unsigned short security; /* Уровень безопасности */
unsigned int truesize; /* Размер буфера */
unsigned char *head; /* Заголовок буфера */
unsigned char *data; /* Указатель заголовка данных */
unsigned char *tail; /* Указатель 'хвоста' */
unsigned char *end; /* Конечный указатель */
void (*destructor)(struct sk_buff*);
#ifdef CONFIG_NETFILTER
unsigned long nfmark;
/* Cache info */
__u32 nfcache;
/* Ассоциированное соединение */
struct nf_ct_info *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int nf_debug;
#endif
#endif /* CONFIG_NETFILTER*/
#if defined(CONFIG_HIPPI)
union {
__u32 ifield;
} private;
#endif
#ifdef CONFIG_WET_SCHED
__u32 tc_index; /* Индекс контроля трафика */
#endif
};
Данная структура описана в файле /usr/src/linux/include/linux/skbuff.h
. После формирования структуры sk_buff
она передается драйвером функции netif_rx.
int netif_rx(struct sk_buff *skb);
Функция netif_rx() описана в файле /usr/src/linux/net/core/dev.c
. Она получает пакет от драйвера сетевого устройства и ставит его в очередь (очередь называется backlog) протокола высшего уровня. Функция возвращает следующие значения:
♦ NET_RX_SUCCESS — пакет удачно поставлен в очередь;
♦ NET_RX_CN_LOW — имеется небольшая «пробка» при постановке пакета в очередь, но скоро она «рассосется»;
♦ NET_RX_CN_MOD — «пробка» чуть больше — средней «длины»;
♦ NET_RX_CN_HIGH — очень большая «пробка»;
♦ NET_RX_DROP — пакет был удален.
Если в очереди backlog находятся более 300 пакетов, новый пакет будет удален без какого-либо предупреждения.
Драйвер сетевого устройства при формировании структуры sk_buff
устанавливает ее поле protocol
. Функция netif_rx(), как уже было сказано, передает пакет «наверх», затем функция net_bh() использует значение поля protocol
, установленное драйвером, для вызова соответствующей протоколу программы и передает этой программе пакет. Для протокола ICMP такой программой является функция icmp_rcv(), описанная в файле /usr/src/linux/net/ipv4/icmp.с
.
int icmp_rcv(struct sk_buff *skb);
Функция icmp_rcv выполняет следующие действия:
1. Увеличивает значение счетчика входящих пакетов ICMP_INC_STATS_BH(IcmpInMsgs).
2. Удаляет пакет, если его размер слишком мал.
3. Проверяет контрольную сумму: если она ошибочна, увеличивает счетчик некорректных пакетов.
4. Проверяет тип ICMP-пакета. Если тип пакета превышает максимальное значение 18, то пакет удаляется. При этом увеличивается счетчик некорректных пакетов.
5. Вызывает функцию-обработчик ICMP-сообщения в зависимости от значения типа сообщения.
Соответствие номеров типа служебным функциям (описаны в файле icmp.c) Таблица 27.9
Тип | Функция | Описание |
---|---|---|
0, 1, 2, 6, 7, 9, 10, 12, 14-16, 18 | void icmp_discard(struct sk_buff *skb) | Удаляет пакет |
3, 4, 11 | void icmp_unreach(struct sk_buff *skb) | Данная функция определяет максимальный размер модуля передачи (MTU, Maximum Transmission Unit), а также передает информацию об ошибке любому модулю, которому нужна эта информация |
5 | void icmp_redirect(struct sk_buff *skb) | Пакет переадресации, который означает примерно следующее: «Не посылайте мне пакет по адресу xxx.xxx.ххх.xxx, потому что он будет отправлен обратно» |
8 | void icmp_echo(struct sk_buff *skb) | Функция для отправки эхо-запроса. Эхо-ответ (тип 0) отправляется ядром автоматически (если вы не отключили эту возможность) |