blob: 52db94a26857ae63c7c3a28008029a6deba3248f [file] [log] [blame]
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -03001/*
2 * Copyright (c) 2010 Christiano F. Haesbaert <haesbaert@haesbaert.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <sys/socket.h>
Christiano F. Haesbaertadb23832010-06-22 22:42:05 -030020#include <sys/queue.h>
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030021#include <sys/un.h>
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -030022#include <netinet/in.h>
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030023
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030024#include <arpa/inet.h>
25
Christiano F. Haesbaertc98f5702010-05-06 20:17:19 -030026#include <fcntl.h>
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030027#include <errno.h>
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -020028#include <err.h>
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -030029#include <stdio.h>
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -020030#include <stdlib.h>
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030031#include <string.h>
32#include <unistd.h>
33
Christiano F. Haesbaertadb23832010-06-22 22:42:05 -030034#include <imsg.h>
35
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030036#include "../mdnsd/mdnsd.h"
Christiano F. Haesbaertd3ca1bb2010-03-20 01:11:31 -030037#include "mdns.h"
Christiano F. Haesbaertd3ca1bb2010-03-20 01:11:31 -030038
Christiano F. Haesbaertc98f5702010-05-06 20:17:19 -030039static int mdns_connect(void);
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -030040static int mdns_lookup_do(struct mdns *, const char [MAXHOSTNAMELEN],
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030041 u_int16_t, u_int16_t);
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -030042static int ibuf_send_imsg(struct imsgbuf *, u_int32_t,
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030043 void *, u_int16_t);
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -030044static int splitdname(char [MAXHOSTNAMELEN], char [MAXHOSTNAMELEN],
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -030045 char [MAXLABEL], char [4], int *);
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -020046static int imsgctl_to_event(int);
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -030047
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -020048static int mdns_browse_adddel(struct mdns *, const char *, const char *, u_int);
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -030049static int mdns_handle_lookup(struct mdns *, struct rr *, int);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030050static int mdns_handle_browse(struct mdns *, struct rr *, int);
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -030051static int mdns_handle_resolve(struct mdns *, struct mdns_service *, int);
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -020052static int mdns_handle_group(struct mdns *, char [MAXHOSTNAMELEN], int);
Christiano F. Haesbaert572e6292010-05-01 10:51:18 -030053
Christiano F. Haesbaert83d50a92010-03-07 18:56:01 -030054int
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030055mdns_open(struct mdns *m)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -030056{
Christiano F. Haesbaert82ab04e2010-05-27 20:56:41 -030057 int sockfd;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030058
59 bzero(m, sizeof(*m));
Christiano F. Haesbaert82ab04e2010-05-27 20:56:41 -030060 if ((sockfd = mdns_connect()) == -1)
61 return (-1);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030062 imsg_init(&m->ibuf, sockfd);
63
Christiano F. Haesbaert82ab04e2010-05-27 20:56:41 -030064 return (sockfd);
65}
66
67void
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030068mdns_close(struct mdns *m)
Christiano F. Haesbaert82ab04e2010-05-27 20:56:41 -030069{
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030070 imsg_clear(&m->ibuf);
71}
72
73void
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -030074mdns_set_lookup_A_hook(struct mdns *m, lookup_A_hook lhk)
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030075{
76 m->lhk_A = lhk;
77}
78
79void
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -030080mdns_set_lookup_PTR_hook(struct mdns *m, lookup_PTR_hook lhk)
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030081{
82 m->lhk_PTR = lhk;
83}
84
85void
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -030086mdns_set_lookup_HINFO_hook(struct mdns *m, lookup_HINFO_hook hhk)
Christiano F. Haesbaertdc6aa5d2010-09-04 20:20:45 -030087{
88 m->lhk_HINFO = hhk;
89}
90
91void
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -030092mdns_set_browse_hook(struct mdns *m, browse_hook bhk)
93{
94 m->bhk = bhk;
95}
96
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -030097void
98mdns_set_resolve_hook(struct mdns *m, resolve_hook rhk)
99{
100 m->rhk = rhk;
101}
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300102
103void
104mdns_set_udata(struct mdns *m, void *udata)
105{
106 m->udata = udata;
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300107}
108
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200109void
110mdns_set_group_hook(struct mdns *m, group_hook ghk)
111{
112 m->ghk = ghk;
113}
114
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300115int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300116mdns_lookup_A(struct mdns *m, const char *host)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300117{
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300118 return (mdns_lookup_do(m, host, T_A, C_IN));
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300119}
120
121int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300122mdns_lookup_PTR(struct mdns *m, const char *ptr)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300123{
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300124 return (mdns_lookup_do(m, ptr, T_PTR, C_IN));
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300125}
126
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300127int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300128mdns_lookup_rev(struct mdns *m, struct in_addr *addr)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300129{
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300130 char name[MAXHOSTNAMELEN];
Christiano F. Haesbaertb57f0d32010-05-26 11:05:53 -0300131
Christiano F. Haesbaert7fe38c72010-09-04 19:38:57 -0300132 reversstr(name, addr);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300133 name[sizeof(name) - 1] = '\0';
134
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300135 return (mdns_lookup_PTR(m, name));
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300136}
137
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300138int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300139mdns_lookup_HINFO(struct mdns *m, const char *host)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300140{
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300141 return (mdns_lookup_do(m, host, T_HINFO, C_IN));
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300142}
143
144static int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300145mdns_lookup_do(struct mdns *m, const char name[MAXHOSTNAMELEN], u_int16_t type,
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300146 u_int16_t class)
147{
148 struct rrset rrs;
149
150 bzero(&rrs, sizeof(rrs));
151 rrs.type = type;
152 rrs.class = class;
153 if (strlcpy(rrs.dname, name, sizeof(rrs.dname)) >= sizeof(rrs.dname)) {
154 errno = ENAMETOOLONG;
155 return (-1);
156 }
157 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_LOOKUP,
158 &rrs, sizeof(rrs)) == -1)
159 return (-1); /* XXX: set errno */
160
161 return (0);
162}
163
164int
165mdns_browse_add(struct mdns *m, const char *app, const char *proto)
166{
167 return (mdns_browse_adddel(m, app, proto, IMSG_CTL_BROWSE_ADD));
168}
169
170int
171mdns_browse_del(struct mdns *m, const char *app, const char *proto)
172{
173 return (mdns_browse_adddel(m, app, proto, IMSG_CTL_BROWSE_DEL));
174}
175
176static int
177mdns_browse_adddel(struct mdns *m, const char *app, const char *proto,
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200178 u_int msgtype)
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300179{
Christiano F. Haesbaert1ad8a8a2010-08-16 00:00:03 -0300180 struct rrset mlkup;
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300181
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300182 if (app != NULL && strlen(app) > MAXHOSTNAMELEN) {
183 errno = ENAMETOOLONG;
184 return (-1);
185 }
186
187 bzero(&mlkup, sizeof(mlkup));
188
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300189 /* browsing for service types */
190 if (app == NULL && proto == NULL)
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200191 (void)strlcpy(mlkup.dname, "_services._dns-sd._udp.local",
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300192 sizeof(mlkup.dname));
Christiano F. Haesbaert068d6112010-06-08 19:00:19 -0300193 else if (snprintf(mlkup.dname, sizeof(mlkup.dname),
194 "_%s._%s.local", app, proto) >= (int) sizeof(mlkup.dname)) {
195 errno = ENAMETOOLONG;
196 return (-1);
197 }
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300198 mlkup.type = T_PTR;
199 mlkup.class = C_IN;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300200
201 if (ibuf_send_imsg(&m->ibuf, msgtype,
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300202 &mlkup, sizeof(mlkup)) == -1)
203 return (-1); /* XXX: set errno */
204
Christiano F. Haesbaert307df702010-05-25 20:40:58 -0300205 return (0);
206}
207
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300208int
209mdns_resolve(struct mdns *m, const char *name, const char *app,
210 const char *proto)
211{
212 char buf[MAXHOSTNAMELEN];
213
214 if (strcmp(proto, "tcp") != 0 && strcmp(proto, "udp") != 0) {
215 errno = EINVAL;
216 return (-1);
217 }
218
219 if (snprintf(buf, sizeof(buf), "%s._%s._%s.local",
220 name, app, proto) >= (int) sizeof(buf)) {
221 errno = ENAMETOOLONG;
222 return (-1);
223 }
224
225 buf[sizeof(buf) - 1] = '\0';
226
227 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_RESOLVE,
228 buf, sizeof(buf)) == -1)
229 return (-1); /* XXX: set errno */
230
231 return (0);
232}
233
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200234int
235mdns_group_add(struct mdns *m, const char *group)
Christiano F. Haesbaertbfdba022010-10-17 16:29:46 -0200236{
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200237 char msg[MAXHOSTNAMELEN];
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200238
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200239 bzero(msg, sizeof(msg));
240 if (strlcpy(msg, group, sizeof(msg))
241 >= sizeof(msg))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200242 return (-1);
243 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_GROUP_ADD,
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200244 msg, sizeof(msg)) == -1)
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200245 return (-1);
246
247 return (0);
Christiano F. Haesbaertbfdba022010-10-17 16:29:46 -0200248}
249
250int
Christiano F. Haesbaert259edee2010-10-25 22:35:27 -0200251mdns_group_reset(struct mdns *m, const char *group)
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200252{
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200253 char msg[MAXHOSTNAMELEN];
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200254
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200255 bzero(msg, sizeof(msg));
256 if (strlcpy(msg, group, sizeof(msg))
257 >= sizeof(msg))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200258 return (-1);
Christiano F. Haesbaert259edee2010-10-25 22:35:27 -0200259 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_GROUP_RESET,
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200260 msg, sizeof(msg)) == -1)
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200261 return (-1);
262
263 return (0);
264}
265
266int
267mdns_group_add_service(struct mdns *m, const char *group,
268 struct mdns_service *ms)
269{
Christiano F. Haesbaert259edee2010-10-25 22:35:27 -0200270 if (strcmp(group, ms->name) != 0)
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200271 return (-1);
272 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_GROUP_ADD_SERVICE,
273 ms, sizeof(*ms)) == -1)
274 return (-1);
275
276 return (0);
277}
278
279int
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200280mdns_group_commit(struct mdns *m, const char *group)
281{
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200282 char msg[MAXHOSTNAMELEN];
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200283
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200284 if (strlcpy(msg, group, sizeof(msg))
285 >= sizeof(msg))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200286 return (-1);
287 if (ibuf_send_imsg(&m->ibuf, IMSG_CTL_GROUP_COMMIT,
Christiano F. Haesbaert1e7081e2010-10-30 22:56:46 -0200288 msg, sizeof(msg)) == -1)
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200289 return (-1);
290
291 return (0);
292}
293
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200294int
295mdns_service_init(struct mdns_service *ms, const char *name, const char *app,
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200296 const char *proto, u_int16_t port, const char *txt, struct in_addr *addr)
Christiano F. Haesbaertbfdba022010-10-17 16:29:46 -0200297{
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200298 bzero(ms, sizeof(*ms));
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200299
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200300 if (strcmp(proto, "tcp") != 0 && strcmp(proto, "udp") != 0)
301 return (-1);
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200302 if (strlcpy(ms->name, name, sizeof(ms->name)) >= sizeof(ms->name))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200303 return (-1);
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200304 if (strlcpy(ms->app, app, sizeof(ms->app)) >= sizeof(ms->app))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200305 return (-1);
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200306 if (strlcpy(ms->proto, proto, sizeof(ms->proto)) >= sizeof(ms->proto))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200307 return (-1);
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200308 ms->port = port;
309 if (strlcpy(ms->txt, txt, sizeof(ms->txt)) >= sizeof(ms->txt))
Christiano F. Haesbaertccf0bfd2010-10-22 21:50:14 -0200310 return (-1);
Christiano F. Haesbaertd1a20822010-10-17 17:39:55 -0200311 if (addr != NULL)
312 ms->addr = *addr;
313
Christiano F. Haesbaertdd7033e2010-10-17 16:40:55 -0200314 return (0);
315}
316
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300317ssize_t
318mdns_read(struct mdns *m)
319{
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200320 int ev;
321 size_t r;
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300322 ssize_t n;
323 struct imsg imsg;
324 struct rr rr;
325 struct mdns_service ms;
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200326 char groupname[MAXHOSTNAMELEN];
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300327
328 n = imsg_read(&m->ibuf);
329
330 if (n == -1 || n == 0)
331 return (n);
332
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200333 /* TODO call imsgctl_to_event() */
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300334 while ((r = imsg_get(&m->ibuf, &imsg)) > 0) {
335 switch (imsg.hdr.type) {
336 case IMSG_CTL_LOOKUP: /* FALLTHROUGH */
337 case IMSG_CTL_LOOKUP_FAILURE:
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300338 if ((imsg.hdr.len - IMSG_HEADER_SIZE) != sizeof(rr))
339 return (-1);
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300340 ev = imsg.hdr.type == IMSG_CTL_LOOKUP ?
Christiano F. Haesbaertbf5ee762010-09-30 20:53:23 -0300341 MDNS_LOOKUP_SUCCESS : MDNS_LOOKUP_FAILURE;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300342 memcpy(&rr, imsg.data, sizeof(rr));
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300343 r = mdns_handle_lookup(m, &rr, ev);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300344 break;
345 case IMSG_CTL_BROWSE_ADD:
346 case IMSG_CTL_BROWSE_DEL:
347 if ((imsg.hdr.len - IMSG_HEADER_SIZE) != sizeof(rr))
348 return (-1);
349 ev = imsg.hdr.type == IMSG_CTL_BROWSE_ADD ?
Christiano F. Haesbaertbf5ee762010-09-30 20:53:23 -0300350 MDNS_SERVICE_UP : MDNS_SERVICE_DOWN;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300351 memcpy(&rr, imsg.data, sizeof(rr));
352 r = mdns_handle_browse(m, &rr, ev);
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300353 break;
354 case IMSG_CTL_RESOLVE:
355 case IMSG_CTL_RESOLVE_FAILURE:
356 if ((imsg.hdr.len - IMSG_HEADER_SIZE) != sizeof(ms))
357 return (-1);
358 ev = imsg.hdr.type == IMSG_CTL_RESOLVE ?
Christiano F. Haesbaertbf5ee762010-09-30 20:53:23 -0300359 MDNS_RESOLVE_SUCCESS : MDNS_RESOLVE_FAILURE;
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300360 memcpy(&ms, imsg.data, sizeof(ms));
361 r = mdns_handle_resolve(m, &ms, ev);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300362 break;
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200363 case IMSG_CTL_GROUP_ADD:
364 case IMSG_CTL_GROUP_RESET:
365 case IMSG_CTL_GROUP_ADD_SERVICE:
366 case IMSG_CTL_GROUP_COMMIT:
367 case IMSG_CTL_GROUP_ERR_COLLISION:
368 case IMSG_CTL_GROUP_ERR_NOT_FOUND:
369 case IMSG_CTL_GROUP_ERR_DOUBLE_ADD:
370 case IMSG_CTL_GROUP_PROBING:
371 case IMSG_CTL_GROUP_ANNOUNCING:
372 case IMSG_CTL_GROUP_PUBLISHED:
373 if ((imsg.hdr.len - IMSG_HEADER_SIZE) !=
374 sizeof(groupname))
375 return (-1);
376 if ((ev = imsgctl_to_event(imsg.hdr.type)) == -1)
377 return (-1);
378 memcpy(groupname, imsg.data, sizeof(groupname));
379 r = mdns_handle_group(m, groupname, ev);
380
381
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300382 default:
383 return (-1);
384 }
385
386 imsg_free(&imsg);
387 }
388
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300389 return (n);
390}
391
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300392static int
Christiano F. Haesbaert4093a2f2010-09-04 20:25:50 -0300393mdns_handle_lookup(struct mdns *m, struct rr *rr, int ev)
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300394{
Christiano F. Haesbaertdc6aa5d2010-09-04 20:20:45 -0300395 struct hinfo *h;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300396 switch (rr->rrs.type) {
397 case T_A:
398 if (m->lhk_A == NULL)
399 return (0);
400 m->lhk_A(m, ev, rr->rrs.dname, rr->rdata.A);
401 break;
402 case T_PTR:
403 if (m->lhk_PTR == NULL)
404 return (0);
405 m->lhk_PTR(m, ev, rr->rrs.dname, rr->rdata.PTR);
406 break;
Christiano F. Haesbaertdc6aa5d2010-09-04 20:20:45 -0300407 case T_HINFO:
408 if (m->lhk_HINFO == NULL)
409 return (0);
410 h = &rr->rdata.HINFO;
411 m->lhk_HINFO(m, ev, rr->rrs.dname, h->cpu, h->os);
412 break;
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300413 default:
414 return (-1);
415 }
416
417 return (0);
418}
419
420static int
421mdns_handle_browse(struct mdns *m, struct rr *rr, int ev)
422{
423 char name[MAXHOSTNAMELEN];
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300424 char app[MAXLABELLEN];
425 char proto[MAXPROTOLEN];
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300426 int hasname;
427
428 if (rr->rrs.type != T_PTR)
429 return (-1);
430
431 if (m->bhk == NULL)
432 return (0);
433
Christiano F. Haesbaert0cce8042010-09-14 18:10:34 -0300434 if (splitdname(rr->rdata.PTR, name, app, proto, &hasname) == -1)
435 return (-1);
436
437 if (hasname)
438 m->bhk(m, ev, name, app, proto);
439 else
440 m->bhk(m, ev, NULL, app, proto);
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300441
442 return (0);
443}
444
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300445static int
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300446mdns_handle_resolve(struct mdns *m, struct mdns_service *ms, int ev)
447{
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300448 int hasname;
449
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300450 if (m->rhk == NULL)
451 return (0);
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300452 if (splitdname(ms->name, ms->name, ms->app, ms->proto, &hasname) == -1)
453 return (-1);
Christiano F. Haesbaert5685e902010-09-24 09:16:51 -0300454 if (hasname == 0)
Christiano F. Haesbaert339c5872010-09-14 18:17:53 -0300455 return (-1);
456
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300457 m->rhk(m, ev, ms);
458
459 return (0);
460}
461
462static int
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200463mdns_handle_group(struct mdns *m, char groupname[MAXHOSTNAMELEN], int ev)
464{
465 if (m->ghk == NULL)
466 return (0);
467
468 m->ghk(m, ev, groupname);
469
470 return (0);
471}
472
473static int
Christiano F. Haesbaertc98f5702010-05-06 20:17:19 -0300474mdns_connect(void)
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300475{
476 struct sockaddr_un sun;
477 int sockfd;
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300478
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300479 bzero(&sun, sizeof(sun));
480 if ((sockfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
481 return (-1);
482 sun.sun_family = AF_UNIX;
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200483 (void)strlcpy(sun.sun_path, MDNSD_SOCKET,
484 sizeof(sun.sun_path));
Christiano F. Haesbaert6162f3a2010-03-25 19:30:23 -0300485 if (connect(sockfd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
486 if (errno == ENOENT)
487 errno = ECONNREFUSED;
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300488 return (-1);
Christiano F. Haesbaert6162f3a2010-03-25 19:30:23 -0300489 }
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300490
Christiano F. Haesbaertc98f5702010-05-06 20:17:19 -0300491 return (sockfd);
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300492}
493
494static int
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -0300495ibuf_send_imsg(struct imsgbuf *ibuf, u_int32_t type,
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300496 void *data, u_int16_t datalen)
497{
Christiano F. Haesbaertadb23832010-06-22 22:42:05 -0300498 struct ibuf *wbuf;
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300499
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -0300500 if ((wbuf = imsg_create(ibuf, type, 0,
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300501 0, datalen)) == NULL)
502 return (-1);
503
Christiano F. Haesbaert31ed96a2010-03-29 18:00:49 -0300504 if (imsg_add(wbuf, data, datalen) == -1)
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300505 return (-1);
506
507 wbuf->fd = -1;
508
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -0300509 imsg_close(ibuf, wbuf);
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300510
Christiano F. Haesbaert435f1b82010-04-27 19:39:03 -0300511 if (msgbuf_write(&ibuf->w))
Christiano F. Haesbaert0e2793e2010-02-22 20:13:59 -0300512 return (-1);
513
514 return (0);
515}
516
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300517/* XXX: Too ugly, code me again with love */
518static int
519splitdname(char fname[MAXHOSTNAMELEN], char sname[MAXHOSTNAMELEN],
Christiano F. Haesbaert339c5872010-09-14 18:17:53 -0300520 char app[MAXLABEL], char proto[MAXPROTOLEN], int *hasname)
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300521{
522 char namecp[MAXHOSTNAMELEN];
523 char *p, *start;
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300524
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300525 *hasname = 1;
Christiano F. Haesbaert0a577d42010-09-06 03:33:58 -0300526/* ubuntu810desktop [00:0c:29:4d:22:ce]._workstation._tcp.local */
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300527/* _workstation._tcp.local */
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300528 /* work on a copy */
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200529 (void)strlcpy(namecp, fname, sizeof(namecp));
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300530
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300531 /* check if we have a name, or only an application protocol */
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300532 if ((p = strstr(namecp, "._")) != NULL) {
533 p += 2;
534 if ((p = strstr(p, "._")) == NULL)
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300535 *hasname = 0;
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300536 }
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300537
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300538 p = start = namecp;
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300539
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300540 /* if we have a name, copy */
Christiano F. Haesbaert803e9672010-09-14 23:32:58 -0300541 if (*hasname == 1 && sname != NULL) {
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300542 if ((p = strstr(start, "._")) == NULL)
543 return (-1);
544 *p++ = 0;
545 p++;
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200546 (void)strlcpy(sname, start, MAXHOSTNAMELEN);
Christiano F. Haesbaertbd49de02010-06-01 19:51:50 -0300547 start = p;
548 }
549 else
550 start++;
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300551
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300552 if ((p = strstr(start, "._")) == NULL)
553 return (-1);
554 *p++ = 0;
555 p++;
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200556 (void)strlcpy(app, start, MAXLABEL);
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300557 start = p;
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300558
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300559 if ((p = strstr(start, ".")) == NULL)
560 return (-1);
561 *p++ = 0;
Christiano F. Haesbaerteefe6de2010-10-27 20:48:30 -0200562 (void)strlcpy(proto, start, MAXPROTOLEN);
Christiano F. Haesbaertbeea4662010-07-02 02:57:14 -0300563
Christiano F. Haesbaertae99b252010-05-28 23:37:15 -0300564 return (0);
565}
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300566
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200567static int
568imsgctl_to_event(int msgtype)
569{
570 switch (msgtype) {
571 case IMSG_CTL_GROUP_ERR_COLLISION:
572 return
573 (MDNS_GROUP_ERR_COLLISION);
574 break;
575 case IMSG_CTL_GROUP_ERR_NOT_FOUND:
576 return
577 (MDNS_GROUP_ERR_NOT_FOUND);
578 break;
579 case IMSG_CTL_GROUP_ERR_DOUBLE_ADD:
580 return
581 (MDNS_GROUP_ERR_DOUBLE_ADD);
582 break;
583 case IMSG_CTL_GROUP_PROBING:
584 return
585 (MDNS_GROUP_PROBING);
586 break;
587 case IMSG_CTL_GROUP_ANNOUNCING:
588 return
589 (MDNS_GROUP_ANNOUNCING);
590 break;
591 case IMSG_CTL_GROUP_PUBLISHED:
592 return
593 (MDNS_GROUP_PUBLISHED);
594 break;
595 default:
596 /* TODO remove this once in the wild */
597 warnx("imsgctl_to_event: Unknown imsgctl %d",
598 msgtype);
599 }
600 /* NOTREACHED */
601 return (-1);
602}
603
Christiano F. Haesbaerte14e1192010-09-04 19:16:08 -0300604void
605reversstr(char str[MAXHOSTNAMELEN], struct in_addr *addr)
606{
607 const u_char *uaddr = (const u_char *)addr;
608
609 (void) snprintf(str, MAXHOSTNAMELEN, "%u.%u.%u.%u.in-addr.arpa",
610 (uaddr[3] & 0xff), (uaddr[2] & 0xff),
611 (uaddr[1] & 0xff), (uaddr[0] & 0xff));
612}
Christiano F. Haesbaert1a411ef2010-12-31 14:32:48 -0200613