1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2026-04-19 09:23:06 +00:00
Files
PLASMA/src/libsrc/dhcp.pla
T
2017-12-13 14:40:31 -08:00

231 lines
5.7 KiB
Plaintext

//
// DHCP
//
include "inc/cmdsys.plh"
include "inc/inet.plh"
//
// Needed to init subnet
//
const IP_BROADCAST = $FFFF
const IP4ADR_SIZE = 4
//
// DHCP message
//
struc t_dhcp
byte dhcp_op
byte dhcp_htype
byte dhcp_hlen
byte dhcp_hops
byte[4] dhcp_xid
word dhcp_secs
word dhcp_flags
byte[4] dhcp_clientip
byte[4] dhcp_yourip
byte[4] dhcp_serverip
byte[4] dhcp_gatewayip
byte[16] dhcp_clientha
byte[192] dhcp_bootp
byte[4] dhcp_magic
byte[60] dhcp_opts
end
//
// DHCP messages
//
const DHCP_DISCOVER = $01
const DHCP_OFFER = $02
const DHCP_REQUEST = $03
const DHCP_DECLINE = $04
const DHCP_ACK = $05
const DHCP_NACK = $06
const DHCP_RELEASE = $07
//
// Track DHCP progress
//
byte retry
word timeout
//
// DHCP ports
//
const DHCP_CLIENT_PORT = 68
const DHCP_SERVER_PORT = 67
word portDHCP
byte[4] zeros
byte[4] ones = $FF, $FF, $FF, $FF
//
// Default static net IP addresses
//
byte localdns = 8,8,8,8
byte localgw = 192,168,1,1
byte localip = 192,168,1,10
byte localnet = 255,255,255,0
//
// Pre-configured DHCP packet
//
byte DHCP = $01// OP = BOOT
byte = $01 // HTYPE = ETHERNET
byte = $06 // HLEN = 6
byte = $00 // HOPS
byte[4] = $01,$02,$03,$04 // TRANSACTION ID
word = $0000 // SECONDS
word = 0 // FLAGS
byte[4] = 0 // CLIENT IP
byte[4] = 0 // YOUR IP
byte[4] = 0 // SERVER IP
byte[4] = 0 // GATEWAY IP
byte[16] = 0 // CLIENT HA
byte[64] = 0 // SERVER HOST NAME
byte[128] = 0 // BOOT FILE NAME
byte[4] = $63,$82,$53,$63 // MAGIC
byte optsOP = 53,1,1 // DISCOVER
byte optsCID = 61,7, $01,$00,$00,$00,$00,$00,$00
byte = 12, "AppleII"
byte optsIP = 50,4, 0,0,0,0 // IP requested
byte = 55,4, 1,3,6,42 // Parameter request list
byte optsSRV = 54,4, 0,0,0,0 // DHCP server
byte = 255
byte[] endDHCP
//
// DEBUG
//
//byte boundstr = "Apple II bound to:\n"
//byte dnsstr = "DNS: "
//def putb(hexb)
// return call($FDDA, hexb, 0, 0, 0)
//end
//def puth(hex)
// return call($F941, hex >> 8, hex, 0, 0)
//end
//def putip(ipptr)
// byte i
//
// for i = 0 to 2
// puti(ipptr->[i]); putc('.')
// next
// puti(ipptr->[i])
//end
//def dumpbytes(buf, len)
// word i
//
// for i = 0 to len - 1
// putb(buf->[i])
// if i & 15 == 15
// putln
// else
// putc(' ')
// fin
// next
//end
//def dumpdhcp(pkt)
// putb(pkt->dhcp_op);putln
// putb(pkt->dhcp_htype);putln
// putb(pkt->dhcp_hlen);putln
// putb(pkt->dhcp_hops);putln
// dumpbytes(@pkt->dhcp_xid, 4);putln
// putip(@pkt->dhcp_clientip);putln
// putip(@pkt->dhcp_yourip);putln
// putip(@pkt->dhcp_serverip);putln
// putip(@pkt->dhcp_gatewayip);putln
// dumpbytes(@pkt->dhcp_opts, 48);putln
//end
def parseopts(opts, match)
byte i
i = 0
while opts->[i] <> $FF and i < 64
while !opts->[i] and i < 64
i = i + 1
loop
if opts->[i] == match
return i
fin
i = i + opts->[i + 1] + 2
loop
return -1
end
def recvDHCP(remip, remport, pkt, len, param)
word servopts, maskopts, gwopts, dnsopts
//putip(remip);putc(':');puti(remport);putln
//dumpdhcp(pkt)
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
//
// Copy offer parameters to request
//
optsOP.2 = DHCP_REQUEST
memcpy(@optsIP.2, @pkt->dhcp_yourip, IP4ADR_SIZE)
servopts = parseopts(@pkt->dhcp_opts, 54) + 2
if servopts >= 0
optsSRV = 54
memcpy(@optsSRV.2, @pkt->dhcp_opts.[servopts], IP4ADR_SIZE)
fin
iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, @endDHCP - @DHCP)
break
is DHCP_ACK
optsOP.2 = DHCP_ACK
//
// Copy parameters to working copy
//
memcpy(@localip, @pkt->dhcp_yourip, IP4ADR_SIZE)
maskopts = parseopts(@pkt->dhcp_opts, 1) + 2
if maskopts >= 0
memcpy(@localnet, @pkt->dhcp_opts.[maskopts], IP4ADR_SIZE)
fin
gwopts = parseopts(@pkt->dhcp_opts, 3) + 2
if gwopts >= 0
memcpy(@localgw, @pkt->dhcp_opts.[gwopts], IP4ADR_SIZE)
fin
dnsopts = parseopts(@pkt->dhcp_opts, 6) + 2
if dnsopts >= 0
memcpy(@localdns, @pkt->dhcp_opts.[dnsopts], IP4ADR_SIZE)
fin
break
otherwise
//dumpdhcp(pkt)
wend
fin
return 0
end
//
// Get the local hardware address into the DHCP packet
//
iNet:getInterfaceHA(@DHCP.dhcp_clientha)
iNet:getInterfaceHA(@optsCID.3)
//
// Clear our local IP address
//
iNet:setInterfaceIP(@zeros,@ones, @zeros)
//
// Prepare to receive DHCP packets from a server
//
portDHCP = iNet:openUDP(DHCP_CLIENT_PORT, @recvDHCP, 0)
//
// Service IP
//
retry = 0
repeat
//
// Broadcast DHCP DISCOVER message
//
optsOP.2 = DHCP_DISCOVER
optsIP:2 = 0
optsIP:4 = 0
optsSRV = 255
DHCP.dhcp_secs.1 = retry
iNet:sendUDP(portDHCP, 0, DHCP_SERVER_PORT, @DHCP, @optsSRV - @DHCP + 1)
for timeout = 0 to 1000
iNet:serviceIP()
if optsOP.2 == DHCP_ACK
break
fin
next
retry = retry + 1
until retry > 4 or optsOP.2 == DHCP_ACK
iNet:closeUDP(portDHCP)
iNet:setInterfaceIP(@localip, @localnet, @localgw)
//puts(@boundstr);putip(@localip);putc('/');putip(@localnet);putln
iNet:setDNS(@localdns)
//puts(@dnsstr);putip(@localdns);putln
done