简易ping程序

当我把icmp的检验和设置成0时,ping百度是可以有echo返回。但是ping其他主机是没有返回响应。

手动添加检验和后正常。

原因:可能是baidu服务器并没有检测校验和就返回一个echo,这样可以减少服务器的负担。

而其他一些站点都会校验。


注意点:IPV4的icmp,在原始套接字收到后,收到的是包含IP头在内的完整数据报

IPV6的icmp,则是去除所有ip头和扩展头部的净载荷。

#include "unp.h"
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <assert.h>
char 	sendbuf[MAXLINE], recvbuf[MAXLINE];
int 		datalen = 56,	 nseq = 0;
int 		sockfd;
struct sockaddr_in	dst, src;
socklen_t 		dstlen, srclen;


void callfunc(int signo) ;
void send_icmp( ) ;
void  recv_icmp();
unsigned short icmp_cksum(unsigned short *addr, int len);

int	main( int argc, char **argv) {
	if(argc  != 2) {
		err_quit("args");
	}
	char buf[100];
	struct addrinfo *addr, hints, *next;
	struct sockaddr *servaddr;
	struct sockaddr_in *temp;
	bzero(&hints, sizeof(struct addrinfo));
	hints.ai_family = AF_UNSPEC;
	getaddrinfo(argv[1], NULL, &hints, &addr);
	for(; addr != NULL; addr = addr->ai_next) {
		temp = (struct sockaddr_in *)(addr->ai_addr);
		dst = *temp;
		dstlen = srclen = sizeof(struct sockaddr);
		 printf("the dst ip is %s\n", inet_ntop(AF_INET, &(temp->sin_addr), buf, sizeof(buf)));
		break;
	}
	sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
	setuid(getuid());
	signal(SIGALRM, callfunc);
	callfunc(SIGALRM);
	for(;;) {
		recv_icmp();
	}
}
void callfunc(int signo) {
	send_icmp();
	alarm(1);
}
void send_icmp( ) {
	struct icmp		*icmp;
	/*		struct timeval		*timeval;*/
	icmp = (struct icmp *)sendbuf;
	icmp->icmp_type = 8;
	icmp->icmp_code = 0;
	icmp->icmp_cksum = 0;
	icmp->icmp_id = 88;
	icmp->icmp_seq = nseq ++;
	gettimeofday((struct timeval *)(icmp->icmp_data), NULL);
	icmp->icmp_cksum = icmp_cksum((u_short *)icmp, 56+8);
	sendto(sockfd, sendbuf, 56+8, 0, (SA *)&dst, dstlen);
	return;
}
void cal_time(struct timeval *time1, struct timeval *time2) { /*大 小*/
	time1->tv_usec = ((time1->tv_usec)/1000) + ((time1->tv_sec)*1000);
	time2->tv_usec = ((time2->tv_usec)/1000) + ((time2->tv_sec)*1000);
	time1->tv_usec = (time1->tv_usec) -(time2->tv_usec);
}
void  recv_icmp() {
	struct ip		*ip;
	struct icmp	*icmp;
	struct timeval *rtime;
	int			n,hl;
	char 	buf[100];
	again:
	if(( n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, (SA *)&src, &srclen) ) < 0) {
		if(errno == EINTR)
			goto again;
		else
			exit(0);
	}
	//printf("return a echo\n");

	ip = (struct ip *)recvbuf;
	hl = ip->ip_hl;
	hl = hl<< 2;
	icmp = (struct icmp *)(recvbuf + hl);
	if(icmp == NULL)
		printf("icmp is null\n");
	assert(icmp);
	assert(recvbuf);
	rtime = (struct timeval *)malloc(sizeof(struct timeval));
	if((icmp->icmp_type == 0) && (icmp->icmp_code == 0) &&(icmp->icmp_id == 88)){
		gettimeofday(rtime, NULL);
		cal_time(rtime, (struct timeval *)(icmp->icmp_data));
		printf("The seq %d ,", icmp->icmp_seq);
		printf("Ping the ip is %s :", inet_ntop(AF_INET,&( (&src)->sin_addr), buf, sizeof(buf)));
		printf("ttl  %d  ms\n", rtime->tv_usec);
		
	}
}

unsigned short icmp_cksum(unsigned short *addr, int len)
{
	int				nleft = len;
	int				sum = 0;
	unsigned short	*w = addr;
	unsigned short	answer = 0;
	while (nleft > 1)  {
		sum += *w++;
		nleft -= 2;
	}
	if (nleft == 1) {
		*(unsigned char *)(&answer) = *(unsigned char *)w ;
		sum += answer;
	}
	sum = (sum >> 16) + (sum & 0xffff);	
	sum += (sum >> 16);			
	answer = ~sum;				
	return(answer);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值