static void proxy_log_connect_error(struct login_proxy *proxy) { string_t *str = t_str_new(128); struct ip_addr local_ip; in_port_t local_port; str_printfa(str, "proxy(%s): ", proxy->client->virtual_user); if (!proxy->connected) { str_printfa(str, "connect(%s, %u) failed: %m", proxy->host, proxy->port); } else { str_printfa(str, "Login for %s:%u timed out in state=%u", proxy->host, proxy->port, proxy->client->proxy_state); } str_printfa(str, " (after %u secs", (unsigned int)(ioloop_time - proxy->created.tv_sec)); if (proxy->reconnect_count > 0) str_printfa(str, ", %u reconnects", proxy->reconnect_count); if (proxy->server_fd != -1 && net_getsockname(proxy->server_fd, &local_ip, &local_port) == 0) { str_printfa(str, ", local=%s:%u", net_ip2addr(&local_ip), local_port); } else if (proxy->source_ip.family != 0) { str_printfa(str, ", local=%s", net_ip2addr(&proxy->source_ip)); } str_append_c(str, ')'); client_log_err(proxy->client, str_c(str)); }
void fd_debug_verify_leaks(int first_fd, int last_fd) { struct ip_addr addr, raddr; unsigned int port, rport; struct stat st; int old_errno; for (; first_fd <= last_fd; first_fd++) { if (fcntl(first_fd, F_GETFD, 0) == -1 && errno == EBADF) continue; old_errno = errno; if (net_getsockname(first_fd, &addr, &port) == 0) { if (addr.family == AF_UNIX) { struct sockaddr_un sa; socklen_t socklen = sizeof(sa); if (getsockname(first_fd, (void *)&sa, &socklen) < 0) sa.sun_path[0] = '\0'; i_panic("Leaked UNIX socket fd %d: %s", first_fd, sa.sun_path); } if (net_getpeername(first_fd, &raddr, &rport) < 0) { memset(&raddr, 0, sizeof(raddr)); rport = 0; } i_panic("Leaked socket fd %d: %s:%u -> %s:%u", first_fd, net_ip2addr(&addr), port, net_ip2addr(&raddr), rport); } if (fstat(first_fd, &st) == 0) { #ifdef __APPLE__ /* OSX workaround: gettimeofday() calls shm_open() internally and the fd won't get closed on exec. We'll just skip all ino/dev=0 files and hope they weren't anything else. */ if (st.st_ino == 0 && st.st_dev == 0) continue; #endif #ifdef HAVE_SYS_SYSMACROS_H i_panic("Leaked file fd %d: dev %s.%s inode %s", first_fd, dec2str(major(st.st_dev)), dec2str(minor(st.st_dev)), dec2str(st.st_ino)); #else i_panic("Leaked file fd %d: dev %s inode %s", first_fd, dec2str(st.st_dev), dec2str(st.st_ino)); #endif } i_panic("Leaked unknown fd %d (errno = %s)", first_fd, strerror(old_errno)); } }
static int server_connection_read_settings(struct server_connection *conn) { const struct setting_parser_info *set_roots[] = { &doveadm_setting_parser_info, NULL }; struct master_service_settings_input input; struct master_service_settings_output output; const char *error; in_port_t port; void *set; memset(&input, 0, sizeof(input)); input.roots = set_roots; input.service = "doveadm"; (void)net_getsockname(conn->fd, &input.local_ip, &port); (void)net_getpeername(conn->fd, &input.remote_ip, &port); if (master_service_settings_read(master_service, &input, &output, &error) < 0) { i_error("Error reading configuration: %s", error); return -1; } set = master_service_settings_get_others(master_service)[0]; conn->set = settings_dup(&doveadm_setting_parser_info, set, conn->pool); return 0; }
/* Start listening for incoming connections */ static GIOChannel *dcc_listen_port(GIOChannel *iface, IPADDR *ip, int port) { if (net_getsockname(iface, ip, NULL) == -1) return NULL; if (IPADDR_IS_V6(ip)) return net_listen(NULL, &port); else return net_listen(&ip4_any, &port); }
/* Start listening for incoming connections */ GIOChannel *dcc_listen(GIOChannel *iface, IPADDR *ip, int *port) { GIOChannel *handle; IPADDR *listen_ip = NULL; const char *dcc_port, *p, *own_ip; int first, last; if (net_getsockname(iface, ip, NULL) == -1) return NULL; /* figure out if we want to listen in IPv4 address or in "any" address, which may mean IPv4+IPv6 or just IPv6 depending on OS. */ own_ip = settings_get_str("dcc_own_ip"); if (*own_ip != '\0') { if (is_ipv4_address(own_ip)) listen_ip = &ip4_any; } else { if (!IPADDR_IS_V6(ip)) listen_ip = &ip4_any; } /* get first port */ dcc_port = settings_get_str("dcc_port"); first = atoi(dcc_port); if (first == 0) { /* random port */ *port = 0; return net_listen(listen_ip, port); } /* get last port */ p = strchr(dcc_port, ' '); if (p == NULL) p = strchr(dcc_port, '-'); dcc_port = p; if (dcc_port == NULL) last = first; else { last = atoi(dcc_port+1); if (last == 0) last = first; } /* use the first available port */ for (*port = first; *port <= last; (*port)++) { handle = net_listen(listen_ip, port); if (handle != NULL) return handle; } return NULL; }
static void client_connected_finish(const struct master_service_connection *conn) { struct client *client; struct ssl_proxy *proxy; struct ip_addr local_ip; const struct login_settings *set; const struct master_service_ssl_settings *ssl_set; unsigned int local_port; pool_t pool; int fd_ssl; void **other_sets; if (net_getsockname(conn->fd, &local_ip, &local_port) < 0) { memset(&local_ip, 0, sizeof(local_ip)); local_port = 0; } pool = pool_alloconly_create("login client", 8*1024); set = login_settings_read(pool, &local_ip, &conn->remote_ip, NULL, &ssl_set, &other_sets); if (!ssl_connections && !conn->ssl) { client = client_create(conn->fd, FALSE, pool, set, ssl_set, other_sets, &local_ip, &conn->remote_ip); } else { fd_ssl = ssl_proxy_alloc(conn->fd, &conn->remote_ip, pool, set, ssl_set, &proxy); if (fd_ssl == -1) { net_disconnect(conn->fd); pool_unref(&pool); master_service_client_connection_destroyed(master_service); return; } client = client_create(fd_ssl, TRUE, pool, set, ssl_set, other_sets, &local_ip, &conn->remote_ip); client->ssl_proxy = proxy; ssl_proxy_set_client(proxy, client); ssl_proxy_start(proxy); } client->real_remote_port = client->remote_port = conn->remote_port; client->real_local_port = client->local_port = local_port; if (auth_client_to != NULL) timeout_remove(&auth_client_to); }
/* command: DCC CHAT */ static void cmd_dcc_chat(const char *data, IRC_SERVER_REC *server) { DCC_REC *dcc; IPADDR own_ip; char *str, host[MAX_IP_LEN]; int port, handle; g_return_if_fail(data != NULL); if (*data == '\0') cmd_return_error(CMDERR_NOT_ENOUGH_PARAMS); dcc = dcc_find_item(DCC_TYPE_CHAT, data, NULL); if (dcc != NULL) { /* found from dcc list - so we're the connecting side.. */ dcc_chat_connect(dcc); return; } /* send dcc chat request */ if (server == NULL || !server->connected) cmd_return_error(CMDERR_NOT_CONNECTED); if (net_getsockname(server->handle, &own_ip, NULL) == -1) cmd_return_error(CMDERR_ERRNO); port = settings_get_int("dcc_port"); handle = net_listen(&own_ip, &port); if (handle == -1) cmd_return_error(CMDERR_ERRNO); dcc = dcc_create(DCC_TYPE_CHAT, handle, data, "chat", server, NULL); dcc->tagread = g_input_add(dcc->handle, G_INPUT_READ, (GInputFunction) dcc_chat_listen, dcc); /* send the request */ dcc_make_address(&own_ip, host); str = g_strdup_printf("PRIVMSG %s :\001DCC CHAT CHAT %s %d\001", data, host, port); irc_send_cmd(server, str); g_free(str); }
struct client_connection * client_connection_create(int fd, int listen_fd, bool ssl) { struct client_connection *conn; const char *ip; pool_t pool; pool = pool_alloconly_create("doveadm client", 1024*16); conn = p_new(pool, struct client_connection, 1); conn->pool = pool; conn->fd = fd; conn->io = io_add(fd, IO_READ, client_connection_input, conn); conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE, FALSE); conn->output = o_stream_create_fd(fd, (size_t)-1, FALSE); o_stream_set_no_error_handling(conn->output, TRUE); (void)net_getsockname(fd, &conn->local_ip, &conn->local_port); (void)net_getpeername(fd, &conn->remote_ip, &conn->remote_port); i_stream_set_name(conn->input, net_ip2addr(&conn->remote_ip)); o_stream_set_name(conn->output, net_ip2addr(&conn->remote_ip)); ip = net_ip2addr(&conn->remote_ip); if (ip[0] != '\0') i_set_failure_prefix("doveadm(%s): ", ip); if (client_connection_read_settings(conn) < 0) { client_connection_destroy(&conn); return NULL; } if (ssl) { if (client_connection_init_ssl(conn) < 0) { client_connection_destroy(&conn); return NULL; } } client_connection_send_auth_handshake(conn, listen_fd); return conn; }
gboolean proxy_init(void) { gchar ipaddr[MAX_IP_LEN]; const char *password; const char *addr; int port; proxy_settings_init(); proxy_data = g_new0(PLUGIN_DATA, 1); password = settings_get_str("proxy_listen_password"); addr = settings_get_str("proxy_listen_addr"); port = settings_get_int("proxy_listen_port"); plug = module_find("proxy"); proxy_data->plugin = plug; if (*password != '\0') { /* args = password */ proxy_data->password = g_strdup(password); } if (*addr != '\0') { /* specify ip address to listen */ net_host2ip(addr, &proxy_data->ip); } if (port != 0) { /* specify port to use */ proxy_data->port = port; } if (proxy_data->password == NULL) { /* no password - bad idea! */ printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Warning!! Password not specified, everyone can use this proxy! Use /set proxy_listen_password <password> to set it"); } if (servers == NULL) { /* FIXME: not good */ printtext(NULL, NULL, MSGLEVEL_CLIENTERROR, "You need to specify IP address to listen with /set proxy_listen_addr <address>"); deinit(); return FALSE; } else { SERVER_REC *server; server = servers->data; if (net_getsockname(net_sendbuffer_handle(server->handle), &proxy_data->ip, NULL)) { deinit(); return FALSE; } } net_ip2host(&proxy_data->ip, ipaddr); printtext(NULL, NULL, MSGLEVEL_CLIENTNOTICE, "Proxy plugin loaded - listening in interface %s port %d", ipaddr, proxy_data->port); plugin_proxy_listen_init(proxy_data); proxy_data->loaded = TRUE; return TRUE; }
/* command: DCC SEND */ static void cmd_dcc_send(const char *data, IRC_SERVER_REC *server, WI_IRC_REC *item) { char *params, *target, *fname, *str, *ptr; char host[MAX_IP_LEN]; int hfile, hlisten, port; long fsize; DCC_REC *dcc, *chat; IPADDR own_ip; g_return_if_fail(data != NULL); params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &fname); if (*target == '\0' || *fname == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); /* if we're in dcc chat, send the request via it. */ chat = item_get_dcc(item); if (chat != NULL && (chat->mirc_ctcp || g_strcasecmp(target, chat->nick) != 0)) chat = NULL; if ((server == NULL || !server->connected) && chat == NULL) cmd_param_error(CMDERR_NOT_CONNECTED); if (dcc_find_item(DCC_TYPE_SEND, target, fname)) { signal_emit("dcc error send exists", 2, target, fname); g_free(params); return; } str = convert_home(fname); if (!g_path_is_absolute(str)) { char *path; g_free(str); path = convert_home(settings_get_str("dcc_upload_path")); str = g_strconcat(path, G_DIR_SEPARATOR_S, fname, NULL); g_free(path); } hfile = open(str, O_RDONLY); g_free(str); if (hfile == -1) { signal_emit("dcc error file not found", 2, target, fname); g_free(params); return; } fsize = lseek(hfile, 0, SEEK_END); lseek(hfile, 0, SEEK_SET); /* get the IP address we use with IRC server */ if (net_getsockname(chat != NULL ? chat->handle : server->handle, &own_ip, NULL) == -1) { close(hfile); cmd_param_error(CMDERR_ERRNO); } /* start listening */ port = settings_get_int("dcc_port"); hlisten = net_listen(&own_ip, &port); if (hlisten == -1) { close(hfile); cmd_param_error(CMDERR_ERRNO); } /* skip path, change all spaces to _ */ fname = g_strdup(g_basename(fname)); for (ptr = fname; *ptr != '\0'; ptr++) if (*ptr == ' ') *ptr = '_'; dcc = dcc_create(DCC_TYPE_SEND, hlisten, target, fname, server, chat); dcc->port = port; dcc->size = fsize; dcc->fhandle = hfile; dcc->tagread = g_input_add(hlisten, G_INPUT_READ, (GInputFunction) dcc_send_init, dcc); /* send DCC request */ dcc_make_address(&own_ip, host); str = g_strdup_printf("DCC SEND %s %s %d %lu", fname, host, port, fsize); dcc_ctcp_message(target, server, chat, FALSE, str); g_free(str); g_free(fname); g_free(params); }