LCOV - code coverage report
Current view: top level - providers - fail_over_srv.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 128 327 39.1 %
Date: 2015-10-19 Functions: 8 13 61.5 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2013 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <strings.h>
      22             : #include <talloc.h>
      23             : #include <tevent.h>
      24             : 
      25             : #include "util/util.h"
      26             : #include "resolv/async_resolv.h"
      27             : #include "providers/fail_over_srv.h"
      28             : 
      29             : struct fo_discover_srv_state {
      30             :     char *dns_domain;
      31             :     struct fo_server_info *servers;
      32             :     size_t num_servers;
      33             :     uint32_t ttl;
      34             : };
      35             : 
      36             : static void fo_discover_srv_done(struct tevent_req *subreq);
      37             : 
      38           6 : struct tevent_req *fo_discover_srv_send(TALLOC_CTX *mem_ctx,
      39             :                                         struct tevent_context *ev,
      40             :                                         struct resolv_ctx *resolv_ctx,
      41             :                                         const char *service,
      42             :                                         const char *protocol,
      43             :                                         const char **discovery_domains)
      44             : {
      45           6 :     struct fo_discover_srv_state *state = NULL;
      46           6 :     struct tevent_req *req = NULL;
      47           6 :     struct tevent_req *subreq = NULL;
      48             :     errno_t ret;
      49             : 
      50           6 :     req = tevent_req_create(mem_ctx, &state, struct fo_discover_srv_state);
      51           6 :     if (req == NULL) {
      52           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
      53           0 :         return NULL;
      54             :     }
      55             : 
      56           6 :     subreq = resolv_discover_srv_send(state, ev, resolv_ctx, service,
      57             :                                       protocol, discovery_domains);
      58           6 :     if (subreq == NULL) {
      59           0 :         ret = ENOMEM;
      60           0 :         goto immediately;
      61             :     }
      62             : 
      63           6 :     tevent_req_set_callback(subreq, fo_discover_srv_done, req);
      64             : 
      65           6 :     return req;
      66             : 
      67             : immediately:
      68           0 :     tevent_req_error(req, ret);
      69           0 :     tevent_req_post(req, ev);
      70             : 
      71           0 :     return req;
      72             : }
      73             : 
      74           6 : static void fo_discover_srv_done(struct tevent_req *subreq)
      75             : {
      76           6 :     struct fo_discover_srv_state *state = NULL;
      77           6 :     struct tevent_req *req = NULL;
      78           6 :     struct ares_srv_reply *reply_list = NULL;
      79           6 :     struct ares_srv_reply *record = NULL;
      80             :     int i;
      81             :     errno_t ret;
      82             : 
      83           6 :     req = tevent_req_callback_data(subreq, struct tevent_req);
      84           6 :     state = tevent_req_data(req, struct fo_discover_srv_state);
      85             : 
      86           6 :     ret = resolv_discover_srv_recv(state, subreq,
      87             :                                    &reply_list, &state->ttl, &state->dns_domain);
      88           6 :     talloc_zfree(subreq);
      89           6 :     if (ret == ENOENT) {
      90           0 :         ret = ERR_SRV_NOT_FOUND;
      91           0 :         goto done;
      92           6 :     } else if (ret == EIO) {
      93           0 :         ret = ERR_SRV_LOOKUP_ERROR;
      94           0 :         goto done;
      95           6 :     } else if (ret != EOK) {
      96           0 :         goto done;
      97             :     }
      98             : 
      99           6 :     DEBUG(SSSDBG_TRACE_FUNC, "Got answer. Processing...\n");
     100             : 
     101             :     /* sort and store the answer */
     102           6 :     ret = resolv_sort_srv_reply(&reply_list);
     103           6 :     if (ret != EOK) {
     104           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Could not sort the answers from DNS "
     105             :                                     "[%d]: %s\n", ret, strerror(ret));
     106           0 :         goto done;
     107             :     }
     108             : 
     109           6 :     state->num_servers = 0;
     110          18 :     for (record = reply_list; record != NULL; record = record->next) {
     111          12 :         state->num_servers++;
     112             :     }
     113             : 
     114           6 :     DEBUG(SSSDBG_TRACE_FUNC, "Got %zu servers\n", state->num_servers);
     115             : 
     116           6 :     state->servers = talloc_array(state, struct fo_server_info,
     117             :                                   state->num_servers);
     118           6 :     if (state->servers == NULL) {
     119           0 :         ret = ENOMEM;
     120           0 :         goto done;
     121             :     }
     122             : 
     123          24 :     for (record = reply_list, i = 0;
     124             :          record != NULL;
     125          12 :          record = record->next, i++) {
     126          12 :         state->servers[i].host = talloc_steal(state->servers, record->host);
     127          12 :         state->servers[i].port = record->port;
     128          12 :         state->servers[i].priority = record->priority;
     129             :     }
     130             : 
     131           6 :     talloc_zfree(reply_list);
     132             : 
     133           6 :     ret = EOK;
     134             : 
     135             : done:
     136           6 :     if (ret != EOK) {
     137           0 :         tevent_req_error(req, ret);
     138           0 :         return;
     139             :     }
     140             : 
     141           6 :     tevent_req_done(req);
     142             : }
     143             : 
     144           6 : errno_t fo_discover_srv_recv(TALLOC_CTX *mem_ctx,
     145             :                              struct tevent_req *req,
     146             :                              char **_dns_domain,
     147             :                              uint32_t *_ttl,
     148             :                              struct fo_server_info **_servers,
     149             :                              size_t *_num_servers)
     150             : {
     151           6 :     struct fo_discover_srv_state *state = NULL;
     152           6 :     state = tevent_req_data(req, struct fo_discover_srv_state);
     153             : 
     154           6 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     155             : 
     156           6 :     if (_dns_domain != NULL) {
     157           6 :         *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
     158             :     }
     159             : 
     160           6 :     if (_servers != NULL) {
     161           6 :         *_servers = talloc_steal(mem_ctx, state->servers);
     162             :     }
     163             : 
     164           6 :     if (_ttl != NULL) {
     165           6 :         *_ttl = state->ttl;
     166             :     }
     167             : 
     168           6 :     if (_num_servers != NULL) {
     169           6 :         *_num_servers = state->num_servers;
     170             :     }
     171             : 
     172           6 :     return EOK;
     173             : }
     174             : 
     175             : struct fo_discover_servers_state {
     176             :     struct tevent_context *ev;
     177             :     struct resolv_ctx *resolv_ctx;
     178             :     const char *service;
     179             :     const char *protocol;
     180             :     const char *primary_domain;
     181             :     const char *backup_domain;
     182             : 
     183             :     char *dns_domain;
     184             :     uint32_t ttl;
     185             :     struct fo_server_info *primary_servers;
     186             :     size_t num_primary_servers;
     187             :     struct fo_server_info *backup_servers;
     188             :     size_t num_backup_servers;
     189             : };
     190             : 
     191             : static void fo_discover_servers_primary_done(struct tevent_req *subreq);
     192             : static void fo_discover_servers_backup_done(struct tevent_req *subreq);
     193             : 
     194           0 : struct tevent_req *fo_discover_servers_send(TALLOC_CTX *mem_ctx,
     195             :                                             struct tevent_context *ev,
     196             :                                             struct resolv_ctx *resolv_ctx,
     197             :                                             const char *service,
     198             :                                             const char *protocol,
     199             :                                             const char *primary_domain,
     200             :                                             const char *backup_domain)
     201             : {
     202           0 :     struct fo_discover_servers_state *state = NULL;
     203           0 :     struct tevent_req *req = NULL;
     204           0 :     struct tevent_req *subreq = NULL;
     205           0 :     const char **domains = NULL;
     206             :     errno_t ret;
     207             : 
     208           0 :     req = tevent_req_create(mem_ctx, &state,
     209             :                             struct fo_discover_servers_state);
     210           0 :     if (req == NULL) {
     211           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     212           0 :         return NULL;
     213             :     }
     214             : 
     215           0 :     if (primary_domain == NULL) {
     216           0 :         if (backup_domain == NULL) {
     217           0 :             state->primary_servers = NULL;
     218           0 :             state->num_primary_servers = 0;
     219           0 :             state->backup_servers = NULL;
     220           0 :             state->num_backup_servers = 0;
     221           0 :             state->dns_domain = NULL;
     222           0 :             state->ttl = 0;
     223             : 
     224           0 :             ret = EOK;
     225           0 :             goto immediately;
     226             :         } else {
     227           0 :             primary_domain = backup_domain;
     228           0 :             backup_domain = NULL;
     229             :         }
     230             :     }
     231             : 
     232           0 :     state->ev = ev;
     233           0 :     state->resolv_ctx = resolv_ctx;
     234             : 
     235           0 :     state->service = talloc_strdup(state, service);
     236           0 :     if (state->service == NULL) {
     237           0 :         ret = ENOMEM;
     238           0 :         goto immediately;
     239             :     }
     240             : 
     241           0 :     state->protocol = talloc_strdup(state, protocol);
     242           0 :     if (state->protocol == NULL) {
     243           0 :         ret = ENOMEM;
     244           0 :         goto immediately;
     245             :     }
     246             : 
     247           0 :     state->primary_domain = talloc_strdup(state, primary_domain);
     248           0 :     if (state->primary_domain == NULL) {
     249           0 :         ret = ENOMEM;
     250           0 :         goto immediately;
     251             :     }
     252             : 
     253           0 :     state->backup_domain = talloc_strdup(state, backup_domain);
     254           0 :     if (state->backup_domain == NULL && backup_domain != NULL) {
     255           0 :         ret = ENOMEM;
     256           0 :         goto immediately;
     257             :     }
     258             : 
     259           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Looking up primary servers\n");
     260             : 
     261           0 :     domains = talloc_zero_array(state, const char *, 3);
     262           0 :     if (domains == NULL) {
     263           0 :         ret = ENOMEM;
     264           0 :         goto immediately;
     265             :     }
     266             : 
     267           0 :     domains[0] = state->primary_domain;
     268           0 :     domains[1] = state->backup_domain;
     269             : 
     270           0 :     subreq = fo_discover_srv_send(state, ev, resolv_ctx,
     271           0 :                                   state->service, state->protocol, domains);
     272           0 :     if (subreq == NULL) {
     273           0 :         ret = ENOMEM;
     274           0 :         goto immediately;
     275             :     }
     276             : 
     277           0 :     tevent_req_set_callback(subreq, fo_discover_servers_primary_done, req);
     278             : 
     279           0 :     return req;
     280             : 
     281             : immediately:
     282           0 :     tevent_req_error(req, ret);
     283           0 :     tevent_req_post(req, ev);
     284             : 
     285           0 :     return req;
     286             : }
     287             : 
     288           0 : static void fo_discover_servers_primary_done(struct tevent_req *subreq)
     289             : {
     290           0 :     struct fo_discover_servers_state *state = NULL;
     291           0 :     struct tevent_req *req = NULL;
     292           0 :     const char **domains = NULL;
     293             :     errno_t ret;
     294             : 
     295           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     296           0 :     state = tevent_req_data(req, struct fo_discover_servers_state);
     297             : 
     298           0 :     ret = fo_discover_srv_recv(state, subreq,
     299             :                                &state->dns_domain,
     300             :                                &state->ttl,
     301             :                                &state->primary_servers,
     302             :                                &state->num_primary_servers);
     303           0 :     talloc_zfree(subreq);
     304           0 :     if (ret != EOK) {
     305           0 :         DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve primary servers "
     306             :                                   "[%d]: %s\n", ret, sss_strerror(ret));
     307           0 :         if (ret != ERR_SRV_NOT_FOUND && ret != ERR_SRV_LOOKUP_ERROR) {
     308             :             /* abort on system error */
     309           0 :             goto done;
     310             :         }
     311             :     }
     312             : 
     313           0 :     if (state->backup_domain == NULL) {
     314             :         /* if there is no backup domain, we are done */
     315           0 :         DEBUG(SSSDBG_TRACE_FUNC, "No backup domain specified\n");
     316           0 :         goto done;
     317             :     }
     318             : 
     319           0 :     if (state->dns_domain != NULL
     320           0 :             && strcasecmp(state->dns_domain, state->backup_domain) == 0) {
     321             :         /* If there was no error and dns_domain is the same as backup domain,
     322             :          * it means that we were unable to resolve SRV in primary domain, but
     323             :          * SRV from backup domain was resolved and those servers are considered
     324             :          * to be primary. We are done. */
     325           0 :         state->backup_servers = NULL;
     326           0 :         state->num_backup_servers = 0;
     327             : 
     328           0 :         ret = EOK;
     329           0 :         goto done;
     330             :     }
     331             : 
     332           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Looking up backup servers\n");
     333             : 
     334           0 :     domains = talloc_zero_array(state, const char *, 2);
     335           0 :     if (domains == NULL) {
     336           0 :         ret = ENOMEM;
     337           0 :         goto done;
     338             :     }
     339             : 
     340           0 :     domains[0] = state->backup_domain;
     341             : 
     342           0 :     subreq = fo_discover_srv_send(state, state->ev, state->resolv_ctx,
     343             :                                   state->service, state->protocol, domains);
     344           0 :     if (subreq == NULL) {
     345           0 :         ret = ENOMEM;
     346           0 :         goto done;
     347             :     }
     348             : 
     349           0 :     tevent_req_set_callback(subreq, fo_discover_servers_backup_done, req);
     350             : 
     351           0 :     ret = EAGAIN;
     352             : 
     353             : done:
     354           0 :     if (ret == EOK) {
     355           0 :         tevent_req_done(req);
     356           0 :     } else if (ret != EAGAIN) {
     357           0 :         tevent_req_error(req, ret);
     358             :     }
     359             : 
     360           0 :     return;
     361             : }
     362             : 
     363           0 : static void fo_discover_servers_backup_done(struct tevent_req *subreq)
     364             : {
     365           0 :     struct fo_discover_servers_state *state = NULL;
     366           0 :     struct tevent_req *req = NULL;
     367             :     errno_t ret;
     368             : 
     369           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     370           0 :     state = tevent_req_data(req, struct fo_discover_servers_state);
     371             : 
     372           0 :     ret = fo_discover_srv_recv(state, subreq, NULL,
     373             :                                NULL, &state->backup_servers,
     374             :                                &state->num_backup_servers);
     375           0 :     talloc_zfree(subreq);
     376           0 :     if (ret != EOK) {
     377           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Unable to retrieve backup servers "
     378             :                                      "[%d]: %s\n", ret, sss_strerror(ret));
     379           0 :         if (ret == ERR_SRV_NOT_FOUND || ret == ERR_SRV_LOOKUP_ERROR) {
     380             :             /* we have successfully fetched primary servers, so we will
     381             :              * finish the request normally on non system error */
     382           0 :             ret = EOK;
     383             :         }
     384             :     }
     385             : 
     386           0 :     if (ret != EOK) {
     387           0 :         tevent_req_error(req, ret);
     388           0 :         return;
     389             :     }
     390             : 
     391           0 :     tevent_req_done(req);
     392             : }
     393             : 
     394           0 : errno_t fo_discover_servers_recv(TALLOC_CTX *mem_ctx,
     395             :                                  struct tevent_req *req,
     396             :                                  char **_dns_domain,
     397             :                                  uint32_t *_ttl,
     398             :                                  struct fo_server_info **_primary_servers,
     399             :                                  size_t *_num_primary_servers,
     400             :                                  struct fo_server_info **_backup_servers,
     401             :                                  size_t *_num_backup_servers)
     402             : {
     403           0 :     struct fo_discover_servers_state *state = NULL;
     404           0 :     state = tevent_req_data(req, struct fo_discover_servers_state);
     405             : 
     406           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     407             : 
     408           0 :     if (_primary_servers) {
     409           0 :         *_primary_servers = talloc_steal(mem_ctx, state->primary_servers);
     410             :     }
     411             : 
     412           0 :     if (_num_primary_servers) {
     413           0 :         *_num_primary_servers = state->num_primary_servers;
     414             :     }
     415             : 
     416           0 :     if (_backup_servers) {
     417           0 :         *_backup_servers = talloc_steal(mem_ctx, state->backup_servers);
     418             :     }
     419             : 
     420           0 :     if (_num_backup_servers) {
     421           0 :         *_num_backup_servers = state->num_backup_servers;
     422             :     }
     423             : 
     424           0 :     if (_dns_domain) {
     425           0 :         *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
     426             :     }
     427             : 
     428           0 :     if (_ttl) {
     429           0 :         *_ttl = state->ttl;
     430             :     }
     431             : 
     432             : 
     433           0 :     return EOK;
     434             : }
     435             : 
     436             : struct fo_resolve_srv_dns_ctx {
     437             :     struct resolv_ctx *resolv_ctx;
     438             :     enum restrict_family family_order;
     439             :     enum host_database *host_dbs;
     440             :     char *hostname;
     441             :     char *sssd_domain;
     442             :     char *detected_domain;
     443             : };
     444             : 
     445             : struct fo_resolve_srv_dns_state {
     446             :     struct tevent_context *ev;
     447             :     struct fo_resolve_srv_dns_ctx *ctx;
     448             :     const char *service;
     449             :     const char *protocol;
     450             :     const char *discovery_domain;
     451             : 
     452             :     char *dns_domain;
     453             :     uint32_t ttl;
     454             :     struct fo_server_info *servers;
     455             :     size_t num_servers;
     456             : };
     457             : 
     458             : static void fo_resolve_srv_dns_domain_done(struct tevent_req *subreq);
     459             : static errno_t fo_resolve_srv_dns_discover(struct tevent_req *req);
     460             : static void fo_resolve_srv_dns_done(struct tevent_req *subreq);
     461             : 
     462             : struct fo_resolve_srv_dns_ctx *
     463           3 : fo_resolve_srv_dns_ctx_init(TALLOC_CTX *mem_ctx,
     464             :                             struct resolv_ctx *resolv_ctx,
     465             :                             enum restrict_family family_order,
     466             :                             enum host_database *host_dbs,
     467             :                             const char *hostname,
     468             :                             const char *sssd_domain)
     469             : {
     470           3 :     struct fo_resolve_srv_dns_ctx *ctx = NULL;
     471             : 
     472           3 :     ctx = talloc_zero(mem_ctx, struct fo_resolve_srv_dns_ctx);
     473           3 :     if (ctx == NULL) {
     474           0 :         return NULL;
     475             :     }
     476             : 
     477           3 :     ctx->resolv_ctx = resolv_ctx;
     478           3 :     ctx->family_order = family_order;
     479           3 :     ctx->host_dbs = host_dbs;
     480             : 
     481           3 :     ctx->hostname = talloc_strdup(ctx, hostname);
     482           3 :     if (ctx->hostname == NULL) {
     483           0 :         goto fail;
     484             :     }
     485             : 
     486           3 :     ctx->sssd_domain = talloc_strdup(ctx, sssd_domain);
     487           3 :     if (ctx->sssd_domain == NULL) {
     488           0 :         goto fail;
     489             :     }
     490             : 
     491           3 :     return ctx;
     492             : 
     493             : fail:
     494           0 :     talloc_free(ctx);
     495           0 :     return NULL;
     496             : }
     497             : 
     498           6 : struct tevent_req *fo_resolve_srv_dns_send(TALLOC_CTX *mem_ctx,
     499             :                                            struct tevent_context *ev,
     500             :                                            const char *service,
     501             :                                            const char *protocol,
     502             :                                            const char *discovery_domain,
     503             :                                            void *pvt)
     504             : {
     505           6 :     struct fo_resolve_srv_dns_state *state = NULL;
     506           6 :     struct fo_resolve_srv_dns_ctx *ctx = NULL;
     507           6 :     struct tevent_req *req = NULL;
     508           6 :     struct tevent_req *subreq = NULL;
     509             :     errno_t ret;
     510             : 
     511           6 :     req = tevent_req_create(mem_ctx, &state, struct fo_resolve_srv_dns_state);
     512           6 :     if (req == NULL) {
     513           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     514           0 :         return NULL;
     515             :     }
     516             : 
     517           6 :     ctx = talloc_get_type(pvt, struct fo_resolve_srv_dns_ctx);
     518           6 :     if (ctx == NULL) {
     519           0 :         ret = EINVAL;
     520           0 :         goto immediately;
     521             :     }
     522             : 
     523           6 :     state->ev = ev;
     524           6 :     state->ctx = ctx;
     525           6 :     state->service = service;
     526           6 :     state->protocol = protocol;
     527             : 
     528           6 :     if (discovery_domain == NULL) {
     529           0 :         state->discovery_domain = NULL;
     530             :     } else {
     531           6 :         state->discovery_domain = discovery_domain;
     532             :     }
     533             : 
     534           6 :     if (discovery_domain == NULL && ctx->detected_domain == NULL) {
     535             :         /* we will try to detect proper discovery domain */
     536           0 :         subreq = resolv_get_domain_send(state, state->ev, ctx->resolv_ctx,
     537           0 :                                         ctx->hostname, ctx->host_dbs,
     538             :                                         ctx->family_order);
     539           0 :         if (subreq == NULL) {
     540           0 :             ret = ENOMEM;
     541           0 :             goto immediately;
     542             :         }
     543             : 
     544           0 :         tevent_req_set_callback(subreq, fo_resolve_srv_dns_domain_done, req);
     545             :     } else {
     546             :         /* we will use either provided or previously detected
     547             :          * discovery domain */
     548           6 :         ret = fo_resolve_srv_dns_discover(req);
     549           6 :         if (ret != EAGAIN) {
     550           0 :             goto immediately;
     551             :         }
     552             :     }
     553             : 
     554           6 :     return req;
     555             : 
     556             : immediately:
     557           0 :     if (ret == EOK) {
     558           0 :         tevent_req_done(req);
     559             :     } else {
     560           0 :         tevent_req_error(req, ret);
     561             :     }
     562           0 :     tevent_req_post(req, ev);
     563             : 
     564           0 :     return req;
     565             : }
     566             : 
     567           0 : static void fo_resolve_srv_dns_domain_done(struct tevent_req *subreq)
     568             : {
     569           0 :     struct fo_resolve_srv_dns_state *state = NULL;
     570           0 :     struct tevent_req *req = NULL;
     571             :     errno_t ret;
     572             : 
     573           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     574           0 :     state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
     575             : 
     576           0 :     ret = resolv_get_domain_recv(state->ctx, subreq,
     577           0 :                                  &state->ctx->detected_domain);
     578           0 :     talloc_zfree(subreq);
     579           0 :     if (ret != EOK) {
     580           0 :         goto done;
     581             :     }
     582             : 
     583           0 :     ret = fo_resolve_srv_dns_discover(req);
     584             : 
     585             : done:
     586           0 :     if (ret == EOK) {
     587           0 :         tevent_req_done(req);
     588           0 :     } else if (ret != EAGAIN) {
     589           0 :         tevent_req_error(req, ret);
     590             :     }
     591             : 
     592           0 :     return;
     593             : }
     594             : 
     595           6 : static errno_t fo_resolve_srv_dns_discover(struct tevent_req *req)
     596             : {
     597           6 :     struct fo_resolve_srv_dns_state *state = NULL;
     598           6 :     struct fo_resolve_srv_dns_ctx *ctx = NULL;
     599           6 :     struct tevent_req *subreq = NULL;
     600           6 :     const char **domains = NULL;
     601             :     errno_t ret;
     602             : 
     603           6 :     state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
     604           6 :     ctx = state->ctx;
     605             : 
     606           6 :     domains = talloc_zero_array(state, const char *, 3);
     607           6 :     if (domains == NULL) {
     608           0 :         ret = ENOMEM;
     609           0 :         goto done;
     610             :     }
     611             : 
     612           6 :     if (state->discovery_domain == NULL) {
     613             :         /* we will use detected domain with SSSD domain as fallback */
     614           0 :         domains[0] = talloc_strdup(domains, ctx->detected_domain);
     615           0 :         if (domains[0] == NULL) {
     616           0 :             ret = ENOMEM;
     617           0 :             goto done;
     618             :         }
     619             : 
     620           0 :         if (strcasecmp(ctx->detected_domain, ctx->sssd_domain) != 0) {
     621           0 :             domains[1] = talloc_strdup(domains, ctx->sssd_domain);
     622           0 :             if (domains[1] == NULL) {
     623           0 :                 ret = ENOMEM;
     624           0 :                 goto done;
     625             :             }
     626             :         }
     627             :     } else {
     628             :         /* We will use only discovery domain that was provided via plugin
     629             :          * interface. We don't have to dup here because it is already on
     630             :          * state. */
     631           6 :         domains[0] = state->discovery_domain;
     632             :     }
     633             : 
     634           6 :     subreq = fo_discover_srv_send(state, state->ev, ctx->resolv_ctx,
     635             :                                   state->service, state->protocol, domains);
     636           6 :     if (subreq == NULL) {
     637           0 :         ret = ENOMEM;
     638           0 :         goto done;
     639             :     }
     640             : 
     641           6 :     tevent_req_set_callback(subreq, fo_resolve_srv_dns_done, req);
     642             : 
     643           6 :     ret = EAGAIN;
     644             : 
     645             : done:
     646           6 :     if (ret != EAGAIN) {
     647           0 :         talloc_free(domains);
     648             :     }
     649             : 
     650           6 :     return ret;
     651             : }
     652             : 
     653           6 : static void fo_resolve_srv_dns_done(struct tevent_req *subreq)
     654             : {
     655           6 :     struct fo_resolve_srv_dns_state *state = NULL;
     656           6 :     struct tevent_req *req = NULL;
     657             :     errno_t ret;
     658             : 
     659           6 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     660           6 :     state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
     661             : 
     662           6 :     ret = fo_discover_srv_recv(state, subreq,
     663             :                                &state->dns_domain, &state->ttl,
     664             :                                &state->servers, &state->num_servers);
     665           6 :     talloc_zfree(subreq);
     666           6 :     if (ret != EOK) {
     667           0 :         goto done;
     668             :     }
     669             : 
     670             : done:
     671           6 :     if (ret != EOK) {
     672           0 :         tevent_req_error(req, ret);
     673           0 :         return;
     674             :     }
     675             : 
     676           6 :     tevent_req_done(req);
     677             : }
     678             : 
     679           6 : errno_t fo_resolve_srv_dns_recv(TALLOC_CTX *mem_ctx,
     680             :                                 struct tevent_req *req,
     681             :                                 char **_dns_domain,
     682             :                                 uint32_t *_ttl,
     683             :                                 struct fo_server_info **_primary_servers,
     684             :                                 size_t *_num_primary_servers,
     685             :                                 struct fo_server_info **_backup_servers,
     686             :                                 size_t *_num_backup_servers)
     687             : {
     688           6 :     struct fo_resolve_srv_dns_state *state = NULL;
     689           6 :     state = tevent_req_data(req, struct fo_resolve_srv_dns_state);
     690             : 
     691           6 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     692             : 
     693           6 :     if (_primary_servers) {
     694           6 :         *_primary_servers = talloc_steal(mem_ctx, state->servers);
     695             :     }
     696             : 
     697           6 :     if (_num_primary_servers) {
     698           6 :         *_num_primary_servers = state->num_servers;
     699             :     }
     700             : 
     701             :     /* backup servers are not supported by simple srv lookup */
     702           6 :     if (_backup_servers) {
     703           6 :         *_backup_servers = NULL;
     704             :     }
     705             : 
     706           6 :     if (_num_backup_servers) {
     707           6 :         *_num_backup_servers = 0;
     708             :     }
     709             : 
     710           6 :     if (_dns_domain) {
     711           6 :         *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
     712             :     }
     713             : 
     714           6 :     if (_ttl) {
     715           6 :         *_ttl = state->ttl;
     716             :     }
     717             : 
     718           6 :     return EOK;
     719             : }

Generated by: LCOV version 1.10