resolv.conf: Add support for OpenBSD style resolv.conf syntax where a non-standard DNS server port can be specified using a backet syntax.

This commit is contained in:
Gregory Nutt 2016-01-14 17:55:53 -06:00
parent 8a3033643e
commit 2a5c7e9a92
5 changed files with 128 additions and 18 deletions

@ -1 +1 @@
Subproject commit 5eb7ce16316971813ced45e4869167ec55a72b45 Subproject commit a4a4be4004173c67c8ed160cc48fcea1cf57308a

View File

@ -606,23 +606,54 @@ config NETDB_RESOLVCONF_PATH
string "Path to host configuration file" string "Path to host configuration file"
default "/etc/resolv.conf" default "/etc/resolv.conf"
config NETDB_RESOLVCONF_NONSTDPORT
bool "Non-standard port support"
default n
---help---
By default, the resolv.conf file will hold only records like:
nameserver xx.xx.xx.xx
nameserver xxxx:::::::xxxx
The default port of 53 is always assumed.
If this option is selected, then OpenBSD style resolv.conf files
will be supported. This adds logic for a bracket port notation
like:
nameserver [xx.xx.xx.xx]:ppppp
nameserver [xxxx:::::::xxxx]:ppppp
endif # NETDB_RESOLVCONF endif # NETDB_RESOLVCONF
choice choice
prompt "DNS server address type" prompt "DNS server address type"
default NETDB_DNSSERVER_NOADDR default NETDB_DNSSERVER_IPv4 if NET_IPv4
default NETDB_DNSSERVER_IPv6 if !NET_IPv4 && NET_IPv6
default NETDB_DNSSERVER_NOADDR if !NET_IPv4 && !NET_IPv6
depends on !NETDB_RESOLVCONF depends on !NETDB_RESOLVCONF
config NETDB_DNSSERVER_NOADDR config NETDB_DNSSERVER_NOADDR
bool "No default DNS server address" bool "No default DNS server address"
---help---
There is not default DNS nameserver address. Application must call
dns_add_server() at runtime to add the DNS server address.
config NETDB_DNSSERVER_IPv4 config NETDB_DNSSERVER_IPv4
bool "IPv4 DNS server address" bool "IPv4 DNS server address"
depends on NET_IPv4 depends on NET_IPv4
---help---
An IPv4 default DNS nameserver address will be provided. Application
may overwrite this start default server address by calling
dns_add_server() at runtime.
config NETDB_DNSSERVER_IPv6 config NETDB_DNSSERVER_IPv6
bool "IPv6 DNS server address" bool "IPv6 DNS server address"
depends on NET_IPv6 depends on NET_IPv6
---help---
An IPv6 default DNS nameserver address will be provided. Application
may overwrite this start default server address by calling
dns_add_server() at runtime.
endchoice # DNS server address type endchoice # DNS server address type

View File

