Добавил:
korayakov
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip_icmp.h>
#include <signal.h>
#include <getopt.h>
typedef struct sockaddr SA;
SA *r_addr;
SA *in_addr;
socklen_t r_len;
socklen_t in_len;
#define MAX_LENGTH 65536
char dgram_buf[MAX_LENGTH];
char in_buf[MAX_LENGTH];
int datalen = 56;
int verbose = 0;
#define vprintf if (verbose) printf
int sd = -1; /* socket descriptor */
unsigned short nseq = 0;
int stop = 0;
#include "icmp_strings.h"
double tv_diff(struct timeval *old, struct timeval *new)
{
return (new->tv_sec - old->tv_sec)*1000 +
((double)(new->tv_usec - old->tv_usec))/1000;
}
void proc_v4()
{
struct ip *ip;
struct icmp *icmp;
int iplen, icmplen;
double rtt;
static char s_addr[128]; /* max UNIX domain */
ssize_t res = recvfrom(sd, in_buf, MAX_LENGTH, 0, in_addr, &in_len);
if (res <= 0) return;
struct timeval ntv, *tvsend;
gettimeofday(&ntv, NULL);
ip = (struct ip *)in_buf; /* ip header */
iplen = ip->ip_hl << 2; /* ip header length = ip_hl / 4 */
icmp = (struct icmp *)(in_buf+iplen); /* icmp header*/
if ( (icmplen = res - iplen) < 8){
vprintf("Incomplete icmp packet len=%d\n", icmplen);
return;
}
struct sockaddr_in *sin = (struct sockaddr_in*)in_addr;
inet_ntop(AF_INET, &sin->sin_addr,
s_addr, sizeof(s_addr));
if (icmp->icmp_type == ICMP_ECHOREPLY){
if (ntohs(icmp->icmp_id) != getpid()){
vprintf("FOREIGN %d bytes from %s: seq=%d ttl=%d\n",
icmplen, s_addr, ntohs(icmp->icmp_seq), ip->ip_ttl);
return;
}
tvsend = (struct timeval *)icmp->icmp_data;
rtt = tv_diff(tvsend, &ntv);
printf("%d bytes from %s: seq=%d ttl=%d rtt=%.3f ms\n",
icmplen, s_addr, ntohs(icmp->icmp_seq), ip->ip_ttl, rtt);
}
else{
/*if (ntohs(icmp->icmp_id) != getpid()){
vprintf("Receive %d bytes from %s: type %d, code %d\n",
icmplen, s_addr, icmp->icmp_type, icmp->icmp_code);
return;
}*/
printf("From %s: %s - %s\n",
s_addr,
ICMP_TYPES[icmp->icmp_type],
ICMP_CODES[icmp->icmp_type][icmp->icmp_code]);
}
}
unsigned short in_checksum(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;
}
void send_v4(int sig_num)
{
int len;
struct icmp *hdr = (struct icmp *)dgram_buf;
len = 8 + datalen;
memset(hdr, 0, len);
hdr->icmp_type = ICMP_ECHO;
hdr->icmp_code = 0;
hdr->icmp_id = htons(getpid());
hdr->icmp_seq = htons(nseq++);
gettimeofday((struct timeval *)hdr->icmp_data, NULL);
hdr->icmp_cksum = 0;
hdr->icmp_cksum = in_checksum((u_short *)hdr, len);
sendto(sd, dgram_buf, len, 0, r_addr, r_len);
alarm(1);
return;
}
void sig_int(sig_num)
{
printf("Catch interrupt\n");
stop++;
exit(0);
}
void main_loop()
{
sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if (sd < 0){
perror("Create socket"); exit(1);
}
setuid(getuid());
stop = 0;
signal(SIGINT, &sig_int);
signal(SIGALRM, &send_v4);
kill(getpid(), SIGALRM);
fd_set rset;
FD_ZERO(&rset);
FD_SET(sd, &rset);
printf("Start ping cicle\n");
while (!stop){
FD_SET(sd, &rset);
select(sd+1,&rset,NULL,NULL,NULL);
if (FD_ISSET(sd, &rset)){
proc_v4();
}
}
printf("Finish\n");
}
int main(int argc, char *argv[])
{
printf("Net_ping program.\n");
char c;
while ( (c = getopt(argc, argv, "v")) != -1 ){
switch (c){
case 'v':
verbose = 1;
printf("Running verbose mode\n");
break;
case '?':
fprintf(stderr, "Unrecognised option: %c", c);
exit(1);
}
}
if (argc < 2){ /* print usage */
perror("Not enough arguments");
printf("Usage: %s <remote_ip>\n", argv[0]);
exit(1);
}
const char *remote_ip = argv[argc-1];
printf("Remote machine: %s\n", argv[argc-1]);
in_len = sizeof(struct sockaddr_in);
in_addr = (struct sockaddr *) malloc(in_len);
r_len = sizeof(struct sockaddr_in);
r_addr = (struct sockaddr *) malloc(r_len);
struct sockaddr_in *t_addr = (struct sockaddr_in *)r_addr;
memset(t_addr, 0, r_len);
t_addr->sin_family = AF_INET;
if (inet_pton(AF_INET, remote_ip, &(t_addr->sin_addr))<=0){
perror("Bad remote_ip address");
return -1;
}
main_loop();
free(r_addr);
free(in_addr);
return 0;
}