23,126
社区成员
发帖
与我相关
我的任务
分享
/* main.c */
#include "errexit.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <errno.h>
#include <linux/icmp.h>
#include <linux/ip.h>
#include <unistd.h>
#define BUFFLENGTH 4096
void Usage()__attribute__((noreturn));
unsigned short in_cksum(unsigned short *addr, int len);
char *ProgName = "rping";
char *myip = "192.168.1.3";
int main( int argc, char * argv[])
{
if( argc != 2 )
Usage();
struct sockaddr_in to, from;
char *buffer[BUFFLENGTH];
char *recvbuffer[BUFFLENGTH];
struct icmphdr *icmphd;
struct iphdr *iphd;
int res;
int tosock;
int fromlen = sizeof(struct sockaddr);
int one = 1;
int *ptr_one = &one;
to.sin_family = AF_INET;
res = inet_aton(argv[1],&to.sin_addr);
if( res < 0 )
errexit("invalid address!\n%s\n",strerror(errno));
memset(buffer,0x00,BUFFLENGTH);
memset(recvbuffer,0x00,BUFFLENGTH);
/*
* create a socket to send out the icmp echo message
*/
tosock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if(tosock<0)
errexit("create socket failed!\n%s\n",strerror(errno));
res = setsockopt(tosock, IPPROTO_IP, IP_HDRINCL,ptr_one, sizeof(one));
if(res < 0)
errexit("setsockopt failed!\n%s\n",strerror(errno));
/*
* construct the ip header
*/
iphd = ( struct iphdr *)buffer;
iphd->version = 4;
iphd->ihl = 5;
iphd->tos = 0;
iphd->tot_len = 84;
iphd->id = getpid() & 0xffff;
iphd->frag_off =0;
iphd->ttl = 32;
iphd->protocol =IPPROTO_ICMP;
iphd->check = 0;
iphd->saddr = inet_addr(myip);
iphd->daddr = to.sin_addr.s_addr;
/*
* construct the icmp header
*/
icmphd = (struct icmphdr *)(iphd+1);
icmphd->type = ICMP_ECHO;
icmphd->code = 5;
icmphd->checksum = in_cksum((unsigned short *)icmphd,64);
icmphd->un.echo.id = (short)(getpid()&0xffff);
icmphd->un.echo.sequence = 1;
while(1)
{
res = sendto(tosock,(void *)buffer,84,0,(struct sockaddr*)&to,sizeof(struct sockaddr));
if(res == -1)
errexit("rping error occured!\n%s\n",strerror(errno));
else if(res == 84)
break;
else if (errno == EINTR)
continue;
}
printf("done,%d bytes sent.\n",res);
char *addr = (char *)&(iphd->saddr);
printf("src ip address is :%d.%d.%d.%d\n",
addr[0]&0xff,addr[1]&0xff,addr[2]&0xff,addr[3]&0xff);
while(1)
{
res = recvfrom(tosock,recvbuffer,BUFFLENGTH,0,(struct sockaddr*)&from,(socklen_t *)&fromlen);
if(res == -1)
errexit("rping recv failed!\n%s\n",strerror(errno));
else if( errno == EINTR)
continue;
iphd = (struct iphdr *)recvbuffer;
char *saddr = (char *)&(iphd->saddr);
icmphd = (struct icmphdr*)(iphd+1);
if(icmphd->type == ICMP_ECHO)
continue;
if(icmphd->type == ICMP_ECHOREPLY)
{
printf("ping %d bytes received,seq = %d,code = %d\n",
res,
icmphd->un.echo.sequence & 0xffff,
icmphd->code & 0xff);
printf("src ip address is :%d.%d.%d.%d\n",
saddr[0]&0xff,saddr[1]&0xff,saddr[2]&0xff,saddr[3]&0xff);
break;
}
}
return 0;
}
void Usage()
{
printf("%s dstIPaddress\n",ProgName);
exit(-1);
}
unsigned short in_cksum(unsigned short *addr, int len)
{
register int nleft = len;
register unsigned short *w = addr;
register unsigned short answer;
register int sum = 0;
while(nleft > 1)
{
sum+=*w++;
nleft -= 2;
}
/* mop up and odd byte, if necessary */
if(nleft == 1)
{
unsigned short u = 0;
*(unsigned short *)(&u) = *(unsigned short *)w;
sum +=u;
}
sum = ( sum >> 16 ) + (sum & 0xffff)
sum +=(sum>>16);
answer = ~sum;
return ( answer );
}
/* errexit.h */
#ifndef ERREXIT_H
#define ERREXIT_H
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
extern void errexit(const char *fmt,...)__attribute__((format(printf,1,2)));
#endif
/* errexit.c */
#include "errexit.h"
void errexit(const char * fmt,...){
va_list vp;
va_start(vp,fmt);
vfprintf(stderr,fmt,vp);
va_end(vp);
exit(-1);
}
/*
* construct the icmp header
*/
icmphd = (struct icmphdr *)(iphd+1);
icmphd->type = ICMP_ECHO;
icmphd->code = 5;
icmphd->checksum = in_cksum((unsigned short *)icmphd,64);
icmphd->un.echo.id = (short)(getpid()&0xffff);
icmphd->un.echo.sequence = 1;
/*
* construct the icmp header
*/
icmphd = (struct icmphdr *)(iphd+1);
icmphd->type = ICMP_ECHO;
icmphd->code = 0;
icmphd->un.echo.id = (short)(getpid()&0xffff);
icmphd->un.echo.sequence = 1;
icmphd->checksum = in_cksum((unsigned short *)icmphd,64);