IPv6 address range parsing for --domain.

Counted string DHCP option type printing
This commit is contained in:
Simon Kelley
2012-02-07 20:51:56 +00:00
parent 70c5e3e076
commit d74942a03d
3 changed files with 126 additions and 28 deletions

View File

@@ -913,7 +913,8 @@ char *get_domain(struct in_addr addr)
struct cond_domain *c; struct cond_domain *c;
for (c = daemon->cond_domain; c; c = c->next) for (c = daemon->cond_domain; c; c = c->next)
if (ntohl(addr.s_addr) >= ntohl(c->start.s_addr) && if (!c->is6 &&
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
ntohl(addr.s_addr) <= ntohl(c->end.s_addr)) ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
return c->domain; return c->domain;
@@ -924,14 +925,15 @@ char *get_domain(struct in_addr addr)
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
char *get_domain6(struct in6_addr *addr) char *get_domain6(struct in6_addr *addr)
{ {
struct cond_domain6 *c; struct cond_domain *c;
u64 addrpart = addr6part(addr); u64 addrpart = addr6part(addr);
for (c = daemon->cond_domain6; c; c = c->next) for (c = daemon->cond_domain; c; c = c->next)
if (is_same_net6(addr, &c->start, 64) && if (c->is6 &&
addrpart >= addr6part(&c->start) && is_same_net6(addr, &c->start6, 64) &&
addrpart <= addr6part(&c->end)) addrpart >= addr6part(&c->start6) &&
addrpart <= addr6part(&c->end6))
return c->domain; return c->domain;
return daemon->domain_suffix; return daemon->domain_suffix;

View File

@@ -588,15 +588,13 @@ struct dhcp_bridge {
struct cond_domain { struct cond_domain {
char *domain; char *domain;
struct in_addr start, end; struct in_addr start, end;
#ifdef HAVE_IPV6
struct in6_addr start6, end6;
#endif
int is6;
struct cond_domain *next; struct cond_domain *next;
}; };
struct cond_domain6 {
char *domain;
struct in6_addr start, end;
struct cond_domain6 *next;
};
struct dhcp_context { struct dhcp_context {
unsigned int lease_time, addr_epoch; unsigned int lease_time, addr_epoch;
struct in_addr netmask, broadcast; struct in_addr netmask, broadcast;
@@ -683,7 +681,6 @@ extern struct daemon {
int group_set, osport; int group_set, osport;
char *domain_suffix; char *domain_suffix;
struct cond_domain *cond_domain; struct cond_domain *cond_domain;
struct cond_domain6 *cond_domain6;
char *runfile; char *runfile;
char *lease_change_command; char *lease_change_command;
struct iname *if_names, *if_addrs, *if_except, *dhcp_except; struct iname *if_names, *if_addrs, *if_except, *dhcp_except;

View File

@@ -543,6 +543,30 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
buf[j++] = '.'; buf[j++] = '.';
} }
} }
else if ((ot[o].size & OT_CSTRING))
{
int k, len;
unsigned char *p;
i = 0, j = 0;
while (1)
{
p = &val[i];
GETSHORT(len, p);
for (k = 0; k < len && j < buf_len; k++)
{
char c = *p++;
if (isprint((int)c))
buf[j++] = c;
}
i += len +2;
if (i >= opt_len)
break;
if (j < buf_len)
buf[j++] = ',';
}
}
#endif #endif
else else
nodecode = 1; nodecode = 1;
@@ -1628,14 +1652,15 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
unhide_metas(comma); unhide_metas(comma);
if ((netpart = split_chr(comma, '/'))) if ((netpart = split_chr(comma, '/')))
{ {
int msize, mask; int msize;
arg = split(netpart); arg = split(netpart);
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 || if (!atoi_check(netpart, &msize))
!atoi_check(netpart, &msize))
option = '?'; option = '?';
else else if (inet_pton(AF_INET, comma, &new->start))
{ {
mask = (1 << (32 - msize)) - 1; int mask = (1 << (32 - msize)) - 1;
new->is6 = 0;
new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask); new->start.s_addr = ntohl(htonl(new->start.s_addr) & ~mask);
new->end.s_addr = new->start.s_addr | htonl(mask); new->end.s_addr = new->start.s_addr | htonl(mask);
if (arg) if (arg)
@@ -1677,19 +1702,93 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
} }
} }
} }
} #ifdef HAVE_IPV6
else if ((arg = split(comma))) else if (inet_pton(AF_INET6, comma, &new->start6))
{ {
if ((new->start.s_addr = inet_addr(comma)) == (in_addr_t)-1 || u64 mask = (1LLU << (128 - msize)) - 1LLU;
(new->end.s_addr = inet_addr(arg)) == (in_addr_t)-1) u64 addrpart = addr6part(&new->start6);
new->is6 = 1;
/* prefix==64 overflows the mask calculation above */
if (msize == 64)
mask = (u64)-1LL;
new->end6 = new->start6;
setaddr6part(&new->start6, addrpart & ~mask);
setaddr6part(&new->end6, addrpart | mask);
if (msize < 64)
option = '?';
else if (arg)
{
/* generate the equivalent of
local=/<domain>/
local=/xxx.yyy.zzz.ip6.arpa/ */
if (strcmp(arg, "local") != 0 || (msize & 4 != 0))
option = '?';
else
{
struct server *serv = opt_malloc(sizeof(struct server));
in_addr_t a = ntohl(new->start.s_addr) >> 8;
char *p;
memset(serv, 0, sizeof(struct server));
serv->domain = d;
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers;
daemon->servers = serv;
serv = opt_malloc(sizeof(struct server));
memset(serv, 0, sizeof(struct server));
p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */
for (i = msize-1; i >= 0; i -= 4)
{
int dig = ((unsigned char *)&new->start6)[i>>3];
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
}
p += sprintf(p, "ip6.arpa");
serv->flags = SERV_HAS_DOMAIN | SERV_NO_ADDR;
serv->next = daemon->servers;
daemon->servers = serv;
}
}
}
#endif
else
option = '?'; option = '?';
} }
else if ((new->start.s_addr = new->end.s_addr = inet_addr(comma)) == (in_addr_t)-1) else
{
arg = split(comma);
if (inet_pton(AF_INET, comma, &new->start))
{
new->is6 = 0;
if (!arg)
new->end.s_addr = new->start.s_addr;
else if (!inet_pton(AF_INET, arg, &new->end))
option = '?';
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, comma, &new->start6))
{
new->is6 = 1;
if (!arg)
memcpy(&new->end6, &new->start6, IN6ADDRSZ);
else if (!inet_pton(AF_INET6, arg, &new->end6))
option = '?';
}
#endif
else
option = '?'; option = '?';
new->domain = d; new->domain = d;
new->next = daemon->cond_domain; new->next = daemon->cond_domain;
daemon->cond_domain = new; daemon->cond_domain = new;
}
} }
else else
daemon->domain_suffix = d; daemon->domain_suffix = d;