responder_dp.c revision f1bc4e8b9daf04a5cb4b9464021bb9e816eed3ea
/*
Authors:
Simo Sorce <ssorce@redhat.com>
Stephen Gallagher <sgallagh@redhat.com>
Copyright (C) 2009 Red Hat
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <time.h>
#include "responder/common/responder_packet.h"
#include "responder/common/responder.h"
#include "providers/data_provider.h"
#include "sbus/sbus_client.h"
struct sss_dp_req;
struct sss_dp_callback {
struct sss_dp_callback *prev;
struct sss_dp_callback *next;
struct sss_dp_req *sdp_req;
void *callback_ctx;
};
struct sss_dp_req {
struct tevent_context *ev;
char *key;
struct tevent_timer *tev;
struct sss_dp_callback *cb_list;
char *err_msg;
};
static int sss_dp_callback_destructor(void *ptr)
{
return EOK;
}
static int sss_dp_req_destructor(void *ptr)
{
/* Cancel Dbus pending reply if still pending */
if (sdp_req->pending_reply) {
}
/* Destroy the hash entry */
if (hret != HASH_SUCCESS) {
/* This should never happen */
DEBUG(0, ("Could not clear entry from request queue\n"));
}
/* Free any remaining callback */
}
while (cb) {
cb->callback_ctx);
}
return 0;
}
struct tevent_timer *te,
{
/* steal te on NULL because it will be freed as soon as the handler
* returns. Causing a double free if we don't, as te is allocated on
* sdp_req and we are just going to free it */
}
char **err_msg);
struct tevent_timer *te,
{
struct sss_dp_callback *cb;
struct tevent_timer *tev;
/* Remove the callback from the list, the caller may free it, within the
* callback. */
cb->callback_ctx);
/* Call the next callback if needed */
tv = tevent_timeval_current();
if (!te) {
/* Out of memory or other serious error */
goto done;
}
return;
}
/* No more callbacks to invoke. Destroy the request */
done:
/* steal te on NULL because it will be freed as soon as the handler
* returns. Causing a double free if we don't, as te is allocated on
* sdp_req and we are just going to free it */
}
{
int ret;
struct sss_dp_req *sdp_req;
struct sss_dp_callback *cb;
struct tevent_timer *te;
/* prevent trying to cancel a reply that we already received */
}
else {
"Failed to get reply from Data Provider");
}
}
/* Check whether we need to issue any callbacks */
/* No callbacks to invoke. Destroy the hash entry */
return;
}
}
/* Queue up all callbacks */
tv = tevent_timeval_current();
if (!te) {
/* Out of memory or other serious error */
goto error;
}
return;
}
const char *domain,
char *filter,
int timeout,
void *callback_ctx,
struct sss_dp_req **ndp);
bool fast_reply, int type,
{
char *filter;
struct sss_dp_callback *cb;
/* either, or, not both */
return EINVAL;
}
if (!domain) {
return EINVAL;
}
switch (type) {
case SSS_DP_USER:
break;
case SSS_DP_GROUP:
break;
case SSS_DP_INITGROUPS:
break;
default:
return EINVAL;
}
if (fast_reply) {
be_type |= BE_REQ_FAST;
}
if (dp_requests == NULL) {
/* Create a hash table to handle queued update requests */
if (ret != HASH_SUCCESS) {
return EIO;
}
}
if (!tmp_ctx) {
return ENOMEM;
}
if (opt_name) {
} else if (opt_id) {
} else {
}
return ENOMEM;
}
/* Check whether there's already a request in progress */
switch (hret) {
case HASH_SUCCESS:
/* Request already in progress
* Add an additional callback if needed and return
*/
if (callback) {
/* We have a new request asking for a callback */
if (!sdp_req) {
DEBUG(0, ("Could not retrieve DP request context\n"));
goto done;
}
if (!cb) {
goto done;
}
}
break;
case HASH_ERROR_KEY_NOT_FOUND:
/* No such request in progress
* Create a new request
*/
&sdp_req);
goto done;
}
if (hret != HASH_SUCCESS) {
DEBUG(0, ("Could not store request query (%s)\n",
goto done;
}
DEBUG(0, ("Out of Memory!?\n"));
goto done;
}
break;
default:
DEBUG(0,("Could not query request list (%s)\n",
}
done:
return ret;
}
const char *domain,
char *filter,
int timeout,
void *callback_ctx,
struct sss_dp_req **ndp)
{
struct sss_dp_callback *cb;
struct sss_dp_req *sdp_req;
int ret;
/* double check dp_ctx has actually been initialized.
* in some pathological cases it may happen that nss starts up before
* dp connection code is actually able to establish a connection.
*/
" This maybe a bug, it shouldn't happen!\n", domain));
return EIO;
}
/* create the message */
DEBUG(0,("Out of memory?!\n"));
return ENOMEM;
}
if (!dbret) {
return EIO;
}
if (!sdp_req) {
return ENOMEM;
}
sdp_req, &pending_reply);
/*
* Critical Failure
* We can't communicate on this connection
* We'll drop it using the default destructor.
*/
DEBUG(0, ("D-BUS send failed.\n"));
return EIO;
}
if (callback) {
if (!cb) {
return ENOMEM;
}
}
return EOK;
}
char **err_msg)
{
int type;
if (!reply) {
/* reply should never be null. This function shouldn't be called
* until reply is valid or timeout has occurred. If reply is NULL
* here, something is seriously wrong and we should bail out.
*/
DEBUG(0, ("Severe error. A reply callback was called but no reply was received and no timeout occurred\n"));
/* FIXME: Destroy this connection ? */
goto done;
}
switch (type) {
if (!ret) {
/* FIXME: Destroy this connection ? */
goto done;
}
break;
case DBUS_MESSAGE_TYPE_ERROR:
DBUS_ERROR_NO_REPLY) == 0) {
goto done;
}
DEBUG(0,("The Data Provider returned an error [%s]\n",
/* Falling through to default intentionally*/
default:
/*
* Timeout or other error occurred or something
* unexpected happened.
* It doesn't matter which, because either way we
* know that this connection isn't trustworthy.
* We'll destroy it now.
*/
/* FIXME: Destroy this connection ? */
}
done:
return err;
}