| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef __IPADDR_H__ |
| #define __IPADDR_H__ |
| |
| #include <zebra.h> |
| |
| #include "lib/log.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| |
| |
| |
| enum ipaddr_type_t { |
| IPADDR_NONE = AF_UNSPEC, |
| IPADDR_V4 = AF_INET, |
| IPADDR_V6 = AF_INET6, |
| }; |
| |
| struct ipaddr { |
| enum ipaddr_type_t ipa_type; |
| union { |
| uint8_t addr; |
| struct in_addr _v4_addr; |
| struct in6_addr _v6_addr; |
| } ip; |
| #define ipaddr_v4 ip._v4_addr |
| #define ipaddr_v6 ip._v6_addr |
| }; |
| |
| #define IS_IPADDR_NONE(p) ((p)->ipa_type == IPADDR_NONE) |
| #define IS_IPADDR_V4(p) ((p)->ipa_type == IPADDR_V4) |
| #define IS_IPADDR_V6(p) ((p)->ipa_type == IPADDR_V6) |
| |
| #define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4 |
| #define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6 |
| |
| #define IPADDRSZ(p) \ |
| (IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr)) |
| |
| static inline int ipaddr_family(const struct ipaddr *ip) |
| { |
| switch (ip->ipa_type) { |
| case IPADDR_V4: |
| return AF_INET; |
| case IPADDR_V6: |
| return AF_INET6; |
| default: |
| return AF_UNSPEC; |
| } |
| } |
| |
| static inline int str2ipaddr(const char *str, struct ipaddr *ip) |
| { |
| int ret; |
| |
| memset(ip, 0, sizeof(struct ipaddr)); |
| |
| ret = inet_pton(AF_INET, str, &ip->ipaddr_v4); |
| if (ret > 0) |
| { |
| ip->ipa_type = IPADDR_V4; |
| return 0; |
| } |
| ret = inet_pton(AF_INET6, str, &ip->ipaddr_v6); |
| if (ret > 0) |
| { |
| ip->ipa_type = IPADDR_V6; |
| return 0; |
| } |
| |
| return -1; |
| } |
| |
| static inline char *ipaddr2str(const struct ipaddr *ip, char *buf, int size) |
| { |
| buf[0] = '\0'; |
| if (ip) |
| inet_ntop(ip->ipa_type, &ip->ip.addr, buf, size); |
| return buf; |
| } |
| |
| #define IS_MAPPED_IPV6(A) \ |
| ((A)->s6_addr32[0] == 0x00000000 \ |
| ? ((A)->s6_addr32[1] == 0x00000000 \ |
| ? (ntohl((A)->s6_addr32[2]) == 0xFFFF ? 1 : 0) \ |
| : 0) \ |
| : 0) |
| |
| |
| |
| |
| |
| |
| |
| static inline void ipv4_to_ipv4_mapped_ipv6(struct in6_addr *in6, |
| struct in_addr in) |
| { |
| uint32_t addr_type = htonl(0xFFFF); |
| |
| memset(in6, 0, sizeof(struct in6_addr)); |
| memcpy((char *)in6 + 8, &addr_type, sizeof(addr_type)); |
| memcpy((char *)in6 + 12, &in, sizeof(struct in_addr)); |
| } |
| |
| |
| |
| |
| static inline void ipv4_mapped_ipv6_to_ipv4(const struct in6_addr *in6, |
| struct in_addr *in) |
| { |
| memset(in, 0, sizeof(struct in_addr)); |
| memcpy(in, (char *)in6 + 12, sizeof(struct in_addr)); |
| } |
| |
| |
| |
| |
| static inline bool ipaddr_isset(struct ipaddr *ip) |
| { |
| static struct ipaddr a = {}; |
| return (0 != memcmp(&a, ip, sizeof(struct ipaddr))); |
| } |
| |
| |
| |
| |
| static inline int ipaddr_cmp(const struct ipaddr *a, const struct ipaddr *b) |
| { |
| uint32_t va, vb; |
| va = a->ipa_type; |
| vb = b->ipa_type; |
| if (va != vb) |
| return (va < vb) ? -1 : 1; |
| switch (a->ipa_type) { |
| case IPADDR_V4: |
| va = ntohl(a->ipaddr_v4.s_addr); |
| vb = ntohl(b->ipaddr_v4.s_addr); |
| if (va != vb) |
| return (va < vb) ? -1 : 1; |
| return 0; |
| case IPADDR_V6: |
| return memcmp((void *)&a->ipaddr_v6, (void *)&b->ipaddr_v6, |
| sizeof(a->ipaddr_v6)); |
| default: |
| return 0; |
| } |
| } |
| |
| #ifdef _FRR_ATTRIBUTE_PRINTFRR |
| #pragma FRR printfrr_ext "%pIA" (struct ipaddr *) |
| #endif |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |