Merge branch 'inet_get_addr' into net-next
Serhey Popovych says: ==================== It looks confusing to have multiple independent routines to get internet address from it's string representation: get_addr() and inet_get_addr(). Most complicated users of inet_get_addr() is iplink_geneve.c and iplink_vxlan.c because they required to handle both AF_INET and AF_INET6 for their local/remote endpoints. On the other hand get_addr() does not provide additional information like address type: need to address this. to get rid of current and possible future code duplications. Note that this functionality is first step to make proto independent handling of local/remote endpoints in ip/tunnel code (there will be additional series based on this one). Also fix get_addr_1() and get_prefix() to make sure it always provide correct ->family and ->bitlen. As always comments, suggestions and criticism are welcome. ==================== Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
commit
40cf5b0959
|
|
@ -54,7 +54,40 @@ typedef struct
|
|||
__u32 data[64];
|
||||
} inet_prefix;
|
||||
|
||||
#define PREFIXLEN_SPECIFIED 1
|
||||
enum {
|
||||
PREFIXLEN_SPECIFIED = (1 << 0),
|
||||
ADDRTYPE_INET = (1 << 1),
|
||||
ADDRTYPE_UNSPEC = (1 << 2),
|
||||
ADDRTYPE_MULTI = (1 << 3),
|
||||
|
||||
ADDRTYPE_INET_UNSPEC = ADDRTYPE_INET | ADDRTYPE_UNSPEC,
|
||||
ADDRTYPE_INET_MULTI = ADDRTYPE_INET | ADDRTYPE_MULTI
|
||||
};
|
||||
|
||||
static inline bool is_addrtype_inet(const inet_prefix *p)
|
||||
{
|
||||
return p->flags & ADDRTYPE_INET;
|
||||
}
|
||||
|
||||
static inline bool is_addrtype_inet_unspec(const inet_prefix *p)
|
||||
{
|
||||
return (p->flags & ADDRTYPE_INET_UNSPEC) == ADDRTYPE_INET_UNSPEC;
|
||||
}
|
||||
|
||||
static inline bool is_addrtype_inet_multi(const inet_prefix *p)
|
||||
{
|
||||
return (p->flags & ADDRTYPE_INET_MULTI) == ADDRTYPE_INET_MULTI;
|
||||
}
|
||||
|
||||
static inline bool is_addrtype_inet_not_unspec(const inet_prefix *p)
|
||||
{
|
||||
return (p->flags & ADDRTYPE_INET_UNSPEC) == ADDRTYPE_INET;
|
||||
}
|
||||
|
||||
static inline bool is_addrtype_inet_not_multi(const inet_prefix *p)
|
||||
{
|
||||
return (p->flags & ADDRTYPE_INET_MULTI) == ADDRTYPE_INET;
|
||||
}
|
||||
|
||||
#define DN_MAXADDL 20
|
||||
#ifndef AF_DECnet
|
||||
|
|
@ -236,7 +269,6 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n);
|
|||
extern int cmdlineno;
|
||||
ssize_t getcmdline(char **line, size_t *len, FILE *in);
|
||||
int makeargs(char *line, char *argv[], int maxargs);
|
||||
int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6);
|
||||
|
||||
struct iplink_req {
|
||||
struct nlmsghdr n;
|
||||
|
|
|
|||
|
|
@ -57,9 +57,8 @@ static void check_duparg(__u64 *attrs, int type, const char *key,
|
|||
static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
inet_prefix daddr;
|
||||
__u32 vni = 0;
|
||||
__u32 daddr = 0;
|
||||
struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
|
||||
__u32 label = 0;
|
||||
__u8 ttl = 0;
|
||||
__u8 tos = 0;
|
||||
|
|
@ -72,6 +71,8 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
bool set_op = (n->nlmsg_type == RTM_NEWLINK &&
|
||||
!(n->nlmsg_flags & NLM_F_CREATE));
|
||||
|
||||
daddr.flags = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
if (!matches(*argv, "id") ||
|
||||
!matches(*argv, "vni")) {
|
||||
|
|
@ -84,11 +85,8 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_GENEVE_REMOTE, "remote",
|
||||
*argv);
|
||||
if (!inet_get_addr(*argv, &daddr, &daddr6)) {
|
||||
fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
|
||||
get_addr(&daddr, *argv, AF_UNSPEC);
|
||||
if (!is_addrtype_inet_not_multi(&daddr))
|
||||
invarg("invalid remote address", *argv);
|
||||
} else if (!matches(*argv, "ttl") ||
|
||||
!matches(*argv, "hoplimit")) {
|
||||
|
|
@ -191,18 +189,17 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
* ID (VNI) to identify the geneve device, and we do not need
|
||||
* the remote IP.
|
||||
*/
|
||||
if (!set_op && !daddr && IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
|
||||
if (!set_op && !is_addrtype_inet(&daddr)) {
|
||||
fprintf(stderr, "geneve: remote link partner not specified\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
addattr32(n, 1024, IFLA_GENEVE_ID, vni);
|
||||
if (daddr)
|
||||
addattr_l(n, 1024, IFLA_GENEVE_REMOTE, &daddr, 4);
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
|
||||
addattr_l(n, 1024, IFLA_GENEVE_REMOTE6, &daddr6,
|
||||
sizeof(struct in6_addr));
|
||||
if (is_addrtype_inet(&daddr)) {
|
||||
int type = (daddr.family == AF_INET) ? IFLA_GENEVE_REMOTE :
|
||||
IFLA_GENEVE_REMOTE6;
|
||||
addattr_l(n, sizeof(1024), type, daddr.data, daddr.bytelen);
|
||||
}
|
||||
if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_LABEL))
|
||||
addattr32(n, 1024, IFLA_GENEVE_LABEL, label);
|
||||
|
|
|
|||
|
|
@ -74,11 +74,9 @@ static void check_duparg(__u64 *attrs, int type, const char *key,
|
|||
static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
||||
struct nlmsghdr *n)
|
||||
{
|
||||
inet_prefix saddr;
|
||||
inet_prefix daddr;
|
||||
__u32 vni = 0;
|
||||
__u32 gaddr = 0;
|
||||
__u32 daddr = 0;
|
||||
struct in6_addr gaddr6 = IN6ADDR_ANY_INIT;
|
||||
struct in6_addr daddr6 = IN6ADDR_ANY_INIT;
|
||||
__u8 learning = 1;
|
||||
__u16 dstport = 0;
|
||||
__u8 metadata = 0;
|
||||
|
|
@ -86,6 +84,9 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
bool set_op = (n->nlmsg_type == RTM_NEWLINK &&
|
||||
!(n->nlmsg_flags & NLM_F_CREATE));
|
||||
|
||||
saddr.family = daddr.family = AF_UNSPEC;
|
||||
saddr.flags = daddr.flags = 0;
|
||||
|
||||
while (argc > 0) {
|
||||
if (!matches(*argv, "id") ||
|
||||
!matches(*argv, "vni")) {
|
||||
|
|
@ -98,54 +99,33 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
vni >= 1u << 24)
|
||||
invarg("invalid id", *argv);
|
||||
} else if (!matches(*argv, "group")) {
|
||||
if (daddr || !IN6_IS_ADDR_UNSPECIFIED(&daddr6)) {
|
||||
if (is_addrtype_inet_not_multi(&daddr)) {
|
||||
fprintf(stderr, "vxlan: both group and remote");
|
||||
fprintf(stderr, " cannot be specified\n");
|
||||
return -1;
|
||||
}
|
||||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_VXLAN_GROUP, "group", *argv);
|
||||
if (!inet_get_addr(*argv, &gaddr, &gaddr6)) {
|
||||
fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr)))
|
||||
get_addr(&daddr, *argv, saddr.family);
|
||||
if (!is_addrtype_inet_multi(&daddr))
|
||||
invarg("invalid group address", *argv);
|
||||
} else if (!matches(*argv, "remote")) {
|
||||
if (gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) {
|
||||
if (is_addrtype_inet_multi(&daddr)) {
|
||||
fprintf(stderr, "vxlan: both group and remote");
|
||||
fprintf(stderr, " cannot be specified\n");
|
||||
return -1;
|
||||
}
|
||||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_VXLAN_GROUP, "remote", *argv);
|
||||
if (!inet_get_addr(*argv, &daddr, &daddr6)) {
|
||||
fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr)))
|
||||
get_addr(&daddr, *argv, saddr.family);
|
||||
if (!is_addrtype_inet_not_multi(&daddr))
|
||||
invarg("invalid remote address", *argv);
|
||||
} else if (!matches(*argv, "local")) {
|
||||
__u32 saddr = 0;
|
||||
struct in6_addr saddr6 = IN6ADDR_ANY_INIT;
|
||||
|
||||
NEXT_ARG();
|
||||
check_duparg(&attrs, IFLA_VXLAN_LOCAL, "local", *argv);
|
||||
if (strcmp(*argv, "any")) {
|
||||
if (!inet_get_addr(*argv, &saddr, &saddr6)) {
|
||||
fprintf(stderr, "Invalid address \"%s\"\n", *argv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6))
|
||||
get_addr(&saddr, *argv, daddr.family);
|
||||
if (!is_addrtype_inet_not_multi(&saddr))
|
||||
invarg("invalid local address", *argv);
|
||||
|
||||
if (saddr)
|
||||
addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4);
|
||||
else if (!IN6_IS_ADDR_UNSPECIFIED(&saddr6))
|
||||
addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6,
|
||||
sizeof(struct in6_addr));
|
||||
} else if (!matches(*argv, "dev")) {
|
||||
unsigned int link;
|
||||
|
||||
|
|
@ -350,7 +330,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if ((gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) &&
|
||||
if (is_addrtype_inet_multi(&daddr) &&
|
||||
!VXLAN_ATTRSET(attrs, IFLA_VXLAN_LINK)) {
|
||||
fprintf(stderr, "vxlan: 'group' requires 'dev' to be specified\n");
|
||||
return -1;
|
||||
|
|
@ -369,18 +349,18 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
|
|||
|
||||
if (VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID))
|
||||
addattr32(n, 1024, IFLA_VXLAN_ID, vni);
|
||||
if (gaddr)
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4);
|
||||
else if (daddr)
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
|
||||
else if (!IN6_IS_ADDR_UNSPECIFIED(&gaddr6))
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr));
|
||||
else if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6))
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
|
||||
else if (preferred_family == AF_INET)
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4);
|
||||
else if (preferred_family == AF_INET6)
|
||||
addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr));
|
||||
|
||||
if (is_addrtype_inet(&saddr)) {
|
||||
int type = (saddr.family == AF_INET) ? IFLA_VXLAN_LOCAL
|
||||
: IFLA_VXLAN_LOCAL6;
|
||||
addattr_l(n, 1024, type, saddr.data, saddr.bytelen);
|
||||
}
|
||||
|
||||
if (is_addrtype_inet(&daddr)) {
|
||||
int type = (daddr.family == AF_INET) ? IFLA_VXLAN_GROUP
|
||||
: IFLA_VXLAN_GROUP6;
|
||||
addattr_l(n, 1024, type, daddr.data, daddr.bytelen);
|
||||
}
|
||||
|
||||
if (!set_op || VXLAN_ATTRSET(attrs, IFLA_VXLAN_LEARNING))
|
||||
addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning);
|
||||
|
|
|
|||
|
|
@ -431,7 +431,10 @@ static struct ipv6_sr_hdr *parse_srh(char *segbuf, int hmac, bool encap)
|
|||
|
||||
i = srh->first_segment;
|
||||
for (s = strtok(segbuf, ","); s; s = strtok(NULL, ",")) {
|
||||
inet_get_addr(s, NULL, &srh->segments[i]);
|
||||
inet_prefix addr;
|
||||
|
||||
get_addr(&addr, s, AF_INET6);
|
||||
memcpy(&srh->segments[i], addr.data, sizeof(struct in6_addr));
|
||||
i--;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ static int genl_family = -1;
|
|||
|
||||
static struct {
|
||||
unsigned int cmd;
|
||||
struct in6_addr addr;
|
||||
inet_prefix addr;
|
||||
__u32 keyid;
|
||||
const char *pass;
|
||||
__u8 alg_id;
|
||||
|
|
@ -152,7 +152,7 @@ static int seg6_do_cmd(void)
|
|||
break;
|
||||
}
|
||||
case SEG6_CMD_SET_TUNSRC:
|
||||
addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, &opts.addr,
|
||||
addattr_l(&req.n, sizeof(req), SEG6_ATTR_DST, opts.addr.data,
|
||||
sizeof(struct in6_addr));
|
||||
break;
|
||||
case SEG6_CMD_DUMPHMAC:
|
||||
|
|
@ -226,9 +226,7 @@ int do_seg6(int argc, char **argv)
|
|||
} else if (matches(*argv, "set") == 0) {
|
||||
NEXT_ARG();
|
||||
opts.cmd = SEG6_CMD_SET_TUNSRC;
|
||||
if (!inet_get_addr(*argv, NULL, &opts.addr))
|
||||
invarg("tunsrc ADDRESS value is invalid",
|
||||
*argv);
|
||||
get_addr(&opts.addr, *argv, AF_INET6);
|
||||
} else {
|
||||
invarg("unknown", *argv);
|
||||
}
|
||||
|
|
|
|||
106
lib/utils.c
106
lib/utils.c
|
|
@ -534,7 +534,7 @@ int get_addr64(__u64 *ap, const char *cp)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int get_addr_1(inet_prefix *addr, const char *name, int family)
|
||||
static int __get_addr_1(inet_prefix *addr, const char *name, int family)
|
||||
{
|
||||
memset(addr, 0, sizeof(*addr));
|
||||
|
||||
|
|
@ -543,9 +543,9 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)
|
|||
strcmp(name, "any") == 0) {
|
||||
if ((family == AF_DECnet) || (family == AF_MPLS))
|
||||
return -1;
|
||||
addr->family = family;
|
||||
addr->bytelen = (family == AF_INET6 ? 16 : 4);
|
||||
addr->bitlen = -1;
|
||||
addr->family = (family != AF_UNSPEC) ? family : AF_INET;
|
||||
addr->bytelen = af_byte_len(addr->family);
|
||||
addr->bitlen = -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -619,6 +619,36 @@ int get_addr_1(inet_prefix *addr, const char *name, int family)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int get_addr_1(inet_prefix *addr, const char *name, int family)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = __get_addr_1(addr, name, family);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (addr->family) {
|
||||
case AF_INET:
|
||||
if (!addr->data[0])
|
||||
addr->flags |= ADDRTYPE_INET_UNSPEC;
|
||||
else if (IN_MULTICAST(ntohl(addr->data[0])))
|
||||
addr->flags |= ADDRTYPE_INET_MULTI;
|
||||
else
|
||||
addr->flags |= ADDRTYPE_INET;
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (IN6_IS_ADDR_UNSPECIFIED(addr->data))
|
||||
addr->flags |= ADDRTYPE_INET_UNSPEC;
|
||||
else if (IN6_IS_ADDR_MULTICAST(addr->data))
|
||||
addr->flags |= ADDRTYPE_INET_MULTI;
|
||||
else
|
||||
addr->flags |= ADDRTYPE_INET;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int af_bit_len(int af)
|
||||
{
|
||||
switch (af) {
|
||||
|
|
@ -644,46 +674,46 @@ int af_byte_len(int af)
|
|||
|
||||
int get_prefix_1(inet_prefix *dst, char *arg, int family)
|
||||
{
|
||||
int err;
|
||||
unsigned int plen;
|
||||
char *slash;
|
||||
|
||||
memset(dst, 0, sizeof(*dst));
|
||||
|
||||
if (strcmp(arg, "default") == 0 ||
|
||||
strcmp(arg, "any") == 0 ||
|
||||
strcmp(arg, "all") == 0) {
|
||||
if ((family == AF_DECnet) || (family == AF_MPLS))
|
||||
return -1;
|
||||
dst->family = family;
|
||||
dst->bytelen = 0;
|
||||
dst->bitlen = 0;
|
||||
dst->flags |= PREFIXLEN_SPECIFIED;
|
||||
return 0;
|
||||
}
|
||||
int err, bitlen, flags;
|
||||
|
||||
slash = strchr(arg, '/');
|
||||
if (slash)
|
||||
*slash = 0;
|
||||
|
||||
err = get_addr_1(dst, arg, family);
|
||||
if (err == 0) {
|
||||
dst->bitlen = af_bit_len(dst->family);
|
||||
|
||||
if (slash) {
|
||||
if (get_netmask(&plen, slash+1, 0)
|
||||
|| plen > dst->bitlen) {
|
||||
err = -1;
|
||||
goto done;
|
||||
}
|
||||
dst->flags |= PREFIXLEN_SPECIFIED;
|
||||
dst->bitlen = plen;
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (slash)
|
||||
*slash = '/';
|
||||
return err;
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
bitlen = af_bit_len(dst->family);
|
||||
|
||||
flags = PREFIXLEN_SPECIFIED;
|
||||
if (slash) {
|
||||
unsigned int plen;
|
||||
|
||||
if (dst->bitlen == -2)
|
||||
return -1;
|
||||
if (get_netmask(&plen, slash + 1, 0))
|
||||
return -1;
|
||||
if (plen > bitlen)
|
||||
return -1;
|
||||
|
||||
bitlen = plen;
|
||||
} else {
|
||||
if (dst->bitlen == -2)
|
||||
bitlen = 0;
|
||||
else
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
dst->flags |= flags;
|
||||
dst->bitlen = bitlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *family_name_verbose(int family)
|
||||
|
|
@ -1250,14 +1280,6 @@ int makeargs(char *line, char *argv[], int maxargs)
|
|||
return argc;
|
||||
}
|
||||
|
||||
int inet_get_addr(const char *src, __u32 *dst, struct in6_addr *dst6)
|
||||
{
|
||||
if (strchr(src, ':'))
|
||||
return inet_pton(AF_INET6, src, dst6);
|
||||
else
|
||||
return inet_pton(AF_INET, src, dst);
|
||||
}
|
||||
|
||||
void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n)
|
||||
{
|
||||
char *tstr;
|
||||
|
|
|
|||
Loading…
Reference in New Issue