From 843fc374ccd4cc375ec05b9ec5bd3a78c383cdb2 Mon Sep 17 00:00:00 2001 From: Min RK Date: Sat, 21 Sep 2024 22:47:09 +0200 Subject: [PATCH 1/2] don't include link-local (169.254) addresses in public_ips public_ips is meant to return addresses that might be connectable, which link-local are not --- jupyter_client/localinterfaces.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jupyter_client/localinterfaces.py b/jupyter_client/localinterfaces.py index 8e622f13..6ab3cbb5 100644 --- a/jupyter_client/localinterfaces.py +++ b/jupyter_client/localinterfaces.py @@ -87,7 +87,9 @@ def _populate_from_list(addrs: Sequence[str] | None) -> None: for ip in addrs: local_ips.append(ip) if not ip.startswith("127."): - public_ips.append(ip) + if not ip.startswith("169.254."): + # don't include link-local address in public_ips + public_ips.append(ip) elif not LOCALHOST: LOCALHOST = ip @@ -168,6 +170,9 @@ def _load_ips_psutil() -> None: addr = address_data.address if not (iface.startswith("lo") or addr.startswith("127.")): public_ips.append(addr) + elif addr.startswith("169.254."): + # don't include link-local address in public_ips + pass elif not LOCALHOST: LOCALHOST = addr local_ips.append(addr) @@ -198,6 +203,9 @@ def _load_ips_netifaces() -> None: continue if not (iface.startswith("lo") or addr.startswith("127.")): public_ips.append(addr) + elif addr.startswith("169.254."): + # don't include link-local address in public_ips + pass elif not LOCALHOST: LOCALHOST = addr local_ips.append(addr) From 965c25ba1f016f0f545f8d2bfe4828b685b150ad Mon Sep 17 00:00:00 2001 From: Min RK Date: Sun, 22 Sep 2024 08:59:14 +0200 Subject: [PATCH 2/2] consolidate netifaces/psutil into _populate_from_dict where dict is like `{"en0": ["1.2.3.4"]}` --- jupyter_client/localinterfaces.py | 84 ++++++++++++------------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/jupyter_client/localinterfaces.py b/jupyter_client/localinterfaces.py index 6ab3cbb5..e257b26f 100644 --- a/jupyter_client/localinterfaces.py +++ b/jupyter_client/localinterfaces.py @@ -8,11 +8,11 @@ import socket import subprocess from subprocess import PIPE, Popen -from typing import Any, Callable, Iterable, Sequence +from typing import Any, Callable, Iterable, Mapping, Sequence from warnings import warn -LOCAL_IPS: list = [] -PUBLIC_IPS: list = [] +LOCAL_IPS: list[str] = [] +PUBLIC_IPS: list[str] = [] LOCALHOST: str = "" @@ -75,29 +75,34 @@ class NoIPAddresses(Exception): # noqa pass -def _populate_from_list(addrs: Sequence[str] | None) -> None: +def _populate_from_list(addrs: Sequence[str]) -> None: """populate local and public IPs from flat list of all IPs""" + _populate_from_dict({"all": addrs}) + + +def _populate_from_dict(addrs: Mapping[str, Sequence[str]]) -> None: + """populate local and public IPs from dict of {'en0': 'ip'}""" if not addrs: - raise NoIPAddresses + raise NoIPAddresses() global LOCALHOST public_ips = [] local_ips = [] - for ip in addrs: - local_ips.append(ip) - if not ip.startswith("127."): - if not ip.startswith("169.254."): + for iface, ip_list in addrs.items(): + for ip in ip_list: + local_ips.append(ip) + if not LOCALHOST and (iface.startswith("lo") or ip.startswith("127.")): + LOCALHOST = ip + if not iface.startswith("lo") and not ip.startswith(("127.", "169.254.")): # don't include link-local address in public_ips public_ips.append(ip) - elif not LOCALHOST: - LOCALHOST = ip if not LOCALHOST or LOCALHOST == "127.0.0.1": LOCALHOST = "127.0.0.1" local_ips.insert(0, LOCALHOST) - local_ips.extend(["0.0.0.0", ""]) # noqa + local_ips.extend(["0.0.0.0", ""]) # noqa: S104 LOCAL_IPS[:] = _uniq_stable(local_ips) PUBLIC_IPS[:] = _uniq_stable(public_ips) @@ -157,65 +162,38 @@ def _load_ips_psutil() -> None: """load ip addresses with netifaces""" import psutil - global LOCALHOST - local_ips = [] - public_ips = [] + addr_dict: dict[str, list[str]] = {} # dict of iface_name: address_list, eg # {"lo": [snicaddr(family=, address="127.0.0.1", # ...), snicaddr(family=, ...)]} for iface, ifaddresses in psutil.net_if_addrs().items(): - for address_data in ifaddresses: - if address_data.family == socket.AF_INET: - addr = address_data.address - if not (iface.startswith("lo") or addr.startswith("127.")): - public_ips.append(addr) - elif addr.startswith("169.254."): - # don't include link-local address in public_ips - pass - elif not LOCALHOST: - LOCALHOST = addr - local_ips.append(addr) - if not LOCALHOST: - # we never found a loopback interface (can this ever happen?), assume common default - LOCALHOST = "127.0.0.1" - local_ips.insert(0, LOCALHOST) - local_ips.extend(["0.0.0.0", ""]) # noqa - LOCAL_IPS[:] = _uniq_stable(local_ips) - PUBLIC_IPS[:] = _uniq_stable(public_ips) + addr_dict[iface] = [ + address_data.address + for address_data in ifaddresses + if address_data.family == socket.AF_INET + ] + + _populate_from_dict(addr_dict) def _load_ips_netifaces() -> None: """load ip addresses with netifaces""" import netifaces # type: ignore[import-not-found] - global LOCALHOST - local_ips = [] - public_ips = [] + addr_dict: dict[str, list[str]] = {} # list of iface names, 'lo0', 'eth0', etc. for iface in netifaces.interfaces(): # list of ipv4 addrinfo dicts + addr_dict[iface] = [] + ipv4s = netifaces.ifaddresses(iface).get(netifaces.AF_INET, []) for entry in ipv4s: addr = entry.get("addr") - if not addr: - continue - if not (iface.startswith("lo") or addr.startswith("127.")): - public_ips.append(addr) - elif addr.startswith("169.254."): - # don't include link-local address in public_ips - pass - elif not LOCALHOST: - LOCALHOST = addr - local_ips.append(addr) - if not LOCALHOST: - # we never found a loopback interface (can this ever happen?), assume common default - LOCALHOST = "127.0.0.1" - local_ips.insert(0, LOCALHOST) - local_ips.extend(["0.0.0.0", ""]) # noqa - LOCAL_IPS[:] = _uniq_stable(local_ips) - PUBLIC_IPS[:] = _uniq_stable(public_ips) + if addr: + addr_dict[iface].append(addr) + _populate_from_dict(addr_dict) def _load_ips_gethostbyname() -> None: