百思不得其解:从ip包头中取源目地址不正确
smn 2003-11-29 04:59:37 用libpcap抓包,目的是得到该包的源目IP地址。首先参照tcpdump的sniffer.c定义两个结构体
/* Ethernet header */
struct sniff_ethernet {
u_char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
u_char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
u_short ether_type; /* IP? ARP? RARP? etc */
};
/* IP header */
struct sniff_ip {
#if BYTE_ORDER == LITTLE_ENDIAN
u_int ip_hl:4, /* header length */
ip_v:4; /* version */
#if BYTE_ORDER == BIG_ENDIAN
u_int ip_v:4, /* version */
ip_hl:4; /* header length */
#endif
#endif /* not _IP_VHL */
u_char ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_char ip_ttl; /* time to live */
u_char ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src,ip_dst; /* source and dest address */
};
抓到包后就在其前加上以太网头
struct sniff_ip *ip=(struct sniff_ip*)(packet + sizeof(struct sniff_ethernet));
然后从中取出源目IP地址
printf("\tFrom: %s\n", inet_ntoa(ip->ip_src));
printf("\tTo: %s\n", inet_ntoa(ip->ip_dst));
当我pcap_lookupnet()里用的网络设备是eth0的时候,得到的两个IP地址就只是我的网卡和ADSL MODEM的IP,例如192.168.1.2和192.168.1.1。但我的目的是想得到本机在互联网上的IP和我所浏览的网站的IP,例如218.20.225.71和216.239.41.99。
于是我pcap_lookupnet()里用的网络设备是ppp0(当然是用pppoe虚拟拨号后才能运行),结果很奇怪,源目IP的位置移位了!
例如,我查到本机在互联网的IP是61.144.119.155,然后一边 ping 202.96.128.68,一边运行我的抓包程序,连续抓几个包显示如下:1
From: 58.217.61.144
To: 119.155.202.96
2
From: 162.203.202.96
To: 128.68.61.144
3
From: 58.217.61.144
To: 119.155.202.96
4
From: 162.65.202.96
To: 128.68.61.144
......
从中可见,两个IP的位置都移动了,源IP 61.144.119.155 在第一个包中前两个字节在源IP,后两个字节在目的IP;目的IP 202.96.128.68 在第一个包中前两个字节在目的IP,后两个字节就不在此包中了。
难道IP包头的结构会变化的吗?请高手们指点一下吧,我在此问题上已经磨了很久了,看过很多例子都是用这个IP头结构来取得源目IP地址的,但用的都是eth0网络设备,所以都只能得到在局域网内的IP,而不是互联网IP。
分不够的再加,多少都行。