diff options
author | Oxore <oxore@protonmail.com> | 2023-12-13 00:20:34 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-12-13 00:20:34 +0300 |
commit | 574ef210268681aab4c6729cb7556793d89f4b5a (patch) | |
tree | bfc3fd171a84bcb6572e6b628986e6c0e668ad5c | |
parent | 17c01af9dea19ab9e553ef0db775e43f74a752e5 (diff) |
Impl ip addr parser
-rw-r--r-- | client.c | 75 |
1 files changed, 72 insertions, 3 deletions
@@ -1,13 +1,82 @@ // Initially based on https://stackoverflow.com/a/35570418 #include <netinet/in.h> +#include <stdbool.h> +#include <stdint.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <unistd.h> -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 <address> <port>\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( |