From bb74f00512995f15bf61517fc039f32713e0af73 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 16 Jun 2020 23:40:58 +0100 Subject: [crypto] Ensure that test code drags in required ASN.1 object identifiers Signed-off-by: Michael Brown --- src/include/ipxe/asn1.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/include') diff --git a/src/include/ipxe/asn1.h b/src/include/ipxe/asn1.h index 24caecdc5..efc66631d 100644 --- a/src/include/ipxe/asn1.h +++ b/src/include/ipxe/asn1.h @@ -312,6 +312,24 @@ struct asn1_algorithm { /** Declare an ASN.1 OID-identified algorithm */ #define __asn1_algorithm __table_entry ( ASN1_ALGORITHMS, 01 ) +/* ASN.1 OID-identified algorithms */ +extern struct asn1_algorithm rsa_encryption_algorithm; +extern struct asn1_algorithm md5_with_rsa_encryption_algorithm; +extern struct asn1_algorithm sha1_with_rsa_encryption_algorithm; +extern struct asn1_algorithm sha256_with_rsa_encryption_algorithm; +extern struct asn1_algorithm sha384_with_rsa_encryption_algorithm; +extern struct asn1_algorithm sha512_with_rsa_encryption_algorithm; +extern struct asn1_algorithm sha224_with_rsa_encryption_algorithm; +extern struct asn1_algorithm oid_md4_algorithm; +extern struct asn1_algorithm oid_md5_algorithm; +extern struct asn1_algorithm oid_sha1_algorithm; +extern struct asn1_algorithm oid_sha256_algorithm; +extern struct asn1_algorithm oid_sha384_algorithm; +extern struct asn1_algorithm oid_sha512_algorithm; +extern struct asn1_algorithm oid_sha224_algorithm; +extern struct asn1_algorithm oid_sha512_224_algorithm; +extern struct asn1_algorithm oid_sha512_256_algorithm; + /** An ASN.1 bit string */ struct asn1_bit_string { /** Data */ -- cgit v1.2.3-55-g7522 From a61b27b97f572a83ede765a0e779694865950cf2 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 23 Jun 2020 23:08:49 +0100 Subject: [efi] Enable stack protection where possible Enable -fstack-protector for EFI builds, where binary size is less critical than for BIOS builds. The stack cookie must be constructed immediately on entry, which prohibits the use of any viable entropy source. Construct a cookie by XORing together various mildly random quantities to produce a value that will at least not be identical on each run. On detecting a stack corruption, attempt to call Exit() with an appropriate error. If that fails, then lock up the machine since there is no other safe action that can be taken. The old conditional check for support of -fno-stack-protector is omitted since this flag dates back to GCC 4.1. Signed-off-by: Michael Brown --- src/Makefile.efi | 8 ++++++ src/Makefile.housekeeping | 18 +++++------- src/include/ipxe/efi/efi.h | 32 +++++++++++++++++++++ src/interface/efi/efi_init.c | 62 ++++++++++++++++++++++++++++++++++++++++ src/interface/efi/efidrvprefix.c | 3 ++ src/interface/efi/efiprefix.c | 3 ++ 6 files changed, 115 insertions(+), 11 deletions(-) (limited to 'src/include') diff --git a/src/Makefile.efi b/src/Makefile.efi index 151b33186..10f3fe74b 100644 --- a/src/Makefile.efi +++ b/src/Makefile.efi @@ -1,5 +1,13 @@ # -*- makefile -*- : Force emacs to use Makefile mode +# Enable stack protection if available +# +SPG_TEST = $(CC) -fstack-protector-strong -mstack-protector-guard=global \ + -x c -c /dev/null -o /dev/null >/dev/null 2>&1 +SPG_FLAGS := $(shell $(SPG_TEST) && $(ECHO) '-fstack-protector-strong ' \ + '-mstack-protector-guard=global') +CFLAGS += $(SPG_FLAGS) + # The EFI linker script # LDSCRIPT = scripts/efi.lds diff --git a/src/Makefile.housekeeping b/src/Makefile.housekeeping index 1dd147949..66d6dd449 100644 --- a/src/Makefile.housekeeping +++ b/src/Makefile.housekeeping @@ -146,17 +146,6 @@ define NEWLINE endef -# Some widespread patched versions of gcc include -fstack-protector by -# default, even when -ffreestanding is specified. We therefore need -# to disable -fstack-protector if the compiler supports it. -# -ifeq ($(CCTYPE),gcc) -SP_TEST = $(CC) -fno-stack-protector -x c -c /dev/null \ - -o /dev/null >/dev/null 2>&1 -SP_FLAGS := $(shell $(SP_TEST) && $(ECHO) '-fno-stack-protector') -WORKAROUND_CFLAGS += $(SP_FLAGS) -endif - # gcc 4.4 generates .eh_frame sections by default, which distort the # output of "size". Inhibit this. # @@ -415,6 +404,13 @@ ifdef BIN incdirs : @$(ECHO) $(INCDIRS) +# Inhibit -fstack-protector (which is implicitly enabled in some +# patched gcc versions) unless explicitly mentioned in CFLAGS. +# +ifeq ($(findstring -fstack-protector,$(CFLAGS)),) +CFLAGS += -fno-stack-protector +endif + # Common flags # CFLAGS += $(foreach INC,$(INCDIRS),-I$(INC)) diff --git a/src/include/ipxe/efi/efi.h b/src/include/ipxe/efi/efi.h index 669e5364a..b8777ef47 100644 --- a/src/include/ipxe/efi/efi.h +++ b/src/include/ipxe/efi/efi.h @@ -65,6 +65,8 @@ typedef struct {} *EFI_HANDLE; #include #include +#include +#include /** An EFI protocol used by iPXE */ struct efi_protocol { @@ -272,6 +274,36 @@ extern void dbg_efi_protocols ( EFI_HANDLE handle ); #define DBGCP_EFI_PROTOCOLS( ... ) \ DBGC_EFI_PROTOCOLS_IF ( PROFILE, ##__VA_ARGS__ ) +extern unsigned long __stack_chk_guard; +extern unsigned long efi_stack_cookie ( EFI_HANDLE handle ); +extern void __stack_chk_fail ( void ); + +/** + * Initialise stack cookie + * + * @v handle Image handle + */ +static inline __attribute__ (( always_inline )) void +efi_init_stack_guard ( EFI_HANDLE handle ) { + + /* The calling function must not itself use stack protection, + * since the change in the stack guard value would trigger a + * false positive. + * + * There is unfortunately no way to annotate a function to + * exclude the use of stack protection. We must therefore + * rely on correctly anticipating the compiler's decision on + * the use of stack protection. + * + * The calculation of the stack cookie value deliberately + * takes the address of a stack variable (to provide an + * additional source of entropy). This operation would + * trigger the application of stack protection to the calling + * function, and so must be externalised. + */ + __stack_chk_guard = efi_stack_cookie ( handle ); +} + extern EFI_STATUS efi_init ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ); diff --git a/src/interface/efi/efi_init.c b/src/interface/efi/efi_init.c index ed9707f2c..df46bb17b 100644 --- a/src/interface/efi/efi_init.c +++ b/src/interface/efi/efi_init.c @@ -47,6 +47,16 @@ int efi_shutdown_in_progress; /** Event used to signal shutdown */ static EFI_EVENT efi_shutdown_event; +/** Stack cookie */ +unsigned long __stack_chk_guard; + +/** Exit function + * + * Cached to minimise external dependencies when a stack check + * failure is triggered. + */ +static EFI_EXIT efi_exit; + /* Forward declarations */ static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle ); @@ -87,6 +97,29 @@ static void * efi_find_table ( EFI_GUID *guid ) { return NULL; } +/** + * Construct a stack cookie value + * + * @v handle Image handle + * @ret cookie Stack cookie + */ +__attribute__ (( noinline )) unsigned long +efi_stack_cookie ( EFI_HANDLE handle ) { + + /* There is no viable source of entropy available at this + * point. Construct a value that is at least likely to vary + * between platforms and invocations. + * + * Ensure that the value contains a NUL byte, to act as a + * runaway string terminator. Construct the NUL using a shift + * rather than a mask, to avoid losing valuable entropy in the + * low-order bits. + */ + return ( ( ( ( unsigned long ) handle ) ^ + ( ( unsigned long ) &handle ) ^ + profile_timestamp() ^ build_id ) << 8 ); +} + /** * Initialise EFI environment * @@ -130,6 +163,9 @@ EFI_STATUS efi_init ( EFI_HANDLE image_handle, DBGC ( systab, "EFI handle %p systab %p\n", image_handle, systab ); bs = systab->BootServices; + /* Store abort function pointer */ + efi_exit = bs->Exit; + /* Look up used protocols */ for_each_table_entry ( prot, EFI_PROTOCOLS ) { if ( ( efirc = bs->LocateProtocol ( &prot->guid, NULL, @@ -240,3 +276,29 @@ static EFI_STATUS EFIAPI efi_unload ( EFI_HANDLE image_handle __unused ) { return 0; } + +/** + * Abort on stack check failure + * + */ +__attribute__ (( noreturn )) void __stack_chk_fail ( void ) { + EFI_STATUS efirc; + int rc; + + /* Report failure (when debugging) */ + DBGC ( efi_systab, "EFI stack check failed (cookie %#lx); aborting\n", + __stack_chk_guard ); + + /* Attempt to exit cleanly with an error status */ + if ( efi_exit ) { + efirc = efi_exit ( efi_image_handle, EFI_COMPROMISED_DATA, + 0, NULL ); + rc = -EEFI ( efirc ); + DBGC ( efi_systab, "EFI stack check exit failed: %s\n", + strerror ( rc ) ); + } + + /* If the exit fails for any reason, lock the system */ + while ( 1 ) {} + +} diff --git a/src/interface/efi/efidrvprefix.c b/src/interface/efi/efidrvprefix.c index 4fbb19ff7..f9bfa4c1d 100644 --- a/src/interface/efi/efidrvprefix.c +++ b/src/interface/efi/efidrvprefix.c @@ -36,6 +36,9 @@ EFI_STATUS EFIAPI _efidrv_start ( EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *systab ) { EFI_STATUS efirc; + /* Initialise stack cookie */ + efi_init_stack_guard ( image_handle ); + /* Initialise EFI environment */ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 ) return efirc; diff --git a/src/interface/efi/efiprefix.c b/src/interface/efi/efiprefix.c index de3572c75..2c5a5b31d 100644 --- a/src/interface/efi/efiprefix.c +++ b/src/interface/efi/efiprefix.c @@ -41,6 +41,9 @@ EFI_STATUS EFIAPI _efi_start ( EFI_HANDLE image_handle, EFI_STATUS efirc; int rc; + /* Initialise stack cookie */ + efi_init_stack_guard ( image_handle ); + /* Initialise EFI environment */ if ( ( efirc = efi_init ( image_handle, systab ) ) != 0 ) goto err_init; -- cgit v1.2.3-55-g7522 From 2f032c84a2cbed37308da8b29e84efb6eb2fe9e5 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 7 Jul 2020 13:13:28 +0100 Subject: [libc] Provide an unoptimised generic_memcpy_reverse() Signed-off-by: Michael Brown --- src/core/string.c | 25 ++++++++++++++++++++----- src/include/string.h | 2 ++ 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/include') diff --git a/src/core/string.c b/src/core/string.c index 5bd9dae8b..c35015b59 100644 --- a/src/core/string.c +++ b/src/core/string.c @@ -52,7 +52,7 @@ void * generic_memset ( void *dest, int character, size_t len ) { } /** - * Copy memory region + * Copy memory region (forwards) * * @v dest Destination region * @v src Source region @@ -69,24 +69,39 @@ void * generic_memcpy ( void *dest, const void *src, size_t len ) { } /** - * Copy (possibly overlapping) memory region + * Copy memory region (backwards) * * @v dest Destination region * @v src Source region * @v len Length * @ret dest Destination region */ -void * generic_memmove ( void *dest, const void *src, size_t len ) { +void * generic_memcpy_reverse ( void *dest, const void *src, size_t len ) { const uint8_t *src_bytes = ( src + len ); uint8_t *dest_bytes = ( dest + len ); - if ( dest < src ) - return generic_memcpy ( dest, src, len ); while ( len-- ) *(--dest_bytes) = *(--src_bytes); return dest; } +/** + * Copy (possibly overlapping) memory region + * + * @v dest Destination region + * @v src Source region + * @v len Length + * @ret dest Destination region + */ +void * generic_memmove ( void *dest, const void *src, size_t len ) { + + if ( dest < src ) { + return generic_memcpy ( dest, src, len ); + } else { + return generic_memcpy_reverse ( dest, src, len ); + } +} + /** * Compare memory regions * diff --git a/src/include/string.h b/src/include/string.h index 0f4182001..5f5aecb92 100644 --- a/src/include/string.h +++ b/src/include/string.h @@ -15,6 +15,8 @@ extern void * generic_memset ( void *dest, int character, size_t len ) __nonnull; extern void * generic_memcpy ( void *dest, const void *src, size_t len ) __nonnull; +extern void * generic_memcpy_reverse ( void *dest, const void *src, + size_t len ) __nonnull; extern void * generic_memmove ( void *dest, const void *src, size_t len ) __nonnull; -- cgit v1.2.3-55-g7522 From f7ddda435cf0d116098351986f89517e3d88af13 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 9 Jul 2020 13:51:30 +0100 Subject: [libc] Add bit-rotation functions for unsigned long values Generalise the bit rotation implementations to use a common macro, and add roll() and rorl() to handle unsigned long values. Each function will still compile down to a single instruction. Signed-off-by: Michael Brown --- src/include/ipxe/rotate.h | 34 ++++++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) (limited to 'src/include') diff --git a/src/include/ipxe/rotate.h b/src/include/ipxe/rotate.h index b5693e3ca..4dea09aeb 100644 --- a/src/include/ipxe/rotate.h +++ b/src/include/ipxe/rotate.h @@ -10,44 +10,62 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include +#define ROLx( data, rotation ) \ + ( ( (data) << (rotation) ) | \ + ( (data) >> ( ( 8 * sizeof (data) ) - (rotation) ) ) ); + +#define RORx( data, rotation ) \ + ( ( (data) >> (rotation) ) | \ + ( (data) << ( ( 8 * sizeof (data) ) - (rotation) ) ) ); + static inline __attribute__ (( always_inline )) uint8_t rol8 ( uint8_t data, unsigned int rotation ) { - return ( ( data << rotation ) | ( data >> ( 8 - rotation ) ) ); + return ROLx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint8_t ror8 ( uint8_t data, unsigned int rotation ) { - return ( ( data >> rotation ) | ( data << ( 8 - rotation ) ) ); + return RORx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint16_t rol16 ( uint16_t data, unsigned int rotation ) { - return ( ( data << rotation ) | ( data >> ( 16 - rotation ) ) ); + return ROLx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint16_t ror16 ( uint16_t data, unsigned int rotation ) { - return ( ( data >> rotation ) | ( data << ( 16 - rotation ) ) ); + return RORx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint32_t rol32 ( uint32_t data, unsigned int rotation ) { - return ( ( data << rotation ) | ( data >> ( 32 - rotation ) ) ); + return ROLx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint32_t ror32 ( uint32_t data, unsigned int rotation ) { - return ( ( data >> rotation ) | ( data << ( 32 - rotation ) ) ); + return RORx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint64_t rol64 ( uint64_t data, unsigned int rotation ) { - return ( ( data << rotation ) | ( data >> ( 64 - rotation ) ) ); + return ROLx ( data, rotation ); } static inline __attribute__ (( always_inline )) uint64_t ror64 ( uint64_t data, unsigned int rotation ) { - return ( ( data >> rotation ) | ( data << ( 64 - rotation ) ) ); + return RORx ( data, rotation ); +} + +static inline __attribute__ (( always_inline )) unsigned long +roll ( unsigned long data, unsigned int rotation ) { + return ROLx ( data, rotation ); +} + +static inline __attribute__ (( always_inline )) unsigned long +rorl ( unsigned long data, unsigned int rotation ) { + return RORx ( data, rotation ); } #endif /* _IPXE_ROTATE_H */ -- cgit v1.2.3-55-g7522 From a95a2eafc58b921431cbd53fc0cbff6a1a7761d1 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 15 Jul 2020 18:46:58 +0100 Subject: [xfer] Remove address family from definition of a socket opener All implemented socket openers provide definitions for both IPv4 and IPv6 using exactly the same opener method. Simplify the logic by omitting the address family from the definition. Signed-off-by: Michael Brown --- src/core/open.c | 4 +--- src/include/ipxe/open.h | 2 -- src/net/ping.c | 12 ++---------- src/net/tcp.c | 12 ++---------- src/net/udp.c | 12 ++---------- 5 files changed, 7 insertions(+), 35 deletions(-) (limited to 'src/include') diff --git a/src/core/open.c b/src/core/open.c index 9d665ffda..c27d8a021 100644 --- a/src/core/open.c +++ b/src/core/open.c @@ -147,10 +147,8 @@ int xfer_open_socket ( struct interface *intf, int semantics, socket_family_name ( peer->sa_family ) ); for_each_table_entry ( opener, SOCKET_OPENERS ) { - if ( ( opener->semantics == semantics ) && - ( opener->family == peer->sa_family ) ) { + if ( opener->semantics == semantics ) return opener->open ( intf, peer, local ); - } } DBGC ( INTF_COL ( intf ), "INTF " INTF_FMT " attempted to open " diff --git a/src/include/ipxe/open.h b/src/include/ipxe/open.h index 43d4cdc66..64e12d177 100644 --- a/src/include/ipxe/open.h +++ b/src/include/ipxe/open.h @@ -70,8 +70,6 @@ struct uri_opener { struct socket_opener { /** Communication semantics (e.g. SOCK_STREAM) */ int semantics; - /** Address family (e.g. AF_INET) */ - int family; /** Open socket * * @v intf Object interface diff --git a/src/net/ping.c b/src/net/ping.c index 3f4fa5c11..f0729e159 100644 --- a/src/net/ping.c +++ b/src/net/ping.c @@ -259,17 +259,9 @@ static int ping_open ( struct interface *xfer, struct sockaddr *peer, return rc; } -/** Ping IPv4 socket opener */ -struct socket_opener ping_ipv4_socket_opener __socket_opener = { +/** Ping socket opener */ +struct socket_opener ping_socket_opener __socket_opener = { .semantics = PING_SOCK_ECHO, - .family = AF_INET, - .open = ping_open, -}; - -/** Ping IPv6 socket opener */ -struct socket_opener ping_ipv6_socket_opener __socket_opener = { - .semantics = PING_SOCK_ECHO, - .family = AF_INET6, .open = ping_open, }; diff --git a/src/net/tcp.c b/src/net/tcp.c index 6bba44282..2a98221f6 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -1743,17 +1743,9 @@ static struct interface_descriptor tcp_xfer_desc = *************************************************************************** */ -/** TCP IPv4 socket opener */ -struct socket_opener tcp_ipv4_socket_opener __socket_opener = { +/** TCP socket opener */ +struct socket_opener tcp_socket_opener __socket_opener = { .semantics = TCP_SOCK_STREAM, - .family = AF_INET, - .open = tcp_open, -}; - -/** TCP IPv6 socket opener */ -struct socket_opener tcp_ipv6_socket_opener __socket_opener = { - .semantics = TCP_SOCK_STREAM, - .family = AF_INET6, .open = tcp_open, }; diff --git a/src/net/udp.c b/src/net/udp.c index 1fbc12d48..2c0b343dc 100644 --- a/src/net/udp.c +++ b/src/net/udp.c @@ -396,17 +396,9 @@ static struct interface_descriptor udp_xfer_desc = *************************************************************************** */ -/** UDP IPv4 socket opener */ -struct socket_opener udp_ipv4_socket_opener __socket_opener = { +/** UDP socket opener */ +struct socket_opener udp_socket_opener __socket_opener = { .semantics = UDP_SOCK_DGRAM, - .family = AF_INET, - .open = udp_open, -}; - -/** UDP IPv6 socket opener */ -struct socket_opener udp_ipv6_socket_opener __socket_opener = { - .semantics = UDP_SOCK_DGRAM, - .family = AF_INET6, .open = udp_open, }; -- cgit v1.2.3-55-g7522 From a08ee6e7221ea50d9096579d57674a07f3409da3 Mon Sep 17 00:00:00 2001 From: Joe Groocock Date: Fri, 20 Sep 2019 13:41:29 +0100 Subject: [cmdline] Add "--timeout" parameter to "ifconf" command Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/hci/commands/ifmgmt_cmd.c | 8 +++++++- src/include/usr/ifmgmt.h | 3 ++- src/usr/autoboot.c | 2 +- src/usr/ifmgmt.c | 6 ++++-- 4 files changed, 14 insertions(+), 5 deletions(-) (limited to 'src/include') diff --git a/src/hci/commands/ifmgmt_cmd.c b/src/hci/commands/ifmgmt_cmd.c index c89af2e81..2e976d3fb 100644 --- a/src/hci/commands/ifmgmt_cmd.c +++ b/src/hci/commands/ifmgmt_cmd.c @@ -193,6 +193,8 @@ static int ifstat_exec ( int argc, char **argv ) { /** "ifconf" options */ struct ifconf_options { + /** Configuration timeout */ + unsigned long timeout; /** Configurator */ struct net_device_configurator *configurator; }; @@ -202,6 +204,9 @@ static struct option_descriptor ifconf_opts[] = { OPTION_DESC ( "configurator", 'c', required_argument, struct ifconf_options, configurator, parse_netdev_configurator ), + OPTION_DESC ( "timeout", 't', required_argument, + struct ifconf_options, timeout, + parse_timeout ), }; /** @@ -216,7 +221,8 @@ static int ifconf_payload ( struct net_device *netdev, int rc; /* Attempt configuration */ - if ( ( rc = ifconf ( netdev, opts->configurator ) ) != 0 ) { + if ( ( rc = ifconf ( netdev, opts->configurator, + opts->timeout ) ) != 0 ) { /* Close device on failure, to avoid memory exhaustion */ netdev_close ( netdev ); diff --git a/src/include/usr/ifmgmt.h b/src/include/usr/ifmgmt.h index 5c386327b..52f88f957 100644 --- a/src/include/usr/ifmgmt.h +++ b/src/include/usr/ifmgmt.h @@ -14,7 +14,8 @@ struct net_device_configurator; extern int ifopen ( struct net_device *netdev ); extern int ifconf ( struct net_device *netdev, - struct net_device_configurator *configurator ); + struct net_device_configurator *configurator, + unsigned long timeout ); extern void ifclose ( struct net_device *netdev ); extern void ifstat ( struct net_device *netdev ); extern int iflinkwait ( struct net_device *netdev, unsigned long timeout ); diff --git a/src/usr/autoboot.c b/src/usr/autoboot.c index 106e0f879..51b07e125 100644 --- a/src/usr/autoboot.c +++ b/src/usr/autoboot.c @@ -396,7 +396,7 @@ int netboot ( struct net_device *netdev ) { ifstat ( netdev ); /* Configure device */ - if ( ( rc = ifconf ( netdev, NULL ) ) != 0 ) + if ( ( rc = ifconf ( netdev, NULL, 0 ) ) != 0 ) goto err_dhcp; route(); diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index f367149f7..f1172bafb 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -264,10 +264,12 @@ static int ifconf_progress ( struct ifpoller *ifpoller ) { * * @v netdev Network device * @v configurator Network device configurator, or NULL to use all + * @v timeout Timeout period, in ticks * @ret rc Return status code */ int ifconf ( struct net_device *netdev, - struct net_device_configurator *configurator ) { + struct net_device_configurator *configurator, + unsigned long timeout ) { int rc; /* Ensure device is open and link is up */ @@ -296,5 +298,5 @@ int ifconf ( struct net_device *netdev, ( configurator ? configurator->name : "" ), ( configurator ? "] " : "" ), netdev->name, netdev->ll_protocol->ntoa ( netdev->ll_addr ) ); - return ifpoller_wait ( netdev, configurator, 0, ifconf_progress ); + return ifpoller_wait ( netdev, configurator, timeout, ifconf_progress ); } -- cgit v1.2.3-55-g7522