pxe: centralize all the IP information and export it to modules
authorH. Peter Anvin <hpa@linux.intel.com>
Sat, 19 Jun 2010 01:16:48 +0000 (18:16 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Sat, 19 Jun 2010 01:19:37 +0000 (18:19 -0700)
It appears that there still are PXE stacks in the field which needs
the crutch of being pointed to the default gateway.  As such, put all
the IP information into a single memory structure and allow modules to
see it.

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
com32/include/syslinux/config.h
core/comboot.inc
core/fs/pxe/dhcp_option.c
core/fs/pxe/dnsresolv.c
core/fs/pxe/idle.c
core/fs/pxe/pxe.c
core/fs/pxe/pxe.h
core/pxelinux.asm
doc/comboot.txt

index 868b0f1..60d8d23 100644 (file)
@@ -54,6 +54,14 @@ struct syslinux_version {
     const char *copyright_string;
 };
 
+struct syslinux_ipinfo {
+    uint32_t ipver;
+    uint32_t myip;
+    uint32_t netmask;
+    uint32_t gateway;
+    uint32_t serverip;
+};
+
 extern __nocommon struct syslinux_version __syslinux_version;
 static inline const struct syslinux_version *syslinux_version(void)
 {
@@ -116,6 +124,7 @@ union syslinux_derivative_info {
        uint32_t _eflags;
        const void *pxenvptr;
        const void *stack;
+       const struct syslinux_ipinfo *ipinfo;
     } pxe;                     /* pxelinux */
     struct {
        uint16_t _gs, _fs, _es, _ds;
index 45b770f..0c9956a 100644 (file)
@@ -580,8 +580,10 @@ comapi_derinfo:
                mov P_SI,ax
                mov ax,[InitStack+2]
                mov P_FS,ax
-               mov eax,[MyIP]
+               mov eax,[IPInfo.MyIP]
                mov P_ECX,eax
+               mov P_GS,0
+               mov P_DI,IPInfo
 %else
                ; Physical medium...
 
index e18b605..39b5166 100644 (file)
@@ -16,14 +16,14 @@ static void subnet_mask(void *data, int opt_len)
 {
     if (opt_len != 4)
        return;
-    net_mask = *(uint32_t *)data;
+    IPInfo.netmask = *(uint32_t *)data;
 }
 
 static void router(void *data, int opt_len)
 {
     if (opt_len != 4)
        return;
-    gate_way = *(uint32_t *)data;
+    IPInfo.gateway = *(uint32_t *)data;
 }
 
 static void dns_servers(void *data, int opt_len)
@@ -83,12 +83,12 @@ static void server(void *data, int opt_len)
     if (opt_len != 4)
        return;
     
-    if (server_ip)
+    if (IPInfo.serverip)
         return;
     
     ip = *(uint32_t *)data;
     if (ip_ok(ip))
-        server_ip = ip;
+        IPInfo.serverip = ip;
 }
 
 static void client_identifier(void *data, int opt_len)
@@ -246,10 +246,10 @@ void parse_dhcp(int pkt_len)
 
     over_load = 0;
     if (ip_ok(dhcp->yip))
-        MyIP = dhcp->yip;
+        IPInfo.myip = dhcp->yip;
     
     if (ip_ok(dhcp->sip))
-        server_ip = dhcp->sip;
+        IPInfo.serverip = dhcp->sip;
     
     opt_len = (char *)dhcp + pkt_len - (char *)&dhcp->options;
     if (opt_len && (dhcp->option_magic == BOOTP_OPTION_MAGIC)) 
index df7f33c..ecee785 100644 (file)
@@ -229,7 +229,7 @@ uint32_t dns_resolv(const char *name)
            continue;  /* just move on before runing the time out */
         udp_write.status      = 0;
         udp_write.ip          = srv;
-        udp_write.gw          = ((srv ^ MyIP) & net_mask) ? gate_way : 0;
+        udp_write.gw          = gateway(srv);
         udp_write.src_port    = local_port;
         udp_write.dst_port    = DNS_PORT;
         udp_write.buffer_size = p - DNSSendBuf;
@@ -242,7 +242,7 @@ uint32_t dns_resolv(const char *name)
        while (1) {
             udp_read.status      = 0;
             udp_read.src_ip      = srv;
-            udp_read.dest_ip     = MyIP;
+            udp_read.dest_ip     = IPInfo.myip;
             udp_read.s_port      = DNS_PORT;
             udp_read.d_port      = local_port;
             udp_read.buffer_size = DNS_MAX_PACKET;
@@ -349,4 +349,5 @@ void pxe_dns_resolv(com32sys_t *regs)
     const char *name = MK_PTR(regs->ds, regs->esi.w[0]);
 
     regs->eax.l = dns_resolv(name);
+    printf("dnsresolv returns %08x\n", regs->eax.l);
 }
index 0538b16..52a87c3 100644 (file)
@@ -27,7 +27,7 @@ static int pxe_idle_poll(void)
     memset(&read_buf, 0, sizeof read_buf);
 
     read_buf.src_ip  = 0;       /* Any destination */
-    read_buf.dest_ip = MyIP;
+    read_buf.dest_ip = IPInfo.myip;
     read_buf.s_port  = 0;       /* Any source port */
     read_buf.d_port  = htons(9); /* Discard port (not used...) */
     read_buf.buffer_size = sizeof junk_pkt;
index 011ef29..ef2398b 100644 (file)
@@ -9,10 +9,7 @@
 
 #define GPXE 1
 
-uint32_t server_ip = 0;            /* IP address of boot server */
-uint32_t net_mask = 0;             /* net_mask of this subnet */
-uint32_t gate_way = 0;             /* Default router */
-uint16_t real_base_mem;            /* Amount of DOS memory after freeing */
+static uint16_t real_base_mem;    /* Amount of DOS memory after freeing */
 
 uint8_t MAC[MAC_MAX];             /* Actual MAC address */
 uint8_t MAC_len;                   /* MAC address len */
@@ -297,7 +294,7 @@ static void tftp_error(struct inode *inode, uint16_t errnum,
     udp_write.src_port    = socket->tftp_localport;
     udp_write.dst_port    = socket->tftp_remoteport;
     udp_write.ip          = socket->tftp_remoteip;
-    udp_write.gw          = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw          = gateway(udp_write.ip);
     udp_write.buffer      = FAR_PTR(&err_buf);
     udp_write.buffer_size = 4 + len + 1;
 
@@ -326,7 +323,7 @@ static void ack_packet(struct inode *inode, uint16_t ack_num)
     udp_write.src_port    = socket->tftp_localport;
     udp_write.dst_port    = socket->tftp_remoteport;
     udp_write.ip          = socket->tftp_remoteip;
-    udp_write.gw          = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw          = gateway(udp_write.ip);
     udp_write.buffer      = FAR_PTR(ack_packet_buf);
     udp_write.buffer_size = 4;
 
@@ -513,7 +510,7 @@ static void fill_buffer(struct inode *inode)
         udp_read.buffer      = FAR_PTR(packet_buf);
         udp_read.buffer_size = PKTBUF_SIZE;
         udp_read.src_ip      = socket->tftp_remoteip;
-        udp_read.dest_ip     = MyIP;
+        udp_read.dest_ip     = IPInfo.myip;
         udp_read.s_port      = socket->tftp_remoteport;
         udp_read.d_port      = socket->tftp_localport;
         err = pxe_call(PXENV_UDP_READ, &udp_read);
@@ -688,12 +685,12 @@ static void pxe_searchdir(const char *filename, struct file *file)
     case PXE_RELATIVE:         /* Really shouldn't happen... */
     case PXE_URL:
        buf = stpcpy(buf, filename);
-       ip = server_ip;         /* Default server */
+       ip = IPInfo.serverip;   /* Default server */
        break;
 
     case PXE_HOMESERVER:
        buf = stpcpy(buf, filename+2);
-       ip = server_ip;
+       ip = IPInfo.serverip;
        break;
 
     case PXE_TFTP:
@@ -781,7 +778,7 @@ sendreq:
     tid = socket->tftp_localport;   /* TID(local port No) */
     udp_write.buffer    = FAR_PTR(rrq_packet_buf);
     udp_write.ip        = ip;
-    udp_write.gw        = ((udp_write.ip ^ MyIP) & net_mask) ? gate_way : 0;
+    udp_write.gw        = gateway(udp_write.ip);
     udp_write.src_port  = tid;
     udp_write.dst_port  = server_port;
     udp_write.buffer_size = buf - rrq_packet_buf;
@@ -794,7 +791,7 @@ wait_pkt:
         buf                  = packet_buf;
         udp_read.buffer      = FAR_PTR(buf);
         udp_read.buffer_size = PKTBUF_SIZE;
-        udp_read.dest_ip     = MyIP;
+        udp_read.dest_ip     = IPInfo.myip;
         udp_read.d_port      = tid;
         err = pxe_call(PXENV_UDP_READ, &udp_read);
         if (err) {
@@ -1107,7 +1104,7 @@ static int pxe_load_config(void)
         return 0;
 
     /* Nope, try hexadecimal IP prefixes... */
-    uchexbytes(config_file, (uint8_t *)&MyIP, 4);     /* Convet to hex string */
+    uchexbytes(config_file, (uint8_t *)&IPInfo.myip, 4);     /* Convet to hex string */
     last = &config_file[8];
     while (tries) {
         *last = '\0';        /* Zero-terminate string */
@@ -1151,26 +1148,23 @@ char __bss16 IPOption[3+4*16];
 static void genipopt(void)
 {
     char *p = IPOption;
+    const uint32_t *v = &IPInfo.myip;
+    int i;
 
     p = stpcpy(p, "ip=");
 
-    p += gendotquad(p, MyIP);
-    *p++ = ':';
-
-    p += gendotquad(p, server_ip);
-    *p++ = ':';
-
-    p += gendotquad(p, gate_way);
-    *p++ = ':';
-
-    gendotquad(p, net_mask);
+    for (i = 0; i < 4; i++) {
+       p += gendotquad(p, *v++);
+       *p++ = ':';
+    }
+    *--p = '\0';
 }
 
 
 /* Generate ip= option and print the ip adress */
 static void ip_init(void)
 {
-    uint32_t ip = MyIP;
+    uint32_t ip = IPInfo.myip;
 
     genipopt();
     gendotquad(dot_quad_buf, ip);
@@ -1412,7 +1406,7 @@ static void udp_init(void)
 {
     int err;
     static __lowmem struct s_PXENV_UDP_OPEN udp_open;
-    udp_open.src_ip = MyIP;
+    udp_open.src_ip = IPInfo.myip;
     err = pxe_call(PXENV_UDP_OPEN, &udp_open);
     if (err || udp_open.status) {
         printf("Failed to initialize UDP stack ");
index e801aea..cad6350 100644 (file)
@@ -170,13 +170,20 @@ struct pxe_pvt_inode {
 #define PVT(i) ((struct pxe_pvt_inode *)((i)->pvt))
 
 /*
+ * Network boot information
+ */
+struct ip_info {
+    uint32_t ipv4;
+    uint32_t myip;
+    uint32_t serverip;
+    uint32_t gateway;
+    uint32_t netmask;
+};
+
+/*
  * Variable externs
  */
-extern uint32_t server_ip;
-extern uint32_t MyIP;
-extern uint32_t net_mask;
-extern uint32_t gate_way;
-extern uint16_t server_port;
+extern struct ip_info IPInfo;
 
 extern uint8_t MAC[];
 extern char BOOTIFStr[];
@@ -195,7 +202,6 @@ extern char dot_quad_buf[];
 
 extern uint32_t dns_server[];
 
-extern uint16_t real_base_mem;
 extern uint16_t APIVer;
 extern far_ptr_t PXEEntry;
 extern uint8_t KeepPXE;
@@ -209,6 +215,17 @@ extern char uuid[];
 extern uint16_t BIOS_fbm;
 extern const uint8_t TimeoutTable[];
 
+/*
+ * Compute the suitable gateway for a specific route -- too many
+ * vendor PXE stacks don't do this correctly...
+ */
+static inline uint32_t gateway(uint32_t ip)
+{
+    if ((ip ^ IPInfo.myip) & IPInfo.netmask)
+       return IPInfo.gateway;
+    else
+       return 0;
+}
 
 /*
  * functions 
index 0b87e73..6fb77c2 100644 (file)
@@ -530,7 +530,15 @@ exten_table_end:
 KeepPXE                db 0                    ; Should PXE be kept around?
 
 ;
-; IP information (initialized to "unknown" values)
+; IP information.  Note that the field are in the same order as the
+; Linux kernel expects in the ip= option.
+;
+               section .bss16
                alignz 4
-                global MyIP
-MyIP           dd 0                    ; My IP address 
+               global IPInfo
+IPInfo:
+.IPv4          resd 1                  ; IPv4 information
+.MyIP          resd 1                  ; My IP address 
+.ServerIP      resd 1
+.GatewayIP     resd 1
+.Netmask       resd 1
index f39d724..036bd78 100644 (file)
@@ -448,6 +448,7 @@ AX=000Ah [2.00]     Get Derivative-Specific Information
                ECX     Local IP number (network byte order) [3.85]
                ES:BX   pointer to PXENV+ or !PXE structure
                FS:SI   pointer to original stack with invocation record
+               GS:DI   pointer to network information [4.00]
 
                Note: DX notes the API version detected by PXELINUX,
                which may be more conservative than the actual version
@@ -481,6 +482,13 @@ AX=000Ah [2.00]    Get Derivative-Specific Information
                [fs:si+44]      PXE return IP   <- t.o.s. when PXELINUX invoked
                [fs:si+46]      PXE return CS
 
+               GS:DI points to a structure of the following form:
+
+               [gs:di+0]       4               - IPv4
+               [gs:di+4]       My IP
+               [gs:di+8]       Boot server IP
+               [gs:di+12]      Gateway IP
+               [gs:di+16]      Netmask
 
        [ISOLINUX]
        Input:  AX      000Ah