Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple fixes #456

Merged
merged 5 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/gallia/command/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,10 @@ async def setup(self, args: Namespace) -> None:
if shutil.which("dumpcap") is None:
self.parser.error("--dumpcap specified but `dumpcap` is not available")
self.dumpcap = await Dumpcap.start(args.target, self.artifacts_dir)
await self.dumpcap.sync()
if self.dumpcap is None:
logger.error("Dumpcap could not be started!")
else:
await self.dumpcap.sync()

self.transport = await load_transport(args.target).connect(args.target)

Expand Down
19 changes: 9 additions & 10 deletions src/gallia/commands/discover/doip.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,22 +272,21 @@ async def enumerate_target_addresses( # noqa: PLR0913
logger.debug(f"[🚧] Attempting connection to {target_addr:#x}")

conn.target_addr = target_addr
current_target = f"doip://{tgt_hostname}:{tgt_port}?activation_type={correct_rat:#x}&src_addr={correct_src:#x}&target_addr={target_addr:#x}"

try:
req = TesterPresentRequest(suppress_response=False)
await conn.write_diag_request(req.pdu)

# If we reach this, the request was not denied due to unknown TargetAddress
known_targets.append(
f"doip://{tgt_hostname}:{tgt_port}?activation_type={correct_rat:#x}&src_addr={correct_src:#x}&target_addr={target_addr:#x}"
)
known_targets.append(current_target)
logger.notice(
f"[🥇] HEUREKA: target address {target_addr:#x} is valid! "
)
async with aiofiles.open(
self.artifacts_dir.joinpath("3_valid_targets.txt"), "a"
) as f:
await f.write(f"{known_targets[-1]}\n")
await f.write(f"{current_target}\n")

logger.info(f"[⏳] Waiting for reply of target {target_addr:#x}")
# Hardcoded loop to detect potential broadcasts
Expand Down Expand Up @@ -316,13 +315,13 @@ async def enumerate_target_addresses( # noqa: PLR0913
logger.notice(
f"[🥳] It cannot get nicer: {target_addr:#x} responded: {resp}"
)
responsive_targets.append(known_targets[-1])
responsive_targets.append(current_target)
async with aiofiles.open(
self.artifacts_dir.joinpath("4_responsive_targets.txt"), "a"
) as f:
await f.write(f"{known_targets[-1]}\n")
await f.write(f"{current_target}\n")
if self.db_handler is not None:
await self.db_handler.insert_discovery_result(known_targets[-1])
await self.db_handler.insert_discovery_result(current_target)

except DoIPNegativeAckError as e:
if (
Expand All @@ -333,11 +332,11 @@ async def enumerate_target_addresses( # noqa: PLR0913
continue
elif e.nack_code == DiagnosticMessageNegativeAckCodes.TargetUnreachable:
logger.info(f"[💤] {target_addr:#x} is (currently?) unreachable")
unreachable_targets.append(known_targets[-1])
unreachable_targets.append(current_target)
async with aiofiles.open(
self.artifacts_dir.joinpath("5_unreachable_targets.txt"), "a"
) as f:
await f.write(f"{known_targets[-1]}\n")
await f.write(f"{current_target}\n")
continue
else:
logger.warning(
Expand All @@ -356,7 +355,7 @@ async def enumerate_target_addresses( # noqa: PLR0913
async with aiofiles.open(
self.artifacts_dir.joinpath("5_unresponsive_targets.txt"), "a"
) as f:
await f.write(f"{known_targets[-1]}\n")
await f.write(f"{current_target}\n")
continue

except (ConnectionError, ConnectionResetError) as e:
Expand Down
6 changes: 3 additions & 3 deletions src/gallia/commands/discover/uds/isotp.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def configure_parser(self) -> None:
self.parser.add_argument(
"--pdu",
type=unhexlify,
default=bytes([0x10, 0x01]),
default=bytes([0x3E, 0x00]),
help="set pdu used for discovery",
)
self.parser.add_argument(
Expand Down Expand Up @@ -178,7 +178,7 @@ async def main(self, args: Namespace) -> None:

await transport.sendto(pdu, timeout=0.1, dst=dst_addr)
try:
addr, _ = await transport.recvfrom(timeout=0.1)
addr, payload = await transport.recvfrom(timeout=0.1)
if addr == ID:
logger.info(
f"The same CAN ID {can_id_repr(ID)} answered. Skipping…"
Expand Down Expand Up @@ -210,7 +210,7 @@ async def main(self, args: Namespace) -> None:
)
else:
logger.result(
f"found endpoint on CAN ID [src:dst]: {can_id_repr(ID)}:{can_id_repr(addr)}"
f"found endpoint on CAN ID [src:dst]: {can_id_repr(ID)}:{can_id_repr(addr)}: {payload.hex()}"
)
target_args = {}
target_args["is_fd"] = str(transport.config.is_fd).lower()
Expand Down
18 changes: 11 additions & 7 deletions src/gallia/dumpcap.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ async def start(
cls,
target: TargetURI,
artifacts_dir: Path,
) -> Dumpcap:
) -> Dumpcap | None:
ts = int(datetime.now().timestamp())
if target.scheme in [ISOTPTransport.SCHEME, RawCANTransport.SCHEME]:
outfile = artifacts_dir.joinpath(f"candump-{ts}.pcap.gz")
Expand All @@ -65,6 +65,8 @@ async def start(
outfile = artifacts_dir.joinpath(f"eth-{ts}.pcap.gz")
cmd = await cls._eth_cmd(target.netloc)

if cmd is None:
return None
cmd_str = shlex.join(cmd)
try:
proc = await asyncio.create_subprocess_exec(
Expand All @@ -75,12 +77,11 @@ async def start(
await asyncio.sleep(0.2)
except Exception as e:
logger.error(f"Could not start dumpcap: ({e!r})")
raise
return None

if proc.returncode:
raise RuntimeError(
f"dumpcap terminated with exit code: [{proc.returncode}]"
)
logger.error(f"dumpcap terminated with exit code: [{proc.returncode}]")
return None

logger.info(f'Started "dumpcap": {cmd_str}')

Expand Down Expand Up @@ -122,15 +123,18 @@ def _swap_bytes_16(x: int) -> int:
return cast(int, struct.unpack(">H", struct.pack("<H", x))[0])

@staticmethod
def _can_cmd(iface: str, src_addr: int | None, dst_addr: int | None) -> list[str]:
def _can_cmd(
iface: str, src_addr: int | None, dst_addr: int | None
) -> list[str] | None:
args = ["dumpcap", "-q", "-i", iface, "-w", "-"]
# Debug this with `dumpcap -d` or `tshark -x` to inspect the captured buffer.
filter_ = "link[1] == 0x01" # broadcast flag; ignore "sent by us" frames

if src_addr is not None and dst_addr is not None:
# TODO: Support extended CAN IDs
if src_addr > 0x800 or dst_addr > 0x800:
raise ValueError("Extended CAN IDs are currently not supported!")
logger.error("Extended CAN Ids are currently not supported!")
return None

# Debug this with `dumpcap -d` or `tshark -x` to inspect the captured buffer.
filter_ += (
Expand Down
2 changes: 1 addition & 1 deletion src/gallia/services/uds/core/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class UDSIsoServices(IntEnum):
ShowCurrentData = 0x01
ShowFreezeFrameData = 0x02
ShowstoredDiagnosticTroubleCodes = 0x03
ShowStoredDiagnosticTroubleCodes = 0x03
ClearDiagnosticTroubleCodesAndStoredValues = 0x04
TestResultsOxygenSensorMonitoring = 0x05
TestResultsOtherComponentSystemMonitoring = 0x06
Expand Down
2 changes: 0 additions & 2 deletions src/gallia/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,8 @@ async def write_target_list(
:params db_handler: if given, urls are also written to the database as discovery results
:return: None
"""
urls = []
async with aiofiles.open(path, "w") as f:
for target in targets:
urls.append(str(target))
await f.write(f"{target}\n")

if db_handler is not None:
Expand Down
Loading