293 lines
5.9 KiB
C
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;
|
||
|
}
|
||
|
}
|