Browse Source

[settings] Formalise notion of setting applicability

Expose a function setting_applies() to allow a caller to determine
whether or not a particular setting is applicable to a particular
settings block.

Restrict DHCP-backed settings blocks to accepting only DHCP-based
settings.

Restrict network device settings blocks to accepting only DHCP-based
settings and network device-specific settings such as "mac".

Inspired-by: Glenn Brown <glenn@myri.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
f5fd4dec3b

+ 14
- 0
src/core/nvo.c View File

@@ -184,6 +184,19 @@ static int nvo_save ( struct nvo_block *nvo ) {
184 184
 	return 0;
185 185
 }
186 186
 
187
+/**
188
+ * Check applicability of NVO setting
189
+ *
190
+ * @v settings		Settings block
191
+ * @v setting		Setting
192
+ * @ret applies		Setting applies within this settings block
193
+ */
194
+static int nvo_applies ( struct settings *settings __unused,
195
+			 struct setting *setting ) {
196
+
197
+	return dhcpopt_applies ( setting->tag );
198
+}
199
+
187 200
 /**
188 201
  * Store value of NVO setting
189 202
  *
@@ -236,6 +249,7 @@ static int nvo_fetch ( struct settings *settings, struct setting *setting,
236 249
 
237 250
 /** NVO settings operations */
238 251
 static struct settings_operations nvo_settings_operations = {
252
+	.applies = nvo_applies,
239 253
 	.store = nvo_store,
240 254
 	.fetch = nvo_fetch,
241 255
 };

+ 30
- 7
src/core/settings.c View File

