| 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. 92. 93. 94. 95. 96. 97. 98. 99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111. 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125. 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139. 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. | /*
ping.c
pings a host and gives stats on interupt
only takes ip addresses
have to be setuid for raw socket
drops privs after getting socket
tgo - http://anomalous-security.org
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip_icmp.h>
#include <netinet/ip.h>
#define DATALEN 56
#define PACKETSIZE 1500
int sent = 0;
int received = 0;
struct icmp *icmp;
char packet[PACKETSIZE+1];
int sock;
char *host;
void die(char *reason){
perror(reason);
exit(1);
}
void usage(char *prog){
printf("%s <ip address>\n",prog);
exit(1);
}
/* stolen - everyone does it */
in_cksum(addr, len)
u_short *addr;
int len;
{
register int nleft = len;
register u_short *w = addr;
register int sum = 0;
/*
* 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 += *(u_char *)w;
/*
* add back carry outs from top 16 bits to low 16 bits
*/
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16); /* add hi 16 to low 16 */
return ( (~sum) & 0xFFFF);
}
void send_request(){
struct sockaddr where;
struct sockaddr_in *whereto;
int total = DATALEN + 8;
memset(packet,0x00,sizeof(packet));
whereto = (struct sockaddr_in *)&where;
whereto->sin_family = AF_INET;
whereto->sin_addr.s_addr = inet_addr(host);
/* fill icmp structure to ping host */
icmp = (struct icmp *)packet;
icmp->icmp_code = 0;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_seq = htons(sent);
icmp->icmp_id = htons(0x029a + sent);
memset(icmp->icmp_data,0x41,DATALEN);
gettimeofday((struct timeval *) icmp->icmp_data,NULL);
icmp->icmp_cksum = 0;
icmp->icmp_cksum = in_cksum(icmp,total);
if( sendto(sock,packet,total,0,&where,sizeof(struct sockaddr)) < 0)
die("sendto");
sent++;
}
void get_response(){
memset(packet,0x00,sizeof(packet));
read(sock,&packet,1500);
int type;
struct sockaddr_in source;
struct ip *ip = (struct ip *) (packet);
icmp = (struct icmp *)(packet + sizeof(struct ip));
type = icmp->icmp_type;
if (type == ICMP_ECHOREPLY){
received++;
memcpy(&source.sin_addr, (struct sockaddr_in *)&ip->ip_src , sizeof(source.sin_addr) );
printf("reply from: %s, id %d, sequence %d, length %d, ttl %d, type %d\n"
,inet_ntoa(source.sin_addr.s_addr)
,htons(icmp->icmp_id)
,htons(icmp->icmp_seq)
,htons(ip->ip_len)
,(short)ip->ip_ttl
,type
);
}
else if ( type != ICMP_ECHO )
printf("Error code %d received - check /usr/include/netinet/ip_icmp.h for value\n",type);
}
void alarm_called(int signo){
/* sends ping request then sets alarm to go off one second later ( send another ping ) */
send_request();
alarm(1);
}
void print_stats(){
/* called on SIGINT, print stats and exits */
if (sent > 0){
printf(
"\n\n--- Stats for: %s ---\n"
"Sent: %d\n"
"Received: %d\n"
"Percent: %d% returned\n"
"---------------------\n"
,inet_ntoa(inet_addr(host))
,sent
,received
,(received/sent)*100
);
}else
printf("no packets sent yet\n");
exit(0);
}
int get_sock(){
/* set socket and drop privs after getting socket */
int sock;
if((sock = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0)
die("socket");
setuid(getuid());
return sock;
}
int main(int argc,char *argv[]){
if (argc < 2) usage(argv[0]);
/* set socket and host */
sock = get_sock();
host = argv[1];
/* sigalarm does 1 second interval pings */
if ( signal(SIGALRM,alarm_called) < 0 )
die("signal");
/* on control+c ( interupt ) print stats and exit */
if ( signal(SIGINT,print_stats) < 0 )
die("signal");
/* signal alarm for first packet */
alarm(1);
/* keep reading responses */
while(1) get_response();
} |