Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions tests/services/test_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,8 @@ def test_service_info_rejects_expired_records(self):
assert info.properties[b"ci"] == b"2"
zc.close()

@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_get_info_partial(self):

zc = r.Zeroconf(interfaces=['127.0.0.1'])
Expand Down Expand Up @@ -576,6 +578,8 @@ async def test_multiple_a_addresses():
await aiozc.async_close()


@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_filter_address_by_type_from_service_info():
"""Verify dns_addresses can filter by ipversion."""
desc = {'path': '/~paulsm/'}
Expand Down
6 changes: 5 additions & 1 deletion tests/test_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import asyncio
import logging
import os
import socket
import time
import threading
Expand Down Expand Up @@ -32,7 +33,7 @@
from zeroconf._services.info import ServiceInfo
from zeroconf._utils.time import current_time_millis

from . import _clear_cache
from . import _clear_cache, has_working_ipv6

log = logging.getLogger('zeroconf')
original_logging_level = logging.NOTSET
Expand Down Expand Up @@ -349,6 +350,9 @@ async def test_async_wait_unblocks_on_update() -> None:
@pytest.mark.asyncio
async def test_service_info_async_request() -> None:
"""Test registering services broadcasts and query with AsyncServceInfo.async_request."""
if not has_working_ipv6() or os.environ.get('SKIP_IPV6'):
pytest.skip('Requires IPv6')

aiozc = AsyncZeroconf(interfaces=['127.0.0.1'])
type_ = "_test1-srvc-type._tcp.local."
name = "xxxyyy"
Expand Down
5 changes: 5 additions & 0 deletions tests/test_dns.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
""" Unit tests for zeroconf._dns. """

import logging
import os
import socket
import time
import unittest
Expand All @@ -18,6 +19,8 @@
ServiceInfo,
)

from . import has_working_ipv6

log = logging.getLogger('zeroconf')
original_logging_level = logging.NOTSET

Expand Down Expand Up @@ -52,6 +55,8 @@ def test_dns_pointer_repr(self):
pointer = r.DNSPointer('irrelevant', const._TYPE_PTR, const._CLASS_IN, const._DNS_OTHER_TTL, '123')
repr(pointer)

@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_dns_address_repr(self):
address = r.DNSAddress('irrelevant', const._TYPE_SOA, const._CLASS_IN, 1, b'a')
assert repr(address).endswith("b'a'")
Expand Down
9 changes: 8 additions & 1 deletion tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import asyncio
import logging
import os
import pytest
import socket
import time
Expand All @@ -19,7 +20,7 @@
from zeroconf.asyncio import AsyncZeroconf


from . import _clear_cache, _inject_response
from . import _clear_cache, _inject_response, has_working_ipv6

log = logging.getLogger('zeroconf')
original_logging_level = logging.NOTSET
Expand Down Expand Up @@ -274,6 +275,8 @@ def test_ptr_optimization():
zc.close()


@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_any_query_for_ptr():
"""Test that queries for ANY will return PTR records."""
zc = Zeroconf(interfaces=['127.0.0.1'])
Expand Down Expand Up @@ -301,6 +304,8 @@ def test_any_query_for_ptr():
zc.close()


@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_aaaa_query():
"""Test that queries for AAAA records work."""
zc = Zeroconf(interfaces=['127.0.0.1'])
Expand All @@ -326,6 +331,8 @@ def test_aaaa_query():
zc.close()


@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_a_and_aaaa_record_fate_sharing():
"""Test that queries for AAAA always return A records in the additionals."""
zc = Zeroconf(interfaces=['127.0.0.1'])
Expand Down
5 changes: 5 additions & 0 deletions tests/test_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import copy
import logging
import os
import socket
import struct
import unittest
Expand All @@ -18,6 +19,8 @@
DNSText,
)

from . import has_working_ipv6

log = logging.getLogger('zeroconf')
original_logging_level = logging.NOTSET

Expand Down Expand Up @@ -468,6 +471,8 @@ def test_incoming_circular_reference(self):
)
).valid

@unittest.skipIf(not has_working_ipv6(), 'Requires IPv6')
@unittest.skipIf(os.environ.get('SKIP_IPV6'), 'IPv6 tests disabled')
def test_incoming_ipv6(self):
addr = "2606:2800:220:1:248:1893:25c8:1946" # example.com
packed = socket.inet_pton(socket.AF_INET6, addr)
Expand Down
4 changes: 4 additions & 0 deletions tests/utils/test_net.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,10 @@ def test_add_multicast_member():
with patch("socket.socket.setsockopt", side_effect=OSError(errno.ENODEV, None)):
assert netutils.add_multicast_member(sock, ('2001:db8::', 1, 1)) is False

# No IPv6 support should return False for IPv6
with patch("socket.inet_pton", side_effect=OSError()):
assert netutils.add_multicast_member(sock, ('2001:db8::', 1, 1)) is False

# No error should return True
with patch("socket.socket.setsockopt"):
assert netutils.add_multicast_member(sock, interface) is True
15 changes: 12 additions & 3 deletions zeroconf/_utils/net.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import ifaddr

from .._logger import log
from ..const import _IPPROTO_IPV6, _MDNS_ADDR6_BYTES, _MDNS_ADDR_BYTES, _MDNS_PORT
from ..const import _IPPROTO_IPV6, _MDNS_ADDR, _MDNS_ADDR6, _MDNS_PORT


@enum.unique
Expand Down Expand Up @@ -259,11 +259,20 @@ def add_multicast_member(
log.debug('Adding %r (socket %d) to multicast group', interface, listen_socket.fileno())
try:
if is_v6:
try:
mdns_addr6_bytes = socket.inet_pton(socket.AF_INET6, _MDNS_ADDR6)
except OSError:
log.info(
'Unable to translate IPv6 address when adding %s to multicast group, '
'this can happen if IPv6 is disabled on the system',
interface,
)
return False
iface_bin = struct.pack('@I', cast(int, interface[1]))
_value = _MDNS_ADDR6_BYTES + iface_bin
_value = mdns_addr6_bytes + iface_bin
listen_socket.setsockopt(_IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, _value)
else:
_value = _MDNS_ADDR_BYTES + socket.inet_aton(cast(str, interface))
_value = socket.inet_aton(_MDNS_ADDR) + socket.inet_aton(cast(str, interface))
listen_socket.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, _value)
except socket.error as e:
_errno = get_errno(e)
Expand Down
4 changes: 0 additions & 4 deletions zeroconf/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
USA
"""

import contextlib
import re
import socket

Expand All @@ -44,10 +43,7 @@
# Some DNS constants

_MDNS_ADDR = '224.0.0.251'
_MDNS_ADDR_BYTES = socket.inet_aton(_MDNS_ADDR)
_MDNS_ADDR6 = 'ff02::fb'
with contextlib.suppress(OSError): # can't use AF_INET6, IPv6 is disabled
_MDNS_ADDR6_BYTES = socket.inet_pton(socket.AF_INET6, _MDNS_ADDR6)
Comment thread
bdraco marked this conversation as resolved.
_MDNS_PORT = 5353
_DNS_PORT = 53
_DNS_HOST_TTL = 120 # two minute for host records (A, SRV etc) as-per RFC6762
Expand Down