int proxy_db_finish_stmt(pool *p, const char *stmt) { sqlite3_stmt *pstmt; int res; if (p == NULL || stmt == NULL) { errno = EINVAL; return -1; } if (prepared_stmts == NULL) { errno = ENOENT; return -1; } pstmt = pr_table_get(prepared_stmts, stmt, NULL); if (pstmt == NULL) { pr_trace_msg(trace_channel, 19, "unable to find prepared statement for '%s'", stmt); errno = ENOENT; return -1; } res = sqlite3_finalize(pstmt); if (res != SQLITE_OK) { pr_trace_msg(trace_channel, 3, "error finishing prepared statement '%s': %s", stmt, sqlite3_errmsg(proxy_dbh)); errno = EPERM; return -1; } (void) pr_table_remove(prepared_stmts, stmt, NULL); return 0; }
END_TEST START_TEST (cmd_get_errno_test) { int res, *xerrno = NULL; cmd_rec *cmd = NULL; res = pr_cmd_get_errno(NULL); fail_unless(res == -1, "Failed to handle null cmd_rec"); fail_unless(errno == EINVAL, "Failed to set errno to EINVAL"); cmd = pr_cmd_alloc(p, 1, "foo"); res = pr_cmd_get_errno(cmd); fail_unless(res == 0, "Expected errno 0, got %d", res); (void) pr_table_remove(cmd->notes, "errno", NULL); res = pr_cmd_get_errno(cmd); fail_unless(res < 0, "Failed to handle missing 'errno' note"); fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT, strerror(errno), errno); xerrno = pcalloc(cmd->pool, sizeof(int)); (void) pr_table_add(cmd->notes, "errno", xerrno, sizeof(int)); res = pr_cmd_set_errno(NULL, ENOENT); fail_unless(res < 0, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, strerror(errno), errno); res = pr_cmd_set_errno(cmd, ENOENT); fail_unless(res == 0, "Failed to stash errno ENOENT: %s", strerror(errno)); res = pr_cmd_get_errno(cmd); fail_unless(res == ENOENT, "Expected errno ENOENT, got %s (%d)", strerror(res), res); }
int pr_var_delete(const char *name) { if (var_tab == NULL) { errno = EPERM; return -1; } if (name == NULL) { errno = EINVAL; return -1; } return pr_table_remove(var_tab, name, NULL) ? 0 : -1; }
int pr_var_remove(const char *name) { if (!name) { errno = EINVAL; return -1; } if (!var_tab) { errno = EPERM; return -1; } return pr_table_remove(var_tab, name, NULL) ? 0 : -1; }
MODRET copy_log_site(cmd_rec *cmd) { if (copy_engine == FALSE) { return PR_DECLINED(cmd); } if (cmd->argc < 3 || strncasecmp(cmd->argv[1], "CPTO", 5) != 0) { return PR_DECLINED(cmd); } /* Delete the stashed CPFR path from the session.notes table. */ (void) pr_table_remove(session.notes, "mod_copy.cpfr-path", NULL); return PR_DECLINED(cmd); }
int pr_trace_set_levels(const char *channel, int min_level, int max_level) { if (channel == NULL) { void *v; if (trace_tab == NULL) { errno = EINVAL; return -1; } v = pr_table_remove(trace_tab, channel, NULL); if (v == NULL) { errno = EINVAL; return -1; } return 0; } if (min_level > max_level) { errno = EINVAL; return -1; } if (trace_tab == NULL && min_level < 0) { return 0; } if (trace_pool == NULL) { trace_pool = make_sub_pool(permanent_pool); pr_pool_tag(trace_pool, "Trace API"); trace_tab = pr_table_alloc(trace_pool, 0); /* Register a handler for churning the log pool during HUP. */ pr_event_register(NULL, "core.restart", trace_restart_ev, NULL); } if (min_level >= 0) { struct trace_levels *levels; levels = pcalloc(trace_pool, sizeof(struct trace_levels)); levels->min_level = min_level; levels->max_level = max_level; if (strcmp(channel, PR_TRACE_DEFAULT_CHANNEL) != 0) { int count = pr_table_exists(trace_tab, channel); if (count <= 0) { if (pr_table_add(trace_tab, pstrdup(trace_pool, channel), levels, sizeof(struct trace_levels)) < 0) { return -1; } } else { if (pr_table_set(trace_tab, pstrdup(trace_pool, channel), levels, sizeof(struct trace_levels)) < 0) return -1; } } else { register unsigned int i; for (i = 0; trace_channels[i]; i++) { (void) pr_trace_set_levels(trace_channels[i], min_level, max_level); } } } else { if (strcmp(channel, PR_TRACE_DEFAULT_CHANNEL) != 0) { (void) pr_table_remove(trace_tab, channel, NULL); } else { register unsigned int i; for (i = 0; trace_channels[i]; i++) { (void) pr_table_remove(trace_tab, trace_channels[i], NULL); } } } return 0; }
conn_t *proxy_conn_get_server_conn(pool *p, struct proxy_session *proxy_sess, pr_netaddr_t *remote_addr) { pr_netaddr_t *bind_addr = NULL, *local_addr = NULL; const char *remote_ipstr = NULL; unsigned int remote_port; conn_t *server_conn, *ctrl_conn; int res; if (proxy_sess->connect_timeout > 0) { const char *notes_key = "mod_proxy.proxy-connect-address"; proxy_sess->connect_timerno = pr_timer_add(proxy_sess->connect_timeout, -1, &proxy_module, proxy_conn_connect_timeout_cb, "ProxyTimeoutConnect"); (void) pr_table_remove(session.notes, notes_key, NULL); if (pr_table_add(session.notes, notes_key, remote_addr, sizeof(pr_netaddr_t)) < 0) { (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error stashing proxy connect address note: %s", strerror(errno)); } } remote_ipstr = pr_netaddr_get_ipstr(remote_addr); remote_port = ntohs(pr_netaddr_get_port(remote_addr)); /* Check the family of the retrieved address vs what we'll be using * to connect. If there's a mismatch, we need to get an addr with the * matching family. */ if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(remote_addr)) { local_addr = session.c->local_addr; } else { /* In this scenario, the proxy has an IPv6 socket, but the remote/backend * server has an IPv4 (or IPv4-mapped IPv6) address. OR it's the proxy * which has an IPv4 socket, and the remote/backend server has an IPv6 * address. */ if (pr_netaddr_get_family(session.c->local_addr) == AF_INET) { char *ip_str; /* Convert the local address from an IPv4 to an IPv6 addr. */ ip_str = pcalloc(p, INET6_ADDRSTRLEN + 1); snprintf(ip_str, INET6_ADDRSTRLEN, "::ffff:%s", pr_netaddr_get_ipstr(session.c->local_addr)); local_addr = pr_netaddr_get_addr(p, ip_str, NULL); } else { local_addr = pr_netaddr_v6tov4(p, session.c->local_addr); if (local_addr == NULL) { pr_trace_msg(trace_channel, 4, "error converting IPv6 local address %s to IPv4 address: %s", pr_netaddr_get_ipstr(session.c->local_addr), strerror(errno)); } } if (local_addr == NULL) { local_addr = session.c->local_addr; } } bind_addr = proxy_sess->src_addr; if (bind_addr == NULL) { bind_addr = local_addr; } /* Note: IF mod_proxy is running on localhost, and the connection to be * made is to a public IP address, then this connect(2) attempt would most * likely fail with ENETUNREACH, since localhost is a loopback network, * and of course not reachable from a public IP. Thus we check for this * edge case (which happens often for development). */ if (pr_netaddr_is_loopback(bind_addr) == TRUE) { const char *local_name; pr_netaddr_t *local_addr; local_name = pr_netaddr_get_localaddr_str(p); local_addr = pr_netaddr_get_addr(p, local_name, NULL); if (local_addr != NULL) { pr_trace_msg(trace_channel, 14, "%s is a loopback address, and unable to reach %s; using %s instead", pr_netaddr_get_ipstr(bind_addr), remote_ipstr, pr_netaddr_get_ipstr(local_addr)); bind_addr = local_addr; } } server_conn = pr_inet_create_conn(p, -1, bind_addr, INPORT_ANY, FALSE); if (server_conn == NULL) { int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error creating connection to %s: %s", pr_netaddr_get_ipstr(bind_addr), strerror(xerrno)); pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); errno = xerrno; return NULL; } pr_trace_msg(trace_channel, 11, "connecting to backend address %s#%u from %s", remote_ipstr, remote_port, pr_netaddr_get_ipstr(bind_addr)); res = pr_inet_connect_nowait(p, server_conn, remote_addr, ntohs(pr_netaddr_get_port(remote_addr))); if (res < 0) { int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error starting connect to %s#%u: %s", remote_ipstr, remote_port, strerror(xerrno)); pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); errno = xerrno; return NULL; } if (res == 0) { pr_netio_stream_t *nstrm; int nstrm_mode = PR_NETIO_IO_RD; if (proxy_opts & PROXY_OPT_USE_PROXY_PROTOCOL) { /* Rather than waiting for the stream to be readable (because the * other end sent us something), wait for the stream to be writable * so that we can send something to the other end). */ nstrm_mode = PR_NETIO_IO_WR; } /* Not yet connected. */ nstrm = proxy_netio_open(p, PR_NETIO_STRM_OTHR, server_conn->listen_fd, nstrm_mode); if (nstrm == NULL) { int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error opening stream to %s#%u: %s", remote_ipstr, remote_port, strerror(xerrno)); pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); pr_inet_close(p, server_conn); errno = xerrno; return NULL; } proxy_netio_set_poll_interval(nstrm, 1); switch (proxy_netio_poll(nstrm)) { case 1: { /* Aborted, timed out. Note that we shouldn't reach here. */ pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); proxy_netio_close(nstrm); pr_inet_close(p, server_conn); errno = ETIMEDOUT; return NULL; } case -1: { /* Error */ int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error connecting to %s#%u: %s", remote_ipstr, remote_port, strerror(xerrno)); pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); proxy_netio_close(nstrm); pr_inet_close(p, server_conn); errno = xerrno; return NULL; } default: { /* Connected */ server_conn->mode = CM_OPEN; pr_timer_remove(proxy_sess->connect_timerno, &proxy_module); pr_table_remove(session.notes, "mod_proxy.proxy-connect-addr", NULL); res = pr_inet_get_conn_info(server_conn, server_conn->listen_fd); if (res < 0) { int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "error obtaining local socket info on fd %d: %s", server_conn->listen_fd, strerror(xerrno)); proxy_netio_close(nstrm); pr_inet_close(p, server_conn); errno = xerrno; return NULL; } break; } } } pr_trace_msg(trace_channel, 5, "successfully connected to %s#%u from %s#%d", remote_ipstr, remote_port, pr_netaddr_get_ipstr(server_conn->local_addr), ntohs(pr_netaddr_get_port(server_conn->local_addr))); ctrl_conn = proxy_inet_openrw(p, server_conn, NULL, PR_NETIO_STRM_CTRL, -1, -1, -1, FALSE); if (ctrl_conn == NULL) { int xerrno = errno; (void) pr_log_writefile(proxy_logfd, MOD_PROXY_VERSION, "unable to open control connection to %s#%u: %s", remote_ipstr, remote_port, strerror(xerrno)); pr_inet_close(p, server_conn); errno = xerrno; return NULL; } return ctrl_conn; }