pxe: move redirect processing to the URL-parsing level
authorH. Peter Anvin <hpa@zytor.com>
Sun, 24 Apr 2011 20:59:18 +0000 (13:59 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Sun, 24 Apr 2011 20:59:18 +0000 (13:59 -0700)
Move redirect processing out of the HTTP code and into the top
URL-processing level.  This both makes the code simpler and also deals
with absurdities like HTTP redirecting to an FTP URL (which is legal.)

Signed-off-by: H. Peter Anvin <hpa@zytor.com>
core/fs/pxe/ftp.c
core/fs/pxe/http.c
core/fs/pxe/pxe.c
core/fs/pxe/pxe.h
core/fs/pxe/tftp.c

index 0c03355..ca4b3d6 100644 (file)
@@ -169,7 +169,7 @@ static void ftp_close_file(struct inode *inode)
     ftp_free(inode);
 }
 
-void ftp_open(struct url_info *url, struct inode *inode)
+void ftp_open(struct url_info *url, struct inode *inode, const char **redir)
 {
     struct pxe_pvt_inode *socket = PVT(inode);
     struct pxe_pvt_inode *ctlsock;
@@ -179,6 +179,7 @@ void ftp_open(struct url_info *url, struct inode *inode)
     int resp;
     err_t err;
 
+    (void)redir;               /* FTP does not redirect */
     inode->size = 0;
 
     if (!url->port)
index 8d19755..f46cd4c 100644 (file)
@@ -45,7 +45,7 @@ static bool append_ch(char *str, size_t size, size_t *pos, int ch)
     return success;
 }
 
-void http_open(struct url_info *url, struct inode *inode)
+void http_open(struct url_info *url, struct inode *inode, const char **redir)
 {
     struct pxe_pvt_inode *socket = PVT(inode);
     char header_buf[4096];
@@ -67,18 +67,15 @@ void http_open(struct url_info *url, struct inode *inode)
        st_eoh,
     } state;
     struct ip_addr addr;
-    char location[1024], new_url[1024];
+    static char location[FILENAME_MAX];
     uint32_t content_length; /* same as inode->size */
     size_t response_size;
     int status;
     int pos;
-    int redirect_count;
 
     socket->fill_buffer = tcp_fill_buffer;
     socket->close = tcp_close_file;
-    redirect_count = 0;
 
-restart:
     /* Reset all of the variables */
     inode->size = content_length = -1;
 
@@ -193,7 +190,7 @@ restart:
                    /* Skip leading whitespace */
                    while (isspace(*next))
                        next++;
-                   strcpy(location, next);
+                   strlcpy(location, next, sizeof location);
                }
                /* Start the field name and field value afress */
                field_name_len = 1;
@@ -275,16 +272,8 @@ restart:
        /* A redirect */
        if (!location[0])
            goto fail;
-       redirect_count++;
-       if (redirect_count > 5)
-           goto fail;
-       strlcpy(new_url, location, sizeof new_url);
-       parse_url(url, new_url);
-       url_set_ip(url);
-       tcp_close_file(inode);
-       /* XXX: This needs to go all the way back to scheme selection */
-       goto restart;
-       break;
+       *redir = location;
+       goto fail;
     default:
        goto fail;
        break;
index 71532d6..0f76804 100644 (file)
@@ -37,7 +37,7 @@ __lowmem char packet_buf[PKTBUF_SIZE] __aligned(16);
 
 static struct url_scheme {
     const char *name;
-    void (*open)(struct url_info *url, struct inode *inode);
+    void (*open)(struct url_info *url, struct inode *inode, const char **redir);
 } url_schemes[] = {
     { "tftp", tftp_open },
     { "http", http_open },
@@ -382,27 +382,36 @@ static void __pxe_searchdir(const char *filename, struct file *file)
     char fullpath[2*FILENAME_MAX];
     struct url_info url;
     const struct url_scheme *us;
+    int redirect_count = 0;
 
     inode = file->inode = NULL;
 
-    strlcpy(fullpath, filename, sizeof fullpath);
-    parse_url(&url, fullpath);
-    if (url.type == URL_SUFFIX) {
-       snprintf(fullpath, sizeof fullpath, "%s%s", fs->cwd_name, filename);
-       parse_url(&url, fullpath);
-    }
-
-    inode = allocate_socket(fs);
-    if (!inode)
-       return;                 /* Allocation failure */
+    while (filename) {
+       if (redirect_count++ > 5)
+           break;
 
-    url_set_ip(&url);
+       strlcpy(fullpath, filename, sizeof fullpath);
+       parse_url(&url, fullpath);
+       if (url.type == URL_SUFFIX) {
+           snprintf(fullpath, sizeof fullpath, "%s%s", fs->cwd_name, filename);
+           parse_url(&url, fullpath);
+       }
 
-    for (us = url_schemes; us->name; us++) {
-       if (!strcmp(us->name, url.scheme)) {
-           us->open(&url, inode);
-           break;
+       inode = allocate_socket(fs);
+       if (!inode)
+           return;                     /* Allocation failure */
+       
+       url_set_ip(&url);
+       
+       filename = NULL;
+       for (us = url_schemes; us->name; us++) {
+           if (!strcmp(us->name, url.scheme)) {
+               us->open(&url, inode, &filename);
+               break;
+           }
        }
+
+       /* filename here is set on a redirect */
     }
 
     if (inode->size)
index 699cf65..b23f7a7 100644 (file)
@@ -245,17 +245,17 @@ uint16_t get_port(void);
 void free_port(uint16_t port);
 
 /* tftp.c */
-void tftp_open(struct url_info *url, struct inode *inode);
+void tftp_open(struct url_info *url, struct inode *inode, const char **redir);
 
 /* gpxeurl.c */
 void gpxe_open(struct inode *inode, const char *url);
 #define GPXE 1
 
 /* http.c */
-void http_open(struct url_info *url, struct inode *inode);
+void http_open(struct url_info *url, struct inode *inode, const char **redir);
 
 /* ftp.c */
-void ftp_open(struct url_info *url, struct inode *inode);
+void ftp_open(struct url_info *url, struct inode *inode, const char **redir);
 
 /* tcp.c */
 void tcp_close_file(struct inode *inode);
index 89b21ae..637f0e9 100644 (file)
@@ -210,7 +210,7 @@ static void tftp_get_packet(struct inode *inode)
  * @out: the lenght of this file, stores in file->file_len
  *
  */
-void tftp_open(struct url_info *url, struct inode *inode)
+void tftp_open(struct url_info *url, struct inode *inode, const char **redir)
 {
     struct pxe_pvt_inode *socket = PVT(inode);
     char *buf;
@@ -234,6 +234,8 @@ void tftp_open(struct url_info *url, struct inode *inode)
     uint32_t opdata, *opdata_ptr;
     struct ip_addr addr;
 
+    (void)redir;               /* TFTP does not redirect */
+
     if (url->type != URL_OLD_TFTP) {
        /*
         * The TFTP URL specification allows the TFTP to end with a