summaryrefslogtreecommitdiffstats
path: root/src/net/udp
diff options
context:
space:
mode:
authorMichael Brown2008-03-25 21:46:16 +0100
committerMichael Brown2008-03-25 21:46:16 +0100
commit92d15eff30410dcb0ec406e06b131fb7d9179ffd (patch)
tree191d29013372b541d353bbfa55114b8060dd557c /src/net/udp
parent[PXEXT] Avoid returning a false EOF when we have an empty buffer queued (diff)
downloadipxe-92d15eff30410dcb0ec406e06b131fb7d9179ffd.tar.gz
ipxe-92d15eff30410dcb0ec406e06b131fb7d9179ffd.tar.xz
ipxe-92d15eff30410dcb0ec406e06b131fb7d9179ffd.zip
[Settings] Remove assumption that all settings have DHCP tag values
Allow for settings to be described by something other than a DHCP option tag if desirable. Currently used only for the MAC address setting. Separate out fake DHCP packet creation code from dhcp.c to fakedhcp.c. Remove notion of settings from dhcppkt.c. Rationalise dhcp.c to use settings API only for final registration of the DHCP options, rather than using {store,fetch}_setting throughout.
Diffstat (limited to 'src/net/udp')
-rw-r--r--src/net/udp/dhcp.c303
-rw-r--r--src/net/udp/dns.c17
-rw-r--r--src/net/udp/tftp.c17
3 files changed, 154 insertions, 183 deletions
diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c
index 8789f925..98b8af0b 100644
--- a/src/net/udp/dhcp.c
+++ b/src/net/udp/dhcp.c
@@ -130,9 +130,6 @@ static uint32_t dhcp_xid ( struct net_device *netdev ) {
return xid;
}
-/** Settings block name used for ProxyDHCP responses */
-#define PROXYDHCP_SETTINGS_NAME "proxydhcp"
-
/**
* Create a DHCP packet
*
@@ -180,12 +177,12 @@ int create_dhcp_packet ( struct dhcp_packet *dhcppkt,
memcpy ( dhcphdr->chaddr, netdev->ll_addr, hlen );
memcpy ( dhcphdr->options, options->data, options_len );
- /* Initialise DHCP packet structure and settings interface */
+ /* Initialise DHCP packet structure */
memset ( dhcppkt, 0, sizeof ( *dhcppkt ) );
- dhcppkt_init ( dhcppkt, NULL, data, max_len );
+ dhcppkt_init ( dhcppkt, data, max_len );
/* Set DHCP_MESSAGE_TYPE option */
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_MESSAGE_TYPE,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_MESSAGE_TYPE,
&msgtype, sizeof ( msgtype ) ) ) != 0 )
return rc;
@@ -230,10 +227,10 @@ struct dhcp_client_uuid {
* @v max_len Size of DHCP packet buffer
* @ret rc Return status code
*/
-static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
- struct net_device *netdev,
- struct dhcp_packet *dhcpoffer,
- void *data, size_t max_len ) {
+int create_dhcp_request ( struct dhcp_packet *dhcppkt,
+ struct net_device *netdev,
+ struct dhcp_packet *dhcpoffer,
+ void *data, size_t max_len ) {
struct device_description *desc = &netdev->dev->desc;
struct dhcp_netdev_desc dhcp_desc;
struct dhcp_client_id client_id;
@@ -258,27 +255,26 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
struct in_addr server_id;
struct in_addr requested_ip;
- if ( ( rc = fetch_ipv4_setting ( &dhcpoffer->settings,
- DHCP_SERVER_IDENTIFIER,
- &server_id ) ) < 0 ) {
+ if ( dhcppkt_fetch ( dhcpoffer, DHCP_SERVER_IDENTIFIER,
+ &server_id, sizeof ( server_id ) )
+ != sizeof ( server_id ) ) {
DBG ( "DHCP offer missing server identifier\n" );
return -EINVAL;
}
- if ( ( rc = fetch_ipv4_setting ( &dhcpoffer->settings,
- DHCP_EB_YIADDR,
- &requested_ip ) ) < 0 ) {
+ if ( dhcppkt_fetch ( dhcpoffer, DHCP_EB_YIADDR,
+ &requested_ip, sizeof ( requested_ip ) )
+ != sizeof ( requested_ip ) ) {
DBG ( "DHCP offer missing IP address\n" );
return -EINVAL;
}
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_SERVER_IDENTIFIER, &server_id,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_SERVER_IDENTIFIER,
+ &server_id,
sizeof ( server_id ) ) ) != 0 ) {
DBG ( "DHCP could not set server identifier: %s\n ",
strerror ( rc ) );
return rc;
}
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_REQUESTED_ADDRESS,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_REQUESTED_ADDRESS,
&requested_ip,
sizeof ( requested_ip ) ) ) != 0 ){
DBG ( "DHCP could not set requested address: %s\n",
@@ -289,8 +285,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
/* Add options to identify the feature list */
dhcp_features_len = ( dhcp_features_end - dhcp_features );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_EB_ENCAP,
- dhcp_features, dhcp_features_len ) ) !=0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_ENCAP, dhcp_features,
+ dhcp_features_len ) ) != 0 ) {
DBG ( "DHCP could not set features list option: %s\n",
strerror ( rc ) );
return rc;
@@ -300,8 +296,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
dhcp_desc.type = desc->bus_type;
dhcp_desc.vendor = htons ( desc->vendor );
dhcp_desc.device = htons ( desc->device );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_EB_BUS_ID,
- &dhcp_desc, sizeof ( dhcp_desc ) ) ) !=0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_EB_BUS_ID, &dhcp_desc,
+ sizeof ( dhcp_desc ) ) ) != 0 ) {
DBG ( "DHCP could not set bus ID option: %s\n",
strerror ( rc ) );
return rc;
@@ -314,8 +310,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
ll_addr_len = netdev->ll_protocol->ll_addr_len;
assert ( ll_addr_len <= sizeof ( client_id.ll_addr ) );
memcpy ( client_id.ll_addr, netdev->ll_addr, ll_addr_len );
- if ( ( rc = store_setting ( &dhcppkt->settings, DHCP_CLIENT_ID,
- &client_id, ( ll_addr_len + 1 ) ) ) != 0 ){
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_ID, &client_id,
+ ( ll_addr_len + 1 ) ) ) != 0 ) {
DBG ( "DHCP could not set client ID: %s\n",
strerror ( rc ) );
return rc;
@@ -324,8 +320,8 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
/* Add client UUID, if we have one. Required for PXE. */
client_uuid.type = DHCP_CLIENT_UUID_TYPE;
if ( ( rc = get_uuid ( &client_uuid.uuid ) ) == 0 ) {
- if ( ( rc = store_setting ( &dhcppkt->settings,
- DHCP_CLIENT_UUID, &client_uuid,
+ if ( ( rc = dhcppkt_store ( dhcppkt, DHCP_CLIENT_UUID,
+ &client_uuid,
sizeof ( client_uuid ) ) ) != 0 ) {
DBG ( "DHCP could not set client UUID: %s\n",
strerror ( rc ) );
@@ -336,169 +332,109 @@ static int create_dhcp_request ( struct dhcp_packet *dhcppkt,
return 0;
}
-/**
- * Create DHCPDISCOVER packet
+/****************************************************************************
*
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
+ * DHCP settings
*
- * Used by external code.
*/
-int create_dhcpdiscover ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- int rc;
- if ( ( rc = create_dhcp_request ( &dhcppkt, netdev, NULL, data,
- max_len ) ) != 0 ) {
- DBG ( "Could not create DHCPDISCOVER: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
+/** A DHCP settings block */
+struct dhcp_settings {
+ /** Reference counter */
+ struct refcnt refcnt;
+ /** Containing I/O buffer */
+ struct io_buffer *iobuf;
+ /** DHCP packet */
+ struct dhcp_packet dhcppkt;
+ /** Setting interface */
+ struct settings settings;
+};
/**
- * Create DHCPACK packet
+ * Free DHCP settings block
*
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
- *
- * Used by external code.
+ * @v refcnt Reference counter
*/
-int create_dhcpack ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- int rc;
-
- /* Create base DHCPACK packet */
- if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
- data, max_len ) ) != 0 ) {
- DBG ( "Could not create DHCPACK: %s\n", strerror ( rc ) );
- return rc;
- }
-
- /* Merge in globally-scoped settings, then netdev-specific
- * settings. Do it in this order so that netdev-specific
- * settings take precedence regardless of stated priorities.
- */
- if ( ( rc = copy_settings ( &dhcppkt.settings, NULL ) ) != 0 ) {
- DBG ( "Could not set DHCPACK global settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
- if ( ( rc = copy_settings ( &dhcppkt.settings,
- netdev_settings ( netdev ) ) ) != 0 ) {
- DBG ( "Could not set DHCPACK netdev settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
+static void dhcpset_free ( struct refcnt *refcnt ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( refcnt, struct dhcp_settings, refcnt );
- return 0;
+ free_iob ( dhcpset->iobuf );
+ free ( dhcpset );
}
/**
- * Create ProxyDHCPACK packet
- *
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
+ * Decrement reference count on DHCP settings block
*
- * Used by external code.
+ * @v dhcpset DHCP settings block
*/
-int create_proxydhcpack ( struct net_device *netdev,
- void *data, size_t max_len ) {
- struct dhcp_packet dhcppkt;
- struct settings *settings;
- int rc;
-
- /* Identify ProxyDHCP settings */
- settings = find_settings ( PROXYDHCP_SETTINGS_NAME );
-
- /* No ProxyDHCP settings => return empty block */
- if ( ! settings ) {
- memset ( data, 0, max_len );
- return 0;
- }
-
- /* Create base DHCPACK packet */
- if ( ( rc = create_dhcp_packet ( &dhcppkt, netdev, DHCPACK, NULL,
- data, max_len ) ) != 0 ) {
- DBG ( "Could not create ProxyDHCPACK: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- /* Merge in ProxyDHCP options */
- if ( ( rc = copy_settings ( &dhcppkt.settings, settings ) ) != 0 ) {
- DBG ( "Could not set ProxyDHCPACK settings: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- return 0;
+static inline void dhcpset_put ( struct dhcp_settings *dhcpset ) {
+ ref_put ( &dhcpset->refcnt );
}
-/****************************************************************************
- *
- * DHCP packets contained in I/O buffers
+/**
+ * Store value of DHCP setting
*
+ * @v settings Settings block
+ * @v setting Setting to store
+ * @v data Setting data, or NULL to clear setting
+ * @v len Length of setting data
+ * @ret rc Return status code
*/
+static int dhcpset_store ( struct settings *settings, struct setting *setting,
+ const void *data, size_t len ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( settings, struct dhcp_settings, settings );
-/** A DHCP packet contained in an I/O buffer */
-struct dhcp_iobuf_packet {
- /** DHCP packet */
- struct dhcp_packet dhcppkt;
- /** Reference counter */
- struct refcnt refcnt;
- /** Containing I/O buffer */
- struct io_buffer *iobuf;
-};
+ return dhcppkt_store ( &dhcpset->dhcppkt, setting->tag, data, len );
+}
/**
- * Free DHCP packet contained in an I/O buffer
+ * Fetch value of setting
*
- * @v refcnt Reference counter
+ * @v settings Settings block, or NULL to search all blocks
+ * @v setting Setting to fetch
+ * @v data Buffer to fill with setting data
+ * @v len Length of buffer
+ * @ret len Length of setting data, or negative error
*/
-static void dhcpiob_free ( struct refcnt *refcnt ) {
- struct dhcp_iobuf_packet *dhcpiob =
- container_of ( refcnt, struct dhcp_iobuf_packet, refcnt );
+static int dhcpset_fetch ( struct settings *settings, struct setting *setting,
+ void *data, size_t len ) {
+ struct dhcp_settings *dhcpset =
+ container_of ( settings, struct dhcp_settings, settings );
- free_iob ( dhcpiob->iobuf );
- free ( dhcpiob );
+ return dhcppkt_fetch ( &dhcpset->dhcppkt, setting->tag, data, len );
}
+/** DHCP settings operations */
+static struct settings_operations dhcpset_settings_operations = {
+ .store = dhcpset_store,
+ .fetch = dhcpset_fetch,
+};
+
/**
- * Create DHCP packet from I/O buffer
+ * Create DHCP setting block from I/O buffer
*
* @v iobuf I/O buffer
- * @ret dhcpiob DHCP packet contained in I/O buffer
+ * @ret dhcpset DHCP settings block
*
* This function takes ownership of the I/O buffer. Future accesses
- * must be via the @c dhcpiob data structure.
+ * must be via the @c dhcpset data structure.
*/
-static struct dhcp_iobuf_packet * dhcpiob_create ( struct io_buffer *iobuf ) {
- struct dhcp_iobuf_packet *dhcpiob;
-
- dhcpiob = zalloc ( sizeof ( *dhcpiob ) );
- if ( dhcpiob ) {
- dhcpiob->refcnt.free = dhcpiob_free;
- dhcpiob->iobuf = iobuf;
- dhcppkt_init ( &dhcpiob->dhcppkt, &dhcpiob->refcnt,
+static struct dhcp_settings * dhcpset_create_iob ( struct io_buffer *iobuf ) {
+ struct dhcp_settings *dhcpset;
+
+ dhcpset = zalloc ( sizeof ( *dhcpset ) );
+ if ( dhcpset ) {
+ dhcpset->refcnt.free = dhcpset_free;
+ dhcpset->iobuf = iobuf;
+ dhcppkt_init ( &dhcpset->dhcppkt,
iobuf->data, iob_len ( iobuf ) );
+ settings_init ( &dhcpset->settings,
+ &dhcpset_settings_operations, &dhcpset->refcnt,
+ DHCP_SETTINGS_NAME );
}
- return dhcpiob;
-}
-
-static void dhcpiob_put ( struct dhcp_iobuf_packet *dhcpiob ) {
- if ( dhcpiob )
- ref_put ( &dhcpiob->refcnt );
+ return dhcpset;
}
/****************************************************************************
@@ -526,9 +462,9 @@ struct dhcp_session {
*/
int state;
/** Response obtained from DHCP server */
- struct dhcp_iobuf_packet *response;
+ struct dhcp_settings *response;
/** Response obtained from ProxyDHCP server */
- struct dhcp_iobuf_packet *proxy_response;
+ struct dhcp_settings *proxy_response;
/** Retransmission timer */
struct retry_timer timer;
/** Session start time (in ticks) */
@@ -545,8 +481,8 @@ static void dhcp_free ( struct refcnt *refcnt ) {
container_of ( refcnt, struct dhcp_session, refcnt );
netdev_put ( dhcp->netdev );
- dhcpiob_put ( dhcp->response );
- dhcpiob_put ( dhcp->proxy_response );
+ dhcpset_put ( dhcp->response );
+ dhcpset_put ( dhcp->proxy_response );
free ( dhcp );
}
@@ -584,7 +520,7 @@ static int dhcp_register_settings ( struct dhcp_session *dhcp ) {
/* Register ProxyDHCP settings, if present */
if ( dhcp->proxy_response ) {
- settings = &dhcp->proxy_response->dhcppkt.settings;
+ settings = &dhcp->proxy_response->settings;
settings->name = PROXYDHCP_SETTINGS_NAME;
old_settings = find_settings ( settings->name );
if ( old_settings )
@@ -595,7 +531,7 @@ static int dhcp_register_settings ( struct dhcp_session *dhcp ) {
/* Register DHCP settings */
parent = netdev_settings ( dhcp->netdev );
- settings = &dhcp->response->dhcppkt.settings;
+ settings = &dhcp->response->settings;
old_settings = find_child_settings ( parent, settings->name );
if ( old_settings )
unregister_settings ( old_settings );
@@ -701,24 +637,24 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
struct xfer_metadata *meta __unused ) {
struct dhcp_session *dhcp =
container_of ( xfer, struct dhcp_session, xfer );
- struct dhcp_iobuf_packet *response;
- struct dhcp_iobuf_packet **store_response;
+ struct dhcp_settings *response;
+ struct dhcp_settings **store_response;
struct dhcphdr *dhcphdr;
- struct settings *settings;
- unsigned int msgtype;
+ uint8_t msgtype = 0;
+ uint8_t priority = 0;
+ uint8_t existing_priority = 0;
unsigned long elapsed;
int is_proxy;
- int ignore_proxy;
+ uint8_t ignore_proxy = 0;
int rc;
/* Convert packet into a DHCP-packet-in-iobuf */
- response = dhcpiob_create ( iobuf );
+ response = dhcpset_create_iob ( iobuf );
if ( ! response ) {
DBGC ( dhcp, "DHCP %p could not store DHCP packet\n", dhcp );
return -ENOMEM;
}
dhcphdr = response->dhcppkt.dhcphdr;
- settings = &response->dhcppkt.settings;
/* Check for matching transaction ID */
if ( dhcphdr->xid != dhcp_xid ( dhcp->netdev ) ) {
@@ -730,7 +666,8 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
/* Determine and verify message type */
is_proxy = ( dhcphdr->yiaddr.s_addr == 0 );
- msgtype = fetch_uintz_setting ( settings, DHCP_MESSAGE_TYPE );
+ dhcppkt_fetch ( &response->dhcppkt, DHCP_MESSAGE_TYPE, &msgtype,
+ sizeof ( msgtype ) );
DBGC ( dhcp, "DHCP %p received %s%s\n", dhcp,
( is_proxy ? "Proxy" : "" ), dhcp_msgtype_name ( msgtype ) );
if ( ( ( dhcp->state != DHCPDISCOVER ) || ( msgtype != DHCPOFFER ) ) &&
@@ -746,14 +683,18 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
* currently-stored options.
*/
store_response = ( is_proxy ? &dhcp->proxy_response : &dhcp->response);
- if ( ( ! *store_response ) ||
- ( fetch_uintz_setting ( settings, DHCP_EB_PRIORITY ) >=
- fetch_uintz_setting ( &(*store_response)->dhcppkt.settings,
- DHCP_EB_PRIORITY ) ) ) {
- dhcpiob_put ( *store_response );
+ if ( *store_response ) {
+ dhcppkt_fetch ( &(*store_response)->dhcppkt, DHCP_EB_PRIORITY,
+ &existing_priority,
+ sizeof ( existing_priority ) );
+ }
+ dhcppkt_fetch ( &response->dhcppkt, DHCP_EB_PRIORITY, &priority,
+ sizeof ( priority ) );
+ if ( priority >= existing_priority ) {
+ dhcpset_put ( *store_response );
*store_response = response;
} else {
- dhcpiob_put ( response );
+ dhcpset_put ( response );
}
/* If we don't yet have a standard DHCP response (i.e. one
@@ -763,8 +704,8 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
goto out;
/* Handle DHCP response */
- ignore_proxy = fetch_uintz_setting ( &dhcp->response->dhcppkt.settings,
- DHCP_EB_NO_PROXYDHCP );
+ dhcppkt_fetch ( &dhcp->response->dhcppkt, DHCP_EB_NO_PROXYDHCP,
+ &ignore_proxy, sizeof ( ignore_proxy ) );
switch ( dhcp->state ) {
case DHCPDISCOVER:
/* If we have allowed sufficient time for ProxyDHCP
@@ -780,7 +721,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
case DHCPREQUEST:
/* DHCP finished; register options and exit */
if ( ignore_proxy && dhcp->proxy_response ) {
- dhcpiob_put ( dhcp->proxy_response );
+ dhcpset_put ( dhcp->proxy_response );
dhcp->proxy_response = NULL;
}
if ( ( rc = dhcp_register_settings ( dhcp ) ) != 0 ) {
@@ -797,7 +738,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer,
return 0;
out_discard:
- dhcpiob_put ( response );
+ dhcpset_put ( response );
return 0;
}
diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c
index 5e632d18..1bcdbc7e 100644
--- a/src/net/udp/dns.c
+++ b/src/net/udp/dns.c
@@ -506,6 +506,21 @@ struct resolver dns_resolver __resolver ( RESOLV_NORMAL ) = {
.resolv = dns_resolv,
};
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** DNS server setting */
+struct setting dns_setting __setting = {
+ .name = "dns",
+ .description = "DNS server",
+ .tag = DHCP_DNS_SERVERS,
+ .type = &setting_type_ipv4,
+};
+
/**
* Apply nameserver setting
*
@@ -516,7 +531,7 @@ static int apply_nameserver_setting ( void ) {
( struct sockaddr_in * ) &nameserver;
int len;
- if ( ( len = fetch_ipv4_setting ( NULL, DHCP_DNS_SERVERS,
+ if ( ( len = fetch_ipv4_setting ( NULL, &dns_setting,
&sin_nameserver->sin_addr ) ) >= 0 ){
sin_nameserver->sin_family = AF_INET;
DBG ( "DNS using nameserver %s\n",
diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c
index 8bd2b80b..e49bcf9f 100644
--- a/src/net/udp/tftp.c
+++ b/src/net/udp/tftp.c
@@ -1093,6 +1093,21 @@ struct uri_opener mtftp_uri_opener __uri_opener = {
.open = mtftp_open,
};
+/******************************************************************************
+ *
+ * Settings
+ *
+ ******************************************************************************
+ */
+
+/** TFTP server setting */
+struct setting next_server_setting __setting = {
+ .name = "next-server",
+ .description = "TFTP server",
+ .tag = DHCP_EB_SIADDR,
+ .type = &setting_type_ipv4,
+};
+
/**
* Apply TFTP configuration settings
*
@@ -1106,7 +1121,7 @@ static int tftp_apply_settings ( void ) {
/* Retrieve TFTP server setting */
last_tftp_server = tftp_server;
- fetch_ipv4_setting ( NULL, DHCP_EB_SIADDR, &tftp_server );
+ fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
/* If TFTP server setting has changed, set the current working
* URI to match. Do it only when the TFTP server has changed