mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-09-12 02:54:54 +00:00
881 lines
24 KiB
ArmAsm
881 lines
24 KiB
ArmAsm
; a simple NETBIOS over TCP server
|
|
; aka "Common Internet File System"
|
|
;
|
|
; refs: RFC1001, RFC1002, "Implementing CIFS" - http://ubiqx.org/cifs/
|
|
|
|
.include "zeropage.inc"
|
|
.include "../inc/common.i"
|
|
|
|
.ifndef KPR_API_VERSION_NUMBER
|
|
.define EQU =
|
|
.include "../inc/kipper_constants.i"
|
|
.endif
|
|
|
|
DEFAULT_CIFS_CMD_BUFFER = $6800
|
|
DEFAULT_SMB_RESPONSE_BUFFER = $6000
|
|
|
|
.export cifs_l1_encode
|
|
.export cifs_l1_decode
|
|
.export cifs_start
|
|
|
|
.import copymem
|
|
.importzp copy_src
|
|
.importzp copy_dest
|
|
|
|
.import cfg_ip
|
|
.import output_buffer
|
|
.importzp udp_data
|
|
.import udp_send
|
|
.import udp_inp
|
|
.importzp udp_data
|
|
.import udp_send_dest
|
|
.import udp_send_src_port
|
|
.import udp_send_dest_port
|
|
.import udp_send_len
|
|
.importzp ip_src
|
|
.importzp ip_dest
|
|
.import ip_data
|
|
.import ip_inp
|
|
.import tcp_close
|
|
.import tcp_listen
|
|
.import tcp_callback
|
|
.import tcp_inbound_data_length
|
|
.import tcp_inbound_data_ptr
|
|
.import tcp_send
|
|
.import tcp_send_data_len
|
|
|
|
.import ip65_process
|
|
.import udp_add_listener
|
|
.import udp_callback
|
|
|
|
nbns_txn_id = 0
|
|
nbns_opcode = 2
|
|
nbns_flags_rcode = 3
|
|
nbns_qdcount = 4
|
|
nbns_ancount = 6
|
|
nbns_nscount = 8
|
|
nbns_arcount = 10
|
|
nbns_question_name = 12
|
|
nbns_service_type = 43
|
|
|
|
nbns_my_ip = 64
|
|
nbns_registration_message_length = 68
|
|
|
|
; given an ASCII (or PETSCII) hostname, convert to
|
|
; canonical 'level 1 encoded' form.
|
|
;
|
|
; only supports the default scope (' ' : 0x20)
|
|
; inputs:
|
|
; AX: pointer to null terminated hostname to be encoded
|
|
; outputs:
|
|
; AX: pointer to decoded hostname
|
|
cifs_l1_encode:
|
|
stax ptr1
|
|
lda #0
|
|
tax
|
|
sta hostname_buffer+32
|
|
@empty_buffer_loop:
|
|
lda #$43
|
|
sta hostname_buffer,x
|
|
inx
|
|
lda #$41
|
|
sta hostname_buffer,x
|
|
inx
|
|
cpx #$20
|
|
bmi @empty_buffer_loop
|
|
ldy #0
|
|
ldx #0
|
|
@copy_loop:
|
|
lda (ptr1),y
|
|
beq @done
|
|
lsr
|
|
lsr
|
|
lsr
|
|
lsr
|
|
clc
|
|
adc #$41
|
|
sta hostname_buffer,x
|
|
inx
|
|
lda (ptr1),y
|
|
and #$0F
|
|
clc
|
|
adc #$41
|
|
sta hostname_buffer,x
|
|
inx
|
|
iny
|
|
cpx #$1D
|
|
bmi @copy_loop
|
|
@done:
|
|
ldax #hostname_buffer
|
|
rts
|
|
|
|
; given a 'level 1 encoded' hostname, decode to ASCII.
|
|
;
|
|
; inputs:
|
|
; AX: pointer to encoded hostname to be decoded
|
|
; outputs:
|
|
; AX: pointer to decoded hostname (will be 16 byte hostname, right padded with spaces, nul terminated)
|
|
cifs_l1_decode:
|
|
stax ptr1
|
|
ldy #0
|
|
ldx #0
|
|
@decode_loop:
|
|
lda (ptr1),y
|
|
sec
|
|
sbc #$41
|
|
asl
|
|
asl
|
|
asl
|
|
asl
|
|
sta hi_nibble
|
|
iny
|
|
lda (ptr1),y
|
|
sec
|
|
sbc #$41
|
|
clc
|
|
adc hi_nibble
|
|
sta hostname_buffer,x
|
|
iny
|
|
inx
|
|
cpx #$10
|
|
bmi @decode_loop
|
|
lda #0
|
|
sta hostname_buffer,x
|
|
ldax #hostname_buffer
|
|
rts
|
|
|
|
; start a CIFS (SMB) server process, and advertise the specified hostname on the local LAN
|
|
;
|
|
; inputs:
|
|
; AX = ptr to hostname to be used
|
|
; outputs:
|
|
; none
|
|
cifs_start:
|
|
; save the hostname in 'raw' form
|
|
stax copy_src
|
|
ldax #raw_local_hostname
|
|
stax copy_dest
|
|
ldax #$0f
|
|
stx raw_local_hostname+15
|
|
jsr copymem
|
|
|
|
; set up callbacks
|
|
ldax #nbns_callback
|
|
stax udp_callback
|
|
ldax #137
|
|
jsr udp_add_listener
|
|
|
|
ldax #nbns_callback
|
|
stax udp_callback
|
|
ldax #137
|
|
jsr udp_add_listener
|
|
|
|
ldax #raw_local_hostname
|
|
jsr cifs_l1_encode
|
|
ldx #0
|
|
@copy_hostname_loop:
|
|
lda hostname_buffer,x
|
|
sta local_hostname,x
|
|
inx
|
|
cpx #$21
|
|
bmi @copy_hostname_loop
|
|
|
|
jsr cifs_advertise_hostname
|
|
jsr cifs_advertise_hostname
|
|
|
|
ldax #nb_session_callback
|
|
stax tcp_callback
|
|
@listen:
|
|
ldax #-4 ; start at -4, to skip the NBT header length
|
|
stax cifs_cmd_length
|
|
|
|
ldax cifs_cmd_buffer
|
|
stax cifs_cmd_buffer_ptr
|
|
ldax #139
|
|
stx connection_closed
|
|
|
|
jsr tcp_listen
|
|
|
|
@loop:
|
|
inc $d020 ; FIXME
|
|
jsr ip65_process
|
|
lda connection_closed
|
|
beq @loop
|
|
|
|
jmp @listen
|
|
rts
|
|
|
|
; broadcast a Name Registration Request message to the local LAN
|
|
cifs_advertise_hostname:
|
|
; advertise the 'server' service for own hostname
|
|
; overwrite the hostname in 'DNS compressed form'
|
|
; we assume this hostname ends with <20>
|
|
lda #$20 ; indicates what follows is a netbios name
|
|
sta output_buffer+nbns_question_name
|
|
|
|
ldx #0
|
|
@copy_hostname_loop:
|
|
lda local_hostname,x
|
|
sta registration_request_servername+1,x
|
|
inx
|
|
cpx #$21
|
|
bmi @copy_hostname_loop
|
|
|
|
jsr @send_nbns_message
|
|
|
|
; copy our encode hostname to the host announcment
|
|
ldax #local_hostname
|
|
stax copy_src
|
|
ldax #host_announce_hostname
|
|
stax copy_dest
|
|
ldax #$20
|
|
jsr copymem
|
|
|
|
; copy our raw hostname to the host announcment
|
|
ldax #raw_local_hostname
|
|
stax copy_src
|
|
ldax #host_announce_servername
|
|
stax copy_dest
|
|
ldax #$10
|
|
jsr copymem
|
|
|
|
; copy the local IP address to the 'sender' field of the host announcment
|
|
ldx #03
|
|
@copy_sending_address_loop:
|
|
lda cfg_ip,x
|
|
sta host_announce_my_ip,x
|
|
dex
|
|
bpl @copy_sending_address_loop
|
|
|
|
ldax #138
|
|
stax udp_send_dest_port
|
|
stax udp_send_src_port
|
|
|
|
ldax #host_announce_message_length
|
|
stax udp_send_len
|
|
|
|
ldax #host_announce_message
|
|
jsr udp_send
|
|
rts
|
|
|
|
@send_nbns_message:
|
|
; copy the local IP address
|
|
ldx #03
|
|
@copy_my_address_loop:
|
|
lda cfg_ip,x
|
|
sta nbns_my_ip,x
|
|
dex
|
|
bpl @copy_my_address_loop
|
|
|
|
; send to the broadcast address
|
|
lda #$ff
|
|
ldx #03
|
|
@copy_broadcast_address_loop:
|
|
sta udp_send_dest,x
|
|
dex
|
|
bpl @copy_broadcast_address_loop
|
|
|
|
ldax #137
|
|
stax udp_send_dest_port
|
|
stax udp_send_src_port
|
|
|
|
ldax #nbns_registration_message_length
|
|
stax udp_send_len
|
|
|
|
ldax #registration_request
|
|
jsr udp_send
|
|
rts
|
|
|
|
nbns_callback:
|
|
lda udp_inp+udp_data+nbns_opcode
|
|
and #$f8 ; mask the lower three bits
|
|
beq @name_request
|
|
rts
|
|
@name_request:
|
|
; this is a NB NAME REQUEST.
|
|
; is it a unicast message?
|
|
ldx #3
|
|
@check_unicast_loop:
|
|
lda ip_inp+ip_dest,x
|
|
cmp cfg_ip,x
|
|
bne @not_unicast
|
|
dex
|
|
bpl @check_unicast_loop
|
|
|
|
jmp @looking_for_us
|
|
|
|
@not_unicast:
|
|
; is it looking for our local hostname?
|
|
ldax #udp_inp+udp_data+nbns_question_name+1
|
|
stax ptr1
|
|
ldy #0
|
|
@cmp_loop:
|
|
lda (ptr1),y
|
|
cmp local_hostname,y
|
|
bne @not_us
|
|
iny
|
|
cpy #30
|
|
bne @cmp_loop
|
|
|
|
@looking_for_us:
|
|
; this is a request for our name!
|
|
; copy the txn id
|
|
ldax udp_inp+udp_data ; first 2 bytes of data are txn id
|
|
stax netbios_name_query_response
|
|
|
|
; set the sender & recipients IP address
|
|
ldx #03
|
|
@copy_address_loop:
|
|
lda ip_inp+ip_src,x
|
|
sta udp_send_dest,x
|
|
lda cfg_ip,x
|
|
sta netbios_name_query_response_ip,x
|
|
dex
|
|
bpl @copy_address_loop
|
|
|
|
; copy our encoded hostname
|
|
ldax #local_hostname
|
|
stax copy_src
|
|
ldax #netbios_name_query_response_hostname
|
|
stax copy_dest
|
|
ldax #30
|
|
jsr copymem
|
|
|
|
.import eth_inp
|
|
|
|
; copy the service identifier - last 2 bytes in the query hostname
|
|
ldax eth_inp+$55
|
|
stax netbios_name_query_response_hostname+30
|
|
|
|
ldax #137
|
|
stax udp_send_dest_port
|
|
stax udp_send_src_port
|
|
|
|
ldax #netbios_name_query_response_length
|
|
stax udp_send_len
|
|
|
|
ldax #netbios_name_query_response
|
|
jmp udp_send
|
|
|
|
@not_us:
|
|
rts
|
|
|
|
nb_session_callback:
|
|
lda tcp_inbound_data_length+1
|
|
cmp #$ff
|
|
bne @not_eof
|
|
@eof:
|
|
inc connection_closed
|
|
@done:
|
|
rts
|
|
@not_eof:
|
|
; copy this chunk to our input buffer
|
|
ldax cifs_cmd_buffer_ptr
|
|
stax copy_dest
|
|
ldax tcp_inbound_data_ptr
|
|
stax copy_src
|
|
ldax tcp_inbound_data_length
|
|
jsr copymem
|
|
|
|
; increment the pointer into the input buffer
|
|
clc
|
|
lda cifs_cmd_buffer_ptr
|
|
adc tcp_inbound_data_length
|
|
sta cifs_cmd_buffer_ptr
|
|
lda cifs_cmd_buffer_ptr+1
|
|
adc tcp_inbound_data_length+1
|
|
sta cifs_cmd_buffer_ptr+1
|
|
|
|
; increment the cmd buffer length
|
|
clc
|
|
lda cifs_cmd_length
|
|
adc tcp_inbound_data_length
|
|
sta cifs_cmd_length
|
|
lda cifs_cmd_length+1
|
|
adc tcp_inbound_data_length+1
|
|
sta cifs_cmd_length+1
|
|
|
|
; have we got a complete message?
|
|
ldax cifs_cmd_buffer
|
|
stax ptr1
|
|
ldy #3
|
|
lda (ptr1),y
|
|
cmp cifs_cmd_length
|
|
bne @not_got_full_message
|
|
dey
|
|
lda (ptr1),y
|
|
cmp cifs_cmd_length+1
|
|
bne @not_got_full_message
|
|
|
|
; we have a complete message!
|
|
ldy #0
|
|
lda (ptr1),y ; get the message type
|
|
cmp #$81 ; is it a session request?
|
|
bne @not_session_request
|
|
ldax #positive_session_response_packet_length
|
|
stax tcp_send_data_len
|
|
ldax #positive_session_response_packet
|
|
jsr tcp_send
|
|
jmp @message_handled
|
|
|
|
@not_session_request:
|
|
cmp #$00 ; is it a session message?
|
|
bne @not_session_message
|
|
|
|
; this SHOULD be a SMB - best check the header
|
|
ldy #4
|
|
lda (ptr1),y ; get the message data
|
|
cmp #$FF ; start of SMB header
|
|
bne @not_smb
|
|
iny
|
|
lda (ptr1),y ; get the message data
|
|
cmp #'S' ; start of SMB header
|
|
bne @not_smb
|
|
|
|
jsr smb_handler
|
|
|
|
jmp @message_handled
|
|
|
|
; this doesn't look like a NBT session message or SMB, so give up
|
|
@not_session_message:
|
|
@not_smb:
|
|
jsr tcp_close
|
|
jmp @eof
|
|
|
|
@message_handled:
|
|
; reset ready for next message on this connection
|
|
ldax #-4 ; start at -4, to skip the NBT header length
|
|
stax cifs_cmd_length
|
|
|
|
ldax cifs_cmd_buffer
|
|
stax cifs_cmd_buffer_ptr
|
|
|
|
@not_got_full_message:
|
|
rts
|
|
|
|
smb_handler:
|
|
; at this point, ptr1 points to an SMB block encapsulated in an NBT session header
|
|
clc
|
|
lda ptr1
|
|
adc #4
|
|
sta smb_ptr ; skip past the NBT header
|
|
lda ptr1+1
|
|
adc #00
|
|
sta smb_ptr+1
|
|
|
|
ldy #8
|
|
lda (ptr1),y ; get the SMB type
|
|
cmp #$72
|
|
bne @not_negotiate_protocol
|
|
jmp @negotiate_protocol
|
|
|
|
@not_negotiate_protocol:
|
|
; we assume it is an "AndX" command
|
|
sta andx_opcode
|
|
lda smb_ptr
|
|
clc
|
|
adc #$20 ; skip over SMB header
|
|
sta andx_ptr
|
|
|
|
lda smb_ptr+1
|
|
adc #00
|
|
sta andx_ptr+1
|
|
|
|
jsr start_smb_response
|
|
|
|
@parse_andx_block:
|
|
ldax andx_ptr
|
|
stax ptr1
|
|
lda andx_opcode
|
|
|
|
cmp #$ff
|
|
beq @done_all_andx_blocks
|
|
|
|
ldy #0
|
|
@andx_opcode_scan:
|
|
lda andx_opcodes,y
|
|
beq @opcode_not_found
|
|
cmp andx_opcode
|
|
beq @opcode_found
|
|
iny
|
|
iny
|
|
iny
|
|
jmp @andx_opcode_scan
|
|
@opcode_found:
|
|
lda andx_opcodes+1,y
|
|
sta andx_handler+1
|
|
lda andx_opcodes+2,y
|
|
sta andx_handler+2
|
|
jsr andx_handler
|
|
jmp @go_to_next_andx_block
|
|
|
|
@opcode_not_found:
|
|
jsr unknown_andx
|
|
|
|
@go_to_next_andx_block:
|
|
ldy #3
|
|
lda (ptr1),y ; get the AndX offset low byte
|
|
clc
|
|
adc smb_ptr
|
|
sta andx_ptr
|
|
iny
|
|
lda (ptr1),y ; get the AndX offset high byte
|
|
adc smb_ptr+1
|
|
sta andx_ptr+1
|
|
ldy #1
|
|
lda (ptr1),y ; get the subsequent AndX opcode
|
|
sta andx_opcode
|
|
|
|
jmp @parse_andx_block
|
|
|
|
@done_all_andx_blocks:
|
|
ldax smb_response_length
|
|
inx ; FIXME! this is to force wireshark to dump as SMB even tho packet is incorrect
|
|
stax tcp_send_data_len
|
|
ldax smb_response_buffer
|
|
jsr tcp_send
|
|
rts
|
|
|
|
@negotiate_protocol:
|
|
; copy the request TID,PID,UID,MID into the response
|
|
ldy #28 ; offset of TID from start of message
|
|
ldx #0
|
|
: lda (ptr1),y
|
|
sta negotiate_protocol_response_tid,x
|
|
inx
|
|
iny
|
|
cpx #8
|
|
bne :-
|
|
|
|
lda #$ff
|
|
sta dialect_index
|
|
sta dialect_index+1
|
|
clc
|
|
lda cifs_cmd_buffer
|
|
adc #$26
|
|
sta ptr1
|
|
lda cifs_cmd_buffer+1
|
|
adc #$00
|
|
sta ptr1+1
|
|
|
|
ldy #$0
|
|
@dialect_scan_loop:
|
|
iny
|
|
bmi @end_of_dialects ; if we go to offset $80, we have gone too far
|
|
lda dialect_index
|
|
cmp #$10 ; if we've scanned more than $10 dialects, something is wrong
|
|
beq @end_of_dialects
|
|
lda (ptr1),y
|
|
cmp #$02
|
|
bne @test_dialect
|
|
inc dialect_index
|
|
jmp @dialect_scan_loop
|
|
@test_dialect:
|
|
tya
|
|
clc
|
|
adc ptr1
|
|
sta ptr1
|
|
bcc :+
|
|
inc ptr1+1
|
|
: ldy #0
|
|
|
|
@test_dialect_loop:
|
|
lda (ptr1),y
|
|
cmp preferred_dialect_id,y
|
|
bne @dialect_scan_loop
|
|
iny
|
|
cpy #preferred_dialect_id_length
|
|
bne @test_dialect_loop
|
|
inc dialect_index+1
|
|
jmp @found_preferred_dialect
|
|
|
|
@end_of_dialects:
|
|
lda #$ff
|
|
sta dialect_index
|
|
|
|
@found_preferred_dialect:
|
|
ldax #negotiate_protocol_response_message_length
|
|
stax tcp_send_data_len
|
|
ldax #negotiate_protocol_response_message
|
|
jsr tcp_send
|
|
rts
|
|
|
|
start_smb_response:
|
|
ldax smb_response_buffer
|
|
stax ptr2
|
|
ldy #0
|
|
@copy_header_loop:
|
|
lda (ptr1),y ; copy_src should be the SMB request - cloning this will set PID / MID etc
|
|
sta (ptr2),y
|
|
iny
|
|
cpy #smb_response_header_length
|
|
bne @copy_header_loop
|
|
lda #0
|
|
sta smb_response_length+1
|
|
lda #smb_response_header_length
|
|
sta smb_response_length
|
|
ldy #3
|
|
sta (ptr2),y
|
|
|
|
; set the flags correctly
|
|
ldy #smb_response_flags_offset
|
|
lda #$82 ; FLAGS byte
|
|
sta (ptr2),y
|
|
iny
|
|
lda #$01 ; FLAGS2 low byte
|
|
sta (ptr2),y
|
|
iny
|
|
lda #$00 ; FLAGS2 hi byte
|
|
sta (ptr2),y
|
|
rts
|
|
|
|
add_andx_response:
|
|
rts
|
|
|
|
.import print_a
|
|
.import print_hex
|
|
session_setup_andx:
|
|
lda #'S'
|
|
jsr print_a
|
|
rts
|
|
|
|
tree_connect_andx:
|
|
lda #'T'
|
|
jsr print_a
|
|
rts
|
|
|
|
unknown_andx:
|
|
lda andx_opcode
|
|
jsr print_hex
|
|
lda #'?'
|
|
jsr print_a
|
|
rts
|
|
|
|
|
|
.rodata
|
|
|
|
andx_opcodes:
|
|
.byte $73
|
|
.word session_setup_andx
|
|
.byte $75
|
|
.word tree_connect_andx
|
|
.byte $00
|
|
|
|
|
|
.data
|
|
|
|
andx_handler:
|
|
jmp $FFFF ; filled in later
|
|
|
|
smb_response_header:
|
|
negotiate_protocol_response_message:
|
|
.byte $00 ; message type = session message
|
|
.byte $00,$00,negotiate_protocol_response_message_length-4 ; NBT header
|
|
.byte $FF,"SMB" ; SMB header
|
|
.byte $72 ; command = negotiate protocol
|
|
.byte $00,$00,$00,$00 ; status = OK
|
|
smb_response_flags_offset = *-smb_response_header
|
|
.byte $82 ; flags : oplocks not supported, paths are case sensitive
|
|
.byte $01,$00 ; flags 2 - long file names allowed
|
|
.byte $00, $00 ; PID HIGH
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00 ; signature
|
|
.byte $00, $00 ; reserved
|
|
negotiate_protocol_response_tid:
|
|
.byte $00,$00 ; tree ID
|
|
.byte $98,$76 ; PID - to be overwritten
|
|
.byte $65,$64 ; USER ID - to be overwritten
|
|
.byte $ab,$cd ; multiplex ID - to be overwritten
|
|
smb_response_header_length = *-smb_response_header
|
|
.byte $11 ; word count
|
|
dialect_index:
|
|
.byte $00, $00 ; index of selected dialect
|
|
.byte $00 ; security mode: share, no encryption
|
|
.byte $01,$00 ; Max MPX count
|
|
.byte $01,$00 ; Max VCs count
|
|
.byte $00,$08,$00,$00 ; max buffer size
|
|
.byte $00,$08,$00,$00 ; max raw size
|
|
.byte $12,$34,$56,$78 ; session key
|
|
.byte $00,$00,$00,$00 ; capabilities
|
|
.byte $00,$00,$00,$00 ; server time low
|
|
.byte $00,$00,$00,$00 ; server time high
|
|
.byte $00,$00 ; server GMT offset
|
|
.byte $00 ; encryption key length
|
|
.word negotiate_protocol_response_message_data_length ; data length
|
|
negotiate_protocol_response_message_data:
|
|
.byte "WORKGROUP",0
|
|
.byte "SERVERNAME",0
|
|
|
|
negotiate_protocol_response_message_length = *-negotiate_protocol_response_message
|
|
negotiate_protocol_response_message_data_length = *-negotiate_protocol_response_message_data
|
|
|
|
host_announce_message:
|
|
.byte $11 ; message type = direct group datagram
|
|
.byte $02 ; no more fragments, this is first fragment, node type = B
|
|
.byte $ab,$cd ; txn id
|
|
host_announce_my_ip:
|
|
.byte $0,0,0,0 ; source IP
|
|
.byte $0,138 ; source port
|
|
.byte $00,<(host_announce_message_length-4) ; datagram length
|
|
.byte $00,$00 ; packet offset
|
|
.byte $20 ; hostname length
|
|
host_announce_hostname:
|
|
.res 32 ; hostname
|
|
.byte $0 ; nul at end of hostname
|
|
; now WORKGROUP<1D> encoded
|
|
|
|
.byte $20, $46, $48, $45, $50, $46, $43, $45, $4c, $45, $48, $46, $43, $45, $50, $46
|
|
.byte $46, $46, $41, $43, $41, $43, $41, $43, $41, $43, $41, $43, $41, $43, $41, $42, $4E, $00
|
|
|
|
.byte $ff,"SMB" ; Server Message Block header
|
|
.byte $25 ; SMB command = Transaction
|
|
.byte $00 ; error class = success
|
|
.byte $00 ; reserved
|
|
.byte $00,$00 ; no error
|
|
.byte $00 ; flags
|
|
.byte $00,$00 ; flags2
|
|
.byte $00,$00 ; PID high
|
|
.byte $00,$00,$00,$00,$00,$00,$00,$00 ; Signature
|
|
.byte $00,$00 ; reserved
|
|
.byte $00,$00 ; tree ID
|
|
.byte $00,$00 ; process ID
|
|
.byte $00,$00 ; user ID
|
|
.byte $00,$00 ; multiplex ID
|
|
.byte $11 ; txn word count
|
|
.byte $00,$00 ; txn paramater count
|
|
.byte $21,$00 ; txn total data count
|
|
.byte $00,$00 ; txn max paramater count
|
|
.byte $00,$00 ; txn max data count
|
|
.byte $00 ; txn max setup count
|
|
.byte $00 ; reserved
|
|
.byte $00,$00 ; flags
|
|
.byte $ed,$03,$00,$00 ; timeout = 1 second
|
|
.byte $00,$00 ; reserved
|
|
.byte $00,$00 ; paramater count
|
|
.byte $00,$00 ; paramater offset
|
|
.byte $21,$00 ; data count
|
|
.byte $56,$00 ; data offset
|
|
.byte $03 ; setup count
|
|
.byte $00 ; reserved
|
|
|
|
.byte $01,$00 ; opcode = WRITE MAIL SLOT
|
|
.byte $00,$00 ; priority 0
|
|
.byte $02,$00 ; class = unreliable & broadcast
|
|
.byte $32,$00 ; byte count
|
|
.byte "\MAILSLOT\BROWSE", 0
|
|
.byte $01 ; command - HOST ANNOUNCEMENT
|
|
.byte $0 ; update count 0
|
|
.byte $80,$fc,03,00 ; update period
|
|
host_announce_servername:
|
|
.res 16
|
|
.byte $01 ; OS major version
|
|
.byte $64 ; OS minor version
|
|
.byte $03,$02,$0,$0 ; advertise as a workstation, server & print host
|
|
.byte $0F ; browser major version
|
|
.byte $01 ; browser minor version
|
|
.byte $55,$aa ; signature
|
|
.byte $0 ; host comment
|
|
host_announce_message_length = *-host_announce_message
|
|
|
|
netbios_name_query_response:
|
|
.byte $12,$34 ; transaction id
|
|
.byte $85,$00 ; flags: name query response, no error
|
|
.byte $00,$00 ; questions = 0
|
|
.byte $00,$01 ; answers = 1
|
|
.byte $00,$00 ; authority records = 0
|
|
.byte $00,$00 ; additional records = 0
|
|
.byte $20
|
|
netbios_name_query_response_hostname:
|
|
.res 30 ; will be replaced with encoded hostname
|
|
.byte $43,$41
|
|
.byte $00
|
|
.byte $00,$20 ; type = NB
|
|
.byte $00,$01 ; class = IN
|
|
.byte $00,$00,$01,$40 ; TTL = 64 seconds
|
|
.byte $00,$06 ; data length
|
|
.byte $00,$00 ; FLAGS = B-NODE, UNIQUE NAME
|
|
netbios_name_query_response_ip:
|
|
.res 4 ; filled in with our IP
|
|
netbios_name_query_response_length = *-netbios_name_query_response
|
|
|
|
registration_request:
|
|
.byte $0c,$64 ; txn ID
|
|
.byte $29,$10 ; Registration Request opcode & flags
|
|
.byte $00,$01 ; questions = 1
|
|
.byte $00,$00 ; answers = 0
|
|
.byte $00,$00 ; authority records = 0
|
|
.byte $00,$01 ; additional records = 1
|
|
registration_request_servername:
|
|
; now WORKGROUP<00> encoded
|
|
.byte $20, $46, $48, $45, $50, $46, $43, $45, $4c, $45, $48, $46, $43, $45, $50, $46
|
|
.byte $46, $46, $41, $43, $41, $43, $41, $43, $41, $43, $41, $43, $41, $43, $41, $41, $41, $00
|
|
|
|
.byte $00,$20 ; question_type = NB
|
|
.byte $00,$01 ; question_class = IN
|
|
.byte $c0,$0c ; additional record name : ptr to string in QUESTION NAME
|
|
.byte $00,$20 ; question_type = NB
|
|
.byte $00,$01 ; question_class = IN
|
|
.byte $00,$00,$01,$40 ; TTL = 64 seconds
|
|
.byte $00,$06 ; data length
|
|
.byte $00,$00 ; FLAGS = B-NODE, UNIQUE NAME
|
|
|
|
|
|
.rodata
|
|
|
|
preferred_dialect_id: .byte "NT LM 0.12"
|
|
preferred_dialect_id_length = *-preferred_dialect_id
|
|
|
|
positive_session_response_packet:
|
|
.byte $82 ; packet type = Positive session response
|
|
.byte $00 ; flags
|
|
.byte $00,$00 ; message length
|
|
positive_session_response_packet_length = *-positive_session_response_packet
|
|
|
|
|
|
.data
|
|
|
|
cifs_cmd_buffer: .word DEFAULT_CIFS_CMD_BUFFER
|
|
|
|
smb_response_buffer: .word DEFAULT_SMB_RESPONSE_BUFFER
|
|
|
|
|
|
.bss
|
|
|
|
hostname_buffer: .res 33
|
|
|
|
local_hostname: .res 33
|
|
|
|
raw_local_hostname: .res 16
|
|
|
|
hi_nibble: .res 1
|
|
|
|
connection_closed: .res 1
|
|
|
|
cifs_cmd_buffer_ptr: .res 2
|
|
cifs_cmd_length: .res 2
|
|
|
|
andx_opcode: .res 1
|
|
andx_ptr: .res 2 ; pointer to next 'AndX' command
|
|
andx_length: .res 2
|
|
smb_ptr: .res 2
|
|
smb_response_length: .res 2
|
|
|
|
|
|
|
|
; The contents of this file are subject to the Mozilla Public License
|
|
; Version 1.1 (the "License"); you may not use this file except in
|
|
; compliance with the License. You may obtain a copy of the License at
|
|
; http://www.mozilla.org/MPL/
|
|
;
|
|
; Software distributed under the License is distributed on an "AS IS"
|
|
; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
|
; License for the specific language governing rights and limitations
|
|
; under the License.
|
|
;
|
|
; The Original Code is ip65.
|
|
;
|
|
; The Initial Developer of the Original Code is Jonno Downes,
|
|
; jonno@jamtronix.com.
|
|
; Portions created by the Initial Developer are Copyright (C) 2009
|
|
; Jonno Downes. All Rights Reserved.
|
|
; -- LICENSE END --
|