Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Цилюрик О.И. Модули ядра 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)); 

Предыдущий раздел: Оглавление Следующий раздел:
Путь пакета сквозь стек протоколов   Протокол транспортного уровня