mirror of
git://git.code.sf.net/p/dhcpd-pools/code
synced 2025-12-17 16:26:59 +00:00
IPv6: add DHCPv6 support
The DHCP version is determined according to the first IP address that appears in the configuration file. Caveat; counters are of native long type. Since IPv6 address space has 2^128 addresses, they are subject to overflow. [Sami Kerola: This commit also fixed a percent sorting bug, which has been broken always. See changes ret_percent() for the fix.] CC: LI Zimu <lzm@cernet.edu.cn> CC: Xing Li <xing@cernet.edu.cn> Reviewed-by: Sami Kerola <kerolasa@iki.fi> Signed-off-by: Cheer Xiao <xiaqqaix@gmail.com>
This commit is contained in:
parent
71bcee14e9
commit
a57d399643
8 changed files with 267 additions and 119 deletions
72
src/other.c
72
src/other.c
|
|
@ -45,6 +45,78 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
|
||||
int parse_ipaddr(const char *restrict src, union ipaddr_t *restrict dst)
|
||||
{
|
||||
int rv;
|
||||
if (dhcp_version == VERSION_UNKNOWN) {
|
||||
struct in_addr addr;
|
||||
struct in6_addr addr6;
|
||||
if (inet_aton(src, &addr) == 1) {
|
||||
dhcp_version = VERSION_4;
|
||||
} else if (inet_pton(AF_INET6, src, &addr6) == 1) {
|
||||
dhcp_version = VERSION_6;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (dhcp_version == VERSION_6) {
|
||||
struct in6_addr addr;
|
||||
rv = inet_pton(AF_INET6, src, &addr);
|
||||
memcpy(&dst->v6, addr.s6_addr, sizeof(addr.s6_addr));
|
||||
} else {
|
||||
struct in_addr addr;
|
||||
rv = inet_aton(src, &addr);
|
||||
dst->v4 = ntohl(addr.s_addr);
|
||||
}
|
||||
return rv == 1;
|
||||
}
|
||||
|
||||
void copy_ipaddr(union ipaddr_t *restrict dst,
|
||||
const union ipaddr_t *restrict src)
|
||||
{
|
||||
if (dhcp_version == VERSION_6) {
|
||||
memcpy(&dst->v6, &src->v6, sizeof(src->v6));
|
||||
} else {
|
||||
dst->v4 = src->v4;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ntop_ipaddr(const union ipaddr_t *ip)
|
||||
{
|
||||
static char
|
||||
buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
|
||||
if (dhcp_version == VERSION_6) {
|
||||
struct in6_addr addr;
|
||||
memcpy(addr.s6_addr, ip->v6, sizeof(addr.s6_addr));
|
||||
return inet_ntop(AF_INET6, &addr, buffer, sizeof(buffer));
|
||||
} else {
|
||||
struct in_addr addr;
|
||||
addr.s_addr = htonl(ip->v4);
|
||||
return inet_ntop(AF_INET, &addr, buffer, sizeof(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long get_range_size(const struct range_t *r)
|
||||
{
|
||||
if (dhcp_version == VERSION_6) {
|
||||
unsigned long size = 0;
|
||||
int i;
|
||||
/* When calculating the size of an IPv6 range overflow may
|
||||
* occur. In that case only the last LONG_BIT bits are
|
||||
* preserved, thus we just skip the first (16 - LONG_BIT)
|
||||
* bits... */
|
||||
for (i = LONG_BIT / 8 < 16 ? 16 - LONG_BIT / 8 : 0; i < 16; i++) {
|
||||
size <<= 8;
|
||||
size += (int)r->last_ip.v6[i] - (int)r->first_ip.v6[i];
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
return size + 1;
|
||||
} else {
|
||||
return r->last_ip.v4 - r->first_ip.v4 + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue