gscifs/src/SMBDEMO.S

1414 lines
30 KiB
ArmAsm

*
* Marinetti / SMB2 Test, Mark II
*
* CHANGELOG
* Thursday, April 30, 2015 - Restarted effort, ported code from ORCA/M to Merlin32 and debugged Merlin32 environment
* Friday, May 1, 2015 - Ported more code to Merlin32, set up Merlin32 equates
* Saturday, May 2, 2015 - Formatting fixes, refactoring, rewritten SMB Negotiation code
* Saturday, May 9, 2015 - Receive and interpret NEG_PROT reply and start login
*
* REFERENCES
* smb.c / smb.h from libOGC
* http://www.ubiqx.org/cifs/SMB.html
*
rel
dsk smbdemo.l
* Macros (mostly from Merlin32 dist)
use GsOs.Macs
use Util.Macs
use Misc.Macs
use Locator.Macs
use Mem.Macs
use Qd.Macs
use QdAux.Macs
use Event.Macs
use Window.Macs
use Ctl.Macs
use Menu.Macs
use Desk.Macs
use Sound.Macs
use Line.Macs
use Dialog.Macs
use TCPIP.Macs ; from MOSP CVS
* Equates (ripped off from Merlin 16)
use E16.Dialog.Macs
use E16.GsOs.Macs
* Equates (from MOSP/Tools/Orca.M/e16.tcpip)
use E16.TCPIP.Macs
*-----------------------------------------------------------------------------
* DP variables and local equates
*-----------------------------------------------------------------------------
* DUM $000000 is broken on merlin32, if you want LDA (DP) $A5 opcode, write one-byte equates instead
* cause merlin32 will always give you $AD (LDAL)
* dum 0
*AppMMID
* ds 2,0 ; Memory Manager ID
*HndlRef
* ds 2,0 ; For Dereferencing MM Handle
*DPBase
* ds 1,0 ; Deref'd handle
* dend
* workaround: do this instead for DP variables
AppMMID = $0
HndlRef = $2
DPBase = $4
*-----------------------------------------------------------------------------
* GS/OS Program Entry Point
*-----------------------------------------------------------------------------
Entry mx %00
phk
plb
brl Main
*
* Check for toolbox errors
* too-simple error handler
*
CheckError bcs SysDeath
rts
SysDeath pha
PushLong #0000
_SysFailMgr
*
* StartUpTools - start up the various toolsets
*
StartUpTools _TLStartUp
pha
_MMStartUp
jsr CheckError
PullWord AppMMID
_MTStartUp
pha
pha
PushLong #$800 ; 8 pages of DP space
PushWord AppMMID
PushWord #$C005 ; Fixed, Page-Aligned, Locked, Unpurgeable
PushLong #$000000 ; in Bank $00, $0000
_NewHandle
jsr CheckError
PullLong HndlRef
lda [HndlRef]
sta DPBase
pha ; save dp pointer for later
pha
PushWord #$0080 ; Screen Mode ($0000 = 320, $0080 = 640)
PushWord #$00A0 ; Pixel Map Size ($0050 = 320, $00A0 = 640)
PushWord AppMMID
_QDStartUp
jsr CheckError
pla ; saved dp pointer
clc
adc #$300
pha ; save dp pointer for later
pha
PushWord #20 ; Event Queue size
PushWord #0 ; Min X clamp
PushWord #640 ; Max X clamp
PushWord #0 ; Min Y clamp
PushWord #200 ; Max Y clamp
PushWord AppMMID
_EMStartUp
jsr CheckError
PushWord #0
_SetBackColor
PushWord #3
_SetForeColor
PushWord #50 ; X position
PushWord #85 ; Y position
_MoveTo
PushLong #OneMoment
_DrawCString
PushLong #ToolList
_LoadTools
jsr CheckError
PushWord AppMMID
_WindStartUp
jsr CheckError
pla ; saved dp pointer
clc
adc #$100
pha ; save it for later
tax ; save dp pointer in x
PushWord AppMMID
phx
_CtlStartUp
jsr CheckError
pla
clc
adc #$100
pha
tax
PushWord AppMMID
phx
_LEStartUp
jsr CheckError
PushWord AppMMID
_DialogStartUp
jsr CheckError
pla
clc
adc #$100
pha
tax
PushWord AppMMID
phx
_MenuStartUp
jsr CheckError
_DeskStartUp
jsr CheckError
pla
clc
adc #$100
pha
_SoundStartUp
jsr CheckError
_TCPIPStartUp
jsr CheckError
rts
*
* ShutDownTools - shut em back down
*
ShutDownTools lda ToolList
asl
asl
tax
lda ToolList-2,x
cmp #$2 ; Memory Manager?
bne ShutDownOne ; Nope, do it normally
PushWord AppMMID
_DisposeAll
PushWord AppMMID
lda #$2 ; set up for toolset #2 (MM)
ShutDownOne ora #$300 ; Call #3 (Shutdown)
tax
jsl $E10000
dec ToolList
bne ShutDownTools
rts
*
* Main - main sequence of events
*
Main jsr StartUpTools
jsr PrepDeskTop
sep $20
ldal $e0c034
sta ScreenColorByte
lda #00
stal $e0c034
rep $30
* pretty corner rounding
PushWord #0000
_SetForeColor
* upper left
PushWord #0001
PushWord #0000
_MoveTo
PushWord #0001
PushWord #0002
_LineTo
PushWord #0002
PushWord #0000
_MoveTo
PushWord #0002
PushWord #0001
_LineTo
PushWord #0003
PushWord #0000
_MoveTo
PushWord #0003
PushWord #0000
_LineTo
* upper right
PushWord #0638
PushWord #0000
_MoveTo
PushWord #0638
PushWord #0002
_LineTo
PushWord #0637
PushWord #0000
_MoveTo
PushWord #0637
PushWord #0001
_LineTo
* lower left
PushWord #0000
PushWord #0195
_MoveTo
PushWord #0000
PushWord #0199
_LineTo
PushWord #0001
PushWord #0197
_MoveTo
PushWord #0001
PushWord #0199
_LineTo
PushWord #0002
PushWord #0199
_MoveTo
PushWord #0002
PushWord #0199
_LineTo
* lower right
PushWord #0639
PushWord #0195
_MoveTo
PushWord #0639
PushWord #0199
_LineTo
PushWord #0638
PushWord #0197
_MoveTo
PushWord #0638
PushWord #0199
_LineTo
PushWord #0637
PushWord #0199
_MoveTo
PushWord #0637
PushWord #0199
_LineTo
EventLoop pha ; Result Space
PushWord #$ffff ; Event Mask
PushLong #EventRec
_TaskMaster
pla
beq EventLoop
cmp #$11 ; wInMenuBar?
bne EventLoop ; no, so ignore
jsr MenuDispatch
bit QuitFlag
bpl EventLoop
sep $20
lda ScreenColorByte
stal $e0c034
rep $30
jsr ShutDownTools
iGSOS _Quit;QParams;1
*
* Prepare Desktop
*
PrepDeskTop PushLong #0000
_RefreshDesktop
_InitCursor
NextMenu pha
pha
lda MenuTbl
asl
tax
lda MenuTbl,x
phb
phb
pha
_NewMenu
PushWord #0000
_InsertMenu
dec MenuTbl
bne NextMenu
PushWord #1
_FixAppleMenu
pha
_FixMenuBar
pla
_DrawMenuBar
rts
*
* Apple Menu: About
*
About PushLong #AboutString
jsr InfoDialog
rts
*
* File Menu: Quit
*
Quit dec QuitFlag
rts
*
* TCP/IP Test
*
TCPIPTest pha
PushWord #0000
_TCPIPGetConnectStatus
pla
cmp #$0000
bne tgood
PushLong #MarinettiBad
jsr InfoDialog
bra tret
tgood PushLong #MarinettiGood
jsr InfoDialog
tret pla
rts
*
* Connect To Server
*
ConnectToSvr PushLong #$00000000 ; space for result
PushLong #CTSRect
_GetNewModalDialog
PullLong CTSWinPtr
PushLong CTSWinPtr
_BeginUpdate
PushLong CTSWinPtr
_DrawDialog
PushLong CTSWinPtr
_EndUpdate
PushLong #00000000
_TCPIPConnect ; make sure marinetti is connected
PushLong #00000000
_TCPIPGetMyIPAddress
plx
ply
PushWord #0000
phy
phx
PushLong #ascaddr
PushWord #0000
_TCPIPConvertIPToASCII ; convert our address to ASCII
pla
PushLong CTSWinPtr
PushWord #1360
PushLong #ascaddr
_SetIText ; show it
CTSLoop1 PushWord #0000 ; space for result
PushLong #00000000 ; nil filter
_ModalDialog
pla ; get item hit
cmp #2 ; Cancel?
beq CTSClose
cmp #1 ; Connect?
bne CTSLoop1
bra CTSConnect
CTSClose PushLong CTSWinPtr
_CloseDialog
rts
CTSConnect PushLong #00000000
PushLong CTSWinPtr
PushWord #0001
_GetControlDItem
plx
ply
PushWord #255
phy
phx
_HiliteControl ; dim/disable 'Connect' button
PushLong #00000000
PushLong CTSWinPtr
PushWord #1349
_GetControlDItem
plx
ply
PushWord #255
phy
phx
_HiliteControl ; dim/disable 'Address' text input
PushLong CTSWinPtr
PushWord #1349
PushLong #fqdnptr
_GetIText
PushWord CTSText4 ; preserve old length byte (word)
sep #$30
mx %11
lda fqdnptr
tax
clc
adc CTSText4
sta CTSText4
hostcopy lda fqdnptr,x
sta inhost-1,x
dex
bne hostcopy
rep #$30
mx %00
PushLong CTSWinPtr
PushWord #1350
PushLong #CTSText4
_SetIText ; show 'resolving' status string
pla
sta CTSText4
PushWord #0000
PushWord #$F800
PushLong #fqdnptr
_TCPIPMangleDomainName ; mangle entered domain name
pla ; port number; trash
PushWord #0000
PushLong #fqdnptr
_TCPIPValidateIPString
pla
beq resolve ; engage DNS if this wasn't an ip address
PushLong #ipaddrip
PushLong #fqdnptr
_TCPIPConvertIPToHex ; else just convert to long
bra Connect ; and on with the show
resolve PushLong #fqdnptr
PushLong #ipaddr
_TCPIPDNRNameToIP ; resolve fqdn
ResolvLoop PushWord #0000 ; check for mouse events (cancel)
PushWord #$0006 ; with _EventAvail
PushLong #EventRec ; because _ModalDialog will block
_EventAvail
pla
beq noevent
PushWord #0000
PushLong #00000000
_ModalDialog
pla
cmp #2
beq CTSClose2
noevent _TCPIPPoll
lda ipaddr
cmp #$0001
beq Connect ; continue to Connect if resolved okay
cmp #$0000
beq ResolvLoop ; pending; stay in 'Resolving' loop
bra CTSBadDNS
CTSClose2 PushLong CTSWinPtr
_CloseDialog
rts
CTSBadDNS PushLong CTSWinPtr
PushWord #1350
PushLong #CTSText5
_SetIText
bra CTSClose2
Connect PushWord #0000
PushLong ipaddrip
PushLong #destaddr
PushWord #0000
_TCPIPConvertIPToASCII
pla
PushWord CTSText6 ; preserve old length byte (word)
sep #$30
mx %11
lda destaddr
tax
clc
adc CTSText6
sta CTSText6
ipcopy lda destaddr,x
sta ascdest-1,x
dex
bne ipcopy
rep #$30
mx %00
PushLong CTSWinPtr
PushWord #1350
PushLong #CTSText6
_SetIText ; change status to 'Connecting'
pla
sta CTSText6 ; restore length byte
PushWord #0000 ; space for result
PushWord AppMMID ; our Memory Manager handle
PushLong ipaddrip ; ipaddress to connect to
PushWord #0445 ; try port 445 first
PushWord #0000 ; default TOS: 0000
PushWord #$0040 ; default TTL: 64
_TCPIPLogin
pla
sta MyIPID
PushWord #$0000
PushWord MyIPID
_TCPIPOpenTCP
pla
beq ConnectLoop
jmp CTSClose3
ConnectLoop PushWord #0000
PushWord #$0006
PushLong #EventRec
_EventAvail
pla
beq noevent2
PushWord #0000 ; space for result
PushLong #00000000 ; nil filter procedure
_ModalDialog
pla
cmp #2
bne noevent2
jmp CTSClose3
noevent2 _TCPIPPoll
PushWord #0000
PushWord MyIPID
PushLong #statbuf
_TCPIPStatusTCP
pla
beq notbroke
jmp CTSClose3 ; something broke
notbroke lda statbuf
cmp #$0004
beq estab
cmp #$0000
beq closed_trampoline
bra ConnectLoop
estab PushLong CTSWinPtr
PushWord #1350
PushLong #CTSText9
_SetIText
PushLong MyIPID
jsr SMB_Init ; feed our Marinetti IPID into SMB system
PullLong MySMBHandle ; get back our SMB handle
PushLong MySMBHandle ; SMB_Negotiate wants our SMB handle
jsr SMB_Negotiate ; and hopefully we send a SMB Negotiate Protocol Request and get a response
bra ct_far
closed_trampoline jmp closed
ct_far
sendloop2 PushWord #0000
PushWord #$0006
PushLong #EventRec
_EventAvail
pla
beq noevent3
PushWord #0000
PushLong #00000000
_ModalDialog
pla
cmp #2
bne noevent3
noevent3 PushLong MySMBHandle
jsr SMB_Negotiate_Poll
pla ; get negotiation status
bcc sendloop2
login PushLong CTSWinPtr
PushWord #1350
PushLong #CTSTextB
_SetIText
jmp SMB_input_brk ; die so we can inspect things
closed PushLong CTSWinPtr
PushWord #1350
PushLong #CTSTextA
_SetIText
CTSClose3 PushWord #MyIPID
_TCPIPLogout ; get rid of our IPID
PushLong CTSWinPtr ; and close the dialog window
_CloseDialog
rts
*
* Menu Dispatcher
*
MenuDispatch lda TaskData
and #$00ff
asl
tax
jsr (MenuDispatchTbl,x)
PushWord #0000
PushWord TaskData+2
_HiliteMenu
rts
*
* Information Dialog
*
InfoDialog plx ; preserve return address
PullLong dialogMsg
phx ; put return back on stack
pha ; room for result
PushLong #OurAlert ; pointer to dialog
PushLong #$0000
_NoteAlert
pla ; get the item selected
rts
*
* Non-DP Variables
*
QuitFlag dw 00,00
ScreenColorByte dw 00
MyIPID dw 00 ; Marinetti IPID
MySMBHandle dw 00,00 ; SMB driver handle
CTSWinPtr dw 00,00 ; Connect To Server grafport ptr
fqdnptr ds 101 ; 101 bytes for user-entered hostname
ipaddr dw 00 ; DNS resolution status
ipaddrip dw 00,00 ; Resolved IP address
ascaddr ds 16 ; My IP address, in ASCII
destaddr ds 16 ; Destination IP address, in ASCII
statbuf ds 2 ; TCP state, statbuf+0
ds 2 ; ICMP error code, statbuf+2
ds 4 ; sendq size, statbuf+4
ds 4 ; recvq size, statbuf+8
ds 4 ; dest ip
ds 2 ; dest port
ds 2 ; connection type
ds 2 ; accept count
readbuf ds 4 ; rrBuffCount
ds 4 ; rrBuffHandle
ds 2 ; rrMoreFlag
ds 2 ; rrPushFlag
ds 2 ; rrUrgentFlag
*
* Tool List
*
ToolList dw 13 ; Tool Count
dw 01,00 ; Tool Locator, any vers
dw 02,00 ; Memory Manager, any vers
dw 03,00 ; Misc Tools, any vers
dw 04,00 ; QuickDraw II, any vers
dw 06,00 ; Event Manager, any vers
dw 14,00 ; Window Manager, any vers
dw 16,00 ; Control Manager, any vers
dw 15,00 ; Menu Manager, any vers
dw 05,00 ; Desk Manager, any vers
dw 08,00 ; Sound Manager, any vers
dw 20,00 ; Line Edit, any vers
dw 21,00 ; Dialog Manager, any vers
dw 54,00 ; Marinetti, any vers
ToolListEnd
*
* Menu Structures
*
MenuDispatchTbl dw About
dw Quit
dw TCPIPTest
dw ConnectToSvr
MenuTbl dw 4 ; count
dw Menu1
dw Menu2
dw Menu3
dw Menu4
MenuTblEnd
Menu1 asc '>>@\XN1'00
asc '--About This Program...\N256*??'00
asc '---\D'00
asc '>'
Menu2 asc '>> File \N2'00
asc '--Quit\N257*Qq'00
asc '>'
Menu3 asc '>> Edit \N3D'00
asc '--Undo\N250V*Zz'00
asc '--Cut\N251*Xx'00
asc '--Copy\N252*Cc'00
asc '--Paste\N253V*Vv'00
asc '--Clear\N254'00
asc '>'
Menu4 asc '>> Test \N4'00
asc '--TCP/IP Test\N258*Tt'00
asc '--Connect to Server\N259*Uu'00
asc '>'
*
* Event Record
*
EventRec
Event_What ds 2
Event_Msg ds 4
Event_When ds 4
Event_Where ds 4
Event_Mods ds 2
TaskData ds 4
TaskMask dw $1fff,$0000
*
* Strings
*
OneMoment asc 'One Moment Please...'00
MarinettiGood str 'Marinetti is Up.'
MarinettiBad str 'Marinetti is Not Up.'
AboutString str 'TCPIP Test Program'
But1 str 'OK'
*
* Connect To Server Dialog
*
CTSRect dw 30,120,120,520 ; bounds rect
CTSVis dw 0001 ; visible
CTSRef dw 0000,0000 ; refcon
CTSiptr1 adrl CTSItem1 ; string 'Host To Connect To'
CTSiptr2 adrl CTSItem2 ; edit line
CTSiptr3 adrl CTSItem3 ; connect button
CTSiptr4 adrl CTSItem4 ; cancel button
CTSiptr5 adrl CTSItem5 ; status line
CTSiptr6 adrl CTSItem6 ; My IP Address
CTSiptr7 adrl CTSItem7 ; "My Ip Address: "
dw 0000 ; end of the line
CTSItem1 dw 1348 ; id
dw 5,10,15,300 ; bounds
dw statText+$8000 ; type + disabled
adrl CTSText1
dw 00 ; item value
dw 00 ; item flag
adrl 00 ; end
CTSText1 str 'Address Of CIFS Server To Connect To:'
CTSItem2 dw 1349 ; id
dw 25,10,38,200 ; bounds
dw editLine
adrl CTSText2
dw 100
dw 00
adrl 00
CTSText2 str 'example.com'
CTSItem3 dw 1
dw 50,10,60,100
dw buttonItem
adrl But2
dw 00
dw 00
adrl 00
But2 str 'Connect'
CTSItem4 dw 2
dw 50,111,60,210
dw buttonItem
adrl But3
dw 00
dw 00
adrl 00
But3 str 'Cancel'
CTSItem5 dw 1350 ; id
dw 65,10,75,300 ; bounds
dw statText+$8000 ; type + disabled
adrl CTSText3
dw 00
dw 00
adrl 00
CTSText3 str 'Status: Awaiting Input'
CTSText4 str 'Status: Resolving Hostname '
inhost ds 101
CTSText5 str 'Status: Resolution Failure'
CTSText6 str 'Status: Connecting to '
ascdest ds 20
CTSText9 str 'Status: Connected, CIFS negotiating'
CTSTextA str 'Status: Connect Failed'
CTSTextB str 'Status: Logging In'
CTSItem6 dw 1360 ; id
dw 77,120,87,300 ; bounds
dw statText+$8000
adrl CTSText7
dw 00
dw 00
adrl 00
CTSText7 str '0.0.0.0'
CTSItem7 dw 1361 ; id
dw 77,10,87,120 ; bounds
dw statText+$8000
adrl CTSText8
dw 00
dw 00
adrl 00
CTSText8 str 'My IP Address:'
*
* TCPIP Test Output Dialog
*
OurAlert dw 30,120,80,520 ; bounds rect
dw 2374 ; id
db $80
db $80
db $80
db $80
adrl item1
adrl item2
adrl 00
item1 dw 1 ; id
dw 25,320,0,0 ; bounds rect for button
dw buttonItem ; type
adrl But1 ; item descriptor
dw 00 ; item value
dw 00 ; item flag
adrl 00 ; item color
item2 dw 1348 ; id
dw 11,72,200,640 ; bounds rect for message
dw statText+$8000 ; type + disabled
dialogMsg adrl MarinettiGood ; item descriptor
dw 00 ; item value
dw 00 ; item flag
adrl 00 ; item color
*
* GS/OS Quit Params
*
QParams ds 4
ds 4
*** CIFS / SMB internals only past this point (will eventually be its own linker segment)
*
* SMB equates (should move into Library/E16.CIFS.Macs.s eventually)
*
* offsets into SMB header
SMB_offset_tcplength = 1 ; tcp length: all dgram length including header
SMB_offset_proto = 0+4
SMB_offset_cmd = 4+4
SMB_offset_ntstatus = 5+4
SMB_offset_eclass = 5+4
SMB_offset_flags = 9+4
SMB_offset_flags2 = 10+4
SMB_offset_extra = 12+4
SMB_offset_tid = 24+4
SMB_offset_pid = 26+4
SMB_offset_uid = 28+4
SMB_offset_mid = 30+4
SMB_header_size = 32+4 ; SMB headers are always 32 bytes long
* message / commands
NBT_session_msg = 00
SMB_neg_protocol = $72
SMB_setup_ANDX = $73
SMB_treec_ANDX = $75
* keepalive
NBT_keepalive_msg = $85
keepalive_size = 4
* SMBTrans2
SMB_trans2 = $32
SMB_open2 = 0
SMB_find_first2 = 1
SMB_find_next2 = 2
SMB_query_fs_info = 3
SMB_query_path_info = 5
SMB_set_path_info = 6
SMB_query_file_info = 7
SMB_set_file_info = 8
SMB_create_dir = 13
SMB_find_close2 = $34
SMB_query_file_all_info = $107
* File I/O
SMB_open_ANDX = $2d
SMB_write_ANDX = $2f
SMB_read_ANDX = $2e
SMB_close = $04
* SMB_COM
SMB_COM_create_directory = $00
SMB_COM_delete_directory = $01
SMB_COM_delete = $06
SMB_COM_rename = $07
SMB_COM_query_information_disk = $80
* TRANS2 offsets
T2_word_cnt = SMB_header_size
T2_prm_cnt = T2_word_cnt+1
T2_data_cnt = T2_prm_cnt+2
T2_maxprm_cnt = T2_data_cnt+2
T2_maxbuffer = T2_maxprm_cnt+2
T2_setup_cnt = T2_maxbuffer+2
T2_sprm_cnt = T2_setup_cnt+10
T2_sprm_ofs = T2_sprm_cnt+2
T2_sdata_cnt = T2_sprm_ofs+2
T2_sdata_ofs = T2_sdata_cnd+2
T2_ssetup_cnt = T2_sdata_ofs+2
T2_sub_cmd = T2_ssetup_cnt+2
T2_byte_cnt = T2_sub_cmd+2
SMB_proto1 = $53ff ; $ff + 'S'
SMB_proto2 = $424d ; 'MB'
SMB_max_net_read_size = 16384
SMB_max_net_write_size = 4096
SMB_max_transmit_size = 16384
CAP_large_files = $00000008 ; 64-bit file sizes and offsets supported
CAP_unicode = $00000004 ; unicode supported
CIFS_flags1 = $08 ; paths are caseless
CIFS_flags2_unicode = $8001 ; server may return long components in paths in the response - Unicode supported
CIFS_flags2 = $0001 ; server may return long components in paths in the response - ASCII supported
SMB_connhandles_max = 8
SMB_filehandles_max = (32*SMB_connhandles_max)
SMB_objtype_handle = 7
* NBT session service packet type codes
SESS_msg = $0
SESS_req = $81
SESS_pos_resp = $82
SESS_neg_resp = $83
SESS_retarget = $84
SESS_keepalive = $85
SMB_maxpath = 4096
* SMB error codes
SMB_success = 0
SMB_error = $ffff ; -1
SMB_bad_protocol = $fffe ; -2
SMB_bad_command = $fffd ; -3
SMB_proto_fail = $fffc ; -4
SMB_not_user = $fffb ; -5
SMB_bad_keylen = $fffa ; -6
SMB_bad_datalen = $fff9 ; -7
SMB_bad_logindata = $fff8 ; -8
* SMB file open function
SMB_of_open = 1
SMB_of_truncate = 2
SMB_of_create = 16
* FileSearch
SMB_srch_readonly = 1
SMB_srch_hidden = 2
SMB_srch_system = 4
SMB_srch_volume = 8
SMB_srch_directory = 16
SMB_srch_archive = 32
* SMB file access modes
SMB_open_reading = 0
SMB_open_writing = 1
SMB_open_readwrite = 2
SMB_open_compatible = 0
SMB_deny_readwrite = $10
SMB_deny_write = $20
SMB_deny_read = $30
SMB_deny_none = $40
*
* SMB variable space
*
* SMB DP variables
SMB_sessid = 8
SMB_tmp1 = 12
SMB_tmp2 = 14
* SMB session information
* TODO dynamically allocate these - see SMB_Init
SMB_sess_begin
SMB_sess_ipid dw 0 ; Marinetti IPID
SMB_sess_tid dw 0 ; SMB TID
SMB_sess_pid dw $dead ; SMB PID
SMB_sess_uid dw 0 ; SMB UID
SMB_sess_mid dw $0001 ; SMB MID
SMB_sess_skey dw 0,0 ; sKey
SMB_sess_caps dw 0,0 ; capabilities
SMB_sess_maxbuffer dw 0,0 ; max buffer
SMB_sess_seclvl dw 0 ; server security level
SMB_sess_maxmpx dw 0 ; server max pending outstanding requests
SMB_sess_maxvcs dw 0 ; server max virtual circuits
SMB_sess_challenge_used dw 0 ; challenge Used?
SMB_sess_challenge dw 0,0,0,0 ; challenge
SMB_sess_domain ds 32 ; sloppy 32 byte buffer to hold SMB domain
* Strings
SMB_dialect asc 02'NT LM 0.12'00 ; the only dialect we're gonna speak
* SMB packet staging area
* TODO these will probably be dynamically allocated too?
* also SMB_max_transmit size should go up to 65535 and use an allocated bank like Marinetti does
SMB_staging_brk brk 00 ; jump here to crash somewhere where you can easily inspect the generated SMB datagram
SMB_staging ds SMB_max_transmit_size+2
SMB_input_brk brk 00
SMB_input ds SMB_max_net_read_size ; TODO Memory Manage this eh
*
* SMB Subroutines
*
* SMB_Init - Call me to tell me about your Marinetti IPID and get a session handle returned for future SMB calls
* Arguments:
* Marinetti IPID (one word, on stack)
* Returns:
* SMB session handle (two words, on stack)
* Carry flag set if error
* TODO: make this support multiple sessions in the future
SMB_Init plx ; return address
pla
sta SMB_sess_ipid
PushLong #SMB_sess_begin
phx ; saved return address
clc
rts
* SMB_Negotiate - Call me when you've opened a TCPIP connection and want to perform Negotiate Protocol Request
* Arguments:
* SMB session handle (two words, on stack)
* Things I return on stack:
* Carry flag set if error
SMB_Negotiate plx ; return address
PullLong SMB_sessid
phx ; saved return address
PushWord #SMB_neg_protocol ; command
PushWord #CIFS_flags1 ; flags1
PushWord #CIFS_flags2 ; flags2
jsr _InitSMBHeader ; make an SMB header with this information
sep $30
mx %11
ldy #0
ldx #0
dialect_copy lda SMB_dialect,x ; 8-bit copy of dialect string into SMB staging area
beq dialect_done
sta SMB_staging+SMB_header_size+3,x
inx
iny
bra dialect_copy
dialect_done sta SMB_staging+SMB_header_size+3,x ; do write the trailing zero
inx
iny
rep $30
mx %00
tya
sta SMB_staging+SMB_header_size+1 ; save byte count
clc
adc #SMB_header_size+3
pha ; 'length' parameter for _SMB_Send
dec
dec
dec
dec
xba
sta SMB_staging+SMB_offset_tcplength+1 ; save length for naked-TCP dgram
jsr _SMB_Send
clc
rts
* SMB_Negotiate_Poll - Call me until I tell you to stop, to receive and complete SMB negotiation
* Arguments:
* SMB session handle (two words, on stock)
* Things I return on stack:
* Negotiation status (word)
* $0000 - Negotiation proceeding
* $0001 - Negotiation finished
* $0002 - Negotiation failed
* Carry flag set means you can stop calling me
SMB_Negotiate_Poll
plx ; our return address
PullLong SMB_sessid ; your smb sessid
phx
_TCPIPPoll
PushWord #0000 ; space for result
ldy #SMB_sess_ipid-SMB_sess_begin
lda [SMB_sessid],y
pha ; push Marinetti IPID for this SMB_sessid
PushLong #statbuf
_TCPIPStatusTCP ; see if marinetti has anything for us
pla
cmp #terrNOCONNECTION
beq nf_trampoline
cmp #terrBADIPID
beq nf_trampoline
lda statbuf+8 ; get recvq size, low word
cmp #0000 ; yeah i know. for clarity.
beq np_trampoline ; poll us again later, marinetti got nothing
PushWord #0000 ; space for result
ldy #SMB_sess_ipid-SMB_sess_begin
lda [SMB_sessid],y
pha ; push Marinetti IPID for this SMB_sessid
PushWord #0000 ; bufftype: static pre-allocated buffer
PushLong #SMB_input ; where it's all goin
PushLong #SMB_max_net_read_size
PushLong #readbuf
_TCPIPReadTCP
pla
cmp #terrNOCONNECTION
beq nf_trampoline
cmp #terrBADIPID
beq nf_trampoline
jsr _SMB_Check ; do basic check to make sure we received SMB data
bcs np_trampoline ; if not, wait for them to send again i guess
` lda SMB_input+SMB_offset_cmd
cmp #SMB_neg_protocol
bne np_trampoline ; punt if not protocol negotiation reply
lda SMB_input+SMB_offset_eclass
cmp #0000
bne nf_trampoline ; they returned an error, kbye
lda SMB_input+SMB_header_size
and #$ff
cmp #17
bne nf_trampoline ; they should always return 17 words
lda SMB_input+SMB_header_size
xba
and #$ff
cmp #00
bne nf_trampoline ; they should always select dialect 0
bra nft_far
nf_trampoline jmp nego_failed
np_trampoline jmp nego_proceeding
nft_far
lda SMB_input+SMB_header_size+3
and #$01
ldy #SMB_sess_seclvl-SMB_sess_begin
sta [SMB_sessid],y ; save session security level (1=user level, 0=share level)
lda SMB_input+SMB_header_size+4
and #$ff
ldy #SMB_sess_maxmpx-SMB_sess_begin
sta [SMB_sessid],y ; save session MaxMPX
lda SMB_input+SMB_header_size+6
and #$ff
ldy #SMB_sess_maxvcs-SMB_sess_begin
sta [SMB_sessid],y ; save session MaxVCS
lda SMB_input+SMB_header_size+8
ldy #SMB_sess_maxbuffer-SMB_sess_begin
sta [SMB_sessid],y ; save session maxbuffer
lda SMB_input+SMB_header_size+16
ldy #SMB_sess_skey-SMB_sess_begin
sta [SMB_sessid],y ; save skey
lda SMB_input+SMB_header_size+20
ldy #SMB_sess_caps-SMB_sess_begin
sta [SMB_sessid],y
iny
iny
lda SMB_input+SMB_header_size+22
sta [SMB_sessid],y ; save server capabilities
; TODO serverTime
lda SMB_input+SMB_header_size+33
and #$ff
cmp #8
bne challenge_used
cmp #0
bne nego_failed ; should be either 8 or zero
lda #$0000
ldy #SMB_sess_challenge_used
sta [SMB_sessid],y
bra getdomain
challenge_used lda #$0001
ldy #SMB_sess_challenge_used
sta [SMB_sessid],y
lda SMB_input+SMB_header_size+36
ldy #SMB_sess_challenge-SMB_sess_begin
sta [SMB_sessid],y
iny
iny
lda SMB_input+SMB_header_size+38
sta [SMB_sessid],y
iny
iny
lda SMB_input+SMB_header_size+40
sta [SMB_sessid],y
iny
iny
lda SMB_input+SMB_header_size+42
sta [SMB_sessid],y ; save 8-byte challenge
getdomain ldy #SMB_sess_domain-SMB_sess_begin
ldx #00
gdloop lda SMB_input+SMB_header_size+45,x
and #$ff00
xba
cmp #0000
beq eod
sta [SMB_sessid],y ; if this looks off to you, see how
iny ; the domain name is actually encoded
inx ; W\00O\00R\00K\00G\00R\00O\00U\00P\00
inx
bra gdloop
eod sta [SMB_sessid],y ; save terminating zero
nego_finished plx ; our return address
PushWord #0001 ; finished!
phx
sec
rts
nego_failed plx ; our return address
PushWord #0002 ; failure
phx
sec
rts
nego_proceeding plx ; our return address
PushWord #0000 ; in progress
phx
clc
rts
*
* SMB internal subroutines
*
* _SMB_Check - Check to see if TCP received data is SMB
_SMB_Check lda SMB_input+SMB_offset_proto
cmp #SMB_proto1
bne check_inv
lda SMB_input+SMB_offset_proto+2
cmp #SMB_proto2
bne check_inv ; starts with 'SMB'\ff
clc
rts
check_inv sec
rts
* _SMB_Send - Send the SMB datagram staging area out to Marinetti
* Arguments:
* length (word, pushed on stack first)
_SMB_Send plx ; save return address
PullWord SMB_tmp1
phx ; restore return address
lda #0
sta SMB_tmp2
PushWord #0000
ldy #SMB_sess_ipid-SMB_sess_begin
lda [SMB_sessid],y
pha ; IPID for Marinetti
PushLong #SMB_staging
PushLong SMB_tmp1 ; length
PushWord #0001 ; Samba sets PSH, so will I
PushWord #0000
_TCPIPWriteTCP
pla
rts
* _InitSMBHeader - Zero-out old SMB datagram data and start with some fresh header values
* Arguments:
* Command (word, pushed on stack first)
* Flags1 (word, pushed on stack second)
* Flags2 (word, pushed on stack third)
* Session Handle (already stored in DP SMB_sessid)
* Things I return on stack:
* Carry flag set if error
_InitSMBHeader ldx #00
lda #00
zero_loop sta SMB_staging,x ; loop to zero-out any old data from SMB header staging place
inx
inx
cpx #SMB_max_transmit_size
blt zero_loop
lda #SMB_proto1
sta SMB_staging+SMB_offset_proto
lda #SMB_proto2
sta SMB_staging+SMB_offset_proto+2 ; $FF + 'SMB' at start of header
ldy #SMB_sess_tid-SMB_sess_begin
lda [SMB_sessid],y
sta SMB_staging+SMB_offset_tid ; set session TID
ldy #SMB_sess_pid-SMB_sess_begin
lda [SMB_sessid],y
sta SMB_staging+SMB_offset_pid ; set session PID
ldy #SMB_sess_uid-SMB_sess_begin
lda [SMB_sessid],y
sta SMB_staging+SMB_offset_uid ; set session UID
ldy #SMB_sess_mid-SMB_sess_begin
lda [SMB_sessid],y
sta SMB_staging+SMB_offset_mid ; set session MID
plx ; save return address
pla ; flags2 (word)
sta SMB_staging+SMB_offset_flags2 ; set Flags2
pla ; flags1 (word, but written as byte)
ora SMB_staging+SMB_offset_flags
sta SMB_staging+SMB_offset_flags ; write one-byte value where it goes
pla ; command (word, but written as byte)
ora SMB_staging+SMB_offset_cmd
sta SMB_staging+SMB_offset_cmd ; write one-byte value where it goes
phx
rts