1 module app;
2 import std.stdio;
3 import std.string;
4 import std.socket;
5 import core.thread;
6 import std.datetime.stopwatch;
7 import ipcmp;
8 import utils;
9 
10 const int PING_PKT_S = 64;
11 
12 struct PingPacket
13 {
14     icmp_hdr hdr;
15     ubyte[PING_PKT_S - icmp_hdr.sizeof] msg;
16 }
17 
18 struct PingReply
19 {
20     ubyte type; // ICMP message type (should be 0x00 for Echo Reply)
21     ubyte code; // ICMP message code (should be 0x00 for Echo Reply)
22     ushort checksum; // ICMP header checksum
23     ushort identifier; // Identifier field (16 bits)
24     ushort sequence; // Sequence number field (16 bits)
25     int timestamp; // Use this field to store the timestamp
26 }
27 
28 ushort checksum(void* data, size_t len)
29 {
30     ushort* buf = cast(ushort*) data;
31     uint sum = 0;
32 
33     while (len > 1)
34     {
35         sum += *buf++;
36         len -= 2;
37     }
38 
39     if (len == 1)
40     {
41         sum += *cast(ubyte*) buf;
42     }
43 
44     while (sum >> 16)
45     {
46         sum = (sum & 0xFFFF) + (sum >> 16);
47     }
48 
49     return cast(ushort)(~sum);
50 }
51 
52 void main(string[] args)
53 {
54     if (args.length < 2)
55     {
56         writeln("Supply a hostname as parameter");
57         return;
58     }
59 
60     string host = args[1];
61 
62     int seq = 0;
63 
64     PingPacket packet = PingPacket();
65     packet.hdr.type = 8;
66     packet.hdr.code = 0;
67     packet.hdr.un.echo.id = cast(ushort)(getpid() & 0xFFFF);
68 
69     packet.hdr.un.echo.sequence = cast(ushort)(seq++);
70 
71     packet.hdr.checksum = checksum(&packet, PingPacket.sizeof);
72 
73     Address[] addresses = getAddress(host);
74 
75     Socket s = new Socket(AddressFamily.INET, SocketType.RAW, ProtocolType.ICMP);
76 
77     StopWatch sw = StopWatch(AutoStart.yes);
78     s.sendTo((cast(ubyte*)&packet)[0 .. packet.sizeof], addresses[0]);
79 
80     ubyte[64] recvBuf;
81     s.receiveFrom(recvBuf);
82 
83     long time = sw.peek.total!"msecs";
84 
85     // PingReply reply;
86 
87     // // Parse the fields from recvBuf
88     // reply.type = recvBuf[0];
89     // reply.code = recvBuf[1];
90     // reply.checksum = recvBuf[2 .. 4].toType!ushort;
91     // reply.identifier = recvBuf[4 .. 6].toType!ushort;
92     // reply.sequence = recvBuf[6 .. 8].toType!ushort;
93     // reply.timestamp = recvBuf[8 .. 12].toType!int;
94 
95     writeln("Reply from ", host, " in ", time , "ms");
96 }