[syslinux] [5.10] PXE + dhcp opts 209, 210 and path issues in tftp/http

Gerardo Exequiel Pozzi vmlinuz386 at yahoo.com.ar
Wed Jun 12 08:56:39 PDT 2013


On 06/12/2013 12:31 PM, Matt Fleming wrote:
>>From f48d79be8c79241dd4635165e393683809edd823 Mon Sep 17 00:00:00 2001
> From: Matt Fleming <matt.fleming at intel.com>
> Date: Wed, 12 Jun 2013 13:04:44 +0100
> Subject: [PATCH] PATH: Change the PATH directive syntax
> 
> In retrospect, choosing the colon character as the entry separator for
> the PATH directive was not a smart move, as that character is also used
> in TFTP-style paths. This conflict manifests as PXELINUX being unable to
> find and load files.

Nope :( I tested using this fixed patch, but still not work:

dnsmasq-tftp: sent /run/archiso/bootmnt/arch/boot/syslinux/lpxelinux.0
to 192.168.0.90
dnsmasq-tftp: file /run/archiso/bootmnt/arch/ldlinux.c32 not found
dnsmasq-tftp: file /run/archiso/bootmnt/arch//ldlinux.c32 not found
dnsmasq-tftp: file /run/archiso/bootmnt/arch//ldlinux.c32 not found
dnsmasq-tftp: file /run/archiso/bootmnt/arch//boot/isolinux/ldlinux.c32
not found
dnsmasq-tftp: file /run/archiso/bootmnt/arch//isolinux/ldlinux.c32 not found
dnsmasq-tftp: file /run/archiso/bootmnt/arch//boot/syslinuxldlinux.c32
not found
dnsmasq-tftp: sent /run/archiso/bootmnt/arch//boot/syslinux/ldlinux.c32
to 192.168.0.90
dnsmasq-tftp: failed sending
/run/archiso/bootmnt/arch//boot/syslinux/ldlinux.c32 to 192.168.0.90


Syslinux directory uploaded here [#1]


Run command:

dnsmasq --port=0 \
        --no-daemon \
        --enable-tftp \
        --tftp-root=/run/archiso/bootmnt \
        --dhcp-range=192.168.0.2,192.168.0.254,86400 \
        --dhcp-boot=/arch/boot/syslinux/lpxelinux.0 \
        --dhcp-option-force=209,boot/syslinux/archiso.cfg \
        --dhcp-option-force=210,/arch/


[#1]
https://dl.dropboxusercontent.com/u/88891866/archiso_syslinux_510_g962e435.tar.xz
https://dl.dropboxusercontent.com/u/88891866/archiso_syslinux_510_g962e435.tar.xz.sig


> 
> An example dnsmasq log looks like,
> 
> dnsmasq-tftp: sent /arch/boot/syslinux/lpxelinux.0 to 192.168.0.90
> dnsmasq-tftp: file /arch/ldlinux.c32 not found
> dnsmasq-tftp: file /arch//ldlinux.c32 not found
> dnsmasq-tftp: file /arch//boot/isolinux/ldlinux.c32 not found
> dnsmasq-tftp: file /arch//isolinux/ldlinux.c32 not found
> dnsmasq-tftp: file /arch//boot/syslinuxldlinux.c32 not found
> dnsmasq-tftp: sent /arch//boot/syslinux/ldlinux.c32 to 192.168.0.90
> dnsmasq-tftp: error 0 No error, file close received from 192.168.0.90
> dnsmasq-tftp: failed sending /arch//boot/syslinux/ldlinux.c32 to 192.168.0.90
> dnsmasq-tftp: sent /arch/boot/syslinux/archiso.cfg to 192.168.0.90
> dnsmasq-tftp: sent /arch/boot/syslinux/whichsys.c32 to 192.168.0.90
> dnsmasq-tftp: file /arch/libcom32.c32 not found
> dnsmasq-tftp: file /arch//libcom32.c32 not found
> dnsmasq-tftp: file /arch/libcom32.c32 not found
> dnsmasq-tftp: file /arch//arch//boot/syslinux/libcom32.c32 not found
> 
> The last line of the log is the indication that there's a problem.
> Internally, Syslinux adds the location of ldlinux.c32 to PATH by
> querying the current working directory once ldlinux.c32 is successfully
> loaded. Under PXELINUX that means the initial PATH string will be,
> 
>    "::/arch/boot/syslinux/"
> 
> The PATH parsing code doesn't know how to correctly parse the "::"
> string and hence, the file is searched for relative to the 210 dhcp
> option directory - /arch/.
> 
> Switch to using the space character to separate PATH entries instead,
> which not only allows TFTP-style paths but also http and ftp urls. If we
> ever support filenames containing spaces in config files, then we'll
> have to introduce some means of quotation, to distinguish filenames
> containing spaces from separate PATH entries.
> 
> Internally, PATH is now a linked list which *greatly* simplifies the
> path code, and means we no longer have to parse strings backwards and
> forwards.
> 
> Note: This change is not backwards-compatible, which means that anyone
> using the PATH directive with versions before 5.11 will need to change
> their config file when upgrading.
> 
> Signed-off-by: Matt Fleming <matt.fleming at intel.com>
> ---
>  com32/elflink/ldlinux/readconfig.c | 53 +++++++++++++++++++++++++-------------
>  com32/lib/sys/module/common.c      | 36 +++++++++-----------------
>  core/elflink/load_env32.c          | 26 +++----------------
>  core/fs/fs.c                       |  2 --
>  core/include/fs.h                  | 10 ++++++-
>  core/path.c                        | 42 ++++++++++++++++++++++++++++++
>  doc/syslinux.txt                   |  2 +-
>  7 files changed, 103 insertions(+), 68 deletions(-)
>  create mode 100644 core/path.c
> 
> diff --git a/com32/elflink/ldlinux/readconfig.c b/com32/elflink/ldlinux/readconfig.c
> index 35b137e..12cb7e3 100644
> --- a/com32/elflink/ldlinux/readconfig.c
> +++ b/com32/elflink/ldlinux/readconfig.c
> @@ -770,6 +770,39 @@ extern void loadkeys(char *);
>  extern char syslinux_banner[];
>  extern char copyright_str[];
>  
> +/*
> + * PATH-based lookup
> + *
> + * Each entry in the PATH directive is separated by a space, e.g.
> + *
> + *     PATH /bar /bin/foo /baz/bar/bin
> + */
> +static int parse_path(char *p)
> +{
> +    struct path_entry *entry;
> +    const char *str;
> +
> +    while (*p) {
> +	/* Find the next directory */
> +	str = refdup_word(&p);
> +	if (!str)
> +	    goto bail;
> +
> +	entry = path_add(str);
> +	refstr_put(str);
> +
> +	if (!entry)
> +	    goto bail;
> +
> +	p = skipspace(p);
> +    }
> +
> +    return 0;
> +
> +bail:
> +    return -1;
> +}
> +
>  static void parse_config_file(FILE * f)
>  {
>      char line[MAX_LINE], *p, *ep, ch;
> @@ -1337,24 +1370,8 @@ do_include:
>  	} else if (looking_at(p, "say")) {
>  		printf("%s\n", p+4);
>  	} else if (looking_at(p, "path")) {
> -		/* PATH-based lookup */
> -		const char *new_path;
> -		char *_p;
> -		size_t len, new_len;
> -
> -		new_path = refstrdup(skipspace(p + 4));
> -		len = strlen(PATH);
> -		new_len = strlen(new_path);
> -		_p = malloc(len + new_len + 2);
> -		if (_p) {
> -			strncpy(_p, PATH, len);
> -			_p[len++] = ':';
> -			strncpy(_p + len, new_path, new_len);
> -			_p[len + new_len] = '\0';
> -			free(PATH);
> -			PATH = _p;
> -		} else
> -			printf("Failed to realloc PATH\n");
> +		if (parse_path(skipspace(p + 4)))
> +			printf("Failed to parse PATH\n");
>  	} else if (looking_at(p, "sendcookies")) {
>  		const union syslinux_derivative_info *sdi;
>  
> diff --git a/com32/lib/sys/module/common.c b/com32/lib/sys/module/common.c
> index 8547036..b763704 100644
> --- a/com32/lib/sys/module/common.c
> +++ b/com32/lib/sys/module/common.c
> @@ -59,40 +59,28 @@ void print_elf_symbols(struct elf_module *module) {
>  
>  FILE *findpath(char *name)
>  {
> +	struct path_entry *entry;
>  	char path[FILENAME_MAX];
>  	FILE *f;
> -	char *p, *n;
> -	int i;
>  
>  	f = fopen(name, "rb"); /* for full path */
>  	if (f)
>  		return f;
>  
> -	p = PATH;
> -again:
> -	i = 0;
> -	while (*p && *p != ':' && i < FILENAME_MAX - 1) {
> -		path[i++] = *p++;
> -	}
> -
> -	if (*p == ':')
> -		p++;
> +	list_for_each_entry(entry, &PATH, list) {
> +		bool slash = false;
>  
> -	/* Ensure we have a '/' separator */
> -	if (path[i] != '/' && i < FILENAME_MAX - 1)
> -		path[i++] = '/';
> +		/* Ensure we have a '/' separator */
> +		if (entry->str[strlen(entry->str) - 1] != '/')
> +			slash = true;
>  
> -	n = name;
> -	while (*n && i < FILENAME_MAX - 1)
> -		path[i++] = *n++;
> -	path[i] = '\0';
> +		snprintf(path, sizeof(path), "%s%s%s",
> +			 entry->str, slash ? "/" : "", name);
>  
> -	f = fopen(path, "rb");
> -	if (f)
> -		return f;
> -
> -	if (p >= PATH && p < PATH + strlen(PATH))
> -		goto again;
> +		f = fopen(path, "rb");
> +		if (f)
> +			return f;
> +	}
>  
>  	return NULL;
>  }
> diff --git a/core/elflink/load_env32.c b/core/elflink/load_env32.c
> index 0483d86..8551831 100644
> --- a/core/elflink/load_env32.c
> +++ b/core/elflink/load_env32.c
> @@ -124,14 +124,11 @@ void load_env32(com32sys_t * regs __unused)
>  
>  	dprintf("Starting 32 bit elf module subsystem...\n");
>  
> -	PATH = malloc(strlen(CurrentDirName) + 1);
> -	if (!PATH) {
> +	if (strlen(CurrentDirName) && !path_add(CurrentDirName)) {
>  		printf("Couldn't allocate memory for PATH\n");
>  		goto out;
>  	}
>  
> -	strcpy(PATH, CurrentDirName);
> -
>  	init_module_subsystem(&core_module);
>  
>  	start_ldlinux(1, argv);
> @@ -159,30 +156,15 @@ void load_env32(com32sys_t * regs __unused)
>  		if (!core_getcwd(path, sizeof(path)))
>  			goto out;
>  
> -		if (!strlen(PATH)) {
> -			PATH = realloc(PATH, strlen(path) + 1);
> -			if (!PATH) {
> -				printf("Couldn't allocate memory for PATH\n");
> -				goto out;
> -			}
> -
> -			strcpy(PATH, path);
> -		} else {
> -			PATH = realloc(PATH, strlen(path) + strlen(PATH) + 2);
> -			if (!PATH) {
> -				printf("Couldn't allocate memory for PATH\n");
> -				goto out;
> -			}
> -
> -			strcat(PATH, ":");
> -			strcat(PATH, path);
> +		if (!path_add(path)) {
> +			printf("Couldn't allocate memory for PATH\n");
> +			goto out;
>  		}
>  
>  		start_ldlinux(1, argv);
>  	}
>  
>  out:
> -	free(PATH);
>  	writestr("\nFailed to load ldlinux.c32");
>  }
>  
> diff --git a/core/fs/fs.c b/core/fs/fs.c
> index 1cb4b00..b6ee19c 100644
> --- a/core/fs/fs.c
> +++ b/core/fs/fs.c
> @@ -10,8 +10,6 @@
>  #include "fs.h"
>  #include "cache.h"
>  
> -__export char *PATH;
> -
>  /* The currently mounted filesystem */
>  __export struct fs_info *this_fs = NULL;		/* Root filesystem */
>  
> diff --git a/core/include/fs.h b/core/include/fs.h
> index c7d0fd7..b5c7f0d 100644
> --- a/core/include/fs.h
> +++ b/core/include/fs.h
> @@ -1,6 +1,7 @@
>  #ifndef FS_H
>  #define FS_H
>  
> +#include <linux/list.h>
>  #include <stddef.h>
>  #include <stdbool.h>
>  #include <string.h>
> @@ -182,7 +183,14 @@ static inline struct file *handle_to_file(uint16_t handle)
>      return handle ? &files[handle-1] : NULL;
>  }
>  
> -extern char *PATH;
> +struct path_entry {
> +    struct list_head list;
> +    const char *str;
> +};
> +
> +extern struct list_head PATH;
> +
> +extern struct path_entry *path_add(const char *str);
>  
>  /* fs.c */
>  void pm_mangle_name(com32sys_t *);
> diff --git a/core/path.c b/core/path.c
> new file mode 100644
> index 0000000..8e517ca
> --- /dev/null
> +++ b/core/path.c
> @@ -0,0 +1,42 @@
> +/* ----------------------------------------------------------------------- *
> + *
> + *   Copyright 2013 Intel Corporation; author: Matt Fleming
> + *
> + *   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, Inc., 51 Franklin St, Fifth Floor,
> + *   Boston MA 02110-1301, USA; either version 2 of the License, or
> + *   (at your option) any later version; incorporated herein by reference.
> + *
> + * ----------------------------------------------------------------------- */
> +
> +#include <klibc/compiler.h>
> +#include <linux/list.h>
> +#include <fs.h>
> +#include <string.h>
> +
> +__export LIST_HEAD(PATH);
> +
> +__export struct path_entry *path_add(const char *str)
> +{
> +    struct path_entry *entry;
> +
> +    if (!strlen(str))
> +	return NULL;
> +
> +    entry = malloc(sizeof(*entry));
> +    if (!entry)
> +	return NULL;
> +
> +    entry->str = strdup(str);
> +    if (!entry->str)
> +	goto bail;
> +
> +    list_add(&entry->list, &PATH);
> +
> +    return entry;
> +
> +bail:
> +    free(entry);
> +    return NULL;
> +}
> diff --git a/doc/syslinux.txt b/doc/syslinux.txt
> index a4b201f..0dfecee 100644
> --- a/doc/syslinux.txt
> +++ b/doc/syslinux.txt
> @@ -551,7 +551,7 @@ F12 filename
>  	<Ctrl-F>0.
>  
>  PATH path
> -	Specify a colon-separated (':') list of directories to search
> +	Specify a list of directories (separated by spaces) to search
>  	when attempting to load modules. This directive is useful for
>  	specifying the directories containing the lib*.c32 library
>  	files as other modules may be dependent on these files, but
> 


-- 
Gerardo Exequiel Pozzi
\cos^2\alpha + \sin^2\alpha = 1

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 555 bytes
Desc: OpenPGP digital signature
URL: <http://www.zytor.com/pipermail/syslinux/attachments/20130612/65e5550e/attachment.sig>


More information about the Syslinux mailing list