Библиотека сайта rus-linux.net
| Цилюрик О.И. Модули ядра Linux | ||
| Назад | Внешние интерфейсы модуля | Вперед |
Протокол сетевого уровня
На этом уровне обеспечивается обработка таких протоколов, как: IP/IPv4/IPv6, IPX, ICMP, RIP, OSPF, ARP, или добавление оригинальных пользовательских протоколов. Для установки обработчиков сетевого уровня предоставляется API сетевого уровня (<linux/netdevice.h> ):
struct packet_type {
__be16 type; /* This is really htons(ether_type). */
struct net_device *dev; /* NULL is wildcarded here */
int (*func) (struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
...
struct list_head list;
};
extern void dev_add_pack( struct packet_type *pt );
extern void dev_remove_pack( struct packet_type *pt );
Примеры добавления собственных обработчиков сетевых протоколов находятся в архиве netproto.tgz. Вот так может быть добавлен обработчик нового протокола сетевого уровня:
net_proto.c :
#include <linux/module.h>
#include <linux/init.h>
#include <linux/netdevice.h>
int test_pack_rcv( struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *odev ) {
printk( KERN_INFO "packet received with length: %u\n", skb->len );
return skb->len;
};
#define TEST_PROTO_ID 0x1234
static struct packet_type test_proto = {
__constant_htons( ETH_P_ALL ), // may be: __constant_htons( TEST_PROTO_ID ),
NULL,
test_pack_rcv,
(void*)1,
NULL
};
static int __init my_init( void ) {
dev_add_pack( &test_proto );
printk( KERN_INFO "module loaded\n" );
return 0;
}
static void __exit my_exit( void ) {
dev_remove_pack( &test_proto );
printk( KERN_INFO "module unloaded\n" );
}
module_init( my_init );
module_exit( my_exit );
MODULE_AUTHOR( "Oleg Tsiliuric" );
MODULE_LICENSE( "GPL v2" );
Выполнение примера:
$ sudo insmod net_proto.ko
$ dmesg | tail -n6
module loaded packet received with length: 74 packet received with length: 60 packet received with length: 66 packet received with length: 241 packet received with length: 52
$ sudo rmmod net_proto
В этом примере обработчик протокола перехватывает (фильтрует) все пакеты (константа ETH_P_ALL) на всех сетевых интерфейсах. В случае собственного протокола здесь должна бы быть константа TEST_PROTO_ID (но для такого случая на нечем оттестировать модуль). Очень большое число идентификаторов протоколов (Ethernet Protocol ID's) находим в <linux/if_ether.h>, некоторые наиболее интересные из них, для примера:
#define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ ... #define ETH_P_IP 0x0800 /* Internet Protocol packet */ ... #define ETH_P_ARP 0x0806 /* Address Resolution packet */ ... #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ ... #define ETH_P_ALL 0x0003 /* Every packet (be careful!!!) */ ...
Здесь же находим описание заголовка Ethernet пакета, который помогает в заполнении структуры struct packet_type :
struct ethhdr {
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
__be16 h_proto; /* packet type ID field */
} __attribute__((packed));
| Предыдущий раздел: | Оглавление | Следующий раздел: |
| Путь пакета сквозь стек протоколов | Протокол транспортного уровня |
