#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
int in_cksum(u_short *p, int n);
int main (int argc, char **argv)
{
int icmp_socket, ret;
char buffer[1024];
struct sockaddr_in you_addr, your_addr;
struct icmp *p,*icmp;
unsigned int sl;
struct ip *ip;
int hlen;
if ((icmp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0) {
perror("socket error :");
exit(0);
}
memset(buffer, 0x00, 1024);
// make icmp packet
p = (struct icmp *) buffer;
p->icmp_type = ICMP_ECHO;
p->icmp_code = 0;
p->icmp_cksum = 0;
p->icmp_seq = 15;
p->icmp_id = getpid();
p->icmp_cksum = in_cksum((u_short *)p, 1000);
memset(&you_addr,0,sizeof(0));
you_addr.sin_addr.s_addr = inet_addr(argv[1]);
you_addr.sin_family = AF_INET;
//sent icmp packet to d host
ret = sendto(icmp_socket, p, sizeof(*p), MSG_DONTWAIT, (struct sockaddr *)&you_addr, sizeof(you_addr));
if (ret<0){
perror("sendto error!");
}
//wait icmp reply
sl= sizeof(your_addr);
ret= recvfrom(icmp_socket, buffer, 1024,0,(struct sockaddr *)&your_addr, &sl);
if(ret<0){
printf("%d %d %d\n", ret,errno, EAGAIN);
perror("recvfrom error!");
}
//when receive the reply output the ip and icmp packet info.
ip = (struct ip *)buffer;
hlen= ip->ip_hl*4;
icmp = (struct icmp *)(buffer+hlen);
printf("reply from %s\n", inet_ntoa(your_addr.sin_addr));
printf("TYPE: %d \n", icmp->icmp_type);
printf("CODE: %d \n", icmp->icmp_code);
printf("SEQ: %d \n", icmp->icmp_seq);
printf("ID: %d \n", icmp->icmp_id);
return 1;
}
int in_cksum(u_short *p, int n)
{
register u_short answer;
register long sum = 0;
u_short odd_byte = 0;
while(n >1)
{
sum += *p++;
n-=2;
}
if (n==1)
{
*(u_char*)(&odd_byte)=*(u_char*)p;
sum+=odd_byte;
}
sum = (sum>>16)+(sum&0xffff);
sum+=(sum>>16);
answer = ~sum;
return (answer);
}
上面这段代码,我以root运行,而且iptables所有禁止ICMP的规则都已注释,但运行:
./ping baidu.com
时还是会报:
sendto error!: Permission denied
这是怎么回事呢?
