#include <arpa/inet.h>
#include <netinet/in.h>
#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include <libloc/address.h>
else
return __loc_address6_str(address, buffer, LOC_ADDRESS_BUFFER_LENGTH);
}
+
+static void loc_address_from_address4(struct in6_addr* address,
+ const struct in_addr* address4) {
+ address->s6_addr32[0] = 0;
+ address->s6_addr32[1] = 0;
+ address->s6_addr32[2] = htonl(0xffff);
+ address->s6_addr32[3] = address4->s_addr;
+}
+
+int loc_address_parse(struct in6_addr* address, unsigned int* prefix, const char* string) {
+ char buffer[INET6_ADDRSTRLEN + 4];
+ int r;
+
+ if (!address || !string) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Copy the string into the buffer
+ r = snprintf(buffer, sizeof(buffer) - 1, "%s", string);
+ if (r < 0)
+ return 1;
+
+ // Find /
+ char* p = strchr(buffer, '/');
+ if (p) {
+ // Terminate the IP address
+ *p++ = '\0';
+ }
+
+ int family = AF_UNSPEC;
+
+ // Try parsing as an IPv6 address
+ r = inet_pton(AF_INET6, buffer, address);
+ switch (r) {
+ // This is not a valid IPv6 address
+ case 0:
+ break;
+
+ // This is a valid IPv6 address
+ case 1:
+ family = AF_INET6;
+ break;
+
+ // Unexpected error
+ default:
+ return 1;
+ }
+
+ // Try parsing as an IPv4 address
+ if (!family) {
+ struct in_addr address4;
+
+ r = inet_pton(AF_INET, buffer, &address4);
+ switch (r) {
+ // This was not a valid IPv4 address
+ case 0:
+ break;
+
+ // This was a valid IPv4 address
+ case 1:
+ family = AF_INET;
+
+ // Copy the result
+ loc_address_from_address4(address, &address4);
+ break;
+
+ // Unexpected error
+ default:
+ return 1;
+ }
+ }
+
+ // Invalid input
+ if (family == AF_UNSPEC) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ // Did the user request a prefix?
+ if (prefix) {
+ // Set the prefix to the default value
+ *prefix = loc_address_family_bit_length(family);
+
+ // Parse the actual string
+ if (p)
+ *prefix = strtol(p, NULL, 10);
+ }
+
+ return 0;
+}
const char* string, struct loc_network** network) {
struct in6_addr address;
- int r = loc_parse_address(db->ctx, string, &address);
+ int r = loc_address_parse(&address, NULL, string);
if (r)
return r;
LOC_EXPORT void loc_set_log_priority(struct loc_ctx* ctx, int priority) {
ctx->log_priority = priority;
}
-
-LOC_EXPORT int loc_parse_address(struct loc_ctx* ctx, const char* string, struct in6_addr* address) {
- DEBUG(ctx, "Parsing IP address %s\n", string);
-
- // Try parsing this as an IPv6 address
- int r = inet_pton(AF_INET6, string, address);
-
- // If inet_pton returns one it has been successful
- if (r == 1) {
- DEBUG(ctx, "%s is an IPv6 address\n", string);
- return 0;
- }
-
- // Try parsing this as an IPv4 address
- struct in_addr ipv4_address;
- r = inet_pton(AF_INET, string, &ipv4_address);
- if (r == 1) {
- DEBUG(ctx, "%s is an IPv4 address\n", string);
-
- // Convert to IPv6-mapped address
- address->s6_addr32[0] = htonl(0x0000);
- address->s6_addr32[1] = htonl(0x0000);
- address->s6_addr32[2] = htonl(0xffff);
- address->s6_addr32[3] = ipv4_address.s_addr;
-
- return 0;
- }
-
- DEBUG(ctx, "%s is not an valid IP address\n", string);
- return -EINVAL;
-}
*/
const char* loc_address_str(const struct in6_addr* address);
+int loc_address_parse(struct in6_addr* address, unsigned int* prefix, const char* string);
static inline int loc_address_family(const struct in6_addr* address) {
if (IN6_IS_ADDR_V4MAPPED(address))
int loc_get_log_priority(struct loc_ctx* ctx);
void loc_set_log_priority(struct loc_ctx* ctx, int priority);
-#ifdef LIBLOC_PRIVATE
-int loc_parse_address(struct loc_ctx* ctx, const char* string, struct in6_addr* address);
-#endif
-
#ifdef __cplusplus
} /* extern "C" */
#endif
struct in6_addr* address, unsigned int prefix) {
// Validate the prefix
if (!loc_address_valid_prefix(address, prefix)) {
- ERROR(ctx, "Invalid prefix: %u\n", prefix);
+ ERROR(ctx, "Invalid prefix in %s: %u\n", loc_address_str(address), prefix);
errno = EINVAL;
return 1;
}
return 0;
}
-LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx, struct loc_network** network,
- const char* address_string) {
- struct in6_addr first_address;
- char* prefix_string;
- unsigned int prefix = 128;
- int r = -EINVAL;
-
- DEBUG(ctx, "Attempting to parse network %s\n", address_string);
-
- // Make a copy of the string to work on it
- char* buffer = strdup(address_string);
- address_string = prefix_string = buffer;
-
- // Split address and prefix
- address_string = strsep(&prefix_string, "/");
-
- DEBUG(ctx, " Split into address = %s, prefix = %s\n", address_string, prefix_string);
+LOC_EXPORT int loc_network_new_from_string(struct loc_ctx* ctx,
+ struct loc_network** network, const char* string) {
+ struct in6_addr address;
+ unsigned int prefix;
- // Parse the address
- r = loc_parse_address(ctx, address_string, &first_address);
+ // Parse the input
+ int r = loc_address_parse(&address, &prefix, string);
if (r) {
- DEBUG(ctx, "The address could not be parsed\n");
- goto FAIL;
- }
-
- // If a prefix was given, we will try to parse it
- if (prefix_string) {
- // Convert prefix to integer
- prefix = strtol(prefix_string, NULL, 10);
-
- if (!prefix) {
- DEBUG(ctx, "The prefix was not parsable: %s\n", prefix_string);
- goto FAIL;
- }
- }
-
-FAIL:
- // Free temporary buffer
- free(buffer);
-
- // Exit if the parsing was unsuccessful
- if (r)
+ ERROR(ctx, "Could not parse network %s: %m\n", string);
return r;
+ }
// Create a new network
- return loc_network_new(ctx, network, &first_address, prefix);
+ return loc_network_new(ctx, network, &address, prefix);
}
LOC_EXPORT struct loc_network* loc_network_ref(struct loc_network* network) {
// Try adding an invalid network
struct loc_network* network;
err = loc_writer_add_network(writer, &network, "xxxx:xxxx::/32");
- if (err != -EINVAL) {
+ if (!err) {
fprintf(stderr, "It was possible to add an invalid network (err = %d)\n", err);
exit(EXIT_FAILURE);
}