// Initially based on https://stackoverflow.com/a/35570418 #include #include #include #include #include #include #include #include #include static unsigned char udp_buffer[UINT16_MAX]; static inline bool IsDigit(char c) { return c >= '0' && c <= '9'; } static uint32_t ParseAddress(char const *str, FILE *log_stream) { uint32_t addr = 0; unsigned 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 specified\n"); return 1; } int const fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) { perror("socket failed"); return 1; } struct sockaddr_in const serveraddr = { .sin_family = AF_INET, .sin_port = htons(port), .sin_addr.s_addr = htonl(addr), }; ssize_t const ret = sendto( fd, "\x2a", 1, 0, (struct sockaddr const *)&serveraddr, sizeof(serveraddr)); if (ret < 0) { perror("sendto failed"); return 1; } printf("message sent\n"); struct sockaddr_in source_address; socklen_t source_address_len = sizeof(source_address); int const length = recvfrom( fd, udp_buffer, sizeof(udp_buffer) - 1, 0, (struct sockaddr*)&source_address, &source_address_len); (void) length; uint32_t const addr2 = ntohl(source_address.sin_addr.s_addr); uint8_t const a0 = addr2 >> 24; uint8_t const a1 = addr2 >> 16; uint8_t const a2 = addr2 >> 8; uint8_t const a3 = addr2; uint16_t const port2 = ntohs(source_address.sin_port); printf("Received: %u from %u.%u.%u.%u:%u\n", udp_buffer[0], a0, a1, a2, a3, port2); close(fd); }