view dcclib/clnt_init.c @ 0:c7f6b056b673

First import of vendor version
author Peter Gervai <grin@grin.hu>
date Tue, 10 Mar 2009 13:49:58 +0100
parents
children
line wrap: on
line source

/* Distributed Checksum Clearinghouse
 *
 * connect to a DCC server for an administrative program
 *
 * Copyright (c) 2008 by Rhyolite Software, LLC
 *
 * This agreement is not applicable to any entity which sells anti-spam
 * solutions to others or provides an anti-spam solution as part of a
 * security solution sold to other entities, or to a private network
 * which employs the DCC or uses data provided by operation of the DCC
 * but does not provide corresponding data to other users.
 *
 * Permission to use, copy, modify, and distribute this software without
 * changes for any purpose with or without fee is hereby granted, provided
 * that the above copyright notice and this permission notice appear in all
 * copies and any distributed versions or copies are either unchanged
 * or not called anything similar to "DCC" or "Distributed Checksum
 * Clearinghouse".
 *
 * Parties not eligible to receive a license under this agreement can
 * obtain a commercial license to use DCC by contacting Rhyolite Software
 * at sales@rhyolite.com.
 *
 * A commercial license would be for Distributed Checksum and Reputation
 * Clearinghouse software.  That software includes additional features.  This
 * free license for Distributed ChecksumClearinghouse Software does not in any
 * way grant permision to use Distributed Checksum and Reputation Clearinghouse
 * software
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND RHYOLITE SOFTWARE, LLC DISCLAIMS ALL
 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL RHYOLITE SOFTWARE, LLC
 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 *
 * Rhyolite Software DCC 1.3.103-1.49 $Revision$
 */

#include "dcc_clnt.h"
#include "dcc_heap_debug.h"


static DCC_CLNT_CTXT *ctxt_free;
static int ctxts_active;


/* this can give the wrong answer if another thread sneaks in and
 * switches servers */
const char *
dcc_srvr_nm(u_char grey)
{
	const DCC_SRVR_CLASS *class;
	SRVR_INX srvr_inx;
	const DCC_SRVR_ADDR *cur_addr;
	NAM_INX nam_inx;

	if (!dcc_clnt_info)
		return "???";
	class = grey ? &dcc_clnt_info->dcc : &dcc_clnt_info->grey;
	srvr_inx = class->srvr_inx;
	if (GOOD_SRVR(class, srvr_inx)) {
		cur_addr = &class->addrs[srvr_inx];
		nam_inx = cur_addr->nam_inx;
		if (GOOD_NAM(nam_inx))
			return class->nms[nam_inx].hostname;
	}
	return grey ? "greylist server" : "DCC server";
}



/* Create a DCC client context
 *	The contexts must be locked */
DCC_CLNT_CTXT *				/* 0=failed */
dcc_alloc_ctxt(void)
{
	DCC_CLNT_CTXT *ctxt;

	assert_ctxts_locked();

	ctxt = ctxt_free;
	if (ctxt) {
		ctxt_free = ctxt->fwd;
	} else {
		ctxt = dcc_malloc(sizeof(*ctxt));
	}
	memset(ctxt, 0, sizeof(*ctxt));
	ctxt->soc = INVALID_SOCKET;
	++ctxts_active;

	return ctxt;
}



/* the contexts must be locked */
void
dcc_rel_ctxt(DCC_CLNT_CTXT *ctxt)
{
	assert_ctxts_locked();

	dcc_clnt_soc_close(ctxt);

	ctxt->fwd = ctxt_free;
	ctxt_free = ctxt;

	if (--ctxts_active < 0)
		abort();
}



/* create a temporary an anonymous map file
 *	The contexts must be locked.
 *	On failure, everything is undone.
 *	On success, the file is initialized and mapped. */
