Example #1
0
/** @brief API to look for a TCP stream identified by 'tuple5' **/
pntoh_tcp_stream_t ntoh_tcp_find_stream ( pntoh_tcp_session_t session , pntoh_tcp_tuple5_t tuple5 )
{
	ntoh_tcp_key_t		key = 0;
	ntoh_tcp_tuple5_t	tuplerev = {0};
	pntoh_tcp_stream_t	ret = 0;

	if ( !session || !tuple5 )
		return ret;

	key = tcp_getkey( session , tuple5 );

	lock_access( &session->lock );

	if ( ! ( ret = (pntoh_tcp_stream_t) htable_find ( session->streams , key , 0) ) )
	{
		tuplerev.destination = tuple5->source;
		tuplerev.source = tuple5->destination;
		tuplerev.sport = tuple5->dport;
		tuplerev.dport = tuple5->sport;
		tuplerev.protocol = tuple5->protocol;

		key = tcp_getkey( session , &tuplerev );

		ret = (pntoh_tcp_stream_t) htable_find ( session->streams , key , 0);
	}

	unlock_access( &session->lock );

	return ret;
}
Example #2
0
/** @brief Remove the stream from the session streams hash table, and notify the user **/
inline static void delete_stream ( pntoh_tcp_session_t session , pntoh_tcp_stream_t *stream , int reason , int extra )
{
	pntoh_tcp_stream_t item = 0;

	if ( !stream || !(*stream) )
		return;

	item = *stream;

	if ( session->streams != 0 )
	{
	  if ( htable_find ( session->streams, item->key, 0 ) != 0 )
		{
		  htable_remove ( session->streams , item->key, 0);
			sem_post ( &session->max_streams );
		}
	}

	if ( session->timewait != 0 )
	{
	  if ( htable_find ( session->timewait, item->key, 0 ) != 0 )
		{
		  htable_remove ( session->timewait , item->key, 0 );
			sem_post ( &session->max_timewait );
		}
	}

	switch ( extra )
	{
		case NTOH_MAX_SYN_RETRIES_REACHED:
			extra = NTOH_REASON_MAX_SYN_RETRIES_REACHED;
			break;

		case NTOH_MAX_SYNACK_RETRIES_REACHED:
			extra = NTOH_REASON_MAX_SYNACK_RETRIES_REACHED;
			break;

		case NTOH_HANDSHAKE_FAILED:
			extra = NTOH_REASON_HSFAILED;
			break;
	}

	if ( item->client.receive )
		((pntoh_tcp_callback_t)item->function)(item,&item->client, &item->server,0, reason , extra );

    free_lockaccess ( &item->lock );

	free ( item );
	*stream = 0;

	return;
}
Example #3
0
static void smtpd_peer_from_pass_attr(SMTPD_STATE *state)
{
    HTABLE *attr = (HTABLE *) vstream_context(state->client);
    const char *cp;

    /*
     * Extract the client endpoint information from the attribute hash.
     */
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_ADDR)) == 0)
	msg_fatal("missing client address from proxy");
    if (strrchr(cp, ':') != 0) {
	if (valid_ipv6_hostaddr(cp, DO_GRIPE) == 0)
	    msg_fatal("bad IPv6 client address syntax from proxy: %s", cp);
	state->addr = mystrdup(cp);
	state->rfc_addr = concatenate(IPV6_COL, cp, (char *) 0);
	state->addr_family = AF_INET6;
    } else {
	if (valid_ipv4_hostaddr(cp, DO_GRIPE) == 0)
	    msg_fatal("bad IPv4 client address syntax from proxy: %s", cp);
	state->addr = mystrdup(cp);
	state->rfc_addr = mystrdup(cp);
	state->addr_family = AF_INET;
    }
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_CLIENT_PORT)) == 0)
	msg_fatal("missing client port from proxy");
    if (valid_hostport(cp, DO_GRIPE) == 0)
	msg_fatal("bad TCP client port number syntax from proxy: %s", cp);
    state->port = mystrdup(cp);

    /*
     * The Dovecot authentication server needs the server IP address.
     */
    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_ADDR)) == 0)
	msg_fatal("missing server address from proxy");
    if (valid_hostaddr(cp, DO_GRIPE) == 0)
	msg_fatal("bad IPv6 server address syntax from proxy: %s", cp);
    state->dest_addr = mystrdup(cp);

    if ((cp = htable_find(attr, MAIL_ATTR_ACT_SERVER_PORT)) == 0)
	msg_fatal("missing server port from proxy");
    if (valid_hostport(cp, DO_GRIPE) == 0)
	msg_fatal("bad TCP server port number syntax from proxy: %s", cp);
    state->dest_port = mystrdup(cp);

    /*
     * Convert the client address from string to binary form.
     */
    smtpd_peer_hostaddr_to_sockaddr(state);
}
Example #4
0
static void anvil_remote_disconnect(VSTREAM *client_stream, const char *ident)
{
    ANVIL_REMOTE *anvil_remote;
    ANVIL_LOCAL *anvil_local;
    const char *myname = "anvil_remote_disconnect";

    if (msg_verbose)
	msg_info("%s fd=%d stream=0x%lx ident=%s",
		 myname, vstream_fileno(client_stream),
		 (unsigned long) client_stream, ident);

    /*
     * Update local and remote info if this remote connection is listed for
     * this local server.
     */
    if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) != 0
	&& (anvil_remote =
	    (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) != 0
	&& ANVIL_LOCAL_REMOTE_LINKED(anvil_local, anvil_remote)) {
	ANVIL_REMOTE_DROP_ONE(anvil_remote);
	ANVIL_LOCAL_DROP_ONE(anvil_local, anvil_remote);
    }
    if (msg_verbose)
	msg_info("%s: anvil_local 0x%lx",
		 myname, (unsigned long) anvil_local);

    /*
     * Respond to the local server.
     */
    attr_print_plain(client_stream, ATTR_FLAG_NONE,
		     ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
		     ATTR_TYPE_END);
}
Example #5
0
static void anvil_remote_newtls_stat(VSTREAM *client_stream, const char *ident)
{
    ANVIL_REMOTE *anvil_remote;
    int     rate;

    /*
     * Be prepared for "postfix reload" after "connect".
     */
    if ((anvil_remote =
	 (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
	rate = 0;
    }

    /*
     * Do not report stale information.
     */
    else {
	if (anvil_remote->start != 0
	    && anvil_remote->start + var_anvil_time_unit < event_time())
	    ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
	rate = anvil_remote->ntls;
    }

    /*
     * Respond to local server.
     */
    attr_print_plain(client_stream, ATTR_FLAG_NONE,
		     ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
		     ATTR_TYPE_INT, ANVIL_ATTR_RATE, rate,
		     ATTR_TYPE_END);
}
Example #6
0
static void anvil_remote_newtls(VSTREAM *client_stream, const char *ident)
{
    ANVIL_REMOTE *anvil_remote;

    /*
     * Be prepared for "postfix reload" after "connect".
     */
    if ((anvil_remote =
	 (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0)
	anvil_remote = anvil_remote_conn_update(client_stream, ident);

    /*
     * Update newtls rate and respond to local server.
     */
    ANVIL_REMOTE_INCR_NTLS(anvil_remote);
    attr_print_plain(client_stream, ATTR_FLAG_NONE,
		     ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
		     ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->ntls,
		     ATTR_TYPE_END);

    /*
     * Update peak statistics.
     */
    if (anvil_remote->ntls > max_ntls_rate.value)
	ANVIL_MAX_UPDATE(max_ntls_rate, anvil_remote->ntls, anvil_remote->ident);
}
Example #7
0
DICT   *dict_open3(const char *dict_type, const char *dict_name,
		           int open_flags, int dict_flags)
{
    const char *myname = "dict_open";
    DICT_OPEN_INFO *dp;
    DICT   *dict;

    if (*dict_type == 0 || *dict_name == 0)
	msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"",
		  dict_type, dict_name);
    if (dict_open_hash == 0)
	dict_open_init();
    if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
	return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
			     "unsupported dictionary type: %s", dict_type));
    if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
	return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
			    "cannot open %s:%s: %m", dict_type, dict_name));
    if (msg_verbose)
	msg_info("%s: %s:%s", myname, dict_type, dict_name);
    /* XXX the choice between wait-for-lock or no-wait is hard-coded. */
    if (dict_flags & DICT_FLAG_OPEN_LOCK) {
	if (dict_flags & DICT_FLAG_LOCK)
	    msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
		      myname, dict_type, dict_name);
	if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
	    msg_fatal("%s:%s: unable to get exclusive lock: %m",
		      dict_type, dict_name);
    }
    return (dict);
}
int     psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name,
			           int dnsbl_index)
{
    const char *myname = "psc_dnsbl_retrieve";
    PSC_DNSBL_SCORE *score;
    int     result_score;

    /*
     * Sanity check.
     */
    if ((score = (PSC_DNSBL_SCORE *)
	 htable_find(dnsbl_score_cache, client_addr)) == 0)
	msg_panic("%s: no blocklist score for %s", myname, client_addr);

    /*
     * Disable callbacks.
     */
    PSC_CALL_BACK_CANCEL(score, dnsbl_index);

    /*
     * Reads are destructive.
     */
    result_score = score->total;
    *dnsbl_name = score->dnsbl_name;
    score->refcount -= 1;
    if (score->refcount < 1) {
	if (msg_verbose > 1)
	    msg_info("%s: delete blocklist score for %s", myname, client_addr);
	htable_delete(dnsbl_score_cache, client_addr, myfree);
    }
    return (result_score);
}
Example #9
0
static void show_parameters(int mode, char **names)
{
    HTABLE_INFO **list;
    HTABLE_INFO **ht;
    char  **namep;
    char   *value;

    /*
     * Show all parameters.
     */
    if (*names == 0) {
	list = htable_list(param_table);
	qsort((char *) list, param_table->used, sizeof(*list), comp_names);
	for (ht = list; *ht; ht++)
	    print_parameter(mode, ht[0]->value);
	myfree((char *) list);
	return;
    }

    /*
     * Show named parameters.
     */
    for (namep = names; *namep; namep++) {
	if ((value = htable_find(param_table, *namep)) == 0) {
	    msg_warn("%s: unknown parameter", *namep);
	} else {
	    print_parameter(mode, value);
	}
    }
}
Example #10
0
static void
run_test(HTable* htable)
{
	int i, j;

	/* fill table */
	for(i = 1; i <= N; i++)
	{
		for(j = 1; j <= N; j++)
		{
			bool isNewNode;
			ExpressionTableNodeData new_node_data;
			sprintf(new_node_data.expression, "%d + %d", i, j);
			new_node_data.value = (i + j);
			htable_insert(htable, (HTableNode*)&new_node_data, &isNewNode);
			assert(isNewNode);
		}
	}

	assert(htable_nitems(htable) == (N*N));

	/* check hash table is filled right */
	for(i = 1; i <= N; i++)
	{
		for(j = 1; j <= N; j++)
		{
			ExpressionTableNode found_node;
			ExpressionTableNodeData query;
			sprintf(query.expression, "%d + %d", i, j);
			found_node = (ExpressionTableNode)htable_find(htable, (HTableNode*)&query);
			assert(found_node != NULL);
			assert(found_node->value == (i + j));
		}
	}

	/* try to delete a non-existing node */
	{
		bool result;
		ExpressionTableNodeData query;
		sprintf(query.expression, "ololo trololo");
		result = htable_delete(htable, (HTableNode*)&query);
		assert(result == false);
	}

	/* clean table */
	for(i = 1; i <= N; i++)
	{
		for(j = 1; j <= N; j++)
		{
			bool result;
			ExpressionTableNodeData query;
			sprintf(query.expression, "%d + %d", i, j);
			result = htable_delete(htable, (HTableNode*)&query);
			assert(result == true);
		}
	}

	assert(htable_nitems(htable) == 0);
}
Example #11
0
int     forward_append(DELIVER_ATTR attr)
{
    FORWARD_INFO *info;
    HTABLE *table_snd;

    /*
     * Sanity checks.
     */
    if (msg_verbose)
	msg_info("forward delivered=%s sender=%s recip=%s",
		 attr.delivered, attr.sender, attr.rcpt.address);
    if (forward_dt == 0)
	msg_panic("forward_append: missing forward_init call");

    /*
     * In order to find the recipient list, first index a table by
     * delivered-to header address, then by envelope sender address.
     */
    if ((table_snd = (HTABLE *) htable_find(forward_dt, attr.delivered)) == 0) {
	table_snd = htable_create(0);
	htable_enter(forward_dt, attr.delivered, (void *) table_snd);
    }
    if ((info = (FORWARD_INFO *) htable_find(table_snd, attr.sender)) == 0) {
	if ((info = forward_open(attr.request, attr.sender)) == 0)
	    return (-1);
	htable_enter(table_snd, attr.sender, (void *) info);
    }

    /*
     * Append the recipient to the message envelope. Don't send the original
     * recipient or notification mask if it was reset due to mailing list
     * expansion.
     */
    if (*attr.rcpt.dsn_orcpt)
	rec_fprintf(info->cleanup, REC_TYPE_ATTR, "%s=%s",
		    MAIL_ATTR_DSN_ORCPT, attr.rcpt.dsn_orcpt);
    if (attr.rcpt.dsn_notify)
	rec_fprintf(info->cleanup, REC_TYPE_ATTR, "%s=%d",
		    MAIL_ATTR_DSN_NOTIFY, attr.rcpt.dsn_notify);
    if (*attr.rcpt.orig_addr)
	rec_fputs(info->cleanup, REC_TYPE_ORCP, attr.rcpt.orig_addr);
    rec_fputs(info->cleanup, REC_TYPE_RCPT, attr.rcpt.address);

    return (vstream_ferror(info->cleanup));
}
Example #12
0
DICT   *dict_open3(const char *dict_type, const char *dict_name,
		           int open_flags, int dict_flags)
{
    const char *myname = "dict_open";
    DICT_OPEN_INFO *dp;
    DICT_OPEN_FN open_fn;
    DICT   *dict;

    if (*dict_type == 0 || *dict_name == 0)
	msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"",
		  dict_type, dict_name);
    if (dict_open_hash == 0)
	dict_open_init();
    if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) {
	if (dict_open_extend_hook != 0
	    && (open_fn = dict_open_extend_hook(dict_type)) != 0) {
	    dict_open_register(dict_type, open_fn);
	    dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type);
	}
	if (dp == 0)
	    return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
			     "unsupported dictionary type: %s", dict_type));
    }
    if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
	return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
			    "cannot open %s:%s: %m", dict_type, dict_name));
    if (msg_verbose)
	msg_info("%s: %s:%s", myname, dict_type, dict_name);
    /* XXX The choice between wait-for-lock or no-wait is hard-coded. */
    if (dict->flags & DICT_FLAG_OPEN_LOCK) {
	if (dict->flags & DICT_FLAG_LOCK)
	    msg_panic("%s: attempt to open %s:%s with both \"open\" lock and \"access\" lock",
		      myname, dict_type, dict_name);
	/* Multi-writer safe map: downgrade persistent lock to temporary. */
	if (dict->flags & DICT_FLAG_MULTI_WRITER) {
	    dict->flags &= ~DICT_FLAG_OPEN_LOCK;
	    dict->flags |= DICT_FLAG_LOCK;
	}
	/* Multi-writer unsafe map: acquire exclusive lock or bust. */
	else if (dict->lock(dict, MYFLOCK_OP_EXCLUSIVE | MYFLOCK_OP_NOWAIT) < 0)
	    msg_fatal("%s:%s: unable to get exclusive lock: %m",
		      dict_type, dict_name);
    }
    return (dict);
}
Example #13
0
QMGR_TRANSPORT *qmgr_transport_create(const char *name)
{
    QMGR_TRANSPORT *transport;

    if (htable_find(qmgr_transport_byname, name) != 0)
	msg_panic("qmgr_transport_create: transport exists: %s", name);
    transport = (QMGR_TRANSPORT *) mymalloc(sizeof(QMGR_TRANSPORT));
    transport->flags = 0;
    transport->pending = 0;
    transport->name = mystrdup(name);

    /*
     * Use global configuration settings or transport-specific settings.
     */
    transport->dest_concurrency_limit =
	get_mail_conf_int2(name, _DEST_CON_LIMIT,
			   var_dest_con_limit, 0, 0);
    transport->recipient_limit =
	get_mail_conf_int2(name, _DEST_RCPT_LIMIT,
			   var_dest_rcpt_limit, 0, 0);
    transport->init_dest_concurrency =
	get_mail_conf_int2(name, _INIT_DEST_CON,
			   var_init_dest_concurrency, 1, 0);
    transport->xport_rate_delay = get_mail_conf_time2(name, _XPORT_RATE_DELAY,
						      var_xport_rate_delay,
						      's', 0, 0);
    transport->rate_delay = get_mail_conf_time2(name, _DEST_RATE_DELAY,
						var_dest_rate_delay,
						's', 0, 0);

    if (transport->rate_delay > 0)
	transport->dest_concurrency_limit = 1;
    if (transport->dest_concurrency_limit != 0
    && transport->dest_concurrency_limit < transport->init_dest_concurrency)
	transport->init_dest_concurrency = transport->dest_concurrency_limit;

    transport->queue_byname = htable_create(0);
    QMGR_LIST_INIT(transport->queue_list);
    transport->dsn = 0;
    qmgr_feedback_init(&transport->pos_feedback, name, _CONC_POS_FDBACK,
		       VAR_CONC_POS_FDBACK, var_conc_pos_feedback);
    qmgr_feedback_init(&transport->neg_feedback, name, _CONC_NEG_FDBACK,
		       VAR_CONC_NEG_FDBACK, var_conc_neg_feedback);
    transport->fail_cohort_limit =
	get_mail_conf_int2(name, _CONC_COHORT_LIM,
			   var_conc_cohort_limit, 0, 0);
    if (qmgr_transport_byname == 0)
	qmgr_transport_byname = htable_create(10);
    htable_enter(qmgr_transport_byname, name, (void *) transport);
    QMGR_LIST_APPEND(qmgr_transport_list, transport);
    if (msg_verbose)
	msg_info("qmgr_transport_create: %s concurrency %d recipients %d",
		 transport->name, transport->dest_concurrency_limit,
		 transport->recipient_limit);
    return (transport);
}
Example #14
0
DICT   *dict_open3(const char *dict_type, const char *dict_name,
		           int open_flags, int dict_flags)
{
    const char *myname = "dict_open";
    DICT_OPEN_INFO *dp;
    DICT   *dict;

    if (*dict_type == 0 || *dict_name == 0)
	msg_fatal("open dictionary: expecting \"type:name\" form instead of \"%s:%s\"",
		  dict_type, dict_name);
    if (dict_open_hash == 0)
	dict_open_init();
    if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0) {
#ifdef NO_DYNAMIC_MAPS
	msg_fatal("%s: unsupported dictionary type: %s", myname, dict_type);
#else
	struct stat st;
	LIB_FN fn[2];
	DICT *(*open) (const char *, int, int);
	DLINFO *dl=dict_open_dlfind(dict_type);
	if (!dl)
	    msg_fatal("%s: unsupported dictionary type: %s:  Is the postfix-%s package installed?", myname, dict_type, dict_type);
	if (stat(dl->soname,&st) < 0) {
	    msg_fatal("%s: unsupported dictionary type: %s (%s not found.  Is the postfix-%s package installed?)",
		myname, dict_type, dl->soname, dict_type);
	}
	fn[0].name = dl->openfunc;
	fn[0].ptr  = (void**)&open;
	fn[1].name = NULL;
	load_library_symbols(dl->soname, fn, NULL);
	dict_open_register(dict_type, open);
	dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type);
