版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wr132/article/details/79113640
以下函数全部基于3.10.90版本的内核,对于更老或者更新的内核,可能会有所区别。
用于LOG输出的宏
- LOG宏的使用方式与printk完全相同
- 可以自定义tag,用于在dmesg输出的日志中过滤出属于本模块的信息
- 可以通过debug宏控制是否输出日志,当关闭日志后,所有日志代码不会被编译
#define debug 1
#define MOD_TAG "custom tag"
#if debug
#define LOG(fmt, args...) \
do{\
printk("[%s]:", MOD_TAG);\
printk(fmt, ##args);\
printk("\n");\
}while(0)
#else
#define LOG(msg)
#endif
获取sk_buff中的saddr和daddr
在获取IP的时候,一定要确定此时sk_buff中是存在IP的。
因为可能在很多函数中都会调用这个函数,为了区分调用者,增加了caller这个参数,可以传入一个字符串或者直接使用__FUNCTION__
。
static void show_skb_ip(struct sk_buff *skb, const char *caller)
{
LOG("called by %s", caller);
struct iphdr *iph = NULL;
unsigned char *ip = NULL;
iph = ip_hdr(skb);
ip = (unsigned char*)&iph->daddr;
LOG("daddr:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
ip = (unsigned char*)&iph->saddr;
LOG("saddr:%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
获取网卡设备的IP地址
static __be32 get_dev_addr(char *dev_name)
{
struct net_device *net_dev;
struct in_ifaddr *ifaddr;
if(!dev_name)
goto err_name_null;
net_dev = dev_get_by_name(&init_net, dev_name);
ifaddr = net_dev->ip_ptr->ifa_list;
if(!ifaddr)
goto err_ifaddr_null;
LOG("%s %x", __FUNCTION__, ifaddr->ifa_local);
return ifaddr->ifa_local;
err_name_null:
LOG("device name is NULL");
return 0;
err_ifaddr_null:
LOG("ifaddr is NULL, maybe it has no ip address");
return 0;
}
获取局域网其它设备的MAC地址
利用邻居子系统的arp_table查询其它设备的MAC地址,需要知道对方的IP地址,以及所查找设备所对应的网卡接口。
static char *get_neigh_ha(struct net_device *dev, __be32 ip)
{
struct neighbour *neigh;
if(!dev)
goto err_no_such_dev;
neigh = neigh_lookup(&arp_tbl, &ip, dev);
if(!neigh)
goto err_no_such_neigh;
return neigh->ha;
err_no_such_dev:
LOG("%s:no such device", __FUNCTION__);
return NULL;
err_no_such_neigh:
LOG("%s:no such neigh", __FUNCTION__);
return NULL;
}
获取网卡当前的IP地址
static __be32 get_dev_addr(char *dev_name)
{
struct net_device *net_dev;
struct in_ifaddr *ifaddr;
if(!dev_name)
goto err_name_null;
net_dev = dev_get_by_name(&init_net, dev_name);
ifaddr = net_dev->ip_ptr->ifa_list;
if(!ifaddr)
goto err_ifaddr_null;
LOG("%s %x", __FUNCTION__, ifaddr->ifa_local);
return ifaddr->ifa_local;
err_name_null:
LOG("device name is NULL");
return 0;
err_ifaddr_null:
LOG("ifaddr is NULL, maybe it has no ip address");
return 0;
}
强制向局域网中的某台设备发送数据包,而忽略目的IP
static int dev_xmit(struct sk_buff *skb, char *dev_name, __be32 target_ip)
{
int err;
unsigned char *neigh_ha,
*local_ha;
struct ethhdr *mac_h;
struct net_device *dev;
dev = dev_get_by_name(&init_net, dev_name);
if(!dev)
goto err_get_dev;
neigh_ha = get_neigh_ha(dev, target_ip);
if(!neigh_ha)
goto err_get_neigh;
show_ha("neighbor", neigh_ha);
local_ha = dev->dev_addr;
if(!local_ha)
goto err_get_local;
show_ha("local", dev->dev_addr);
skb->dev = dev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->priority = 0;
show_skb_ip(skb, __FUNCTION__);
skb_push(skb, sizeof(struct ethhdr));
skb_reset_mac_header(skb);
mac_h = eth_hdr(skb);
memset(mac_h, 0, sizeof(struct ethhdr));
mac_h->h_proto = __constant_htons(ETH_P_IP);
memcpy(mac_h->h_source, local_ha, ETH_ALEN);
memcpy(mac_h->h_dest, neigh_ha, ETH_ALEN);
err = dev_queue_xmit(skb);
if(err < 0)
goto err_xmit;
return 0;
err_get_dev:
LOG("fail to get dev %s", dev_name);
return -1;
err_get_neigh:
LOG("fail to get neighbor %x 's mac address over %s", target_ip, dev_name);
return -1;
err_get_local:
LOG("fail to get local mac address");
return -1;
err_xmit:
LOG("fail to xmit skb");
return -1;
}