* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
- * $Id: irc.c,v 1.64 2002/02/19 20:06:45 alex Exp $
+ * $Id: irc.c,v 1.68 2002/02/25 17:46:27 alex Exp $
*
* irc.c: IRC-Befehle
*
* $Log: irc.c,v $
+ * Revision 1.68 2002/02/25 17:46:27 alex
+ * - an User wird nun immer ein "komplettes" Prefix verschickt.
+ *
+ * Revision 1.67 2002/02/25 13:21:25 alex
+ * - WHOIS wird nicht mehr automatisch an den "Original-Server" weiterge-
+ * leitet: war eh nicht RFC-konform und machte Probleme mit Clients.
+ *
+ * Revision 1.66 2002/02/23 21:39:48 alex
+ * - IRC-Befehl KILL sowie Kills bei Nick Collsisions implementiert.
+ *
+ * Revision 1.65 2002/02/23 00:03:54 alex
+ * - Ergebnistyp von Conn_GetIdle() und Conn_LastPing() auf "time_t" geaendert.
+ *
* Revision 1.64 2002/02/19 20:06:45 alex
* - User-Registrierung wird nicht mehr als Nick-Aenderung protokolliert,
* - VERSION liefert nun doch wieder den Debug-Status im Reply.
LOCAL BOOLEAN Hello_User( CLIENT *Client );
LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
-LOCAL VOID Kill_Nick( CHAR *Nick );
+LOCAL VOID Kill_Nick( CHAR *Nick, CHAR *Reason );
LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan );
LOCAL BOOLEAN Send_LUSERS( CLIENT *Client );
+CHAR *Get_Prefix( CLIENT *Target, CLIENT *Client );
+
GLOBAL VOID IRC_Init( VOID )
{
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
- return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Client_ID( Prefix ), buffer );
+ return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Get_Prefix( Client_NextHop( Client ), Prefix ), buffer );
} /* IRC_WriteStrClientPrefix */
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
{
+ BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
CHAR buffer[1000];
- BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED;
CL2CHAN *cl2chan;
CLIENT *c;
INT s, i;
assert( s >= 0 );
assert( s < MAX_CONNECTIONS );
sock[s] = TRUE;
+ if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
+ else is_server[s] = FALSE;
}
cl2chan = Channel_NextMember( Chan, cl2chan );
}
{
if( sock[i] )
{
- ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
+ if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
+ else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
if( ! ok ) break;
}
}
GLOBAL BOOLEAN IRC_WriteStrRelatedPrefix( CLIENT *Client, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
{
- BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED;
+ BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED;
CL2CHAN *chan_cl2chan, *cl2chan;
CHAR buffer[1000];
CHANNEL *chan;
assert( s >= 0 );
assert( s < MAX_CONNECTIONS );
sock[s] = TRUE;
+ if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE;
+ else is_server[s] = FALSE;
}
cl2chan = Channel_NextMember( chan, cl2chan );
}
{
if( sock[i] )
{
- ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
+ if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
+ else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
if( ! ok ) break;
}
}
* sowohl der neue, als auch der alte Client muessen nun
* disconnectiert werden. */
Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
- Kill_Nick( Req->argv[0] );
+ Kill_Nick( Req->argv[0], "Nick collision" );
return CONNECTED;
}
if( ! intr_c )
{
Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
- Kill_Nick( Req->argv[0] );
+ Kill_Nick( Req->argv[0], "Unknown server" );
return CONNECTED;
}
* Der Client muss disconnectiert werden, damit der Netz-
* status konsistent bleibt. */
Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
- Kill_Nick( Req->argv[0] );
+ Kill_Nick( Req->argv[0], "Server error" );
return CONNECTED;
}
/* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
* aktualisiert, daher muss das hier nicht mehr gemacht werden. */
- if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %d seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
+ if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %ld seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
return CONNECTED;
if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
ptr = Req->argv[1];
}
-#ifndef STRICT_RFC
- else if( Client_Conn( c ) == NONE )
- {
- /* Client ist nicht von uns. Ziel-Server suchen */
- target = c;
- ptr = Req->argv[0];
- }
-#endif
- else target = NULL;
+ else target = Client_ThisServer( );
+
+ assert( target != NULL );
- if( target && ( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
+ if(( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
/* Nick, User und Name */
if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
} /* IRC_VERSION */
+GLOBAL BOOLEAN IRC_KILL( CLIENT *Client, REQUEST *Req )
+{
+ CLIENT *prefix, *c;
+
+ assert( Client != NULL );
+ assert( Req != NULL );
+
+ if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
+
+ /* Falsche Anzahl Parameter? */
+ if(( Req->argc != 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+
+ prefix = Client_GetFromID( Req->prefix );
+ if( ! prefix )
+ {
+ Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Req->prefix );
+ prefix = Client_ThisServer( );
+ }
+
+ Log( LOG_NOTICE, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
+
+ /* andere Server benachrichtigen */
+ IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s", Req->argv[0], Req->argv[1] );
+
+ /* haben wir selber einen solchen Client? */
+ c = Client_GetFromID( Req->argv[0] );
+ if( c && ( Client_Conn( c ) != NONE )) Conn_Close( Client_Conn( c ), NULL, Req->argv[1], TRUE );
+
+ return CONNECTED;
+} /* IRC_KILL */
+
+
LOCAL BOOLEAN Hello_User( CLIENT *Client )
{
assert( Client != NULL );
} /* Show_MOTD */
-LOCAL VOID Kill_Nick( CHAR *Nick )
+LOCAL VOID Kill_Nick( CHAR *Nick, CHAR *Reason )
{
- Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected!", Nick );
- /* FIXME */
- Log( LOG_ALERT, "[Kill_Nick() not implemented - OOOPS!]" );
+ CLIENT *c;
+
+ assert( Nick != NULL );
+ assert( Reason != NULL );
+
+ Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
+
+ /* andere Server benachrichtigen */
+ IRC_WriteStrServers( NULL, "KILL %s :%s", Nick, Reason );
+
+ /* Ggf. einen eigenen Client toeten */
+ c = Client_GetFromID( Nick );
+ if( c && ( Client_Conn( c ) != NONE )) Conn_Close( Client_Conn( c ), NULL, Reason, TRUE );
} /* Kill_Nick */
} /* Send_LUSERS */
+CHAR *Get_Prefix( CLIENT *Target, CLIENT *Client )
+{
+ assert( Target != NULL );
+ assert( Client != NULL );
+
+ if( Client_Type( Target ) == CLIENT_SERVER ) return Client_ID( Client );
+ else return Client_Mask( Client );
+} /* Get_Prefix */
+
+
/* -eof- */