Files
bongo/src/agents/queue/conf.c
T
2026-07-16 14:26:58 +02:00

269 lines
9.9 KiB
C

/****************************************************************************
* <Novell-copyright>
* Copyright (c) 2001 Novell, Inc. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
* 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, contact Novell, Inc.
*
* To contact Novell about this file by physical or electronic mail, you
* may find current contact information at www.novell.com.
* </Novell-copyright>
* (C) 2007 Patrick Felt
****************************************************************************/
#include <config.h>
#include "queued.h"
#include "conf.h"
#include "queue.h"
#include <xpl.h>
#include <memmgr.h>
#include <logger.h>
#include <bongoutil.h>
#include <nmap.h>
#include <nmlib.h>
#include <msgapi.h>
#include <connio.h>
#include "domain.h"
#include "messages.h"
#define STACKSPACE_Q (1024*80)
#define STACKSPACE_S (1024*80)
#define DEFAULT_MAX_LINGER (4 * 24 * 60 * 60)
#define QLIMIT_CONCURRENT 250
#define QLIMIT_SEQUENTIAL 500
int aliasCmpFunc (const void *lft, const void *rgt);
QueueConfiguration Conf = {0};
long
CalculateCheckQueueLimit(unsigned long concurrent, unsigned long sequential)
{
if (concurrent < sequential) {
return(sequential - ((sequential - concurrent) >> 1));
}
return(sequential);
}
int hostedSortFunc(const void *str1, const void *str2) {
int i = strcasecmp(*(char **)str1, *(char **)str2);
return i;
}
static BongoConfigItem trustedHostsConfig[] = {
{ BONGO_JSON_STRING, NULL, &Conf.trustedHosts},
{ BONGO_JSON_NULL, NULL, NULL }
};
static BongoConfigItem domainsConfig[] = {
{ BONGO_JSON_STRING, NULL, &Conf.domains},
{ BONGO_JSON_NULL, NULL, NULL }
};
static BongoConfigItem QueueConfig[] = {
{ BONGO_JSON_BOOL, "o:debug/b", &Conf.debug },
{ BONGO_JSON_ARRAY, "o:domains/a", &domainsConfig },
{ BONGO_JSON_BOOL, "o:limitremoteprocessing/b", &Conf.deferEnabled },
{ BONGO_JSON_INT, "o:limitremotebegweekday/i", &Conf.i_deferStartWD },
{ BONGO_JSON_INT, "o:limitremotebegweekend/i", &Conf.i_deferStartWE },
{ BONGO_JSON_INT, "o:limitremoteendweekday/i", &Conf.i_deferEndWD },
{ BONGO_JSON_INT, "o:limitremoteendweekend/i", &Conf.i_deferEndWE },
{ BONGO_JSON_INT, "o:queuetuning_concurrent/i", &Conf.maxConcurrentWorkers },
{ BONGO_JSON_INT, "o:queuetuning_sequential/i", &Conf.maxSequentialWorkers },
{ BONGO_JSON_INT, "o:queuetuning_load_high/i", &Conf.loadMonitorHigh },
{ BONGO_JSON_INT, "o:queuetuning_load_low/i", &Conf.loadMonitorLow },
{ BONGO_JSON_INT, "o:queuetuning_trigger/i", &Conf.limitTrigger },
{ BONGO_JSON_INT, "o:queuetimeout/i", &Conf.maxLinger },
{ BONGO_JSON_STRING, "o:quotamessage/s", &Conf.quotaMessage },
{ BONGO_JSON_INT, "o:port/i", &Agent.agent.port },
{ BONGO_JSON_BOOL, "o:forwardundeliverable_enabled/b", &Conf.forwardUndeliverableEnabled },
{ BONGO_JSON_STRING, "o:forwardundeliverable_to/s", &Conf.forwardUndeliverableAddress },
{ BONGO_JSON_INT, "o:queueinterval/i", &Conf.queueInterval },
{ BONGO_JSON_INT, "o:minimumfreespace/i", &Conf.minimumFree },
{ BONGO_JSON_ARRAY, "o:trustedhosts/a", &trustedHostsConfig },
{ BONGO_JSON_BOOL, "o:rtsantispamconfig_enabled/b", &Conf.bounceBlockSpam },
{ BONGO_JSON_INT, "o:rtsantispamconfig_delay/i", &Conf.bounceInterval },
{ BONGO_JSON_INT, "o:rtsantispamconfig_threshold/i", &Conf.bounceMax },
{ BONGO_JSON_BOOL, "o:bouncereturn/b", &Conf.b_bounceReturn },
{ BONGO_JSON_BOOL, "o:bounceccpostmaster/b", &Conf.b_bounceCCPostmaster },
{ BONGO_JSON_NULL, NULL, NULL }
};
int aliasCmpFunc (const void *lft, const void *rgt){
struct _AliasStruct *l = (struct _AliasStruct *)(lft);
struct _AliasStruct *r = (struct _AliasStruct *)(rgt);;
return strcasecmp(l->original, r->original);
}
BOOL
ReadConfiguration (BOOL *recover)
{
if (!MsgGetServerCredential((char *)&Conf.serverHash)) {
return FALSE;
}
if (!ReadBongoConfiguration(QueueConfig, "queue")) {
return FALSE;
}
if (!ReadBongoConfiguration(GlobalConfig, "global")) {
return FALSE;
}
*recover = MsgGetRecoveryFlag("queue");
/* set some arrays up */
if (Conf.deferEnabled) {
Conf.deferStart[0] = Conf.i_deferStartWE; /* sunday */
Conf.deferStart[1] = Conf.i_deferStartWD;
Conf.deferStart[2] = Conf.i_deferStartWD;
Conf.deferStart[3] = Conf.i_deferStartWD;
Conf.deferStart[4] = Conf.i_deferStartWD;
Conf.deferStart[5] = Conf.i_deferStartWD;
Conf.deferStart[6] = Conf.i_deferStartWE; /* saturday */
Conf.deferEnd[0] = Conf.i_deferEndWE;
Conf.deferEnd[1] = Conf.i_deferEndWD;
Conf.deferEnd[2] = Conf.i_deferEndWD;
Conf.deferEnd[3] = Conf.i_deferEndWD;
Conf.deferEnd[4] = Conf.i_deferEndWD;
Conf.deferEnd[5] = Conf.i_deferEndWD;
Conf.deferEnd[6] = Conf.i_deferEndWE;
}
if (Conf.debug) {
Agent.flags |= QUEUE_AGENT_DEBUG;
} else {
Agent.flags &= ~QUEUE_AGENT_DEBUG;
}
Conf.queueCheck = CalculateCheckQueueLimit(Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers);
/* Set the globals for loadmonitor */
Conf.defaultConcurrentWorkers = Conf.maxConcurrentWorkers;
Conf.defaultSequentialWorkers = Conf.maxSequentialWorkers;
strcpy(Conf.spoolPath, XPL_DEFAULT_SPOOL_DIR);
MsgMakePath(Conf.spoolPath);
sprintf(Conf.queueClientsPath, "%s/qclients", MsgGetDir(MSGAPI_DIR_DBF, NULL, 0));
Conf.bounceMaxBodySize = 0;
/* Some sanity checking on the QLimit stuff to prevent running out of memory */
if (XplGetMemAvail() < (unsigned long)((STACKSPACE_Q + STACKSPACE_S) * Conf.maxSequentialWorkers)) {
Conf.maxSequentialWorkers = (XplGetMemAvail() / (STACKSPACE_Q+STACKSPACE_S)) / 2;
Conf.maxConcurrentWorkers = Conf.maxSequentialWorkers / 2;
Conf.queueCheck = CalculateCheckQueueLimit(Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers);
XplBell();
XplConsolePrintf("bongoqueue: WARNING - Tuning parameters adjusted to %ld par./%ld seq.\r\n", Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers);
XplBell();
Log(LOG_INFO, "Not enough memory; tuning parameters adjusted; concurrent limit: %d, sequential limit: %d", Conf.maxConcurrentWorkers, Conf.maxSequentialWorkers);
Conf.defaultConcurrentWorkers = Conf.maxConcurrentWorkers;
Conf.defaultSequentialWorkers = Conf.maxSequentialWorkers;
}
g_array_sort(Conf.trustedHosts, (ArrayCompareFunc)strcmp);
if (Conf.b_bounceReturn) {
Conf.bounceHandling |= BOUNCE_RETURN;
} else {
Conf.bounceHandling &= ~BOUNCE_RETURN;
}
if (Conf.b_bounceCCPostmaster) {
Conf.bounceHandling |= BOUNCE_CC_POSTMASTER;
} else {
Conf.bounceHandling &= ~BOUNCE_CC_POSTMASTER;
}
/* sort the hostedDomains to make searching later faster. */
g_array_sort(Conf.domains, (ArrayCompareFunc)hostedSortFunc);
/* now let's iterate over the domains and read in any aliasing information for those domains */
{
Conf.aliasList = g_array_sized_new(FALSE, FALSE, sizeof(struct _AliasStruct), Conf.domains->len);
unsigned int x;
for(x=0;x<Conf.domains->len;x++) {
char *aconfig;
char path[100];
BongoJsonNode *node;
struct _AliasStruct a;
a.original = MemStrdup(g_array_index(Conf.domains, char *, x));
a.to = NULL;
a.aliases = NULL;
a.mapping_type = 0;
sprintf(path, "aliases/%s", a.original);
if(NMAPReadConfigFile(path, &aconfig)) {
if (BongoJsonParseString(aconfig, &node) == BONGO_JSON_OK) {
BongoJsonObject *obj;
BongoJsonJPathGetString(node, "o:domainalias/s", (char **)&(a.to));
BongoJsonJPathGetInt(node, "o:username-mapping/i", &a.mapping_type);
/* now get any specific aliases */
if (BongoJsonJPathGetObject(node, "o:aliases/o", &obj) == BONGO_JSON_OK) {
BongoJsonObjectIter iter;
a.aliases = g_array_new(FALSE, FALSE, sizeof(struct _AliasStruct));
BongoJsonObjectIterFirst(obj, &iter);
while (iter.key) {
/* TODO: do i need to parse the addresses?
* I'd need to parse original and only use the user portion
* I'd need to parse the to and append the domain if none exists
*/
struct _AliasStruct b;
b.original = MemStrdup(iter.key);
b.to = MemStrdup(BongoJsonNodeAsString(iter.value));
b.aliases = NULL;
b.mapping_type = 0;
g_array_append_val(a.aliases, b);
BongoJsonObjectIterNext(obj, &iter);
}
g_array_sort(a.aliases, (ArrayCompareFunc)aliasCmpFunc);
}
BongoJsonNodeFree(node);
}
}
g_array_append_val(Conf.aliasList, a);
}
/* sort the list for speed later */
g_array_sort(Conf.aliasList, (ArrayCompareFunc)aliasCmpFunc);
}
return TRUE;
}
void
CheckConfig(BongoAgent *agent)
{
UNUSED_PARAMETER(agent);
/* TODO: Figure out how we are going to handle this type of situation */
return;
}