2001-12-12 18:18:20 +01:00
|
|
|
/*
|
|
|
|
* ngIRCd -- The Next Generation IRC Daemon
|
2010-02-11 00:01:53 +01:00
|
|
|
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
2001-12-12 18:18:20 +01:00
|
|
|
*
|
2002-12-12 12:26:08 +01:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
* Please read the file COPYING, README and AUTHORS for more information.
|
2001-12-12 18:18:20 +01:00
|
|
|
*
|
2002-12-12 12:26:08 +01:00
|
|
|
* Configuration management (reading, parsing & validation)
|
2001-12-12 18:18:20 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "portab.h"
|
2001-12-12 18:18:20 +01:00
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "imp.h"
|
2001-12-12 18:18:20 +01:00
|
|
|
#include <assert.h>
|
2001-12-30 20:26:11 +01:00
|
|
|
#include <errno.h>
|
2004-10-20 15:47:32 +02:00
|
|
|
#ifdef PROTOTYPES
|
|
|
|
# include <stdarg.h>
|
|
|
|
#else
|
|
|
|
# include <varargs.h>
|
|
|
|
#endif
|
2001-12-30 20:26:11 +01:00
|
|
|
#include <stdio.h>
|
2002-01-01 19:25:44 +01:00
|
|
|
#include <stdlib.h>
|
2001-12-30 20:26:11 +01:00
|
|
|
#include <string.h>
|
2004-01-17 04:17:00 +01:00
|
|
|
#include <strings.h>
|
2002-03-27 17:39:22 +01:00
|
|
|
#include <unistd.h>
|
2002-11-09 00:09:26 +01:00
|
|
|
#include <pwd.h>
|
|
|
|
#include <grp.h>
|
|
|
|
#include <sys/types.h>
|
2002-12-18 03:47:12 +01:00
|
|
|
#include <unistd.h>
|
2001-12-30 20:26:11 +01:00
|
|
|
|
2002-11-30 23:15:49 +01:00
|
|
|
#ifdef HAVE_CTYPE_H
|
|
|
|
# include <ctype.h>
|
|
|
|
#endif
|
|
|
|
|
2005-07-29 11:29:47 +02:00
|
|
|
#include "array.h"
|
2002-03-27 17:39:22 +01:00
|
|
|
#include "ngircd.h"
|
2002-05-27 15:09:26 +02:00
|
|
|
#include "conn.h"
|
2009-03-07 00:21:43 +01:00
|
|
|
#include "channel.h"
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "defines.h"
|
2001-12-30 20:26:11 +01:00
|
|
|
#include "log.h"
|
2008-08-16 02:36:30 +02:00
|
|
|
#include "match.h"
|
2001-12-30 20:26:11 +01:00
|
|
|
#include "tool.h"
|
2001-12-12 18:18:20 +01:00
|
|
|
|
2002-03-12 15:37:51 +01:00
|
|
|
#include "exp.h"
|
2001-12-12 18:18:20 +01:00
|
|
|
#include "conf.h"
|
|
|
|
|
|
|
|
|
2010-12-02 16:51:21 +01:00
|
|
|
static bool Use_Log = true, Using_MotdFile = true;
|
2005-07-31 22:13:07 +02:00
|
|
|
static CONF_SERVER New_Server;
|
|
|
|
static int New_Server_Idx;
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
static size_t Conf_Oper_Count;
|
2008-11-24 22:59:10 +01:00
|
|
|
static size_t Conf_Channel_Count;
|
2010-08-11 22:52:06 +02:00
|
|
|
static char Conf_MotdFile[FNAME_LEN];
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Set_Defaults PARAMS(( bool InitServers ));
|
2008-03-18 21:12:47 +01:00
|
|
|
static bool Read_Config PARAMS(( bool ngircd_starting ));
|
2008-05-28 00:31:20 +02:00
|
|
|
static bool Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
|
2002-01-02 03:44:36 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
|
2011-01-09 19:42:42 +01:00
|
|
|
static void Handle_FEATURES PARAMS(( int Line, char *Var, char *Arg ));
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
|
|
|
|
static void Handle_SERVER PARAMS(( int Line, char *Var, char *Arg ));
|
|
|
|
static void Handle_CHANNEL PARAMS(( int Line, char *Var, char *Arg ));
|
2002-01-02 03:44:36 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Config_Error PARAMS(( const int Level, const char *Format, ... ));
|
2001-12-26 23:48:53 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Config_Error_NaN PARAMS(( const int LINE, const char *Value ));
|
|
|
|
static void Config_Error_TooLong PARAMS(( const int LINE, const char *Value ));
|
2005-01-20 01:13:08 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
|
2002-12-30 01:01:42 +01:00
|
|
|
|
2008-05-19 14:34:48 +02:00
|
|
|
#ifdef WANT_IPV6
|
|
|
|
#define DEFAULT_LISTEN_ADDRSTR "::,0.0.0.0"
|
|
|
|
#else
|
|
|
|
#define DEFAULT_LISTEN_ADDRSTR "0.0.0.0"
|
|
|
|
#endif
|
2001-12-26 23:48:53 +01:00
|
|
|
|
2008-09-13 15:10:32 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
struct SSLOptions Conf_SSLOptions;
|
|
|
|
|
|
|
|
static void
|
|
|
|
ConfSSL_Init(void)
|
|
|
|
{
|
|
|
|
free(Conf_SSLOptions.KeyFile);
|
|
|
|
Conf_SSLOptions.KeyFile = NULL;
|
|
|
|
|
|
|
|
free(Conf_SSLOptions.CertFile);
|
|
|
|
Conf_SSLOptions.CertFile = NULL;
|
|
|
|
|
|
|
|
free(Conf_SSLOptions.DHFile);
|
|
|
|
Conf_SSLOptions.DHFile = NULL;
|
|
|
|
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
|
|
|
|
}
|
|
|
|
|
2009-09-20 20:43:12 +02:00
|
|
|
static bool
|
2009-10-17 14:31:27 +02:00
|
|
|
ssl_print_configvar(const char *name, const char *file)
|
2009-09-20 20:43:12 +02:00
|
|
|
{
|
2009-10-17 14:31:27 +02:00
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if (!file) {
|
|
|
|
printf(" %s =\n", name);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
fp = fopen(file, "r");
|
2009-09-20 20:43:12 +02:00
|
|
|
if (fp)
|
|
|
|
fclose(fp);
|
|
|
|
else
|
|
|
|
fprintf(stderr, "ERROR: %s \"%s\": %s\n",
|
|
|
|
name, file, strerror(errno));
|
2009-10-17 14:31:27 +02:00
|
|
|
|
|
|
|
printf(" %s = %s\n", name, file);
|
2009-09-20 20:43:12 +02:00
|
|
|
return fp != NULL;
|
|
|
|
}
|
2008-09-13 15:10:32 +02:00
|
|
|
|
2009-09-20 20:43:12 +02:00
|
|
|
static bool
|
2008-09-13 15:10:32 +02:00
|
|
|
ConfSSL_Puts(void)
|
|
|
|
{
|
2009-10-17 14:31:27 +02:00
|
|
|
bool ret;
|
|
|
|
|
|
|
|
ret = ssl_print_configvar("SSLKeyFile", Conf_SSLOptions.KeyFile);
|
|
|
|
|
|
|
|
if (!ssl_print_configvar("SSLCertFile", Conf_SSLOptions.CertFile))
|
|
|
|
ret = false;
|
|
|
|
|
|
|
|
if (!ssl_print_configvar("SSLDHFile", Conf_SSLOptions.DHFile))
|
|
|
|
ret = false;
|
2009-09-20 20:43:12 +02:00
|
|
|
|
2008-09-13 15:10:32 +02:00
|
|
|
if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
|
2009-10-17 14:31:27 +02:00
|
|
|
puts(" SSLKeyFilePassword = <secret>");
|
|
|
|
|
2008-09-13 15:10:32 +02:00
|
|
|
array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
|
2009-09-20 20:43:12 +02:00
|
|
|
|
|
|
|
return ret;
|
2008-09-13 15:10:32 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
static char *
|
|
|
|
strdup_warn(const char *str)
|
|
|
|
{
|
2005-09-24 19:06:54 +02:00
|
|
|
char *ptr = strdup(str);
|
|
|
|
if (!ptr)
|
2005-09-11 01:42:12 +02:00
|
|
|
Config_Error(LOG_ERR, "Could not allocate mem for string: %s", str);
|
2005-09-24 19:06:54 +02:00
|
|
|
return ptr;
|
2005-09-11 01:42:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-29 11:29:47 +02:00
|
|
|
static void
|
|
|
|
ports_puts(array *a)
|
|
|
|
{
|
2006-05-10 23:24:01 +02:00
|
|
|
size_t len;
|
2005-07-29 11:29:47 +02:00
|
|
|
UINT16 *ports;
|
|
|
|
len = array_length(a, sizeof(UINT16));
|
|
|
|
if (len--) {
|
|
|
|
ports = (UINT16*) array_start(a);
|
|
|
|
printf("%u", (unsigned int) *ports);
|
|
|
|
while (len--) {
|
|
|
|
ports++;
|
|
|
|
printf(", %u", (unsigned int) *ports);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
putc('\n', stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
ports_parse(array *a, int Line, char *Arg)
|
|
|
|
{
|
|
|
|
char *ptr;
|
|
|
|
int port;
|
|
|
|
UINT16 port16;
|
|
|
|
|
|
|
|
array_trunc(a);
|
|
|
|
|
|
|
|
/* Ports on that the server should listen. More port numbers
|
|
|
|
* must be separated by "," */
|
|
|
|
ptr = strtok( Arg, "," );
|
|
|
|
while (ptr) {
|
2009-09-11 22:52:12 +02:00
|
|
|
ngt_TrimStr(ptr);
|
|
|
|
port = atoi(ptr);
|
2005-07-29 11:29:47 +02:00
|
|
|
if (port > 0 && port < 0xFFFF) {
|
|
|
|
port16 = (UINT16) port;
|
|
|
|
if (!array_catb(a, (char*)&port16, sizeof port16))
|
|
|
|
Config_Error(LOG_ERR, "%s, line %d Could not add port number %ld: %s",
|
|
|
|
NGIRCd_ConfFile, Line, port, strerror(errno));
|
|
|
|
} else {
|
|
|
|
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!",
|
|
|
|
NGIRCd_ConfFile, Line, port );
|
|
|
|
}
|
|
|
|
|
|
|
|
ptr = strtok( NULL, "," );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Conf_Init( void )
|
2001-12-12 18:18:20 +01:00
|
|
|
{
|
2008-03-18 21:12:47 +01:00
|
|
|
Read_Config( true );
|
2006-07-23 18:42:45 +02:00
|
|
|
Validate_Config(false, false);
|
2002-03-27 17:39:22 +01:00
|
|
|
} /* Config_Init */
|
|
|
|
|
|
|
|
|
2008-03-18 21:12:47 +01:00
|
|
|
GLOBAL bool
|
2005-03-19 19:43:48 +01:00
|
|
|
Conf_Rehash( void )
|
2002-12-30 01:01:42 +01:00
|
|
|
{
|
2008-03-18 21:12:47 +01:00
|
|
|
if (!Read_Config(false))
|
|
|
|
return false;
|
2006-07-23 18:42:45 +02:00
|
|
|
Validate_Config(false, true);
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2006-10-03 12:59:40 +02:00
|
|
|
/* Update CLIENT structure of local server */
|
|
|
|
Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
|
2008-03-18 21:12:47 +01:00
|
|
|
return true;
|
2002-12-30 01:01:42 +01:00
|
|
|
} /* Config_Rehash */
|
|
|
|
|
|
|
|
|
2008-04-21 00:45:19 +02:00
|
|
|
static const char*
|
|
|
|
yesno_to_str(int boolean_value)
|
|
|
|
{
|
|
|
|
if (boolean_value)
|
|
|
|
return "yes";
|
|
|
|
return "no";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
static void
|
|
|
|
opers_free(void)
|
|
|
|
{
|
|
|
|
struct Conf_Oper *op;
|
|
|
|
size_t len;
|
2011-01-09 19:42:42 +01:00
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
len = array_length(&Conf_Opers, sizeof(*op));
|
|
|
|
op = array_start(&Conf_Opers);
|
|
|
|
while (len--) {
|
|
|
|
free(op->mask);
|
|
|
|
op++;
|
|
|
|
}
|
|
|
|
array_free(&Conf_Opers);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
opers_puts(void)
|
|
|
|
{
|
|
|
|
struct Conf_Oper *op;
|
|
|
|
size_t len;
|
2011-01-09 19:42:42 +01:00
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
len = array_length(&Conf_Opers, sizeof(*op));
|
|
|
|
op = array_start(&Conf_Opers);
|
|
|
|
while (len--) {
|
|
|
|
assert(op->name[0]);
|
|
|
|
|
|
|
|
puts("[OPERATOR]");
|
|
|
|
printf(" Name = %s\n", op->name);
|
|
|
|
printf(" Password = %s\n", op->pwd);
|
|
|
|
printf(" Mask = %s\n\n", op->mask ? op->mask : "");
|
|
|
|
op++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
|
|
|
Conf_Test( void )
|
2002-03-27 17:39:22 +01:00
|
|
|
{
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Read configuration, validate and output it. */
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2002-11-09 00:09:26 +01:00
|
|
|
struct passwd *pwd;
|
|
|
|
struct group *grp;
|
2005-07-11 16:11:35 +02:00
|
|
|
unsigned int i;
|
2008-05-28 00:31:20 +02:00
|
|
|
bool config_valid;
|
2008-11-24 22:59:10 +01:00
|
|
|
size_t predef_channel_count;
|
|
|
|
struct Conf_Channel *predef_chan;
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
Use_Log = false;
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2008-05-28 00:31:20 +02:00
|
|
|
if (! Read_Config(true))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
config_valid = Validate_Config(true, false);
|
2001-12-30 20:26:11 +01:00
|
|
|
|
2005-03-22 19:57:08 +01:00
|
|
|
/* If stdin and stdout ("you can read our nice message and we can
|
|
|
|
* read in your keypress") are valid tty's, wait for a key: */
|
2005-09-11 01:42:12 +02:00
|
|
|
if( isatty( fileno( stdin )) && isatty( fileno( stdout ))) {
|
2002-03-27 17:39:22 +01:00
|
|
|
puts( "OK, press enter to see a dump of your service configuration ..." );
|
|
|
|
getchar( );
|
2005-09-11 01:42:12 +02:00
|
|
|
} else {
|
|
|
|
puts( "Ok, dump of your server configuration follows:\n" );
|
2002-03-27 17:39:22 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
puts( "[GLOBAL]" );
|
2010-02-11 00:01:53 +01:00
|
|
|
printf(" Name = %s\n", Conf_ServerName);
|
|
|
|
printf(" Info = %s\n", Conf_ServerInfo);
|
2010-07-11 17:01:45 +02:00
|
|
|
#ifndef PAM
|
2010-02-11 00:01:53 +01:00
|
|
|
printf(" Password = %s\n", Conf_ServerPwd);
|
2010-07-11 17:01:45 +02:00
|
|
|
#endif
|
2010-02-11 00:01:53 +01:00
|
|
|
printf(" WebircPassword = %s\n", Conf_WebircPwd);
|
|
|
|
printf(" AdminInfo1 = %s\n", Conf_ServerAdmin1);
|
|
|
|
printf(" AdminInfo2 = %s\n", Conf_ServerAdmin2);
|
|
|
|
printf(" AdminEMail = %s\n", Conf_ServerAdminMail);
|
2010-12-02 16:51:21 +01:00
|
|
|
if (Using_MotdFile) {
|
|
|
|
printf(" MotdFile = %s\n", Conf_MotdFile);
|
|
|
|
printf(" MotdPhrase =\n");
|
|
|
|
} else {
|
|
|
|
printf(" MotdFile = \n");
|
|
|
|
printf(" MotdPhrase = %s\n", array_bytes(&Conf_Motd)
|
|
|
|
? (const char*) array_start(&Conf_Motd) : "");
|
|
|
|
}
|
2010-02-11 00:01:53 +01:00
|
|
|
printf(" ChrootDir = %s\n", Conf_Chroot);
|
|
|
|
printf(" PidFile = %s\n", Conf_PidFile);
|
2008-09-13 15:10:32 +02:00
|
|
|
printf(" Listen = %s\n", Conf_ListenAddress);
|
2005-07-29 11:29:47 +02:00
|
|
|
fputs(" Ports = ", stdout);
|
|
|
|
ports_puts(&Conf_ListenPorts);
|
2008-09-13 15:10:32 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
fputs(" SSLPorts = ", stdout);
|
|
|
|
ports_puts(&Conf_SSLOptions.ListenPorts);
|
2009-09-20 20:43:12 +02:00
|
|
|
if (!ConfSSL_Puts())
|
|
|
|
config_valid = false;
|
2008-09-13 15:10:32 +02:00
|
|
|
#endif
|
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
pwd = getpwuid(Conf_UID);
|
|
|
|
if (pwd)
|
|
|
|
printf(" ServerUID = %s\n", pwd->pw_name);
|
|
|
|
else
|
|
|
|
printf(" ServerUID = %ld\n", (long)Conf_UID);
|
|
|
|
grp = getgrgid(Conf_GID);
|
|
|
|
if (grp)
|
|
|
|
printf(" ServerGID = %s\n", grp->gr_name);
|
|
|
|
else
|
|
|
|
printf(" ServerGID = %ld\n", (long)Conf_GID);
|
2010-09-24 17:39:11 +02:00
|
|
|
#ifdef SYSLOG
|
|
|
|
printf(" SyslogFacility = %s\n",
|
|
|
|
ngt_SyslogFacilityName(Conf_SyslogFacility));
|
|
|
|
#endif
|
2008-04-13 16:39:08 +02:00
|
|
|
printf(" PingTimeout = %d\n", Conf_PingTimeout);
|
|
|
|
printf(" PongTimeout = %d\n", Conf_PongTimeout);
|
|
|
|
printf(" ConnectRetry = %d\n", Conf_ConnectRetry);
|
|
|
|
printf(" OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode));
|
|
|
|
printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
|
|
|
|
printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper));
|
|
|
|
printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
|
2008-04-21 00:45:19 +02:00
|
|
|
#ifdef WANT_IPV6
|
2008-04-29 15:27:44 +02:00
|
|
|
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
|
2008-04-21 00:45:19 +02:00
|
|
|
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
|
|
|
|
#endif
|
2008-04-13 16:39:08 +02:00
|
|
|
printf(" MaxConnections = %ld\n", Conf_MaxConnections);
|
|
|
|
printf(" MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
|
|
|
|
printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1);
|
|
|
|
printf(" MaxNickLength = %u\n\n", Conf_MaxNickLength - 1);
|
2005-09-11 01:42:12 +02:00
|
|
|
|
2011-01-09 19:42:42 +01:00
|
|
|
puts("[FEATURES]");
|
|
|
|
printf(" DNS = %s\n", yesno_to_str(Conf_DNS));
|
|
|
|
printf(" Ident = %s\n", yesno_to_str(Conf_Ident));
|
|
|
|
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
|
|
|
|
puts("");
|
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
opers_puts();
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-05-22 13:14:36 +02:00
|
|
|
if( ! Conf_Server[i].name[0] ) continue;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Valid "Server" section */
|
2002-03-27 17:39:22 +01:00
|
|
|
puts( "[SERVER]" );
|
|
|
|
printf( " Name = %s\n", Conf_Server[i].name );
|
|
|
|
printf( " Host = %s\n", Conf_Server[i].host );
|
2006-05-10 23:24:01 +02:00
|
|
|
printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
|
2008-09-13 15:10:32 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
printf( " SSLConnect = %s\n", Conf_Server[i].SSLConnect?"yes":"no");
|
|
|
|
#endif
|
2002-11-19 13:50:20 +01:00
|
|
|
printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
|
|
|
|
printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
|
2008-08-16 02:36:30 +02:00
|
|
|
printf( " ServiceMask = %s\n", Conf_Server[i].svs_mask);
|
2007-06-28 07:15:12 +02:00
|
|
|
printf( " Group = %d\n", Conf_Server[i].group );
|
|
|
|
printf( " Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no");
|
2002-03-27 17:39:22 +01:00
|
|
|
}
|
2002-05-21 02:10:16 +02:00
|
|
|
|
2008-11-24 22:59:10 +01:00
|
|
|
predef_channel_count = array_length(&Conf_Channels, sizeof(*predef_chan));
|
|
|
|
predef_chan = array_start(&Conf_Channels);
|
|
|
|
|
|
|
|
for (i = 0; i < predef_channel_count; i++, predef_chan++) {
|
|
|
|
if (!predef_chan->name[0])
|
|
|
|
continue;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Valid "Channel" section */
|
2002-05-21 02:10:16 +02:00
|
|
|
puts( "[CHANNEL]" );
|
2008-11-24 22:59:10 +01:00
|
|
|
printf(" Name = %s\n", predef_chan->name);
|
|
|
|
printf(" Modes = %s\n", predef_chan->modes);
|
|
|
|
printf(" Key = %s\n", predef_chan->key);
|
|
|
|
printf(" MaxUsers = %lu\n", predef_chan->maxusers);
|
2009-01-01 22:26:13 +01:00
|
|
|
printf(" Topic = %s\n", predef_chan->topic);
|
|
|
|
printf(" KeyFile = %s\n\n", predef_chan->keyfile);
|
2002-05-21 02:10:16 +02:00
|
|
|
}
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2008-05-28 00:31:20 +02:00
|
|
|
return (config_valid ? 0 : 1);
|
2002-03-27 17:39:22 +01:00
|
|
|
} /* Conf_Test */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
2002-12-30 01:01:42 +01:00
|
|
|
Conf_UnsetServer( CONN_ID Idx )
|
|
|
|
{
|
|
|
|
/* Set next time for next connection attempt, if this is a server
|
|
|
|
* link that is (still) configured here. If the server is set as
|
|
|
|
* "once", delete it from our configuration.
|
|
|
|
* Non-Server-Connections will be silently ignored. */
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
int i;
|
2005-10-11 21:29:23 +02:00
|
|
|
time_t t;
|
2002-12-30 01:01:42 +01:00
|
|
|
|
|
|
|
/* Check all our configured servers */
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
if( Conf_Server[i].conn_id != Idx ) continue;
|
|
|
|
|
|
|
|
/* Gotcha! Mark server configuration as "unused": */
|
|
|
|
Conf_Server[i].conn_id = NONE;
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Delete configuration here */
|
|
|
|
Init_Server_Struct( &Conf_Server[i] );
|
2005-09-11 01:42:12 +02:00
|
|
|
} else {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Set time for next connect attempt */
|
2006-11-05 14:03:46 +01:00
|
|
|
t = time(NULL);
|
|
|
|
if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) {
|
|
|
|
/* The connection has been "long", so we don't
|
|
|
|
* require the next attempt to be delayed. */
|
|
|
|
Conf_Server[i].lasttry =
|
|
|
|
t - Conf_ConnectRetry + RECONNECT_DELAY;
|
|
|
|
} else
|
|
|
|
Conf_Server[i].lasttry = t;
|
2002-12-30 01:01:42 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} /* Conf_UnsetServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL void
|
|
|
|
Conf_SetServer( int ConfServer, CONN_ID Idx )
|
2002-12-30 01:01:42 +01:00
|
|
|
{
|
|
|
|
/* Set connection for specified configured server */
|
|
|
|
|
|
|
|
assert( ConfServer > NONE );
|
|
|
|
assert( Idx > NONE );
|
|
|
|
|
|
|
|
Conf_Server[ConfServer].conn_id = Idx;
|
|
|
|
} /* Conf_SetServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL int
|
2002-12-30 01:01:42 +01:00
|
|
|
Conf_GetServer( CONN_ID Idx )
|
|
|
|
{
|
|
|
|
/* Get index of server in configuration structure */
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
int i = 0;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
assert( Idx > NONE );
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
if( Conf_Server[i].conn_id == Idx ) return i;
|
|
|
|
}
|
|
|
|
return NONE;
|
|
|
|
} /* Conf_GetServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2009-04-12 01:09:42 +02:00
|
|
|
Conf_EnableServer( const char *Name, UINT16 Port )
|
2002-12-31 17:12:50 +01:00
|
|
|
{
|
|
|
|
/* Enable specified server and adjust port */
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
int i;
|
2002-12-31 17:12:50 +01:00
|
|
|
|
|
|
|
assert( Name != NULL );
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
|
|
|
if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
|
2002-12-31 17:12:50 +01:00
|
|
|
/* Gotcha! Set port and enable server: */
|
|
|
|
Conf_Server[i].port = Port;
|
|
|
|
Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
|
2009-07-17 14:55:30 +02:00
|
|
|
return (Conf_Server[i].port && Conf_Server[i].host[0]);
|
2002-12-31 17:12:50 +01:00
|
|
|
}
|
|
|
|
}
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2002-12-31 17:12:50 +01:00
|
|
|
} /* Conf_EnableServer */
|
|
|
|
|
|
|
|
|
2007-06-28 07:15:12 +02:00
|
|
|
GLOBAL bool
|
|
|
|
Conf_EnablePassiveServer(const char *Name)
|
|
|
|
{
|
|
|
|
/* Enable specified server */
|
|
|
|
int i;
|
|
|
|
|
|
|
|
assert( Name != NULL );
|
|
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
|
|
if ((strcasecmp( Conf_Server[i].name, Name ) == 0) && (Conf_Server[i].port > 0)) {
|
|
|
|
/* BINGO! Enable server */
|
|
|
|
Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
} /* Conf_EnablePassiveServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2009-04-12 01:09:42 +02:00
|
|
|
Conf_DisableServer( const char *Name )
|
2002-12-31 17:12:50 +01:00
|
|
|
{
|
|
|
|
/* Enable specified server and adjust port */
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
int i;
|
2002-12-31 17:12:50 +01:00
|
|
|
|
|
|
|
assert( Name != NULL );
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
|
|
|
if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) {
|
2002-12-31 17:12:50 +01:00
|
|
|
/* Gotcha! Disable and disconnect server: */
|
|
|
|
Conf_Server[i].flags |= CONF_SFLAG_DISABLED;
|
2005-03-19 19:43:48 +01:00
|
|
|
if( Conf_Server[i].conn_id > NONE ) Conn_Close( Conf_Server[i].conn_id, NULL, "Server link terminated on operator request", true);
|
|
|
|
return true;
|
2002-12-31 17:12:50 +01:00
|
|
|
}
|
|
|
|
}
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2002-12-31 17:12:50 +01:00
|
|
|
} /* Conf_DisableServer */
|
|
|
|
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
GLOBAL bool
|
2009-04-12 01:09:42 +02:00
|
|
|
Conf_AddServer( const char *Name, UINT16 Port, const char *Host, const char *MyPwd, const char *PeerPwd )
|
2002-12-31 17:12:50 +01:00
|
|
|
{
|
|
|
|
/* Add new server to configuration */
|
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
int i;
|
2002-12-31 17:12:50 +01:00
|
|
|
|
|
|
|
assert( Name != NULL );
|
|
|
|
assert( Host != NULL );
|
|
|
|
assert( MyPwd != NULL );
|
|
|
|
assert( PeerPwd != NULL );
|
|
|
|
|
|
|
|
/* Search unused item in server configuration structure */
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-12-31 17:12:50 +01:00
|
|
|
/* Is this item used? */
|
|
|
|
if( ! Conf_Server[i].name[0] ) break;
|
|
|
|
}
|
2005-03-19 19:43:48 +01:00
|
|
|
if( i >= MAX_SERVERS ) return false;
|
2002-12-31 17:12:50 +01:00
|
|
|
|
|
|
|
Init_Server_Struct( &Conf_Server[i] );
|
|
|
|
strlcpy( Conf_Server[i].name, Name, sizeof( Conf_Server[i].name ));
|
|
|
|
strlcpy( Conf_Server[i].host, Host, sizeof( Conf_Server[i].host ));
|
|
|
|
strlcpy( Conf_Server[i].pwd_out, MyPwd, sizeof( Conf_Server[i].pwd_out ));
|
|
|
|
strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in ));
|
|
|
|
Conf_Server[i].port = Port;
|
|
|
|
Conf_Server[i].flags = CONF_SFLAG_ONCE;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
return true;
|
2002-12-31 17:12:50 +01:00
|
|
|
} /* Conf_AddServer */
|
|
|
|
|
|
|
|
|
2008-08-16 02:36:30 +02:00
|
|
|
/**
|
|
|
|
* Check if the given nick name is an service
|
|
|
|
*/
|
|
|
|
GLOBAL bool
|
2009-04-12 01:09:42 +02:00
|
|
|
Conf_IsService(int ConfServer, const char *Nick)
|
2008-08-16 02:36:30 +02:00
|
|
|
{
|
|
|
|
return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick);
|
|
|
|
} /* Conf_IsService */
|
|
|
|
|
|
|
|
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
static void
|
|
|
|
Set_Defaults_Optional(void)
|
|
|
|
{
|
|
|
|
#ifdef IDENTAUTH
|
|
|
|
Conf_Ident = true;
|
|
|
|
#else
|
|
|
|
Conf_Ident = false;
|
|
|
|
#endif
|
|
|
|
#ifdef PAM
|
|
|
|
Conf_PAM = true;
|
|
|
|
#else
|
|
|
|
Conf_PAM = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
/**
|
|
|
|
* Initialize configuration settings with their default values.
|
|
|
|
*/
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2008-04-13 16:39:08 +02:00
|
|
|
Set_Defaults(bool InitServers)
|
2002-03-27 17:39:22 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
int i;
|
2002-12-30 01:01:42 +01:00
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
strcpy(Conf_ServerName, "");
|
|
|
|
snprintf(Conf_ServerInfo, sizeof Conf_ServerInfo, "%s %s",
|
|
|
|
PACKAGE_NAME, PACKAGE_VERSION);
|
|
|
|
strcpy(Conf_ServerPwd, "");
|
2001-12-30 20:26:11 +01:00
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
strcpy(Conf_ServerAdmin1, "");
|
|
|
|
strcpy(Conf_ServerAdmin2, "");
|
|
|
|
strcpy(Conf_ServerAdminMail, "");
|
2004-05-07 13:19:20 +02:00
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
strlcpy(Conf_MotdFile, SYSCONFDIR, sizeof(Conf_MotdFile));
|
|
|
|
strlcat(Conf_MotdFile, MOTD_FILE, sizeof(Conf_MotdFile));
|
2004-05-07 13:19:20 +02:00
|
|
|
|
2008-04-13 16:39:08 +02:00
|
|
|
Conf_UID = Conf_GID = 0;
|
|
|
|
strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot));
|
|
|
|
strlcpy(Conf_PidFile, PID_FILE, sizeof(Conf_PidFile));
|
2005-02-04 15:24:20 +01:00
|
|
|
|
2008-05-19 00:12:41 +02:00
|
|
|
free(Conf_ListenAddress);
|
|
|
|
Conf_ListenAddress = NULL;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2001-12-26 15:45:37 +01:00
|
|
|
Conf_PingTimeout = 120;
|
2002-03-25 17:14:15 +01:00
|
|
|
Conf_PongTimeout = 20;
|
2002-01-02 03:44:36 +01:00
|
|
|
Conf_ConnectRetry = 60;
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
Conf_DNS = true;
|
2002-01-02 03:44:36 +01:00
|
|
|
|
|
|
|
Conf_Oper_Count = 0;
|
2002-05-21 02:10:16 +02:00
|
|
|
Conf_Channel_Count = 0;
|
2002-09-02 16:59:17 +02:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
Conf_OperCanMode = false;
|
|
|
|
Conf_OperServerMode = false;
|
2008-04-13 16:39:08 +02:00
|
|
|
Conf_AllowRemoteOper = false;
|
|
|
|
Conf_PredefChannelsOnly = false;
|
2006-11-05 14:03:46 +01:00
|
|
|
|
2008-04-21 00:45:19 +02:00
|
|
|
Conf_ConnectIPv4 = true;
|
|
|
|
Conf_ConnectIPv6 = true;
|
|
|
|
|
2007-10-24 02:48:41 +02:00
|
|
|
Conf_MaxConnections = 0;
|
2003-11-05 22:41:01 +01:00
|
|
|
Conf_MaxConnectionsIP = 5;
|
2002-12-13 18:32:33 +01:00
|
|
|
Conf_MaxJoins = 10;
|
2007-11-21 13:16:33 +01:00
|
|
|
Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT;
|
2002-12-30 01:01:42 +01:00
|
|
|
|
2010-09-24 17:39:11 +02:00
|
|
|
#ifdef SYSLOG
|
|
|
|
#ifdef LOG_LOCAL5
|
|
|
|
Conf_SyslogFacility = LOG_LOCAL5;
|
|
|
|
#else
|
|
|
|
Conf_SyslogFacility = 0;
|
|
|
|
#endif
|
|
|
|
#endif
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
Set_Defaults_Optional();
|
2010-09-24 17:39:11 +02:00
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Initialize server configuration structures */
|
2008-04-13 16:39:08 +02:00
|
|
|
if (InitServers) {
|
|
|
|
for (i = 0; i < MAX_SERVERS;
|
|
|
|
Init_Server_Struct(&Conf_Server[i++]));
|
|
|
|
}
|
2011-01-18 22:01:27 +01:00
|
|
|
|
|
|
|
/* Free MOTD; this is important when reloading the configuration */
|
|
|
|
array_free(&Conf_Motd);
|
2002-03-27 17:39:22 +01:00
|
|
|
} /* Set_Defaults */
|
2001-12-12 18:18:20 +01:00
|
|
|
|
|
|
|
|
2009-08-31 19:42:59 +02:00
|
|
|
static bool
|
|
|
|
no_listenports(void)
|
|
|
|
{
|
2009-09-11 22:52:12 +02:00
|
|
|
size_t cnt = array_bytes(&Conf_ListenPorts);
|
2009-08-31 19:42:59 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
cnt += array_bytes(&Conf_SSLOptions.ListenPorts);
|
|
|
|
#endif
|
|
|
|
return cnt == 0;
|
|
|
|
}
|
|
|
|
|
2010-08-11 22:52:06 +02:00
|
|
|
static void
|
|
|
|
Read_Motd(const char *filename)
|
|
|
|
{
|
|
|
|
char line[127];
|
|
|
|
FILE *fp;
|
|
|
|
|
|
|
|
if (*filename == '\0')
|
|
|
|
return;
|
|
|
|
|
|
|
|
fp = fopen(filename, "r");
|
|
|
|
if (!fp) {
|
|
|
|
Log(LOG_WARNING, "Can't read MOTD file \"%s\": %s",
|
|
|
|
filename, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
array_free(&Conf_Motd);
|
2010-12-02 16:51:21 +01:00
|
|
|
Using_MotdFile = true;
|
2010-08-11 22:52:06 +02:00
|
|
|
|
|
|
|
while (fgets(line, (int)sizeof line, fp)) {
|
|
|
|
ngt_TrimLastChr( line, '\n');
|
|
|
|
|
|
|
|
/* add text including \0 */
|
|
|
|
if (!array_catb(&Conf_Motd, line, strlen(line) + 1)) {
|
|
|
|
Log(LOG_WARNING, "Cannot add MOTD text: %s", strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
2008-03-18 21:12:47 +01:00
|
|
|
static bool
|
|
|
|
Read_Config( bool ngircd_starting )
|
2001-12-26 23:48:53 +01:00
|
|
|
{
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Read configuration file. */
|
2001-12-30 20:26:11 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
|
2005-07-29 11:29:47 +02:00
|
|
|
const UINT16 defaultport = 6667;
|
2005-03-19 19:43:48 +01:00
|
|
|
int line, i, n;
|
2001-12-30 20:26:11 +01:00
|
|
|
FILE *fd;
|
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Open configuration file */
|
2002-03-27 17:39:22 +01:00
|
|
|
fd = fopen( NGIRCd_ConfFile, "r" );
|
2005-09-11 01:42:12 +02:00
|
|
|
if( ! fd ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* No configuration file found! */
|
2005-09-11 01:42:12 +02:00
|
|
|
Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s",
|
|
|
|
NGIRCd_ConfFile, strerror( errno ));
|
2008-03-18 21:12:47 +01:00
|
|
|
if (!ngircd_starting)
|
|
|
|
return false;
|
2003-03-31 17:54:21 +02:00
|
|
|
Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
|
2001-12-30 20:26:11 +01:00
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
opers_free();
|
2008-03-18 21:12:47 +01:00
|
|
|
Set_Defaults( ngircd_starting );
|
|
|
|
|
2002-11-22 18:57:40 +01:00
|
|
|
Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile );
|
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Clean up server configuration structure: mark all already
|
|
|
|
* configured servers as "once" so that they are deleted
|
2003-03-27 02:21:38 +01:00
|
|
|
* after the next disconnect and delete all unused servers.
|
|
|
|
* And delete all servers which are "duplicates" of servers
|
|
|
|
* that are already marked as "once" (such servers have been
|
|
|
|
* created by the last rehash but are now useless). */
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
if( Conf_Server[i].conn_id == NONE ) Init_Server_Struct( &Conf_Server[i] );
|
2005-09-11 01:42:12 +02:00
|
|
|
else {
|
2003-03-27 02:21:38 +01:00
|
|
|
/* This structure is in use ... */
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) {
|
2003-03-27 02:21:38 +01:00
|
|
|
/* Check for duplicates */
|
2005-09-11 01:42:12 +02:00
|
|
|
for( n = 0; n < MAX_SERVERS; n++ ) {
|
2003-03-27 02:21:38 +01:00
|
|
|
if( n == i ) continue;
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_Server[i].conn_id == Conf_Server[n].conn_id ) {
|
2003-03-27 02:21:38 +01:00
|
|
|
Init_Server_Struct( &Conf_Server[n] );
|
2005-09-11 01:42:12 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
Log(LOG_DEBUG,"Deleted unused duplicate server %d (kept %d).",
|
|
|
|
n, i );
|
|
|
|
#endif
|
2003-03-27 02:21:38 +01:00
|
|
|
}
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
} else {
|
2003-03-27 02:21:38 +01:00
|
|
|
/* Mark server as "once" */
|
|
|
|
Conf_Server[i].flags |= CONF_SFLAG_ONCE;
|
2003-04-21 01:09:43 +02:00
|
|
|
Log( LOG_DEBUG, "Marked server %d as \"once\"", i );
|
2003-03-27 02:21:38 +01:00
|
|
|
}
|
|
|
|
}
|
2002-12-30 01:01:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize variables */
|
2001-12-30 20:26:11 +01:00
|
|
|
line = 0;
|
2002-01-02 03:44:36 +01:00
|
|
|
strcpy( section, "" );
|
2002-12-30 01:01:42 +01:00
|
|
|
Init_Server_Struct( &New_Server );
|
|
|
|
New_Server_Idx = NONE;
|
2008-09-13 15:10:32 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
ConfSSL_Init();
|
|
|
|
#endif
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Read configuration file */
|
2005-09-11 01:42:12 +02:00
|
|
|
while( true ) {
|
2001-12-31 03:18:51 +01:00
|
|
|
if( ! fgets( str, LINE_LEN, fd )) break;
|
2001-12-30 20:26:11 +01:00
|
|
|
ngt_TrimStr( str );
|
|
|
|
line++;
|
|
|
|
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Skip comments and empty lines */
|
2001-12-30 20:26:11 +01:00
|
|
|
if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue;
|
|
|
|
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Is this the beginning of a new section? */
|
2005-09-11 01:42:12 +02:00
|
|
|
if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) {
|
2002-12-26 18:04:54 +01:00
|
|
|
strlcpy( section, str, sizeof( section ));
|
2011-01-09 22:19:17 +01:00
|
|
|
if (strcasecmp( section, "[GLOBAL]" ) == 0 ||
|
|
|
|
strcasecmp( section, "[FEATURES]") == 0)
|
2005-09-11 01:42:12 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if( strcasecmp( section, "[SERVER]" ) == 0 ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Check if there is already a server to add */
|
2005-09-11 01:42:12 +02:00
|
|
|
if( New_Server.name[0] ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Copy data to "real" server structure */
|
|
|
|
assert( New_Server_Idx > NONE );
|
|
|
|
Conf_Server[New_Server_Idx] = New_Server;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Re-init structure for new server */
|
|
|
|
Init_Server_Struct( &New_Server );
|
|
|
|
|
|
|
|
/* Search unused item in server configuration structure */
|
2005-09-11 01:42:12 +02:00
|
|
|
for( i = 0; i < MAX_SERVERS; i++ ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Is this item used? */
|
|
|
|
if( ! Conf_Server[i].name[0] ) break;
|
2002-01-02 03:44:36 +01:00
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( i >= MAX_SERVERS ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Oops, no free item found! */
|
|
|
|
Config_Error( LOG_ERR, "Too many servers configured." );
|
|
|
|
New_Server_Idx = NONE;
|
|
|
|
}
|
|
|
|
else New_Server_Idx = i;
|
2002-01-02 03:44:36 +01:00
|
|
|
continue;
|
|
|
|
}
|
2008-11-24 22:59:10 +01:00
|
|
|
if (strcasecmp(section, "[CHANNEL]") == 0) {
|
|
|
|
Conf_Channel_Count++;
|
2002-05-21 02:10:16 +02:00
|
|
|
continue;
|
|
|
|
}
|
2009-11-07 12:14:37 +01:00
|
|
|
if (strcasecmp(section, "[OPERATOR]") == 0) {
|
|
|
|
Conf_Oper_Count++;
|
|
|
|
continue;
|
|
|
|
}
|
2008-11-24 22:59:10 +01:00
|
|
|
|
2002-03-27 17:39:22 +01:00
|
|
|
Config_Error( LOG_ERR, "%s, line %d: Unknown section \"%s\"!", NGIRCd_ConfFile, line, section );
|
2002-01-02 03:44:36 +01:00
|
|
|
section[0] = 0x1;
|
|
|
|
}
|
|
|
|
if( section[0] == 0x1 ) continue;
|
|
|
|
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Split line into variable name and parameters */
|
2001-12-30 20:26:11 +01:00
|
|
|
ptr = strchr( str, '=' );
|
2005-09-11 01:42:12 +02:00
|
|
|
if( ! ptr ) {
|
2002-03-27 17:39:22 +01:00
|
|
|
Config_Error( LOG_ERR, "%s, line %d: Syntax error!", NGIRCd_ConfFile, line );
|
2001-12-30 20:26:11 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*ptr = '\0';
|
|
|
|
var = str; ngt_TrimStr( var );
|
|
|
|
arg = ptr + 1; ngt_TrimStr( arg );
|
2002-01-02 03:44:36 +01:00
|
|
|
|
|
|
|
if( strcasecmp( section, "[GLOBAL]" ) == 0 ) Handle_GLOBAL( line, var, arg );
|
2011-01-09 19:42:42 +01:00
|
|
|
else if( strcasecmp( section, "[FEATURES]" ) == 0 ) Handle_FEATURES( line, var, arg );
|
2002-01-02 03:44:36 +01:00
|
|
|
else if( strcasecmp( section, "[OPERATOR]" ) == 0 ) Handle_OPERATOR( line, var, arg );
|
|
|
|
else if( strcasecmp( section, "[SERVER]" ) == 0 ) Handle_SERVER( line, var, arg );
|
2002-05-21 02:10:16 +02:00
|
|
|
else if( strcasecmp( section, "[CHANNEL]" ) == 0 ) Handle_CHANNEL( line, var, arg );
|
2002-03-27 17:39:22 +01:00
|
|
|
else Config_Error( LOG_ERR, "%s, line %d: Variable \"%s\" outside section!", NGIRCd_ConfFile, line, var );
|
2002-01-02 03:44:36 +01:00
|
|
|
}
|
2002-12-30 01:01:42 +01:00
|
|
|
|
|
|
|
/* Close configuration file */
|
2002-01-02 03:44:36 +01:00
|
|
|
fclose( fd );
|
2002-12-30 01:01:42 +01:00
|
|
|
|
|
|
|
/* Check if there is still a server to add */
|
2005-09-11 01:42:12 +02:00
|
|
|
if( New_Server.name[0] ) {
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Copy data to "real" server structure */
|
|
|
|
assert( New_Server_Idx > NONE );
|
|
|
|
Conf_Server[New_Server_Idx] = New_Server;
|
|
|
|
}
|
2005-07-29 11:29:47 +02:00
|
|
|
|
2009-08-31 19:42:59 +02:00
|
|
|
/* not a single listening port? Add default. */
|
|
|
|
if (no_listenports() &&
|
|
|
|
!array_copyb(&Conf_ListenPorts, (char*) &defaultport, sizeof defaultport))
|
|
|
|
{
|
|
|
|
Config_Error(LOG_ALERT, "Could not add default listening Port %u: %s",
|
|
|
|
(unsigned int) defaultport, strerror(errno));
|
|
|
|
|
|
|
|
exit(1);
|
2002-03-30 14:08:10 +01:00
|
|
|
}
|
2008-05-19 00:12:41 +02:00
|
|
|
|
2008-05-19 14:34:48 +02:00
|
|
|
if (!Conf_ListenAddress)
|
|
|
|
Conf_ListenAddress = strdup_warn(DEFAULT_LISTEN_ADDRSTR);
|
|
|
|
|
2008-05-19 00:12:41 +02:00
|
|
|
if (!Conf_ListenAddress) {
|
|
|
|
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
|
|
|
|
exit(1);
|
|
|
|
}
|
2010-08-11 22:52:06 +02:00
|
|
|
|
|
|
|
/* No MOTD phrase configured? (re)try motd file. */
|
|
|
|
if (array_bytes(&Conf_Motd) == 0)
|
|
|
|
Read_Motd(Conf_MotdFile);
|
2008-03-18 21:12:47 +01:00
|
|
|
return true;
|
2002-01-02 03:44:36 +01:00
|
|
|
} /* Read_Config */
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static bool
|
2005-03-15 17:56:16 +01:00
|
|
|
Check_ArgIsTrue( const char *Arg )
|
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
if( strcasecmp( Arg, "yes" ) == 0 ) return true;
|
|
|
|
if( strcasecmp( Arg, "true" ) == 0 ) return true;
|
|
|
|
if( atoi( Arg ) != 0 ) return true;
|
2005-03-15 17:56:16 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
return false;
|
2005-03-15 17:56:16 +01:00
|
|
|
} /* Check_ArgIsTrue */
|
|
|
|
|
|
|
|
|
2010-10-24 21:48:32 +02:00
|
|
|
static unsigned int
|
|
|
|
Handle_MaxNickLength(int Line, const char *Arg)
|
2007-11-21 13:16:33 +01:00
|
|
|
{
|
|
|
|
unsigned new;
|
|
|
|
|
|
|
|
new = (unsigned) atoi(Arg) + 1;
|
|
|
|
if (new > CLIENT_NICK_LEN) {
|
|
|
|
Config_Error(LOG_WARNING,
|
|
|
|
"%s, line %d: Value of \"MaxNickLength\" exceeds %u!",
|
|
|
|
NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1);
|
|
|
|
return CLIENT_NICK_LEN;
|
|
|
|
}
|
|
|
|
if (new < 2) {
|
|
|
|
Config_Error(LOG_WARNING,
|
|
|
|
"%s, line %d: Value of \"MaxNickLength\" must be at least 1!",
|
|
|
|
NGIRCd_ConfFile, Line);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return new;
|
|
|
|
} /* Handle_MaxNickLength */
|
|
|
|
|
|
|
|
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
static void
|
2011-01-09 17:54:21 +01:00
|
|
|
WarnIdent(int UNUSED Line)
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
{
|
|
|
|
#ifndef IDENTAUTH
|
|
|
|
if (Conf_Ident) {
|
|
|
|
/* user has enabled ident lookups explicitly, but ... */
|
|
|
|
Config_Error(LOG_WARNING,
|
2011-01-09 18:17:35 +01:00
|
|
|
"%s: line %d: %s=True, but ngircd was built without support",
|
|
|
|
NGIRCd_ConfFile, Line, "Ident");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
WarnPAM(int UNUSED Line)
|
|
|
|
{
|
|
|
|
#ifndef PAM
|
|
|
|
if (Conf_PAM) {
|
|
|
|
Config_Error(LOG_WARNING,
|
|
|
|
"%s: line %d: %s=True, but ngircd was built without support",
|
|
|
|
NGIRCd_ConfFile, Line, "PAM");
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool
|
|
|
|
CheckLegacyNoOption(const char *Var, const char *Arg)
|
|
|
|
{
|
|
|
|
if( strcasecmp( Var, "NoDNS" ) == 0 ) {
|
|
|
|
Conf_DNS = !Check_ArgIsTrue( Arg );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (strcasecmp(Var, "NoIdent") == 0) {
|
|
|
|
Conf_Ident = !Check_ArgIsTrue(Arg);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if(strcasecmp(Var, "NoPAM") == 0) {
|
|
|
|
Conf_PAM = !Check_ArgIsTrue(Arg);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-01-09 17:54:21 +01:00
|
|
|
static const char *
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
NoNo(const char *str)
|
|
|
|
{
|
|
|
|
assert(strncasecmp("no", str, 2) == 0 && str[2]);
|
|
|
|
return str + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
InvertArg(const char *arg)
|
|
|
|
{
|
|
|
|
return yesno_to_str(!Check_ArgIsTrue(arg));
|
|
|
|
}
|
2010-08-11 22:52:06 +02:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2005-03-19 19:43:48 +01:00
|
|
|
Handle_GLOBAL( int Line, char *Var, char *Arg )
|
2002-01-02 03:44:36 +01:00
|
|
|
{
|
2002-11-09 00:09:26 +01:00
|
|
|
struct passwd *pwd;
|
|
|
|
struct group *grp;
|
2005-09-11 01:42:12 +02:00
|
|
|
size_t len;
|
2002-01-02 03:44:36 +01:00
|
|
|
|
|
|
|
assert( Line > 0 );
|
|
|
|
assert( Var != NULL );
|
|
|
|
assert( Arg != NULL );
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "Name" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Server name */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerName, Arg, sizeof( Conf_ServerName ));
|
|
|
|
if (len >= sizeof( Conf_ServerName ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "Info" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Info text of server */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerInfo, Arg, sizeof( Conf_ServerInfo ));
|
|
|
|
if (len >= sizeof( Conf_ServerInfo ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong ( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "Password" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Global server password */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerPwd, Arg, sizeof( Conf_ServerPwd ));
|
|
|
|
if (len >= sizeof( Conf_ServerPwd ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-01-03 03:27:20 +01:00
|
|
|
return;
|
|
|
|
}
|
2010-02-11 00:01:53 +01:00
|
|
|
if (strcasecmp(Var, "WebircPassword") == 0) {
|
|
|
|
/* Password required for WEBIRC command */
|
|
|
|
len = strlcpy(Conf_WebircPwd, Arg, sizeof(Conf_WebircPwd));
|
|
|
|
if (len >= sizeof(Conf_WebircPwd))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "AdminInfo1" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Administrative info #1 */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerAdmin1, Arg, sizeof( Conf_ServerAdmin1 ));
|
|
|
|
if (len >= sizeof( Conf_ServerAdmin1 ))
|
|
|
|
Config_Error_TooLong ( Line, Var );
|
2002-09-16 11:13:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "AdminInfo2" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Administrative info #2 */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerAdmin2, Arg, sizeof( Conf_ServerAdmin2 ));
|
|
|
|
if (len >= sizeof( Conf_ServerAdmin2 ))
|
|
|
|
Config_Error_TooLong ( Line, Var );
|
2002-09-16 11:13:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "AdminEMail" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Administrative email contact */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_ServerAdminMail, Arg, sizeof( Conf_ServerAdminMail ));
|
|
|
|
if (len >= sizeof( Conf_ServerAdminMail ))
|
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-09-16 11:13:06 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-07-29 11:29:47 +02:00
|
|
|
|
|
|
|
if( strcasecmp( Var, "Ports" ) == 0 ) {
|
|
|
|
ports_parse(&Conf_ListenPorts, Line, Arg);
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "MotdFile" ) == 0 ) {
|
|
|
|
len = strlcpy( Conf_MotdFile, Arg, sizeof( Conf_MotdFile ));
|
|
|
|
if (len >= sizeof( Conf_MotdFile ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "MotdPhrase" ) == 0 ) {
|
2004-05-07 13:19:20 +02:00
|
|
|
/* "Message of the day" phrase (instead of file) */
|
2010-08-11 22:52:06 +02:00
|
|
|
len = strlen(Arg);
|
|
|
|
if (len == 0)
|
|
|
|
return;
|
|
|
|
if (len >= LINE_LEN) {
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2010-08-11 22:52:06 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!array_copyb(&Conf_Motd, Arg, len + 1))
|
|
|
|
Config_Error(LOG_WARNING, "%s, line %d: Could not append MotdPhrase: %s",
|
|
|
|
NGIRCd_ConfFile, Line, strerror(errno));
|
2010-12-02 16:51:21 +01:00
|
|
|
Using_MotdFile = false;
|
2004-05-07 13:19:20 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "ChrootDir" ) == 0 ) {
|
2004-05-07 13:19:20 +02:00
|
|
|
/* directory for chroot() */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_Chroot, Arg, sizeof( Conf_Chroot ));
|
|
|
|
if (len >= sizeof( Conf_Chroot ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2004-05-07 13:19:20 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if ( strcasecmp( Var, "PidFile" ) == 0 ) {
|
2005-02-04 15:24:20 +01:00
|
|
|
/* name of pidfile */
|
2005-09-11 01:42:12 +02:00
|
|
|
len = strlcpy( Conf_PidFile, Arg, sizeof( Conf_PidFile ));
|
|
|
|
if (len >= sizeof( Conf_PidFile ))
|
2005-02-04 15:24:20 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "ServerUID" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* UID the daemon should switch to */
|
2002-11-09 00:09:26 +01:00
|
|
|
pwd = getpwnam( Arg );
|
|
|
|
if( pwd ) Conf_UID = pwd->pw_uid;
|
2005-09-11 01:42:12 +02:00
|
|
|
else {
|
2005-03-19 19:43:48 +01:00
|
|
|
Conf_UID = (unsigned int)atoi( Arg );
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!Conf_UID && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN(Line, Var);
|
2002-11-30 23:15:49 +01:00
|
|
|
}
|
2002-03-30 00:33:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "ServerGID" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* GID the daemon should use */
|
2002-11-09 00:09:26 +01:00
|
|
|
grp = getgrnam( Arg );
|
|
|
|
if( grp ) Conf_GID = grp->gr_gid;
|
2005-09-11 01:42:12 +02:00
|
|
|
else {
|
2011-01-18 22:41:27 +01:00
|
|
|
Conf_GID = (unsigned int)atoi(Arg);
|
|
|
|
if (!Conf_GID && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN( Line, Var );
|
2002-11-30 23:15:49 +01:00
|
|
|
}
|
2002-03-30 00:33:05 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "PingTimeout" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* PING timeout */
|
2002-01-02 03:44:36 +01:00
|
|
|
Conf_PingTimeout = atoi( Arg );
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_PingTimeout < 5 ) {
|
|
|
|
Config_Error( LOG_WARNING, "%s, line %d: Value of \"PingTimeout\" too low!",
|
|
|
|
NGIRCd_ConfFile, Line );
|
2002-11-30 23:15:49 +01:00
|
|
|
Conf_PingTimeout = 5;
|
|
|
|
}
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "PongTimeout" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* PONG timeout */
|
2002-01-02 03:44:36 +01:00
|
|
|
Conf_PongTimeout = atoi( Arg );
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_PongTimeout < 5 ) {
|
|
|
|
Config_Error( LOG_WARNING, "%s, line %d: Value of \"PongTimeout\" too low!",
|
|
|
|
NGIRCd_ConfFile, Line );
|
2002-11-30 23:15:49 +01:00
|
|
|
Conf_PongTimeout = 5;
|
|
|
|
}
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "ConnectRetry" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Seconds between connection attempts to other servers */
|
2002-01-02 03:44:36 +01:00
|
|
|
Conf_ConnectRetry = atoi( Arg );
|
2005-09-11 01:42:12 +02:00
|
|
|
if( Conf_ConnectRetry < 5 ) {
|
|
|
|
Config_Error( LOG_WARNING, "%s, line %d: Value of \"ConnectRetry\" too low!",
|
|
|
|
NGIRCd_ConfFile, Line );
|
2002-11-30 23:15:49 +01:00
|
|
|
Conf_ConnectRetry = 5;
|
|
|
|
}
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2006-11-05 14:03:46 +01:00
|
|
|
if( strcasecmp( Var, "PredefChannelsOnly" ) == 0 ) {
|
|
|
|
/* Should we only allow pre-defined-channels? (i.e. users cannot create their own channels) */
|
|
|
|
Conf_PredefChannelsOnly = Check_ArgIsTrue( Arg );
|
|
|
|
return;
|
|
|
|
}
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
|
|
|
|
if (CheckLegacyNoOption(Var, Arg)) {
|
|
|
|
Config_Error(LOG_WARNING, "%s, line %d: \"No\"-Prefix has been removed, use "
|
2011-01-09 19:42:42 +01:00
|
|
|
"\"%s = %s\" in [FEATURES] section instead",
|
config: deprecate NoXX-Options
ngircd unfortunately uses several options using double-negation, e.g.
NoIdent = No, NoPam = No, etc.
This renames all options by dropping the "No" prefix, e.g.
"NoIdent = no" becomes "Ident = yes".
The old options will continue to work, but will cause a warning
message.
Also update man pages and default config.
To prevent silly
'Ident = yes' from appearing in --configtest output in the
'ident support not compiled in and Ident Option not used' case,
make default value depend on feature availability.
If feature is available, enable by default, otherwise disable.
We might consider moving these options to a new
[Feature]
section, or something like that, because none of these options are
essential.
Another possible improvement:
'Ident = yes' option in ngircd.conf causes a warning if ngircd was
built without ident support.
This does not happen with e.g. zeroconf....
2011-01-08 15:56:14 +01:00
|
|
|
NGIRCd_ConfFile, Line, NoNo(Var), InvertArg(Arg));
|
|
|
|
if (strcasecmp(Var, "NoIdent") == 0)
|
|
|
|
WarnIdent(Line);
|
2011-01-09 18:17:35 +01:00
|
|
|
else if (strcasecmp(Var, "NoPam") == 0)
|
|
|
|
WarnPAM(Line);
|
2007-10-25 13:01:19 +02:00
|
|
|
return;
|
|
|
|
}
|
2008-04-21 00:45:19 +02:00
|
|
|
#ifdef WANT_IPV6
|
|
|
|
/* the default setting for all the WANT_IPV6 special options is 'true' */
|
|
|
|
if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
|
|
|
|
/* connect to other hosts using ipv6, if they have an AAAA record? */
|
|
|
|
Conf_ConnectIPv6 = Check_ArgIsTrue( Arg );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( strcasecmp( Var, "ConnectIPv4" ) == 0 ) {
|
|
|
|
/* connect to other hosts using ipv4.
|
|
|
|
* again, this can be used for ipv6-only setups */
|
|
|
|
Conf_ConnectIPv4 = Check_ArgIsTrue( Arg );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Are IRC operators allowed to use MODE in channels they aren't Op in? */
|
2005-03-15 17:56:16 +01:00
|
|
|
Conf_OperCanMode = Check_ArgIsTrue( Arg );
|
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "OperServerMode" ) == 0 ) {
|
2005-03-15 17:56:16 +01:00
|
|
|
/* Mask IRC operator as if coming from the server? (ircd-irc2 compat hack) */
|
|
|
|
Conf_OperServerMode = Check_ArgIsTrue( Arg );
|
2002-09-02 16:59:17 +02:00
|
|
|
return;
|
|
|
|
}
|
2008-04-13 16:39:08 +02:00
|
|
|
if(strcasecmp(Var, "AllowRemoteOper") == 0) {
|
|
|
|
/* Are remote IRC operators allowed to control this server? */
|
|
|
|
Conf_AllowRemoteOper = Check_ArgIsTrue(Arg);
|
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "MaxConnections" ) == 0 ) {
|
2007-10-13 21:11:06 +02:00
|
|
|
/* Maximum number of connections. 0 -> "no limit". */
|
2002-11-02 23:59:01 +01:00
|
|
|
Conf_MaxConnections = atol( Arg );
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!Conf_MaxConnections && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN(Line, Var);
|
2002-11-02 23:59:01 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "MaxConnectionsIP" ) == 0 ) {
|
2007-10-13 21:11:06 +02:00
|
|
|
/* Maximum number of simultaneous connections from one IP. 0 -> "no limit" */
|
2003-11-05 22:41:01 +01:00
|
|
|
Conf_MaxConnectionsIP = atoi( Arg );
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!Conf_MaxConnectionsIP && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN(Line, Var);
|
2003-11-05 22:41:01 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "MaxJoins" ) == 0 ) {
|
2007-10-13 21:11:06 +02:00
|
|
|
/* Maximum number of channels a user can join. 0 -> "no limit". */
|
2002-12-13 18:32:33 +01:00
|
|
|
Conf_MaxJoins = atoi( Arg );
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!Conf_MaxJoins && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN(Line, Var);
|
2002-12-13 18:32:33 +01:00
|
|
|
return;
|
|
|
|
}
|
2007-11-21 13:16:33 +01:00
|
|
|
if( strcasecmp( Var, "MaxNickLength" ) == 0 ) {
|
|
|
|
/* Maximum length of a nick name; must be same on all servers
|
|
|
|
* within the IRC network! */
|
|
|
|
Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "Listen" ) == 0 ) {
|
2003-09-11 14:05:28 +02:00
|
|
|
/* IP-Address to bind sockets */
|
2008-05-19 00:12:41 +02:00
|
|
|
if (Conf_ListenAddress) {
|
|
|
|
Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Conf_ListenAddress = strdup_warn(Arg);
|
|
|
|
/*
|
|
|
|
* if allocation fails, we're in trouble:
|
|
|
|
* we cannot ignore the error -- otherwise ngircd
|
|
|
|
* would listen on all interfaces.
|
|
|
|
*/
|
|
|
|
if (!Conf_ListenAddress) {
|
|
|
|
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
|
|
|
|
exit(1);
|
|
|
|
}
|
2003-11-05 22:41:01 +01:00
|
|
|
return;
|
2003-09-11 14:05:28 +02:00
|
|
|
}
|
2008-09-13 15:10:32 +02:00
|
|
|
|
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
if( strcasecmp( Var, "SSLPorts" ) == 0 ) {
|
|
|
|
ports_parse(&Conf_SSLOptions.ListenPorts, Line, Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( strcasecmp( Var, "SSLKeyFile" ) == 0 ) {
|
|
|
|
assert(Conf_SSLOptions.KeyFile == NULL );
|
|
|
|
Conf_SSLOptions.KeyFile = strdup_warn(Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( strcasecmp( Var, "SSLCertFile" ) == 0 ) {
|
|
|
|
assert(Conf_SSLOptions.CertFile == NULL );
|
|
|
|
Conf_SSLOptions.CertFile = strdup_warn(Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( strcasecmp( Var, "SSLKeyFilePassword" ) == 0 ) {
|
|
|
|
assert(array_bytes(&Conf_SSLOptions.KeyFilePassword) == 0);
|
|
|
|
if (!array_copys(&Conf_SSLOptions.KeyFilePassword, Arg))
|
|
|
|
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Could not copy %s: %s!",
|
|
|
|
NGIRCd_ConfFile, Line, Var, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( strcasecmp( Var, "SSLDHFile" ) == 0 ) {
|
|
|
|
assert(Conf_SSLOptions.DHFile == NULL);
|
|
|
|
Conf_SSLOptions.DHFile = strdup_warn( Arg );
|
|
|
|
return;
|
|
|
|
}
|
2010-09-24 17:39:11 +02:00
|
|
|
#endif
|
|
|
|
#ifdef SYSLOG
|
|
|
|
if (strcasecmp(Var, "SyslogFacility") == 0) {
|
|
|
|
Conf_SyslogFacility = ngt_SyslogFacilityID(Arg,
|
|
|
|
Conf_SyslogFacility);
|
|
|
|
return;
|
|
|
|
}
|
2008-09-13 15:10:32 +02:00
|
|
|
#endif
|
2008-05-19 00:12:41 +02:00
|
|
|
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
|
|
|
|
NGIRCd_ConfFile, Line, Var);
|
2002-01-02 03:44:36 +01:00
|
|
|
} /* Handle_GLOBAL */
|
|
|
|
|
|
|
|
|
2011-01-09 19:42:42 +01:00
|
|
|
static void
|
|
|
|
Handle_FEATURES(int Line, char *Var, char *Arg)
|
|
|
|
{
|
|
|
|
assert( Line > 0 );
|
|
|
|
assert( Var != NULL );
|
|
|
|
assert( Arg != NULL );
|
|
|
|
|
|
|
|
if( strcasecmp( Var, "DNS" ) == 0 ) {
|
|
|
|
/* do reverse dns lookups when clients connect? */
|
|
|
|
Conf_DNS = Check_ArgIsTrue( Arg );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (strcasecmp(Var, "Ident") == 0) {
|
|
|
|
/* do IDENT lookups when clients connect? */
|
|
|
|
Conf_Ident = Check_ArgIsTrue(Arg);
|
|
|
|
WarnIdent(Line);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(strcasecmp(Var, "PAM") == 0) {
|
|
|
|
/* use PAM library to authenticate users */
|
|
|
|
Conf_PAM = Check_ArgIsTrue(Arg);
|
|
|
|
WarnPAM(Line);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2005-03-19 19:43:48 +01:00
|
|
|
Handle_OPERATOR( int Line, char *Var, char *Arg )
|
2002-01-02 03:44:36 +01:00
|
|
|
{
|
2005-07-17 20:58:04 +02:00
|
|
|
size_t len;
|
2009-11-07 12:14:37 +01:00
|
|
|
struct Conf_Oper *op;
|
|
|
|
|
2002-01-02 03:44:36 +01:00
|
|
|
assert( Line > 0 );
|
|
|
|
assert( Var != NULL );
|
|
|
|
assert( Arg != NULL );
|
|
|
|
assert( Conf_Oper_Count > 0 );
|
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
op = array_alloc(&Conf_Opers, sizeof(*op), Conf_Oper_Count - 1);
|
|
|
|
if (!op) {
|
|
|
|
Config_Error(LOG_ERR, "Could not allocate memory for operator (%d:%s = %s)", Line, Var, Arg);
|
2005-07-17 20:58:04 +02:00
|
|
|
return;
|
2009-11-07 12:14:37 +01:00
|
|
|
}
|
2005-07-17 20:58:04 +02:00
|
|
|
|
2009-11-07 12:14:37 +01:00
|
|
|
if (strcasecmp(Var, "Name") == 0) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Name of IRC operator */
|
2009-11-07 12:14:37 +01:00
|
|
|
len = strlcpy(op->name, Arg, sizeof(op->name));
|
|
|
|
if (len >= sizeof(op->name))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2009-11-07 12:14:37 +01:00
|
|
|
if (strcasecmp(Var, "Password") == 0) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Password of IRC operator */
|
2009-11-07 12:14:37 +01:00
|
|
|
len = strlcpy(op->pwd, Arg, sizeof(op->pwd));
|
|
|
|
if (len >= sizeof(op->pwd))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
2001-12-30 20:26:11 +01:00
|
|
|
}
|
2009-11-07 12:14:37 +01:00
|
|
|
if (strcasecmp(Var, "Mask") == 0) {
|
|
|
|
if (op->mask)
|
|
|
|
return; /* Hostname already configured */
|
|
|
|
op->mask = strdup_warn( Arg );
|
2005-03-02 17:07:30 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-07-17 20:58:04 +02:00
|
|
|
Config_Error( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!",
|
|
|
|
NGIRCd_ConfFile, Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
} /* Handle_OPERATOR */
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2005-03-19 19:43:48 +01:00
|
|
|
Handle_SERVER( int Line, char *Var, char *Arg )
|
2002-01-02 03:44:36 +01:00
|
|
|
{
|
2005-03-19 19:43:48 +01:00
|
|
|
long port;
|
2005-09-02 15:50:52 +02:00
|
|
|
size_t len;
|
2002-01-02 03:44:36 +01:00
|
|
|
|
|
|
|
assert( Line > 0 );
|
|
|
|
assert( Var != NULL );
|
|
|
|
assert( Arg != NULL );
|
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
/* Ignore server block if no space is left in server configuration structure */
|
|
|
|
if( New_Server_Idx <= NONE ) return;
|
|
|
|
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "Host" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Hostname of the server */
|
2005-09-02 15:50:52 +02:00
|
|
|
len = strlcpy( New_Server.host, Arg, sizeof( New_Server.host ));
|
|
|
|
if (len >= sizeof( New_Server.host ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong ( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "Name" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Name of the server ("Nick"/"ID") */
|
2005-09-02 15:50:52 +02:00
|
|
|
len = strlcpy( New_Server.name, Arg, sizeof( New_Server.name ));
|
|
|
|
if (len >= sizeof( New_Server.name ))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2007-11-23 17:26:03 +01:00
|
|
|
if (strcasecmp(Var, "Bind") == 0) {
|
2008-02-26 23:50:35 +01:00
|
|
|
if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0))
|
2007-11-23 17:26:03 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
|
|
|
|
NGIRCd_ConfFile, Line, Arg);
|
|
|
|
return;
|
|
|
|
}
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "MyPassword" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Password of this server which is sent to the peer */
|
2005-09-02 15:58:52 +02:00
|
|
|
if (*Arg == ':') {
|
|
|
|
Config_Error(LOG_ERR,
|
|
|
|
"%s, line %d (section \"Server\"): MyPassword must not start with ':'!",
|
|
|
|
NGIRCd_ConfFile, Line);
|
|
|
|
}
|
2005-09-02 15:50:52 +02:00
|
|
|
len = strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in ));
|
|
|
|
if (len >= sizeof( New_Server.pwd_in ))
|
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-11-19 13:50:20 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "PeerPassword" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Passwort of the peer which must be received */
|
2005-09-02 15:50:52 +02:00
|
|
|
len = strlcpy( New_Server.pwd_out, Arg, sizeof( New_Server.pwd_out ));
|
|
|
|
if (len >= sizeof( New_Server.pwd_out ))
|
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "Port" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Port to which this server should connect */
|
2002-01-02 03:44:36 +01:00
|
|
|
port = atol( Arg );
|
2011-01-18 22:45:01 +01:00
|
|
|
if (port >= 0 && port < 0xFFFF)
|
2005-09-02 15:50:52 +02:00
|
|
|
New_Server.port = (UINT16)port;
|
|
|
|
else
|
2011-01-18 22:45:01 +01:00
|
|
|
Config_Error(LOG_ERR,
|
|
|
|
"%s, line %d (section \"Server\"): Illegal port number %ld!",
|
|
|
|
NGIRCd_ConfFile, Line, port );
|
2002-01-02 03:44:36 +01:00
|
|
|
return;
|
|
|
|
}
|
2008-09-13 15:10:32 +02:00
|
|
|
#ifdef SSL_SUPPORT
|
|
|
|
if( strcasecmp( Var, "SSLConnect" ) == 0 ) {
|
|
|
|
New_Server.SSLConnect = Check_ArgIsTrue(Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2005-09-02 15:50:52 +02:00
|
|
|
if( strcasecmp( Var, "Group" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Server group */
|
2002-12-30 01:01:42 +01:00
|
|
|
New_Server.group = atoi( Arg );
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!New_Server.group && strcmp(Arg, "0"))
|
|
|
|
Config_Error_NaN(Line, Var);
|
2002-03-10 18:50:48 +01:00
|
|
|
return;
|
|
|
|
}
|
2007-06-28 07:15:12 +02:00
|
|
|
if( strcasecmp( Var, "Passive" ) == 0 ) {
|
|
|
|
if (Check_ArgIsTrue(Arg))
|
|
|
|
New_Server.flags |= CONF_SFLAG_DISABLED;
|
|
|
|
return;
|
|
|
|
}
|
2008-08-16 02:36:30 +02:00
|
|
|
if (strcasecmp(Var, "ServiceMask") == 0) {
|
|
|
|
len = strlcpy(New_Server.svs_mask, ngt_LowerStr(Arg),
|
|
|
|
sizeof(New_Server.svs_mask));
|
|
|
|
if (len >= sizeof(New_Server.svs_mask))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
|
|
|
return;
|
|
|
|
}
|
2008-11-24 22:59:10 +01:00
|
|
|
|
2005-09-02 15:50:52 +02:00
|
|
|
Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!",
|
|
|
|
NGIRCd_ConfFile, Line, Var );
|
2002-01-02 03:44:36 +01:00
|
|
|
} /* Handle_SERVER */
|
2001-12-26 23:48:53 +01:00
|
|
|
|
|
|
|
|
2006-11-20 20:32:07 +01:00
|
|
|
static bool
|
2008-11-24 22:59:10 +01:00
|
|
|
Handle_Channelname(struct Conf_Channel *new_chan, const char *name)
|
2006-11-20 20:32:07 +01:00
|
|
|
{
|
2008-11-24 22:59:10 +01:00
|
|
|
size_t size = sizeof(new_chan->name);
|
|
|
|
char *dest = new_chan->name;
|
2006-11-20 20:32:07 +01:00
|
|
|
|
2009-03-07 00:21:43 +01:00
|
|
|
if (!Channel_IsValidName(name)) {
|
|
|
|
/*
|
|
|
|
* maybe user forgot to add a '#'.
|
|
|
|
* This is only here for user convenience.
|
|
|
|
*/
|
2006-11-20 20:32:07 +01:00
|
|
|
*dest = '#';
|
|
|
|
--size;
|
|
|
|
++dest;
|
|
|
|
}
|
|
|
|
return size > strlcpy(dest, name, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2008-11-24 22:59:10 +01:00
|
|
|
Handle_CHANNEL(int Line, char *Var, char *Arg)
|
2002-05-21 02:10:16 +02:00
|
|
|
{
|
2005-09-11 01:42:12 +02:00
|
|
|
size_t len;
|
2008-11-24 22:59:10 +01:00
|
|
|
size_t chancount;
|
|
|
|
struct Conf_Channel *chan;
|
2005-09-11 01:42:12 +02:00
|
|
|
|
2002-05-21 02:10:16 +02:00
|
|
|
assert( Line > 0 );
|
|
|
|
assert( Var != NULL );
|
|
|
|
assert( Arg != NULL );
|
2008-11-24 22:59:10 +01:00
|
|
|
assert(Conf_Channel_Count > 0);
|
2002-05-21 02:10:16 +02:00
|
|
|
|
2008-11-24 22:59:10 +01:00
|
|
|
chancount = Conf_Channel_Count - 1;
|
|
|
|
|
|
|
|
chan = array_alloc(&Conf_Channels, sizeof(*chan), chancount);
|
|
|
|
if (!chan) {
|
|
|
|
Config_Error(LOG_ERR, "Could not allocate memory for predefined channel (%d:%s = %s)", Line, Var, Arg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (strcasecmp(Var, "Name") == 0) {
|
|
|
|
if (!Handle_Channelname(chan, Arg))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
2002-05-21 02:10:16 +02:00
|
|
|
return;
|
|
|
|
}
|
2008-11-24 22:59:10 +01:00
|
|
|
if (strcasecmp(Var, "Modes") == 0) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Initial modes */
|
2008-11-24 22:59:10 +01:00
|
|
|
len = strlcpy(chan->modes, Arg, sizeof(chan->modes));
|
|
|
|
if (len >= sizeof(chan->modes))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-05-21 02:10:16 +02:00
|
|
|
return;
|
|
|
|
}
|
2005-09-11 01:42:12 +02:00
|
|
|
if( strcasecmp( Var, "Topic" ) == 0 ) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Initial topic */
|
2008-11-24 22:59:10 +01:00
|
|
|
len = strlcpy(chan->topic, Arg, sizeof(chan->topic));
|
|
|
|
if (len >= sizeof(chan->topic))
|
2005-01-20 01:13:08 +01:00
|
|
|
Config_Error_TooLong( Line, Var );
|
2002-05-21 02:10:16 +02:00
|
|
|
return;
|
|
|
|
}
|
2006-12-29 15:09:48 +01:00
|
|
|
if( strcasecmp( Var, "Key" ) == 0 ) {
|
|
|
|
/* Initial Channel Key (mode k) */
|
2008-11-24 22:59:10 +01:00
|
|
|
len = strlcpy(chan->key, Arg, sizeof(chan->key));
|
|
|
|
if (len >= sizeof(chan->key))
|
2006-12-29 15:09:48 +01:00
|
|
|
Config_Error_TooLong(Line, Var);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( strcasecmp( Var, "MaxUsers" ) == 0 ) {
|
|
|
|
/* maximum user limit, mode l */
|
2008-11-24 22:59:10 +01:00
|
|
|
chan->maxusers = (unsigned long) atol(Arg);
|
2011-01-18 22:41:27 +01:00
|
|
|
if (!chan->maxusers && strcmp(Arg, "0"))
|
2006-12-29 15:09:48 +01:00
|
|
|
Config_Error_NaN(Line, Var);
|
|
|
|
return;
|
|
|
|
}
|
2009-01-01 22:26:13 +01:00
|
|
|
if (strcasecmp(Var, "KeyFile") == 0) {
|
|
|
|
/* channel keys */
|
|
|
|
len = strlcpy(chan->keyfile, Arg, sizeof(chan->keyfile));
|
|
|
|
if (len >= sizeof(chan->keyfile))
|
|
|
|
Config_Error_TooLong(Line, Var);
|
|
|
|
return;
|
|
|
|
}
|
2006-12-29 15:09:48 +01:00
|
|
|
|
2005-09-11 01:42:12 +02:00
|
|
|
Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!",
|
|
|
|
NGIRCd_ConfFile, Line, Var );
|
2002-05-21 02:10:16 +02:00
|
|
|
} /* Handle_CHANNEL */
|
|
|
|
|
|
|
|
|
2008-05-28 00:31:20 +02:00
|
|
|
static bool
|
2006-07-23 18:42:45 +02:00
|
|
|
Validate_Config(bool Configtest, bool Rehash)
|
2001-12-30 20:26:11 +01:00
|
|
|
{
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Validate configuration settings. */
|
2002-12-30 01:01:42 +01:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
2005-03-19 19:43:48 +01:00
|
|
|
int i, servers, servers_once;
|
2002-12-30 01:01:42 +01:00
|
|
|
#endif
|
2008-05-28 00:31:20 +02:00
|
|
|
bool config_valid = true;
|
2006-07-23 18:42:45 +02:00
|
|
|
char *ptr;
|
|
|
|
|
|
|
|
/* Validate configured server name, see RFC 2812 section 2.3.1 */
|
|
|
|
ptr = Conf_ServerName;
|
|
|
|
do {
|
|
|
|
if (*ptr >= 'a' && *ptr <= 'z') continue;
|
|
|
|
if (*ptr >= 'A' && *ptr <= 'Z') continue;
|
2006-11-10 11:05:00 +01:00
|
|
|
if (*ptr >= '0' && *ptr <= '9') continue;
|
2006-07-23 18:42:45 +02:00
|
|
|
if (ptr > Conf_ServerName) {
|
|
|
|
if (*ptr == '.' || *ptr == '-')
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Conf_ServerName[0] = '\0';
|
|
|
|
break;
|
|
|
|
} while (*(++ptr));
|
2002-12-30 01:01:42 +01:00
|
|
|
|
2006-07-23 18:42:45 +02:00
|
|
|
if (!Conf_ServerName[0]) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* No server name configured! */
|
2008-05-28 00:31:20 +02:00
|
|
|
config_valid = false;
|
2006-07-23 18:42:45 +02:00
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"No (valid) server name configured in \"%s\" (section 'Global': 'Name')!",
|
|
|
|
NGIRCd_ConfFile);
|
|
|
|
if (!Configtest && !Rehash) {
|
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"%s exiting due to fatal errors!",
|
|
|
|
PACKAGE_NAME);
|
|
|
|
exit(1);
|
2002-12-18 03:47:12 +01:00
|
|
|
}
|
2001-12-30 20:26:11 +01:00
|
|
|
}
|
2006-07-23 18:42:45 +02:00
|
|
|
|
|
|
|
if (Conf_ServerName[0] && !strchr(Conf_ServerName, '.')) {
|
2003-04-29 14:36:09 +02:00
|
|
|
/* No dot in server name! */
|
2008-05-28 00:31:20 +02:00
|
|
|
config_valid = false;
|
2006-07-23 18:42:45 +02:00
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"Invalid server name configured in \"%s\" (section 'Global': 'Name'): Dot missing!",
|
|
|
|
NGIRCd_ConfFile);
|
|
|
|
if (!Configtest) {
|
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"%s exiting due to fatal errors!",
|
|
|
|
PACKAGE_NAME);
|
|
|
|
exit(1);
|
2003-04-29 14:36:09 +02:00
|
|
|
}
|
|
|
|
}
|
2002-09-16 11:13:06 +02:00
|
|
|
|
|
|
|
#ifdef STRICT_RFC
|
2006-07-23 18:42:45 +02:00
|
|
|
if (!Conf_ServerAdminMail[0]) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* No administrative contact configured! */
|
2008-05-28 00:31:20 +02:00
|
|
|
config_valid = false;
|
2006-07-23 18:42:45 +02:00
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"No administrator email address configured in \"%s\" ('AdminEMail')!",
|
|
|
|
NGIRCd_ConfFile);
|
|
|
|
if (!Configtest) {
|
|
|
|
Config_Error(LOG_ALERT,
|
|
|
|
"%s exiting due to fatal errors!",
|
|
|
|
PACKAGE_NAME);
|
|
|
|
exit(1);
|
2002-12-18 03:47:12 +01:00
|
|
|
}
|
2002-09-16 11:13:06 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2006-07-23 18:42:45 +02:00
|
|
|
if (!Conf_ServerAdmin1[0] && !Conf_ServerAdmin2[0]
|
|
|
|
&& !Conf_ServerAdminMail[0]) {
|
2002-12-12 12:26:08 +01:00
|
|
|
/* No administrative information configured! */
|
2006-07-23 18:42:45 +02:00
|
|
|
Config_Error(LOG_WARNING,
|
|
|
|
"No administrative information configured but required by RFC!");
|
2002-09-16 11:13:06 +02:00
|
|
|
}
|
2006-07-23 18:42:45 +02:00
|
|
|
|
2010-07-11 17:01:45 +02:00
|
|
|
#ifdef PAM
|
|
|
|
if (Conf_ServerPwd[0])
|
|
|
|
Config_Error(LOG_ERR,
|
|
|
|
"This server uses PAM, \"Password\" will be ignored!");
|
|
|
|
#endif
|
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
#ifdef DEBUG
|
|
|
|
servers = servers_once = 0;
|
2006-07-23 18:42:45 +02:00
|
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
|
|
if (Conf_Server[i].name[0]) {
|
2002-12-30 01:01:42 +01:00
|
|
|
servers++;
|
2006-07-23 18:42:45 +02:00
|
|
|
if (Conf_Server[i].flags & CONF_SFLAG_ONCE)
|
|
|
|
servers_once++;
|
2002-12-30 01:01:42 +01:00
|
|
|
}
|
|
|
|
}
|
2006-07-23 18:42:45 +02:00
|
|
|
Log(LOG_DEBUG,
|
|
|
|
"Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
|
|
|
|
Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
|
2002-12-30 01:01:42 +01:00
|
|
|
#endif
|
2008-05-28 00:31:20 +02:00
|
|
|
|
|
|
|
return config_valid;
|
2001-12-30 20:26:11 +01:00
|
|
|
} /* Validate_Config */
|
|
|
|
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2005-03-19 16:46:38 +01:00
|
|
|
Config_Error_TooLong ( const int Line, const char *Item )
|
2005-01-20 01:13:08 +01:00
|
|
|
{
|
|
|
|
Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" too long!", NGIRCd_ConfFile, Line, Item );
|
|
|
|
}
|
|
|
|
|
2005-11-21 17:31:30 +01:00
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2005-03-19 16:46:38 +01:00
|
|
|
Config_Error_NaN( const int Line, const char *Item )
|
2005-01-20 01:13:08 +01:00
|
|
|
{
|
2005-09-11 01:42:12 +02:00
|
|
|
Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" is not a number!",
|
|
|
|
NGIRCd_ConfFile, Line, Item );
|
2005-01-20 01:13:08 +01:00
|
|
|
}
|
|
|
|
|
2005-11-21 17:31:30 +01:00
|
|
|
|
2002-05-30 18:52:20 +02:00
|
|
|
#ifdef PROTOTYPES
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Config_Error( const int Level, const char *Format, ... )
|
2002-05-30 18:52:20 +02:00
|
|
|
#else
|
2005-07-31 22:13:07 +02:00
|
|
|
static void Config_Error( Level, Format, va_alist )
|
2005-03-19 19:43:48 +01:00
|
|
|
const int Level;
|
|
|
|
const char *Format;
|
2002-05-30 18:52:20 +02:00
|
|
|
va_dcl
|
|
|
|
#endif
|
2002-03-27 17:39:22 +01:00
|
|
|
{
|
2002-12-12 12:26:08 +01:00
|
|
|
/* Error! Write to console and/or logfile. */
|
2002-03-27 17:39:22 +01:00
|
|
|
|
2005-03-19 19:43:48 +01:00
|
|
|
char msg[MAX_LOG_MSG_LEN];
|
2002-03-27 17:39:22 +01:00
|
|
|
va_list ap;
|
|
|
|
|
|
|
|
assert( Format != NULL );
|
|
|
|
|
2002-05-30 18:52:20 +02:00
|
|
|
#ifdef PROTOTYPES
|
2002-03-27 17:39:22 +01:00
|
|
|
va_start( ap, Format );
|
2002-05-30 18:52:20 +02:00
|
|
|
#else
|
|
|
|
va_start( ap );
|
|
|
|
#endif
|
2002-03-27 17:39:22 +01:00
|
|
|
vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap );
|
|
|
|
va_end( ap );
|
2002-12-12 12:26:08 +01:00
|
|
|
|
|
|
|
/* During "normal operations" the log functions of the daemon should
|
|
|
|
* be used, but during testing of the configuration file, all messages
|
|
|
|
* should go directly to the console: */
|
2005-09-11 01:42:12 +02:00
|
|
|
if (Use_Log) Log( Level, "%s", msg );
|
2002-03-27 17:39:22 +01:00
|
|
|
else puts( msg );
|
|
|
|
} /* Config_Error */
|
|
|
|
|
|
|
|
|
2008-04-09 19:03:24 +02:00
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
GLOBAL void
|
|
|
|
Conf_DebugDump(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
Log(LOG_DEBUG, "Configured servers:");
|
|
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
|
|
if (! Conf_Server[i].name[0])
|
|
|
|
continue;
|
|
|
|
Log(LOG_DEBUG,
|
|
|
|
" - %s: %s:%d, last=%ld, group=%d, flags=%d, conn=%d",
|
|
|
|
Conf_Server[i].name, Conf_Server[i].host,
|
|
|
|
Conf_Server[i].port, Conf_Server[i].lasttry,
|
|
|
|
Conf_Server[i].group, Conf_Server[i].flags,
|
|
|
|
Conf_Server[i].conn_id);
|
|
|
|
}
|
|
|
|
} /* Conf_DebugDump */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2005-07-31 22:13:07 +02:00
|
|
|
static void
|
2002-12-30 01:01:42 +01:00
|
|
|
Init_Server_Struct( CONF_SERVER *Server )
|
|
|
|
{
|
|
|
|
/* Initialize server configuration structur to default values */
|
|
|
|
|
|
|
|
assert( Server != NULL );
|
|
|
|
|
2005-01-20 01:13:08 +01:00
|
|
|
memset( Server, 0, sizeof (CONF_SERVER) );
|
|
|
|
|
2002-12-30 01:01:42 +01:00
|
|
|
Server->group = NONE;
|
|
|
|
Server->lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY;
|
2005-01-20 01:13:08 +01:00
|
|
|
|
2002-12-31 17:12:50 +01:00
|
|
|
if( NGIRCd_Passive ) Server->flags = CONF_SFLAG_DISABLED;
|
2005-01-20 01:13:08 +01:00
|
|
|
|
2010-05-18 17:38:12 +02:00
|
|
|
Proc_InitStruct(&Server->res_stat);
|
2002-12-30 01:01:42 +01:00
|
|
|
Server->conn_id = NONE;
|
2008-02-26 23:50:35 +01:00
|
|
|
memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
|
2002-12-30 01:01:42 +01:00
|
|
|
} /* Init_Server_Struct */
|
|
|
|
|
|
|
|
|
2001-12-12 18:18:20 +01:00
|
|
|
/* -eof- */
|