2023-07-15 06:38:50 +00:00
|
|
|
#!/usr/bin/env nix-shell
|
|
|
|
#!nix-shell -i python3 -p "python3.withPackages (ps: [ ])"
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import json
|
|
|
|
import os.path
|
|
|
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class Connection:
|
|
|
|
comment: str | None
|
2023-10-28 10:28:47 +00:00
|
|
|
ssid: str # also used as "id", more generally
|
2023-07-15 06:38:50 +00:00
|
|
|
passphrase: str | None
|
2023-10-28 10:28:47 +00:00
|
|
|
# LTE connections:
|
|
|
|
uuid: str | None
|
|
|
|
gsm_apn: str | None
|
|
|
|
gsm_number: str | None
|
|
|
|
|
|
|
|
@property
|
|
|
|
def type_(self) -> str:
|
|
|
|
if self.gsm_apn is not None or self.gsm_number is not None:
|
|
|
|
return "gsm"
|
|
|
|
return "wifi"
|
2023-07-15 06:38:50 +00:00
|
|
|
|
|
|
|
def parse_manifest(manifest_path: str) -> list[Connection]:
|
|
|
|
for entry in json.load(open(manifest_path)):
|
|
|
|
comment = entry.get("comment")
|
|
|
|
ssid = entry["ssid"]
|
|
|
|
passphrase = entry.get("passphrase")
|
2023-10-28 10:28:47 +00:00
|
|
|
uuid = entry.get("uuid")
|
|
|
|
gsm_apn = entry.get("gsm_apn")
|
|
|
|
gsm_number = entry.get("gsm_number")
|
2023-07-15 06:38:50 +00:00
|
|
|
if ssid != "<EOF>":
|
2023-10-28 10:28:47 +00:00
|
|
|
yield Connection(
|
|
|
|
comment=comment,
|
|
|
|
ssid=ssid,
|
|
|
|
passphrase=passphrase,
|
|
|
|
uuid=uuid,
|
|
|
|
gsm_apn=gsm_apn,
|
|
|
|
gsm_number=gsm_number,
|
|
|
|
)
|
2023-07-15 06:38:50 +00:00
|
|
|
|
2023-07-15 06:58:32 +00:00
|
|
|
def write_iwd(fh: "file", con: Connection) -> None:
|
|
|
|
fh.write("[Security]\n")
|
|
|
|
if con.passphrase is not None:
|
|
|
|
fh.write(f"Passphrase={con.passphrase}\n")
|
|
|
|
|
|
|
|
def write_nm(fh: "file", con: Connection) -> None:
|
|
|
|
fh.write("[connection]\n")
|
|
|
|
fh.write(f"id={con.ssid}\n")
|
2023-10-28 10:28:47 +00:00
|
|
|
if con.uuid is not None:
|
|
|
|
fh.write(f"uuid={con.uuid}\n")
|
|
|
|
fh.write(f"type={con.type_}\n")
|
2023-07-15 06:58:32 +00:00
|
|
|
|
2023-10-28 10:28:47 +00:00
|
|
|
if con.type_ == "wifi":
|
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[wifi]\n")
|
|
|
|
fh.write("mode=infrastructure\n")
|
|
|
|
fh.write(f"ssid={con.ssid}\n")
|
2023-07-15 06:58:32 +00:00
|
|
|
|
2023-10-28 10:28:47 +00:00
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[wifi-security]\n")
|
|
|
|
fh.write("auth-alg=open\n")
|
|
|
|
fh.write("key-mgmt=wpa-psk\n")
|
|
|
|
if con.passphrase is not None:
|
|
|
|
fh.write(f"psk={con.passphrase}\n")
|
|
|
|
elif con.type_ == "gsm":
|
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[gsm]\n")
|
|
|
|
if con.gsm_apn is not None:
|
|
|
|
fh.write(f"apn={con.gsm_apn}\n")
|
|
|
|
if con.gsm_number is not None:
|
|
|
|
fh.write(f"number={con.gsm_number}\n")
|
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[ppp]\n")
|
2023-07-15 06:58:32 +00:00
|
|
|
|
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[ipv4]\n")
|
|
|
|
fh.write("method=auto\n")
|
|
|
|
|
|
|
|
fh.write("\n")
|
|
|
|
fh.write("[ipv6]\n")
|
|
|
|
fh.write("addr-gen-mode=default\n")
|
|
|
|
fh.write("method=auto\n")
|
|
|
|
|
2023-10-28 10:28:47 +00:00
|
|
|
# fh.write("\n")
|
|
|
|
# fh.write("[proxy]\n")
|
|
|
|
|
2023-07-15 06:58:32 +00:00
|
|
|
def install_all(manifest: list[Connection], destination: str, flavor: str) -> None:
|
|
|
|
ext, writer = dict(
|
|
|
|
iwd=("psk", write_iwd),
|
|
|
|
nm=("nmconnection", write_nm),
|
|
|
|
)[flavor]
|
2023-07-15 06:38:50 +00:00
|
|
|
for con in manifest:
|
2023-07-15 06:58:32 +00:00
|
|
|
path = os.path.join(destination, f"{con.ssid}.{ext}")
|
|
|
|
with open(path, "w") as fh:
|
|
|
|
writer(fh, con)
|
2023-07-15 06:38:50 +00:00
|
|
|
|
|
|
|
def stamp(destination: str, stamp: str) -> None:
|
|
|
|
if stamp:
|
|
|
|
with open(os.path.join(destination, stamp), "w"):
|
|
|
|
pass
|
|
|
|
|
2023-07-15 06:58:32 +00:00
|
|
|
def main() -> None:
|
2023-07-15 06:38:50 +00:00
|
|
|
parser = argparse.ArgumentParser(description="create network connection descriptions from a static manifest")
|
|
|
|
parser.add_argument("manifest", help="path to the manifest.json")
|
|
|
|
parser.add_argument("destination", help="directory in which to install files")
|
2023-07-15 06:58:32 +00:00
|
|
|
parser.add_argument("--flavor", help="'nm' or 'iwd' based on which program will read the results", default="iwd")
|
2023-07-15 06:38:50 +00:00
|
|
|
parser.add_argument("--stamp", default=".install-nm.stamp", help="relative path of empty file to touch after completion")
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
manifest = parse_manifest(args.manifest)
|
2023-07-15 06:58:32 +00:00
|
|
|
install_all(manifest, args.destination, flavor=args.flavor)
|
2023-07-15 06:38:50 +00:00
|
|
|
stamp(args.destination, args.stamp)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|