commit hplip for openSUSE:Factory
Hello community,
here is the log from the commit of package hplip for openSUSE:Factory checked in at 2016-08-31 14:27:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hplip (Old)
and /work/SRC/openSUSE:Factory/.hplip.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hplip"
Changes:
--------
--- /work/SRC/openSUSE:Factory/hplip/hplip.changes 2016-07-01 09:50:44.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.hplip.new/hplip.changes 2016-08-31 14:27:44.000000000 +0200
@@ -1,0 +2,8 @@
+Fri Aug 26 15:13:30 UTC 2016 - martin.wilck@suse.com
+
+- Fixed device communication/detection problems with mdns/Bonjour
+ * added hplip-mdns.patch (MDNS send/receive on every iterface)
+ * added hplip-mdns-retry-query.patch (MDNS retry)
+ See https://bugs.launchpad.net/hplip/+bug/1616861
+
+-------------------------------------------------------------------
New:
----
hplip-mdns-retry-query.patch
hplip-mdns.patch
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ hplip.spec ++++++
--- /var/tmp/diff_new_pack.yhrzBK/_old 2016-08-31 14:27:45.000000000 +0200
+++ /var/tmp/diff_new_pack.yhrzBK/_new 2016-08-31 14:27:45.000000000 +0200
@@ -56,6 +56,10 @@
# Patch108 add_missing_includes_and_define_GNU_SOURCE.patch adds missing '#include <...>'
# and missing '#define _GNU_SOURCE' see https://bugs.launchpad.net/hplip/+bug/1456590
Patch108: add_missing_includes_and_define_GNU_SOURCE.patch
+# Patch200 fixes device communication and detection via MDNS in some network setups:
+Patch200: hplip-mdns.patch
+# Patch201 makes MDNS lookups more robust by retrying queries:
+Patch201: hplip-mdns-retry-query.patch
# HPLIP's Python module cupsext.so has a build-time dependancy on the CUPS version:
# It needs symbols (like ippFirstAttribute, ippNextAttribute, ippSetOperation etc)
# that are defined only in libcups.so version > 1.5. For backward compatibility
@@ -350,6 +354,8 @@
# Patch108 add_missing_includes_and_define_GNU_SOURCE.patch adds missing '#include <...>'
# and missing '#define _GNU_SOURCE' see https://bugs.launchpad.net/hplip/+bug/1456590
%patch108 -p1 -b .add_missing_includes_and_define_GNU_SOURCE.orig
+%patch200 -p1 -b .mdns
+%patch201 -p1 -b .mdns-retry
%build
# If AUTOMAKE='automake --foreign' is not set, autoreconf (in fact automake)
@@ -407,7 +413,8 @@
--with-drvdir=%{_libexecdir}/cups/driver \
--with-mimedir=%{_sysconfdir}/cups \
--with-docdir=%{_defaultdocdir}/%{name} \
- --with-htmldir==%{_defaultdocdir}/%{name}
+ --with-htmldir==%{_defaultdocdir}/%{name} \
+ CFLAGS='%{optflags}'
make
%install
++++++ hplip-mdns-retry-query.patch ++++++
diff --git a/protocol/discovery/mdns.c b/protocol/discovery/mdns.c
index 92e153a..75ef0ea 100644
--- a/protocol/discovery/mdns.c
+++ b/protocol/discovery/mdns.c
@@ -436,7 +436,7 @@ static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvb
FD_SET(udp_socket, &master);
maxfd = udp_socket;
tmo.tv_sec = 0;
- tmo.tv_usec = 300000;
+ tmo.tv_usec = 10000;
readfd = master;
ret = select(maxfd + 1, &readfd, NULL, NULL, &tmo);
@@ -549,6 +549,34 @@ static void mdns_rr_cleanup(DNS_RECORD *rr)
}
}
+static DNS_RECORD* send_and_receive(struct mdns_socket *mdns_sock,
+ const char *name,
+ int query_type, int read_mode)
+{
+ /* wait up to ~1s */
+ const useconds_t DELTA_T = 251000;
+ const int RETRIES = 8;
+ int retry = RETRIES;
+ DNS_RECORD *rr_list;
+
+ while (retry) {
+ if (mdns_send_query(mdns_sock, name, query_type) == MDNS_STATUS_OK) {
+ rr_list = mdns_read_responses(mdns_sock->socket, read_mode, name);
+ if (rr_list != NULL) {
+ DBG("send_and_receive: got response after %d retries\n",
+ RETRIES - retry);
+ return rr_list;
+ }
+ }
+ /* MDNS servers delay responses. If the server just responded
+ * to some query (maybe an earlier one we sent), we may need to wait. */
+ --retry;
+ usleep(DELTA_T);
+ }
+ BUG("send_and_receive: no response after %d retries\n", RETRIES);
+ return NULL;
+}
+
int mdns_probe_nw_scanners(char* uris_buf, int buf_size, int *count)
{
int n = 0, bytes_read = 0;
@@ -562,11 +590,7 @@ int mdns_probe_nw_scanners(char* uris_buf, int buf_size, int *count)
if (mdns_open_socket(&mdns_sock) != MDNS_STATUS_OK)
goto bugout;
- /* Send dns query */
- mdns_send_query(&mdns_sock, scanner_name, QTYPE_PTR);
-
- /* Read Responses */
- rr_list = mdns_read_responses(mdns_sock.socket, MODE_READ_ALL, scanner_name);
+ rr_list = send_and_receive(&mdns_sock, scanner_name, QTYPE_PTR, MODE_READ_ALL);
/* Update URIs buffer */
bytes_read = mdns_update_uris(rr_list, uris_buf, buf_size, count);
@@ -598,10 +622,8 @@ int mdns_lookup(char* hostname, unsigned char* ip)
/* Send dns query */
sprintf(fqdn, "%s.local", hostname);
- mdns_send_query(&mdns_sock, fqdn, QTYPE_A);
- /* Read Responses */
- rr_list = mdns_read_responses(mdns_sock.socket, MODE_READ_SINGLE, fqdn);
+ rr_list = send_and_receive(&mdns_sock, fqdn, QTYPE_A, MODE_READ_SINGLE);
/* Update IP Address buffer */
if(rr_list)
diff --git a/protocol/discovery/mdns.h b/protocol/discovery/mdns.h
index 34066fb..56d8847 100644
--- a/protocol/discovery/mdns.h
+++ b/protocol/discovery/mdns.h
@@ -102,5 +102,8 @@ static int mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr);
static void mdns_rr_cleanup(DNS_RECORD *rr);
static DNS_RECORD *mdns_read_responses(int udp_socket, int mode, const char *question);
static unsigned char* mdns_readMDL(unsigned char *p, unsigned char *normalized_mdl, int len);
+static DNS_RECORD* send_and_receive(struct mdns_socket *mdns_sock, const char *name,
+ int query_type, int read_mode);
+static int get_ipv4_address(const char *iface, struct in_addr *addr);
#endif // _DISCOVERY_MDNS_H
++++++ hplip-mdns.patch ++++++
diff --git a/base/mdns.py b/base/mdns.py
index 03bdb92..11d08b8 100644
--- a/base/mdns.py
+++ b/base/mdns.py
@@ -35,6 +35,17 @@ from .g import *
from . import utils
from .sixext import BytesIO, to_bytes_utf8, to_bytes_latin, to_string_latin
+if hasattr(socket, "if_nameindex"):
+ if_nameindex = socket.if_nameindex
+else:
+ def _if_nameindex():
+ """"Poor man's if_nameindex for Python 2."""
+ import os
+ sysdir = "/sys/class/net"
+ return sorted([ (int(open("%s/%s/ifindex" % (sysdir, iface), "r").read(), 0), iface)
+ for iface in os.listdir(sysdir) ])
+ if_nameindex = _if_nameindex
+
MAX_ANSWERS_PER_PACKET = 24
QTYPE_A = 1
@@ -45,6 +56,8 @@ QTYPE_PTR = 12
QCLASS_IN = 1
+MCAST_ADDR='224.0.0.251'
+
# Caller needs to ensure, data should be in string format.
def read_utf8(offset, data, l):
return offset+l, data[offset:offset+l]
@@ -188,11 +201,6 @@ def createSocketsWithsetOption(ttl=4):
s=None
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
- x = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- x.connect(('1.2.3.4', 56))
- intf = x.getsockname()[0]
- x.close()
-
s.setblocking(0)
ttl = struct.pack('B', ttl)
except socket.error:
@@ -209,14 +217,42 @@ def createSocketsWithsetOption(ttl=4):
try:
s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_TTL, ttl)
- s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, socket.inet_aton(intf) + socket.inet_aton('0.0.0.0'))
s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_LOOP ,1)
except Exception as e:
log.error("Unable to setup multicast socket for mDNS: %s" % e)
if s:
s.close()
return None
- return s
+
+ ifaces = []
+ for idx, name in if_nameindex():
+ mreqn = struct.pack("=4sii", socket.inet_aton(MCAST_ADDR),
+ socket.ntohl(socket.INADDR_ANY), idx)
+ try:
+ s.setsockopt(socket.SOL_IP, socket.IP_ADD_MEMBERSHIP, mreqn)
+ except Exception as e:
+ log.debug("Failed to join multicast group on interface %s: %s" %
+ (name, e))
+ else:
+ log.debug("Joined multicast group on interface %s" % name)
+ ifaces.append((idx, name))
+
+ if len(ifaces) == 0:
+ log.error("failed to join multicast group on any interface")
+ s.close()
+ return None
+
+ return (s, ifaces)
+
+def closeSocket(s):
+ for idx, name in if_nameindex():
+ mreqn = struct.pack("=4sii", socket.inet_aton(MCAST_ADDR),
+ socket.ntohl(socket.INADDR_ANY), idx)
+ try:
+ s.setsockopt(socket.SOL_IP, socket.IP_DROP_MEMBERSHIP, mreqn)
+ except Exception:
+ pass
+ s.close()
def updateReceivedData(data, answers):
update_spinner()
@@ -299,13 +335,22 @@ def updateReceivedData(data, answers):
break
return y, answers
+def send_packets(s, answers, name, mcast_addr, mcast_port):
+ for p in create_outgoing_packets(answers):
+ log.debug("Outgoing on %s: (%d)" % (name, len(p)))
+ log.log_data(p, width=16)
+ try:
+ s.sendto(p, 0, (mcast_addr, mcast_port))
+ except socket.error as e:
+ log.debug("Unable to send broadcast DNS packet on %s: %s" % (name, e))
+ raise
def detectNetworkDevices(ttl=4, timeout=10):
- mcast_addr, mcast_port ='224.0.0.251', 5353
+ mcast_addr, mcast_port =MCAST_ADDR, 5353
found_devices = {}
answers = []
- s = createSocketsWithsetOption(ttl)
+ s, ifaces = createSocketsWithsetOption(ttl)
if not s:
return {}
@@ -321,14 +366,24 @@ def detectNetworkDevices(ttl=4, timeout=10):
break
if now >= next:
- try:
- for p in create_outgoing_packets(answers):
- log.debug("Outgoing: (%d)" % len(p))
- log.log_data(p, width=16)
- s.sendto(p, 0, (mcast_addr, mcast_port))
+ good = []
+ for idx, name in ifaces:
+ mreqn = struct.pack("=4sii", socket.inet_aton(mcast_addr),
+ socket.ntohl(socket.INADDR_ANY), idx)
+ try:
+ s.setsockopt(socket.SOL_IP, socket.IP_MULTICAST_IF, mreqn)
+ except socket.error as e:
+ log.debug("failed to set IP_MULTICAST_IF on %s" % name)
+ continue
+ try:
+ send_packets(s, answers, name, mcast_addr, mcast_port)
+ except socket.error:
+ continue
+ else:
+ good.append((idx, name))
- except socket.error as e:
- log.error("Unable to send broadcast DNS packet: %s" % e)
+ if len(good) == 0:
+ log.error("Failed to send MDNS packet on any interface")
next += delay
delay *= 2
@@ -347,7 +402,5 @@ def detectNetworkDevices(ttl=4, timeout=10):
found_devices[y['ip']] = y
log.debug("Found %d devices" % len(found_devices))
- s.close()
+ closeSocket(s)
return found_devices
-
-
diff --git a/protocol/discovery/mdns.c b/protocol/discovery/mdns.c
index 3324d2a..92e153a 100644
--- a/protocol/discovery/mdns.c
+++ b/protocol/discovery/mdns.c
@@ -1,3 +1,4 @@
+
/*****************************************************************************
mdns.c - mDNS related calls
@@ -29,14 +30,17 @@
#endif
#include
participants (1)
-
root@hilbert.suse.de