Browse Source

[uri] Generalise tftp_uri() to pxe_uri()

Merge the functionality of parse_next_server_and_filename() and
tftp_uri() into a single pxe_uri(), which takes a server address
(IPv4/IPv6/none) and a filename, and produces a URI using the rule:

 - if the filename is a hierarchical absolute URI (i.e. includes a
   scheme such as "http://" or "tftp://") then use that URI and ignore
   the server address,

 - otherwise, if the server address is recognised (according to
   sa_family) then construct a TFTP URI based on the server address,
   port, and filename

 - otherwise fail.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
53d2d9e3c3
5 changed files with 159 additions and 117 deletions
  1. 11
    13
      src/arch/i386/interface/pxe/pxe_tftp.c
  2. 37
    16
      src/core/uri.c
  3. 2
    2
      src/include/ipxe/uri.h
  4. 77
    29
      src/tests/uri_test.c
  5. 32
    57
      src/usr/autoboot.c

+ 11
- 13
src/arch/i386/interface/pxe/pxe_tftp.c View File

159
 	.xfer = INTF_INIT ( pxe_tftp_xfer_desc ),
159
 	.xfer = INTF_INIT ( pxe_tftp_xfer_desc ),
160
 };
160
 };
161
 
161
 
162
-/**
163
- * Maximum length of a PXE TFTP URI
164
- *
165
- * The PXE TFTP API provides 128 characters for the filename; the
166
- * extra 128 bytes allow for the remainder of the URI.
167
- */
168
-#define PXE_TFTP_URI_LEN 256
169
-
170
 /**
162
 /**
171
  * Open PXE TFTP connection
163
  * Open PXE TFTP connection
172
  *
164
  *
173
  * @v ipaddress		IP address
165
  * @v ipaddress		IP address
174
- * @v port		TFTP server port
166
+ * @v port		TFTP server port (in network byte order)
175
  * @v filename		File name
167
  * @v filename		File name
176
  * @v blksize		Requested block size
168
  * @v blksize		Requested block size
177
  * @ret rc		Return status code
169
  * @ret rc		Return status code
178
  */
170
  */
179
 static int pxe_tftp_open ( IP4_t ipaddress, UDP_PORT_t port,
171
 static int pxe_tftp_open ( IP4_t ipaddress, UDP_PORT_t port,
180
 			   UINT8_t *filename, UINT16_t blksize ) {
172
 			   UINT8_t *filename, UINT16_t blksize ) {
181
-	struct in_addr address;
173
+	union {
174
+		struct sockaddr sa;
175
+		struct sockaddr_in sin;
176
+	} server;
182
 	struct uri *uri;
177
 	struct uri *uri;
183
 	int rc;
178
 	int rc;
184
 
179
 
191
 	pxe_tftp.rc = -EINPROGRESS;
186
 	pxe_tftp.rc = -EINPROGRESS;
192
 
187
 
193
 	/* Construct URI */
188
 	/* Construct URI */
194
-	address.s_addr = ipaddress;
195
-	DBG ( " %s", inet_ntoa ( address ) );
189
+	memset ( &server, 0, sizeof ( server ) );
190
+	server.sin.sin_family = AF_INET;
191
+	server.sin.sin_addr.s_addr = ipaddress;
192
+	server.sin.sin_port = port;
193
+	DBG ( " %s", sock_ntoa ( &server.sa ) );
196
 	if ( port )
194
 	if ( port )
197
 		DBG ( ":%d", ntohs ( port ) );
195
 		DBG ( ":%d", ntohs ( port ) );
198
 	DBG ( ":%s", filename );
196
 	DBG ( ":%s", filename );
199
-	uri = tftp_uri ( address, ntohs ( port ), ( ( char * ) filename ) );
197
+	uri = pxe_uri ( &server.sa, ( ( char * ) filename ) );
200
 	if ( ! uri ) {
198
 	if ( ! uri ) {
201
 		DBG ( " could not create URI\n" );
199
 		DBG ( " could not create URI\n" );
202
 		return -ENOMEM;
200
 		return -ENOMEM;

+ 37
- 16
src/core/uri.c View File

36
 #include <ctype.h>
36
 #include <ctype.h>
37
 #include <ipxe/vsprintf.h>
37
 #include <ipxe/vsprintf.h>
38
 #include <ipxe/params.h>
38
 #include <ipxe/params.h>
39
+#include <ipxe/tcpip.h>
39
 #include <ipxe/uri.h>
40
 #include <ipxe/uri.h>
40
 
41
 
41
 /**
42
 /**
711
 }
712
 }
712
 
713
 
713
 /**
714
 /**
714
- * Construct TFTP URI from next-server and filename
715
+ * Construct URI from server address and filename
715
  *
716
  *
716
- * @v next_server	Next-server address
717
- * @v port		Port number, or zero to use the default port
717
+ * @v sa_server		Server address
718
  * @v filename		Filename
718
  * @v filename		Filename
719
  * @ret uri		URI, or NULL on failure
719
  * @ret uri		URI, or NULL on failure
720
  *
720
  *
721
- * TFTP filenames specified via the DHCP next-server field often
721
+ * PXE TFTP filenames specified via the DHCP next-server field often
722
  * contain characters such as ':' or '#' which would confuse the
722
  * contain characters such as ':' or '#' which would confuse the
723
  * generic URI parser.  We provide a mechanism for directly
723
  * generic URI parser.  We provide a mechanism for directly
724
  * constructing a TFTP URI from the next-server and filename.
724
  * constructing a TFTP URI from the next-server and filename.
725
  */
725
  */
726
-struct uri * tftp_uri ( struct in_addr next_server, unsigned int port,
727
-			const char *filename ) {
726
+struct uri * pxe_uri ( struct sockaddr *sa_server, const char *filename ) {
728
 	char buf[ 6 /* "65535" + NUL */ ];
727
 	char buf[ 6 /* "65535" + NUL */ ];
729
-	struct uri uri;
730
-
731
-	memset ( &uri, 0, sizeof ( uri ) );
732
-	uri.scheme = "tftp";
733
-	uri.host = inet_ntoa ( next_server );
734
-	if ( port ) {
735
-		snprintf ( buf, sizeof ( buf ), "%d", port );
736
-		uri.port = buf;
728
+	struct sockaddr_tcpip *st_server =
729
+		( ( struct sockaddr_tcpip * ) sa_server );
730
+	struct uri tmp;
731
+	struct uri *uri;
732
+
733
+	/* Fail if filename is empty */
734
+	if ( ! ( filename && filename[0] ) )
735
+		return NULL;
736
+
737
+	/* If filename is a hierarchical absolute URI, then use that
738
+	 * URI.  (We accept only hierarchical absolute URIs, since PXE
739
+	 * filenames sometimes start with DOS drive letters such as
740
+	 * "C:\", which get misinterpreted as opaque absolute URIs.)
741
+	 */
742
+	uri = parse_uri ( filename );
743
+	if ( uri && uri_is_absolute ( uri ) && ( ! uri->opaque ) )
744
+		return uri;
745
+	uri_put ( uri );
746
+
747
+	/* Otherwise, construct a TFTP URI directly */
748
+	memset ( &tmp, 0, sizeof ( tmp ) );
749
+	tmp.scheme = "tftp";
750
+	tmp.host = sock_ntoa ( sa_server );
751
+	if ( ! tmp.host )
752
+		return NULL;
753
+	if ( st_server->st_port ) {
754
+		snprintf ( buf, sizeof ( buf ), "%d",
755
+			   ntohs ( st_server->st_port ) );
756
+		tmp.port = buf;
737
 	}
757
 	}
738
-	uri.path = filename;
739
-	return uri_dup ( &uri );
758
+	tmp.path = filename;
759
+	uri = uri_dup ( &tmp );
760
+	return uri;
740
 }
761
 }

+ 2
- 2
src/include/ipxe/uri.h View File

206
 			     const char *relative_path );
206
 			     const char *relative_path );
207
 extern struct uri * resolve_uri ( const struct uri *base_uri,
207
 extern struct uri * resolve_uri ( const struct uri *base_uri,
208
 				  struct uri *relative_uri );
208
 				  struct uri *relative_uri );
209
-extern struct uri * tftp_uri ( struct in_addr next_server, unsigned int port,
210
-			       const char *filename );
209
+extern struct uri * pxe_uri ( struct sockaddr *sa_server,
210
+			      const char *filename );
211
 extern void churi ( struct uri *uri );
211
 extern void churi ( struct uri *uri );
212
 
212
 
213
 #endif /* _IPXE_URI_H */
213
 #endif /* _IPXE_URI_H */

+ 77
- 29
src/tests/uri_test.c View File

35
 #include <string.h>
35
 #include <string.h>
36
 #include <byteswap.h>
36
 #include <byteswap.h>
37
 #include <ipxe/uri.h>
37
 #include <ipxe/uri.h>
38
+#include <ipxe/tcpip.h>
38
 #include <ipxe/params.h>
39
 #include <ipxe/params.h>
39
 #include <ipxe/test.h>
40
 #include <ipxe/test.h>
40
 
41
 
66
 	const char *resolved;
67
 	const char *resolved;
67
 };
68
 };
