summaryrefslogtreecommitdiff
path: root/gpxe/src/core/settings.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
committerH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
commitf2f897a1762fab84d2905f32b1c15dd7b42abb56 (patch)
treea38f51d3f1fcbf44afddb4736d549c12eaf491be /gpxe/src/core/settings.c
parent72d2959272b4616f17a97667e6dfa9d06bf109a3 (diff)
downloadsyslinux-f2f897a1762fab84d2905f32b1c15dd7b42abb56.tar.gz
gpxe: delete long since obsolete snapshot of gPXE
gPXE has been deprecated in favor of iPXE for many, many years now. It is much better than users get it directly from the iPXE project, since we should no longer need any special modifications for Syslinux use. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'gpxe/src/core/settings.c')
-rw-r--r--gpxe/src/core/settings.c1456
1 files changed, 0 insertions, 1456 deletions
diff --git a/gpxe/src/core/settings.c b/gpxe/src/core/settings.c
deleted file mode 100644
index 7d83101c..00000000
--- a/gpxe/src/core/settings.c
+++ /dev/null
@@ -1,1456 +0,0 @@
-/*
- * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <byteswap.h>
-#include <errno.h>
-#include <assert.h>
-#include <gpxe/in.h>
-#include <gpxe/vsprintf.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/uuid.h>
-#include <gpxe/uri.h>
-#include <gpxe/settings.h>
-
-/** @file
- *
- * Configuration settings
- *
- */
-
-/******************************************************************************
- *
- * Generic settings blocks
- *
- ******************************************************************************
- */
-
-/**
- * A generic setting
- *
- */
-struct generic_setting {
- /** List of generic settings */
- struct list_head list;
- /** Setting */
- struct setting setting;
- /** Size of setting name */
- size_t name_len;
- /** Size of setting data */
- size_t data_len;
-};
-
-/**
- * Get generic setting name
- *
- * @v generic Generic setting
- * @ret name Generic setting name
- */
-static inline void * generic_setting_name ( struct generic_setting *generic ) {
- return ( ( ( void * ) generic ) + sizeof ( *generic ) );
-}
-
-/**
- * Get generic setting data
- *
- * @v generic Generic setting
- * @ret data Generic setting data
- */
-static inline void * generic_setting_data ( struct generic_setting *generic ) {
- return ( ( ( void * ) generic ) + sizeof ( *generic ) +
- generic->name_len );
-}
-
-/**
- * Find generic setting
- *
- * @v generics Generic settings block
- * @v setting Setting to find
- * @ret generic Generic setting, or NULL
- */
-static struct generic_setting *
-find_generic_setting ( struct generic_settings *generics,
- struct setting *setting ) {
- struct generic_setting *generic;
-
- list_for_each_entry ( generic, &generics->list, list ) {
- if ( setting_cmp ( &generic->setting, setting ) == 0 )
- return generic;
- }
- return NULL;
-}
-
-/**
- * Store value of generic setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v data Setting data, or NULL to clear setting
- * @v len Length of setting data
- * @ret rc Return status code
- */
-int generic_settings_store ( struct settings *settings,
- struct setting *setting,
- const void *data, size_t len ) {
- struct generic_settings *generics =
- container_of ( settings, struct generic_settings, settings );
- struct generic_setting *old;
- struct generic_setting *new = NULL;
- size_t name_len;
-
- /* Identify existing generic setting, if any */
- old = find_generic_setting ( generics, setting );
-
- /* Create new generic setting, if required */
- if ( len ) {
- /* Allocate new generic setting */
- name_len = ( strlen ( setting->name ) + 1 );
- new = zalloc ( sizeof ( *new ) + name_len + len );
- if ( ! new )
- return -ENOMEM;
-
- /* Populate new generic setting */
- new->name_len = name_len;
- new->data_len = len;
- memcpy ( &new->setting, setting, sizeof ( new->setting ) );
- new->setting.name = generic_setting_name ( new );
- memcpy ( generic_setting_name ( new ),
- setting->name, name_len );
- memcpy ( generic_setting_data ( new ), data, len );
- }
-
- /* Delete existing generic setting, if any */
- if ( old ) {
- list_del ( &old->list );
- free ( old );
- }
-
- /* Add new setting to list, if any */
- if ( new )
- list_add ( &new->list, &generics->list );
-
- return 0;
-}
-
-/**
- * Fetch value of generic setting
- *
- * @v settings Settings block
- * @v setting Setting to fetch
- * @v data Buffer to fill with setting data
- * @v len Length of buffer
- * @ret len Length of setting data, or negative error
- */
-int generic_settings_fetch ( struct settings *settings,
- struct setting *setting,
- void *data, size_t len ) {
- struct generic_settings *generics =
- container_of ( settings, struct generic_settings, settings );
- struct generic_setting *generic;
-
- /* Find generic setting */
- generic = find_generic_setting ( generics, setting );
- if ( ! generic )
- return -ENOENT;
-
- /* Copy out generic setting data */
- if ( len > generic->data_len )
- len = generic->data_len;
- memcpy ( data, generic_setting_data ( generic ), len );
- return generic->data_len;
-}
-
-/**
- * Clear generic settings block
- *
- * @v settings Settings block
- */
-void generic_settings_clear ( struct settings *settings ) {
- struct generic_settings *generics =
- container_of ( settings, struct generic_settings, settings );
- struct generic_setting *generic;
- struct generic_setting *tmp;
-
- list_for_each_entry_safe ( generic, tmp, &generics->list, list ) {
- list_del ( &generic->list );
- free ( generic );
- }
- assert ( list_empty ( &generics->list ) );
-}
-
-/** Generic settings operations */
-struct settings_operations generic_settings_operations = {
- .store = generic_settings_store,
- .fetch = generic_settings_fetch,
- .clear = generic_settings_clear,
-};
-
-/******************************************************************************
- *
- * Registered settings blocks
- *
- ******************************************************************************
- */
-
-/** Root generic settings block */
-struct generic_settings generic_settings_root = {
- .settings = {
- .refcnt = NULL,
- .name = "",
- .siblings =
- LIST_HEAD_INIT ( generic_settings_root.settings.siblings ),
- .children =
- LIST_HEAD_INIT ( generic_settings_root.settings.children ),
- .op = &generic_settings_operations,
- },
- .list = LIST_HEAD_INIT ( generic_settings_root.list ),
-};
-
-/** Root settings block */
-#define settings_root generic_settings_root.settings
-
-/**
- * Find child named settings block
- *
- * @v parent Parent settings block
- * @v name Name within this parent
- * @ret settings Settings block, or NULL
- */
-static struct settings * find_child_settings ( struct settings *parent,
- const char *name ) {
- struct settings *settings;
-
- /* Treat empty name as meaning "this block" */
- if ( ! *name )
- return parent;
-
- /* Look for child with matching name */
- list_for_each_entry ( settings, &parent->children, siblings ) {
- if ( strcmp ( settings->name, name ) == 0 )
- return settings;
- }
-
- return NULL;
-}
-
-/**
- * Find or create child named settings block
- *
- * @v parent Parent settings block
- * @v name Name within this parent
- * @ret settings Settings block, or NULL
- */
-static struct settings * autovivify_child_settings ( struct settings *parent,
- const char *name ) {
- struct {
- struct generic_settings generic;
- char name[ strlen ( name ) + 1 /* NUL */ ];
- } *new_child;
- struct settings *settings;
-
- /* Return existing settings, if existent */
- if ( ( settings = find_child_settings ( parent, name ) ) != NULL )
- return settings;
-
- /* Create new generic settings block */
- new_child = zalloc ( sizeof ( *new_child ) );
- if ( ! new_child ) {
- DBGC ( parent, "Settings %p could not create child %s\n",
- parent, name );
- return NULL;
- }
- memcpy ( new_child->name, name, sizeof ( new_child->name ) );
- generic_settings_init ( &new_child->generic, NULL, new_child->name );
- settings = &new_child->generic.settings;
- register_settings ( settings, parent );
- return settings;
-}
-
-/**
- * Return settings block name (for debug only)
- *
- * @v settings Settings block
- * @ret name Settings block name
- */
-static const char * settings_name ( struct settings *settings ) {
- static char buf[64];
- char tmp[ sizeof ( buf ) ];
- int count;
-
- for ( count = 0 ; settings ; settings = settings->parent ) {
- memcpy ( tmp, buf, sizeof ( tmp ) );
- snprintf ( buf, sizeof ( buf ), "%s%c%s", settings->name,
- ( count++ ? '.' : '\0' ), tmp );
- }
- return ( buf + 1 );
-}
-
-/**
- * Parse settings block name
- *
- * @v name Name
- * @v get_child Function to find or create child settings block
- * @ret settings Settings block, or NULL
- */
-static struct settings *
-parse_settings_name ( const char *name,
- struct settings * ( * get_child ) ( struct settings *,
- const char * ) ) {
- struct settings *settings = &settings_root;
- char name_copy[ strlen ( name ) + 1 ];
- char *subname;
- char *remainder;
-
- /* Create modifiable copy of name */
- memcpy ( name_copy, name, sizeof ( name_copy ) );
- remainder = name_copy;
-
- /* Parse each name component in turn */
- while ( remainder ) {
- struct net_device *netdev;
-
- subname = remainder;
- remainder = strchr ( subname, '.' );
- if ( remainder )
- *(remainder++) = '\0';
-
- /* Special case "netX" root settings block */
- if ( ( subname == name_copy ) && ! strcmp ( subname, "netX" ) &&
- ( ( netdev = last_opened_netdev() ) != NULL ) )
- settings = get_child ( settings, netdev->name );
- else
- settings = get_child ( settings, subname );
-
- if ( ! settings )
- break;
- }
-
- return settings;
-}
-
-/**
- * Find named settings block
- *
- * @v name Name
- * @ret settings Settings block, or NULL
- */
-struct settings * find_settings ( const char *name ) {
-
- return parse_settings_name ( name, find_child_settings );
-}
-
-/**
- * Apply all settings
- *
- * @ret rc Return status code
- */
-static int apply_settings ( void ) {
- struct settings_applicator *applicator;
- int rc;
-
- /* Call all settings applicators */
- for_each_table_entry ( applicator, SETTINGS_APPLICATORS ) {
- if ( ( rc = applicator->apply() ) != 0 ) {
- DBG ( "Could not apply settings using applicator "
- "%p: %s\n", applicator, strerror ( rc ) );
- return rc;
- }
- }
-
- return 0;
-}
-
-/**
- * Reprioritise settings
- *
- * @v settings Settings block
- *
- * Reorders the settings block amongst its siblings according to its
- * priority.
- */
-static void reprioritise_settings ( struct settings *settings ) {
- struct settings *parent = settings->parent;
- long priority;
- struct settings *tmp;
- long tmp_priority;
-
- /* Stop when we reach the top of the tree */
- if ( ! parent )
- return;
-
- /* Read priority, if present */
- priority = fetch_intz_setting ( settings, &priority_setting );
-
- /* Remove from siblings list */
- list_del ( &settings->siblings );
-
- /* Reinsert after any existing blocks which have a higher priority */
- list_for_each_entry ( tmp, &parent->children, siblings ) {
- tmp_priority = fetch_intz_setting ( tmp, &priority_setting );
- if ( priority > tmp_priority )
- break;
- }
- list_add_tail ( &settings->siblings, &tmp->siblings );
-
- /* Recurse up the tree */
- reprioritise_settings ( parent );
-}
-
-/**
- * Register settings block
- *
- * @v settings Settings block
- * @v parent Parent settings block, or NULL
- * @ret rc Return status code
- */
-int register_settings ( struct settings *settings, struct settings *parent ) {
- struct settings *old_settings;
-
- /* NULL parent => add to settings root */
- assert ( settings != NULL );
- if ( parent == NULL )
- parent = &settings_root;
-
- /* Remove any existing settings with the same name */
- if ( ( old_settings = find_child_settings ( parent, settings->name ) ))
- unregister_settings ( old_settings );
-
- /* Add to list of settings */
- ref_get ( settings->refcnt );
- ref_get ( parent->refcnt );
- settings->parent = parent;
- list_add_tail ( &settings->siblings, &parent->children );
- DBGC ( settings, "Settings %p (\"%s\") registered\n",
- settings, settings_name ( settings ) );
-
- /* Fix up settings priority */
- reprioritise_settings ( settings );
-
- /* Apply potentially-updated settings */
- apply_settings();
-
- return 0;
-}
-
-/**
- * Unregister settings block
- *
- * @v settings Settings block
- */
-void unregister_settings ( struct settings *settings ) {
-
- DBGC ( settings, "Settings %p (\"%s\") unregistered\n",
- settings, settings_name ( settings ) );
-
- /* Remove from list of settings */
- ref_put ( settings->refcnt );
- ref_put ( settings->parent->refcnt );
- settings->parent = NULL;
- list_del ( &settings->siblings );
-
- /* Apply potentially-updated settings */
- apply_settings();
-}
-
-/******************************************************************************
- *
- * Core settings routines
- *
- ******************************************************************************
- */
-
-/**
- * Store value of setting
- *
- * @v settings Settings block, or NULL
- * @v setting Setting to store
- * @v data Setting data, or NULL to clear setting
- * @v len Length of setting data
- * @ret rc Return status code
- */
-int store_setting ( struct settings *settings, struct setting *setting,
- const void *data, size_t len ) {
- int rc;
-
- /* NULL settings implies storing into the global settings root */
- if ( ! settings )
- settings = &settings_root;
-
- /* Sanity check */
- if ( ! settings->op->store )
- return -ENOTSUP;
-
- /* Store setting */
- if ( ( rc = settings->op->store ( settings, setting,
- data, len ) ) != 0 )
- return rc;
-
- /* Reprioritise settings if necessary */
- if ( setting_cmp ( setting, &priority_setting ) == 0 )
- reprioritise_settings ( settings );
-
- /* If these settings are registered, apply potentially-updated
- * settings
- */
- for ( ; settings ; settings = settings->parent ) {
- if ( settings == &settings_root ) {
- if ( ( rc = apply_settings() ) != 0 )
- return rc;
- break;
- }
- }
-
- return 0;
-}
-
-/**
- * Fetch value of setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v data Buffer to fill with setting data
- * @v len Length of buffer
- * @ret len Length of setting data, or negative error
- *
- * The actual length of the setting will be returned even if
- * the buffer was too small.
- */
-int fetch_setting ( struct settings *settings, struct setting *setting,
- void *data, size_t len ) {
- struct settings *child;
- int ret;
-
- /* Avoid returning uninitialised data on error */
- memset ( data, 0, len );
-
- /* NULL settings implies starting at the global settings root */
- if ( ! settings )
- settings = &settings_root;
-
- /* Sanity check */
- if ( ! settings->op->fetch )
- return -ENOTSUP;
-
- /* Try this block first */
- if ( ( ret = settings->op->fetch ( settings, setting,
- data, len ) ) >= 0 )
- return ret;
-
- /* Recurse into each child block in turn */
- list_for_each_entry ( child, &settings->children, siblings ) {
- if ( ( ret = fetch_setting ( child, setting,
- data, len ) ) >= 0 )
- return ret;
- }
-
- return -ENOENT;
-}
-
-/**
- * Fetch length of setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @ret len Length of setting data, or negative error
- *
- * This function can also be used as an existence check for the
- * setting.
- */
-int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
- return fetch_setting ( settings, setting, NULL, 0 );
-}
-
-/**
- * Fetch value of string setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v data Buffer to fill with setting string data
- * @v len Length of buffer
- * @ret len Length of string setting, or negative error
- *
- * The resulting string is guaranteed to be correctly NUL-terminated.
- * The returned length will be the length of the underlying setting
- * data.
- */
-int fetch_string_setting ( struct settings *settings, struct setting *setting,
- char *data, size_t len ) {
- memset ( data, 0, len );
- return fetch_setting ( settings, setting, data,
- ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
-}
-
-/**
- * Fetch value of string setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v data Buffer to allocate and fill with setting string data
- * @ret len Length of string setting, or negative error
- *
- * The resulting string is guaranteed to be correctly NUL-terminated.
- * The returned length will be the length of the underlying setting
- * data. The caller is responsible for eventually freeing the
- * allocated buffer.
- */
-int fetch_string_setting_copy ( struct settings *settings,
- struct setting *setting,
- char **data ) {
- int len;
- int check_len = 0;
-
- len = fetch_setting_len ( settings, setting );
- if ( len < 0 )
- return len;
-
- *data = malloc ( len + 1 );
- if ( ! *data )
- return -ENOMEM;
-
- check_len = fetch_string_setting ( settings, setting, *data,
- ( len + 1 ) );
- assert ( check_len == len );
- return len;
-}
-
-/**
- * Fetch value of IPv4 address setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v inp IPv4 address to fill in
- * @ret len Length of setting, or negative error
- */
-int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
- struct in_addr *inp ) {
- int len;
-
- len = fetch_setting ( settings, setting, inp, sizeof ( *inp ) );
- if ( len < 0 )
- return len;
- if ( len < ( int ) sizeof ( *inp ) )
- return -ERANGE;
- return len;
-}
-
-/**
- * Fetch value of signed integer setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v value Integer value to fill in
- * @ret len Length of setting, or negative error
- */
-int fetch_int_setting ( struct settings *settings, struct setting *setting,
- long *value ) {
- union {
- uint8_t u8[ sizeof ( long ) ];
- int8_t s8[ sizeof ( long ) ];
- } buf;
- int len;
- int i;
-
- /* Avoid returning uninitialised data on error */
- *value = 0;
-
- /* Fetch raw (network-ordered, variable-length) setting */
- len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
- if ( len < 0 )
- return len;
- if ( len > ( int ) sizeof ( buf ) )
- return -ERANGE;
-
- /* Convert to host-ordered signed long */
- *value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
- for ( i = 0 ; i < len ; i++ ) {
- *value = ( ( *value << 8 ) | buf.u8[i] );
- }
-
- return len;
-}
-
-/**
- * Fetch value of unsigned integer setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v value Integer value to fill in
- * @ret len Length of setting, or negative error
- */
-int fetch_uint_setting ( struct settings *settings, struct setting *setting,
- unsigned long *value ) {
- long svalue;
- int len;
-
- /* Avoid returning uninitialised data on error */
- *value = 0;
-
- /* Fetch as a signed long */
- len = fetch_int_setting ( settings, setting, &svalue );
- if ( len < 0 )
- return len;
-
- /* Mask off sign-extended bits */
- assert ( len <= ( int ) sizeof ( long ) );
- *value = ( svalue & ( -1UL >> ( 8 * ( sizeof ( long ) - len ) ) ) );
-
- return len;
-}
-
-/**
- * Fetch value of signed integer setting, or zero
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @ret value Setting value, or zero
- */
-long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
- long value;
-
- fetch_int_setting ( settings, setting, &value );
- return value;
-}
-
-/**
- * Fetch value of unsigned integer setting, or zero
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @ret value Setting value, or zero
- */
-unsigned long fetch_uintz_setting ( struct settings *settings,
- struct setting *setting ) {
- unsigned long value;
-
- fetch_uint_setting ( settings, setting, &value );
- return value;
-}
-
-/**
- * Fetch value of UUID setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v uuid UUID to fill in
- * @ret len Length of setting, or negative error
- */
-int fetch_uuid_setting ( struct settings *settings, struct setting *setting,
- union uuid *uuid ) {
- int len;
-
- len = fetch_setting ( settings, setting, uuid, sizeof ( *uuid ) );
- if ( len < 0 )
- return len;
- if ( len != sizeof ( *uuid ) )
- return -ERANGE;
- return len;
-}
-
-/**
- * Clear settings block
- *
- * @v settings Settings block
- */
-void clear_settings ( struct settings *settings ) {
- if ( settings->op->clear )
- settings->op->clear ( settings );
-}
-
-/**
- * Compare two settings
- *
- * @v a Setting to compare
- * @v b Setting to compare
- * @ret 0 Settings are the same
- * @ret non-zero Settings are not the same
- */
-int setting_cmp ( struct setting *a, struct setting *b ) {
-
- /* If the settings have tags, compare them */
- if ( a->tag && ( a->tag == b->tag ) )
- return 0;
-
- /* Otherwise, if the settings have names, compare them */
- if ( a->name && b->name && a->name[0] )
- return strcmp ( a->name, b->name );
-
- /* Otherwise, return a non-match */
- return ( ! 0 );
-}
-
-/******************************************************************************
- *
- * Formatted setting routines
- *
- ******************************************************************************
- */
-
-/**
- * Store value of typed setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v type Settings type
- * @v value Formatted setting data, or NULL
- * @ret rc Return status code
- */
-int storef_setting ( struct settings *settings, struct setting *setting,
- const char *value ) {
-
- /* NULL value implies deletion. Avoid imposing the burden of
- * checking for NULL values on each typed setting's storef()
- * method.
- */
- if ( ! value )
- return delete_setting ( settings, setting );
-
- return setting->type->storef ( settings, setting, value );
-}
-
-/**
- * Find named setting
- *
- * @v name Name
- * @ret setting Named setting, or NULL
- */
-static struct setting * find_setting ( const char *name ) {
- struct setting *setting;
-
- for_each_table_entry ( setting, SETTINGS ) {
- if ( strcmp ( name, setting->name ) == 0 )
- return setting;
- }
- return NULL;
-}
-
-/**
- * Parse setting name as tag number
- *
- * @v name Name
- * @ret tag Tag number, or 0 if not a valid number
- */
-static unsigned int parse_setting_tag ( const char *name ) {
- char *tmp = ( ( char * ) name );
- unsigned int tag = 0;
-
- while ( 1 ) {
- tag = ( ( tag << 8 ) | strtoul ( tmp, &tmp, 0 ) );
- if ( *tmp == 0 )
- return tag;
- if ( *tmp != '.' )
- return 0;
- tmp++;
- }
-}
-
-/**
- * Find setting type
- *
- * @v name Name
- * @ret type Setting type, or NULL
- */
-static struct setting_type * find_setting_type ( const char *name ) {
- struct setting_type *type;
-
- for_each_table_entry ( type, SETTING_TYPES ) {
- if ( strcmp ( name, type->name ) == 0 )
- return type;
- }
- return NULL;
-}
-
-/**
- * Parse setting name
- *
- * @v name Name of setting
- * @v get_child Function to find or create child settings block
- * @v settings Settings block to fill in
- * @v setting Setting to fill in
- * @v tmp_name Buffer for copy of setting name
- * @ret rc Return status code
- *
- * Interprets a name of the form
- * "[settings_name/]tag_name[:type_name]" and fills in the appropriate
- * fields.
- *
- * The @c tmp_name buffer must be large enough to hold a copy of the
- * setting name.
- */
-static int
-parse_setting_name ( const char *name,
- struct settings * ( * get_child ) ( struct settings *,
- const char * ),
- struct settings **settings, struct setting *setting,
- char *tmp_name ) {
- char *settings_name;
- char *setting_name;
- char *type_name;
- struct setting *named_setting;
-
- /* Set defaults */
- *settings = &settings_root;
- memset ( setting, 0, sizeof ( *setting ) );
- setting->name = "";
- setting->type = &setting_type_string;
-
- /* Split name into "[settings_name/]setting_name[:type_name]" */
- strcpy ( tmp_name, name );
- if ( ( setting_name = strchr ( tmp_name, '/' ) ) != NULL ) {
- *(setting_name++) = 0;
- settings_name = tmp_name;
- } else {
- setting_name = tmp_name;
- settings_name = NULL;
- }
- if ( ( type_name = strchr ( setting_name, ':' ) ) != NULL )
- *(type_name++) = 0;
-
- /* Identify settings block, if specified */
- if ( settings_name ) {
- *settings = parse_settings_name ( settings_name, get_child );
- if ( *settings == NULL ) {
- DBG ( "Unrecognised settings block \"%s\" in \"%s\"\n",
- settings_name, name );
- return -ENODEV;
- }
- }
-
- /* Identify setting */
- if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
- /* Matches a defined named setting; use that setting */
- memcpy ( setting, named_setting, sizeof ( *setting ) );
- } else if ( ( setting->tag = parse_setting_tag ( setting_name ) ) !=0){
- /* Is a valid numeric tag; use the tag */
- setting->tag |= (*settings)->tag_magic;
- } else {
- /* Use the arbitrary name */
- setting->name = setting_name;
- }
-
- /* Identify setting type, if specified */
- if ( type_name ) {
- setting->type = find_setting_type ( type_name );
- if ( setting->type == NULL ) {
- DBG ( "Invalid setting type \"%s\" in \"%s\"\n",
- type_name, name );
- return -ENOTSUP;
- }
- }
-
- return 0;
-}
-
-/**
- * Parse and store value of named setting
- *
- * @v name Name of setting
- * @v value Formatted setting data, or NULL
- * @ret rc Return status code
- */
-int storef_named_setting ( const char *name, const char *value ) {
- struct settings *settings;
- struct setting setting;
- char tmp_name[ strlen ( name ) + 1 ];
- int rc;
-
- if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
- &settings, &setting, tmp_name )) != 0)
- return rc;
- return storef_setting ( settings, &setting, value );
-}
-
-/**
- * Fetch and format value of named setting
- *
- * @v name Name of setting
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
- struct settings *settings;
- struct setting setting;
- char tmp_name[ strlen ( name ) + 1 ];
- int rc;
-
- if ( ( rc = parse_setting_name ( name, find_child_settings,
- &settings, &setting, tmp_name )) != 0)
- return rc;
- return fetchf_setting ( settings, &setting, buf, len );
-}
-
-/******************************************************************************
- *
- * Setting types
- *
- ******************************************************************************
- */
-
-/**
- * Parse and store value of string setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @ret rc Return status code
- */
-static int storef_string ( struct settings *settings, struct setting *setting,
- const char *value ) {
- return store_setting ( settings, setting, value, strlen ( value ) );
-}
-
-/**
- * Fetch and format value of string setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_string ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- return fetch_string_setting ( settings, setting, buf, len );
-}
-
-/** A string setting type */
-struct setting_type setting_type_string __setting_type = {
- .name = "string",
- .storef = storef_string,
- .fetchf = fetchf_string,
-};
-
-/**
- * Parse and store value of URI-encoded string setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @ret rc Return status code
- */
-static int storef_uristring ( struct settings *settings,
- struct setting *setting,
- const char *value ) {
- char buf[ strlen ( value ) + 1 ]; /* Decoding never expands string */
- size_t len;
-
- len = uri_decode ( value, buf, sizeof ( buf ) );
- return store_setting ( settings, setting, buf, len );
-}
-
-/**
- * Fetch and format value of URI-encoded string setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_uristring ( struct settings *settings,
- struct setting *setting,
- char *buf, size_t len ) {
- ssize_t raw_len;
-
- /* We need to always retrieve the full raw string to know the
- * length of the encoded string.
- */
- raw_len = fetch_setting ( settings, setting, NULL, 0 );
- if ( raw_len < 0 )
- return raw_len;
-
- {
- char raw_buf[ raw_len + 1 ];
-
- fetch_string_setting ( settings, setting, raw_buf,
- sizeof ( raw_buf ) );
- return uri_encode ( raw_buf, buf, len, URI_FRAGMENT );
- }
-}
-
-/** A URI-encoded string setting type */
-struct setting_type setting_type_uristring __setting_type = {
- .name = "uristring",
- .storef = storef_uristring,
- .fetchf = fetchf_uristring,
-};
-
-/**
- * Parse and store value of IPv4 address setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @ret rc Return status code
- */
-static int storef_ipv4 ( struct settings *settings, struct setting *setting,
- const char *value ) {
- struct in_addr ipv4;
-
- if ( inet_aton ( value, &ipv4 ) == 0 )
- return -EINVAL;
- return store_setting ( settings, setting, &ipv4, sizeof ( ipv4 ) );
-}
-
-/**
- * Fetch and format value of IPv4 address setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_ipv4 ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- struct in_addr ipv4;
- int raw_len;
-
- if ( ( raw_len = fetch_ipv4_setting ( settings, setting, &ipv4 ) ) < 0)
- return raw_len;
- return snprintf ( buf, len, "%s", inet_ntoa ( ipv4 ) );
-}
-
-/** An IPv4 address setting type */
-struct setting_type setting_type_ipv4 __setting_type = {
- .name = "ipv4",
- .storef = storef_ipv4,
- .fetchf = fetchf_ipv4,
-};
-
-/**
- * Parse and store value of integer setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @v size Integer size, in bytes
- * @ret rc Return status code
- */
-static int storef_int ( struct settings *settings, struct setting *setting,
- const char *value, unsigned int size ) {
- union {
- uint32_t num;
- uint8_t bytes[4];
- } u;
- char *endp;
-
- u.num = htonl ( strtoul ( value, &endp, 0 ) );
- if ( *endp )
- return -EINVAL;
- return store_setting ( settings, setting,
- &u.bytes[ sizeof ( u ) - size ], size );
-}
-
-/**
- * Parse and store value of 8-bit integer setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @v size Integer size, in bytes
- * @ret rc Return status code
- */
-static int storef_int8 ( struct settings *settings, struct setting *setting,
- const char *value ) {
- return storef_int ( settings, setting, value, 1 );
-}
-
-/**
- * Parse and store value of 16-bit integer setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @v size Integer size, in bytes
- * @ret rc Return status code
- */
-static int storef_int16 ( struct settings *settings, struct setting *setting,
- const char *value ) {
- return storef_int ( settings, setting, value, 2 );
-}
-
-/**
- * Parse and store value of 32-bit integer setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @v size Integer size, in bytes
- * @ret rc Return status code
- */
-static int storef_int32 ( struct settings *settings, struct setting *setting,
- const char *value ) {
- return storef_int ( settings, setting, value, 4 );
-}
-
-/**
- * Fetch and format value of signed integer setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_int ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- long value;
- int rc;
-
- if ( ( rc = fetch_int_setting ( settings, setting, &value ) ) < 0 )
- return rc;
- return snprintf ( buf, len, "%ld", value );
-}
-
-/**
- * Fetch and format value of unsigned integer setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_uint ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- unsigned long value;
- int rc;
-
- if ( ( rc = fetch_uint_setting ( settings, setting, &value ) ) < 0 )
- return rc;
- return snprintf ( buf, len, "%#lx", value );
-}
-
-/** A signed 8-bit integer setting type */
-struct setting_type setting_type_int8 __setting_type = {
- .name = "int8",
- .storef = storef_int8,
- .fetchf = fetchf_int,
-};
-
-/** A signed 16-bit integer setting type */
-struct setting_type setting_type_int16 __setting_type = {
- .name = "int16",
- .storef = storef_int16,
- .fetchf = fetchf_int,
-};
-
-/** A signed 32-bit integer setting type */
-struct setting_type setting_type_int32 __setting_type = {
- .name = "int32",
- .storef = storef_int32,
- .fetchf = fetchf_int,
-};
-
-/** An unsigned 8-bit integer setting type */
-struct setting_type setting_type_uint8 __setting_type = {
- .name = "uint8",
- .storef = storef_int8,
- .fetchf = fetchf_uint,
-};
-
-/** An unsigned 16-bit integer setting type */
-struct setting_type setting_type_uint16 __setting_type = {
- .name = "uint16",
- .storef = storef_int16,
- .fetchf = fetchf_uint,
-};
-
-/** An unsigned 32-bit integer setting type */
-struct setting_type setting_type_uint32 __setting_type = {
- .name = "uint32",
- .storef = storef_int32,
- .fetchf = fetchf_uint,
-};
-
-/**
- * Parse and store value of hex string setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @ret rc Return status code
- */
-static int storef_hex ( struct settings *settings, struct setting *setting,
- const char *value ) {
- char *ptr = ( char * ) value;
- uint8_t bytes[ strlen ( value ) ]; /* cannot exceed strlen(value) */
- unsigned int len = 0;
-
- while ( 1 ) {
- bytes[len++] = strtoul ( ptr, &ptr, 16 );
- switch ( *ptr ) {
- case '\0' :
- return store_setting ( settings, setting, bytes, len );
- case ':' :
- ptr++;
- break;
- default :
- return -EINVAL;
- }
- }
-}
-
-/**
- * Fetch and format value of hex string setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_hex ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- int raw_len;
- int check_len;
- int used = 0;
- int i;
-
- raw_len = fetch_setting_len ( settings, setting );
- if ( raw_len < 0 )
- return raw_len;
-
- {
- uint8_t raw[raw_len];
-
- check_len = fetch_setting ( settings, setting, raw,
- sizeof ( raw ) );
- if ( check_len < 0 )
- return check_len;
- assert ( check_len == raw_len );
-
- if ( len )
- buf[0] = 0; /* Ensure that a terminating NUL exists */
- for ( i = 0 ; i < raw_len ; i++ ) {
- used += ssnprintf ( ( buf + used ), ( len - used ),
- "%s%02x", ( used ? ":" : "" ),
- raw[i] );
- }
- return used;
- }
-}
-
-/** A hex-string setting */
-struct setting_type setting_type_hex __setting_type = {
- .name = "hex",
- .storef = storef_hex,
- .fetchf = fetchf_hex,
-};
-
-/**
- * Parse and store value of UUID setting
- *
- * @v settings Settings block
- * @v setting Setting to store
- * @v value Formatted setting data
- * @ret rc Return status code
- */
-static int storef_uuid ( struct settings *settings __unused,
- struct setting *setting __unused,
- const char *value __unused ) {
- return -ENOTSUP;
-}
-
-/**
- * Fetch and format value of UUID setting
- *
- * @v settings Settings block, or NULL to search all blocks
- * @v setting Setting to fetch
- * @v buf Buffer to contain formatted value
- * @v len Length of buffer
- * @ret len Length of formatted value, or negative error
- */
-static int fetchf_uuid ( struct settings *settings, struct setting *setting,
- char *buf, size_t len ) {
- union uuid uuid;
- int raw_len;
-
- if ( ( raw_len = fetch_uuid_setting ( settings, setting, &uuid ) ) < 0)
- return raw_len;
- return snprintf ( buf, len, "%s", uuid_ntoa ( &uuid ) );
-}
-
-/** UUID setting type */
-struct setting_type setting_type_uuid __setting_type = {
- .name = "uuid",
- .storef = storef_uuid,
- .fetchf = fetchf_uuid,
-};
-
-/******************************************************************************
- *
- * Settings
- *
- ******************************************************************************
- */
-
-/** Hostname setting */
-struct setting hostname_setting __setting = {
- .name = "hostname",
- .description = "Host name",
- .tag = DHCP_HOST_NAME,
- .type = &setting_type_string,
-};
-
-/** Filename setting */
-struct setting filename_setting __setting = {
- .name = "filename",
- .description = "Boot filename",
- .tag = DHCP_BOOTFILE_NAME,
- .type = &setting_type_string,
-};
-
-/** Root path setting */
-struct setting root_path_setting __setting = {
- .name = "root-path",
- .description = "iSCSI root path",
- .tag = DHCP_ROOT_PATH,
- .type = &setting_type_string,
-};
-
-/** Username setting */
-struct setting username_setting __setting = {
- .name = "username",
- .description = "User name",
- .tag = DHCP_EB_USERNAME,
- .type = &setting_type_string,
-};
-
-/** Password setting */
-struct setting password_setting __setting = {
- .name = "password",
- .description = "Password",
- .tag = DHCP_EB_PASSWORD,
- .type = &setting_type_string,
-};
-
-/** Priority setting */
-struct setting priority_setting __setting = {
- .name = "priority",
- .description = "Priority of these settings",
- .tag = DHCP_EB_PRIORITY,
- .type = &setting_type_int8,
-};