blob: a66952665c0f0fca1eff0451df953f82cb4687ca [file] [log] [blame]
Neels Hofmeyr407925d2019-11-20 03:35:37 +01001/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
2 *
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <stdlib.h>
21#include <unistd.h>
22
23#include <osmocom/mslookup/mslookup.h>
24#include <osmocom/mslookup/mdns.h>
25#include <osmocom/hlr/logging.h>
26#include <osmocom/hlr/hlr.h>
27#include <osmocom/hlr/mslookup_server.h>
28#include <osmocom/hlr/mslookup_server_mdns.h>
29
30static void osmo_mslookup_server_mdns_tx(struct osmo_mslookup_server_mdns *server,
31 uint16_t packet_id,
32 const struct osmo_mslookup_query *query,
33 const struct osmo_mslookup_result *result)
34{
35 struct msgb *msg;
36 const char *errmsg = NULL;
37 void *ctx = talloc_named_const(server, 0, __func__);
38
39 msg = osmo_mdns_result_encode(ctx, packet_id, query, result, server->domain_suffix);
40 if (!msg)
41 errmsg = "Error encoding mDNS answer packet";
42 else if (osmo_mdns_sock_send(server->sock, msg))
43 errmsg = "Error sending mDNS answer";
44 if (errmsg)
45 LOGP(DMSLOOKUP, LOGL_ERROR, "%s: mDNS: %s\n", osmo_mslookup_result_name_c(ctx, query, result), errmsg);
46 talloc_free(ctx);
47}
48
49static void osmo_mslookup_server_mdns_handle_request(uint16_t packet_id,
50 struct osmo_mslookup_server_mdns *server,
51 const struct osmo_mslookup_query *query)
52{
53 struct osmo_mslookup_result result;
54
55 mslookup_server_rx(query, &result);
56 /* Error logging already happens in mslookup_server_rx() */
57 if (result.rc != OSMO_MSLOOKUP_RC_RESULT)
58 return;
59
60 osmo_mslookup_server_mdns_tx(server, packet_id, query, &result);
61}
62
63static int osmo_mslookup_server_mdns_rx(struct osmo_fd *osmo_fd, unsigned int what)
64{
65 struct osmo_mslookup_server_mdns *server = osmo_fd->data;
66 struct osmo_mslookup_query *query;
67 uint16_t packet_id;
68 int n;
69 uint8_t buffer[1024];
70 void *ctx;
71
72 /* Parse the message and print it */
73 n = read(osmo_fd->fd, buffer, sizeof(buffer));
Neels Hofmeyr010ceb82020-05-04 19:15:22 +020074 if (n <= 0)
Neels Hofmeyr407925d2019-11-20 03:35:37 +010075 return n;
76
77 ctx = talloc_named_const(server, 0, __func__);
78 query = osmo_mdns_query_decode(ctx, buffer, n, &packet_id, server->domain_suffix);
79 if (!query) {
80 talloc_free(ctx);
81 return -1;
82 }
83
84 osmo_mslookup_id_name_buf((char *)buffer, sizeof(buffer), &query->id);
85 LOGP(DMSLOOKUP, LOGL_DEBUG, "mDNS rx request: %s.%s\n", query->service, buffer);
86 osmo_mslookup_server_mdns_handle_request(packet_id, server, query);
87 talloc_free(ctx);
88 return n;
89}
90
91struct osmo_mslookup_server_mdns *osmo_mslookup_server_mdns_start(void *ctx, const struct osmo_sockaddr_str *bind_addr,
92 const char *domain_suffix)
93{
94 struct osmo_mslookup_server_mdns *server = talloc_zero(ctx, struct osmo_mslookup_server_mdns);
95 OSMO_ASSERT(server);
96 *server = (struct osmo_mslookup_server_mdns){
97 .bind_addr = *bind_addr,
98 .domain_suffix = talloc_strdup(server, domain_suffix)
99 };
100
101 server->sock = osmo_mdns_sock_init(server,
102 bind_addr->ip, bind_addr->port,
103 osmo_mslookup_server_mdns_rx,
104 server, 0);
105 if (!server->sock) {
106 LOGP(DMSLOOKUP, LOGL_ERROR,
107 "mslookup mDNS server: error initializing multicast bind on " OSMO_SOCKADDR_STR_FMT "\n",
108 OSMO_SOCKADDR_STR_FMT_ARGS(bind_addr));
109 talloc_free(server);
110 return NULL;
111 }
112
113 return server;
114}
115
116void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server)
117{
118 if (!server)
119 return;
120 osmo_mdns_sock_cleanup(server->sock);
121 talloc_free(server);
122}
123
124void mslookup_server_mdns_config_apply()
125{
126 /* Check whether to start/stop/restart mDNS server */
127 bool should_run;
128 bool should_stop;
129
130 should_run = g_hlr->mslookup.allow_startup
131 && g_hlr->mslookup.server.enable && g_hlr->mslookup.server.mdns.enable;
132 should_stop = g_hlr->mslookup.server.mdns.running
133 && (!should_run
134 || osmo_sockaddr_str_cmp(&g_hlr->mslookup.server.mdns.bind_addr,
135 &g_hlr->mslookup.server.mdns.running->bind_addr)
136 || strcmp(g_hlr->mslookup.server.mdns.domain_suffix,
137 g_hlr->mslookup.server.mdns.running->domain_suffix));
138
139 if (should_stop) {
140 osmo_mslookup_server_mdns_stop(g_hlr->mslookup.server.mdns.running);
141 g_hlr->mslookup.server.mdns.running = NULL;
142 LOGP(DMSLOOKUP, LOGL_NOTICE, "Stopped mslookup mDNS server\n");
143 }
144
145 if (should_run && !g_hlr->mslookup.server.mdns.running) {
146 g_hlr->mslookup.server.mdns.running =
147 osmo_mslookup_server_mdns_start(g_hlr, &g_hlr->mslookup.server.mdns.bind_addr,
148 g_hlr->mslookup.server.mdns.domain_suffix);
149 if (!g_hlr->mslookup.server.mdns.running)
150 LOGP(DMSLOOKUP, LOGL_ERROR, "Failed to start mslookup mDNS server on " OSMO_SOCKADDR_STR_FMT "\n",
151 OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.bind_addr));
152 else
153 LOGP(DMSLOOKUP, LOGL_NOTICE, "Started mslookup mDNS server, receiving mDNS requests at multicast "
154 OSMO_SOCKADDR_STR_FMT "\n",
155 OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.running->bind_addr));
156 }
157}