[LEDE-DEV,mdns] Send reverse DNS lookup entry for IPv4 address

Message ID 20170210104031.18330-1-zajec5@gmail.com
State Changes Requested
Delegated to: Rafał Miłecki
Headers show

Commit Message

Rafał Miłecki Feb. 10, 2017, 10:40 a.m.
From: Rafał Miłecki <rafal@milecki.pl>

Whenever we send A(AAA) records, let's also include reverse lookup ones.
This should be extended in the future by adding IPv6.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
 announce.c  |  2 +-
 dns.c       | 38 +++++++++++++++++++++++++++++++++++---
 dns.h       |  2 +-
 interface.c |  2 +-
 4 files changed, 38 insertions(+), 6 deletions(-)

Comments

Rafal Milecki March 14, 2017, 7:50 a.m. | #1
On 02/10/2017 11:40 AM, Rafał Miłecki wrote:
 > From: Rafał Miłecki <rafal@milecki.pl>
 >
 > Whenever we send A(AAA) records, let's also include reverse lookup ones.
 > This should be extended in the future by adding IPv6.

Ping. Any opinions on this?


 > @@ -210,6 +210,38 @@ dns_reply_a(struct interface *iface, int ttl)
 >  	freeifaddrs(ifap);
 >  }
 >
 > +static void
 > +dns_reply_rev_lookup(struct interface *iface, int ttl)
 > +{
 > +	char name[32];
 > +	int len;
 > +
 > +	if (!iface->v6) {
 > +		struct in_addr rev_v4_addr;
 > +
 > +		/* PTR recored starts with IP with reversed octets order */
 > +		memcpy(&rev_v4_addr, &iface->v4_addr, sizeof(iface->v4_addr));
 > +		rev_v4_addr.s_addr = bswap_32(rev_v4_addr.s_addr);

Is there some more appropriate solution for this than bswap_32?


 > +
 > +		/* Prepare name with reversed IP & second level domain suffix */
 > +		inet_ntop(AF_INET, &rev_v4_addr, name, sizeof(name));
 > +		strcat(name, ".in-addr.arpa");
 > +
 > +		dns_init_answer();
 > +		len = dn_comp(mdns_hostname_local, mdns_buf, sizeof(mdns_buf), NULL, NULL);
 > +		if (len > 0)
 > +			dns_add_answer(TYPE_PTR, mdns_buf, len, ttl);
 > +		dns_send_answer(iface, name);
 > +	}
 > +}
Jo-Philipp Wich March 14, 2017, 7:38 p.m. | #2
Hi,

>> Whenever we send A(AAA) records, let's also include reverse lookup ones.
>> This should be extended in the future by adding IPv6.
> 
> Ping. Any opinions on this?

Go for it.

