int main(int argc, char *argv[]) { struct ovs_cmdl_context ctx = { .argc = 0, }; set_program_name(argv[0]); vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_EMER); parse_options(argc, argv); ctx.argc = argc - optind; ctx.argv = argv + optind; ovs_cmdl_run_command(&ctx, get_all_commands()); return 0; } static void parse_target(const char *s_, struct in_addr *addr, unsigned short int *min, unsigned short int *max) { char *s = xstrdup(s_); char *colon; int error; colon = strchr(s, ':'); if (colon) { *colon = '\0'; } if (*s != '\0') { error = lookup_hostname(s, addr); if (error) { ovs_fatal(error, "failed to look up IP address for \"%s\"", s_); } } else { addr->s_addr = htonl(INADDR_ANY); } *min = *max = 0; if (colon && colon[1] != '\0') { const char *ports = colon + 1; if (ovs_scan(ports, "%hu-%hu", min, max)) { if (*min > *max) { ovs_fatal(0, "%s: minimum is greater than maximum", s_); } } else if (ovs_scan(ports, "%hu", min)) { *max = *min; } else { ovs_fatal(0, "%s: number or range expected", s_); } } free(s); }
/* Parses 'str' as an Ethernet address into 'mac'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT str_to_mac(const char *str, struct eth_addr *mac) { if (!ovs_scan(str, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(*mac))) { return xasprintf("invalid mac address %s", str); } return NULL; }
/* Returns true if specified address specifies a dynamic address, * supporting the following formats: * * "dynamic": * Both MAC and IP are to be allocated dynamically. * * "xx:xx:xx:xx:xx:xx dynamic": * Use specified MAC address, but allocate an IP address * dynamically. */ bool is_dynamic_lsp_address(const char *address) { struct eth_addr ea; int n; return (!strcmp(address, "dynamic") || (ovs_scan(address, ETH_ADDR_SCAN_FMT" dynamic%n", ETH_ADDR_SCAN_ARGS(ea), &n) && address[n] == '\0')); }
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; }