kolibrios-gitea/programs/network_old/ftps/trunk/FTPS.ASM
hidnplayr e4cf34c0de Merge new network stack with trunk
git-svn-id: svn://kolibrios.org@3545 a494cfbc-eb01-0410-851d-a64ba20cac60
2013-05-28 17:34:26 +00:00

1725 lines
37 KiB
NASM

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; FTPS
; FTP Server
;
; Compile with FASM for Menuet
;
; note: telnet == 23, ftp cmd == 21, data on 20
use32
org 0x0
db 'MENUET01' ; 8 byte id
dd 1 ; header version
dd START ; program start
dd I_END ; program image size
dd 0x170000 ; required amount of memory
dd 0x16FFF0 ; esp = 0x16FFF0
dd 0, 0 ; no params, no path
include '../../../macros.inc'
; Various states of client connection
USER_NONE equ 0 ; Awaiting a connection
USER_CONNECTED equ 1 ; User just connected, prompt given
USER_USERNAME equ 2 ; User given username
USER_LOGGED_IN equ 3 ; User given password
START: ; start of execution
; Clear the screen memory
mov eax, ' '
mov edi,text
mov ecx,80*30 /4
cld
rep stosd
call draw_window
; init the receive buffer pointer
mov [buffptr], buff
; Init FTP server state machine
mov [state], USER_NONE
; Open the listening socket
call connect
still:
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[CmdSocket]
mcall
mov ebx, [CmdSocketStatus]
mov [CmdSocketStatus], eax
cmp eax, ebx
je waitev
; If the socket closed by remote host, open it again.
cmp eax, 7
je con
; If socket closed by Reset, open it again
cmp eax, 11
je con
; If a user has just connected, start by outputting welcome msg
cmp eax, 4
jne noc
mov esi, loginStr0
mov edx, loginStr0_end - loginStr0
call outputStr
mov [state], USER_CONNECTED
jmp noc
con:
; Need to call disconnect, since a remote close does not fully
; close the socket
call disconnect
mov eax,5
mov ebx,10 ; Delay for 100ms
mcall
call connect
jmp noc
noc:
; Display the changed connected status
call draw_window
waitev:
mov eax,23 ; wait here for event
mov ebx,1 ; Delay for up to 1s
mcall
cmp eax,1 ; redraw request ?
je red
cmp eax,2 ; key in buffer ?
je key
cmp eax,3 ; button in buffer ?
je button
; any data from the socket?
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [CmdSocket]
mcall
test eax, eax
jz still
read_input:
mov eax, 53
mov ebx, 3 ; Get a byte from socket in bl
mov ecx, [CmdSocket]
mcall
call ftpRxCmdData ; process incoming ftp command
; Keep processing data until there is no more to process
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [CmdSocket]
mcall
cmp eax, 0
jne read_input
; Now redraw the text text field.
; Probably not required, since ftp requires no
; console i/o.
; Leave in for now, for debugging.
; (fall through to "red:")
; call draw_text
; jmp still
red: ; REDRAW WINDOW
call draw_window
jmp still
key: ; KEY
mov eax,2 ; get but ignore
mcall
jmp still
button:
mov eax,17
mcall
cmp ah,1
jne still
; Exit button pressed, so close socket and quit
mov eax,53
mov ebx,8
mov ecx,[CmdSocket]
mcall
; ... terminate program
or eax,-1
mcall
jmp still
; *********************************************
; ******* WINDOW DEFINITIONS AND DRAW ********
; *********************************************
draw_window:
pusha
mov eax,12
mov ebx,1
mcall
xor eax,eax ; DRAW WINDOW
mov ebx,100*65536+491 + 8 +15
mov ecx,100*65536+270 + 20 ; 20 for status bar
mov edx,0x14000000
mov edi,labelt
mcall
; draw status bar
mov eax, 13
mov ebx, 4*65536+484 + 8 +15
mov ecx, 270*65536 + 3
mov edx, 0x00557799
mcall
mov esi,contlen-contt ; display connected status
mov edx, contt
cmp [CmdSocketStatus], 4 ; 4 is connected
je pcon
mov esi,discontlen-discontt
mov edx, discontt
pcon:
mov eax,4 ; status text
mov ebx,380*65536+276
mov ecx,0x00ffffff
mcall
; Draw the text on the screen, clearing it first
; This can go when we loose debuggin info.
xor eax,eax
mov edi,text+80*30
mov ecx,80*30 /4
cld
rep stosd
call draw_text
mov eax,12
mov ebx,2
mcall
popa
ret
;***************************************************************************
; Function
; draw_text
;
; Description
; Updates the text on the screen. This is part of the debugging code
;
; Inputs
; Character to add in bl
;
;***************************************************************************
draw_text:
pusha
mov esi,text
mov eax,0
mov ebx,0
newletter:
mov cl,[esi]
cmp cl,[esi+30*80]
jz noletter
yesletter:
mov [esi+30*80],cl
; erase character
pusha
mov edx, 0 ; bg colour
mov ecx, ebx
add ecx, 26
shl ecx, 16
mov cx, 9
mov ebx, eax
add ebx, 6
shl ebx, 16
mov bx, 6
mov eax, 13
mcall
popa
; draw character
pusha
mov ecx, 0x00ffffff
push bx
mov ebx,eax
add ebx,6
shl ebx,16
pop bx
add bx,26
mov eax,4
mov edx,esi
mov esi,1
mcall
popa
noletter:
add esi,1
add eax,6
cmp eax,80*6
jb newletter
mov eax,0
add ebx,10
cmp ebx,24*10
jb newletter
popa
ret
;***************************************************************************
; Function
; ftpRxCmdData
;
; Description
; Prcoesses incoming command data, calling a handler for each command.
; Commands are built up in buff before being processed.
;
; Inputs
; Character to add in bl
;
;***************************************************************************
ftpRxCmdData:
; Quit if we are not connected
;( This case shouldn't be necessary, but be safe )
mov al, [state]
cmp al, USER_NONE
je frcd_exit
; Store the incoming character
mov esi, [buffptr]
mov [esi], bl
inc esi
mov [buffptr], esi
; For debugging, show the data coming in
pusha
call printChar
popa
; Do we have an end of line? (LF)
; if not, just exit
cmp bl, 0x0a
jne frcd_exit
; OK we have a complete command.
; Process, and send response
; There are a number of states involved in ftp,
; to do with logging in.
mov al, [state]
cmp al, USER_CONNECTED
jne fs001
; This should be the username
; TODO validate username
; OK, username accepted - ask for password
mov esi, loginStr1
mov edx, loginStr1_end - loginStr1
call outputStr
mov [state], USER_USERNAME
; init the receive buffer pointer
mov [buffptr], buff
jmp frcd_exit
fs001:
cmp al, USER_USERNAME
jne fs002
; This should be the password
; TODO validate password
; OK, password accepted - show they are logged in
mov esi, loginStr2
mov edx, loginStr2_end - loginStr2
call outputStr
mov [state], USER_LOGGED_IN
; init the receive buffer pointer
mov [buffptr], buff
jmp frcd_exit
fs002:
cmp al, USER_LOGGED_IN
jne fs003
; This should be a cmd
call findCmd
mov eax, [cmdPtr]
cmp eax, 0
je fs002b
call [cmdPtr]
fs002a:
; init the receive buffer pointer
mov [buffptr], buff
jmp frcd_exit
fs002b:
; an unsupported command was entered.
; Tell user that the command is not supported
mov esi, unsupStr
mov edx, unsupStr_end - unsupStr
call outputStr
jmp fs002a
fs003:
frcd_exit:
ret
;***************************************************************************
; Function
; outputStr
;
; Description
; Sends a string over the 'Command' socket
;
; Inputs
; String in esi
; Length in edx
;
;***************************************************************************
outputStr:
push esi
push edx
mov eax,53
mov ebx,7
mov ecx,[CmdSocket]
mcall
pop edx
pop esi
cmp eax, 0
je os_exit
; The TCP/IP transmit queue is full; Wait a bit, then retry
pusha
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
popa
jmp outputStr
os_exit:
ret
;***************************************************************************
; Function
; outputDataStr
;
; Description
; Sends a string over the 'Data' socket
;
; Inputs
; String in esi
; Length in edx
;
;***************************************************************************
outputDataStr:
push esi
push edx
mov eax,53
mov ebx,7
mov ecx,[DataSocket]
mcall
pop edx
pop esi
cmp eax, 0
je ods_exit
; The TCP/IP transmit queue is full; Wait a bit, then retry
pusha
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
popa
jmp outputDataStr
ods_exit:
ret
;***************************************************************************
; Function
; printChar
;
; Description
; Writes a character to the screen; Used to display the data coming
; in from the user. Really only useful for debugging.
;
; Inputs
; Character in bl
;
;***************************************************************************
printChar:
cmp bl,13 ; BEGINNING OF LINE
jne nobol
mov ecx,[pos]
add ecx,1
boll1:
sub ecx,1
mov eax,ecx
xor edx,edx
mov ebx,80
div ebx
cmp edx,0
jne boll1
mov [pos],ecx
jmp newdata
nobol:
cmp bl,10 ; LINE DOWN
jne nolf
addx1:
add [pos],dword 1
mov eax,[pos]
xor edx,edx
mov ecx,80
div ecx
cmp edx,0
jnz addx1
mov eax,[pos]
jmp cm1
nolf:
cmp bl,8 ; BACKSPACE
jne nobasp
mov eax,[pos]
dec eax
mov [pos],eax
mov [eax+text],byte 32
mov [eax+text+60*80],byte 0
jmp newdata
nobasp:
cmp bl,15 ; CHARACTER
jbe newdata
putcha:
mov eax,[pos]
mov [eax+text],bl
mov eax,[pos]
add eax,1
cm1:
mov ebx,[scroll+4]
imul ebx,80
cmp eax,ebx
jb noeaxz
mov esi,text+80
mov edi,text
mov ecx,ebx
cld
rep movsb
mov eax,ebx
sub eax,80
noeaxz:
mov [pos],eax
newdata:
ret
;***************************************************************************
; Function
; disconnect
;
; Description
; Closes the command socket
;
; Inputs
; None
;
;***************************************************************************
disconnect:
mov eax, 53 ; Stack Interface
mov ebx,8 ; Close TCP socket
mov ecx,[CmdSocket]
mcall
ret
;***************************************************************************
; Function
; disconnectData
;
; Description
; Closes the data socket
;
; Inputs
; None
;
;***************************************************************************
disconnectData:
; This delay would be better done by allowing the socket code
; to wait for all data to pass through the stack before closing
pusha
mov eax,5
mov ebx,10 ; Delay for 100ms
mcall
popa
mov eax, 53 ; Stack Interface
mov ebx,8 ; Close TCP socket
mov ecx,[DataSocket]
mcall
ret
;***************************************************************************
; Function
; connect
;
; Description
; Opens the command socket
;
; Inputs
; None
;
;***************************************************************************
connect:
pusha
mov eax, 53 ; Stack Interface
mov ebx, 5 ; Open TCP socket
mov esi, 0 ; No remote IP address
mov edx, 0 ; No remote port
mov ecx, 21 ; ftp command port id
mov edi, 0 ; passive open
mcall
mov [CmdSocket], eax
popa
ret
;***************************************************************************
; Function
; connectData
;
; Description
; Opens the data socket
;
; Inputs
; None
;
;***************************************************************************
connectData:
pusha
mov eax, 53 ; Stack Interface
mov ebx, 5 ; Open TCP socket
mov esi, [DataIP] ; remote IP address
mov edx, [DataPort] ; remote port
mov ecx, 0 ; ftp data port id
mov edi, 1 ; active open
mcall
mov [DataSocket], eax
popa
ret
;***************************************************************************
; Function
; findCmd
;
; Description
; Scans the command string for a valid command. The command string
; is in the global variable buff.
;
; Returns result in cmdPtr. This will be zero if none found
;
; Inputs
; None
;
;***************************************************************************
findCmd:
; Setup to return 'none' in cmdPtr, if we find no cmd
mov eax, 0
mov [cmdPtr], eax
cld
mov esi, buff
mov edi, CMDList
fc000:
cmp [edi], byte 0 ; Are we at the end of the CMDList?
je fc_exit
fc000a:
cmpsb
je fc_nextbyte
; Command is different - move to the next entry in cmd table
mov esi, buff
fc001:
; skip to the next command in the list
cmp [edi], byte 0
je fc002
inc edi
jmp fc001
fc002:
add edi, 5
jmp fc000
fc_nextbyte:
; Have we reached the end of the CMD text?
cmp [edi], byte 0
je fc_got ; Yes - so we have a match
jmp fc000a ; No - loop back
fc_got:
; Copy the function pointer for the selected command
inc edi
mov eax, [edi]
mov [cmdPtr], eax
fc_exit:
ret
;***************************************************************************
; Function
; decStr2Byte
;
; Description
; Converts the decimal string pointed to by esi to a byte
;
; Inputs
; string ptr in esi
;
; Outputs
; esi points to next character not in string
; eax holds result ( 0..255)
;
;***************************************************************************
decStr2Byte:
xor eax, eax
xor ebx, ebx
mov ecx, 3
dsb001:
mov bl, [esi]
cmp bl, '0'
jb dsb_exit
cmp bl, '9'
ja dsb_exit
imul eax, 10
add eax, ebx
sub eax, '0'
inc esi
loop dsb001
dsb_exit:
ret
;***************************************************************************
; Function
; parsePortStr
;
; Description
; Converts the parameters of the PORT command, and stores them in the
; appropriate variables.
;
; Inputs
; None ( string in global variable buff )
;
; Outputs
; None
;
;***************************************************************************
parsePortStr:
; skip past the PORT text to get the the parameters. The command format
; is
; PORT i,i,i,i,p,p,0x0d,0x0a
; where i and p are decimal byte values, high byte first.
xor eax, eax
mov [DataIP], eax
mov [DataPort], eax
mov esi, buff + 4 ; Start at first space character
pps001:
cmp [esi], byte ' ' ; Look for first non space character
jne pps002
inc esi
jmp pps001
pps002:
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataIP], eax
ror dword [DataIP], 8
inc esi
call decStr2Byte
add [DataPort], eax
shl [DataPort], 8
inc esi
call decStr2Byte
add [DataPort], eax
ret
;***************************************************************************
; Function
; sendDir
;
; Description
; Transmits the directory listing over the data connection.
; The data connection is already open.
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
sendDir:
mov eax, text+0x4000
mov [fsize], eax
mov ebx, dirinfoblock
and dword [ebx+4], 0 ; start from zero block
sd001:
; Read the next DirBlocksPerCall (=16) blocks
mov eax, 70
mcall
; Did we read anything?
test eax, eax
jz @f
cmp eax, 6
jnz sd_exit
@@:
test ebx, ebx
jz sd_exit
; Parse these blocks. There could be up to 16 files specified
mov esi, text + 0x1300 + 0x20
sd002:
dec ebx
js sd004
push ebx
; OK, lets parse the entry. Ignore volume entries
test byte [esi], 8
jnz sd003
; Valid file or directory. Start to compose the string we will send
mov edi, dirStr
; If we have been called as a result of an NLST command, we only display
; the filename
cmp [buff], byte 'N'
jz sd006
mov [edi], byte '-'
test byte [esi], 10h
jz @f
mov [edi], byte 'd'
@@:
; Ok, now copy across the directory listing text that will be constant
; ( I dont bother looking at the read only or archive bits )
mov ebx, tmplStr
@@:
inc edi
mov al, [ebx]
test al, al
jz @f
mov [edi], al
inc ebx
jmp @b
@@:
; point to the last character of the string;
; We will write the file size here, backwards
push edi ; Remember where the string ends
dec edi
; eax holds the number
mov eax, [esi+32]
mov ebx, 10
@@:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
test eax, eax
jnz @b
pop edi
; now create the time & date fields
;timeStr: db ' Jan 1 2000 ',0
mov al, ' '
stosb
movzx eax, byte [esi+28+1]
mov eax, dword [months + (eax-1)*4]
stosd
mov al, byte [esi+28]
aam
test ah, ah
jz sd005a
xchg al, ah
add ax, '00'
jmp sd005b
sd005a:
add al, '0'
mov ah, ' '
sd005b:
stosw
mov al, ' '
mov ecx, 6
rep stosb
push edi
movzx eax, word [esi+28+2]
@@:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
test eax, eax
jnz @b
pop edi
inc edi
mov al, ' '
stosb
sd006:
; ** End of copying
; now copy the filename across
lea ebx, [esi+40]
@@:
mov al, [ebx]
inc ebx
test al, al
jz @f
stosb
jmp @b
@@:
terminate:
; Now terminate the line by putting CRLF sequence in
mov al, 0x0D
stosb
mov al, 0x0A
stosb
; Send the completed line to the user over data socket
push esi
push edi
mov esi, dirStr
mov ecx, edi
sub ecx, esi
mov edi, [fsize]
cld
rep movsb
mov [fsize], edi
cmp edi, text+0x4400
jb @f
mov esi, text+0x4000
mov edx, [fsize]
sub edx, esi
mov [fsize], esi
call outputDataStr
@@:
pop edi
pop esi
sd003: ; Move to next entry in the block
pop ebx
add esi, 304
jmp sd002
sd004:
mov ebx, dirinfoblock
add dword [ebx+4], DirBlocksPerCall
jmp sd001
sd_exit:
mov esi, text+0x4000
mov edx, [fsize]
sub edx, esi
call outputDataStr
ret
;***************************************************************************
; Function
; setupFilePath
;
; Description
; Copies the file name from the input request string into the
; file descriptor
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
setupFilePath:
mov esi, buff + 4 ; Point to (1 before) first character of file
; Skip any trailing spaces or / character
sfp001:
inc esi
cmp [esi], byte ' '
je sfp001
cmp [esi], byte '/'
je sfp001
; esi points to start of filename.
cld
push esi
; Copy across the directory path '/'
; into the fileinfoblock
mov esi, dirpath
mov edi, filename
sfp003:
movsb
cmp [esi], byte 0
jne sfp003
mov al, '/'
stosb
pop esi
; Copy across the filename
sfp002:
movsb
cmp [esi], byte 0x0d
jne sfp002
mov [edi], byte 0
ret
;***************************************************************************
; Function
; sendFile
;
; Description
; Transmits the requested file over the open data socket
; The file to send is named in the buff string
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
sendFile:
call setupFilePath
; init fileblock descriptor, for file read
mov ebx, fileinfoblock
and dword [ebx], 0 ; read cmd
and dword [ebx+4], 0 ; first block
mov dword [ebx+12], 0x400 ; block size
sf002a:
; now read the file..
mov eax,70
mcall
test eax, eax
jz @f
cmp eax, 6
jnz sf_exit
@@:
push eax
mov esi, text + 0x1300
mov edx, ebx
call outputDataStr
pop eax
test eax, eax
jnz sf_exit
; wait a bit
mov eax, 5
mov ebx, 1
mcall
mov ebx, fileinfoblock
add dword [ebx+4], edx
jmp sf002a
sf_exit:
ret
;***************************************************************************
; Function
; getFile
;
; Description
; Receives the specified file over the open data socket
; The file to receive is named in the buff string
;
; Inputs
; None
;
; Outputs
; None
;
;***************************************************************************
getFile:
call setupFilePath
; init fileblock descriptor, for file write
xor eax, eax
mov [fsize], eax ; Start filelength at 0
mov [fileinfoblock+4], eax ; set to 0
inc eax
inc eax
mov [fileinfoblock], eax ; write cmd
; Read data from the socket until the socket closes
; loop
; loop
; read byte from socket
; write byte to file buffer
; until no more bytes in socket
; sleep 100ms
; until socket no longer connected
; write file to ram
gf000:
mov eax, 53
mov ebx, 2 ; Get # of bytes in input queue
mov ecx, [DataSocket]
mcall
test eax, eax
je gf_sleep
mov eax, 53
mov ebx, 11 ; Get bytes from socket
mov ecx, [DataSocket]
mov edx, text + 0x1300
add edx, dword [fsize]
xor esi, esi
mcall ; returned data len in eax
add dword [fsize], eax
jmp gf000
gf_sleep:
; Check to see if socket closed...
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
cmp eax, 7
jne gf001 ; still open, so just sleep a bit
; Finished, so write the file
mov eax, [fsize]
mov [fileinfoblock+12], eax
mov eax,70
mov ebx,fileinfoblock
mcall
ret ; Finished
gf001:
; wait a bit
mov eax,5
mov ebx,1 ; Delay for up 10ms
mcall
jmp gf000 ; try for more data
;***************************************************************************
; COMMAND HANDLERS FOLLOW
;
; These handlers implement the functionality of each supported FTP Command
;
;***************************************************************************
cmdPWD:
cld
mov edi, text+0x1300
mov esi, curdir_1
mov ecx, curdir_2-curdir_1
rep movsb
mov esi, [curdirptr]
cmp [esi], byte 0
jne cpwd_000
mov al, '/'
stosb
jmp cpwd_001
cpwd_000:
movsb
cmp [esi], byte 0
jne cpwd_000
cpwd_001:
mov esi, curdir_2
mov ecx, curdir_end-curdir_2
rep movsb
; OK, show the directory name text
mov esi, text+0x1300
mov edx, edi
sub edx, esi
call outputStr
ret
cmdCWD:
lea esi, [buff+4]
mov edi, [curdirptr]
mov ecx, -1
xor eax, eax
repne scasb
dec edi
cmp [esi], word '..'
je ccwd_002
test [esi], byte 0xE0
je ccwd_000
push edi
mov al, '/'
stosb
@@:
movsb
cmp [esi], byte 0xD
jne @b
xor al, al
stosb
mov eax, 70
mov ebx, dirinfoblock
and dword [ebx+4], 0
mcall
pop edi
test eax, eax
je @f
cmp eax, 6
jne ccwd_000
@@:
test ebx, ebx
je ccwd_000
mov esi, text + 0x1300 + 0x20
mov al, byte [esi]
and al, 0x18
cmp al, 0x10
jne ccwd_000
ccwd_ok:
; OK, show the directory name text
mov esi, chdir
mov edx, chdir_end - chdir
jmp ccwd_001
ccwd_002:
dec edi
cmp byte [edi], '/'
je ccwd_003
cmp edi, [curdirptr]
ja ccwd_002
jmp ccwd_ok
ccwd_003:
mov byte [edi], 0
jmp ccwd_ok
ccwd_000:
mov byte [edi], 0
; Tell user there is no such directory
mov esi, noFileStr
mov edx, noFileStr_end - noFileStr
ccwd_001:
call outputStr
ret
cmdQUIT:
; The remote end will do the close; We just
; say goodbye.
mov esi, byeStr
mov edx, byeStr_end - byeStr
call outputStr
ret
cmdABOR:
; Close port
call disconnectData
mov esi, abortStr
mov edx, abortStr_end - abortStr
call outputStr
ret
cmdPORT:
; TODO
; Copy the IP and port values to DataIP and DataPort
call parsePortStr
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
cmdnoop:
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
cmdTYPE:
; TODO
; Note the type field selected - reject if needed.
; Indicate the command was accepted
mov esi, cmdOKStr
mov edx, cmdOKStr_end - cmdOKStr
call outputStr
ret
cmdsyst:
; Indicate the system type
mov esi, systStr
mov edx, systStr_end - systStr
call outputStr
ret
cmdDELE:
call setupFilePath
mov ebx, fileinfoblock
mov dword [ebx], 8
and dword [ebx+4], 0
push dword [ebx+12]
push dword [ebx+16]
and dword [ebx+12], 0
and dword [ebx+16], 0
mov eax, 70
mcall
mov ebx, fileinfoblock
pop dword [ebx+16]
pop dword [ebx+12]
test eax, eax
jne cmdDele_err
mov esi, delokStr
mov edx, delokStr_end - delokStr
call outputStr
jmp cmdDele_exit
cmdDele_err:
mov esi, noFileStr
mov edx, noFileStr_end - noFileStr
call outputStr
cmdDele_exit:
ret
cmdNLST:
cmdLIST:
; Indicate the command was accepted
mov esi, startStr
mov edx, startStr_end - startStr
call outputStr
call connectData
; Wait for socket to establish
cl001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
cmp eax, 4
jne cl001
; send directory listing
call sendDir
; Close port
call disconnectData
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
ret
cmdRETR:
; Indicate the command was accepted
mov esi, startStr
mov edx, startStr_end - startStr
call outputStr
call connectData
; Wait for socket to establish
cr001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
cmp eax, 4
jne cr001
; send data to remote user
call sendFile
; Close port
call disconnectData
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
ret
cmdSTOR:
; Indicate the command was accepted
mov esi, storStr
mov edx, storStr_end - storStr
call outputStr
call connectData
; Wait for socket to establish
cs001:
; wait a bit
mov eax,5
mov ebx,10 ; Delay for up 100ms
mcall
; check connection status
mov eax,53
mov ebx,6 ; Get socket status
mov ecx,[DataSocket]
mcall
cmp eax, 4
je @f
cmp eax, 7
jne cs001
@@:
; get data file from remote user
call getFile
mov esi, endStr
mov edx, endStr_end - endStr
call outputStr
; Close port
call disconnectData
ret
; DATA AREA
; This is the list of supported commands, and the function to call
; The list end with a NULL.
CMDList:
db 'pwd',0
dd cmdPWD
db 'PWD',0
dd cmdPWD
db 'XPWD',0
dd cmdPWD
db 'xpwd',0
dd cmdPWD
db 'QUIT',0
dd cmdQUIT
db 'quit',0
dd cmdQUIT
db 'PORT',0
dd cmdPORT
db 'port',0
dd cmdPORT
db 'LIST',0
dd cmdLIST
db 'list',0
dd cmdLIST
db 'NLST',0
dd cmdNLST
db 'nlst',0
dd cmdNLST
db 'TYPE',0
dd cmdTYPE
db 'type',0
dd cmdTYPE
db 'syst',0
dd cmdsyst
db 'noop',0
dd cmdnoop
db 'CWD',0
dd cmdCWD
db 'cwd',0
dd cmdCWD
db 'RETR',0
dd cmdRETR
db 'retr',0
dd cmdRETR
db 'DELE',0
dd cmdDELE
db 'dele',0
dd cmdDELE
db 'stor',0
dd cmdSTOR
db 'STOR',0
dd cmdSTOR
db 'ABOR',0
dd cmdABOR
db 'abor',0
dd cmdABOR
db 0xff,0xf4,0xff,0xf2,'ABOR',0
dd cmdABOR
db 0
cmdPtr dd 0
CmdSocket dd 0x0
CmdSocketStatus dd 0x0
DataSocket dd 0x0
DataSocketStatus dd 0x0
DataPort dd 0x00
DataIP dd 0x00
pos dd 80 * 1
scroll dd 1
dd 24
labelt db 'FTP Server v0.1',0
contt db 'Connected'
contlen:
discontt db 'Disconnected'
discontlen:
cmdOKStr: db '200 Command OK',0x0d,0x0a
cmdOKStr_end:
loginStr0: db '220- Menuet FTP Server v0.1',0x0d,0x0a
db '220 Username and Password required',0x0d,0x0a
loginStr0_end:
loginStr1: db '331 Password now required',0x0d,0x0a
loginStr1_end:
loginStr2: db '230 You are now logged in.',0x0d,0x0a
loginStr2_end:
byeStr: db '221 Bye bye!',0x0d,0x0a
byeStr_end:
systStr: db '215 UNIX system type',0x0d,0x0a
systStr_end:
curdir_1: db '257 "'
curdir_2: db '"',0x0d,0x0a
curdir_end:
chdir: db '250 CWD command successful',0x0d,0x0a
chdir_end:
unsupStr: db '500 Unsupported command',0x0d,0x0a
unsupStr_end:
noFileStr: db '550 No such file',0x0d,0x0a
noFileStr_end:
delokStr: db '250 DELE command successful',0x0d,0x0a
delokStr_end:
startStr: db '150 Here it comes...',0x0d,0x0a
startStr_end:
storStr: db '150 Connecting for STOR',0x0d,0x0a
storStr_end:
endStr: db '226 Transfer OK, Closing connection',0x0d,0x0a
endStr_end:
abortStr: db '225 Abort successful',0x0d,0x0a
abortStr_end:
; This is the buffer used for building up a directory listing line
dirStr: times 128 db 0
; This is template string used in building up a directory listing line
tmplStr: db 'rw-rw-rw- 1 0 0 ',0
months:
dd 'Jan ','Feb ','Mar ','Apr ','May ','Jun '
dd 'Jul ','Aug ','Sep ','Oct ','Nov ','Dec '
fileinfoblock:
dd 0x00
dd 0x00
dd 0x00
dd 0x200 ; bytes to read
dd text + 0x1300 ; data area
filename: times 256 db 0
; The following lines define data for reading a directory block
DirBlocksPerCall = 16
dirinfoblock:
dd 1
dd 0x00
dd 0x00
dd DirBlocksPerCall
dd text + 0x1300 ; data area
; The 'filename' for a directory listing
dirpath: db '/sys'
times 252 db 0
curdirptr: dd dirpath+4
fsize: dd 0
state db 0
buffptr dd 0
buff: times 256 db 0 ; Could put this after iend
; Ram use at the end of the application:
; text : 2400 bytes for screen memory
; text + 0x1300 : file data area
text:
I_END: