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 :
25 : #include "util/util.h"
26 : #include "resolv/async_resolv.h"
27 : #include "providers/fail_over_srv.h"
28 : #include "providers/ipa/ipa_srv.h"
29 :
30 : #define IPA_DNS_LOCATION "_location"
31 :
32 : struct ipa_srv_plugin_ctx {
33 : struct resolv_ctx *resolv_ctx;
34 : const char *hostname;
35 : const char *ipa_domain;
36 : };
37 :
38 : struct ipa_srv_plugin_ctx *
39 0 : ipa_srv_plugin_ctx_init(TALLOC_CTX *mem_ctx,
40 : struct resolv_ctx *resolv_ctx,
41 : const char *hostname,
42 : const char *ipa_domain)
43 : {
44 0 : struct ipa_srv_plugin_ctx *ctx = NULL;
45 :
46 0 : ctx = talloc_zero(mem_ctx, struct ipa_srv_plugin_ctx);
47 0 : if (ctx == NULL) {
48 0 : return NULL;
49 : }
50 :
51 0 : ctx->resolv_ctx = resolv_ctx;
52 :
53 0 : ctx->hostname = talloc_strdup(ctx, hostname);
54 0 : if (ctx->hostname == NULL) {
55 0 : goto fail;
56 : }
57 :
58 0 : ctx->ipa_domain = talloc_strdup(ctx, ipa_domain);
59 0 : if (ctx->ipa_domain == NULL) {
60 0 : goto fail;
61 : }
62 :
63 0 : return ctx;
64 :
65 : fail:
66 0 : talloc_free(ctx);
67 0 : return NULL;
68 : }
69 :
70 : struct ipa_srv_plugin_state {
71 : char *dns_domain;
72 : uint32_t ttl;
73 : struct fo_server_info *primary_servers;
74 : size_t num_primary_servers;
75 : struct fo_server_info *backup_servers;
76 : size_t num_backup_servers;
77 : };
78 :
79 : static void ipa_srv_plugin_done(struct tevent_req *subreq);
80 :
81 : /* If IPA server supports sites, we will use
82 : * _locations.hostname.discovery_domain for primary servers and
83 : * discovery_domain for backup servers. If the server does not support sites or
84 : * client's SRV record is not found, we will use the latter for primary
85 : * servers, setting backup servers to NULL */
86 0 : struct tevent_req *ipa_srv_plugin_send(TALLOC_CTX *mem_ctx,
87 : struct tevent_context *ev,
88 : const char *service,
89 : const char *protocol,
90 : const char *discovery_domain,
91 : void *pvt)
92 : {
93 0 : struct ipa_srv_plugin_state *state = NULL;
94 0 : struct ipa_srv_plugin_ctx *ctx = NULL;
95 0 : struct tevent_req *req = NULL;
96 0 : struct tevent_req *subreq = NULL;
97 0 : const char *primary_domain = NULL;
98 0 : const char *backup_domain = NULL;
99 : errno_t ret;
100 :
101 0 : req = tevent_req_create(mem_ctx, &state,
102 : struct ipa_srv_plugin_state);
103 0 : if (req == NULL) {
104 0 : DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n");
105 0 : return NULL;
106 : }
107 :
108 0 : ctx = talloc_get_type(pvt, struct ipa_srv_plugin_ctx);
109 0 : if (ctx == NULL) {
110 0 : ret = EINVAL;
111 0 : goto immediately;
112 : }
113 :
114 0 : if (discovery_domain != NULL) {
115 0 : backup_domain = talloc_strdup(state, discovery_domain);
116 : } else {
117 0 : backup_domain = talloc_strdup(state, ctx->ipa_domain);
118 : }
119 0 : if (backup_domain == NULL) {
120 0 : ret = ENOMEM;
121 0 : goto immediately;
122 : }
123 :
124 0 : if (strchr(ctx->hostname, '.') == NULL) {
125 : /* not FQDN, append domain name */
126 0 : primary_domain = talloc_asprintf(state, IPA_DNS_LOCATION ".%s.%s",
127 : ctx->hostname, backup_domain);
128 : } else {
129 0 : primary_domain = talloc_asprintf(state, IPA_DNS_LOCATION ".%s",
130 : ctx->hostname);
131 : }
132 0 : if (primary_domain == NULL) {
133 0 : ret = ENOMEM;
134 0 : goto immediately;
135 : }
136 :
137 0 : DEBUG(SSSDBG_TRACE_FUNC, "About to discover primary and "
138 : "backup servers\n");
139 :
140 0 : subreq = fo_discover_servers_send(state, ev, ctx->resolv_ctx, service,
141 : protocol, primary_domain, backup_domain);
142 0 : if (subreq == NULL) {
143 0 : ret = ENOMEM;
144 0 : goto immediately;
145 : }
146 :
147 0 : tevent_req_set_callback(subreq, ipa_srv_plugin_done, req);
148 :
149 0 : return req;
150 :
151 : immediately:
152 0 : tevent_req_error(req, ret);
153 0 : tevent_req_post(req, ev);
154 :
155 0 : return req;
156 : }
157 :
158 0 : static void ipa_srv_plugin_done(struct tevent_req *subreq)
159 : {
160 0 : struct ipa_srv_plugin_state *state = NULL;
161 0 : struct tevent_req *req = NULL;
162 : errno_t ret;
163 :
164 0 : req = tevent_req_callback_data(subreq, struct tevent_req);
165 0 : state = tevent_req_data(req, struct ipa_srv_plugin_state);
166 :
167 0 : ret = fo_discover_servers_recv(state, subreq, &state->dns_domain,
168 : &state->ttl,
169 : &state->primary_servers,
170 : &state->num_primary_servers,
171 : &state->backup_servers,
172 : &state->num_backup_servers);
173 0 : talloc_zfree(subreq);
174 0 : if (ret != EOK) {
175 0 : tevent_req_error(req, ret);
176 0 : return;
177 : }
178 :
179 0 : DEBUG(SSSDBG_TRACE_FUNC, "Got %zu primary and %zu backup servers\n",
180 : state->num_primary_servers, state->num_backup_servers);
181 :
182 0 : tevent_req_done(req);
183 : }
184 :
185 0 : errno_t ipa_srv_plugin_recv(TALLOC_CTX *mem_ctx,
186 : struct tevent_req *req,
187 : char **_dns_domain,
188 : uint32_t *_ttl,
189 : struct fo_server_info **_primary_servers,
190 : size_t *_num_primary_servers,
191 : struct fo_server_info **_backup_servers,
192 : size_t *_num_backup_servers)
193 : {
194 0 : struct ipa_srv_plugin_state *state = NULL;
195 0 : state = tevent_req_data(req, struct ipa_srv_plugin_state);
196 :
197 0 : TEVENT_REQ_RETURN_ON_ERROR(req);
198 :
199 0 : if (_primary_servers) {
200 0 : *_primary_servers = talloc_steal(mem_ctx, state->primary_servers);
201 : }
202 :
203 0 : if (_num_primary_servers) {
204 0 : *_num_primary_servers = state->num_primary_servers;
205 : }
206 :
207 0 : if (_backup_servers) {
208 0 : *_backup_servers = talloc_steal(mem_ctx, state->backup_servers);
209 : }
210 :
211 0 : if (_num_backup_servers) {
212 0 : *_num_backup_servers = state->num_backup_servers;
213 : }
214 :
215 0 : if (_dns_domain) {
216 0 : *_dns_domain = talloc_steal(mem_ctx, state->dns_domain);
217 : }
218 :
219 0 : if (_ttl) {
220 0 : *_ttl = state->ttl;
221 : }
222 :
223 0 : return EOK;
224 : }
|