以下函數全部基於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;}