@ -80,7 +80,8 @@
# define CONFIG_NETDB_RESOLVCONF_PATH "/etc/resolv.conf" # define CONFIG_NETDB_RESOLVCONF_PATH "/etc/resolv.conf"
#endif #endif
#define DNS_MAX_LINE 80 #define DNS_MAX_ADDRSTR 48
#define DNS_MAX_LINE 64
#define NETDB_DNS_KEYWORD "nameserver" #define NETDB_DNS_KEYWORD "nameserver"
/**************************************************************************** /****************************************************************************

View File

@ -80,7 +80,11 @@ bool g_dns_address; /* true: We have the address of the DNS server */
int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen) int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
{ {
FAR FILE *stream; FAR FILE *stream;
char line[DNS_MAX_LINE]; char addrstr[DNS_MAX_ADDRSTR];
#ifdef CONFIG_NETDB_RESOLVCONF_NONSTDPORT
uint16_t port;
#endif
int status;
int ret; int ret;
stream = fopen(CONFIG_NETDB_RESOLVCONF_PATH, "at"); stream = fopen(CONFIG_NETDB_RESOLVCONF_PATH, "at");
@ -107,20 +111,26 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
{ {
FAR struct sockaddr_in *in4 = (FAR struct sockaddr_in *)addr; FAR struct sockaddr_in *in4 = (FAR struct sockaddr_in *)addr;
if (inet_ntop(AF_INET, &in4->sin_addr, line, DNS_MAX_LINE) == NULL) if (inet_ntop(AF_INET, &in4->sin_addr, addrstr, DNS_MAX_ADDRSTR) == NULL)
{ {
ret = -errno; ret = -errno;
ndbg("ERROR: inet_ntop failed: %d\n", errcode); ndbg("ERROR: inet_ntop failed: %d\n", errcode);
DEBUGASSERT(errcode < 0); DEBUGASSERT(errcode < 0);
goto errout; goto errout;
} }
#ifdef CONFIG_NETDB_RESOLVCONF_NONSTDPORT
/* Get the port number */
port = ntohs(in4->sin_port);
#endif
} }
} }
else else
#endif #endif
#ifdef CONFIG_NET_IPv6 #ifdef CONFIG_NET_IPv6
/* Check for an IPv4 address */ /* Check for an IPv6 address */
if (addr->sa_family == AF_INET6) if (addr->sa_family == AF_INET6)
{ {
@ -133,13 +143,19 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
{ {
FAR struct sockaddr_in6 *in6 = (FAR struct sockaddr_in6 *)addr; FAR struct sockaddr_in6 *in6 = (FAR struct sockaddr_in6 *)addr;
if (inet_ntop(AF_INET6, &in6->sin6_addr, line, DNS_MAX_LINE) == NULL) if (inet_ntop(AF_INET6, &in6->sin6_addr, addrstr, DNS_MAX_ADDRSTR) == NULL)
{ {
ret = -errno; ret = -errno;
ndbg("ERROR: inet_ntop failed: %d\n", errcode); ndbg("ERROR: inet_ntop failed: %d\n", errcode);
DEBUGASSERT(errcode < 0); DEBUGASSERT(errcode < 0);
goto errout; goto errout;
} }
#ifdef CONFIG_NETDB_RESOLVCONF_NONSTDPORT
/* Get the port number */
port = ntohs(in6->sin6_port);
#endif
} }
} }
else else
@ -151,9 +167,30 @@ int dns_add_nameserver(FAR const struct sockaddr *addr, socklen_t addrlen)
goto errout; goto errout;
} }
/* Write the new record to the end of the resolv.conf file */ /* Write the new record to the end of the resolv.conf file. */
if (fprintf(stream, "%s %s\n", NETDB_DNS_KEYWORD, line) < 0) #ifdef CONFIG_NETDB_RESOLVCONF_NONSTDPORT
/* The OpenBSD version supports a [host]:port syntax. When a non-standard
* port is specified the host address must be enclosed in square brackets.
* For example:
*
* nameserver [10.0.0.1]:5353
* nameserver [::1]:5353
*/
if (port != 0 && port != DNS_DEFAULT_PORT)
{
status = fprintf(stream, "%s [%s]:%u\n",
NETDB_DNS_KEYWORD, addrstr, port);
}
else
#endif
{
status = fprintf(stream, "%s %s\n",
NETDB_DNS_KEYWORD, addrstr);
}
if (status < 0)
{ {
ret = -errno; ret = -errno;
ndbg("ERROR: fprintf failed: %d\n", errcode); ndbg("ERROR: fprintf failed: %d\n", errcode);

View File

@ -40,6 +40,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
@ -94,6 +95,7 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
char line[DNS_MAX_LINE]; char line[DNS_MAX_LINE];
FAR char *addrstr; FAR char *addrstr;
FAR char *ptr; FAR char *ptr;
uint16_t port;
int keylen; int keylen;
int ret; int ret;
@ -133,9 +135,12 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
ptr = find_spaces(addrstr); ptr = find_spaces(addrstr);
*ptr = '\0'; *ptr = '\0';
/* Convert the address string to a binary representation */ /* Convert the address string to a binary representation. */
/* REVISIT: We really need a customizable port number. The
* OpenBSD version supports a [host]:port syntax. When a port = HTONS(DNS_DEFAULT_PORT);
#ifdef CONFIG_NETDB_RESOLVCONF_NONSTDPORT
/* The OpenBSD version supports a [host]:port syntax. When a
* non-standard port is specified the host address must be * non-standard port is specified the host address must be
* enclosed in square brackets. For example: * enclosed in square brackets. For example:
* *
@ -143,6 +148,46 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
* nameserver [::1]:5353 * nameserver [::1]:5353
*/ */
if (*addrstr == '[')
{
/* Make sure that ther is a right bracket */
ptr = strchr(addrstr, ']');
if (ptr == NULL)
{
ndbg("ERROR: Missing right bracket after %s\n", line);
continue;
}
/* Replace the right bracket with a NULL terminator */
addrstr++;
*ptr++ = '\0';
/* Get the port number following the right bracket */
if (*ptr == ':')
{
FAR char *portstr;
int tmp;
/* Isolate the port string */
portstr = ptr;
ptr = find_spaces(addrstr);
*ptr = '\0';
/* Get the port number */
tmp = atoi(portstr);
if (tmp != 0)
{
port = htons(tmp);
}
}
}
#endif /* CONFIG_NETDB_RESOLVCONF_NONSTDPORT */
#ifdef CONFIG_NET_IPv4 #ifdef CONFIG_NET_IPv4
/* Try to convert the IPv4 address */ /* Try to convert the IPv4 address */
@ -152,10 +197,8 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
if (ret == 1) if (ret == 1)
{ {
/* REVISIT: We really need a customizable port number */
u.ipv4.sin_family = AF_INET; u.ipv4.sin_family = AF_INET;
u.ipv4.sin_port = HTONS(DNS_DEFAULT_PORT); u.ipv4.sin_port = port;
ret = callback(arg, (FAR struct sockaddr *)&u.ipv4, ret = callback(arg, (FAR struct sockaddr *)&u.ipv4,
sizeof(struct sockaddr_in)); sizeof(struct sockaddr_in));
} }
@ -173,10 +216,8 @@ int dns_foreach_nameserver(dns_callback_t callback, FAR void *arg)
if (ret == 1) if (ret == 1)
{ {
/* REVISIT: We really need a customizable port number */
u.ipv6.sin6_family = AF_INET6; u.ipv6.sin6_family = AF_INET6;
u.ipv6.sin6_port = HTONS(DNS_DEFAULT_PORT); u.ipv6.sin6_port = port;
ret = callback(arg, (FAR struct sockaddr *)&u.ipv6, ret = callback(arg, (FAR struct sockaddr *)&u.ipv6,
sizeof(struct sockaddr_in6)); sizeof(struct sockaddr_in6));
} }