diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source3/smbd/dnsregister.c | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/smbd/dnsregister.c')
-rw-r--r-- | source3/smbd/dnsregister.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c new file mode 100644 index 0000000..df18900 --- /dev/null +++ b/source3/smbd/dnsregister.c @@ -0,0 +1,200 @@ +/* + Unix SMB/CIFS implementation. + DNS-SD registration + Copyright (C) Rishi Srivatsavai 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <includes.h> +#include "smbd/smbd.h" + +/* Uses DNS service discovery (libdns_sd) to + * register the SMB service. SMB service is registered + * on ".local" domain via Multicast DNS & any + * other unicast DNS domains available. + * + * Users use the smbclient -B (Browse) option to + * browse for advertised SMB services. + */ + +#define DNS_REG_RETRY_INTERVAL (5*60) /* in seconds */ + +#ifdef WITH_DNSSD_SUPPORT + +#include <dns_sd.h> + +struct dns_reg_state { + struct tevent_context *event_ctx; + uint16_t port; + DNSServiceRef srv_ref; + struct tevent_timer *te; + int fd; + struct tevent_fd *fde; +}; + +static int dns_reg_state_destructor(struct dns_reg_state *dns_state) +{ + if (dns_state->srv_ref != NULL) { + /* Close connection to the mDNS daemon */ + DNSServiceRefDeallocate(dns_state->srv_ref); + dns_state->srv_ref = NULL; + } + + /* Clear event handler */ + TALLOC_FREE(dns_state->te); + TALLOC_FREE(dns_state->fde); + dns_state->fd = -1; + + return 0; +} + +static void dns_register_smbd_retry(struct tevent_context *ctx, + struct tevent_timer *te, + struct timeval now, + void *private_data); +static void dns_register_smbd_fde_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data); + +static bool dns_register_smbd_schedule(struct dns_reg_state *dns_state, + struct timeval tval) +{ + dns_reg_state_destructor(dns_state); + + dns_state->te = tevent_add_timer(dns_state->event_ctx, + dns_state, + tval, + dns_register_smbd_retry, + dns_state); + if (!dns_state->te) { + return false; + } + + return true; +} + +static void dns_register_smbd_retry(struct tevent_context *ctx, + struct tevent_timer *te, + struct timeval now, + void *private_data) +{ + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); + DNSServiceErrorType err; + + dns_reg_state_destructor(dns_state); + + DEBUG(6, ("registering _smb._tcp service on port %d\n", + dns_state->port)); + + /* Register service with DNS. Connects with the mDNS + * daemon running on the local system to perform DNS + * service registration. + */ + err = DNSServiceRegister(&dns_state->srv_ref, 0 /* flags */, + kDNSServiceInterfaceIndexAny, + NULL /* service name */, + "_smb._tcp" /* service type */, + NULL /* domain */, + "" /* SRV target host name */, + htons(dns_state->port), + 0 /* TXT record len */, + NULL /* TXT record data */, + NULL /* callback func */, + NULL /* callback context */); + + if (err != kDNSServiceErr_NoError) { + /* Failed to register service. Schedule a re-try attempt. + */ + DEBUG(3, ("unable to register with mDNS (err %d)\n", err)); + goto retry; + } + + dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref); + if (dns_state->fd == -1) { + goto retry; + } + + dns_state->fde = tevent_add_fd(dns_state->event_ctx, + dns_state, + dns_state->fd, + TEVENT_FD_READ, + dns_register_smbd_fde_handler, + dns_state); + if (!dns_state->fde) { + goto retry; + } + + return; + retry: + dns_register_smbd_schedule(dns_state, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0)); +} + +/* Processes reply from mDNS daemon. Returns true if a reply was received */ +static void dns_register_smbd_fde_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); + DNSServiceErrorType err; + + err = DNSServiceProcessResult(dns_state->srv_ref); + if (err != kDNSServiceErr_NoError) { + DEBUG(3, ("failed to process mDNS result (err %d), re-trying\n", + err)); + goto retry; + } + + talloc_free(dns_state); + return; + + retry: + dns_register_smbd_schedule(dns_state, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0)); +} + +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port) +{ + struct dns_reg_state *dns_state; + + dns_state = talloc_zero(mem_ctx, struct dns_reg_state); + if (dns_state == NULL) { + return false; + } + dns_state->event_ctx = ev; + dns_state->port = port; + dns_state->fd = -1; + + talloc_set_destructor(dns_state, dns_reg_state_destructor); + + return dns_register_smbd_schedule(dns_state, timeval_zero()); +} + +#else /* WITH_DNSSD_SUPPORT */ + +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port) +{ + return true; +} + +#endif /* WITH_DNSSD_SUPPORT */ |