X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/ecae4cccfe0b8e4e81b425336e49aa72f980a65c..8855bb48b449ed06cfd3ce528b3c0a77c37cb24b:/lib/irc_ipv6.c diff --git a/lib/irc_ipv6.c b/lib/irc_ipv6.c index 6f44d0bf..ba6817e1 100644 --- a/lib/irc_ipv6.c +++ b/lib/irc_ipv6.c @@ -77,6 +77,48 @@ const char* ircd_ntoa_r(char* buf, const struct irc_in_addr* in) } } +/** Convert a CIDR mask to printable ASCII form. + * This is generally deprecated in favor of ircd_ntoa_masked_r(). + * @param[in] in Address to convert. + * @param[in] bits Mask bits. + * @return Pointer to a static buffer containing the readable form. + */ +const char* ircd_ntoa_masked(const struct irc_in_addr* in, unsigned char bits) +{ + static char buf[CIDRLEN]; + return ircd_ntoa_masked_r(buf, in, bits); +} + +/** Convert a CIDR mask to printable ASCII form. + * @param[out] buf Output buffer to write to. + * @param[in] in Address to format. + * @param[in] bits Mask bits. + * @return Pointer to the output buffer \a buf. + */ +const char* ircd_ntoa_masked_r(char* buf, const struct irc_in_addr* in, unsigned char bits) +{ + char inname[SOCKIPLEN]; + struct irc_in_addr intemp; + int i; + + for(i=0;i<8;i++) { + int curbits = bits - i * 16; + + if (curbits<0) + curbits = 0; + else if (curbits>16) + curbits = 16; + + uint16_t mask = 0xffff & ~((1 << (16 - curbits)) - 1); + intemp.in6_16[i] = htons(ntohs(in->in6_16[i]) & mask); + } + + ircd_ntoa_r(inname, &intemp); + sprintf(buf, "%s/%u", inname, irc_bitlen(in, bits)); + + return buf; +} + /** Attempt to parse an IPv4 address into a network-endian form. * @param[in] input Input string. * @param[out] output Network-endian representation of the address. @@ -486,3 +528,27 @@ int ipmask_check(const struct irc_in_addr *addr, const struct irc_in_addr *mask, } return -1; } + +/** Convert IP addresses to canonical form for comparison. 6to4 and Teredo addresses + * are converted to IPv4 addresses. All other addresses are left alone. + * @param[out] out Receives canonical format for address. + * @param[in] in IP address to canonicalize. + */ +void ip_canonicalize_tunnel(struct irc_in_addr *out, const struct irc_in_addr *in) +{ + if (in->in6_16[0] == htons(0x2002)) { /* 6to4 */ + out->in6_16[0] = out->in6_16[1] = out->in6_16[2] = 0; + out->in6_16[3] = out->in6_16[4] = 0; + out->in6_16[5] = 0xffff; + out->in6_16[6] = in->in6_16[1]; + out->in6_16[7] = in->in6_16[2]; + } else if(in->in6_16[0] == htons(0x2001) && in->in6_16[1] == 0) { /* Teredo */ + out->in6_16[0] = out->in6_16[1] = out->in6_16[2] = 0; + out->in6_16[3] = out->in6_16[4] = 0; + out->in6_16[5] = 0xffff; + out->in6_16[6] = ~(in->in6_16[6]); + out->in6_16[7] = ~(in->in6_16[7]); + } else + memcpy(out, in, sizeof(*out)); +} +