mirror of
https://github.com/xcat2/xcat-dep.git
synced 2024-11-27 03:39:11 +00:00
86940f9344
Former-commit-id: eacd37318109c23709fca65e1ff3936e8055c681
317 lines
11 KiB
Diff
317 lines
11 KiB
Diff
diff -purN yaboot-1.3.14.orig/include/file.h yaboot-1.3.14/include/file.h
|
|
--- yaboot-1.3.14.orig/include/file.h 2009-10-15 11:39:01.112642471 +1100
|
|
+++ yaboot-1.3.14/include/file.h 2009-10-15 15:29:04.692654961 +1100
|
|
@@ -45,6 +45,7 @@ struct boot_fspec_t {
|
|
char* giaddr; /* Gateway address */
|
|
char* bootp_retries; /* Bootp retries */
|
|
char* tftp_retries; /* TFTP retries */
|
|
+ char* subnetmask; /* Subnet mask */
|
|
char* addl_params; /* copy all additional parameters */
|
|
|
|
/* Following fields are used only in ipv6 format */
|
|
diff -purN yaboot-1.3.14.orig/include/prom.h yaboot-1.3.14/include/prom.h
|
|
--- yaboot-1.3.14.orig/include/prom.h 2009-10-15 15:23:39.796944672 +1100
|
|
+++ yaboot-1.3.14/include/prom.h 2009-10-15 15:29:04.692654961 +1100
|
|
@@ -153,7 +153,7 @@ struct bootp_packet {
|
|
unsigned char chaddr[16];
|
|
unsigned char sname[64];
|
|
unsigned char file[128];
|
|
- /* vendor options go here if we need them */
|
|
+ unsigned char options[]; /* vendor options */
|
|
};
|
|
|
|
struct bootp_packet * prom_get_netinfo (void);
|
|
diff -purN yaboot-1.3.14.orig/second/cfg.c yaboot-1.3.14/second/cfg.c
|
|
--- yaboot-1.3.14.orig/second/cfg.c 2009-10-15 15:23:39.798647660 +1100
|
|
+++ yaboot-1.3.14/second/cfg.c 2009-10-15 15:29:04.693668247 +1100
|
|
@@ -597,6 +597,9 @@ int cfg_set_default_by_mac (char *mac_ad
|
|
char * label = NULL;
|
|
int haslabel = 0;
|
|
|
|
+ if (mac_addr == NULL)
|
|
+ return 0;
|
|
+
|
|
/* check if there is an image label equal to mac_addr */
|
|
for (tmp = images; tmp; tmp = tmp->next) {
|
|
label = cfg_get_strg_i (tmp->table, "label");
|
|
diff -purN yaboot-1.3.14.orig/second/file.c yaboot-1.3.14/second/file.c
|
|
--- yaboot-1.3.14.orig/second/file.c 2009-10-15 15:23:39.802647442 +1100
|
|
+++ yaboot-1.3.14/second/file.c 2009-10-15 15:29:04.694645423 +1100
|
|
@@ -51,6 +51,42 @@ ipv4_to_str(__u32 ip)
|
|
return buf;
|
|
}
|
|
|
|
+/* FIXME: COMMENT */
|
|
+static char * is_valid_ip_str(char *str)
|
|
+{
|
|
+ int i;
|
|
+ long tmp;
|
|
+ __u32 ip = 0;
|
|
+ char *ptr=str, *endptr;
|
|
+
|
|
+ if (str == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ for (i=0; i<4; i++, ptr = ++endptr) {
|
|
+ tmp = strtol(ptr, &endptr, 10);
|
|
+ if ((tmp & 0xff) != tmp)
|
|
+ return NULL;
|
|
+
|
|
+ /* If we reach the end of the string but we're not in the 4th octet
|
|
+ * we have an invalid IP */
|
|
+ if (*endptr == '\x0' && i!=3)
|
|
+ return NULL;
|
|
+
|
|
+ /* If we have anything other than a NULL or '.' we have an invlaid
|
|
+ * IP */
|
|
+ if (*endptr != '\x0' && *endptr != '.')
|
|
+ return NULL;
|
|
+
|
|
+ ip += (tmp << (24-(i*8)));
|
|
+ }
|
|
+
|
|
+ if (ip == 0 || ip == ~0u)
|
|
+ return NULL;
|
|
+
|
|
+ return str;
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
* Copy the string from source to dest till newline or comma(,) is seen
|
|
* in the source.
|
|
@@ -130,12 +166,13 @@ extract_ipv4_args(char *imagepath, struc
|
|
* read the arguments in order: siaddr,filename,ciaddr,giaddr,
|
|
* bootp-retries,tftp-retries,addl_prameters
|
|
*/
|
|
- result->siaddr = scopy(&str, &args);
|
|
+ result->siaddr = is_valid_ip_str(scopy(&str, &args));
|
|
result->file = scopy(&str, &args);
|
|
- result->ciaddr = scopy(&str, &args);
|
|
- result->giaddr = scopy(&str, &args);
|
|
+ result->ciaddr = is_valid_ip_str(scopy(&str, &args));
|
|
+ result->giaddr = is_valid_ip_str(scopy(&str, &args));
|
|
result->bootp_retries = scopy(&str, &args);
|
|
result->tftp_retries = scopy(&str, &args);
|
|
+ result->subnetmask = scopy(&str, &args);
|
|
if (*args) {
|
|
result->addl_params = strdup(args);
|
|
if (!result->addl_params)
|
|
@@ -144,6 +181,82 @@ extract_ipv4_args(char *imagepath, struc
|
|
return 1;
|
|
}
|
|
|
|
+/* DHCP options */
|
|
+enum dhcp_options {
|
|
+ DHCP_PAD = 0,
|
|
+ DHCP_NETMASK = 1,
|
|
+ DHCP_ROUTERS = 3,
|
|
+ DHCP_DNS = 6,
|
|
+ DHCP_END = 255,
|
|
+};
|
|
+
|
|
+#define DHCP_COOKIE 0x63825363
|
|
+#define DHCP_COOKIE_SIZE 4
|
|
+
|
|
+/*
|
|
+ * FIXME: COMMENT
|
|
+ */
|
|
+static void
|
|
+extract_vendor_options(struct bootp_packet *packet, struct boot_fspec_t *result)
|
|
+{
|
|
+ int i = 0;
|
|
+ __u32 cookie;
|
|
+ __u8 *options = &packet->options[0];
|
|
+
|
|
+ memcpy(&cookie, &options[i], DHCP_COOKIE_SIZE);
|
|
+
|
|
+ if (cookie != DHCP_COOKIE) {
|
|
+ prom_printf("EEEK! cookie is fubar got %08x expected %08x\n",
|
|
+ cookie, DHCP_COOKIE);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ i += DHCP_COOKIE_SIZE;
|
|
+
|
|
+ /* FIXME: It may be possible to run off the end of a packet here /if/
|
|
+ * it's malformed. :( */
|
|
+ while (options[i] != DHCP_END) {
|
|
+ __u8 tag = options[i++], len;
|
|
+ __u32 value;
|
|
+
|
|
+ if (tag == DHCP_PAD)
|
|
+ continue;
|
|
+
|
|
+ len = options[i++];
|
|
+ memcpy(&value, &options[i], len);
|
|
+
|
|
+#if DEBUG
|
|
+{
|
|
+ DEBUG_F("tag=%2d, len=%2d, data=", tag, len);
|
|
+ int j;
|
|
+ for (j=0; j<len; j++)
|
|
+ prom_printf("%02x", options[i+j]);
|
|
+ prom_printf("\n");
|
|
+}
|
|
+#endif
|
|
+
|
|
+ switch (tag) {
|
|
+ case DHCP_NETMASK:
|
|
+ if ((result->subnetmask == NULL || *(result->subnetmask) == '\x0') && value != 0) {
|
|
+ result->subnetmask = ipv4_to_str(value);
|
|
+ DEBUG_F("Storing %s as subnetmask from options\n",
|
|
+ result->subnetmask);
|
|
+ }
|
|
+ /* FIXME: do we need to grok the subnet mask? */
|
|
+ break;
|
|
+ case DHCP_ROUTERS:
|
|
+ if ((result->giaddr == NULL || *(result->giaddr) == '\x0')
|
|
+ && value != 0) {
|
|
+ result->giaddr = ipv4_to_str(value);
|
|
+ DEBUG_F("Storing %s as gateway from options\n",
|
|
+ result->giaddr);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ i += len;
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
* Check netinfo for ipv4 parameters and add them to the fspec iff the
|
|
* fspec has no existing value.
|
|
@@ -170,16 +283,18 @@ extract_netinfo_args(struct boot_fspec_t
|
|
if (packet->ciaddr == 0 && packet->yiaddr != 0)
|
|
packet->ciaddr = packet->yiaddr;
|
|
|
|
- if ((result->siaddr == NULL || *(result->siaddr) == NULL)
|
|
+ if ((result->siaddr == NULL || *(result->siaddr) == '\x0')
|
|
&& packet->siaddr != 0)
|
|
result->siaddr = ipv4_to_str(packet->siaddr);
|
|
- if ((result->ciaddr == NULL || *(result->ciaddr) == NULL)
|
|
+ if ((result->ciaddr == NULL || *(result->ciaddr) == '\x0')
|
|
&& packet->ciaddr != 0)
|
|
result->ciaddr = ipv4_to_str(packet->ciaddr);
|
|
- if ((result->giaddr == NULL || *(result->giaddr) == NULL)
|
|
+ if ((result->giaddr == NULL || *(result->giaddr) == '\x0')
|
|
&& packet->giaddr != 0)
|
|
result->giaddr = ipv4_to_str(packet->giaddr);
|
|
|
|
+ extract_vendor_options(packet, result);
|
|
+
|
|
/* FIXME: Yck! if we /still/ do not have a gateway then "cheat" and use
|
|
* the server. This will be okay if the client and server are on
|
|
* the same IP network, if not then lets hope the server does ICMP
|
|
diff -purN yaboot-1.3.14.orig/second/fs_of.c yaboot-1.3.14/second/fs_of.c
|
|
--- yaboot-1.3.14.orig/second/fs_of.c 2009-10-15 15:23:39.805647069 +1100
|
|
+++ yaboot-1.3.14/second/fs_of.c 2009-10-15 15:29:04.695645439 +1100
|
|
@@ -137,6 +137,7 @@ of_net_open(struct boot_file_t* file,
|
|
static char buffer[1024];
|
|
char *filename = NULL;
|
|
char *p;
|
|
+ int new_tftp;
|
|
|
|
DEBUG_ENTER;
|
|
DEBUG_OPEN;
|
|
@@ -148,34 +149,47 @@ of_net_open(struct boot_file_t* file,
|
|
*p = '\\';
|
|
}
|
|
|
|
- DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>; ipv6 <%d>\n",
|
|
- fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr, fspec->is_ipv6);
|
|
+ DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>;"
|
|
+ " ipv6 <%d>\n",
|
|
+ fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr,
|
|
+ fspec->is_ipv6);
|
|
+
|
|
strncpy(buffer, fspec->dev, 768);
|
|
if (fspec->is_ipv6)
|
|
strcat(buffer, TOK_IPV6 ",");
|
|
- /* If we didn't get a ':' include one */
|
|
- if (fspec->dev[strlen(fspec->dev)-1] != ':')
|
|
+ else if (fspec->dev[strlen(fspec->dev)-1] != ':')
|
|
strcat(buffer, ":");
|
|
- strcat(buffer, fspec->siaddr);
|
|
- strcat(buffer, ",");
|
|
- if (fspec->is_ipv6 && (strstr(filename, "filename=") == NULL))
|
|
- strcat(buffer, "filename=");
|
|
- strcat(buffer, filename);
|
|
- strcat(buffer, ",");
|
|
- strcat(buffer, fspec->ciaddr);
|
|
- strcat(buffer, ",");
|
|
- strcat(buffer, fspec->giaddr);
|
|
|
|
- /* If /packages/cas exists the we have a "new skool" tftp */
|
|
- if (prom_finddevice("/packages/cas") != PROM_INVALID_HANDLE) {
|
|
+ /* If /packages/cas exists the we have a "new skool" tftp.
|
|
+ * This means that siaddr is the tftp server and that we can add
|
|
+ * {tftp,bootp}_retrys, subnet mask and tftp block size to the load
|
|
+ * method */
|
|
+ new_tftp = (prom_finddevice("/packages/cas") != PROM_INVALID_HANDLE);
|
|
+ DEBUG_F("Using %s tftp style\n", (new_tftp? "new": "old"));
|
|
+
|
|
+ if (new_tftp) {
|
|
+ strcat(buffer, fspec->siaddr);
|
|
+ strcat(buffer, ",");
|
|
+
|
|
+ if (fspec->is_ipv6 && (strstr(filename, "filename=") == NULL))
|
|
+ strcat(buffer, "filename=");
|
|
+
|
|
+ strcat(buffer, filename);
|
|
+ strcat(buffer, ",");
|
|
+ strcat(buffer, fspec->ciaddr);
|
|
strcat(buffer, ",");
|
|
+ strcat(buffer, fspec->giaddr);
|
|
+ strcat(buffer, ",");
|
|
strcat(buffer, fspec->bootp_retries);
|
|
strcat(buffer, ",");
|
|
strcat(buffer, fspec->tftp_retries);
|
|
strcat(buffer, ",");
|
|
+ strcat(buffer, fspec->subnetmask);
|
|
+ strcat(buffer, ",");
|
|
strcat(buffer, fspec->addl_params);
|
|
} else {
|
|
- DEBUG_F("No \"/packages/cas\" using simple args\n")
|
|
+ strcat(buffer, ",");
|
|
+ strcat(buffer, filename);
|
|
}
|
|
|
|
DEBUG_F("Opening: \"%s\"\n", buffer);
|
|
diff -purN yaboot-1.3.14.orig/second/prom.c yaboot-1.3.14/second/prom.c
|
|
--- yaboot-1.3.14.orig/second/prom.c 2009-10-15 15:23:39.806647224 +1100
|
|
+++ yaboot-1.3.14/second/prom.c 2009-10-15 15:29:04.696645314 +1100
|
|
@@ -685,6 +685,10 @@ struct bootp_packet * prom_get_netinfo (
|
|
void *bootp_response = NULL;
|
|
char *propname;
|
|
struct bootp_packet *packet;
|
|
+ /* struct bootp_packet contains a VLA, so sizeof won't work.
|
|
+ the VLA /must/ be the last field in the structure so use it's
|
|
+ offset as a good estimate of the packet size */
|
|
+ size_t packet_size = offsetof(struct bootp_packet, options);
|
|
int i = 0, size, offset = 0;
|
|
prom_handle chosen;
|
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
|
|
@@ -709,7 +713,7 @@ struct bootp_packet * prom_get_netinfo (
|
|
if (size <= 0)
|
|
return NULL;
|
|
|
|
- if (sizeof(*packet) > size - offset) {
|
|
+ if (packet_size > size - offset) {
|
|
prom_printf("Malformed %s property?\n", propname);
|
|
return NULL;
|
|
}
|
|
diff -purN yaboot-1.3.14.orig/second/yaboot.c yaboot-1.3.14/second/yaboot.c
|
|
--- yaboot-1.3.14.orig/second/yaboot.c 2009-10-15 15:23:39.809646432 +1100
|
|
+++ yaboot-1.3.14/second/yaboot.c 2009-10-15 15:29:04.697642396 +1100
|
|
@@ -471,6 +471,10 @@ static int load_my_config_file(struct bo
|
|
int minlen;
|
|
|
|
packet = prom_get_netinfo();
|
|
+ if (packet == NULL) {
|
|
+ prom_printf("Failed to get netinfo data\n");
|
|
+ return 0;
|
|
+ }
|
|
|
|
/*
|
|
* First, try to match on mac address with the hardware type
|