Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Apr 1999 21:00:45 +0200 (CEST)
From:      Philipp Mergenthaler <p@i609.hadiko.de>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   misc/11316: [PATCH] HTTP proxy support for sysinstall
Message-ID:  <199904251900.VAA03052@i609.hadiko.de>

next in thread | raw e-mail | index | archive | help

>Number:         11316
>Category:       misc
>Synopsis:       [PATCH] HTTP proxy support for sysinstall
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Apr 25 12:10:01 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Philipp Mergenthaler
>Release:        FreeBSD 4.0-CURRENT i386
>Organization:
University of Karlsruhe, Germany
>Environment:

	-current as of 1999/04/18
    in src/release/sysinstall:
     Makefile of February,  4th
     $Id: dispatch.c,v 1.27 1999/02/05 22:15:48 jkh Exp $
     $Id: media.c,v 1.97 1999/03/10 21:59:01 jkh Exp $
     $Id: menus.c,v 1.193 1999/03/19 10:54:37 jkh Exp $
     $Id: sysinstall.h,v 1.160 1999/04/06 08:25:53 jkh Exp $

>Description:

	This patch introduces a new installation medium - from an FTP
    server via a HTTP-Proxy (which I think are more common nowadays
    than native FTP proxies). It's quick'n dirty, and I tested it
    only on an already-installed sytem, not from an installation
    floppy. Consider it as a suggestion or demo. :-)

    mediaSetHTTP() is a wrapper to mediaSetFTP which lets you choose
      the FTP server and then the proxy. It should have more checks.

    mediaInitHTTP() is an ugly hack, see the comment there.
      It could perhaps be integrated in mediaSetHTTP() or
      replaced by code in dist.c .

    mediaGetHTTP() opens a connection to the proxy and sends the
      request. Then it swallows the response's headers, checks
      them cursory for errors and returns a stream associated
      with the socket.
       

>How-To-Repeat:
>Fix:
	

diff -ruN sysinstall/Makefile sysinstall2/Makefile
--- sysinstall/Makefile	Thu Feb  4 14:47:54 1999
+++ sysinstall2/Makefile	Sun Apr 25 17:32:31 1999
@@ -11,13 +11,13 @@
 
 SRCS=	anonFTP.c cdrom.c command.c config.c devices.c kget.c \
 	disks.c dispatch.c dist.c dmenu.c doc.c dos.c floppy.c \
-	ftp.c globals.c index.c install.c installUpgrade.c keymap.c \
+	ftp.c http.c globals.c index.c install.c installUpgrade.c keymap.c \
 	label.c lndir.c main.c makedevs.c media.c menus.c misc.c mouse.c \
 	msg.c network.c nfs.c options.c package.c register.c system.c \
 	tape.c tcpip.c termcap.c ufs.c user.c variable.c wizard.c \
 	keymap.h
 
-CFLAGS+= -Wall -I${.CURDIR}/../../gnu/lib/libdialog -I${.OBJDIR}
+CFLAGS+= -g -Wall -I${.CURDIR}/../../gnu/lib/libdialog -I${.OBJDIR}
 CFLAGS+= -I${.CURDIR}/../../sys
 CFLAGS+= -DUC_PRIVATE -DKERN_NO_SYMBOLS
 
diff -ruN sysinstall/dispatch.c sysinstall2/dispatch.c
--- sysinstall/dispatch.c	Fri Feb  5 23:15:48 1999
+++ sysinstall2/dispatch.c	Fri Apr 23 08:49:47 1999
@@ -98,6 +98,7 @@
     { "mediaSetFTP",		mediaSetFTP		},
     { "mediaSetFTPActive",	mediaSetFTPActive	},
     { "mediaSetFTPPassive",	mediaSetFTPPassive	},
+    { "mediaSetHTTP",		mediaSetHTTP		},
     { "mediaSetUFS",		mediaSetUFS		},
     { "mediaSetNFS",		mediaSetNFS		},
     { "mediaSetFTPUserPass",	mediaSetFTPUserPass	},
