Quantcast
Channel: Linux.org.ru: Форум (тех. форум)
Viewing all articles
Browse latest Browse all 73844

трассировка icmp

$
0
0

Привет всем. Никак не могу понять как правильно написать. Программа использует icmp протокол. Например я пингую хост, в настройках ip устанавливаю ttl++. В wireshark пишет некоректная чексумма, она такая, а должна быть такая. А как мне известно, что icmp с неправильной чексуммой не дождёться ответа, но, маршрут проходит до хоста, но последний хост в моей программе не отображаеться, хоть я могу сам дописать, но может что-то в чек сумме? Вот код.

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ip_icmp.h>
#include <unistd.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <errno.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <time.h>
#include <strings.h>
#include <sys/time.h>

unsigned short checksum(unsigned short *, int);

int main(int argc, char *argv[]){

	int sockfd;
	struct sockaddr_in dst;
	struct sockaddr_in from;
	struct hostent *ht;
	struct icmp *icmp;
	struct ip *ip;
	pid_t pid = getpid();
	static int icmplen = 64;
	char sendbuf[1500];
	char readbuf[1500];
	int ttl;
	int seq = 0;
	int len;

	if ((sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) == -1){
		perror("socket() failed");
		exit(-1);
	}

	if (setuid(getuid()) == -1)
		perror("setuid() failed");

	if ((ht = gethostbyname(argv[1])) == NULL){
		herror("gethostbyname() failed");
		exit(-1);
	}

	dst.sin_family = AF_INET;
	dst.sin_port = IPPROTO_ICMP;
	dst.sin_addr = *((struct in_addr *)ht->h_addr);
	

	for(ttl = 1; ttl <= 64; ttl++){
	  if(setsockopt(sockfd, SOL_IP, IP_TTL,&ttl,sizeof(ttl)) == -1){
  	  perror("setsockopt() failed");
   		exit(-1);
  	}

		bzero(&sendbuf, 1500);
		bzero(&readbuf, 1500);
		icmp = (struct icmp *) sendbuf;
		icmp->icmp_type = ICMP_ECHO;
		icmp->icmp_code = 0;
		icmp->icmp_id = pid;
		icmp->icmp_seq = seq;
		icmp->icmp_cksum = 0;
		icmp->icmp_cksum = checksum((unsigned short *)icmp, icmplen);

		if(sendto(	sockfd,
								sendbuf, 
								icmplen, 
								0, 
								(struct sockaddr *)&dst,
								sizeof(dst)) == -1){
			perror("sendto failed");
			exit(-1);
		}

		unsigned int fromlen = sizeof(from);
		if((len =recvfrom(sockfd,
								readbuf,
								icmplen, 
								0,
								(struct sockaddr *)&from,
								&fromlen)) == -1){
			perror("recvfrom() failed");
			exit(-1);
		}

		char *ptr = &readbuf[0];
		int iplen;
		ip = (struct ip *) ptr;
		iplen = ip->ip_hl << 2;

		icmp = (struct icmp *) (ptr + iplen);

		if(icmp->icmp_type == ICMP_TIME_EXCEEDED)
			printf(	"%s ttl=%d len=%d icmplen=%d\n", 
							inet_ntoa(from.sin_addr),ttl, len,icmplen);
		else if(icmp->icmp_type == ICMP_ECHOREPLY){
			printf("%s\n", inet_ntoa(from.sin_addr));
			exit(0);
		}
		//seq++;
	}
	
}

unsigned short checksum(unsigned short *addr, int count){
	register long sum;
//	unsigned short sum;
	unsigned short icmpsum;

	while(count > 1){
		sum += (unsigned short) *addr++;
		count -= 2;
	}

	if(count == 1)
		sum += *(unsigned char *) addr;

	while(sum >> 16)
		sum = (sum & 0xffff) + (sum >> 16);

	icmpsum = ~sum;
	return icmpsum;
}

 ,


Viewing all articles
Browse latest Browse all 73844

Trending Articles