Enhance the parseing of IPv4 information.
authorTony Breeds <tony@bakeyournoodle.com>
Thu, 5 Mar 2009 04:04:47 +0000 (15:04 +1100)
committerTony Breeds <tony@bakeyournoodle.com>
Thu, 9 Apr 2009 23:03:12 +0000 (09:03 +1000)
Pull information out of the bootp-reply (or similar) property.  This
successfully netboots in a wider variety of OF "boot" lines.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
second/file.c
second/fs_of.c
second/yaboot.c

index 875cad807063efaac91c729648786a470d4e938c..5d5ccbdf10bd2df10b687fb2d5ae867025a74772 100644 (file)
 
 extern char bootdevice[];
 
 
 extern char bootdevice[];
 
+/* Convert __u32 into std, dotted quad string, leaks like a sive :( */
+static char *
+ipv4_to_str(__u32 ip)
+{
+     char *buf = malloc(sizeof("000.000.000.000"));
+
+     sprintf(buf,"%u.%u.%u.%u",
+             (ip & 0xff000000) >> 24, (ip & 0x00ff0000) >> 16,
+             (ip & 0x0000ff00) >>  8, (ip & 0x000000ff));
+
+     return buf;
+}
+
 /*
  * Copy the string from source to dest till newline or comma(,) is seen
  * in the source.
 /*
  * Copy the string from source to dest till newline or comma(,) is seen
  * in the source.
@@ -131,12 +144,60 @@ extract_ipv4_args(char *imagepath, struct boot_fspec_t *result)
      return 1;
 }
 
      return 1;
 }
 
+/*
+ * Check netinfo for ipv4 parameters and add them to the fspec iff the
+ * fspec has no existing value.
+ *
+ * Returns 1 on success, 0 on failure.
+ */
+static int
+extract_netinfo_args(struct boot_fspec_t *result)
+{
+     struct bootp_packet *packet;
+
+     /* Check to see if we can get the [scyg]iaddr fields from netinfo */
+     packet = prom_get_netinfo();
+     if (!packet)
+          return 0;
+
+     DEBUG_F("We have a boot packet\n");
+     DEBUG_F(" siaddr = <%x>\n", packet->siaddr);
+     DEBUG_F(" ciaddr = <%x>\n", packet->ciaddr);
+     DEBUG_F(" yiaddr = <%x>\n", packet->yiaddr);
+     DEBUG_F(" giaddr = <%x>\n", packet->giaddr);
+
+     /* Try to fallback to yiaddr if ciaddr is empty. Broken? */
+     if (packet->ciaddr == 0 && packet->yiaddr != 0)
+          packet->ciaddr = packet->yiaddr;
+
+     if ((result->siaddr == NULL || *(result->siaddr) == NULL)
+         && packet->siaddr != 0)
+          result->siaddr = ipv4_to_str(packet->siaddr);
+     if ((result->ciaddr == NULL || *(result->ciaddr) == NULL)
+         && packet->ciaddr != 0)
+          result->ciaddr = ipv4_to_str(packet->ciaddr);
+     if ((result->giaddr == NULL || *(result->giaddr) == NULL)
+         && packet->giaddr != 0)
+          result->giaddr = ipv4_to_str(packet->giaddr);
+
+     /* 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
+      *        redirections */
+     if (result->giaddr == NULL) {
+          result->giaddr = ipv4_to_str(packet->siaddr);
+          DEBUG_F("Forcing giaddr to siaddr <%s>\n", result->giaddr);
+     }
+
+     return 1;
+}
+
 /*
  * Extract all the arguments provided in the imagepath and fill it in result.
  * Returns 1 on success, 0 on failure.
  */
 static int
 /*
  * Extract all the arguments provided in the imagepath and fill it in result.
  * Returns 1 on success, 0 on failure.
  */
 static int
-extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result)
+extract_netboot_args(char *imagepath, struct boot_fspec_t *result)
 {
      int ret;
 
 {
      int ret;
 
@@ -146,6 +207,7 @@ extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result)
          return 1;
 
      ret = extract_ipv4_args(imagepath, result);
          return 1;
 
      ret = extract_ipv4_args(imagepath, result);
+     ret |= extract_netinfo_args(result);
 
      DEBUG_F("siaddr = <%s>\n", result->siaddr);
      DEBUG_F("file = <%s>\n", result->file);
 
      DEBUG_F("siaddr = <%s>\n", result->siaddr);
      DEBUG_F("file = <%s>\n", result->file);
@@ -154,6 +216,7 @@ extract_args_from_netdev_path(char *imagepath, struct boot_fspec_t *result)
      DEBUG_F("bootp_retries = <%s>\n", result->bootp_retries);
      DEBUG_F("tftp_retries = <%s>\n", result->tftp_retries);
      DEBUG_F("addl_params = <%s>\n", result->addl_params);
      DEBUG_F("bootp_retries = <%s>\n", result->bootp_retries);
      DEBUG_F("tftp_retries = <%s>\n", result->tftp_retries);
      DEBUG_F("addl_params = <%s>\n", result->addl_params);
+   
      return ret;
 }
 
      return ret;
 }
 
@@ -293,10 +356,13 @@ parse_device_path(char *imagepath, char *defdevice, int defpart,
 
      if (device_kind == FILE_DEVICE_NET) {
          if (strchr(ipath, ':')) {
 
      if (device_kind == FILE_DEVICE_NET) {
          if (strchr(ipath, ':')) {
-              if (extract_args_from_netdev_path(ipath, result) == 0)
+              if (extract_netboot_args(ipath, result) == 0)
                   return 0;
                   return 0;
-         } else
+         } else {
+               /* If we didn't get a ':' then look only in netinfo */
+              extract_netinfo_args(result);
               result->file = strdup(ipath);
               result->file = strdup(ipath);
+          }
 
          if (!defdev)
               result->dev = netdev_path_to_dev(ipath);
 
          if (!defdev)
               result->dev = netdev_path_to_dev(ipath);
index ecc0366dae5c62ccf017ceac2f9e1aab69d40819..5c7dd9bee949d81b269bc761bfd00c4f539eaf2d 100644 (file)
@@ -151,6 +151,9 @@ of_net_open(struct boot_file_t* file,
      DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>;\n",
                fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr);
      strncpy(buffer, fspec->dev, 768);
      DEBUG_F("siaddr <%s>; filename <%s>; ciaddr <%s>; giaddr <%s>;\n",
                fspec->siaddr, filename, fspec->ciaddr, fspec->giaddr);
      strncpy(buffer, fspec->dev, 768);
+     /* If we didn't get a ':' include one */
+     if (fspec->dev[strlen(fspec->dev)-1] != ':')
+          strcat(buffer, ":");
      strcat(buffer, fspec->siaddr);
      strcat(buffer, ",");
      strcat(buffer, filename);
      strcat(buffer, fspec->siaddr);
      strcat(buffer, ",");
      strcat(buffer, filename);
@@ -158,12 +161,18 @@ of_net_open(struct boot_file_t* file,
      strcat(buffer, fspec->ciaddr);
      strcat(buffer, ",");
      strcat(buffer, fspec->giaddr);
      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->addl_params);
+
+     /* If /packages/cas exists the we have a "new skool" tftp */
+     if (prom_finddevice("/packages/cas") != PROM_INVALID_HANDLE) {
+          strcat(buffer, ",");
+          strcat(buffer, fspec->bootp_retries);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->tftp_retries);
+          strcat(buffer, ",");
+          strcat(buffer, fspec->addl_params);
+     } else {
+          DEBUG_F("No \"/packages/cas\" using simple args\n")
+     }
 
      DEBUG_F("Opening: \"%s\"\n", buffer);
 
 
      DEBUG_F("Opening: \"%s\"\n", buffer);
 
index 8a74d7a5de89c1749738dbe775356655968362b0..66f288b82aea9eaff21c59ed1fd3bf52c26224b5 100644 (file)
@@ -471,6 +471,8 @@ static int load_my_config_file(struct boot_fspec_t *orig_fspec)
      int minlen;
 
      packet = prom_get_netinfo();
      int minlen;
 
      packet = prom_get_netinfo();
+     if (!packet)
+          goto out;
 
      /*
       * First, try to match on mac address with the hardware type
 
      /*
       * First, try to match on mac address with the hardware type