utils: Fast inet address classification after get_addr()

It looks very useful to receive additional information
from get_addr_1() and get_addr() about address to simplify
caller and get rid of code duplications.

For now following information can be returned:

  1) address is unspecified (zero)
  2) address is multicast
  3) address is internet: family is either AF_INET or
     AF_INET6.

More information can be added in the future.

Introduce inline helpers to make code using this new
address classification interface more self explaining:

  bool is_addrtype_inet(inet_prefix *addr)
    true if @addr is inet address

  bool is_addrtype_inet_unspec(inet_prefix *addr)
    true if @addr is unspecified inet address

  bool is_addrtype_inet_multi(inet_prefix *addr)
    true if @addr is multicast inet address

  bool is_addrtype_inet_not_unspec(inet_prefix *addr)
    true if @addr is not unspecified inet address
    false if @addr is not inet or unspecified inet

  bool is_addrtype_inet_not_multi(inet_prefix *addr)
    true if @addr is not multicast inet address
    false if @addr is not inet or multicast inet

Last two are useful for case when we need inet address
that is not unspecified or multicast.

Signed-off-by: Serhey Popovych <serhe.popovych@gmail.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
This commit is contained in:
Serhey Popovych 2018-01-18 20:13:44 +02:00 committed by David Ahern
parent 93fa12418d
commit 7bf5e876d0
2 changed files with 65 additions and 2 deletions

View File

@ -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

View File

@ -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));
@ -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) {