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

[FEATURE REQUEST]: Add Capture Channel to Report CSV #221

Open
2 tasks done
nickjvturner opened this issue Nov 5, 2024 · 1 comment
Open
2 tasks done

[FEATURE REQUEST]: Add Capture Channel to Report CSV #221

nickjvturner opened this issue Nov 5, 2024 · 1 comment
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@nickjvturner
Copy link
Member

What happened?

I profiled a device on channel 36, 52, 100 and 164, hoping to discover different max_power values between the U-NII bands.
When I download the report CSV it is not immediately clear which channel was in use for each association request.

Relevant log output

n/a

How often does this bug happen?

Every time

What version of the app are you using?

3.2.3

Contributions

  • I have read the contribution guidelines

Code of Conduct

  • I agree to follow WLAN Pi's Code of Conduct
@nickjvturner nickjvturner added enhancement New feature or request untriaged labels Nov 5, 2024
@joshschmelzle joshschmelzle added good first issue Good for newcomers and removed untriaged labels Nov 8, 2024
@joshschmelzle
Copy link
Member

joshschmelzle commented Nov 8, 2024

Impacted code is in write_analysis_to_file_system() here:

def write_analysis_to_file_system(
self,
text_report,
capabilities,
frame,
oui_manuf,
chipset,
randomized: bool,
band,
channel,
listen_only,
):
"""Write report files out to a directory on the WLAN Pi"""
log = logging.getLogger(inspect.stack()[0][3])
# dump out the text to a file
client_mac = frame.addr2.replace(":", "-", 5)
dest = os.path.join(self.clients_dir, client_mac)
if not os.path.isdir(dest):
try:
os.mkdir(dest)
except OSError:
log.exception("problem creating %s directory", dest)
sys.exit(signal.SIGHUP)
data = {}
data["mac"] = client_mac
data["is_laa"] = randomized
data["manuf"] = oui_manuf
data["chipset"] = chipset
if band[0] == "2":
band_db = 2
elif band[0] == "5":
band_db = 5
elif band[0] == "6":
band_db = 6
else:
band_db = 0
data["band"] = band_db
data["capture_channel"] = channel
data["listen_only"] = listen_only
features = {}
for capability in capabilities:
if capability.db_key:
features[capability.db_key] = capability.db_value
data["features"] = features
data["pcap"] = json.dumps(bytes(frame), cls=Base64Encoder)
data["schema_version"] = 1
data["profiler_version"] = __version__
# if there is a malformed radiotap header
if band == "unknown":
band = ""
else:
band = f"_{band}"
text_filename = os.path.join(dest, f"{client_mac}{band}.txt")
json_filename = os.path.join(dest, f"{client_mac}{band}.json")
try:
same = False
write_time = strftime("%Y%m%dt%H%M%S")
if os.path.exists(json_filename):
with open(json_filename, "r") as _file:
existing_json = json.load(_file)
if hash(str(json.dumps(existing_json.get("features")))) == hash(
str(json.dumps(features))
):
# previously profiled client has the same features
same = True
if not same:
json_filename = json_filename.replace(
".json", f"_diff.{write_time}.json"
)
log.debug("writing json report to %s", json_filename)
with open(json_filename, "w") as write_json_file:
json.dump(data, write_json_file)
if os.path.exists(text_filename):
with open(text_filename, "r") as read_file:
existing_text = read_file.readlines()
temp = []
for line in existing_text:
temp.append(line.replace("\n", ""))
existing_text = temp
if not same:
text_report = list(
Differ().compare(existing_text, text_report.split("\n"))
)
text_filename = text_filename.replace(
".txt", f"_diff.{write_time}.txt"
)
text_report = "\n".join(text_report)
log.debug("writing to %s", text_filename)
with open(text_filename, "w") as file_writer:
file_writer.write(text_report)
except OSError:
log.exception(
"error creating flat files to dump client info (%s)", text_filename
)
sys.exit(signal.SIGHUP)
out_row = {"Client_Mac": client_mac, "OUI_Manuf": oui_manuf}
out_fieldnames = ["Client_Mac", "OUI_Manuf"]
for capability in capabilities:
if capability.db_key:
features[capability.db_key] = capability.db_value
for capability in capabilities:
if capability.db_key is not None and capability.db_value is not None:
out_fieldnames.append(capability.db_key)
out_row[capability.db_key] = capability.db_value
# dump out the frame to a file
pcap_filename = os.path.splitext(text_filename)[0] + ".pcap"
log.debug("writing to %s", pcap_filename)
wrpcap(pcap_filename, [frame])
# check if csv file exists
if not os.path.exists(self.csv_file):
# create file with csv headers
with open(self.csv_file, mode="w") as file_obj:
csv_writer = csv.DictWriter(file_obj, fieldnames=out_fieldnames)
csv_writer.writeheader()
# append data to csv file
with open(self.csv_file, mode="a") as file_obj:
csv_writer = csv.DictWriter(file_obj, fieldnames=out_fieldnames)
csv_writer.writerow(out_row)

I believe we can just add channel as capture_channel here:

out_row = {"Client_Mac": client_mac, "OUI_Manuf": oui_manuf}
out_fieldnames = ["Client_Mac", "OUI_Manuf"]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants