summaryrefslogtreecommitdiffstats
path: root/src/include/gpxe/settings.h
blob: 7198399ef212b109e4158ab76b0fefc2826ab706 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#ifndef _GPXE_SETTINGS_H
#define _GPXE_SETTINGS_H

/** @file
 *
 * Configuration settings
 *
 */

#include <stdint.h>
#include <gpxe/tables.h>
#include <gpxe/list.h>
#include <gpxe/refcnt.h>

struct settings;
struct in_addr;

/** Settings block operations */
struct settings_operations {
	/** Set value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @v data		Setting data, or NULL to clear setting
	 * @v len		Length of setting data
	 * @ret rc		Return status code
	 */
	int ( * set ) ( struct settings *settings, unsigned int tag,
			const void *data, size_t len );
	/** Get value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @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 ( * get ) ( struct settings *settings, unsigned int tag,
			void *data, size_t len );
};

/** A settings block */
struct settings {
	/** Reference counter */
	struct refcnt *refcnt;
	/** Name */
	char name[16];
	/** List of all settings */
	struct list_head list;
	/** Settings block operations */
	struct settings_operations *op;
};

/**
 * A setting type
 *
 * This represents a type of setting (e.g. string, IPv4 address,
 * etc.).
 */
struct setting_type {
	/** Name
	 *
	 * This is the name exposed to the user (e.g. "string").
	 */
	const char *name;
	/** Parse and set value of setting
	 *
	 * @v settings		Settings block
	 * @v tag		Setting tag number
	 * @v value		Formatted setting data
	 * @ret rc		Return status code
	 */
	int ( * setf ) ( struct settings *settings, unsigned int tag,
			 const char *value );
	/** Get and format value of setting
	 *
	 * @v settings		Settings block, or NULL to search all blocks
	 * @v tag		Setting tag number
	 * @v buf		Buffer to contain formatted value
	 * @v len		Length of buffer
	 * @ret len		Length of formatted value, or negative error
	 */
	int ( * getf ) ( struct settings *settings, unsigned int tag,
			 char *buf, size_t len );
};

/** Declare a configuration setting type */
#define	__setting_type \
	__table ( struct setting_type, setting_types, 01 )

/**
 * A named setting
 *
 * This represents a single setting (e.g. "hostname"), encapsulating
 * the information about the setting's tag number and type.
 */
struct named_setting {
	/** Name
	 *
	 * This is the human-readable name for the setting.  Where
	 * possible, it should match the name used in dhcpd.conf (see
	 * dhcp-options(5)).
	 */
	const char *name;
	/** Description */
	const char *description;
	/** Setting tag number */
	unsigned int tag;
	/** Setting type
	 *
	 * This identifies the type of setting (e.g. string, IPv4
	 * address, etc.).
	 */
	struct setting_type *type;
};

/** Declare a configuration setting */
#define	__named_setting __table ( struct named_setting, named_settings, 01 )

extern struct settings interactive_settings;

extern int get_setting ( struct settings *settings, unsigned int tag,
			 void *data, size_t len );
extern int get_setting_len ( struct settings *settings, unsigned int tag );
extern int get_string_setting ( struct settings *settings, unsigned int tag,
				char *data, size_t len );
extern int get_ipv4_setting ( struct settings *settings, unsigned int tag,
			      struct in_addr *inp );
extern int get_int_setting ( struct settings *settings, unsigned int tag,
			     long *value );
extern int get_uint_setting ( struct settings *settings, unsigned int tag,
			      unsigned long *value );
extern struct settings * find_settings ( const char *name );
extern int set_typed_setting ( struct settings *settings,
			       unsigned int tag, struct setting_type *type,
			       const char *value );
extern int set_named_setting ( const char *name, const char *value );
extern int get_named_setting ( const char *name, char *buf, size_t len );

/**
 * Set value of setting
 *
 * @v settings		Settings block
 * @v tag		Setting tag number
 * @v data		Setting data, or NULL to clear setting
 * @v len		Length of setting data
 * @ret rc		Return status code
 */
static inline int set_setting ( struct settings *settings, unsigned int tag,
				const void *data, size_t len ) {
	return settings->op->set ( settings, tag, data, len );
}

/**
 * Delete setting
 *
 * @v settings		Settings block
 * @v tag		Setting tag number
 * @ret rc		Return status code
 */
static inline int delete_setting ( struct settings *settings,
				   unsigned int tag ) {
	return set_setting ( settings, tag, NULL, 0 );
}

/**
 * Get and format value of setting
 *
 * @v settings		Settings block, or NULL to search all blocks
 * @v tag		Setting tag number
 * @v type		Settings type
 * @v buf		Buffer to contain formatted value
 * @v len		Length of buffer
 * @ret len		Length of formatted value, or negative error
 */
static inline int get_typed_setting ( struct settings *settings,
				      unsigned int tag,
				      struct setting_type *type,
				      char *buf, size_t len ) {
	return type->getf ( settings, tag, buf, len );
}

/**
 * Delete named setting
 *
 * @v name		Name of setting
 * @ret rc		Return status code
 */
static inline int delete_named_setting ( const char *name ) {
	return set_named_setting ( name, NULL );
}

#endif /* _GPXE_SETTINGS_H */