packet-tracer-skill 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/LICENSES/LICENSE.Twofish-BSD-3-Clause.txt +29 -0
- package/README.md +687 -0
- package/SKILL.md +221 -0
- package/bin/packet-tracer-skill.js +635 -0
- package/examples/blueprint_minimal.json +46 -0
- package/package.json +42 -0
- package/references/packettracer-sample-catalog.json +21410 -0
- package/references/packettracer-sample-catalog.md +1124 -0
- package/references/pkt-format.md +57 -0
- package/references/xml-skeleton-notes.md +44 -0
- package/requirements-dev.txt +1 -0
- package/requirements.txt +6 -0
- package/scripts/build_sample_catalog.py +65 -0
- package/scripts/donor_diagnostics.py +35 -0
- package/scripts/generate_pkt.py +1264 -0
- package/scripts/install_skill.py +71 -0
- package/scripts/intent_parser.py +712 -0
- package/scripts/packet_tracer_env.py +278 -0
- package/scripts/pkt_builder.py +15 -0
- package/scripts/pkt_codec.py +181 -0
- package/scripts/pkt_editor.py +752 -0
- package/scripts/pkt_transformer.py +541 -0
- package/scripts/sample_catalog.py +385 -0
- package/scripts/sample_selector.py +156 -0
- package/scripts/setup.ps1 +26 -0
- package/scripts/twofish_diagnostics.py +91 -0
- package/scripts/vendor/README.md +46 -0
- package/scripts/vendor/twofish.py +81 -0
- package/scripts/workspace_repair.py +441 -0
- package/templates/pt900/base_empty.xml +21 -0
- package/templates/pt900/device_library/pc.xml +20 -0
- package/templates/pt900/device_library/printer.xml +432 -0
- package/templates/pt900/device_library/router.xml +16 -0
- package/templates/pt900/device_library/switch.xml +38 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Packet Tracer 9.0 Format Notes
|
|
2
|
+
|
|
3
|
+
This skill targets the modern Packet Tracer `.pkt` format described in the
|
|
4
|
+
research notes supplied alongside the skill update request.
|
|
5
|
+
|
|
6
|
+
## High-Level Pipeline
|
|
7
|
+
|
|
8
|
+
1. Packet Tracer XML bytes
|
|
9
|
+
2. qCompress wrapper
|
|
10
|
+
3. Stage-2 XOR obfuscation
|
|
11
|
+
4. Twofish/EAX encryption with a 16-byte authentication tag
|
|
12
|
+
5. Stage-1 reverse/XOR obfuscation
|
|
13
|
+
|
|
14
|
+
## qCompress Wrapper
|
|
15
|
+
|
|
16
|
+
The qCompress-compatible wrapper used here is:
|
|
17
|
+
|
|
18
|
+
- 4-byte big-endian uncompressed length
|
|
19
|
+
- zlib-compressed payload
|
|
20
|
+
|
|
21
|
+
## Modern Codec Constants
|
|
22
|
+
|
|
23
|
+
- Twofish key: `0x89` repeated 16 times
|
|
24
|
+
- EAX nonce seed: `0x10` repeated 16 times
|
|
25
|
+
- Tag length: `16`
|
|
26
|
+
|
|
27
|
+
## Stage-2 XOR
|
|
28
|
+
|
|
29
|
+
Stage-2 XOR is symmetric:
|
|
30
|
+
|
|
31
|
+
```text
|
|
32
|
+
out[i] = in[i] XOR ((L - i) & 0xFF)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
where `L` is the input length.
|
|
36
|
+
|
|
37
|
+
## Stage-1 Obfuscation
|
|
38
|
+
|
|
39
|
+
For output:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
out[L - 1 - i] = in[i] XOR ((L - i * L) & 0xFF)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
For decode:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
clear[i] = obf[L - 1 - i] XOR ((L - i * L) & 0xFF)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Compatibility Notes
|
|
52
|
+
|
|
53
|
+
- The XML root should be `PACKETTRACER5`
|
|
54
|
+
- The targeted version field is `9.0.0.0810`
|
|
55
|
+
- Cross-version compatibility is not assumed
|
|
56
|
+
- The template library in this skill is a controlled starter set, not a complete
|
|
57
|
+
reverse-engineered clone of all Packet Tracer internals
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# XML Skeleton Notes
|
|
2
|
+
|
|
3
|
+
The builder uses a `PACKETTRACER5` root and organizes generated content under a
|
|
4
|
+
`NETWORK` node with `DEVICES`, `LINKS`, and `SHAPETESTS`.
|
|
5
|
+
|
|
6
|
+
## Base Document Shape
|
|
7
|
+
|
|
8
|
+
```xml
|
|
9
|
+
<PACKETTRACER5>
|
|
10
|
+
<VERSION>9.0.0.0810</VERSION>
|
|
11
|
+
<PIXMAPBANK />
|
|
12
|
+
<MOVIEBANK />
|
|
13
|
+
<NETWORK>
|
|
14
|
+
<DEVICES />
|
|
15
|
+
<LINKS />
|
|
16
|
+
<SHAPETESTS />
|
|
17
|
+
</NETWORK>
|
|
18
|
+
<OPTIONS />
|
|
19
|
+
<PHYSICALWORKSPACE />
|
|
20
|
+
</PACKETTRACER5>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Template Strategy
|
|
24
|
+
|
|
25
|
+
This skill does not attempt to synthesize the entire Cisco-internal XML schema from
|
|
26
|
+
scratch. Instead, it uses:
|
|
27
|
+
|
|
28
|
+
- a stable base XML document
|
|
29
|
+
- per-device XML templates
|
|
30
|
+
- targeted placeholder replacement for names, models, positions, ports, and configs
|
|
31
|
+
|
|
32
|
+
## Current Supported Device Templates
|
|
33
|
+
|
|
34
|
+
- `router.xml`
|
|
35
|
+
- `switch.xml`
|
|
36
|
+
- `pc.xml`
|
|
37
|
+
|
|
38
|
+
Each template includes:
|
|
39
|
+
|
|
40
|
+
- a generated device id
|
|
41
|
+
- human-readable device name
|
|
42
|
+
- type and model fields
|
|
43
|
+
- layout coordinates
|
|
44
|
+
- a config section appropriate for the device family
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pytest>=8,<9
|
package/requirements.txt
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Runtime Python dependencies
|
|
2
|
+
#
|
|
3
|
+
# The main runtime is intentionally standard-library-first.
|
|
4
|
+
# Packet Tracer encode/decode for modern 9.x files additionally needs a local
|
|
5
|
+
# Twofish bridge binary configured via PKT_TWOFISH_LIBRARY or placed under
|
|
6
|
+
# scripts/vendor/.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
|
|
6
|
+
from packet_tracer_env import require_packet_tracer_saves_root
|
|
7
|
+
from pkt_codec import decode_pkt_modern
|
|
8
|
+
from sample_catalog import write_catalog_outputs
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def summarize_pkt(path: Path) -> dict:
|
|
12
|
+
saves_root = require_packet_tracer_saves_root()
|
|
13
|
+
xml = decode_pkt_modern(path.read_bytes())
|
|
14
|
+
root = ET.fromstring(xml)
|
|
15
|
+
devices = []
|
|
16
|
+
for device in root.findall(".//DEVICES/DEVICE"):
|
|
17
|
+
type_node = device.find("./ENGINE/TYPE")
|
|
18
|
+
devices.append(
|
|
19
|
+
{
|
|
20
|
+
"name": device.findtext("./ENGINE/NAME", default=""),
|
|
21
|
+
"type": device.findtext("./ENGINE/TYPE", default=""),
|
|
22
|
+
"model": type_node.get("model", "") if type_node is not None else "",
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
links = []
|
|
26
|
+
for link in root.findall(".//LINKS/LINK"):
|
|
27
|
+
cable = link.find("./CABLE")
|
|
28
|
+
ports = cable.findall("PORT") if cable is not None else []
|
|
29
|
+
links.append(
|
|
30
|
+
{
|
|
31
|
+
"type": link.findtext("./TYPE", default=""),
|
|
32
|
+
"cable_type": cable.findtext("./TYPE", default="") if cable is not None else "",
|
|
33
|
+
"ports": [port.text or "" for port in ports[:2]],
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
return {
|
|
37
|
+
"relative_path": str(path.relative_to(saves_root)),
|
|
38
|
+
"version": root.findtext("./VERSION", default=""),
|
|
39
|
+
"device_count": len(devices),
|
|
40
|
+
"link_count": len(links),
|
|
41
|
+
"devices": devices,
|
|
42
|
+
"links": links,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def build_catalog() -> list[dict]:
|
|
47
|
+
saves_root = require_packet_tracer_saves_root()
|
|
48
|
+
items = []
|
|
49
|
+
for path in sorted(saves_root.rglob("*.pkt")):
|
|
50
|
+
try:
|
|
51
|
+
items.append(summarize_pkt(path))
|
|
52
|
+
except Exception as exc:
|
|
53
|
+
items.append({"relative_path": str(path.relative_to(saves_root)), "error": f"{type(exc).__name__}: {exc}"})
|
|
54
|
+
return items
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main() -> None:
|
|
58
|
+
require_packet_tracer_saves_root()
|
|
59
|
+
items = build_catalog()
|
|
60
|
+
write_catalog_outputs(items)
|
|
61
|
+
print(f"Wrote {len(items)} sample entries")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
if __name__ == "__main__":
|
|
65
|
+
main()
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Runtime diagnostics for Packet Tracer donor compatibility."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import json
|
|
7
|
+
from packet_tracer_env import inspect_packet_tracer_compatibility_donor
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def main() -> int:
|
|
11
|
+
details = inspect_packet_tracer_compatibility_donor()
|
|
12
|
+
result = {
|
|
13
|
+
"target_version": details.target_version,
|
|
14
|
+
"resolved_donor_path": str(details.resolved_path) if details.resolved_path else "",
|
|
15
|
+
"donor_path": str(details.resolved_path) if details.resolved_path else "",
|
|
16
|
+
"donor_version": details.donor_version or "",
|
|
17
|
+
"donor_source": details.donor_source or "",
|
|
18
|
+
"status": details.status,
|
|
19
|
+
"message": (
|
|
20
|
+
f"{details.resolved_path} (version {details.donor_version})"
|
|
21
|
+
if details.status == "ok" and details.resolved_path and details.donor_version
|
|
22
|
+
else details.blocking_reason or details.status
|
|
23
|
+
),
|
|
24
|
+
"blocking_reason": details.blocking_reason,
|
|
25
|
+
"candidate_paths": [
|
|
26
|
+
{"source": source, "path": str(path)}
|
|
27
|
+
for source, path in details.candidate_paths[:10]
|
|
28
|
+
],
|
|
29
|
+
}
|
|
30
|
+
print(json.dumps(result))
|
|
31
|
+
return 0
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
if __name__ == "__main__":
|
|
35
|
+
raise SystemExit(main())
|