@@ -492,6 +492,19 @@ void unregister_settings ( struct settings *settings ) {
492 492
  ******************************************************************************
493 493
  */
494 494
 
495
+/**
496
+ * Check applicability of setting
497
+ *
498
+ * @v settings		Settings block
499
+ * @v setting		Setting
500
+ * @ret applies		Setting applies within this settings block
501
+ */
502
+int setting_applies ( struct settings *settings, struct setting *setting ) {
503
+
504
+	return ( settings->op->applies ?
505
+		 settings->op->applies ( settings, setting ) : 1 );
506
+}
507
+
495 508
 /**
496 509
  * Store value of setting
497 510
  *
@@ -509,6 +522,10 @@ int store_setting ( struct settings *settings, struct setting *setting,
509 522
 	if ( ! settings )
510 523
 		settings = &settings_root;
511 524
 
525
+	/* Fail if tag does not apply to this settings block */
526
+	if ( ! setting_applies ( settings, setting ) )
527
+		return -ENOTTY;
528
+
512 529
 	/* Sanity check */
513 530
 	if ( ! settings->op->store )
514 531
 		return -ENOTSUP;
@@ -564,10 +581,12 @@ int fetch_setting ( struct settings *settings, struct setting *setting,
564 581
 	if ( ! settings->op->fetch )
565 582
 		return -ENOTSUP;
566 583
 
567
-	/* Try this block first */
568
-	if ( ( ret = settings->op->fetch ( settings, setting,
569
-					   data, len ) ) >= 0 )
584
+	/* Try this block first, if applicable */
585
+	if ( setting_applies ( settings, setting ) &&
586
+	     ( ( ret = settings->op->fetch ( settings, setting,
587
+					     data, len ) ) >= 0 ) ) {
570 588
 		return ret;
589
+	}
571 590
 
572 591
 	/* Recurse into each child block in turn */
573 592
 	list_for_each_entry ( child, &settings->children, siblings ) {
@@ -886,17 +905,19 @@ struct setting * find_setting ( const char *name ) {
886 905
 /**
887 906
  * Parse setting name as tag number
888 907
  *
908
+ * @v settings		Settings block
889 909
  * @v name		Name
890 910
  * @ret tag		Tag number, or 0 if not a valid number
891 911
  */
892
-static unsigned int parse_setting_tag ( const char *name ) {
912
+static unsigned int parse_setting_tag ( struct settings *settings,
913
+					const char *name ) {
893 914
 	char *tmp = ( ( char * ) name );
894 915
 	unsigned int tag = 0;
895 916
 
896 917
 	while ( 1 ) {
897 918
 		tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
898 919
 		if ( *tmp == 0 )
899
-			return tag;
920
+			return ( tag | settings->tag_magic );
900 921
 		if ( *tmp != '.' )
901 922
 			return 0;
902 923
 		tmp++;
@@ -946,6 +967,7 @@ parse_setting_name ( const char *name,
946 967
 	char *setting_name;
947 968
 	char *type_name;
948 969
 	struct setting *named_setting;
970
+	unsigned int tag;
949 971
 
950 972
 	/* Set defaults */
951 973
 	*settings = &settings_root;
@@ -979,9 +1001,10 @@ parse_setting_name ( const char *name,
979 1001
 	if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
980 1002
 		/* Matches a defined named setting; use that setting */
981 1003
 		memcpy ( setting, named_setting, sizeof ( *setting ) );
982
-	} else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
1004
+	} else if ( ( tag = parse_setting_tag ( *settings,
1005
+						setting_name ) ) != 0 ) {
983 1006
 		/* Is a valid numeric tag; use the tag */
984
-		setting->tag |= (*settings)->tag_magic;
1007
+		setting->tag = tag;
985 1008
 	} else {
986 1009
 		/* Use the arbitrary name */
987 1010
 		setting->name = setting_name;

+ 21
- 4
src/drivers/net/phantom/phantom.c View File

@@ -1697,6 +1697,24 @@ phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) {
1697 1697
 	return 0;
1698 1698
 }
1699 1699
 
1700
+/**
1701
+ * Check applicability of Phantom CLP setting
1702
+ *
1703
+ * @v settings		Settings block
1704
+ * @v setting		Setting
1705
+ * @ret applies		Setting applies within this settings block
1706
+ */
1707
+static int phantom_setting_applies ( struct settings *settings,
1708
+				     struct setting *setting ) {
1709
+	struct phantom_nic *phantom =
1710
+		container_of ( settings, struct phantom_nic, settings );
1711
+	unsigned int clp_setting;
1712
+
1713
+	/* Find Phantom setting equivalent to iPXE setting */
1714
+	clp_setting = phantom_clp_setting ( phantom, setting );
1715
+	return ( clp_setting != 0 );
1716
+}
1717
+
1700 1718
 /**
1701 1719
  * Store Phantom CLP setting
1702 1720
  *
@@ -1716,8 +1734,7 @@ static int phantom_store_setting ( struct settings *settings,
1716 1734
 
1717 1735
 	/* Find Phantom setting equivalent to iPXE setting */
1718 1736
 	clp_setting = phantom_clp_setting ( phantom, setting );
1719
-	if ( ! clp_setting )
1720
-		return -ENOTSUP;
1737
+	assert ( clp_setting != 0 );
1721 1738
 
1722 1739
 	/* Store setting */
1723 1740
 	if ( ( rc = phantom_clp_store ( phantom, phantom->port,
@@ -1750,8 +1767,7 @@ static int phantom_fetch_setting ( struct settings *settings,
1750 1767
 
1751 1768
 	/* Find Phantom setting equivalent to iPXE setting */
1752 1769
 	clp_setting = phantom_clp_setting ( phantom, setting );
1753
-	if ( ! clp_setting )
1754
-		return -ENOTSUP;
1770
+	assert ( clp_setting != 0 );
1755 1771
 
1756 1772
 	/* Fetch setting */
1757 1773
 	if ( ( read_len = phantom_clp_fetch ( phantom, phantom->port,
@@ -1767,6 +1783,7 @@ static int phantom_fetch_setting ( struct settings *settings,
1767 1783
 
1768 1784
 /** Phantom CLP settings operations */
1769 1785
 static struct settings_operations phantom_settings_operations = {
1786
+	.applies	= phantom_setting_applies,
1770 1787
 	.store		= phantom_store_setting,
1771 1788
 	.fetch		= phantom_fetch_setting,
1772 1789
 };

+ 1
- 0
src/include/ipxe/dhcpopts.h View File

@@ -28,6 +28,7 @@ struct dhcp_options {
28 28
 	int ( * realloc ) ( struct dhcp_options *options, size_t len );
29 29
 };
30 30
 
31
+extern int dhcpopt_applies ( unsigned int tag );
31 32
 extern int dhcpopt_store ( struct dhcp_options *options, unsigned int tag,
32 33
 			   const void *data, size_t len );
33 34
 extern int dhcpopt_fetch ( struct dhcp_options *options, unsigned int tag,

+ 21
- 0
src/include/ipxe/net80211.h View File

@@ -1183,4 +1183,25 @@ static inline u16 net80211_cts_duration ( struct net80211_device *dev,
1183 1183
 		 net80211_duration ( dev, size, dev->rates[dev->rate] ) );
1184 1184
 }
1185 1185
 
1186
+/** 802.11 device setting tag magic */
1187
+#define NET80211_SETTING_TAG_MAGIC 0x8211
1188
+
1189
+/**
1190
+ * Construct 802.11 setting tag
1191
+ *
1192
+ * @v id		Unique identifier
1193
+ * @ret tag		Setting tag
1194
+ */
1195
+#define NET80211_SETTING_TAG( id ) \
1196
+	NETDEV_SETTING_TAG ( ( NET80211_SETTING_TAG_MAGIC << 8 ) | (id) )
1197
+
1198
+/** SSID setting tag */
1199
+#define NET80211_SETTING_TAG_SSID NET80211_SETTING_TAG ( 0x01 )
1200
+
1201
+/** Active scanning setting tag */
1202
+#define NET80211_SETTING_TAG_ACTIVE_SCAN NET80211_SETTING_TAG ( 0x02 )
1203
+
1204
+/** Wireless key setting tag */
1205
+#define NET80211_SETTING_TAG_KEY NET80211_SETTING_TAG ( 0x03 )
1206
+
1186 1207
 #endif

+ 32
- 0
src/include/ipxe/netdevice.h View File

@@ -390,6 +390,38 @@ struct net_driver {
390 390
 /** Declare a network driver */
391 391
 #define __net_driver __table_entry ( NET_DRIVERS, 01 )
392 392
 
393
+/** Network device setting tag magic
394
+ *
395
+ * All DHCP option settings are deemed to be valid as network device
396
+ * settings.  There are also some extra non-DHCP settings (such as
397
+ * "mac"), which are marked as being valid network device settings by
398
+ * using a magic tag value.
399
+ */
400
+#define NETDEV_SETTING_TAG_MAGIC 0xeb
401
+
402
+/**
403
+ * Construct network device setting tag
404
+ *
405
+ * @v id		Unique identifier
406
+ * @ret tag		Setting tag
407
+ */
408
+#define NETDEV_SETTING_TAG( id ) ( ( NETDEV_SETTING_TAG_MAGIC << 24 ) | (id) )
409
+
410
+/**
411
+ * Check if tag is a network device setting tag
412
+ *
413
+ * @v tag		Setting tag
414
+ * @ret is_ours		Tag is a network device setting tag
415
+ */
416
+#define IS_NETDEV_SETTING_TAG( tag ) \
417
+	( ( (tag) >> 24 ) == NETDEV_SETTING_TAG_MAGIC )
418
+
419
+/** MAC address setting tag */
420
+#define NETDEV_SETTING_TAG_MAC NETDEV_SETTING_TAG ( 0x01 )
421
+
422
+/** Bus ID setting tag */
423
+#define NETDEV_SETTING_TAG_BUS_ID NETDEV_SETTING_TAG ( 0x02 )
424
+
393 425
 extern struct list_head net_devices;
394 426
 extern struct net_device_operations null_netdev_operations;
395 427
 extern struct settings_operations netdev_settings_operations;

+ 36
- 4
src/include/ipxe/settings.h View File

@@ -33,7 +33,31 @@ struct setting {
33 33
 	 * address, etc.).
34 34
 	 */
35 35
 	struct setting_type *type;
36
-	/** DHCP option number, if applicable */
36
+	/** Setting tag, if applicable
37
+	 *
38
+	 * The setting tag is a numerical description of the setting
39
+	 * (such as a DHCP option number, or an SMBIOS structure and
40
+	 * field number).
41
+	 *
42
+	 * Users can construct tags for settings that are not
43
+	 * explicitly known to iPXE using the generic syntax for
44
+	 * numerical settings.  For example, the setting name "60"
45
+	 * will be interpreted as referring to DHCP option 60 (the
46
+	 * vendor class identifier).
47
+	 *
48
+	 * This creates a potential for namespace collisions, since
49
+	 * the interpretation of the numerical description will vary
50
+	 * according to the settings block.  When a user attempts to
51
+	 * fetch a generic numerical setting, we need to ensure that
52
+	 * only the intended settings block interprets the numerical
53
+	 * description.  (For example, we do not want to attempt to
54
+	 * retrieve the subnet mask from SMBIOS, or the system UUID
55
+	 * from DHCP.)
56
+	 *
57
+	 * This potential problem is resolved by allowing the setting
58
+	 * tag to include a "magic" value indicating the
59
+	 * interpretation to be placed upon the numerical description.
60
+	 */
37 61
 	unsigned int tag;
38 62
 };
39 63
 
@@ -45,6 +69,14 @@ struct setting {
45 69
 
46 70
 /** Settings block operations */
47 71
 struct settings_operations {
72
+	/** Check applicability of setting
73
+	 *
74
+	 * @v settings		Settings block
75
+	 * @v setting		Setting
76
+	 * @ret applies		Setting applies within this settings block
77
+	 */
78
+	int ( * applies ) ( struct settings *settings,
79
+			    struct setting *setting );
48 80
 	/** Store value of setting
49 81
 	 *
50 82
 	 * @v settings		Settings block
@@ -84,9 +116,7 @@ struct settings {
84 116
 	/** Tag magic
85 117
 	 *
86 118
 	 * This value will be ORed in to any numerical tags
87
-	 * constructed by parse_setting_name(), and can be used to
88
-	 * avoid e.g. attempting to retrieve the subnet mask from
89
-	 * SMBIOS, or the system UUID from DHCP.
119
+	 * constructed by parse_setting_name().
90 120
 	 */
91 121
 	unsigned int tag_magic;
92 122
 	/** Parent settings block */
@@ -181,6 +211,8 @@ extern int register_settings ( struct settings *settings,
181 211
 			       struct settings *parent, const char *name );
182 212
 extern void unregister_settings ( struct settings *settings );
183 213
 
214
+extern int setting_applies ( struct settings *settings,
215
+			     struct setting *setting );
184 216
 extern int store_setting ( struct settings *settings, struct setting *setting,
185 217
 			   const void *data, size_t len );
186 218
 extern int fetch_setting ( struct settings *settings, struct setting *setting,

+ 18
- 2
src/interface/smbios/smbios_settings.c View File

@@ -63,6 +63,22 @@ FILE_LICENCE ( GPL2_OR_LATER );
63 63
 	  ( (_type) << 16 ) |					\
64 64
 	  ( offsetof ( _structure, _field ) << 8 ) )
65 65
 
66
+/**
67
+ * Check applicability of SMBIOS setting
68
+ *
69
+ * @v settings		Settings block
70
+ * @v setting		Setting
71
+ * @ret applies		Setting applies within this settings block
72
+ */
73
+static int smbios_applies ( struct settings *settings __unused,
74
+			    struct setting *setting ) {
75
+	unsigned int tag_magic;
76
+
77
+	/* Check tag magic */
78
+	tag_magic = ( setting->tag >> 24 );
79
+	return ( tag_magic == SMBIOS_TAG_MAGIC );
80
+}
81
+
66 82
 /**
67 83
  * Fetch value of SMBIOS setting
68 84
  *
@@ -87,8 +103,7 @@ static int smbios_fetch ( struct settings *settings __unused,
87 103
 	tag_type = ( ( setting->tag >> 16 ) & 0xff );
88 104
 	tag_offset = ( ( setting->tag >> 8 ) & 0xff );
89 105
 	tag_len = ( setting->tag & 0xff );
90
-	if ( tag_magic != SMBIOS_TAG_MAGIC )
91
-		return -ENOENT;
106
+	assert ( tag_magic == SMBIOS_TAG_MAGIC );
92 107
 
93 108
 	/* Find SMBIOS structure */
94 109
 	if ( ( rc = find_smbios_structure ( tag_type, &structure ) ) != 0 )
@@ -119,6 +134,7 @@ static int smbios_fetch ( struct settings *settings __unused,
119 134
 
120 135
 /** SMBIOS settings operations */
121 136
 static struct settings_operations smbios_settings_operations = {
137
+	.applies = smbios_applies,
122 138
 	.fetch = smbios_fetch,
123 139
 };
124 140
 

+ 3
- 0
src/net/80211/net80211.c View File

@@ -206,6 +206,7 @@ struct setting net80211_ssid_setting __setting = {
206 206
 	.name = "ssid",
207 207
 	.description = "802.11 SSID (network name)",
208 208
 	.type = &setting_type_string,
209
+	.tag = NET80211_SETTING_TAG_SSID,
209 210
 };
210 211
 
211 212
 /** Whether to use active scanning
@@ -218,6 +219,7 @@ struct setting net80211_active_setting __setting = {
218 219
 	.name = "active-scan",
219 220
 	.description = "Use an active scan during 802.11 association",
220 221
 	.type = &setting_type_int8,
222
+	.tag = NET80211_SETTING_TAG_ACTIVE_SCAN,
221 223
 };
222 224
 
223 225
 /** The cryptographic key to use
@@ -230,6 +232,7 @@ struct setting net80211_key_setting __setting = {
230 232
 	.name = "key",
231 233
 	.description = "Encryption key for protected 802.11 networks",
232 234
 	.type = &setting_type_string,
235
+	.tag = NET80211_SETTING_TAG_KEY,
233 236
 };
234 237
 
235 238
 /** @} */

+ 12
- 0
src/net/dhcpopts.c View File

@@ -347,6 +347,18 @@ static int set_dhcp_option ( struct dhcp_options *options, unsigned int tag,
347 347
 	return offset;
348 348
 }
349 349
 
350
+/**
351
+ * Check applicability of DHCP option setting
352
+ *
353
+ * @v tag		Setting tag number
354
+ * @ret applies		Setting applies to this option block
355
+ */
356
+int dhcpopt_applies ( unsigned int tag ) {
357
+
358
+	return ( tag && ( tag <= DHCP_ENCAP_OPT ( DHCP_MAX_OPTION,
359
+						  DHCP_MAX_OPTION ) ) );
360
+}
361
+
350 362
 /**
351 363
  * Store value of DHCP option setting
352 364
  *

+ 29
- 0
src/net/dhcppkt.c View File

@@ -134,6 +134,19 @@ find_dhcp_packet_field ( unsigned int tag ) {
134 134
 	return NULL;
135 135
 }
136 136
 
137
+/**
138
+ * Check applicability of DHCP setting
139
+ *
140
+ * @v dhcppkt		DHCP packet
141
+ * @v tag		Setting tag number
142
+ * @ret applies		Setting applies within this settings block
143
+ */
144
+static int dhcppkt_applies ( struct dhcp_packet *dhcppkt __unused,
145
+			     unsigned int tag ) {
146
+
147
+	return dhcpopt_applies ( tag );
148
+}
149
+
137 150
 /**
138 151
  * Store value of DHCP packet setting
139 152
  *
@@ -204,6 +217,21 @@ int dhcppkt_fetch ( struct dhcp_packet *dhcppkt, unsigned int tag,
204 217
  *
205 218
  */
206 219
 
220
+/**
221
+ * Check applicability of DHCP setting
222
+ *
223
+ * @v settings		Settings block
224
+ * @v setting		Setting
225
+ * @ret applies		Setting applies within this settings block
226
+ */
227
+static int dhcppkt_settings_applies ( struct settings *settings,
228
+				      struct setting *setting ) {
229
+	struct dhcp_packet *dhcppkt =
230
+		container_of ( settings, struct dhcp_packet, settings );
231
+
232
+	return dhcppkt_applies ( dhcppkt, setting->tag );
233
+}
234
+
207 235
 /**
208 236
  * Store value of DHCP setting
209 237
  *
@@ -242,6 +270,7 @@ static int dhcppkt_settings_fetch ( struct settings *settings,
242 270
 
243 271
 /** DHCP settings operations */
244 272
 static struct settings_operations dhcppkt_settings_operations = {
273
+	.applies = dhcppkt_settings_applies,
245 274
 	.store = dhcppkt_settings_store,
246 275
 	.fetch = dhcppkt_settings_fetch,
247 276
 };

+ 18
- 0
src/net/netdev_settings.c View File

@@ -22,6 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
22 22
 #include <errno.h>
23 23
 #include <byteswap.h>
24 24
 #include <ipxe/dhcp.h>
25
+#include <ipxe/dhcpopts.h>
25 26
 #include <ipxe/settings.h>
26 27
 #include <ipxe/device.h>
27 28
 #include <ipxe/netdevice.h>
@@ -37,13 +38,29 @@ struct setting mac_setting __setting = {
37 38
 	.name = "mac",
38 39
 	.description = "MAC address",
39 40
 	.type = &setting_type_hex,
41
+	.tag = NETDEV_SETTING_TAG_MAC,
40 42
 };
41 43
 struct setting busid_setting __setting = {
42 44
 	.name = "busid",
43 45
 	.description = "Bus ID",
44 46
 	.type = &setting_type_hex,
47
+	.tag = NETDEV_SETTING_TAG_BUS_ID,
45 48
 };
46 49
 
50
+/**
51
+ * Check applicability of network device setting
52
+ *
53
+ * @v settings		Settings block
54
+ * @v setting		Setting
55
+ * @ret applies		Setting applies within this settings block
56
+ */
57
+static int netdev_applies ( struct settings *settings __unused,
58
+			    struct setting *setting ) {
59
+
60
+	return ( IS_NETDEV_SETTING_TAG ( setting->tag ) ||
61
+		 dhcpopt_applies ( setting->tag ) );
62
+}
63
+
47 64
 /**
48 65
  * Store value of network device setting
49 66
  *
@@ -114,6 +131,7 @@ static void netdev_clear ( struct settings *settings ) {
114 131
 
115 132
 /** Network device configuration settings operations */
116 133
 struct settings_operations netdev_settings_operations = {
134
+	.applies = netdev_applies,
117 135
 	.store = netdev_store,
118 136
 	.fetch = netdev_fetch,
119 137
 	.clear = netdev_clear,

Loading…
Cancel
Save