int timeoutconn6(int s,const char ip[16],uint16 port,unsigned int scope_id,unsigned int timeout) { struct taia now; struct taia deadline; iopause_fd x; if (socket_connect6(s,ip,port,scope_id) == -1) { if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; x.fd = s; x.events = IOPAUSE_WRITE; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = ETIMEDOUT; /* note that connect attempt is continuing */ return -1; } } if (!socket_connected(s)) return -1; } if (ndelay_off(s) == -1) return -1; return 0; }
static int make_connection(char* ip,uint16 port,uint32 scope_id,int s) { int v6=byte_diff(ip,12,V4mappedprefix); if (v6) { if (s==-1) { s=socket_tcp6(); if (s==-1) return -1; } if (socket_connect6(s,ip,port,scope_id)==-1) { if (errno==EAGAIN || errno==EINPROGRESS || errno==EISCONN) return s; ++kaputt; if (errno!=ECONNREFUSED && errno!=ECONNRESET) carpsys("socket_connect6"); close(s); return -1; } } else { if (s==-1) { s=socket_tcp4(); if (s==-1) return -1; } if (socket_connect4(s,ip+12,port)==-1) { if (errno==EAGAIN || errno==EINPROGRESS || errno==EISCONN) return s; ++kaputt; if (errno!=ECONNREFUSED && errno!=ECONNRESET) carpsys("socket_connect6"); close(s); return -1; } } return s; }
static void handle_reconnects( void ) { int i; for( i=0; i<g_connection_count; ++i ) if( PROXYPEER_NEEDSCONNECT( g_connections[i].state ) ) { int64 newfd = socket_tcp6( ); fprintf( stderr, "(Re)connecting to peer..." ); if( newfd < 0 ) continue; /* No socket for you */ io_fd(newfd); if( socket_bind6_reuse(newfd,g_serverip,g_serverport,0) ) { io_close( newfd ); continue; } if( socket_connect6(newfd,g_connections[i].ip,g_connections[i].port,0) == -1 && errno != EINPROGRESS && errno != EWOULDBLOCK ) { close(newfd); continue; } io_wantwrite(newfd); /* So we will be informed when it is connected */ io_setcookie(newfd,g_connections+i); /* Prepare connection info block */ reset_info_block( g_connections+i ); g_connections[i].fd = newfd; PROXYPEER_SETCONNECTING( g_connections[i].state ); } g_connection_reconn = time(NULL) + 30; }
static int make_connection(char* ip,uint16 port,uint32 scope_id) { int v6=byte_diff(ip,12,V4mappedprefix); int s; if (v6) { s=socket_tcp6(); if (s==-1) panic("socket_tcp6()"); ndelay_off(s); if (bindport) { for (;;) { int r=socket_bind6_reuse(s,V6any,bindport,0); if (++bindport<1024) bindport=1024; if (r==0) break; if (errno!=EADDRINUSE) panic("socket_bind6"); } } if (socket_connect6(s,ip,port,scope_id)==-1) { carp("socket_connect6"); close(s); return -1; } } else { s=socket_tcp4(); if (s==-1) panic("socket_tcp4()"); ndelay_off(s); if (bindport) { for (;;) { int r=socket_bind4_reuse(s,V6any,bindport); if (++bindport<1024) bindport=1024; if (r==0) break; if (errno!=EADDRINUSE) panic("socket_bind4"); } } if (socket_connect4(s,ip+12,port)==-1) { carp("socket_connect4"); close(s); return -1; } } return s; }
static int thisudp(struct dns_transmit *d) { const char *ip; socketfree(d); while (d->udploop < 4) { for (;d->curserver < 16;++d->curserver) { ip = d->servers + 16 * d->curserver; if (byte_diff(ip,16,V6any)) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); d->s1 = 1 + socket_udp6(); if (!d->s1) { dns_transmit_free(d); return -1; } if (randombind(d) == -1) { dns_transmit_free(d); return -1; } if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { struct taia now; taia_now(&now); taia_uint(&d->deadline,timeouts[d->udploop]); taia_add(&d->deadline,&d->deadline,&now); d->tcpstate = 0; return 0; } socketfree(d); } } ++d->udploop; d->curserver = 0; } dns_transmit_free(d); return -1; }
static int thistcp(struct dns_transmit *d) { struct taia now; const char *ip; socketfree(d); packetfree(d); for (;d->curserver < 16;++d->curserver) { ip = d->servers + 16 * d->curserver; if (byte_diff(ip,16,V6any)) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); d->s1 = 1 + socket_tcp6(); if (!d->s1) { dns_transmit_free(d); return -1; } if (randombind(d) == -1) { dns_transmit_free(d); return -1; } taia_now(&now); taia_uint(&d->deadline,10); taia_add(&d->deadline,&d->deadline,&now); if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) { d->tcpstate = 2; return 0; } if ((errno == error_inprogress) || (errno == error_wouldblock)) { d->tcpstate = 1; return 0; } socketfree(d); } } dns_transmit_free(d); return -1; }
int socket_deadlineconnstamp6 (int s, char const *ip, uint16 port, struct taia const *deadline, struct taia *stamp) { if (socket_connect6(s, ip, port) >= 0) return 1 ; if (!error_isagain(errno) && !error_isalready(errno)) return 0 ; return socket_waitconn(s, deadline, stamp) ; }
int main(int argc, char* argv[]) { int s; uint16 port = 2342; uint32 scope_id = 0; char ip[16]; char buf[8192]; int i; struct pollfd p[2]; if(argc < 3) { usage: __write2("usage: client ip port\n\nexample: dump -0 -f - | client 10.0.0.149 8000\n"); return 0; } if(argv[1][i = scan_ip6if(argv[1], ip, &scope_id)]) { __write2("client: error: invalid ip address!\n"); goto usage; } if(argv[2][scan_ushort(argv[2], &port)]) { __write2("client: error: invalid port number!\n"); goto usage; } if(byte_equal(ip, 12, V4mappedprefix)) { s = socket_tcp4b(); if(s == -1) panic("client: error: socket() failed"); if(socket_connect4(s, ip + 12, port) == -1) panic("client: error: connect() failed"); } else { s = socket_tcp6b(); if(s == -1) panic("client: error: socket() failed"); if(socket_connect6(s, ip, port, scope_id) == -1) panic("client: error: connect() failed"); } ndelay_off(s); p[0].fd = 0; p[0].events = POLLIN; p[1].fd = s; p[1].events = POLLIN; while(poll(p, 2, 5000)) { if(p[0].revents) { int j; if(p[0].revents & POLLERR) panic("client: error: poll() signals POLLERR\n"); i = read(0, buf, sizeof(buf)); if(i == 0) { shutdown(s, SHUT_WR); blockingcopy(s, 1); } for(j = 0; j < i;) { int k = write(s, buf + j, i - j); if(k == -1) panic("client: error: write() failed"); if(k == 0) panic("client: error: short write!\n"); j += k; } } if(p[1].revents) { int j; if(p[1].revents & POLLERR) panic("client: error: poll() signals POLLERR\n"); i = read(s, buf, sizeof(buf)); if(i == 0) { shutdown(1, SHUT_WR); blockingcopy(0, s); } for(j = 0; j < i;) { int k = write(1, buf + j, i - j); if(k == -1) panic("client: error: write() failed"); if(k == 0) panic("client: error: short write!\n"); j += k; } } } return 0; }
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; } 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); 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; }