Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[dns] Append local domain to relative names
Try to qualify relative names in the DNS resolver using the DHCP Domain
Name.  For example:

  DHCP Domain Name: etherboot.org
  (Relative) Name: www

yields:

  www.etherboot.org

Only names with no dots ('.') will be modified.  A name with one or more
dots is unchanged.
  • Loading branch information
stefanha authored and Michael Brown committed Jan 27, 2009
1 parent a128973 commit d10a7e7
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 11 deletions.
1 change: 1 addition & 0 deletions src/include/gpxe/settings.h
Expand Up @@ -218,6 +218,7 @@ extern struct setting ip_setting __setting;
extern struct setting netmask_setting __setting;
extern struct setting gateway_setting __setting;
extern struct setting dns_setting __setting;
extern struct setting domain_setting __setting;
extern struct setting hostname_setting __setting;
extern struct setting filename_setting __setting;
extern struct setting root_path_setting __setting;
Expand Down
76 changes: 65 additions & 11 deletions src/net/udp/dns.c
Expand Up @@ -22,6 +22,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <gpxe/refcnt.h>
Expand All @@ -47,6 +48,9 @@ static struct sockaddr_tcpip nameserver = {
.st_port = htons ( DNS_PORT ),
};

/** The local domain */
static char *localdomain;

/** A DNS request */
struct dns_request {
/** Reference counter */
Expand Down Expand Up @@ -179,6 +183,27 @@ static union dns_rr_info * dns_find_rr ( struct dns_request *dns,
return NULL;
}

/**
* Append DHCP domain name if available and name is not fully qualified
*
* @v string Name as a NUL-terminated string
* @ret fqdn Fully-qualified domain name, malloc'd copy
*
* The caller must free fqdn which is allocated even if the name is already
* fully qualified.
*/
static char * dns_qualify_name ( const char *string ) {
char *fqdn;

/* Leave unchanged if already fully-qualified or no local domain */
if ( ( ! localdomain ) || ( strchr ( string, '.' ) != 0 ) )
return strdup ( string );

/* Append local domain to name */
asprintf ( &fqdn, "%s.%s", string, localdomain );
return fqdn;
}

/**
* Convert a standard NUL-terminated string to a DNS name
*
Expand Down Expand Up @@ -452,19 +477,30 @@ static struct xfer_interface_operations dns_socket_operations = {
static int dns_resolv ( struct resolv_interface *resolv,
const char *name, struct sockaddr *sa ) {
struct dns_request *dns;
char *fqdn;
int rc;

/* Fail immediately if no DNS servers */
if ( ! nameserver.st_family ) {
DBG ( "DNS not attempting to resolve \"%s\": "
"no DNS servers\n", name );
return -ENXIO;
rc = -ENXIO;
goto err_no_nameserver;
}

/* Ensure fully-qualified domain name if DHCP option was given */
fqdn = dns_qualify_name ( name );
if ( ! fqdn ) {
rc = -ENOMEM;
goto err_qualify_name;
}

/* Allocate DNS structure */
dns = zalloc ( sizeof ( *dns ) );
if ( ! dns )
return -ENOMEM;
if ( ! dns ) {
rc = -ENOMEM;
goto err_alloc_dns;
}
resolv_init ( &dns->resolv, &null_resolv_ops, &dns->refcnt );
xfer_init ( &dns->socket, &dns_socket_operations, &dns->refcnt );
dns->timer.expired = dns_timer_expired;
Expand All @@ -474,7 +510,7 @@ static int dns_resolv ( struct resolv_interface *resolv,
dns->query.dns.flags = htons ( DNS_FLAG_QUERY | DNS_FLAG_OPCODE_QUERY |
DNS_FLAG_RD );
dns->query.dns.qdcount = htons ( 1 );
dns->qinfo = ( void * ) dns_make_name ( name, dns->query.payload );
dns->qinfo = ( void * ) dns_make_name ( fqdn, dns->query.payload );
dns->qinfo->qtype = htons ( DNS_TYPE_A );
dns->qinfo->qclass = htons ( DNS_CLASS_IN );

Expand All @@ -484,7 +520,7 @@ static int dns_resolv ( struct resolv_interface *resolv,
NULL ) ) != 0 ) {
DBGC ( dns, "DNS %p could not open socket: %s\n",
dns, strerror ( rc ) );
goto err;
goto err_open_socket;
}

/* Send first DNS packet */
Expand All @@ -493,10 +529,15 @@ static int dns_resolv ( struct resolv_interface *resolv,
/* Attach parent interface, mortalise self, and return */
resolv_plug_plug ( &dns->resolv, resolv );
ref_put ( &dns->refcnt );
free ( fqdn );
return 0;

err:
err_open_socket:
err_alloc_dns:
ref_put ( &dns->refcnt );
err_qualify_name:
free ( fqdn );
err_no_nameserver:
return rc;
}

Expand All @@ -521,12 +562,20 @@ struct setting dns_setting __setting = {
.type = &setting_type_ipv4,
};

/** Domain name setting */
struct setting domain_setting __setting = {
.name = "domain",
.description = "Local domain",
.tag = DHCP_DOMAIN_NAME,
.type = &setting_type_string,
};

/**
* Apply nameserver setting
* Apply DNS settings
*
* @ret rc Return status code
*/
static int apply_nameserver_setting ( void ) {
static int apply_dns_settings ( void ) {
struct sockaddr_in *sin_nameserver =
( struct sockaddr_in * ) &nameserver;
int len;
Expand All @@ -538,10 +587,15 @@ static int apply_nameserver_setting ( void ) {
inet_ntoa ( sin_nameserver->sin_addr ) );
}

/* Get local domain DHCP option */
if ( ( len = fetch_string_setting_copy ( NULL, &domain_setting,
&localdomain ) ) >= 0 )
DBG ( "DNS local domain %s\n", localdomain );

return 0;
}

/** Nameserver setting applicator */
struct settings_applicator nameserver_applicator __settings_applicator = {
.apply = apply_nameserver_setting,
/** DNS settings applicator */
struct settings_applicator dns_applicator __settings_applicator = {
.apply = apply_dns_settings,
};

0 comments on commit d10a7e7

Please sign in to comment.