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.popov...@gmail.com> --- include/utils.h | 35 ++++++++++++++++++++++++++++++++++- lib/utils.c | 32 +++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/include/utils.h b/include/utils.h index d3895d5..6f072f6 100644 --- a/include/utils.h +++ b/include/utils.h @@ -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 diff --git a/lib/utils.c b/lib/utils.c index 48c4bcb..e66c1ff 100644 --- a/lib/utils.c +++ b/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)); @@ -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) { -- 1.7.10.4