Procházet zdrojové kódy

[pxe] Always retrieve cached DHCPACK and apply to relevant network device

When chainloading, always retrieve the cached DHCPACK packet from the
underlying PXE stack, and apply it as the original contents of the
"net<X>.dhcp" settings block.  This allows cached DHCP settings to be
used for any chainloaded iPXE binary (not just undionly.kkpxe).

This change eliminates the undocumented "use-cached" setting.  Issuing
the "dhcp" command will now always result in a fresh DHCP request.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown před 11 roky
rodič
revize
10d19bd2ac

+ 188
- 0
src/arch/i386/core/cachedhcp.c Zobrazit soubor

@@ -0,0 +1,188 @@
1
+/*
2
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <stdint.h>
23
+#include <stdlib.h>
24
+#include <ipxe/dhcppkt.h>
25
+#include <ipxe/init.h>
26
+#include <ipxe/netdevice.h>
27
+#include <realmode.h>
28
+#include <pxe_api.h>
29
+
30
+/** @file
31
+ *
32
+ * Cached DHCP packet
33
+ *
34
+ */
35
+
36
+/** Cached DHCPACK physical address
37
+ *
38
+ * This can be set by the prefix.
39
+ */
40
+uint32_t __bss16 ( cached_dhcpack_phys );
41
+#define cached_dhcpack_phys __use_data16 ( cached_dhcpack_phys )
42
+
43
+/** Colour for debug messages */
44
+#define colour &cached_dhcpack_phys
45
+
46
+/** Cached DHCPACK */
47
+static struct dhcp_packet *cached_dhcpack;
48
+
49
+/**
50
+ * Cached DHCPACK startup function
51
+ *
52
+ */
53
+static void cachedhcp_startup ( void ) {
54
+	struct dhcp_packet *dhcppkt;
55
+	struct dhcp_packet *tmp;
56
+	struct dhcphdr *dhcphdr;
57
+	size_t len;
58
+
59
+	/* Do nothing if no cached DHCPACK is present */
60
+	if ( ! cached_dhcpack_phys ) {
61
+		DBGC ( colour, "CACHEDHCP found no cached DHCPACK\n" );
62
+		return;
63
+	}
64
+
65
+	/* No reliable way to determine length before parsing packet;
66
+	 * start by assuming maximum length permitted by PXE.
67
+	 */
68
+	len = sizeof ( BOOTPLAYER_t );
69
+
70
+	/* Allocate and populate DHCP packet */
71
+	dhcppkt = zalloc ( sizeof ( *dhcppkt ) + len );
72
+	if ( ! dhcppkt ) {
73
+		DBGC ( colour, "CACHEDHCP could not allocate copy\n" );
74
+		return;
75
+	}
76
+	dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
77
+	copy_from_user ( dhcphdr, phys_to_user ( cached_dhcpack_phys ), 0,
78
+			 len );
79
+	dhcppkt_init ( dhcppkt, dhcphdr, len );
80
+
81
+	/* Resize packet to required length.  If reallocation fails,
82
+	 * just continue to use the original packet.
83
+	 */
84
+	len = dhcppkt_len ( dhcppkt );
85
+	tmp = realloc ( dhcppkt, ( sizeof ( *dhcppkt ) + len ) );
86
+	if ( tmp )
87
+		dhcppkt = tmp;
88
+
89
+	/* Reinitialise packet at new address */
90
+	dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( *dhcppkt ) );
91
+	dhcppkt_init ( dhcppkt, dhcphdr, len );
92
+
93
+	/* Store as cached DHCPACK, and mark original copy as consumed */
94
+	DBGC ( colour, "CACHEDHCP found cached DHCPACK at %08x+%zx\n",
95
+	       cached_dhcpack_phys, len );
96
+	cached_dhcpack = dhcppkt;
97
+	cached_dhcpack_phys = 0;
98
+}
99
+
100
+/**
101
+ * Cached DHCPACK shutdown function
102
+ *
103
+ * @v booting		Shutting down in order to boot
104
+ */
105
+static void cachedhcp_shutdown ( int booting __unused ) {
106
+
107
+	/* If cached DHCP packet has not yet been claimed, free it */
108
+	if ( cached_dhcpack ) {
109
+		DBGC ( colour, "CACHEDHCP freeing unclaimed cached DHCPACK\n" );
110
+		dhcppkt_put ( cached_dhcpack );
111
+		cached_dhcpack = NULL;
112
+	}
113
+}
114
+
115
+/** Cached DHCPACK initialisation function */
116
+struct startup_fn cachedhcp_startup_fn __startup_fn ( STARTUP_NORMAL ) = {
117
+	.startup = cachedhcp_startup,
118
+	.shutdown = cachedhcp_shutdown,
119
+};
120
+
121
+/**
122
+ * Apply cached DHCPACK to network device, if applicable
123
+ *
124
+ * @v netdev		Network device
125
+ * @ret rc		Return status code
126
+ */
127
+static int cachedhcp_probe ( struct net_device *netdev ) {
128
+	struct ll_protocol *ll_protocol = netdev->ll_protocol;
129
+	int rc;
130
+
131
+	/* Do nothing unless we have a cached DHCPACK */
132
+	if ( ! cached_dhcpack )
133
+		return 0;
134
+
135
+	/* Do nothing unless cached DHCPACK's MAC address matches this
136
+	 * network device.
137
+	 */
138
+	if ( memcmp ( netdev->ll_addr, cached_dhcpack->dhcphdr->chaddr,
139
+		      ll_protocol->ll_addr_len ) != 0 ) {
140
+		DBGC ( colour, "CACHEDHCP cached DHCPACK does not match %s\n",
141
+		       netdev->name );
142
+		return 0;
143
+	}
144
+	DBGC ( colour, "CACHEDHCP cached DHCPACK is for %s\n", netdev->name );
145
+
146
+	/* Register as DHCP settings for this network device */
147
+	if ( ( rc = register_settings ( &cached_dhcpack->settings,
148
+					netdev_settings ( netdev ),
149
+					DHCP_SETTINGS_NAME ) ) != 0 ) {
150
+		DBGC ( colour, "CACHEDHCP could not register settings: %s\n",
151
+		       strerror ( rc ) );
152
+		return rc;
153
+	}
154
+
155
+	/* Claim cached DHCPACK */
156
+	dhcppkt_put ( cached_dhcpack );
157
+	cached_dhcpack = NULL;
158
+
159
+	return 0;
160
+}
161
+
162
+/**
163
+ * Handle network device link state change
164
+ *
165
+ * @v netdev		Network device
166
+ */
167
+static void cachedhcp_notify ( struct net_device *netdev __unused ) {
168
+
169
+	/* Nothing to do */
170
+}
171
+
172
+/**
173
+ * Handle network device removal
174
+ *
175
+ * @v netdev		Network device
176
+ */
177
+static void cachedhcp_remove ( struct net_device *netdev __unused ) {
178
+
179
+	/* Nothing to do */
180
+}
181
+
182
+/** Cached DHCP packet network device driver */
183
+struct net_driver cachedhcp_driver __net_driver = {
184
+	.name = "cachedhcp",
185
+	.probe = cachedhcp_probe,
186
+	.notify = cachedhcp_notify,
187
+	.remove = cachedhcp_remove,
188
+};

