3 * Copyright (c) 2018-2019 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * This file contains support routines for the DNSSD SRP update and mDNS proxies.
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
34 #include "srp-crypto.h"
36 #include "dnssd-proxy.h"
38 #include "config-parse.h"
39 #include "srp-proxy.h"
41 static dns_name_t
*service_update_zone
; // The zone to update when we receive an update for default.service.arpa.
43 // Free the data structures into which the SRP update was parsed. The pointers to the various DNS objects that these
44 // structures point to are owned by the parsed DNS message, and so these do not need to be freed here.
46 srp_update_free_parts(service_instance_t
*service_instances
, service_instance_t
*added_instances
,
47 service_t
*services
, dns_host_description_t
*host_description
)
49 service_instance_t
*sip
;
52 for (sip
= service_instances
; sip
; ) {
53 service_instance_t
*next
= sip
->next
;
57 for (sip
= added_instances
; sip
; ) {
58 service_instance_t
*next
= sip
->next
;
62 for (sp
= services
; sp
; ) {
63 service_t
*next
= sp
->next
;
67 if (host_description
!= NULL
) {
68 host_addr_t
*host_addr
, *next
;
69 for (host_addr
= host_description
->addrs
; host_addr
; host_addr
= next
) {
70 next
= host_addr
->next
;
73 free(host_description
);
78 add_host_addr(host_addr_t
**dest
, dns_rr_t
*rr
)
80 host_addr_t
*addr
= calloc(1, sizeof *addr
);
82 ERROR("add_host_addr: no memory for record");
87 dest
= &(*dest
)->next
;
95 replace_zone_name(dns_name_t
**nzp_in
, dns_name_t
*uzp
, dns_name_t
*replacement_zone
)
97 dns_name_t
**nzp
= nzp_in
;
98 while (*nzp
!= NULL
&& *nzp
!= uzp
) {
99 nzp
= &((*nzp
)->next
);
102 ERROR("replace_zone: dns_name_subdomain_of returned bogus pointer.");
106 // Free the suffix we're replacing
110 *nzp
= dns_name_copy(replacement_zone
);
112 ERROR("replace_zone_name: no memory for replacement zone");
118 // We call advertise_finished when a client request has finished, successfully or otherwise.
120 send_fail_response(comm_t
*connection
, message_t
*message
, int rcode
)
125 memset(&response
, 0, DNS_HEADER_SIZE
);
126 response
.id
= message
->wire
.id
;
127 response
.bitfield
= message
->wire
.bitfield
;
128 dns_rcode_set(&response
, rcode
);
129 dns_qr_set(&response
, dns_qr_response
);
131 iov
.iov_base
= &response
;
132 iov
.iov_len
= DNS_HEADER_SIZE
;
134 ioloop_send_message(connection
, message
, &iov
, 1);
138 srp_evaluate(comm_t
*connection
, dns_message_t
*message
, message_t
*raw_message
)
141 dns_host_description_t
*host_description
= NULL
;
142 delete_t
*deletes
= NULL
, *dp
, **dpp
= &deletes
;
143 service_instance_t
*service_instances
= NULL
, *sip
, **sipp
= &service_instances
;
144 service_t
*services
= NULL
, *sp
, **spp
= &services
;
148 dns_name_t
*update_zone
, *replacement_zone
;
150 dns_rr_t
*key
= NULL
;
151 dns_rr_t
**keys
= NULL
;
154 bool found_key
= false;
155 uint32_t lease_time
, key_lease_time
;
157 int rcode
= dns_rcode_servfail
;
158 bool found_lease
= false;
160 // Update requires a single SOA record as the question
161 if (message
->qdcount
!= 1) {
162 ERROR("srp_evaluate: update received with qdcount > 1");
166 // Update should contain zero answers.
167 if (message
->ancount
!= 0) {
168 ERROR("srp_evaluate: update received with ancount > 0");
172 if (message
->questions
[0].type
!= dns_rrtype_soa
) {
173 ERROR("srp_evaluate: update received with rrtype %d instead of SOA in question section.",
174 message
->questions
[0].type
);
178 update_zone
= message
->questions
[0].name
;
179 if (service_update_zone
!= NULL
&& dns_names_equal_text(update_zone
, "default.service.arpa.")) {
180 replacement_zone
= service_update_zone
;
182 replacement_zone
= NULL
;
185 // Scan over the authority RRs; do the delete consistency check. We can't do other consistency checks
186 // because we can't assume a particular order to the records other than that deletes have to come before
188 for (i
= 0; i
< message
->nscount
; i
++) {
189 dns_rr_t
*rr
= &message
->authority
[i
];
191 // If this is a delete for all the RRs on a name, record it in the list of deletes.
192 if (rr
->type
== dns_rrtype_any
&& rr
->qclass
== dns_qclass_any
&& rr
->ttl
== 0) {
193 for (dp
= deletes
; dp
; dp
= dp
->next
) {
194 if (dns_names_equal(dp
->name
, rr
->name
)) {
195 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
196 ERROR("srp_evaluate: two deletes for the same name: " PRI_DNS_NAME_SRP
,
197 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
198 rcode
= dns_rcode_formerr
;
202 dp
= calloc(1, sizeof *dp
);
204 ERROR("srp_evaluate: no memory.");
210 // Make sure the name is a subdomain of the zone being updated.
211 dp
->zone
= dns_name_subdomain_of(rr
->name
, update_zone
);
212 if (dp
->zone
== NULL
) {
213 DNS_NAME_GEN_SRP(update_zone
, update_zone_buf
);
214 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
215 ERROR("srp_evaluate: delete for record not in update zone " PRI_DNS_NAME_SRP
": " PRI_DNS_NAME_SRP
,
216 DNS_NAME_PARAM_SRP(update_zone
, update_zone_buf
), DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
217 rcode
= dns_rcode_formerr
;
223 // The update should really only contain one key, but it's allowed for keys to appear on
224 // service instance names as well, since that's what will be stored in the zone. So if
225 // we get one key, we'll assume it's a host key until we're done scanning, and then check.
226 // If we get more than one, we allocate a buffer and store all the keys so that we can
227 // check them all later.
228 else if (rr
->type
== dns_rrtype_key
) {
234 // We can't have more keys than there are authority records left, plus
235 // one for the key we already have, so allocate a buffer that large.
236 max_keys
= message
->nscount
- i
+ 1;
237 keys
= calloc(max_keys
, sizeof *keys
);
239 ERROR("srp_evaluate: no memory");
244 if (num_keys
>= max_keys
) {
245 ERROR("srp_evaluate: coding error in key allocation");
248 keys
[num_keys
++] = rr
;
252 // Otherwise if it's an A or AAAA record, it's part of a hostname entry.
253 else if (rr
->type
== dns_rrtype_a
|| rr
->type
== dns_rrtype_aaaa
) {
254 // Allocate the hostname record
255 if (!host_description
) {
256 host_description
= calloc(1, sizeof *host_description
);
257 if (!host_description
) {
258 ERROR("srp_evaluate: no memory");
263 // Make sure it's preceded by a deletion of all the RRs on the name.
264 if (!host_description
->delete) {
265 for (dp
= deletes
; dp
; dp
= dp
->next
) {
266 if (dns_names_equal(dp
->name
, rr
->name
)) {
271 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
272 ERROR("srp_evaluate: ADD for hostname " PRI_DNS_NAME_SRP
" without a preceding delete.",
273 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
274 rcode
= dns_rcode_formerr
;
277 host_description
->delete = dp
;
278 host_description
->name
= dp
->name
;
279 dp
->consumed
= true; // This delete is accounted for.
281 // In principle, we should be checking this name to see that it's a subdomain of the update
282 // zone. However, it turns out we don't need to, because the /delete/ has to be a subdomain
283 // of the update zone, and we won't find that delete if it's not present.
286 if (rr
->type
== dns_rrtype_a
|| rr
->type
== dns_rrtype_aaaa
) {
287 if (!add_host_addr(&host_description
->addrs
, rr
)) {
293 // Otherwise if it's an SRV entry, that should be a service instance name.
294 else if (rr
->type
== dns_rrtype_srv
|| rr
->type
== dns_rrtype_txt
) {
295 // Should be a delete that precedes this service instance.
296 for (dp
= deletes
; dp
; dp
= dp
->next
) {
297 if (dns_names_equal(dp
->name
, rr
->name
)) {
302 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
303 ERROR("srp_evaluate: ADD for service instance not preceded by delete: " PRI_DNS_NAME_SRP
,
304 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
305 rcode
= dns_rcode_formerr
;
308 for (sip
= service_instances
; sip
; sip
= sip
->next
) {
309 if (dns_names_equal(sip
->name
, rr
->name
)) {
314 sip
= calloc(1, sizeof *sip
);
316 ERROR("srp_evaluate: no memory");
321 sip
->name
= dp
->name
;
325 if (rr
->type
== dns_rrtype_srv
) {
326 if (sip
->srv
!= NULL
) {
327 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
328 ERROR("srp_evaluate: more than one SRV rr received for service instance: " PRI_DNS_NAME_SRP
,
329 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
330 rcode
= dns_rcode_formerr
;
334 } else if (rr
->type
== dns_rrtype_txt
) {
335 if (sip
->txt
!= NULL
) {
336 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
337 ERROR("srp_evaluate: more than one TXT rr received for service instance: " PRI_DNS_NAME_SRP
,
338 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
339 rcode
= dns_rcode_formerr
;
346 // Otherwise if it's a PTR entry, that should be a service name
347 else if (rr
->type
== dns_rrtype_ptr
) {
348 sp
= calloc(1, sizeof *sp
);
350 ERROR("srp_evaluate: no memory");
357 // Make sure the service name is in the update zone.
358 sp
->zone
= dns_name_subdomain_of(sp
->rr
->name
, update_zone
);
359 if (sp
->zone
== NULL
) {
360 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
361 DNS_NAME_GEN_SRP(rr
->data
.ptr
.name
, data_name_buf
);
362 ERROR("srp_evaluate: service name " PRI_DNS_NAME_SRP
" for " PRI_DNS_NAME_SRP
363 " is not in the update zone", DNS_NAME_PARAM_SRP(rr
->name
, name_buf
),
364 DNS_NAME_PARAM_SRP(rr
->data
.ptr
.name
, data_name_buf
));
365 rcode
= dns_rcode_formerr
;
370 // Otherwise it's not a valid update
372 DNS_NAME_GEN_SRP(rr
->name
, name_buf
);
373 ERROR("srp_evaluate: unexpected rrtype %d on " PRI_DNS_NAME_SRP
" in update.", rr
->type
,
374 DNS_NAME_PARAM_SRP(rr
->name
, name_buf
));
375 rcode
= dns_rcode_formerr
;
380 // Now that we've scanned the whole update, do the consistency checks for updates that might
381 // not have come in order.
383 // First, make sure there's a host description.
384 if (host_description
== NULL
) {
385 ERROR("srp_evaluate: SRP update does not include a host description.");
386 rcode
= dns_rcode_formerr
;
390 // Make sure that each service add references a service instance that's in the same update.
391 for (sp
= services
; sp
; sp
= sp
->next
) {
392 for (sip
= service_instances
; sip
; sip
= sip
->next
) {
393 if (dns_names_equal(sip
->name
, sp
->rr
->data
.ptr
.name
)) {
394 // Note that we have already verified that there is only one service instance
395 // with this name, so this could only ever happen once in this loop even without
396 // the break statement.
398 sip
->num_instances
++;
402 // If this service doesn't point to a service instance that's in the update, then the
403 // update fails validation.
405 DNS_NAME_GEN_SRP(sp
->rr
->name
, name_buf
);
406 ERROR("srp_evaluate: service points to an instance that's not included: " PRI_DNS_NAME_SRP
,
407 DNS_NAME_PARAM_SRP(sp
->rr
->name
, name_buf
));
408 rcode
= dns_rcode_formerr
;
413 for (sip
= service_instances
; sip
; sip
= sip
->next
) {
414 // For each service instance, make sure that at least one service references it
415 if (sip
->num_instances
== 0) {
416 DNS_NAME_GEN_SRP(sip
->name
, name_buf
);
417 ERROR("srp_evaluate: service instance update for " PRI_DNS_NAME_SRP
418 " is not referenced by a service update.", DNS_NAME_PARAM_SRP(sip
->name
, name_buf
));
419 rcode
= dns_rcode_formerr
;
423 // For each service instance, make sure that it references the host description
424 if (dns_names_equal(host_description
->name
, sip
->srv
->data
.srv
.name
)) {
425 sip
->host
= host_description
;
426 host_description
->num_instances
++;
430 // Make sure that at least one service instance references the host description
431 if (host_description
->num_instances
== 0) {
432 DNS_NAME_GEN_SRP(host_description
->name
, name_buf
);
433 ERROR("srp_evaluate: host description " PRI_DNS_NAME_SRP
" is not referenced by any service instances.",
434 DNS_NAME_PARAM_SRP(host_description
->name
, name_buf
));
435 rcode
= dns_rcode_formerr
;
439 // Make sure the host description has at least one address record.
440 if (host_description
->addrs
== NULL
) {
441 DNS_NAME_GEN_SRP(host_description
->name
, name_buf
);
442 ERROR("srp_evaluate: host description " PRI_DNS_NAME_SRP
" doesn't contain any IP addresses.",
443 DNS_NAME_PARAM_SRP(host_description
->name
, name_buf
));
444 rcode
= dns_rcode_formerr
;
448 for (i
= 0; i
< num_keys
; i
++) {
449 // If this isn't the only key, make sure it's got the same contents as the other keys.
451 if (!dns_keys_rdata_equal(key
, keys
[i
])) {
452 ERROR("srp_evaluate: more than one key presented");
453 rcode
= dns_rcode_formerr
;
456 // This is a hack so that if num_keys == 1, we don't have to allocate keys[].
457 // At the bottom of this if statement, key is always the key we are looking at.
460 // If there is a key, and the host description doesn't currently have a key, check
461 // there first since that's the default.
462 if (host_description
->key
== NULL
&& dns_names_equal(key
->name
, host_description
->name
)) {
463 host_description
->key
= key
;
466 for (sip
= service_instances
; sip
!= NULL
; sip
= sip
->next
) {
467 if (dns_names_equal(sip
->name
, key
->name
)) {
474 DNS_NAME_GEN_SRP(key
->name
, key_name_buf
);
475 ERROR("srp_evaluate: key present for name " PRI_DNS_NAME_SRP
476 " which is neither a host nor an instance name.", DNS_NAME_PARAM_SRP(key
->name
, key_name_buf
));
477 rcode
= dns_rcode_formerr
;
486 // And make sure it has a key record
487 if (host_description
->key
== NULL
) {
488 DNS_NAME_GEN_SRP(host_description
->name
, host_name_buf
);
489 ERROR("srp_evaluate: host description " PRI_DNS_NAME_SRP
" doesn't contain a key.",
490 DNS_NAME_PARAM_SRP(host_description
->name
, host_name_buf
));
491 rcode
= dns_rcode_formerr
;
495 // Make sure that all the deletes are for things that are then added.
496 for (dp
= deletes
; dp
; dp
= dp
->next
) {
498 DNS_NAME_GEN_SRP(host_description
->name
, host_name_buf
);
499 ERROR("srp_evaluate: delete for which there is no subsequent add: " PRI_DNS_NAME_SRP
,
500 DNS_NAME_PARAM_SRP(host_description
->name
, host_name_buf
));
501 rcode
= dns_rcode_formerr
;
506 // The signature should be the last thing in the additional section. Even if the signature
507 // is valid, if it's not at the end we reject it. Note that we are just checking for SIG(0)
508 // so if we don't find what we're looking for, we forward it to the DNS auth server which
509 // will either accept or reject it.
510 if (message
->arcount
< 1) {
511 ERROR("srp_evaluate: signature not present");
512 rcode
= dns_rcode_formerr
;
515 signature
= &message
->additional
[message
->arcount
-1];
516 if (signature
->type
!= dns_rrtype_sig
) {
517 ERROR("srp_evaluate: signature is not at the end or is not present");
518 rcode
= dns_rcode_formerr
;
522 // Make sure that the signer name is the hostname. If it's not, it could be a legitimate
523 // update with a different key, but it's not an SRP update, so we pass it on.
524 if (!dns_names_equal(signature
->data
.sig
.signer
, host_description
->name
)) {
525 DNS_NAME_GEN_SRP(signature
->data
.sig
.signer
, signer_name_buf
);
526 DNS_NAME_GEN_SRP(host_description
->name
, host_name_buf
);
527 ERROR("srp_evaluate: signer " PRI_DNS_NAME_SRP
" doesn't match host " PRI_DNS_NAME_SRP
,
528 DNS_NAME_PARAM_SRP(signature
->data
.sig
.signer
, signer_name_buf
),
529 DNS_NAME_PARAM_SRP(host_description
->name
, host_name_buf
));
530 rcode
= dns_rcode_formerr
;
534 // Make sure we're in the time limit for the signature. Zeroes for the inception and expiry times
535 // mean the host that send this doesn't have a working clock. One being zero and the other not isn't
536 // valid unless it's 1970.
537 if (signature
->data
.sig
.inception
!= 0 || signature
->data
.sig
.expiry
!= 0) {
538 gettimeofday(&now
, NULL
);
539 // The sender does the bracketing, so we can just do a simple comparison.
540 if ((uint32_t)(now
.tv_sec
& UINT32_MAX
) > signature
->data
.sig
.expiry
||
541 (uint32_t)(now
.tv_sec
& UINT32_MAX
) < signature
->data
.sig
.inception
) {
542 ERROR("signature is not timely: %lu < %lu < %lu does not hold",
543 (unsigned long)signature
->data
.sig
.inception
, (unsigned long)now
.tv_sec
,
544 (unsigned long)signature
->data
.sig
.expiry
);
549 // Now that we have the key, we can validate the signature. If the signature doesn't validate,
550 // there is no need to pass the message on.
551 if (!srp_sig0_verify(&raw_message
->wire
, host_description
->key
, signature
)) {
552 ERROR("signature is not valid");
556 // Now that we have validated the SRP message, go through and fix up all instances of
557 // *default.service.arpa to use the replacement zone, if this update is for
558 // default.services.arpa and there is a replacement zone.
559 if (replacement_zone
!= NULL
) {
560 // All of the service instances and the host use the name from the delete, so if
561 // we update these, the names for those are taken care of. We already found the
562 // zone for which the delete is a subdomain, so we can just replace it without
564 for (dp
= deletes
; dp
; dp
= dp
->next
) {
565 replace_zone_name(&dp
->name
, dp
->zone
, replacement_zone
);
568 // All services have PTR records, which point to names. Both the service name and the
569 // PTR name have to be fixed up.
570 for (sp
= services
; sp
; sp
= sp
->next
) {
571 replace_zone_name(&sp
->rr
->name
, sp
->zone
, replacement_zone
);
572 uzp
= dns_name_subdomain_of(sp
->rr
->data
.ptr
.name
, update_zone
);
573 // We already validated that the PTR record points to something in the zone, so this
574 // if condition should always be false.
576 ERROR("srp_evaluate: service PTR record zone match fail!!");
579 replace_zone_name(&sp
->rr
->data
.ptr
.name
, uzp
, replacement_zone
);
582 // All service instances have SRV records, which point to names. The service instance
583 // name is already fixed up, because it's the same as the delete, but the name in the
584 // SRV record must also be fixed.
585 for (sip
= service_instances
; sip
; sip
= sip
->next
) {
586 uzp
= dns_name_subdomain_of(sip
->srv
->data
.srv
.name
, update_zone
);
587 // We already validated that the SRV record points to something in the zone, so this
588 // if condition should always be false.
590 ERROR("srp_evaluate: service instance SRV record zone match fail!!");
593 replace_zone_name(&sip
->srv
->data
.srv
.name
, uzp
, replacement_zone
);
596 // We shouldn't need to replace the hostname zone because it's actually pointing to
597 // the name of a delete.
600 // Get the lease time.
602 key_lease_time
= 604800;
603 for (edns0
= message
->edns0
; edns0
; edns0
= edns0
->next
) {
604 if (edns0
->type
== dns_opt_update_lease
) {
606 if (edns0
->length
!= 4 && edns0
->length
!= 8) {
607 ERROR("srp_evaluate: edns0 update-lease option length bogus: %d", edns0
->length
);
608 rcode
= dns_rcode_formerr
;
611 dns_u32_parse(edns0
->data
, edns0
->length
, &off
, &lease_time
);
612 if (edns0
->length
== 8) {
613 dns_u32_parse(edns0
->data
, edns0
->length
, &off
, &key_lease_time
);
615 key_lease_time
= 7 * lease_time
;
623 DNS_NAME_GEN_SRP(host_description
->name
, host_description_name_buf
);
624 INFO("srp_evaluate: update for " PRI_DNS_NAME_SRP
" xid %x validates.",
625 DNS_NAME_PARAM_SRP(host_description
->name
, host_description_name_buf
), raw_message
->wire
.id
);
626 rcode
= dns_rcode_noerror
;
627 ret
= srp_update_start(connection
, message
, raw_message
, host_description
, service_instances
, services
,
628 replacement_zone
== NULL
? update_zone
: replacement_zone
,
629 lease_time
, key_lease_time
);
633 ERROR("update start failed");
637 // True means it was intended for us, and shouldn't be forwarded.
639 // We're not actually going to return this; it simply indicates that we aren't sending a fail response.
640 rcode
= dns_rcode_noerror
;
641 // Because we're saying this is ours, we have to free the parsed message.
642 dns_message_free(message
);
645 // free everything we allocated but (it turns out) aren't going to use
649 srp_update_free_parts(service_instances
, NULL
, services
, host_description
);
652 // No matter how we get out of this, we free the delete structures, because they are not
653 // used to do the update.
654 for (dp
= deletes
; dp
; ) {
655 delete_t
*next
= dp
->next
;
660 if (ret
== true && rcode
!= dns_rcode_noerror
) {
661 send_fail_response(connection
, raw_message
, rcode
);
667 dns_evaluate(comm_t
*connection
, message_t
*message
)
669 dns_message_t
*parsed_message
;
671 // Drop incoming responses--we're a server, so we only accept queries.
672 if (dns_qr_get(&message
->wire
) == dns_qr_response
) {
673 ERROR("dns_evaluate: received a message that was a DNS response: %d", dns_opcode_get(&message
->wire
));
677 // Forward incoming messages that are queries but not updates.
678 // XXX do this later--for now we operate only as a translator, not a proxy.
679 if (dns_opcode_get(&message
->wire
) != dns_opcode_update
) {
680 send_fail_response(connection
, message
, dns_rcode_refused
);
681 ERROR("dns_evaluate: received a message that was not a DNS update: %d", dns_opcode_get(&message
->wire
));
685 // Parse the UPDATE message.
686 if (!dns_wire_parse(&parsed_message
, &message
->wire
, message
->length
)) {
687 send_fail_response(connection
, message
, dns_rcode_servfail
);
688 ERROR("dns_wire_parse failed.");
692 // We need the wire message to validate the signature...
693 if (!srp_evaluate(connection
, parsed_message
, message
)) {
694 // The message wasn't invalid, but wasn't an SRP message.
695 dns_message_free(parsed_message
);
696 // dns_forward(connection)
697 send_fail_response(connection
, message
, dns_rcode_refused
);
702 dns_input(comm_t
*comm
, message_t
*message
, void *context
)
705 dns_evaluate(comm
, message
);
708 struct srp_proxy_listener_state
{
709 comm_t
*NULLABLE tcp_listener
;
710 comm_t
*NULLABLE tls_listener
;
711 comm_t
*NULLABLE udp_listener
;
715 srp_proxy_listener_cancel(srp_proxy_listener_state_t
*listener_state
)
717 if (listener_state
->tcp_listener
!= NULL
) {
718 ioloop_listener_cancel(listener_state
->tcp_listener
);
719 ioloop_listener_release(listener_state
->tcp_listener
);
721 if (listener_state
->tls_listener
!= NULL
) {
722 ioloop_listener_cancel(listener_state
->tls_listener
);
723 ioloop_listener_release(listener_state
->tls_listener
);
725 if (listener_state
->udp_listener
!= NULL
) {
726 ioloop_listener_cancel(listener_state
->udp_listener
);
727 ioloop_listener_release(listener_state
->udp_listener
);
729 free(listener_state
);
732 srp_proxy_listener_state_t
*
733 srp_proxy_listen(const char *update_zone
, uint16_t *avoid_ports
, int num_avoid_ports
, ready_callback_t ready
)
735 #if SRP_STREAM_LISTENER_ENABLED
736 uint16_t tcp_listen_port
;
738 uint16_t tls_listen_port
;
741 srp_proxy_listener_state_t
*listeners
= calloc(1, sizeof *listeners
);
742 if (listeners
== NULL
) {
743 ERROR("srp_proxy_listen: no memory for listeners structure.");
747 (void)num_avoid_ports
;
749 #if SRP_STREAM_LISTENER_ENABLED
750 tcp_listen_port
= 53;
751 tls_listen_port
= 853;
755 // XXX UDP listeners should bind to interface addresses, not INADDR_ANY.
756 listeners
->udp_listener
= ioloop_listener_create(false, false, avoid_ports
,
757 num_avoid_ports
, NULL
, NULL
, "UDP listener", dns_input
,
758 NULL
, NULL
, ready
, NULL
, NULL
);
759 if (listeners
->udp_listener
== NULL
) {
760 srp_proxy_listener_cancel(listeners
);
761 ERROR("UDP listener: fail.");
764 #ifdef SRP_STREAM_LISTENER_ENABLED
765 listeners
->tcp_listener
= ioloop_listener_create(true, false, NULL
, 0, NULL
, NULL
,
766 "TCP listener", dns_input
, NULL
, NULL
, ready
, NULL
, NULL
);
767 if (listeners
->tcp_listener
== NULL
) {
768 srp_proxy_listener_cancel(listeners
);
769 ERROR("TCP listener: fail.");
773 listeners
->tls_listener
= ioloop_listener_create(true, true, NULL
, 0, NULL
, NULL
,
774 "TLS listener", dns_input
, NULL
, NULL
, ready
, NULL
, NULL
);
775 if (listeners
->tls_listener
== NULL
) {
776 srp_proxy_listener_cancel(listeners
);
777 ERROR("TLS listener: fail.");
783 // For now, hardcoded, should be configurable
784 if (service_update_zone
!= NULL
) {
785 dns_name_free(service_update_zone
);
787 service_update_zone
= dns_pres_name_parse(update_zone
);
795 // c-file-style: "bsd"
798 // indent-tabs-mode: nil