diff options
author | sr | 2012-09-03 21:00:26 +0200 |
---|---|---|
committer | sr | 2012-09-03 21:00:26 +0200 |
commit | 60b2ba6ef9ed779d750958b6422f05c93a4a2d91 (patch) | |
tree | 46fdacf6a9439947e91af4c3d9de3006d41e5380 /src/server/helper.c | |
parent | [*] Fixed and unified formatting (diff) | |
download | dnbd3-60b2ba6ef9ed779d750958b6422f05c93a4a2d91.tar.gz dnbd3-60b2ba6ef9ed779d750958b6422f05c93a4a2d91.tar.xz dnbd3-60b2ba6ef9ed779d750958b6422f05c93a4a2d91.zip |
[SERVER] Check which dnbd3 devices are idle and ready to use for proxy mode
[SERVER] Skeleton of server-to-server communication
[SERVER] Update access-time of images in use by actual clients
[*] Add dnbd3_host_t type to handle address+port+addrtype consistently across the project
Diffstat (limited to 'src/server/helper.c')
-rw-r--r-- | src/server/helper.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/server/helper.c b/src/server/helper.c new file mode 100644 index 0000000..293fa36 --- /dev/null +++ b/src/server/helper.c @@ -0,0 +1,162 @@ +#include "helper.h" +#include <arpa/inet.h> +#include <string.h> +#include <stdlib.h> +#include <glib/gmacros.h> +#include "../config.h" + +/** + * Parse IPv4 or IPv6 address in string representation to a suitable format usable by the BSD socket library + * @string eg. "1.2.3.4" or "2a01::10:5", optially with port appended, eg "1.2.3.4:6666" or "[2a01::10:5]:6666" + * @af will contain either AF_INET or AF_INET6 + * @addr will contain the address in network representation + * @port will contain the port in network representation, defaulting to #define PORT if none was given + * returns 1 on success, 0 in failure. contents of af, addr and port are undefined in the latter case + * !! Contents of @string might be modified by this function !! + */ +char parse_address(char *string, dnbd3_host_t *host) +{ + struct in_addr v4; + struct in6_addr v6; + + // Try IPv4 without port + if (1 == inet_pton(AF_INET, string, &v4)) + { + host->type = AF_INET; + memcpy(host->addr, &v4, 4); + host->port = htons(PORT); + return 1; + } + // Try IPv6 without port + if (1 == inet_pton(AF_INET6, string, &v6)) + { + host->type = AF_INET6; + memcpy(host->addr, &v6, 16); + host->port = htons(PORT); + return 1; + } + + // Scan for port + char *portpos = NULL, *ptr = string; + while (*ptr) + { + if (*ptr == ':') + portpos = ptr; + ++ptr; + } + if (portpos == NULL) + return 0; // No port in string + // Consider IP being surrounded by [ ] + if (*string == '[' && *(portpos - 1) == ']') + { + ++string; + *(portpos - 1) = '\0'; + } + *portpos++ = '\0'; + int p = atoi(portpos); + if (p < 1 || p > 65535) + return 0; // Invalid port + host->port = htons((uint16_t)p); + + // Try IPv4 with port + if (1 == inet_pton(AF_INET, string, &v4)) + { + host->type = AF_INET; + memcpy(host->addr, &v4, 4); + return 1; + } + // Try IPv6 with port + if (1 == inet_pton(AF_INET6, string, &v6)) + { + host->type = AF_INET6; + memcpy(host->addr, &v6, 16); + return 1; + } + + // FAIL + return 0; +} + +/** + * Convert a host and port (network byte order) to printable representation. + * Worst case required buffer len is 48, eg. [1234:1234:1234:1234:1234:1234:1234:1234]:12345 (+ \0) + * Returns TRUE on success, FALSE on error + */ +char host_to_string(const dnbd3_host_t *host, char *target, size_t targetlen) +{ + // Worst case: Port 5 chars, ':' to separate ip and port 1 char, terminating null 1 char = 7, [] for IPv6 + if (targetlen < 10) + return FALSE; + if (host->type == AF_INET6) + { + *target++ = '['; + inet_ntop(AF_INET6, host->addr, target, targetlen - 9); + target += strlen(target); + *target++ = ']'; + } + else if (host->type == AF_INET) + { + inet_ntop(AF_INET, host->addr, target, targetlen - 7); + target += strlen(target); + } + else + { + snprintf(target, targetlen, "<?addrtype=%d>", (int)host->type); + return FALSE; + } + *target = '\0'; + if (host->port != 0) + { + // There are still at least 7 bytes left in the buffer, port is at most 5 bytes + ':' + '\0' = 7 + snprintf(target, 7, ":%d", (int)ntohs(host->port)); + } + return TRUE; +} + +char is_valid_namespace(char *namespace) +{ + if (*namespace == '\0' || *namespace == '/') + return 0; // Invalid: Length = 0 or starting with a slash + while (*namespace) + { + if (*namespace != '/' && *namespace != '-' && (*namespace < 'a' || *namespace > 'z') + && (*namespace < 'A' || *namespace > 'Z') + && (*namespace < '0' || *namespace > '9')) + return 0; + ++namespace; + } + if (strstr(namespace, "//") != NULL) + return 0; // Invalid: Double slash + if (*(namespace - 1) == '/') + return 0; // Invalid: Ends in a slash + return 1; +} + +char is_valid_imagename(char *namespace) +{ + if (*namespace == '\0' || *namespace == ' ') + return 0; // Invalid: Length = 0 or starting with a space + while (*namespace) + { + // Check for invalid chars + if (*namespace != '.' && *namespace != '-' && *namespace != ' ' + && *namespace != '(' && *namespace != ')' + && (*namespace < 'a' || *namespace > 'z') && (*namespace < 'A' || *namespace > 'Z') + && (*namespace < '0' || *namespace > '9')) + return 0; + ++namespace; + } + if (*(namespace - 1) == ' ') + return 0; // Invalid: Ends in a space + return 1; +} + +void strtolower(char *string) +{ + while (*string) + { + if (*string >= 'A' && *string <= 'Z') + *string += 32; + ++string; + } +} |