Browse Source

use hostname from SRV record to look up IP addresses

On many devices, the main record name contains the long form hostname,
whereas the A/AAAA records are assigned to the hostname indicated in the
SRV record.
This fixes getting IP addresses via browse for many devices

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Felix Fietkau 6 months ago
parent
commit
b42b22152d
3 changed files with 12 additions and 6 deletions
  1. 6 2
      cache.c
  2. 2 1
      cache.h
  3. 4 3
      ubus.c

+ 6 - 2
cache.c

@@ -382,7 +382,8 @@ void cache_answer(struct interface *iface, struct sockaddr *from, uint8_t *base,
 }
 
 void
-cache_dump_records(struct blob_buf *buf, const char *name, int array)
+cache_dump_records(struct blob_buf *buf, const char *name, int array,
+		   const char **hostname)
 {
 	struct cache_record *r, *last, *next;
 	const char *txt;
@@ -454,8 +455,11 @@ cache_dump_records(struct blob_buf *buf, const char *name, int array)
 			break;
 
 		case TYPE_SRV:
-			if (r->rdata)
+			if (r->rdata) {
 				blobmsg_add_string(buf, "host", (char *)r->rdata + sizeof(struct dns_srv_data));
+				if (hostname)
+					*hostname = (char *)r->rdata + sizeof(struct dns_srv_data);
+			}
 			if (r->port)
 				blobmsg_add_u32(buf, "port", r->port);
 			break;

+ 2 - 1
cache.h

@@ -58,7 +58,8 @@ void cache_answer(struct interface *iface, struct sockaddr *from, uint8_t *base,
 		  int blen, char *name, struct dns_answer *a, uint8_t *rdata,
 		  int flush);
 int cache_host_is_known(char *record);
-void cache_dump_records(struct blob_buf *buf, const char *name, int array);
+void cache_dump_records(struct blob_buf *buf, const char *name, int array,
+			const char **hostname);
 void cache_dump_recursive(struct blob_buf *b, const char *name, uint16_t type, struct interface *iface);
 
 #endif

+ 4 - 3
ubus.c

@@ -83,6 +83,7 @@ umdns_browse(struct ubus_context *ctx, struct ubus_object *obj,
 
 	blob_buf_init(&b, 0);
 	avl_for_each_element(&services, s, avl) {
+		const char *hostname = buffer;
 		char *local;
 
 		snprintf(buffer, MAX_NAME_LEN, "%s", (const char *) s->avl.key);
@@ -103,9 +104,9 @@ umdns_browse(struct ubus_context *ctx, struct ubus_object *obj,
 		c2 = blobmsg_open_table(&b, buffer);
 		strncat(buffer, ".local", MAX_NAME_LEN);
 		blobmsg_add_string(&b, "iface", s->iface->name);
+		cache_dump_records(&b, s->entry, array, &hostname);
 		if (address)
-			cache_dump_records(&b, buffer, array);
-		cache_dump_records(&b, s->entry, array);
+			cache_dump_records(&b, hostname, array, NULL);
 		blobmsg_close_table(&b, c2);
 		q = avl_next_element(s, avl);
 		if (!q || avl_is_last(&services, &s->avl) || strcmp(s->avl.key, q->avl.key)) {
@@ -134,7 +135,7 @@ umdns_hosts(struct ubus_context *ctx, struct ubus_object *obj,
 		/* Query each domain just once */
 		if (!prev || strcmp(r->record, prev->record)) {
 			c = blobmsg_open_table(&b, r->record);
-			cache_dump_records(&b, r->record, false);
+			cache_dump_records(&b, r->record, false, NULL);
 			blobmsg_close_table(&b, c);
 		}
 		prev = r;