bool netblock_match(const struct sockaddr_storage *ss1, const struct sockaddr_storage *ss2, unsigned prefix) { if (ss1 == NULL || ss2 == NULL) { return false; } if (ss1->ss_family != ss2->ss_family) { return false; } const uint8_t *addr1, *addr2; switch (ss1->ss_family) { case AF_INET: addr1 = ipv4_addr(ss1); addr2 = ipv4_addr(ss2); prefix = prefix > IPV4_PREFIXLEN ? IPV4_PREFIXLEN : prefix; break; case AF_INET6: addr1 = ipv6_addr(ss1); addr2 = ipv6_addr(ss2); prefix = prefix > IPV6_PREFIXLEN ? IPV6_PREFIXLEN : prefix; break; default: return false; } /* Compare full bytes address block. */ uint8_t full_bytes = prefix / 8; for (int i = 0; i < full_bytes; i++) { if (addr1[i] != addr2[i]) { return false; } } /* Compare last partial byte address block. */ uint8_t rest_bits = prefix % 8; if (rest_bits > 0) { uint8_t rest1 = addr1[full_bytes] >> (8 - rest_bits); uint8_t rest2 = addr2[full_bytes] >> (8 - rest_bits); if (rest1 != rest2) { return false; } }
int port(struct sockaddr_storage *addr) { if (AF_INET == addr->ss_family) { return ntohs(ipv4_addr(addr)->sin_port); } else if (AF_INET6 == addr->ss_family) { return ntohs(ipv6_addr(addr)->sin6_port); } return 0; }
const char *inet_ntop(struct sockaddr_storage *addr) { if (AF_INET == addr->ss_family) { return ::inet_ntop(AF_INET, &(ipv4_addr(addr)->sin_addr), m_buffer, sizeof(m_buffer)); } else if (AF_INET6 == addr->ss_family) { return ::inet_ntop(AF_INET6, &(ipv6_addr(addr)->sin6_addr), m_buffer, sizeof(m_buffer)); } return NULL; }