pxechn.c32: add -S to transform sname to siaddr
authorGene Cumm <gene.cumm@gmail.com>
Sat, 2 Jun 2012 01:40:46 +0000 (21:40 -0400)
committerGene Cumm <gene.cumm@gmail.com>
Sat, 2 Jun 2012 01:40:46 +0000 (21:40 -0400)
Signed-off-by: Gene Cumm <gene.cumm@gmail.com>
com32/modules/pxechn.c

index 301f311..2637690 100644 (file)
@@ -117,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];
@@ -463,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++){
@@ -741,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)
@@ -775,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) {
@@ -819,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 */
@@ -836,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);