#endif
    }
    if (msg_verbose>1) {
	msg_info("%s: calling %s open routine",myname,dict_type);
    }
    if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
	msg_fatal("opening %s:%s %m", dict_type, dict_name);
    if (msg_verbose)
	msg_info("%s: %s:%s", myname, dict_type, dict_name);
    return (dict);
}
Example #15
0
//First ensure the search name, if it has a cname, search the cname
//If we find it in fwd table, return the ip length, it's > 0
//Here we dont care the cname in fwd table, if somebody want to do this
//Add the main domain in fwd table
int pre_find(struct qoutinfo *qo,struct htable *fwd,struct htable *ht,uchar *ip)
{
 uchar td[512] = {0},*itor = NULL;
 int xlen = 0,dbg = 100;
 uchar buffer[2000] = {0};
 struct mvalue *mv = NULL;
 qo->qname = Q_DOMAIN; //default
 if(qo->hascname == 1)
	{
	 qo->qing = qo->qbuffer; //latest cname
	 memcpy(td + 1,qo->qbuffer,strlen(qo->qbuffer) + 1);
	}
 else
	{
	 memcpy(td,qo->td,qo->dlen + 1);
	 qo->qing = qo->td + 1;
	}
 td[0] = A; //forward ip
 xlen = htable_find(fwd,td,ip,1900,NULL); //100 for struct mvalue
 if(xlen > 0)
	{
	 ip = ip + xlen;
	 mv = (struct mvalue*)ip;
	 mv->num = 0; //tail 0
	 mv->ttl = 0;
	 mv->hits = 0;
	 mv->len = 0;
	 return xlen;
	}
 if(qo->td[0] == CNAME) //query cname
	return 0; //find nothing
 td[0] = CNAME;
 itor = buffer;
 while(1) //find cname
	{
	 xlen = find_record_with_ttl(ht,td,itor,2000,NULL);
	 if(xlen > 0)
		{//if domain has a cname, put it in qo->qbuffer
		 qo->qname = Q_CNAME;
		 qo->hascname = 1;
		 mv = (struct mvalue*)itor;
		 itor = itor + sizeof(struct mvalue);
		 memcpy(td + 1,itor,mv->len);
		 if(mv->len > (QBUFFER_SIZE - 1))
			return -1;
		 memcpy(qo->qbuffer,itor,mv->len);
		 qo->qing = qo->qbuffer;
		}
	 else
		break;
	 if((dbg --) == 0)
		 return -1;
	}
 return 0;
}
Example #16
0
static QMGR_JOB *qmgr_job_find(QMGR_MESSAGE *message, QMGR_TRANSPORT *transport)
{

    /*
     * Instead of traversing the message job list, we use single per
     * transport hash table. This is better (at least with respect to memory
     * usage) than having single hash table (usually almost empty) for each
     * message.
     */
    return ((QMGR_JOB *) htable_find(transport->job_byname, message->queue_id));
}
Example #17
0
static const char *dict_ht_lookup(DICT *dict, const char *name)
{
    DICT_HT *dict_ht = (DICT_HT *) dict;

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_FIX) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(10);
	vstring_strcpy(dict->fold_buf, name);
	name = lowercase(vstring_str(dict->fold_buf));
    }
    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, htable_find(dict_ht->table, name));
}
Example #18
0
void    dict_open_register(const char *type, DICT_OPEN_FN open)
{
    const char *myname = "dict_open_register";
    DICT_OPEN_INFO *dp;
    HTABLE_INFO *ht;

    if (dict_open_hash == 0)
	dict_open_init();
    if (htable_find(dict_open_hash, type))
	msg_panic("%s: dictionary type exists: %s", myname, type);
    dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp));
    dp->open = open;
    ht = htable_enter(dict_open_hash, type, (char *) dp);
    dp->type = ht->key;
}
Example #19
0
void    dict_open_register(const char *type,
			           DICT *(*open) (const char *, int, int))
{
    const char *myname = "dict_open_register";
    DICT_OPEN_INFO *dp;

    if (dict_open_hash == 0)
	dict_open_init();
    if (htable_find(dict_open_hash, type))
	msg_panic("%s: dictionary type exists: %s", myname, type);
    dp = (DICT_OPEN_INFO *) mymalloc(sizeof(*dp));
    dp->type = mystrdup(type);
    dp->open = open;
    htable_enter(dict_open_hash, dp->type, (char *) dp);
}
Example #20
0
void    mkmap_open_register(const char *type, MKMAP_OPEN_FN open_fn)
{
    static const char myname[] = "mkmap_open_register";
    MKMAP_OPEN_INFO *mp;
    HTABLE_INFO *ht;

    if (mkmap_open_hash == 0)
	mkmap_open_init();
    if (htable_find(mkmap_open_hash, type))
	msg_panic("%s: database type exists: %s", myname, type);
    mp = (MKMAP_OPEN_INFO *) mymalloc(sizeof(*mp));
    mp->before_open = open_fn;
    ht = htable_enter(mkmap_open_hash, type, (char *) mp);
    mp->type = ht->key;
}
Example #21
0
int     tls_mgr_lookup(const char *unused_type, const char *key, VSTRING *buf)
{
    VSTRING *s;

    if (tls_cache == 0)
	return TLS_MGR_STAT_ERR;

    if ((s = (VSTRING *) htable_find(tls_cache, key)) == 0)
	return TLS_MGR_STAT_ERR;

    vstring_memcpy(buf, vstring_str(s), VSTRING_LEN(s));

    ++cache_hits;
    return (TLS_MGR_STAT_OK);
}
Example #22
0
static ANVIL_REMOTE *anvil_remote_conn_update(VSTREAM *client_stream, const char *ident)
{
    ANVIL_REMOTE *anvil_remote;
    ANVIL_LOCAL *anvil_local;
    const char *myname = "anvil_remote_conn_update";

    if (msg_verbose)
	msg_info("%s fd=%d stream=0x%lx ident=%s",
		 myname, vstream_fileno(client_stream),
		 (unsigned long) client_stream, ident);

    /*
     * Look up remote connection count information. Update remote connection
     * rate information. Simply reset the counter every var_anvil_time_unit
     * seconds. This is easier than maintaining a moving average and it gives
     * a quicker response to tresspassers.
     */
    if ((anvil_remote =
	 (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
	anvil_remote = (ANVIL_REMOTE *) mymalloc(sizeof(*anvil_remote));
	ANVIL_REMOTE_FIRST_CONN(anvil_remote, ident);
	htable_enter(anvil_remote_map, ident, (char *) anvil_remote);
	if (max_cache_size < anvil_remote_map->used) {
	    max_cache_size = anvil_remote_map->used;
	    max_cache_time = event_time();
	}
    } else {
	ANVIL_REMOTE_NEXT_CONN(anvil_remote);
    }

    /*
     * Record this connection under the local server information, so that we
     * can clean up all its connection state when the local server goes away.
     */
    if ((anvil_local = (ANVIL_LOCAL *) vstream_context(client_stream)) == 0) {
	anvil_local = (ANVIL_LOCAL *) mymalloc(sizeof(*anvil_local));
	ANVIL_LOCAL_INIT(anvil_local);
	vstream_control(client_stream,
			VSTREAM_CTL_CONTEXT, (void *) anvil_local,
			VSTREAM_CTL_END);
    }
    ANVIL_LOCAL_ADD_ONE(anvil_local, anvil_remote);
    if (msg_verbose)
	msg_info("%s: anvil_local 0x%lx",
		 myname, (unsigned long) anvil_local);

    return (anvil_remote);
}
Example #23
0
int     mypwnam_err(const char *name, struct mypasswd ** result)
{
    struct passwd *pwd;
    struct mypasswd *mypwd;

    /*
     * See if this is the same user as last time.
     */
    if (last_pwd != 0) {
	if (strcmp(last_pwd->pw_name, name) != 0) {
	    mypwfree(last_pwd);
	    last_pwd = 0;
	} else {
	    *result = mypwd = last_pwd;
	    mypwd->refcount++;
	    return (0);
	}
    }

    /*
     * Find the info in the cache or in the password database.
     */
    if ((mypwd = (struct mypasswd *) htable_find(mypwcache_name, name)) == 0) {
#ifdef HAVE_POSIX_GETPW_R
	char    pwstore[GETPW_R_BUFSIZ];
	struct passwd pwbuf;
	int     err;

	err = getpwnam_r(name, &pwbuf, pwstore, sizeof(pwstore), &pwd);
	if (err != 0)
	    return (err);
	if (pwd == 0) {
	    *result = 0;
	    return (0);
	}
#else
	if ((pwd = getpwnam(name)) == 0) {
	    *result = 0;
	    return (0);
	}
#endif
	mypwd = mypwenter(pwd);
    }
    *result = last_pwd = mypwd;
    mypwd->refcount += 2;
    return (0);
}
Example #24
0
int
find_record_with_ttl(struct htable *ht, uchar * key, int klen, int type, uchar *val, int vlen,
                     struct mvalue *md, hashval_t *hash)
{
    int idx, ret;
    uchar *oval;
    idx = get_pre_mem_hash(key, klen, hash);
    ret = htable_find(ht + idx, key, klen, type, val, vlen, md, hash);
    if (ret > 0) {
        if (ttl_expired(val) == 1) {
            oval = htable_delete(ht + idx, key, klen, type, *hash);
            if (oval != NULL)
                free(oval);
        } else {
            return ret;
        }
    }
    return -1;
}
Example #25
0
int     psc_dnsbl_retrieve(const char *client_addr, const char **dnsbl_name,
			           int dnsbl_index, int *dnsbl_ttl)
{
    const char *myname = "psc_dnsbl_retrieve";
    PSC_DNSBL_SCORE *score;
    int     result_score;
    int     result_ttl;

    /*
     * Sanity check.
     */
    if ((score = (PSC_DNSBL_SCORE *)
	 htable_find(dnsbl_score_cache, client_addr)) == 0)
	msg_panic("%s: no blocklist score for %s", myname, client_addr);

    /*
     * Disable callbacks.
     */
    PSC_CALL_BACK_CANCEL(score, dnsbl_index);

    /*
     * Reads are destructive.
     */
    result_score = score->total;
    *dnsbl_name = score->dnsbl_name;
    result_ttl = (result_score > 0) ? score->fail_ttl : score->pass_ttl;
    /* As with dnsblog(8), a value < 0 means no reply TTL. */
    if (result_ttl < var_psc_dnsbl_min_ttl)
	result_ttl = var_psc_dnsbl_min_ttl;
    if (result_ttl > var_psc_dnsbl_max_ttl)
	result_ttl = var_psc_dnsbl_max_ttl;
    *dnsbl_ttl = result_ttl;
    if (msg_verbose)
	msg_info("%s: addr=%s score=%d ttl=%d",
		 myname, client_addr, result_score, result_ttl);
    score->refcount -= 1;
    if (score->refcount < 1) {
	if (msg_verbose > 1)
	    msg_info("%s: delete blocklist score for %s", myname, client_addr);
	htable_delete(dnsbl_score_cache, client_addr, myfree);
    }
    return (result_score);
}
Example #26
0
static void anvil_remote_lookup(VSTREAM *client_stream, const char *ident)
{
    ANVIL_REMOTE *anvil_remote;
    const char *myname = "anvil_remote_lookup";

    if (msg_verbose)
	msg_info("%s fd=%d stream=0x%lx ident=%s",
		 myname, vstream_fileno(client_stream),
		 (unsigned long) client_stream, ident);

    /*
     * Look up remote client information.
     */
    if ((anvil_remote =
	 (ANVIL_REMOTE *) htable_find(anvil_remote_map, ident)) == 0) {
	attr_print_plain(client_stream, ATTR_FLAG_NONE,
			 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
			 ATTR_TYPE_INT, ANVIL_ATTR_COUNT, 0,
			 ATTR_TYPE_INT, ANVIL_ATTR_RATE, 0,
			 ATTR_TYPE_INT, ANVIL_ATTR_MAIL, 0,
			 ATTR_TYPE_INT, ANVIL_ATTR_RCPT, 0,
			 ATTR_TYPE_INT, ANVIL_ATTR_NTLS, 0,
			 ATTR_TYPE_END);
    } else {

	/*
	 * Do not report stale information.
	 */
	if (anvil_remote->start != 0
	    && anvil_remote->start + var_anvil_time_unit < event_time())
	    ANVIL_REMOTE_RSET_RATE(anvil_remote, 0);
	attr_print_plain(client_stream, ATTR_FLAG_NONE,
			 ATTR_TYPE_INT, ANVIL_ATTR_STATUS, ANVIL_STAT_OK,
		       ATTR_TYPE_INT, ANVIL_ATTR_COUNT, anvil_remote->count,
			 ATTR_TYPE_INT, ANVIL_ATTR_RATE, anvil_remote->rate,
			 ATTR_TYPE_INT, ANVIL_ATTR_MAIL, anvil_remote->mail,
			 ATTR_TYPE_INT, ANVIL_ATTR_RCPT, anvil_remote->rcpt,
			 ATTR_TYPE_INT, ANVIL_ATTR_NTLS, anvil_remote->ntls,
			 ATTR_TYPE_END);
    }
}
Example #27
0
static const char *dict_thash_lookup(DICT *dict, const char *name)
{
    DICT_THASH *dict_thash = (DICT_THASH *) dict;
    const char *result = 0;

    /*
     * Optionally fold the key.
     */
    if (dict->flags & DICT_FLAG_FOLD_FIX) {
	if (dict->fold_buf == 0)
	    dict->fold_buf = vstring_alloc(10);
	vstring_strcpy(dict->fold_buf, name);
	name = lowercase(vstring_str(dict->fold_buf));
    }

    /*
     * Look up the value.
     */
    result = htable_find(dict_thash->table, name);

    DICT_ERR_VAL_RETURN(dict, DICT_ERR_NONE, result);
}
Example #28
0
const HEADER_OPTS *header_opts_find(const char *string)
{
    const char *cp;

    if (header_hash == 0)
	header_opts_init();

    /*
     * Look up the lower-cased version of the header name.
     */
    VSTRING_RESET(header_key);
    for (cp = string; *cp != ':'; cp++) {
	if (*cp == 0)
	    msg_panic("header_opts_find: no colon in header: %.30s", string);
	VSTRING_ADDCH(header_key, TOLOWER(*cp));
    }
    vstring_truncate(header_key,
		     trimblanks(vstring_str(header_key), cp - string)
		     - vstring_str(header_key));
    VSTRING_TERMINATE(header_key);
    return ((const HEADER_OPTS *) htable_find(header_hash, vstring_str(header_key)));
}
Example #29
0
QMGR_QUEUE *qmgr_queue_find(QMGR_TRANSPORT *transport, const char *name)
{
    return ((QMGR_QUEUE *) htable_find(transport->queue_byname, name));
}
Example #30
0
MKMAP  *mkmap_open(const char *type, const char *path,
		           int open_flags, int dict_flags)
{
    MKMAP  *mkmap;
    const MKMAP_OPEN_INFO *mp;
    MKMAP_OPEN_FN open_fn;

    /*
     * Find out what map type to use.
     */
    if (mkmap_open_hash == 0)
	mkmap_open_init();
    if ((mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type)) == 0) {
	if (mkmap_open_extend_hook != 0 &&
	    (open_fn = mkmap_open_extend_hook(type)) != 0) {
	    mkmap_open_register(type, open_fn);
	    mp = (MKMAP_OPEN_INFO *) htable_find(mkmap_open_hash, type);
	}
	if (mp == 0)
	    msg_fatal("unsupported map type for this operation: %s", type);
    }
    if (msg_verbose)
	msg_info("open %s %s", type, path);

    /*
     * Do whatever before-open initialization is needed, such as acquiring a
     * global exclusive lock on an existing database file. Individual Postfix
     * dict modules implement locking only for individual record operations,
     * because most Postfix applications don't need global exclusive locks.
     */
    mkmap = mp->before_open(path);

    /*
     * Delay signal delivery, so that we won't leave the database in an
     * inconsistent state if we can avoid it.
     */
    sigdelay();

    /*
     * Truncate the database upon open, and update it. Read-write mode is
     * needed because the underlying routines read as well as write. We
     * explicitly clobber lock_fd to trigger a fatal error when a map wants
     * to unlock the database after individual transactions: that would
     * result in race condition problems. We clobbber stat_fd as well,
     * because that, too, is used only for individual-transaction clients.
     */
    mkmap->dict = mkmap->open(path, open_flags, dict_flags);
    mkmap->dict->lock_fd = -1;			/* XXX just in case */
    mkmap->dict->stat_fd = -1;			/* XXX just in case */
    mkmap->dict->flags |= DICT_FLAG_DUP_WARN;
    mkmap->multi_writer = (mkmap->dict->flags & DICT_FLAG_MULTI_WRITER);

    /*
     * Do whatever post-open initialization is needed, such as acquiring a
     * global exclusive lock on a database file that did not exist.
     * Individual Postfix dict modules implement locking only for individual
     * record operations, because most Postfix applications don't need global
     * exclusive locks.
     */
    if (mkmap->after_open)
	mkmap->after_open(mkmap);

    /*
     * Resume signal delivery if multi-writer safe.
     */
    if (mkmap->multi_writer)
	sigresume();

    return (mkmap);
}