diff -ruN sysinstall/http.c sysinstall2/http.c
--- sysinstall/http.c	Thu Jan  1 01:00:00 1970
+++ sysinstall2/http.c	Sun Apr 25 19:06:27 1999
@@ -0,0 +1,183 @@
+#include "sysinstall.h"
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/param.h>
+#include <netdb.h>
+
+int HttpPort;
+
+Boolean
+mediaInitHTTP(Device *dev)
+{
+/* 
+ * Some proxies think that files with the extension ".ai" are postscript
+ * files and use "ascii mode" instead of "binary mode" for ftp.
+ * The FTP server then translates all LF to CRLF.
+ * I don't know how to handle this elegantly...
+ * Squid uses ascii mode, ftpget uses binary mode and both tell us:
+ * "Content-Type: application/postscript"
+ *
+ * Probably the safest way would be to get the file, look at its checksum
+ * and, if it doesn't match, replace all CRLF by LF and check again.
+ *
+ * You can force Squid to use binary mode by appending ";type=i" to the URL,
+ * which is what I do here.
+ *
+ */
+
+    extern int h_errno;
+    int rv,s;
+    bool el;                    /* end of header line */
+    char *cp, buf[PATH_MAX], req[1000];
+    struct sockaddr_in peer;
+    struct hostent *peer_in;
+
+    s=socket(PF_INET, SOCK_STREAM, 6);    /* tcp */
+    if (s == -1) {
+      msgConfirm("Network error");
+      return FALSE;
+    }
+
+    peer_in=gethostbyname(variable_get(VAR_HTTP_HOST));
+    if (peer_in == NULL) {
+      msgConfirm("%s",hstrerror(h_errno));
+      return FALSE;
+    }
+
+    peer.sin_len=peer_in->h_length;
+    peer.sin_family=peer_in->h_addrtype;
+    peer.sin_port=htons((u_short) HttpPort);
+    bcopy(peer_in->h_addr_list[0], &peer.sin_addr, peer_in->h_length);
+
+    rv=connect(s,(struct sockaddr *)&peer,sizeof(peer));
+    if (rv == -1) {
+      msgConfirm("Couldn't connect to proxy %s:%s",
+                  variable_get(VAR_HTTP_HOST),variable_get(VAR_FTP_PORT));
+      return FALSE;
+    }
+
+    sprintf(req,"GET / HTTP/1.0\r\n\r\n");
+    write(s,req,strlen(req));
+/*
+ *  scan the headers of the response
+ *  this is extremely quick'n dirty
+ *
+ */
+    cp=buf;
+    el=FALSE;
+    rv=read(s,cp,1);
+    variable_set2(VAR_HTTP_FTP_MODE,"",0);
+    while (rv>0) {
+      if ((*cp == '\012') && el) { 
+        /* reached end of a header line */
+        if (!strncmp(buf,"Server: ",8)) {
+          if (!strncmp(buf,"Server: Squid",13)) {
+            variable_set2(VAR_HTTP_FTP_MODE,";type=i",1);
+          } else {
+            variable_set2(VAR_HTTP_FTP_MODE,"",1);
+          }
+        }
+        /* ignore other headers */
+        /* check for "\015\012" at beginning of line, i.e. end of headers */
+        if ((cp-buf) == 1)
+          break;
+        cp=buf;
+        rv=read(s,cp,1);
+      } else {
+        el=FALSE;
+        if (*cp == '\015')
+          el=TRUE;
+        cp++;
+        rv=read(s,cp,1);
+      }
+    }
+    close(s);
+    return TRUE;
+} 
+
+
+FILE *
+mediaGetHTTP(Device *dev, char *file, Boolean probe)
+{
+    FILE *fp;
+    int rv,s;
+    bool el;			/* end of header line */
+    char *cp, buf[PATH_MAX], req[1000];
+    struct sockaddr_in peer;
+    struct hostent *peer_in;
+
+    s=socket(PF_INET, SOCK_STREAM, 6);    /* tcp */
+    if (s == -1) {
+      msgConfirm("Network error");
+      return NULL;
+    }
+      
+    peer_in=gethostbyname(variable_get(VAR_HTTP_HOST));
+    peer.sin_len=peer_in->h_length;
+    peer.sin_family=peer_in->h_addrtype;
+    peer.sin_port=htons((u_short) HttpPort);
+    bcopy(peer_in->h_addr_list[0], &peer.sin_addr, peer_in->h_length);
+
+    rv=connect(s,(struct sockaddr *)&peer,sizeof(peer));
+    if (rv == -1) {
+      msgConfirm("Couldn't connect to proxy %s:%s",
+                  variable_get(VAR_HTTP_HOST),variable_get(VAR_FTP_PORT));
+      return NULL;
+    }
+                                                   
+    sprintf(req,"GET ftp://%s:%s%s%s/%s%s HTTP/1.0\r\n\r\n",
+            variable_get(VAR_FTP_HOST), variable_get(VAR_FTP_PORT),
+            "/pub/FreeBSD/", variable_get(VAR_RELNAME),
+            file,variable_get(VAR_HTTP_FTP_MODE));
+    msgDebug("sending http request: %s",req);
+    write(s,req,strlen(req));
+
+/*
+ *  scan the headers of the response
+ *  this is extremely quick'n dirty
+ *
+ */
+    cp=buf;
+    el=FALSE;
+    rv=read(s,cp,1);
+    while (rv>0) {
+      if ((*cp == '\012') && el) {
+        /* reached end of a header line */
+        if (!strncmp(buf,"HTTP",4)) {
+          rv=strtol((char *)(buf+9),0,0);
+          *(cp-1)='\0';		/* chop the CRLF off */
+          if (rv >= 500) {
+            msgConfirm("Server error %s, you could try an other server",buf);
+            return NULL;
+          } else if (rv == 404) {
+            msgConfirm("%s was not found, maybe directory or release-version are wrong?",req);
+            return NULL;
+          } else if (rv >= 400) {
+            msgConfirm("Client error %s, you could try an other server",buf);
+            return NULL;
+          } else if (rv >= 300) {
+            msgConfirm("Error %s,",buf);
+            return NULL;
+          } else if (rv != 200) {
+            msgConfirm("Error %s when trying to fetch %s",buf,req);
+            return NULL;
+          }
+        }
+        /* ignore other headers */
+        /* check for "\015\012" at beginning of line, i.e. end of headers */
+        if ((cp-buf) == 1) 
+          break;
+        cp=buf;
+        rv=read(s,cp,1);
+      } else {
+        el=FALSE;
+        if (*cp == '\015')
+          el=TRUE;
+        cp++;
+        rv=read(s,cp,1);
+      }
+    }
+    fp=fdopen(s,"r");
+    return fp;
+}
diff -ruN sysinstall/media.c sysinstall2/media.c
--- sysinstall/media.c	Wed Mar 10 22:59:01 1999
+++ sysinstall2/media.c	Sun Apr 25 17:26:41 1999
@@ -436,6 +436,51 @@
     return mediaSetFTP(self);
 }
 
