2d6bd814e6
- Fixed device communication/detection problems with mdns/Bonjour see https://bugs.launchpad.net/hplip/+bug/1616861 In my home network, the HP printer/scanner (ENVY 5530) often fails with messages like this: hp-toolbox[7119]: [7119]: error: Unable to communicate with device (code=12): hp:/net/ENVY_5530_series?zc=HP3464A9E628B4 I've tracked this down to two problems with the MDNS implementation in HPLIP: 1. On a multi-homed host, HPLIP uses only one interface for MDNS multicast send and receive. This leads to failure if the printer is not on the "default" network. The code uses just INADDR_ANY in its multicast IP_MULTPATH_IF and IP_ADD_MEMBERSHIP setsockopt calls, meaning that the kernel has to figure out the interface to use. This fails if the system has no default route, or if the HP device is on a different network than the default route. The solution is to receive and send multicast on all interfaces. 2. MDNS authorities (including HP printers) don't answer every query, especially the same query is repeated quickly. The latter happens when the HP tools start, causing the MDNS lookup procedure to fail and the "communication error" to be detected. This can be solved by retrying the query after a short wait (1-2s). This build contains fixes for both problems. OBS-URL: https://build.opensuse.org/request/show/423113 OBS-URL: https://build.opensuse.org/package/show/Printing/hplip?expand=0&rev=128
554 lines
18 KiB
Diff
554 lines
18 KiB
Diff
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 <stdio.h>
|
|
+#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <syslog.h>
|
|
#include <sys/socket.h>
|
|
#include <netinet/in.h>
|
|
#include <netdb.h>
|
|
#include <arpa/inet.h>
|
|
+#include <net/if.h>
|
|
#include "mdns.h"
|
|
#include <unistd.h>
|
|
+#include <sys/ioctl.h>
|
|
|
|
/* Convert "www.google.com" to "3www6google3com". */
|
|
static int mdns_convert_name_to_dns(const char *name, int name_size, char *dns_name)
|
|
@@ -71,14 +75,50 @@ static int mdns_convert_name_to_dns(const char *name, int name_size, char *dns_n
|
|
return x; /* return length DOES include null termination */
|
|
}
|
|
|
|
+#define MREQN_INIT(_mr, index) do { \
|
|
+ (&(_mr))->imr_multiaddr.s_addr = inet_addr("224.0.0.251"); \
|
|
+ (&(_mr))->imr_address.s_addr = htonl(INADDR_ANY); \
|
|
+ (&(_mr))->imr_ifindex = (index); \
|
|
+ } while(0)
|
|
+
|
|
+struct mdns_socket {
|
|
+ int socket;
|
|
+ struct if_nameindex *idx;
|
|
+ struct if_nameindex **good;
|
|
+};
|
|
+#define MDNS_SOCKET_INIT { .socket = -1, .idx = NULL, .good = NULL, }
|
|
+
|
|
+static int get_ipv4_address(const char *iface, struct in_addr *addr)
|
|
+{
|
|
+ int s, r;
|
|
+ struct ifreq ifr;
|
|
+
|
|
+ memset(&ifr, 0, sizeof(ifr));
|
|
+ strncpy(ifr.ifr_name, iface, IFNAMSIZ-1);
|
|
+
|
|
+ s = socket(AF_INET, SOCK_DGRAM, 0);
|
|
+ r = ioctl(s, SIOCGIFADDR, &ifr);
|
|
+ close(s);
|
|
+
|
|
+ if (r == -1) {
|
|
+ DBG("error in SIOCGIFADDR for %s: %m\n", iface);
|
|
+ return MDNS_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
+ if (addr != NULL)
|
|
+ memcpy(addr, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr,
|
|
+ sizeof(*addr));
|
|
+ return MDNS_STATUS_OK;
|
|
+}
|
|
|
|
-static int mdns_open_socket(int *psocket)
|
|
+static int mdns_open_socket(struct mdns_socket *mdns_sock)
|
|
{
|
|
int stat = MDNS_STATUS_ERROR;
|
|
- int udp_socket = -1, yes = 1;
|
|
+ int udp_socket = -1, yes = 1, ifaces;
|
|
char loop = 0, ttl = 255;
|
|
struct sockaddr_in recv_addr , addr;
|
|
- struct ip_mreq mreq;
|
|
+ struct ip_mreqn mreqn;
|
|
+ struct if_nameindex *idx;
|
|
|
|
DBG("mdns_open_socket entry.\n");
|
|
|
|
@@ -120,24 +160,86 @@ static int mdns_open_socket(int *psocket)
|
|
goto bugout;
|
|
}
|
|
|
|
- /* Join the .local multicast group */
|
|
- mreq.imr_multiaddr.s_addr = inet_addr("224.0.0.251");
|
|
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
|
|
- if (setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(struct ip_mreq)) == -1) {
|
|
- BUG("unable to add to multicast group: %m\n");
|
|
- close(udp_socket);
|
|
+ mdns_sock->idx = if_nameindex();
|
|
+ if (mdns_sock->idx == NULL) {
|
|
+ BUG("if_nameindex failed: %m\n");
|
|
+ goto bugout;
|
|
+ }
|
|
+
|
|
+ for (idx = mdns_sock->idx, ifaces = 0;
|
|
+ idx && (idx->if_index != 0 || idx->if_name != NULL); idx++) {
|
|
+ ifaces ++;
|
|
+ }
|
|
+
|
|
+ mdns_sock->good = calloc(ifaces, sizeof(struct if_nameindex*));
|
|
+ if (mdns_sock->good == NULL)
|
|
+ goto bugout;
|
|
+
|
|
+ for (idx = mdns_sock->idx, ifaces = 0;
|
|
+ idx && (idx->if_index != 0 || idx->if_name != NULL); idx++) {
|
|
+
|
|
+ /* Skip lo and interfaces without IPv4 address */
|
|
+ if (!strcmp(idx->if_name, "lo"))
|
|
+ continue;
|
|
+ if (get_ipv4_address(idx->if_name, NULL) == MDNS_STATUS_ERROR)
|
|
+ continue;
|
|
+
|
|
+ /* Join the multicast group on each local interface */
|
|
+ MREQN_INIT(mreqn, idx->if_index);
|
|
+ if (setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqn,
|
|
+ sizeof(struct ip_mreqn)) == -1) {
|
|
+ BUG("unable to add to multicast group for %s: %m\n", idx->if_name);
|
|
+ } else {
|
|
+ mdns_sock->good[ifaces++] = idx;
|
|
+ DBG("added multicast group on interface %s\n", idx->if_name);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ifaces == 0) {
|
|
+ BUG("no interfaces for multicast found\n");
|
|
goto bugout;
|
|
}
|
|
|
|
- *psocket = udp_socket;
|
|
- DBG("pSocket = [%d]: %m\n", *psocket);
|
|
+ mdns_sock->socket = udp_socket;
|
|
+ DBG("Socket = [%d]: %m\n", mdns_sock->socket);
|
|
stat = MDNS_STATUS_OK;
|
|
|
|
bugout:
|
|
+ if (stat != MDNS_STATUS_OK)
|
|
+ mdns_close_socket(mdns_sock);
|
|
return stat;
|
|
}
|
|
|
|
-static void mdns_create_query_packet(char* fqdn, int query_type, char* querybuf, int *length)
|
|
+static void mdns_close_socket(struct mdns_socket *mdns_sock)
|
|
+{
|
|
+ int i;
|
|
+ struct if_nameindex *idx;
|
|
+ struct ip_mreqn mreqn;
|
|
+ if (mdns_sock->socket != -1) {
|
|
+ for (i = 0; mdns_sock->good[i]; i++) {
|
|
+ idx = mdns_sock->good[i];
|
|
+ MREQN_INIT(mreqn, idx->if_index);
|
|
+ if (setsockopt(mdns_sock->socket, IPPROTO_IP, IP_DROP_MEMBERSHIP,
|
|
+ &mreqn, sizeof(struct ip_mreqn)) == -1) {
|
|
+ BUG("unable to drop multicast group for %s: %m\n", idx->if_name);
|
|
+ };
|
|
+ }
|
|
+ close(mdns_sock->socket);
|
|
+ mdns_sock->socket = -1;
|
|
+ }
|
|
+
|
|
+ if (mdns_sock->idx != NULL) {
|
|
+ if_freenameindex(mdns_sock->idx);
|
|
+ mdns_sock->idx = NULL;
|
|
+ }
|
|
+
|
|
+ if (mdns_sock->good != NULL) {
|
|
+ free(mdns_sock->good);
|
|
+ mdns_sock->good = NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void mdns_create_query_packet(const char* fqdn, int query_type, char* querybuf, int *length)
|
|
{
|
|
int n = 0;
|
|
char header[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
|
@@ -157,14 +259,14 @@ static void mdns_create_query_packet(char* fqdn, int query_type, char* querybuf,
|
|
*length = n;
|
|
}
|
|
|
|
-static int mdns_send_query(int udp_socket, char *fqdn, int query_type)
|
|
+static int mdns_send_query(struct mdns_socket *mdns_sock, const char *fqdn, int query_type)
|
|
{
|
|
char querybuf[256] = {0,};
|
|
- int length = 0;
|
|
+ int length = 0, i, success;
|
|
int stat = MDNS_STATUS_OK;
|
|
struct sockaddr_in send_addr;
|
|
|
|
- DBG("mdns_send_query entry. send socket=%d len=%d\n", udp_socket, length);
|
|
+ DBG("mdns_send_query entry. send socket=%d len=%d\n", mdns_sock->socket, length);
|
|
|
|
mdns_create_query_packet(fqdn, query_type, querybuf, &length);
|
|
|
|
@@ -172,8 +274,26 @@ static int mdns_send_query(int udp_socket, char *fqdn, int query_type)
|
|
send_addr.sin_family = AF_INET;
|
|
send_addr.sin_addr.s_addr = inet_addr("224.0.0.251");
|
|
send_addr.sin_port = htons(5353);
|
|
- if (sendto(udp_socket, querybuf, length, 0, (struct sockaddr *) &send_addr, sizeof(send_addr)) < 0)
|
|
- stat = MDNS_STATUS_ERROR;
|
|
+
|
|
+ for (i = 0, success = 0; mdns_sock->good[i]; i++) {
|
|
+ struct if_nameindex *idx;
|
|
+ struct ip_mreqn mreqn;
|
|
+ idx = mdns_sock->good[i];
|
|
+ MREQN_INIT(mreqn, idx->if_index);
|
|
+ if (setsockopt(mdns_sock->socket, IPPROTO_IP, IP_MULTICAST_IF, &mreqn, sizeof(mreqn))
|
|
+ == -1) {
|
|
+ DBG("failed to set IP_MULTICAST_IF to %s\n", idx->if_name);
|
|
+ continue;
|
|
+ }
|
|
+ if (sendto(mdns_sock->socket, querybuf, length, 0,
|
|
+ (struct sockaddr *) &send_addr, sizeof(send_addr))< 0) {
|
|
+ DBG("failed to send on %s\n", idx->if_name);
|
|
+ } else
|
|
+ success++;
|
|
+ }
|
|
+
|
|
+ if (success == 0)
|
|
+ stat = MDNS_STATUS_ERROR;
|
|
|
|
DBG("mdns_send_query returning with status(%d)...\n", stat);
|
|
return stat;
|
|
@@ -252,7 +372,7 @@ static void mdns_read_header(char *Response, DNS_PKT_HEADER *h)
|
|
|
|
}
|
|
|
|
-static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr)
|
|
+static int mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr)
|
|
{
|
|
unsigned char *p = Response;
|
|
unsigned short type = 0, data_len = 0;
|
|
@@ -263,6 +383,11 @@ static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr)
|
|
mdns_read_header(Response, &h);
|
|
p += MDNS_HEADER_SIZE;
|
|
|
|
+ if (h.answers + h.additionals <= 0) {
|
|
+ DBG("mdns_parse_respponse: no answers");
|
|
+ return MDNS_STATUS_ERROR;
|
|
+ }
|
|
+
|
|
for (i = 0; i < h.questions; i++)
|
|
{
|
|
p += mdns_readName(Response, p, rr->name);
|
|
@@ -295,6 +420,7 @@ static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr)
|
|
}
|
|
|
|
DBG("mdns_parse_respponse returning MDL = %s, IP = %s\n",rr->mdl, rr->ip);
|
|
+ return MDNS_STATUS_OK;
|
|
}
|
|
|
|
static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvbufsize)
|
|
@@ -328,7 +454,7 @@ static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvb
|
|
return ret;
|
|
}
|
|
|
|
-static DNS_RECORD *mdns_read_responses(int udp_socket, int mode)
|
|
+static DNS_RECORD *mdns_read_responses(int udp_socket, int mode, const char *question)
|
|
{
|
|
int retries = 3, ret = 0;
|
|
char recvbuffer[MAX_MDNS_RESPONSE_LEN] = { 0, };
|
|
@@ -351,17 +477,22 @@ static DNS_RECORD *mdns_read_responses(int udp_socket, int mode)
|
|
temp = (DNS_RECORD *)malloc(sizeof(DNS_RECORD));
|
|
if(temp)
|
|
{
|
|
- temp->next = NULL;
|
|
- if(head == NULL)
|
|
- rr = head = temp;
|
|
- else
|
|
- {
|
|
- rr->next = temp;
|
|
- rr = rr->next;
|
|
- }
|
|
-
|
|
- memset(rr, 0, sizeof(DNS_RECORD));
|
|
- mdns_parse_respponse(recvbuffer, rr);
|
|
+ memset(temp, 0, sizeof(DNS_RECORD));
|
|
+ if (mdns_parse_respponse(recvbuffer, temp) == MDNS_STATUS_OK &&
|
|
+ (mode == MODE_READ_ALL || question == NULL ||
|
|
+ !strncmp(question, temp->name, sizeof(temp->name)-1))) {
|
|
+ if(head == NULL)
|
|
+ rr = head = temp;
|
|
+ else
|
|
+ {
|
|
+ rr->next = temp;
|
|
+ rr = rr->next;
|
|
+ }
|
|
+ } else {
|
|
+ DBG("Parse error or wrong MDNS name");
|
|
+ free(temp);
|
|
+ continue;
|
|
+ }
|
|
|
|
if(mode == MODE_READ_SINGLE)
|
|
break;
|
|
@@ -421,28 +552,28 @@ static void mdns_rr_cleanup(DNS_RECORD *rr)
|
|
int mdns_probe_nw_scanners(char* uris_buf, int buf_size, int *count)
|
|
{
|
|
int n = 0, bytes_read = 0;
|
|
- int udp_socket = 0;
|
|
+ struct mdns_socket mdns_sock = MDNS_SOCKET_INIT;
|
|
int stat = MDNS_STATUS_ERROR;
|
|
DNS_RECORD *rr_list = NULL;
|
|
+ const char scanner_name[] = "_scanner._tcp.local";
|
|
|
|
DBG("mdns_probe_nw_scanners entry.\n");
|
|
/* Open UDP socket */
|
|
- if (mdns_open_socket(&udp_socket) != MDNS_STATUS_OK)
|
|
+ if (mdns_open_socket(&mdns_sock) != MDNS_STATUS_OK)
|
|
goto bugout;
|
|
|
|
/* Send dns query */
|
|
- mdns_send_query(udp_socket, "_scanner._tcp.local", QTYPE_PTR);
|
|
+ mdns_send_query(&mdns_sock, scanner_name, QTYPE_PTR);
|
|
|
|
/* Read Responses */
|
|
- rr_list = mdns_read_responses(udp_socket, MODE_READ_ALL);
|
|
+ rr_list = mdns_read_responses(mdns_sock.socket, MODE_READ_ALL, scanner_name);
|
|
|
|
/* Update URIs buffer */
|
|
bytes_read = mdns_update_uris(rr_list, uris_buf, buf_size, count);
|
|
DBG("mdns_probe_nw_scanners returned with bytes_read = [%d].\n",bytes_read);
|
|
|
|
bugout:
|
|
- if (udp_socket >= 0)
|
|
- close(udp_socket);
|
|
+ mdns_close_socket(&mdns_sock);
|
|
|
|
mdns_rr_cleanup(rr_list);
|
|
|
|
@@ -455,22 +586,22 @@ bugout:
|
|
*/
|
|
int mdns_lookup(char* hostname, unsigned char* ip)
|
|
{
|
|
- int udp_socket = 0;
|
|
+ struct mdns_socket mdns_sock = MDNS_SOCKET_INIT;
|
|
int stat = MDNS_STATUS_ERROR;
|
|
char fqdn[MAX_NAME_LENGTH] = {0};
|
|
DNS_RECORD *rr_list = NULL;
|
|
|
|
DBG("mdns_probe_nw_scanners entry.\n");
|
|
/* Open UDP socket */
|
|
- if (mdns_open_socket(&udp_socket) != MDNS_STATUS_OK)
|
|
+ if (mdns_open_socket(&mdns_sock) != MDNS_STATUS_OK)
|
|
goto bugout;
|
|
|
|
/* Send dns query */
|
|
sprintf(fqdn, "%s.local", hostname);
|
|
- mdns_send_query(udp_socket, fqdn, QTYPE_A);
|
|
+ mdns_send_query(&mdns_sock, fqdn, QTYPE_A);
|
|
|
|
/* Read Responses */
|
|
- rr_list = mdns_read_responses(udp_socket, MODE_READ_SINGLE);
|
|
+ rr_list = mdns_read_responses(mdns_sock.socket, MODE_READ_SINGLE, fqdn);
|
|
|
|
/* Update IP Address buffer */
|
|
if(rr_list)
|
|
@@ -481,8 +612,7 @@ int mdns_lookup(char* hostname, unsigned char* ip)
|
|
}
|
|
|
|
bugout:
|
|
- if (udp_socket >= 0)
|
|
- close(udp_socket);
|
|
+ mdns_close_socket(&mdns_sock);
|
|
|
|
mdns_rr_cleanup(rr_list);
|
|
return stat;
|
|
diff --git a/protocol/discovery/mdns.h b/protocol/discovery/mdns.h
|
|
index 8fccc82..34066fb 100644
|
|
--- a/protocol/discovery/mdns.h
|
|
+++ b/protocol/discovery/mdns.h
|
|
@@ -86,19 +86,21 @@ typedef struct _DNS_PKT_HEADER
|
|
int mdns_probe_nw_scanners(char* buf, int buf_size, int *count);
|
|
int mdns_lookup(char* hostname, unsigned char* ip);
|
|
|
|
+struct mdns_socket;
|
|
|
|
/*Helper Function Prototypes*/
|
|
static int mdns_convert_name_to_dns(const char *name, int name_size, char *dns_name);
|
|
static int mdns_read_single_response(int udp_socket, char *recvbuffer, int recvbufsize);
|
|
-static int mdns_open_socket(int *psocket);
|
|
-static int mdns_send_query(int udp_socket, char *fqdn, int query_type);
|
|
+static int mdns_open_socket(struct mdns_socket *mdns_sock);
|
|
+static void mdns_close_socket(struct mdns_socket *mdns_sock);
|
|
+static int mdns_send_query(struct mdns_socket *mdns_sock, const char *fqdn, int query_type);
|
|
static int mdns_readName(unsigned char* start, unsigned char *p, char *buf);
|
|
static int mdns_update_uris(DNS_RECORD *rr, char* uris_buf, int buf_size, int *count);
|
|
-static void mdns_create_query_packet(char* fqdn, int query_type, char* dnsquery, int *length);
|
|
+static void mdns_create_query_packet(const char* fqdn, int query_type, char* dnsquery, int *length);
|
|
static void mdns_read_header(char *Response, DNS_PKT_HEADER *h);
|
|
-static void mdns_parse_respponse(unsigned char *Response, DNS_RECORD *rr);
|
|
+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);
|
|
+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);
|
|
#endif // _DISCOVERY_MDNS_H
|
|
|