分类: LINUX
2010-07-30 09:38:44
原贴:
我在内核构造一帧数据想发出去,使用了两种方法均以失败告终,用抓包工具根本没抓到,请指教(附源码)
这是源码包:
可以直接make,生成testmodule.ko,插入后便会发一帧数据出去,但是用嗅探器(wireshark)抓不到我发的包,看样子是没发出去
但是两种方法中,dev_queue_xmit及kernel_sendmsg都没有返回错误,贴出代码如下(头文件在源码包里),大家也可以直接看附件里的源码
在testmod_init中大家可以发现,我尝试了两种方式,一种是通过kernel socket发包,另一种是DIY sk_buff发包,可惜呀,都没有成功,不清楚问题到底出在了什么地方,请大家指教一下
#include "testmodule.h"
struct socket *sock;
static int k_sendmsg(struct socket *sock, void * buff, size_t len,
unsigned flags, struct sockaddr *addr, int addr_len)
{
struct kvec vec;
struct msghdr msg;
vec.iov_base = buff;
vec.iov_len = len;
memset(&msg, 0x00, sizeof(msg));
/* msg.msg_name = addr; */
/* msg.msg_namelen = addr_len; */
/* msg.msg_flags = flags | MSG_DONTWAIT; */
return kernel_sendmsg(sock, &msg, &vec, 1, len);
}
static void send_by_sock()
{
struct sockaddr_in addr;
u8 buf[15] = {"hello world"};
int ret;
sock_create_kern(PF_INET, SOCK_DGRAM, 0, &sock);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(319);
addr.sin_addr.s_addr = in_aton("192.168.1.36");
kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
ret = k_sendmsg(sock, buf, sizeof(buf), 0, (struct sockaddr *) &addr, sizeof(addr));
if (ret) {
printk("kernel_msg: %d\n", ret);
}
}
static void sock_init()
{
struct ifreq ifr;
sock_create_kern(PF_INET, SOCK_DGRAM, 0, &sock);
strcpy(ifr.ifr_ifrn.ifrn_name, IF_NAME);
kernel_sock_ioctl(sock, SIOCSIFNAME, (unsigned long) &ifr);
}
static void send_by_skb()
{
struct net_device *netdev;
struct net *net;
struct sk_buff *skb;
struct ethhdr *eth_header;
struct iphdr *ip_header;
struct udphdr *udp_header;
__be32 dip = in_aton(DIP);
__be32 sip = in_aton(SIP);
u8 buf[16] = {"hello world"};
u16 data_len = sizeof(buf);
u16 expand_len = 16; /* for skb align */
u8 *pdata = NULL;
u32 skb_len;
u8 dst_mac[ETH_ALEN] = {DST_MAC_00, DST_MAC_01, DST_MAC_02, DST_MAC_03, DST_MAC_04, DST_MAC_05}; /* dst MAC */
u8 src_mac[ETH_ALEN] = {SRC_MAC_00, SRC_MAC_01, SRC_MAC_02, SRC_MAC_03, SRC_MAC_04, SRC_MAC_05}; /* src MAC */
/* construct skb */
sock_init();
net = sock_net((const struct sock *) sock->sk);
netdev = dev_get_by_name(net, IF_NAME);
skb_len = LL_RESERVED_SPACE(netdev) + sizeof(struct iphdr) + sizeof(struct udphdr) + data_len + expand_len;
printk("iphdr: %d\n", sizeof(struct iphdr));
printk("udphdr: %d\n", sizeof(struct udphdr));
printk("data_len: %d\n", data_len);
printk("skb_len: %d\n", skb_len);
skb = dev_alloc_skb(skb_len);
if (!skb) {
return;
}
skb_reserve(skb, LL_RESERVED_SPACE(netdev));
skb->dev = netdev;
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = htons(ETH_P_IP);
skb->ip_summed = CHECKSUM_NONE;
skb->priority = 0;
/* construct ethernet header in skb */
eth_header = (struct ethhdr *) skb_put(skb, sizeof(struct ethhdr));
memcpy(eth_header->h_dest, dst_mac, ETH_ALEN);
memcpy(eth_header->h_source, src_mac, ETH_ALEN);
eth_header->h_proto = htons(ETH_P_IP);
/* construct ip header in skb */
skb_set_network_header(skb, 0);
skb_put(skb, sizeof(struct iphdr));
ip_header = ip_hdr(skb);
ip_header->version = 4;
ip_header->ihl = sizeof(struct iphdr) >> 2;
ip_header->frag_off = 0;
ip_header->protocol = IPPROTO_UDP;
ip_header->tos = 0;
ip_header->daddr = dip;
ip_header->saddr = sip;
ip_header->ttl = 0x40;
ip_header->tot_len = htons(skb->len);
ip_header->check = 0;
/* construct udp header in skb */
skb_set_transport_header(skb, sizeof(struct iphdr));
skb_put(skb, sizeof(struct udphdr));
udp_header = udp_hdr(skb);
udp_header->source = htons(SPORT);
udp_header->dest = htons(DPORT);
/* insert data in skb */
pdata = skb_put(skb, data_len);
if (pdata) {
memcpy(pdata, buf, data_len);
}
/* caculate checksum */
udp_header->check = csum_tcpudp_magic(sip, dip, skb->len - ip_header->ihl * 4, IPPROTO_UDP, skb->csum);
skb->csum = skb_checksum(skb, ip_header->ihl * 4, skb->len - ip_header->ihl * 4, 0);
/* send packet */
if (dev_queue_xmit(skb) < 0) {
dev_put(netdev);
kfree_skb(skb);
printk("send packet by skb failed.\n");
return;
}
printk("send packet by skb success.\n");
}
static int __init testmod_init(void)
{
/* send_by_sock(); */
send_by_skb();
printk("testmod kernel module load!\n");
return 0;
}
static void __exit testmod_exit(void)
{
sock_release(sock);
printk("testmod kernel module removed!\n");
}
module_init(testmod_init);
module_exit(testmod_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lion3875 <>");
MODULE_DESCRIPTION("A packet generation & send kernel module");