Removed non portable -v flag for rm command.
[uftps.git] / enable_passive.c
blob3743b91241d33bc10bb8a5112bd069f80d067902
1 /*
2 * User FTP Server, Share folders over FTP without being root.
3 * Copyright (C) 2008 Isaac Jurado
5 * This program is free software; you can redistribute it and/or modify it under
6 * the terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
8 * version.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "uftps.h"
21 #ifdef __MINGW32__
22 # include "hase.h"
23 #else
24 # include <sys/socket.h>
25 # include <arpa/inet.h>
26 # include <unistd.h>
27 #endif
28 #include <string.h>
29 #include <stdio.h>
33 * PASV command implementation. Nothing else to mention here, read the FTP RFC
34 * if you don't know about data transmission in passive mode.
36 void enable_passive (void)
38 int bsk, l, e;
39 struct sockaddr_in sai;
40 socklen_t sai_len = sizeof(struct sockaddr_in);
41 unsigned char addr[6];
42 char pasv_reply[32];
44 /* Safety check in case there was some error before */
45 if (SS.passive_sk != -1)
47 closesocket(SS.passive_sk);
48 SS.passive_sk = -1;
49 SS.mode = DEFAULT_MODE;
52 bsk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
53 if (bsk == -1)
55 error("Creating passive socket");
56 goto out_error;
58 e = 1;
59 setsockopt(bsk, SOL_SOCKET, SO_REUSEADDR, CCP_CAST &e, sizeof(int));
61 /* In case there are various network interfaces, bind only to the one
62 * the client is connected to; and use port 0 to let the system choose
63 * one for us */
64 sai_len = sizeof(struct sockaddr_in);
65 memcpy(&sai, &SS.local_address, sai_len);
66 sai.sin_port = 0;
67 e = bind(bsk, (struct sockaddr *) &sai, sai_len);
68 if (e == -1)
70 error("Binding to a random port");
71 goto out_error;
73 e = listen(bsk, 1);
74 if (e == -1)
76 error("Listening on passive socket");
77 goto out_error;
80 /* Check what port number we were assigned */
81 e = getsockname(bsk, (struct sockaddr *) &sai, &sai_len);
82 if (e == -1)
84 error("Retrieving passive socket information");
85 goto out_error;
87 debug("Passive mode listening on port %d", ntohs(sai.sin_port));
89 /* String conversion is straightforward in IPv4, provided that all
90 * fields in sockaddr_in structures are in network byte order */
91 memcpy(&addr[0], &sai.sin_addr, 4);
92 memcpy(&addr[4], &sai.sin_port, 2);
93 l = snprintf(pasv_reply, 32, "227 =%u,%u,%u,%u,%u,%u\r\n", addr[0],
94 addr[1], addr[2], addr[3], addr[4], addr[5]);
96 SS.passive_sk = bsk;
97 SS.mode = PASSIVE_MODE;
98 reply(pasv_reply, l);
99 return;
101 out_error:
102 closesocket(bsk); /* bsk could be -1; never mind, only produces EBADF */
103 reply_c("425 No way to open a port.\r\n");