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.
27 #include <gpxe/settings.h>
31 * Configuration settings
35 /** Registered configuration setting types */
36 static struct config_setting_type
37 config_setting_types[0] __table_start ( config_setting_types );
38 static struct config_setting_type
39 config_setting_types_end[0] __table_end ( config_setting_types );
41 /** Registered configuration settings */
42 static struct config_setting
43 config_settings[0] __table_start ( config_settings );
44 static struct config_setting
45 config_settings_end[0] __table_end ( config_settings );
48 * Find configuration setting type
51 * @ret type Configuration setting type, or NULL
53 static struct config_setting_type *
54 find_config_setting_type ( const char *name ) {
55 struct config_setting_type *type;
57 for ( type = config_setting_types ; type < config_setting_types_end ;
59 if ( strcmp ( name, type->name ) == 0 )
66 * Find configuration setting
69 * @ret setting Configuration setting, or NULL
71 static struct config_setting * find_config_setting ( const char *name ) {
72 struct config_setting *setting;
74 for ( setting = config_settings ; setting < config_settings_end ;
76 if ( strcmp ( name, setting->name ) == 0 )
83 * Find or build configuration setting
86 * @v tmp_setting Temporary buffer for constructing a setting
87 * @ret setting Configuration setting, or NULL
89 * Find setting if it exists. If it doesn't exist, but the name is of
90 * the form "<num>.<type>" (e.g. "12.string"), then construct a
91 * setting for that tag and data type, and return it. The constructed
92 * setting will be placed in the temporary buffer.
94 static struct config_setting *
95 find_or_build_config_setting ( const char *name,
96 struct config_setting *tmp_setting ) {
97 struct config_setting *setting;
100 /* Look in the list of registered settings first */
101 setting = find_config_setting ( name );
105 /* If name is of the form "<num>.<type>", try to construct a setting */
106 setting = tmp_setting;
107 memset ( setting, 0, sizeof ( *setting ) );
108 setting->name = name;
109 setting->tag = strtoul ( name, &separator, 10 );
110 if ( *separator != '.' )
112 setting->type = find_config_setting_type ( separator + 1 );
113 if ( ! setting->type )
119 * Show value of setting
121 * @v context Configuration context
122 * @v name Configuration setting name
123 * @v buf Buffer to contain value
124 * @v len Length of buffer
125 * @ret rc Return status code
127 int show_setting ( struct config_context *context, const char *name,
128 char *buf, size_t len ) {
129 struct config_setting *setting;
130 struct config_setting tmp_setting;
132 setting = find_or_build_config_setting ( name, &tmp_setting );
135 return setting->type->show ( context, setting, buf, len );
139 * Set value of setting
141 * @v context Configuration context
142 * @v name Configuration setting name
143 * @v value Setting value (as a string)
144 * @ret rc Return status code
146 int set_setting ( struct config_context *context, const char *name,
147 const char *value ) {
148 struct config_setting *setting;
149 struct config_setting tmp_setting;
151 setting = find_or_build_config_setting ( name, &tmp_setting );
154 return setting->type->set ( context, setting, value );
160 * @v context Configuration context
161 * @v name Configuration setting name
162 * @ret rc Return status code
164 int clear_setting ( struct config_context *context, const char *name ) {
165 struct config_setting *setting;
166 struct config_setting tmp_setting;
168 setting = find_or_build_config_setting ( name, &tmp_setting );
172 /* All types of settings get cleared the same way */
173 delete_dhcp_option ( context->options, setting->tag );
179 * Show value of string setting
181 * @v context Configuration context
182 * @v setting Configuration setting
183 * @v buf Buffer to contain value
184 * @v len Length of buffer
185 * @ret rc Return status code
187 static int show_string ( struct config_context *context,
188 struct config_setting *setting,
189 char *buf, size_t len ) {
190 struct dhcp_option *option;
192 option = find_dhcp_option ( context->options, setting->tag );
195 dhcp_snprintf ( buf, len, option );
200 * Set value of string setting
202 * @v context Configuration context
203 * @v setting Configuration setting
204 * @v value Setting value (as a string)
205 * @ret rc Return status code
207 static int set_string ( struct config_context *context,
208 struct config_setting *setting,
209 const char *value ) {
210 struct dhcp_option *option;
212 option = set_dhcp_option ( context->options, setting->tag,
213 value, strlen ( value ) );
219 /** A string configuration setting */
220 struct config_setting_type config_setting_type_string __config_setting_type = {
227 * Show value of IPv4 setting
229 * @v context Configuration context
230 * @v setting Configuration setting
231 * @v buf Buffer to contain value
232 * @v len Length of buffer
233 * @ret rc Return status code
235 static int show_ipv4 ( struct config_context *context,
236 struct config_setting *setting,
237 char *buf, size_t len ) {
238 struct dhcp_option *option;
241 option = find_dhcp_option ( context->options, setting->tag );
244 dhcp_ipv4_option ( option, &ipv4 );
245 snprintf ( buf, len, inet_ntoa ( ipv4 ) );
250 * Set value of IPV4 setting
252 * @v context Configuration context
253 * @v setting Configuration setting
254 * @v value Setting value (as a string)
255 * @ret rc Return status code
257 static int set_ipv4 ( struct config_context *context,
258 struct config_setting *setting,
259 const char *value ) {
260 struct dhcp_option *option;
264 if ( inet_aton ( value, &ipv4 ) == 0 )
266 option = set_dhcp_option ( context->options, setting->tag,
267 &ipv4, sizeof ( ipv4 ) );
273 /** An IPv4 configuration setting */
274 struct config_setting_type config_setting_type_ipv4 __config_setting_type = {
281 * Show value of integer setting
283 * @v context Configuration context
284 * @v setting Configuration setting
285 * @v buf Buffer to contain value
286 * @v len Length of buffer
287 * @ret rc Return status code
289 static int show_int ( struct config_context *context,
290 struct config_setting *setting,
291 char *buf, size_t len ) {
292 struct dhcp_option *option;
295 option = find_dhcp_option ( context->options, setting->tag );
298 num = dhcp_num_option ( option );
299 snprintf ( buf, len, "%ld", num );
304 * Set value of integer setting
306 * @v context Configuration context
307 * @v setting Configuration setting
308 * @v value Setting value (as a string)
309 * @v size Size of integer (in bytes)
310 * @ret rc Return status code
312 static int set_int ( struct config_context *context,
313 struct config_setting *setting,
314 const char *value, unsigned int size ) {
315 struct dhcp_option *option;
325 u.num = htonl ( strtoul ( value, &endp, 0 ) );
330 option = set_dhcp_option ( context->options, setting->tag,
331 &u.bytes[ sizeof ( u ) - size ], size );
338 * Set value of 8-bit integer setting
340 * @v context Configuration context
341 * @v setting Configuration setting
342 * @v value Setting value (as a string)
343 * @v size Size of integer (in bytes)
344 * @ret rc Return status code
346 static int set_int8 ( struct config_context *context,
347 struct config_setting *setting,
348 const char *value ) {
349 return set_int ( context, setting, value, 8 );
352 /** An 8-bit integer configuration setting */
353 struct config_setting_type config_setting_type_int8 __config_setting_type = {
359 /** Some basic setting definitions */
360 struct config_setting ip_config_setting __config_setting = {
362 .tag = DHCP_EB_YIADDR,
363 .type = &config_setting_type_ipv4,
365 struct config_setting hostname_config_setting __config_setting = {
367 .tag = DHCP_HOST_NAME,
368 .type = &config_setting_type_string,
370 struct config_setting username_config_setting __config_setting = {
372 .tag = DHCP_EB_USERNAME,
373 .type = &config_setting_type_string,
375 struct config_setting password_config_setting __config_setting = {
377 .tag = DHCP_EB_PASSWORD,
378 .type = &config_setting_type_string,
380 struct config_setting root_path_config_setting __config_setting = {
382 .tag = DHCP_ROOT_PATH,
383 .type = &config_setting_type_string,
385 struct config_setting priority_config_setting __config_setting = {
387 .tag = DHCP_EB_PRIORITY,
388 .type = &config_setting_type_int8,