Coding style fix.
[uftps.git] / init_session.c
blob98cddeba8089dc77d833493f5fdffba972ffa36c
1 /*
2 * User FTP Server
3 * Autor : C2H5OH
4 * License: GPL v2
6 * init_session.c - Preparing to serve one client.
7 */
9 #include "uftps.h"
11 #define ERR_FINISH_MSG "421 Cannot attend you now, sorry.\r\n"
14 * get_random_port
16 * Returns a random non-privileged port, range 1025..65536
18 static inline unsigned short get_random_port (void)
20 unsigned char byte;
21 unsigned short port;
23 port = 0x0000U;
24 byte = (unsigned char) rand();
25 port |= byte;
26 port <<= 8;
27 byte = (unsigned char) rand();
28 port |= byte;
29 if (port < 1024)
30 port += 1024;
31 return port;
35 void init_session (int cmd_sk)
37 unsigned short port;
38 int err, i, sk;
39 struct sockaddr_in saddr;
40 socklen_t saddr_len;
41 char address[16];
43 /* Get my own IP. As the server is listening to all network interfaces,
44 * we won't know the real IP until we are connected to someone */
45 saddr_len = (socklen_t) sizeof(saddr);
46 err = getsockname(cmd_sk, (struct sockaddr *) &saddr, &saddr_len);
47 if (err == -1) {
48 send_reply(cmd_sk, ERR_FINISH_MSG);
49 fatal("trying to get my own address");
52 debug_msg("* Local address: %s\n", inet_ntoa(saddr.sin_addr));
54 /* Create a data socket to use in passive mode. This socket is cached
55 * and only one of these sockets is created per client. Thus, the
56 * response to PASV is easier (and, maybe, quicker) */
57 sk = socket(PF_INET, SOCK_STREAM, 0);
58 if (sk == -1) {
59 send_reply(cmd_sk, ERR_FINISH_MSG);
60 fatal("Could not create data socket");
63 /* 9 random tries to get an available port */
64 i = 1;
65 err = -1;
66 setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &i, sizeof (i));
67 srand((unsigned int) times (NULL));
68 for (i = 9; i > 0 && err == -1; i--) {
69 port = get_random_port();
70 saddr.sin_port = htons(port);
71 err = bind(sk, (struct sockaddr *) &saddr, saddr_len);
73 if (i <= 0) {
74 send_reply(cmd_sk, ERR_FINISH_MSG);
75 fatal("Could not find any bindable port");
78 debug_msg("* Number of bind() tries for PASV port: %d\n", 9 - i);
80 err = listen(sk, 1);
81 if (err == -1) {
82 send_reply(cmd_sk, ERR_FINISH_MSG);
83 fatal("cannot listen on port");
86 /* As de passive socket is cached, we can do the same for the PASV
87 * response string */
88 strncpy(address, inet_ntoa(saddr.sin_addr), 16);
89 for (i = 0; i < 16; i++) {
90 if (address[i] == '.')
91 address[i] = ',';
93 snprintf(S_passive_str, 64,
94 "227 Entering Passive Mode (%s,%d,%d).\r\n", address,
95 port >> 8, port & 0x00FF);
97 debug_msg("* Passive data port: %d\n", port);
98 debug_msg("* Passive string reply: %s", S_passive_str);
100 /* Set up the rest of the session state variables, except for Basedir
101 * which is inherited from uftps.c */
102 S_cmd_sk = cmd_sk;
103 S_data_sk = -1;
104 S_offset = 0;
105 S_passive_bind_sk = sk;
106 S_passive_mode = 0;
108 send_reply(cmd_sk, "220 User FTP Server ready.\r\n");