#ifndef _TUPLE_H #define _TUPLE_H #ifdef __cpluscplus extern "C" { #endif #include #include #include #include "uthash.h" enum address_type { ADDR_TYPE_IPV4, ADDR_TYPE_IPV6, }; struct ipv4_address { struct in_addr src; /* network order */ struct in_addr dst; /* network order */ }; struct ipv6_address { struct in6_addr src; /* network order */ struct in6_addr dst; /* network order */ }; union ip_address { struct ipv4_address ipv4; /* network order */ struct ipv6_address ipv6; /* network order */ }; struct two_tuple { enum address_type type; union ip_address addr; /* network order */ }; struct four_tuple { struct two_tuple two_tuple; in_port_t src_port; /* network order */ in_port_t dst_port; /* network order */ }; #define SET_HUMAN_READABLE_IPV4_TUPLE(tuple, src_addr_str, src_port, dst_addr_str, dst_port) \ do \ { \ memset(tuple, 0, sizeof(struct four_tuple)); \ two_tuple_set_ipv4_string(&(tuple)->two_tuple, src_addr_str, dst_addr_str); \ four_tuple_set_port(tuple, htons(src_port), htons(dst_port)); \ } while (0) #define SET_HUMAN_READABLE_IPV6_TUPLE(tuple, src_addr_str, src_port, dst_addr_str, dst_port) \ do \ { \ memset(tuple, 0, sizeof(struct four_tuple)); \ two_tuple_set_ipv6_string(&(tuple)->two_tuple, src_addr_str, dst_addr_str); \ four_tuple_set_port(tuple, htons(src_port), htons(dst_port)); \ } while (0) /****************************************************************************** * two tuple ******************************************************************************/ inline void two_tuple_set_ipv4_string(struct two_tuple *tuple, const char *src, const char *dst) { memset(tuple, 0, sizeof(struct two_tuple)); struct ipv4_address *ipv4 = &(tuple->addr.ipv4); tuple->type = ADDR_TYPE_IPV4; inet_pton(AF_INET, src, &ipv4->src); inet_pton(AF_INET, dst, &ipv4->dst); } inline void two_tuple_set_ipv6_string(struct two_tuple *tuple, const char *src, const char *dst) { memset(tuple, 0, sizeof(struct two_tuple)); struct ipv6_address *ipv6 = &(tuple->addr.ipv6); tuple->type = ADDR_TYPE_IPV6; inet_pton(AF_INET6, src, &ipv6->src); inet_pton(AF_INET6, dst, &ipv6->dst); } inline void two_tuple_set_ipv4_address(struct two_tuple *tuple, const struct in_addr *src, const struct in_addr *dst) { memset(tuple, 0, sizeof(struct two_tuple)); struct ipv4_address *ipv4 = &(tuple->addr.ipv4); tuple->type = ADDR_TYPE_IPV4; ipv4->src = *src; ipv4->dst = *dst; } inline void two_tuple_set_ipv6_address(struct two_tuple *tuple, const struct in6_addr *src, const struct in6_addr *dst) { memset(tuple, 0, sizeof(struct two_tuple)); struct ipv6_address *ipv6 = &(tuple->addr.ipv6); tuple->type = ADDR_TYPE_IPV6; ipv6->src = *src; ipv6->dst = *dst; } inline int two_tuple_get_address_length(const struct two_tuple *tuple) { if (tuple->type == ADDR_TYPE_IPV4) { return sizeof(struct in_addr); } else { return sizeof(struct in6_addr); } } inline const char *two_tuple_get_src_address(const struct two_tuple *tuple) { if (tuple->type == ADDR_TYPE_IPV4) { return (const char *)&(tuple->addr.ipv4.src); } else { return (const char *)&(tuple->addr.ipv6.src); } } inline const char *two_tuple_get_dst_address(const struct two_tuple *tuple) { if (tuple->type == ADDR_TYPE_IPV4) { return (const char *)&(tuple->addr.ipv4.dst); } else { return (const char *)&(tuple->addr.ipv6.dst); } } inline void two_tuple_copy(struct two_tuple *dst, const struct two_tuple *src) { memset(dst, 0, sizeof(struct two_tuple)); dst->type = src->type; if (src->type == ADDR_TYPE_IPV4) { dst->addr.ipv4 = src->addr.ipv4; } else { dst->addr.ipv6 = src->addr.ipv6; } } inline int two_tuple_cmp(const struct two_tuple *tuple1, const struct two_tuple *tuple2) { if (tuple1->type != tuple2->type) { return -1; } if (tuple1->type == ADDR_TYPE_IPV4) { if (memcmp(&(tuple1->addr.ipv4.src), &(tuple2->addr.ipv4.src), sizeof(struct in_addr)) != 0) { return -1; } if (memcmp(&(tuple1->addr.ipv4.dst), &(tuple2->addr.ipv4.dst), sizeof(struct in_addr)) != 0) { return -1; } return 0; } else { if (memcmp(&(tuple1->addr.ipv6.src), &(tuple2->addr.ipv6.src), sizeof(struct in6_addr)) != 0) { return -1; } if (memcmp(&(tuple1->addr.ipv6.dst), &(tuple2->addr.ipv6.dst), sizeof(struct in6_addr)) != 0) { return -1; } return 0; } } inline void two_tuple_reverse(const struct two_tuple *orin, struct two_tuple *out) { memset(out, 0, sizeof(struct two_tuple)); if (orin->type == ADDR_TYPE_IPV4) { out->type = ADDR_TYPE_IPV4; struct ipv4_address *ipv4_out = &(out->addr.ipv4); const struct ipv4_address *ipv4_orin = &(orin->addr.ipv4); ipv4_out->src = ipv4_orin->dst; ipv4_out->dst = ipv4_orin->src; } if (orin->type == ADDR_TYPE_IPV6) { out->type = ADDR_TYPE_IPV6; struct ipv6_address *ipv6_out = &(out->addr.ipv6); const struct ipv6_address *ipv6_orin = &(orin->addr.ipv6); ipv6_out->src = ipv6_orin->dst; ipv6_out->dst = ipv6_orin->src; } } inline char *two_tuple_tostring(const struct two_tuple *tuple) { char *str_ret = NULL; if (tuple->type == ADDR_TYPE_IPV4) { char src[INET_ADDRSTRLEN] = {0}; char dst[INET_ADDRSTRLEN] = {0}; inet_ntop(AF_INET, &tuple->addr.ipv4.src, src, sizeof(src)); inet_ntop(AF_INET, &tuple->addr.ipv4.dst, dst, sizeof(dst)); asprintf(&str_ret, "%s %s", src, dst); } if (tuple->type == ADDR_TYPE_IPV6) { char src[INET6_ADDRSTRLEN] = {0}; char dst[INET6_ADDRSTRLEN] = {0}; inet_ntop(AF_INET6, &tuple->addr.ipv6.src, src, sizeof(src)); inet_ntop(AF_INET6, &tuple->addr.ipv6.dst, dst, sizeof(dst)); asprintf(&str_ret, "%s %s", src, dst); } return str_ret; } /****************************************************************************** * four tuple ******************************************************************************/ inline void four_tuple_set_ipv4_string(struct four_tuple *tuple, const char *src, const char *dst) { two_tuple_set_ipv4_string(&(tuple->two_tuple), src, dst); } inline void four_tuple_set_ipv6_string(struct four_tuple *tuple, const char *src, const char *dst) { two_tuple_set_ipv6_string(&(tuple->two_tuple), src, dst); } inline void four_tuple_set_ipv4_address(struct four_tuple *tuple, const struct in_addr *src, const struct in_addr *dst) { two_tuple_set_ipv4_address(&(tuple->two_tuple), src, dst); } inline void four_tuple_set_ipv6_address(struct four_tuple *tuple, const struct in6_addr *src, const struct in6_addr *dst) { two_tuple_set_ipv6_address(&(tuple->two_tuple), src, dst); } inline void four_tuple_set_port(struct four_tuple *tuple, const in_port_t src, const in_port_t dst) { tuple->src_port = 0; tuple->dst_port = 0; tuple->src_port = src; tuple->dst_port = dst; } inline int four_tuple_get_address_length(const struct four_tuple *tuple) { return two_tuple_get_address_length(&(tuple->two_tuple)); } inline const char *four_tuple_get_src_address(const struct four_tuple *tuple) { return two_tuple_get_src_address(&(tuple->two_tuple)); } inline const char *four_tuple_get_dst_address(const struct four_tuple *tuple) { return two_tuple_get_dst_address(&(tuple->two_tuple)); } inline void four_tuple_copy(struct four_tuple *dst, const struct four_tuple *src) { memset(dst, 0, sizeof(struct four_tuple)); two_tuple_copy(&(dst->two_tuple), &(src->two_tuple)); dst->src_port = src->src_port; dst->dst_port = src->dst_port; } inline int four_tuple_cmp(const struct four_tuple *tuple1, const struct four_tuple *tuple2) { if (tuple1->src_port != tuple2->src_port) { return -1; } if (tuple1->dst_port != tuple2->dst_port) { return -1; } return two_tuple_cmp(&(tuple1->two_tuple), &(tuple2->two_tuple)); } inline void four_tuple_reverse(const struct four_tuple *orin, struct four_tuple *out) { memset(out, 0, sizeof(struct four_tuple)); out->src_port = orin->dst_port; out->dst_port = orin->src_port; two_tuple_reverse(&(orin->two_tuple), &(out->two_tuple)); } inline char *four_tuple_tostring(const struct four_tuple *tuple) { char *str_ret = NULL; if (tuple->two_tuple.type == ADDR_TYPE_IPV4) { char src[INET_ADDRSTRLEN] = {0}; char dst[INET_ADDRSTRLEN] = {0}; uint16_t src_port = ntohs((uint16_t)tuple->src_port); uint16_t dst_port = ntohs((uint16_t)tuple->dst_port); inet_ntop(AF_INET, &tuple->two_tuple.addr.ipv4.src, src, sizeof(src)); inet_ntop(AF_INET, &tuple->two_tuple.addr.ipv4.dst, dst, sizeof(dst)); asprintf(&str_ret, "%s %u %s %u", src, src_port, dst, dst_port); } if (tuple->two_tuple.type == ADDR_TYPE_IPV6) { char src[INET6_ADDRSTRLEN] = {0}; char dst[INET6_ADDRSTRLEN] = {0}; uint16_t src_port = ntohs((uint16_t)tuple->src_port); uint16_t dst_port = ntohs((uint16_t)tuple->dst_port); inet_ntop(AF_INET6, &tuple->two_tuple.addr.ipv6.src, src, sizeof(src)); inet_ntop(AF_INET6, &tuple->two_tuple.addr.ipv6.dst, dst, sizeof(dst)); asprintf(&str_ret, "%s %u %s %u", src, src_port, dst, dst_port); } return str_ret; } inline uint64_t four_tuple_hash(const struct four_tuple *tuple) { uint64_t hash_value = 0; HASH_VALUE(tuple, sizeof(struct four_tuple), hash_value); return hash_value; } #ifdef __cpluscplus } #endif #endif