[syslinux] [Etherboot-developers] gPxe functionality in pxelinux

Stefan Hajnoczi stefanha at gmail.com
Thu Nov 27 01:26:20 PST 2008


> Is there any way to get it to honor the 'domain-name' setting from DHCP and do a dns search like the libc resolver does for resolv.conf ?

The following patch appends the DHCP Domain Name setting to relative
names.  Any name with one or more "." is considered qualified and is
not affected.

DNS experts, please advise whether this is correct!  Pointers to the
relevant RFCs or source appreciated.

mcb30: I'm not sure why some code implements a settings_applicator and
keeps a local copy of the setting value.  Is this a covenience to
avoid going through the settings API every time we access the value or
is there some other reason?

Thanks,
Stefan

Warning: GMail wraps lines - use the attachment if you want to apply the patch!

>From c7489b85f1b4c25d8b39389891268d6aec86aa54 Mon Sep 17 00:00:00 2001
From: Stefan Hajnoczi <stefanha at gmail.com>
Date: Thu, 27 Nov 2008 09:30:37 +0000
Subject: [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

Names that are already qualified are not affected.
---
 src/include/gpxe/settings.h |    1 +
 src/net/udp/dns.c           |   49 ++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/src/include/gpxe/settings.h b/src/include/gpxe/settings.h
index 37c01b0..7505150 100644
--- a/src/include/gpxe/settings.h
+++ b/src/include/gpxe/settings.h
@@ -215,6 +215,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;
diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c
index 1bcdbc7..de7ac5c 100644
--- a/src/net/udp/dns.c
+++ b/src/net/udp/dns.c
@@ -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>
@@ -180,6 +181,36 @@ static union dns_rr_info * dns_find_rr ( struct
dns_request *dns,
 }

 /**
+ * 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;
+	char domain[256]; /* local domain */
+
+	/* Already fully-qualified? */
+	if ( strchr ( string, '.' ) )
+		goto treat_as_fqdn;
+
+	/* Get local domain DHCP option */
+	if ( fetch_string_setting ( NULL, &domain_setting,
+	                            domain, sizeof domain ) <= 0 )
+		goto treat_as_fqdn;
+
+	/* Append local domain to name */
+	asprintf ( &fqdn, "%s.%s", string, domain );
+	return fqdn;
+
+treat_as_fqdn:
+	return strdup ( string );
+}
+
+/**
  * Convert a standard NUL-terminated string to a DNS name
  *
  * @v string		Name as a NUL-terminated string
@@ -452,6 +483,7 @@ 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 = NULL;
 	int rc;

 	/* Fail immediately if no DNS servers */
@@ -461,6 +493,11 @@ static int dns_resolv ( struct resolv_interface *resolv,
 		return -ENXIO;
 	}

+	/* Ensure fully-qualified domain name if DHCP option was given */
+	fqdn = dns_qualify_name ( name );
+	if ( ! fqdn )
+		return -ENOMEM;
+
 	/* Allocate DNS structure */
 	dns = zalloc ( sizeof ( *dns ) );
 	if ( ! dns )
@@ -474,7 +511,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 );

@@ -493,10 +530,12 @@ 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:
 	ref_put ( &dns->refcnt );
+	free ( fqdn );
 	return rc;
 }

@@ -521,6 +560,14 @@ 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
  *
-- 
1.5.6.5
-------------- next part --------------
A non-text attachment was scrubbed...
Name: domain.diff
Type: text/x-diff
Size: 4256 bytes
Desc: not available
URL: <http://www.zytor.com/pipermail/syslinux/attachments/20081127/c9242514/attachment.bin>


More information about the Syslinux mailing list