Skip to content

Commit 08c2393

Browse files
author
David Graeff
committed
Allow to provide multiple host names
1 parent 4a17f59 commit 08c2393

4 files changed

Lines changed: 96 additions & 30 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ enable LLMNR name resolution over IPv6 use:
6464
$ llmnrd -6
6565
```
6666

67+
By default, `llmnrd` respond to name requests matching the systems hostname.
68+
Provide one or more additional names via the `-H` argument:
69+
70+
```
71+
$ llmnrd -H a_name -H another_name
72+
```
73+
6774
Use `llmnrd --help` to show additional usage information.
6875

6976
Additionally, the `llmnr-query` utility is shipped together with llmnrd and

llmnr.c

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,38 +40,73 @@
4040

4141
static bool llmnr_ipv6 = false;
4242
/* Host name in DNS name format (length octet + name + 0 byte) */
43-
static char llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 2];
43+
#define LLMNR_LABEL_LEN (LLMNR_LABEL_MAX_SIZE + 2)
44+
static char** llmnr_hostnames = NULL;
45+
int llmnr_hostname_count = 0;
46+
47+
static void set_hostname(int entry_index, const char *hostname)
48+
{
49+
char* entry_llmnr_hostname = NULL;
50+
51+
llmnr_hostnames[entry_index] = xzalloc(LLMNR_LABEL_LEN);
52+
entry_llmnr_hostname = llmnr_hostnames[entry_index];
53+
54+
entry_llmnr_hostname[0] = strlen(hostname);
55+
strncpy(&entry_llmnr_hostname[1], hostname, LLMNR_LABEL_MAX_SIZE);
56+
entry_llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 1] = '\0';
57+
}
4458

4559
void llmnr_set_hostname(const char *hostname)
4660
{
47-
llmnr_hostname[0] = strlen(hostname);
48-
strncpy(&llmnr_hostname[1], hostname, LLMNR_LABEL_MAX_SIZE);
49-
llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 1] = '\0';
61+
set_hostname(0, hostname);
5062
}
5163

52-
void llmnr_init(const char *hostname, bool ipv6)
64+
void llmnr_init(const char *hostnames[], int hostname_count, bool ipv6)
5365
{
54-
llmnr_set_hostname(hostname);
66+
int name_i = 0;
67+
llmnr_hostname_count = hostname_count;
68+
llmnr_hostnames = xzalloc(hostname_count);
69+
for (;name_i < hostname_count; ++name_i) {
70+
set_hostname(name_i, hostnames[name_i]);
71+
}
5572
llmnr_ipv6 = ipv6;
5673
}
5774

58-
static bool llmnr_name_matches(const uint8_t *query)
75+
void llmnr_release() {
76+
int name_i = 0;
77+
for(; name_i < llmnr_hostname_count; ++name_i) {
78+
free(llmnr_hostnames[name_i]);
79+
}
80+
free(llmnr_hostnames);
81+
}
82+
83+
/* Return the matched name entry (first byte represents the string length) or NULL */
84+
static char* llmnr_name_matches(const uint8_t *query)
5985
{
60-
uint8_t n = llmnr_hostname[0];
86+
uint8_t n;
87+
int name_i = 0;
88+
89+
for(; name_i < llmnr_hostname_count; ++name_i) {
90+
n = llmnr_hostnames[name_i][0];
91+
92+
/* length */
93+
if (query[0] != n)
94+
continue;
95+
/* NULL byte */
96+
if (query[1 + n] != 0)
97+
continue;
98+
99+
if (strncasecmp((const char *)&query[1], &llmnr_hostnames[name_i][1], n) == 0)
100+
return llmnr_hostnames[name_i];
101+
}
61102

62-
/* length */
63-
if (query[0] != n)
64-
return false;
65-
/* NULL byte */
66-
if (query[1 + n] != 0)
67-
return false;
68103

69-
return strncasecmp((const char *)&query[1], &llmnr_hostname[1], n) == 0;
104+
return NULL;
70105
}
71106

72107
static void llmnr_respond(unsigned int ifindex, const struct llmnr_hdr *hdr,
73108
const uint8_t *query, size_t query_len, int sock,
74-
const struct sockaddr_storage *sst)
109+
const struct sockaddr_storage *sst, char* matched_hostname_entry)
75110
{
76111
uint16_t qtype, qclass;
77112
uint8_t name_len = query[0];
@@ -164,7 +199,7 @@ static void llmnr_respond(unsigned int ifindex, const struct llmnr_hdr *hdr,
164199

165200
/* NAME */
166201
if (i == 0)
167-
memcpy(pkt_put(p, llmnr_hostname[0] + 2), llmnr_hostname, llmnr_hostname[0] + 2);
202+
memcpy(pkt_put(p, matched_hostname_entry[0] + 2), matched_hostname_entry, matched_hostname_entry[0] + 2);
168203
else {
169204
/* message compression (RFC 1035, section 4.1.3) */
170205
uint16_t ptr = 0xC000 | (sizeof(*hdr) + query_len);
@@ -196,6 +231,7 @@ static void llmnr_packet_process(int ifindex, const uint8_t *pktbuf, size_t len,
196231
const uint8_t *query;
197232
size_t query_len;
198233
uint8_t name_len;
234+
char* matched_hostname_entry;
199235

200236
/* Query too short? */
201237
if (len < sizeof(struct llmnr_hdr))
@@ -218,8 +254,9 @@ static void llmnr_packet_process(int ifindex, const uint8_t *pktbuf, size_t len,
218254
return;
219255

220256
/* Authoritative? */
221-
if (llmnr_name_matches(query))
222-
llmnr_respond(ifindex, hdr, query, query_len, sock, sst);
257+
matched_hostname_entry = llmnr_name_matches(query);
258+
if (matched_hostname_entry)
259+
llmnr_respond(ifindex, hdr, query, query_len, sock, sst, matched_hostname_entry);
223260
}
224261

225262
void llmnr_recv(int sock)

llmnr.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
#include <stdbool.h>
2323

2424
void llmnr_set_hostname(const char *hostname);
25-
void llmnr_init(const char *hostname, bool ipv6);
25+
void llmnr_init(const char *hostnames[], int hostname_count, bool ipv6);
26+
void llmnr_release(void);
2627
void llmnr_recv(int sock);
2728

2829
#endif /* LLMNR_H */

llmnrd.c

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ int main(int argc, char **argv)
187187
int c, ret = -1;
188188
long num_arg;
189189
bool daemonize = false, ipv6 = false;
190-
char *hostname = NULL;
190+
char **hostnames = NULL;
191+
int name_count = 0, name_i = 0;
191192
char *iface = NULL;
192193
uint16_t port = LLMNR_UDP_PORT;
193194
int llmnrd_sock_rtnl = -1;
@@ -196,6 +197,17 @@ int main(int argc, char **argv)
196197

197198
setlinebuf(stdout);
198199

200+
/* First count given (host)names, if any, to allocate memory */
201+
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
202+
if (c == 'H')
203+
++name_count;
204+
}
205+
206+
if (!name_count)
207+
name_count = 1;
208+
hostnames = xzalloc(name_count);
209+
210+
optind = 1;
199211
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
200212
switch (c) {
201213
case 'd':
@@ -206,7 +218,8 @@ int main(int argc, char **argv)
206218
log_to_syslog();
207219
break;
208220
case 'H':
209-
hostname = xstrdup(optarg);
221+
hostnames[name_i] = xstrdup(optarg);
222+
++name_i;
210223
break;
211224
case 'i':
212225
iface = xstrdup(optarg);
@@ -236,13 +249,13 @@ int main(int argc, char **argv)
236249
register_signal(SIGTERM, signal_handler);
237250
register_signal(SIGHUP, signal_handler);
238251

239-
if (!hostname) {
240-
hostname = xzalloc(MAXHOSTNAMELEN);
241-
if (gethostname(hostname, MAXHOSTNAMELEN) != 0) {
252+
if (name_i == 0) {
253+
hostnames[0] = xzalloc(MAXHOSTNAMELEN);
254+
if (gethostname(hostnames[0], MAXHOSTNAMELEN) != 0) {
242255
log_err("Failed to get hostname");
243256
return EXIT_FAILURE;
244257
}
245-
hostname[MAXHOSTNAMELEN - 1] = '\0';
258+
hostnames[0][MAXHOSTNAMELEN - 1] = '\0';
246259

247260
llmnrd_fd_hostname = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY);
248261
}
@@ -257,7 +270,11 @@ int main(int argc, char **argv)
257270
rm_pid_file = true;
258271
}
259272

260-
log_info("Starting llmnrd on port %u, hostname %s\n", port, hostname);
273+
log_info("Starting llmnrd on port %u, hostname(s): ", port);
274+
for(name_i = 0; name_i < name_count; ++name_i)
275+
log_info("%s ", hostnames[name_i]);
276+
log_info("\n");
277+
261278
if (iface)
262279
log_info("Binding to interface %s\n", iface);
263280

@@ -275,7 +292,7 @@ int main(int argc, char **argv)
275292
if (llmnrd_sock_rtnl < 0)
276293
goto out;
277294

278-
llmnr_init(hostname, ipv6);
295+
llmnr_init((const char **) hostnames, name_count, ipv6);
279296

280297
ret = iface_init(llmnrd_sock_rtnl, iface, ipv6, &iface_event_handle);
281298
if (ret < 0)
@@ -318,7 +335,7 @@ int main(int argc, char **argv)
318335
if (llmnrd_sock_ipv6 >= 0 && FD_ISSET(llmnrd_sock_ipv6, &rfds))
319336
llmnr_recv(llmnrd_sock_ipv6);
320337
if (llmnrd_fd_hostname >= 0 && FD_ISSET(llmnrd_fd_hostname, &efds))
321-
hostname_change_handle(hostname, MAXHOSTNAMELEN);
338+
hostname_change_handle(hostnames[0], MAXHOSTNAMELEN);
322339
}
323340
}
324341

@@ -332,7 +349,11 @@ int main(int argc, char **argv)
332349
close(llmnrd_sock_ipv6);
333350
if (llmnrd_sock_ipv4 >= 0)
334351
close(llmnrd_sock_ipv4);
335-
free(hostname);
352+
for(name_i = 0; name_i < name_count; ++name_i) {
353+
free(hostnames[name_i]);
354+
}
355+
free(hostnames);
356+
llmnr_release();
336357
if (rm_pid_file)
337358
unlink(PIDFILE);
338359
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;

0 commit comments

Comments
 (0)