2 * TUX - Integrated Application Protocols Layer and Object Cache
4 * Copyright (C) 2000, 2001, Ingo Molnar <mingo@redhat.com>
6 * ftp_proto.c: FTP application protocol support
9 #define __KERNEL_SYSCALLS__
12 /****************************************************************
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 ****************************************************************/
29 #define HELLO "220 Linux/TUX 3.0 FTP server welcomes you!\r\n"
30 #define WRITE_DONE "226 Transfer complete.\r\n"
31 #define BAD_FILENAME "550 No such file or directory.\r\n"
32 #define GOOD_DIR "250 CWD command successful.\r\n"
33 #define LIST_ERR "503 LIST without PORT! Closing connection.\r\n"
34 #define LIST_ERR_MEM "503 LIST could not allocate memory! Closing connection.\r\n"
35 #define WRITE_FILE "150 Opening BINARY mode data connection.\r\n"
36 #define WRITE_LIST "150 Opening ASCII mode data connection.\r\n"
37 #define RETR_ERR "503 RETR without PORT! Closing connection.\r\n"
38 #define PORT_OK "200 PORT command successful.\r\n"
39 #define LOGIN_OK "230-There are currently %d users logged in, out of %d maximum.\r\n230-Bandwidth served by TUX currently: %d KB/sec\r\n230 TUX Guest login ok.\r\n"
40 #define LOGIN_OK_ONE "230-There is currently 1 user logged in, out of %d maximum.\r\n230-Bandwidth served by TUX currently: %d KB/sec\r\n230 TUX Guest login ok.\r\n"
41 #define LOGIN_OK_PASS "230 TUX Guest login ok.\r\n"
42 #define LOGIN_FORBIDDEN "530 Sorry, Login Denied!\r\n"
43 #define TYPE_OK "200 Type set to I.\r\n"
44 #define BYE "221 Thank You for using TUX!\r\n"
45 #define NOT_IMPLEMENTED "502 Command not implemented.\r\n"
46 #define CLOSE_2 "221 Cannot handle request, closing connection!\r\n"
47 #define CLOSE "500 Unknown command.\r\n"
48 #define CLOSE_TIMEOUT "421 Timeout, closing connection!\r\n"
49 #define LINUX_SYST "215 UNIX Type: L8, Linux/TUX/3.0\r\n"
50 #define COMMAND_OK "200 Command OK.\r\n"
51 #define REST_OK "350 Restart offset OK.\r\n"
52 #define WRITE_ABORTED "426 Transfer aborted, data connection closed.\r\n"
53 #define SITE "214 No SITE commands are recognized.\r\n"
57 unsigned long last_measurement;
58 unsigned int ftp_bytes_sent;
59 unsigned int ftp_bandwidth;
61 static void __update_bandwidth (tux_req_t *req, unsigned int bytes)
64 * Bandwidth measurement. Not completely accurate,
65 * but it's good enough and lightweight enough.
67 if (jiffies >= last_measurement + INTERVAL*HZ) {
68 ftp_bandwidth = (ftp_bytes_sent + 1023)/INTERVAL/1024;
70 last_measurement = jiffies;
73 atomic_add(bytes, (atomic_t *)&ftp_bytes_sent);
74 Dprintk("update_bandwidth(%p,%d), bytes_sent: %d, bandwidth: %d.\n",
75 req, bytes, ftp_bytes_sent, ftp_bandwidth);
78 #define update_bandwidth(req,bytes) \
80 if (unlikely(tux_ftp_login_message)) \
81 __update_bandwidth(req, bytes); \
84 static inline void __ftp_send_async_message (tux_req_t *req,
85 const char *message, int status, unsigned int size)
87 update_bandwidth(req, size);
88 __send_async_message(req, message, status, size, 1);
91 #define ftp_send_async_message(req,str,status) \
92 __ftp_send_async_message(req,str,status,sizeof(str)-1)
95 static void ftp_flush_req (tux_req_t *req, int cachemiss)
97 tux_push_pending(req->sock->sk);
98 add_req_to_workqueue(req);
101 static void ftp_execute_command (tux_req_t *req, int cachemiss);
103 static void ftp_lookup_vhost (tux_req_t *req, int cachemiss)
105 struct dentry *dentry;
106 struct nameidata base = { };
107 struct vfsmount *mnt = NULL;
108 unsigned int flag = cachemiss ? 0 : LOOKUP_ATOMIC;
109 char ip[3+1+3+1+3+1+3 + 2];
111 sprintf(ip, "%d.%d.%d.%d", NIPQUAD(inet_sk(req->sock->sk)->rcv_saddr));
112 Dprintk("ftp_lookup_vhost(%p, %d, virtual: %d, host: %s.)\n",
113 req, flag, req->virtual, ip);
115 base.flags = LOOKUP_FOLLOW|flag;
116 base.last_type = LAST_ROOT;
117 base.dentry = dget(req->proto->main_docroot.dentry);
118 base.mnt = mntget(req->proto->main_docroot.mnt);
120 dentry = __tux_lookup(req, ip, &base, &mnt);
122 Dprintk("looked up dentry %p.\n", dentry);
123 if (dentry && !IS_ERR(dentry) && !dentry->d_inode)
126 if (!dentry || IS_ERR(dentry)) {
127 if (PTR_ERR(dentry) == -EWOULDBLOCKIO) {
128 add_tux_atom(req, ftp_lookup_vhost);
129 queue_cachemiss(req);
135 req->docroot_dentry = dentry;
136 req->docroot_mnt = mnt;
138 add_tux_atom(req, ftp_execute_command);
139 add_req_to_workqueue(req);
153 add_req_to_workqueue(req);
156 static void ftp_got_request (tux_req_t *req)
158 add_tux_atom(req, parse_request);
159 add_tux_atom(req, ftp_flush_req);
160 ftp_send_async_message(req, HELLO, 220);
163 #define GOTO_ERR { TDprintk("FTP protocol error at: %s:%d\n", \
164 __FILE__, __LINE__); goto error; }
166 static void zap_data_socket (tux_req_t *req)
170 Dprintk("zapping req %p's data socket %p.\n", req, req->data_sock);
172 unlink_tux_data_socket(req);
173 sock_release(req->data_sock);
174 req->data_sock = NULL;
177 static int parse_ftp_message (tux_req_t *req, const int total_len)
179 int comm, comm1 = 0, comm2 = 0, comm3 = 0, comm4 = 0;
181 const char *mess, *curr;
183 curr = mess = req->headers;
185 Dprintk("FTP parser got %d bytes: --->{%s}<---\n", total_len, curr);
188 for (i = 0; i < total_len; i++, curr++) {
191 if (!(*curr == '\r') || !(*(curr+1) == '\n'))
196 Dprintk("Newline pos: %d\n", newline_pos);
197 if (newline_pos == -1) {
198 Dprintk("incomplete mess on req %p!\n", req);
204 #define toup(c) ((((c) >= 'a') && ((c) <= 'z')) ? ((c) + 'A' - 'a') : (c))
206 #define STRING_VAL(c1,c2,c3,c4) \
207 (toup(c1) + (toup(c2) << 8) + (toup(c3) << 16) + (toup(c4) << 24))
209 #define STRING_VAL_STR(str) \
210 STRING_VAL(str[0], str[1], str[2], str[3])
212 Dprintk("string val (%c%c%c%c): %08x\n",
213 mess[0], mess[1], mess[2], mess[3],
214 STRING_VAL_STR(mess));
216 #define PARSE_FTP_COMM(c1,c2,c3,c4,name,num) \
217 if (STRING_VAL_STR(mess) == STRING_VAL(c1,c2,c3,c4)) \
219 Dprintk("parsed "#name".\n"); \
220 comm##num = FTP_COMM_##name; \
223 PARSE_FTP_COMM('A','C','C','T', ACCT,2);
224 PARSE_FTP_COMM('C','D','U','P', CDUP,3);
225 PARSE_FTP_COMM('S','M','N','T', SMNT,4);
226 PARSE_FTP_COMM('Q','U','I','T', QUIT,1);
227 PARSE_FTP_COMM('R','E','I','N', REIN,2);
228 PARSE_FTP_COMM('P','A','S','V', PASV,3);
229 PARSE_FTP_COMM('S','T','R','U', STRU,4);
230 PARSE_FTP_COMM('S','T','O','R', STOR,2);
231 PARSE_FTP_COMM('S','T','O','U', STOU,3);
232 PARSE_FTP_COMM('A','P','P','E', APPE,4);
233 PARSE_FTP_COMM('A','L','L','O', ALLO,1);
234 PARSE_FTP_COMM('R','N','F','R', RNFR,2);
235 PARSE_FTP_COMM('R','N','T','O', RNTO,3);
236 PARSE_FTP_COMM('A','B','O','R', ABOR,4);
237 PARSE_FTP_COMM('D','E','L','E', DELE,1);
238 PARSE_FTP_COMM('R','M','D',' ', RMD, 2);
239 PARSE_FTP_COMM('M','K','D',' ', MKD, 3);
240 PARSE_FTP_COMM('P','W','D',' ', PWD, 4);
241 PARSE_FTP_COMM('S','Y','S','T', SYST,2);
242 PARSE_FTP_COMM('N','O','O','P', NOOP,3);
243 PARSE_FTP_COMM('F','E','A','T', FEAT,4);
245 comm = comm1 | comm2 | comm3 | comm4;
248 if (newline_pos != 4)
250 req->ftp_command = comm;
254 switch (STRING_VAL(mess[0], mess[1], mess[2], mess[3])) {
256 #define PARSE_FTP_COMM_3CHAR(c1,c2,c3,name) \
257 case STRING_VAL(c1,c2,c3,'\r'): \
259 Dprintk("parsed "#name".\n"); \
260 req->ftp_command = FTP_COMM_##name; \
261 if (newline_pos != 3) \
265 #define PARSE_FTP_3CHAR_COMM_IGNORE(c1,c2,c3,name) \
266 case STRING_VAL(c1,c2,c3,' '): \
268 Dprintk("parsed "#name".\n"); \
269 req->ftp_command = FTP_COMM_##name; \
272 #define PARSE_FTP_COMM_IGNORE(c1,c2,c3,c4,name) \
273 case STRING_VAL(c1,c2,c3,c4): \
275 Dprintk("parsed "#name".\n"); \
276 req->ftp_command = FTP_COMM_##name; \
279 #define PARSE_FTP_3CHAR_COMM_1_FIELD(c1,c2,c3,name,field,field_len,max) \
280 case STRING_VAL(c1,c2,c3,' '): \
282 Dprintk("parsed "#name".\n"); \
283 req->ftp_command = FTP_COMM_##name; \
284 if (newline_pos == 4) \
286 if (newline_pos >= 5) { \
288 if (*curr++ != ' ') \
290 *(field_len) = newline_pos-4; \
291 if (*(field_len) >= max) \
293 memcpy(field, curr, *(field_len)); \
294 (field)[*(field_len)] = 0; \
298 #define PARSE_FTP_COMM_1_FIELD(c1,c2,c3,c4,name,field,field_len,max) \
299 case STRING_VAL(c1,c2,c3,c4): \
301 Dprintk("parsed "#name".\n"); \
302 req->ftp_command = FTP_COMM_##name; \
303 if (newline_pos < 4) \
305 if (newline_pos == 4) \
309 if (*curr++ != ' ') \
311 *(field_len) = newline_pos-5; \
312 if (*(field_len) >= max) \
314 memcpy(field, curr, *(field_len)); \
315 (field)[*(field_len)] = 0; \
319 PARSE_FTP_COMM_1_FIELD('U','S','E','R', USER,
320 req->username, &req->username_len,
322 if (!req->username_len)
327 #define MAX_PASS_LEN 100
328 char pass[MAX_PASS_LEN];
329 unsigned int pass_len;
330 PARSE_FTP_COMM_1_FIELD('P','A','S','S', PASS,
338 PARSE_FTP_3CHAR_COMM_1_FIELD('C','W','D', CWD,
339 req->objectname, &req->objectname_len,
340 MAX_OBJECTNAME_LEN-1);
341 if (!req->objectname_len)
343 req->uri_str = req->objectname;
344 req->uri_len = req->objectname_len;
347 PARSE_FTP_COMM_3CHAR('P','W','D', PWD); break;
351 unsigned int type_len;
353 PARSE_FTP_COMM_1_FIELD('T','Y','P','E', TYPE,
357 if ((type[0] != 'I') && (type[0] != 'A'))
362 PARSE_FTP_COMM_1_FIELD('R','E','T','R', RETR,
363 req->objectname, &req->objectname_len,
364 MAX_OBJECTNAME_LEN-1);
365 if (!req->objectname_len) {
366 zap_data_socket(req);
367 req->ftp_command = FTP_COMM_NONE;
369 req->uri_str = req->objectname;
370 req->uri_len = req->objectname_len;
373 PARSE_FTP_COMM_1_FIELD('S','I','Z','E', SIZE,
374 req->objectname, &req->objectname_len,
375 MAX_OBJECTNAME_LEN-1);
376 if (!req->objectname_len)
377 req->ftp_command = FTP_COMM_NONE;
378 req->uri_str = req->objectname;
379 req->uri_len = req->objectname_len;
382 PARSE_FTP_COMM_1_FIELD('M','D','T','M', MDTM,
383 req->objectname, &req->objectname_len,
384 MAX_OBJECTNAME_LEN-1);
385 if (!req->objectname_len)
386 req->ftp_command = FTP_COMM_NONE;
387 req->uri_str = req->objectname;
388 req->uri_len = req->objectname_len;
391 PARSE_FTP_COMM_IGNORE('M','O','D','E', MODE);
394 PARSE_FTP_COMM_IGNORE('S','T','A','T', STAT);
397 PARSE_FTP_COMM_IGNORE('S','I','T','E', SITE);
400 PARSE_FTP_COMM_1_FIELD('L','I','S','T', LIST,
401 req->objectname, &req->objectname_len,
402 MAX_OBJECTNAME_LEN-1);
403 if (req->objectname[0] == '-') {
404 req->objectname_len = 0;
405 req->objectname[0] = 0;
407 if (req->objectname_len) {
408 req->uri_str = req->objectname;
409 req->uri_len = req->objectname_len;
413 PARSE_FTP_COMM_1_FIELD('N','L','S','T', NLST,
414 req->objectname, &req->objectname_len,
415 MAX_OBJECTNAME_LEN-1);
416 if (req->objectname[0] == '-') {
417 req->objectname_len = 0;
418 req->objectname[0] = 0;
420 if (req->objectname_len) {
421 req->uri_str = req->objectname;
422 req->uri_len = req->objectname_len;
426 PARSE_FTP_COMM_IGNORE('H','E','L','P', HELP);
429 PARSE_FTP_COMM_IGNORE('C','L','N','T', CLNT);
432 #define IS_NUM(n) (((n) >= '0') && ((n) <= '9'))
434 #define GET_DIGIT(curr,n) \
435 n += (*curr) - '0'; \
437 if (IS_NUM(*curr)) { \
440 #define PARSE_PORTNUM(curr,n) \
442 Dprintk("PORT NUM parser:--->{%s}<---\n", curr);\
443 if (!IS_NUM(*curr)) \
452 Dprintk("PORT NUM parser:--->{%s}<---\n", curr);\
453 Dprintk("PORT NUM parser parsed %d.\n", n); \
456 #define PARSE_NUM(curr,n) \
458 Dprintk("NUM parser:--->{%s}<---\n", curr); \
459 if (!IS_NUM(*curr)) \
473 Dprintk("NUM parser:--->{%s}<---\n", curr); \
474 Dprintk("NUM parser parsed %d.\n", n); \
477 case STRING_VAL('P','O','R','T'):
479 unsigned int h1, h2, h3, h4, p1, p2;
481 zap_data_socket(req);
483 * Minimum size: "PORT 0,0,0,0,0,0", 16 bytes.
485 if (newline_pos < 16)
487 Dprintk("parsed PORT.\n");
493 PARSE_PORTNUM(curr,h1);
496 PARSE_PORTNUM(curr,h2);
499 PARSE_PORTNUM(curr,h3);
502 PARSE_PORTNUM(curr,h4);
505 PARSE_PORTNUM(curr,p1);
508 PARSE_PORTNUM(curr,p2);
509 if (curr-mess != newline_pos)
511 req->ftp_command = FTP_COMM_PORT;
512 req->ftp_user_addr = (h1<<24) + (h2<<16) + (h3<<8) + h4;
513 req->ftp_user_port = (p1<<8) + p2;
514 Dprintk("FTP PORT got: %d.%d.%d.%d:%d.\n",
515 h1, h2, h3, h4, req->ftp_user_port);
516 Dprintk("FTP user-addr: %08x (htonl: %08x), socket: %08x.\n",
517 req->ftp_user_addr, htonl(req->ftp_user_addr),
518 inet_sk(req->sock->sk)->daddr);
520 * Do not allow redirection of connections, and do
521 * not allow reserved ports to be accessed.
523 if (inet_sk(req->sock->sk)->daddr != htonl(req->ftp_user_addr))
525 if (req->ftp_user_port < 1024)
529 case STRING_VAL('R','E','S','T'):
534 * Minimum size: "REST 0", 6 bytes.
538 Dprintk("parsed REST.\n");
542 PARSE_NUM(curr,offset);
543 if (curr-mess != newline_pos)
545 req->ftp_command = FTP_COMM_REST;
546 req->ftp_offset_start = offset;
547 Dprintk("FTP REST got: %d bytes offset.\n", offset);
552 req->ftp_command = FTP_COMM_NONE;
557 req->parsed_len = newline_pos + 2;
559 req->virtual = tux_ftp_virtual_server;
561 add_tux_atom(req, ftp_lookup_vhost);
563 req->docroot_dentry = dget(req->proto->main_docroot.dentry);
564 req->docroot_mnt = mntget(req->proto->main_docroot.mnt);
565 add_tux_atom(req, ftp_execute_command);
568 return req->parsed_len;
570 clear_keepalive(req);
571 TDprintk("rejecting FTP session!\n");
572 TDprintk("mess :--->{%s}<---\n", mess);
573 TDprintk("mess left:--->{%s}<---\n", curr);
578 static void ftp_wait_close (tux_req_t *req, int cachemiss);
579 static void ftp_wait_syn (tux_req_t *req, int cachemiss);
581 static int ftp_check_req_err (tux_req_t *req, int cachemiss)
583 int state = req->sock->sk->sk_state;
584 int err = req->sock->sk->sk_err | req->error;
585 int urg = tcp_sk(req->sock->sk)->urg_data;
587 if (req->data_sock) {
588 urg |= tcp_sk(req->data_sock->sk)->urg_data;
589 state |= req->data_sock->sk->sk_state;
590 err |= req->data_sock->sk->sk_err;
593 if ((state <= TCP_SYN_RECV) && !err) {
596 req->in_file->f_pos = 0;
597 add_tux_atom(req, flush_request);
598 zap_data_socket(req);
599 ftp_send_async_message(req, WRITE_ABORTED, 426);
602 #ifdef CONFIG_TUX_DEBUG
603 req->bytes_expected = 0;
607 req->in_file->f_pos = 0;
608 TDprintk("zapping, data sock state: %d (err: %d, urg: %d)\n",
611 * We are in the middle of a file transfer,
612 * zap it immediately:
614 req->error = TUX_ERROR_CONN_CLOSE;
615 zap_request(req, cachemiss);
619 void ftp_send_file (tux_req_t *req, int cachemiss)
623 SET_TIMESTAMP(req->output_timestamp);
625 ret = generic_send_file(req, req->data_sock, cachemiss);
626 update_bandwidth(req, req->in_file->f_pos - req->prev_pos);
627 req->prev_pos = req->in_file->f_pos;
631 add_tux_atom(req, ftp_send_file);
635 add_tux_atom(req, ftp_send_file);
636 if (add_output_space_event(req, req->data_sock)) {
642 add_tux_atom(req, ftp_send_file);
643 queue_cachemiss(req);
648 req->in_file->f_pos = 0;
650 if (tux_ftp_wait_close) {
651 req->data_sock->ops->shutdown(req->data_sock, SEND_SHUTDOWN);
652 add_tux_atom(req, ftp_wait_close);
653 add_req_to_workqueue(req);
656 Dprintk("FTP send file req %p finished!\n", req);
657 zap_data_socket(req);
658 add_tux_atom(req, ftp_flush_req);
660 ftp_send_async_message(req, BAD_FILENAME, 200);
662 ftp_send_async_message(req, WRITE_DONE, 200);
668 (!(sk)->sk_err && ((1 << (sk)->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)))
669 #define req_syn(req) \
670 (!(req)->error && sk_syn((req)->data_sock->sk))
672 static void ftp_wait_syn (tux_req_t *req, int cachemiss)
674 Dprintk("ftp_wait_syn in: data socket state %d.\n", req->data_sock->state);
676 spin_lock_irq(&req->ti->work_lock);
677 add_keepalive_timer(req);
678 if (test_and_set_bit(0, &req->idle_input))
680 spin_unlock_irq(&req->ti->work_lock);
682 add_tux_atom(req, ftp_wait_syn);
687 Dprintk("ftp_wait_syn out: data socket state %d.\n", req->data_sock->state);
688 add_req_to_workqueue(req);
691 static void ftp_wait_close (tux_req_t *req, int cachemiss)
693 struct sock *sk = req->data_sock->sk;
695 Dprintk("ftp_wait_close: data socket state %d.\n", sk->sk_state);
697 if (!req->error && (sk->sk_state <= TCP_FIN_WAIT1) && !sk->sk_err) {
698 spin_lock_irq(&req->ti->work_lock);
699 add_keepalive_timer(req);
700 if (test_and_set_bit(0, &req->idle_input))
702 spin_unlock_irq(&req->ti->work_lock);
703 if (!req->error && (sk->sk_state <= TCP_FIN_WAIT1) && !sk->sk_err) {
704 add_tux_atom(req, ftp_wait_close);
709 zap_data_socket(req);
710 add_tux_atom(req, ftp_flush_req);
712 ftp_send_async_message(req, BAD_FILENAME, 200);
714 ftp_send_async_message(req, WRITE_DONE, 200);
717 void ftp_get_size (tux_req_t *req, int cachemiss)
723 missed = lookup_object(req, cachemiss ? 0 : LOOKUP_ATOMIC);
724 if (!missed && !req->dentry) {
725 ftp_send_async_message(req, BAD_FILENAME, 200);
731 add_tux_atom(req, ftp_get_size);
732 queue_cachemiss(req);
736 req->in_file->f_pos = 0;
737 len = sprintf(file_size, "213 %Li\r\n", req->dentry->d_inode->i_size);
738 __ftp_send_async_message(req, file_size, 200, len);
741 void ftp_get_mdtm (tux_req_t *req, int cachemiss)
743 unsigned int flag = cachemiss ? 0 : LOOKUP_ATOMIC;
744 struct dentry *dentry;
745 struct vfsmount *mnt = NULL;
750 dentry = tux_lookup(req, req->objectname, flag, &mnt);
751 if (!dentry || IS_ERR(dentry)) {
752 if (PTR_ERR(dentry) == -EWOULDBLOCKIO) {
755 add_tux_atom(req, ftp_get_mdtm);
756 queue_cachemiss(req);
761 err = permission(dentry->d_inode, MAY_READ, NULL);
765 req->in_file->f_pos = 0;
766 len = mdtm_time (file_mdtm, dentry->d_inode->i_mtime.tv_sec);
769 __ftp_send_async_message(req, file_mdtm, 200, len);
776 ftp_send_async_message(req, BAD_FILENAME, 550);
779 static void ftp_get_file (tux_req_t *req, int cachemiss)
784 missed = lookup_object(req, cachemiss ? 0 : LOOKUP_ATOMIC);
785 if (!missed && !req->dentry) {
786 ftp_send_async_message(req, BAD_FILENAME, 200);
792 add_tux_atom(req, ftp_get_file);
793 queue_cachemiss(req);
797 Dprintk("ftp_send_file %p, ftp_offset: %Ld, total_len: %Ld.\n", req, req->ftp_offset_start, req->total_file_len);
798 req->in_file->f_pos = 0;
799 if (req->ftp_offset_start) {
800 if (req->ftp_offset_start <= req->total_file_len) {
801 req->offset_start = req->ftp_offset_start;
802 req->in_file->f_pos = req->offset_start;
804 req->ftp_offset_start = 0;
806 req->output_len = req->total_file_len - req->offset_start;
807 req->prev_pos = req->in_file->f_pos;
808 Dprintk("ftp_send_file %p, f_pos: %Ld (out_len: %Ld).\n", req, req->in_file->f_pos, req->output_len);
809 add_tux_atom(req, ftp_send_file);
810 add_tux_atom(req, ftp_wait_syn);
811 add_tux_atom(req, ftp_flush_req);
812 ftp_send_async_message(req, WRITE_FILE, 200);
815 static void __exchange_sockets (tux_req_t *req)
819 tmp = req->data_sock;
820 req->data_sock = req->sock;
823 req->in_file->f_pos = 0;
826 static void ftp_do_ls_start (tux_req_t *req, int cachemiss)
828 Dprintk("ftp_do_ls_start(%p, %d).\n", req, cachemiss);
829 if (!req->cwd_dentry)
831 __exchange_sockets(req);
832 queue_cachemiss(req);
835 static void ftp_do_ls_end (tux_req_t *req, int cachemiss)
837 Dprintk("ftp_do_ls_end(%p, %d).\n", req, cachemiss);
838 __exchange_sockets(req);
839 if (tux_ftp_wait_close) {
840 req->data_sock->ops->shutdown(req->data_sock, SEND_SHUTDOWN);
841 add_tux_atom(req, ftp_wait_close);
842 add_req_to_workqueue(req);
845 zap_data_socket(req);
846 add_tux_atom(req, ftp_flush_req);
848 ftp_send_async_message(req, BAD_FILENAME, 200);
850 ftp_send_async_message(req, WRITE_DONE, 200);
853 static void ftp_chdir (tux_req_t *req, int cachemiss)
855 unsigned int flag = cachemiss ? 0 : LOOKUP_ATOMIC;
856 struct dentry *dentry;
857 struct vfsmount *mnt = NULL;
860 Dprintk("ftp_chdir(%p, %d, {%s})\n", req, cachemiss, req->objectname);
861 dentry = tux_lookup(req, req->objectname, flag, &mnt);
862 if (!dentry || IS_ERR(dentry)) {
863 if (PTR_ERR(dentry) == -EWOULDBLOCKIO) {
866 add_tux_atom(req, ftp_chdir);
867 queue_cachemiss(req);
872 err = permission(dentry->d_inode, MAY_EXEC, NULL);
875 req->cwd_dentry = dentry;
877 ftp_send_async_message(req, GOOD_DIR, 200);
884 ftp_send_async_message(req, BAD_FILENAME, 550);
887 void ftp_accept_pasv (tux_req_t *req, int cachemiss)
889 struct socket *sock, *new_sock = NULL;
890 struct inet_connection_sock *icsk1, *icsk2;
891 struct tcp_sock *tp1, *tp2;
894 tp1 = tcp_sk(req->data_sock->sk);
895 icsk1 = inet_csk(req->data_sock->sk);
897 Dprintk("PASV accept on req %p, accept_queue: %p.\n",
898 req, &icsk1->icsk_accept_queue);
899 if (req->error || (req->data_sock->sk->sk_state != TCP_LISTEN))
902 if (reqsk_queue_empty(&icsk1->icsk_accept_queue)) {
903 spin_lock_irq(&req->ti->work_lock);
904 add_keepalive_timer(req);
905 if (test_and_set_bit(0, &req->idle_input))
907 spin_unlock_irq(&req->ti->work_lock);
908 if (reqsk_queue_empty(&icsk1->icsk_accept_queue)) {
909 add_tux_atom(req, ftp_accept_pasv);
914 new_sock = sock_alloc();
917 sock = req->data_sock;
918 new_sock->type = sock->type;
919 new_sock->ops = sock->ops;
921 err = sock->ops->accept(sock, new_sock, O_NONBLOCK);
922 Dprintk("PASV accept() returned %d (state %d).\n", err, new_sock->sk->sk_state);
925 if (new_sock->sk->sk_state != TCP_ESTABLISHED)
928 * Do not allow other clients to steal the FTP connection!
930 if (inet_sk(new_sock->sk)->daddr != inet_sk(req->sock->sk)->daddr) {
931 Dprintk("PASV: ugh, unauthorized connect?\n");
932 sock_release(new_sock);
937 * Zap the listen socket:
939 zap_data_socket(req);
941 tp2 = tcp_sk(new_sock->sk);
942 icsk2 = inet_csk(new_sock->sk);
944 icsk2->icsk_ack.pingpong = tux_ack_pingpong;
945 new_sock->sk->sk_reuse = 1;
946 sock_set_flag(new_sock->sk, SOCK_URGINLINE);
947 sock_reset_flag(new_sock->sk, SOCK_LINGER);
949 link_tux_data_socket(req, new_sock);
950 add_req_to_workqueue(req);
955 sock_release(new_sock);
957 zap_data_socket(req);
958 ftp_send_async_message(req, CLOSE, 500);
961 static char * ftp_print_dir_line (tux_req_t *req, char *tmp, char *d_name, int d_len, int d_type, struct dentry *dentry, struct inode *inode)
966 if (req->ftp_command == FTP_COMM_NLST) {
967 memcpy(tmp, d_name, d_len);
978 if (tux_hide_unreadable)
984 if (tux_hide_unreadable)
990 if (tux_hide_unreadable)
1000 if (tux_hide_unreadable)
1014 if (tux_hide_unreadable)
1020 if (inode->i_mode & S_IRUSR) *tmp++ = 'r'; else *tmp++ = '-';
1021 if (inode->i_mode & S_IWUSR) *tmp++ = 'w'; else *tmp++ = '-';
1022 if (inode->i_mode & S_IXUSR) *tmp++ = 'x'; else *tmp++ = '-';
1023 if (inode->i_mode & S_IRGRP) *tmp++ = 'r'; else *tmp++ = '-';
1024 if (inode->i_mode & S_IWGRP) *tmp++ = 'w'; else *tmp++ = '-';
1025 if (inode->i_mode & S_IXGRP) *tmp++ = 'x'; else *tmp++ = '-';
1026 if (inode->i_mode & S_IROTH) *tmp++ = 'r'; else *tmp++ = '-';
1027 if (inode->i_mode & S_IWOTH) *tmp++ = 'w'; else *tmp++ = '-';
1028 if (inode->i_mode & S_IXOTH) *tmp++ = 'x'; else *tmp++ = '-';
1032 size = sprintf(tmp, "%4i %d", inode->i_nlink, inode->i_uid);
1038 memset(tmp, ' ', size);
1041 size = sprintf(tmp, "%d", inode->i_gid);
1047 memset(tmp, ' ', size);
1050 tmp += sprintf(tmp, "%8Li", inode->i_size);
1053 tmp += time_unix2ls(inode->i_mtime.tv_sec, tmp);
1056 memcpy(tmp, d_name, d_len);
1059 if (d_type == DT_LNK) {
1060 int len = 0, max_len;
1061 #define ARROW " -> "
1063 memcpy(tmp, ARROW, sizeof(ARROW)-1);
1064 tmp += sizeof(ARROW)-1;
1065 max_len = MAX_OBJECTNAME_LEN-(tmp-string0);
1066 if (inode->i_op && inode->i_op->readlink) {
1069 oldmm = get_fs(); set_fs(KERNEL_DS);
1071 len = inode->i_op->readlink(dentry, tmp, max_len);
1077 Dprintk("hm, readlink() returned %d.\n", len);
1088 static void ftp_do_ls_onefile (tux_req_t *req, int cachemiss)
1090 char string0[MAX_OBJECTNAME_LEN+200], *tmp;
1092 tmp = ftp_print_dir_line(req, string0, req->objectname, req->objectname_len,
1093 DT_REG, req->dentry, req->dentry->d_inode);
1096 add_req_to_workqueue(req);
1099 if (tmp - string0 >= MAX_OBJECTNAME_LEN+200)
1101 __ftp_send_async_message(req, string0, 200, tmp - string0);
1104 static void ftp_lookup_listfile (tux_req_t *req, int cachemiss)
1106 unsigned int flag = cachemiss ? 0 : LOOKUP_ATOMIC;
1107 struct dentry *dentry;
1108 struct vfsmount *mnt = NULL;
1111 Dprintk("ftp_lookup_listfile(%p, %d, {%s})\n", req, cachemiss, req->objectname);
1112 dentry = tux_lookup(req, req->objectname, flag, &mnt);
1113 if (!dentry || IS_ERR(dentry)) {
1114 if (PTR_ERR(dentry) == -EWOULDBLOCKIO) {
1117 add_tux_atom(req, ftp_lookup_listfile);
1118 queue_cachemiss(req);
1124 if (S_ISDIR(dentry->d_inode->i_mode)) {
1125 err = permission(dentry->d_inode, MAY_EXEC, NULL);
1127 Dprintk("Directory permission error: %d.\n", err);
1130 install_req_dentry(req, dentry, mnt);
1132 add_tux_atom(req, ftp_do_ls_end);
1133 if (!req->cwd_dentry)
1135 add_tux_atom(req, list_directory);
1137 install_req_dentry(req, dentry, mnt);
1139 add_tux_atom(req, ftp_do_ls_end);
1140 add_tux_atom(req, ftp_do_ls_onefile);
1143 add_tux_atom(req, ftp_do_ls_start);
1144 add_tux_atom(req, ftp_wait_syn);
1145 add_tux_atom(req, ftp_flush_req);
1146 ftp_send_async_message(req, WRITE_LIST, 200);
1153 ftp_send_async_message(req, BAD_FILENAME, 550);
1156 static void ftp_execute_command (tux_req_t *req, int cachemiss)
1158 if (!req->parsed_len)
1161 req->keep_alive = 1;
1163 switch (req->ftp_command) {
1166 "226 Abort successful.\r\n"
1170 zap_data_socket(req);
1171 ftp_send_async_message(req, ABORTED, 226);
1177 unsigned int str_len;
1180 buf = (char *)__get_free_page(GFP_KERNEL);
1183 ftp_send_async_message(req, LIST_ERR_MEM, 200);
1187 if (!req->cwd_dentry) {
1188 req->cwd_dentry = dget(req->docroot_dentry);
1189 req->cwd_mnt = mntget(req->docroot_mnt);
1192 // "257 "/" is current directory.\r\n"
1194 #define PART_1 "257 \""
1195 #define PART_1_LEN (sizeof(PART_1)-1)
1197 #define PART_3 "\" is current directory.\r\n"
1198 #define PART_3_LEN sizeof(PART_3)
1200 path = tux_print_path(req, req->cwd_dentry, req->cwd_mnt,
1201 buf+PART_1_LEN, PAGE_SIZE - PART_3_LEN - PART_1_LEN);
1203 if (path < buf + PART_1_LEN)
1206 memcpy(path - PART_1_LEN, PART_1, PART_1_LEN);
1207 memcpy(buf + PAGE_SIZE-PART_3_LEN-1, PART_3, PART_3_LEN);
1208 str_len = buf + PAGE_SIZE-1 - (path - PART_1_LEN) - 1;
1210 __ftp_send_async_message(req, path - PART_1_LEN, 226, str_len);
1211 free_page((unsigned long)buf);
1217 memcpy(req->objectname, "..", 3);
1218 req->objectname_len = 2;
1219 req->uri_str = req->objectname;
1220 req->uri_len = req->objectname_len;
1222 // fall through to CWD:
1226 ftp_chdir(req, cachemiss);
1233 if (!req->data_sock) {
1235 ftp_send_async_message(req, LIST_ERR, 200);
1240 if (!req->cwd_dentry) {
1241 req->cwd_dentry = dget(req->docroot_dentry);
1242 req->cwd_mnt = mntget(req->docroot_mnt);
1244 if (req->objectname_len)
1245 ftp_lookup_listfile(req, cachemiss);
1247 dget(req->cwd_dentry);
1248 mntget(req->cwd_mnt);
1249 install_req_dentry(req, req->cwd_dentry, req->cwd_mnt);
1252 add_tux_atom(req, ftp_do_ls_end);
1253 if (!req->cwd_dentry)
1255 add_tux_atom(req, list_directory);
1256 add_tux_atom(req, ftp_do_ls_start);
1257 add_tux_atom(req, ftp_wait_syn);
1258 add_tux_atom(req, ftp_flush_req);
1259 ftp_send_async_message(req, WRITE_LIST, 200);
1266 if (!req->data_sock) {
1268 ftp_send_async_message(req, RETR_ERR, 200);
1271 ftp_get_file(req, cachemiss);
1277 ftp_get_size(req, cachemiss);
1283 ftp_get_mdtm(req, cachemiss);
1289 char buf [36 + 4*3 + 5 + 10];
1290 struct socket *data_sock;
1291 struct sockaddr_in addr;
1292 unsigned int str_len;
1293 struct tcp_sock *tp;
1294 struct inet_connection_sock *icsk;
1299 zap_data_socket(req);
1301 * Create FTP data connection to client:
1303 err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_IP, &data_sock);
1305 Dprintk("sock create err: %d\n", err);
1307 ftp_send_async_message(req, CLOSE, 500);
1311 local_addr = inet_sk(req->sock->sk)->rcv_saddr;
1312 addr.sin_family = AF_INET;
1314 addr.sin_addr.s_addr = local_addr;
1315 Dprintk("client address: (%d,%d,%d,%d).\n",
1316 NIPQUAD(inet_sk(req->sock->sk)->daddr));
1318 data_sock->sk->sk_reuse = 1;
1319 sock_set_flag(data_sock->sk, SOCK_URGINLINE);
1320 sock_reset_flag(data_sock->sk, SOCK_LINGER);
1322 err = data_sock->ops->bind(data_sock,
1323 (struct sockaddr*)&addr, sizeof(addr));
1324 tp = tcp_sk(data_sock->sk);
1325 icsk = inet_csk(data_sock->sk);
1328 Dprintk("PASV bind() ret: %d.\n", err);
1331 sock_release(data_sock);
1332 ftp_send_async_message(req, CLOSE, 500);
1336 icsk->icsk_ack.pingpong = tux_ack_pingpong;
1338 if (!tux_keepalive_timeout)
1341 tp->linger2 = tux_keepalive_timeout * HZ;
1343 err = data_sock->ops->listen(data_sock, 1);
1344 Dprintk("PASV listen() ret: %d\n", err);
1347 sock_release(data_sock);
1348 ftp_send_async_message(req, CLOSE, 500);
1351 link_tux_data_socket(req, data_sock);
1353 Dprintk("FTP PASV listen sock state: %d, sk state: %d\n",
1354 data_sock->state, data_sock->sk->sk_state);
1356 str_len = sprintf(buf,
1357 "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n",
1358 NIPQUAD(local_addr),
1359 ntohs(inet_sk(data_sock->sk)->sport) / 256,
1360 ntohs(inet_sk(data_sock->sk)->sport) & 255 );
1361 Dprintk("PASV mess: {%s}\n", buf);
1363 add_tux_atom(req, ftp_accept_pasv);
1364 add_tux_atom(req, ftp_flush_req);
1365 __ftp_send_async_message(req, buf, 227, str_len);
1371 struct socket *data_sock;
1372 struct sockaddr_in addr;
1373 kernel_cap_t saved_cap;
1378 * Create FTP data connection to client:
1380 err = sock_create_kern(AF_INET, SOCK_STREAM, IPPROTO_IP, &data_sock);
1382 Dprintk("sock create err: %d\n", err);
1384 ftp_send_async_message(req, CLOSE, 500);
1388 local_addr = inet_sk(req->sock->sk)->rcv_saddr;
1389 addr.sin_family = AF_INET;
1390 addr.sin_port = htons(20);
1391 addr.sin_addr.s_addr = local_addr;
1393 Dprintk("data socket address: (%d,%d,%d,%d).\n",
1394 NIPQUAD(local_addr));
1396 data_sock->sk->sk_reuse = 1;
1397 sock_set_flag(data_sock->sk, SOCK_URGINLINE);
1398 sock_reset_flag(data_sock->sk, SOCK_LINGER);
1400 saved_cap = current->cap_effective;
1401 cap_raise (current->cap_effective, CAP_NET_BIND_SERVICE);
1402 err = data_sock->ops->bind(data_sock,
1403 (struct sockaddr*)&addr, sizeof(addr));
1404 current->cap_effective = saved_cap;
1406 Dprintk("ACTIVE bind() ret: %d.\n", err);
1408 sock_release(data_sock);
1410 ftp_send_async_message(req, CLOSE, 500);
1413 tcp_sk(data_sock->sk)->nonagle = 2;
1415 link_tux_data_socket(req, data_sock);
1417 addr.sin_family = AF_INET;
1418 addr.sin_port = htons(req->ftp_user_port);
1419 addr.sin_addr.s_addr = htonl(req->ftp_user_addr);
1421 err = data_sock->ops->connect(data_sock, (struct sockaddr *) &addr, sizeof(addr), O_RDWR|O_NONBLOCK);
1422 if (err && (err != -EINPROGRESS)) {
1423 Dprintk("connect error: %d\n", err);
1424 zap_data_socket(req);
1426 ftp_send_async_message(req, CLOSE, 500);
1429 Dprintk("FTP data sock state: %d, sk state: %d\n", data_sock->state, data_sock->sk->sk_state);
1430 ftp_send_async_message(req, PORT_OK, 200);
1436 if (!strcmp(req->username, "ftp")
1437 || !strcmp(req->username, "FTP")
1438 || !strcmp(req->username, "anonymous")
1439 || !strcmp(req->username, "ANONYMOUS")) {
1440 unsigned int str_len;
1441 char login_ok [200];
1443 if (!tux_ftp_login_message) {
1444 ftp_send_async_message(req, LOGIN_OK_PASS, 230);
1447 update_bandwidth(req, 0); /* get current bandwidth */
1448 if (nr_requests_used() == 1)
1449 str_len = sprintf(login_ok, LOGIN_OK_ONE,
1450 tux_max_connect, ftp_bandwidth);
1452 str_len = sprintf(login_ok, LOGIN_OK,
1453 nr_requests_used(), tux_max_connect, ftp_bandwidth);
1454 __ftp_send_async_message(req, login_ok, 200, str_len);
1456 clear_keepalive(req);
1457 ftp_send_async_message(req, LOGIN_FORBIDDEN, 530);
1463 ftp_send_async_message(req, LOGIN_OK_PASS, 230);
1468 ftp_send_async_message(req, SITE, 214);
1473 ftp_send_async_message(req, LINUX_SYST, 200);
1478 ftp_send_async_message(req, TYPE_OK, 200);
1481 #define EXTRA_FEATURES "211-Extensions supported:\r\n SIZE\r\n MDTM\r\n211 End\r\n"
1485 ftp_send_async_message(req, EXTRA_FEATURES, 211);
1492 ftp_send_async_message(req, COMMAND_OK, 200);
1497 ftp_send_async_message(req, REST_OK, 200);
1502 clear_keepalive(req);
1503 ftp_send_async_message(req, BYE, 200);
1509 req->keep_alive = 1;
1510 ftp_send_async_message(req, CLOSE, 500);
1516 Dprintk("rejecting FTP session!\n");
1521 static void ftp_timeout (tux_req_t *req, int cachemiss)
1523 Dprintk("called ftp_timeout(%p)\n", req);
1524 if (req->error != TUX_ERROR_CONN_TIMEOUT)
1526 ftp_send_async_message(req, CLOSE_TIMEOUT, 421);
1529 static void ftp_close (tux_req_t *req, int cachemiss)
1531 Dprintk("called ftp_close(%p)\n", req);
1532 ftp_send_async_message(req, CLOSE, 500);
1535 static void ftp_pre_log (tux_req_t *req)
1537 if (tux_ftp_log_retr_only && (req->ftp_command != FTP_COMM_RETR))
1540 req->status = req->ftp_command;
1543 tux_proto_t tux_proto_ftp = {
1546 .got_request = ftp_got_request,
1547 .parse_message = parse_ftp_message,
1548 .illegal_request = ftp_close,
1549 .request_timeout = ftp_timeout,
1550 .pre_log = ftp_pre_log,
1551 .check_req_err = ftp_check_req_err,
1552 .print_dir_line = ftp_print_dir_line,