+ 0
- 70
src/arch/i386/interface/pxeparent/pxeparent_dhcp.c Zobrazit soubor

@@ -1,70 +0,0 @@
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., 51 Franklin Street, Fifth Floor, Boston, MA
17
- * 02110-1301, USA.
18
- */
19
-
20
-FILE_LICENCE ( GPL2_OR_LATER );
21
-
22
-#include <string.h>
23
-#include <ipxe/dhcp.h>
24
-#include <ipxe/netdevice.h>
25
-#include <undipreload.h>
26
-#include <pxeparent.h>
27
-#include <realmode.h>
28
-#include <pxe_api.h>
29
-
30
-/**
31
- * Present cached DHCP packet if it exists
32
- */
33
-void get_cached_dhcpack ( void ) {
34
-	struct undi_device *undi;
35
-	struct s_PXENV_GET_CACHED_INFO get_cached_info;
36
-	int rc;
37
-
38
-	/* Use preloaded UNDI device to get at PXE entry point */
39
-	undi = &preloaded_undi;
40
-	if ( ! undi->entry.segment ) {
41
-		DBG ( "PXEDHCP no preloaded UNDI device found\n" );
42
-		return;
43
-	}
44
-
45
-	/* Check that stack is available to get cached info */
46
-	if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
47
-		DBG ( "PXEDHCP stack was unloaded, no cache available\n" );
48
-		return;
49
-	}
50
-
51
-	/* Obtain cached DHCP packet */
52
-	memset ( &get_cached_info, 0, sizeof ( get_cached_info ) );
53
-	get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK;
54
-
55
-	if ( ( rc = pxeparent_call ( undi->entry, PXENV_GET_CACHED_INFO,
56
-				     &get_cached_info,
57
-				     sizeof ( get_cached_info ) ) ) != 0 ) {
58
-		DBG ( "PXEDHCP GET_CACHED_INFO failed: %s\n", strerror ( rc ) );
59
-		return;
60
-	}
61
-
62
-	DBG ( "PXEDHCP got cached info at %04x:%04x length %d\n",
63
-	      get_cached_info.Buffer.segment, get_cached_info.Buffer.offset,
64
-	      get_cached_info.BufferSize );
65
-
66
-	/* Present cached DHCP packet */
67
-	store_cached_dhcpack ( real_to_user ( get_cached_info.Buffer.segment,
68
-					      get_cached_info.Buffer.offset ),
69
-			       get_cached_info.BufferSize );
70
-}

+ 48
- 3
src/arch/i386/prefix/pxeprefix.S Zobrazit soubor

@@ -5,6 +5,8 @@ FILE_LICENCE ( GPL2_OR_LATER )
5 5
 #define PXENV_UNDI_GET_IFACE_INFO	0x0013
6 6
 #define	PXENV_STOP_UNDI			0x0015
7 7
 #define PXENV_UNLOAD_STACK		0x0070
8
+#define PXENV_GET_CACHED_INFO		0x0071
9
+#define PXENV_PACKET_TYPE_DHCP_ACK		0x0002
8 10
 #define PXENV_FILE_CMDLINE		0x00e8
9 11
 
10 12
 #define PXE_HACK_EB54			0x0001
@@ -20,7 +22,18 @@ FILE_LICENCE ( GPL2_OR_LATER )
20 22
 #define EB_MAGIC_1 ( 'E' + ( 't' << 8 ) + ( 'h' << 16 ) + ( 'e' << 24 ) )
21 23
 #define EB_MAGIC_2 ( 'r' + ( 'b' << 8 ) + ( 'o' << 16 ) + ( 'o' << 24 ) )
22 24
 
25
+/* Prefix memory layout:
26
+ *
27
+ *     iPXE binary image
28
+ *     Temporary stack
29
+ *     Temporary copy of DHCPACK packet
30
+ *     Temporary copy of command line
31
+ */
23 32
 #define PREFIX_STACK_SIZE 2048
33
+#define PREFIX_TEMP_DHCPACK PREFIX_STACK_SIZE
34
+#define PREFIX_TEMP_DHCPACK_SIZE ( 1260 /* sizeof ( BOOTPLAYER_t ) */ )
35
+#define PREFIX_TEMP_CMDLINE ( PREFIX_TEMP_DHCPACK + PREFIX_TEMP_DHCPACK_SIZE )
36
+#define PREFIX_TEMP_CMDLINE_SIZE 4096
24 37
 
25 38
 /*****************************************************************************
26 39
  * Entry point:	set operating context, print welcome message
@@ -382,6 +395,32 @@ get_iface_type:
382 395
 99:	movb	$0x0a, %al
383 396
 	call	print_character
384 397
 
398
+/*****************************************************************************
399
+ * Get cached DHCP_ACK packet
400
+ *****************************************************************************
401
+ */
402
+get_dhcpack:
403
+	/* Issue PXENV_GET_CACHED_INFO */
404
+	xorl	%esi, %esi
405
+	movw	%ss, %si
406
+	movw	%si, ( pxe_parameter_structure + 0x08 )
407
+	movw	$PREFIX_TEMP_DHCPACK, ( pxe_parameter_structure + 0x06 )
408
+	movw	$PREFIX_TEMP_DHCPACK_SIZE, ( pxe_parameter_structure +0x04 )
409
+	movw	$PXENV_PACKET_TYPE_DHCP_ACK, ( pxe_parameter_structure + 0x02 )
410
+	movw	$PXENV_GET_CACHED_INFO, %bx
411
+	call	pxe_call
412
+	jnc	1f
413
+	call	print_pxe_error
414
+	jmp	99f
415
+1:	/* Store physical address of packet */
416
+	shll	$4, %esi
417
+	addl	$PREFIX_TEMP_DHCPACK, %esi
418
+	movl	%esi, pxe_cached_dhcpack
419
+99:
420
+	.section ".prefix.data", "aw", @progbits
421
+pxe_cached_dhcpack:
422
+	.long	0
423
+	.previous
385 424
 
386 425
 /*****************************************************************************
387 426
  * Check for a command line
@@ -392,8 +431,8 @@ get_cmdline:
392 431
 	xorl	%esi, %esi
393 432
 	movw	%ss, %si
394 433
 	movw	%si, ( pxe_parameter_structure + 0x06 )
395
-	movw	$PREFIX_STACK_SIZE, ( pxe_parameter_structure + 0x04 )
396
-	movw	$0xffff, ( pxe_parameter_structure + 0x02 )
434
+	movw	$PREFIX_TEMP_CMDLINE, ( pxe_parameter_structure + 0x04 )
435
+	movw	$PREFIX_TEMP_CMDLINE_SIZE, ( pxe_parameter_structure + 0x02 )
397 436
 	movw	$PXENV_FILE_CMDLINE, %bx
398 437
 	call	pxe_call
399 438
 	jc	99f  /* Suppress errors; this is an iPXE extension API call */
@@ -403,7 +442,7 @@ get_cmdline:
403 442
 	jz	99f
404 443
 	/* Record command line */
405 444
 	shll	$4, %esi
406
-	addl	$PREFIX_STACK_SIZE, %esi
445
+	addl	$PREFIX_TEMP_CMDLINE, %esi
407 446
 	movl	%esi, pxe_cmdline
408 447
 99:
409 448
 	.section ".prefix.data", "aw", @progbits
@@ -761,6 +800,9 @@ run_ipxe:
761 800
 	/* Retrieve PXE command line, if any */
762 801
 	movl	pxe_cmdline, %esi
763 802
 
803
+	/* Retrieve cached DHCPACK, if any */
804
+	movl	pxe_cached_dhcpack, %ecx
805
+
764 806
 	/* Jump to .text16 segment with %ds pointing to .data16 */
765 807
 	movw	%bx, %ds
766 808
 	pushw	%ax
@@ -774,6 +816,9 @@ run_ipxe:
774 816
 	/* Store command-line pointer */
775 817
 	movl	%esi, cmdline_phys
776 818
 
819
+	/* Store cached DHCPACK pointer */
820
+	movl	%ecx, cached_dhcpack_phys
821
+
777 822
 	/* Run main program */
778 823
 	pushl	$main
779 824
 	pushw	%cs

+ 1
- 16
src/include/ipxe/dhcp.h Zobrazit soubor

@@ -397,14 +397,7 @@ struct dhcp_netdev_desc {
397 397
 	uint16_t device;
398 398
 } __attribute__ (( packed ));
399 399
 
400
-/** Use cached network settings
401
- *
402
- * Cached network settings may be available from a prior DHCP request
403
- * (if running as a PXE NBP), non-volatile storage on the NIC, or
404
- * settings set via the command line or an embedded image. If this
405
- * flag is not set, it will be assumed that those sources are
406
- * insufficient and that DHCP should still be run when autobooting.
407
- */
400
+/** Use cached network settings (obsolete; do not reuse this value) */
408 401
 #define DHCP_EB_USE_CACHED DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xb2 )
409 402
 
410 403
 /** BIOS drive number
@@ -677,12 +670,4 @@ extern int start_dhcp ( struct interface *job, struct net_device *netdev );
677 670
 extern int start_pxebs ( struct interface *job, struct net_device *netdev,
678 671
 			 unsigned int pxe_type );
679 672
 
680
-/* In environments that can provide cached DHCP packets, this function
681
- * should look for such a packet and call store_cached_dhcpack() with
682
- * it if it exists.
683
- */
684
-extern void get_cached_dhcpack ( void );
685
-
686
-extern void store_cached_dhcpack ( userptr_t data, size_t len );
687
-
688 673
 #endif /* _IPXE_DHCP_H */

+ 0
- 78
src/net/cachedhcp.c Zobrazit soubor

