From bf2347bd7df19156da8a2884e41ca5b98a3c94c6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 26 Jan 2009 14:55:54 +0100 Subject: s3:smbd: make mdns registration event driven. metze --- source3/include/includes.h | 14 --- source3/include/proto.h | 11 +-- source3/smbd/dnsregister.c | 208 +++++++++++++++++++++------------------------ source3/smbd/server.c | 25 +++--- 4 files changed, 111 insertions(+), 147 deletions(-) (limited to 'source3') diff --git a/source3/include/includes.h b/source3/include/includes.h index 50140c17f7..ea856f1c16 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -678,20 +678,6 @@ struct printjob; #include "smb_ldap.h" -struct dns_reg_state; - -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout); - -void dns_register_close(struct dns_reg_state ** dns_state_ptr); - - -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout); - /* * Reasons for cache flush. */ diff --git a/source3/include/proto.h b/source3/include/proto.h index ae49290539..f8a9dbce66 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6651,14 +6651,9 @@ uint32 dmapi_file_flags(const char * const path); /* The following definitions come from smbd/dnsregister.c */ -void dns_register_close(struct dns_reg_state **dns_state_ptr); -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout); -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout); +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port); /* The following definitions come from smbd/dosmode.c */ diff --git a/source3/smbd/dnsregister.c b/source3/smbd/dnsregister.c index c092251fee..2fd95f9fb7 100644 --- a/source3/smbd/dnsregister.c +++ b/source3/smbd/dnsregister.c @@ -35,18 +35,16 @@ #include struct dns_reg_state { + struct tevent_context *event_ctx; + uint16_t port; DNSServiceRef srv_ref; - struct timed_event *retry_handler; + struct tevent_timer *te; + int fd; + struct tevent_fd *fde; }; -void dns_register_close(struct dns_reg_state **dns_state_ptr) +static int dns_reg_state_destructor(struct dns_reg_state *dns_state) { - struct dns_reg_state *dns_state = *dns_state_ptr; - - if (dns_state == NULL) { - return; - } - if (dns_state->srv_ref != NULL) { /* Close connection to the mDNS daemon */ DNSServiceRefDeallocate(dns_state->srv_ref); @@ -54,81 +52,52 @@ void dns_register_close(struct dns_reg_state **dns_state_ptr) } /* Clear event handler */ - if (dns_state->retry_handler != NULL) { - TALLOC_FREE(dns_state->retry_handler); - dns_state->retry_handler = NULL; - } + TALLOC_FREE(dns_state->te); + TALLOC_FREE(dns_state->fde); + dns_state->fd = -1; - talloc_free(dns_state); - *dns_state_ptr = NULL; + return 0; } -static void dns_register_smbd_retry(struct event_context *ctx, - struct timed_event *te, - const struct timeval *now, - void *private_data) +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) { - struct dns_reg_state *dns_state = (struct dns_reg_state *)private_data; - - /* Clear previous registration state to force new - * registration attempt. Clears event handler. - */ - dns_register_close(&dns_state); -} - -static void schedule_dns_register_smbd_retry(struct dns_reg_state *dns_state, - struct timeval *timeout) -{ - struct timed_event * event; - - dns_state->srv_ref = NULL; - event= event_add_timed(smbd_event_context(), - NULL, - timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0), - dns_register_smbd_retry, - dns_state); + 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; + } - dns_state->retry_handler = event; - get_timed_events_timeout(smbd_event_context(), timeout); + return true; } -/* Kick off a mDNS request to register the "_smb._tcp" on the specified port. - * We really ought to register on all the ports we are listening on. This will - * have to be an exercise for some-one who knows the DNS registration API a bit - * better. - */ -void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout) +static void dns_register_smbd_retry(struct tevent_context *ctx, + struct tevent_timer *te, + struct timeval now, + void *private_data) { - int mdnsd_conn_fd; + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); DNSServiceErrorType err; - struct dns_reg_state *dns_state = *dns_state_ptr; - - if (dns_state == NULL) { - *dns_state_ptr = dns_state = talloc(NULL, struct dns_reg_state); - if (dns_state == NULL) { - return; - } - } - - /* Quit if a re-try attempt has been scheduled. */ - if (dns_state->retry_handler != NULL) { - return; - } - /* If a registration is active add conn - * fd to select listen_set and return - */ - if (dns_state->srv_ref != NULL) { - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); - FD_SET(mdnsd_conn_fd, listen_set); - return; - } + dns_reg_state_destructor(dns_state); - DEBUG(6, ("registering _smb._tcp service on port %d\n", port)); + 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 @@ -140,7 +109,7 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, "_smb._tcp" /* service type */, NULL /* domain */, "" /* SRV target host name */, - htons(port), + htons(dns_state->port), 0 /* TXT record len */, NULL /* TXT record data */, NULL /* callback func */, @@ -150,62 +119,81 @@ void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, /* Failed to register service. Schedule a re-try attempt. */ DEBUG(3, ("unable to register with mDNS (err %d)\n", err)); - schedule_dns_register_smbd_retry(dns_state, timeout); - return; + goto retry; + } + + dns_state->fd = DNSServiceRefSockFD(dns_state->srv_ref); + if (dns_state->fd == -1) { + goto retry; } - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); - FD_SET(mdnsd_conn_fd, listen_set); - *maxfd = MAX(*maxfd, mdnsd_conn_fd); - *timeout = timeval_zero(); + 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 */ -bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout) +static void dns_register_smbd_fde_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) { - int mdnsd_conn_fd = -1; + struct dns_reg_state *dns_state = talloc_get_type_abort(private_data, + struct dns_reg_state); + DNSServiceErrorType err; - if (dns_state->srv_ref == NULL) { - return false; + 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; } - mdnsd_conn_fd = DNSServiceRefSockFD(dns_state->srv_ref); + talloc_free(dns_state); + return; - /* Process reply from daemon. Handles any errors. */ - if ((mdnsd_conn_fd != -1) && (FD_ISSET(mdnsd_conn_fd,lfds)) ) { - 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)); - schedule_dns_register_smbd_retry(dns_state, timeout); - } + retry: + dns_register_smbd_schedule(dns_state, + timeval_current_ofs(DNS_REG_RETRY_INTERVAL, 0)); +} - return true; +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 false; + return dns_register_smbd_schedule(dns_state, timeval_zero()); } #else /* WITH_DNSSD_SUPPORT */ - void dns_register_smbd(struct dns_reg_state ** dns_state_ptr, - unsigned port, - int *maxfd, - fd_set *listen_set, - struct timeval *timeout) -{} - - void dns_register_close(struct dns_reg_state ** dns_state_ptr) -{} - - bool dns_register_smbd_reply(struct dns_reg_state *dns_state, - fd_set *lfds, struct timeval *timeout) +bool smbd_setup_mdns_registration(struct tevent_context *ev, + TALLOC_CTX *mem_ctx, + uint16_t port) { - return false; + return true; } #endif /* WITH_DNSSD_SUPPORT */ diff --git a/source3/smbd/server.c b/source3/smbd/server.c index f95fa874ff..d71a04ebc1 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -309,13 +309,15 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) int maxfd = 0; int i; char *ports; - struct dns_reg_state * dns_reg = NULL; + TALLOC_CTX *dns_ctx = NULL; unsigned dns_port = 0; #ifdef HAVE_ATEXIT atexit(killkids); #endif + dns_ctx = talloc_new(NULL); + /* Stop zombies */ smbd_setup_sig_chld_handler(); @@ -535,6 +537,11 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) MSG_SMB_INJECT_FAULT, msg_inject_fault); #endif + if (dns_port != 0) { + smbd_setup_mdns_registration(smbd_event_context(), + dns_ctx, dns_port); + } + /* now accept incoming connections - forking a new process for each incoming connection */ DEBUG(2,("waiting for a connection\n")); @@ -554,12 +561,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) FD_ZERO(&w_fds); GetTimeOfDay(&now); - /* Kick off our mDNS registration. */ - if (dns_port != 0) { - dns_register_smbd(&dns_reg, dns_port, &maxfd, - &r_fds, &idle_timeout); - } - event_add_to_select_args(smbd_event_context(), &now, &r_fds, &w_fds, &idle_timeout, &maxfd); @@ -580,11 +581,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) exit_server_cleanly("idle timeout"); } - /* process pending nDNS responses */ - if (dns_register_smbd_reply(dns_reg, &r_fds, &idle_timeout)) { - --num; - } - /* check if we need to reload services */ check_reload(time(NULL)); @@ -624,6 +620,8 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) ((child = sys_fork())==0)) { /* Child code ... */ + TALLOC_FREE(dns_ctx); + /* Stop zombies, the parent explicitly handles * them, counting worker smbds. */ CatchChild(); @@ -632,9 +630,6 @@ static bool open_sockets_smbd(bool interactive, const char *smb_ports) for(i = 0; i < num_sockets; i++) close(fd_listenset[i]); - /* close our mDNS daemon handle */ - dns_register_close(&dns_reg); - /* close our standard file descriptors */ close_low_fds(False); -- cgit