首先例子中, udpcksum.h包含了两个头文件 ip_var.h/udp_var.h,我是centos5.5的,系统中并无这些头文件。如果自己隐掉,编译时明显就会报struct udpiphdr结构不存在。可在udpcksum.h中增加以下代码:
struct ipvolg{
u_char ih_x1 [9]; //9 bit
u_char ih_pr; //1 bit
u_short ih_len; //2 bytes
struct in_addr ih_src; //4 bytes;
struct in_addr ih_dst; //4 bytes;
};
struct udpiphdr{
struct ipvolg ui_i;
struct udphdr ui_u;
};
#define ui_x1 ui_i.ih_x1
#define ui_pr ui_i.ih_pr
#define ui_sum ui_i.ih_len
#define ui_src ui_i.ih_src
#define ui_dst ui_i.ih_dst
#define ui_sport ui_u.source
#define ui_dport ui_u.dest
#define ui_ulen ui_u.len
free bsd系统中,应该是有这个结构声明的,网上有这些文件说明。参考udpwrite.c文件中的udp_write函数,可以看出些端倪。
ip = (struct ip *) buf;
ui = (struct udpiphdr *) buf;
明显就是对ip的头和udp的头进行设置,具体字段的设置,请参照tcp/ip的协议。
当然,里面有部分代码需要改造下,我觉得应该是bug,以centos的系统为例,其他系统并未验证过。
udpwrite.c/udp_write()
ui->ui_len = htons((uint16_t) (sizeof(struct udphdr) + userlen)); 替换成 ui->ui_ulen = htons((uint16_t) (sizeof(struct udphdr) + userlen));
ui->ui_ulen = ui->ui_len; 注释掉
udpwrite.c/open_output(void)
rawfd = Socket(dest->sa_family, SOCK_RAW, 0); 应改成 rawfd = Socket(dest->sa_family, SOCK_RAW, IPPROTO_RAW);,否则提示协议不支持
udpwrite.c/udpread.c 都用到了in_cksum函数,但Makefile文件并没有把相应实现包含进来,需要在makefile文件中补充下。
main.c 的main函数,在参数解析时, aip = Host_serv(argv[optind], argv[optind+1], AF_INET, SOCK_DGRAM); 要留意下,并不能获取正确的服务器 ip和端口
最后make一下,senddnsquery-libnet.c仍旧有错误,但并不影响使用,暂时为解决这个错误。用wireshark活tcpdump看下,可以看到预期的效果。