Serenity Operating System
at master 145 lines 4.0 kB view raw
1/* 2 * Copyright (c) 2020-2022, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Function.h> 8#include <AK/IPv4Address.h> 9#include <LibCore/System.h> 10#include <LibMain/Main.h> 11#include <net/if.h> 12#include <netinet/in.h> 13#include <stdio.h> 14#include <string.h> 15#include <sys/socket.h> 16 17static void test_invalid(int); 18static void test_no_route(int); 19static void test_valid(int); 20static void test_send(int); 21 22static ErrorOr<void> test(Function<void(int)> test_fn) 23{ 24 auto fd = TRY(Core::System::socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); 25 test_fn(fd); 26 27 // be a responsible boi 28 TRY(Core::System::close(fd)); 29 30 return {}; 31} 32 33ErrorOr<int> serenity_main(Main::Arguments) 34{ 35 TRY(test(test_invalid)); 36 TRY(test(test_valid)); 37 TRY(test(test_no_route)); 38 TRY(test(test_send)); 39 40 return 0; 41} 42 43void test_invalid(int fd) 44{ 45 // bind to an interface that does not exist 46 char buf[IFNAMSIZ]; 47 socklen_t buflen = IFNAMSIZ; 48 memcpy(buf, "foodev", 7); 49 50 auto setsockopt_maybe_error = Core::System::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, buflen); 51 if (setsockopt_maybe_error.is_error()) { 52 warnln("setsockopt(SO_BINDTODEVICE) :: invalid (Should fail with ENODEV)."); 53 puts("PASS invalid"); 54 } else { 55 puts("FAIL invalid"); 56 } 57} 58 59void test_valid(int fd) 60{ 61 // bind to an interface that exists 62 char buf[IFNAMSIZ]; 63 socklen_t buflen = IFNAMSIZ; 64 memcpy(buf, "loop", 5); 65 66 auto setsockopt_maybe_error = Core::System::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, buflen); 67 if (setsockopt_maybe_error.is_error()) { 68 warnln("setsockopt(SO_BINDTODEVICE) :: valid"); 69 puts("FAIL valid"); 70 } else { 71 puts("PASS valid"); 72 } 73} 74 75void test_no_route(int fd) 76{ 77 // bind to an interface that cannot deliver 78 char buf[IFNAMSIZ]; 79 socklen_t buflen = IFNAMSIZ; 80 memcpy(buf, "loop", 5); 81 82 auto setsockopt_maybe_error = Core::System::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, buflen); 83 if (setsockopt_maybe_error.is_error()) { 84 warnln("setsockopt(SO_BINDTODEVICE) :: no_route"); 85 puts("FAIL no_route"); 86 return; 87 } 88 sockaddr_in sin; 89 memset(&sin, 0, sizeof(sin)); 90 91 sin.sin_addr.s_addr = IPv4Address { 10, 0, 2, 15 }.to_u32(); 92 sin.sin_port = 8080; 93 sin.sin_family = AF_INET; 94 95 auto bind_maybe_error = Core::System::bind(fd, (sockaddr*)&sin, sizeof(sin)); 96 if (bind_maybe_error.is_error()) { 97 warnln("bind() :: no_route"); 98 puts("FAIL no_route"); 99 return; 100 } 101 102 auto sendto_maybe_error = Core::System::sendto(fd, "TEST", 4, 0, (sockaddr*)&sin, sizeof(sin)); 103 if (sendto_maybe_error.is_error()) { 104 warnln("sendto() :: no_route (Should fail with EHOSTUNREACH)"); 105 puts("PASS no_route"); 106 } else 107 puts("FAIL no_route"); 108} 109 110void test_send(int fd) 111{ 112 // bind to an interface that cannot deliver 113 char buf[IFNAMSIZ]; 114 socklen_t buflen = IFNAMSIZ; 115 // FIXME: Look up the proper device name instead of hard-coding it 116 memcpy(buf, "ep0s7", 6); 117 118 auto setsockopt_maybe_error = Core::System::setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, buf, buflen); 119 if (setsockopt_maybe_error.is_error()) { 120 warnln("setsockopt(SO_BINDTODEVICE) :: send"); 121 puts("FAIL send"); 122 return; 123 } 124 sockaddr_in sin; 125 memset(&sin, 0, sizeof(sin)); 126 127 sin.sin_addr.s_addr = IPv4Address { 10, 0, 2, 15 }.to_u32(); 128 sin.sin_port = 8080; 129 sin.sin_family = AF_INET; 130 131 auto bind_maybe_error = Core::System::bind(fd, (sockaddr*)&sin, sizeof(sin)); 132 if (bind_maybe_error.is_error()) { 133 warnln("bind() :: send"); 134 puts("FAIL send"); 135 return; 136 } 137 138 auto sendto_maybe_error = Core::System::sendto(fd, "TEST", 4, 0, (sockaddr*)&sin, sizeof(sin)); 139 if (sendto_maybe_error.is_error()) { 140 warnln("sendto() :: send"); 141 puts("FAIL send"); 142 return; 143 } 144 puts("PASS send"); 145}