1 include { "internet.g" }
2
3 import "ws2_32.dll" {
4
5 int setsockopt( uint, int, int, uint, int )
6 int getsockopt( uint, int, int, uint, uint )
7 int sendto( uint, uint, int, int, uint, int )
8 int recvfrom( uint, uint, int, int, uint, uint )
9 uint WSASocketA( uint, uint, uint, uint, uint, uint )->WSASocket
10 uint getprotobyname( uint )
11 }
12
13 import "kernel32.dll" {
14 uint GetTickCount()
15 Sleep( uint )
16 uint GetCurrentProcessId()
17 }
18
19 define {
20 SOL_SOCKET = 0xFFFF
21 SO_SNDTIMEO = 0x1005 /* send timeout */
22 SO_RCVTIMEO = 0x1006 /* receive timeout */
23
24 ICMP_ECHO = 8
25
26 MAX_PACKET = 1024
27
28 INADDR_ANY = 0x00000000
29
30 }
31
32 type icmphdr {
33 byte icmp_type /* type of message */
34 byte icmp_code /* type sub code */
35 ushort icmp_cksum /* ones complement cksum */
36 ushort icmp_id /* identifier */
37 ushort icmp_seq /* sequence number */
38 uint timestamp
39 }
40
41 type protoent {
42 uint p_name
43 uint p_aliases
44 short p_proto;
45 };
46
47
48 func ushort checksum( uint b, uint len )
49 {
50 uint lsum = 0
51 uint m = b + len
52
53 while b < m
54 {
55 lsum += b->ushort /* add word value to sum */
56 b += 2
57 }
58
59 /*if( len % 1 )
60 {
61 lsum += ( b - 1 )->ushort;
62 }*/
63
64 lsum = (lsum & 0xffff) + (lsum>>16)
65 lsum += (lsum >> 16)
66
67 return ( ~lsum )
68 }
69
70 func uint ping( str hostname, uint timeout, uint datasize, uint timerep, uint a_errcode )
71 {
72 uint sock
73 uint hp, addr
74 uint seq_no
75 int bwrote, bread
76 uint i
77 sockaddr_in dest, from;
78 uint tmp
79 buf icmp, recv
80 uint icmp_d, recv_d
81 timeout = max( timeout, 1000 )
82 datasize = max( datasize, 1 )
83 uint pr
84 uint he
85
86 pr as getprotobyname("icmp".ptr())->protoent
87 if !&pr
88 {
89 if a_errcode : a_errcode->uint = 1
90 return 0
91 }
92
93 sock = createsocket( $AF_INET, $SOCK_RAW, pr.p_proto)//$IPPROTO_ICMP
94
95 if sock == $INVALID_SOCKET
96 {
97 if a_errcode : a_errcode->uint = 2
98 return 0
99 }
100
101 if setsockopt( sock, $SOL_SOCKET, $SO_RCVTIMEO, &timeout, 4 ) == $SOCKET_ERROR ||
102 setsockopt( sock, $SOL_SOCKET, $SO_SNDTIMEO, &timeout, 4 ) == $SOCKET_ERROR
103 {
104 if a_errcode : a_errcode->uint = 3
105 return 0
106 }
107
108 dest.sin_addr = inet_addr( hostname.ptr() )
109 if dest.sin_addr == 0xFFFFFFFF
110 {
111 he = gethostbyname( hostname.ptr() )
112 if !he
113 {
114 if a_errcode : a_errcode->uint = 4
115 return 0
116 }
117 dest.sin_addr = ( he->hostent.h_addr_list->uint)->uint
118 }
119 dest.sin_family = $AF_INET;
120
121 datasize += sizeof( icmphdr );
122 datasize = min( $MAX_PACKET, datasize )
123
124 icmp.expand($MAX_PACKET);
125 recv.expand($MAX_PACKET);
126
127 icmp_d as icmp.ptr()->icmphdr
128
129 icmp_d.icmp_type = $ICMP_ECHO;
130
131 icmp_d.icmp_id = ushort( GetCurrentProcessId() );
132
133 fornum i = sizeof( icmphdr ), datasize
134 {
135 icmp[i] = i % 256
136 }
137
138 from.sin_addr = $INADDR_ANY
139 from.sin_family = $AF_INET
140
141 while(1)
142 {
143
144 icmp_d.icmp_cksum = 0;
145 icmp_d.timestamp = GetTickCount();
146 icmp_d.icmp_seq = seq_no++;
147 icmp_d.icmp_cksum = checksum( &icmp_d, datasize );
148
149 bwrote = sendto( sock, &icmp_d, datasize, 0, &dest, sizeof(sockaddr_in) )
150 if ( bwrote == $SOCKET_ERROR )
151 {
152 if a_errcode : a_errcode->uint = 5
153 return 0
154 }
155
156 bwrote = sizeof( sockaddr_in )
157 while ( 1 )
158 {
159 bread = recvfrom( sock, recv.ptr(), $MAX_PACKET, 0, &from, &bwrote )
160
161 if bread == $SOCKET_ERROR
162 {
163 if a_errcode : a_errcode->uint = 6
164 return 0
165 }
166 recv_d = recv.ptr()
167 recv.use = bread
168 recv_d += ( recv_d->byte & 0x0F ) * 4
169
170 recv_d as icmphdr
171 if recv_d.icmp_id == icmp_d.icmp_id &&
172 recv_d.icmp_seq == icmp_d.icmp_seq
173 {
174
175 break
176 }
177 }
178 if timerep
179 {
180 Sleep( timerep )
181 }
182 else : break;
183 }
184 return 1;
185
186 }
187
188