diff options
author | Simon Rettberg | 2020-02-24 14:25:15 +0100 |
---|---|---|
committer | Simon Rettberg | 2020-02-24 14:25:15 +0100 |
commit | a77b33e5357278509ffde6284821682351c4d52a (patch) | |
tree | f57c48a8f3d2ff9102b1977f19867065db879fd1 | |
parent | Merge branch 'master' into openslx (diff) | |
parent | [iscsi] Eliminate variable-length stack allocation in URI parsing (diff) | |
download | ipxe-a77b33e5357278509ffde6284821682351c4d52a.tar.gz ipxe-a77b33e5357278509ffde6284821682351c4d52a.tar.xz ipxe-a77b33e5357278509ffde6284821682351c4d52a.zip |
Merge branch 'master' into openslx
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | src/Makefile | 17 | ||||
-rw-r--r-- | src/core/settings.c | 9 | ||||
-rw-r--r-- | src/drivers/net/efi/snpnet.c | 6 | ||||
-rw-r--r-- | src/net/infiniband/ib_srp.c | 24 | ||||
-rw-r--r-- | src/net/peerdisc.c | 69 | ||||
-rw-r--r-- | src/net/peerdist.c | 38 | ||||
-rw-r--r-- | src/net/tcp/iscsi.c | 90 | ||||
-rw-r--r-- | src/net/udp/slam.c | 32 | ||||
-rw-r--r-- | src/net/udp/tftp.c | 17 |
10 files changed, 249 insertions, 56 deletions
diff --git a/.travis.yml b/.travis.yml index 0e75158e..43849cc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,9 @@ dist: trusty sudo: false +git: + depth: false + language: c cache: ccache diff --git a/src/Makefile b/src/Makefile index c0bc45fa..a84efd6d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -207,14 +207,27 @@ install : # # Version number calculations # +ifneq ($(wildcard ../.git),) +VERSIONS := $(shell git describe --tags --always --long --abbrev=1 --match "v*") +VERSION_TUPLE := $(subst ., ,$(subst -, ,$(patsubst v%,%,$(VERSIONS)))) +VERSION_MAJOR := $(word 1,$(VERSION_TUPLE)) +VERSION_MINOR := $(word 2,$(VERSION_TUPLE)) +VERSION_PATCH := $(word 3,$(VERSION_TUPLE)) +ifeq ($(word 4,$(VERSION_TUPLE)),0) +EXTRAVERSION := +else +EXTRAVERSION := + +endif +GITVERSION = $(word 5,$(VERSION_TUPLE)) +else VERSION_MAJOR = 1 VERSION_MINOR = 0 VERSION_PATCH = 0 EXTRAVERSION = + +endif MM_VERSION = $(VERSION_MAJOR).$(VERSION_MINOR) VERSION = $(MM_VERSION).$(VERSION_PATCH)$(EXTRAVERSION) -ifneq ($(wildcard ../.git),) -GITVERSION := $(shell git describe --always --abbrev=1 --match "" 2>/dev/null) +ifneq ($(GITVERSION),) VERSION += ($(GITVERSION)) endif version : diff --git a/src/core/settings.c b/src/core/settings.c index bfe618d9..d6ab6b20 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -371,12 +371,14 @@ const char * settings_name ( struct settings *settings ) { static struct settings * parse_settings_name ( const char *name, get_child_settings_t get_child ) { struct settings *settings = &settings_root; - char name_copy[ strlen ( name ) + 1 ]; + char *name_copy; char *subname; char *remainder; /* Create modifiable copy of name */ - memcpy ( name_copy, name, sizeof ( name_copy ) ); + name_copy = strdup ( name ); + if ( ! name_copy ) + return NULL; remainder = name_copy; /* Parse each name component in turn */ @@ -390,6 +392,9 @@ parse_settings_name ( const char *name, get_child_settings_t get_child ) { break; } + /* Free modifiable copy of name */ + free ( name_copy ); + return settings; } diff --git a/src/drivers/net/efi/snpnet.c b/src/drivers/net/efi/snpnet.c index 88474b0b..536248bc 100644 --- a/src/drivers/net/efi/snpnet.c +++ b/src/drivers/net/efi/snpnet.c @@ -300,6 +300,9 @@ static int snpnet_rx_filters ( struct net_device *netdev ) { EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), + ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST ), ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST ), }; @@ -310,7 +313,8 @@ static int snpnet_rx_filters ( struct net_device *netdev ) { /* Try possible receive filters in turn */ for ( i = 0; i < ( sizeof ( filters ) / sizeof ( filters[0] ) ); i++ ) { efirc = snp->snp->ReceiveFilters ( snp->snp, filters[i], - 0, TRUE, 0, NULL ); + EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST, TRUE, + 0, NULL ); if ( efirc == 0 ) return 0; rc = -EEFI ( efirc ); diff --git a/src/net/infiniband/ib_srp.c b/src/net/infiniband/ib_srp.c index cf1ef3bf..4913f449 100644 --- a/src/net/infiniband/ib_srp.c +++ b/src/net/infiniband/ib_srp.c @@ -498,14 +498,21 @@ static struct ib_srp_root_path_parser ib_srp_rp_parser[] = { static int ib_srp_parse_root_path ( const char *rp_string, struct ib_srp_root_path *rp ) { struct ib_srp_root_path_parser *parser; - char rp_string_copy[ strlen ( rp_string ) + 1 ]; char *rp_comp[IB_SRP_NUM_RP_COMPONENTS]; - char *rp_string_tmp = rp_string_copy; + char *rp_string_copy; + char *rp_string_tmp; unsigned int i = 0; int rc; + /* Create modifiable copy of root path */ + rp_string_copy = strdup ( rp_string ); + if ( ! rp_string_copy ) { + rc = -ENOMEM; + goto err_strdup; + } + rp_string_tmp = rp_string_copy; + /* Split root path into component parts */ - strcpy ( rp_string_copy, rp_string ); while ( 1 ) { rp_comp[i++] = rp_string_tmp; if ( i == IB_SRP_NUM_RP_COMPONENTS ) @@ -514,7 +521,8 @@ static int ib_srp_parse_root_path ( const char *rp_string, if ( ! *rp_string_tmp ) { DBG ( "IBSRP root path \"%s\" too short\n", rp_string ); - return -EINVAL_RP_TOO_SHORT; + rc = -EINVAL_RP_TOO_SHORT; + goto err_split; } } *(rp_string_tmp++) = '\0'; @@ -527,11 +535,15 @@ static int ib_srp_parse_root_path ( const char *rp_string, DBG ( "IBSRP could not parse \"%s\" in root path " "\"%s\": %s\n", rp_comp[i], rp_string, strerror ( rc ) ); - return rc; + goto err_parse; } } - return 0; + err_parse: + err_split: + free ( rp_string_copy ); + err_strdup: + return rc; } /** diff --git a/src/net/peerdisc.c b/src/net/peerdisc.c index 20ac2427..55e3f7fa 100644 --- a/src/net/peerdisc.c +++ b/src/net/peerdisc.c @@ -37,6 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/netdevice.h> #include <ipxe/timer.h> #include <ipxe/fault.h> +#include <ipxe/settings.h> #include <ipxe/pccrd.h> #include <ipxe/peerdisc.h> @@ -72,6 +73,9 @@ static LIST_HEAD ( peerdisc_segments ); */ unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS; +/** Hosted cache server */ +static char *peerhost; + static struct peerdisc_segment * peerdisc_find ( const char *id ); static int peerdisc_discovered ( struct peerdisc_segment *segment, const char *location ); @@ -442,6 +446,7 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { char *uuid_copy; char *id_copy; unsigned int i; + int rc; /* Generate a random message UUID. This does not require high * quality randomness. @@ -458,7 +463,7 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { /* Allocate and initialise structure */ segment = zalloc ( sizeof ( *segment ) + id_len + uuid_len ); if ( ! segment ) - return NULL; + goto err_alloc; id_copy = ( ( ( void * ) segment ) + sizeof ( *segment ) ); memcpy ( id_copy, id, id_len ); uuid_copy = ( ( ( void * ) id_copy ) + id_len ); @@ -469,14 +474,30 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) { INIT_LIST_HEAD ( &segment->peers ); INIT_LIST_HEAD ( &segment->clients ); timer_init ( &segment->timer, peerdisc_expired, &segment->refcnt ); - DBGC2 ( segment, "PEERDISC %p discovering %s\n", segment, segment->id ); - /* Start discovery timer */ - start_timer_nodelay ( &segment->timer ); + /* Add hosted cache server or initiate discovery */ + if ( peerhost ) { + + /* Add hosted cache server to list of peers */ + if ( ( rc = peerdisc_discovered ( segment, peerhost ) ) != 0 ) + goto err_peerhost; + + } else { + + /* Start discovery timer */ + start_timer_nodelay ( &segment->timer ); + DBGC2 ( segment, "PEERDISC %p discovering %s\n", + segment, segment->id ); + } /* Add to list of segments, transfer reference to list, and return */ list_add_tail ( &segment->list, &peerdisc_segments ); return segment; + + err_peerhost: + ref_put ( &segment->refcnt ); + err_alloc: + return NULL; } /** @@ -579,3 +600,43 @@ void peerdisc_close ( struct peerdisc_client *peerdisc ) { if ( list_empty ( &peerdisc_segments ) ) peerdisc_socket_close ( 0 ); } + +/****************************************************************************** + * + * Settings + * + ****************************************************************************** + */ + +/** PeerDist hosted cache server setting */ +const struct setting peerhost_setting __setting ( SETTING_MISC, peerhost ) = { + .name = "peerhost", + .description = "PeerDist hosted cache", + .type = &setting_type_string, +}; + +/** + * Apply PeerDist discovery settings + * + * @ret rc Return status code + */ +static int apply_peerdisc_settings ( void ) { + + /* Free any existing hosted cache server */ + free ( peerhost ); + peerhost = NULL; + + /* Fetch hosted cache server */ + fetch_string_setting_copy ( NULL, &peerhost_setting, &peerhost ); + if ( peerhost ) { + DBGC ( &peerhost, "PEERDISC using hosted cache %s\n", + peerhost ); + } + + return 0; +} + +/** PeerDist discovery settings applicator */ +struct settings_applicator peerdisc_applicator __settings_applicator = { + .apply = apply_peerdisc_settings, +}; diff --git a/src/net/peerdist.c b/src/net/peerdist.c index 48933f95..3210ac0e 100644 --- a/src/net/peerdist.c +++ b/src/net/peerdist.c @@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <stdio.h> #include <ipxe/http.h> +#include <ipxe/settings.h> #include <ipxe/peermux.h> /** @file @@ -35,6 +36,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * misfortune to encounter, and I've encountered multicast TFTP. */ +/** PeerDist is globally enabled */ +static long peerdist_enabled = 1; + /** * Check whether or not to support PeerDist encoding for this request * @@ -43,6 +47,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ static int http_peerdist_supported ( struct http_transaction *http ) { + /* Allow PeerDist to be globally enabled/disabled */ + if ( ! peerdist_enabled ) + return 0; + /* Support PeerDist encoding only if we can directly access an * underlying data transfer buffer. Direct access is required * in order to support decryption of data received via the @@ -143,3 +151,33 @@ struct http_content_encoding peerdist_encoding __http_content_encoding = { .supported = http_peerdist_supported, .init = http_peerdist_init, }; + +/** PeerDist enabled setting */ +const struct setting peerdist_setting __setting ( SETTING_MISC, peerdist ) = { + .name = "peerdist", + .description = "PeerDist enabled", + .type = &setting_type_int8, +}; + +/** + * Apply PeerDist settings + * + * @ret rc Return status code + */ +static int apply_peerdist_settings ( void ) { + + /* Fetch global PeerDist enabled setting */ + if ( fetch_int_setting ( NULL, &peerdist_setting, + &peerdist_enabled ) < 0 ) { + peerdist_enabled = 1; + } + DBGC ( &peerdist_enabled, "PEERDIST is %s\n", + ( peerdist_enabled ? "enabled" : "disabled" ) ); + + return 0; +} + +/** PeerDist settings applicator */ +struct settings_applicator peerdist_applicator __settings_applicator = { + .apply = apply_peerdist_settings, +}; diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index f8379b28..3a44b90f 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -980,18 +980,26 @@ static int iscsi_handle_chap_i_value ( struct iscsi_session *iscsi, */ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi, const char *value ) { - uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */ + uint8_t *buf; unsigned int i; int len; int rc; + /* Allocate decoding buffer */ + len = strlen ( value ); /* Decoding never expands data */ + buf = malloc ( len ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + /* Process challenge */ - len = iscsi_large_binary_decode ( value, buf, sizeof ( buf ) ); + len = iscsi_large_binary_decode ( value, buf, len ); if ( len < 0 ) { rc = len; DBGC ( iscsi, "iSCSI %p invalid CHAP challenge \"%s\": %s\n", iscsi, value, strerror ( rc ) ); - return rc; + goto err_decode; } chap_update ( &iscsi->chap, buf, len ); @@ -1009,7 +1017,13 @@ static int iscsi_handle_chap_c_value ( struct iscsi_session *iscsi, } } - return 0; + /* Success */ + rc = 0; + + err_decode: + free ( buf ); + err_alloc: + return rc; } /** @@ -1050,7 +1064,7 @@ static int iscsi_handle_chap_n_value ( struct iscsi_session *iscsi, */ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, const char *value ) { - uint8_t buf[ strlen ( value ) ]; /* Decoding never expands data */ + uint8_t *buf; int len; int rc; @@ -1059,7 +1073,7 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p could not initialise CHAP: %s\n", iscsi, strerror ( rc ) ); - return rc; + goto err_chap_init; } chap_set_identifier ( &iscsi->chap, iscsi->chap_challenge[0] ); if ( iscsi->target_password ) { @@ -1070,31 +1084,47 @@ static int iscsi_handle_chap_r_value ( struct iscsi_session *iscsi, ( sizeof ( iscsi->chap_challenge ) - 1 ) ); chap_respond ( &iscsi->chap ); + /* Allocate decoding buffer */ + len = strlen ( value ); /* Decoding never expands data */ + buf = malloc ( len ); + if ( ! buf ) { + rc = -ENOMEM; + goto err_alloc; + } + /* Process response */ - len = iscsi_large_binary_decode ( value, buf, sizeof ( buf ) ); + len = iscsi_large_binary_decode ( value, buf, len ); if ( len < 0 ) { rc = len; DBGC ( iscsi, "iSCSI %p invalid CHAP response \"%s\": %s\n", iscsi, value, strerror ( rc ) ); - return rc; + goto err_decode; } /* Check CHAP response */ if ( len != ( int ) iscsi->chap.response_len ) { DBGC ( iscsi, "iSCSI %p invalid CHAP response length\n", iscsi ); - return -EPROTO_INVALID_CHAP_RESPONSE; + rc = -EPROTO_INVALID_CHAP_RESPONSE; + goto err_response_len; } if ( memcmp ( buf, iscsi->chap.response, len ) != 0 ) { DBGC ( iscsi, "iSCSI %p incorrect CHAP response \"%s\"\n", iscsi, value ); - return -EACCES_INCORRECT_TARGET_PASSWORD; + rc = -EACCES_INCORRECT_TARGET_PASSWORD; + goto err_response; } /* Mark session as authenticated */ iscsi->status |= ISCSI_STATUS_AUTH_REVERSE_OK; - return 0; + err_response: + err_response_len: + err_decode: + free ( buf ); + err_alloc: + err_chap_init: + return rc; } /** An iSCSI text string that we want to handle */ @@ -1918,15 +1948,22 @@ const struct setting reverse_password_setting __setting ( SETTING_AUTH_EXTRA, */ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, const char *root_path ) { - char rp_copy[ strlen ( root_path ) + 1 ]; + char *rp_copy; char *rp_comp[NUM_RP_COMPONENTS]; - char *rp = rp_copy; + char *rp; int skip = 0; int i = 0; int rc; + /* Create modifiable copy of root path */ + rp_copy = strdup ( root_path ); + if ( ! rp_copy ) { + rc = -ENOMEM; + goto err_strdup; + } + rp = rp_copy; + /* Split root path into component parts */ - strcpy ( rp_copy, root_path ); while ( 1 ) { rp_comp[i++] = rp; if ( i == NUM_RP_COMPONENTS ) @@ -1935,7 +1972,8 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, if ( ! *rp ) { DBGC ( iscsi, "iSCSI %p root path \"%s\" " "too short\n", iscsi, root_path ); - return -EINVAL_ROOT_PATH_TOO_SHORT; + rc = -EINVAL_ROOT_PATH_TOO_SHORT; + goto err_split; } else if ( *rp == '[' ) { skip = 1; } else if ( *rp == ']' ) { @@ -1947,21 +1985,31 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, /* Use root path components to configure iSCSI session */ iscsi->target_address = strdup ( rp_comp[RP_SERVERNAME] ); - if ( ! iscsi->target_address ) - return -ENOMEM; + if ( ! iscsi->target_address ) { + rc = -ENOMEM; + goto err_servername; + } iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 ); if ( ! iscsi->target_port ) iscsi->target_port = ISCSI_PORT; if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n", iscsi, rp_comp[RP_LUN] ); - return rc; + goto err_lun; } iscsi->target_iqn = strdup ( rp_comp[RP_TARGETNAME] ); - if ( ! iscsi->target_iqn ) - return -ENOMEM; + if ( ! iscsi->target_iqn ) { + rc = -ENOMEM; + goto err_targetname; + } - return 0; + err_targetname: + err_lun: + err_servername: + err_split: + free ( rp_copy ); + err_strdup: + return rc; } /** diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index c165b4fb..47f60080 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -655,35 +655,49 @@ static struct interface_descriptor slam_xfer_desc = */ static int slam_parse_multicast_address ( struct slam_request *slam, const char *path, - struct sockaddr_in *address ) { - char path_dup[ strlen ( path ) /* no +1 */ ]; + struct sockaddr_tcpip *address ) { + char *path_dup; char *sep; char *end; + int rc; /* Create temporary copy of path, minus the leading '/' */ assert ( *path == '/' ); - memcpy ( path_dup, ( path + 1 ) , sizeof ( path_dup ) ); + path_dup = strdup ( path + 1 ); + if ( ! path_dup ) { + rc = -ENOMEM; + goto err_strdup; + } /* Parse port, if present */ sep = strchr ( path_dup, ':' ); if ( sep ) { *(sep++) = '\0'; - address->sin_port = htons ( strtoul ( sep, &end, 0 ) ); + address->st_port = htons ( strtoul ( sep, &end, 0 ) ); if ( *end != '\0' ) { DBGC ( slam, "SLAM %p invalid multicast port " "\"%s\"\n", slam, sep ); - return -EINVAL; + rc = -EINVAL; + goto err_port; } } /* Parse address */ - if ( inet_aton ( path_dup, &address->sin_addr ) == 0 ) { + if ( sock_aton ( path_dup, ( ( struct sockaddr * ) address ) ) == 0 ) { DBGC ( slam, "SLAM %p invalid multicast address \"%s\"\n", slam, path_dup ); - return -EINVAL; + rc = -EINVAL; + goto err_addr; } - return 0; + /* Success */ + rc = 0; + + err_addr: + err_port: + free ( path_dup ); + err_strdup: + return rc; } /** @@ -701,7 +715,7 @@ static int slam_open ( struct interface *xfer, struct uri *uri ) { }; struct slam_request *slam; struct sockaddr_tcpip server; - struct sockaddr_in multicast; + struct sockaddr_tcpip multicast; int rc; /* Sanity checks */ diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index 6ce27497..a0dac1ec 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -545,8 +545,7 @@ static void tftp_timer_expired ( struct retry_timer *timer, int fail ) { * @v value Option value * @ret rc Return status code */ -static int tftp_process_blksize ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_blksize ( struct tftp_request *tftp, char *value ) { char *end; tftp->blksize = strtoul ( value, &end, 10 ); @@ -567,8 +566,7 @@ static int tftp_process_blksize ( struct tftp_request *tftp, * @v value Option value * @ret rc Return status code */ -static int tftp_process_tsize ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_tsize ( struct tftp_request *tftp, char *value ) { char *end; tftp->tsize = strtoul ( value, &end, 10 ); @@ -589,13 +587,11 @@ static int tftp_process_tsize ( struct tftp_request *tftp, * @v value Option value * @ret rc Return status code */ -static int tftp_process_multicast ( struct tftp_request *tftp, - const char *value ) { +static int tftp_process_multicast ( struct tftp_request *tftp, char *value ) { union { struct sockaddr sa; struct sockaddr_in sin; } socket; - char buf[ strlen ( value ) + 1 ]; char *addr; char *port; char *port_end; @@ -604,8 +600,7 @@ static int tftp_process_multicast ( struct tftp_request *tftp, int rc; /* Split value into "addr,port,mc" fields */ - memcpy ( buf, value, sizeof ( buf ) ); - addr = buf; + addr = value; port = strchr ( addr, ',' ); if ( ! port ) { DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp ); @@ -662,7 +657,7 @@ struct tftp_option { * @v value Option value * @ret rc Return status code */ - int ( * process ) ( struct tftp_request *tftp, const char *value ); + int ( * process ) ( struct tftp_request *tftp, char *value ); }; /** Recognised TFTP options */ @@ -682,7 +677,7 @@ static struct tftp_option tftp_options[] = { * @ret rc Return status code */ static int tftp_process_option ( struct tftp_request *tftp, - const char *name, const char *value ) { + const char *name, char *value ) { struct tftp_option *option; for ( option = tftp_options ; option->name ; option++ ) { |