Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to provide multiple host names #39

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ enable LLMNR name resolution over IPv6 use:
$ llmnrd -6
```

By default, `llmnrd` responds to name requests matching the systems hostname.
Instead you can provide one or more names via the `-H` argument:

```
$ llmnrd -H a_name -H another_name
```

Use `llmnrd --help` to show additional usage information.

Additionally, the `llmnr-query` utility is shipped together with llmnrd and
Expand Down
76 changes: 57 additions & 19 deletions llmnr.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,38 +40,74 @@

static bool llmnr_ipv6 = false;
/* Host name in DNS name format (length octet + name + 0 byte) */
static char llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 2];
#define LLMNR_LABEL_LEN (LLMNR_LABEL_MAX_SIZE + 2)
static char** llmnr_hostnames = NULL;
size_t llmnr_hostname_count = 0;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this static, it's not used outside the file.


static void set_hostname(int entry_index, const char *hostname)
{
char* entry_llmnr_hostname = NULL;

llmnr_hostnames[entry_index] = xzalloc(LLMNR_LABEL_LEN);
entry_llmnr_hostname = llmnr_hostnames[entry_index];

entry_llmnr_hostname[0] = (uint8_t)strlen(hostname);
strncpy(&entry_llmnr_hostname[1], hostname, LLMNR_LABEL_MAX_SIZE);
entry_llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 1] = '\0';
}

void llmnr_set_hostname(const char *hostname)
{
llmnr_hostname[0] = strlen(hostname);
strncpy(&llmnr_hostname[1], hostname, LLMNR_LABEL_MAX_SIZE);
llmnr_hostname[LLMNR_LABEL_MAX_SIZE + 1] = '\0';
set_hostname(0, hostname);
}

void llmnr_init(const char *hostname, bool ipv6)
void llmnr_init(const char *hostnames[], size_t hostname_count, bool ipv6)
{
llmnr_set_hostname(hostname);
size_t i;
llmnr_hostname_count = hostname_count;
Comment on lines +66 to +67
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an empty line after variable declaration:

Suggested change
size_t i;
llmnr_hostname_count = hostname_count;
size_t i;
llmnr_hostname_count = hostname_count;

llmnr_hostnames = xzalloc(hostname_count);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should allocate hostname_count * sizeof(*llmnr_hostnames).

for (i = 0; i < hostname_count; ++i) {
set_hostname(i, hostnames[i]);
}
llmnr_ipv6 = ipv6;
}

static bool llmnr_name_matches(const uint8_t *query)
void llmnr_release(void)
{
size_t i;
for(i = 0; i < llmnr_hostname_count; ++i) {
Comment on lines +77 to +78
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an empty line after variable declaration and add a space after the for keyword:

Suggested change
size_t i;
for(i = 0; i < llmnr_hostname_count; ++i) {
size_t i;
for (i = 0; i < llmnr_hostname_count; ++i) {

free(llmnr_hostnames[i]);
}
free(llmnr_hostnames);
}

/* Return the matched name entry (first byte represents the string length) or NULL */
static char *llmnr_name_matches(const uint8_t *query)
{
uint8_t n = llmnr_hostname[0];
size_t i;

for (i = 0; i < llmnr_hostname_count; ++i) {
uint8_t n;
n = llmnr_hostnames[i][0];
Comment on lines +90 to +91
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assign this on declaration:

Suggested change
uint8_t n;
n = llmnr_hostnames[i][0];
uint8_t n = llmnr_hostnames[i][0];


/* length */
if (query[0] != n)
continue;
/* NULL byte */
if (query[1 + n] != 0)
continue;

if (strncasecmp((const char *) &query[1], &llmnr_hostnames[i][1], n) == 0)
return llmnr_hostnames[i];
}

/* length */
if (query[0] != n)
return false;
/* NULL byte */
if (query[1 + n] != 0)
return false;

return strncasecmp((const char *)&query[1], &llmnr_hostname[1], n) == 0;
return NULL;
}

static void llmnr_respond(unsigned int ifindex, const struct llmnr_hdr *hdr,
const uint8_t *query, size_t query_len, int sock,
const struct sockaddr_storage *sst)
const struct sockaddr_storage *sst, char* matched_hostname_entry)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const struct sockaddr_storage *sst, char* matched_hostname_entry)
const struct sockaddr_storage *sst,
const char* matched_hostname)

{
uint16_t qtype, qclass;
uint8_t name_len = query[0];
Expand Down Expand Up @@ -164,7 +200,7 @@ static void llmnr_respond(unsigned int ifindex, const struct llmnr_hdr *hdr,

/* NAME */
if (i == 0)
memcpy(pkt_put(p, llmnr_hostname[0] + 2), llmnr_hostname, llmnr_hostname[0] + 2);
memcpy(pkt_put(p, matched_hostname_entry[0] + 2), matched_hostname_entry, matched_hostname_entry[0] + 2);
else {
/* message compression (RFC 1035, section 4.1.3) */
uint16_t ptr = 0xC000 | (sizeof(*hdr) + query_len);
Expand Down Expand Up @@ -196,6 +232,7 @@ static void llmnr_packet_process(int ifindex, const uint8_t *pktbuf, size_t len,
const uint8_t *query;
size_t query_len;
uint8_t name_len;
char* matched_hostname_entry;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
char* matched_hostname_entry;
const char* matched_hostname;


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

/* Authoritative? */
if (llmnr_name_matches(query))
llmnr_respond(ifindex, hdr, query, query_len, sock, sst);
matched_hostname_entry = llmnr_name_matches(query);
if (matched_hostname_entry)
llmnr_respond(ifindex, hdr, query, query_len, sock, sst, matched_hostname_entry);
}

void llmnr_recv(int sock)
Expand Down
3 changes: 2 additions & 1 deletion llmnr.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
#include <stdbool.h>

void llmnr_set_hostname(const char *hostname);
void llmnr_init(const char *hostname, bool ipv6);
void llmnr_init(const char *hostnames[], size_t hostname_count, bool ipv6);
void llmnr_release(void);
void llmnr_recv(int sock);

#endif /* LLMNR_H */
41 changes: 31 additions & 10 deletions llmnrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ int main(int argc, char **argv)
int c, ret = -1;
long num_arg;
bool daemonize = false, ipv6 = false;
char *hostname = NULL;
char **hostnames = NULL;
size_t name_count = 0, name_i = 0;
char *iface = NULL;
uint16_t port = LLMNR_UDP_PORT;
int llmnrd_sock_rtnl = -1;
Expand All @@ -196,6 +197,17 @@ int main(int argc, char **argv)

setlinebuf(stdout);

/* First count given (host)names, if any, to allocate memory */
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
if (c == 'H')
++name_count;
}
Comment on lines +200 to +204
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like the idea of iterating the options twice. But I guess there is no alternative to this :-(


if (!name_count)
name_count = 1;
hostnames = xzalloc(name_count);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should allocate name_count * sizeof(*hostnames).


optind = 1;
while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
switch (c) {
case 'd':
Expand All @@ -206,7 +218,8 @@ int main(int argc, char **argv)
log_to_syslog();
break;
case 'H':
hostname = xstrdup(optarg);
hostnames[name_i] = xstrdup(optarg);
++name_i;
break;
case 'i':
iface = xstrdup(optarg);
Expand Down Expand Up @@ -236,13 +249,13 @@ int main(int argc, char **argv)
register_signal(SIGTERM, signal_handler);
register_signal(SIGHUP, signal_handler);

if (!hostname) {
hostname = xzalloc(MAXHOSTNAMELEN);
if (gethostname(hostname, MAXHOSTNAMELEN) != 0) {
if (name_i == 0) {
hostnames[0] = xzalloc(MAXHOSTNAMELEN);
if (gethostname(hostnames[0], MAXHOSTNAMELEN) != 0) {
log_err("Failed to get hostname");
return EXIT_FAILURE;
}
hostname[MAXHOSTNAMELEN - 1] = '\0';
hostnames[0][MAXHOSTNAMELEN - 1] = '\0';

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

log_info("Starting llmnrd on port %u, hostname %s\n", port, hostname);
log_info("Starting llmnrd on port %u. Assigned hostname(s):\n", port);

for(name_i = 0; name_i < name_count; ++name_i)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space after the for keyword:

Suggested change
for(name_i = 0; name_i < name_count; ++name_i)
for (name_i = 0; name_i < name_count; ++name_i)

log_info("%s\n", hostnames[name_i]);

if (iface)
log_info("Binding to interface %s\n", iface);

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

llmnr_init(hostname, ipv6);
llmnr_init((const char **) hostnames, name_count, ipv6);
tklauser marked this conversation as resolved.
Show resolved Hide resolved

ret = iface_init(llmnrd_sock_rtnl, iface, ipv6, &iface_event_handle);
if (ret < 0)
Expand Down Expand Up @@ -318,7 +335,7 @@ int main(int argc, char **argv)
if (llmnrd_sock_ipv6 >= 0 && FD_ISSET(llmnrd_sock_ipv6, &rfds))
llmnr_recv(llmnrd_sock_ipv6);
if (llmnrd_fd_hostname >= 0 && FD_ISSET(llmnrd_fd_hostname, &efds))
hostname_change_handle(hostname, MAXHOSTNAMELEN);
hostname_change_handle(hostnames[0], MAXHOSTNAMELEN);
}
}

Expand All @@ -332,7 +349,11 @@ int main(int argc, char **argv)
close(llmnrd_sock_ipv6);
if (llmnrd_sock_ipv4 >= 0)
close(llmnrd_sock_ipv4);
free(hostname);
for(name_i = 0; name_i < name_count; ++name_i) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a space after the for keyword:

Suggested change
for(name_i = 0; name_i < name_count; ++name_i) {
for (name_i = 0; name_i < name_count; ++name_i) {

free(hostnames[name_i]);
}
free(hostnames);
llmnr_release();
if (rm_pid_file)
unlink(PIDFILE);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
Expand Down