commit bf4aa50b38f509f15ef01c0474fdf15a8272c471 Author: Martin Tonusoo Date: Thu Jun 15 17:55:10 2023 +0300 Initial commit diff --git a/1224ABORT.bin b/1224ABORT.bin new file mode 100644 index 0000000..2ffefa8 Binary files /dev/null and b/1224ABORT.bin differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bef4c91 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Martin Tonusoo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..fcf1b2b --- /dev/null +++ b/README.md @@ -0,0 +1,502 @@ +

Linux-based CPE for Telia's (AS3249) "Koduinternet" service

+ +

:book: Table of Contents

+
+ Table of Contents +
    +
  1. ➤ About The Project
  2. +
  3. ➤ Hardware
  4. +
  5. ➤ Configuring NIC NVRAM
  6. +
  7. ➤ Modifying the NIC driver
  8. +
  9. ➤ Rooting the SFP ONT
  10. +
  11. ➤ Modifying the SFP ONT serial
  12. +
  13. + ➤ Debian 10 config + +
  14. +
  15. + ➤ Hardware mods + +
  16. +
  17. ➤ Acknowledgements
  18. +
  19. ➤ License
  20. +
+
+ +

:pencil: About The Project

+

+Debian based router on conventional PC hardware and SFP GPON ONT replacing the Technicolor or Genexis router and stand-alone Huawei ONT provided by ISP. +

