|
/* creat the raw socket for icmp */
if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket");
exit(2);
}
你可以把IPPROTO_ICMP改成你要得协议
/* set destination host information */
bzero(&it, sizeof(it));
it.sin_family = AF_INET;
其中it的结构 struct sockaddr_in it; /* destination host information */
/* check host format */
if ( ( lHostIp = inet_addr(host) ) != INADDR_NONE ) {
/* is available ip adress */
it.sin_addr.s_addr = lHostIp;
strcpy( dst_host, host );
} else if ( h = gethostbyname(host) ) {
/* is available host name */
/* from hosts file of local host */
/* or from DNS */
bcopy(h->h_addr, &it.sin_addr, h->h_length);
sprintf( dst_host, "%s (%s)", host,
inet_ntoa(it.sin_addr) );
} else {
/* bad ip adress or host name */
/* exit */
fprintf( stderr, "bad IP or host\n" );
exit(3);
}
//////////////////////////////////////
char buf[200];
int iPacketSize;
/* make the icmp header information */
ICMPHEAD *pIcmpHead = (ICMPHEAD *)buf;
pIcmpHead->icmp_type = ICMP_ECHO;
pIcmpHead->icmp_code = 0;
pIcmpHead->icmp_id = seq;
pIcmpHead->icmp_seq = seq;
pIcmpHead->icmp_chksum = 0;
/* store time information as icmp packet content, 4 bytes */
/* u may store other information instead */
*((long *)pIcmpHead->icmp_data) = time_now();
iPacketSize = ICMP_HEADSIZE + 4; /* icmp packet length */
/* icmp header check sum */
pIcmpHead->icmp_chksum = ChkSum((u_short *)pIcmpHead,
iPacketSize );
/* remember the time when send for calculate round trip time */
lSendTime = time_now();
/* send the icmp packet to des host */
if ( sendto(sock, buf, iPacketSize, 0, (struct sockaddr *)&it,
sizeof(it) ) < 0) {
perror("send failed");
exit(6);
}
/////////////////////////////////////////////
其中 Sendto是发送函数
同样当你接受到报文以后,再手动的用上一贴中定义的包结构来拆分从套接字缓存区得到的数据,并拆出ACK位。下面是一个ICMP报文拆包的例子
/* block to received echo back datagram */
size = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *)&it, &namelen);
if (size == -1 && errno == EINTR) {
/* receive error or system call */
/* interrupted */
continue;
}
/* calculate the round trip time, */
/* time when receive minus time when send */
delta = (int)((time_now() - lSendTime)/1000);
/* get echo back packet and check its ip header */
pIpHead = (IPHEAD *)buf;
/* get the ip packet lenth */
/* if too small, not the icmp echoreply packet */
/* give it up */
iIpHeadLen = (int)((pIpHead->ip_verlen & 0x0f) << 2);
if (size < iIpHeadLen + ICMP_HEADSIZE) {
continue;
}
ttl = pIpHead->ip_ttl; /* time to live param */
/* get the icmp header information */
pIcmpHead = (ICMPHEAD *)(buf + iIpHeadLen);
/* not icmp echo reply packet, give it up */
if (pIcmpHead->icmp_type != ICMP_ECHOREPLY) {
continue;
}
/* not proper icmp sequent number, give it up */
if (pIcmpHead->icmp_id != seq || pIcmpHead->icmp_seq != seq) {
continue;
} |
|