>> @@ -210,6 +210,38 @@ dns_reply_a(struct interface *iface, int ttl)
>>      freeifaddrs(ifap);
>>  }
>>
>> +static void
>> +dns_reply_rev_lookup(struct interface *iface, int ttl)
>> +{
>> +    char name[32];
>> +    int len;
>> +
>> +    if (!iface->v6) {
>> +        struct in_addr rev_v4_addr;
>> +
>> +        /* PTR recored starts with IP with reversed octets order */
>> +        memcpy(&rev_v4_addr, &iface->v4_addr, sizeof(iface->v4_addr));
>> +        rev_v4_addr.s_addr = bswap_32(rev_v4_addr.s_addr);
> 
> Is there some more appropriate solution for this than bswap_32?

I prefer the more explicit variant:

 - make "rev_v4_addr" unsigned char
 - use asprintf(&ptr, "%u.%u.%u.%u.in-addr.arpa",
                rev_v4_addr[3], rev_v4_addr[2],
                rev_v4_addr[1], rev_v4_addr[0]);

This also makes dealing with IPv6 later easier.

~ Jo

Patch

diff --git a/announce.c b/announce.c
index 7bbce4a..8d9b080 100644
--- a/announce.c
+++ b/announce.c
@@ -65,7 +65,7 @@  announce_timer(struct uloop_timeout *timeout)
 			/* Fall through */
 
 		case STATE_ANNOUNCE:
-			dns_reply_a(iface, announce_ttl);
+			dns_reply_domain_name(iface, announce_ttl);
 			service_announce(iface, announce_ttl);
 			uloop_timeout_set(timeout, announce_ttl * 800);
 			break;
diff --git a/dns.c b/dns.c
index de0c21a..e5703aa 100644
--- a/dns.c
+++ b/dns.c
@@ -181,7 +181,7 @@  dns_send_answer(struct interface *iface, const char *answer)
 		fprintf(stderr, "failed to send question\n");
 }
 
-void
+static void
 dns_reply_a(struct interface *iface, int ttl)
 {
 	struct ifaddrs *ifap, *ifa;
@@ -210,6 +210,38 @@  dns_reply_a(struct interface *iface, int ttl)
 	freeifaddrs(ifap);
 }
 
+static void
+dns_reply_rev_lookup(struct interface *iface, int ttl)
+{
+	char name[32];
+	int len;
+
+	if (!iface->v6) {
+		struct in_addr rev_v4_addr;
+
+		/* PTR recored starts with IP with reversed octets order */
+		memcpy(&rev_v4_addr, &iface->v4_addr, sizeof(iface->v4_addr));
+		rev_v4_addr.s_addr = bswap_32(rev_v4_addr.s_addr);
+
+		/* Prepare name with reversed IP & second level domain suffix */
+		inet_ntop(AF_INET, &rev_v4_addr, name, sizeof(name));
+		strcat(name, ".in-addr.arpa");
+
+		dns_init_answer();
+		len = dn_comp(mdns_hostname_local, mdns_buf, sizeof(mdns_buf), NULL, NULL);
+		if (len > 0)
+			dns_add_answer(TYPE_PTR, mdns_buf, len, ttl);
+		dns_send_answer(iface, name);
+	}
+}
+
+void
+dns_reply_domain_name(struct interface *iface, int ttl)
+{
+	dns_reply_a(iface, ttl);
+	dns_reply_rev_lookup(iface, ttl);
+}
+
 static int
 scan_name(const uint8_t *buffer, int len)
 {
@@ -361,8 +393,8 @@  parse_question(struct interface *iface, char *name, struct dns_question *q)
 	switch (q->type) {
 	case TYPE_ANY:
 		if (!strcmp(name, mdns_hostname_local)) {
+			dns_reply_domain_name(iface, announce_ttl);
 			service_reply(iface, NULL, announce_ttl);
-			dns_reply_a(iface, announce_ttl);
 		}
 		break;
 
@@ -377,7 +409,7 @@  parse_question(struct interface *iface, char *name, struct dns_question *q)
 		if (host)
 			*host = '\0';
 		if (!strcmp(mdns_hostname, name))
-			dns_reply_a(iface, announce_ttl);
+			dns_reply_domain_name(iface, announce_ttl);
 		break;
 	};
 }
diff --git a/dns.h b/dns.h
index 7f3cbe1..fa532a7 100644
--- a/dns.h
+++ b/dns.h
@@ -77,7 +77,7 @@  void dns_send_question(struct interface *iface, const char *question, int type,
 void dns_init_answer(void);
 void dns_add_answer(int type, const uint8_t *rdata, uint16_t rdlength, int ttl);
 void dns_send_answer(struct interface *iface, const char *answer);
-void dns_reply_a(struct interface *iface, int ttl);
+void dns_reply_domain_name(struct interface *iface, int ttl);
 const char* dns_type_string(uint16_t type);
 void dns_handle_packet(struct interface *iface, struct sockaddr *s, uint16_t port, uint8_t *buf, int len);
 
diff --git a/interface.c b/interface.c
index 463335a..4ddddde 100644
--- a/interface.c
+++ b/interface.c
@@ -621,7 +621,7 @@  void interface_shutdown(void)
 	vlist_for_each_element(&interfaces, iface, node)
 		if (iface->fd.fd > 0 && iface->multicast) {
 			service_announce(iface, 0);
-			dns_reply_a(iface, 0);
+			dns_reply_domain_name(iface, 0);
 		}
 	vlist_for_each_element(&interfaces, iface, node)
 		interface_close(iface);