LCOV - code coverage report
Current view: top level - resolv - async_resolv_utils.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 148 0.0 %
Date: 2016-06-29 Functions: 0 7 0.0 %

          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 <string.h>
      22             : #include <talloc.h>
      23             : #include <tevent.h>
      24             : #include <unistd.h>
      25             : 
      26             : #include "util/util.h"
      27             : #include "resolv/async_resolv.h"
      28             : 
      29             : struct resolv_get_domain_state {
      30             :     char *fqdn;
      31             :     char *hostname;
      32             : };
      33             : 
      34             : static void resolv_get_domain_done(struct tevent_req *subreq);
      35             : 
      36             : struct tevent_req *
      37           0 : resolv_get_domain_send(TALLOC_CTX *mem_ctx,
      38             :                         struct tevent_context *ev,
      39             :                         struct resolv_ctx *resolv_ctx,
      40             :                         const char *hostname,
      41             :                         enum host_database *host_dbs,
      42             :                         enum restrict_family family_order)
      43             : {
      44           0 :     struct resolv_get_domain_state *state = NULL;
      45           0 :     struct tevent_req *req = NULL;
      46           0 :     struct tevent_req *subreq = NULL;
      47             :     char system_hostname[HOST_NAME_MAX + 1];
      48             :     errno_t ret;
      49             : 
      50           0 :     req = tevent_req_create(mem_ctx, &state,
      51             :                             struct resolv_get_domain_state);
      52           0 :     if (req == NULL) {
      53           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
      54           0 :         return NULL;
      55             :     }
      56             : 
      57           0 :     if (hostname == NULL) {
      58             :         /* use system hostname */
      59           0 :         ret = gethostname(system_hostname, HOST_NAME_MAX);
      60           0 :         if (ret) {
      61           0 :             ret = errno;
      62           0 :             DEBUG(SSSDBG_CRIT_FAILURE, "gethostname() failed: [%d]: %s\n",
      63             :                                         ret, strerror(ret));
      64           0 :             goto immediately;
      65             :         }
      66           0 :         system_hostname[HOST_NAME_MAX] = '\0';
      67           0 :         hostname = system_hostname;
      68             :     }
      69             : 
      70           0 :     state->fqdn = NULL;
      71           0 :     state->hostname = talloc_strdup(state, hostname);
      72           0 :     if (state->hostname == NULL) {
      73           0 :         ret = ENOMEM;
      74           0 :         goto immediately;
      75             :     }
      76             : 
      77           0 :     DEBUG(SSSDBG_TRACE_LIBS, "Host name is: %s\n", state->hostname);
      78             : 
      79           0 :     subreq = resolv_gethostbyname_send(state, ev, resolv_ctx, state->hostname,
      80             :                                        family_order, host_dbs);
      81           0 :     if (subreq == NULL) {
      82           0 :         talloc_zfree(req);
      83           0 :         return NULL;
      84             :     }
      85             : 
      86           0 :     tevent_req_set_callback(subreq, resolv_get_domain_done, req);
      87             : 
      88           0 :     return req;
      89             : 
      90             : immediately:
      91           0 :     tevent_req_error(req, ret);
      92           0 :     tevent_req_post(req, ev);
      93             : 
      94           0 :     return req;
      95             : }
      96             : 
      97           0 : static void resolv_get_domain_done(struct tevent_req *subreq)
      98             : {
      99           0 :     struct resolv_get_domain_state *state = NULL;
     100           0 :     struct tevent_req *req = NULL;
     101             :     struct resolv_hostent *rhostent;
     102             :     int resolv_status;
     103             :     errno_t ret;
     104             : 
     105           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     106           0 :     state = tevent_req_data(req, struct resolv_get_domain_state);
     107             : 
     108           0 :     ret = resolv_gethostbyname_recv(subreq, req, &resolv_status,
     109             :                                     NULL, &rhostent);
     110           0 :     talloc_zfree(subreq);
     111           0 :     if (ret != EOK) {
     112           0 :         DEBUG(SSSDBG_OP_FAILURE,
     113             :               "Could not get fully qualified name for host name %s "
     114             :                "error [%d]: %s, resolver returned: [%d]: %s\n",
     115             :                state->hostname, ret, strerror(ret), resolv_status,
     116             :                resolv_strerror(resolv_status));
     117           0 :         state->fqdn = state->hostname;
     118             :     } else {
     119           0 :         DEBUG(SSSDBG_TRACE_LIBS, "The FQDN is: %s\n", rhostent->name);
     120           0 :         state->fqdn = talloc_steal(state, rhostent->name);
     121           0 :         talloc_zfree(rhostent);
     122             :     }
     123             : 
     124           0 :     tevent_req_done(req);
     125           0 : }
     126             : 
     127           0 : errno_t resolv_get_domain_recv(TALLOC_CTX *mem_ctx,
     128             :                                struct tevent_req *req,
     129             :                                char **_dns_domain)
     130             : {
     131           0 :     struct resolv_get_domain_state *state = NULL;
     132           0 :     char *dns_domain = NULL;
     133           0 :     char *domptr = NULL;
     134             : 
     135           0 :     state = tevent_req_data(req, struct resolv_get_domain_state);
     136             : 
     137           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     138             : 
     139           0 :     domptr = strchr(state->fqdn, '.');
     140           0 :     if (domptr == NULL || (*(domptr+1) == '\0')) {
     141             :         /* If the FQDN did not contain a dot or the dot was the last character
     142             :          * (broken DNS server perhaps) */
     143           0 :         dns_domain = state->fqdn;
     144             :     } else {
     145           0 :         dns_domain = domptr + 1;
     146             :     }
     147             : 
     148           0 :     *_dns_domain = talloc_strdup(mem_ctx, dns_domain);
     149           0 :     if (*_dns_domain == NULL) {
     150           0 :         return ENOMEM;
     151             :     }
     152             : 
     153           0 :     return EOK;
     154             : }
     155             : 
     156             : struct resolv_discover_srv_state {
     157             :     struct tevent_context *ev;
     158             :     struct resolv_ctx *resolv_ctx;
     159             :     const char *service;
     160             :     const char *protocol;
     161             :     const char **discovery_domains;
     162             :     int domain_index;
     163             : 
     164             :     struct ares_srv_reply *reply_list;
     165             :     uint32_t ttl;
     166             : };
     167             : 
     168             : static errno_t resolv_discover_srv_next_domain(struct tevent_req *req);
     169             : static void resolv_discover_srv_done(struct tevent_req *subreq);
     170             : 
     171           0 : struct tevent_req *resolv_discover_srv_send(TALLOC_CTX *mem_ctx,
     172             :                                             struct tevent_context *ev,
     173             :                                             struct resolv_ctx *resolv_ctx,
     174             :                                             const char *service,
     175             :                                             const char *protocol,
     176             :                                             const char **discovery_domains)
     177             : {
     178           0 :     struct resolv_discover_srv_state *state = NULL;
     179           0 :     struct tevent_req *req = NULL;
     180             :     errno_t ret;
     181             : 
     182           0 :     req = tevent_req_create(mem_ctx, &state,
     183             :                             struct resolv_discover_srv_state);
     184           0 :     if (req == NULL) {
     185           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
     186           0 :         return NULL;
     187             :     }
     188             : 
     189           0 :     if (resolv_ctx == NULL || service == NULL || protocol == NULL
     190           0 :         || discovery_domains == NULL) {
     191           0 :         ret = EINVAL;
     192           0 :         goto immediately;
     193             :     }
     194             : 
     195           0 :     state->ev = ev;
     196           0 :     state->resolv_ctx = resolv_ctx;
     197           0 :     state->discovery_domains = discovery_domains;
     198           0 :     state->service = service;
     199           0 :     state->protocol = protocol;
     200           0 :     state->domain_index = 0;
     201             : 
     202           0 :     ret = resolv_discover_srv_next_domain(req);
     203           0 :     if (ret != EAGAIN) {
     204           0 :         goto immediately;
     205             :     }
     206             : 
     207           0 :     return req;
     208             : 
     209             : immediately:
     210           0 :     if (ret == EOK) {
     211           0 :         tevent_req_done(req);
     212             :     } else {
     213           0 :         tevent_req_error(req, ret);
     214             :     }
     215           0 :     tevent_req_post(req, ev);
     216             : 
     217           0 :     return req;
     218             : }
     219             : 
     220           0 : static errno_t resolv_discover_srv_next_domain(struct tevent_req *req)
     221             : {
     222           0 :     struct resolv_discover_srv_state *state = NULL;
     223           0 :     struct tevent_req *subreq = NULL;
     224           0 :     const char *domain = NULL;
     225           0 :     char *query = NULL;
     226             :     errno_t ret;
     227             : 
     228           0 :     state = tevent_req_data(req, struct resolv_discover_srv_state);
     229             : 
     230           0 :     domain = state->discovery_domains[state->domain_index];
     231           0 :     if (domain == NULL) {
     232           0 :         ret = EOK;
     233           0 :         goto done;
     234             :     }
     235             : 
     236           0 :     query = talloc_asprintf(state, "_%s._%s.%s", state->service,
     237             :                             state->protocol, domain);
     238           0 :     if (query == NULL) {
     239           0 :         ret = ENOMEM;
     240           0 :         goto done;
     241             :     }
     242             : 
     243           0 :     DEBUG(SSSDBG_TRACE_FUNC, "SRV resolution of service '%s'. Will use DNS "
     244             :           "discovery domain '%s'\n", state->service, domain);
     245             : 
     246           0 :     subreq = resolv_getsrv_send(state, state->ev,
     247             :                                 state->resolv_ctx, query);
     248           0 :     if (subreq == NULL) {
     249           0 :         ret = ENOMEM;
     250           0 :         goto done;
     251             :     }
     252             : 
     253           0 :     tevent_req_set_callback(subreq, resolv_discover_srv_done, req);
     254             : 
     255           0 :     state->domain_index++;
     256           0 :     ret = EAGAIN;
     257             : 
     258             : done:
     259           0 :     if (ret != EAGAIN) {
     260           0 :         talloc_free(query);
     261             :     }
     262             : 
     263           0 :     return ret;
     264             : }
     265             : 
     266           0 : static void resolv_discover_srv_done(struct tevent_req *subreq)
     267             : {
     268           0 :     struct resolv_discover_srv_state *state = NULL;
     269           0 :     struct tevent_req *req = NULL;
     270             :     int status;
     271             :     errno_t ret;
     272             : 
     273           0 :     req = tevent_req_callback_data(subreq, struct tevent_req);
     274           0 :     state = tevent_req_data(req, struct resolv_discover_srv_state);
     275             : 
     276           0 :     ret = resolv_getsrv_recv(state, subreq, &status, NULL,
     277             :                              &state->reply_list, &state->ttl);
     278           0 :     talloc_zfree(subreq);
     279           0 :     if (ret != EOK) {
     280           0 :         DEBUG(SSSDBG_OP_FAILURE, "SRV query failed [%d]: %s\n",
     281             :                                   status, resolv_strerror(status));
     282             : 
     283           0 :         if (status == ARES_ENOTFOUND) {
     284             :             /* continue with next discovery domain */
     285           0 :             ret = resolv_discover_srv_next_domain(req);
     286           0 :             if (ret == EOK) {
     287             :                 /* there are no more domains to try */
     288           0 :                 ret = ENOENT;
     289             :             }
     290             : 
     291           0 :             goto done;
     292             :         }
     293             : 
     294             :         /* critical error when fetching SRV record */
     295           0 :         ret = EIO;
     296           0 :         goto done;
     297             :     }
     298             : 
     299             : done:
     300           0 :     if (ret == EOK) {
     301           0 :         tevent_req_done(req);
     302           0 :     } else if (ret != EAGAIN) {
     303           0 :         tevent_req_error(req, ret);
     304             :     }
     305             : 
     306           0 :     return;
     307             : }
     308             : 
     309           0 : errno_t resolv_discover_srv_recv(TALLOC_CTX *mem_ctx,
     310             :                                  struct tevent_req *req,
     311             :                                  struct ares_srv_reply **_reply_list,
     312             :                                  uint32_t *_ttl,
     313             :                                  char **_dns_domain)
     314             : {
     315           0 :     struct resolv_discover_srv_state *state = NULL;
     316           0 :     char *domain = NULL;
     317             : 
     318           0 :     state = tevent_req_data(req, struct resolv_discover_srv_state);
     319             : 
     320           0 :     TEVENT_REQ_RETURN_ON_ERROR(req);
     321             : 
     322           0 :     if (_dns_domain != NULL) {
     323             :         /* domain_index now points to selected domain + 1 */
     324           0 :         domain = talloc_strdup(mem_ctx,
     325           0 :                            state->discovery_domains[state->domain_index - 1]);
     326           0 :         if (domain == NULL) {
     327           0 :             return ENOMEM;
     328             :         }
     329             : 
     330           0 :         *_dns_domain = domain;
     331             :     }
     332             : 
     333           0 :     if (_reply_list != NULL) {
     334           0 :         *_reply_list = talloc_steal(mem_ctx, state->reply_list);
     335             :     }
     336             : 
     337           0 :     if (_ttl != NULL) {
     338           0 :         *_ttl = state->ttl;
     339             :     }
     340             : 
     341           0 :     return EOK;
     342             : }

Generated by: LCOV version 1.10