/* Extracts the mac, IPv4 and IPv6 addresses from the * "nbrec_logical_router_port" parameter 'lrp'. Stores the IPv4 and * IPv6 addresses in the 'ipv4_addrs' and 'ipv6_addrs' fields of * 'laddrs', respectively. In addition, a link local IPv6 address * based on the 'mac' member of 'lrp' is added to the 'ipv6_addrs' * field. * * Return true if a valid 'mac' address is found in 'lrp', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_lrp_networks(const struct nbrec_logical_router_port *lrp, struct lport_addresses *laddrs) { memset(laddrs, 0, sizeof *laddrs); if (!eth_addr_from_string(lrp->mac, &laddrs->ea)) { laddrs->ea = eth_addr_zero; return false; } snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs->ea)); for (int i = 0; i < lrp->n_networks; i++) { ovs_be32 ip4; struct in6_addr ip6; unsigned int plen; char *error; error = ip_parse_cidr(lrp->networks[i], &ip4, &plen); if (!error) { if (!ip4 || plen == 32) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); continue; } add_ipv4_netaddr(laddrs, ip4, plen); continue; } free(error); error = ipv6_parse_cidr(lrp->networks[i], &ip6, &plen); if (!error) { if (plen == 128) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 1); VLOG_WARN_RL(&rl, "bad 'networks' %s", lrp->networks[i]); continue; } add_ipv6_netaddr(laddrs, ip6, plen); } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_INFO_RL(&rl, "invalid syntax '%s' in networks", lrp->networks[i]); free(error); } } /* Always add the IPv6 link local address. */ struct in6_addr lla; in6_generate_lla(laddrs->ea, &lla); add_ipv6_netaddr(laddrs, lla, 64); return true; }
/* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which * should be of the format "MAC [IP1 IP2 ..] .." where IPn should be a * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and * 'ipv6_addrs' fields of 'laddrs'. There may be additional content in * 'address' after "MAC [IP1 IP2 .. ]". The value of 'ofs' that is * returned indicates the offset where that additional content begins. * * Returns true if at least 'MAC' is found in 'address', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_addresses(const char *address, struct lport_addresses *laddrs, int *ofs) { memset(laddrs, 0, sizeof *laddrs); const char *buf = address; const char *const start = buf; int buf_index = 0; const char *buf_end = buf + strlen(address); if (!ovs_scan_len(buf, &buf_index, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(laddrs->ea))) { laddrs->ea = eth_addr_zero; *ofs = 0; return false; } snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs->ea)); ovs_be32 ip4; struct in6_addr ip6; unsigned int plen; char *error; /* Loop through the buffer and extract the IPv4/IPv6 addresses * and store in the 'laddrs'. Break the loop if invalid data is found. */ buf += buf_index; while (buf < buf_end) { buf_index = 0; error = ip_parse_cidr_len(buf, &buf_index, &ip4, &plen); if (!error) { add_ipv4_netaddr(laddrs, ip4, plen); buf += buf_index; continue; } free(error); error = ipv6_parse_cidr_len(buf, &buf_index, &ip6, &plen); if (!error) { add_ipv6_netaddr(laddrs, ip6, plen); } else { free(error); break; } buf += buf_index; } *ofs = buf - start; return true; }
/* Extracts the mac, IPv4 and IPv6 addresses from * 'address' which * should be of the format 'MAC [IP1 IP2 ..]" where IPn should be a * valid IPv4 or IPv6 address and stores them in the 'ipv4_addrs' and * 'ipv6_addrs' fields of 'laddrs'. * * Return true if at least 'MAC' is found in 'address', false otherwise. * * The caller must call destroy_lport_addresses(). */ bool extract_lsp_addresses(const char *address, struct lport_addresses *laddrs) { memset(laddrs, 0, sizeof *laddrs); const char *buf = address; int buf_index = 0; const char *buf_end = buf + strlen(address); if (!ovs_scan_len(buf, &buf_index, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(laddrs->ea))) { laddrs->ea = eth_addr_zero; return false; } snprintf(laddrs->ea_s, sizeof laddrs->ea_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(laddrs->ea)); ovs_be32 ip4; struct in6_addr ip6; unsigned int plen; char *error; /* Loop through the buffer and extract the IPv4/IPv6 addresses * and store in the 'laddrs'. Break the loop if invalid data is found. */ buf += buf_index; while (buf < buf_end) { buf_index = 0; error = ip_parse_cidr_len(buf, &buf_index, &ip4, &plen); if (!error) { add_ipv4_netaddr(laddrs, ip4, plen); buf += buf_index; continue; } free(error); error = ipv6_parse_cidr_len(buf, &buf_index, &ip6, &plen); if (!error) { add_ipv6_netaddr(laddrs, ip6, plen); } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); VLOG_INFO_RL(&rl, "invalid syntax '%s' in address", address); free(error); break; } buf += buf_index; } return true; }