Renamed the sendfile RETR flavour to linux.
[uftps.git] / enable_passive.c
blob9e3dc8e6ccb35bafe23be227aa49cefb6f2e1d47
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 #include <arpa/inet.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdio.h>
28 * PASV command implementation. Nothing else to mention here, read the FTP RFC
29 * if you don't know about data transmission in passive mode.
31 void enable_passive (void)
33 int bsk, l, e;
34 struct sockaddr_in sai;
35 socklen_t sai_len = sizeof(struct sockaddr_in);
36 unsigned char addr[6];
37 char pasv_reply[32];
39 /* Safety check in case there was some error before */
40 if (SS.passive_sk != -1)
42 close(SS.passive_sk);
43 SS.passive_sk = -1;
44 SS.mode = DEFAULT_MODE;
47 bsk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
48 if (bsk == -1)
50 error("Creating passive socket");
51 goto out_error;
53 e = 1;
54 setsockopt(bsk, SOL_SOCKET, SO_REUSEADDR, &e, sizeof(int));
56 /* In case there are various network interfaces, bind only to the one
57 * the client is connected to; and use port 0 to let the system choose
58 * one for us */
59 sai_len = sizeof(struct sockaddr_in);
60 memcpy(&sai, &SS.local_address, sizeof(struct sockaddr_in));
61 sai.sin_port = 0;
62 e = bind(bsk, (struct sockaddr *) &sai, sai_len);
63 if (e == -1)
65 error("Binding to a random port");
66 goto out_error;
68 e = listen(bsk, 1);
69 if (e == -1)
71 error("Listening on passive socket");
72 goto out_error;
75 /* Check what port number we were assigned */
76 e = getsockname(bsk, (struct sockaddr *) &sai, &sai_len);
77 if (e == -1)
79 error("Retrieving passive socket information");
80 goto out_error;
82 debug("Passive mode listening on port %d", ntohs(sai.sin_port));
84 /* String conversion is straightforward in IPv4, provided that all
85 * fields in sockaddr_in structures are in network byte order */
86 memcpy(&addr[0], &sai.sin_addr, 4);
87 memcpy(&addr[4], &sai.sin_port, 2);
88 l = snprintf(pasv_reply, 32, "227 =%u,%u,%u,%u,%u,%u\r\n", addr[0],
89 addr[1], addr[2], addr[3], addr[4], addr[5]);
91 SS.passive_sk = bsk;
92 SS.mode = PASSIVE_MODE;
93 reply(pasv_reply, l);
94 return;
96 out_error:
97 close(bsk); /* bsk could be -1; never mind, only produces EBADF */
98 reply_c("425 No way to open a port.\r\n");