在普通程序中普遍用ioctl函數來設置,該函數很值得大家好好的了解,因為它的使用非常的廣泛。下面
給出設置網卡混雜模式的實現代碼:
#include
#include
#include
#include
int set_all_promisc()
{ struct ifreq ifaces[16];
struct ifconf param;
int sock, i;
param.ifc_len = sizeof(ifaces);
param.ifc_req = ifaces;
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock <= 0)
return 0;
if (ioctl(sock, SIOCGIFCONF, ?m))
return 0;
for (i = 0; i < param.ifc_len / sizeof(struct ifreq); i++) {
if (ioctl(sock, SIOCGIFFLAGS, ifaces + i))
return 0;
ifaces[i].ifr_flags |= IFF_PROMISC; /*如果恢復網卡模式,把|= 改成 &=~ */
if (ioctl(sock, SIOCSIFFLAGS, ifaces + i))
return 0;
}
return 1;
}
二、在核心空間中設置混雜模式
1.在kernel-2.2.x 中
static struct device *sniffer_dev = NULL;
static unsigned short old_flags, old_gflags;
int init_module ( void ) /* 模塊初始化 */
{
......
sniffer_dev = dev_get("eth0");
if ( sniffer_dev != NULL )
{
/* thanks for difeijing of whnet's Security */
old_flags = sniffer_dev->flags;
old_gflags = sniffer_dev->gflags;
/*
* 參看net/core/dev.c裏的dev_change_flags()
* ->gflags的作用是避免多次重復設置混雜模式,沒有其他特別含義
*/
/* 設置混雜模式 */
sniffer_dev->flags |= IFF_PROMISC;
sniffer_dev->gflags |= IFF_PROMISC;
start_bh_atomic();
/* 註意,這個回調函數還是會報告 eth0: Setting promiscuous mode. */
sniffer_dev->set_multicast_list( sniffer_dev );
end_bh_atomic();
}
......
return 0;
}
void cleanup_module(void)
{
......
if (sniffer_dev != NULL)
{
/* 恢復原有模式 */
sniffer_dev>flags = old_flags;
sniffer_dev>gflags = old_gflags;
start_bh_atomic();
sniffer_dev>set_multicast_list( sniffer_dev );
end_bh_atomic();
}
......
}
2.在kernel-2.4.x 中
在2.4中有了許多變化,首先struct device結構改為struct net_device, 再者dev_get
功能改為測試網絡設備是否存在,真正的設置網絡混雜模式的函數改為
void dev_set_promiscuity(struct net_device *dev, int inc);
其中根據inc的值來設置混雜模式還是恢復原來設置模式,通過計數來恢復原來模式,這樣的好處就是:不會和其他的程序沖突,不在像上述兩種實現方式中恢復原來模式就全恢復了,不管還有沒有其他的程序是否也設置了混雜模式。現在就通過計數來恢復原來的模式,只要當計數相加為零才設置成普通模式。
linux源代碼的註釋如下:
/**
* dev_set_promiscuity - update promiscuity count on a device
* @dev: device
* @inc: modifier
*
* Add or remove promsicuity from a device. While the count in the device
* remains above zero the interface remains promiscuous. Once it hits zero
* the device reverts back to normal filtering operation. A negative inc
* value is used to drop promiscuity on the device.
*/
設置網卡混雜模式的實現代碼如下:
struct net_device *sniffer_dev = NULL;
int dev_flags = 0;
int init_module ( void ) /* 模塊初始化 */
{
......
sniffer_dev = dev_get_by_name("eth0");
if (sniffer_dev != NULL)
{
dev_flags = 1;
dev_set_promiscuity(sniffer_dev, 1);
dev_put(sniffer_dev);
sniffer_dev = NULL;
}
......
return 0;
}
void cleanup_module(void)
{
......
if (dev_flags)
{
sniffer_dev = dev_get_by_name("eth0");
if (sniffer_dev != NULL)
{
dev_flags = 0;
dev_set_promiscuity(sniffer_dev, -1); /*註意此處的第二個參數*/
dev_put(sniffer_dev);
sniffer_dev = NULL;
}
}
......
}