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) отправляется ядром автоматически (если вы не отключили эту возможность) | 
