summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-03-12 15:51:42 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-03-12 15:51:42 +0100
commita017a7744279a29ab490c0aa7d2a81deb0997ae4 (patch)
treeb33d8d4c51d437b460ffa2ce9213edf40644bccd /Userland
parent8e667747f0ac744e74b1acb5b83a0b9db0b7acde (diff)
downloadserenity-a017a7744279a29ab490c0aa7d2a81deb0997ae4.zip
Kernel+LibC+Userland: Start working on an IPv4 socket backend.
The first userland networking program will be "ping" :^)
Diffstat (limited to 'Userland')
-rw-r--r--Userland/.gitignore1
-rw-r--r--Userland/Makefile5
-rw-r--r--Userland/ping.cpp58
3 files changed, 64 insertions, 0 deletions
diff --git a/Userland/.gitignore b/Userland/.gitignore
index fc991ef960..17a5d60640 100644
--- a/Userland/.gitignore
+++ b/Userland/.gitignore
@@ -37,3 +37,4 @@ su
env
chown
stat
+ping
diff --git a/Userland/Makefile b/Userland/Makefile
index 3450d3d912..6acf59947b 100644
--- a/Userland/Makefile
+++ b/Userland/Makefile
@@ -33,6 +33,7 @@ OBJS = \
su.o \
env.o \
stat.o \
+ ping.o \
rm.o
APPS = \
@@ -71,6 +72,7 @@ APPS = \
su \
env \
stat \
+ ping \
rm
ARCH_FLAGS =
@@ -198,6 +200,9 @@ env: env.o
stat: stat.o
$(LD) -o $@ $(LDFLAGS) $< -lc
+ping: ping.o
+ $(LD) -o $@ $(LDFLAGS) $< -lc
+
.cpp.o:
@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
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;
+}