Skip to content

Commit a63f3ac

Browse files
author
Your Name
committed
Ivan's ping.c
1 parent 2ec26e4 commit a63f3ac

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

sockets/RAW/ping.c

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
* ping.c
3+
* written by Ivan Ryabtsov ivriabtsov at gmail dot com
4+
*/
5+
#include <unistd.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
#include <time.h>
9+
#include <limits.h>
10+
11+
#include <sys/types.h>
12+
#include <sys/socket.h>
13+
#include <netinet/in.h>
14+
#include <netdb.h>
15+
#include <netinet/ip_icmp.h>
16+
#include <netinet/ip.h>
17+
#include <string.h>
18+
19+
struct stuff {
20+
int recv_sock, send_sock;
21+
struct sockaddr_in recv_sockaddr, send_sockaddr;
22+
struct hostent *h_ent;
23+
};
24+
25+
int ping(const char *name);
26+
int routines(struct stuff *conn);
27+
unsigned short in_cksum(unsigned short *addr, size_t len);
28+
29+
int main(int argc, char *argv[])
30+
{
31+
if (argc < 2) {
32+
printf("need hostname\n");
33+
exit(1);
34+
}
35+
if (ping(argv[1])) {
36+
printf("host %s is alive\n", argv[1]);
37+
} else {
38+
printf("host %s is not alive\n", argv[1]);
39+
}
40+
return 0;
41+
}
42+
43+
44+
int ping(const char *name)
45+
{
46+
struct stuff *conn;
47+
conn = malloc(sizeof(struct stuff));
48+
conn->h_ent = gethostbyname(name);
49+
if (!conn->h_ent) {
50+
perror("gethostbyname: ");
51+
return 0;
52+
}
53+
if ( (conn->send_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) ==
54+
-1) {
55+
perror("socket: ");
56+
return 0;
57+
}
58+
conn->send_sockaddr.sin_family = AF_INET;
59+
conn->send_sockaddr.sin_addr.s_addr =
60+
*(in_addr_t *)conn->h_ent->h_addr_list[0];
61+
/*printf("0x%X\n", send_sockaddr.sin_addr.s_addr);*/
62+
if ( (conn->recv_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) ==
63+
-1) {
64+
perror("socket: ");
65+
return 0;
66+
}
67+
conn->recv_sockaddr.sin_family = AF_INET;
68+
conn->recv_sockaddr.sin_addr.s_addr = *(long *)conn->
69+
h_ent->h_addr_list[0];
70+
/*printf("0x%X\n", recv_sockaddr.sin_addr.s_addr);*/
71+
if (routines(conn) >= 3) {
72+
return 1;
73+
} else {
74+
return 0;
75+
}
76+
}
77+
78+
#define BUF_SIZ 100
79+
#define LOAD_SIZ 5
80+
struct s_frame {
81+
struct icmphdr _icmphdr;
82+
char payload[LOAD_SIZ];
83+
};
84+
int routines(struct stuff *conn)
85+
{
86+
struct s_frame *send_frame;
87+
void *recv_frame;
88+
unsigned short cksum, seqtmp;
89+
int i, succ_cnt = 0;
90+
time_t t;
91+
int iphdrlen, icmplen;
92+
socklen_t len = sizeof(struct sockaddr_in);
93+
srand((unsigned int)time(&t));
94+
send_frame = malloc(sizeof(struct s_frame));
95+
if (!send_frame) {
96+
perror("malloc: ");
97+
return 0;
98+
}
99+
recv_frame = malloc(BUF_SIZ);
100+
if (!recv_frame) {
101+
perror("malloc: ");
102+
return 0;
103+
}
104+
send_frame->_icmphdr.type = ICMP_ECHO;
105+
send_frame->_icmphdr.code = ICMP_ECHOREPLY;
106+
/*send_frame->_icmphdr.un.echo.id = rand() % (USHRT_MAX + 1);*/
107+
send_frame->_icmphdr.un.echo.id = rand() % (USHRT_MAX + 1);
108+
send_frame->_icmphdr.un.echo.sequence = htons(1);
109+
/*send_frame->payload = rand() % (UINT_MAX + 1);*/
110+
for (i = 0; i < 4; i++) {
111+
memset(recv_frame, 0, 1400);
112+
send_frame->_icmphdr.checksum = 0;
113+
send_frame->_icmphdr.checksum =
114+
in_cksum((unsigned short *)send_frame,
115+
sizeof(struct s_frame));
116+
if (sendto(conn->send_sock, send_frame, sizeof(struct s_frame),
117+
0, (struct sockaddr *)&conn->
118+
send_sockaddr,
119+
sizeof(struct sockaddr_in)) == -1) {
120+
perror("!!!!!sendto: ");
121+
goto cont;
122+
}
123+
if (recvfrom(conn->recv_sock, recv_frame, BUF_SIZ,
124+
MSG_WAITALL,
125+
(struct sockaddr *)&conn->recv_sockaddr,
126+
&len) == -1) {
127+
perror("!!!!!recvfrom: ");
128+
goto cont;
129+
}
130+
/*sleep(1);*/
131+
/* comparison src and dest addresses */
132+
if ( *(unsigned int *)conn->h_ent->h_addr_list[0] ==
133+
((struct iphdr *)recv_frame)->saddr) {
134+
printf("package with a valid addresses\n");
135+
} else {
136+
printf("!!!!!src and dest addresses is not walid\n");
137+
goto cont;
138+
}
139+
/*
140+
printf("s 0x%X, d 0x%X\n", ((struct iphdr *)recv_frame)->saddr,
141+
((struct iphdr *)recv_frame)->daddr);
142+
*/
143+
iphdrlen = ((struct iphdr *)recv_frame)->ihl * sizeof(int);
144+
/* check chksum in ip header */
145+
cksum = ((struct iphdr *)recv_frame)->check;
146+
((struct iphdr *)recv_frame)->check = 0;
147+
if (cksum == in_cksum((unsigned short *)recv_frame, iphdrlen)){
148+
printf("ip cksum is equal %hu\n", cksum);
149+
} else {
150+
printf("!!!!!ip cksum is not equal %hu\n", cksum);
151+
goto cont;
152+
}
153+
/* compute len of icmp header */
154+
icmplen = ntohs(((struct iphdr *)recv_frame)->tot_len) -
155+
iphdrlen;
156+
/*printf("iphdr len: %d, icmp len: %d, all frame len: %hu\n",
157+
iphdrlen, icmplen,
158+
ntohs(((struct iphdr *)recv_frame)->tot_len));
159+
printf("%p, %p\n", recv_frame, recv_frame + iphdrlen);
160+
printf("%p, %p\n", recv_frame, (struct icmphdr *)(recv_frame +
161+
iphdrlen));
162+
printf("%d\n", ((struct icmphdr *)(recv_frame + iphdrlen))->
163+
checksum);*/
164+
/* check icmp id and sequence number */
165+
if (((struct icmphdr *)(recv_frame + iphdrlen))->un.echo.id ==
166+
send_frame->_icmphdr.un.echo.id) {
167+
printf("recv and send id is equal %hu\n",
168+
ntohs(send_frame->_icmphdr.un.echo.id));
169+
} else {
170+
printf("!!!!!id is not equal %hu\n",
171+
ntohs(send_frame->_icmphdr.un.echo.id));
172+
goto cont;
173+
}
174+
if (((struct icmphdr *)(recv_frame + iphdrlen))->
175+
un.echo.sequence ==
176+
send_frame->_icmphdr.un.echo.sequence) {
177+
printf("recv end send seq is equal %hu\n",
178+
ntohs(send_frame->
179+
_icmphdr.un.echo.sequence));
180+
} else {
181+
printf("!!!!sequence is not equal l %hu, r %hu\n",
182+
ntohs(send_frame->
183+
_icmphdr.un.echo.sequence),
184+
htons(((struct icmphdr *)
185+
(recv_frame + iphdrlen))
186+
->un.echo.sequence));
187+
// goto cont;
188+
}
189+
190+
/* check chksum of icmp header */
191+
cksum = ((struct icmphdr *)(recv_frame + iphdrlen))->
192+
checksum;
193+
/*printf("recv chsum: %hu\n", cksum);*/
194+
((struct icmphdr *)(recv_frame + iphdrlen))->checksum = 0;
195+
if (cksum == in_cksum((unsigned short *)
196+
(recv_frame + iphdrlen), icmplen)) {
197+
printf("icmp cksum is equal %d\n", cksum);
198+
succ_cnt++;
199+
printf("%d\n", succ_cnt);
200+
} else {
201+
printf("!!!!!icmp checksum is not walid %hu\n", cksum);
202+
goto cont;
203+
}
204+
cont:
205+
seqtmp = ntohs(send_frame->_icmphdr.un.echo.sequence);
206+
seqtmp++;
207+
send_frame->_icmphdr.un.echo.sequence = htons(seqtmp);
208+
printf("next sequence is %hu\n=============\n", seqtmp);
209+
}
210+
return succ_cnt;
211+
}
212+
213+
unsigned short in_cksum(unsigned short *addr, size_t len)
214+
{
215+
int nleft = len;
216+
int sum = 0;
217+
unsigned short *w = addr;
218+
unsigned short answer = 0;
219+
220+
while (nleft > 1) {
221+
sum += *w++;
222+
nleft -= 2;
223+
}
224+
225+
if (nleft == 1) {
226+
*(unsigned char *)(&answer) += *(unsigned char *)w;
227+
sum += answer;
228+
}
229+
230+
sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
231+
sum += (sum >> 16); /* add carry */
232+
answer = ~sum; /* truncate to 16 bits */
233+
return(answer);
234+
}
235+

0 commit comments

Comments
 (0)