366 lines
10 KiB
C
366 lines
10 KiB
C
#ifndef _TUPLE_H
|
|
#define _TUPLE_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <arpa/inet.h>
|
|
|
|
#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 __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|