Install a missing network tool on demand via apt. Whitelisted packages only. The Ragnar service runs as root, so apt is invoked directly.
(tool)
| 1868 | return {'success': False, |
| 1869 | 'error': 'trusted and untrusted ports are not set — designate them first', |
| 1870 | 'need_config': True} |
| 1871 | |
| 1872 | members = [trusted, untrusted] |
| 1873 | packets, err = _dhcp_snoop_capture(members, seconds) |
| 1874 | if err: |
| 1875 | return {'success': False, 'error': err} |
| 1876 | |
| 1877 | reasons = [] |
| 1878 | rogue_msgs = [] # server messages seen on the untrusted port |
| 1879 | bindings = {} # chaddr -> latest binding |
| 1880 | servers = {} # server_id/ip -> {port, trusted} |
| 1881 | client_macs = set() |
| 1882 | |
| 1883 | for p in packets: |
| 1884 | on_trusted = p['iface'] == trusted |
| 1885 | if p['is_server'] and p['msg_type'] in _DHCP_SERVER_MSGS: |
| 1886 | sid = p.get('server_id') or p.get('src_ip') |
| 1887 | servers.setdefault(sid, {'port': p['iface'], |
| 1888 | 'trusted': on_trusted, |
| 1889 | 'router': p.get('router')}) |
| 1890 | if not on_trusted: |
| 1891 | rogue_msgs.append(p) |
| 1892 | if p['msg_type'] in ('offer', 'ack') and p.get('chaddr'): |
| 1893 | bindings[p['chaddr']] = { |
| 1894 | 'mac': p['chaddr'], 'ip': p.get('yiaddr'), |
| 1895 | 'server': sid, 'router': p.get('router'), |
| 1896 | 'lease': p.get('lease'), 'port': p['iface'], |
| 1897 | 'via': p['msg_type']} |
| 1898 | elif p['msg_type'] in _DHCP_CLIENT_MSGS and p.get('chaddr'): |
| 1899 | client_macs.add(p['chaddr']) |
| 1900 | |
| 1901 | rogue_servers = sorted({(m.get('server_id') or m['src_ip']) for m in rogue_msgs}) |
| 1902 | for sid in rogue_servers: |
| 1903 | info = servers.get(sid, {}) |
| 1904 | reasons.append(f"rogue DHCP server {sid} answering on the UNTRUSTED port " |
| 1905 | f"{untrusted}" + (f" (offers gateway {info.get('router')})" |
| 1906 | if info.get('router') else "") |
| 1907 | + " — a DHCP server must never appear on the client side") |
| 1908 | |
| 1909 | starvation = len(client_macs) |
| 1910 | if starvation >= _DHCP_STARV_MIN_CLIENTS: |
| 1911 | reasons.append(f"{starvation} distinct DHCP clients requested leases in " |
| 1912 | f"{seconds}s — starvation (pool-exhaustion) signature") |
no test coverage detected