u_char					/* 0=failed; 1=mapped & locked */
dcc_map_tmp_info(DCC_EMSG emsg,		/* cleared of stale messages */
		 const DCC_SRVR_NM *nm,
		 const DCC_IP *src,
		 u_char info_flags)	/* DCC_INFO_FG_* */
{
	DCC_PATH tmp_info_nm;
	int fd;

	assert_ctxts_locked();

	fd = dcc_mkstemp(emsg, tmp_info_nm, sizeof(tmp_info_nm), 0, 0, 0,
			 0, "map", 1, 0);
	if (fd < 0)
		return 0;

	if (!dcc_create_map(emsg, tmp_info_nm, &fd, nm, 1, nm, 1,
			    src, info_flags | DCC_INFO_FG_TMP))
		return 0;

	return dcc_map_info(emsg, tmp_info_nm, fd);
}



/* start to get ready for an operation
 *	on entry, nothing is locked,
 *	on success, the contexts and info are locked
 *	on failure, nothing is locked */
DCC_CLNT_CTXT *				/* 0=failed */
dcc_clnt_start(DCC_EMSG emsg, DCC_CLNT_CTXT *ctxt,
	       const char *new_info_map_nm,
	       DCC_CLNT_FGS clnt_fgs)
{
	if (emsg)
		*emsg = '\0';
	dcc_ctxts_lock();

	if (!ctxt)
		ctxt = dcc_alloc_ctxt();

	if (!dcc_map_info(emsg, new_info_map_nm, -1)) {
		dcc_rel_ctxt(ctxt);
		dcc_ctxts_unlock();
		return 0;
	}

	if (emsg)
		*emsg = '\0';
	if (!dcc_clnt_rdy(emsg, ctxt, clnt_fgs)) {
		if (!(clnt_fgs & DCC_CLNT_FG_BAD_SRVR_OK)) {
			dcc_unmap_close_info(0);
			dcc_rel_ctxt(ctxt);
			dcc_ctxts_unlock();
			return 0;
		}
		if (emsg && dcc_clnt_debug)
			dcc_trace_msg("%s", emsg);

		/* lock the shared information since we are not failing */
		if (!dcc_info_lock(emsg)) {
			dcc_rel_ctxt(ctxt);
			dcc_ctxts_unlock();
			return 0;
		}
	}

	return ctxt;
}



DCC_CLNT_CTXT *				/* 0=failed */
dcc_clnt_start_fin(DCC_EMSG emsg,	/* cleared of stale messages */
		   DCC_CLNT_CTXT *ctxt)
{
	if (!dcc_info_unlock(emsg)) {
		dcc_unmap_close_info(0);
		dcc_rel_ctxt(ctxt);
		dcc_ctxts_unlock();
		return 0;
	}
	dcc_ctxts_unlock();
	return ctxt;
}



/* on success the info file is mapped, but nothing is locked
 * on failure, nothing is mapped or locked */
DCC_CLNT_CTXT *				/* 0=failed */
dcc_clnt_init(DCC_EMSG emsg, DCC_CLNT_CTXT *ctxt,
	      const char *new_info_map_nm,
	      DCC_CLNT_FGS clnt_fgs)
{
	ctxt = dcc_clnt_start(emsg, ctxt, new_info_map_nm, clnt_fgs);
	if (ctxt)
		ctxt = dcc_clnt_start_fin(emsg, ctxt);
	return ctxt;
}



/* start talking to a DCC server using an temporary parameter file */
DCC_CLNT_CTXT *				/* 0=failed, 1=ready */
dcc_tmp_clnt_init(DCC_EMSG emsg, DCC_CLNT_CTXT *ctxt,
		  const DCC_SRVR_NM *new_srvr,
		  const DCC_IP *src,
		  DCC_CLNT_FGS clnt_fgs,
		  u_char info_flags)	/* DCC_INFO_FG_* */
{
	if (emsg)
		*emsg = '\0';

	dcc_ctxts_lock();
	if (!dcc_map_tmp_info(emsg, new_srvr, src, info_flags)) {
		if (ctxt)
			dcc_rel_ctxt(ctxt);
		dcc_ctxts_unlock();
		return 0;
	}
	dcc_ctxts_unlock();

	ctxt = dcc_clnt_init(emsg, ctxt, 0, clnt_fgs | DCC_CLNT_FG_NO_FAIL);
	if (!ctxt) {
		dcc_ctxts_lock();
		dcc_unmap_close_info(0);
		dcc_ctxts_unlock();
	}
	return ctxt;
}