This repository has been archived on 2025-02-12. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
NeoStats/src/ircprotocol.c
2005-12-07 23:07:16 +00:00

393 lines
9.8 KiB
C

/* NeoStats - IRC Statistical Services
** Copyright (c) 1999-2005 Adam Rutter, Justin Hammond, Mark Hetherington
** http://www.neostats.net/
**
** Portions Copyright (c) 2000-2001 ^Enigma^
**
** 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.
**
** 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, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
** USA
**
** NeoStats CVS Identification
** $Id$
*/
#include "neostats.h"
#include "ircprotocol.h"
#include "protocol.h"
#include "ircsend.h"
#include "ircrecv.h"
#include "numerics.h"
#include "modes.h"
#include "dl.h"
#include "services.h"
ircd_server ircd_srv;
static char protocol_path[MAXPATH];
ProtocolInfo *protocol_info;
void *protocol_module_handle;
irc_cmd *cmd_list;
int (*irc_parse) (void *notused, void *rline, int len);
/** @brief process_ircd_cmd
*
* process ircd commands
*
* @param cmdptr source flag
* @param cmd command string
* @param origin of command
* @param av array of arguments
* @param ac count of args in av
*
* @return none
*/
void process_ircd_cmd( int cmdptr, const char *cmd, char *origin, char **av, int ac )
{
irc_cmd *ircd_cmd_ptr;
irc_cmd *intrinsic_cmd_ptr;
SET_SEGV_LOCATION();
ircd_cmd_ptr = cmd_list;
while( ircd_cmd_ptr->name )
{
if( ircstrcasecmp( *ircd_cmd_ptr->name, cmd ) == 0 ||
( ( ircd_srv.protocol & PROTOCOL_TOKEN ) && ircd_cmd_ptr->token && ircstrcasecmp( *ircd_cmd_ptr->token, cmd ) == 0 ) ) {
if( ircd_cmd_ptr->handler )
{
dlog( DEBUG3, "process_ircd_cmd: running command %s", *ircd_cmd_ptr->name );
ircd_cmd_ptr->handler( origin, av, ac, cmdptr );
}
else
{
dlog( DEBUG3, "process_ircd_cmd: ignoring command %s", cmd );
}
ircd_cmd_ptr->usage++;
return;
}
ircd_cmd_ptr ++;
}
intrinsic_cmd_ptr = intrinsic_cmd_list;
while( intrinsic_cmd_ptr->handler )
{
if( *intrinsic_cmd_ptr->name )
{
if( ircstrcasecmp( *intrinsic_cmd_ptr->name, cmd ) == 0 ||
( ( ircd_srv.protocol & PROTOCOL_TOKEN ) && *intrinsic_cmd_ptr->token && ircstrcasecmp( *intrinsic_cmd_ptr->token, cmd ) == 0 ) )
{
dlog( DEBUG3, "process_ircd_cmd: running command %s", *intrinsic_cmd_ptr->name );
intrinsic_cmd_ptr->handler( origin, av, ac, cmdptr );
intrinsic_cmd_ptr->usage++;
return;
}
}
intrinsic_cmd_ptr ++;
}
ircd_cmd_ptr = numeric_cmd_list;
/* Process numeric replies */
while( ircd_cmd_ptr->name )
{
if( ircstrcasecmp( *ircd_cmd_ptr->name, cmd ) == 0 )
{
if( ircd_cmd_ptr->handler ) {
dlog( DEBUG3, "process_ircd_cmd: running command %s", *ircd_cmd_ptr->name );
ircd_cmd_ptr->handler( origin, av, ac, cmdptr );
}
else
{
dlog( DEBUG3, "process_ircd_cmd: ignoring command %s", cmd );
}
ircd_cmd_ptr->usage++;
return;
}
ircd_cmd_ptr ++;
}
nlog( LOG_INFO, "No support for %s", cmd );
}
/** @brief parse
*
* parser
*
* @param notused
* @param rline
* @param len
*
* @return NS_SUCCESS if succeeds, NS_FAILURE if not
*/
static int parse( void *notused, void *rline, int len )
{
char origin[64], cmd[64], *coreLine;
char *line = (char *)rline;
int cmdptr = 0;
int ac = 0;
char **av = NULL;
SET_SEGV_LOCATION();
if( *line == '\0' )
return NS_FAILURE;
dlog( DEBUG1, "------------------------BEGIN PARSE-------------------------" );
dlog( DEBUGRX, "%s", line );
if( *line == ':' )
{
coreLine = strpbrk( line, " " );
if( coreLine == NULL )
return NS_FAILURE;
*coreLine = 0;
while( isspace( *++coreLine ) );
strlcpy( origin, line + 1, sizeof( origin ) );
memmove( line, coreLine, strnlen( coreLine, BUFSIZE ) + 1 );
cmdptr = 1;
}
else
{
cmdptr = 0;
*origin = 0;
}
if( *line == '\0' )
return NS_FAILURE;
coreLine = strpbrk( line, " " );
if( coreLine )
{
*coreLine = 0;
while( isspace( *++coreLine ) );
}
else
{
coreLine = line + strlen( line );
}
strlcpy( cmd, line, sizeof( cmd ) );
dlog( DEBUG1, "origin: %s", origin );
dlog( DEBUG1, "cmd : %s", cmd );
dlog( DEBUG1, "args : %s", coreLine );
ac = ircsplitbuf( coreLine, &av, 1 );
process_ircd_cmd( cmdptr, cmd, origin, av, ac );
ns_free( av );
dlog( DEBUG1, "-------------------------END PARSE--------------------------" );
return NS_SUCCESS;
}
/** @brief parsep10
*
* P10 parser
* formats:
* :<source> <command> <param1> <paramN> :<last parameter>
* <source> <command> <param1> <paramN> :<last parameter>
*
* @param notused Justin????
* @param rline Justin????
* @param len Justin????
*
* @return NS_SUCCESS if succeeds, NS_FAILURE if not
*/
static int parsep10( void *notused, void *rline, int len )
{
char origin[64], cmd[64], *coreLine;
char *line = ( char * )rline;
int cmdptr = 0;
int ac = 0;
char **av = NULL;
SET_SEGV_LOCATION();
if( *line == '\0' )
return NS_FAILURE;
dlog( DEBUG1, "------------------------BEGIN PARSE-------------------------" );
dlog( DEBUGRX, "%s", line );
coreLine = strpbrk( line, " " );
if( coreLine )
{
*coreLine = 0;
while( isspace( *++coreLine ) );
}
else
{
coreLine = line + strlen( line );
}
if( ( ircstrcasecmp( line, "SERVER" ) ) == 0 || ( ircstrcasecmp( line, "PASS" ) == 0 ) )
{
strlcpy( cmd, line, sizeof( cmd ) );
dlog( DEBUG1, "cmd : %s", cmd );
dlog( DEBUG1, "args : %s", coreLine );
ac = ircsplitbuf( coreLine, &av, 1 );
cmdptr = 2;
dlog( DEBUG1, "0 %d", ac );
/* really needs to be in AddServer since this is a NeoStats wide bug
if config uplink name does not match our uplinks server name we can
never find the uplink!
*/
if( strcmp( cmd, "SERVER" ) == 0 )
strlcpy( me.uplink, av[0], MAXHOST );
}
else
{
strlcpy( origin, line, sizeof( origin ) );
cmdptr = 0;
line = strpbrk( coreLine, " " );
if( line )
{
*line = 0;
while( isspace( *++line ) );
}
/*else
{
coreLine = line + strlen( line );
}*/
strlcpy( cmd, coreLine, sizeof( cmd ) );
dlog( DEBUG1, "origin: %s", origin );
dlog( DEBUG1, "cmd : %s", cmd );
dlog( DEBUG1, "args : %s", line );
if( line )
ac = ircsplitbuf( line, &av, 1 );
dlog( DEBUG1, "0 %d", ac );
}
process_ircd_cmd( cmdptr, cmd, origin, av, ac );
ns_free( av );
dlog( DEBUG1, "-------------------------END PARSE--------------------------" );
return NS_SUCCESS;
}
/** @brief InitIrcdProtocol
*
* Init protocol info
*
* @param none
*
* @return NS_SUCCESS if succeeds, NS_FAILURE if not
*/
static int InitIrcdProtocol( void )
{
protocol_info = ns_dlsym( protocol_module_handle, "protocol_info" );
if( protocol_info == NULL )
{
nlog( LOG_CRITICAL, "Unable to find protocol_info in protocol module %s", protocol_path );
return NS_FAILURE;
}
if( protocol_info->required & PROTOCOL_CLIENTMODE )
nsconfig.singlebotmode = 1;
strlcpy( me.servicescmode, protocol_info->services_cmode, MODESIZE );
strlcpy( me.servicesumode, protocol_info->services_umode, MODESIZE );
/* set min protocol */
ircd_srv.protocol = protocol_info->required;
/* Allow protocol module to "override" the parser */
irc_parse = ns_dlsym( protocol_module_handle, "parse" );
/* Use internal parser */
if( irc_parse == NULL )
{
if( ircd_srv.protocol & PROTOCOL_P10 )
irc_parse = parsep10;
else
irc_parse = parse;
}
cmd_list = ns_dlsym( protocol_module_handle, "cmd_list" );
if( cmd_list == NULL )
{
nlog( LOG_CRITICAL, "Unable to find command list in selected IRCd module" );
return NS_FAILURE;
}
return NS_SUCCESS;
}
/** @brief InitIrcdModes
*
* Lookup mode tables and init neostats mode lookup tables
*
* @param none
*
* @return NS_SUCCESS if succeeds, NS_FAILURE if not
*/
static int InitIrcdModes( void )
{
mode_init *chan_umodes;
mode_init *chan_modes;
mode_init *user_umodes;
mode_init *user_smodes;
chan_umodes = ns_dlsym( protocol_module_handle, "chan_umodes" );
chan_modes = ns_dlsym( protocol_module_handle, "chan_modes" );
user_umodes = ns_dlsym( protocol_module_handle, "user_umodes" );
/* Not required */
user_smodes = ns_dlsym( protocol_module_handle, "user_smodes" );
if( user_smodes )
ircd_srv.features |= FEATURE_USERSMODES;
if( InitModeTables( chan_umodes, chan_modes, user_umodes, user_smodes ) != NS_SUCCESS )
return NS_FAILURE;
return NS_SUCCESS;
}
/** @brief InitIrcd
*
* ircd initialisation
*
* @param none
*
* @return NS_SUCCESS if succeeds, NS_FAILURE if not
*/
int InitIrcd( void )
{
/* Clear IRCD info */
os_memset( &ircd_srv, 0, sizeof( ircd_srv ) );
/* Open protocol module */
ircsnprintf( protocol_path, 255, "%s/%s%s", MOD_PATH, me.protocol,MOD_STDEXT );
nlog( LOG_NORMAL, "Using protocol module %s", protocol_path );
protocol_module_handle = ns_dlopen( protocol_path, RTLD_NOW || RTLD_GLOBAL );
if( protocol_module_handle == NULL )
{
nlog( LOG_CRITICAL, "Unable to load protocol module %s", protocol_path );
return NS_FAILURE;
}
/* Setup protocol options */
if( InitIrcdProtocol() != NS_SUCCESS )
return NS_FAILURE;
/* Setup IRCD function calls */
if( InitIrcdSymbols() != NS_SUCCESS )
return NS_FAILURE;
/* Build mode tables */
if( InitIrcdModes() != NS_SUCCESS )
return NS_FAILURE;
return NS_SUCCESS;
}
/** @brief FiniIrcd
*
* fini ircd
*
* @param none
*
* @return none
*/
void FiniIrcd( void )
{
ns_dlclose( protocol_module_handle );
}
/** @brief HaveFeature
*
* Check to see if a feature is supported
*
* @param mask of features to check
*
* @return 1 if have else 0
*/
int HaveFeature( int mask )
{
return( ircd_srv.features & mask );
}