static void privop_pasv_get_data_sock(session_t *sess) { unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd); char ip[16] = {0}; priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip)); printf("privop_pasv_get_data_sock port=%u and ip=%s\n", port, ip); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); int fd = tcp_client(20); if(fd == -1) { printf("aaaaaaaaaaaaaaaaaaa\n"); priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } socklen_t len = sizeof(struct sockaddr_in);; if(connect(fd, (struct sockaddr*)&addr, len) < 0) { printf("bbbbbbbbbbbbbbbbb\n"); ERR_EXIT("ccccconect"); close(fd); priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); ERR_EXIT("connect"); return; } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->parent_fd, fd); close(fd); }
int vsf_ftpdataio_post_mark_connect(struct vsf_session* p_sess) { int ret = 0; if (!p_sess->data_use_ssl) { return 1; } if (!p_sess->ssl_slave_active) { ret = ssl_accept(p_sess, p_sess->data_fd); } else { int sock_ret; priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_HANDSHAKE); priv_sock_send_fd(p_sess->ssl_consumer_fd, p_sess->data_fd); sock_ret = priv_sock_get_result(p_sess->ssl_consumer_fd); if (sock_ret == PRIV_SOCK_RESULT_OK) { ret = 1; } } if (ret != 1) { if (tunable_require_ssl_reuse) { vsf_cmdio_write_exit(p_sess, FTP_DATATLSBAD, "SSL connection failed: session reuse required", 1); } else { vsf_cmdio_write(p_sess, FTP_DATATLSBAD, "SSL connection failed"); } } return ret; }
static void cmd_process_get_data_sock(struct vsf_session* p_sess) { int sock_fd = vsf_privop_get_ftp_port_sock(p_sess); priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(p_sess->parent_fd, sock_fd); vsf_sysutil_close(sock_fd); }
void vsf_two_process_chown_upload(struct vsf_session* p_sess, int fd) { char res; priv_sock_send_cmd(p_sess->child_fd, PRIV_SOCK_CHOWN); priv_sock_send_fd(p_sess->child_fd, fd); res = priv_sock_get_result(p_sess->child_fd); if (res != PRIV_SOCK_RESULT_OK) { die("unexpected failure in vsf_two_process_chown_upload"); } }
static void privop_pasv_accept(session_t *sess) { // 因为服务器端给出的端口是随机的,accept 返回数据套接字关联的端口是进程独立的 int fd = accept_timeout(sess->pasv_listen_fd, NULL, tunable_accept_timeout); close(sess->pasv_listen_fd); sess->pasv_listen_fd = -1; if (fd < 0) { priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->nobody_fd, fd); close(fd); }
static void privop_pasv_accept(session_t *sess) { int fd = accept_timeout(sess->pasv_listen_fd, NULL, tunable_accept_timeout); close(sess->pasv_listen_fd); sess->pasv_listen_fd = -1; if (fd == -1) { priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->parent_fd, fd); close(fd); }
void PrivPar::privop_pasv_accept(session_t *sess) { int fd = sysutil::accept_timeout(sess->pasv_listen_fd, NULL, parseconfig->get_accept_timeout()); close(sess->pasv_listen_fd); sess->pasv_listen_fd = -1; if (fd == -1) { priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->parent_fd, fd); close(fd); }
/** * 创建数据连接通道 * @param sess [description] */ void PrivPar::privop_pasv_get_data_sock(session_t *sess) { /* nobody进程接收PRIV_SOCK_GET_DATA_SOCK命令 进一步接收一个整数,也就是port 接收一个字符串,也就是ip fd = socket bind(20) connect(ip, port); OK send_fd BAD */ unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd); char ip[16] = {0}; priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip)); //从ftp服务进程获取IP地址 struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); int fd = sysutil::tcp_client(20); if (fd == -1) { priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } if (sysutil::connect_timeout(fd, &addr, parseconfig->get_accept_timeout()) < 0) { close(fd); priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->parent_fd, fd); close(fd); }
static void privop_pasv_get_data_sock(session_t *sess) { /* socket bind 20 connect */ // tcp_client(20); /* */ char ip[16] = {0}; unsigned short port = (unsigned short)priv_sock_get_int(sess->parent_fd); priv_sock_recv_buf(sess->parent_fd, ip, sizeof(ip)); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); int fd = tcp_client(20); if (fd == -1) { priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } if (connect_timeout(fd, &addr, tunable_connect_timeout) < 0) { close(fd); priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->parent_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->parent_fd, fd); close(fd); }
int vsf_ftpdataio_post_mark_connect(struct vsf_session* p_sess) { int ret = 0; if (!p_sess->data_use_ssl) { return 1; } if (!p_sess->ssl_slave_active) { ret = ssl_accept(p_sess, p_sess->data_fd); } else { int sock_ret; priv_sock_send_cmd(p_sess->ssl_consumer_fd, PRIV_SOCK_DO_SSL_HANDSHAKE); priv_sock_send_fd(p_sess->ssl_consumer_fd, p_sess->data_fd); sock_ret = priv_sock_get_result(p_sess->ssl_consumer_fd); if (sock_ret == PRIV_SOCK_RESULT_OK) { ret = 1; } } if (ret != 1) { static struct mystr s_err_msg; str_alloc_text(&s_err_msg, "SSL connection failed"); if (tunable_require_ssl_reuse) { str_append_text(&s_err_msg, "; session reuse required"); str_append_text( &s_err_msg, ": see require_ssl_reuse option in vsftpd.conf man page"); } vsf_cmdio_write_str(p_sess, FTP_DATATLSBAD, &s_err_msg); } return ret; }
static void privop_port_get_data_sock(session_t *sess) { unsigned short port = (unsigned short)priv_sock_get_int(sess->nobody_fd); char ip[20] = {0}; priv_sock_recv_buf(sess->nobody_fd, ip, sizeof(ip)); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = inet_addr(ip); // 当多个客户端连接服务器时,可以同时有多个nobody进程bind 20端口+ip,因为此时客户端给出的端口是随机的,故 // 四元组还是能识别一个数据连接 // 当客户端位于NAT服务器之后使用PORT模式时,需要在NAT服务器上配置映射才能让服务器主动连接到客户端 // 所以采用的是标准固定的20端口,这样NAT服务器就不用维护很多的表目 int fd = tcp_client(20); if (fd == -1) { priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_BAD); return; } if (connect_timeout(fd, &addr, tunable_connect_timeout) < 0) { close(fd); priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_BAD); return; } priv_sock_send_result(sess->nobody_fd, PRIV_SOCK_RESULT_OK); priv_sock_send_fd(sess->nobody_fd, fd); close(fd); //父进程必须close(fd),否则子进程关闭close(data_fd)的时候也不会发送FIN段。 //因为通过unix域协议传递套接字等于是对方也打开套接字,而直接简单的赋值是没有这样的效果的。 }