You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
4.3 KiB
C
178 lines
4.3 KiB
C
#include "socket.h"
|
|
#include "io.h"
|
|
#include "buffer.h"
|
|
#include "ip6.h"
|
|
#include "str.h"
|
|
#include "dns.h"
|
|
#include <errno.h>
|
|
#include <getopt.h>
|
|
#include "scan.h"
|
|
#include <stdlib.h>
|
|
|
|
struct state {
|
|
int64 a,b;
|
|
char buf[1024];
|
|
int connected;
|
|
int done,todo;
|
|
enum { UNDECIDED, FORA, FORB } dir;
|
|
};
|
|
|
|
int main(int argc,char* argv[]) {
|
|
int s=socket_tcp6();
|
|
uint32 scope_id;
|
|
char ip[16];
|
|
uint16 port;
|
|
char hisip[16];
|
|
uint16 hisport;
|
|
uint32 hisscope_id;
|
|
static char seed[128];
|
|
static stralloc fqdn;
|
|
static stralloc out;
|
|
|
|
if (argc!=4) {
|
|
usage:
|
|
buffer_putsflush(buffer_2,"usage: proxy myip myport hisip hisport\n"
|
|
"\n"
|
|
"e.g.: proxy 0 119 news.fu-berlin.de 119\n");
|
|
return 0;
|
|
}
|
|
|
|
if (argv[1][scan_ip6if(argv[1],ip,&scope_id)]) {
|
|
if (str_equal(argv[1],"0")) {
|
|
byte_zero(ip,16);
|
|
scope_id=0;
|
|
} else
|
|
goto usage;
|
|
}
|
|
if (argv[2][scan_ushort(argv[2],&port)]) goto usage;
|
|
if (argv[3][scan_ip6if(argv[3],hisip,&hisscope_id)]) {
|
|
dns_random_init(seed);
|
|
if (!stralloc_copys(&fqdn,argv[3])) goto nomem;
|
|
if (dns_ip4(&out,&fqdn) == -1) {
|
|
buffer_puts(buffer_2,"unable to find IP address for ");
|
|
buffer_puts(buffer_2,argv[3]);
|
|
buffer_puts(buffer_2,": ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
return 111;
|
|
}
|
|
} else
|
|
if (!stralloc_catb(&out,hisip,16)) {
|
|
nomem:
|
|
buffer_putsflush(buffer_2,"out of memory\n");
|
|
return 111;
|
|
}
|
|
if (argv[4][scan_ushort(argv[4],&hisport)]) goto usage;
|
|
|
|
if (socket_bind6_reuse(s,ip,port,scope_id)==-1) {
|
|
buffer_puts(buffer_2,"socket_bind6_reuse: ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
return 111;
|
|
}
|
|
if (socket_listen(s,16)==-1) {
|
|
buffer_puts(buffer_2,"socket_listen: ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
return 111;
|
|
}
|
|
io_nonblock(s);
|
|
if (!io_fd(s)) {
|
|
buffer_puts(buffer_2,"io_fd: ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
return 111;
|
|
}
|
|
io_wantread(s);
|
|
for (;;) {
|
|
int64 i;
|
|
io_wait();
|
|
while ((i=io_canread())!=-1) {
|
|
if (i==s) {
|
|
/* the read event is on the server socket */
|
|
/* that means it's an incoming connection */
|
|
int n;
|
|
while ((n=socket_accept6(s,ip,&port,&scope_id))!=-1) {
|
|
int x=socket_tcp6();
|
|
if (x==-1) {
|
|
buffer_puts(buffer_2,"socket_tcp6 failed: ");
|
|
fail:
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
io_close(n);
|
|
} else {
|
|
struct state* s=malloc(sizeof(struct state));
|
|
if (!s) goto closefail;
|
|
s->a=n; s->b=x; s->connected=0; s->done=s->todo=0;
|
|
s->dir=UNDECIDED;
|
|
io_nonblock(x);
|
|
io_nonblock(n);
|
|
socket_connect6(x,out.s,hisport,hisscope_id);
|
|
if (!io_fd(x) || !io_fd(n)) {
|
|
buffer_puts(buffer_2,"io_fd failed: ");
|
|
closefail:
|
|
free(s);
|
|
io_close(x);
|
|
goto fail;
|
|
}
|
|
io_setcookie(x,s);
|
|
io_setcookie(n,s);
|
|
io_wantwrite(x);
|
|
}
|
|
}
|
|
if (errno!=EAGAIN) {
|
|
buffer_puts(buffer_2,"socket_accept6 failed: ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
}
|
|
} else {
|
|
/* read event on an established connection */
|
|
struct state* s=io_getcookie(i);
|
|
int l=io_tryread(i,s->buf,sizeof(s->buf));
|
|
if (l==-1) {
|
|
buffer_puts(buffer_2,"io_tryread(");
|
|
buffer_putulong(buffer_2,i);
|
|
buffer_puts(buffer_2,"): ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
io_close(s->a);
|
|
io_close(s->b);
|
|
} else if (l==0) {
|
|
buffer_puts(buffer_2,"eof on fd #");
|
|
buffer_putulong(buffer_2,i);
|
|
buffer_putnlflush(buffer_2);
|
|
io_close(i);
|
|
} else {
|
|
int r;
|
|
switch (r=io_trywrite(i,s->buf,l)) {
|
|
case -1:
|
|
buffer_puts(buffer_2,"io_tryread(");
|
|
buffer_putulong(buffer_2,i);
|
|
buffer_puts(buffer_2,"): ");
|
|
buffer_puterror(buffer_2);
|
|
buffer_putnlflush(buffer_2);
|
|
io_close(i);
|
|
break;
|
|
case 0:
|
|
buffer_puts(buffer_2,"write eof on fd #");
|
|
buffer_putulong(buffer_2,i);
|
|
buffer_putnlflush(buffer_2);
|
|
io_close(i);
|
|
default:
|
|
if (r!=l) {
|
|
buffer_puts(buffer_2,"short write on fd #");
|
|
buffer_putulong(buffer_2,i);
|
|
buffer_puts(buffer_2,": wrote ");
|
|
buffer_putulong(buffer_2,r);
|
|
buffer_puts(buffer_2,", wanted to write ");
|
|
buffer_putulong(buffer_2,l);
|
|
buffer_putsflush(buffer_2,").\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|