pr_netio_stream_t *proxy_netio_open(pool *p, int strm_type, int fd, int mode) { int xerrno; pr_netio_stream_t *nstrm = NULL; pr_netio_t *curr_netio; curr_netio = proxy_netio_unset(strm_type, "netio_open"); nstrm = pr_netio_open(p, strm_type, fd, mode); xerrno = errno; proxy_netio_set(strm_type, curr_netio); errno = xerrno; return nstrm; }
END_TEST START_TEST (inet_copy_conn_test) { int fd = -1, sockfd = -1, port = INPORT_ANY; conn_t *conn, *conn2; const char *name; conn = pr_inet_copy_conn(NULL, NULL); fail_unless(conn == NULL, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); conn = pr_inet_copy_conn(p, NULL); fail_unless(conn == NULL, "Failed to handle null conn argument"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn2 = pr_inet_copy_conn(p, conn); fail_unless(conn2 != NULL, "Failed to copy conn: %s", strerror(errno)); pr_inet_close(p, conn); pr_inet_close(p, conn2); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); name = "127.0.0.1"; conn->remote_addr = pr_netaddr_get_addr(p, name, NULL); fail_unless(conn->remote_addr != NULL, "Failed to resolve '%s': %s", name, strerror(errno)); conn->remote_name = pstrdup(p, name); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_WR); fail_unless(conn->instrm != NULL, "Failed to open ctrl writing stream: %s", strerror(errno)); conn2 = pr_inet_copy_conn(p, conn); fail_unless(conn2 != NULL, "Failed to copy conn: %s", strerror(errno)); mark_point(); pr_inet_lingering_close(NULL, NULL, 0L); pr_inet_lingering_close(p, conn, 0L); pr_inet_close(p, conn2); conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, fd, PR_NETIO_IO_WR); fail_unless(conn->instrm != NULL, "Failed to open ctrl writing stream: %s", strerror(errno)); mark_point(); pr_inet_lingering_abort(NULL, NULL, 0L); pr_inet_lingering_abort(p, conn, 0L); }
END_TEST START_TEST (inet_connect_ipv4_test) { int res; conn_t *conn; const pr_netaddr_t *addr; mark_point(); res = proxy_inet_connect(NULL, NULL, NULL, 0); fail_unless(res < 0, "Failed to handle null pool"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); mark_point(); res = proxy_inet_connect(p, NULL, NULL, 0); fail_unless(res < 0, "Failed to handle null conn"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, NULL, 0); fail_unless(res < 0, "Failed to handle null addr"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL); fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 80); fail_unless(res < 0, "Connected to 127.0.0.1#80 unexpectedly"); fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got '%s' (%d)", ECONNREFUSED, strerror(errno), errno); proxy_inet_close(p, conn); /* Try connecting to Google's DNS server. */ addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL); fail_unless(addr != NULL, "Failed to resolve '8.8.8.8': %s", strerror(errno)); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 53); fail_if(res < 0, "Failed to connect to 8.8.8.8#53: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); /* Now start supplying in/out streams. */ conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, -1, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 53); fail_if(res < 0, "Failed to connect to 8.8.8.8#53: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, -1, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_OTHR, -1, PR_NETIO_IO_WR); fail_unless(conn->outstrm != NULL, "Failed to open othr writing stream: %s", strerror(errno)); mark_point(); res = proxy_inet_connect(p, conn, addr, 53); fail_if(res < 0, "Failed to connect to 8.8.8.8#53: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); }
END_TEST START_TEST (inet_listen_test) { int res; conn_t *conn; mark_point(); res = proxy_inet_listen(NULL, NULL, 0, 0); fail_unless(res < 0, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); mark_point(); res = proxy_inet_listen(p, NULL, 0, 0); fail_unless(res < 0, "Failed to handle null conn"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); mark_point(); res = proxy_inet_listen(p, conn, 5, 0); fail_unless(res == 0, "Failed to listen on conn: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); /* Now start providing in/out streams. */ conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, -1, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); mark_point(); res = proxy_inet_listen(p, conn, 5, 0); fail_unless(res == 0, "Failed to listen on conn: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); conn = pr_inet_create_conn(p, -1, NULL, INPORT_ANY, FALSE); fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); conn->instrm = pr_netio_open(p, PR_NETIO_STRM_CTRL, -1, PR_NETIO_IO_RD); fail_unless(conn->instrm != NULL, "Failed to open ctrl reading stream: %s", strerror(errno)); conn->outstrm = pr_netio_open(p, PR_NETIO_STRM_OTHR, -1, PR_NETIO_IO_WR); fail_unless(conn->outstrm != NULL, "Failed to open othr writing stream: %s", strerror(errno)); mark_point(); res = proxy_inet_listen(p, conn, 5, 0); fail_unless(res == 0, "Failed to listen on conn: %s", strerror(errno)); mark_point(); proxy_inet_close(p, conn); }
char *pr_ident_lookup(pool *p, conn_t *c) { char *ret = "UNKNOWN"; pool *tmp_pool = NULL; conn_t *ident_conn = NULL, *ident_io = NULL; char buf[256] = {'\0'}, *tok = NULL, *tmp = NULL; int timerno, i = 0; int ident_port = pr_inet_getservport(p, "ident", "tcp"); tmp_pool = make_sub_pool(p); ident_timeout = 0; nstrm = NULL; if (ident_port == -1) { destroy_pool(tmp_pool); return pstrdup(p, ret); } /* Set up our timer before going any further. */ timerno = pr_timer_add(PR_TUNABLE_TIMEOUTIDENT, -1, NULL, (callback_t) ident_timeout_cb, "ident lookup"); if (timerno <= 0) { destroy_pool(tmp_pool); return pstrdup(p, ret); } ident_conn = pr_inet_create_connection(tmp_pool, NULL, -1, c->local_addr, INPORT_ANY, FALSE); pr_inet_set_nonblock(tmp_pool, ident_conn); i = pr_inet_connect_nowait(tmp_pool, ident_conn, c->remote_addr, ident_port); if (i < 0) { int xerrno = errno; pr_timer_remove(timerno, ANY_MODULE); pr_inet_close(tmp_pool, ident_conn); pr_trace_msg(trace_channel, 5, "connection to %s, port %d failed: %s", pr_netaddr_get_ipstr(c->remote_addr), ident_port, strerror(xerrno)); destroy_pool(tmp_pool); errno = xerrno; return pstrdup(p, ret); } if (!i) { /* Not yet connected. */ nstrm = pr_netio_open(p, PR_NETIO_STRM_OTHR, ident_conn->listen_fd, PR_NETIO_IO_RD); pr_netio_set_poll_interval(nstrm, 1); switch (pr_netio_poll(nstrm)) { /* Aborted, timed out */ case 1: { if (ident_timeout) { pr_timer_remove(timerno, ANY_MODULE); pr_netio_close(nstrm); pr_inet_close(tmp_pool, ident_conn); pr_trace_msg(trace_channel, 5, "lookup timed out, returning '%s'", ret); destroy_pool(tmp_pool); return pstrdup(p, ret); } break; } /* Error. */ case -1: { int xerrno = errno; pr_timer_remove(timerno, ANY_MODULE); pr_netio_close(nstrm); pr_inet_close(tmp_pool, ident_conn); pr_trace_msg(trace_channel, 6, "lookup failed (%s), returning '%s'", strerror(xerrno), ret); destroy_pool(tmp_pool); errno = xerrno; return pstrdup(p, ret); } /* Connected. */ default: { ident_conn->mode = CM_OPEN; if (pr_inet_get_conn_info(ident_conn, ident_conn->listen_fd) < 0) { int xerrno = errno; pr_timer_remove(timerno, ANY_MODULE); pr_netio_close(nstrm); pr_inet_close(tmp_pool, ident_conn); pr_trace_msg(trace_channel, 2, "lookup timed out (%s), returning '%s'", strerror(xerrno), ret); destroy_pool(tmp_pool); errno = xerrno; return pstrdup(p, ret); } break; } } } ident_io = pr_inet_openrw(tmp_pool, ident_conn, NULL, PR_NETIO_STRM_OTHR, -1, -1, -1, FALSE); if (ident_io == NULL) { int xerrno = errno; pr_timer_remove(timerno, ANY_MODULE); pr_inet_close(tmp_pool, ident_conn); pr_trace_msg(trace_channel, 3, "failed opening read/write connection: %s", strerror(xerrno)); destroy_pool(tmp_pool); errno = xerrno; return pstrdup(p, ret); } nstrm = ident_io->instrm; pr_inet_set_nonblock(tmp_pool, ident_io); pr_netio_set_poll_interval(ident_io->instrm, 1); pr_netio_set_poll_interval(ident_io->outstrm, 1); pr_netio_printf(ident_io->outstrm, "%d, %d\r\n", c->remote_port, c->local_port); /* If the timer fires while in netio_gets(), netio_gets() will simply return * either a partial string, or NULL. This works because ident_timeout_cb * aborts the stream from which we are reading. netio_set_poll_interval() is * used to make sure significant delays don't occur on systems that * automatically restart syscalls after the SIGALRM signal. */ pr_trace_msg(trace_channel, 4, "reading response from remote ident server"); if (pr_netio_gets(buf, sizeof(buf), ident_io->instrm)) { strip_end(buf, "\r\n"); pr_trace_msg(trace_channel, 6, "received '%s' from remote ident server", buf); tmp = buf; tok = get_token(&tmp, ":"); if (tok && (tok = get_token(&tmp, ":"))) { while (*tok && isspace((int) *tok)) { pr_signals_handle(); tok++; } strip_end(tok, " \t"); if (strcasecmp(tok, "ERROR") == 0) { if (tmp) { while (*tmp && isspace((int) *tmp)) { pr_signals_handle(); tmp++; } strip_end(tmp, " \t"); if (strcasecmp(tmp, "HIDDEN-USER") == 0) ret = "HIDDEN-USER"; } } else if (strcasecmp(tok, "USERID") == 0) { if (tmp && (tok = get_token(&tmp, ":"))) { if (tmp) { while (*tmp && isspace((int) *tmp)) { pr_signals_handle(); tmp++; } strip_end(tmp, " \t"); ret = tmp; } } } } } pr_timer_remove(timerno, ANY_MODULE); pr_inet_close(tmp_pool, ident_io); pr_inet_close(tmp_pool, ident_conn); destroy_pool(tmp_pool); return pstrdup(p, ret); }