mirror of
https://github.com/dschmenk/PLASMA.git
synced 2024-12-24 15:29:29 +00:00
REady for use Uthernet IP modules
This commit is contained in:
parent
f2c9526c79
commit
235d6f5363
@ -7,14 +7,12 @@ import cmdsys
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip, subnet_mask, gateway
|
||||
predef swab, sendUDP, recvUDP, shutUDP, serviceIP
|
||||
end
|
||||
import icmp
|
||||
import inet
|
||||
byte localha, localip, subnet, gateway
|
||||
predef swab, sendUDP, listenUDP, hangupUDP, serviceIP
|
||||
end
|
||||
//
|
||||
// Needed to init subnet_mask
|
||||
// Needed to init subnet
|
||||
//
|
||||
const IP_BROADCAST = $FFFF
|
||||
//
|
||||
@ -48,6 +46,10 @@ const DHCP_ACK = $05
|
||||
const DHCP_NACK = $06
|
||||
const DHCP_RELEASE = $07
|
||||
//
|
||||
// Track DHCP progress
|
||||
//
|
||||
byte stateDHCP, retry, timeout
|
||||
//
|
||||
// DHCP ports
|
||||
//
|
||||
const DHCP_CLIENT_PORT = 68
|
||||
@ -156,6 +158,7 @@ def servdhcp(remip, remport, lclport, pkt, len, param)
|
||||
if pkt=>dhcp_xid:0 == $0201 and pkt=>dhcp_xid:2 = $0403
|
||||
when pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 53) + 2]
|
||||
is DHCP_OFFER
|
||||
stateDHCP = DHCP_OFFER
|
||||
//puts(@offerstr); putip(@pkt->dhcp_yourip); putln
|
||||
//
|
||||
// Copy offer parameters to request
|
||||
@ -167,13 +170,18 @@ def servdhcp(remip, remport, lclport, pkt, len, param)
|
||||
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
|
||||
break
|
||||
is DHCP_ACK
|
||||
stateDHCP = DHCP_ACK
|
||||
//
|
||||
// Stop listening to UDP port
|
||||
//
|
||||
hangupUDP(DHCP_CLIENT_PORT)
|
||||
//puts(@ackstr)
|
||||
//
|
||||
// Copy parameters to working copy
|
||||
//
|
||||
memcpy(@localip, @pkt->dhcp_yourip, 4)
|
||||
memcpy(@subnet_mask, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4)
|
||||
puts(@boundstr);putip(@localip);putc('/');putip(@subnet_mask);putln
|
||||
memcpy(@subnet, @pkt->dhcp_opts.[parseopts(@pkt->dhcp_opts, 1) + 2], 4)
|
||||
puts(@boundstr);putip(@localip);putc('/');putip(@subnet);putln
|
||||
break
|
||||
otherwise
|
||||
dumpdhcp(pkt)
|
||||
@ -191,20 +199,30 @@ memset(@localip, 0, 4)
|
||||
//
|
||||
// Set subnet mask to all 1's
|
||||
//
|
||||
memset(@subnet_mask, IP_BROADCAST, 4)
|
||||
memset(@subnet, IP_BROADCAST, 4)
|
||||
//
|
||||
// Prepare to receive DHCP packets from a server
|
||||
//
|
||||
recvUDP(DHCP_CLIENT_PORT, @servdhcp, 0)
|
||||
//
|
||||
// Broadcast DHCP DISCOVER message
|
||||
//
|
||||
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
|
||||
listenUDP(DHCP_CLIENT_PORT, @servdhcp, 0)
|
||||
//
|
||||
// Service IP
|
||||
//
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
while retry < 3
|
||||
//
|
||||
// Broadcast DHCP DISCOVER message
|
||||
//
|
||||
sendUDP(0, DHCP_SERVER_PORT, DHCP_CLIENT_PORT, @DHCP, t_dhcp)
|
||||
for timeout = 1 to 1000
|
||||
serviceIP
|
||||
if stateDHCP == DHCP_ACK
|
||||
return 0
|
||||
fin
|
||||
next
|
||||
retry = retry + 1
|
||||
loop
|
||||
//
|
||||
// Nobody answered
|
||||
//
|
||||
return -1
|
||||
|
||||
done
|
@ -1,12 +1,18 @@
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
byte MACHID
|
||||
end
|
||||
import uthernet
|
||||
predef copyMAC, writeEther, writevEther, readEther, recvEther
|
||||
end
|
||||
//
|
||||
// Module don't free memory
|
||||
//
|
||||
const modkeep = $2000
|
||||
const modinitkeep = $4000
|
||||
//
|
||||
// Predefine service routine
|
||||
//
|
||||
predef serviceIP
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
@ -47,50 +53,26 @@ struc t_iphdr
|
||||
byte[IPADR_SIZE] ip_dst
|
||||
byte[] ip_options
|
||||
end
|
||||
const t_ethriphdr = t_ethrhdr + t_iphdr
|
||||
const IP_BROADCAST = $FFFF
|
||||
const IP_PROTO_ICMP = $01
|
||||
const IP_PROTO_UDP = $11
|
||||
const IP_PROTO_TCP = $06
|
||||
//
|
||||
// ARP packet
|
||||
// ICMP type/codes
|
||||
//
|
||||
const HW_ETHER = $0100 // BE format
|
||||
const ARP_PROTO = $0008 // BE format
|
||||
const ARP_REQST = $0100 // BE format
|
||||
const ARP_REPLY = $0200 // BE format
|
||||
struc t_arp
|
||||
word arp_hw
|
||||
word arp_proto
|
||||
byte arp_hlen
|
||||
byte arp_plen
|
||||
word arp_op
|
||||
byte[MAC_SIZE] arp_senderha
|
||||
byte[IPADR_SIZE] arp_senderip
|
||||
byte[MAC_SIZE] arp_targha
|
||||
byte[IPADR_SIZE] arp_targip
|
||||
const IP_PROTO_ICMP = 1
|
||||
const ICMP_ECHO_REQST = 8
|
||||
const ICMP_ECHO_REPLY = 0
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_chksm
|
||||
word[2] icmp_header
|
||||
end
|
||||
const t_earp = t_ethrhdr+t_arp
|
||||
//
|
||||
// Pre-configured ARP packet
|
||||
//
|
||||
byte[] ARP
|
||||
byte[MAC_SIZE] dstMAC
|
||||
byte[MAC_SIZE] srcMAC
|
||||
word = PAYLOAD_ARP
|
||||
word = HW_ETHER // HW TYPE
|
||||
word = ARP_PROTO // PROTO TYPE
|
||||
byte = MAC_SIZE // HLEN
|
||||
byte = IPADR_SIZE // PLEN
|
||||
word opARP // OP
|
||||
export byte[MAC_SIZE] localha
|
||||
export byte[IPADR_SIZE] localip
|
||||
byte[MAC_SIZE] remoteha
|
||||
byte[IPADR_SIZE] remoteip
|
||||
//
|
||||
// Local network parameters
|
||||
//
|
||||
export byte[IPADR_SIZE] subnet_mask
|
||||
export byte[IPADR_SIZE] gateway
|
||||
//
|
||||
// UDP IPv4 psuedo header
|
||||
//
|
||||
@ -120,6 +102,60 @@ struc t_tcphdr
|
||||
word tcp_chksm
|
||||
end
|
||||
//
|
||||
// ARP packet
|
||||
//
|
||||
const HW_ETHER = $0100 // BE format
|
||||
const ARP_PROTO = $0008 // BE format
|
||||
const ARP_REQST = $0100 // BE format
|
||||
const ARP_REPLY = $0200 // BE format
|
||||
struc t_arp
|
||||
word arp_hw
|
||||
word arp_proto
|
||||
byte arp_hlen
|
||||
byte arp_plen
|
||||
word arp_op
|
||||
byte[MAC_SIZE] arp_senderha
|
||||
byte[IPADR_SIZE] arp_senderip
|
||||
byte[MAC_SIZE] arp_targha
|
||||
byte[IPADR_SIZE] arp_targip
|
||||
end
|
||||
const t_earp = t_ethrhdr+t_arp
|
||||
//
|
||||
// Pre-configured Ethernet header
|
||||
//
|
||||
byte[] eFrame
|
||||
//
|
||||
// Destination MAC address
|
||||
//
|
||||
byte[MAC_SIZE] dstMAC
|
||||
//
|
||||
// My MAC address
|
||||
//
|
||||
byte[MAC_SIZE] myMAC
|
||||
//
|
||||
// Ethernet payload
|
||||
//
|
||||
word ePayload = PAYLOAD_ARP
|
||||
//
|
||||
// Pre-configured ARP packet - MUST follow ethernet header!
|
||||
//
|
||||
word ARP = HW_ETHER // HW TYPE
|
||||
word = ARP_PROTO // PROTO TYPE
|
||||
byte = MAC_SIZE // HLEN
|
||||
byte = IPADR_SIZE // PLEN
|
||||
word opARP // OP
|
||||
export byte[MAC_SIZE] localha
|
||||
export byte[IPADR_SIZE] localip
|
||||
byte[MAC_SIZE] remoteha
|
||||
byte[IPADR_SIZE] remoteip
|
||||
//
|
||||
// Local network parameters
|
||||
//
|
||||
export byte[IPADR_SIZE] subnet
|
||||
export byte[IPADR_SIZE] gateway
|
||||
const MAX_UDP_NOTIFIES = 16
|
||||
const MAX_TCP_NOTIFIES = 8
|
||||
//
|
||||
// Notify callbacks
|
||||
//
|
||||
struc t_notify
|
||||
@ -127,14 +163,16 @@ struc t_notify
|
||||
word notify_func
|
||||
word notify_parm
|
||||
end
|
||||
const MAX_UDP_NOTIFIES = 16
|
||||
const MAX_TCP_NOTIFIES = 8
|
||||
word portsUDP
|
||||
word portsTCP
|
||||
//
|
||||
// Service ICMP externally
|
||||
// Service ICMP hook
|
||||
//
|
||||
export word serviceICMP
|
||||
export word hookICMP
|
||||
//
|
||||
// Ethernet driver entrypoints
|
||||
//
|
||||
word setFrameLen, writeFrame, getFrameLen, readFrame
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
@ -142,8 +180,6 @@ asm equates
|
||||
!SOURCE "vmsrc/plvmzp.inc"
|
||||
end
|
||||
//
|
||||
// ASM utility functions
|
||||
//
|
||||
// Swap bytes in word
|
||||
//
|
||||
export asm swab
|
||||
@ -201,214 +237,12 @@ CHKLP LDA (SRC),Y
|
||||
INX
|
||||
INX
|
||||
RTS
|
||||
end//
|
||||
// DEBUG
|
||||
//
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putha(haptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 4
|
||||
putb(haptr->[i]); putc(':')
|
||||
next
|
||||
return putb(haptr->[i])
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
def dumpehdr(packet)
|
||||
putha(packet + ethr_dst); putc(' ')
|
||||
putha(packet + ethr_src); putc(' ')
|
||||
putc('$');puth(packet=>ethr_payload); putln
|
||||
end
|
||||
def dumparp(packet)
|
||||
putc('$');puth(packet=>arp_hw); putln
|
||||
putc('$');puth(packet=>arp_proto); putln
|
||||
putc('$');putb(packet->arp_hlen); putln
|
||||
putc('$');putb(packet->arp_plen); putln
|
||||
putc('$');puth(packet=>arp_op); putln
|
||||
putha(packet + arp_senderha)
|
||||
putc('=')
|
||||
putip(packet + arp_senderip); putln
|
||||
putha(packet + arp_targha)
|
||||
putc('=')
|
||||
putip(packet + arp_targip); putln
|
||||
end
|
||||
def dumpip(packet)
|
||||
putc('$');putb(packet->ip_vers_hlen); putln
|
||||
puti(swab(packet=>ip_length)); putln
|
||||
puti(packet->ip_proto); putln
|
||||
putip(packet + ip_src); putln
|
||||
putip(packet + ip_dst); putln
|
||||
end
|
||||
def dumpudp(packet)
|
||||
puti(swab(packet=>udp_src));putln
|
||||
puti(swab(packet=>udp_dst));putln
|
||||
puti(swab(packet=>udp_len));putln
|
||||
end
|
||||
def dumpfrm(packet, len)
|
||||
word i
|
||||
|
||||
if len > 64
|
||||
len = 64
|
||||
fin
|
||||
len = len - 1
|
||||
for i = 0 to len
|
||||
if (i & 7) == 0
|
||||
putln
|
||||
else
|
||||
putc(' ')
|
||||
fin
|
||||
putb(^(packet+i))
|
||||
next
|
||||
putln
|
||||
end
|
||||
//
|
||||
// Service incoming packets
|
||||
//
|
||||
export def serviceIP
|
||||
word pkt, iphdr, hdr, opt, len, optlen, port, lclport, remport
|
||||
byte i
|
||||
|
||||
len = recvEther
|
||||
if len
|
||||
len = len - t_ethrhdr
|
||||
when readEther(t_ethrhdr)=>ethr_payload
|
||||
is PAYLOAD_ARP
|
||||
pkt = readEther(len)
|
||||
len = 0
|
||||
when pkt=>arp_op
|
||||
is ARP_REPLY
|
||||
//
|
||||
// Fill in ARP cache
|
||||
//
|
||||
memcpy(@remoteha, @pkt=>arp_senderha, 10) // copy ha and ip
|
||||
//putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
break
|
||||
is ARP_REQST
|
||||
//
|
||||
// Is this a request for me?
|
||||
//
|
||||
if pkt=>arp_targip:0 == localip:0 and pkt=>arp_targip:2 == localip:2
|
||||
memcpy(@dstMAC, @pkt=>arp_senderha, MAC_SIZE)
|
||||
memcpy(@remoteha, @pkt=>arp_senderha, 10) // copy ha and ip
|
||||
opARP = ARP_REPLY
|
||||
writeEther(@ARP, t_earp)
|
||||
//putha(pkt+arp_senderha);putc('=');putip(pkt+arp_senderip);putln
|
||||
fin
|
||||
break
|
||||
otherwise
|
||||
//dumparp(pkt)
|
||||
wend
|
||||
break
|
||||
is PAYLOAD_IP
|
||||
len = len - t_iphdr
|
||||
iphdr = readEther(t_iphdr)
|
||||
if iphdr->ip_vers_hlen <> $45
|
||||
optlen = iphdr=>ip_vers_hlen
|
||||
if optlen & $F0 <> $40
|
||||
//
|
||||
// Not IPv4, ignore
|
||||
//
|
||||
break
|
||||
fin
|
||||
optlen = (optlen & $0F) << 2
|
||||
if optlen > t_iphdr
|
||||
//
|
||||
// Read the options and throw them on the ground!
|
||||
//
|
||||
opt = readEther(optlen - t_iphdr)
|
||||
len = len - (optlen - t_iphdr)
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Filter valid destination address
|
||||
//
|
||||
if iphdr=>ip_dst:2 <> localip:2 // Yes, this is a little lazy
|
||||
if (iphdr=>ip_dst:0|subnet_mask:0) & (iphdr=>ip_dst:2|subnet_mask:2) <> IP_BROADCAST
|
||||
break
|
||||
fin
|
||||
fin
|
||||
when iphdr->ip_proto
|
||||
is IP_PROTO_UDP
|
||||
port = portsUDP
|
||||
if port
|
||||
len = len - t_udphdr
|
||||
hdr = readEther(t_udphdr)
|
||||
lclport = swab(hdr=>udp_dst)
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if port=>notify_port == lclport)
|
||||
//dumpip(iphdr)
|
||||
//dumpudp(hdr)
|
||||
port=>notify_func(@iphdr=>ip_src,swab(hdr=>udp_src),lclport,readEther(len),swab(hdr=>udp_len),port=>notify_parm)
|
||||
len = 0
|
||||
break
|
||||
fin
|
||||
port = port + t_notify
|
||||
next
|
||||
fin
|
||||
break
|
||||
is IP_PROTO_TCP
|
||||
port = portsTCP
|
||||
if port
|
||||
len = len - t_tcphdr
|
||||
hdr = readEther(t_tcphdr)
|
||||
lclport = swab(hdr=>tcp_dst)
|
||||
remport = swab(hdr=>tcp_src)
|
||||
for i = 1 to MAX_TCP_NOTIFIES
|
||||
if port=>notify_port == lclport)
|
||||
//dumpip(iphdr)
|
||||
//dumptcp(tcphdr)
|
||||
port=>notify_func(@iphdr=>ip_src,swab(hdr=>tcp_src),lclport,readEther(len),swab(hdr=>tcp_len),port=>notify_parm)
|
||||
len = 0
|
||||
break
|
||||
fin
|
||||
port = port + t_notify
|
||||
next
|
||||
fin
|
||||
break
|
||||
is IP_PROTO_ICMP
|
||||
if serviceICMP
|
||||
serviceICMP(@iphdr=>ip_src, readEther(len), len)
|
||||
len = 0
|
||||
fin
|
||||
wend
|
||||
break
|
||||
otherwise
|
||||
//dumpehdr(readEther(len) - t_ethrhdr)
|
||||
//len = 0
|
||||
wend
|
||||
if len; readEther(len); fin // Drop it
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Send IP datagram
|
||||
//
|
||||
export def sendIP(ipdst, proto, seglist, size)
|
||||
byte[t_iphdr] hdr
|
||||
byte[MAC_SIZE] dstha
|
||||
byte[t_iphdr] hdr
|
||||
byte retry
|
||||
word timeout
|
||||
|
||||
@ -423,19 +257,22 @@ export def sendIP(ipdst, proto, seglist, size)
|
||||
memcpy(@hdr.ip_src, @localip, IPADR_SIZE)
|
||||
if !ipdst // IP_BROADCAST
|
||||
memset(@hdr.ip_dst, IP_BROADCAST, IPADR_SIZE)
|
||||
memset(@dstha, MAC_BROADCAST, MAC_SIZE)
|
||||
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
|
||||
else
|
||||
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
|
||||
retry = 0
|
||||
while ipdst=>0 <> remoteip:0 and ipdst=>2 <> remoteip:2
|
||||
while hdr:ip_dst:0 <> remoteip:0 and hdr:ip_dst:2 <> remoteip:2
|
||||
if retry >= 3
|
||||
return -1 // ARP failed
|
||||
fin
|
||||
retry = retry + 1
|
||||
memset(@dstMAC, MAC_BROADCAST, MAC_SIZE)
|
||||
memset(@remoteha, 0, MAC_SIZE)
|
||||
memcpy(@remoteip, ipdst, IPADR_SIZE)
|
||||
opARP = ARP_REQST
|
||||
writeEther(@ARP, t_earp)
|
||||
memcpy(@remoteip, @hdr.ip_dst, IPADR_SIZE)
|
||||
ePayload = PAYLOAD_ARP
|
||||
opARP = ARP_REQST
|
||||
setFrameLen(t_earp)
|
||||
writeFrame(@eFrame, t_earp)
|
||||
for timeout = 1000 downto 0
|
||||
serviceIP
|
||||
if remoteha:0 | remoteha:2 | remoteha:4
|
||||
@ -443,53 +280,55 @@ export def sendIP(ipdst, proto, seglist, size)
|
||||
fin
|
||||
next
|
||||
loop
|
||||
memcpy(@hdr.ip_dst, ipdst, IPADR_SIZE)
|
||||
memcpy(@dstha, @remoteha, MAC_SIZE)
|
||||
memcpy(@dstMAC, @remoteha, MAC_SIZE)
|
||||
fin
|
||||
//
|
||||
// Calculate checksum
|
||||
//
|
||||
hdr:ip_chksm = sum1(0, @hdr, t_iphdr) ^ $FFFF
|
||||
//
|
||||
// Fill in remaining segment list for IP header and write it out
|
||||
// set the ethernet payload and frame length
|
||||
//
|
||||
seglist=>seg_buf = @hdr
|
||||
seglist=>seg_len = t_iphdr
|
||||
return writevEther(@dstha, PAYLOAD_IP, seglist, t_iphdr + size)
|
||||
ePayload = PAYLOAD_IP
|
||||
setFrameLen(t_ethriphdr + size)
|
||||
//
|
||||
// Write the ethernet header
|
||||
//
|
||||
writeFrame(@eFrame, t_ethrhdr)
|
||||
//
|
||||
// Write the IP header
|
||||
//
|
||||
writeFrame(@hdr, t_iphdr)
|
||||
//
|
||||
// Write the remaining segments
|
||||
//
|
||||
while size > 0
|
||||
writeFrame(seglist=>seg_buf, seglist=>seg_len)
|
||||
size = size - seglist=>seg_len
|
||||
seglist = seglist + t_segment
|
||||
loop
|
||||
end
|
||||
//
|
||||
// Send UDP datagram
|
||||
//
|
||||
export def sendUDP(ipdst, portdst, portsrc, data, len)
|
||||
word[12] seglist // list of data and header segments
|
||||
//word segsum
|
||||
//byte[t_piphdr] phdr
|
||||
word[8] seglist // list of data and header segments
|
||||
byte[t_udphdr] hdr
|
||||
|
||||
//memcpy(@phdr.pip_src, @localip, IPADR_SIZE)
|
||||
//memcpy(@phdr.pip_dst, ipdst, IPADR_SIZE)
|
||||
//phdr.pip_zero = 0
|
||||
//phdr.pip_proto = IP_PROTO_UDP
|
||||
//phdr.pip_len = swab(t_udphdr + len)
|
||||
hdr:udp_src = swab(portsrc)
|
||||
hdr:udp_dst = swab(portdst)
|
||||
hdr:udp_len = swab(t_udphdr + len)
|
||||
hdr:udp_chksm = 0
|
||||
//segsum = sum1(0, @phdr, t_piphdr + t_udphdr)
|
||||
//segsum = sum1(segsum, data, len)
|
||||
//hdr:udp_chksm = segsum ^ $FFFF
|
||||
//seglist:0:seg_buf reserved for IP header
|
||||
//seglist:0:seg_len reserved for IP header
|
||||
seglist:4:seg_buf = @hdr
|
||||
seglist:4:seg_len = t_udphdr
|
||||
seglist:8:seg_buf = data
|
||||
seglist:8:seg_len = len
|
||||
seglist:0:seg_buf = @hdr
|
||||
seglist:0:seg_len = t_udphdr
|
||||
seglist:4:seg_buf = data
|
||||
seglist:4:seg_len = len
|
||||
return sendIP(ipdst, IP_PROTO_UDP, @seglist, t_udphdr + len)
|
||||
end
|
||||
//
|
||||
// Notify on UDP datagram received
|
||||
//
|
||||
export def recvUDP(localport, callback, param)
|
||||
export def listenUDP(localport, callback, param)
|
||||
word port
|
||||
byte i
|
||||
|
||||
@ -530,7 +369,7 @@ end
|
||||
//
|
||||
// Clear notify on UDP port
|
||||
//
|
||||
export def shutUDP(localport)
|
||||
export def hangupUDP(localport)
|
||||
word port
|
||||
byte i
|
||||
|
||||
@ -548,8 +387,136 @@ export def shutUDP(localport)
|
||||
return -1
|
||||
end
|
||||
//
|
||||
// Fill in MAC
|
||||
// Service incoming packets
|
||||
//
|
||||
copyMAC(@srcMAC)
|
||||
copyMAC(@localha)
|
||||
done
|
||||
export def serviceIP
|
||||
word rxsize, rxpacket, rxptr
|
||||
word iphdr, opt, optlen, port, lclport, remport
|
||||
byte i, echolen
|
||||
word[4] seglist
|
||||
byte[128] echo_reply
|
||||
|
||||
//
|
||||
// Check for received packet
|
||||
//
|
||||
rxsize = getFrameLen()
|
||||
if rxsize
|
||||
//
|
||||
// Read the entire packet into memory
|
||||
//
|
||||
rxpacket = heapalloc(rxsize)
|
||||
readFrame(rxpacket, rxsize)
|
||||
rxptr = rxpacket + t_ethrhdr
|
||||
rxsize = rxsize - t_ethrhdr
|
||||
//
|
||||
// What kind of packet is it?
|
||||
//
|
||||
when rxpacket=>ethr_payload
|
||||
is PAYLOAD_IP
|
||||
iphdr = rxptr
|
||||
rxptr = rxptr + t_iphdr
|
||||
rxsize = rxsize - t_iphdr
|
||||
if iphdr->ip_vers_hlen <> $45
|
||||
optlen = iphdr=>ip_vers_hlen
|
||||
if optlen & $F0 <> $40
|
||||
//
|
||||
// Not IPv4, ignore
|
||||
//
|
||||
break
|
||||
fin
|
||||
optlen = (optlen & $0F) << 2
|
||||
if optlen > t_iphdr
|
||||
//
|
||||
// Read the options and throw them on the ground!
|
||||
//
|
||||
rxptr = rxptr + (optlen - t_iphdr)
|
||||
rxsize = rxsize - (optlen - t_iphdr)
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// Filter valid destination address
|
||||
//
|
||||
if iphdr=>ip_dst:2 <> localip:2 // Yes, this is a little lazy
|
||||
if (iphdr=>ip_dst:0|subnet:0) & (iphdr=>ip_dst:2|subnet:2) <> IP_BROADCAST
|
||||
break
|
||||
fin
|
||||
fin
|
||||
//
|
||||
// What kind of IP protocol is it?
|
||||
//
|
||||
when iphdr->ip_proto
|
||||
is IP_PROTO_UDP
|
||||
port = portsUDP
|
||||
if port
|
||||
lclport = swab(rxptr=>udp_dst)
|
||||
for i = 1 to MAX_UDP_NOTIFIES
|
||||
if port=>notify_port == lclport)
|
||||
port=>notify_func(@iphdr=>ip_src,swab(rxptr=>udp_src),lclport,rxptr+t_udphdr,swab(rxptr=>udp_len),port=>notify_parm)
|
||||
break
|
||||
fin
|
||||
port = port + t_notify
|
||||
next
|
||||
fin
|
||||
break
|
||||
is IP_PROTO_TCP
|
||||
break
|
||||
is IP_PROTO_ICMP
|
||||
//
|
||||
// Service ICMP packets
|
||||
//
|
||||
if rxptr->icmp_type == ICMP_ECHO_REQST
|
||||
if rxsize > 128
|
||||
echolen = 128
|
||||
else
|
||||
echolen = rxsize
|
||||
fin
|
||||
memcpy(@echo_reply, rxptr, echolen)
|
||||
echo_reply.icmp_type = ICMP_ECHO_REPLY
|
||||
echo_reply:icmp_chksm = 0
|
||||
seglist:seg_buf = @echo_reply
|
||||
seglist:seg_len = echolen
|
||||
sendIP(@iphdr=>ip_src, IP_PROTO_ICMP, @seglist, echolen)
|
||||
fin
|
||||
if hookICMP
|
||||
hookICMP(@iphdr=>ip_src, rxptr, rxsize)
|
||||
fin
|
||||
wend
|
||||
break
|
||||
is PAYLOAD_ARP
|
||||
when rxptr=>arp_op
|
||||
is ARP_REPLY
|
||||
//
|
||||
// Fill in ARP cache
|
||||
//
|
||||
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
|
||||
break
|
||||
is ARP_REQST
|
||||
//
|
||||
// Is this a request for me?
|
||||
//
|
||||
if rxptr=>arp_targip:0 == localip:0 and rxptr=>arp_targip:2 == localip:2
|
||||
memcpy(@dstMAC, @rxptr=>arp_senderha, MAC_SIZE)
|
||||
memcpy(@remoteha, @rxptr=>arp_senderha, 10) // copy ha and ip
|
||||
ePayload = PAYLOAD_ARP
|
||||
opARP = ARP_REPLY
|
||||
setFrameLen(t_earp)
|
||||
writeFrame(@eFrame, t_earp)
|
||||
fin
|
||||
wend
|
||||
wend
|
||||
heaprelease(rxpacket)
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Initialize the driver interface
|
||||
//
|
||||
export def setEtherDriver(MAC, getlen, readframe, setlen, writeframe)
|
||||
memcpy(@myMAC, MAC, MAC_SIZE)
|
||||
memcpy(@localha, MAC, MAC_SIZE)
|
||||
getFrameLen = getlen
|
||||
readFrame = readframe
|
||||
setFrameLen = setlen
|
||||
writeFrame = writeframe
|
||||
end
|
||||
|
||||
done
|
35
src/libsrc/inet.pla
Normal file
35
src/libsrc/inet.pla
Normal file
@ -0,0 +1,35 @@
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
byte MACHID
|
||||
end
|
||||
import uthernet
|
||||
byte localip, subnet, gateway
|
||||
predef serviceIP
|
||||
end
|
||||
|
||||
byte dhcp = "DHCP"
|
||||
|
||||
byte serverip = 192,168,123,1
|
||||
byte staticip = 192,168,123,10
|
||||
byte staticmask = 255,255,255,0
|
||||
|
||||
if modexec(@dhcp) < 0
|
||||
//
|
||||
// Set our local IP address
|
||||
//
|
||||
memcpy(@localip, @staticip, 4)
|
||||
memcpy(@subnet, @staticmask, 4)
|
||||
memcpy(@gateway, @serverip, 4)
|
||||
fin
|
||||
|
||||
//
|
||||
// Service IP
|
||||
//
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
|
||||
done
|
@ -1,8 +1,8 @@
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease, heapavail
|
||||
byte MACHID
|
||||
//
|
||||
// Include dependency on S/W IP stack
|
||||
//
|
||||
import etherip
|
||||
predef setEtherDriver
|
||||
end
|
||||
//
|
||||
// Module don't free memory
|
||||
@ -10,33 +10,6 @@ end
|
||||
const modkeep = $2000
|
||||
const modinitkeep = $4000
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// MAC size
|
||||
//
|
||||
const MAC_SIZE = 6
|
||||
//
|
||||
// Ethernet header
|
||||
//
|
||||
struc t_ethrhdr
|
||||
byte[MAC_SIZE] ethr_dst
|
||||
byte[MAC_SIZE] ethr_src
|
||||
word ethr_payload
|
||||
end
|
||||
//
|
||||
// Max Ethernet frame size
|
||||
//
|
||||
const MAX_FRAME_SIZE = 1518
|
||||
//
|
||||
// MAC address
|
||||
//
|
||||
byte MAC = $00,$0A,$99,$1E,$02,$00
|
||||
//
|
||||
// Uthernet register offsets
|
||||
//
|
||||
const TXDATA = $00
|
||||
@ -58,9 +31,9 @@ byte isq
|
||||
byte pregidx
|
||||
byte pregdata
|
||||
//
|
||||
// Current receive status and packet size
|
||||
// Uthernet MAC address
|
||||
//
|
||||
word rxsize, rxpacket, rxptr
|
||||
byte[6] utherMAC = $00,$0A,$99,$1E,$02,$00
|
||||
//
|
||||
// Defines for ASM routines
|
||||
//
|
||||
@ -68,21 +41,7 @@ asm equates
|
||||
!SOURCE "vmsrc/plvmzp.inc"
|
||||
end
|
||||
//
|
||||
// I/O access
|
||||
//
|
||||
// POKE BYTE INTO I/O SPACE
|
||||
// _pokeio(DATA)
|
||||
//
|
||||
//asm _pokeio
|
||||
// LDA ESTKL,X
|
||||
//end
|
||||
//asm _pokeiol
|
||||
// STA $C000
|
||||
// RTS
|
||||
//end
|
||||
//
|
||||
// POKE WORD INTO I/O SPACE
|
||||
// _pokeiow(DATA)
|
||||
// Uthernet I/O functions
|
||||
//
|
||||
asm _pokeiow
|
||||
LDA ESTKL,X
|
||||
@ -126,7 +85,7 @@ asm _peekiowh
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// WRITE PACKET FRAME INTO I/O SPACE
|
||||
// WRITE FRAME DATA INTO I/O SPACE
|
||||
// pokefrm(BUF, LEN)
|
||||
//
|
||||
asm pokefrm
|
||||
@ -164,7 +123,7 @@ asm _pokefrmh
|
||||
RTS
|
||||
end
|
||||
//
|
||||
// READ PACKET FRAME FROM I/O SPACE
|
||||
// READ FRAME DATA FROM I/O SPACE
|
||||
// peekfrm(BUF, LEN)
|
||||
//
|
||||
asm peekfrm
|
||||
@ -201,10 +160,6 @@ asm _peekfrmh
|
||||
EXPSW INX
|
||||
RTS
|
||||
end
|
||||
//def pokeio(io, data)
|
||||
// _pokeiowl.1 = io
|
||||
// return _pokeio(data)
|
||||
//end
|
||||
def pokeiow(io, data)
|
||||
_pokeiowl.1 = io
|
||||
_pokeiowh.1 = io+1
|
||||
@ -228,63 +183,30 @@ def peekpreg(reg)
|
||||
return peekiow(pregdata)
|
||||
end
|
||||
//
|
||||
// Uthernet interface
|
||||
// Set the length of the next packet to send and wait for data space availability
|
||||
//
|
||||
export def copyMAC(ptr)
|
||||
if !rxpacket; rxpacket = heapalloc(MAX_FRAME_SIZE); fin
|
||||
memcpy(ptr, @MAC, MAC_SIZE)
|
||||
return MAC_SIZE
|
||||
end
|
||||
export def writeEther(packet, size)
|
||||
def pokefrmlen(len)
|
||||
pokeiow(txcmd, $C0)
|
||||
pokeiow(txlen, size)
|
||||
pokeiow(txlen, len)
|
||||
repeat; until peekpreg($0138) & $0100
|
||||
return pokefrm(packet, size)
|
||||
end
|
||||
export def writevEther(destha, payload, seglist, size)
|
||||
pokeiow(txcmd, $C0)
|
||||
pokeiow(txlen, size + t_ethrhdr)
|
||||
repeat; until peekpreg($0138) & $0100
|
||||
pokefrm(destha, MAC_SIZE)
|
||||
pokefrm(@MAC, MAC_SIZE)
|
||||
pokefrm(@payload, 2)
|
||||
while size > 0
|
||||
pokefrm(seglist=>seg_buf, seglist=>seg_len)
|
||||
size = size - seglist=>seg_len
|
||||
seglist = seglist + t_segment
|
||||
loop
|
||||
end
|
||||
export def readEther(size)
|
||||
word segptr
|
||||
|
||||
if rxsize > 0
|
||||
if size > rxsize
|
||||
size = rxsize
|
||||
fin
|
||||
segptr = rxptr
|
||||
rxptr = rxptr + size
|
||||
rxsize = rxsize - size
|
||||
else
|
||||
segptr = 0
|
||||
fin
|
||||
return segptr
|
||||
end
|
||||
export def recvEther
|
||||
if rxsize == 0
|
||||
if peekiow(isq) & $3F == $04
|
||||
if peekio(rxdata_hi) & $01
|
||||
peekio(rxdata_lo)
|
||||
rxsize.1 = peekio(rxdata_hi)
|
||||
rxsize.0 = peekio(rxdata_lo)
|
||||
peekfrm(rxpacket, rxsize)
|
||||
rxptr = rxpacket
|
||||
else
|
||||
peekio(rxdata_lo)
|
||||
pokepreg($0102, $0140) // Skip pkt
|
||||
fin
|
||||
//
|
||||
// Return the length of awaiting packet, 0 otherwise
|
||||
//
|
||||
def peekfrmlen
|
||||
word len
|
||||
len = 0
|
||||
if peekiow(isq) & $3F == $04
|
||||
if peekio(rxdata_hi) & $01
|
||||
peekio(rxdata_lo)
|
||||
len.1 = peekio(rxdata_hi)
|
||||
len.0 = peekio(rxdata_lo)
|
||||
else
|
||||
peekio(rxdata_lo)
|
||||
pokepreg($0102, $0140) // Skip pkt
|
||||
fin
|
||||
fin
|
||||
return rxsize
|
||||
return len
|
||||
end
|
||||
//
|
||||
// Identify Uthernet card and initialize
|
||||
@ -304,13 +226,17 @@ for slot = $F0 downto $90 step $10
|
||||
_pokefrmh.1 = slot+1
|
||||
_peekfrml.1 = slot
|
||||
_peekfrmh.1 = slot+1
|
||||
pokepreg($0158, MAC:0) // MAC addr
|
||||
pokepreg($015A, MAC:2) // MAC addr
|
||||
pokepreg($015C, MAC:4) // MAC addr
|
||||
pokepreg($0158, utherMAC:0) // MAC addr
|
||||
pokepreg($015A, utherMAC:2) // MAC addr
|
||||
pokepreg($015C, utherMAC:4) // MAC addr
|
||||
pokepreg($0102, $0100) // Recv cfg
|
||||
pokepreg($0104, $0D00) // Recv ctrl
|
||||
pokepreg($0106, $8200) // Xmit cfg
|
||||
pokepreg($0112, $00C0) // Line ctrl
|
||||
//
|
||||
// Install etherip driver
|
||||
//
|
||||
setEtherDriver(@utherMAC, @peekfrmlen, @peekfrm, @pokefrmlen, @pokefrm)
|
||||
return modkeep
|
||||
fin
|
||||
fin
|
33
src/makefile
33
src/makefile
@ -11,9 +11,8 @@ ROD = ROD\#FE1000
|
||||
SIEVE = SIEVE\#FE1000
|
||||
UTHERNET= UTHERNET\#FE1000
|
||||
ETHERIP = ETHERIP\#FE1000
|
||||
ICMP = ICMP\#FE1000
|
||||
INET = INET\#FE1000
|
||||
DHCP = DHCP\#FE1000
|
||||
STATICIP= STATICIP\#FE1000
|
||||
ROGUE = ROGUE\#FE1000
|
||||
ROGUEIO = ROGUEIO\#FE1000
|
||||
ROGUEMAP= ROGUEMAP\#FE1000
|
||||
@ -46,7 +45,7 @@ TXTTYPE = .TXT
|
||||
#SYSTYPE = \#FF2000
|
||||
#TXTTYPE = \#040000
|
||||
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(ICMP) $(DHCP) $(STATICIP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
all: $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03) $(CMD) $(MEMMGR) $(MEMTEST) $(SB) $(MON) $(ROD) $(SIEVE) $(UTHERNET) $(ETHERIP) $(INET) $(DHCP) $(ROGUE) $(ROGUEMAP) $(ROGUECOMBAT) $(ROGUEIO) $(HGR1)
|
||||
|
||||
clean:
|
||||
-rm *FE1000 *FF2000 $(PLASM) $(PLVM) $(PLVM01) $(PLVM02) $(PLVM03)
|
||||
@ -123,25 +122,21 @@ $(SIEVE): samplesrc/sieve.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/sieve.pla > samplesrc/sieve.a
|
||||
acme --setpc 4094 -o $(SIEVE) samplesrc/sieve.a
|
||||
|
||||
$(UTHERNET): samplesrc/uthernet.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/uthernet.pla > samplesrc/uthernet.a
|
||||
acme --setpc 4094 -o $(UTHERNET) samplesrc/uthernet.a
|
||||
$(UTHERNET): libsrc/uthernet.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/uthernet.pla > libsrc/uthernet.a
|
||||
acme --setpc 4094 -o $(UTHERNET) libsrc/uthernet.a
|
||||
|
||||
$(ETHERIP): samplesrc/etherip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/etherip.pla > samplesrc/etherip.a
|
||||
acme --setpc 4094 -o $(ETHERIP) samplesrc/etherip.a
|
||||
$(ETHERIP): libsrc/etherip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/etherip.pla > libsrc/etherip.a
|
||||
acme --setpc 4094 -o $(ETHERIP) libsrc/etherip.a
|
||||
|
||||
$(ICMP): samplesrc/icmp.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/icmp.pla > samplesrc/icmp.a
|
||||
acme --setpc 4094 -o $(ICMP) samplesrc/icmp.a
|
||||
$(INET): libsrc/inet.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/inet.pla > libsrc/inet.a
|
||||
acme --setpc 4094 -o $(INET) libsrc/inet.a
|
||||
|
||||
$(DHCP): samplesrc/dhcp.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/dhcp.pla > samplesrc/dhcp.a
|
||||
acme --setpc 4094 -o $(DHCP) samplesrc/dhcp.a
|
||||
|
||||
$(STATICIP): samplesrc/staticip.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/staticip.pla > samplesrc/staticip.a
|
||||
acme --setpc 4094 -o $(STATICIP) samplesrc/staticip.a
|
||||
$(DHCP): libsrc/dhcp.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < libsrc/dhcp.pla > libsrc/dhcp.a
|
||||
acme --setpc 4094 -o $(DHCP) libsrc/dhcp.a
|
||||
|
||||
$(ROGUE): samplesrc/rogue.pla $(PLVM02) $(PLASM)
|
||||
./$(PLASM) -AM < samplesrc/rogue.pla > samplesrc/rogue.a
|
||||
|
@ -1,96 +0,0 @@
|
||||
//
|
||||
// ICMP service
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip
|
||||
word serviceICMP
|
||||
predef sendIP
|
||||
end
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// ICMP type/codes
|
||||
//
|
||||
const IP_PROTO_ICMP = 1
|
||||
const ICMP_ECHO_REQST = 8
|
||||
const ICMP_ECHO_REPLY = 0
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_chksm
|
||||
word[2] icmp_header
|
||||
end
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
byte icmpstr = "ICMP "
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
//
|
||||
// Service ICMP packets
|
||||
//
|
||||
def icmp(srcip, pkt, len)
|
||||
byte[4] echoip
|
||||
word[8] seglist
|
||||
byte[128] echo_reply
|
||||
|
||||
//puts(@icmpstr);putip(srcip);putc(' ')
|
||||
//puti(pkt->icmp_type);putc(' ');puti(pkt->icmp_code);putln
|
||||
|
||||
if pkt->icmp_type == ICMP_ECHO_REQST
|
||||
if len > 128
|
||||
len = 128
|
||||
fin
|
||||
memcpy(@echo_reply, pkt, len)
|
||||
echo_reply.icmp_type = ICMP_ECHO_REPLY
|
||||
echo_reply:icmp_chksm = 0
|
||||
//echo_reply:icmp_chksm = sum1(0, @echo_reply, len) ^ $FFFF
|
||||
memcpy(@echoip, srcip, 4)
|
||||
seglist:4:seg_buf = @echo_reply
|
||||
seglist:4:seg_len = len
|
||||
sendIP(@echoip, IP_PROTO_ICMP, @seglist, len)
|
||||
fin
|
||||
end
|
||||
//
|
||||
// Set to notify on ICMP packets
|
||||
//
|
||||
serviceICMP = @icmp
|
||||
done
|
@ -1,98 +0,0 @@
|
||||
//
|
||||
// Static IP
|
||||
//
|
||||
import cmdsys
|
||||
predef syscall, call, getc, gets, putc, puts, putln
|
||||
predef memset, memcpy, modaddr, modexec
|
||||
predef heapmark, heapallocalign, heapalloc, heaprelease
|
||||
byte MACHID
|
||||
end
|
||||
import etherip
|
||||
byte localha, localip
|
||||
predef sendUDP, recvUDP, shutUDP, sendIP, serviceIP, sum1
|
||||
end
|
||||
import icmp
|
||||
end
|
||||
//
|
||||
// Segment list element
|
||||
//
|
||||
struc t_segment
|
||||
word seg_buf
|
||||
word seg_len
|
||||
end
|
||||
//
|
||||
// ICMP type/codes
|
||||
//
|
||||
const ICMP_ECHO_REQST = 8
|
||||
const ICMP_ECHO_REPLY = 0
|
||||
//
|
||||
// ICMP message format
|
||||
//
|
||||
struc t_icmp
|
||||
byte icmp_type
|
||||
byte icmp_code
|
||||
word icmp_chksm
|
||||
word[2] icmp_header
|
||||
end
|
||||
//
|
||||
// ICMP echo packet
|
||||
//
|
||||
const IP_PROTO_ICMP = $01
|
||||
byte ECHO = 8 // ECHO request
|
||||
byte = 0 // code
|
||||
word = 0 // checksum
|
||||
byte = 0, 69, 0, 1 // rest of header
|
||||
word segecho = 0, 0, @ECHO, 8
|
||||
byte serverip = 192,168,123,129
|
||||
byte staticip = 192,168,123,10
|
||||
byte staticmask = 255,255,255,0
|
||||
word echo_reply
|
||||
//
|
||||
// DEBUG
|
||||
//
|
||||
def putln
|
||||
return putc($0D)
|
||||
end
|
||||
def putb(hexb)
|
||||
return call($FDDA, hexb, 0, 0, 0)
|
||||
end
|
||||
def puth(hex)
|
||||
return call($F941, hex >> 8, hex, 0, 0)
|
||||
end
|
||||
def puti(i)
|
||||
if i < 0; putc('-'); i = -i; fin
|
||||
if i < 10
|
||||
putc(i + '0')
|
||||
else
|
||||
puti(i / 10)
|
||||
putc(i % 10 + '0')
|
||||
fin
|
||||
end
|
||||
def putip(ipptr)
|
||||
byte i
|
||||
|
||||
for i = 0 to 2
|
||||
puti(ipptr->[i]); putc('.')
|
||||
next
|
||||
return puti(ipptr->[i])
|
||||
end
|
||||
//
|
||||
// Set our local IP address
|
||||
//
|
||||
memcpy(@localip, @staticip, 4)
|
||||
//
|
||||
// Calculate checksum
|
||||
//
|
||||
ECHO:icmp_chksm = sum1(0, @ECHO, t_icmp) ^ $FFFF
|
||||
//
|
||||
// Send an echo to the server
|
||||
//
|
||||
sendIP(@serverip, IP_PROTO_ICMP, @segecho, 0)
|
||||
//
|
||||
// Service IP
|
||||
//
|
||||
repeat
|
||||
serviceIP
|
||||
until ^$C000 > 127
|
||||
^$C010
|
||||
done
|
Loading…
Reference in New Issue
Block a user