68
 
69
 
69
-/** A TFTP URI test */
70
-struct uri_tftp_test {
71
-	/** Next-server address */
72
-	struct in_addr next_server;
73
-	/** Port number */
74
-	unsigned int port;
70
+/** A PXE URI test */
71
+struct uri_pxe_test {
72
+	/** Server address */
73
+	union {
74
+		struct sockaddr sa;
75
+		struct sockaddr_in sin;
76
+		struct sockaddr_in6 sin6;
77
+		struct sockaddr_tcpip st;
78
+	} server;
75
 	/** Filename */
79
 	/** Filename */
76
 	const char *filename;
80
 	const char *filename;
77
 	/** URI */
81
 	/** URI */
323
 	uri_resolve_path_okx ( test, __FILE__, __LINE__ )
327
 	uri_resolve_path_okx ( test, __FILE__, __LINE__ )
324
 
328
 
325
 /**
329
 /**
326
- * Report URI TFTP test result
330
+ * Report URI PXE test result
327
  *
331
  *
328
- * @v test		URI TFTP test
332
+ * @v test		URI PXE test
329
  * @v file		Test code file
333
  * @v file		Test code file
330
  * @v line		Test code line
334
  * @v line		Test code line
331
  */
335
  */
332
-static void uri_tftp_okx ( struct uri_tftp_test *test, const char *file,
333
-			   unsigned int line ) {
336
+static void uri_pxe_okx ( struct uri_pxe_test *test, const char *file,
337
+			  unsigned int line ) {
334
 	char buf[ strlen ( test->string ) + 1 /* NUL */ ];
338
 	char buf[ strlen ( test->string ) + 1 /* NUL */ ];
335
 	struct uri *uri;
339
 	struct uri *uri;
336
 	size_t len;
340
 	size_t len;
337
 
341
 
338
 	/* Construct URI */
342
 	/* Construct URI */
339
-	uri = tftp_uri ( test->next_server, test->port, test->filename );
343
+	uri = pxe_uri ( &test->server.sa, test->filename );
340
 	okx ( uri != NULL, file, line );
344
 	okx ( uri != NULL, file, line );
341
 	if ( uri ) {
345
 	if ( uri ) {
342
 		uri_okx ( uri, &test->uri, file, line );
346
 		uri_okx ( uri, &test->uri, file, line );
346
 	}
350
 	}
347
 	uri_put ( uri );
351
 	uri_put ( uri );
348
 }
352
 }
349
-#define uri_tftp_ok( test ) uri_tftp_okx ( test, __FILE__, __LINE__ )
353
+#define uri_pxe_ok( test ) uri_pxe_okx ( test, __FILE__, __LINE__ )
350
 
354
 
351
 /**
355
 /**
352
  * Report current working URI test result
356
  * Report current working URI test result
678
 	"http://192.168.0.254/test#bar",
682
 	"http://192.168.0.254/test#bar",
679
 };
683
 };
680
 
684
 
681
-/** TFTP URI with absolute path */
682
-static struct uri_tftp_test uri_tftp_absolute = {
683
-	{ .s_addr = htonl ( 0xc0a80002 ) /* 192.168.0.2 */ }, 0,
685
+/** PXE URI with absolute URI */
686
+static struct uri_pxe_test uri_pxe_absolute = {
687
+	{
688
+		/* 192.168.0.3 */
689
+		.sin = {
690
+			.sin_family = AF_INET,
691
+			.sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
692
+		},
693
+	},
694
+	"http://not.a.tftp/uri",
695
+	{
696
+		.scheme = "http",
697
+		.host = "not.a.tftp",
698
+		.path = "/uri",
699
+	},
700
+	"http://not.a.tftp/uri",
701
+};
702
+
703
+/** PXE URI with absolute path */
704
+static struct uri_pxe_test uri_pxe_absolute_path = {
705
+	{
706
+		/* 192.168.0.2 */
707
+		.sin = {
708
+			.sin_family = AF_INET,
709
+			.sin_addr = { .s_addr = htonl ( 0xc0a80002 ) },
710
+		},
711
+	},
684
 	"/absolute/path",
712
 	"/absolute/path",
685
 	{
713
 	{
686
 		.scheme = "tftp",
714
 		.scheme = "tftp",
690
 	"tftp://192.168.0.2/absolute/path",
718
 	"tftp://192.168.0.2/absolute/path",
691
 };
719
 };
692
 
720
 
693
-/** TFTP URI with relative path */
694
-static struct uri_tftp_test uri_tftp_relative = {
695
-	{ .s_addr = htonl ( 0xc0a80003 ) /* 192.168.0.3 */ }, 0,
721
+/** PXE URI with relative path */
722
+static struct uri_pxe_test uri_pxe_relative_path = {
723
+	{
724
+		/* 192.168.0.3 */
725
+		.sin = {
726
+			.sin_family = AF_INET,
727
+			.sin_addr = { .s_addr = htonl ( 0xc0a80003 ) },
728
+		},
729
+	},
696
 	"relative/path",
730
 	"relative/path",
697
 	{
731
 	{
698
 		.scheme = "tftp",
732
 		.scheme = "tftp",
702
 	"tftp://192.168.0.3/relative/path",
736
 	"tftp://192.168.0.3/relative/path",
703
 };
737
 };
704
 
738
 
705
-/** TFTP URI with path containing special characters */
706
-static struct uri_tftp_test uri_tftp_icky = {
707
-	{ .s_addr = htonl ( 0x0a000006 ) /* 10.0.0.6 */ }, 0,
739
+/** PXE URI with path containing special characters */
740
+static struct uri_pxe_test uri_pxe_icky = {
741
+	{
742
+		/* 10.0.0.6 */
743
+		.sin = {
744
+			.sin_family = AF_INET,
745
+			.sin_addr = { .s_addr = htonl ( 0x0a000006 ) },
746
+		},
747
+	},
708
 	"C:\\tftpboot\\icky#path",
748
 	"C:\\tftpboot\\icky#path",
709
 	{
749
 	{
710
 		.scheme = "tftp",
750
 		.scheme = "tftp",
714
 	"tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
754
 	"tftp://10.0.0.6/C%3A\\tftpboot\\icky%23path",
715
 };
755
 };
716
 
756
 
717
-/** TFTP URI with custom port */
718
-static struct uri_tftp_test uri_tftp_port = {
719
-	{ .s_addr = htonl ( 0xc0a80001 ) /* 192.168.0.1 */ }, 4069,
757
+/** PXE URI with custom port */
758
+static struct uri_pxe_test uri_pxe_port = {
759
+	{
760
+		/* 192.168.0.1:4069 */
761
+		.sin = {
762
+			.sin_family = AF_INET,
763
+			.sin_addr = { .s_addr = htonl ( 0xc0a80001 ) },
764
+			.sin_port = htons ( 4069 ),
765
+		},
766
+	},
720
 	"/another/path",
767
 	"/another/path",
721
 	{
768
 	{
722
 		.scheme = "tftp",
769
 		.scheme = "tftp",
857
 	uri_resolve_ok ( &uri_query );
904
 	uri_resolve_ok ( &uri_query );
858
 	uri_resolve_ok ( &uri_fragment );
905
 	uri_resolve_ok ( &uri_fragment );
859
 
906
 
860
-	/* TFTP URI construction tests */
861
-	uri_tftp_ok ( &uri_tftp_absolute );
862
-	uri_tftp_ok ( &uri_tftp_relative );
863
-	uri_tftp_ok ( &uri_tftp_icky );
864
-	uri_tftp_ok ( &uri_tftp_port );
907
+	/* PXE URI construction tests */
908
+	uri_pxe_ok ( &uri_pxe_absolute );
909
+	uri_pxe_ok ( &uri_pxe_absolute_path );
910
+	uri_pxe_ok ( &uri_pxe_relative_path );
911
+	uri_pxe_ok ( &uri_pxe_icky );
912
+	uri_pxe_ok ( &uri_pxe_port );
865
 
913
 
866
 	/* Current working URI tests */
914
 	/* Current working URI tests */
867
 	uri_churi_ok ( uri_churi );
915
 	uri_churi_ok ( uri_churi );

+ 32
- 57
src/usr/autoboot.c View File

87
 	return -ENOTSUP;
87
 	return -ENOTSUP;
88
 }
88
 }
89
 
89
 
90
-/**
91
- * Parse next-server and filename into a URI
92
- *
93
- * @v next_server	Next-server address
94
- * @v filename		Filename
95
- * @ret uri		URI, or NULL on failure
96
- */
97
-static struct uri * parse_next_server_and_filename ( struct in_addr next_server,
98
-						     const char *filename ) {
99
-	struct uri *uri;
100
-
101
-	/* Parse filename */
102
-	uri = parse_uri ( filename );
103
-	if ( ! uri )
104
-		return NULL;
105
-
106
-	/* Construct a TFTP URI for the filename, if applicable */
107
-	if ( next_server.s_addr && filename[0] && ! uri_is_absolute ( uri ) ) {
108
-		uri_put ( uri );
109
-		uri = tftp_uri ( next_server, 0, filename );
110
-		if ( ! uri )
111
-			return NULL;
112
-	}
113
-
114
-	return uri;
115
-}
116
-
117
 /** The "keep-san" setting */
90
 /** The "keep-san" setting */
118
 const struct setting keep_san_setting __setting ( SETTING_SANBOOT_EXTRA,
91
 const struct setting keep_san_setting __setting ( SETTING_SANBOOT_EXTRA,
119
 						  keep-san ) = {
92
 						  keep-san ) = {
250
  * @ret uri		URI, or NULL on failure
223
  * @ret uri		URI, or NULL on failure
251
  */
224
  */
252
 struct uri * fetch_next_server_and_filename ( struct settings *settings ) {
225
 struct uri * fetch_next_server_and_filename ( struct settings *settings ) {
253
-	struct in_addr next_server = { 0 };
226
+	union {
227
+		struct sockaddr sa;
228
+		struct sockaddr_in sin;
229
+	} next_server;
254
 	char *raw_filename = NULL;
230
 	char *raw_filename = NULL;
255
 	struct uri *uri = NULL;
231
 	struct uri *uri = NULL;
256
 	char *filename;
232
 	char *filename;
257
 
233
 
234
+	/* Initialise server address */
235
+	memset ( &next_server, 0, sizeof ( next_server ) );
236
+
258
 	/* If we have a filename, fetch it along with the next-server
237
 	/* If we have a filename, fetch it along with the next-server
259
 	 * setting from the same settings block.
238
 	 * setting from the same settings block.
260
 	 */
239
 	 */
263
 		fetch_string_setting_copy ( settings, &filename_setting,
242
 		fetch_string_setting_copy ( settings, &filename_setting,
264
 					    &raw_filename );
243
 					    &raw_filename );
265
 		fetch_ipv4_setting ( settings, &next_server_setting,
244
 		fetch_ipv4_setting ( settings, &next_server_setting,
266
-				     &next_server );
245
+				     &next_server.sin.sin_addr );
246
+	}
247
+	if ( ! raw_filename )
248
+		goto err_fetch;
249
+
250
+	/* Populate server address */
251
+	if ( next_server.sin.sin_addr.s_addr ) {
252
+		next_server.sin.sin_family = AF_INET;
253
+		printf ( "Next server: %s\n",
254
+			 inet_ntoa ( next_server.sin.sin_addr ) );
267
 	}
255
 	}
268
 
256
 
269
 	/* Expand filename setting */
257
 	/* Expand filename setting */
270
-	filename = expand_settings ( raw_filename ? raw_filename : "" );
258
+	filename = expand_settings ( raw_filename );
271
 	if ( ! filename )
259
 	if ( ! filename )
272
 		goto err_expand;
260
 		goto err_expand;
273
-
274
-	/* Parse next server and filename */
275
-	if ( next_server.s_addr )
276
-		printf ( "Next server: %s\n", inet_ntoa ( next_server ) );
277
 	if ( filename[0] )
261
 	if ( filename[0] )
278
 		printf ( "Filename: %s\n", filename );
262
 		printf ( "Filename: %s\n", filename );
279
-	uri = parse_next_server_and_filename ( next_server, filename );
263
+
264
+	/* Construct URI */
265
+	uri = pxe_uri ( &next_server.sa, filename );
280
 	if ( ! uri )
266
 	if ( ! uri )
281
 		goto err_parse;
267
 		goto err_parse;
282
 
268
 
284
 	free ( filename );
270
 	free ( filename );
285
  err_expand:
271
  err_expand:
286
 	free ( raw_filename );
272
 	free ( raw_filename );
273
+ err_fetch:
287
 	return uri;
274
 	return uri;
288
 }
275
 }
289
 
276
 
301
 	/* Fetch root-path setting */
288
 	/* Fetch root-path setting */
302
 	fetch_string_setting_copy ( settings, &root_path_setting,
289
 	fetch_string_setting_copy ( settings, &root_path_setting,
303
 				    &raw_root_path );
290
 				    &raw_root_path );
291
+	if ( ! raw_root_path )
292
+		goto err_fetch;
304
 
293
 
305
 	/* Expand filename setting */
294
 	/* Expand filename setting */
306
-	root_path = expand_settings ( raw_root_path ? raw_root_path : "" );
295
+	root_path = expand_settings ( raw_root_path );
307
 	if ( ! root_path )
296
 	if ( ! root_path )
308
 		goto err_expand;
297
 		goto err_expand;
309
 
298
 
318
 	free ( root_path );
307
 	free ( root_path );
319
  err_expand:
308
  err_expand:
320
 	free ( raw_root_path );
309
 	free ( raw_root_path );
310
+ err_fetch:
321
 	return uri;
311
 	return uri;
322
 }
312
 }
323
 
313
 
378
 		goto err_pxe_menu_boot;
368
 		goto err_pxe_menu_boot;
379
 	}
369
 	}
380
 
370
 
381
-	/* Fetch next server and filename */
371
+	/* Fetch next server and filename (if any) */
382
 	filename = fetch_next_server_and_filename ( NULL );
372
 	filename = fetch_next_server_and_filename ( NULL );
383
-	if ( ! filename )
384
-		goto err_filename;
385
-	if ( ! uri_has_path ( filename ) ) {
386
-		/* Ignore empty filename */
387
-		uri_put ( filename );
388
-		filename = NULL;
389
-	}
390
 
373
 
391
-	/* Fetch root path */
374
+	/* Fetch root path (if any) */
392
 	root_path = fetch_root_path ( NULL );
375
 	root_path = fetch_root_path ( NULL );
393
-	if ( ! root_path )
394
-		goto err_root_path;
395
-	if ( ! uri_is_absolute ( root_path ) ) {
396
-		/* Ignore empty root path */
397
-		uri_put ( root_path );
398
-		root_path = NULL;
399
-	}
400
 
376
 
401
 	/* If we have both a filename and a root path, ignore an
377
 	/* If we have both a filename and a root path, ignore an
402
-	 * unsupported URI scheme in the root path, since it may
403
-	 * represent an NFS root.
378
+	 * unsupported or missing URI scheme in the root path, since
379
+	 * it may represent an NFS root.
404
 	 */
380
 	 */
405
 	if ( filename && root_path &&
381
 	if ( filename && root_path &&
406
-	     ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) {
382
+	     ( ! ( uri_is_absolute ( root_path ) ||
383
+		   ( xfer_uri_opener ( root_path->scheme ) == NULL ) ) ) ) {
407
 		printf ( "Ignoring unsupported root path\n" );
384
 		printf ( "Ignoring unsupported root path\n" );
408
 		uri_put ( root_path );
385
 		uri_put ( root_path );
409
 		root_path = NULL;
386
 		root_path = NULL;
424
  err_uriboot:
401
  err_uriboot:
425
  err_no_boot:
402
  err_no_boot:
426
 	uri_put ( root_path );
403
 	uri_put ( root_path );
427
- err_root_path:
428
 	uri_put ( filename );
404
 	uri_put ( filename );
429
- err_filename:
430
  err_pxe_menu_boot:
405
  err_pxe_menu_boot:
431
  err_dhcp:
406
  err_dhcp:
432
  err_ifopen:
407
  err_ifopen:

Loading…
Cancel
Save