minix/commands/httpd/proxy.c
2005-09-16 13:37:29 +00:00

293 lines
5.9 KiB
C

/* proxy.c Copyright 2000 by Michael Temari All Rights Reserved */
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <net/netlib.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <net/gen/tcp.h>
#include <net/gen/tcp_io.h>
#include <net/gen/socket.h>
#include <net/gen/netdb.h>
#include "config.h"
#include "http.h"
#include "utility.h"
#include "net.h"
_PROTOTYPE(static int connect, (char *host));
#if 0
_PROTOTYPE(static int readline, (char *p, int len));
#endif
_PROTOTYPE(static int sendout, (int fd, char *data));
static int connect(host)
char *host;
{
nwio_tcpconf_t tcpconf;
nwio_tcpcl_t tcpcopt;
char *tcp_device;
int netfd;
ipaddr_t nethost;
tcpport_t netport = 0;
struct hostent *hp;
struct servent *sp;
char *p;
int s;
int tries;
p = host;
while(*p && *p != ':') p++;
if(*p == ':') {
*p++ = '\0';
netport = htons(atoi(p));
}
if((hp = gethostbyname(host)) == (struct hostent *)NULL) {
fprintf(stderr, "Unknown host %s!\n", host);
return(-1);
} else
memcpy((char *) &nethost, (char *) hp->h_addr, hp->h_length);
/* Now, to which port must we connect? */
if(netport == 0)
if((sp = getservbyname("http", "tcp")) == (struct servent *)NULL) {
fprintf(stderr, "HTTP port is unknown????\n");
return(-1);
} else
netport = sp->s_port;
/* Connect to the host */
if((tcp_device = getenv("TCP_DEVICE")) == NULL)
tcp_device = TCP_DEVICE;
if((netfd = open(tcp_device, O_RDWR)) < 0) {
perror("httpget: opening tcp");
return(-1);
}
tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
tcpconf.nwtc_remaddr = nethost;
tcpconf.nwtc_remport = netport;
s = ioctl(netfd, NWIOSTCPCONF, &tcpconf);
if(s < 0) {
perror("httpget: NWIOSTCPCONF");
close(netfd);
return(-1);
}
s = ioctl(netfd, NWIOGTCPCONF, &tcpconf);
if(s < 0) {
perror("httpget: NWIOGTCPCONF");
close(netfd);
return(-1);
}
tcpcopt.nwtcl_flags = 0;
tries = 0;
do {
s = ioctl(netfd, NWIOTCPCONN, &tcpcopt);
if(s == -1 && errno == EAGAIN) {
if(tries++ >= 10)
break;
sleep(10);
} else
break;
} while(1);
if(s < 0) {
perror("httpget: NWIOTCPCONN");
close(netfd);
return(-1);
}
return(netfd);
}
char buffer[8192];
#if 0
static int readline(p, len)
char *p;
int len;
{
int c;
int cr = 0;
int n = 0;
len--;
if(len < 0) return(-1);
while(len > 0 && (c = getchar()) != EOF) {
if(c == '\n' && cr) {
*p = '\0';
return(n);
}
if(c == '\r') {
cr = 1;
continue;
}
n++;
*p++ = c;
}
*p = '\0';
return(n);
}
#endif
static int sendout(fd, data)
int fd;
char *data;
{
if(strlen(data) > 0)
write(fd, data, strlen(data));
write(fd, "\r\n", 2);
if(dbglog != (FILE *)NULL) {
fprintf(dbglog, "REPLY: %s\n", data);
fflush(dbglog);
}
return(0);
}
void proxy(rq, rp)
struct http_request *rq;
struct http_reply *rp;
{
int s;
char *p;
char *ps;
char *b;
char *host;
static char user[256];
static char pass[256];
char *url;
char *at;
int fd;
int bad;
while(1) {
bad = 0;
p = rq->uri;
if(tolower(*p++) != 'h') bad++;
if(tolower(*p++) != 't') bad++;
if(tolower(*p++) != 't') bad++;
if(tolower(*p++) != 'p') bad++;
if(tolower(*p++) != ':') bad++;
if(tolower(*p++) != '/') bad++;
if(tolower(*p++) != '/') bad++;
if(bad) {
sprintf(buffer, "HTTP/%d.%d 400 Bad Request",
rq->vmajor, rq->vminor);
sendout(1, buffer);
sendout(1, "");
sendout(1, "Proxy Request was not http:");
return;
}
host = p;
while(*p && *p != '/') p++;
url = p;
*url = '\0';
at = strchr(host, '@');
if(at != (char *)NULL) {
*at = '\0';
p = host;
while(*p && *p != ':') p++;
if(*p)
*p++ = '\0';
strcpy(user, host);
strcpy(pass, p);
host = at + 1;
} else {
user[0] = '\0';
pass[0] = '\0';
}
fd = connect(host);
if(fd < 0) {
sprintf(buffer, "HTTP/%d.%d 400 Bad Request",
rq->vmajor, rq->vminor);
sendout(1, buffer);
sendout(1, "");
sendout(1, "Could not connect to host");
return;
}
if(rq->method == HTTP_METHOD_GET)
write(fd, "GET ", 4); else
if(rq->method == HTTP_METHOD_POST)
write(fd, "POST ", 5);
*url = '/';
if(strlen(url) > 0)
write(fd, url, strlen(url));
write(fd, " ", 1);
sprintf(buffer, "HTTP/%d.%d", rq->vmajor, rq->vminor);
sendout(fd, buffer);
if(rq->ifmodsince != -1) {
write(fd, "If-Mod-Since: ", 14);
sendout(fd, httpdate(&rq->ifmodsince));
}
if(rq->size != 0) {
sendout(fd, "Content-Type: application/x-www-form-urlencoded");
sprintf(buffer, "Content-Length: %lu", rq->size);
sendout(fd, buffer);
}
if(*rq->cookie) {
sprintf(buffer, "Cookie: %s", rq->cookie);
sendout(fd, buffer);
}
if(*rq->useragent) {
sprintf(buffer, "User-Agent: %s", rq->useragent);
sendout(fd, buffer);
}
if(*rq->host) {
sprintf(buffer, "Host: %s", rq->host);
sendout(fd, buffer);
}
if(*rq->wwwauth) {
sprintf(buffer, "Authorization: %s", rq->wwwauth);
sendout(fd, buffer);
}
sprintf(buffer, "X-Forwarded-From: %s", rmthostaddr);
sendout(fd, buffer);
sendout(fd, "");
if(rq->size != 0) {
if(stdlog != (FILE *)NULL) {
fprintf(stdlog, "%s %s %d %d ",
logdate((time_t *)NULL), rmthostname,
rq->method, rp->status);
fprintf(stdlog, "proxy %s?", rq->uri);
}
while((s = read(0, buffer, rq->size >
sizeof(buffer) ? sizeof(buffer) : rq->size)) > 0) {
write(fd, buffer, s);
rq->size -= s;
b = buffer;
if(stdlog != (FILE *)NULL)
while(s--) fputc(*b++, stdlog);
if(rq->size == 0) break;
}
if(stdlog != (FILE *)NULL) {
fprintf(stdlog, "\n");
fflush(stdlog);
}
}
while((s = read(fd, buffer, sizeof(buffer))) > 0) {
write(1, buffer, s);
}
close(fd);
return;
}
}