summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-12-13 00:20:34 +0300
committerOxore <oxore@protonmail.com>2023-12-13 00:20:34 +0300
commit574ef210268681aab4c6729cb7556793d89f4b5a (patch)
treebfc3fd171a84bcb6572e6b628986e6c0e668ad5c
parent17c01af9dea19ab9e553ef0db775e43f74a752e5 (diff)
Impl ip addr parser
-rw-r--r--client.c75
1 files 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 <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(