Connection API compatibility break v3.0.0-v3.0.3 and v3.0.4 onwar

Arran Cudbard-Bell a.cudbardb at freeradius.org
Tue Jun 24 12:14:54 CEST 2014


Because of the talloc threadsafety issues we've been experiencing,
the allocations in the connection pool API have had to be modified
so that they're all performed from the NULL context.

Many fr_connection_create callback functions allocated connection 
structs directly from the module's instance ctx.
This was not thread safe and may have caused subtle memory corruption.

The new fr_connection_create_t is passed a TALLOC_CTX allocated from
the NULL ctx.

The module should allocate any handle specific memory under this ctx.

When the connection is destroyed the TALLOC_CTX will be freed. 
Modules which require additional cleanup (such as closing sockets),
should add a destructor to the memory allocated under the 
TALLOC_CTX (not the TALLOC_CTX itself).

The fr_connection_delete_t callback has been removed completely, and
is no longer supported.


fr_connection_create_t
----------------------

/** Create a new connection handle
 *
 * This function will be called whenever the connection pool manager needs
 * to spawn a new connection, and on reconnect.
 *
 * Memory should be talloced in the parent context to hold the module's
 * connection structure. The parent context is allocated in the NULL
 * context, but will be freed when fr_connection_t is freed.
 *
 * There is no delete callback, so operations such as closing sockets and
 * freeing library connection handles should be done by a destructor attached
 * to memory allocated beneath ctx.
 *
 * @note A function pointer matching this prototype must be passed
 * to fr_connection_pool.
 *
 * @param[in,out] ctx to allocate memory in.
 * @param[in] opaque pointer passed to fr_connection_pool_init.
 * @return NULL on error, else a connection handle.
 */
typedef void *(*fr_connection_create_t)(TALLOC_CTX *ctx, void *opaque);

Creating rlm_ldap handles (module specific data)
------------------------------------------------

/** Close and delete a connection
 *
 * Unbinds the LDAP connection, informing the server and freeing any memory.
 *
 * @param conn to destroy.
 * @return always indicates success.
 */
static int _mod_conn_free(ldap_handle_t *conn)
{
	if (conn->handle) ldap_unbind_s(conn->handle);

	return 0;
}

/** Create and return a new connection
 *
 * Create a new ldap connection and allocate memory for a new rlm_handle_t
 *
 * @param ctx to allocate connection handle memory in.
 * @param instance rlm_ldap instance.
 * @return A new connection handle or NULL on error.
 */
void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
{
	...

	ldap_instance_t *inst = instance;
	ldap_handle_t *conn;

	/*
	 *	Allocate memory for the handle.
	 */
	conn = talloc_zero(ctx, ldap_handle_t);
	if (!conn) return NULL;
	talloc_set_destructor(conn, _mod_conn_free);
	...

#ifdef HAVE_LDAP_INITIALIZE
	if (inst->is_url) {
		DEBUG("rlm_ldap (%s): Connecting to %s", inst->xlat_name, inst->server);

		ldap_errno = ldap_initialize(&conn->handle, inst->server);
		if (ldap_errno != LDAP_SUCCESS) {
			LDAP_ERR("ldap_initialize failed: %s", ldap_err2string(ldap_errno));
			goto error;
		}
	} else
#endif
	...
	return conn
}


Freeing rlm_yubikey handles (no module specific data)
-----------------------------------------------------
/** Frees a ykclient handle
 *
 * @param[in] yandle rlm_yubikey_handle_t to close and free.
 * @return returns 0.
 */
static int _mod_conn_free(ykclient_handle_t **yandle)
{
	ykclient_handle_done(yandle);

	return 0;
}

/** Creates a new connection handle for use by the FR connection API.
 *
 * Matches the fr_connection_create_t function prototype, is passed to
 * fr_connection_pool_init, and called when a new connection is required by the
 * connection pool API.
 *
 * @see fr_connection_pool_init
 * @see fr_connection_create_t
 * @see connection.c
 *
 * @param[in] ctx to allocate connection data from.
 * @param[in] instance configuration data.
 * @return connection handle or NULL if the connection failed or couldn't
 *	be initialised.
 */
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance)
{
	rlm_yubikey_t *inst = instance;
	ykclient_rc status;
	ykclient_handle_t *yandle, **marker;

	status = ykclient_handle_init(inst->ykc, &yandle);
	if (status != YKCLIENT_OK) {
		ERROR("rlm_yubikey (%s): %s", inst->name, ykclient_strerror(status));

		return NULL;
	}
	marker = talloc(ctx, ykclient_handle_t *);
	talloc_set_destructor(marker, _mod_conn_free);
	*marker = yandle;

	return yandle;
}


Arran Cudbard-Bell <a.cudbardb at freeradius.org>
FreeRADIUS Development Team

FD31 3077 42EC 7FCD 32FE 5EE2 56CF 27F9 30A8 CAA2

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 881 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <http://lists.freeradius.org/pipermail/freeradius-devel/attachments/20140624/57a3723c/attachment.pgp>


More information about the Freeradius-Devel mailing list