+int mediaSetHTTP(dialogMenuItem *self)
+{
+    int result;
+    char *cp, *idx, hostname[MAXHOSTNAMELEN];
+    extern int HttpPort;
+    int what = DITEM_RESTORE;
+
+
+    result = mediaSetFTP(self);
+    /* XXX - depending on the result (e.g. DITEM_FAILURE because of
+       unresolvable FTP server) we should probably repeat mediaSetFTP
+       or abort.
+    */
+    
+    variable_set2(VAR_HTTP_PATH, "", 0);
+    cp = variable_get_value(VAR_HTTP_PATH,
+            "Please enter the address of the HTTP proxy in this format:\n"
+            " hostname:port (the ':port' is optional, default is 3128)",0);
+    if (!cp)
+    return DITEM_FAILURE;
+    SAFE_STRCPY(hostname, cp);
+    if (!(idx = index(hostname, ':')))
+      HttpPort=3128;		/* try this as default */
+    else {
+      *(idx++) = '\0';
+      HttpPort = strtol(idx, 0, 0);
+    }
+
+    variable_set2(VAR_HTTP_HOST, hostname, 0);
+    variable_set2(VAR_HTTP_PORT, itoa(HttpPort), 0);
+    msgDebug("VAR_HTTP_HOST, _PORT: %s:%s",variable_get(VAR_HTTP_HOST),
+                                           variable_get(VAR_HTTP_PORT));
+
+    msgDebug("VAR_FTP_HOST, _PORT: %s:%s",variable_get(VAR_FTP_HOST),
+                                          variable_get(VAR_FTP_PORT));
+
+    /* mediaDevice has been set by mediaSetFTP(), overwrite partly: */
+    mediaDevice->type = DEVICE_TYPE_HTTP;
+    mediaDevice->init = mediaInitHTTP;
+    mediaDevice->get = mediaGetHTTP;
+    mediaDevice->shutdown = dummyShutdown;
+    return DITEM_SUCCESS | DITEM_LEAVE_MENU | what;
+}
+   
+
 int
 mediaSetUFS(dialogMenuItem *self)
 {
diff -ruN sysinstall/menus.c sysinstall2/menus.c
--- sysinstall/menus.c	Fri Mar 19 11:54:37 1999
+++ sysinstall2/menus.c	Fri Apr 23 23:28:25 1999
@@ -272,6 +272,7 @@
       { "Media, UFS",		"Select UFS installation media.",	NULL, mediaSetUFS },
       { "Media, FTP",		"Select FTP installation media.",	NULL, mediaSetFTP },
       { "Media, FTP Passive",	"Select passive FTP installation media.", NULL, mediaSetFTPPassive },
+      { "Media, HTTP",		"Select FTP via HTTP proxy installation media.", NULL, mediaSetHTTP },
       { "Network Interfaces",	"Configure network interfaces",		NULL, tcpMenuSelect },
       { "Networking Services",	"The network services menu.",		NULL, dmenuSubmenu, NULL, &MenuNetworking },
       { "NFS, client",		"Set NFS client flag.",			dmenuVarCheck, dmenuToggleVariable, NULL, "nfs_client_enable=YES" },
@@ -699,6 +700,7 @@
     { { "1 CDROM",		"Install from a FreeBSD CDROM",		NULL, mediaSetCDROM },
       { "2 FTP",		"Install from an FTP server",		NULL, mediaSetFTPActive },
       { "3 FTP Passive",	"Install from an FTP server through a firewall", NULL, mediaSetFTPPassive },
+      { "3b HTTP",		"Install from an FTP server through a http proxy", NULL, mediaSetHTTP },
       { "4 DOS",		"Install from a DOS partition",		NULL, mediaSetDOS },
       { "5 NFS",		"Install over NFS",			NULL, mediaSetNFS },
       { "6 File System",	"Install from an existing filesystem",	NULL, mediaSetUFS },
diff -ruN sysinstall/sysinstall.h sysinstall2/sysinstall.h
--- sysinstall/sysinstall.h	Tue Apr  6 10:25:53 1999
+++ sysinstall2/sysinstall.h	Sun Apr 25 17:29:18 1999
@@ -109,6 +109,10 @@
 #define VAR_FTP_STATE			"ftpState"
 #define VAR_FTP_USER			"ftpUser"
 #define VAR_FTP_HOST			"ftpHost"
+#define VAR_HTTP_PATH			"_httpPath"
+#define VAR_HTTP_PORT			"httpPort"
+#define VAR_HTTP_HOST			"httpHost"
+#define VAR_HTTP_FTP_MODE		"httpFtpMode"
 #define VAR_GATED_PKG			"gated_pkg"
 #define VAR_GATEWAY			"defaultrouter"
 #define VAR_GEOMETRY			"geometry"
@@ -230,6 +234,7 @@
     DEVICE_TYPE_UFS,
     DEVICE_TYPE_NFS,
     DEVICE_TYPE_ANY,
+    DEVICE_TYPE_HTTP,
 } DeviceType;
 
 /* CDROM mount codes */
@@ -516,6 +521,10 @@
 extern FILE	*mediaGetFTP(Device *dev, char *file, Boolean probe);
 extern void	mediaShutdownFTP(Device *dev);
 
+/* http.c */
+extern Boolean	mediaInitHTTP(Device *dev);
+extern FILE	*mediaGetHTTP(Device *dev, char *file, Boolean probe);
+
 /* globals.c */
 extern void	globalsInit(void);
 
@@ -584,6 +593,7 @@
 extern int	mediaSetFTP(dialogMenuItem *self);
 extern int	mediaSetFTPActive(dialogMenuItem *self);
 extern int	mediaSetFTPPassive(dialogMenuItem *self);
+extern int	mediaSetHTTP(dialogMenuItem *self);
 extern int	mediaSetUFS(dialogMenuItem *self);
 extern int	mediaSetNFS(dialogMenuItem *self);
 extern int	mediaSetFTPUserPass(dialogMenuItem *self);

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199904251900.VAA03052>