From patchwork Sat May 26 06:06:01 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920927 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLB6ft7z9s16 for ; Sat, 26 May 2018 16:06:26 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLB28cXzDr2k for ; Sat, 26 May 2018 16:06:26 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCKy6Vj2zDqH3 for ; Sat, 26 May 2018 16:06:14 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 08C34402242D; Sat, 26 May 2018 06:06:12 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id F267E210C6C0; Sat, 26 May 2018 06:06:10 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:01 +0200 Message-Id: <1527314768-4797-2-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:12 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:12 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 1/8] libnet: Pass ip_version via struct filename_ip X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" When we will support loading of pxelinux.cfg files later, we have to call the tftp load function multiple times from different places. To avoid that we've also got to pass around the ip_version information via function para- meters to all spots, let's rather put it into struct filename_ip instead since we've got this struct filename_ip info available everywhere already. While we're at it, also drop the __attribute__((packed)) from the struct. The struct is only used internally, without exchanging it with the outside world, so the attribute is certainly not necessary here. Signed-off-by: Thomas Huth --- lib/libnet/netload.c | 11 ++++++----- lib/libnet/tftp.c | 4 ++-- lib/libnet/tftp.h | 10 +++++----- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index 8dca654..bce9bb7 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -404,13 +404,13 @@ static void seed_rng(uint8_t mac[]) srand(seed); } -static int tftp_load(filename_ip_t *fnip, unsigned char *buffer, int len, - unsigned int retries, int ip_vers) +static int tftp_load(filename_ip_t *fnip, void *buffer, int len, + unsigned int retries) { tftp_err_t tftp_err; int rc; - rc = tftp(fnip, buffer, len, retries, &tftp_err, ip_vers); + rc = tftp(fnip, buffer, len, retries, &tftp_err); if (rc > 0) { printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, @@ -737,6 +737,8 @@ int netload(char *buffer, int len, char *args_fs, int alen) fn_ip.filename[sizeof(fn_ip.filename)-1] = 0; } + fn_ip.ip_version = ip_version; + if (ip_version == 4) { printf(" Requesting file \"%s\" via TFTP from %d.%d.%d.%d\n", fn_ip.filename, @@ -752,8 +754,7 @@ int netload(char *buffer, int len, char *args_fs, int alen) } /* Do the TFTP load and print error message if necessary */ - rc = tftp_load(&fn_ip, (unsigned char *)buffer, len, - obp_tftp_args.tftp_retries, ip_version); + rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); if (obp_tftp_args.ip_init == IP_INIT_DHCP) dhcp_send_release(fn_ip.fd); diff --git a/lib/libnet/tftp.c b/lib/libnet/tftp.c index 5e7951f..302c8f4 100644 --- a/lib/libnet/tftp.c +++ b/lib/libnet/tftp.c @@ -501,12 +501,12 @@ void handle_tftp_dun(uint8_t err_code) * NON ZERO - size of received file */ int tftp(filename_ip_t * _fn_ip, unsigned char *_buffer, int _len, - unsigned int _retries, tftp_err_t * _tftp_err, int _ip_version) + unsigned int _retries, tftp_err_t * _tftp_err) { retries = _retries; fn_ip = _fn_ip; len = _len; - ip_version = _ip_version; + ip_version = _fn_ip->ip_version; tftp_errno = 0; tftp_err = _tftp_err; tftp_err->bad_tftp_packets = 0; diff --git a/lib/libnet/tftp.h b/lib/libnet/tftp.h index a09cf71..c30fe78 100644 --- a/lib/libnet/tftp.h +++ b/lib/libnet/tftp.h @@ -29,8 +29,9 @@ struct filename_ip { ip6_addr_t server_ip6; ip6_addr_t dns_ip6; char filename[256]; - int fd; -} __attribute__ ((packed)); + int fd; + int ip_version; +}; typedef struct filename_ip filename_ip_t; typedef struct { @@ -40,9 +41,8 @@ typedef struct { uint32_t blocks_received; } tftp_err_t; -int tftp(filename_ip_t *, unsigned char *, int, unsigned int, - tftp_err_t *, int ip_version); - +int tftp(filename_ip_t *fnip, unsigned char *buf, int len, + unsigned int retries, tftp_err_t *err); int32_t handle_tftp(int fd, uint8_t *, int32_t); void handle_tftp_dun(uint8_t err_code); int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd, int len); From patchwork Sat May 26 06:06:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920928 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLH5w3Cz9s16 for ; Sat, 26 May 2018 16:06:31 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLH402nzDr10 for ; Sat, 26 May 2018 16:06:31 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCKz4TKfzDqH3 for ; Sat, 26 May 2018 16:06:15 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 737357D839; Sat, 26 May 2018 06:06:13 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 67B41210C6C0; Sat, 26 May 2018 06:06:12 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:02 +0200 Message-Id: <1527314768-4797-3-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 26 May 2018 06:06:13 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 26 May 2018 06:06:13 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 2/8] libc: Add the snprintf() function X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" Code has been taken from the sprintf() function (which is almost the same, except that snprintf calls vsnprintf instead of vsprintf internally). Signed-off-by: Thomas Huth --- lib/libc/include/stdio.h | 1 + lib/libc/stdio/Makefile.inc | 2 +- lib/libc/stdio/snprintf.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 lib/libc/stdio/snprintf.c diff --git a/lib/libc/include/stdio.h b/lib/libc/include/stdio.h index c54528f..1cd5faf 100644 --- a/lib/libc/include/stdio.h +++ b/lib/libc/include/stdio.h @@ -43,6 +43,7 @@ int fileno(FILE *stream); int printf(const char *format, ...) __attribute__((format (printf, 1, 2))); int fprintf(FILE *stream, const char *format, ...) __attribute__((format (printf, 2, 3))); int sprintf(char *str, const char *format, ...) __attribute__((format (printf, 2, 3))); +int snprintf(char *str, size_t size, const char *format, ...) __attribute__((format (printf, 3, 4))); int vfprintf(FILE *stream, const char *format, va_list); int vsprintf(char *str, const char *format, va_list); int vsnprintf(char *str, size_t size, const char *format, va_list); diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc index ac5302d..6688317 100644 --- a/lib/libc/stdio/Makefile.inc +++ b/lib/libc/stdio/Makefile.inc @@ -13,7 +13,7 @@ STDIO_SRC_C = fscanf.c sprintf.c vfprintf.c vsnprintf.c vsprintf.c fprintf.c \ printf.c setvbuf.c putc.c puts.c putchar.c scanf.c stdchnls.c \ - vfscanf.c vsscanf.c fileno.c + vfscanf.c vsscanf.c fileno.c snprintf.c STDIO_SRC_ASM = STDIO_SRCS = $(STDIO_SRC_C:%=$(STDIOCMNDIR)/%) $(STDIO_SRC_ASM:%=$(STDIOCMNDIR)/%) diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c new file mode 100644 index 0000000..19c8a38 --- /dev/null +++ b/lib/libc/stdio/snprintf.c @@ -0,0 +1,28 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include + +int snprintf(char *buff, size_t size, const char *format, ...) +{ + va_list ar; + int count; + + if (!buff || !format) + return -1; + + va_start(ar, format); + count = vsnprintf(buff, size, format, ar); + va_end(ar); + + return count; +} From patchwork Sat May 26 06:06:03 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920929 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLM6tSvz9s16 for ; Sat, 26 May 2018 16:06:35 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLM4ZvDzDqx4 for ; Sat, 26 May 2018 16:06:35 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL1031RzDqH3 for ; Sat, 26 May 2018 16:06:17 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DC7124187E48; Sat, 26 May 2018 06:06:14 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id D15A42023433; Sat, 26 May 2018 06:06:13 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:03 +0200 Message-Id: <1527314768-4797-4-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Sat, 26 May 2018 06:06:14 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.5]); Sat, 26 May 2018 06:06:14 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 3/8] libnet: Put code for determing TFTP error strings into a separate function X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" This way we can easily re-use the rc --> string translation in later patches. Reviewed-by: Greg Kurz Signed-off-by: Thomas Huth --- lib/libnet/netload.c | 79 +++------------------------------------- lib/libnet/tftp.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/libnet/tftp.h | 2 + 3 files changed, 109 insertions(+), 73 deletions(-) diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index bce9bb7..f06c2fd 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -415,79 +415,12 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len, if (rc > 0) { printf(" TFTP: Received %s (%d KBytes)\n", fnip->filename, rc / 1024); - } else if (rc == -1) { - netload_error(0x3003, "unknown TFTP error"); - return -103; - } else if (rc == -2) { - netload_error(0x3004, "TFTP buffer of %d bytes " - "is too small for %s", - len, fnip->filename); - return -104; - } else if (rc == -3) { - netload_error(0x3009, "file not found: %s", - fnip->filename); - return -108; - } else if (rc == -4) { - netload_error(0x3010, "TFTP access violation"); - return -109; - } else if (rc == -5) { - netload_error(0x3011, "illegal TFTP operation"); - return -110; - } else if (rc == -6) { - netload_error(0x3012, "unknown TFTP transfer ID"); - return -111; - } else if (rc == -7) { - netload_error(0x3013, "no such TFTP user"); - return -112; - } else if (rc == -8) { - netload_error(0x3017, "TFTP blocksize negotiation failed"); - return -116; - } else if (rc == -9) { - netload_error(0x3018, "file exceeds maximum TFTP transfer size"); - return -117; - } else if (rc <= -10 && rc >= -15) { - const char *icmp_err_str; - switch (rc) { - case -ICMP_NET_UNREACHABLE - 10: - icmp_err_str = "net unreachable"; - break; - case -ICMP_HOST_UNREACHABLE - 10: - icmp_err_str = "host unreachable"; - break; - case -ICMP_PROTOCOL_UNREACHABLE - 10: - icmp_err_str = "protocol unreachable"; - break; - case -ICMP_PORT_UNREACHABLE - 10: - icmp_err_str = "port unreachable"; - break; - case -ICMP_FRAGMENTATION_NEEDED - 10: - icmp_err_str = "fragmentation needed and DF set"; - break; - case -ICMP_SOURCE_ROUTE_FAILED - 10: - icmp_err_str = "source route failed"; - break; - default: - icmp_err_str = " UNKNOWN"; - break; - } - netload_error(0x3005, "ICMP ERROR \"%s\"", icmp_err_str); - return -105; - } else if (rc == -40) { - netload_error(0x3014, "TFTP error occurred after " - "%d bad packets received", - tftp_err.bad_tftp_packets); - return -113; - } else if (rc == -41) { - netload_error(0x3015, "TFTP error occurred after " - "missing %d responses", - tftp_err.no_packets); - return -114; - } else if (rc == -42) { - netload_error(0x3016, "TFTP error missing block %d, " - "expected block was %d", - tftp_err.blocks_missed, - tftp_err.blocks_received); - return -115; + } else { + int ecode; + const char *errstr = NULL; + rc = tftp_get_error_info(fnip, &tftp_err, rc, &errstr, &ecode); + if (errstr) + netload_error(ecode, errstr); } return rc; diff --git a/lib/libnet/tftp.c b/lib/libnet/tftp.c index 302c8f4..9a5817a 100644 --- a/lib/libnet/tftp.c +++ b/lib/libnet/tftp.c @@ -690,3 +690,104 @@ int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd, return 0; } } + +int tftp_get_error_info(filename_ip_t *fnip, tftp_err_t *tftperr, int rc, + const char **errstr, int *ecode) +{ + static char estrbuf[80]; + + if (rc == -1) { + *ecode = 0x3003; + *errstr = "unknown TFTP error"; + return -103; + } else if (rc == -2) { + *ecode = 0x3004; + snprintf(estrbuf, sizeof(estrbuf), + "TFTP buffer of %d bytes is too small for %s", len, + fnip->filename); + *errstr = estrbuf; + return -104; + } else if (rc == -3) { + *ecode = 0x3009; + snprintf(estrbuf, sizeof(estrbuf), "file not found: %s", + fnip->filename); + *errstr = estrbuf; + return -108; + } else if (rc == -4) { + *ecode = 0x3010; + *errstr = "TFTP access violation"; + return -109; + } else if (rc == -5) { + *ecode = 0x3011; + *errstr = "illegal TFTP operation"; + return -110; + } else if (rc == -6) { + *ecode = 0x3012; + *errstr = "unknown TFTP transfer ID"; + return -111; + } else if (rc == -7) { + *ecode = 0x3013; + *errstr = "no such TFTP user"; + return -112; + } else if (rc == -8) { + *ecode = 0x3017; + *errstr = "TFTP blocksize negotiation failed"; + return -116; + } else if (rc == -9) { + *ecode = 0x3018; + *errstr = "file exceeds maximum TFTP transfer size"; + return -117; + } else if (rc <= -10 && rc >= -15) { + const char *icmp_err_str; + switch (rc) { + case -ICMP_NET_UNREACHABLE - 10: + icmp_err_str = "net unreachable"; + break; + case -ICMP_HOST_UNREACHABLE - 10: + icmp_err_str = "host unreachable"; + break; + case -ICMP_PROTOCOL_UNREACHABLE - 10: + icmp_err_str = "protocol unreachable"; + break; + case -ICMP_PORT_UNREACHABLE - 10: + icmp_err_str = "port unreachable"; + break; + case -ICMP_FRAGMENTATION_NEEDED - 10: + icmp_err_str = "fragmentation needed and DF set"; + break; + case -ICMP_SOURCE_ROUTE_FAILED - 10: + icmp_err_str = "source route failed"; + break; + default: + icmp_err_str = "UNKNOWN"; + break; + } + *ecode = 0x3005; + sprintf(estrbuf, "ICMP ERROR \"%s\"", icmp_err_str); + *errstr = estrbuf; + return -105; + } else if (rc == -40) { + *ecode = 0x3014; + sprintf(estrbuf, + "TFTP error occurred after %d bad packets received", + tftperr->bad_tftp_packets); + *errstr = estrbuf; + return -113; + } else if (rc == -41) { + *ecode = 0x3015; + sprintf(estrbuf, + "TFTP error occurred after missing %d responses", + tftperr->no_packets); + *errstr = estrbuf; + return -114; + } else if (rc == -42) { + *ecode = 0x3016; + sprintf(estrbuf, + "TFTP error missing block %d, expected block was %d", + tftperr->blocks_missed, tftperr->blocks_received); + *errstr = estrbuf; + return -115; + } + + return rc; +} diff --git a/lib/libnet/tftp.h b/lib/libnet/tftp.h index c30fe78..ca8029e 100644 --- a/lib/libnet/tftp.h +++ b/lib/libnet/tftp.h @@ -46,5 +46,7 @@ int tftp(filename_ip_t *fnip, unsigned char *buf, int len, int32_t handle_tftp(int fd, uint8_t *, int32_t); void handle_tftp_dun(uint8_t err_code); int parse_tftp_args(char buffer[], char *server_ip, char filename[], int fd, int len); +int tftp_get_error_info(filename_ip_t *fnip, tftp_err_t *tftperr, int rc, + const char **errstr, int *ecode); #endif From patchwork Sat May 26 06:06:04 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920930 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLS48R8z9s16 for ; Sat, 26 May 2018 16:06:40 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLS2l8XzDr4N for ; Sat, 26 May 2018 16:06:40 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL22v2JzDqH3 for ; Sat, 26 May 2018 16:06:18 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 53BAF40201C4; Sat, 26 May 2018 06:06:16 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 472BF2023433; Sat, 26 May 2018 06:06:15 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:04 +0200 Message-Id: <1527314768-4797-5-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:16 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:16 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 4/8] libnet: Add functions for downloading and parsing pxelinux.cfg files X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" Booting a kernel via pxelinux.cfg files is common on x86 and also with ppc64 bootloaders like petitboot, so it would be nice to support this in SLOF, too. This patch adds functions for downloading and parsing such pxelinux.cfg files. See this URL for more details on pxelinux.cfg: https://www.syslinux.org/wiki/index.php?title=PXELINUX Signed-off-by: Thomas Huth --- lib/libnet/Makefile | 2 +- lib/libnet/pxelinux.c | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/libnet/pxelinux.h | 33 ++++++++ 3 files changed, 246 insertions(+), 1 deletion(-) create mode 100644 lib/libnet/pxelinux.c create mode 100644 lib/libnet/pxelinux.h diff --git a/lib/libnet/Makefile b/lib/libnet/Makefile index dfefea9..a2a6570 100644 --- a/lib/libnet/Makefile +++ b/lib/libnet/Makefile @@ -19,7 +19,7 @@ include $(TOP)/make.rules CFLAGS += -I. -I.. -I../libc/include -I$(TOP)/include $(FLAG) SRCS = ethernet.c ipv4.c udp.c tcp.c dns.c bootp.c dhcp.c tftp.c \ - ipv6.c dhcpv6.c icmpv6.c ndp.c netload.c ping.c args.c + ipv6.c dhcpv6.c icmpv6.c ndp.c netload.c ping.c args.c pxelinux.c OBJS = $(SRCS:%.c=%.o) diff --git a/lib/libnet/pxelinux.c b/lib/libnet/pxelinux.c new file mode 100644 index 0000000..d702811 --- /dev/null +++ b/lib/libnet/pxelinux.c @@ -0,0 +1,212 @@ +/***************************************************************************** + * pxelinux.cfg-style config file support. + * + * See https://www.syslinux.org/wiki/index.php?title=PXELINUX for information + * about the pxelinux config file layout. + * + * Copyright 2018 Red Hat, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the BSD License which accompanies this distribution, and is + * available at http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * Thomas Huth, Red Hat Inc. - initial implementation + *****************************************************************************/ + +#include +#include +#include "tftp.h" +#include "pxelinux.h" + +/** + * Call tftp() and report errors (excet "file-not-found" errors) + */ +static int pxelinux_tftp_load(filename_ip_t *fnip, void *buffer, int len, + int retries) +{ + tftp_err_t tftp_err; + int rc, ecode; + + rc = tftp(fnip, buffer, len, retries, &tftp_err); + + if (rc > 0) { + printf("\r TFTP: Received %s (%d bytes)\n", + fnip->filename, rc); + } else if (rc == -3) { + /* Ignore file-not-found (since we are probing the files) + * and simply erase the "Receiving data: 0 KBytes" string */ + printf("\r \r"); + } else { + const char *errstr = NULL; + rc = tftp_get_error_info(fnip, &tftp_err, rc, &errstr, &ecode); + if (errstr) + printf("\r TFTP error: %s\n", errstr); + } + + return rc; +} + +/** + * Try to load a pxelinux.cfg file by probing the possible file names. + * Note that this function will overwrite filename_ip_t->filename. + */ +static int pxelinux_load_cfg(filename_ip_t *fn_ip, uint8_t *mac, + int retries, char *cfgbuf, int cfgbufsize) +{ + int rc, idx; + char *baseptr; + + /* Try to get a usable base directory from the DHCP bootfile name */ + baseptr = strrchr(fn_ip->filename, '/'); + if (!baseptr) + baseptr = fn_ip->filename; + else + ++baseptr; + /* Check that we've got enough space to store "pxelinux.cfg/" and + * the UUID (which is the longest file name) there */ + if (baseptr - fn_ip->filename > sizeof(fn_ip->filename) - 50) { + puts("Error: The bootfile string is too long for deriving the " + "pxelinux.cfg file name from it."); + return -1; + } + strcpy(baseptr, "pxelinux.cfg/"); + baseptr += strlen(baseptr); + + puts("Trying pxelinux.cfg files..."); + + /* Look for config file with MAC address in its name */ + sprintf(baseptr, "01-%02x-%02x-%02x-%02x-%02x-%02x", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + rc = pxelinux_tftp_load(fn_ip, cfgbuf, cfgbufsize - 1, retries); + if (rc > 0) { + return rc; + } + + /* Look for config file with IP address in its name */ + if (fn_ip->ip_version == 4) { + sprintf(baseptr, "%02X%02X%02X%02X", + (fn_ip->own_ip >> 24) & 0xff, + (fn_ip->own_ip >> 16) & 0xff, + (fn_ip->own_ip >> 8) & 0xff, + fn_ip->own_ip & 0xff); + for (idx = 0; idx <= 7; idx++) { + baseptr[8 - idx] = 0; + rc = pxelinux_tftp_load(fn_ip, cfgbuf, cfgbufsize - 1, + retries); + if (rc > 0) { + return rc; + } + } + } + + /* Try "default" config file */ + strcpy(baseptr, "default"); + rc = pxelinux_tftp_load(fn_ip, cfgbuf, cfgbufsize - 1, retries); + + return rc; +} + +/** + * Parse a pxelinux-style configuration file. + * The discovered entries are filled into the "struct pl_cfg_entry entries[]" + * array. Note that the callers must keep the cfg buffer valid as long as + * they wish to access the "struct pl_cfg_entry" entries, since the pointers + * in entries point to the original location in the cfg buffer area. The cfg + * buffer is altered for this, too, e.g. terminating NUL-characters are put + * into the right locations. + * @param cfg Pointer to the buffer with contents of the config file + * @param cfgsize Size of the cfg buffer + * @param entries Pointer to array where the results should be put into + * @param max_entries Number of available slots in the entries array + * @param def_ent Used to return the index of the default entry + * @return Number of valid entries + */ +int pxelinux_parse_cfg(char *cfg, int cfgsize, struct pl_cfg_entry *entries, + int max_entries, int *def_ent) +{ + int num_entries = 0; + char *ptr = cfg, *nextptr, *eol, *arg; + char *defaultlabel = NULL; + + *def_ent = 0; + + cfg[cfgsize - 1] = 0; /* Make sure it is NUL-terminated */ + + while (ptr < cfg + cfgsize && num_entries < max_entries) { + eol = strchr(ptr, '\n'); + if (!eol) { + eol = cfg + cfgsize; + } + nextptr = eol + 1; + do { + *eol-- = '\0'; /* Remove spaces, tabs and returns */ + } while (eol >= ptr && + (*eol == '\r' || *eol == ' ' || *eol == '\t')); + while (*ptr == ' ' || *ptr == '\t') { + ptr++; + } + if (*ptr == 0 || *ptr == '#') { + goto nextline; /* Ignore comments and empty lines */ + } + arg = strchr(ptr, ' '); /* Search space between cmnd and arg */ + if (!arg) { + arg = strchr(ptr, '\t'); + } + if (!arg) { + printf("Failed to parse this line:\n %s\n", ptr); + goto nextline; + } + *arg++ = 0; + while (*arg == ' ' || *arg == '\t') { + arg++; + } + if (!strcasecmp("default", ptr)) { + defaultlabel = arg; + } else if (!strcasecmp("label", ptr)) { + entries[num_entries].label = arg; + if (defaultlabel && !strcmp(arg, defaultlabel)) { + *def_ent = num_entries; + } + num_entries++; + } else if (!strcasecmp("kernel", ptr) && num_entries) { + entries[num_entries - 1].kernel = arg; + } else if (!strcasecmp("initrd", ptr) && num_entries) { + entries[num_entries - 1].initrd = arg; + } else if (!strcasecmp("append", ptr) && num_entries) { + entries[num_entries - 1].append = arg; + } else { + printf("Command '%s' is not supported.\n", ptr); + } +nextline: + ptr = nextptr; + } + + return num_entries; +} + +/** + * Try to load and parse a pxelinux-style configuration file. + * @param fn_ip must contain server and client IP information + * @param mac MAC address which should be used for probing + * @param retries Amount of TFTP retries before giving up + * @param cfgbuf Pointer to the buffer where config file should be loaded + * @param cfgsize Size of the cfgbuf buffer + * @param entries Pointer to array where the results should be put into + * @param max_entries Number of available slots in the entries array + * @param def_ent Used to return the index of the default entry + * @return Number of valid entries + */ +int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, + int retries, char *cfgbuf, int cfgsize, + struct pl_cfg_entry *entries, int max_entries, + int *def_ent) +{ + int rc; + + rc = pxelinux_load_cfg(fn_ip, mac, retries, cfgbuf, cfgsize); + if (rc < 0) + return rc; + + return pxelinux_parse_cfg(cfgbuf, rc, entries, max_entries, def_ent); +} diff --git a/lib/libnet/pxelinux.h b/lib/libnet/pxelinux.h new file mode 100644 index 0000000..98b3925 --- /dev/null +++ b/lib/libnet/pxelinux.h @@ -0,0 +1,33 @@ +/***************************************************************************** + * Definitions for pxelinux-style config file support + * + * Copyright 2018 Red Hat, Inc. + * + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * Thomas Huth, Red Hat Inc. - initial implementation + *****************************************************************************/ + +#ifndef LIBNET_PXELINUX_H +#define LIBNET_PXELINUX_H + +/* This structure holds the data from one pxelinux.cfg file entry */ +struct pl_cfg_entry { + const char *label; + const char *kernel; + const char *initrd; + const char *append; +}; + +int pxelinux_parse_cfg(char *cfg, int cfgsize, struct pl_cfg_entry *entries, + int max_entries, int *def_ent); +int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, + int retries, char *cfgbuf, int cfgsize, + struct pl_cfg_entry *entries, + int max_entries, int *def_ent); + +#endif From patchwork Sat May 26 06:06:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920931 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLX4fxgz9s1R for ; Sat, 26 May 2018 16:06:44 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLX2f8NzDr0r for ; Sat, 26 May 2018 16:06:44 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL407MlzDqrM for ; Sat, 26 May 2018 16:06:20 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BD485818BAF4; Sat, 26 May 2018 06:06:17 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id B1A76210C6C0; Sat, 26 May 2018 06:06:16 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:05 +0200 Message-Id: <1527314768-4797-6-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 26 May 2018 06:06:17 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Sat, 26 May 2018 06:06:17 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 5/8] libnet: Wire up pxelinux.cfg network booting X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" In case the normal network loading failed, try to load a pxelinux.cfg config file. If that succeeds, load the kernel and initrd with the information that could be found in this file. Signed-off-by: Thomas Huth --- include/helpers.h | 2 ++ lib/libnet/netload.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-- slof/helpers.c | 15 ++++++++-- 3 files changed, 96 insertions(+), 5 deletions(-) diff --git a/include/helpers.h b/include/helpers.h index 04ee771..9dfe3ae 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -36,6 +36,8 @@ extern void SLOF_pci_config_write16(long offset, long value); extern void SLOF_pci_config_write8(long offset, long value); extern void *SLOF_translate_my_address(void *addr); extern int write_mm_log(char *data, unsigned int len, unsigned short type); +extern void SLOF_set_chosen_int(const char *s, long val); +extern void SLOF_set_chosen_bytes(const char *s, const char *addr, size_t size); extern void SLOF_encode_bootp_response(void *addr, size_t size); extern void SLOF_encode_dhcp_response(void *addr, size_t size); diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index f06c2fd..8a38771 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -26,6 +26,7 @@ #include #include "args.h" #include "netapps.h" +#include "pxelinux.h" #define IP_INIT_DEFAULT 5 #define IP_INIT_NONE 0 @@ -426,6 +427,75 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len, return rc; } +#define CFG_BUF_SIZE 2048 +#define MAX_PL_CFG_ENTRIES 16 +static int net_pxelinux_load(filename_ip_t *fnip, char *loadbase, + int maxloadlen, uint8_t *mac, int retries) +{ + struct pl_cfg_entry entries[MAX_PL_CFG_ENTRIES]; + int def, rc, ilen; + static char *cfgbuf; + + cfgbuf = malloc(CFG_BUF_SIZE); + if (!cfgbuf) { + puts("Not enough memory for pxelinux config file buffer!"); + return -1; + } + + rc = pxelinux_load_parse_cfg(fnip, mac, retries, cfgbuf, CFG_BUF_SIZE, + entries, MAX_PL_CFG_ENTRIES, &def); + if (rc < 0) + goto out_free; + if (rc == 0) { + puts("No valid entries in pxelinux config file."); + rc = -1; + goto out_free; + } + + /* Load kernel */ + strncpy(fnip->filename, entries[def].kernel, + sizeof(fnip->filename) - 1); + fnip->filename[sizeof(fnip->filename) - 1] = 0; + rc = tftp_load(fnip, loadbase, maxloadlen, retries); + if (rc <= 0) + goto out_free; + + /* Load ramdisk */ + if (entries[def].initrd) { + loadbase += rc; + maxloadlen -= rc; + if (maxloadlen <= 0) { + puts(" Not enough space for loading the initrd!"); + rc = -1; + goto out_free; + } + strncpy(fnip->filename, entries[def].initrd, + sizeof(fnip->filename) - 1); + ilen = tftp_load(fnip, loadbase, maxloadlen, retries); + if (ilen < 0) { + rc = ilen; + goto out_free; + } + /* The ELF loader will move the kernel to some spot in low mem + * later, thus move the initrd to the end of the RAM instead */ + memmove(loadbase + maxloadlen - ilen, loadbase, ilen); + /* Encode the initrd information in the device tree */ + SLOF_set_chosen_int("linux,initrd-start", + (long)loadbase + maxloadlen - ilen); + SLOF_set_chosen_int("linux,initrd-end", + (long)loadbase + maxloadlen); + } + + if (entries[def].append) { + SLOF_set_chosen_bytes("bootargs", entries[def].append, + strlen(entries[def].append) + 1); + } + +out_free: + free(cfgbuf); + return rc; +} + static void encode_response(char *pkt_buffer, size_t size, int ip_init) { switch(ip_init) { @@ -444,7 +514,7 @@ static void encode_response(char *pkt_buffer, size_t size, int ip_init) int netload(char *buffer, int len, char *args_fs, int alen) { - int rc; + int rc, filename_len; filename_ip_t fn_ip; int fd_device; obp_tftp_args_t obp_tftp_args; @@ -687,7 +757,17 @@ int netload(char *buffer, int len, char *args_fs, int alen) } /* Do the TFTP load and print error message if necessary */ - rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); + rc = 0; + filename_len = strlen(fn_ip.filename); + if (filename_len > 0 && fn_ip.filename[filename_len - 1] != '/') { + rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); + } + + if (rc <= 0 && !obp_tftp_args.filename[0] && + (!filename_len || fn_ip.filename[filename_len - 1] == '/')) { + rc = net_pxelinux_load(&fn_ip, buffer, len, own_mac, + obp_tftp_args.tftp_retries); + } if (obp_tftp_args.ip_init == IP_INIT_DHCP) dhcp_send_release(fn_ip.fd); diff --git a/slof/helpers.c b/slof/helpers.c index a8d575c..bd0742e 100644 --- a/slof/helpers.c +++ b/slof/helpers.c @@ -181,7 +181,16 @@ int write_mm_log(char *data, unsigned int len, unsigned short type) return forth_eval_pop("write-mm-log"); } -static void SLOF_encode_response(void *addr, size_t size,char *s) +void SLOF_set_chosen_int(const char *s, long val) +{ + forth_push(val); + forth_eval("encode-int"); + forth_push((unsigned long)s); + forth_push(strlen(s)); + forth_eval("set-chosen"); +} + +void SLOF_set_chosen_bytes(const char *s, const char *addr, size_t size) { forth_push((unsigned long)addr); forth_push(size); @@ -193,10 +202,10 @@ static void SLOF_encode_response(void *addr, size_t size,char *s) void SLOF_encode_bootp_response(void *addr, size_t size) { - SLOF_encode_response(addr, size, "bootp-response"); + SLOF_set_chosen_bytes("bootp-response", addr, size); } void SLOF_encode_dhcp_response(void *addr, size_t size) { - SLOF_encode_response(addr, size, "dhcp-response"); + SLOF_set_chosen_bytes("dhcp-response", addr, size); } From patchwork Sat May 26 06:06:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920932 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLd3YNRz9s16 for ; Sat, 26 May 2018 16:06:49 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLd29pvzDqsx for ; Sat, 26 May 2018 16:06:49 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL51gm8zDqx4 for ; Sat, 26 May 2018 16:06:21 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 318F47A7E1; Sat, 26 May 2018 06:06:19 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 26A3E210C6C0; Sat, 26 May 2018 06:06:17 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:06 +0200 Message-Id: <1527314768-4797-7-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 26 May 2018 06:06:19 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Sat, 26 May 2018 06:06:19 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 6/8] libnet: Add support for DHCPv4 options 209 and 210 X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" There are two dedicated DHCP options for loading PXELINUX config files, option 209 (config file name) and 210 (path prefix). We should support them, too, in case some users want to configure their boot flow this way. See RFC 5071 and the following URL for more details: https://www.syslinux.org/wiki/index.php?title=PXELINUX#DHCP_options Unlike most other strings in libnet, I've chosen to not use fixed-size arrays for these two strings, but to allocate the memory via malloc here. We always have to make sure not to overflow the stack in Paflof, so adding 2 * 256 byte arrays to struct filename_ip sounded just too dangerous to me. Signed-off-by: Thomas Huth --- lib/libnet/dhcp.c | 33 +++++++++++++++++++++++++++++++ lib/libnet/netload.c | 5 ++++- lib/libnet/ping.c | 14 ++++++++----- lib/libnet/pxelinux.c | 54 ++++++++++++++++++++++++++++++++++++++------------- lib/libnet/tftp.h | 2 ++ 5 files changed, 88 insertions(+), 20 deletions(-) diff --git a/lib/libnet/dhcp.c b/lib/libnet/dhcp.c index d3e5170..85cd7c0 100644 --- a/lib/libnet/dhcp.c +++ b/lib/libnet/dhcp.c @@ -79,6 +79,8 @@ #define DHCP_TFTP_SERVER 66 #define DHCP_BOOTFILE 67 #define DHCP_CLIENT_ARCH 93 +#define DHCP_PXELINUX_CFGFILE 209 /* See RFC 5071 */ +#define DHCP_PXELINUX_PREFIX 210 #define DHCP_ENDOPT 0xFF #define DHCP_PADOPT 0x00 @@ -167,6 +169,8 @@ static uint32_t dhcp_siaddr_ip = 0; static char dhcp_filename[256]; static char dhcp_tftp_name[256]; static uint32_t dhcp_xid; +static char *pxelinux_cfgfile; +static char *pxelinux_prefix; static char * response_buffer; @@ -185,6 +189,8 @@ int32_t dhcpv4(char *ret_buffer, filename_ip_t *fn_ip) strcpy(dhcp_filename, ""); strcpy(dhcp_tftp_name, ""); + pxelinux_cfgfile = pxelinux_prefix = NULL; + response_buffer = ret_buffer; if (dhcp_attempt(fd) == 0) @@ -232,6 +238,10 @@ int32_t dhcpv4(char *ret_buffer, filename_ip_t *fn_ip) fn_ip -> server_ip = dhcp_tftp_ip; strcpy(fn_ip->filename, dhcp_filename); + fn_ip->pl_cfgfile = pxelinux_cfgfile; + fn_ip->pl_prefix = pxelinux_prefix; + pxelinux_cfgfile = pxelinux_prefix = NULL; + return 0; } @@ -456,6 +466,26 @@ static int32_t dhcp_decode_options(uint8_t opt_field[], uint32_t opt_len, offset += 4; break; + case DHCP_PXELINUX_CFGFILE: + pxelinux_cfgfile = malloc(opt_field[offset + 1] + 1); + if (pxelinux_cfgfile) { + memcpy(pxelinux_cfgfile, opt_field + offset + 2, + opt_field[offset + 1]); + pxelinux_cfgfile[opt_field[offset + 1]] = 0; + } + offset += 2 + opt_field[offset + 1]; + break; + + case DHCP_PXELINUX_PREFIX: + pxelinux_prefix = malloc(opt_field[offset + 1] + 1); + if (pxelinux_prefix) { + memcpy(pxelinux_prefix, opt_field + offset + 2, + opt_field[offset + 1]); + pxelinux_prefix[opt_field[offset + 1]] = 0; + } + offset += 2 + opt_field[offset + 1]; + break; + case DHCP_PADOPT : offset++; break; @@ -681,6 +711,9 @@ static void dhcp_send_request(int fd) opt.request_list[DHCP_ROUTER] = 1; opt.request_list[DHCP_TFTP_SERVER] = 1; opt.request_list[DHCP_BOOTFILE] = 1; + opt.request_list[DHCP_PXELINUX_CFGFILE] = 1; + opt.request_list[DHCP_PXELINUX_PREFIX] = 1; + opt.request_list[DHCP_CLIENT_ARCH] = USE_DHCPARCH; opt.flag[DHCP_CLIENT_ARCH] = USE_DHCPARCH; diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index 8a38771..4c7ac37 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -759,7 +759,8 @@ int netload(char *buffer, int len, char *args_fs, int alen) /* Do the TFTP load and print error message if necessary */ rc = 0; filename_len = strlen(fn_ip.filename); - if (filename_len > 0 && fn_ip.filename[filename_len - 1] != '/') { + if (filename_len > 0 && fn_ip.filename[filename_len - 1] != '/' && + !fn_ip.pl_cfgfile) { rc = tftp_load(&fn_ip, buffer, len, obp_tftp_args.tftp_retries); } @@ -779,5 +780,7 @@ int netload(char *buffer, int len, char *args_fs, int alen) } err_out: SLOF_free_mem(pkt_buffer, MAX_PKT_SIZE); + free(fn_ip.pl_cfgfile); + free(fn_ip.pl_prefix); return rc; } diff --git a/lib/libnet/ping.c b/lib/libnet/ping.c index edad5eb..051269f 100644 --- a/lib/libnet/ping.c +++ b/lib/libnet/ping.c @@ -115,6 +115,7 @@ int ping(char *args_fs, int alen) uint8_t own_mac[6]; uint32_t netmask; char args[256]; + int ret = -1; memset(&ping_args, 0, sizeof(struct ping_args)); @@ -164,8 +165,7 @@ int ping(char *args_fs, int alen) if (arp_failed == -1) { printf("\n DHCP: Could not get ip address\n"); - close(fn_ip.fd); - return -1; + goto free_out; } } else { @@ -210,12 +210,16 @@ int ping(char *args_fs, int alen) receive_ether(fd_device); if(pong_ipv4() == 0) { printf("success\n"); - close(fn_ip.fd); - return 0; + ret = 0; + goto free_out; } } printf("failed\n"); +free_out: + free(fn_ip.pl_cfgfile); + free(fn_ip.pl_prefix); close(fn_ip.fd); - return -1; + + return ret; } diff --git a/lib/libnet/pxelinux.c b/lib/libnet/pxelinux.c index d702811..91b3c13 100644 --- a/lib/libnet/pxelinux.c +++ b/lib/libnet/pxelinux.c @@ -57,24 +57,50 @@ static int pxelinux_load_cfg(filename_ip_t *fn_ip, uint8_t *mac, int rc, idx; char *baseptr; - /* Try to get a usable base directory from the DHCP bootfile name */ - baseptr = strrchr(fn_ip->filename, '/'); - if (!baseptr) - baseptr = fn_ip->filename; - else - ++baseptr; - /* Check that we've got enough space to store "pxelinux.cfg/" and - * the UUID (which is the longest file name) there */ - if (baseptr - fn_ip->filename > sizeof(fn_ip->filename) - 50) { - puts("Error: The bootfile string is too long for deriving the " - "pxelinux.cfg file name from it."); - return -1; + /* Did we get a usable base directory via DHCP? */ + if (fn_ip->pl_prefix) { + idx = strlen(fn_ip->pl_prefix); + /* Do we have enough space left to store a UUID file name? */ + if (idx > sizeof(fn_ip->filename) - 36) { + puts("Error: pxelinux prefix is too long!"); + return -1; + } + strcpy(fn_ip->filename, fn_ip->pl_prefix); + baseptr = &fn_ip->filename[idx]; + } else { + /* Try to get a usable base directory from the DHCP bootfile name */ + baseptr = strrchr(fn_ip->filename, '/'); + if (!baseptr) + baseptr = fn_ip->filename; + else + ++baseptr; + /* Check that we've got enough space to store "pxelinux.cfg/" + * and the UUID (which is the longest file name) there */ + if (baseptr - fn_ip->filename > sizeof(fn_ip->filename) - 50) { + puts("Error: The bootfile string is too long for " + "deriving the pxelinux.cfg file name from it."); + return -1; + } + strcpy(baseptr, "pxelinux.cfg/"); + baseptr += strlen(baseptr); } - strcpy(baseptr, "pxelinux.cfg/"); - baseptr += strlen(baseptr); puts("Trying pxelinux.cfg files..."); + /* Try to load config file according to file name in DHCP option 209 */ + if (fn_ip->pl_cfgfile) { + if (strlen(fn_ip->pl_cfgfile) + strlen(fn_ip->filename) + > sizeof(fn_ip->filename)) { + puts("Error: pxelinux.cfg prefix + filename too long!"); + return -1; + } + strcpy(baseptr, fn_ip->pl_cfgfile); + rc = pxelinux_tftp_load(fn_ip, cfgbuf, cfgbufsize - 1, retries); + if (rc > 0) { + return rc; + } + } + /* Look for config file with MAC address in its name */ sprintf(baseptr, "01-%02x-%02x-%02x-%02x-%02x-%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); diff --git a/lib/libnet/tftp.h b/lib/libnet/tftp.h index ca8029e..d2c0919 100644 --- a/lib/libnet/tftp.h +++ b/lib/libnet/tftp.h @@ -29,6 +29,8 @@ struct filename_ip { ip6_addr_t server_ip6; ip6_addr_t dns_ip6; char filename[256]; + char *pl_cfgfile; /* For PXELINUX DHCPv4 option 209. Must be free()ed */ + char *pl_prefix; /* For PXELINUX DHCPv4 option 210. Must be free()ed */ int fd; int ip_version; }; From patchwork Sat May 26 06:06:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920933 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLj3k6mz9s16 for ; Sat, 26 May 2018 16:06:53 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLj20c3zDr10 for ; Sat, 26 May 2018 16:06:53 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL65V1ZzDqL5 for ; Sat, 26 May 2018 16:06:22 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8318840201C5; Sat, 26 May 2018 06:06:20 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id 787232023433; Sat, 26 May 2018 06:06:19 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:07 +0200 Message-Id: <1527314768-4797-8-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:20 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.6]); Sat, 26 May 2018 06:06:20 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 7/8] slof: Add a helper function to get the contents of a property in C code X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" We will need to retrieve the UUID of the VM in the libnet code, so we need a function to get the contents from a device tree property. Signed-off-by: Thomas Huth --- include/helpers.h | 2 ++ slof/helpers.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/helpers.h b/include/helpers.h index 9dfe3ae..5834bce 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -40,6 +40,8 @@ extern void SLOF_set_chosen_int(const char *s, long val); extern void SLOF_set_chosen_bytes(const char *s, const char *addr, size_t size); extern void SLOF_encode_bootp_response(void *addr, size_t size); extern void SLOF_encode_dhcp_response(void *addr, size_t size); +extern int SLOF_get_property(const char *node, const char *propname, + char **addr, int *len); #define offset_of(type, member) ((long) &((type *)0)->member) #define container_of(ptr, type, member) ({ \ diff --git a/slof/helpers.c b/slof/helpers.c index bd0742e..dfb0c13 100644 --- a/slof/helpers.c +++ b/slof/helpers.c @@ -209,3 +209,18 @@ void SLOF_encode_dhcp_response(void *addr, size_t size) { SLOF_set_chosen_bytes("dhcp-response", addr, size); } + +int SLOF_get_property(const char *node, const char *propname, + char **addr, int *len) +{ + forth_push((unsigned long)propname); + forth_push(strlen(propname)); + forth_push((unsigned long)node); + forth_push(strlen(node)); + forth_eval("find-node get-property"); + if (forth_pop()) + return -1; + *len = forth_pop(); + *addr = (char *)forth_pop(); + return 0; +} From patchwork Sat May 26 06:06:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 920934 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40tCLn3qytz9s16 for ; Sat, 26 May 2018 16:06:57 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40tCLn2R70zDqnw for ; Sat, 26 May 2018 16:06:57 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com X-Original-To: slof@lists.ozlabs.org Delivered-To: slof@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=redhat.com (client-ip=66.187.233.73; helo=mx1.redhat.com; envelope-from=thuth@redhat.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=redhat.com Received: from mx1.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 40tCL81k88zDr3M for ; Sat, 26 May 2018 16:06:24 +1000 (AEST) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EDF3411DB0A; Sat, 26 May 2018 06:06:21 +0000 (UTC) Received: from thh440s.redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by smtp.corp.redhat.com (Postfix) with ESMTP id E172B210C6C0; Sat, 26 May 2018 06:06:20 +0000 (UTC) From: Thomas Huth To: slof@lists.ozlabs.org Date: Sat, 26 May 2018 08:06:08 +0200 Message-Id: <1527314768-4797-9-git-send-email-thuth@redhat.com> In-Reply-To: <1527314768-4797-1-git-send-email-thuth@redhat.com> References: <1527314768-4797-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 26 May 2018 06:06:21 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.1]); Sat, 26 May 2018 06:06:21 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Subject: [SLOF] [PATCH v3 8/8] libnet: Support UUID-based pxelinux.cfg file names X-BeenThere: slof@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "Patches for https://github.com/aik/SLOF" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Greg Kurz MIME-Version: 1.0 Errors-To: slof-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "SLOF" Retrieve the UUID from the device tree and pass it to the pxelinux.cfg function, so that we can look there for UUID-based file names, too. Signed-off-by: Thomas Huth --- lib/libnet/netload.c | 18 +++++++++++++++++- lib/libnet/pxelinux.c | 16 +++++++++++++--- lib/libnet/pxelinux.h | 2 +- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/lib/libnet/netload.c b/lib/libnet/netload.c index 4c7ac37..4b95eab 100644 --- a/lib/libnet/netload.c +++ b/lib/libnet/netload.c @@ -427,6 +427,21 @@ static int tftp_load(filename_ip_t *fnip, void *buffer, int len, return rc; } +static const char *get_uuid(void) +{ + char *addr; + int len; + + if (SLOF_get_property("/", "system-id", &addr, &len)) + return NULL; + if (len < 37) { /* This should never happen... */ + puts("Warning: UUID property is too short."); + return NULL; + } + + return addr; +} + #define CFG_BUF_SIZE 2048 #define MAX_PL_CFG_ENTRIES 16 static int net_pxelinux_load(filename_ip_t *fnip, char *loadbase, @@ -442,7 +457,8 @@ static int net_pxelinux_load(filename_ip_t *fnip, char *loadbase, return -1; } - rc = pxelinux_load_parse_cfg(fnip, mac, retries, cfgbuf, CFG_BUF_SIZE, + rc = pxelinux_load_parse_cfg(fnip, mac, get_uuid(), retries, + cfgbuf, CFG_BUF_SIZE, entries, MAX_PL_CFG_ENTRIES, &def); if (rc < 0) goto out_free; diff --git a/lib/libnet/pxelinux.c b/lib/libnet/pxelinux.c index 91b3c13..718ceca 100644 --- a/lib/libnet/pxelinux.c +++ b/lib/libnet/pxelinux.c @@ -51,7 +51,7 @@ static int pxelinux_tftp_load(filename_ip_t *fnip, void *buffer, int len, * Try to load a pxelinux.cfg file by probing the possible file names. * Note that this function will overwrite filename_ip_t->filename. */ -static int pxelinux_load_cfg(filename_ip_t *fn_ip, uint8_t *mac, +static int pxelinux_load_cfg(filename_ip_t *fn_ip, uint8_t *mac, const char *uuid, int retries, char *cfgbuf, int cfgbufsize) { int rc, idx; @@ -101,6 +101,15 @@ static int pxelinux_load_cfg(filename_ip_t *fn_ip, uint8_t *mac, } } + /* Try to load config file with name based on the VM UUID */ + if (uuid) { + strcpy(baseptr, uuid); + rc = pxelinux_tftp_load(fn_ip, cfgbuf, cfgbufsize - 1, retries); + if (rc > 0) { + return rc; + } + } + /* Look for config file with MAC address in its name */ sprintf(baseptr, "01-%02x-%02x-%02x-%02x-%02x-%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -215,6 +224,7 @@ nextline: * Try to load and parse a pxelinux-style configuration file. * @param fn_ip must contain server and client IP information * @param mac MAC address which should be used for probing + * @param uuid UUID which should be used for probing (can be NULL) * @param retries Amount of TFTP retries before giving up * @param cfgbuf Pointer to the buffer where config file should be loaded * @param cfgsize Size of the cfgbuf buffer @@ -223,14 +233,14 @@ nextline: * @param def_ent Used to return the index of the default entry * @return Number of valid entries */ -int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, +int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, const char *uuid, int retries, char *cfgbuf, int cfgsize, struct pl_cfg_entry *entries, int max_entries, int *def_ent) { int rc; - rc = pxelinux_load_cfg(fn_ip, mac, retries, cfgbuf, cfgsize); + rc = pxelinux_load_cfg(fn_ip, mac, uuid, retries, cfgbuf, cfgsize); if (rc < 0) return rc; diff --git a/lib/libnet/pxelinux.h b/lib/libnet/pxelinux.h index 98b3925..0514d0d 100644 --- a/lib/libnet/pxelinux.h +++ b/lib/libnet/pxelinux.h @@ -25,7 +25,7 @@ struct pl_cfg_entry { int pxelinux_parse_cfg(char *cfg, int cfgsize, struct pl_cfg_entry *entries, int max_entries, int *def_ent); -int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, +int pxelinux_load_parse_cfg(filename_ip_t *fn_ip, uint8_t *mac, const char *uuid, int retries, char *cfgbuf, int cfgsize, struct pl_cfg_entry *entries, int max_entries, int *def_ent);