@@ -1,78 +0,0 @@
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., 51 Franklin Street, Fifth Floor, Boston, MA
17
- * 02110-1301, USA.
18
- */
19
-
20
-FILE_LICENCE ( GPL2_OR_LATER );
21
-
22
-#include <stdio.h>
23
-#include <stdlib.h>
24
-#include <string.h>
25
-#include <ipxe/dhcp.h>
26
-#include <ipxe/dhcppkt.h>
27
-#include <ipxe/netdevice.h>
28
-#include <ipxe/iobuf.h>
29
-#include <ipxe/uaccess.h>
30
-
31
-/** @file
32
- *
33
- * Cached DHCP packet handling
34
- *
35
- */
36
-
37
-/**
38
- * Store cached DHCPACK packet
39
- *
40
- * @v data		User pointer to cached DHCP packet data
41
- * @v len		Length of cached DHCP packet data
42
- * @ret rc		Return status code
43
- *
44
- * This function should be called by the architecture-specific
45
- * get_cached_dhcpack() handler.
46
- */
47
-void store_cached_dhcpack ( userptr_t data, size_t len ) {
48
-	struct dhcp_packet *dhcppkt;
49
-	struct dhcphdr *dhcphdr;
50
-	struct settings *parent;
51
-	int rc;
52
-
53
-	/* Create DHCP packet */
54
-	dhcppkt = zalloc ( sizeof ( *dhcppkt ) + len );
55
-	if ( ! dhcppkt )
56
-		return;
57
-
58
-	/* Fill in data for DHCP packet */
59
-	dhcphdr = ( ( ( void * ) dhcppkt ) + sizeof ( * dhcppkt ) );
60
-	copy_from_user ( dhcphdr, data, 0, len );
61
-	dhcppkt_init ( dhcppkt, dhcphdr, len );
62
-	DBG_HD ( dhcppkt->options.data, dhcppkt->options.used_len );
63
-
64
-	/* Register settings on the last opened network device.
65
-	 * This will have the effect of registering cached settings
66
-	 * with a network device when "dhcp netX" is performed for that
67
-	 * device, which is usually what we want.
68
-	 */
69
-	parent = netdev_settings ( last_opened_netdev() );
70
-	if ( ( rc = register_settings ( &dhcppkt->settings, parent,
71
-					DHCP_SETTINGS_NAME ) ) != 0 )
72
-		DBG ( "DHCP could not register cached settings: %s\n",
73
-		      strerror ( rc ) );
74
-
75
-	dhcppkt_put ( dhcppkt );
76
-
77
-	DBG ( "DHCP registered cached settings\n" );
78
-}

+ 1
- 26
src/net/udp/dhcp.c Zobrazit soubor

@@ -107,14 +107,6 @@ struct setting user_class_setting __setting ( SETTING_HOST_EXTRA ) = {
107 107
 	.type = &setting_type_string,
108 108
 };
109 109
 
110
-/** Use cached network settings */
111
-struct setting use_cached_setting __setting ( SETTING_MISC ) = {
112
-	.name = "use-cached",
113
-	.description = "Use cached settings",
114
-	.tag = DHCP_EB_USE_CACHED,
115
-	.type = &setting_type_uint8,
116
-};
117
-
118 110
 /**
119 111
  * Most recent DHCP transaction ID
120 112
  *
@@ -1284,38 +1276,21 @@ static struct sockaddr dhcp_peer = {
1284 1276
 	.sa_family = AF_INET,
1285 1277
 };
1286 1278
 
1287
-/**
1288
- * Get cached DHCPACK where none exists
1289
- */
1290
-__weak void get_cached_dhcpack ( void ) { __keepme }
1291
-
1292 1279
 /**
1293 1280
  * Start DHCP state machine on a network device
1294 1281
  *
1295 1282
  * @v job		Job control interface
1296 1283
  * @v netdev		Network device
1297
- * @ret rc		Return status code, or positive if cached
1284
+ * @ret rc		Return status code
1298 1285
  *
1299 1286
  * Starts DHCP on the specified network device.  If successful, the
1300 1287
  * DHCPACK (and ProxyDHCPACK, if applicable) will be registered as
1301 1288
  * option sources.
1302
- *
1303
- * On a return of 0, a background job has been started to perform the
1304
- * DHCP request. Any nonzero return means the job has not been
1305
- * started; a positive return value indicates the success condition of
1306
- * having fetched the appropriate data from cached information.
1307 1289
  */
1308 1290
 int start_dhcp ( struct interface *job, struct net_device *netdev ) {
1309 1291
 	struct dhcp_session *dhcp;
1310 1292
 	int rc;
1311 1293
 
1312
-	/* Check for cached DHCP information */
1313
-	get_cached_dhcpack();
1314
-	if ( fetch_uintz_setting ( NULL, &use_cached_setting ) ) {
1315
-		DBG ( "DHCP using cached network settings\n" );
1316
-		return 1;
1317
-	}
1318
-
1319 1294
 	/* Allocate and initialise structure */
1320 1295
 	dhcp = zalloc ( sizeof ( *dhcp ) );
1321 1296
 	if ( ! dhcp )

+ 1
- 5
src/usr/dhcpmgmt.c Zobrazit soubor

@@ -51,12 +51,8 @@ int dhcp ( struct net_device *netdev ) {
51 51
 	/* Perform DHCP */
52 52
 	printf ( "DHCP (%s %s)", netdev->name,
53 53
 		 netdev->ll_protocol->ntoa ( netdev->ll_addr ) );
54
-	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) {
54
+	if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 )
55 55
 		rc = monojob_wait ( "" );
56
-	} else if ( rc > 0 ) {
57
-		printf ( " using cached\n" );
58
-		rc = 0;
59
-	}
60 56
 
61 57
 	return rc;
62 58
 }

Načítá se…
Zrušit
Uložit