Browse Source

[dhcp] Add generic facility for using cached network settings

When a DHCP session is started (using autoboot or a command-line `dhcp
net0'), check whether the new setting use-cached (DHCP option 175.178)
is TRUE; if so, skip DHCP and rely on currently registered
settings. This lets one combine a static IP with autoboot.

Before checking the use-cached setting, call a weak
get_cached_dhcpack() hook that can be implemented by particular builds
of gPXE supporting some fashion of retrieving a cached DHCPACK packet.
If one is available, it is registered as an options source, and then
either that packet's option 175.178 or the user's prior manual
use-cached setting can allow skipping duplicate DHCP.

Using cached packets is not the default because DHCP servers are often
configured to give gPXE different options than they give a vendor PXE
client; in order to break the infinite loop of PXE chaining, one would
need to load a gPXE with an embedded image that does something more
than autoboot.

Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0-rc1
Joshua Oreman 15 years ago
parent
commit
b1ba80f8fb
4 changed files with 122 additions and 2 deletions
  1. 19
    0
      src/include/gpxe/dhcp.h
  2. 76
    0
      src/net/cachedhcp.c
  3. 21
    1
      src/net/udp/dhcp.c
  4. 6
    1
      src/usr/dhcpmgmt.c

+ 19
- 0
src/include/gpxe/dhcp.h View File

@@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
16 16
 #include <gpxe/tables.h>
17 17
 #include <gpxe/uuid.h>
18 18
 #include <gpxe/netdevice.h>
19
+#include <gpxe/uaccess.h>
19 20
 
20 21
 struct job_interface;
21 22
 struct dhcp_options;
@@ -332,6 +333,16 @@ struct dhcp_netdev_desc {
332 333
 	uint16_t device;
333 334
 } __attribute__ (( packed ));
334 335
 
336
+/** Use cached network settings
337
+ *
338
+ * Cached network settings may be available from a prior DHCP request
339
+ * (if running as a PXE NBP), non-volatile storage on the NIC, or
340
+ * settings set via the command line or an embedded image. If this
341
+ * flag is not set, it will be assumed that those sources are
342
+ * insufficient and that DHCP should still be run when autobooting.
343
+ */
344
+#define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 )
345
+
335 346
 /** BIOS drive number
336 347
  *
337 348
  * This is the drive number for a drive emulated via INT 13.  0x80 is
@@ -615,4 +626,12 @@ extern int start_dhcp ( struct job_interface *job, struct net_device *netdev );
615 626
 extern int start_pxebs ( struct job_interface *job, struct net_device *netdev,
616 627
 			 unsigned int pxe_type );
617 628
 
629
+/* In environments that can provide cached DHCP packets, this function
630
+ * should look for such a packet and call store_cached_dhcpack() with
631
+ * it if it exists.
632
+ */
633
+__weak_decl ( void, get_cached_dhcpack, ( void ), (), );
634
+
635
+extern void store_cached_dhcpack ( userptr_t data, size_t len );
636
+
618 637
 #endif /* _GPXE_DHCP_H */

+ 76
- 0
src/net/cachedhcp.c View File

@@ -0,0 +1,76 @@
1
+/*
2
+ * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdio.h>
22
+#include <stdlib.h>
23
+#include <string.h>
24
+#include <gpxe/dhcp.h>
25
+#include <gpxe/dhcppkt.h>
26
+#include <gpxe/netdevice.h>
27
+#include <gpxe/iobuf.h>
28
+#include <gpxe/uaccess.h>
29
+
30
+/** @file
31
+ *
32
+ * Cached DHCP packet handling
33
+ *
34
+ */
35
+
36
+/**
37
+ * Store cached DHCPACK packet
38
+ *
39
+ * @v data		User pointer to cached DHCP packet data
40
+ * @v len		Length of cached DHCP packet data
41
+ * @ret rc		Return status code
42
+ *
43
+ * This function should be called by the architecture-specific
44
+ * get_cached_dhcpack() handler.
45
+ */
46
+void store_cached_dhcpack ( userptr_t data, size_t len ) {
47
+	struct dhcp_packet *dhcppkt;
48
+	struct dhcphdr *dhcphdr;
49
+	struct settings *parent;
50
+	int rc;
51
+
52
+	/* Create DHCP packet */
53
+	dhcppkt = zalloc ( sizeof ( *dhcppkt ) + len );
54
+	if ( ! dhcppkt )
55
+		return;
56
+
57
+	/* Fill in data for DHCP packet */
58
+	dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( * dhcppkt ) );
59
+	copy_from_user ( dhcphdr, data, 0, len );
60
+	dhcppkt_init ( dhcppkt, dhcphdr, len );
61
+	DBG_HD ( dhcppkt->options.data, dhcppkt->options.len );
62
+
63
+	/* Register settings on the last opened network device.
64
+	 * This will have the effect of registering cached settings
65
+	 * with a network device when "dhcp netX" is performed for that
66
+	 * device, which is usually what we want.
67
+	 */
68
+	parent = netdev_settings ( last_opened_netdev() );
69
+	if ( ( rc = register_settings ( &dhcppkt->settings, parent ) ) != 0 )
70
+		DBG ( "DHCP could not register cached settings: %s\n",
71
+		      strerror ( rc ) );
72
+
73
+	dhcppkt_put ( dhcppkt );
74
+
75
+	DBG ( "DHCP registered cached settings\n" );
76
+}

+ 21
- 1
src/net/udp/dhcp.c View File

@@ -110,6 +110,14 @@ struct setting user_class_setting __setting = {
110 110
 	.type = &setting_type_string,
111 111
 };
112 112
 
113
+/** Use cached network settings */
114
+struct setting use_cached_setting __setting = {
115
+	.name = "use-cached",
116
+	.description = "Use cached network settings",
117
+	.tag = DHCP_EB_USE_CACHED,
118
+	.type = &setting_type_uint8,
119
+};
120
+
113 121
 /**
114 122
  * Name a DHCP packet type
115 123
  *
@@ -1237,16 +1245,28 @@ static struct sockaddr dhcp_peer = {
1237 1245
  *
1238 1246
  * @v job		Job control interface
1239 1247
  * @v netdev		Network device
1240
- * @ret rc		Return status code
1248
+ * @ret rc		Return status code, or positive if cached
1241 1249
  *
1242 1250
  * Starts DHCP on the specified network device.  If successful, the
1243 1251
  * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
1244 1252
  * option sources.
1253
+ *
1254
+ * On a return of 0, a background job has been started to perform the
1255
+ * DHCP request. Any nonzero return means the job has not been
1256
+ * started; a positive return value indicates the success condition of
1257
+ * having fetched the appropriate data from cached information.
1245 1258
  */
1246 1259
 int start_dhcp ( struct job_interface *job, struct net_device *netdev ) {
1247 1260
 	struct dhcp_session *dhcp;
1248 1261
 	int rc;
1249 1262
 
1263
+	/* Check for cached DHCP information */
1264
+	get_cached_dhcpack();
1265
+	if ( fetch_uintz_setting ( NULL, &use_cached_setting ) ) {
1266
+		DBG ( "DHCP using cached network settings\n" );
1267
+		return 1;
1268
+	}
1269
+
1250 1270
 	/* Allocate and initialise structure */
1251 1271
 	dhcp = zalloc ( sizeof ( *dhcp ) );
1252 1272
 	if ( ! dhcp )

+ 6
- 1
src/usr/dhcpmgmt.c View File

@@ -55,8 +55,13 @@ int dhcp ( struct net_device *netdev ) {
55 55
 	printf ( "DHCP (%s ", netdev->name );
56 56
 	while ( hlen-- )
57 57
 		printf ( "%02x%c", *(chaddr++), ( hlen ? ':' : ')' ) );
58
-	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 )
58
+
59
+	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) {
59 60
 		rc = monojob_wait ( "" );
61
+	} else if ( rc > 0 ) {
62
+		printf ( " using cached\n" );
63
+		rc = 0;
64
+	}
60 65
 
61 66
 	return rc;
62 67
 }

Loading…
Cancel
Save