+ +["Configuring NIC NVRAM"](#configuring-nic-nvram) and ["Modifying the NIC driver"](#modifying-the-nic-driver) steps are needed if `2500BASE-X` link between the NIC and SFP ONT is desired instead of `1000BASE-T` link. ["Rooting the SFP ONT"](#rooting-the-sfp-ont) and ["Modifying the SFP ONT serial"](#modifying-the-sfp-ont-serial) steps are mandatory because Telia authenticates ONT by its serial number. + +

:clipboard: Hardware

+ +``` +CPU: Intel Core i7-4790K @ 4.00GHz (Cooler Master Hyper 212 EVO cooler) +MB: ASRock H97 Anniversary +RAM: Crucial 8 GiB CT102464BA160B.C16FER +SSD: Corsair Force LS 2.5" 60 GB SATA3 +NIC: Dell N20KJ; Broadcom BCM57810 (wan0 and lan0; driver bnx2x; firmware /usr/lib/firmware/bnx2x/bnx2x-e2-7.13.1.0.fw; NF-A4x10 fan) +NIC: integrated; Realtek RTL8111/8168/8411 (lan1; driver r8169; firmware /usr/lib/firmware/rtl_nic/rtl8168g-2.fw) +NIC: TP-LINK TG-3468; Realtek RTL8111/8168/8411 (lan2; driver r8169; firmware /usr/lib/firmware/rtl_nic/rtl8168e-2.fw) +NIC: TP-LINK TG-3468; Realtek RTL8111/8168/8411 (lan3; driver r8169; firmware /usr/lib/firmware/rtl_nic/rtl8168e-2.fw) +WNIC: Asus PCE-AC88; Broadcom BCM4366(v4) (wlan0; driver brcmfmac; firmware /usr/lib/firmware/brcm/brcmfmac4366c-pcie.bin) +LTE modem: Huawei E3372s-153 (hw ver: CL1E3372SM Ver.A; firmware ver: 22.286.03.02.07) +SFP ONT: Huawei MA5671A +PSU: Chieftec CTG-500-80P +case: Chieftec 1E0-500A-CT04 +``` + +

:small_blue_diamond: Configuring NIC NVRAM

+ +Both the Huawei MA5671A SFP ONT and Dell N20KJ NIC using the Broadcom BCM57810 chipset support the 2500BASE-X mode. According to Broadcom NetXtreme II Network Adapter User Guide, the 2500BASE-X is a term used by Broadcom to describe 2.5 Gbit/s operation, where electricals are leveraged from IEEE 802.3ae-2002 (XAUI). + + +By default, the `Dell N20KJ` branded NIC supports 1GigE and 10GigE modes. One needs to configure the NIC's NVRAM with [QLogic BCM577xx/BCM578xx diagnostics utility named eDiag](https://github.com/tonusoo/koduinternet-cpe/raw/main/uefi_ediag.tgz) in order to enable the 2500BASE-X mode. For example, the NIC can be passed through to a VM where `ediag_x64.efi` UEFI binary in engineering mode(`-b10eng`) is executed: + +![UEFI shell in qemu VM](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/UEFI_shell_in_qemu_VM.jpg) + +Command for creating the VM in the upper `tmux` pane was: +``` +# PCIe passthrough requires IOMMU support. +# "OVMF.fd" UEFI is from the "ovmf" package. +qemu-system-x86_64 \ + -name eDiag-VM \ + --enable-kvm \ + -m 1G \ + -bios /usr/share/ovmf/OVMF.fd \ + -serial telnet:127.0.0.1:5016,server,nowait \ + -nographic \ + -drive file=fat:rw:UEFI/uefi_ediag/x64/,format=raw \ + -device vfio-pci,host=01:00.0,rombar=0 \ + -device vfio-pci,host=01:00.1,rombar=0 +``` + +As seen on the lower `tmux` pane, the first ports is set to `2.5G` mode: +![UEFI eDiag in qemu VM](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/UEFI_eDiag_in_qemu_VM.jpg) + +`2500BASE-X` mode was enabled and set as a default for the first port with `eDiag` CLI commands below: +``` +device 1 +nvm cfg +7 +35=70 +36=70 +56=6 +59=6 +save +exit +``` + +Correct link settings for the first port can be seen below: +![UEFI eDiag in qemu VM 2.5G settings](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/UEFI_eDiag_in_qemu_VM_2_5G_settings.jpg) + + +

:small_blue_diamond: Modifying the NIC driver

+ +`bnx2x` driver was [patched](https://github.com/tonusoo/koduinternet-cpe/blob/main/code/bnx2x_link.patch) in order to support the 2500BASE-X mode and ignore the Tx fault: + +![bnx2x_link.c diff](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/bnx2x_link_diff.jpg) + +Without ignoring the Tx fault, the Ethernet link would drop down if the fiber to `MA5671A SFP ONT` is not connected and ONT is not successfully registered by the OLT. + +Example of taking the patched driver into use: + +![patching the bnx2x driver](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/patching_the_bnx2x_driver.jpg) + +For troubleshooting purposes, the driver can be loaded in debug mode with `modprobe -v bnx2x debug=0x4102034`. + +`2500BASE-X` link between the `MA5671A SFP ONT` and `Dell N20KJ` NIC observed from the Linux router: + +![MA5671A and 2500BASE-X link from r1](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_and_2500BASE-X_link_from_r1.jpg) + +The same link mode seen from the non-rooted `MA5671A SFP ONT` `minishell` with the `lanpsg`(LAN port status get) command where `link_status` value `5` means `2500BASE-X`: + +![MA5671A and 2500BASE-X link from non-rooted MA5671A](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_and_2500BASE-X_link_from_non-rooted_MA5671A.jpg) + +Link mode checked from the rooted `MA5671A SFP ONT`: + +![MA5671A and 2500BASE-X link from rooted MA5671A](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_and_2500BASE-X_link_from_rooted_MA5671A.jpg) + +In case the `2500BASE-X` mode is not desired, then `Huawei MA5671A SFP ONT` links also in `1000BASE-T` mode: + +![MA5671A and 1000BASE-T link from r1 and rooted MA5671A.jpg](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_and_1000BASE-T_link_from_r1_and_rooted_MA5671A.jpg) + +Once the link is established, the SFP is accessible at 192.168.1.10 via SSH. User is `root` and password is `admin123`. + + +

:small_blue_diamond: Rooting the SFP ONT

+ +One option to root the `Huawei MA5671A SFP ONT` is to short the `GND`(pin `4`) and `Serial Data Input`(pin `5`) of the [flash memory](https://github.com/tonusoo/koduinternet-cpe/blob/main/docs/Infineon-S25FL129P_128-Mbit_3.0_V_Flash_Memory-DataSheet-v11_00-EN.pdf) and power on the SFP. The SFP will boot into bootrom CLI and one can transfer a modified boot loader([1224ABORT.bin](https://github.com/tonusoo/koduinternet-cpe/raw/main/1224ABORT.bin)) to flash chip with XMODEM file transfer protocol. + +`Huawei MA5671A SFP ONT` with wires soldered to `GND` and `SI` pins: +![MA5671A with soldered wires to flash](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_with_soldered_wires_to_flash.jpg) + +`Huawei MA5671A SFP ONT` connected to [Reveltronics adapter board](https://www.reveltronics.com/en/products/sfp-qsfp-xfp): +![MA5671A connected to reveltronics board](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_connected_to_reveltronics_board.jpg) + +As seen above, the `RXD`, `TXD` and `GND` of the USB to TTL (3.3V) adapter are connected to transceivers adapter board. + +Minicom(`115200 8N1`) screenshot of the `Huawei MA5671A SFP ONT` bootup where `GND` and `SI` pins of the flash were shorted: + +![FALCON CLI after modified U-Boot upload](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/falcon_cli_after_modified_u-boot_upload.jpg) + +Typing the `7` in the `ROM:` prompt started the XMODEM file transfer mode and `Ctrl + c` aborted the autoboot. Setting the variables below will keep the bootloader open after the SFP module restart: +``` +FALCON => setenv bootdelay 5 +FALCON => setenv asc 0 +FALCON => setenv preboot "gpio input 105;gpio input 106;gpio input 107;gpio input 108;gpio set 3;gpio set 109;gpio set 110;gpio clear 423;gpio clear 422;gpio clear 325;gpio clear 402;gpio clear 424" +FALCON => saveenv +``` + +After rebooting the module, the `minishell` was replaced with `ash` shell with `sed -i "s|/opt/lantiq/bin/minishell|/bin/ash|g" /etc/passwd`. + +[1224ABORT.bin](https://github.com/tonusoo/koduinternet-cpe/raw/main/1224ABORT.bin)(MD5 `10e94a4b4acdc82dec20c7904b69e5c0`) is a slightly modified U-Boot version 1.22.4 binary image for `MA5671A`. Hex dumps diff between the `1224ABORT.bin` and [unmodified U-boot for this module](https://github.com/minhng99/alcatel_lucent-lantiq_falcon/blob/master/mtd/mtd0)(`Huawei MA5671A` is based on `Alcatel-Lucent G-010S-P`) can be seen below: + +![1224ABORT.bin hex dump compared to vanilla U-boot](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/1224ABORT_hex_dump_compared_to_vanilla_U-boot.jpg) + +Boot messages over serial of the rooted `MA5671A SFP ONT` can be seen [here](https://github.com/tonusoo/koduinternet-cpe/blob/main/docs/rooted_MA5671A_boot_messages.txt). + +

:small_blue_diamond: Modifying the SFP ONT serial

+ +GPON OLT does not register the new SFP ONT if its serial number differs from the serial number of the `Huawei HG8010H ONT` installed by Telia. In other words, the serial number of the ONT is used for authentication. Here is a screenshot of the OLT CLI from [Huawei forum](https://forum.huawei.com/enterprise/en/sfp-mini-ont-ma5671a-ploam-password/thread/686439-100181) showing the status of the ONT: + +![Huawei GPON OLT CLI](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/Huawei_GPON_OLT_CLI.jpg) + +The serial of the `Huawei HG8010H` provided by Telia can be seen from the web interface: + +![HG8010H status](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/HG8010H_status.jpg) + +Default username is `root` and password is `admin`. One could also log in as a privileged user named `telecomadmin` with password `admintelecom`. For example, this allows one to enable telnet access to `Huawei HG8010H ONT` by downloading its configuration file from the web interface, modifying the `TELNETLanEnable` parameter and uploading the configuration. The same serial from `Huawei HG8010H` CLI: + +![HG8010H telnet CLI](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/HG8010H_telnet_cli.jpg) + +The hex representation of the serial is also printed on the label under the `Huawei HG8010H` chassis and additionally on its cardboard box. + +`MA5671A SFP ONT` stores the base64 encoded serial number in U-Boot environment(`/dev/mtd1` flash partition named `uboot_env`) variable called "sfp_a2_info". The "sfp_a2_info" variable contains multiple base64 encoded fields/lines which are separated with `@` character. For example, the MAC address is on the ninth field and GPON ONT password is on the fifth field. However, only the serial needs to be changed and this is on the sixth, 45 bytes long base64 encoded field: + +![MA5671A serial in sfp_a2_info](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_serial_in_sfp_a2_info.jpg) + +As seen above, the output of the `fw_printenv sfp_a2_info` was transferred to `r1` Debian machine where the sixth base64 field was decoded to binary and dumped to hex. In order to change the serial number for example from `HWTCa1b1c1d1` to `HWTCa2b2c2d2`, it's necessary to prepare a new value of "sfp_a2_info" variable: + +![MA5671A new sfp_a2_info prepared](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_new_sfp_a2_info_prepared.jpg) + +As a final step, the modified "sfp_a2_info" variable needs to be written to `/dev/mtd1` with `fw_setenv` and SFP ONT has to be rebooted so U-Boot reads the updated variable: + +![MA5671A new_sfp_a2_info written](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_new_sfp_a2_info_written.jpg) + +As mentioned before, the default password for `root` user is `admin123`. It's recommended to back up the `/dev/mtd1` and output of `fw_printenv` before the changes. + +`MA5671A SFP ONT` registration status can be checked with the `onu ploamsg` command. Value of the `curr_state` has to be `5` which means `O5` or `operation-state`: + +![MA5671A in operation state](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/MA5671A_in_operation_state.jpg) + +The same `O5` value was seen on the screenshot of the `Huawei HG8010H ONT` [web interface](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/HG8010H_status.jpg). On lower `tmux` pane the optical Tx and Rx power reported by the `MA5671A SFP ONT`(plugged into `wan0` port) can be seen. + +

:small_blue_diamond: Debian 10 config

+ +Configuration leans towards traditional or legacy way of doing things, e.g `iptables` over `nftables`, `udev` rules in `/etc/udev/rules.d/` for renaming network interfaces instead of `/etc/systemd/network/*.link` files, etc. This is an intentional design choice. + +

:black_small_square: udev and usb_modeswitch config

+ +`Huawei E3372s-153` USB LTE modem has to be mode switched from `157d`(CD/DVD drive) to [modem mode](https://wiki.dd-wrt.com/wiki/index.php/3G_/_3.5G#Huawei) which is `14dc` for this particular device. + +This is taken care of by following `udev` rule in `/usr/lib/udev/rules.d/40-usb_modeswitch.rules` file installed by `usb-modeswitch-data` package: +``` +ATTRS{idVendor}=="12d1", ATTRS{manufacturer}!="Android", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="usb_modeswitch '/%k'" +``` +The rule above executes the `/usr/lib/udev/usb_modeswitch` script with a "kernel name" for the device as an argument, e.g `/usr/lib/udev/usb_modeswitch 3-2:1.0`. The script starts an instance of the `/lib/systemd/system/usb_modeswitch@.service`, which in turn executes the `usb_modeswitch_dispatcher` binary with a `--switch-mode` option for a specified device. `usb_modeswitch_dispatcher` reads the configuration from the `/usr/share/usb_modeswitch/configPack.tar.gz` tarball: +``` +root@r1:~# tar -xOzf /usr/share/usb_modeswitch/configPack.tar.gz 12d1:157d +# Huawei E3331, E3372 +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 +root@r1:~# +``` +.. and calls the `usb_modeswitch` with the content of the appropriate configuration file as a value of the `--long-config` argument. However, the default configuration does not work if the `cdc_mbim` driver is loaded. As a workaround, `/etc/usb_modeswitch.d/12d1:157d` file is created with `NoMBIMCheck=1` configuration option added: +``` +root@r1:~# cat /etc/usb_modeswitch.d/12d1:157d +# Huawei E3331, E3372 +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 +NoMBIMCheck=1 +root@r1:~# +``` +With the configuration above the `usb_modeswitch` called by `usb_modeswitch_dispatcher` makes the switch from `157d` to `14dc`: +``` +root@r1:~# lsusb -d 12d1: +Bus 003 Device 042: ID 12d1:14dc Huawei Technologies Co., Ltd. E33372 LTE/UMTS/GSM HiLink Modem/Networkcard +root@r1:~# +``` + +`udev` rule named `70-persistent-net.rules` ensures the `wan*`, `wwan*`, `lan*` and `wlan*` interfaces naming convention: +![ip_link_brief](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/ip_link_brief.jpg) + +Configuration files: [/etc/usb_modeswitch.d/12d1:157d](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/usb_modeswitch.d/12d1%3A157d), [/etc/udev/rules.d/70-persistent-net.rules](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/udev/rules.d/70-persistent-net.rules) + + +

:black_small_square: network config

+ +Telia's service works in a way that the Internet traffic is untagged and IPTV traffic is in the VLAN(IEEE 802.1q) 4. Router has a `wan0` interface for untagged Internet traffic and a VLAN interface named `wan0.4` for IPTV. Both interfaces receive the IPv4 address and netmask via DHCP. `wan0` will get a publicly routable IPv4 address and IPTV interface will get a private IPv4 address. In addition, several v4 routes are installed by DHCP. Few /24 publicly routable networks and the 10/8 are routed via the IPTV interface. Default route is via the Internet interface `wan0`. IPv6 part works in a way that Telia delegates a /56 prefix for LAN hosts from their /32 allocation using a DHCPv6. Internet facing interface will not get an IPv6 address and routing works using the IPv6 link local addresses: +``` +root@r1:~# ip -6 r sh default +default via fe80::200:5eff:fe00:1 dev wan0 proto ra metric 1024 expires 3372sec hoplimit 64 pref medium +root@r1:~# +``` + +Additionally, the `wan0` interface has a manually configured address of `192.168.1.200/24` for accessing the `Huawei MA5671A SFP ONT`. `dhclient` enter hook script named [get-static-ipv4-addrs](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs) and exit hook script named [restore-static-ipv4-addrs](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs) ensure that this address does not get flushed by `dhclient`. + +`lan*` and `wlan*` interfaces are part of the Linux bridge named `br0`: +``` +root@r1:~# bridge link +2: lan2: mtu 1500 master br0 state forwarding priority 32 cost 4 +3: lan3: mtu 1500 master br0 state disabled priority 32 cost 4 +4: lan1: mtu 1500 master br0 state disabled priority 32 cost 100 +6: lan0: mtu 1500 master br0 state disabled priority 32 cost 100 +47: wlan0: mtu 1500 master br0 state forwarding priority 32 cost 100 +root@r1:~# +``` +The `br0` interface has a manually configured IPv4 address `192.168.0.1/24`. IPv6 address on `br0` is managed by [dhclient exit hook script](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0). + +In addition, there is a `wwan0`(USB CDC Ethernet device) interface facing the Telia's mobile broadband network with static address of `192.168.8.200/24` and corresponding floating default route: +``` +root@r1:~# ip r sh default dev wwan0 +default via 192.168.8.1 metric 100 +root@r1:~# +``` +Switching the IPv4 connectivity to mobile network and back to fiber by adjusting the default routes metric is managed by [isp-switch](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/isp-switch.service) `systemd` service which calls the [isp-switch](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/sbin/isp-switch) script. IPv6 is not supported by Telia for the mobile broadband service. + +LAN hosts get the IPv4 address of the DNS server(`dnsmasq` running in the router) from DHCPv4 server(also `dnsmasq`). By default, the domain name server sent to DHCPv4 clients is set to the address of the interface running `dnsmasq` which is 192.168.0.1: +``` +root@r1:~# ip -4 --brief a sh dev br0 +br0 UP 192.168.0.1/24 +root@r1:~# +``` +IPv6 address of the DNS server(`dnsmasq` running in the router) is propagated by NDP "Router Advertisement" messages sent by `radvd`. RDNSS(Recursive DNS Server) statement in `radvd` configuration file `/etc/radvd.conf` is set automatically by the `dhclient` exit hook script [ipv6-pd-br0](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0). This script will use the IPv6 [link-local address](https://datatracker.ietf.org/doc/html/rfc8106#section-5.1)(found by `ip -6 a` or [mac_to_ip6_ll_addr](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/bin/mac_to_ip6_ll_addr) script) of the `br0` interface as a value for the `RDNSS` statement for `radvd`: +``` +root@r1:~# ip --brief -6 addr show dev br0 scope link +br0 UP fe80::a7:29ff:fea6:ec61/64 +root@r1:~# +root@r1:~# grep RDNSS /etc/radvd.conf + RDNSS fe80::a7:29ff:fea6:ec61 { }; +root@r1:~# +``` + +[nodnsupdate](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate) `dhclient` enter hook ensures that local [/etc/resolv.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/resolv.conf) is not overwritten by DHCP client. As a safety net, modifications of the [/etc/resolv.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/resolv.conf) were disabled with `chattr +i /etc/resolv.conf`: +``` +root@r1:~# lsattr /etc/resolv.conf +----i---------e---- /etc/resolv.conf +root@r1:~# +``` + +Configuration files and scripts: [/etc/network/interfaces](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/network/interfaces), [/etc/systemd/system/networking.service.d/override.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/networking.service.d/override.conf), [/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0), [/usr/local/bin/mac_to_ip6_ll_addr](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/bin/mac_to_ip6_ll_addr), [/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs), [/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs), [/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate), [/etc/dhcp/dhclient-enter-hooks.d/unset-dhcp-options](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-enter-hooks.d/unset-dhcp-options), [/etc/resolv.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/resolv.conf), [/etc/modprobe.d/bnx2x.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/modprobe.d/bnx2x.conf), [/etc/sysctl.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/sysctl.conf), [/etc/systemd/system/isp-switch.service](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/isp-switch.service), [/usr/local/sbin/isp-switch](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/sbin/isp-switch) + +

:black_small_square: iptables

+ +Notes on `iptables` and `ip6tables` rules: + +* `dhclient` in DHCPv4 mode uses raw sockets(fallback UDP socket for sending unicast packets is also opened) and thus no firewall rule is needed +* important ICMP messages like "frag needed" or "TTL exceeded" are accepted thanks to conntrack "RELATED" state match +* certain ICMP messages sent by the router including "Echo Reply" or "Destination Unreachable" are rate limited by adjusting the kernel parameters in [/etc/sysctl.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/sysctl.conf) +* `recent`(used in SSH chain) module internals are seen in the /proc/net/xt_recent/SSH file +* while `igmpproxy` is using raw sockets on the downstream interface, then in regard to upstream interface the `igmpproxy` simply acts as a normal multicast client(calls `setsockopt()` with IP_ADD_MEMBERSHIP) and thus there is a need to accept IGMP membership query messages sent by ISP. This also means that the IPTV UDP datagrams are sent towards the router application layer and dropped in the filter table INPUT chain. +* IGMP messages can not be tracked by the conntrack module. At least without an helper module. IGMP messages are sent to IPv4 multicast address and thus the `conntrack` module expects a reply sourced from a multicast address in order to move from UNREPLIED state to ESTABLISHED state. However, multicast address is never used as a src IP. +* `igmpproxy` subscribes to 224.0.0.2(IGMP "Leave group" messages) on a downstream interface and packets sent to this address are subject to INPUT chain rules. That's the reason for `-A INPUT -d 224.0.0.2/32 -i br0 -p igmp -j ACCEPT` rule. Details can be seen in [netfilter user mailinglist message](https://marc.info/?l=netfilter&m=168393431101974&w=2). +* dhclient in DHCPv6 mode is able to use ordinary UDP sockets thanks to link-local addresses and does not need to use raw sockets. This means that a firewall rule for DHCPv6 traffic is needed. +* ICMP6 "echo request" messages are rate limited by the `limit` module. Newer kernel versions have the `net.ipv6.icmp.ratemask` which would allow to rate limit the replies to "echo request" messages by adjusting the `net.ipv6.icmp.ratelimit`. ICMP6 "destination unreachable" messages are rate limited according to `net.ipv6.icmp.ratelimit`. +* important ICMP6 messages like "packet too big" or "time exceeded" or "destination unreachable" are accepted thanks to `conntrack` "RELATED" state match +* RA messages sent by radvd to `ff02::1` multicast addr via LAN-facing interface are looped back by the IP layer for local delivery. This is a default behavior and can be controlled by IPV6_MULTICAST_LOOP(`man 7 ipv6`). Those messages are dropped. + +Rules are loaded by `iptables-restore` and `ip6tables-restore` utilities before bringing the `br0` bridge interface up and after taking the `br0` interface down. This is configred in `/etc/network/interfaces` file. + +Configuration files: [/usr/local/etc/IPv4_fw_rules](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/etc/IPv4_fw_rules), [/usr/local/etc/IPv4_default_fw_rules](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/etc/IPv4_default_fw_rules), [/usr/local/etc/IPv6_fw_rules](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/etc/IPv6_fw_rules), [/usr/local/etc/IPv6_default_fw_rules](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/etc/IPv6_default_fw_rules) + +

:black_small_square: dnsmasq

+ +As `dnsmasq` is configured with `interface=br0` and `bind-interfaces`, then `setsockopt()` with `SO_BINDTODEVICE` option is called by `dnsmasq` when started and socket is bound to a `br0` interface. [Under the hood](https://github.com/torvalds/linux/blob/ba0ad6ed89fd5dada3b7b65ef2b08e95d449d4ab/net/core/sock.c#L667), the socket is bound to an ifindex of `br0` interface. As restarting the `networking.service` deletes and recreates the network bridge `br0` and the new `br0` has an [incremented ifindex](https://github.com/torvalds/linux/blob/80e62bc8487b049696e67ad133c503bf7f6806f7/net/core/dev.c#L9553), then `dnsmasq.service` has to be restarted if the `networking.service` is restarted: +``` +root@r1:~# systemctl show dnsmasq | grep PartOf= +PartOf=networking.service +root@r1:~# +root@r1:~# systemctl show networking | grep ConsistsOf= +ConsistsOf=hostapd.service igmpproxy.service dnsmasq.service +root@r1:~# +``` + +`dnsmasq` is configured not to read `/etc/resolv.conf` and use the upstream DNS servers specified in its configuration file: +``` +root@r1:~# grep ^server /etc/dnsmasq.conf +server=2620:fe::fe +server=2620:fe::9 +server=9.9.9.9 +server=149.112.112.112 +root@r1:~# +``` +Configuration files: [/etc/dnsmasq.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dnsmasq.conf), [/etc/systemd/system/dnsmasq.service.d/override.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/dnsmasq.service.d/override.conf) + +

:black_small_square: radvd

+ +`radvd` configuration and necessary reloads for activating the configuration is automatically handled by [dhclient exit hook script](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0) and [expired prefixes removal script](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/sbin/rm-expired-prefixes) executed by `cron` at every minute. + +The general idea is that it's needed to keep advertising the prefixes with no valid or preferred lifetime left towards LAN at least as long as the last non-zero valid lifetime of the prefix in order to ensure that all the hosts in LAN pick up the prefix deprecation. Such setup ensures that the prefix deprecation is seen even by devices which were for example in suspended to RAM state at the time of the delegated prefix change. + +For each "prefix" statement in radvd.conf file the script finds a timestamp in the future when this prefix could be removed from the radvd.conf file in order to avoid stale entries. + +Example of `/etc/radvd.conf`: +![radvd_conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/radvd_conf.jpg) + +Scripts: [/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0), [/usr/local/sbin/rm-expired-prefixes](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/usr/local/sbin/rm-expired-prefixes) + +

:black_small_square: igmpproxy

+ +[Patched](https://github.com/tonusoo/koduinternet-cpe/blob/main/code/igmpproxy.patch)(issue [#95](https://github.com/pali/igmpproxy/issues/95)) version of `igmpproxy` is installed. [igmpproxy_0.2.1-1+relaxed-timeout1_amd64.deb](https://github.com/tonusoo/koduinternet-cpe/blob/main/igmpproxy_0.2.1-1%2Brelaxed-timeout1_amd64.deb) package was built with commands below: +1. `apt source igmpproxy` +2. `cd igmpproxy-0.2.1/` +3. `patch --verbose src/igmpproxy.c ~/koduinternet-cpe/code/igmpproxy.patch` +4. `dch --local +relaxed-timeout` with "relaxed pselect() timeout in main loop" note for the changelog +5. `cd . && dpkg-buildpackage -b` + +Package can be installed with `dpkg -i igmpproxy_0.2.1-1+relaxed-timeout1_amd64.deb` and `apt-mark hold igmpproxy` prevents the package from being automatically upgraded. + +Restarting the `networking.service` will call the `/lib/bridge-utils/ifupdown.sh` script which deletes(`brctl delbr ..`) and recreates(`brctl addbr ..`) the network bridge `br0`. However, the new `br0` interface will have an incremented ifindex(`cat /sys/class/net/br0/ifindex` or `ip l sh dev br0`) and thus the `setsockopt()` calls by `igmpproxy` will fail. Example where interface with ifindex 17(21 in octal) no longer existst: +``` +setsockopt(3, SOL_IP, IP_MULTICAST_IF, "\217U\0\0\300\250\0\1\21\0\0\0", 12) = -1 EADDRNOTAVAIL (Cannot assign requested address) +``` +That's the reason why `igmpproxy.service` is configured to be restarted if `networking.service` is restarted: +``` +root@r1:~# systemctl show igmpproxy | grep PartOf= +PartOf=networking.service +root@r1:~# +root@r1:~# systemctl show networking | grep ConsistsOf= +ConsistsOf=hostapd.service igmpproxy.service dnsmasq.service +root@r1:~# +``` + +As an example, here is the multicast routing table(populated by `igmpproxy`) and switch multicast group membership table(populated by IGMP snooping) at the time when host connected to `lan0` is running `mplayer -vf yadif -volume 80 -fs -ao pulse udp://@239.3.1.106:1234`: +``` +root@r1:~# ip mroute +(10.0.2.28,239.3.1.106) Iif: wan0.4 Oifs: br0 State: resolved +root@r1:~# +root@r1:~# bridge -s mdb +33: br0 lan0 239.3.1.106 temp 251.57 +root@r1:~# +``` + +IGMP snooping is enabled by default: +``` +root@r1:~# cat /sys/devices/virtual/net/br0/bridge/multicast_snooping +1 +root@r1:~# +``` +`force_igmp_version` for `wan0.4` is not touched, i.e it's in IGMPv3 mode and falls back to IGMPv1/v2 mode if needed. + +Configuration files: [/etc/igmpproxy.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/igmpproxy.conf), [/etc/systemd/system/igmpproxy.service.d/override.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/igmpproxy.service.d/override.conf) + +

:black_small_square: NTP config

+ +By default, the `dhclient` `/etc/dhcp/dhclient-exit-hooks.d/timesyncd` script builds the `/run/systemd/timesyncd.conf.d/01-dhclient.conf` configuration file for `systemd-timesyncd` SNTP client and instructs it to use the NTP servers provided by Telia's DHCP server. Instead, the default Debian NTP pool compiled to `systemd-timesyncd` is used by creating a `/etc/systemd/timesyncd.conf.d/01-dhclient.conf` symlink pointing to `/dev/null`. Output of `timedatectl`: + +![timedatectl output](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/timedatectl_output.jpg) + + +

:black_small_square: hostapd

+ +`Asus PCE-AC88`(`Broadcom BCM4366/4` SoC) WNIC is configured to work as `IEEE 802.11a/n/ac` AP. For the `IEEE 802.11ac` mode, the channel width is up to 80 MHz(5170 - 5250 MHz). `hostapd` adds the WNIC named `wlan0` to bridge `br0`. Connectivity between the Wi-Fi clients is allowed. Output of [hostapd_cli](https://manpages.debian.org/testing/hostapd/hostapd_cli.1.en.html) `status` and `get_config` commands can be seen below: + +![hostapd_cli_output](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/hostapd_cli_output.jpg) + +Firmware blob loaded by `brcmfmac` driver is `brcmfmac4366c-pcie.bin`: +``` +root@r1:~# md5sum /lib/firmware/brcm/brcmfmac4366c-pcie.bin +e3bb4457082aa54769253e9168db2269 /lib/firmware/brcm/brcmfmac4366c-pcie.bin +root@r1:~# +root@r1:~# strings /lib/firmware/brcm/brcmfmac4366c-pcie.bin | tail -1 +4366c0-roml/pcie-ag-splitrx-fdap-mbss-mfp-wnm-osen-wl11k-wl11u-txbf-pktctx-amsdutx-ampduretry-chkd2hdma-proptxstatus-11nprop-obss-dbwsw-ringer-dmaindex16-bgdfs-murx-wwdfs Version: 10.28.2 (r769115) CRC: 6924533a Date: Mon 2018-11-05 03:22:36 PST Ucode Ver: 1128.17924 FWID: 01-d2cbb8fd +root@r1:~# +``` +This is provided by `firmware-brcm80211` package, but the same firmware version can also be downloaded from [Linux kernel git repo](https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/tree/brcm/brcmfmac4366c-pcie.bin): +``` +root@r1:~# curl -s https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/brcm/brcmfmac4366c-pcie.bin | md5sum +e3bb4457082aa54769253e9168db2269 - +root@r1:~# +``` +For firmware related troubleshooting purposes, the `brcmfmac` driver can be loaded with `modprobe -v brcmfmac debug=0x1416` when built with debugging support: + +![brcmfmac_with_debug_functions](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/brcmfmac_with_debug_functions.jpg) + +Configuration files: [/etc/hostapd/hostapd.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/hostapd/hostapd.conf), [/etc/systemd/system/hostapd.service.d/override.conf](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/systemd/system/hostapd.service.d/override.conf) + +

:black_small_square: Linux PAM config

+ +Diff with `Debian 10` default Linux PAM `common-auth` enabling 2FA(user password and OTP): +``` +root@r1:~# diff -u /etc/pam.d/common-auth{~,} +--- /etc/pam.d/common-auth~ 2023-06-01 21:22:43.894184345 +0300 ++++ /etc/pam.d/common-auth 2023-06-01 21:48:15.777645409 +0300 +@@ -13,8 +13,16 @@ + # pam-auth-update to manage selection of other modules. See + # pam-auth-update(8) for details. + ++# If pam_yubico.so returns PAM_SUCCESS, then pam_google_authenticator.so is skipped. ++# All other return codes are ignored and pam_google_authenticator.so is used. ++# pam_yubico.so has "forward_pass"(pam_set_item(pamh, PAM_AUTHTOK, onlypasswd)) enabled by default. ++auth [success=1 default=ignore] pam_yubico.so id=12345 authfile=/etc/authorized_yubikeys urllist=https://api.yubico.com/wsapi/2.0/verify ++ ++# pam_google_authenticator.so is able to detect if user password is entered before TOTP. ++auth required pam_google_authenticator.so forward_pass ++ + # here are the per-package modules (the "Primary" block) +-auth [success=1 default=ignore] pam_unix.so nullok_secure ++auth [success=1 default=ignore] pam_unix.so nullok_secure try_first_pass + # here's the fallback if no module succeeds + auth requisite pam_deny.so + # prime the stack with a positive return value if there isn't one already; +root@r1:~# +``` +YubiKeys token IDs are mapped to username in `/etc/authorized_yubikeys` file. `$HOME/.google_authenticator` is created by `google-authenticator` utility and it includes the secret key, emergency scratch codes, rate-limit configuration, etc. SSH keyboard interactive authentication is enabled in `/etc/ssh/sshd_config` by changing the value of `ChallengeResponseAuthentication` to `yes`. + +Configuration files: [/etc/pam.d/common-auth](https://github.com/tonusoo/koduinternet-cpe/blob/main/conf/etc/pam.d/common-auth) + +

:small_blue_diamond: Hardware mods

+

:black_small_square: Replacing the Dell N20KJ stock fan with Noctua NF-A4x10 fan

+ +Stock `ADDA AD0412HB-K96` fan was replaced with silent, `Noctua NF-A4x10` fan: + +![Dell N20KJ with NF-A4x10 fan](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/Dell_N20KJ_with_NF-A4x10_fan.jpg) + +`Noctua NF-A4x10` is connected to motherboard chassis fan connector where it is picked up by `lm-sensors`: + +![NIC fan RPM by lm-sensors](https://github.com/tonusoo/koduinternet-cpe/blob/main/imgs/NIC_fan_RPM_by_lm-sensors.jpg) + +`Dell N20KJ` fan fault detection was disabled in `eDiag` engineering mode(`ediag_x64.efi -b10eng`) with commands below: +``` +nvm cfg +option 4 (board i/o) +83=1 (disabled) +save +exit +``` + +

:small_blue_diamond: Acknowledgements

+ +Users [upnatom](https://www.dslreports.com/profile/1426739) and [JAMESMTL](https://www.dslreports.com/profile/1901978) in [DSLReports forum](https://www.dslreports.com/forums/all) ["Bypassing the HH3K up to 2.5Gbps using a BCM57810S NIC"](https://www.dslreports.com/forum/r32230041-Internet-Bypassing-the-HH3K-up-to-2-5Gbps-using-a-BCM57810S-NIC) thread. +User **anon23891239** and others in [OpenWRT forum](https://forum.openwrt.org/) ["Support MA5671A SFP GPON"](https://forum.openwrt.org/t/support-ma5671a-sfp-gpon/48042/) thread. [README](https://github.com/tonusoo/koduinternet-cpe/blob/main/README.md) is inspired by ["Human-Activity-Recognition"](https://github.com/ma-shamshiri/Human-Activity-Recognition) repo. + +

:small_blue_diamond: License

+ +[MIT License](https://github.com/tonusoo/koduinternet-cpe/blob/main/LICENSE) diff --git a/conf/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs b/conf/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs new file mode 100644 index 0000000..16680df --- /dev/null +++ b/conf/etc/dhcp/dhclient-enter-hooks.d/get-static-ipv4-addrs @@ -0,0 +1,49 @@ +# Title : get-static-ipv4-addrs +# Last modified date : 11.02.2023 +# Author : Martin Tonusoo +# Description : Finds the permanent IPv4 addresses configured on the +# interface and stores those to a variable, which is later +# processed by dhclient restore-static-ipv4-addrs exit +# hook script. +# For example, in case the leased IPv4 address changes or the IPv4 +# address is released by the client(dhclient -r) or the lease +# expires, then dhclient-script called by dhclient flushes all +# the IPv4 addresses configured on the interface. This includes +# IPv4 addresses defined in /etc/network/interfaces or conf +# files in interfaces.d directory. This script finds the non-dynamic +# IPv4 addresses configured on the interface and populates the +# "perm_addrs" variable. Exit hook "restore-static-ipv4-addrs" adds +# those addresses back to interface based on the content of the +# "perm_addrs" variable. +# Options : +# Notes : Script is meant to be run as a dhclient enter hook. +# Script is POSIX sh compliant. +# +# Routes and aliases("ALIAS DECLARATIONS" in dhclient.conf man) +# are not touched. +# +# Dhclient-script called by dhclient binary always adds IPv4 addresses +# to non-alias interface with "valid_lft" and "preferred_lft" set +# which results with a "dynamic" flag set in the output of "ip addr". +# +# This script can't help in case the manually configured address is +# from the same network as the address leased by the DHCP server AND +# the manually configured address is a secondary one- if the dynamic +# primary address expires, then both the dynamic primary and all +# the secondary manually configured addresses are removed by the +# kernel automatically. + +perm_addrs="" + +while read -r _ _ _ perm_addr _; do + + # Sanity check. + case "$perm_addr" in + *.*.*.*/*) + perm_addrs="$perm_addrs $perm_addr" + ;; + esac + +done <<-EOF + $(ip -oneline -4 addr show dev "$interface" permanent label "$interface" 2>/dev/null) +EOF diff --git a/conf/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate b/conf/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate new file mode 100644 index 0000000..1fbdb04 --- /dev/null +++ b/conf/etc/dhcp/dhclient-enter-hooks.d/nodnsupdate @@ -0,0 +1,8 @@ +# make_resolv_conf() function in /sbin/dhclient-script updates +# /etc/resolv.conf based on received values. This is a dummy version +# of this function in order to ensure that /etc/resolv.conf is +# not touched by dhclient. +# In addition, "chattr +i /etc/resolv.conf" was set. +make_resolv_conf() { + true +} diff --git a/conf/etc/dhcp/dhclient-enter-hooks.d/unset-dhcp-options b/conf/etc/dhcp/dhclient-enter-hooks.d/unset-dhcp-options new file mode 100644 index 0000000..d1123ca --- /dev/null +++ b/conf/etc/dhcp/dhclient-enter-hooks.d/unset-dhcp-options @@ -0,0 +1,8 @@ +# Host Name (Option 12) +unset new_host_name + +# Interface MTU (Option 26) +unset new_interface_mtu + +# Domain Search (Option 119) +unset new_domain_search diff --git a/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0 b/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0 new file mode 100644 index 0000000..96917b5 --- /dev/null +++ b/conf/etc/dhcp/dhclient-exit-hooks.d/ipv6-pd-br0 @@ -0,0 +1,432 @@ +# Title : ipv6-pd-br0 +# Last modified date : 26.03.2023 +# Author : Martin Tonusoo +# Description : Script finds the /64 IPv6 network by combining the +# /56 prefix delegated by Telia(from 2001:7d0::/32 +# allocation) and value of "ip6_net" variable. First +# address of this /64 network is added to a port +# specified by "ia_pd_iface" variable or removed +# from this interface depending on the DHCPv6 +# event. In addition, radvd configuration file +# is updated accordingly. +# Options : +# Notes : Script is meant to be run as a dhclient exit hook. +# +# Script expects a single dhclient instance +# in DHCPv6 mode, i.e it is not tested for +# possible race conditions which might occur +# if multiple "dhclient -6 ..." instances +# are running at once. +# +# Script is POSIX sh compliant except the variables +# declared to be local to functions. Coding style +# is based on /usr/sbin/dhclient-script. +# +# Initially based on script seen here: +# https://wiki.debian.org/IPv6PrefixDelegation + + +ia_pd_iface="br0" + + +# Values from 00 to ff. +ip6_net="00" + + +find_ia_pd_addr() { + + local h h1 h2 h3 h4 ip6_prefix + + # According to technical service description, + # Telia delegates a /56 prefix from their + # 2001:7d0::/32 allocation. This function takes + # the delegated /56 prefix as an input, combines + # it with the value of ip6_net variable and + # returns a RFC5952(A Recommendation for IPv6 + # Address Text Representation) compatible /64 prefix. + + + # Explode the possibly compressed IPv6 prefix. + + IFS=: read -r h1 h2 h3 h4 _ <<-EOF + ${1%/56} + EOF + + ip6_prefix="" + for h in "$h1" "$h2" "${h3:-0}" "${h4:-0}"; do + ip6_prefix="$ip6_prefix"$(printf "%04x:" "0x$h") + done + + ip6_prefix="${ip6_prefix%[[:xdigit:]][[:xdigit:]]:}$ip6_net::/64" + + + # Convert the exploded IPv6 prefix back to RFC5952 + # compatible compressed format. + + IFS=: read -r h1 h2 h3 h4 _ <<-EOF + $ip6_prefix + EOF + + # In case both the third and fourth hextet + # is all zeros, then simply do not show those + # in the final output. + if [ "$h3" = "0000" ] && [ "$h4" = "0000" ]; then + h3="" + h4="" + fi + + ip6_prefix="" + for h in "$h1" "$h2" "$h3" "$h4"; do + [ -z "$h" ] && continue + ip6_prefix="$ip6_prefix"$(printf "%x:" "0x$h") + done + + echo "$ip6_prefix:/64" + +} + + +get_prefix_rm_time() { + + local valid_lft="$1" + local unix_time rm_unix_time + + unix_time=$(date +%s) + + # Sanity check. Ensure that $valid_lft is an int. + case "$valid_lft" in + ""|*[!0-9]*) + rm_unix_time="$unix_time" + ;; + *) + rm_unix_time=$(( unix_time + valid_lft )) + ;; + esac + + date --iso-8601="seconds" -d @"$rm_unix_time" + +} + + +get_ip6_ll_addr() { + + local iface="$1" + local mac_addr ll_prefix + + # Pick the first link local IPv6 address. + read -r _ _ ll_prefix _ <<-EOF + $(ip --brief -6 addr show dev "$iface" scope link 2>/dev/null) + EOF + + if [ -n "$ll_prefix" ]; then + + echo "${ll_prefix%/*}" + + elif [ -x "$(PATH=$PATH:/usr/local/bin/ command -v mac_to_ip6_ll_addr)" ]; then + + # As it's possible that the interface is for example in the administratively + # disabled state and thus does not have the automatically found link local + # address set, then use the external script which is able to calculate the + # IPv6 link local address based on the MAC address. + read -r _ _ mac_addr _ <<-EOF + $(ip --brief link show dev "$iface" 2>/dev/null) + EOF + + PATH="$PATH:/usr/local/bin/" mac_to_ip6_ll_addr "$mac_addr" + fi + +} + + +# Function creates an initial Router Advertisement +# Daemon(radvd) configuration file /etc/radvd.conf +# if it does not exist or updates the prefix and +# RDNSS(Recursive DNS Server) statements based on +# DHCPv6 updates in case the /etc/radvd.conf is +# present. Preferred and valid lifetime of the prefix +# set by Telia's DHCPv6 server(s) are propagated +# towards LAN by radvd. +# +# It's needed to keep advertising the prefixes with +# no valid or preferred lifetime left towards LAN at +# least as long as the last non-zero valid lifetime +# of the prefix in order to ensure that all the +# hosts in LAN pick up the prefix deprecation. Such +# setup ensures that the prefix deprecation is seen +# even by devices which were for example in suspended +# to RAM state at the time of the delegated prefix change. +# +# For each "prefix" statement in radvd.conf file the +# function finds a timestamp in the future when this +# prefix could be removed from the radvd.conf file +# in order to avoid stale entries. Prefixes removal +# from radvd.conf are handled by another script +# running in cron as this should not be coupled with +# dhclient. +# +# RDNSS definition is overwritten with a link-local +# address of the interface where the /64 address is +# added. The link-local address is found automatically +# because this interface could be a bridge and depending +# on the kernel version the bridge interface MAC address +# changes depending on its member interfaces. This in +# turn can cause the IPv6 link local address to change. +# +# According to RFC8106 section 5.1 the addresses for +# RDNSSes in the RDNSS option MAY be link-local addresses. +# Tested with Debian 11 host running rdnssd ver 1.0.4. +# +# Function is based on make_resolv_conf() in +# /sbin/dhclient-script. +make_radvd_conf() { + + local prefix="$1" + local preferred_lft="$2" + local valid_lft="$3" + local ll_addr radvd_conf new_radvd_conf line option value prefix_rm_time prefix_found + + ll_addr=$(get_ip6_ll_addr "$ia_pd_iface") + + radvd_conf=$(readlink -f "/etc/radvd.conf" 2>/dev/null) || + radvd_conf="/etc/radvd.conf" + + prefix_rm_time=$(get_prefix_rm_time "$valid_lft") + + if [ -f "$radvd_conf" ]; then + + new_radvd_conf="${radvd_conf}.dhclient-new.$$" + wait_for_rw "$new_radvd_conf" + rm -f "$new_radvd_conf" + + prefix_found="" + while IFS= read -r line; do + + case "$line" in + " RDNSS "*) + printf " RDNSS %s { };\n" "$ll_addr" + ;; + " prefix $prefix {"*) + + if [ "$valid_lft" = "0" ]; then + + IFS=" ;" read -r _ _ _ option value _ <<-EOF + $line + EOF + + if [ "$option" = "AdvValidLifetime" ]; then + # If the value of AdvValidLifetime was already 0, then + # keep using the old expiration field. + if [ "$value" = "0" ]; then + prefix_rm_time="${line##* }" + else + prefix_rm_time=$(get_prefix_rm_time "$value") + fi + fi + fi + + printf " prefix %s { AdvValidLifetime %s; AdvPreferredLifetime %s; }; # expires at %s\n" \ + "$prefix" \ + "$valid_lft" \ + "$preferred_lft" \ + "$prefix_rm_time" + prefix_found="yes" + ;; + "};") + if [ -z "$prefix_found" ]; then + + # Last line of the conf file AND prefix was not found. Add the new prefix. + printf " prefix %s { AdvValidLifetime %s; AdvPreferredLifetime %s; }; # expires at %s\n%s\n" \ + "$prefix" \ + "$valid_lft" \ + "$preferred_lft" \ + "$prefix_rm_time" \ + "};" + else + echo "};" + fi + ;; + *) + echo "$line" + ;; + esac + + done < "$radvd_conf" >>"$new_radvd_conf" + + chown --reference="$radvd_conf" "$new_radvd_conf" + chmod --reference="$radvd_conf" "$new_radvd_conf" + mv -f "$new_radvd_conf" "$radvd_conf" + + else + # Build the initial radvd configuration. + cat <<-EOF > "$radvd_conf" + # Generated by ipv6-pd-br0 dhclient exit hook. + interface $ia_pd_iface + { + # Send RA messages. + AdvSendAdvert on; + MinRtrAdvInterval 60; + MaxRtrAdvInterval 180; + RDNSS $ll_addr { }; + prefix $prefix { AdvValidLifetime $valid_lft; AdvPreferredLifetime $preferred_lft; }; # expires at $prefix_rm_time + }; + EOF + fi + + # Reload the radvd if it is already running. + # This will immediately send a Router Advertisement + # to hosts in LAN. + if systemctl is-active --quiet radvd.service; then + systemctl reload radvd.service 2>/dev/null + fi +} + + +# Only execute on specific occasions +case "$reason" in + BOUND6|EXPIRE6|REBIND6|REBOOT6|RENEW6|RELEASE6|STOP6|DEPREF6) + + # Only execute if either an old or a new or a current prefix is defined + if [ -n "$old_ip6_prefix" ] || [ -n "$new_ip6_prefix" ] || [ -n "$cur_ip6_prefix" ]; then + # Check if interface is defined and exits + if [ -z "$ia_pd_iface" ] || [ ! -e "/sys/class/net/${ia_pd_iface}" ]; then + logger -t "ipv6-pd-br0" -p daemon.err \ + "$reason - ERROR: Interface ${ia_pd_iface:-} not found." + else + + # Remove old prefix if it differs from new prefix or the valid + # lifetime of the new prefix is 0. + if { [ -n "$old_ip6_prefix" ] && [ "$old_ip6_prefix" != "$new_ip6_prefix" ]; } || + { [ -n "$new_max_life" ] && [ "$new_max_life" -eq 0 ]; }; then + + old_ia_pd_addr=$(find_ia_pd_addr "$old_ip6_prefix") + + while read -r error_message; do + case "$error_message" in + "") + logger -t "ipv6-pd-br0" -p daemon.info \ + "$reason - INFO: Deleted old address $old_ia_pd_addr from interface $ia_pd_iface." + ;; + "RTNETLINK answers: Cannot assign requested address") + logger -t "ipv6-pd-br0" -p daemon.info \ + "$reason - INFO: Address $old_ia_pd_addr already deleted from interface $ia_pd_iface." + ;; + *) + logger -t "ipv6-pd-br0" -p daemon.err \ + "$reason - ERROR: Failed to delete old address $old_ia_pd_addr from interface $ia_pd_iface." + esac + + done <<-EOF + $(ip -6 addr del "$old_ia_pd_addr" dev "$ia_pd_iface" scope global 2>&1) + EOF + + # At this point, the address should be removed from the LAN-facing interface + # and the hosts in LAN will soon receive an RA with prefix AdvValidLifetime and + # AdvPreferredLifetime both set to zero. + # + # While the hosts will adjust the preferred lifetime accordingly, then the + # valid lifetime update will be ignored(RFC 4862 Section 5.5.3 point e) and + # this means that hosts can still be using addresses from the old prefix + # for existing connections. + # + # While at least in newer kernels deleting an IPv6 address with a + # non-forever valid lifetime does not remove the route from + # the routing table, then it is likely that LAN hosts valid lifetime + # is higher than the lifetime of the connected route in the router + # because radvd messages are not in sync with dhclient events. + # + # So regardless whether the ISP keeps routing the packets destined to + # addresses from the old prefix, then make sure, that this router is + # not dropping those packets. Thus, update the connected route expiration + # counter with the value of the old valid lifetime of the address. This + # ensures that the connected route is present and it will expire after the + # addresses on LAN hosts. + if [ -n "$old_max_life" ] && [ "$old_max_life" -gt 0 ]; then + ip -6 route replace "$old_ia_pd_addr" dev "$ia_pd_iface" \ + expires "$old_max_life" >/dev/null 2>&1 + fi + + # Inform the downstream clients, that the prefix is no longer valid. + make_radvd_conf "$old_ia_pd_addr" 0 0 + fi + + + # Assign new prefix + if [ -n "$new_ip6_prefix" ] && [ "$new_max_life" -ne 0 ]; then + + new_ia_pd_addr=$(find_ia_pd_addr "$new_ip6_prefix") + + # "ip -6 addr replace ..." adds the address if it's + # missing or updates the valid and preferred lifetime + # counters of the address if the address is already + # configured. + # Adding an IPv6 address with a non-forever valid lifetime + # creates a temporary connected route which has "expires" + # counter with a value equal to valid lifetime of the address. + # At least in newer kernels deleting IPv6 address with a + # non-forever valid lifetime does not remove the route from + # the routing table. The route will expire automatically when + # its expiration counter reaches 0. + if ip -6 addr replace "$new_ia_pd_addr" \ + ${new_max_life:+valid_lft "$new_max_life"} \ + ${new_preferred_life:+preferred_lft "$new_preferred_life"} \ + dev "$ia_pd_iface" >/dev/null 2>&1; then + + logger -t "ipv6-pd-br0" -p daemon.info \ + "$reason - INFO: Added/updated address $new_ia_pd_addr on interface $ia_pd_iface." + else + + logger -t "ipv6-pd-br0" -p daemon.err \ + "$reason - ERROR: Failed to add/update address $new_ia_pd_addr on interface $ia_pd_iface." + fi + + make_radvd_conf "$new_ia_pd_addr" "$new_preferred_life" "$new_max_life" + fi + + + # Handle DEPREF6 similarly to dhclient-script by configuring + # the preferred lifetime of the IP from leased prefix to 0. + # Do not change the valid lifetime. + if [ "$reason" = "DEPREF6" ] && [ -n "$cur_ip6_prefix" ]; then + + cur_ia_pd_addr=$(find_ia_pd_addr "$cur_ip6_prefix") + + # Find the value of valid_lft. Unit of valid_lft is always "sec". + cur_valid_life=$(ip -oneline -6 addr show dev "$ia_pd_iface" to "$cur_ia_pd_addr" 2>/dev/null) + cur_valid_life="${cur_valid_life##*valid_lft }" + cur_valid_life="${cur_valid_life%%sec *}" + + if [ -n "$cur_valid_life" ] && [ "$cur_valid_life" -gt 0 ]; then + + # If one does not specify the value for "valid_lft", then + # it defaults to "forever". + if ip -6 addr change "$cur_ia_pd_addr" \ + dev "$ia_pd_iface" scope global \ + valid_lft "$cur_valid_life" \ + preferred_lft 0 >/dev/null 2>&1; then + + logger -t "ipv6-pd-br0" -p daemon.info \ + "$reason - INFO: Changed the preferred lifetime of $cur_ia_pd_addr on interface $ia_pd_iface to 0." + else + + logger -t "ipv6-pd-br0" -p daemon.err \ + "$reason - ERROR: Failed to change the preferred lifetime of $cur_ia_pd_addr on interface $ia_pd_iface to 0." + fi + + make_radvd_conf "$cur_ia_pd_addr" 0 "$cur_valid_life" + else + # Address was already removed or the valid lifetime was 0. + # Ensure, that the radvd gets configured accordingly. + make_radvd_conf "$cur_ia_pd_addr" 0 0 + fi + + # Ensure that the connected route is present and it will expire after the + # addresses on LAN hosts. + if [ -n "$cur_max_life" ] && [ "$cur_max_life" -gt 0 ]; then + ip -6 route replace "$cur_ia_pd_addr" dev "$ia_pd_iface" \ + expires "$cur_max_life" >/dev/null 2>&1 + fi + fi + fi + fi + ;; +esac diff --git a/conf/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs b/conf/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs new file mode 100644 index 0000000..fb5db7e --- /dev/null +++ b/conf/etc/dhcp/dhclient-exit-hooks.d/restore-static-ipv4-addrs @@ -0,0 +1,13 @@ +# Title : restore-static-ipv4-addrs +# Last modified date : 11.02.2023 +# Author : Martin Tonusoo +# Description : Restores the permanent IPv4 addresses stored in a +# variable, which was populated by get-static-ipv4-addrs +# dhclient enter hook. +# Options : +# Notes : Script is meant to be run as a dhclient exit hook. +# Script is POSIX sh compliant. + +for perm_addr in $perm_addrs; do + ip -4 addr add "$perm_addr" dev "$interface" >/dev/null 2>&1 || true +done diff --git a/conf/etc/dhcp/dhclient.conf b/conf/etc/dhcp/dhclient.conf new file mode 100644 index 0000000..aa43ae9 --- /dev/null +++ b/conf/etc/dhcp/dhclient.conf @@ -0,0 +1,30 @@ +# Option declaration below is needed for understanding the +# "Classless Static Route"(code 121) option sent by the +# DHCP server in Telia IPTV VLAN and also for requesting +# this option. +option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; + +send host-name = gethostname(); +retry 60; + +# At least in Internet VLAN, the Telia's DHCP servers seem +# to ignore the options requested by the DHCP client. For +# example in case of ISC DHCP server this can be configured +# with "dhcp-parameter-request-list" option. +# +# Request the dhclient sane defaults plus "Classless Static Route". +# +# DHCP server in IPTV VLAN returns both the "Router"(3) +# and "Classless Static Route"(121) options. This is +# not an issue as according to RFC3442 "If the DHCP server +# returns both a Classless Static Routes option and a +# Router option, the DHCP client MUST ignore the Router +# option". This can be confirmed by analyzing the dhclient-script +# source. +also request rfc3442-classless-static-routes; + +# Override certain DHCP options with locally-configured values. +# In addition, some DHCP options which might have a meaning for +# dhclient-script, are unset in unset-dhcp-options enter hook +# script. +supersede domain-name "lan"; diff --git a/conf/etc/dnsmasq.conf b/conf/etc/dnsmasq.conf new file mode 100644 index 0000000..4b98c12 --- /dev/null +++ b/conf/etc/dnsmasq.conf @@ -0,0 +1,683 @@ +# Configuration file for dnsmasq. +# +# Format is one option per line, legal options are the same +# as the long options legal on the command line. See +# "/usr/sbin/dnsmasq --help" or "man 8 dnsmasq" for details. + +# Listen on this specific port instead of the standard DNS port +# (53). Setting this to zero completely disables DNS function, +# leaving only DHCP and/or TFTP. +#port=5353 + +# The following two options make you a better netizen, since they +# tell dnsmasq to filter out queries which the public DNS cannot +# answer, and which load the servers (especially the root servers) +# unnecessarily. If you have a dial-on-demand link they also stop +# these requests from bringing up the link unnecessarily. + +# Never forward plain names (without a dot or domain part) +#domain-needed +# Never forward addresses in the non-routed address spaces. +#bogus-priv + +# Uncomment these to enable DNSSEC validation and caching: +# (Requires dnsmasq to be built with DNSSEC option.) +#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf +#dnssec + +# Replies which are not DNSSEC signed may be legitimate, because the domain +# is unsigned, or may be forgeries. Setting this option tells dnsmasq to +# check that an unsigned reply is OK, by finding a secure proof that a DS +# record somewhere between the root and the domain does not exist. +# The cost of setting this is that even queries in unsigned domains will need +# one or more extra DNS queries to verify. +#dnssec-check-unsigned + +# Uncomment this to filter useless windows-originated DNS requests +# which can trigger dial-on-demand links needlessly. +# Note that (amongst other things) this blocks all SRV requests, +# so don't use it if you use eg Kerberos, SIP, XMMP or Google-talk. +# This option only affects forwarding, SRV records originating for +# dnsmasq (via srv-host= lines) are not suppressed by it. +#filterwin2k + +# Change this line if you want dns to get its upstream servers from +# somewhere other that /etc/resolv.conf +#resolv-file= + +# By default, dnsmasq will send queries to any of the upstream +# servers it knows about and tries to favour servers to are known +# to be up. Uncommenting this forces dnsmasq to try each query +# with each server strictly in the order they appear in +# /etc/resolv.conf +#strict-order + +# If you don't want dnsmasq to read /etc/resolv.conf or any other +# file, getting its servers from this file instead (see below), then +# uncomment this. +no-resolv + +# If you don't want dnsmasq to poll /etc/resolv.conf or other resolv +# files for changes and re-read them then uncomment this. +#no-poll + +# Add other name servers here, with domain specs if they are for +# non-public domains. +#server=/localnet/192.168.0.1 +server=2620:fe::fe +server=2620:fe::9 +server=9.9.9.9 +server=149.112.112.112 + +# Example of routing PTR queries to nameservers: this will send all +# address->name queries for 192.168.3/24 to nameserver 10.1.2.3 +#server=/3.168.192.in-addr.arpa/10.1.2.3 + +# Add local-only domains here, queries in these domains are answered +# from /etc/hosts or DHCP only. +#local=/localnet/ + +# Add domains which you want to force to an IP address here. +# The example below send any host in double-click.net to a local +# web-server. +#address=/double-click.net/127.0.0.1 + +# --address (and --server) work with IPv6 addresses too. +#address=/www.thekelleys.org.uk/fe80::20d:60ff:fe36:f83 + +# Add the IPs of all queries to yahoo.com, google.com, and their +# subdomains to the vpn and search ipsets: +#ipset=/yahoo.com/google.com/vpn,search + +# You can control how dnsmasq talks to a server: this forces +# queries to 10.1.2.3 to be routed via eth1 +# server=10.1.2.3@eth1 + +# and this sets the source (ie local) address used to talk to +# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that +# IP on the machine, obviously). +# server=10.1.2.3@192.168.1.1#55 + +# If you want dnsmasq to change uid and gid to something other +# than the default, edit the following lines. +#user= +#group= + +# If you want dnsmasq to listen for DHCP and DNS requests only on +# specified interfaces (and the loopback) give the name of the +# interface (eg eth0) here. +# Repeat the line for more than one interface. +interface=br0 +# Or you can specify which interface _not_ to listen on +#except-interface= +# Or which to listen on by address (remember to include 127.0.0.1 if +# you use this.) +#listen-address= +# If you want dnsmasq to provide only DNS service on an interface, +# configure it as shown above, and then use the following line to +# disable DHCP and TFTP on it. +#no-dhcp-interface= + +# On systems which support it, dnsmasq binds the wildcard address, +# even when it is listening on only some interfaces. It then discards +# requests that it shouldn't reply to. This has the advantage of +# working even when interfaces come and go and change address. If you +# want dnsmasq to really bind only the interfaces it is listening on, +# uncomment this option. About the only time you may need this is when +# running another nameserver on the same machine. +bind-interfaces + +# If you don't want dnsmasq to read /etc/hosts, uncomment the +# following line. +#no-hosts +# or if you want it to read another file, as well as /etc/hosts, use +# this. +#addn-hosts=/etc/banner_add_hosts + +# Set this (and domain: see below) if you want to have a domain +# automatically added to simple names in a hosts-file. +#expand-hosts + +# Set the domain for dnsmasq. this is optional, but if it is set, it +# does the following things. +# 1) Allows DHCP hosts to have fully qualified domain names, as long +# as the domain part matches this setting. +# 2) Sets the "domain" DHCP option thereby potentially setting the +# domain of all systems configured by DHCP +# 3) Provides the domain part for "expand-hosts" +domain=lan + +# Set a different domain for a particular subnet +#domain=wireless.thekelleys.org.uk,192.168.2.0/24 + +# Same idea, but range rather then subnet +#domain=reserved.thekelleys.org.uk,192.68.3.100,192.168.3.200 + +# Uncomment this to enable the integrated DHCP server, you need +# to supply the range of addresses available for lease and optionally +# a lease time. If you have more than one network, you will need to +# repeat this for each network on which you want to supply DHCP +# service. +dhcp-range=192.168.0.50,192.168.0.150,1h + +# This is an example of a DHCP range where the netmask is given. This +# is needed for networks we reach the dnsmasq DHCP server via a relay +# agent. If you don't know what a DHCP relay agent is, you probably +# don't need to worry about this. +#dhcp-range=192.168.0.50,192.168.0.150,255.255.255.0,12h + +# This is an example of a DHCP range which sets a tag, so that +# some DHCP options may be set only for this network. +#dhcp-range=set:red,192.168.0.50,192.168.0.150 + +# Use this DHCP range only when the tag "green" is set. +#dhcp-range=tag:green,192.168.0.50,192.168.0.150,12h + +# Specify a subnet which can't be used for dynamic address allocation, +# is available for hosts with matching --dhcp-host lines. Note that +# dhcp-host declarations will be ignored unless there is a dhcp-range +# of some type for the subnet in question. +# In this case the netmask is implied (it comes from the network +# configuration on the machine running dnsmasq) it is possible to give +# an explicit netmask instead. +#dhcp-range=192.168.0.0,static + +# Enable DHCPv6. Note that the prefix-length does not need to be specified +# and defaults to 64 if missing/ +#dhcp-range=1234::2, 1234::500, 64, 12h + +# Do Router Advertisements, BUT NOT DHCP for this subnet. +#dhcp-range=1234::, ra-only + +# Do Router Advertisements, BUT NOT DHCP for this subnet, also try and +# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack +# hosts. Use the DHCPv4 lease to derive the name, network segment and +# MAC address and assume that the host will also have an +# IPv6 address calculated using the SLAAC algorithm. +#dhcp-range=1234::, ra-names + +# Do Router Advertisements, BUT NOT DHCP for this subnet. +# Set the lifetime to 46 hours. (Note: minimum lifetime is 2 hours.) +#dhcp-range=1234::, ra-only, 48h + +# Do DHCP and Router Advertisements for this subnet. Set the A bit in the RA +# so that clients can use SLAAC addresses as well as DHCP ones. +#dhcp-range=1234::2, 1234::500, slaac + +# Do Router Advertisements and stateless DHCP for this subnet. Clients will +# not get addresses from DHCP, but they will get other configuration information. +# They will use SLAAC for addresses. +#dhcp-range=1234::, ra-stateless + +# Do stateless DHCP, SLAAC, and generate DNS names for SLAAC addresses +# from DHCPv4 leases. +#dhcp-range=1234::, ra-stateless, ra-names + +# Do router advertisements for all subnets where we're doing DHCPv6 +# Unless overridden by ra-stateless, ra-names, et al, the router +# advertisements will have the M and O bits set, so that the clients +# get addresses and configuration from DHCPv6, and the A bit reset, so the +# clients don't use SLAAC addresses. +#enable-ra + +# Supply parameters for specified hosts using DHCP. There are lots +# of valid alternatives, so we will give examples of each. Note that +# IP addresses DO NOT have to be in the range given above, they just +# need to be on the same network. The order of the parameters in these +# do not matter, it's permissible to give name, address and MAC in any +# order. + +# Always allocate the host with Ethernet address 11:22:33:44:55:66 +# The IP address 192.168.0.60 +#dhcp-host=11:22:33:44:55:66,192.168.0.60 + +# Always set the name of the host with hardware address +# 11:22:33:44:55:66 to be "fred" +#dhcp-host=11:22:33:44:55:66,fred + +# Always give the host with Ethernet address 11:22:33:44:55:66 +# the name fred and IP address 192.168.0.60 and lease time 45 minutes +#dhcp-host=11:22:33:44:55:66,fred,192.168.0.60,45m + +# Give a host with Ethernet address 11:22:33:44:55:66 or +# 12:34:56:78:90:12 the IP address 192.168.0.60. Dnsmasq will assume +# that these two Ethernet interfaces will never be in use at the same +# time, and give the IP address to the second, even if it is already +# in use by the first. Useful for laptops with wired and wireless +# addresses. +#dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.60 + +# Give the machine which says its name is "bert" IP address +# 192.168.0.70 and an infinite lease +#dhcp-host=bert,192.168.0.70,infinite + +# Always give the host with client identifier 01:02:02:04 +# the IP address 192.168.0.60 +#dhcp-host=id:01:02:02:04,192.168.0.60 + +# Always give the InfiniBand interface with hardware address +# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the +# ip address 192.168.0.61. The client id is derived from the prefix +# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of +# hex digits of the hardware address. +#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61 + +# Always give the host with client identifier "marjorie" +# the IP address 192.168.0.60 +#dhcp-host=id:marjorie,192.168.0.60 + +# Enable the address given for "judge" in /etc/hosts +# to be given to a machine presenting the name "judge" when +# it asks for a DHCP lease. +#dhcp-host=judge + +# Never offer DHCP service to a machine whose Ethernet +# address is 11:22:33:44:55:66 +#dhcp-host=11:22:33:44:55:66,ignore + +# Ignore any client-id presented by the machine with Ethernet +# address 11:22:33:44:55:66. This is useful to prevent a machine +# being treated differently when running under different OS's or +# between PXE boot and OS boot. +#dhcp-host=11:22:33:44:55:66,id:* + +# Send extra options which are tagged as "red" to +# the machine with Ethernet address 11:22:33:44:55:66 +#dhcp-host=11:22:33:44:55:66,set:red + +# Send extra options which are tagged as "red" to +# any machine with Ethernet address starting 11:22:33: +#dhcp-host=11:22:33:*:*:*,set:red + +# Give a fixed IPv6 address and name to client with +# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2 +# Note the MAC addresses CANNOT be used to identify DHCPv6 clients. +# Note also that the [] around the IPv6 address are obligatory. +#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5] + +# Ignore any clients which are not specified in dhcp-host lines +# or /etc/ethers. Equivalent to ISC "deny unknown-clients". +# This relies on the special "known" tag which is set when +# a host is matched. +#dhcp-ignore=tag:!known + +# Send extra options which are tagged as "red" to any machine whose +# DHCP vendorclass string includes the substring "Linux" +#dhcp-vendorclass=set:red,Linux + +# Send extra options which are tagged as "red" to any machine one +# of whose DHCP userclass strings includes the substring "accounts" +#dhcp-userclass=set:red,accounts + +# Send extra options which are tagged as "red" to any machine whose +# MAC address matches the pattern. +#dhcp-mac=set:red,00:60:8C:*:*:* + +# If this line is uncommented, dnsmasq will read /etc/ethers and act +# on the ethernet-address/IP pairs found there just as if they had +# been given as --dhcp-host options. Useful if you keep +# MAC-address/host mappings there for other purposes. +#read-ethers + +# Send options to hosts which ask for a DHCP lease. +# See RFC 2132 for details of available options. +# Common options can be given to dnsmasq by name: +# run "dnsmasq --help dhcp" to get a list. +# Note that all the common settings, such as netmask and +# broadcast address, DNS server and default route, are given +# sane defaults by dnsmasq. You very likely will not need +# any dhcp-options. If you use Windows clients and Samba, there +# are some options which are recommended, they are detailed at the +# end of this section. + +# Override the default route supplied by dnsmasq, which assumes the +# router is the same machine as the one running dnsmasq. +#dhcp-option=3,1.2.3.4 + +# Do the same thing, but using the option name +#dhcp-option=option:router,1.2.3.4 + +# Override the default route supplied by dnsmasq and send no default +# route at all. Note that this only works for the options sent by +# default (1, 3, 6, 12, 28) the same line will send a zero-length option +# for all other option numbers. +#dhcp-option=3 + +# Set the NTP time server addresses to 192.168.0.4 and 10.10.0.5 +#dhcp-option=option:ntp-server,192.168.0.4,10.10.0.5 + +# Send DHCPv6 option. Note [] around IPv6 addresses. +#dhcp-option=option6:dns-server,[1234::77],[1234::88] + +# Send DHCPv6 option for namservers as the machine running +# dnsmasq and another. +#dhcp-option=option6:dns-server,[::],[1234::88] + +# Ask client to poll for option changes every six hours. (RFC4242) +#dhcp-option=option6:information-refresh-time,6h + +# Set option 58 client renewal time (T1). Defaults to half of the +# lease time if not specified. (RFC2132) +#dhcp-option=option:T1,1m + +# Set option 59 rebinding time (T2). Defaults to 7/8 of the +# lease time if not specified. (RFC2132) +#dhcp-option=option:T2,2m + +# Set the NTP time server address to be the same machine as +# is running dnsmasq +#dhcp-option=42,0.0.0.0 + +# Set the NIS domain name to "welly" +#dhcp-option=40,welly + +# Set the default time-to-live to 50 +#dhcp-option=23,50 + +# Set the "all subnets are local" flag +#dhcp-option=27,1 + +# Send the etherboot magic flag and then etherboot options (a string). +#dhcp-option=128,e4:45:74:68:00:00 +#dhcp-option=129,NIC=eepro100 + +# Specify an option which will only be sent to the "red" network +# (see dhcp-range for the declaration of the "red" network) +# Note that the tag: part must precede the option: part. +#dhcp-option = tag:red, option:ntp-server, 192.168.1.1 + +# The following DHCP options set up dnsmasq in the same way as is specified +# for the ISC dhcpcd in +# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt +# adapted for a typical dnsmasq installation where the host running +# dnsmasq is also the host running samba. +# you may want to uncomment some or all of them if you use +# Windows clients and Samba. +#dhcp-option=19,0 # option ip-forwarding off +#dhcp-option=44,0.0.0.0 # set netbios-over-TCP/IP nameserver(s) aka WINS server(s) +#dhcp-option=45,0.0.0.0 # netbios datagram distribution server +#dhcp-option=46,8 # netbios node type + +# Send an empty WPAD option. This may be REQUIRED to get windows 7 to behave. +#dhcp-option=252,"\n" + +# Send RFC-3397 DNS domain search DHCP option. WARNING: Your DHCP client +# probably doesn't support this...... +#dhcp-option=option:domain-search,eng.apple.com,marketing.apple.com + +# Send RFC-3442 classless static routes (note the netmask encoding) +#dhcp-option=121,192.168.1.0/24,1.2.3.4,10.0.0.0/8,5.6.7.8 + +# Send vendor-class specific options encapsulated in DHCP option 43. +# The meaning of the options is defined by the vendor-class so +# options are sent only when the client supplied vendor class +# matches the class given here. (A substring match is OK, so "MSFT" +# matches "MSFT" and "MSFT 5.0"). This example sets the +# mtftp address to 0.0.0.0 for PXEClients. +#dhcp-option=vendor:PXEClient,1,0.0.0.0 + +# Send microsoft-specific option to tell windows to release the DHCP lease +# when it shuts down. Note the "i" flag, to tell dnsmasq to send the +# value as a four-byte integer - that's what microsoft wants. See +# http://technet2.microsoft.com/WindowsServer/en/library/a70f1bb7-d2d4-49f0-96d6-4b7414ecfaae1033.mspx?mfr=true +#dhcp-option=vendor:MSFT,2,1i + +# Send the Encapsulated-vendor-class ID needed by some configurations of +# Etherboot to allow is to recognise the DHCP server. +#dhcp-option=vendor:Etherboot,60,"Etherboot" + +# Send options to PXELinux. Note that we need to send the options even +# though they don't appear in the parameter request list, so we need +# to use dhcp-option-force here. +# See http://syslinux.zytor.com/pxe.php#special for details. +# Magic number - needed before anything else is recognised +#dhcp-option-force=208,f1:00:74:7e +# Configuration file name +#dhcp-option-force=209,configs/common +# Path prefix +#dhcp-option-force=210,/tftpboot/pxelinux/files/ +# Reboot time. (Note 'i' to send 32-bit value) +#dhcp-option-force=211,30i + +# Set the boot filename for netboot/PXE. You will only need +# this if you want to boot machines over the network and you will need +# a TFTP server; either dnsmasq's built-in TFTP server or an +# external one. (See below for how to enable the TFTP server.) +#dhcp-boot=pxelinux.0 + +# The same as above, but use custom tftp-server instead machine running dnsmasq +#dhcp-boot=pxelinux,server.name,192.168.1.100 + +# Boot for iPXE. The idea is to send two different +# filenames, the first loads iPXE, and the second tells iPXE what to +# load. The dhcp-match sets the ipxe tag for requests from iPXE. +#dhcp-boot=undionly.kpxe +#dhcp-match=set:ipxe,175 # iPXE sends a 175 option. +#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php + +# Encapsulated options for iPXE. All the options are +# encapsulated within option 175 +#dhcp-option=encap:175, 1, 5b # priority code +#dhcp-option=encap:175, 176, 1b # no-proxydhcp +#dhcp-option=encap:175, 177, string # bus-id +#dhcp-option=encap:175, 189, 1b # BIOS drive code +#dhcp-option=encap:175, 190, user # iSCSI username +#dhcp-option=encap:175, 191, pass # iSCSI password + +# Test for the architecture of a netboot client. PXE clients are +# supposed to send their architecture as option 93. (See RFC 4578) +#dhcp-match=peecees, option:client-arch, 0 #x86-32 +#dhcp-match=itanics, option:client-arch, 2 #IA64 +#dhcp-match=hammers, option:client-arch, 6 #x86-64 +#dhcp-match=mactels, option:client-arch, 7 #EFI x86-64 + +# Do real PXE, rather than just booting a single file, this is an +# alternative to dhcp-boot. +#pxe-prompt="What system shall I netboot?" +# or with timeout before first available action is taken: +#pxe-prompt="Press F8 for menu.", 60 + +# Available boot services. for PXE. +#pxe-service=x86PC, "Boot from local disk" + +# Loads /pxelinux.0 from dnsmasq TFTP server. +#pxe-service=x86PC, "Install Linux", pxelinux + +# Loads /pxelinux.0 from TFTP server at 1.2.3.4. +# Beware this fails on old PXE ROMS. +#pxe-service=x86PC, "Install Linux", pxelinux, 1.2.3.4 + +# Use bootserver on network, found my multicast or broadcast. +#pxe-service=x86PC, "Install windows from RIS server", 1 + +# Use bootserver at a known IP address. +#pxe-service=x86PC, "Install windows from RIS server", 1, 1.2.3.4 + +# If you have multicast-FTP available, +# information for that can be passed in a similar way using options 1 +# to 5. See page 19 of +# http://download.intel.com/design/archives/wfm/downloads/pxespec.pdf + + +# Enable dnsmasq's built-in TFTP server +#enable-tftp + +# Set the root directory for files available via FTP. +#tftp-root=/var/ftpd + +# Do not abort if the tftp-root is unavailable +#tftp-no-fail + +# Make the TFTP server more secure: with this set, only files owned by +# the user dnsmasq is running as will be send over the net. +#tftp-secure + +# This option stops dnsmasq from negotiating a larger blocksize for TFTP +# transfers. It will slow things down, but may rescue some broken TFTP +# clients. +#tftp-no-blocksize + +# Set the boot file name only when the "red" tag is set. +#dhcp-boot=tag:red,pxelinux.red-net + +# An example of dhcp-boot with an external TFTP server: the name and IP +# address of the server are given after the filename. +# Can fail with old PXE ROMS. Overridden by --pxe-service. +#dhcp-boot=/var/ftpd/pxelinux.0,boothost,192.168.0.3 + +# If there are multiple external tftp servers having a same name +# (using /etc/hosts) then that name can be specified as the +# tftp_servername (the third option to dhcp-boot) and in that +# case dnsmasq resolves this name and returns the resultant IP +# addresses in round robin fashion. This facility can be used to +# load balance the tftp load among a set of servers. +#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name + +# Set the limit on DHCP leases, the default is 150 +#dhcp-lease-max=150 + +# The DHCP server needs somewhere on disk to keep its lease database. +# This defaults to a sane location, but if you want to change it, use +# the line below. +#dhcp-leasefile=/var/lib/misc/dnsmasq.leases + +# Set the DHCP server to authoritative mode. In this mode it will barge in +# and take over the lease for any client which broadcasts on the network, +# whether it has a record of the lease or not. This avoids long timeouts +# when a machine wakes up on a new network. DO NOT enable this if there's +# the slightest chance that you might end up accidentally configuring a DHCP +# server for your campus/company accidentally. The ISC server uses +# the same option, and this URL provides more information: +# http://www.isc.org/files/auth.html +#dhcp-authoritative + +# Set the DHCP server to enable DHCPv4 Rapid Commit Option per RFC 4039. +# In this mode it will respond to a DHCPDISCOVER message including a Rapid Commit +# option with a DHCPACK including a Rapid Commit option and fully committed address +# and configuration information. This must only be enabled if either the server is +# the only server for the subnet, or multiple servers are present and they each +# commit a binding for all clients. +#dhcp-rapid-commit + +# Run an executable when a DHCP lease is created or destroyed. +# The arguments sent to the script are "add" or "del", +# then the MAC address, the IP address and finally the hostname +# if there is one. +#dhcp-script=/bin/echo + +# Set the cachesize here. +#cache-size=150 + +# If you want to disable negative caching, uncomment this. +#no-negcache + +# Normally responses which come from /etc/hosts and the DHCP lease +# file have Time-To-Live set as zero, which conventionally means +# do not cache further. If you are happy to trade lower load on the +# server for potentially stale date, you can set a time-to-live (in +# seconds) here. +#local-ttl= + +# If you want dnsmasq to detect attempts by Verisign to send queries +# to unregistered .com and .net hosts to its sitefinder service and +# have dnsmasq instead return the correct NXDOMAIN response, uncomment +# this line. You can add similar lines to do the same for other +# registries which have implemented wildcard A records. +#bogus-nxdomain=64.94.110.11 + +# If you want to fix up DNS results from upstream servers, use the +# alias option. This only works for IPv4. +# This alias makes a result of 1.2.3.4 appear as 5.6.7.8 +#alias=1.2.3.4,5.6.7.8 +# and this maps 1.2.3.x to 5.6.7.x +#alias=1.2.3.0,5.6.7.0,255.255.255.0 +# and this maps 192.168.0.10->192.168.0.40 to 10.0.0.10->10.0.0.40 +#alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0 + +# Change these lines if you want dnsmasq to serve MX records. + +# Return an MX record named "maildomain.com" with target +# servermachine.com and preference 50 +#mx-host=maildomain.com,servermachine.com,50 + +# Set the default target for MX records created using the localmx option. +#mx-target=servermachine.com + +# Return an MX record pointing to the mx-target for all local +# machines. +#localmx + +# Return an MX record pointing to itself for all local machines. +#selfmx + +# Change the following lines if you want dnsmasq to serve SRV +# records. These are useful if you want to serve ldap requests for +# Active Directory and other windows-originated DNS requests. +# See RFC 2782. +# You may add multiple srv-host lines. +# The fields are ,,,, +# If the domain part if missing from the name (so that is just has the +# service and protocol sections) then the domain given by the domain= +# config option is used. (Note that expand-hosts does not need to be +# set for this to work.) + +# A SRV record sending LDAP for the example.com domain to +# ldapserver.example.com port 389 +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389 + +# A SRV record sending LDAP for the example.com domain to +# ldapserver.example.com port 389 (using domain=) +#domain=example.com +#srv-host=_ldap._tcp,ldapserver.example.com,389 + +# Two SRV records for LDAP, each with different priorities +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,1 +#srv-host=_ldap._tcp.example.com,ldapserver.example.com,389,2 + +# A SRV record indicating that there is no LDAP server for the domain +# example.com +#srv-host=_ldap._tcp.example.com + +# The following line shows how to make dnsmasq serve an arbitrary PTR +# record. This is useful for DNS-SD. (Note that the +# domain-name expansion done for SRV records _does_not +# occur for PTR records.) +#ptr-record=_http._tcp.dns-sd-services,"New Employee Page._http._tcp.dns-sd-services" + +# Change the following lines to enable dnsmasq to serve TXT records. +# These are used for things like SPF and zeroconf. (Note that the +# domain-name expansion done for SRV records _does_not +# occur for TXT records.) + +#Example SPF. +#txt-record=example.com,"v=spf1 a -all" + +#Example zeroconf +#txt-record=_http._tcp.example.com,name=value,paper=A4 + +# Provide an alias for a "local" DNS name. Note that this _only_ works +# for targets which are names from DHCP or /etc/hosts. Give host +# "bert" another name, bertrand +#cname=bertand,bert + +# For debugging purposes, log each DNS query as it passes through +# dnsmasq. +#log-queries + +# Log lots of extra information about DHCP transactions. +#log-dhcp + +# Include another lot of configuration options. +#conf-file=/etc/dnsmasq.more.conf +#conf-dir=/etc/dnsmasq.d + +# Include all the files in a directory except those ending in .bak +#conf-dir=/etc/dnsmasq.d,.bak + +# Include all files in a directory which end in .conf +#conf-dir=/etc/dnsmasq.d/,*.conf + +# If a DHCP client claims that its name is "wpad", ignore that. +# This fixes a security hole. see CERT Vulnerability VU#598349 +#dhcp-name-match=set:wpad-ignore,wpad +#dhcp-ignore-names=tag:wpad-ignore diff --git a/conf/etc/hostapd/hostapd.conf b/conf/etc/hostapd/hostapd.conf new file mode 100644 index 0000000..c98621f --- /dev/null +++ b/conf/etc/hostapd/hostapd.conf @@ -0,0 +1,130 @@ +# Use the 802.11 Netlink based interface between the hostapd +# and cfg80211 kernel module. +driver=nl80211 + +interface=wlan0 + +# Add the interface wlan0 into bridge br0. +bridge=br0 + +# Log from all modules(IEEE 802.11, driver interface, etc) starting +# from "verbose debugging" severity level. +logger_syslog=-1 +logger_syslog_level=0 + +# Creates an UNIX domain socket in /var/run/hostapd +# directory for listening to requests from external +# programs(for example hostapd_cli) for status info +# and configuration. +ctrl_interface=/var/run/hostapd +ctrl_interface_group=0 + + + +# +# IEEE 802.11 related configuration +# +ssid=r1 + +# Country code for regulatory domain. This can limit +# available channels and transmit power. +# Example output of "iw reg get": +# +# country EE: DFS-ETSI +# (2400 - 2483 @ 40), (N/A, 20), (N/A) +# (5150 - 5250 @ 80), (N/A, 23), (N/A), NO-OUTDOOR, AUTO-BW +# (5250 - 5350 @ 80), (N/A, 20), (0 ms), NO-OUTDOOR, DFS, AUTO-BW +# (5470 - 5725 @ 160), (N/A, 26), (0 ms), DFS +# (5725 - 5875 @ 80), (N/A, 13), (N/A) +# (57000 - 66000 @ 2160), (N/A, 40), (N/A) +country_code=EE + +# Enable IEEE 802.11d. This advertises the "country_code" +# and the set of allowed channels and transmit power +# levels based on the regulatory limits. +ieee80211d=1 + +# 5 GHz mode. For IEEE 802.11ac, the "hw_mode" needs to be set to "a". +hw_mode=a + +# With "vht_oper_chwidth=1" and "vht_oper_centr_freq_seg0_idx=42" +# configuration options below, the frequency range is 5170 - 5250 MHz +# with center frequency of 5210 MHz. In other words, channels 36 - 48 +# with channel 36 being a primary channel. +# Frequency configuration from the hostapd debug output: +# +# nl80211: Set freq 5180 (ht_enabled=1, vht_enabled=1, bandwidth=80 MHz, cf1=5210 MHz, cf2=0 MHz) +# * freq=5180 +# * vht_enabled=1 +# * ht_enabled=1 +# * bandwidth=80 +# * channel_width=3 +# * center_freq1=5210 +# * center_freq2=0 +# +channel=36 + +# Wi-Fi Multimedia. It provides basic QoS features to IEEE 802.11 networks. +# According to https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf WMM has +# to be enabled in case of IEEE 802.11n High Throughput or IEEE 802.11ac +# Very High Throughput modes are desired. +wmm_enabled=1 + +# Disassociate stations based on excessive transmission failures or other +# indications of connection loss. +disassoc_low_ack=1 + +# Allow low-level bridging of frames between associated stations in the +# Wi-Fi network. Additionally, hairpin has to be enabled(bridge link set +# dev wlan0 hairpin on) in order to allow connectivity between Wi-Fi clients. +ap_isolate=0 + + + +# +# IEEE 802.11n related configuration +# +ieee80211n=1 + +# Based on the capabilities in the output of "iw list". +ht_capab=[HT40+] [SHORT-GI-40] + + + +# +# IEEE 802.11ac related configuration +# +ieee80211ac=1 + +# Based on the "VHT Capabilities" in the output of "iw list". +vht_capab=[VHT160] [SHORT-GI-80] [SHORT-GI-160] [MU-BEAMFORMER] [MU-BEAMFORMEE] + +# 80 MHz channel width. +vht_oper_chwidth=1 + +# Center frequency of 5210 MHz. +vht_oper_centr_freq_seg0_idx=42 + + + +# +# WPA/IEEE 802.11i related configuration +# +wpa_key_mgmt=WPA-PSK +wpa_passphrase= + +# WPA2 mode. +wpa=2 + +# Use CCMP encryption protocol instead of TKIP cipher suite. +# Output of "get_config" in hostapd_cli: +# +# bssid=2c:fd:a1:cf:fd:56 +# ssid=r1 +# wps_state=disabled +# wpa=2 +# key_mgmt=WPA-PSK +# group_cipher=CCMP +# rsn_pairwise_cipher=CCMP +# +rsn_pairwise=CCMP diff --git a/conf/etc/igmpproxy.conf b/conf/etc/igmpproxy.conf new file mode 100644 index 0000000..33ebee7 --- /dev/null +++ b/conf/etc/igmpproxy.conf @@ -0,0 +1,39 @@ +######################################################## +# +# Example configuration file for the IgmpProxy +# -------------------------------------------- +# +# The configuration file must define one upstream +# interface, and one or more downstream interfaces. +# +# If multicast traffic originates outside the +# upstream subnet, the "altnet" option can be +# used in order to define legal multicast sources. +# (Se example...) +# +# The "quickleave" should be used to avoid saturation +# of the upstream link. The option should only +# be used if it's absolutely nessecary to +# accurately imitate just one Client. +# +######################################################## + +##------------------------------------------------------ +## Enable Quickleave mode (Sends Leave instantly) +##------------------------------------------------------ +quickleave + +##------------------------------------------------------ +## Configuration for eth0 (Upstream Interface) +##------------------------------------------------------ +phyint wan0.4 upstream ratelimit 0 threshold 1 + altnet 0.0.0.0/0 + +##------------------------------------------------------ +## Configuration for eth1 (Downstream Interface) +##------------------------------------------------------ +phyint br0 downstream ratelimit 0 threshold 1 + +##------------------------------------------------------ +## Configuration for eth2 (Disabled Interface) +##------------------------------------------------------ diff --git a/conf/etc/modprobe.d/bnx2x.conf b/conf/etc/modprobe.d/bnx2x.conf new file mode 100644 index 0000000..c0a9ad4 --- /dev/null +++ b/conf/etc/modprobe.d/bnx2x.conf @@ -0,0 +1,7 @@ +# Make sure, that LRO(Large Receive Offload) is disabled for bnx2x driver +# used by Dell N20KJ(Broadcom BCM57810) NIC. Requires initramfs update. +# "cat /sys/module/bnx2x/parameters/disable_tpa" shows the "disable_tpa" +# option value. "large-receive-offload" feature in the output of "ethtool +# -k " has to be "off". +# Alternatively, "ethtool -K lro off" could be used. +options bnx2x disable_tpa=1 diff --git a/conf/etc/network/interfaces b/conf/etc/network/interfaces new file mode 100644 index 0000000..a1867e1 --- /dev/null +++ b/conf/etc/network/interfaces @@ -0,0 +1,181 @@ +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + + +# The loopback network interface +auto lo +iface lo inet loopback + + +# -> LAN +auto br0 +iface br0 inet static + address 192.168.0.1/24 + + # Use the br0 for loading the iptables rules. + # This ensures that the firewall rules are added + # before any of the physical interfaces are brought + # up and the rules are removed after all the physical + # interfaces are brought down. + # Man page of ifup(8) claims that the "ifdown -a" brings + # the interfaces down in the order in which they are + # currently listed in the state file(/run/network/ifstate), + # but this seems to be a bug: + # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1033651 + # + # Worthwhile notes about iptables rules: + # + # * dhclient in DHCPv4 mode uses raw sockets(fallback UDP + # socket for sending unicast packets is also opened) and + # thus no firewall rule is needed + # + # * important ICMP messages like "frag needed" or + # "TTL exceeded" are accepted thanks to conntrack + # "RELATED" state match + # + # * certain ICMP messages sent by the router including + # "Echo Reply" or "Destination Unreachable" are rate + # limited by adjusting the kernel parameters in + # /etc/sysctl.conf + # + # * recent(used in SSH chain) module internals are seen + # in the /proc/net/xt_recent/SSH file + # + # * while igmpproxy is using raw sockets on the downstream + # interface, then in regard to upstream interface the + # igmpproxy simply acts as a normal multicast client(calls + # setsockopt() with IP_ADD_MEMBERSHIP) and thus there is a + # need to accept IGMP membership query messages sent by ISP. + # This also means that the IPTV UDP datagrams are sent + # towards the router application layer and dropped in the + # filter table INPUT chain. + # + # * IGMP messages can not be tracked by the conntrack module. + # At least without an helper module. IGMP messages are sent + # to IPv4 multicast address and thus the conntrack module + # expects a reply sourced from a multicast address in order + # to move from UNREPLIED state to ESTABLISHED state. However, + # the multicast address is never used as a src IP. + # + # * igmpproxy subscribes to 224.0.0.2(IGMP "Leave group" messages) + # on a downstream interface and packets sent to this address + # are subject to INPUT chain rules. That's the reason for + # "-A INPUT -d 224.0.0.2/32 -i br0 -p igmp -j ACCEPT" rule. Details + # are in https://marc.info/?l=netfilter&m=168393431101974&w=2 + # + pre-up iptables-restore /usr/local/etc/IPv4_fw_rules + + # Consider stray TCP packets with ACK flag set as + # INVALID. By default, such packets would create + # a NEW connection. + # "nf_conntrack_tcp_loose" is configured here instead + # of /etc/sysctl.conf because the nf_conntrack module + # is not yet loaded at the time the systemd-sysctl + # service is run. + pre-up sysctl -w net.netfilter.nf_conntrack_tcp_loose=0 + + # Set the MAC address manually. This ensures that the MAC address + # of br0 will not change when bridge ports are added or removed. + # This will avoid problems like hostapd adding the WNIC to bridge, + # causing the bridge MAC address change and thus breaking the + # dnsmasq if br0 flaps as the dnsmasq is bound to IPv6 link-local + # address derived from the old MAC address of the br0 bridge. + post-up ip link set dev $IFACE address 02:a7:29:a6:ec:61 + + post-down iptables-restore /usr/local/etc/IPv4_default_fw_rules + + # "bridge_ports" requires "bridge-utils" package. + bridge_ports lan0 lan1 lan2 lan3 + +iface br0 inet6 manual + # Worthwhile notes about ip6tables rules: + # + # * dhclient in DHCPv6 mode is able to use ordinary UDP sockets + # thanks to link-local addresses and does not need to use + # raw sockets. This means that a firewall rule for DHCPv6 + # traffic is needed. + # + # * ICMP6 "echo request" messages are rate limited by the + # limit module. Newer kernel versions have the net.ipv6.icmp.ratemask + # which would allow to rate limit the replies to "echo request" + # messages by adjusting the net.ipv6.icmp.ratelimit. + # ICMP6 "destination unreachable" messages are rate limited + # according to net.ipv6.icmp.ratelimit. + # + # * important ICMP6 messages like "packet too big" or + # "time exceeded" or "destination unreachable" are + # accepted thanks to conntrack "RELATED" state match + # + # * RA messages sent by radvd to ff02::1 multicast addr + # via LAN-facing interface are looped back by the IP + # layer for local delivery. This is a default behavior + # and can be controlled by IPV6_MULTICAST_LOOP(man 7 ipv6). + # Those messages are dropped. + # + pre-up ip6tables-restore /usr/local/etc/IPv6_fw_rules + post-down ip6tables-restore /usr/local/etc/IPv6_default_fw_rules + + +# -> Telia fiber +auto wan0 +iface wan0 inet dhcp +# Telia uses DHCPv6 prefix delegation to assign +# a /56 IPv6 prefix. Default route is installed +# thanks to NDP Router Advertisement messages +# and it points to VRRPv3 link-local address. +iface wan0 inet6 auto + + # Stateless DHCPv6. dhclient will be started + # with "-P"(enable IPv6 prefix delegation) and + # without "-N"(normal address query for IPv6), + # i.e IPv6 address is not requested from DHCPv6 + # server. + dhcp 1 + request_prefix 1 + + # Enabling packet forwarding for IPv6(net.ipv6.conf.all.forwarding=1) + # in /etc/sysctl.conf sets the "net.ipv6.conf..forwarding" values + # to 1 which means that Router Solicitation messages are no longer sent + # and Router Advertisements messages are no longer accepted on those + # interfaces. "net.ipv6.conf..forwarding" value has nothing + # to do with controlling the per-interface forwarding like it does + # in case of IPv4. The "accept_ra 2"(net.ipv6.conf.wan0.accept_ra=2) + # means that Router Solicitations are sent and Router Advertisements + # are accepted despite the fact that "net.ipv6.conf..forwarding" is 1. + # Documentation: https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt + accept_ra 2 + +# Mgnt network for Huawei MA5671A SFP ONT. +# SSH server is reachable at 192.168.1.10. +# User: root +# Password: admin123 +# +# Keeping the manually configured IPv4 addr +# on the same interface where the dhclient +# is running works thanks to "get-static-ipv4-addrs" +# and "restore-static-ipv4-addrs" dhclient-script +# enter and exit hooks. An alternative approach +# would be to use a macvlan interface and for +# example keep the static address there while +# dhclient runs on the physical interface. +iface wan0 inet static + address 192.168.1.200/24 + + +# -> Telia IPTV +auto wan0.4 +# IPv6 for wan0.4 is disabled in /etc/sysctl.conf with net.ipv6.conf.wan0/4.disable_ipv6=1 +iface wan0.4 inet dhcp + + +# -> Telia mobile broadband +auto wwan0 +# wwan0 is a Telia-branded Huawei E3372s-153(hardware version CL1E3372SM Ver.A) +# LTE modem with 22.x firmware working in Hilink mode having its own DHCP server +# providing addresses from 192.168.8.0/24 network, web interface, performing NAT, +# etc. For the OS it appears as an Ethernet device. +# SIM is from Telia. Huawei E3372s-153 in Hilink mode does not support IPv6, nor +# is IPv6 supported by Telia for the mobile broadband service. +iface wwan0 inet static + address 192.168.8.200/24 + post-up ip route add default via 192.168.8.1 metric 100 diff --git a/conf/etc/pam.d/common-auth b/conf/etc/pam.d/common-auth new file mode 100644 index 0000000..216b8e4 --- /dev/null +++ b/conf/etc/pam.d/common-auth @@ -0,0 +1,33 @@ +# +# /etc/pam.d/common-auth - authentication settings common to all services +# +# This file is included from other service-specific PAM config files, +# and should contain a list of the authentication modules that define +# the central authentication scheme for use on the system +# (e.g., /etc/shadow, LDAP, Kerberos, etc.). The default is to use the +# traditional Unix authentication mechanisms. +# +# As of pam 1.0.1-6, this file is managed by pam-auth-update by default. +# To take advantage of this, it is recommended that you configure any +# local modules either before or after the default block, and use +# pam-auth-update to manage selection of other modules. See +# pam-auth-update(8) for details. + +# If pam_yubico.so returns PAM_SUCCESS, then pam_google_authenticator.so is skipped. +# All other return codes are ignored and pam_google_authenticator.so is used. +# pam_yubico.so has "forward_pass"(pam_set_item(pamh, PAM_AUTHTOK, onlypasswd)) enabled by default. +auth [success=1 default=ignore] pam_yubico.so id=12345 authfile=/etc/authorized_yubikeys urllist=https://api.yubico.com/wsapi/2.0/verify + +# pam_google_authenticator.so is able to detect if user password is entered before TOTP. +auth required pam_google_authenticator.so forward_pass + +# here are the per-package modules (the "Primary" block) +auth [success=1 default=ignore] pam_unix.so nullok_secure try_first_pass +# here's the fallback if no module succeeds +auth requisite pam_deny.so +# prime the stack with a positive return value if there isn't one already; +# this avoids us returning an error just because nothing sets a success code +# since the modules above will each just jump around +auth required pam_permit.so +# and here are more per-package modules (the "Additional" block) +# end of pam-auth-update config diff --git a/conf/etc/resolv.conf b/conf/etc/resolv.conf new file mode 100644 index 0000000..f44d062 --- /dev/null +++ b/conf/etc/resolv.conf @@ -0,0 +1,3 @@ +domain lan +nameserver ::1 +nameserver 127.0.0.1 diff --git a/conf/etc/sysctl.conf b/conf/etc/sysctl.conf new file mode 100644 index 0000000..4fe4ddc --- /dev/null +++ b/conf/etc/sysctl.conf @@ -0,0 +1,85 @@ +# +# /etc/sysctl.conf - Configuration file for setting system variables +# See /etc/sysctl.d/ for additional system variables. +# See sysctl.conf (5) for information. +# + +#kernel.domainname = example.com + +# Uncomment the following to stop low-level messages on console +#kernel.printk = 3 4 1 3 + +##############################################################3 +# Functions previously found in netbase +# + +# Uncomment the next two lines to enable Spoof protection (reverse-path filter) +# Turn on Source Address Verification in all interfaces to +# prevent some spoofing attacks +#net.ipv4.conf.default.rp_filter=1 +#net.ipv4.conf.all.rp_filter=1 + +# Uncomment the next line to enable TCP/IP SYN cookies +# See http://lwn.net/Articles/277146/ +# Note: This may impact IPv6 TCP sessions too +#net.ipv4.tcp_syncookies=1 + +# Uncomment the next line to enable packet forwarding for IPv4 +net.ipv4.ip_forward=1 + +# Uncomment the next line to enable packet forwarding for IPv6 +# Enabling this option disables Stateless Address Autoconfiguration +# based on Router Advertisements for this host +net.ipv6.conf.all.forwarding=1 + +# Disable IPv6 on IPTV VLAN-interface. +net.ipv6.conf.wan0/4.disable_ipv6=1 + +# Disable IPv6 on Telia mobile broadband interface. +net.ipv6.conf.wwan0.disable_ipv6=1 + +################################################################### +# Additional settings - these settings can improve the network +# security of the host and prevent against some network attacks +# including spoofing attacks and man in the middle attacks through +# redirection. Some network environments, however, require that these +# settings are disabled so review and enable them as needed. +# +# Do not accept ICMP redirects (prevent MITM attacks) +#net.ipv4.conf.all.accept_redirects = 0 +#net.ipv6.conf.all.accept_redirects = 0 +# _or_ +# Accept ICMP redirects only for gateways listed in our default +# gateway list (enabled by default) +# net.ipv4.conf.all.secure_redirects = 1 +# +# Do not send ICMP redirects (we are not a router) +#net.ipv4.conf.all.send_redirects = 0 +# +# Do not accept IP source route packets (we are not a router) +#net.ipv4.conf.all.accept_source_route = 0 +#net.ipv6.conf.all.accept_source_route = 0 +# +# Log Martian Packets +#net.ipv4.conf.all.log_martians = 1 +# +# By default the ICMP "echo reply" messages are not +# rate limited. Adjust the "icmp_ratemask" as router +# is pingable from the Internet and relax the minimal +# space between responses to 0.1s. +# https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt +net.ipv4.icmp_ratemask=88089 +net.ipv4.icmp_ratelimit=100 + + +################################################################### +# Magic system request Key +# 0=disable, 1=enable all, >1 bitmask of sysrq functions +# See https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html +# for what other values do +#kernel.sysrq=438 + +# Ignore routes whose link is down when performing a FIB lookup. +# This ensures instant failover from wan0 to wwan0 and vice versa. +net.ipv4.conf.wan0.ignore_routes_with_linkdown=1 +net.ipv4.conf.wwan0.ignore_routes_with_linkdown=1 diff --git a/conf/etc/systemd/system/dnsmasq.service.d/override.conf b/conf/etc/systemd/system/dnsmasq.service.d/override.conf new file mode 100644 index 0000000..58ef03a --- /dev/null +++ b/conf/etc/systemd/system/dnsmasq.service.d/override.conf @@ -0,0 +1,8 @@ +[Unit] +# As the dnsmasq is configured("bind-interfaces" in /etc/dnsmasq.conf) to +# run strictly on br0 interface and this interface is removed and then +# recreate during the networking restart, then ensure that networking.service +# restarts are propagated to dnsmasq.service so that the dnsmasq will +# bind to new br0. +PartOf=networking.service +After=networking.service diff --git a/conf/etc/systemd/system/hostapd.service.d/override.conf b/conf/etc/systemd/system/hostapd.service.d/override.conf new file mode 100644 index 0000000..8b135f0 --- /dev/null +++ b/conf/etc/systemd/system/hostapd.service.d/override.conf @@ -0,0 +1,10 @@ +[Unit] +# Hostapd adds the WNIC to bridge br0. As the restart of networking service +# removes and recreates the br0 interface, then ensure that networking.service +# restarts are propagated to hostapd.service so the hostapd will insert the +# WNIC to new br0 bridge. +PartOf=networking.service +After=networking.service + +[Service] +ExecStartPost=/sbin/bridge link set dev wlan0 hairpin on diff --git a/conf/etc/systemd/system/igmpproxy.service.d/override.conf b/conf/etc/systemd/system/igmpproxy.service.d/override.conf new file mode 100644 index 0000000..4cb469e --- /dev/null +++ b/conf/etc/systemd/system/igmpproxy.service.d/override.conf @@ -0,0 +1,3 @@ +[Unit] +PartOf=networking.service +After=networking.service diff --git a/conf/etc/systemd/system/isp-switch.service b/conf/etc/systemd/system/isp-switch.service new file mode 100644 index 0000000..3002d03 --- /dev/null +++ b/conf/etc/systemd/system/isp-switch.service @@ -0,0 +1,11 @@ +[Unit] +Description=Switches v4 connectivity to mobile broadband backup +After=network.target + +[Service] +Type=simple +Restart=always +ExecStart=/usr/local/sbin/isp-switch + +[Install] +WantedBy=multi-user.target diff --git a/conf/etc/systemd/system/networking.service.d/override.conf b/conf/etc/systemd/system/networking.service.d/override.conf new file mode 100644 index 0000000..76c8439 --- /dev/null +++ b/conf/etc/systemd/system/networking.service.d/override.conf @@ -0,0 +1,6 @@ +[Unit] +# Start dnsmasq, igmpproxy and hostapd services when +# the networking service is started. dnsmasq, igmpproxy +# and hostapd services are started once the networking +# service has been started. +Wants=dnsmasq.service igmpproxy.service hostapd.service diff --git a/conf/etc/udev/rules.d/70-persistent-net.rules b/conf/etc/udev/rules.d/70-persistent-net.rules new file mode 100644 index 0000000..a1cf4aa --- /dev/null +++ b/conf/etc/udev/rules.d/70-persistent-net.rules @@ -0,0 +1,7 @@ +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:10:18:dc:1d:30", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="wan0" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="0c:5b:8f:27:9a:64", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="wwan0" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:10:18:dc:1d:32", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="lan0" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="d0:50:99:93:71:b5", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="lan1" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="50:3e:aa:11:e8:4f", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="lan2" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="50:3e:aa:11:7f:f0", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="lan3" +SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="2c:fd:a1:cf:fd:56", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="wlan*", NAME="wlan0" diff --git a/conf/etc/usb_modeswitch.d/12d1:157d b/conf/etc/usb_modeswitch.d/12d1:157d new file mode 100644 index 0000000..cc56648 --- /dev/null +++ b/conf/etc/usb_modeswitch.d/12d1:157d @@ -0,0 +1,5 @@ +# Huawei E3331, E3372 +TargetVendor=0x12d1 +TargetProductList="14db,14dc" +HuaweiNewMode=1 +NoMBIMCheck=1 diff --git a/conf/usr/local/bin/mac_to_ip6_ll_addr b/conf/usr/local/bin/mac_to_ip6_ll_addr new file mode 100755 index 0000000..2562f9e --- /dev/null +++ b/conf/usr/local/bin/mac_to_ip6_ll_addr @@ -0,0 +1,74 @@ +#!/usr/bin/env bash + +# Title : mac_to_ip6_ll_addr +# Last modified date : 13.03.2023 +# Author : Martin Tonusoo +# Description : Script finds the IPv6 link local address +# from the MAC address. +# Options : MAC address. +# Notes : Script expects the MAC address as a +# command line argument in the format +# returned by "ip link" command, e.g +# 52:54:00:db:99:99. + + +mac_regex="^([0-9a-f]{2}:){5}([0-9a-f]{2})$" +if [[ ! "$1" =~ $mac_regex ]]; then + printf "%s\n%s\n" "Usage: ${0##*/} " \ + "Example: ${0##*/} 52:54:00:db:99:99" \ + >&2 + exit 1 +fi + +IFS=: read -r o1 o2 o3 o4 o5 o6 <<< "$1" + +# Convert the four least significant bits of +# the first octet of the MAC address from hex +# to decimal. +o1_dec=$(( 16#"${o1:1:1}" )) + +# Loop through the four least significant bits of +# the first octet of the MAC address by shifting +# one bit to right and checking if the bit is set +# or not on each cycle starting from the least +# significant bit and moving towards the most +# significant bit. This will convert the second +# hex character of the MAC address reading from +# left to binary. +for (( n="$o1_dec"; n>0; n >>= 1 )); do + o1_bits="$(( n & 1 ))$o1_bits" +done + +# Prepend leading zeros if needed. +o1_bits=$(printf "%04d" "$o1_bits") + +# Flip the second-least-significant bit of the +# first octet of the MAC address and convert +# four bits back to hex digit. +flipped_bit=$(tr 01 10 <<< "${o1_bits:2:1}") +o1_bits="${o1_bits:0:2}$flipped_bit${o1_bits:3:1}" +o1_bits=$(printf "%x" $((2#"$o1_bits"))) + +# Finally, rebuild the first octet of the MAC address. +o1="${o1:0:1}$o1_bits" + + +# Build the hextets for the IPv6 link local address. +if [[ $o1 == 00 ]] && [[ $o2 == 00 ]]; then + h5="" +else + # Strip possible leading zeros. + h5="$(printf "%x:" "0x$o1$o2")" +fi + +if [[ $o3 == 00 ]]; then + h6="ff:" +else + h6="$(printf "%xff:" "0x$o3")" +fi + +h7="fe$o4:" + +h8="$(printf "%x" "0x$o5$o6")" + +printf "fe80::%s%s%s%s\n" "$h5" "$h6" "$h7" "$h8" diff --git a/conf/usr/local/bin/mcast_converter b/conf/usr/local/bin/mcast_converter new file mode 100755 index 0000000..662d1b3 --- /dev/null +++ b/conf/usr/local/bin/mcast_converter @@ -0,0 +1,75 @@ +#!/usr/bin/env bash + +# Title : mcast_converter +# Last modified date : 12.04.2023 +# Author : Martin Tonusoo +# Description : Script converts IPv4 multicast address to +# multicast MAC address or multicast MAC +# address to IPv4 multicast addresses depending +# on the input. +# Options : IPv4 multicast address or multicast MAC address. +# Notes : + + +# 224.0.0.0 - 239.255.255.255 +read -r mip_regex << EOF +^2(2[4-9]|3[0-9])\.\ +(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.\ +(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.\ +(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)$ +EOF + + +# 01:00:5e:00:00:00 - 01:00:5e:7f:ff:ff +read -r mac_regex << EOF +^01:00:5e:\ +([0-7][0-9a-f]):\ +([0-9a-f]{2}):\ +([0-9a-f]{2})$ +EOF + + +if [[ "$1" =~ $mip_regex ]]; then + + for (( n="${BASH_REMATCH[2]}"; n>0; n >>= 1 )); do + o2_bits="$(( n & 1 ))$o2_bits" + done + + printf -v o2_bits "%08d" "$o2_bits" + o2_bits="0${o2_bits:1}" + + printf "%s:%02x:%02x:%02x\n" \ + "01:00:5e" \ + "$(( 2#$o2_bits ))" \ + "${BASH_REMATCH[3]}" \ + "${BASH_REMATCH[4]}" + +elif [[ "$1" =~ $mac_regex ]]; then + + o4_dec=$(( 16#"${BASH_REMATCH[1]}" )) + + for (( n="$o4_dec"; n>0; n >>= 1 )); do + o4_bits="$(( n & 1 ))$o4_bits" + done + + printf -v o4_bits "%08d" "$o4_bits" + o4_bits="${o4_bits:1}" + + for bits in {0..1}{0..1}{0..1}{0..1}{0..1}; do + + printf "%d.%d.%d.%d\n" \ + $(( 2#"1110${bits:0:4}" )) \ + $(( 2#"${bits:4:1}$o4_bits" )) \ + $(( 16#"${BASH_REMATCH[2]}" )) \ + $(( 16#"${BASH_REMATCH[3]}" )) + + done + +else + + printf "%s\n%s\n" \ + "Invalid multicast MAC or IPv4 address" \ + "Examples: '${0##*/} 01:00:5e:00:99:0a' or '${0##*/} 239.1.2.100'" >&2 + exit 1 + +fi diff --git a/conf/usr/local/etc/IPv4_default_fw_rules b/conf/usr/local/etc/IPv4_default_fw_rules new file mode 100644 index 0000000..a0745a1 --- /dev/null +++ b/conf/usr/local/etc/IPv4_default_fw_rules @@ -0,0 +1,37 @@ +# Generated by xtables-save v1.8.2 on Tue Mar 28 12:43:45 2023 +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 12:43:45 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 12:43:45 2023 +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 12:43:45 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 12:43:45 2023 +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 12:43:45 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 12:43:45 2023 +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 12:43:45 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 12:43:45 2023 +*security +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 12:43:45 2023 diff --git a/conf/usr/local/etc/IPv4_fw_rules b/conf/usr/local/etc/IPv4_fw_rules new file mode 100644 index 0000000..a08acc2 --- /dev/null +++ b/conf/usr/local/etc/IPv4_fw_rules @@ -0,0 +1,62 @@ +# Generated by xtables-save v1.8.2 on Thu Mar 30 23:00:39 2023 +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A POSTROUTING -s 192.168.0.0/24 -o wan0 -j MASQUERADE +-A POSTROUTING -s 192.168.0.0/24 -o wwan0 -j MASQUERADE +COMMIT +# Completed on Thu Mar 30 23:00:39 2023 +# Generated by xtables-save v1.8.2 on Thu Mar 30 23:00:39 2023 +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:SSH - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -m conntrack --ctstate INVALID -j DROP +-A INPUT -p icmp -m icmp --icmp-type 8/0 -j ACCEPT +-A INPUT -p udp -m udp --dport 33434:33534 -m comment --comment "traceroute in UDP mode" -j REJECT --reject-with icmp-port-unreachable +-A INPUT -d 224.0.0.0/4 -i wan0.4 -p igmp -j ACCEPT +-A INPUT -i br0 -p tcp -m tcp --dport 22 -j SSH +-A INPUT -i br0 -p udp -m udp --sport 68 --dport 67 -j ACCEPT +-A INPUT -i br0 -p udp -m udp --dport 53 -j ACCEPT +-A INPUT -i br0 -p tcp -m tcp --dport 53 -j ACCEPT +-A INPUT -d 224.0.0.2/32 -i br0 -p igmp -j ACCEPT +-A FORWARD -i br0 -o wan0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i wan0 -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i br0 -o wwan0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i wwan0 -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i br0 -o wan0.4 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -m comment --comment "IPTV - unicast" -j ACCEPT +-A FORWARD -i wan0.4 -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "IPTV - unicast" -j ACCEPT +-A FORWARD -d 224.0.0.0/4 -i wan0.4 -o br0 -m comment --comment "IPTV - multicast" -j ACCEPT +-A SSH -m recent --set --name SSH --mask 255.255.255.255 --rsource +-A SSH -m recent --update --seconds 30 --hitcount 10 --name SSH --mask 255.255.255.255 --rsource -j LOG --log-prefix "SSH bruteforce: " +-A SSH -m recent --update --seconds 30 --hitcount 10 --name SSH --mask 255.255.255.255 --rsource -j DROP +-A SSH -j ACCEPT +COMMIT +# Completed on Thu Mar 30 23:00:39 2023 +# Generated by xtables-save v1.8.2 on Thu Mar 30 23:00:39 2023 +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Thu Mar 30 23:00:39 2023 +# Generated by xtables-save v1.8.2 on Thu Mar 30 23:00:39 2023 +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +# Completed on Thu Mar 30 23:00:39 2023 +# Generated by xtables-save v1.8.2 on Thu Mar 30 23:00:39 2023 +*security +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Thu Mar 30 23:00:39 2023 diff --git a/conf/usr/local/etc/IPv6_default_fw_rules b/conf/usr/local/etc/IPv6_default_fw_rules new file mode 100644 index 0000000..f64c3b9 --- /dev/null +++ b/conf/usr/local/etc/IPv6_default_fw_rules @@ -0,0 +1,37 @@ +# Generated by xtables-save v1.8.2 on Tue Mar 28 14:40:57 2023 +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 14:40:57 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 14:40:57 2023 +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 14:40:57 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 14:40:57 2023 +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 14:40:57 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 14:40:57 2023 +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 14:40:57 2023 +# Generated by xtables-save v1.8.2 on Tue Mar 28 14:40:57 2023 +*security +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Tue Mar 28 14:40:57 2023 diff --git a/conf/usr/local/etc/IPv6_fw_rules b/conf/usr/local/etc/IPv6_fw_rules new file mode 100644 index 0000000..1bd3e92 --- /dev/null +++ b/conf/usr/local/etc/IPv6_fw_rules @@ -0,0 +1,59 @@ +# Generated by xtables-save v1.8.2 on Fri Mar 31 17:02:25 2023 +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] +:SSH - [0:0] +-A INPUT -i lo -j ACCEPT +-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m limit --limit 10/sec -m comment --comment "Echo Request" -j ACCEPT +-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m comment --comment "Echo Request" -j DROP +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A INPUT -m conntrack --ctstate INVALID -j DROP +-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 135 -m hl --hl-eq 255 -m comment --comment "Neighbor Solicitation" -j ACCEPT +-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 136 -m hl --hl-eq 255 -m comment --comment "Neighbor Advertisement" -j ACCEPT +-A INPUT -i wan0 -p ipv6-icmp -m icmp6 --icmpv6-type 134 -m hl --hl-eq 255 -m comment --comment "Router Advertisement" -j ACCEPT +-A INPUT -i wan0 -p ipv6-icmp -m icmp6 --icmpv6-type 137 -m hl --hl-eq 255 -m comment --comment "Redirect" -j ACCEPT +-A INPUT -i wan0 -p udp -m udp --sport 547 --dport 546 -d fe80::/64 -m comment --comment "DHCPv6 server/relayagent -> DHCPv6 client" -j ACCEPT +-A INPUT -p udp -m udp --dport 33434:33534 -m comment --comment "traceroute in UDP mode" -j REJECT --reject-with icmp6-port-unreachable +-A INPUT -i br0 -p tcp -m tcp --dport 22 -m comment --comment "new SSH connections from LAN" -j SSH +-A INPUT -i br0 -p ipv6-icmp -m icmp6 --icmpv6-type 133 -m hl --hl-eq 255 -m comment --comment "Router Solicitation" -j ACCEPT +-A INPUT -i br0 -p udp -m udp --dport 53 -j ACCEPT +-A INPUT -i br0 -p tcp -m tcp --dport 53 -j ACCEPT +-A FORWARD -i br0 -o wan0 -m conntrack --ctstate NEW,RELATED,ESTABLISHED -j ACCEPT +-A FORWARD -i wan0 -o br0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A SSH -m recent --set --name SSH --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource +-A SSH -m recent --update --seconds 30 --hitcount 10 --name SSH --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -j LOG --log-prefix "SSH bruteforce: " +-A SSH -m recent --update --seconds 30 --hitcount 10 --name SSH --mask ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff --rsource -j DROP +-A SSH -j ACCEPT +COMMIT +# Completed on Fri Mar 31 17:02:25 2023 +# Generated by xtables-save v1.8.2 on Fri Mar 31 17:02:25 2023 +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Fri Mar 31 17:02:25 2023 +# Generated by xtables-save v1.8.2 on Fri Mar 31 17:02:25 2023 +*raw +:PREROUTING ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Fri Mar 31 17:02:25 2023 +# Generated by xtables-save v1.8.2 on Fri Mar 31 17:02:25 2023 +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT +# Completed on Fri Mar 31 17:02:25 2023 +# Generated by xtables-save v1.8.2 on Fri Mar 31 17:02:25 2023 +*security +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +COMMIT +# Completed on Fri Mar 31 17:02:25 2023 diff --git a/conf/usr/local/sbin/isp-switch b/conf/usr/local/sbin/isp-switch new file mode 100755 index 0000000..ddb931c --- /dev/null +++ b/conf/usr/local/sbin/isp-switch @@ -0,0 +1,114 @@ +#!/usr/bin/env bash + +# Title : isp-switch +# Last modified date : 30.05.2023 +# Author : Martin Tonusoo +# Description : Script pings anycast DNS servers IPv4 addresses +# using a primary connection(wan0; Telia fiber) and +# if none of those replies, then switches v4 default +# route to backup connection(wwan0; Telia mobile +# broadband). Once the primary connection restores, +# the v4 default route is switched back to primary +# connection. +# Options : +# Notes : "ignore_routes_with_linkdown" settings in +# /etc/sysctl.conf ensure that the route is +# instantly ignored if its link is down. + + +ping_check() { + + ping_success=0 + + for ip in 1.1.1.1 8.8.8.8 9.9.9.9; do + # Even if one ping out of four succeeds, then + # the exit code is 0. + ping -I "$1" -W 1 -c 4 -q "$ip" &>/dev/null + ping_success=$(( ping_success + $? )) + done + + if (( ping_success >= 3 )); then + # All 12 pings failed. + return 1 + else + return 0 + fi +} + + +read -r ip_regex << EOF +^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)\.){3}\ +(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]?|0)$ +EOF + + +while true; do + + sleep 1 + + read -r _ _ wan0_gw _ wan0_metric _ <<-EOF + $(ip -4 -o route show default dev wan0 2>/dev/null | grep -v " linkdown") + EOF + + read -r _ _ wwan0_gw _ wwan0_metric _ <<-EOF + $(ip -4 -o route show default dev wwan0 2>/dev/null | grep -v " linkdown") + EOF + + + # There is no point to proceed if both or one of the default + # routes is missing. In addition, sanity check the next hop + # address. + if ! { [[ "$wan0_gw" =~ $ip_regex ]] || [[ "$wwan0_gw" =~ $ip_regex ]]; }; then + + echo "No default route found." + continue + + elif ! [[ "$wan0_gw" =~ $ip_regex ]]; then + + echo "Primary default route via wan0 is missing." + continue + + elif ! [[ "$wwan0_gw" =~ $ip_regex ]]; then + + echo "Failover default route via wwan0 is missing." + continue + + fi + + + # Default IPv4 route metric is 0. + if (( ${wan0_metric:-0} < ${wwan0_metric:-0} )); then + + if ! ping_check wan0; then + + # Ping check on primary connection failed. + echo "Switching to backup via $wwan0_gw dev wwan0" + + ip -4 route flush default + ip -4 route add default via "$wwan0_gw" dev wwan0 metric 100 + ip -4 route add default via "$wan0_gw" dev wan0 metric 200 + fi + + else + # Backup connection is in use. Check if it is possible + # to switch back to primary connection. + ip -4 route add default via "$wan0_gw" table 100 + # Specifying the "priority" ensures that there are + # no duplicate rules created. + ip rule add oif wan0 lookup 100 priority 100 + + if ping_check wan0; then + + # Ping check on primary connection succeeded. + echo "Switching to primary via $wan0_gw dev wan0" + + ip -4 route flush default + ip -4 route add default via "$wan0_gw" dev wan0 metric 100 + ip -4 route add default via "$wwan0_gw" dev wwan0 metric 200 + fi + + ip -4 route flush table 100 + ip rule delete oif wan0 lookup 100 priority 100 + + fi +done diff --git a/conf/usr/local/sbin/rm-expired-prefixes b/conf/usr/local/sbin/rm-expired-prefixes new file mode 100755 index 0000000..94e42c3 --- /dev/null +++ b/conf/usr/local/sbin/rm-expired-prefixes @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# Title : rm-expired-prefixes +# Last modified date : 16.03.2023 +# Author : Martin Tonusoo +# Description : Script removes expired "prefix" statements from +# /etc/radvd.conf file based on the expiration +# field(ISO 8601 timestamp) at the end of "prefix" +# line. The expiration field is added to the "prefix" +# statements by dhclient exit hook. +# Options : +# Notes : + +radvd_conf="/etc/radvd.conf" +new_radvd_conf="${radvd_conf}.rm-expired-prefixes.$$" + +while IFS= read -r line; do + + case "$line" in + " prefix "*) + # Add the "prefix" statement if its timestamp + # is in the future. + if [[ "${line##* }" > $(date --iso-8601="seconds") ]]; then + echo "$line" + else + prefix="${line%% \{*}" + logger -t "rm-expired-prefixes" -p daemon.info \ + "INFO: Removed expired ${prefix# } from $radvd_conf" + fi + ;; + *) + echo "$line" + ;; + esac + +done < "$radvd_conf" >> "$new_radvd_conf" + +chown --reference="$radvd_conf" "$new_radvd_conf" +chmod --reference="$radvd_conf" "$new_radvd_conf" + +mv -f "$new_radvd_conf" "$radvd_conf" + +systemctl is-active --quiet radvd.service && systemctl reload radvd.service diff --git a/docs/DS-8085-02_SPS-34-24T-HP-TDFO.pdf b/docs/DS-8085-02_SPS-34-24T-HP-TDFO.pdf new file mode 100644 index 0000000..c5b169c Binary files /dev/null and b/docs/DS-8085-02_SPS-34-24T-HP-TDFO.pdf differ diff --git a/docs/Infineon-S25FL129P_128-Mbit_3.0_V_Flash_Memory-DataSheet-v11_00-EN.pdf b/docs/Infineon-S25FL129P_128-Mbit_3.0_V_Flash_Memory-DataSheet-v11_00-EN.pdf new file mode 100644 index 0000000..9e73544 Binary files /dev/null and b/docs/Infineon-S25FL129P_128-Mbit_3.0_V_Flash_Memory-DataSheet-v11_00-EN.pdf differ diff --git a/docs/eDiag_Eng_Manual.pdf b/docs/eDiag_Eng_Manual.pdf new file mode 100644 index 0000000..7d92928 Binary files /dev/null and b/docs/eDiag_Eng_Manual.pdf differ diff --git a/docs/netxtreme_ii.pdf b/docs/netxtreme_ii.pdf new file mode 100644 index 0000000..a7f4601 Binary files /dev/null and b/docs/netxtreme_ii.pdf differ diff --git a/docs/rooted_MA5671A_boot_messages.txt b/docs/rooted_MA5671A_boot_messages.txt new file mode 100644 index 0000000..8b2e2f2 --- /dev/null +++ b/docs/rooted_MA5671A_boot_messages.txt @@ -0,0 +1,180 @@ + +ROM: V1.1.4 +ROM: CFG 0x00000006 +ROM: SFLASH-4 +hw fuse format 1 + + +U-Boot 2011.12-lantiq-gpon-1.2.24 (Nov 03 2014 - 22:46:28), Build: falcon_sfp_linux + +Board: SFP +DRAM: 64 MiB +Now running in RAM - U-Boot at: 83fc8000 +SF: Detected S25FL129P_64K with page size 64 KiB, total 16 MiB +Chip: FALCON-S (A22) +Bootmode: 0x06 +Reset cause: Power-On Reset +CPU Clock: 400 MHz +Net: SGMII, SERDES [PRIME] +gpio: pin 105 (gpio 105) value is 0 +gpio: pin 106 (gpio 106) value is 1 +gpio: pin 107 (gpio 107) value is 1 +gpio: pin 108 (gpio 108) value is 1 +gpio: pin 3 (gpio 3) value is 1 +gpio: pin 109 (gpio 109) value is 1 +gpio: pin 110 (gpio 110) value is 1 +gpio: pin 423 (gpio 423) value is 0 +gpio: pin 422 (gpio 422) value is 0 +gpio: pin 325 (gpio 325) value is 0 +gpio: pin 402 (gpio 402) value is 0 +gpio: pin 424 (gpio 424) value is 0 +Press SPACE to delay and Ctrl-C to abort autoboot in 5 seconds +SF: Detected S25FL129P_64K with page size 64 KiB, total 16 MiB +## Booting kernel from Legacy Image at 80f00000 ... + Image Name: SFP_7.5.3 + Created: 2017-05-20 1:01:32 UTC + Image Type: MIPS Linux Kernel Image (lzma compressed) + Data Size: 1207793 Bytes = 1.2 MiB + Load Address: 80002000 + Entry Point: 80002000 + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK + +Starting kernel ... + +[ 0.000000] Linux version 3.10.49 (sean@Lantiq-DEV) (gcc version 4.8.3 (OpenWrt/Linaro GCC 4.8-2014.04 14.07_ltq) ) #1 Sat May 20 09:01:27 CST 2017 +[ 0.000000] SoC: Falcon rev A22 +[ 0.000000] bootconsole [early0] enabled +[ 0.000000] CPU revision is: 00019556 (MIPS 34Kc) +[ 0.000000] MIPS: machine is SFP - Lantiq Falcon SFP Stick +[ 0.000000] e=memsize=64 +[ 0.000000] e=initrd_start=0xA0000000 +[ 0.000000] e=initrd_size=0x0 +[ 0.000000] e=flash_start=0xB0000000 +[ 0.000000] e=flash_size=0x90844026 +[ 0.000000] e=ethaddr=10:c1:72:96:75:04 +[ 0.000000] MEMSIZE = 67108864 +[ 0.000000] Determined physical RAM map: +[ 0.000000] memory: 04000000 @ 00000000 (usable) +[ 0.000000] debug: ignoring loglevel setting. +[ 0.000000] User-defined physical RAM map: +[ 0.000000] memory: 03f00000 @ 00000000 (usable) +[ 0.000000] Initrd not found or empty - disabling initrd +[ 0.000000] Zone ranges: +[ 0.000000] Normal [mem 0x00000000-0x03efffff] +[ 0.000000] Movable zone start for each node +[ 0.000000] Early memory node ranges +[ 0.000000] node 0: [mem 0x00000000-0x03efffff] +[ 0.000000] On node 0 totalpages: 16128 +[ 0.000000] free_area_init_node: node 0, pgdat 80312610, node_mem_map 81003ec0 +[ 0.000000] Normal zone: 126 pages used for memmap +[ 0.000000] Normal zone: 0 pages reserved +[ 0.000000] Normal zone: 16128 pages, LIFO batch:3 +[ 0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes. +[ 0.000000] Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes +[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 +[ 0.000000] pcpu-alloc: [0] 0 +[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16002 +[ 0.000000] Kernel command line: rootfstype=squashfs,jffs2 ip=192.168.1.10:192.168.1.100:192.168.2.0:255.255.255.0:::off ethaddr=00:01:02:03:04:05 machtype=SFP ignore_loglevel vpe1_load_addr=0x83f00000 vpe1_mem=1M mem=63M mtdparts=sflash:256k(uboot)ro,512k(uboot_env),7424k(linux),8192k(image1) console=ttyLTQ0,115200 init=/etc/preinit +[ 0.000000] PID hash table entries: 256 (order: -2, 1024 bytes) +[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) +[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) +[ 0.000000] Writing ErrCtl register=00047340 +[ 0.000000] Readback ErrCtl register=00047340 +[ 0.000000] Memory: 60204k/64512k available (2587k kernel code, 4308k reserved, 664k data, 192k init, 0k highmem) +[ 0.000000] NR_IRQS:328 +[ 0.000000] Setting up vectored interrupts +[ 0.000000] CPU Clock: 400MHz +[ 0.000000] Calibrating delay loop... 265.98 BogoMIPS (lpj=531968) +[ 0.036000] pid_max: default: 32768 minimum: 301 +[ 0.040000] Mount-cache hash table entries: 512 +[ 0.048000] pinctrl core: initialized pinctrl subsystem +[ 0.052000] NET: Registered protocol family 16 +[ 0.072000] pinctrl-falcon pinctrl.4: Init done +[ 0.092000] bio: create slab at 0 +[ 0.096000] FALC(tm) ON GPIO Driver, (C) 2012 Lantiq Deutschland Gmbh +[ 0.104000] Switching to clocksource MIPS +[ 0.112000] NET: Registered protocol family 2 +[ 0.116000] TCP established hash table entries: 512 (order: 0, 4096 bytes) +[ 0.124000] TCP bind hash table entries: 512 (order: -1, 2048 bytes) +[ 0.128000] TCP: Hash tables configured (established 512 bind 512) +[ 0.136000] TCP: reno registered +[ 0.140000] UDP hash table entries: 256 (order: 0, 4096 bytes) +[ 0.144000] UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) +[ 0.152000] NET: Registered protocol family 1 +[ 0.156000] RPC: Registered named UNIX socket transport module. +[ 0.160000] RPC: Registered udp transport module. +[ 0.168000] RPC: Registered tcp transport module. +[ 0.172000] RPC: Registered tcp NFSv4.1 backchannel transport module. +[ 0.180000] EASY98000 LED driver, Version 1.0.1 (c) Copyright 2013, Lantiq Deutschland GmbH +[ 0.188000] Wired TLB entries for Linux read_c0_wired() = 0 +[ 0.196000] config3 0x2425 MT 1 +[ 0.196000] MVPControl 0x2, STLB 0 VPC 1 EVP 0 +[ 0.196000] mvpconf0 0xb8008403, PVPE 1 PTC 3 M 1 +[ 0.208000] squashfs: version 4.0 (2009/01/31) Phillip Lougher +[ 0.216000] jffs2: version 2.2 (NAND) (SUMMARY) (LZMA) (RTIME) (CMODE_PRIORITY) (c) 2001-2006 Red Hat, Inc. +[ 0.224000] msgmni has been set to 117 +[ 0.232000] io scheduler noop registered +[ 0.232000] io scheduler deadline registered (default) +[ 0.240000] 1e100c00.serial: ttyLTQ0 at MMIO 0x1e100c00 (irq = 104) is a lantiq,asc +[ 0.248000] console [ttyLTQ0] enabled, bootconsole disabled +[ 0.248000] console [ttyLTQ0] enabled, bootconsole disabled +[ 0.268000] m25p80 spi0.0: found s25fl129p1, expected s25fl129p0 +[ 0.272000] m25p80 spi0.0: s25fl129p1 (16384 Kbytes) +[ 0.276000] 4 cmdlinepart partitions found on MTD device sflash +[ 0.280000] Creating 4 MTD partitions on "sflash": +[ 0.288000] 0x000000000000-0x000000040000 : "uboot" +[ 0.292000] 0x000000040000-0x0000000c0000 : "uboot_env" +[ 0.300000] 0x0000000c0000-0x000000800000 : "linux" +[ 0.304000] 0x0000001e6e31-0x000000800000 : "rootfs" +[ 0.308000] mtd: partition "rootfs" must either start or end on erase block boundary or be smaller than an erase block -- forcing read-only +[ 0.324000] mtd: device 3 (rootfs) set to be root filesystem +[ 0.328000] mtd: partition "rootfs_data" created automatically, ofs=0x400000, len=0x400000 +[ 0.336000] 0x000000400000-0x000000800000 : "rootfs_data" +[ 0.344000] 0x000000800000-0x000001000000 : "image1" +[ 0.352000] wdt 1f8803f0.watchdog: Init done +[ 0.356000] TCP: cubic registered +[ 0.356000] NET: Registered protocol family 17 +[ 0.360000] 8021q: 802.1Q VLAN Support v1.8 +[ 12.424000] VFS: Mounted root (squashfs filesystem) readonly on device 31:3. +[ 12.428000] Freeing unused kernel memory: 192K (80330000 - 80360000) +procd: Console is alive +procd: - watchdog - +[ 15.312000] pps_core: LinuxPPS API ver. 1 registered +[ 15.316000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti +[ 15.328000] PTP clock support registered +procd: - preinit - +Press the [f] key and hit [enter] to enter failsafe mode +Press the [1], [2], [3] or [4] key and hit [enter] to select the debug level +jffs2 is ready +jffs2 is ready +[ 19.168000] jffs2: notice: (274) jffs2_build_xattr_subsystem: complete building xattr subsystem, 1 of xdatum (0 unchecked, 0 orphan) and 23 of xref (0 dead, 2 orphan) found. +switching to overlay +procd: - early - +procd: - watchdog - +procd: - ubus - +procd: - init - +Please press Enter to activate this console. +[ 21.360000] IFXOS, Version 1.6.6 (c) Copyright 2009, Lantiq Deutschland GmbH +[ 21.436000] NET: Registered protocol family 10 +[ 21.456000] GPON SFP I2C Slave Driver, Version 2.2.1 (c) Copyright 2015, Lantiq Beteiligungs-GmbH & Co. KG +[ 21.476000] [sfp_i2c] vpe code with size <4188 bytes> loaded! +[ 21.480000] VPE loader: VPE1 running successfully +[ 21.576000] FALC(tm) ON Optic Driver, version 7.5.1.0 (c) Copyright 2015, Lantiq Beteiligungs-GmbH & Co. KG +[ 22.040000] FALC(tm) ON Base Driver, Version 7.5.1.0 (c) Copyright 2015, Lantiq Beteiligungs-GmbH & Co. KG +[ 22.068000] FALC(tm) ON Ethernet Driver, Version 7.5.1.0 (c) Copyright 2015, Lantiq Beteiligungs-GmbH & Co. KG +[ 22.096000] mod_f24s: Unknown symbol skb_complete_tx_timestamp (err 0) +[ 22.108000] mod_f24s: Unknown symbol skb_complete_tx_timestamp (err 0) +MIPS: set unaligned_action to 'SHOW' + +[ 29.112000] i2c /dev entries driver +[ 29.136000] Custom GPIO-based I2C driver version 0.1.1 +[ 29.156000] i2c-gpio i2c-gpio.0: using pins 37 (SDA) and 38 (SCL) + + +BusyBox v1.22.1 (2017-05-20 08:54:30 CST) built-in shell (ash) +Enter 'help' for a list of built-in commands. + + OpenWrt - (14.07_ltq) --- Lantiq Edition for GPON + ---------------------------------------------- +root@SFP:/# diff --git a/igmpproxy_0.2.1-1+relaxed-timeout1_amd64.deb b/igmpproxy_0.2.1-1+relaxed-timeout1_amd64.deb new file mode 100644 index 0000000..82e218b Binary files /dev/null and b/igmpproxy_0.2.1-1+relaxed-timeout1_amd64.deb differ diff --git a/imgs/1224ABORT_hex_dump_compared_to_vanilla_U-boot.jpg b/imgs/1224ABORT_hex_dump_compared_to_vanilla_U-boot.jpg new file mode 100644 index 0000000..6521171 Binary files /dev/null and b/imgs/1224ABORT_hex_dump_compared_to_vanilla_U-boot.jpg differ diff --git a/imgs/Dell_N20KJ_with_NF-A4x10_fan.jpg b/imgs/Dell_N20KJ_with_NF-A4x10_fan.jpg new file mode 100644 index 0000000..ccb9766 Binary files /dev/null and b/imgs/Dell_N20KJ_with_NF-A4x10_fan.jpg differ diff --git a/imgs/HG8010H_status.jpg b/imgs/HG8010H_status.jpg new file mode 100644 index 0000000..f3e4c4e Binary files /dev/null and b/imgs/HG8010H_status.jpg differ diff --git a/imgs/HG8010H_telnet_cli.jpg b/imgs/HG8010H_telnet_cli.jpg new file mode 100644 index 0000000..cf206dd Binary files /dev/null and b/imgs/HG8010H_telnet_cli.jpg differ diff --git a/imgs/Huawei_GPON_OLT_CLI.jpg b/imgs/Huawei_GPON_OLT_CLI.jpg new file mode 100644 index 0000000..5bd4684 Binary files /dev/null and b/imgs/Huawei_GPON_OLT_CLI.jpg differ diff --git a/imgs/MA5671A_and_1000BASE-T_link_from_r1_and_rooted_MA5671A.jpg b/imgs/MA5671A_and_1000BASE-T_link_from_r1_and_rooted_MA5671A.jpg new file mode 100644 index 0000000..9082674 Binary files /dev/null and b/imgs/MA5671A_and_1000BASE-T_link_from_r1_and_rooted_MA5671A.jpg differ diff --git a/imgs/MA5671A_and_2500BASE-X_link_from_non-rooted_MA5671A.jpg b/imgs/MA5671A_and_2500BASE-X_link_from_non-rooted_MA5671A.jpg new file mode 100644 index 0000000..8a54b07 Binary files /dev/null and b/imgs/MA5671A_and_2500BASE-X_link_from_non-rooted_MA5671A.jpg differ diff --git a/imgs/MA5671A_and_2500BASE-X_link_from_r1.jpg b/imgs/MA5671A_and_2500BASE-X_link_from_r1.jpg new file mode 100644 index 0000000..655ede3 Binary files /dev/null and b/imgs/MA5671A_and_2500BASE-X_link_from_r1.jpg differ diff --git a/imgs/MA5671A_and_2500BASE-X_link_from_rooted_MA5671A.jpg b/imgs/MA5671A_and_2500BASE-X_link_from_rooted_MA5671A.jpg new file mode 100644 index 0000000..8844ba1 Binary files /dev/null and b/imgs/MA5671A_and_2500BASE-X_link_from_rooted_MA5671A.jpg differ diff --git a/imgs/MA5671A_and_CH341A_programmer.jpg b/imgs/MA5671A_and_CH341A_programmer.jpg new file mode 100644 index 0000000..03dce6e Binary files /dev/null and b/imgs/MA5671A_and_CH341A_programmer.jpg differ diff --git a/imgs/MA5671A_connected_to_reveltronics_board.jpg b/imgs/MA5671A_connected_to_reveltronics_board.jpg new file mode 100644 index 0000000..9433cc9 Binary files /dev/null and b/imgs/MA5671A_connected_to_reveltronics_board.jpg differ diff --git a/imgs/MA5671A_in_operation_state.jpg b/imgs/MA5671A_in_operation_state.jpg new file mode 100644 index 0000000..cc906a0 Binary files /dev/null and b/imgs/MA5671A_in_operation_state.jpg differ diff --git a/imgs/MA5671A_new_sfp_a2_info_prepared.jpg b/imgs/MA5671A_new_sfp_a2_info_prepared.jpg new file mode 100644 index 0000000..fba783e Binary files /dev/null and b/imgs/MA5671A_new_sfp_a2_info_prepared.jpg differ diff --git a/imgs/MA5671A_new_sfp_a2_info_written.jpg b/imgs/MA5671A_new_sfp_a2_info_written.jpg new file mode 100644 index 0000000..3d78b62 Binary files /dev/null and b/imgs/MA5671A_new_sfp_a2_info_written.jpg differ diff --git a/imgs/MA5671A_serial_in_sfp_a2_info.jpg b/imgs/MA5671A_serial_in_sfp_a2_info.jpg new file mode 100644 index 0000000..b75d148 Binary files /dev/null and b/imgs/MA5671A_serial_in_sfp_a2_info.jpg differ diff --git a/imgs/MA5671A_with_soldered_wires_to_flash.jpg b/imgs/MA5671A_with_soldered_wires_to_flash.jpg new file mode 100644 index 0000000..5d4bcc4 Binary files /dev/null and b/imgs/MA5671A_with_soldered_wires_to_flash.jpg differ diff --git a/imgs/NIC_fan_RPM_by_lm-sensors.jpg b/imgs/NIC_fan_RPM_by_lm-sensors.jpg new file mode 100644 index 0000000..ce179c2 Binary files /dev/null and b/imgs/NIC_fan_RPM_by_lm-sensors.jpg differ diff --git a/imgs/UEFI_eDiag_in_qemu_VM.jpg b/imgs/UEFI_eDiag_in_qemu_VM.jpg new file mode 100644 index 0000000..4aea0a7 Binary files /dev/null and b/imgs/UEFI_eDiag_in_qemu_VM.jpg differ diff --git a/imgs/UEFI_eDiag_in_qemu_VM_2_5G_settings.jpg b/imgs/UEFI_eDiag_in_qemu_VM_2_5G_settings.jpg new file mode 100644 index 0000000..e272153 Binary files /dev/null and b/imgs/UEFI_eDiag_in_qemu_VM_2_5G_settings.jpg differ diff --git a/imgs/UEFI_shell_in_qemu_VM.jpg b/imgs/UEFI_shell_in_qemu_VM.jpg new file mode 100644 index 0000000..6da52ba Binary files /dev/null and b/imgs/UEFI_shell_in_qemu_VM.jpg differ diff --git a/imgs/bnx2x_link_diff.jpg b/imgs/bnx2x_link_diff.jpg new file mode 100644 index 0000000..e308c00 Binary files /dev/null and b/imgs/bnx2x_link_diff.jpg differ diff --git a/imgs/brcmfmac_with_debug_functions.jpg b/imgs/brcmfmac_with_debug_functions.jpg new file mode 100644 index 0000000..1c7eb65 Binary files /dev/null and b/imgs/brcmfmac_with_debug_functions.jpg differ diff --git a/imgs/falcon_cli_after_modified_u-boot_upload.jpg b/imgs/falcon_cli_after_modified_u-boot_upload.jpg new file mode 100644 index 0000000..97fa075 Binary files /dev/null and b/imgs/falcon_cli_after_modified_u-boot_upload.jpg differ diff --git a/imgs/hostapd_cli_output.jpg b/imgs/hostapd_cli_output.jpg new file mode 100644 index 0000000..0baf93e Binary files /dev/null and b/imgs/hostapd_cli_output.jpg differ diff --git a/imgs/ip_link_brief.jpg b/imgs/ip_link_brief.jpg new file mode 100644 index 0000000..0adde9a Binary files /dev/null and b/imgs/ip_link_brief.jpg differ diff --git a/imgs/patching_the_bnx2x_driver.jpg b/imgs/patching_the_bnx2x_driver.jpg new file mode 100644 index 0000000..efd0022 Binary files /dev/null and b/imgs/patching_the_bnx2x_driver.jpg differ diff --git a/imgs/radvd_conf.jpg b/imgs/radvd_conf.jpg new file mode 100644 index 0000000..c6976d5 Binary files /dev/null and b/imgs/radvd_conf.jpg differ diff --git a/imgs/timedatectl_output.jpg b/imgs/timedatectl_output.jpg new file mode 100644 index 0000000..3074d7b Binary files /dev/null and b/imgs/timedatectl_output.jpg differ diff --git a/patches/bnx2x_link.patch b/patches/bnx2x_link.patch new file mode 100644 index 0000000..1e89080 --- /dev/null +++ b/patches/bnx2x_link.patch @@ -0,0 +1,114 @@ +--- bnx2x_link.c.orig 2023-01-08 22:05:36.052119774 +0200 ++++ bnx2x_link.c 2023-01-22 15:28:31.938666110 +0200 +@@ -151,6 +151,7 @@ typedef int (*read_sfp_module_eeprom_fun + + #define SFP_EEPROM_CON_TYPE_ADDR 0x2 + #define SFP_EEPROM_CON_TYPE_VAL_UNKNOWN 0x0 ++ #define SFP_EEPROM_CON_TYPE_VAL_SC 0x1 + #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 + #define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21 + #define SFP_EEPROM_CON_TYPE_VAL_RJ45 0x22 +@@ -196,6 +197,8 @@ typedef int (*read_sfp_module_eeprom_fun + #define DEFAULT_TX_DRV_POST2 3 + #define DEFAULT_TX_DRV_IPRE_DRIVER 6 + ++int sfp_tx_fault_ignore = 0; ++ + /**********************************************************/ + /* INTERFACE */ + /**********************************************************/ +@@ -4210,6 +4213,15 @@ static void bnx2x_warpcore_set_sgmii_spe + 0x1000); + DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n"); + } else { ++ /* Note that 2.5G works only when used with 1G advertisment */ ++ if (fiber_mode && ++ (phy->req_line_speed == SPEED_2500) && ++ (phy->speed_cap_mask & (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))) { ++ ++ bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x6010); ++ ++ } ++ + bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, + MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16); + val16 &= 0xcebf; +@@ -4220,6 +4232,7 @@ static void bnx2x_warpcore_set_sgmii_spe + val16 |= 0x2000; + break; + case SPEED_1000: ++ case SPEED_2500: + val16 |= 0x0040; + break; + default: +@@ -8173,6 +8186,7 @@ static int bnx2x_get_edc_mode(struct bnx + break; + } + case SFP_EEPROM_CON_TYPE_VAL_UNKNOWN: ++ case SFP_EEPROM_CON_TYPE_VAL_SC: + case SFP_EEPROM_CON_TYPE_VAL_LC: + case SFP_EEPROM_CON_TYPE_VAL_RJ45: + check_limiting_mode = 1; +@@ -8183,7 +8197,8 @@ static int bnx2x_get_edc_mode(struct bnx + (val[SFP_EEPROM_1G_COMP_CODE_ADDR] != 0)) { + DP(NETIF_MSG_LINK, "1G SFP module detected\n"); + phy->media_type = ETH_PHY_SFP_1G_FIBER; +- if (phy->req_line_speed != SPEED_1000) { ++ if ((phy->req_line_speed != SPEED_1000) && ++ (phy->req_line_speed != SPEED_2500)) { + u8 gport = params->port; + phy->req_line_speed = SPEED_1000; + if (!CHIP_IS_E1x(bp)) { +@@ -8325,6 +8340,25 @@ static int bnx2x_verify_sfp_module(struc + netdev_err(bp->dev, "Warning: Unqualified SFP+ module detected," + " Port %d from %s part number %s\n", + params->port, vendor_name, vendor_pn); ++ ++ /* While it is convenient, safe, avoids multiple ++ * EEPROM reads and works in case of HUAWEI ++ * MA5671A ONT as it's not an approved module, ++ * then this check should probably not be ++ * coupled with bnx2x_verify_sfp_module() ++ * function. ++ */ ++ if (!memcmp(vendor_name, "HUAWEI ", 16) && ++ !memcmp(vendor_pn, "MA5671A ", 16)) { ++ ++ sfp_tx_fault_ignore = 1; ++ ++ netdev_err(bp->dev, "Warning: Ignoring TX fault for transceiver " ++ " in port %d. Vendor: %s, part number: %s\n", ++ params->port, vendor_name, vendor_pn); ++ ++ } ++ + if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != + PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_WARNING_MSG) + phy->flags |= FLAGS_SFP_NOT_APPROVED; +@@ -11734,6 +11768,7 @@ static const struct bnx2x_phy phy_warpco + SUPPORTED_100baseT_Full | + SUPPORTED_1000baseT_Full | + SUPPORTED_1000baseKX_Full | ++ SUPPORTED_2500baseX_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_10000baseKR_Full | + SUPPORTED_20000baseKR2_Full | +@@ -12267,6 +12302,7 @@ static int bnx2x_populate_int_phy(struct + break; + case PORT_HW_CFG_NET_SERDES_IF_SFI: + phy->supported &= (SUPPORTED_1000baseT_Full | ++ SUPPORTED_2500baseX_Full | + SUPPORTED_10000baseT_Full | + SUPPORTED_FIBRE | + SUPPORTED_Pause | +@@ -13801,6 +13837,10 @@ static void bnx2x_sfp_tx_fault_detection + u32 cfg_pin, value = 0; + u8 led_change, port = params->port; + ++ if (sfp_tx_fault_ignore) { ++ return; ++ } ++ + /* Get The SFP+ TX_Fault controlling pin ([eg]pio) */ + cfg_pin = (REG_RD(bp, params->shmem_base + offsetof(struct shmem_region, + dev_info.port_hw_config[port].e3_cmn_pin_cfg)) & diff --git a/patches/igmpproxy.patch b/patches/igmpproxy.patch new file mode 100644 index 0000000..77ec549 --- /dev/null +++ b/patches/igmpproxy.patch @@ -0,0 +1,26 @@ +--- src/igmpproxy.c~ 2023-05-15 23:19:03.446584147 +0300 ++++ src/igmpproxy.c 2023-05-15 23:20:55.125401534 +0300 +@@ -263,7 +263,7 @@ + int MaxFD, Rt, secs; + fd_set ReadFDS; + socklen_t dummy = 0; +- struct timespec curtime, lasttime, difftime, tv; ++ struct timespec curtime, lasttime, difftime, tv, pselect_timeout; + // The timeout is a pointer in order to set it to NULL if nessecary. + struct timespec *timeout = &tv; + +@@ -306,8 +306,13 @@ + FD_ZERO( &ReadFDS ); + FD_SET( MRouterFD, &ReadFDS ); + ++ // https://github.com/pali/igmpproxy/issues/95 ++ memcpy(&pselect_timeout, timeout, sizeof(struct timespec)); ++ pselect_timeout.tv_sec *= 2; ++ my_log(LOG_DEBUG, 0, "Calling pselect() with %ld.%09ld seconds timeout", pselect_timeout.tv_sec, pselect_timeout.tv_nsec); ++ + // wait for input +- Rt = pselect( MaxFD +1, &ReadFDS, NULL, NULL, timeout, NULL ); ++ Rt = pselect( MaxFD +1, &ReadFDS, NULL, NULL, &pselect_timeout, NULL ); + + // log and ignore failures + if( Rt < 0 ) { diff --git a/uefi_ediag.tgz b/uefi_ediag.tgz new file mode 100644 index 0000000..2e63474 Binary files /dev/null and b/uefi_ediag.tgz differ