2 #if defined(HAVE_CONFIG_H)
8 #include <talloc/talloc.h>
13 #include "parser-conf.h"
14 #include "parser-utils.h"
18 #include "user-event.h"
20 static const char *pxelinux_prefix = "pxelinux.cfg/";
22 struct pxe_parser_info {
23 struct discover_boot_option *opt;
24 const char *default_name;
27 static void pxe_finish(struct conf_context *conf)
29 struct pxe_parser_info *info = conf->parser_info;
31 discover_context_add_boot_option(conf->dc, info->opt);
34 /* We need a slightly modified version of pb_url_join, to allow for the
35 * pxelinux "::filename" syntax for absolute URLs
37 static struct pb_url *pxe_url_join(void *ctx, const struct pb_url *url,
40 struct pb_url *new_url;
45 if (len > 2 && s[0] == ':' && s[1] == ':') {
49 /* ::/path -> /path */
50 tmp = talloc_strdup(ctx, s+2);
53 tmp = talloc_strdup(ctx, s+1);
57 new_url = pb_url_join(ctx, url, tmp);
63 /* strip leading slashes */
64 for (tmp = s; *tmp == '/'; tmp++)
66 new_url = pb_url_join(ctx, url, tmp);
72 static void pxe_append_string(struct discover_boot_option *opt,
75 if (opt->option->boot_args)
76 opt->option->boot_args = talloc_asprintf_append(
77 opt->option->boot_args, " %s", str);
79 opt->option->boot_args = talloc_strdup(opt->option, str);
82 static void pxe_process_sysappend(struct discover_context *ctx,
83 struct discover_boot_option *opt,
86 struct event *event = ctx->event;
93 const char *mac = event_get_param(event, "mac");
95 str = talloc_asprintf(ctx, "BOOTIF=%s", mac);
96 pxe_append_string(opt, str);
103 pb_log("pxe: unsupported features requested in "
104 "ipappend/sysappend: 0x%04lx", val);
108 static void pxe_process_pair(struct conf_context *ctx,
109 const char *name, char *value)
111 struct pxe_parser_info *parser_info = ctx->parser_info;
112 struct discover_boot_option *opt = parser_info->opt;
115 /* quirk in the syslinux config format: initrd can be separated
117 if (!name && !strncasecmp(value, "initrd=", strlen("initrd="))) {
119 value += strlen("initrd=");
125 if (streq(name, "DEFAULT")) {
126 parser_info->default_name = talloc_strdup(parser_info, value);
130 if (streq(name, "LABEL")) {
134 opt = discover_boot_option_create(ctx->dc, ctx->dc->device);
136 opt->option->name = talloc_strdup(opt, value);
137 opt->option->id = talloc_asprintf(opt, "%s@%p",
138 ctx->dc->device->device->id, opt);
140 opt->option->is_default = parser_info->default_name &&
141 streq(parser_info->default_name, value);
143 parser_info->opt = opt;
147 /* all other parameters need an option */
151 if (streq(name, "KERNEL")) {
152 url = pxe_url_join(ctx->dc, ctx->dc->conf_url, value);
153 opt->boot_image = create_url_resource(opt, url);
155 } else if (streq(name, "INITRD")) {
156 url = pxe_url_join(ctx->dc, ctx->dc->conf_url, value);
157 opt->initrd = create_url_resource(opt, url);
159 } else if (streq(name, "APPEND")) {
162 pxe_append_string(opt, value);
164 str = strcasestr(value, "INITRD=");
166 str += strlen("INITRD=");
167 end = strchrnul(str, ' ');
170 url = pxe_url_join(ctx->dc, ctx->dc->conf_url, str);
171 opt->initrd = create_url_resource(opt, url);
173 } else if (streq(name, "SYSAPPEND") || streq(name, "IPAPPEND")) {
177 type = strtoul(value, &end, 10);
178 if (end != value && !(*end))
179 pxe_process_sysappend(ctx->dc, opt, type);
184 static int pxe_parse(struct discover_context *dc)
186 struct pb_url *pxe_base_url, *url;
187 struct pxe_parser_info *parser_info;
188 char **pxe_conf_files, **filename;
189 struct conf_context *conf;
194 /* Expects dhcp event parameters to support network boot */
198 conf = talloc_zero(dc, struct conf_context);
204 conf->get_pair = conf_get_pair_space;
205 conf->process_pair = pxe_process_pair;
206 conf->finish = pxe_finish;
208 parser_info = talloc_zero(conf, struct pxe_parser_info);
209 conf->parser_info = parser_info;
211 dc->conf_url = user_event_parse_conf_url(dc, dc->event, &complete_url);
216 /* we have a complete URL; use this and we're done. */
217 rc = parser_request_url(dc, dc->conf_url, &buf, &len);
221 pxe_conf_files = user_event_parse_conf_filenames(dc, dc->event);
227 pxe_base_url = pb_url_join(dc, dc->conf_url, pxelinux_prefix);
231 for (filename = pxe_conf_files; *filename; filename++) {
232 url = pb_url_join(dc, pxe_base_url, *filename);
236 rc = parser_request_url(dc, url, &buf, &len);
237 if (!rc) /* found one, just break */
243 talloc_free(pxe_base_url);
245 /* No configuration file found on the boot server */
249 talloc_free(pxe_conf_files);
252 /* Call the config file parser with the data read from the file */
253 conf_parse_buf(conf, buf, len);
261 talloc_free(pxe_conf_files);
268 static struct parser pxe_parser = {
273 register_parser(pxe_parser);