2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
28 #include <gpxe/vsprintf.h>
29 #include <gpxe/settings.h>
33 * Configuration settings
37 /** Registered configuration setting types */
38 static struct config_setting_type config_setting_types[0]
39 __table_start ( struct config_setting_type, config_setting_types );
40 static struct config_setting_type config_setting_types_end[0]
41 __table_end ( struct config_setting_type, config_setting_types );
43 /** Registered configuration settings */
44 static struct config_setting config_settings[0]
45 __table_start ( struct config_setting, config_settings );
46 static struct config_setting config_settings_end[0]
47 __table_end ( struct config_setting, config_settings );
49 struct config_setting_type config_setting_type_hex __config_setting_type;
52 * Find configuration setting type
55 * @ret type Configuration setting type, or NULL
57 static struct config_setting_type *
58 find_config_setting_type ( const char *name ) {
59 struct config_setting_type *type;
61 for ( type = config_setting_types ; type < config_setting_types_end ;
63 if ( strcasecmp ( name, type->name ) == 0 )
70 * Find configuration setting
73 * @ret setting Configuration setting, or NULL
75 static struct config_setting * find_config_setting ( const char *name ) {
76 struct config_setting *setting;
78 for ( setting = config_settings ; setting < config_settings_end ;
80 if ( strcasecmp ( name, setting->name ) == 0 )
87 * Find or build configuration setting
90 * @v tmp_setting Temporary buffer for constructing a setting
91 * @ret setting Configuration setting, or NULL
93 * Find setting if it exists. If it doesn't exist, but the name is of
94 * the form "<num>.<type>" (e.g. "12.string"), then construct a
95 * setting for that tag and data type, and return it. The constructed
96 * setting will be placed in the temporary buffer.
98 static struct config_setting *
99 find_or_build_config_setting ( const char *name,
100 struct config_setting *tmp_setting ) {
101 struct config_setting *setting;
104 /* Look in the list of registered settings first */
105 setting = find_config_setting ( name );
109 /* If name is of the form "<num>.<type>", try to construct a setting */
110 setting = tmp_setting;
111 memset ( setting, 0, sizeof ( *setting ) );
112 setting->name = name;
113 setting->tag = strtoul ( name, &separator, 10 );
114 switch ( *separator ) {
116 setting->type = find_config_setting_type ( separator + 1 );
119 setting->type = &config_setting_type_hex;
124 if ( ! setting->type )
130 * Show value of named setting
132 * @v context Configuration context
133 * @v name Configuration setting name
134 * @v buf Buffer to contain value
135 * @v len Length of buffer
136 * @ret len Length of formatted value, or negative error
138 int show_named_setting ( struct config_context *context, const char *name,
139 char *buf, size_t len ) {
140 struct config_setting *setting;
141 struct config_setting tmp_setting;
143 setting = find_or_build_config_setting ( name, &tmp_setting );
146 return show_setting ( context, setting, buf, len );
150 * Set value of named setting
152 * @v context Configuration context
153 * @v name Configuration setting name
154 * @v value Setting value (as a string)
155 * @ret rc Return status code
157 int set_named_setting ( struct config_context *context, const char *name,
158 const char *value ) {
159 struct config_setting *setting;
160 struct config_setting tmp_setting;
162 setting = find_or_build_config_setting ( name, &tmp_setting );
165 return setting->type->set ( context, setting, value );
169 * Set value of setting
171 * @v context Configuration context
172 * @v setting Configuration setting
173 * @v value Setting value (as a string), or NULL
174 * @ret rc Return status code
176 int set_setting ( struct config_context *context,
177 struct config_setting *setting,
178 const char *value ) {
179 if ( ( ! value ) || ( ! *value ) ) {
180 /* Save putting deletion logic in each individual handler */
181 return clear_setting ( context, setting );
183 return setting->type->set ( context, setting, value );
187 * Show value of string setting
189 * @v context Configuration context
190 * @v setting Configuration setting
191 * @v buf Buffer to contain value
192 * @v len Length of buffer
193 * @ret len Length of formatted value, or negative error
195 static int show_string ( struct config_context *context,
196 struct config_setting *setting,
197 char *buf, size_t len ) {
198 struct dhcp_option *option;
200 option = find_dhcp_option ( context->options, setting->tag );
203 return dhcp_snprintf ( buf, len, option );
207 * Set value of string setting
209 * @v context Configuration context
210 * @v setting Configuration setting
211 * @v value Setting value (as a string)
212 * @ret rc Return status code
214 static int set_string ( struct config_context *context,
215 struct config_setting *setting,
216 const char *value ) {
217 struct dhcp_option *option;
219 option = set_dhcp_option ( context->options, setting->tag,
220 value, strlen ( value ) );
226 /** A string configuration setting */
227 struct config_setting_type config_setting_type_string __config_setting_type = {
229 .description = "Text string",
235 * Show value of IPv4 setting
237 * @v context Configuration context
238 * @v setting Configuration setting
239 * @v buf Buffer to contain value
240 * @v len Length of buffer
241 * @ret len Length of formatted value, or negative error
243 static int show_ipv4 ( struct config_context *context,
244 struct config_setting *setting,
245 char *buf, size_t len ) {
246 struct dhcp_option *option;
249 option = find_dhcp_option ( context->options, setting->tag );
252 dhcp_ipv4_option ( option, &ipv4 );
253 return snprintf ( buf, len, inet_ntoa ( ipv4 ) );
257 * Set value of IPV4 setting
259 * @v context Configuration context
260 * @v setting Configuration setting
261 * @v value Setting value (as a string)
262 * @ret rc Return status code
264 static int set_ipv4 ( struct config_context *context,
265 struct config_setting *setting,
266 const char *value ) {
267 struct dhcp_option *option;
270 if ( inet_aton ( value, &ipv4 ) == 0 )
272 option = set_dhcp_option ( context->options, setting->tag,
273 &ipv4, sizeof ( ipv4 ) );
279 /** An IPv4 configuration setting */
280 struct config_setting_type config_setting_type_ipv4 __config_setting_type = {
282 .description = "IPv4 address",
288 * Show value of integer setting
290 * @v context Configuration context
291 * @v setting Configuration setting
292 * @v buf Buffer to contain value
293 * @v len Length of buffer
294 * @ret len Length of formatted value, or negative error
296 static int show_int ( struct config_context *context,
297 struct config_setting *setting,
298 char *buf, size_t len ) {
299 struct dhcp_option *option;
302 option = find_dhcp_option ( context->options, setting->tag );
305 num = dhcp_num_option ( option );
306 return snprintf ( buf, len, "%ld", num );
310 * Set value of integer setting
312 * @v context Configuration context
313 * @v setting Configuration setting
314 * @v value Setting value (as a string)
315 * @v size Size of integer (in bytes)
316 * @ret rc Return status code
318 static int set_int ( struct config_context *context,
319 struct config_setting *setting,
320 const char *value, unsigned int size ) {
321 struct dhcp_option *option;
331 u.num = htonl ( strtoul ( value, &endp, 0 ) );
336 option = set_dhcp_option ( context->options, setting->tag,
337 &u.bytes[ sizeof ( u ) - size ], size );
344 * Set value of 8-bit integer setting
346 * @v context Configuration context
347 * @v setting Configuration setting
348 * @v value Setting value (as a string)
349 * @v size Size of integer (in bytes)
350 * @ret rc Return status code
352 static int set_int8 ( struct config_context *context,
353 struct config_setting *setting,
354 const char *value ) {
355 return set_int ( context, setting, value, 1 );
359 * Set value of 16-bit integer setting
361 * @v context Configuration context
362 * @v setting Configuration setting
363 * @v value Setting value (as a string)
364 * @v size Size of integer (in bytes)
365 * @ret rc Return status code
367 static int set_int16 ( struct config_context *context,
368 struct config_setting *setting,
369 const char *value ) {
370 return set_int ( context, setting, value, 2 );
374 * Set value of 32-bit integer setting
376 * @v context Configuration context
377 * @v setting Configuration setting
378 * @v value Setting value (as a string)
379 * @v size Size of integer (in bytes)
380 * @ret rc Return status code
382 static int set_int32 ( struct config_context *context,
383 struct config_setting *setting,
384 const char *value ) {
385 return set_int ( context, setting, value, 4 );
388 /** An 8-bit integer configuration setting */
389 struct config_setting_type config_setting_type_int8 __config_setting_type = {
391 .description = "8-bit integer",
396 /** A 16-bit integer configuration setting */
397 struct config_setting_type config_setting_type_int16 __config_setting_type = {
399 .description = "16-bit integer",
404 /** A 32-bit integer configuration setting */
405 struct config_setting_type config_setting_type_int32 __config_setting_type = {
407 .description = "32-bit integer",
413 * Set value of hex-string setting
415 * @v context Configuration context
416 * @v setting Configuration setting
417 * @v value Setting value (as a string)
418 * @ret rc Return status code
420 static int set_hex ( struct config_context *context,
421 struct config_setting *setting,
422 const char *value ) {
423 struct dhcp_option *option;
424 char *ptr = ( char * ) value;
425 uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
426 unsigned int len = 0;
429 bytes[len++] = strtoul ( ptr, &ptr, 16 );
432 option = set_dhcp_option ( context->options,
433 setting->tag, bytes, len );
447 * Show value of hex-string setting
449 * @v context Configuration context
450 * @v setting Configuration setting
451 * @v buf Buffer to contain value
452 * @v len Length of buffer
453 * @ret len Length of formatted value, or negative error
455 static int show_hex ( struct config_context *context,
456 struct config_setting *setting,
457 char *buf, size_t len ) {
458 struct dhcp_option *option;
462 option = find_dhcp_option ( context->options, setting->tag );
466 for ( i = 0 ; i < option->len ; i++ ) {
467 used += ssnprintf ( ( buf + used ), ( len - used ),
468 "%s%02x", ( used ? ":" : "" ),
469 option->data.bytes[i] );
474 /** A hex-string configuration setting */
475 struct config_setting_type config_setting_type_hex __config_setting_type = {
477 .description = "Hex string",
482 /** Some basic setting definitions */
483 struct config_setting basic_config_settings[] __config_setting = {
486 .description = "IP address of this machine (e.g. 192.168.0.1)",
487 .tag = DHCP_EB_YIADDR,
488 .type = &config_setting_type_ipv4,
492 .description = "Host name of this machine",
493 .tag = DHCP_HOST_NAME,
494 .type = &config_setting_type_string,
498 .description = "User name for authentication to servers",
499 .tag = DHCP_EB_USERNAME,
500 .type = &config_setting_type_string,
504 .description = "Password for authentication to servers",
505 .tag = DHCP_EB_PASSWORD,
506 .type = &config_setting_type_string,
510 .description = "NFS/iSCSI root path",
511 .tag = DHCP_ROOT_PATH,
512 .type = &config_setting_type_string,
516 .description = "Priority of these options",
517 .tag = DHCP_EB_PRIORITY,
518 .type = &config_setting_type_int8,
521 .name = "initiator-iqn",
522 .description = "iSCSI qualified name of this machine",
523 .tag = DHCP_ISCSI_INITIATOR_IQN,
524 .type = &config_setting_type_string,