summaryrefslogtreecommitdiffstats
path: root/src/server/helper.c
diff options
context:
space:
mode:
authorsr2012-09-03 21:00:26 +0200
committersr2012-09-03 21:00:26 +0200
commit60b2ba6ef9ed779d750958b6422f05c93a4a2d91 (patch)
tree46fdacf6a9439947e91af4c3d9de3006d41e5380 /src/server/helper.c
parent[*] Fixed and unified formatting (diff)
downloaddnbd3-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.c162
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;
+ }
+}