/* * ping.c * * An ping example. I have used some iputils code * you can get the iputils source here: http://www.skbuff.net/iputils/ * */ #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netdb.h> #include <netinet/ip_icmp.h> #define pexit(s) ({perror(s); exit(EXIT_FAILURE);}) u_short in_cksum(const u_short *addr, register int len, u_short csum); void print_icmphdr(struct icmphdr *); void print_iphdr(struct iphdr *); int main(int argc, char **argv) { int sock; int len; int bytes; int count = -1; u_short cksum; u_int16_t seq; struct sockaddr_in dst_addr; struct sockaddr_in rcv_addr; struct hostent *dst_host; #define BUFLEN 1000000 char outpack[BUFLEN]; struct icmphdr *icp; struct iphdr *ip; if (argc <= 1) { printf("Usage: %s HOST [COUNT]"); exit(EXIT_FAILURE); } sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (sock == -1) pexit("socket"); dst_host = gethostbyname(argv[1]); if (!dst_host) { errno = h_errno; pexit("gethostbyname"); } memcpy(&dst_addr.sin_addr.s_addr, dst_host->h_addr_list[0], sizeof(dst_addr)); dst_addr.sin_family = PF_INET; dst_addr.sin_port = 0; if (argc > 2 ) count = atoi(argv[2]); seq = 1; while (count--) { icp = (struct icmphdr *)outpack; icp->type = ICMP_ECHO; icp->code = 0; icp->un.echo.sequence = seq; icp->un.echo.id = getpid(); icp->checksum = 0; icp->checksum = in_cksum((u_short *)icp, sizeof(struct icmphdr), 0); bytes = sendto(sock, outpack, sizeof(struct icmphdr), MSG_DONTWAIT, (struct sockaddr *)&dst_addr, sizeof(dst_addr)); if (bytes < 0) pexit("sendto"); sleep(1); len = sizeof(struct sockaddr_in); bytes = recvfrom(sock, outpack, sizeof(struct iphdr) + sizeof(struct icmphdr), MSG_DONTWAIT, (struct sockaddr *)&rcv_addr, &len); if (bytes < 0) /* I'm ignoring incoming errors */ continue; ip = (struct iphdr *)outpack; icp = (struct icmphdr *)&outpack[sizeof(struct iphdr)]; cksum = icp->checksum; icp->checksum = 0; icp->checksum = in_cksum((u_short *)icp, sizeof(struct icmphdr), 0); if (cksum != icp->checksum) /* and ignoring */ continue; /* corrupted packets */ switch(icp->type) { case ICMP_ECHOREPLY: /* and repeateds */ if (icp->un.echo.sequence < seq) continue; print_iphdr(ip); print_icmphdr(icp); putchar('\n'); seq++; break; case ICMP_DEST_UNREACH: printf("Destination unreachable\n"); break; } } return 0; } /* * Taken from iputils/ping.c, at http://www.skbuff.net/iputils/ */ u_short in_cksum(const u_short *addr, register int len, u_short csum) { register int nleft = len; const u_short *w = addr; register u_short answer; register int sum = csum; /* * Our algorithm is simple, using a 32 bit accumulator (sum), * we add sequential 16 bit words to it, and at the end, fold * back all the carry bits from the top 16 bits into the lower * 16 bits. */ while (nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if (nleft == 1) sum += htons(*(u_char *)w << 8); /* * add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); } void print_iphdr(struct iphdr *ip) { printf("IP tos=%u id=%u ttl=%u saddr=%s daddr=%s ", ip->tos, ip->id, ip->ttl, inet_ntoa(ip->saddr), inet_ntoa(ip->daddr)); } void print_icmphdr(struct icmphdr *icp) { printf("ICMP seq=%d ", icp->un.echo.sequence); }
quarta-feira, 7 de dezembro de 2011
Ping/ICMP example
I have tried this on my archlinux i686 and works, on arch x86_64 segfaults and I don't no why, I need to work more on this.
Marcadores:
ICMP,
ICMP ECHO,
ICMP example,
Ping example,
ping example in C,
raw socket,
raw sockets,
sockets
Assinar:
Postar comentários (Atom)
Nenhum comentário:
Postar um comentário