Rationalise domain parsing for --rev-server and --domain.

This commit is contained in:
Simon Kelley
2021-06-26 18:51:05 +01:00
parent d515223bb5
commit c9efe8e5e1

View File

@@ -932,58 +932,53 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
return NULL; return NULL;
} }
static struct server *add_rev4(struct in_addr addr, int msize) static int domain_rev4(char *domain, struct in_addr addr, int msize)
{ {
struct server *serv = opt_malloc(sizeof(struct server));
in_addr_t a = ntohl(addr.s_addr); in_addr_t a = ntohl(addr.s_addr);
char *p; char *p;
memset(serv, 0, sizeof(struct server)); *domain = 0;
p = serv->domain = opt_malloc(29); /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
switch (msize) switch (msize)
{ {
case 32: case 32:
p += sprintf(p, "%u.", a & 0xff); domain += sprintf(domain, "%u.", a & 0xff);
/* fall through */ /* fall through */
case 24: case 24:
p += sprintf(p, "%d.", (a >> 8) & 0xff); domain += sprintf(domain, "%d.", (a >> 8) & 0xff);
/* fall through */ /* fall through */
case 16: case 16:
p += sprintf(p, "%d.", (a >> 16) & 0xff); domain += sprintf(domain, "%d.", (a >> 16) & 0xff);
/* fall through */ /* fall through */
case 8: case 8:
p += sprintf(p, "%d.", (a >> 24) & 0xff); domain += sprintf(domain, "%d.", (a >> 24) & 0xff);
break; break;
default: default:
free(serv->domain); return 0;
free(serv);
return NULL;
} }
p += sprintf(p, "in-addr.arpa"); domain += sprintf(domain, "in-addr.arpa");
return serv;
return 1;
} }
static struct server *add_rev6(struct in6_addr *addr, int msize) static int domain_rev6(char *domain, struct in6_addr *addr, int msize)
{ {
struct server *serv = opt_malloc(sizeof(struct server));
char *p;
int i; int i;
memset(serv, 0, sizeof(struct server)); if (msize%4)
p = serv->domain = opt_malloc(73); /* strlen("32*<n.>ip6.arpa")+1 */ return 0;
*domain = 0;
for (i = msize-1; i >= 0; i -= 4) for (i = msize-1; i >= 0; i -= 4)
{ {
int dig = ((unsigned char *)addr)[i>>3]; int dig = ((unsigned char *)addr)[i>>3];
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4); domain += sprintf(domain, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
} }
p += sprintf(p, "ip6.arpa"); domain += sprintf(domain, "ip6.arpa");
return serv; return 1;
} }
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
@@ -2258,7 +2253,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
set_option_bool(OPT_RESOLV_DOMAIN); set_option_bool(OPT_RESOLV_DOMAIN);
else else
{ {
char *d; char *d, *d_raw = arg;
comma = split(arg); comma = split(arg);
if (!(d = canonicalise_opt(arg))) if (!(d = canonicalise_opt(arg)))
ret_err(gen_err); ret_err(gen_err);
@@ -2299,23 +2294,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err_free(gen_err, new); ret_err_free(gen_err, new);
else else
{ {
/* generate the equivalent of char domain[29]; /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
local=/xxx.yyy.zzz.in-addr.arpa/ */ /* local=/xxx.yyy.zzz.in-addr.arpa/ */
struct server *serv = add_rev4(new->start, msize); /* domain_rev4 can't fail here, msize checked above. */
if (!serv) domain_rev4(domain, new->start, msize);
ret_err_free(_("bad prefix"), new); add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, domain, NULL);
serv->flags |= SERV_LITERAL_ADDRESS;
serv->next = daemon->local_domains;
daemon->local_domains = serv;
/* local=/<domain>/ */ /* local=/<domain>/ */
serv = opt_malloc(sizeof(struct server)); /* d_raw can't failed to canonicalise here, checked above. */
memset(serv, 0, sizeof(struct server)); add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
serv->domain = d;
serv->flags = SERV_LITERAL_ADDRESS;
serv->next = daemon->local_domains;
daemon->local_domains = serv;
} }
} }
} }
@@ -2347,20 +2334,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err_free(gen_err, new); ret_err_free(gen_err, new);
else else
{ {
char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
/* generate the equivalent of /* generate the equivalent of
local=/xxx.yyy.zzz.ip6.arpa/ */ local=/xxx.yyy.zzz.ip6.arpa/ */
struct server *serv = add_rev6(&new->start6, msize); domain_rev6(domain, &new->start6, msize);
serv->flags |= SERV_LITERAL_ADDRESS; add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, domain, NULL);
serv->next = daemon->local_domains;
daemon->local_domains = serv;
/* local=/<domain>/ */ /* local=/<domain>/ */
serv = opt_malloc(sizeof(struct server)); /* d_raw can't failed to canonicalise here, checked above. */
memset(serv, 0, sizeof(struct server)); add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, d_raw, NULL);
serv->domain = d;
serv->flags = SERV_LITERAL_ADDRESS;
serv->next = daemon->local_domains;
daemon->local_domains = serv;
} }
} }
} }
@@ -2714,9 +2696,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
{ {
char *string; char *string;
int size; int size;
struct server *serv; u16 flags = 0;
char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
struct in_addr addr4; struct in_addr addr4;
struct in6_addr addr6; struct in6_addr addr6;
union mysockaddr serv_addr, source_addr;
char interface[IF_NAMESIZE+1];
unhide_metas(arg); unhide_metas(arg);
if (!arg) if (!arg)
@@ -2729,28 +2714,27 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (inet_pton(AF_INET, arg, &addr4)) if (inet_pton(AF_INET, arg, &addr4))
{ {
serv = add_rev4(addr4, size); if (!domain_rev4(domain, addr4, size))
if (!serv) ret_err(_("bad IPv4 prefix"));
ret_err(_("bad prefix"));
serv->next = daemon->servers;
daemon->servers = serv;
} }
else if (inet_pton(AF_INET6, arg, &addr6)) else if (inet_pton(AF_INET6, arg, &addr6))
{ {
serv = add_rev6(&addr6, size); if (!domain_rev6(domain, &addr6, size))
serv->next = daemon->servers; ret_err(_("bad IPv6 prefix"));
daemon->servers = serv;
} }
else else
ret_err(gen_err); ret_err(gen_err);
string = parse_server(comma, &serv->addr, &serv->source_addr, serv->interface, &serv->flags); if (!comma)
flags |= SERV_LITERAL_ADDRESS;
if (string) else if ((string = parse_server(comma, &serv_addr, &source_addr, interface, &flags)))
ret_err(string); ret_err(string);
if (servers_only) if (servers_only)
serv->flags |= SERV_FROM_FILE; flags |= SERV_FROM_FILE;
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
ret_err(gen_err);
break; break;
} }