From 574ef210268681aab4c6729cb7556793d89f4b5a Mon Sep 17 00:00:00 2001 From: Oxore Date: Wed, 13 Dec 2023 00:20:34 +0300 Subject: Impl ip addr parser --- client.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 3 deletions(-) diff --git a/client.c b/client.c index c5491f6..007bf2d 100644 --- a/client.c +++ b/client.c @@ -1,13 +1,82 @@ // Initially based on https://stackoverflow.com/a/35570418 #include +#include +#include #include +#include #include #include #include -int main(void) +static inline bool IsDigit(char c) { return c >= '0' && c <= '9'; } + +static unsigned ParseAddress(char const *str, FILE *log_stream) +{ + unsigned addr = 0, byte_counter = 0, byte = 0, digits_counter = 0; + for (size_t i = 0;; i++) { + char const c = str[i]; + if (c == '\0') { + if (byte_counter != 3) { + fprintf(log_stream, "Invalid address specified: %u bytes of 4 expected are specified\n", byte_counter + 1); + return INADDR_NONE; + } + if (digits_counter == 0) { + fprintf(log_stream, "Invalid address specified: no digits on byte %u\n", byte_counter + 1); + return INADDR_NONE; + } + addr |= byte << (8 * (3 - byte_counter)); + break; + } else if (IsDigit(c)) { + digits_counter++; + if (digits_counter > 3) { + fprintf(log_stream, "Invalid address specified: too many digits for byte %u\n", byte_counter + 1); + return INADDR_NONE; + } + byte = byte * 10 + (c - '0'); + if (byte > UINT8_MAX) { + fprintf(log_stream, "Invalid address specified: too big number for byte %u\n", byte_counter + 1); + return INADDR_NONE; + } + } else if (c == '.') { + if (digits_counter == 0) { + fprintf(log_stream, "Invalid address specified: no digits on byte %u\n", byte_counter + 1); + return INADDR_NONE; + } + digits_counter = 0; + addr |= byte << (8 * (3 - byte_counter)); + byte = 0; + byte_counter++; + if (byte_counter > 3) { + fprintf(log_stream, "Invalid address specified: unexpected dot after 4th byte\n"); + return INADDR_NONE; + } + } else { + fprintf(log_stream, "Invalid address specified: char '%c' (0x%02x) is not allowed\n", c, c); + return INADDR_NONE; + } + } + if (addr == INADDR_NONE) { + fprintf(log_stream, "Invalid address specified\n"); + } + return addr; +} + +int main(int const argc, char *const argv[]) { + if (argc < 3) { + fprintf(stderr, "Usage: %s
\n", argv[0]); + return 1; + } + unsigned const addr = ParseAddress(argv[1], stderr); + if (addr == INADDR_NONE) { + return 1; + } + int const port = atoi(argv[2]); + if (port <= 0 || port > UINT16_MAX) { + fprintf(stderr, "Invalid port specifed\n"); + return 1; + } int const fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket failed"); @@ -15,8 +84,8 @@ int main(void) } struct sockaddr_in const serveraddr = { .sin_family = AF_INET, - .sin_port = htons(50037u), - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + .sin_port = htons(port), + .sin_addr.s_addr = htonl(addr), }; for (int i = 0; i < 4; i++) { ssize_t const ret = sendto( -- cgit v1.2.3