Библиотека сайта 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));
Предыдущий раздел: | Оглавление | Следующий раздел: |
Путь пакета сквозь стек протоколов | Протокол транспортного уровня |