mirror of
https://github.com/bobbimanners/emailler.git
synced 2024-11-08 19:10:52 +00:00
244 lines
4.8 KiB
ArmAsm
244 lines
4.8 KiB
ArmAsm
;ICMP implementation
|
|
;
|
|
|
|
.include "../inc/common.i"
|
|
|
|
.export icmp_init
|
|
.export icmp_process
|
|
.export icmp_add_listener
|
|
.export icmp_remove_listener
|
|
|
|
.export icmp_callback
|
|
|
|
.export icmp_inp
|
|
.export icmp_outp
|
|
.exportzp icmp_type
|
|
.exportzp icmp_code
|
|
.exportzp icmp_cksum
|
|
.exportzp icmp_data
|
|
|
|
|
|
.import ip_calc_cksum
|
|
.import ip_inp
|
|
.import ip_outp
|
|
.import ip_broadcast
|
|
.importzp ip_cksum_ptr
|
|
.importzp ip_header_cksum
|
|
.importzp ip_src
|
|
.importzp ip_dest
|
|
.importzp ip_data
|
|
|
|
.import eth_tx
|
|
.import eth_inp
|
|
.import eth_inp_len
|
|
.import eth_outp
|
|
.import eth_outp_len
|
|
|
|
|
|
.bss
|
|
|
|
; argument for icmp_add_listener
|
|
icmp_callback: .res 2
|
|
|
|
; icmp callbacks
|
|
icmp_cbmax = 4
|
|
icmp_cbtmp: .res 3 ; temporary vector
|
|
icmp_cbveclo: .res icmp_cbmax ; table of listener vectors (lsb)
|
|
icmp_cbvechi: .res icmp_cbmax ; table of listener vectors (msb)
|
|
icmp_cbtype: .res icmp_cbmax ; table of listener types
|
|
icmp_cbcount: .res 1 ; number of active listeners
|
|
|
|
; icmp packet offsets
|
|
icmp_inp = ip_inp + ip_data ;pointer to inbound icmp packet
|
|
icmp_outp = ip_outp + ip_data ;pointer to outbound icmp packet
|
|
icmp_type = 0 ;offset of 'type' field in icmp packet
|
|
icmp_code = 1 ;offset of 'code' field in icmp packet
|
|
icmp_cksum = 2 ;offset of 'checksum' field in icmp packet
|
|
icmp_data = 4;offset of 'data' field in icmp packet
|
|
|
|
; icmp echo packet offsets
|
|
icmp_echo_id = 4 ;offset of 'id' field in icmp echo request/echo response
|
|
icmp_echo_seq = 6 ;offset of 'sequence' field in icmp echo request/echo response
|
|
icmp_echo_data = 8 ;offset of 'data' field in icmp echo request/echo response
|
|
|
|
|
|
.code
|
|
|
|
; initialize icmp
|
|
; inputs: none
|
|
; outputs: none
|
|
icmp_init:
|
|
lda #0
|
|
sta icmp_cbcount
|
|
lda #$4c ; jmp addr
|
|
sta icmp_cbtmp
|
|
rts
|
|
|
|
;process incoming icmp packet
|
|
;inputs:
|
|
; eth_inp points to an ethernet frame containing an icmp packet
|
|
;outputs:
|
|
; carry flag - set on any error, clear if OK
|
|
; if inbound packet is a request (e.g. 'echo request') and an icmp listener
|
|
; has been installed, then an appropriate response message will be
|
|
; generated and sent out (overwriting the eth_outp buffer)
|
|
icmp_process:
|
|
lda icmp_inp + icmp_type
|
|
cmp #8 ; ping
|
|
beq @echo
|
|
|
|
lda icmp_cbcount ; any installed icmp listeners?
|
|
beq @drop
|
|
|
|
ldx icmp_cbcount ; check listened types
|
|
dex
|
|
: lda icmp_cbtype,x
|
|
cmp icmp_inp + icmp_type
|
|
beq @handle ; found a match
|
|
dex
|
|
bpl :-
|
|
|
|
@drop:
|
|
sec
|
|
rts
|
|
|
|
@handle:
|
|
lda icmp_cbveclo,x ; copy vector
|
|
sta icmp_cbtmp + 1
|
|
lda icmp_cbvechi,x
|
|
sta icmp_cbtmp + 2
|
|
jsr icmp_cbtmp ; call listener
|
|
clc
|
|
rts
|
|
|
|
@echo:
|
|
lda ip_broadcast ; check if packet is broadcast
|
|
beq @notbc
|
|
sec ; don't reply to broadcast pings
|
|
rts
|
|
@notbc:
|
|
ldx #5
|
|
: lda eth_inp,x ; swap dest and src mac
|
|
sta eth_outp + 6,x
|
|
lda eth_inp + 6,x
|
|
sta eth_outp,x
|
|
dex
|
|
bpl :-
|
|
|
|
ldx #12 ; copy the packet
|
|
: lda eth_inp,x
|
|
sta eth_outp,x
|
|
inx
|
|
cpx eth_inp_len
|
|
bne :-
|
|
|
|
ldx #3
|
|
: lda ip_inp + ip_src,x ; swap dest and src ip
|
|
sta ip_outp + ip_dest,x
|
|
lda ip_inp + ip_dest,x
|
|
sta ip_outp + ip_src,x
|
|
dex
|
|
bpl :-
|
|
|
|
lda #0 ; change type to reply
|
|
sta icmp_outp + icmp_type
|
|
|
|
lda icmp_inp + icmp_cksum ; recalc checksum
|
|
clc
|
|
adc #8
|
|
sta icmp_outp + icmp_cksum
|
|
bcc :+
|
|
inc icmp_outp + icmp_cksum + 1
|
|
:
|
|
lda eth_inp_len ; copy length
|
|
sta eth_outp_len
|
|
lda eth_inp_len + 1
|
|
sta eth_outp_len + 1
|
|
|
|
lda #0 ; clear checksum
|
|
sta ip_outp + ip_header_cksum
|
|
sta ip_outp + ip_header_cksum + 1
|
|
ldax #ip_outp ; calculate ip header checksum
|
|
stax ip_cksum_ptr
|
|
ldax #20
|
|
jsr ip_calc_cksum
|
|
stax ip_outp + ip_header_cksum
|
|
|
|
jsr eth_tx ; send packet
|
|
|
|
clc
|
|
rts
|
|
|
|
|
|
;add an icmp listener
|
|
;inputs:
|
|
; A = icmp type
|
|
; icmp_callback: vector to call when an icmp packet of specified type arrives
|
|
;outputs:
|
|
; carry flag - set if error, clear if no error
|
|
icmp_add_listener:
|
|
ldx icmp_cbcount ; any listeners at all?
|
|
beq @add
|
|
cpx #icmp_cbmax ; max?
|
|
beq @full
|
|
ldx #0
|
|
: cmp icmp_cbtype,x ; check if type is already listened
|
|
beq @busy
|
|
inx
|
|
cpx icmp_cbcount
|
|
bne :-
|
|
@add:
|
|
inc icmp_cbcount ; increase counter
|
|
sta icmp_cbtype,x ; add type
|
|
lda icmp_callback ; and vector
|
|
sta icmp_cbveclo,x
|
|
lda icmp_callback + 1
|
|
sta icmp_cbvechi,x
|
|
|
|
clc
|
|
rts
|
|
@full:
|
|
@busy:
|
|
sec
|
|
rts
|
|
|
|
|
|
;add an icmp listener
|
|
;inputs:
|
|
; A = icmp type
|
|
;outputs:
|
|
; carry flag - set if error (i.e. no listner for this type exists),
|
|
; clear if no error
|
|
icmp_remove_listener:
|
|
ldx icmp_cbcount ; any listeners installed?
|
|
beq @notfound
|
|
: cmp icmp_cbtype,x ; check if type is listened
|
|
beq @remove
|
|
inx
|
|
cpx icmp_cbcount
|
|
bne :-
|
|
@notfound:
|
|
sec
|
|
rts
|
|
@remove:
|
|
txa ; number of listeners below
|
|
eor #$ff
|
|
clc
|
|
adc icmp_cbcount
|
|
beq @done
|
|
@move:
|
|
tay ; number of items to move
|
|
: lda icmp_cbtype + 1,x ; move type
|
|
sta icmp_cbtype,x
|
|
lda icmp_cbveclo + 1,x ; move vector lsb
|
|
sta icmp_cbveclo,x
|
|
lda icmp_cbvechi + 1,x ; move vector msb
|
|
sta icmp_cbvechi,x
|
|
inx
|
|
dey
|
|
bne :-
|
|
@done:
|
|
dec icmp_cbcount ; decrement counter
|
|
clc
|
|
rts
|