diff options
Diffstat (limited to 'com32')
-rw-r--r-- | com32/modules/Makefile | 2 | ||||
-rw-r--r-- | com32/modules/prdhcp.c | 164 | ||||
-rw-r--r-- | com32/modules/pxechn.c | 49 |
3 files changed, 209 insertions, 6 deletions
diff --git a/com32/modules/Makefile b/com32/modules/Makefile index 24b7d283..f110e584 100644 --- a/com32/modules/Makefile +++ b/com32/modules/Makefile @@ -24,7 +24,7 @@ MODULES = config.c32 ethersel.c32 dmitest.c32 cpuidtest.c32 \ meminfo.c32 sdi.c32 sanboot.c32 ifcpu64.c32 vesainfo.c32 \ kbdmap.c32 cmd.c32 vpdtest.c32 host.c32 ls.c32 gpxecmd.c32 \ ifcpu.c32 cpuid.c32 cat.c32 pwd.c32 ifplop.c32 zzjson.c32 \ - whichsys.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 + whichsys.c32 prdhcp.c32 pxechn.c32 kontron_wdt.c32 ifmemdsk.c32 TESTFILES = diff --git a/com32/modules/prdhcp.c b/com32/modules/prdhcp.c new file mode 100644 index 00000000..321d4e77 --- /dev/null +++ b/com32/modules/prdhcp.c @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2010-2011 Gene Cumm - All Rights Reserved + * + * Portions from chain.c: + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Significant portions copyright (C) 2010 Shao Miller + * [partition iteration, GPT, "fs"] + * + * 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., 53 Temple Place Ste 330, + * Boston MA 02111-1307, USA; either version 2 of the License, or + * (at your option) any later version; incorporated herein by reference. + * + * ----------------------------------------------------------------------- */ + +/* + * prdhcp.c + * + * Print the contents of the 3 DHCP packets + */ + +#include <stdio.h> +#include <stdlib.h> +#include <consoles.h> +#include <console.h> +#include <errno.h> +#include <string.h> +#include <syslinux/config.h> +#include <syslinux/loadfile.h> +#include <syslinux/bootrm.h> +#include <syslinux/video.h> +#include <com32.h> +#include <stdint.h> +#include <syslinux/pxe.h> +#include <sys/gpxe.h> +#include <unistd.h> +#include <getkey.h> + +#define DEBUG 1 + +#define dprintf0(f, ...) ((void)0) + +#ifdef DEBUG +# define dpressanykey pressanykey +# define dprintf printf +# define dprint_pxe_bootp_t print_pxe_bootp_t +# define dprint_pxe_vendor_blk print_pxe_vendor_blk +# define dprint_pxe_vendor_raw print_pxe_vendor_raw +#else +# define dpressanykey(void) ((void)0) +# define dprintf(f, ...) ((void)0) +# define dprint_pxe_bootp_t(p, l) ((void)0) +# define dprint_pxe_vendor_blk(p, l) ((void)0) +# define dprint_pxe_vendor_raw(p, l) ((void)0) +#endif + +#define dprintf_opt_cp dprintf0 +#define dprintf_opt_inj dprintf + + +const char app_name_str[] = "prdhcp.c32"; + + +int pressanykey(void) { + int inc; + + printf("Press any key to continue. "); + inc = KEY_NONE; + while (inc == KEY_NONE) + inc = get_key(stdin, 6000); + puts(""); + return inc; +} + +void print_pxe_vendor_blk(pxe_bootp_t *p, size_t len) +{ + int i, vlen, oplen, j; + uint8_t *d; + uint32_t magic; + if (!p) { + printf(" packet pointer is null\n"); + return; + } + vlen = len - ((void *)&(p->vendor) - (void *)p); + printf(" Vendor Data: Len=%d", vlen); + d = p->vendor.d; + /* Print only 256 characters of the vendor/option data */ + /* + print_pxe_vendor_raw(p, (len - vlen) + 256); + vlen = 0; + */ + magic = ntohl(*((uint32_t *)d)); + printf(" Magic: %08X", ntohl(*((uint32_t *)d))); + if (magic != VM_RFC1048) /* Invalid DHCP packet */ + vlen = 0; + for (i = 4; i < vlen; i++) { + if (d[i]) /* Skip the padding */ + printf("\n @%03X-%3d", i, d[i]); + if (d[i] == 255) /* End of list */ + break; + if (d[i]) { + oplen = d[++i]; + printf(" l=%3d:", oplen); + for (j = (++i + oplen); i < vlen && i < j; i++) { + printf(" %02X", d[i]); + } + i--; + } + } + printf("\n"); +} + +void print_pxe_bootp_t(pxe_bootp_t *p, size_t len) +{ + if (!p) { + printf(" packet pointer is null\n"); + return; + } + printf(" op:%02X hw:%02X hl:%02X gh:%02X id:%08X se:%04X f:%04X" + " cip:%08X\n", p->opcode, p->Hardware, p->Hardlen, p->Gatehops, + ntohl(p->ident), ntohs(p->seconds), ntohs(p->Flags), ntohl(p->cip)); + printf(" yip:%08X sip:%08X gip:%08X", + ntohl(p->yip), ntohl(p->sip), ntohl(p->gip)); + printf(" caddr-%02X:%02X:%02X:%02X:%02X:%02X\n", p->CAddr[0], + p->CAddr[1], p->CAddr[2], p->CAddr[3], p->CAddr[4], p->CAddr[5]); + printf(" sName: '%s'\n", p->Sname); + printf(" bootfile: '%s'\n", p->bootfile); + print_pxe_vendor_blk(p, len); +} + +void print_dhcp_pkt_all(void) +{ + pxe_bootp_t *p; + size_t len; + int i; + int ptype[3] = {PXENV_PACKET_TYPE_DHCP_DISCOVER, PXENV_PACKET_TYPE_DHCP_ACK, PXENV_PACKET_TYPE_CACHED_REPLY}; + + for (i = 0; i < 3; i++) { + if (!pxe_get_cached_info(ptype[i], + (void **)&(p), &(len))) { + dprintf("Got packet #%d/%d\n", (i + 1), ptype[i]); + print_pxe_bootp_t(p, len); + pressanykey(); + } + } +} + +int main(void) +{ + int rv= -1; + const struct syslinux_version *sv; + + console_ansi_raw(); + sv = syslinux_version(); + if (sv->filesystem != SYSLINUX_FS_PXELINUX) { + printf("%s: May only run in PXELINUX\n", app_name_str); + return -2; + } + print_dhcp_pkt_all(); + return rv; +} diff --git a/com32/modules/pxechn.c b/com32/modules/pxechn.c index 3f9ebd32..26376900 100644 --- a/com32/modules/pxechn.c +++ b/com32/modules/pxechn.c @@ -43,7 +43,11 @@ #include <limits.h> -#define PXECHN_DEBUG 1 +#ifdef DEBUG +# define PXECHN_DEBUG 1 +#else +# define PXECHN_DEBUG 0 +#endif typedef union { uint64_t q; @@ -54,15 +58,21 @@ typedef union { #define dprintf0(f, ...) ((void)0) +#ifndef dprintf +# if (PXECHN_DEBUG > 0) +# define dprintf printf +# else +# define dprintf(f, ...) ((void)0) +# endif +#endif + #if (PXECHN_DEBUG > 0) # define dpressanykey pressanykey -# define dprintf printf # define dprint_pxe_bootp_t print_pxe_bootp_t # define dprint_pxe_vendor_blk print_pxe_vendor_blk # define dprint_pxe_vendor_raw print_pxe_vendor_raw #else # define dpressanykey(tm) ((void)0) -# define dprintf(f, ...) ((void)0) # define dprint_pxe_bootp_t(p, l) ((void)0) # define dprint_pxe_vendor_blk(p, l) ((void)0) # define dprint_pxe_vendor_raw(p, l) ((void)0) @@ -107,6 +117,7 @@ struct pxelinux_opt { uint32_t force; uint32_t wait; /* Additional decision to wait before boot */ int32_t wds; /* WDS option/level */ + in_addr_t sip; /* siaddr: Next Server IP Address */ struct dhcp_option p[PXECHN_NUM_PKT_AVAIL]; /* original _DHCP_DISCOVER, _DHCP_ACK, _CACHED_REPLY then modified packets */ char host[PXECHN_HOST_LEN]; @@ -453,6 +464,7 @@ void pxechn_init(struct pxelinux_opt *pxe) pxe->wait = 0; pxe->gip = 0; pxe->wds = 0; + pxe->sip = 0; pxe->host[0] = 0; pxe->host[((NUM_DHCP_OPTS) - 1)] = 0; for (int j = 0; j < PXECHN_NUM_PKT_TYPE; j++){ @@ -731,7 +743,7 @@ int pxechn_parse_args(int argc, char *argv[], struct pxelinux_opt *pxe, { int arg, optnum, rv = 0; char *p = NULL; - const char optstr[] = "c:f:g:o:p:t:uwW"; + const char optstr[] = "c:f:g:o:p:St:uwW"; struct dhcp_option iopt; if (pxe->p[5].data) @@ -765,6 +777,9 @@ int pxechn_parse_args(int argc, char *argv[], struct pxelinux_opt *pxe, case 'p': /* prefix */ pxechn_setopt_str(&(opts[210]), optarg); break; + case 'S': /* sip from sName */ + pxe->sip = 1; + break; case 't': /* timeout */ optnum = strtoul(optarg, &p, 0); if (p != optarg) { @@ -809,6 +824,7 @@ int pxechn_args(int argc, char *argv[], struct pxelinux_opt *pxe) pxe_bootp_t *bootp0, *bootp1; int ret = 0; struct dhcp_option *opts; + char *str; opts = pxe->opts[2]; /* Start filling packet #1 */ @@ -826,7 +842,30 @@ int pxechn_args(int argc, char *argv[], struct pxelinux_opt *pxe) ret = pxechn_parse_args(argc, argv, pxe, opts); if (ret) return ret; - bootp1->sip = pxe->fip; + if (pxe->sip > 0xFFFFFF) { /* a real IPv4 address */ + bootp1->sip = pxe->sip; + } else if ((pxe->sip == 1) + && (opts[66].len > 0)){ + /* unterminated? */ + if (strnlen(opts[66].data, opts[66].len) == (size_t)opts[66].len) { + str = malloc(opts[66].len + 1); + if (str) { + memcpy(str, opts[66].data, opts[66].len); + str[opts[66].len] = 0; + } + } else { + str = opts[66].data; + } + if (str) { + bootp1->sip = pxe_dns(str); + if (str != opts[66].data) + free(str); + } else { + bootp1->sip = pxe->fip; + } + } else { + bootp1->sip = pxe->fip; + } bootp1->gip = pxe->gip; ret = dhcp_pack_packet(bootp1, (size_t *)&(pxe->p[5].len), opts); |