Removed non portable -v flag for rm command.
[uftps.git] / open_data_channel.c
blobf5bc8e5161a5a285804bbdf053b5af5436c9d007
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 #ifndef __MINGW32__
22 # include <sys/socket.h>
23 # include <arpa/inet.h>
24 # include <unistd.h>
25 #endif
29 * Open a data channel in passive mode. Return the socket of the data channel
30 * if successful, -1 on any failure.
32 static int passive_connection (void)
34 int sk, e;
35 struct sockaddr_in sai;
36 socklen_t sai_len = sizeof(struct sockaddr_in);
38 sk = accept(SS.passive_sk, NULL, NULL);
40 /* Passive socket not needed anymore */
41 closesocket(SS.passive_sk);
42 SS.passive_sk = -1;
44 if (sk == -1)
45 return -1;
47 /* Check if this new connection comes from the same IP as the client */
48 e = getpeername(sk, (struct sockaddr *) &sai, &sai_len);
49 if (e == -1 || sai.sin_addr.s_addr != SS.client_address.sin_addr.s_addr)
51 if (e == -1)
52 error("Getting remote data socket address");
53 else
54 warning("A different client (%s) connected to a passive socket",
55 inet_ntoa(sai.sin_addr));
56 closesocket(sk);
57 return -1;
60 return sk;
65 * Open a data channel in active mode. Return the socket of the data channel if
66 * successful, -1 on any failure.
68 * Note that peer IP check is not needed here because it was performed directly
69 * on the PORT request.
71 static int active_connection (void)
73 int sk, e;
75 sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
76 if (sk == -1)
77 return -1;
79 e = connect(sk, (struct sockaddr *) &SS.port_destination,
80 sizeof(struct sockaddr_in));
81 if (e == -1)
83 error("Initiating active data connection");
84 closesocket(sk);
85 return -1;
88 return sk;
93 * Open the data channel. When successful, the "data_sk" session field is set
94 * to the data channel socket and zero is returned. If the connection
95 * establishment fails, -1 is returned and the client is notified.
97 int open_data_channel (void)
99 int sk;
101 switch (SS.mode)
103 case ACTIVE_MODE:
104 sk = active_connection();
105 break;
106 case PASSIVE_MODE:
107 sk = passive_connection();
108 break;
109 case DEFAULT_MODE:
110 default:
111 warning("No data transfer mode selected");
112 reply_c("425 Default data transfer mode unsupported.\r\n");
113 return -1;
116 SS.mode = DEFAULT_MODE;
118 if (sk == -1)
120 error("Opening data connection");
121 reply_c("425 Can't open data connection.\r\n");
122 return -1;
125 SS.data_sk = sk;
126 return 0;