sssd  2.2.3
About: SSSD provides a set of daemons to manage access to remote directories and authentication mechanisms such as LDAP, Kerberos or FreeIPA. It provides also an NSS and PAM interface toward the system.
  Fossies Dox: sssd-2.2.3.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

data_provider_fo.c
Go to the documentation of this file.
1 /*
2  SSSD
3 
4  Data Provider Helpers
5 
6  Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 #include <netdb.h>
23 #include <arpa/inet.h>
24 #include "providers/backend.h"
25 #include "resolv/async_resolv.h"
26 
30 
31  struct be_svc_data *svc;
32 
34  void *private_data;
35 };
36 
37 static const char *proto_table[] = { FO_PROTO_TCP, FO_PROTO_UDP, NULL };
38 
39 int be_fo_is_srv_identifier(const char *server)
40 {
41  return server && strcasecmp(server, BE_SRV_IDENTIFIER) == 0;
42 }
43 
44 static int be_fo_get_options(struct be_ctx *ctx,
45  struct fo_options *opts)
46 {
47  opts->service_resolv_timeout = dp_opt_get_int(ctx->be_res->opts,
49  opts->retry_timeout = 30;
50  opts->srv_retry_neg_timeout = 15;
51  opts->family_order = ctx->be_res->family_order;
52 
53  return EOK;
54 }
55 
57 {
58  int ret;
59  struct fo_options fopts;
60 
61  if (ctx->be_fo != NULL) {
62  return EOK;
63  }
64 
65  ctx->be_fo = talloc_zero(ctx, struct be_failover_ctx);
66  if (!ctx->be_fo) {
67  return ENOMEM;
68  }
69 
70  ret = be_res_init(ctx);
71  if (ret != EOK) {
73  "fatal error initializing resolver context\n");
74  talloc_zfree(ctx->be_fo);
75  return ret;
76  }
77  ctx->be_fo->be_res = ctx->be_res;
78 
79  ret = be_fo_get_options(ctx, &fopts);
80  if (ret != EOK) {
81  talloc_zfree(ctx->be_fo);
82  return ret;
83  }
84 
85  ctx->be_fo->fo_ctx = fo_context_init(ctx->be_fo, &fopts);
86  if (!ctx->be_fo->fo_ctx) {
87  talloc_zfree(ctx->be_fo);
88  return ENOMEM;
89  }
90 
91  return EOK;
92 }
93 
94 static int be_svc_data_destroy(void *memptr)
95 {
96  struct be_svc_data *svc;
97 
98  svc = talloc_get_type(memptr, struct be_svc_data);
99 
100  while (svc->callbacks) {
101  /* callbacks removes themselves from the list,
102  * so this while will freem them all and then terminate */
103  talloc_free(svc->callbacks);
104  }
105 
106  return 0;
107 }
108 
109 /*
110  * Find registered be_svc_data by service name.
111  */
112 static struct be_svc_data *be_fo_find_svc_data(struct be_ctx *ctx,
113  const char *service_name)
114 {
115  struct be_svc_data *svc;
116 
117  if (!ctx || !ctx->be_fo) {
118  return 0;
119  }
120 
121  DLIST_FOR_EACH(svc, ctx->be_fo->svcs) {
122  if (strcmp(svc->name, service_name) == 0) {
123  return svc;
124  }
125  }
126 
127  return 0;
128 }
129 
130 int be_fo_add_service(struct be_ctx *ctx, const char *service_name,
131  datacmp_fn user_data_cmp)
132 {
133  struct fo_service *service;
134  struct be_svc_data *svc;
135  int ret;
136 
137  svc = be_fo_find_svc_data(ctx, service_name);
138  if (svc) {
139  DEBUG(SSSDBG_TRACE_FUNC, "Failover service already initialized!\n");
140  /* we already have a service up and configured,
141  * can happen when using both id and auth provider
142  */
143  return EOK;
144  }
145 
146  /* if not in the be service list, try to create new one */
147 
148  ret = fo_new_service(ctx->be_fo->fo_ctx, service_name, user_data_cmp,
149  &service);
150  if (ret != EOK && ret != EEXIST) {
151  DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create failover service!\n");
152  return ret;
153  }
154 
155  svc = talloc_zero(ctx->be_fo, struct be_svc_data);
156  if (!svc) {
157  return ENOMEM;
158  }
159  talloc_set_destructor((TALLOC_CTX *)svc, be_svc_data_destroy);
160 
161  svc->name = talloc_strdup(svc, service_name);
162  if (!svc->name) {
163  talloc_zfree(svc);
164  return ENOMEM;
165  }
166  svc->fo_service = service;
167 
168  DLIST_ADD(ctx->be_fo->svcs, svc);
169 
170  return EOK;
171 }
172 
173 static int be_svc_callback_destroy(void *memptr)
174 {
175  struct be_svc_callback *callback;
176 
177  callback = talloc_get_type(memptr, struct be_svc_callback);
178 
179  if (callback->svc) {
180  DLIST_REMOVE(callback->svc->callbacks, callback);
181  }
182 
183  return 0;
184 }
185 
186 int be_fo_service_add_callback(TALLOC_CTX *memctx,
187  struct be_ctx *ctx, const char *service_name,
189 {
190  struct be_svc_callback *callback;
191  struct be_svc_data *svc;
192 
193  svc = be_fo_find_svc_data(ctx, service_name);
194  if (NULL == svc) {
195  return ENOENT;
196  }
197 
198  callback = talloc_zero(memctx, struct be_svc_callback);
199  if (!callback) {
200  return ENOMEM;
201  }
202  talloc_set_destructor((TALLOC_CTX *)callback, be_svc_callback_destroy);
203 
204  callback->svc = svc;
205  callback->fn = fn;
206  callback->private_data = private_data;
207 
208  DLIST_ADD(svc->callbacks, callback);
209 
210  return EOK;
211 }
212 
216  void *pvt,
217  const char *plugin_name)
218 {
219  bool bret;
220 
221  DEBUG(SSSDBG_TRACE_FUNC, "Trying to set SRV lookup plugin to %s\n",
222  plugin_name);
223 
224  bret = fo_set_srv_lookup_plugin(ctx->be_fo->fo_ctx, send_fn, recv_fn, pvt);
225  if (bret) {
226  DEBUG(SSSDBG_TRACE_FUNC, "SRV lookup plugin is now %s\n",
227  plugin_name);
228  } else {
229  DEBUG(SSSDBG_MINOR_FAILURE, "Unable to set SRV lookup plugin, "
230  "another plugin may be already in place\n");
231  }
232 }
233 
235  const char *hostname)
236 {
237  struct fo_resolve_srv_dns_ctx *srv_ctx = NULL;
238  char resolved_hostname[HOST_NAME_MAX + 1];
239  errno_t ret;
240 
241  if (hostname == NULL) {
242  ret = gethostname(resolved_hostname, sizeof(resolved_hostname));
243  if (ret != EOK) {
244  ret = errno;
246  "gethostname() failed: [%d]: %s\n", ret, strerror(ret));
247  return ret;
248  }
249  resolved_hostname[HOST_NAME_MAX] = '\0';
250  hostname = resolved_hostname;
251  }
252 
256  be_ctx->domain->name);
257  if (srv_ctx == NULL) {
258  DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory?\n");
259  return ENOMEM;
260  }
261 
263  fo_resolve_srv_dns_recv, srv_ctx, "DNS");
264 
265  return EOK;
266 }
267 
269  const char *service_name,
270  const char *query_service,
271  const char *default_discovery_domain,
272  enum be_fo_protocol proto,
273  bool proto_fallback, void *user_data)
274 {
275  struct be_svc_data *svc;
276  const char *domain;
277  int ret;
278  int i;
279 
280  svc = be_fo_find_svc_data(ctx, service_name);
281  if (NULL == svc) {
282  return ENOENT;
283  }
284 
285  domain = dp_opt_get_string(ctx->be_res->opts, DP_RES_OPT_DNS_DOMAIN);
286  if (!domain) {
287  domain = default_discovery_domain;
288  }
289 
290  /* Add the first protocol as the primary lookup */
291  ret = fo_add_srv_server(svc->fo_service, query_service,
292  domain, ctx->domain->name,
293  proto_table[proto], user_data);
294  if (ret && ret != EEXIST) {
296  "Failed to add SRV lookup reference to failover service "
297  "[%d]: %s\n", ret, sss_strerror(ret));
298  return ret;
299  }
300 
301  if (proto_fallback) {
302  i = (proto + 1) % BE_FO_PROTO_SENTINEL;
303  /* All the rest as fallback */
304  while (i != proto) {
305  ret = fo_add_srv_server(svc->fo_service, query_service,
306  domain, ctx->domain->name,
307  proto_table[i], user_data);
308  if (ret && ret != EEXIST) {
310  "Failed to add SRV lookup reference to failover "
311  "service [%d]: %s\n", ret, sss_strerror(ret));
312  return ret;
313  }
314 
315  i = (i + 1) % BE_FO_PROTO_SENTINEL;
316  }
317  }
318 
319  return EOK;
320 }
321 
322 int be_fo_get_server_count(struct be_ctx *ctx, const char *service_name)
323 {
324  struct be_svc_data *svc_data;
325 
326  svc_data = be_fo_find_svc_data(ctx, service_name);
327  if (!svc_data) {
328  return 0;
329  }
330 
331  return fo_get_server_count(svc_data->fo_service);
332 }
333 
334 int be_fo_add_server(struct be_ctx *ctx, const char *service_name,
335  const char *server, int port, void *user_data,
336  bool primary)
337 {
338  struct be_svc_data *svc;
339  int ret;
340 
341  svc = be_fo_find_svc_data(ctx, service_name);
342  if (NULL == svc) {
343  return ENOENT;
344  }
345 
346  ret = fo_add_server(svc->fo_service, server, port,
347  user_data, primary);
348  if (ret && ret != EEXIST) {
350  "Failed to add server to failover service [%d]: %s\n",
351  ret, sss_strerror(ret));
352  return ret;
353  }
354 
355  return EOK;
356 }
357 
359  struct tevent_context *ev;
360  struct be_ctx *ctx;
361 
362  struct be_svc_data *svc;
363  int attempts;
364 
365  struct fo_server *srv;
366  bool first_try;
367 };
368 
370  struct be_ctx *bctx;
371  struct tevent_context *ev;
372 
373  struct be_svc_data *svc;
374  unsigned long timeout;
375 
376  int attempts;
377 };
378 
379 errno_t be_resolve_server_process(struct tevent_req *subreq,
380  struct be_resolve_server_state *state,
381  struct tevent_req **new_subreq);
382 static void be_primary_server_done(struct tevent_req *subreq);
383 static errno_t
384 be_primary_server_timeout_activate(TALLOC_CTX *mem_ctx,
385  struct tevent_context *ev,
386  struct be_ctx *bctx,
387  struct be_svc_data *svc,
388  const unsigned long timeout_seconds);
389 
390 static void
391 be_primary_server_timeout(struct tevent_context *ev,
392  struct tevent_timer *te,
393  struct timeval tv, void *pvt)
394 {
395  struct be_primary_server_ctx *ctx = talloc_get_type(pvt, struct be_primary_server_ctx);
396  struct tevent_req *subreq;
397 
398  ctx->bctx->be_fo->primary_server_handler = NULL;
399 
400  DEBUG(SSSDBG_TRACE_FUNC, "Looking for primary server!\n");
401  subreq = fo_resolve_service_send(ctx->bctx, ctx->ev,
402  ctx->bctx->be_fo->be_res->resolv,
403  ctx->bctx->be_fo->fo_ctx,
404  ctx->svc->fo_service);
405  if (subreq == NULL) {
406  return;
407  }
408  tevent_req_set_callback(subreq, be_primary_server_done, ctx);
409 }
410 
411 static void be_primary_server_done(struct tevent_req *subreq)
412 {
413  errno_t ret;
414  struct be_primary_server_ctx *ctx;
415  struct be_resolve_server_state *resolve_state;
416  struct tevent_req *new_subreq;
417 
418  ctx = tevent_req_callback_data(subreq, struct be_primary_server_ctx);
419 
420  resolve_state = talloc_zero(ctx->bctx, struct be_resolve_server_state);
421  if (resolve_state == NULL) {
422  DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero() failed\n");
423  return;
424  }
425 
426  resolve_state->attempts = ctx->attempts;
427  resolve_state->ctx = ctx->bctx;
428  resolve_state->ev = ctx->ev;
429  resolve_state->first_try = true;
430  resolve_state->srv = NULL;
431  resolve_state->svc = ctx->svc;
432 
433  ret = be_resolve_server_process(subreq, resolve_state, &new_subreq);
434  talloc_free(subreq);
435  if (ret == EAGAIN) {
436  ctx->attempts++;
437  tevent_req_set_callback(new_subreq, be_primary_server_done, ctx);
438  return;
439  } else if (ret == EIO || (ret == EOK &&
440  !fo_is_server_primary(resolve_state->srv))) {
441 
442  /* Schedule another lookup
443  * (either no server could be found or it was not primary)
444  */
445  ret = be_primary_server_timeout_activate(ctx->bctx, ctx->ev, ctx->bctx,
446  ctx->svc, ctx->timeout);
447  if (ret != EOK) {
449  "Could not schedule primary server lookup [%d]: %s\n",
450  ret, sss_strerror(ret));
451  }
452  } else if (ret == EOK) {
453  be_run_reconnect_cb(ctx->bctx);
454  }
455  talloc_zfree(ctx);
456 
457  /* If an error occurred just end the routine */
458 }
459 
460 static errno_t
462  struct tevent_context *ev,
463  struct be_ctx *bctx,
464  struct be_svc_data *svc,
465  const unsigned long timeout_seconds)
466 {
467  struct timeval tv;
468  struct be_primary_server_ctx *ctx;
469  struct be_failover_ctx *fo_ctx = bctx->be_fo;
470 
471  if (fo_ctx->primary_server_handler != NULL) {
472  DEBUG(SSSDBG_TRACE_FUNC, "The primary server reconnection "
473  "is already scheduled\n");
474  return EOK;
475  }
476 
477  ctx = talloc_zero(mem_ctx, struct be_primary_server_ctx);
478  if (ctx == NULL) {
479  return ENOMEM;
480  }
481 
482  ctx->bctx = bctx;
483  ctx->ev = ev;
484  ctx->svc = svc;
485  ctx->timeout = timeout_seconds;
486 
487  tv = tevent_timeval_current();
488  tv = tevent_timeval_add(&tv, timeout_seconds, 0);
489  fo_ctx->primary_server_handler = tevent_add_timer(ev, bctx, tv,
491  if (fo_ctx->primary_server_handler == NULL) {
492  DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
493  talloc_free(ctx);
494  return ENOMEM;
495  }
496 
497  DEBUG(SSSDBG_TRACE_INTERNAL, "Primary server reactivation timeout set "
498  "to %lu seconds\n", timeout_seconds);
499  return EOK;
500 }
501 
502 
503 static void be_resolve_server_done(struct tevent_req *subreq);
504 
505 struct tevent_req *be_resolve_server_send(TALLOC_CTX *memctx,
506  struct tevent_context *ev,
507  struct be_ctx *ctx,
508  const char *service_name,
509  bool first_try)
510 {
511  struct tevent_req *req, *subreq;
512  struct be_resolve_server_state *state;
513  struct be_svc_data *svc;
514 
515  req = tevent_req_create(memctx, &state, struct be_resolve_server_state);
516  if (!req) return NULL;
517 
518  state->ev = ev;
519  state->ctx = ctx;
520 
521  svc = be_fo_find_svc_data(ctx, service_name);
522  if (NULL == svc) {
523  tevent_req_error(req, EINVAL);
524  tevent_req_post(req, ev);
525  return req;
526  }
527 
528  state->svc = svc;
529  state->attempts = 0;
530  state->first_try = first_try;
531 
532  subreq = fo_resolve_service_send(state, ev,
533  ctx->be_fo->be_res->resolv,
534  ctx->be_fo->fo_ctx,
535  svc->fo_service);
536  if (!subreq) {
537  talloc_zfree(req);
538  return NULL;
539  }
540  tevent_req_set_callback(subreq, be_resolve_server_done, req);
541 
542  return req;
543 }
544 
545 static void be_resolve_server_done(struct tevent_req *subreq)
546 {
547  struct tevent_req *new_subreq;
548  struct tevent_req *req = tevent_req_callback_data(subreq,
549  struct tevent_req);
550  struct be_resolve_server_state *state = tevent_req_data(req,
551  struct be_resolve_server_state);
552  time_t timeout = fo_get_service_retry_timeout(state->svc->fo_service) + 1;
553  int ret;
554 
555  ret = be_resolve_server_process(subreq, state, &new_subreq);
556  talloc_zfree(subreq);
557  if (ret == EAGAIN) {
558  tevent_req_set_callback(new_subreq, be_resolve_server_done, req);
559  return;
560  } else if (ret != EOK) {
561  goto fail;
562  }
563 
564  if (!fo_is_server_primary(state->srv)) {
565  /* FIXME: make the timeout configurable */
566  ret = be_primary_server_timeout_activate(state->ctx, state->ev,
567  state->ctx, state->svc,
568  timeout);
569  if (ret != EOK) {
570  goto fail;
571  }
572  }
573 
574  tevent_req_done(req);
575  return;
576 
577 fail:
579  "Server resolution failed: [%d]: %s\n", ret, sss_strerror(ret));
580  state->svc->first_resolved = NULL;
581  tevent_req_error(req, ret);
582 }
583 
584 errno_t be_resolve_server_process(struct tevent_req *subreq,
585  struct be_resolve_server_state *state,
586  struct tevent_req **new_subreq)
587 {
588  errno_t ret;
589  time_t srv_status_change;
590  struct be_svc_callback *callback;
591  char *srvname;
592 
593  ret = fo_resolve_service_recv(subreq, state, &state->srv);
594  switch (ret) {
595  case EOK:
596  if (!state->srv) {
597  return EFAULT;
598  }
599  break;
600 
601  case ENOENT:
602  /* all servers have been tried and none
603  * was found good, go offline */
604  return EIO;
605 
606  default:
607  /* mark server as bad and retry */
608  if (!state->srv) {
609  return EFAULT;
610  }
612  "Couldn't resolve server (%s), resolver returned [%d]: %s\n",
614 
615  state->attempts++;
616  if (state->attempts >= 10) {
617  DEBUG(SSSDBG_OP_FAILURE, "Failed to find a server after 10 attempts\n");
618  return EIO;
619  }
620 
621  /* now try next one */
622  DEBUG(SSSDBG_TRACE_LIBS, "Trying with the next one!\n");
623  subreq = fo_resolve_service_send(state, state->ev,
624  state->ctx->be_fo->be_res->resolv,
625  state->ctx->be_fo->fo_ctx,
626  state->svc->fo_service);
627  if (!subreq) {
628  return ENOMEM;
629  }
630 
631  if (new_subreq) {
632  *new_subreq = subreq;
633  }
634 
635  return EAGAIN;
636  }
637 
638  /* all fine we got the server */
639  if (state->svc->first_resolved == NULL || state->first_try == true) {
640  DEBUG(SSSDBG_TRACE_LIBS, "Saving the first resolved server\n");
641  state->svc->first_resolved = state->srv;
642  } else if (state->svc->first_resolved == state->srv) {
644  "The fail over cycled through all available servers\n");
645  return ENOENT;
646  }
647 
649  struct resolv_hostent *srvaddr;
650  char ipaddr[128];
651  srvaddr = fo_get_server_hostent(state->srv);
652  if (!srvaddr) {
654  "FATAL: No hostent available for server (%s)\n",
655  fo_get_server_str_name(state->srv));
656  return EFAULT;
657  }
658 
659  inet_ntop(srvaddr->family, srvaddr->addr_list[0]->ipaddr,
660  ipaddr, 128);
661 
662  DEBUG(SSSDBG_FUNC_DATA, "Found address for server %s: [%s] TTL %d\n",
663  fo_get_server_str_name(state->srv), ipaddr,
664  srvaddr->addr_list[0]->ttl);
665  }
666 
667  srv_status_change = fo_get_server_hostname_last_change(state->srv);
668 
669  /* now call all svc callbacks if server changed or if it is explicitly
670  * requested or if the server is the same but changed status since last time*/
671  if (state->svc->last_good_srv == NULL ||
672  strcmp(fo_get_server_name(state->srv), state->svc->last_good_srv) != 0 ||
673  fo_get_server_port(state->srv) != state->svc->last_good_port ||
674  state->svc->run_callbacks ||
675  srv_status_change > state->svc->last_status_change) {
676  state->svc->last_status_change = srv_status_change;
677  state->svc->run_callbacks = false;
678 
679  srvname = talloc_strdup(state->svc, fo_get_server_name(state->srv));
680  if (srvname == NULL) {
681  DEBUG(SSSDBG_CRIT_FAILURE, "Unable to copy server name\n");
682  return ENOMEM;
683  }
684 
685  talloc_free(state->svc->last_good_srv);
686  state->svc->last_good_srv = srvname;
687  state->svc->last_good_port = fo_get_server_port(state->srv);
688 
689  DLIST_FOR_EACH(callback, state->svc->callbacks) {
690  callback->fn(callback->private_data, state->srv);
691  }
692  }
693 
694  return EOK;
695 }
696 
697 int be_resolve_server_recv(struct tevent_req *req,
698  TALLOC_CTX *ref_ctx,
699  struct fo_server **srv)
700 {
701  struct be_resolve_server_state *state = tevent_req_data(req,
702  struct be_resolve_server_state);
703 
705 
706  if (srv) {
707  fo_ref_server(ref_ctx, state->srv);
708  *srv = state->srv;
709  }
710 
711  return EOK;
712 }
713 
714 void be_fo_try_next_server(struct be_ctx *ctx, const char *service_name)
715 {
716  struct be_svc_data *svc;
717 
718  svc = be_fo_find_svc_data(ctx, service_name);
719  if (svc) {
721  }
722 }
723 
725  const char *service_name)
726 {
727  struct be_svc_data *svc;
728  struct fo_server *server;
729 
730  svc = be_fo_find_svc_data(ctx, service_name);
731  if (svc != NULL) {
732  server = fo_get_active_server(svc->fo_service);
733  if (server != NULL) {
734  return fo_get_server_name(server);
735  }
736  }
737 
738  return NULL;
739 }
740 
742  const char *service_name)
743 {
744  struct be_svc_data *svc;
745 
746  svc = be_fo_find_svc_data(ctx, service_name);
747  if (NULL == svc) {
748  return ENOENT;
749  }
750 
751  svc->run_callbacks = true;
752 
753  return EOK;
754 }
755 
756 void reset_fo(struct be_ctx *be_ctx)
757 {
759 }
760 
762  const char *svc_name)
763 {
764  struct fo_service *service;
765  int ret;
766 
768  "Resetting all servers in service %s\n", svc_name);
769 
770  ret = fo_get_service(be_ctx->be_fo->fo_ctx, svc_name, &service);
771  if (ret != EOK) {
773  "Cannot retrieve service [%s]\n", svc_name);
774  return;
775  }
776 
777  fo_reset_servers(service);
778 }
779 
781  const char *service_name,
782  struct fo_server *server,
783  enum port_status status,
784  int line,
785  const char *file,
786  const char *function)
787 {
788  struct be_svc_data *be_svc;
789 
790  /* Print debug info */
791  switch (status) {
792  case PORT_NEUTRAL:
794  "Setting status: PORT_NEUTRAL. Called from: %s: %s: %d\n",
795  file, function, line);
796  break;
797  case PORT_WORKING:
799  "Setting status: PORT_WORKING. Called from: %s: %s: %d\n",
800  file, function, line);
801  break;
802  case PORT_NOT_WORKING:
804  "Setting status: PORT_NOT_WORKING. Called from: %s: %s: %d\n",
805  file, function, line);
806  break;
807  }
808 
809  be_svc = be_fo_find_svc_data(ctx, service_name);
810  if (be_svc == NULL) {
812  "No service associated with name %s\n", service_name);
813  return;
814  }
815 
816  if (!fo_svc_has_server(be_svc->fo_service, server)) {
818  "The server %p is not valid anymore, cannot set its status\n",
819  server);
820  return;
821  }
822 
823  /* Now we know that the server is valid */
824  fo_set_port_status(server, status);
825 
826  if (status == PORT_WORKING) {
827  /* We were successful in connecting to the server. Cycle through all
828  * available servers next time */
829  be_svc->first_resolved = NULL;
830  }
831 }
832 
833 /* Resolver back end interface */
834 static struct dp_option dp_res_default_opts[] = {
835  { "lookup_family_order", DP_OPT_STRING, { "ipv4_first" }, NULL_STRING },
836  { "dns_resolver_timeout", DP_OPT_NUMBER, { .number = 6 }, NULL_NUMBER },
837  { "dns_resolver_op_timeout", DP_OPT_NUMBER, { .number = 3 }, NULL_NUMBER },
838  { "dns_resolver_server_timeout", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER },
839  { "dns_discovery_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING },
841 };
842 
843 static errno_t be_res_get_opts(struct be_resolv_ctx *res_ctx,
844  struct confdb_ctx *cdb,
845  const char *conf_path)
846 {
847  errno_t ret;
848  const char *str_family;
849 
850  ret = dp_get_options(res_ctx, cdb, conf_path,
852  DP_RES_OPTS,
853  &res_ctx->opts);
854  if (ret != EOK) {
855  return ret;
856  }
857 
858  str_family = dp_opt_get_string(res_ctx->opts, DP_RES_OPT_FAMILY_ORDER);
859  DEBUG(SSSDBG_CONF_SETTINGS, "Lookup order: %s\n", str_family);
860 
861  if (strcasecmp(str_family, "ipv4_first") == 0) {
862  res_ctx->family_order = IPV4_FIRST;
863  } else if (strcasecmp(str_family, "ipv4_only") == 0) {
864  res_ctx->family_order = IPV4_ONLY;
865  } else if (strcasecmp(str_family, "ipv6_first") == 0) {
866  res_ctx->family_order = IPV6_FIRST;
867  } else if (strcasecmp(str_family, "ipv6_only") == 0) {
868  res_ctx->family_order = IPV6_ONLY;
869  } else {
870  DEBUG(SSSDBG_OP_FAILURE, "Unknown value for option %s: %s\n",
872  return EINVAL;
873  }
874 
875  return EOK;
876 }
877 
879 {
880  errno_t ret;
881 
882  if (ctx->be_res != NULL) {
883  return EOK;
884  }
885 
886  ctx->be_res = talloc_zero(ctx, struct be_resolv_ctx);
887  if (!ctx->be_res) {
888  return ENOMEM;
889  }
890 
891  ret = be_res_get_opts(ctx->be_res, ctx->cdb, ctx->conf_path);
892  if (ret != EOK) {
893  talloc_zfree(ctx->be_res);
894  return ret;
895  }
896 
897  ret = resolv_init(ctx, ctx->ev,
898  dp_opt_get_int(ctx->be_res->opts,
900  dp_opt_get_int(ctx->be_res->opts,
902  &ctx->be_res->resolv);
903  if (ret != EOK) {
904  talloc_zfree(ctx->be_res);
905  return ret;
906  }
907 
908  return EOK;
909 }
DP_RES_OPT_DNS_DOMAIN
@ DP_RES_OPT_DNS_DOMAIN
Definition: data_provider.h:269
be_res_init
errno_t be_res_init(struct be_ctx *ctx)
Definition: data_provider_fo.c:878
be_resolve_server_process
errno_t be_resolve_server_process(struct tevent_req *subreq, struct be_resolve_server_state *state, struct tevent_req **new_subreq)
Definition: data_provider_fo.c:584
fo_options::srv_retry_neg_timeout
time_t srv_retry_neg_timeout
Definition: fail_over.h:81
be_primary_server_ctx::timeout
unsigned long timeout
Definition: data_provider_fo.c:374
fo_get_server_hostname_last_change
time_t fo_get_server_hostname_last_change(struct fo_server *server)
Definition: fail_over.c:1632
IPV4_FIRST
@ IPV4_FIRST
Definition: async_resolv.h:79
sss_strerror
const char * sss_strerror(errno_t error)
return a string describing the error number like strerror()
Definition: util_errors.c:150
fo_resolve_srv_dns_send
struct tevent_req * fo_resolve_srv_dns_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *service, const char *protocol, const char *discovery_domain, void *pvt)
Definition: fail_over_srv.c:498
DP_RES_OPTS
@ DP_RES_OPTS
Definition: data_provider.h:271
fo_options
Definition: fail_over.h:80
be_svc_callback
Definition: data_provider_fo.c:27
SSSDBG_TRACE_INTERNAL
#define SSSDBG_TRACE_INTERNAL
Definition: debug.h:82
resolv_addr::ipaddr
uint8_t * ipaddr
Definition: async_resolv.h:89
fo_srv_lookup_plugin_send_t
struct tevent_req *(* fo_srv_lookup_plugin_send_t)(TALLOC_CTX *mem_ctx, struct tevent_context *ev, const char *service, const char *protocol, const char *discovery_domain, void *pvt)
Definition: fail_over_srv.h:41
dp_res_default_opts
static struct dp_option dp_res_default_opts[]
Definition: data_provider_fo.c:834
be_fo_get_options
static int be_fo_get_options(struct be_ctx *ctx, struct fo_options *opts)
Definition: data_provider_fo.c:44
EOK
#define EOK
Definition: hbac_evaluator.c:40
fo_get_service_retry_timeout
time_t fo_get_service_retry_timeout(struct fo_service *svc)
Definition: fail_over.c:1667
fo_set_port_status
void fo_set_port_status(struct fo_server *server, enum port_status status)
Definition: fail_over.c:1522
DP_OPT_NUMBER
@ DP_OPT_NUMBER
Definition: data_provider.h:184
be_fo_add_server
int be_fo_add_server(struct be_ctx *ctx, const char *service_name, const char *server, int port, void *user_data, bool primary)
Definition: data_provider_fo.c:334
resolv_hostent
Definition: async_resolv.h:93
be_primary_server_ctx::bctx
struct be_ctx * bctx
Definition: data_provider_fo.c:370
be_fo_add_srv_server
int be_fo_add_srv_server(struct be_ctx *ctx, const char *service_name, const char *query_service, const char *default_discovery_domain, enum be_fo_protocol proto, bool proto_fallback, void *user_data)
Definition: data_provider_fo.c:268
DP_RES_OPT_RESOLVER_TIMEOUT
@ DP_RES_OPT_RESOLVER_TIMEOUT
Definition: data_provider.h:266
be_primary_server_ctx
Definition: data_provider_fo.c:369
be_svc_data::callbacks
struct be_svc_callback * callbacks
Definition: backend.h:61
default_host_dbs
enum host_database default_host_dbs[]
Definition: async_resolv.c:63
be_res_get_opts
static errno_t be_res_get_opts(struct be_resolv_ctx *res_ctx, struct confdb_ctx *cdb, const char *conf_path)
Definition: data_provider_fo.c:843
_be_fo_set_port_status
void _be_fo_set_port_status(struct be_ctx *ctx, const char *service_name, struct fo_server *server, enum port_status status, int line, const char *file, const char *function)
Definition: data_provider_fo.c:780
be_resolv_ctx::opts
struct dp_option * opts
Definition: backend.h:44
dp_option
Definition: data_provider.h:201
sss_domain_info::name
char * name
Definition: confdb.h:343
be_svc_data::fo_service
struct fo_service * fo_service
Definition: backend.h:54
DP_RES_OPT_RESOLVER_SERVER_TIMEOUT
@ DP_RES_OPT_RESOLVER_SERVER_TIMEOUT
Definition: data_provider.h:268
status
Definition: fail_over.c:137
be_fo_get_server_count
int be_fo_get_server_count(struct be_ctx *ctx, const char *service_name)
Definition: data_provider_fo.c:322
proto_table
static const char * proto_table[]
Definition: data_provider_fo.c:37
be_primary_server_done
static void be_primary_server_done(struct tevent_req *subreq)
Definition: data_provider_fo.c:411
be_svc_data::last_good_port
int last_good_port
Definition: backend.h:57
be_primary_server_timeout_activate
static errno_t be_primary_server_timeout_activate(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct be_ctx *bctx, struct be_svc_data *svc, const unsigned long timeout_seconds)
Definition: data_provider_fo.c:461
be_resolve_server_state::ev
struct tevent_context * ev
Definition: data_provider_fo.c:359
fo_ref_server
void fo_ref_server(TALLOC_CTX *ref_ctx, struct fo_server *server)
Definition: fail_over.c:864
DP_RES_OPT_FAMILY_ORDER
@ DP_RES_OPT_FAMILY_ORDER
Definition: data_provider.h:265
be_svc_data_destroy
static int be_svc_data_destroy(void *memptr)
Definition: data_provider_fo.c:94
fo_is_server_primary
bool fo_is_server_primary(struct fo_server *server)
Definition: fail_over.c:1626
DEBUG
#define DEBUG(level, format,...)
macro to generate debug messages
Definition: debug.h:123
PORT_NOT_WORKING
@ PORT_NOT_WORKING
Definition: fail_over.h:45
be_svc_data
Definition: backend.h:49
be_fo_is_srv_identifier
int be_fo_is_srv_identifier(const char *server)
Definition: data_provider_fo.c:39
SSSDBG_TRACE_FUNC
#define SSSDBG_TRACE_FUNC
Definition: debug.h:80
resolv_hostent::family
int family
Definition: async_resolv.h:96
resolv_addr::ttl
int ttl
Definition: async_resolv.h:90
SSSDBG_FUNC_DATA
#define SSSDBG_FUNC_DATA
Definition: debug.h:79
be_fo_add_service
int be_fo_add_service(struct be_ctx *ctx, const char *service_name, datacmp_fn user_data_cmp)
Definition: data_provider_fo.c:130
be_resolv_ctx
Definition: backend.h:42
fo_options::service_resolv_timeout
int service_resolv_timeout
Definition: fail_over.h:83
be_resolv_ctx::family_order
enum restrict_family family_order
Definition: backend.h:46
be_fo_protocol
be_fo_protocol
Definition: backend.h:152
errno_t
int errno_t
Definition: hbac_evaluator.c:36
fo_get_server_hostent
struct resolv_hostent * fo_get_server_hostent(struct fo_server *server)
Definition: fail_over.c:1614
dp_opt_get_int
#define dp_opt_get_int(o, i)
Definition: data_provider.h:245
fo_resolve_srv_dns_ctx_init
struct fo_resolve_srv_dns_ctx * fo_resolve_srv_dns_ctx_init(TALLOC_CTX *mem_ctx, struct resolv_ctx *resolv_ctx, enum restrict_family family_order, enum host_database *host_dbs, const char *hostname, const char *sssd_domain)
Definition: fail_over_srv.c:463
SSSDBG_FATAL_FAILURE
#define SSSDBG_FATAL_FAILURE
Definition: debug.h:74
confdb_ctx
Definition: confdb_private.h:25
datacmp_fn
int(* datacmp_fn)(void *, void *)
Definition: fail_over.h:94
be_fo_service_add_callback
int be_fo_service_add_callback(TALLOC_CTX *memctx, struct be_ctx *ctx, const char *service_name, be_svc_callback_fn_t *fn, void *private_data)
Definition: data_provider_fo.c:186
fo_resolve_srv_dns_ctx
Definition: fail_over_srv.c:436
be_svc_data::name
const char * name
Definition: backend.h:53
be_svc_callback::fn
be_svc_callback_fn_t * fn
Definition: data_provider_fo.c:33
DP_OPTION_TERMINATOR
#define DP_OPTION_TERMINATOR
Definition: data_provider.h:208
fo_get_server_str_name
const char * fo_get_server_str_name(struct fo_server *server)
Definition: fail_over.c:1601
IPV6_FIRST
@ IPV6_FIRST
Definition: async_resolv.h:81
fo_get_service
int fo_get_service(struct fo_ctx *ctx, const char *name, struct fo_service **_service)
Definition: fail_over.c:471
be_primary_server_ctx::attempts
int attempts
Definition: data_provider_fo.c:376
fo_server
Definition: fail_over.c:81
be_svc_callback_fn_t
void() be_svc_callback_fn_t(void *, struct fo_server *)
Definition: backend.h:158
port_status
port_status
Definition: fail_over.h:42
be_resolve_server_state::srv
struct fo_server * srv
Definition: data_provider_fo.c:365
be_ctx::be_fo
struct be_failover_ctx * be_fo
Definition: backend.h:86
DP_RES_OPT_RESOLVER_OP_TIMEOUT
@ DP_RES_OPT_RESOLVER_OP_TIMEOUT
Definition: data_provider.h:267
resolv_init
int resolv_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, int timeout, int ares_timeout, struct resolv_ctx **ctxp)
Definition: async_resolv.c:453
be_fo_run_callbacks_at_next_request
int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx, const char *service_name)
Definition: data_provider_fo.c:741
be_fo_set_dns_srv_lookup_plugin
errno_t be_fo_set_dns_srv_lookup_plugin(struct be_ctx *be_ctx, const char *hostname)
Definition: data_provider_fo.c:234
be_resolve_server_state::svc
struct be_svc_data * svc
Definition: data_provider_fo.c:362
be_svc_callback::private_data
void * private_data
Definition: data_provider_fo.c:34
PORT_WORKING
@ PORT_WORKING
Definition: fail_over.h:44
be_fo_get_active_server_name
const char * be_fo_get_active_server_name(struct be_ctx *ctx, const char *service_name)
Definition: data_provider_fo.c:724
BE_SRV_IDENTIFIER
#define BE_SRV_IDENTIFIER
Definition: backend.h:36
fo_reset_services
void fo_reset_services(struct fo_ctx *fo_ctx)
Definition: fail_over.c:1694
be_svc_data::run_callbacks
bool run_callbacks
Definition: backend.h:59
be_fo_reset_svc
void be_fo_reset_svc(struct be_ctx *be_ctx, const char *svc_name)
Definition: data_provider_fo.c:761
async_resolv.h
fo_resolve_service_recv
int fo_resolve_service_recv(struct tevent_req *req, TALLOC_CTX *ref_ctx, struct fo_server **server)
Definition: fail_over.c:1226
be_svc_data::last_status_change
time_t last_status_change
Definition: backend.h:58
SSSDBG_TRACE_LIBS
#define SSSDBG_TRACE_LIBS
Definition: debug.h:81
dp_get_options
int dp_get_options(TALLOC_CTX *memctx, struct confdb_ctx *cdb, const char *conf_path, struct dp_option *def_opts, int num_opts, struct dp_option **_opts)
Definition: data_provider_opts.c:83
ctx
struct nss_ops_ctx * ctx
Definition: wbc_pwd_sssd.c:61
DEBUG_IS_SET
#define DEBUG_IS_SET(level)
checks whether level is set in debug_level
Definition: debug.h:137
fo_resolve_service_send
struct tevent_req * fo_resolve_service_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct resolv_ctx *resolv, struct fo_ctx *ctx, struct fo_service *service)
Definition: fail_over.c:1006
SSSDBG_CONF_SETTINGS
#define SSSDBG_CONF_SETTINGS
Definition: debug.h:78
fo_try_next_server
void fo_try_next_server(struct fo_service *service)
Definition: fail_over.c:1559
fo_options::family_order
enum restrict_family family_order
Definition: fail_over.h:84
fo_resolve_srv_dns_ctx::hostname
char * hostname
Definition: fail_over_srv.c:440
be_ctx::be_res
struct be_resolv_ctx * be_res
Definition: backend.h:87
backend.h
be_primary_server_timeout
static void be_primary_server_timeout(struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *pvt)
Definition: data_provider_fo.c:391
fo_get_server_count
int fo_get_server_count(struct fo_service *service)
Definition: fail_over.c:692
fo_context_init
struct fo_ctx * fo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts)
Definition: fail_over.c:143
reset_fo
void reset_fo(struct be_ctx *be_ctx)
Definition: data_provider_fo.c:756
be_resolve_server_done
static void be_resolve_server_done(struct tevent_req *subreq)
Definition: data_provider_fo.c:545
fo_service
Definition: fail_over.c:64
be_failover_ctx::fo_ctx
struct fo_ctx * fo_ctx
Definition: backend.h:66
fo_add_srv_server
int fo_add_srv_server(struct fo_service *service, const char *srv, const char *discovery_domain, const char *sssd_domain, const char *proto, void *user_data)
Definition: fail_over.c:584
be_resolv_ctx::resolv
struct resolv_ctx * resolv
Definition: backend.h:43
fo_srv_lookup_plugin_recv_t
errno_t(* fo_srv_lookup_plugin_recv_t)(TALLOC_CTX *mem_ctx, struct tevent_req *req, char **_dns_domain, uint32_t *_ttl, struct fo_server_info **_primary_servers, size_t *_num_primary_servers, struct fo_server_info **_backup_servers, size_t *_num_backup_servers)
Definition: fail_over_srv.h:65
fo_get_server_port
int fo_get_server_port(struct fo_server *server)
Definition: fail_over.c:1587
fo_new_service
int fo_new_service(struct fo_ctx *ctx, const char *name, datacmp_fn user_data_cmp, struct fo_service **_service)
Definition: fail_over.c:428
NULL_STRING
#define NULL_STRING
Definition: data_provider.h:175
be_fo_find_svc_data
static struct be_svc_data * be_fo_find_svc_data(struct be_ctx *ctx, const char *service_name)
Definition: data_provider_fo.c:112
dp_opt_get_string
#define dp_opt_get_string(o, i)
Definition: data_provider.h:243
resolv_hostent::addr_list
struct resolv_addr ** addr_list
Definition: async_resolv.h:98
talloc_zfree
#define talloc_zfree(ptr)
Definition: util.h:121
SSSDBG_MINOR_FAILURE
#define SSSDBG_MINOR_FAILURE
Definition: debug.h:77
fo_options::retry_timeout
time_t retry_timeout
Definition: fail_over.h:82
be_resolve_server_state::attempts
int attempts
Definition: data_provider_fo.c:363
be_fo_set_srv_lookup_plugin
void be_fo_set_srv_lookup_plugin(struct be_ctx *ctx, fo_srv_lookup_plugin_send_t send_fn, fo_srv_lookup_plugin_recv_t recv_fn, void *pvt, const char *plugin_name)
Definition: data_provider_fo.c:213
BE_FO_PROTO_SENTINEL
@ BE_FO_PROTO_SENTINEL
Definition: backend.h:155
DP_OPT_STRING
@ DP_OPT_STRING
Definition: data_provider.h:182
be_svc_data::first_resolved
struct fo_server * first_resolved
Definition: backend.h:62
SSSDBG_CRIT_FAILURE
#define SSSDBG_CRIT_FAILURE
Definition: debug.h:75
be_svc_callback::svc
struct be_svc_data * svc
Definition: data_provider_fo.c:31
be_failover_ctx
Definition: backend.h:65
fo_reset_servers
void fo_reset_servers(struct fo_service *service)
Definition: fail_over.c:1676
be_svc_data::last_good_srv
char * last_good_srv
Definition: backend.h:56
be_resolve_server_state::ctx
struct be_ctx * ctx
Definition: data_provider_fo.c:360
fo_resolve_srv_dns_recv
errno_t fo_resolve_srv_dns_recv(TALLOC_CTX *mem_ctx, struct tevent_req *req, char **_dns_domain, uint32_t *_ttl, struct fo_server_info **_primary_servers, size_t *_num_primary_servers, struct fo_server_info **_backup_servers, size_t *_num_backup_servers)
Definition: fail_over_srv.c:679
be_svc_callback::prev
struct be_svc_callback * prev
Definition: data_provider_fo.c:28
be_resolve_server_send
struct tevent_req * be_resolve_server_send(TALLOC_CTX *memctx, struct tevent_context *ev, struct be_ctx *ctx, const char *service_name, bool first_try)
Definition: data_provider_fo.c:505
NULL_NUMBER
#define NULL_NUMBER
Definition: data_provider.h:177
be_init_failover
int be_init_failover(struct be_ctx *ctx)
Definition: data_provider_fo.c:56
fo_add_server
int fo_add_server(struct fo_service *service, const char *name, int port, void *user_data, bool primary)
Definition: fail_over.c:844
be_svc_callback_destroy
static int be_svc_callback_destroy(void *memptr)
Definition: data_provider_fo.c:173
TEVENT_REQ_RETURN_ON_ERROR
#define TEVENT_REQ_RETURN_ON_ERROR(req)
Definition: util.h:132
be_ctx
Definition: backend.h:75
NULL
#define NULL
Definition: util.h:67
be_svc_callback::next
struct be_svc_callback * next
Definition: data_provider_fo.c:29
SSSDBG_OP_FAILURE
#define SSSDBG_OP_FAILURE
Definition: debug.h:76
dp_option::opt_name
const char * opt_name
Definition: data_provider.h:202
be_primary_server_ctx::svc
struct be_svc_data * svc
Definition: data_provider_fo.c:373
fo_get_active_server
struct fo_server * fo_get_active_server(struct fo_service *service)
Definition: fail_over.c:1554
be_run_reconnect_cb
void be_run_reconnect_cb(struct be_ctx *be)
Definition: data_provider_callbacks.c:170
FO_PROTO_TCP
#define FO_PROTO_TCP
Definition: fail_over.h:34
be_failover_ctx::be_res
struct be_resolv_ctx * be_res
Definition: backend.h:67
fo_ctx
Definition: fail_over.c:53
be_resolve_server_state
Definition: data_provider_fo.c:358
be_fo_try_next_server
void be_fo_try_next_server(struct be_ctx *ctx, const char *service_name)
Definition: data_provider_fo.c:714
be_ctx::domain
struct sss_domain_info * domain
Definition: backend.h:78
ret
errno_t ret
Definition: sbus_errors.c:31
PORT_NEUTRAL
@ PORT_NEUTRAL
Definition: fail_over.h:43
be_primary_server_ctx::ev
struct tevent_context * ev
Definition: data_provider_fo.c:371
be_resolve_server_state::first_try
bool first_try
Definition: data_provider_fo.c:366
fo_set_srv_lookup_plugin
bool fo_set_srv_lookup_plugin(struct fo_ctx *ctx, fo_srv_lookup_plugin_send_t send_fn, fo_srv_lookup_plugin_recv_t recv_fn, void *pvt)
Definition: fail_over.c:1759
fo_svc_has_server
bool fo_svc_has_server(struct fo_service *service, struct fo_server *server)
Definition: fail_over.c:1706
IPV6_ONLY
@ IPV6_ONLY
Definition: async_resolv.h:80
FO_PROTO_UDP
#define FO_PROTO_UDP
Definition: fail_over.h:35
SSSDBG_BE_FO
#define SSSDBG_BE_FO
Definition: debug.h:84
IPV4_ONLY
@ IPV4_ONLY
Definition: async_resolv.h:78
fo_get_server_name
const char * fo_get_server_name(struct fo_server *server)
Definition: fail_over.c:1593
be_resolve_server_recv
int be_resolve_server_recv(struct tevent_req *req, TALLOC_CTX *ref_ctx, struct fo_server **srv)
Definition: data_provider_fo.c:697