diff --git a/kernel/branches/net/applications/ftpd/commands.inc b/kernel/branches/net/applications/ftpd/commands.inc index 326a8389ea..fd033049b0 100644 --- a/kernel/branches/net/applications/ftpd/commands.inc +++ b/kernel/branches/net/applications/ftpd/commands.inc @@ -54,7 +54,7 @@ commands: ; all commands must be in uppercase db 'PASS' dd cmdPASS - db 'PWD', 0 + db 'PWD', 0 ; Print Working Directory dd cmdPWD db 'PORT' @@ -118,18 +118,101 @@ align 4 cmdPASS: mcall send, [socketnum2], str230, str230.length, 0 + + push str_pass_ok + call [con_write_asciiz] + mov [state], STATE_ACTIVE ret +align 4 +cmdPASV: + + mov [mode], MODE_PASSIVE + +; TODO: open the UDP socket and return our IP + port + +; 227 Entering Passive Mode (a1,a2,a3,a4,p1,p2) +; where a1.a2.a3.a4 is the IP address and p1*256+p2 is the port number. + + ret + align 4 cmdPWD: + mov dword[buffer], '257 ' + mov byte[buffer+4], '"' + + lea edi, [buffer+5] + mov esi, work_dir + mov ecx, 1024 + .loop: + lodsb + or al, al + jz .ok + stosb + dec ecx + jnz .loop + + .ok: + mov dword[edi], '"' + 0x000a0d00 ; '"',13,10,0 + lea esi, [edi - buffer + 4] + + mcall send, [socketnum2], buffer, , 0 + ret align 4 cmdPORT: +; PORT a1,a2,a3,a4,p1,p2 +; IP address a1.a2.a3.a4, port p1*256+p2 + + mov [mode], MODE_ACTIVE + + lea esi, [esi+5] + xor edx, edx + + call ascii_to_byte + mov dh, bl + inc esi + call ascii_to_byte + mov dl, bl + shl edx, 16 + inc esi + call ascii_to_byte + mov dh, bl + inc esi + call ascii_to_byte + mov dl, bl + inc esi + + mov [datasock.ip], edx + + call ascii_to_byte + mov dh, bl + inc esi + call ascii_to_byte + mov dl, bl + + mov [datasock.port], dx + + mcall socket, AF_INET4, SOCK_DGRAM, 0 + cmp eax, -1 + je .err + mov [datasocketnum], eax + + mcall connect, [datasocketnum], datasock, datasock.length + cmp eax, -1 + je .err + + mcall send, [socketnum2], str225, str225.length, 0 + ret + + .err: + + mcall send, [socketnum2], str425, str425.length, 0 ret align 4 @@ -160,6 +243,79 @@ cmdSYST: align 4 cmdTYPE: + + cmp ecx, 6 + jb parse_cmd.error + + mov al, byte[esi+5] + and al, not 0x20 + + cmp al, 'A' + je .ascii + cmp al, 'E' + je .ebdic + cmp al, 'I' + je .image + cmp al, 'L' + je .local + + jmp parse_cmd.error + + .ascii: + mov [type], TYPE_ASCII + jmp .subtype + + .ebdic: + mov [type], TYPE_EBDIC + + .subtype: + + cmp ecx, 8 + jb .non_print + + mov al, byte[esi+7] + and al, not 0x20 + + cmp al, 'N' + je .non_print + cmp al, 'T' + je .telnet + cmp al, 'C' + je .asacc + + jmp parse_cmd.error + + .non_print: + or [type], TYPE_NP + jmp .ok + + .telnet: + or [type], TYPE_TELNET + jmp .ok + + .asacc: + or [type], TYPE_ASA + jmp .ok + + .image: + mov [type], TYPE_IMAGE + jmp .ok + + .local: + cmp ecx, 8 + jb parse_cmd.error + + mov al, byte[esi+7] + sub al, '0' + jb parse_cmd.error + cmp al, 9 + ja parse_cmd.error + or al, TYPE_LOCAL + mov [type], al + + .ok: + mcall send, [socketnum2], str200, str200.length, 0 + ret align 4 @@ -168,26 +324,71 @@ cmdUSER: mcall send, [socketnum2], str331, str331.length, 0 mov [state], STATE_LOGIN + mov byte [work_dir], "/" + mov byte [work_dir+1], 0 + + push str_logged_in + call [con_write_asciiz] + ret + + + + +align 4 ; esi = ptr to str +ascii_to_byte: + + xor ebx, ebx + + .loop: + + movzx eax, byte[esi] + sub al, '0' + jb .done + cmp al, 9 + ja .done + lea ebx, [ebx*4 + ebx] + shl ebx, 1 + add ebx, eax + inc esi + + jmp .loop + + .done: + ret + + + + + str150 db '150 Here it comes...', 13, 10 str200 db '200 Command OK.', 13, 10 +.length = $ - str200 str215 db '215 UNIX type: L8', 13, 10 .length = $ - str215 str220 db '220 KolibriOS FTP Daemon 1.0', 13, 10 .length = $ - str220 str221 db '221 Bye!', 13, 10 .length = $ - str221 -str225 db '225 Abort successful', 13, 10 +str225 db '225 Data connection open', 13, 10 +.length = $ - str225 str226 db '226 Transfer OK, Closing connection', 13, 10 str230 db '230 You are now logged in.', 13, 10 .length = $ - str230 str250 db '250 command successful', 13, 10 -str257 db '257 ""', 13, 10 +;str257 db '257 "' +;.length = $ - str257 +;str257b db '"', 13, 10 +;.length = $ - str257b str331 db '331 Please specify the password.', 13, 10 .length = $ - str331 +str421 db '421 Timeout!', 13, 10 +.length = $ - str421 +str425 db '425 Cant open data connection.', 13, 10 +.length = $ - str425 str500 db '500 Unsupported command', 13, 10 .length = $ - str500 -str550 db '550 No such file', 13, 10 +str550 db '550 No such file', 13, 10 \ No newline at end of file diff --git a/kernel/branches/net/applications/ftpd/ftpd.asm b/kernel/branches/net/applications/ftpd/ftpd.asm index 42ce0bad51..ef0e330780 100644 --- a/kernel/branches/net/applications/ftpd/ftpd.asm +++ b/kernel/branches/net/applications/ftpd/ftpd.asm @@ -13,6 +13,22 @@ STATE_CONNECTED = 1 STATE_LOGIN = 2 STATE_ACTIVE = 3 +TYPE_UNDEF = 0 + +TYPE_ASCII = 00000100b +TYPE_EBDIC = 00001000b +; subtypes for ascii & ebdic (np = default) +TYPE_NP = 00000001b ; non printable +TYPE_TELNET = 00000010b +TYPE_ASA = 00000011b + +TYPE_IMAGE = 01000000b ; binary data +TYPE_LOCAL = 10000000b ; bits per byte must be specified + ; lower 4 bits will hold this value + +MODE_NOTREADY = 0 +MODE_ACTIVE = 1 +MODE_PASSIVE = 2 use32 db 'MENUET01' ; signature @@ -52,17 +68,22 @@ start: ; initialize console push 1 call [con_start] + push title - push 25 - push 80 - push 25 - push 80 + push -1 + push -1 + push -1 + push -1 call [con_init] mcall 40, 1 shl 7 ; we only want network events + invoke ini.get_int, path, str_ftpd, str_port, 21 + mov [sockaddr1.port], ax + + push eax push str1 - call [con_write_asciiz] + call [con_printf] mcall socket, AF_INET4, SOCK_STREAM, 0 cmp eax, -1 @@ -70,24 +91,31 @@ start: mov [socketnum], eax + push str2 + call [con_write_asciiz] + ;; mcall setsockopt, [socketnum], SOL_SOCKET, SO_REUSEADDR, &yes, ;; cmp eax, -1 ;; je opt_err - invoke ini.get_int, path, str_ftpd, str_port, 21 - mov [sockaddr1.port], ax - mcall bind, [socketnum], sockaddr1, sockaddr1.length cmp eax, -1 je bind_err + push str2 + call [con_write_asciiz] + invoke ini.get_int, path, str_ftpd, str_conn, 1 ; Backlog (max connections) mov edx, eax + + push str2 + call [con_write_asciiz] + mcall listen, [socketnum] cmp eax, -1 je listen_err - push str2 + push str2b call [con_write_asciiz] mcall 10 @@ -108,9 +136,18 @@ start: je .loop push eax + mov byte[buffer+eax], 0 + + + pushd 0x0a + call [con_set_flags] + push buffer call [con_write_asciiz] + pushd 0x07 + call [con_set_flags] + pop ecx mov esi, buffer call parse_cmd @@ -118,21 +155,37 @@ start: jmp .loop acpt_err: + + pushd 0x0c + call [con_set_flags] + push str8 call [con_write_asciiz] jmp done listen_err: + + pushd 0x0c + call [con_set_flags] + push str3 call [con_write_asciiz] jmp done bind_err: + + pushd 0x0c + call [con_set_flags] + push str4 call [con_write_asciiz] jmp done sock_err: + + pushd 0x0c + call [con_set_flags] + push str6 call [con_write_asciiz] jmp done @@ -147,9 +200,10 @@ exit: ; data -title db 'KolibriOS FTP daemon 0.1',0 -str1 db 'Opening socket',10, 0 -str2 db 'Listening for incoming connections...',10,0 +title db 'KolibriOS FTP daemon 0.1', 0 +str1 db 'Starting FTP daemon on port %u', 0 +str2 db '.', 0 +str2b db ' OK!',10,10,0 str3 db 'Listen error',10,10,0 str4 db 'Bind error',10,10,0 str5 db 'Setsockopt error.',10,10,0 @@ -157,6 +211,9 @@ str6 db 'Could not open socket',10,10,0 str7 db 'Got data!',10,10,0 str8 db 'Error accepting connection',10,10,0 +str_logged_in db 'Login ok',10,10,0 +str_pass_ok db 'Password ok - Logged in',10,10,0 + filename db '.ini', 0 str_port db 'port', 0 str_ftpd db 'ftpd', 0 @@ -186,7 +243,8 @@ import console, \ con_cls, 'con_cls',\ con_printf, 'con_printf',\ con_getch2, 'con_getch2',\ - con_set_cursor_pos, 'con_set_cursor_pos' + con_set_cursor_pos, 'con_set_cursor_pos',\ + con_set_flags, 'con_set_flags' import libini, \ ini.get_str, 'ini_get_str',\ @@ -208,9 +266,22 @@ socketnum dd ? ; thread specific data socketnum2 dd ? state dd ? +home_dir rb 1024 +work_dir rb 1024 +type db ? +mode db ? ; active/passive -buffer rb BUFFERSIZE -.length = BUFFERSIZE +datasocketnum dd ? + +datasock: + dw AF_INET4 +.port dw ? +.ip dd ? + rb 10 +.length = $ - datasock + +buffer rb BUFFERSIZE +.length = $ - buffer path rb 1024 mem: