6 * init_session.c - Preparing to serve one client.
11 #define ERR_FINISH_MSG "421 Cannot attend you now, sorry.\r\n"
16 * Returns a random non-privileged port, range 1025..65536
18 static inline unsigned short get_random_port (void)
24 byte
= (unsigned char) rand();
27 byte
= (unsigned char) rand();
35 void init_session (int cmd_sk
)
39 struct sockaddr_in saddr
;
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
);
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);
59 send_reply(cmd_sk
, ERR_FINISH_MSG
);
60 fatal("Could not create data socket");
63 /* 9 random tries to get an available port */
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
);
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
);
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
88 strncpy(address
, inet_ntoa(saddr
.sin_addr
), 16);
89 for (i
= 0; i
< 16; i
++) {
90 if (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 */
105 S_passive_bind_sk
= sk
;
108 send_reply(cmd_sk
, "220 User FTP Server ready.\r\n");