test(java-oracle): DhcpRun records DHCP as Java FILIUS runs it

Builds a core scenario's network in Java FILIUS, starts it as the action
mode does and writes every frame each card saw (the Lauscher) and the
addresses at the end. References for the four DHCP scenarios: one
DISCOVER/REQUEST per attempt, an ARP check that waits one RTT, DECLINE on a
conflict, link-local 169.254.1.x after the fifth failure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-30 10:33:58 +00:00
co-authored by Claude Opus 5.5
parent 396dbacfc5
commit fd445e8889
7 changed files with 1725 additions and 1 deletions
@@ -0,0 +1,489 @@
{
"frames": {
"00000000-0000-0000-0000-000000000101": [
{
"time": 459,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 464,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 688,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 801,
"source": "02:00:00:00:01:13",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "192.168.0.100",
"targetIp": "255.255.255.255"
},
{
"time": 912,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 968,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3663,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 6413,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 9164,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11914,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11915,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 12138,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 12194,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14889,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.191"
},
{
"time": 17640,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.191",
"targetIp": "255.255.255.255"
}
],
"00000000-0000-0000-0000-000000000102": [
{
"time": 338,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 576,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 577,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 801,
"source": "02:00:00:00:01:13",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "192.168.0.100",
"targetIp": "255.255.255.255"
},
{
"time": 801,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 857,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3552,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 6302,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 9052,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11802,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 12026,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 12027,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 12082,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14778,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.191"
},
{
"time": 17528,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.191",
"targetIp": "255.255.255.255"
}
],
"00000000-0000-0000-0000-000000000103": [
{
"time": 459,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 576,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 688,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 690,
"source": "02:00:00:00:01:13",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "192.168.0.100",
"targetIp": "255.255.255.255"
},
{
"time": 912,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 968,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3663,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 6413,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 9164,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11914,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 12026,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=0.0.0.0\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 12138,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDECLINE\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 12194,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14889,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.191"
},
{
"time": 17640,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.191",
"targetIp": "255.255.255.255"
}
]
},
"devices": {
"00000000-0000-0000-0000-000000000101": [
"192.168.0.10",
"255.255.255.0",
"",
""
],
"00000000-0000-0000-0000-000000000102": [
"169.254.1.191",
"255.255.0.0",
"",
""
],
"00000000-0000-0000-0000-000000000103": [
"192.168.0.100",
"255.255.255.0",
"",
""
]
}
}
@@ -0,0 +1,331 @@
{
"frames": {
"00000000-0000-0000-0000-000000000101": [
{
"time": 460,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 464,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 516,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:13"
},
{
"time": 520,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 688,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 743,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.150"
},
{
"time": 3438,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3438,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
},
{
"time": 3493,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:13\nrequested=192.168.0.150\nserverident=192.168.0.10"
},
{
"time": 3494,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nserverident=192.168.0.10"
}
],
"00000000-0000-0000-0000-000000000102": [
{
"time": 337,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 460,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:13"
},
{
"time": 575,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 576,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 631,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 743,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.150"
},
{
"time": 3327,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3493,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:13\nrequested=192.168.0.150\nserverident=192.168.0.10"
},
{
"time": 3549,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
},
{
"time": 3605,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nserverident=192.168.0.10"
}
],
"00000000-0000-0000-0000-000000000103": [
{
"time": 460,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 575,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 631,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=192.168.0.53\nserverident=192.168.0.10"
},
{
"time": 631,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.150"
},
{
"time": 688,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 3382,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:13\nrequested=192.168.0.150\nserverident=192.168.0.10"
},
{
"time": 3438,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3549,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
},
{
"time": 3605,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.150\nchaddr=02:00:00:00:01:13\nserverident=192.168.0.10"
}
]
},
"devices": {
"00000000-0000-0000-0000-000000000101": [
"192.168.0.10",
"255.255.255.0",
"",
""
],
"00000000-0000-0000-0000-000000000102": [
"192.168.0.100",
"255.255.255.0",
"192.168.0.1",
"192.168.0.53"
],
"00000000-0000-0000-0000-000000000103": [
"192.168.0.150",
"255.255.255.0",
"192.168.0.1",
"192.168.0.53"
]
}
}
@@ -0,0 +1,243 @@
{
"frames": {
"00000000-0000-0000-0000-000000000101": [
{
"time": 466,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3199,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 5949,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 8699,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11450,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14201,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.72"
},
{
"time": 16951,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.72",
"targetIp": "255.255.255.255"
}
],
"00000000-0000-0000-0000-000000000102": [
{
"time": 342,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3087,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 5838,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 8588,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11338,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14089,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.72"
},
{
"time": 16840,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.72",
"targetIp": "255.255.255.255"
}
],
"00000000-0000-0000-0000-000000000103": [
{
"time": 466,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 3199,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 5949,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 8699,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 11450,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 14201,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "169.254.1.72"
},
{
"time": 16951,
"source": "02:00:00:00:01:12",
"destination": "ff:ff:ff:ff:ff:ff",
"arp": 2,
"senderIp": "169.254.1.72",
"targetIp": "255.255.255.255"
}
]
},
"devices": {
"00000000-0000-0000-0000-000000000101": [
"192.168.0.10",
"255.255.255.0",
"",
""
],
"00000000-0000-0000-0000-000000000102": [
"169.254.1.72",
"255.255.0.0",
"",
""
],
"00000000-0000-0000-0000-000000000103": [
"192.168.0.30",
"255.255.255.0",
"",
""
]
}
}
@@ -0,0 +1,219 @@
{
"frames": {
"00000000-0000-0000-0000-000000000101": [
{
"time": 455,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 460,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.254\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 572,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.30",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.200\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=8.8.8.8\nserverident=192.168.0.30"
},
{
"time": 684,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 3435,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3435,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
}
],
"00000000-0000-0000-0000-000000000102": [
{
"time": 333,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 572,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.254\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 572,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 627,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.30",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.200\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=8.8.8.8\nserverident=192.168.0.30"
},
{
"time": 3323,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3547,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
}
],
"00000000-0000-0000-0000-000000000103": [
{
"time": 455,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPDISCOVER\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12"
},
{
"time": 460,
"source": "02:00:00:00:01:13",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.30",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.200\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.1\nsubnetmask=255.255.255.0\ndnsserver=8.8.8.8\nserverident=192.168.0.30"
},
{
"time": 572,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPOFFER\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nrouter=192.168.0.254\nsubnetmask=255.255.255.0\ndnsserver=0.0.0.0\nserverident=192.168.0.10"
},
{
"time": 684,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"arp": 1,
"senderIp": "0.0.0.0",
"targetIp": "192.168.0.100"
},
{
"time": 3435,
"source": "02:00:00:00:01:12",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "0.0.0.0",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 68,
"destinationPort": 67,
"payload": "DHCPREQUEST\nyiaddr=0.0.0.0\nchaddr=02:00:00:00:01:12\nrequested=192.168.0.100\nserverident=192.168.0.10"
},
{
"time": 3547,
"source": "02:00:00:00:01:11",
"destination": "FF:FF:FF:FF:FF:FF",
"sourceIp": "192.168.0.10",
"destinationIp": "255.255.255.255",
"protocol": 17,
"sourcePort": 67,
"destinationPort": 68,
"payload": "DHCPACK\nyiaddr=192.168.0.100\nchaddr=02:00:00:00:01:12\nserverident=192.168.0.10"
}
]
},
"devices": {
"00000000-0000-0000-0000-000000000101": [
"192.168.0.10",
"255.255.255.0",
"192.168.0.254",
""
],
"00000000-0000-0000-0000-000000000102": [
"192.168.0.100",
"255.255.255.0",
"192.168.0.254",
"0.0.0.0"
],
"00000000-0000-0000-0000-000000000103": [
"192.168.0.30",
"255.255.255.0",
"",
""
]
}
}
+33
View File
@@ -139,3 +139,36 @@ mit weniger als fünf Feldern lässt Java die ganze Datei verwerfen
überspringt Java, statt sie zu zählen; eine Nachricht mit leerem Text geht überspringt Java, statt sie zu zählen; eine Nachricht mit leerem Text geht
verloren, weil `split` leere Felder am Ende abschneidet. Beim Client gewinnt verloren, weil `split` leere Felder am Ende abschneidet. Beim Client gewinnt
die letzte Zeile, auch eine kaputte, die das Konto leert. die letzte Zeile, auch eine kaputte, die das Konto leert.
## DHCP zur Laufzeit
`DhcpRun` baut das Netz eines Kern-Szenarios (`packages/core/test/scenarios/*.scenario.json`:
Knoten, Kabel, Geräte, DHCP-Server und -Clients; die Schritte bleiben
unbeachtet) in Java-Filius nach und startet es wie der Aktionsmodus
(`starten()` jeder Systemsoftware). Nach der angegebenen Echtzeit schreibt es
nach `<name>.java.json`, was jede Netzwerkkarte gesehen hat (Filius' eigener
Mitschnitt, der `Lauscher`: Zeit, MACs, ARP-Operation und -Adressen,
IP/UDP-Adressen und -Ports samt DHCP-Text), und die Adressen jedes Rechners
am Ende. Die MAC eines Ports ist dieselbe wie im Kern (`mac`, sonst
`stableGeneratedMacAddress`).
* Switches und DHCP-Server starten zuerst: Javas Client wartet auf jeden
aktiven Server, findet sie aber über die Knotenliste der Oberfläche, die das
Werkzeug nicht hat.
* `GUIContainer.getGUIContainer()` wird vor dem Start einmal aufgerufen. Im
echten Filius steht das Fenster schon; ohne das legen zwei Clients den
Singleton gleichzeitig an (nicht synchronisiert), und einer von ihnen
sendet nie etwas (gemessen am Szenario `dhcp-lan`).
* Die Zeiten schwanken von Lauf zu Lauf um einige zehn Millisekunden (echte
Threads), die Link-Local-Adresse würfelt Java mit `Math.random`. Die
Reihenfolge der Nachrichten eines Clients und ihr Inhalt schwanken nicht.
Gemessen (30.09.2026), was Swift anders macht: Je Versuch sendet Java genau
ein DISCOVER bzw. REQUEST und wartet dann bis zu einer RTT (2,5 s) auf die
Antwort; eine unpassende Antwort (etwa das Angebot des zweiten Servers) liest
es und verwirft sie. Vor dem REQUEST prüft es die angebotene Adresse per ARP
und wartet dabei eine RTT; antwortet ein anderer Rechner, lehnt es mit
DHCPDECLINE ab. Javas Server übergeht das DECLINE und hält die Adresse
weiter als Angebot fest (4 RTT). Nach dem fünften Fehlversuch (Zeitablauf)
nimmt der Client eine Link-Local-Adresse `169.254.1.x/16`: ARP-Probe, eine
RTT warten, dann ein ARP-Reply an alle.
+14 -1
View File
@@ -21,7 +21,7 @@ if [ ! -f "$upstream/target/filius.jar" ]; then
fi fi
classpath="$upstream/target/filius.jar:$upstream/target/lib/*" classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
mkdir -p "$here/.build" mkdir -p "$here/.build"
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/DhcpRun.java"
# FILIUS writes its settings below $HOME; keep them out of the real one. # FILIUS writes its settings below $HOME; keep them out of the real one.
mkdir -p "$here/.build/home" mkdir -p "$here/.build/home"
# Removed first: a crashed run must not leave the previous result standing. # Removed first: a crashed run must not leave the previous result standing.
@@ -106,3 +106,16 @@ for written in "$root/packages/fls/test/written" "$root/packages/fls/test/export
test -s "$written.java.json" test -s "$written.java.json"
fi fi
done done
# DHCP as Java FILIUS runs it: a core scenario's network, started as the
# action mode starts it, for the given real-time milliseconds; every frame
# each card saw and the addresses at the end (packages/core/test/dhcpJava.test.ts).
# One run after another: a busy machine stretches the times.
for run in dhcp-lan:8000 dhcp-two-servers:8000 dhcp-conflict:25000 dhcp-no-server:25000; do
name="${run%%:*}"
output="$root/packages/core/test/scenarios/$name.java.json"
rm -f "$output"
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" DhcpRun \
"$root/packages/core/test/scenarios/$name.scenario.json" "${run##*:}" "$output" 2>&1 | grep -v 'logback\|^$' || true
test -s "$output"
done
+396
View File
@@ -0,0 +1,396 @@
// Runs a core scenario's network in Java FILIUS and records what DHCP really
// does: every frame each network card saw (FILIUS' own packet log, the
// Lauscher) and each host's address configuration at the end.
//
// DhcpRun <scenario.json> <milliseconds> <out.json>
//
// The network is built from the scenario (nodes, links, devices,
// dhcpServers, dhcpClients; steps are ignored) the way the core reads it: a
// port's MAC is its `mac`, else the core's stableGeneratedMacAddress. The
// simulation then runs as the action mode starts it (every system software's
// starten()), in real time, for the given milliseconds. Threads make the
// times vary from run to run; the order of one client's messages does not.
import filius.gui.GUIContainer;
import filius.hardware.Kabel;
import filius.hardware.NetzwerkInterface;
import filius.hardware.Port;
import filius.hardware.knoten.InternetKnoten;
import filius.hardware.knoten.Knoten;
import filius.hardware.knoten.LokalerKnoten;
import filius.hardware.knoten.Notebook;
import filius.hardware.knoten.Rechner;
import filius.hardware.knoten.Switch;
import filius.rahmenprogramm.nachrichten.Lauscher;
import filius.software.dhcp.DHCPServer;
import filius.software.netzzugangsschicht.EthernetFrame;
import filius.software.system.InternetKnotenBetriebssystem;
import filius.software.transportschicht.Segment;
import filius.software.vermittlungsschicht.ArpPaket;
import filius.software.vermittlungsschicht.IcmpPaket;
import filius.software.vermittlungsschicht.IpPaket;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class DhcpRun {
public static void main(String[] args) throws Exception {
@SuppressWarnings("unchecked")
Map<String, Object> scenario = (Map<String, Object>) new JsonReader(
new String(Files.readAllBytes(Paths.get(args[0])), StandardCharsets.UTF_8)).value();
long duration = Long.parseLong(args[1]);
Map<String, Knoten> nodes = new LinkedHashMap<>();
Map<String, Port> ports = new HashMap<>();
Map<String, String> macByNode = new LinkedHashMap<>();
for (Object each : list(scenario.get("nodes"))) {
Map<String, Object> node = map(each);
String id = (String) node.get("id");
String kind = (String) node.get("kind");
List<Object> nodePorts = list(node.get("ports"));
Knoten knoten;
switch (kind) {
case "pc":
knoten = new Rechner();
break;
case "notebook":
knoten = new Notebook();
break;
case "networkSwitch":
knoten = new Switch();
break;
default:
throw new IllegalArgumentException("node kind " + kind + " is not built by this tool");
}
knoten.setName(id);
if (knoten instanceof InternetKnoten) {
if (nodePorts.size() != 1) throw new IllegalArgumentException("a host has one port here");
Map<String, Object> port = map(nodePorts.get(0));
NetzwerkInterface nic = ((InternetKnoten) knoten).getNetzwerkInterfaces().get(0);
String mac = port.containsKey("mac") ? (String) port.get("mac") : stableMac((String) port.get("id"));
nic.setMac(mac);
ports.put((String) port.get("id"), nic.getPort());
macByNode.put(id, mac);
} else {
LinkedList<Port> switchPorts = ((LokalerKnoten) knoten).getAnschluesse();
for (int index = 0; index < nodePorts.size(); index++) {
ports.put((String) map(nodePorts.get(index)).get("id"), switchPorts.get(index));
}
}
nodes.put(id, knoten);
}
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("devices", new HashMap<>())).entrySet()) {
Map<String, Object> device = map(entry.getValue());
NetzwerkInterface nic = ((InternetKnoten) nodes.get(entry.getKey())).getNetzwerkInterfaces().get(0);
nic.setIp((String) device.get("ip"));
nic.setSubnetzMaske((String) device.get("mask"));
nic.setGateway((String) device.getOrDefault("gateway", ""));
nic.setDns((String) device.getOrDefault("dns", ""));
}
for (Object each : list(scenario.get("links"))) {
Map<String, Object> link = map(each);
Kabel cable = new Kabel();
cable.setAnschluesse(new Port[] { ports.get(link.get("sourcePort")), ports.get(link.get("targetPort")) });
}
List<String> servers = new ArrayList<>();
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("dhcpServers", new HashMap<>())).entrySet()) {
Map<String, Object> config = map(entry.getValue());
DHCPServer server = system(nodes.get(entry.getKey())).getDHCPServer();
server.setUntergrenze((String) config.getOrDefault("lower", "0.0.0.0"));
server.setObergrenze((String) config.getOrDefault("upper", "0.0.0.0"));
server.setGatewayip((String) config.getOrDefault("gateway", "0.0.0.0"));
server.setDnsserverip((String) config.getOrDefault("dns", "0.0.0.0"));
server.setOwnSettings(Boolean.TRUE.equals(config.get("own")));
for (Object assignment : list(config.getOrDefault("staticAssignments", new ArrayList<>()))) {
server.addStaticAssignment((String) list(assignment).get(0), (String) list(assignment).get(1));
}
server.setAktiv(Boolean.TRUE.equals(config.get("active")));
servers.add(entry.getKey());
}
for (Object each : list(scenario.getOrDefault("dhcpClients", new ArrayList<>()))) {
system(nodes.get((String) each)).setDHCPKonfiguration(true);
}
// Switches and DHCP servers first: FILIUS' client waits for every active
// server to have started (waitUntilDhcpServerStarted, through the GUI's
// node list, which this tool has not got).
// FILIUS' window exists before a simulation starts; created lazily and
// unsynchronized, the first clients to ask for it would race.
GUIContainer.getGUIContainer();
long start = System.currentTimeMillis();
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
if (entry.getValue() instanceof Switch || servers.contains(entry.getKey())) entry.getValue().getSystemSoftware().starten();
}
Thread.sleep(200);
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
if (!(entry.getValue() instanceof Switch || servers.contains(entry.getKey()))) entry.getValue().getSystemSoftware().starten();
}
Thread.sleep(duration);
Field field = Lauscher.class.getDeclaredField("datenEinheiten");
field.setAccessible(true);
@SuppressWarnings("unchecked")
Map<String, LinkedList<Object[]>> log = (Map<String, LinkedList<Object[]>>) field.get(Lauscher.getLauscher());
Json out = new Json();
out.open('{');
out.key("frames").open('{');
for (Map.Entry<String, String> entry : macByNode.entrySet()) {
out.key(entry.getKey()).open('[');
LinkedList<Object[]> frames = log.get(entry.getValue());
if (frames != null) {
synchronized (frames) {
for (Object[] stamped : frames) frame(out, ((Long) stamped[0]) - start, (EthernetFrame) stamped[1]);
}
}
out.close(']');
}
out.close('}');
out.key("devices").open('{');
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
if (!(entry.getValue() instanceof InternetKnoten)) continue;
NetzwerkInterface nic = ((InternetKnoten) entry.getValue()).getNetzwerkInterfaces().get(0);
out.key(entry.getKey()).open('[').string(nic.getIp()).string(nic.getSubnetzMaske()).string(nic.getGateway())
.string(nic.getDns()).close(']');
}
out.close('}');
out.close('}');
for (Knoten knoten : nodes.values()) {
try {
knoten.getSystemSoftware().beenden();
} catch (Exception e) {}
}
try (Writer writer = new OutputStreamWriter(new FileOutputStream(args[2]), StandardCharsets.UTF_8)) {
writer.write(out.toString());
writer.write('\n');
}
System.exit(0);
}
private static void frame(Json out, long time, EthernetFrame frame) {
out.open('{').key("time").number(time).key("source").string(frame.getQuellMacAdresse()).key("destination")
.string(frame.getZielMacAdresse());
Object data = frame.getDaten();
if (data instanceof ArpPaket) {
ArpPaket arp = (ArpPaket) data;
out.key("arp").number(arp.getOperation()).key("senderIp").string(arp.getSenderIP()).key("targetIp")
.string(arp.getTargetIP());
} else if (data instanceof IcmpPaket) {
out.key("icmp").number(((IcmpPaket) data).getIcmpType());
} else if (data instanceof IpPaket) {
IpPaket ip = (IpPaket) data;
Segment segment = ip.getSegment();
out.key("sourceIp").string(ip.getSender()).key("destinationIp").string(ip.getEmpfaenger()).key("protocol")
.number(ip.getProtocol()).key("sourcePort").number(segment.getQuellPort()).key("destinationPort")
.number(segment.getZielPort()).key("payload").string(segment.getDaten());
}
out.close('}');
}
private static InternetKnotenBetriebssystem system(Knoten knoten) {
return (InternetKnotenBetriebssystem) knoten.getSystemSoftware();
}
/** The core's stableGeneratedMacAddress (packages/core/src/model/node.ts). */
static String stableMac(String portId) {
String compact = portId.toUpperCase().replace("-", "");
String suffix = compact.substring(compact.length() - 10);
StringBuilder mac = new StringBuilder("02");
for (int offset = 0; offset < suffix.length(); offset += 2) mac.append(':').append(suffix, offset, offset + 2);
return mac.toString();
}
@SuppressWarnings("unchecked")
private static Map<String, Object> map(Object value) {
return (Map<String, Object>) value;
}
@SuppressWarnings("unchecked")
private static List<Object> list(Object value) {
return (List<Object>) value;
}
/** Just enough JSON for a scenario: objects, arrays, strings, numbers, booleans, null. */
static final class JsonReader {
private final String text;
private int position;
JsonReader(String text) {
this.text = text;
}
Object value() {
skip();
char c = text.charAt(position);
if (c == '{') {
Map<String, Object> result = new TreeMap<>();
position++;
skip();
if (text.charAt(position) == '}') {
position++;
return result;
}
for (;;) {
skip();
String key = (String) value();
skip();
expect(':');
result.put(key, value());
skip();
if (text.charAt(position++) == '}') return result;
}
}
if (c == '[') {
List<Object> result = new ArrayList<>();
position++;
skip();
if (text.charAt(position) == ']') {
position++;
return result;
}
for (;;) {
result.add(value());
skip();
if (text.charAt(position++) == ']') return result;
}
}
if (c == '"') {
StringBuilder result = new StringBuilder();
position++;
for (char each = text.charAt(position++); each != '"'; each = text.charAt(position++)) {
if (each == '\\') {
char escaped = text.charAt(position++);
switch (escaped) {
case 'n':
result.append('\n');
break;
case 't':
result.append('\t');
break;
case 'u':
result.append((char) Integer.parseInt(text.substring(position, position + 4), 16));
position += 4;
break;
default:
result.append(escaped);
}
} else {
result.append(each);
}
}
return result.toString();
}
if (text.startsWith("true", position)) {
position += 4;
return Boolean.TRUE;
}
if (text.startsWith("false", position)) {
position += 5;
return Boolean.FALSE;
}
if (text.startsWith("null", position)) {
position += 4;
return null;
}
int begin = position;
while (position < text.length() && "+-.eE0123456789".indexOf(text.charAt(position)) >= 0) position++;
return Double.parseDouble(text.substring(begin, position));
}
private void skip() {
while (position < text.length() && Character.isWhitespace(text.charAt(position))) position++;
}
private void expect(char c) {
if (text.charAt(position++) != c) throw new IllegalArgumentException("expected " + c + " at " + (position - 1));
}
}
/** A JSON writer with commas and indentation. */
static final class Json {
private final StringBuilder text = new StringBuilder();
private final LinkedList<Boolean> first = new LinkedList<>();
private boolean afterKey;
private void separate() {
if (afterKey) {
afterKey = false;
return;
}
if (first.isEmpty()) return;
if (!first.peek()) text.append(',');
first.pop();
first.push(false);
text.append('\n');
for (int i = 0; i < first.size(); i++) text.append(" ");
}
Json open(char bracket) {
separate();
text.append(bracket);
first.push(true);
return this;
}
Json close(char bracket) {
boolean empty = first.pop();
if (!empty) {
text.append('\n');
for (int i = 0; i < first.size(); i++) text.append(" ");
}
text.append(bracket);
return this;
}
Json key(String key) {
separate();
quote(key);
text.append(": ");
afterKey = true;
return this;
}
Json string(String value) {
separate();
if (value == null) text.append("null");
else quote(value);
return this;
}
Json number(long value) {
separate();
text.append(value);
return this;
}
private void quote(String value) {
text.append('"');
for (char c : value.toCharArray()) {
if (c == '"' || c == '\\') text.append('\\').append(c);
else if (c == '\n') text.append("\\n");
else if (c < 0x20) text.append(String.format("\\u%04x", (int) c));
else text.append(c);
}
text.append('"');
}
@Override
public String toString() {
return text.toString();
}
}
}