summaryrefslogtreecommitdiff
path: root/Userland/ping.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/ping.cpp')
-rw-r--r--Userland/ping.cpp58
1 files changed, 58 insertions, 0 deletions
diff --git a/Userland/ping.cpp b/Userland/ping.cpp
new file mode 100644
index 0000000000..321cdff48c
--- /dev/null
+++ b/Userland/ping.cpp
@@ -0,0 +1,58 @@
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip_icmp.h>
+#include <stdio.h>
+#include <string.h>
+#include <Kernel/NetworkOrdered.h>
+
+NetworkOrdered<word> internet_checksum(const void* ptr, size_t count)
+{
+ dword checksum = 0;
+ auto* w = (const word*)ptr;
+ while (count > 1) {
+ checksum += convert_between_host_and_network(*w++);
+ if (checksum & 0x80000000)
+ checksum = (checksum & 0xffff) | (checksum >> 16);
+ count -= 2;
+ }
+ while (checksum >> 16)
+ checksum = (checksum & 0xffff) + (checksum >> 16);
+ return ~checksum & 0xffff;
+}
+
+
+int main(int argc, char** argv)
+{
+ int fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ if (fd < 0) {
+ perror("socket");
+ return 1;
+ }
+
+ sockaddr_in peer_address;
+ memset(&peer_address, 0, sizeof(peer_address));
+ peer_address.sin_family = AF_INET;
+ peer_address.sin_port = 0;
+ peer_address.sin_addr.s_addr = 0x0105a8c0; // 192.168.5.1
+
+ struct PingPacket {
+ struct icmphdr header;
+ char msg[64 - sizeof(struct icmphdr)];
+ };
+
+ PingPacket ping_packet;
+ memset(&ping_packet, 0, sizeof(PingPacket));
+
+ ping_packet.header.type = 8; // Echo request
+ strcpy(ping_packet.msg, "Hello there!\n");
+
+ ping_packet.header.checksum = htons(internet_checksum(&ping_packet, sizeof(PingPacket)));
+
+ int rc = sendto(fd, &ping_packet, sizeof(PingPacket), 0, (const struct sockaddr*)&peer_address, sizeof(sockaddr_in));
+ if (rc < 0) {
+ perror("sendto");
+ return 1;
+ }
+
+ return 0;
+}