#include #include #include #include union sockaddr_union { struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_in6 sin6; }; static inline int sau_match_ip(union sockaddr_union *l, union sockaddr_union *r) { if (l->sa.sa_family != r->sa.sa_family) return 0; if (l->sa.sa_family == AF_INET) return (l->sin.sin_addr.s_addr == r->sin.sin_addr.s_addr); if (l->sa.sa_family == AF_INET6) return !memcmp(&l->sin6.sin6_addr, &r->sin6.sin6_addr, sizeof(l->sin6.sin6_addr)); return 0; } static inline int sau_match(union sockaddr_union *l, union sockaddr_union *r) { if (l->sa.sa_family != r->sa.sa_family) return 0; if (l->sa.sa_family == AF_INET) return (l->sin.sin_addr.s_addr == r->sin.sin_addr.s_addr) && (l->sin.sin_port == r->sin.sin_port); if (l->sa.sa_family == AF_INET6) return !memcmp(&l->sin6.sin6_addr, &r->sin6.sin6_addr, sizeof(l->sin6.sin6_addr)) && (l->sin6.sin6_port == r->sin6.sin6_port) && (l->sin6.sin6_scope_id == r->sin6.sin6_scope_id) && (l->sin6.sin6_flowinfo == r->sin6.sin6_flowinfo); return 0; } static inline int sau_parse(union sockaddr_union *sau, const char *str) { memset(sau, 0, sizeof(*sau)); if (inet_pton(AF_INET6, str, &sau->sin6.sin6_addr)) { sau->sin6.sin6_family = AF_INET6; sau->sin6.sin6_port = htons(1701); return 1; } if (inet_pton(AF_INET, str, &sau->sin.sin_addr)) { sau->sin.sin_family = AF_INET; sau->sin.sin_port = htons(1701); return 1; } return 0; } static const char *sau_to_str(union sockaddr_union *sau) { static char static_str[4][INET6_ADDRSTRLEN]; static unsigned nr; char *str = static_str[nr++ % 4]; if (sau->sa.sa_family == AF_INET6) return inet_ntop(AF_INET6, &sau->sin6.sin6_addr, str, INET6_ADDRSTRLEN); return inet_ntop(AF_INET, &sau->sin.sin_addr, str, INET6_ADDRSTRLEN); }