今天嘗試用winpcap提供的pcap_sendpacket函數成功發送一個udp數據包到目的地址。 下面就來回顧一下過程。
首先用pcap_findalldevs得到網絡接口,比如在我的機器上得到這樣的結果:
1: /Device/NPF_GenericDialupAdapter
2: /Device/NPF_{06864041-9387-44DC-AF44-37779B0F2E9E}
現在我們及應用"/Device/NPF_{06864041-9387-44DC-AF44-37779B0F2E9E}“對應的接口發送數據。
由於發送數據必須自己構建以太網數據頭, IP數據包頭 和 UDP數據包頭, 數據結構大概是這個樣子的。
" 以太網數據頭 | IP數據頭 | UDP數據包頭 | 數據"
以太網數據頭結構如下,
struct ether_header{
u_char ether_dhost[ETHER_ADDR_LEN];
u_char ether_shost[ETHER_ADDR_LEN];
u_short ether_type; //如果上一層爲IP協議。則ether_type的值就是0x0800
};
以太網地址填充什麼數據, 我不是很清楚, 你可以填上實際的地址, 我這裏全部填1.
IP數據頭
struct ip_header //小端模式__LITTLE_ENDIAN
{
unsigned char ihl:4; //ip header length
unsigned char version:4; //version
u_char tos; //type of service
u_short tot_len; //total length
u_short id; //identification
u_short frag_off; //fragment offset
u_char ttl; //time to live
u_char protocol; //protocol type
u_short check; //check sum
u_int saddr; //source address
u_int daddr; //destination address
};
tot_len爲 整個IP數據包長度 (IP數據頭 | UDP數據包頭 | 數據)
ihl 爲IP數據頭的總長度 除以4. (4字節對齊)
check 爲在數據填好後, check爲0 時的校驗和, 是對於IP數據頭。
protocol 爲IPPROTO_UDP。
UDP數據包頭
struct udphdr
{
u_int16_t source; /* source port */
u_int16_t dest; /* destination port */
u_int16_t len; /* udp length */
u_int16_t checkl; /* udp checksum */
};
len 爲UDP數據包長度,
checkl 校驗和(IP爲首部 | UDP數據包頭 | 數據), 這個比較特殊一點, 要加一個僞首部
struct Psd_Header {
ULONG sourceip; //源IP地址
ULONG destip; //目的IP地址
BYTE mbz; //置空(0)
BYTE ptcl; //協議類型
USHORT plen; //TCP/UDP數據包的長度(即從TCP/UDP報頭算起到數據包結束的長度 單位:字節)
};
plen 和UDP長度是一樣的。
當把這些都填充好了, 就可以用pcap_sendpacket發送出去了