/* Calculate final configuration values needed for IPv6 */ static void finalize_ipv6_config(struct config *config) { set_ipv6_defaults(config); config->live_local_ip = ipv6_parse(config->live_local_ip_string); config->live_remote_ip = ipv6_parse(config->live_remote_ip_string); config->live_prefix_len = DEFAULT_V6_LIVE_PREFIX_LEN; config->live_gateway_ip = ipv6_parse(config->live_gateway_ip_string); config->live_bind_ip = ipv6_parse("::"); config->live_connect_ip = config->live_remote_ip; config->socket_domain = AF_INET6; config->wire_protocol = AF_INET6; }
static bool parse_sockaddr_components(struct sockaddr_storage *ss, const char *host_s, const char *port_s, uint16_t default_port, const char *s) { struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *, ss); int port; if (port_s && port_s[0]) { if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) { VLOG_ERR("%s: bad port number \"%s\"", s, port_s); } } else { port = default_port; } memset(ss, 0, sizeof *ss); if (strchr(host_s, ':')) { struct sockaddr_in6 *sin6 = ALIGNED_CAST(struct sockaddr_in6 *, ss); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(port); if (!ipv6_parse(host_s, &sin6->sin6_addr)) { VLOG_ERR("%s: bad IPv6 address \"%s\"", s, host_s); goto exit; } } else {
/* * Convert ip v6 presentation to binary and set network mask if CIDR notation is present * * @return number of bits in the network mask, 128 if no CIDR mask is present */ int ipv6_pton(const char * p, struct in6_addr * n) { char * e = strchr(p, '/'); if (e) { char * endp; uint64_t bits64 = strtoul(e + 1, &endp, 10); if (e + 1 == endp) return -1; /* digits not present */ if (* endp) return -1; /* junk after digits */ if (128 < bits64) return -1; /* out of range */ if (ipv6_parse_section(p, e - p, n)) { ipv6_set_mask(n, (int)bits64); return (int)bits64; } } else { if (ipv6_parse(p, n)) { return 128; /* no CIDR notation */ } } return -1; /* ip v6 part fails */ }
/* Translates 'host_name', which must be a string representation of an IPv6 * address, into a numeric IPv6 address in '*addr'. Returns 0 if successful, * otherwise a positive errno value. */ int lookup_ipv6(const char *host_name, struct in6_addr *addr) { if (!ipv6_parse(host_name, addr)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "\"%s\" is not a valid IPv6 address", host_name); return ENOENT; } return 0; }
/* * IPV6 presentation parser for a subsection of a string specified by length * * @return AM_TRUE if the section of a string can be parsed as an ip v6 presentation */ static am_bool_t ipv6_parse_section(const char * p, size_t length, struct in6_addr * n) { am_bool_t output; char * a = strndup(p, length); if (a) { output = ipv6_parse(a, n); free(a); } else { output = AM_FALSE; } return output; }
/* Calculate final configuration values needed for ipv4-mapped-ipv6 */ static void finalize_ipv4_mapped_ipv6_config(struct config *config) { set_ipv4_defaults(config); config->live_local_ip = ipv4_parse(config->live_local_ip_string); config->live_remote_ip = ipv4_parse(config->live_remote_ip_string); config->live_prefix_len = netmask_to_prefix(config->live_netmask_ip_string); config->live_gateway_ip = ipv4_parse(config->live_gateway_ip_string); config->live_bind_ip = ipv6_parse("::"); config->live_connect_ip = ipv6_map_from_ipv4(config->live_remote_ip); config->socket_domain = AF_INET6; config->wire_protocol = AF_INET; }
static bool parse_sockaddr_components(struct sockaddr_storage *ss, char *host_s, const char *port_s, uint16_t default_port, const char *s) { struct sockaddr_in *sin = ALIGNED_CAST(struct sockaddr_in *, ss); int port; if (port_s && port_s[0]) { if (!str_to_int(port_s, 10, &port) || port < 0 || port > 65535) { VLOG_ERR("%s: bad port number \"%s\"", s, port_s); goto exit; } } else { port = default_port; } memset(ss, 0, sizeof *ss); if (host_s && strchr(host_s, ':')) { struct sockaddr_in6 *sin6 = ALIGNED_CAST(struct sockaddr_in6 *, ss); char *addr = strsep(&host_s, "%"); sin6->sin6_family = AF_INET6; sin6->sin6_port = htons(port); if (!addr || !*addr || !ipv6_parse(addr, &sin6->sin6_addr)) { VLOG_ERR("%s: bad IPv6 address \"%s\"", s, addr ? addr : ""); goto exit; } #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID char *scope = strsep(&host_s, "%"); if (scope && *scope) { if (!scope[strspn(scope, "0123456789")]) { sin6->sin6_scope_id = atoi(scope); } else { sin6->sin6_scope_id = if_nametoindex(scope); if (!sin6->sin6_scope_id) { VLOG_ERR("%s: bad IPv6 scope \"%s\" (%s)", s, scope, ovs_strerror(errno)); goto exit; } } } #endif } else {
/* Extracts and returns the server name from 'suffix'. The caller must * eventually free it. * * Returns NULL if there is no server name, and particularly if it is an IP * address rather than a host name, since RFC 3546 is explicit that IP * addresses are unsuitable as server name indication (SNI). */ static char * get_server_name(const char *suffix_) { char *suffix = xstrdup(suffix_); char *host, *port; inet_parse_host_port_tokens(suffix, &host, &port); ovs_be32 ipv4; struct in6_addr ipv6; char *server_name = (ip_parse(host, &ipv4) || ipv6_parse(host, &ipv6) ? NULL : xstrdup(host)); free(suffix); return server_name; }
static const char * lex_parse_integer__(const char *p, struct lex_token *token) { lex_token_init(token); token->type = LEX_T_INTEGER; memset(&token->value, 0, sizeof token->value); const char *start = p; const char *end = start; while (isalnum((unsigned char) *end) || *end == ':' || (*end == '.' && end[1] != '.')) { end++; } size_t len = end - start; int n; struct eth_addr mac; if (!len) { lex_error(token, "Integer constant expected."); } else if (len == 17 && ovs_scan(start, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(mac), &n) && n == len) { token->value.mac = mac; token->format = LEX_F_ETHERNET; } else if (start + strspn(start, "0123456789") == end) { if (p[0] == '0' && len > 1) { lex_error(token, "Decimal constants must not have leading zeros."); } else { unsigned long long int integer; char *tail; errno = 0; integer = strtoull(p, &tail, 10); if (tail != end || errno == ERANGE) { lex_error(token, "Decimal constants must be less than 2**64."); } else { token->value.integer = htonll(integer); token->format = LEX_F_DECIMAL; } } } else if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { if (len > 2) { lex_parse_hex_integer(start + 2, len - 2, token); } else { lex_error(token, "Hex digits expected following 0%c.", p[1]); } } else if (len < INET6_ADDRSTRLEN) { char copy[INET6_ADDRSTRLEN]; memcpy(copy, p, len); copy[len] = '\0'; if (ip_parse(copy, &token->value.ipv4)) { token->format = LEX_F_IPV4; } else if (ipv6_parse(copy, &token->value.ipv6)) { token->format = LEX_F_IPV6; } else { lex_error(token, "Invalid numeric constant."); } } else { lex_error(token, "Invalid numeric constant."); } ovs_assert(token->type == LEX_T_INTEGER || token->type == LEX_T_ERROR); return end; }
static const char * lex_parse_integer__(const char *p, struct lex_token *token) { lex_token_init(token); token->type = LEX_T_INTEGER; memset(&token->value, 0, sizeof token->value); /* Find the extent of an "integer" token, which can be in decimal or * hexadecimal, or an Ethernet address or IPv4 or IPv6 address, as 'start' * through 'end'. * * Special cases we handle here are: * * - The ellipsis token "..", used as e.g. 123..456. A doubled dot * is never valid syntax as part of an "integer", so we stop if * we encounter two dots in a row. * * - Syntax like 1.2.3.4:1234 to indicate an IPv4 address followed by a * port number should be considered three tokens: 1.2.3.4 : 1234. * The obvious approach is to allow just dots or just colons within a * given integer, but that would disallow IPv4-mapped IPv6 addresses, * e.g. ::ffff:192.0.2.128. However, even in those addresses, a * colon never follows a dot, so we stop if we encounter a colon * after a dot. * * (There is no corresponding way to parse an IPv6 address followed * by a port number: ::1:2:3:4:1234 is unavoidably ambiguous.) */ const char *start = p; const char *end = start; bool saw_dot = false; while (isalnum((unsigned char) *end) || (*end == ':' && !saw_dot) || (*end == '.' && end[1] != '.')) { if (*end == '.') { saw_dot = true; } end++; } size_t len = end - start; int n; struct eth_addr mac; if (!len) { lex_error(token, "Integer constant expected."); } else if (len == 17 && ovs_scan(start, ETH_ADDR_SCAN_FMT"%n", ETH_ADDR_SCAN_ARGS(mac), &n) && n == len) { token->value.mac = mac; token->format = LEX_F_ETHERNET; } else if (start + strspn(start, "0123456789") == end) { if (p[0] == '0' && len > 1) { lex_error(token, "Decimal constants must not have leading zeros."); } else { unsigned long long int integer; char *tail; errno = 0; integer = strtoull(p, &tail, 10); if (tail != end || errno == ERANGE) { lex_error(token, "Decimal constants must be less than 2**64."); } else { token->value.integer = htonll(integer); token->format = LEX_F_DECIMAL; } } } else if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) { if (len > 2) { lex_parse_hex_integer(start + 2, len - 2, token); } else { lex_error(token, "Hex digits expected following 0%c.", p[1]); } } else if (len < INET6_ADDRSTRLEN) { char copy[INET6_ADDRSTRLEN]; memcpy(copy, p, len); copy[len] = '\0'; if (ip_parse(copy, &token->value.ipv4)) { token->format = LEX_F_IPV4; } else if (ipv6_parse(copy, &token->value.ipv6)) { token->format = LEX_F_IPV6; } else { lex_error(token, "Invalid numeric constant."); } } else { lex_error(token, "Invalid numeric constant."); } ovs_assert(token->type == LEX_T_INTEGER || token->type == LEX_T_ERROR); return end; }