[BACK]Return to client.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/client.c, Revision 1.1.1.1

1.1       tomglok     1: /*
                      2:  * ngIRCd -- The Next Generation IRC Daemon
                      3:  * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify
                      6:  * it under the terms of the GNU General Public License as published by
                      7:  * the Free Software Foundation; either version 2 of the License, or
                      8:  * (at your option) any later version.
                      9:  * Please read the file COPYING, README and AUTHORS for more information.
                     10:  */
                     11:
                     12: #define __client_c__
                     13:
                     14: #include "portab.h"
                     15:
                     16: /**
                     17:  * @file
                     18:  * Client management.
                     19:  */
                     20:
                     21: #include <assert.h>
                     22: #include <unistd.h>
                     23: #include <stdio.h>
                     24: #include <stdlib.h>
                     25: #include <string.h>
                     26: #include <strings.h>
                     27: #include <time.h>
                     28: #include <netdb.h>
                     29:
                     30: #include "conn.h"
                     31: #include "ngircd.h"
                     32: #include "channel.h"
                     33: #include "conf.h"
                     34: #include "conn-func.h"
                     35: #include "hash.h"
                     36: #include "irc-write.h"
                     37: #include "log.h"
                     38: #include "match.h"
                     39: #include "messages.h"
                     40:
                     41: #define GETID_LEN (CLIENT_NICK_LEN-1) + 1 + (CLIENT_USER_LEN-1) + 1 + (CLIENT_HOST_LEN-1) + 1
                     42:
                     43: static CLIENT *This_Server, *My_Clients;
                     44:
                     45: static WHOWAS My_Whowas[MAX_WHOWAS];
                     46: static int Last_Whowas = -1;
                     47: static long Max_Users, My_Max_Users;
                     48:
                     49:
                     50: static unsigned long Count PARAMS(( CLIENT_TYPE Type ));
                     51: static unsigned long MyCount PARAMS(( CLIENT_TYPE Type ));
                     52:
                     53: static CLIENT *New_Client_Struct PARAMS(( void ));
                     54: static void Generate_MyToken PARAMS(( CLIENT *Client ));
                     55: static void Adjust_Counters PARAMS(( CLIENT *Client ));
                     56:
                     57: static void Free_Client PARAMS(( CLIENT **Client ));
                     58:
                     59: static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
                     60:                                       CLIENT *TopServer, int Type, const char *ID,
                     61:                                       const char *User, const char *Hostname, const char *Info,
                     62:                                       int Hops, int Token, const char *Modes,
                     63:                                       bool Idented));
                     64:
                     65: static void Destroy_UserOrService PARAMS((CLIENT *Client,const char *Txt, const char *FwdMsg,
                     66:                                        bool SendQuit));
                     67:
                     68: static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix,
                     69:                                       void *i));
                     70:
                     71: GLOBAL void
                     72: Client_Init( void )
                     73: {
                     74:        struct hostent *h;
                     75:
                     76:        This_Server = New_Client_Struct( );
                     77:        if( ! This_Server )
                     78:        {
                     79:                Log( LOG_EMERG, "Can't allocate client structure for server! Going down." );
                     80:                Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
                     81:                exit( 1 );
                     82:        }
                     83:
                     84:        /* Client structure for this server */
                     85:        This_Server->next = NULL;
                     86:        This_Server->type = CLIENT_SERVER;
                     87:        This_Server->conn_id = NONE;
                     88:        This_Server->introducer = This_Server;
                     89:        This_Server->mytoken = 1;
                     90:        This_Server->hops = 0;
                     91:
                     92:        gethostname( This_Server->host, CLIENT_HOST_LEN );
                     93:        if (Conf_DNS) {
                     94:                h = gethostbyname( This_Server->host );
                     95:                if (h) strlcpy(This_Server->host, h->h_name, sizeof(This_Server->host));
                     96:        }
                     97:        Client_SetID( This_Server, Conf_ServerName );
                     98:        Client_SetInfo( This_Server, Conf_ServerInfo );
                     99:
                    100:        My_Clients = This_Server;
                    101:
                    102:        memset( &My_Whowas, 0, sizeof( My_Whowas ));
                    103: } /* Client_Init */
                    104:
                    105:
                    106: GLOBAL void
                    107: Client_Exit( void )
                    108: {
                    109:        CLIENT *c, *next;
                    110:        int cnt;
                    111:
                    112:        if( NGIRCd_SignalRestart ) Client_Destroy( This_Server, "Server going down (restarting).", NULL, false );
                    113:        else Client_Destroy( This_Server, "Server going down.", NULL, false );
                    114:
                    115:        cnt = 0;
                    116:        c = My_Clients;
                    117:        while(c) {
                    118:                cnt++;
                    119:                next = (CLIENT *)c->next;
                    120:                Free_Client(&c);
                    121:                c = next;
                    122:        }
                    123:        if (cnt)
                    124:                Log(LOG_INFO, "Freed %d client structure%s.",
                    125:                    cnt, cnt == 1 ? "" : "s");
                    126: } /* Client_Exit */
                    127:
                    128:
                    129: GLOBAL CLIENT *
                    130: Client_ThisServer( void )
                    131: {
                    132:        return This_Server;
                    133: } /* Client_ThisServer */
                    134:
                    135:
                    136: /**
                    137:  * Initialize new local client; wrapper function for Init_New_Client().
                    138:  * @return New CLIENT structure.
                    139:  */
                    140: GLOBAL CLIENT *
                    141: Client_NewLocal(CONN_ID Idx, const char *Hostname, int Type, bool Idented)
                    142: {
                    143:        return Init_New_Client(Idx, This_Server, NULL, Type, NULL, NULL,
                    144:                Hostname, NULL, 0, 0, NULL, Idented);
                    145: } /* Client_NewLocal */
                    146:
                    147:
                    148: /**
                    149:  * Initialize new remote server; wrapper function for Init_New_Client().
                    150:  * @return New CLIENT structure.
                    151:  */
                    152: GLOBAL CLIENT *
                    153: Client_NewRemoteServer(CLIENT *Introducer, const char *Hostname, CLIENT *TopServer,
                    154:  int Hops, int Token, const char *Info, bool Idented)
                    155: {
                    156:        return Init_New_Client(NONE, Introducer, TopServer, CLIENT_SERVER,
                    157:                Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented);
                    158: } /* Client_NewRemoteServer */
                    159:
                    160:
                    161: /**
                    162:  * Initialize new remote client; wrapper function for Init_New_Client().
                    163:  * @return New CLIENT structure.
                    164:  */
                    165: GLOBAL CLIENT *
                    166: Client_NewRemoteUser(CLIENT *Introducer, const char *Nick, int Hops, const char *User,
                    167:  const char *Hostname, int Token, const char *Modes, const char *Info, bool Idented)
                    168: {
                    169:        return Init_New_Client(NONE, Introducer, NULL, CLIENT_USER, Nick,
                    170:                User, Hostname, Info, Hops, Token, Modes, Idented);
                    171: } /* Client_NewRemoteUser */
                    172:
                    173:
                    174: /**
                    175:  * Initialize new client and set up the given parameters like client type,
                    176:  * user name, host name, introducing server etc. ...
                    177:  * @return New CLIENT structure.
                    178:  */
                    179: static CLIENT *
                    180: Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
                    181:   int Type, const char *ID, const char *User, const char *Hostname,
                    182:   const char *Info, int Hops, int Token, const char *Modes, bool Idented)
                    183: {
                    184:        CLIENT *client;
                    185:
                    186:        assert(Idx >= NONE);
                    187:        assert(Introducer != NULL);
                    188:
                    189:        client = New_Client_Struct();
                    190:        if (!client)
                    191:                return NULL;
                    192:
                    193:        client->starttime = time(NULL);
                    194:        client->conn_id = Idx;
                    195:        client->introducer = Introducer;
                    196:        client->topserver = TopServer;
                    197:        client->type = Type;
                    198:        if (ID)
                    199:                Client_SetID(client, ID);
                    200:        if (User) {
                    201:                Client_SetUser(client, User, Idented);
                    202:                Client_SetOrigUser(client, User);
                    203:        }
                    204:        if (Hostname)
                    205:                Client_SetHostname(client, Hostname);
                    206:        if (Info)
                    207:                Client_SetInfo(client, Info);
                    208:        client->hops = Hops;
                    209:        client->token = Token;
                    210:        if (Modes)
                    211:                Client_SetModes(client, Modes);
                    212:        if (Type == CLIENT_SERVER)
                    213:                Generate_MyToken(client);
                    214:
                    215:        if (Client_HasMode(client, 'a'))
                    216:                client->away = strndup(DEFAULT_AWAY_MSG, CLIENT_AWAY_LEN - 1);
                    217:
                    218:        client->next = (POINTER *)My_Clients;
                    219:        My_Clients = client;
                    220:
                    221:        Adjust_Counters(client);
                    222:
                    223:        return client;
                    224: } /* Init_New_Client */
                    225:
                    226:
                    227: GLOBAL void
                    228: Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool SendQuit )
                    229: {
                    230:        /* remove a client */
                    231:
                    232:        CLIENT *last, *c;
                    233:        char msg[COMMAND_LEN];
                    234:        const char *txt;
                    235:
                    236:        assert( Client != NULL );
                    237:
                    238:        txt = LogMsg ? LogMsg : FwdMsg;
                    239:        if (!txt)
                    240:                txt = "Reason unknown";
                    241:
                    242:        /* netsplit message */
                    243:        if( Client->type == CLIENT_SERVER ) {
                    244:                strlcpy(msg, This_Server->id, sizeof (msg));
                    245:                strlcat(msg, " ", sizeof (msg));
                    246:                strlcat(msg, Client->id, sizeof (msg));
                    247:        }
                    248:
                    249:        last = NULL;
                    250:        c = My_Clients;
                    251:        while( c )
                    252:        {
                    253:                if(( Client->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c != Client ))
                    254:                {
                    255:                        /*
                    256:                         * The client that is about to be removed is a server,
                    257:                         * the client we are checking right now is a child of that
                    258:                         * server and thus has to be removed, too.
                    259:                         *
                    260:                         * Call Client_Destroy() recursively with the server as the
                    261:                         * new "object to be removed". This starts the cycle again, until
                    262:                         * all servers that are linked via the original server have been
                    263:                         * removed.
                    264:                         */
                    265:                        Client_Destroy( c, NULL, msg, false );
                    266:                        last = NULL;
                    267:                        c = My_Clients;
                    268:                        continue;
                    269:                }
                    270:                if( c == Client )
                    271:                {
                    272:                        /* found  the client: remove it */
                    273:                        if( last ) last->next = c->next;
                    274:                        else My_Clients = (CLIENT *)c->next;
                    275:
                    276:                        if(c->type == CLIENT_USER || c->type == CLIENT_SERVICE)
                    277:                                Destroy_UserOrService(c, txt, FwdMsg, SendQuit);
                    278:                        else if( c->type == CLIENT_SERVER )
                    279:                        {
                    280:                                if (c != This_Server) {
                    281:                                        if (c->conn_id != NONE)
                    282:                                                Log(LOG_NOTICE|LOG_snotice,
                    283:                                                    "Server \"%s\" unregistered (connection %d): %s.",
                    284:                                                c->id, c->conn_id, txt);
                    285:                                        else
                    286:                                                Log(LOG_NOTICE|LOG_snotice,
                    287:                                                    "Server \"%s\" unregistered: %s.",
                    288:                                                    c->id, txt);
                    289:                                }
                    290:
                    291:                                /* inform other servers */
                    292:                                if( ! NGIRCd_SignalQuit )
                    293:                                {
                    294:                                        if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
                    295:                                        else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
                    296:                                }
                    297:                        }
                    298:                        else
                    299:                        {
                    300:                                if (c->conn_id != NONE) {
                    301:                                        if (c->id[0])
                    302:                                                Log(LOG_NOTICE,
                    303:                                                    "Client \"%s\" unregistered (connection %d): %s.",
                    304:                                                    c->id, c->conn_id, txt);
                    305:                                        else
                    306:                                                Log(LOG_NOTICE,
                    307:                                                    "Client unregistered (connection %d): %s.",
                    308:                                                    c->conn_id, txt);
                    309:                                } else {
                    310:                                        Log(LOG_WARNING,
                    311:                                            "Unregistered unknown client \"%s\": %s",
                    312:                                            c->id[0] ? c->id : "(No Nick)", txt);
                    313:                                }
                    314:                        }
                    315:
                    316:                        Free_Client(&c);
                    317:                        break;
                    318:                }
                    319:                last = c;
                    320:                c = (CLIENT *)c->next;
                    321:        }
                    322: } /* Client_Destroy */
                    323:
                    324:
                    325: /**
                    326:  * Set client hostname.
                    327:  *
                    328:  * If global hostname cloaking is in effect, don't set the real hostname
                    329:  * but the configured one.
                    330:  *
                    331:  * @param Client The client of which the hostname should be set.
                    332:  * @param Hostname The new hostname.
                    333:  */
                    334: GLOBAL void
                    335: Client_SetHostname( CLIENT *Client, const char *Hostname )
                    336: {
                    337:        assert(Client != NULL);
                    338:        assert(Hostname != NULL);
                    339:
                    340:        /* Only cloak the hostmask if it has not yet been cloaked.
                    341:         * The period or colon indicates it's still an IP address.
                    342:         * An empty string means a rDNS lookup did not happen (yet). */
                    343:        if (Conf_CloakHost[0] && (!Client->host[0] || strchr(Client->host, '.')
                    344:                                  || strchr(Client->host, ':'))) {
                    345:                char cloak[GETID_LEN];
                    346:
                    347:                strlcpy(cloak, Hostname, GETID_LEN);
                    348:                strlcat(cloak, Conf_CloakHostSalt, GETID_LEN);
                    349:                snprintf(cloak, GETID_LEN, Conf_CloakHost, Hash(cloak));
                    350:
                    351:                LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
                    352:                        Client_ID(Client), Client->host, cloak);
                    353:                strlcpy(Client->host, cloak, sizeof(Client->host));
                    354:        } else {
                    355:                LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
                    356:                         Client_ID(Client), Client->host, Hostname);
                    357:                strlcpy(Client->host, Hostname, sizeof(Client->host));
                    358:        }
                    359: } /* Client_SetHostname */
                    360:
                    361:
                    362: /**
                    363:  * Set IP address to display for a client.
                    364:  *
                    365:  * @param Client The client.
                    366:  * @param IPAText Textual representation of the IP address or NULL to unset.
                    367:  */
                    368: GLOBAL void
                    369: Client_SetIPAText(CLIENT *Client, const char *IPAText)
                    370: {
                    371:        assert(Client != NULL);
                    372:
                    373:        if (Client->ipa_text)
                    374:                free(Client->ipa_text);
                    375:
                    376:        if (*IPAText)
                    377:                Client->ipa_text = strndup(IPAText, CLIENT_HOST_LEN - 1);
                    378:        else
                    379:                Client->ipa_text = NULL;
                    380: }
                    381:
                    382:
                    383: GLOBAL void
                    384: Client_SetID( CLIENT *Client, const char *ID )
                    385: {
                    386:        assert( Client != NULL );
                    387:        assert( ID != NULL );
                    388:
                    389:        strlcpy( Client->id, ID, sizeof( Client->id ));
                    390:
                    391:        if (Conf_CloakUserToNick) {
                    392:                strlcpy( Client->user, ID, sizeof( Client->user ));
                    393:                strlcpy( Client->info, ID, sizeof( Client->info ));
                    394:        }
                    395:
                    396:        /* Hash */
                    397:        Client->hash = Hash( Client->id );
                    398: } /* Client_SetID */
                    399:
                    400:
                    401: GLOBAL void
                    402: Client_SetUser( CLIENT *Client, const char *User, bool Idented )
                    403: {
                    404:        /* set clients username */
                    405:
                    406:        assert( Client != NULL );
                    407:        assert( User != NULL );
                    408:
                    409:        if (Conf_CloakUserToNick) {
                    410:                strlcpy(Client->user, Client->id, sizeof(Client->user));
                    411:        } else if (Idented) {
                    412:                strlcpy(Client->user, User, sizeof(Client->user));
                    413:        } else {
                    414:                Client->user[0] = '~';
                    415:                strlcpy(Client->user + 1, User, sizeof(Client->user) - 1);
                    416:        }
                    417: } /* Client_SetUser */
                    418:
                    419:
                    420: /**
                    421:  * Set "original" user name of a client.
                    422:  * This function saves the "original" user name, the user name specified by
                    423:  * the peer using the USER command, into the CLIENT structure. This user
                    424:  * name may be used for authentication, for example.
                    425:  * @param Client The client.
                    426:  * @param User User name to set.
                    427:  */
                    428: GLOBAL void
                    429: Client_SetOrigUser(CLIENT UNUSED *Client, const char UNUSED *User)
                    430: {
                    431:        assert(Client != NULL);
                    432:        assert(User != NULL);
                    433:
                    434: #if defined(PAM)
                    435:        strlcpy(Client->orig_user, User, sizeof(Client->orig_user));
                    436: #endif
                    437: } /* Client_SetOrigUser */
                    438:
                    439:
                    440: GLOBAL void
                    441: Client_SetInfo( CLIENT *Client, const char *Info )
                    442: {
                    443:        /* set client hostname */
                    444:
                    445:        assert( Client != NULL );
                    446:        assert( Info != NULL );
                    447:
                    448:        if (Conf_CloakUserToNick)
                    449:                strlcpy(Client->info, Client->id, sizeof(Client->info));
                    450:        else
                    451:                strlcpy(Client->info, Info, sizeof(Client->info));
                    452: } /* Client_SetInfo */
                    453:
                    454:
                    455: GLOBAL void
                    456: Client_SetModes( CLIENT *Client, const char *Modes )
                    457: {
                    458:        assert( Client != NULL );
                    459:        assert( Modes != NULL );
                    460:
                    461:        strlcpy(Client->modes, Modes, sizeof( Client->modes ));
                    462: } /* Client_SetModes */
                    463:
                    464:
                    465: GLOBAL void
                    466: Client_SetFlags( CLIENT *Client, const char *Flags )
                    467: {
                    468:        assert( Client != NULL );
                    469:        assert( Flags != NULL );
                    470:
                    471:        strlcpy(Client->flags, Flags, sizeof(Client->flags));
                    472: } /* Client_SetFlags */
                    473:
                    474:
                    475: GLOBAL void
                    476: Client_SetAccountName(CLIENT *Client, const char *AccountName)
                    477: {
                    478:        assert(Client != NULL);
                    479:
                    480:        if (Client->account_name)
                    481:                free(Client->account_name);
                    482:
                    483:        if (*AccountName)
                    484:                Client->account_name = strndup(AccountName,
                    485:                                               CLIENT_NICK_LEN - 1);
                    486:        else
                    487:                Client->account_name = NULL;
                    488: }
                    489:
                    490:
                    491: GLOBAL void
                    492: Client_SetAway( CLIENT *Client, const char *Txt )
                    493: {
                    494:        /* Set AWAY reason of client */
                    495:
                    496:        assert( Client != NULL );
                    497:        assert( Txt != NULL );
                    498:
                    499:        if (Client->away)
                    500:                free(Client->away);
                    501:
                    502:        Client->away = strndup(Txt, CLIENT_AWAY_LEN - 1);
                    503:
                    504:        LogDebug("%s \"%s\" is away: %s", Client_TypeText(Client),
                    505:                 Client_Mask(Client), Txt);
                    506: } /* Client_SetAway */
                    507:
                    508:
                    509: GLOBAL void
                    510: Client_SetType( CLIENT *Client, int Type )
                    511: {
                    512:        assert( Client != NULL );
                    513:        Client->type = Type;
                    514:        if( Type == CLIENT_SERVER ) Generate_MyToken( Client );
                    515:        Adjust_Counters( Client );
                    516: } /* Client_SetType */
                    517:
                    518:
                    519: GLOBAL void
                    520: Client_SetHops( CLIENT *Client, int Hops )
                    521: {
                    522:        assert( Client != NULL );
                    523:        Client->hops = Hops;
                    524: } /* Client_SetHops */
                    525:
                    526:
                    527: GLOBAL void
                    528: Client_SetToken( CLIENT *Client, int Token )
                    529: {
                    530:        assert( Client != NULL );
                    531:        Client->token = Token;
                    532: } /* Client_SetToken */
                    533:
                    534:
                    535: GLOBAL void
                    536: Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
                    537: {
                    538:        assert( Client != NULL );
                    539:        assert( Introducer != NULL );
                    540:        Client->introducer = Introducer;
                    541: } /* Client_SetIntroducer */
                    542:
                    543:
                    544: GLOBAL bool
                    545: Client_ModeAdd( CLIENT *Client, char Mode )
                    546: {
                    547:        /* Set Mode.
                    548:         * If Client already had Mode, return false.
                    549:         * If the Mode was newly set, return true.
                    550:         */
                    551:
                    552:        char x[2];
                    553:
                    554:        assert( Client != NULL );
                    555:
                    556:        x[0] = Mode; x[1] = '\0';
                    557:        if (!Client_HasMode(Client, x[0])) {
                    558:                strlcat( Client->modes, x, sizeof( Client->modes ));
                    559:                return true;
                    560:        }
                    561:        else return false;
                    562: } /* Client_ModeAdd */
                    563:
                    564:
                    565: GLOBAL bool
                    566: Client_ModeDel( CLIENT *Client, char Mode )
                    567: {
                    568:        /* Delete Mode.
                    569:         * If Mode was removed, return true.
                    570:         * If Client did not have Mode, return false.
                    571:         */
                    572:
                    573:        char x[2], *p;
                    574:
                    575:        assert( Client != NULL );
                    576:
                    577:        x[0] = Mode; x[1] = '\0';
                    578:
                    579:        p = strchr( Client->modes, x[0] );
                    580:        if( ! p ) return false;
                    581:
                    582:        /* Client has Mode -> delete */
                    583:        while( *p )
                    584:        {
                    585:                *p = *(p + 1);
                    586:                p++;
                    587:        }
                    588:        return true;
                    589: } /* Client_ModeDel */
                    590:
                    591:
                    592: /**
                    593:  * Search CLIENT structure of a given nick name.
                    594:  *
                    595:  * @return Pointer to CLIENT structure or NULL if not found.
                    596:  */
                    597: GLOBAL CLIENT *
                    598: Client_Search( const char *Nick )
                    599: {
                    600:        char search_id[CLIENT_ID_LEN], *ptr;
                    601:        CLIENT *c = NULL;
                    602:        UINT32 search_hash;
                    603:
                    604:        assert( Nick != NULL );
                    605:
                    606:        /* copy Nick and truncate hostmask if necessary */
                    607:        strlcpy( search_id, Nick, sizeof( search_id ));
                    608:        ptr = strchr( search_id, '!' );
                    609:        if( ptr ) *ptr = '\0';
                    610:
                    611:        search_hash = Hash(search_id);
                    612:
                    613:        c = My_Clients;
                    614:        while (c) {
                    615:                if (c->hash == search_hash && strcasecmp(c->id, search_id) == 0)
                    616:                        return c;
                    617:                c = (CLIENT *)c->next;
                    618:        }
                    619:        return NULL;
                    620: }
                    621:
                    622:
                    623: /**
                    624:  * Search first CLIENT structure matching a given mask of a server.
                    625:  *
                    626:  * The order of servers is arbitrary, but this function makes sure that the
                    627:  * local server is always returned if the mask matches it.
                    628:  *
                    629:  * @return Pointer to CLIENT structure or NULL if no server could be found.
                    630:  */
                    631: GLOBAL CLIENT *
                    632: Client_SearchServer(const char *Mask)
                    633: {
                    634:        CLIENT *c;
                    635:
                    636:        assert(Mask != NULL);
                    637:
                    638:        /* First check if mask matches the local server */
                    639:        if (MatchCaseInsensitive(Mask, Client_ID(Client_ThisServer())))
                    640:                return Client_ThisServer();
                    641:
                    642:        c = My_Clients;
                    643:        while (c) {
                    644:                if (Client_Type(c) == CLIENT_SERVER) {
                    645:                        /* This is a server: check if Mask matches */
                    646:                        if (MatchCaseInsensitive(Mask, c->id))
                    647:                                return c;
                    648:                }
                    649:                c = (CLIENT *)c->next;
                    650:        }
                    651:        return NULL;
                    652: }
                    653:
                    654:
                    655: /**
                    656:  * Get client structure ("introducer") identfied by a server token.
                    657:  * @return CLIENT structure or NULL if none could be found.
                    658:  */
                    659: GLOBAL CLIENT *
                    660: Client_GetFromToken( CLIENT *Client, int Token )
                    661: {
                    662:        CLIENT *c;
                    663:
                    664:        assert( Client != NULL );
                    665:
                    666:        if (!Token)
                    667:                return NULL;
                    668:
                    669:        c = My_Clients;
                    670:        while (c) {
                    671:                if ((c->type == CLIENT_SERVER) && (c->introducer == Client) &&
                    672:                        (c->token == Token))
                    673:                                return c;
                    674:                c = (CLIENT *)c->next;
                    675:        }
                    676:        return NULL;
                    677: } /* Client_GetFromToken */
                    678:
                    679:
                    680: GLOBAL int
                    681: Client_Type( CLIENT *Client )
                    682: {
                    683:        assert( Client != NULL );
                    684:        return Client->type;
                    685: } /* Client_Type */
                    686:
                    687:
                    688: GLOBAL CONN_ID
                    689: Client_Conn( CLIENT *Client )
                    690: {
                    691:        assert( Client != NULL );
                    692:        return Client->conn_id;
                    693: } /* Client_Conn */
                    694:
                    695:
                    696: GLOBAL char *
                    697: Client_ID( CLIENT *Client )
                    698: {
                    699:        assert( Client != NULL );
                    700:
                    701: #ifdef DEBUG
                    702:        if(Client->type == CLIENT_USER)
                    703:                assert(strlen(Client->id) < Conf_MaxNickLength);
                    704: #endif
                    705:
                    706:        if( Client->id[0] ) return Client->id;
                    707:        else return "*";
                    708: } /* Client_ID */
                    709:
                    710:
                    711: GLOBAL char *
                    712: Client_Info( CLIENT *Client )
                    713: {
                    714:        assert( Client != NULL );
                    715:        return Client->info;
                    716: } /* Client_Info */
                    717:
                    718:
                    719: GLOBAL char *
                    720: Client_User( CLIENT *Client )
                    721: {
                    722:        assert( Client != NULL );
                    723:        return Client->user[0] ? Client->user : "~";
                    724: } /* Client_User */
                    725:
                    726:
                    727: #ifdef PAM
                    728:
                    729: /**
                    730:  * Get the "original" user name as supplied by the USER command.
                    731:  * The user name as given by the client is used for authentication instead
                    732:  * of the one detected using IDENT requests.
                    733:  * @param Client The client.
                    734:  * @return Original user name.
                    735:  */
                    736: GLOBAL char *
                    737: Client_OrigUser(CLIENT *Client) {
                    738:        return Client->orig_user;
                    739: } /* Client_OrigUser */
                    740:
                    741: #endif
                    742:
                    743: /**
                    744:  * Return the hostname of a client.
                    745:  * @param Client Pointer to client structure
                    746:  * @return Pointer to client hostname
                    747:  */
                    748: GLOBAL char *
                    749: Client_Hostname(CLIENT *Client)
                    750: {
                    751:        assert (Client != NULL);
                    752:        return Client->host;
                    753: }
                    754:
                    755: /**
                    756:  * Return the cloaked hostname of a client, if set.
                    757:  * @param Client Pointer to the client structure.
                    758:  * @return Pointer to the cloaked hostname or NULL if not set.
                    759:  */
                    760: GLOBAL char *
                    761: Client_HostnameCloaked(CLIENT *Client)
                    762: {
                    763:        assert(Client != NULL);
                    764:        return Client->cloaked;
                    765: }
                    766:
                    767: /**
                    768:  * Get (potentially cloaked) hostname of a client to display it to other users.
                    769:  *
                    770:  * If the client has not enabled cloaking, the real hostname is used.
                    771:  *
                    772:  * @param Client Pointer to client structure
                    773:  * @return Pointer to client hostname
                    774:  */
                    775: GLOBAL char *
                    776: Client_HostnameDisplayed(CLIENT *Client)
                    777: {
                    778:        assert(Client != NULL);
                    779:
                    780:        /* Client isn't cloaked at all, return real hostname: */
                    781:        if (!Client_HasMode(Client, 'x'))
                    782:                return Client_Hostname(Client);
                    783:
                    784:        /* Use an already saved cloaked hostname, if there is one */
                    785:        if (Client->cloaked)
                    786:                return Client->cloaked;
                    787:
                    788:        Client_UpdateCloakedHostname(Client, NULL, NULL);
                    789:        return Client->cloaked;
                    790: }
                    791:
                    792: GLOBAL const char *
                    793: Client_IPAText(CLIENT *Client)
                    794: {
                    795:        assert(Client != NULL);
                    796:
                    797:        /* Not a local client? */
                    798:        if (Client_Conn(Client) <= NONE)
                    799:                return "0.0.0.0";
                    800:
                    801:        if (!Client->ipa_text)
                    802:                return Conn_GetIPAInfo(Client_Conn(Client));
                    803:        else
                    804:                return Client->ipa_text;
                    805: }
                    806:
                    807: /**
                    808:  * Update (and generate, if necessary) the cloaked hostname of a client.
                    809:  *
                    810:  * The newly set cloaked hostname is announced in the network using METADATA
                    811:  * commands to peers that support this feature.
                    812:  *
                    813:  * @param Client The client of which the cloaked hostname should be updated.
                    814:  * @param Origin The originator of the hostname change, or NULL if this server.
                    815:  * @param Hostname The new cloaked hostname, or NULL if it should be generated.
                    816:  */
                    817: GLOBAL void
                    818: Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin,
                    819:                             const char *Hostname)
                    820: {
                    821:        char Cloak_Buffer[CLIENT_HOST_LEN];
                    822:
                    823:        assert(Client != NULL);
                    824:        if (!Origin)
                    825:                Origin = Client_ThisServer();
                    826:
                    827:        if (!Client->cloaked) {
                    828:                Client->cloaked = malloc(CLIENT_HOST_LEN);
                    829:                if (!Client->cloaked)
                    830:                        return;
                    831:        }
                    832:
                    833:        if (!Hostname) {
                    834:                /* Generate new cloaked hostname */
                    835:                if (*Conf_CloakHostModeX) {
                    836:                        strlcpy(Cloak_Buffer, Client->host,
                    837:                                sizeof(Cloak_Buffer));
                    838:                        strlcat(Cloak_Buffer, Conf_CloakHostSalt,
                    839:                                sizeof(Cloak_Buffer));
                    840:                        snprintf(Client->cloaked, CLIENT_HOST_LEN,
                    841:                                 Conf_CloakHostModeX, Hash(Cloak_Buffer));
                    842:                } else
                    843:                        strlcpy(Client->cloaked, Client_ID(Client->introducer),
                    844:                                CLIENT_HOST_LEN);
                    845:        } else
                    846:                strlcpy(Client->cloaked, Hostname, CLIENT_HOST_LEN);
                    847:        LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"",
                    848:                 Client_ID(Client), Client->cloaked);
                    849:
                    850:        /* Inform other servers in the network */
                    851:        IRC_WriteStrServersPrefixFlag(Client_NextHop(Origin), Origin, 'M',
                    852:                                      "METADATA %s cloakhost :%s",
                    853:                                      Client_ID(Client), Client->cloaked);
                    854: }
                    855:
                    856: GLOBAL char *
                    857: Client_Modes( CLIENT *Client )
                    858: {
                    859:        assert( Client != NULL );
                    860:        return Client->modes;
                    861: } /* Client_Modes */
                    862:
                    863:
                    864: GLOBAL char *
                    865: Client_Flags( CLIENT *Client )
                    866: {
                    867:        assert( Client != NULL );
                    868:        return Client->flags;
                    869: } /* Client_Flags */
                    870:
                    871:
                    872: GLOBAL int
                    873: Client_Hops( CLIENT *Client )
                    874: {
                    875:        assert( Client != NULL );
                    876:        return Client->hops;
                    877: } /* Client_Hops */
                    878:
                    879:
                    880: GLOBAL int
                    881: Client_Token( CLIENT *Client )
                    882: {
                    883:        assert( Client != NULL );
                    884:        return Client->token;
                    885: } /* Client_Token */
                    886:
                    887:
                    888: GLOBAL int
                    889: Client_MyToken( CLIENT *Client )
                    890: {
                    891:        assert( Client != NULL );
                    892:        return Client->mytoken;
                    893: } /* Client_MyToken */
                    894:
                    895:
                    896: GLOBAL CLIENT *
                    897: Client_NextHop( CLIENT *Client )
                    898: {
                    899:        CLIENT *c;
                    900:
                    901:        assert( Client != NULL );
                    902:
                    903:        c = Client;
                    904:        while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server ))
                    905:                c = c->introducer;
                    906:
                    907:        return c;
                    908: } /* Client_NextHop */
                    909:
                    910:
                    911: /**
                    912:  * Return ID of a client: "client!user@host"
                    913:  * This client ID is used for IRC prefixes, for example.
                    914:  * Please note that this function uses a global static buffer, so you can't
                    915:  * nest invocations without overwriting earlier results!
                    916:  * @param Client Pointer to client structure
                    917:  * @return Pointer to global buffer containing the client ID
                    918:  */
                    919: GLOBAL char *
                    920: Client_Mask( CLIENT *Client )
                    921: {
                    922:        static char Mask_Buffer[GETID_LEN];
                    923:
                    924:        assert (Client != NULL);
                    925:
                    926:        /* Servers: return name only, there is no "mask" */
                    927:        if (Client->type == CLIENT_SERVER)
                    928:                return Client->id;
                    929:
                    930:        snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
                    931:                 Client->id, Client->user, Client->host);
                    932:        return Mask_Buffer;
                    933: } /* Client_Mask */
                    934:
                    935:
                    936: /**
                    937:  * Return ID of a client with cloaked hostname: "client!user@server-name"
                    938:  *
                    939:  * This client ID is used for IRC prefixes, for example.
                    940:  * Please note that this function uses a global static buffer, so you can't
                    941:  * nest invocations without overwriting earlier results!
                    942:  * If the client has not enabled cloaking, the real hostname is used.
                    943:  *
                    944:  * @param Client Pointer to client structure
                    945:  * @return Pointer to global buffer containing the client ID
                    946:  */
                    947: GLOBAL char *
                    948: Client_MaskCloaked(CLIENT *Client)
                    949: {
                    950:        static char Mask_Buffer[GETID_LEN];
                    951:
                    952:        assert (Client != NULL);
                    953:
                    954:        /* Is the client using cloaking at all? */
                    955:        if (!Client_HasMode(Client, 'x'))
                    956:                return Client_Mask(Client);
                    957:
                    958:        snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user,
                    959:                 Client_HostnameDisplayed(Client));
                    960:
                    961:        return Mask_Buffer;
                    962: } /* Client_MaskCloaked */
                    963:
                    964:
                    965: GLOBAL CLIENT *
                    966: Client_Introducer( CLIENT *Client )
                    967: {
                    968:        assert( Client != NULL );
                    969:        return Client->introducer;
                    970: } /* Client_Introducer */
                    971:
                    972:
                    973: GLOBAL CLIENT *
                    974: Client_TopServer( CLIENT *Client )
                    975: {
                    976:        assert( Client != NULL );
                    977:        return Client->topserver;
                    978: } /* Client_TopServer */
                    979:
                    980:
                    981: GLOBAL bool
                    982: Client_HasMode( CLIENT *Client, char Mode )
                    983: {
                    984:        assert( Client != NULL );
                    985:        return strchr( Client->modes, Mode ) != NULL;
                    986: } /* Client_HasMode */
                    987:
                    988:
                    989: GLOBAL bool
                    990: Client_HasFlag( CLIENT *Client, char Flag )
                    991: {
                    992:        assert( Client != NULL );
                    993:        return strchr( Client->flags, Flag ) != NULL;
                    994: } /* Client_HasFlag */
                    995:
                    996:
                    997: GLOBAL char *
                    998: Client_Away( CLIENT *Client )
                    999: {
                   1000:        assert( Client != NULL );
                   1001:        return Client->away;
                   1002: } /* Client_Away */
                   1003:
                   1004:
                   1005: GLOBAL char *
                   1006: Client_AccountName(CLIENT *Client)
                   1007: {
                   1008:        assert(Client != NULL);
                   1009:        return Client->account_name;
                   1010: }
                   1011:
                   1012:
                   1013: /**
                   1014:  * Make sure that a given nickname is valid.
                   1015:  *
                   1016:  * If the nickname is not valid for the given client, this function sends back
                   1017:  * the appropriate error messages.
                   1018:  *
                   1019:  * @param      Client Client that wants to change the nickname.
                   1020:  * @param      Nick New nickname.
                   1021:  * @returns    true if nickname is valid, false otherwise.
                   1022:  */
                   1023: GLOBAL bool
                   1024: Client_CheckNick(CLIENT *Client, char *Nick)
                   1025: {
                   1026:        assert(Client != NULL);
                   1027:        assert(Nick != NULL);
                   1028:
                   1029:        if (!Client_IsValidNick(Nick)) {
                   1030:                if (strlen(Nick ) >= Conf_MaxNickLength)
                   1031:                        IRC_WriteErrClient(Client, ERR_NICKNAMETOOLONG_MSG,
                   1032:                                           Client_ID(Client), Nick,
                   1033:                                           Conf_MaxNickLength - 1);
                   1034:                else
                   1035:                        IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
                   1036:                                           Client_ID(Client), Nick);
                   1037:                return false;
                   1038:        }
                   1039:
                   1040:        if (Client_Type(Client) != CLIENT_SERVER
                   1041:            && Client_Type(Client) != CLIENT_SERVICE) {
                   1042:                /* Make sure that this isn't a restricted/forbidden nickname */
                   1043:                if (Conf_NickIsBlocked(Nick)) {
                   1044:                        IRC_WriteErrClient(Client, ERR_FORBIDDENNICKNAME_MSG,
                   1045:                                           Client_ID(Client), Nick);
                   1046:                        return false;
                   1047:                }
                   1048:        }
                   1049:
                   1050:        /* Nickname already registered? */
                   1051:        if (Client_Search(Nick)) {
                   1052:                IRC_WriteErrClient(Client, ERR_NICKNAMEINUSE_MSG,
                   1053:                        Client_ID(Client), Nick);
                   1054:                return false;
                   1055:        }
                   1056:
                   1057:        return true;
                   1058: } /* Client_CheckNick */
                   1059:
                   1060:
                   1061: GLOBAL bool
                   1062: Client_CheckID( CLIENT *Client, char *ID )
                   1063: {
                   1064:        char str[COMMAND_LEN];
                   1065:        CLIENT *c;
                   1066:
                   1067:        assert( Client != NULL );
                   1068:        assert( Client->conn_id > NONE );
                   1069:        assert( ID != NULL );
                   1070:
                   1071:        /* ID too long? */
                   1072:        if (strlen(ID) > CLIENT_ID_LEN) {
                   1073:                IRC_WriteErrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
                   1074:                                   Client_ID(Client), ID);
                   1075:                return false;
                   1076:        }
                   1077:
                   1078:        /* ID already in use? */
                   1079:        c = My_Clients;
                   1080:        while (c) {
                   1081:                if (strcasecmp(c->id, ID) == 0) {
                   1082:                        snprintf(str, sizeof(str), "ID \"%s\" already registered", ID);
                   1083:                        if (c->conn_id != NONE)
                   1084:                                Log(LOG_ERR, "%s (on connection %d)!", str, c->conn_id);
                   1085:                        else
                   1086:                                Log(LOG_ERR, "%s (via network)!", str);
                   1087:                        Conn_Close(Client->conn_id, str, str, true);
                   1088:                        return false;
                   1089:                }
                   1090:                c = (CLIENT *)c->next;
                   1091:        }
                   1092:
                   1093:        return true;
                   1094: } /* Client_CheckID */
                   1095:
                   1096:
                   1097: GLOBAL CLIENT *
                   1098: Client_First( void )
                   1099: {
                   1100:        return My_Clients;
                   1101: } /* Client_First */
                   1102:
                   1103:
                   1104: GLOBAL CLIENT *
                   1105: Client_Next( CLIENT *c )
                   1106: {
                   1107:        assert( c != NULL );
                   1108:        return (CLIENT *)c->next;
                   1109: } /* Client_Next */
                   1110:
                   1111:
                   1112: GLOBAL long
                   1113: Client_UserCount( void )
                   1114: {
                   1115:        return Count( CLIENT_USER );
                   1116: } /* Client_UserCount */
                   1117:
                   1118:
                   1119: GLOBAL long
                   1120: Client_ServiceCount( void )
                   1121: {
                   1122:        return Count( CLIENT_SERVICE );;
                   1123: } /* Client_ServiceCount */
                   1124:
                   1125:
                   1126: GLOBAL long
                   1127: Client_ServerCount( void )
                   1128: {
                   1129:        return Count( CLIENT_SERVER );
                   1130: } /* Client_ServerCount */
                   1131:
                   1132:
                   1133: GLOBAL long
                   1134: Client_MyUserCount( void )
                   1135: {
                   1136:        return MyCount( CLIENT_USER );
                   1137: } /* Client_MyUserCount */
                   1138:
                   1139:
                   1140: GLOBAL long
                   1141: Client_MyServiceCount( void )
                   1142: {
                   1143:        return MyCount( CLIENT_SERVICE );
                   1144: } /* Client_MyServiceCount */
                   1145:
                   1146:
                   1147: GLOBAL unsigned long
                   1148: Client_MyServerCount( void )
                   1149: {
                   1150:        CLIENT *c;
                   1151:        unsigned long cnt = 0;
                   1152:
                   1153:        c = My_Clients;
                   1154:        while( c )
                   1155:        {
                   1156:                if(( c->type == CLIENT_SERVER ) && ( c->hops == 1 )) cnt++;
                   1157:                c = (CLIENT *)c->next;
                   1158:        }
                   1159:        return cnt;
                   1160: } /* Client_MyServerCount */
                   1161:
                   1162:
                   1163: GLOBAL unsigned long
                   1164: Client_OperCount( void )
                   1165: {
                   1166:        CLIENT *c;
                   1167:        unsigned long cnt = 0;
                   1168:
                   1169:        c = My_Clients;
                   1170:        while( c )
                   1171:        {
                   1172:                if (c && c->type == CLIENT_USER && Client_HasMode(c, 'o' ))
                   1173:                        cnt++;
                   1174:                c = (CLIENT *)c->next;
                   1175:        }
                   1176:        return cnt;
                   1177: } /* Client_OperCount */
                   1178:
                   1179:
                   1180: GLOBAL unsigned long
                   1181: Client_UnknownCount( void )
                   1182: {
                   1183:        CLIENT *c;
                   1184:        unsigned long cnt = 0;
                   1185:
                   1186:        c = My_Clients;
                   1187:        while( c )
                   1188:        {
                   1189:                if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
                   1190:                c = (CLIENT *)c->next;
                   1191:        }
                   1192:
                   1193:        return cnt;
                   1194: } /* Client_UnknownCount */
                   1195:
                   1196:
                   1197: GLOBAL long
                   1198: Client_MaxUserCount( void )
                   1199: {
                   1200:        return Max_Users;
                   1201: } /* Client_MaxUserCount */
                   1202:
                   1203:
                   1204: GLOBAL long
                   1205: Client_MyMaxUserCount( void )
                   1206: {
                   1207:        return My_Max_Users;
                   1208: } /* Client_MyMaxUserCount */
                   1209:
                   1210:
                   1211: /**
                   1212:  * Check that a given nickname is valid.
                   1213:  *
                   1214:  * @param      Nick the nickname to check.
                   1215:  * @returns    true if nickname is valid, false otherwise.
                   1216:  */
                   1217: GLOBAL bool
                   1218: Client_IsValidNick(const char *Nick)
                   1219: {
                   1220:        const char *ptr;
                   1221:        static const char goodchars[] = ";0123456789-";
                   1222:
                   1223:        assert (Nick != NULL);
                   1224:
                   1225:        if (strchr(goodchars, Nick[0]))
                   1226:                return false;
                   1227:        if (strlen(Nick ) >= Conf_MaxNickLength)
                   1228:                return false;
                   1229:
                   1230:        ptr = Nick;
                   1231:        while (*ptr) {
                   1232:                if (*ptr < 'A' && !strchr(goodchars, *ptr ))
                   1233:                        return false;
                   1234:                if (*ptr > '}')
                   1235:                        return false;
                   1236:                ptr++;
                   1237:        }
                   1238:
                   1239:        return true;
                   1240: } /* Client_IsValidNick */
                   1241:
                   1242:
                   1243: /**
                   1244:  * Return pointer to "My_Whowas" structure.
                   1245:  */
                   1246: GLOBAL WHOWAS *
                   1247: Client_GetWhowas( void )
                   1248: {
                   1249:        return My_Whowas;
                   1250: } /* Client_GetWhowas */
                   1251:
                   1252: /**
                   1253:  * Return the index of the last used WHOWAS entry.
                   1254:  */
                   1255: GLOBAL int
                   1256: Client_GetLastWhowasIndex( void )
                   1257: {
                   1258:        return Last_Whowas;
                   1259: } /* Client_GetLastWhowasIndex */
                   1260:
                   1261:
                   1262: /**
                   1263:  * Get the start time of this client.
                   1264:  * The result is the start time in seconds since 1970-01-01, as reported
                   1265:  * by the C function time(NULL).
                   1266:  */
                   1267: GLOBAL time_t
                   1268: Client_StartTime(CLIENT *Client)
                   1269: {
                   1270:        assert( Client != NULL );
                   1271:        return Client->starttime;
                   1272: } /* Client_Uptime */
                   1273:
                   1274:
                   1275: /**
                   1276:  * Reject a client when logging in.
                   1277:  *
                   1278:  * This function is called when a client isn't allowed to connect to this
                   1279:  * server. Possible reasons are bad server password, bad PAM password,
                   1280:  * or that the client is G/K-Line'd.
                   1281:  *
                   1282:  * After calling this function, the client isn't connected any more.
                   1283:  *
                   1284:  * @param Client The client to reject.
                   1285:  * @param Reason The reason why the client has been rejected.
                   1286:  * @param InformClient If true, send the exact reason to the client.
                   1287:  */
                   1288: GLOBAL void
                   1289: Client_Reject(CLIENT *Client, const char *Reason, bool InformClient)
                   1290: {
                   1291:        char info[COMMAND_LEN];
                   1292:
                   1293:        assert(Client != NULL);
                   1294:        assert(Reason != NULL);
                   1295:
                   1296:        if (InformClient)
                   1297:                snprintf(info, sizeof(info), "Access denied: %s", Reason);
                   1298:        else
                   1299:                strcpy(info, "Access denied: Bad password?");
                   1300:
                   1301:        Log(LOG_ERR,
                   1302:            "User \"%s\" rejected (connection %d): %s!",
                   1303:            Client_Mask(Client), Client_Conn(Client), Reason);
                   1304:        Conn_Close(Client_Conn(Client), Reason, info, true);
                   1305: }
                   1306:
                   1307:
                   1308: /**
                   1309:  * Introduce a new user or service client in the network.
                   1310:  *
                   1311:  * @param From Remote server introducing the client or NULL (local).
                   1312:  * @param Client New client.
                   1313:  * @param Type Type of the client (CLIENT_USER or CLIENT_SERVICE).
                   1314:  */
                   1315: GLOBAL void
                   1316: Client_Introduce(CLIENT *From, CLIENT *Client, int Type)
                   1317: {
                   1318:        /* Set client type (user or service) */
                   1319:        Client_SetType(Client, Type);
                   1320:
                   1321:        if (From) {
                   1322:                if (Conf_NickIsService(Conf_GetServer(Client_Conn(From)),
                   1323:                                   Client_ID(Client)))
                   1324:                        Client_SetType(Client, CLIENT_SERVICE);
                   1325:                LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).",
                   1326:                         Client_TypeText(Client), Client_Mask(Client),
                   1327:                         Client_Modes(Client), Client_ID(From),
                   1328:                         Client_ID(Client_Introducer(Client)),
                   1329:                         Client_Hops(Client), Client_Hops(Client) > 1 ? "s": "");
                   1330:        } else {
                   1331:                Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).",
                   1332:                    Client_TypeText(Client), Client_Mask(Client),
                   1333:                    Client_Conn(Client));
                   1334:                Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s",
                   1335:                                 Client_ID(Client), Client_User(Client),
                   1336:                                 Client_Hostname(Client),
                   1337:                                 Conn_IPA(Client_Conn(Client)),
                   1338:                                 Client_TypeText(Client));
                   1339:        }
                   1340:
                   1341:        /* Inform other servers */
                   1342:        IRC_WriteStrServersPrefixFlag_CB(From,
                   1343:                                From != NULL ? From : Client_ThisServer(),
                   1344:                                '\0', cb_introduceClient, (void *)Client);
                   1345: } /* Client_Introduce */
                   1346:
                   1347:
                   1348: static unsigned long
                   1349: Count( CLIENT_TYPE Type )
                   1350: {
                   1351:        CLIENT *c;
                   1352:        unsigned long cnt = 0;
                   1353:
                   1354:        c = My_Clients;
                   1355:        while( c )
                   1356:        {
                   1357:                if( c->type == Type ) cnt++;
                   1358:                c = (CLIENT *)c->next;
                   1359:        }
                   1360:        return cnt;
                   1361: } /* Count */
                   1362:
                   1363:
                   1364: static unsigned long
                   1365: MyCount( CLIENT_TYPE Type )
                   1366: {
                   1367:        CLIENT *c;
                   1368:        unsigned long cnt = 0;
                   1369:
                   1370:        c = My_Clients;
                   1371:        while( c )
                   1372:        {
                   1373:                if(( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
                   1374:                c = (CLIENT *)c->next;
                   1375:        }
                   1376:        return cnt;
                   1377: } /* MyCount */
                   1378:
                   1379:
                   1380: /**
                   1381:  * Allocate and initialize new CLIENT strcuture.
                   1382:  *
                   1383:  * @return Pointer to CLIENT structure or NULL on error.
                   1384:  */
                   1385: static CLIENT *
                   1386: New_Client_Struct( void )
                   1387: {
                   1388:        CLIENT *c;
                   1389:
                   1390:        c = (CLIENT *)malloc( sizeof( CLIENT ));
                   1391:        if( ! c )
                   1392:        {
                   1393:                Log( LOG_EMERG, "Can't allocate memory! [New_Client_Struct]" );
                   1394:                return NULL;
                   1395:        }
                   1396:
                   1397:        memset( c, 0, sizeof ( CLIENT ));
                   1398:
                   1399:        c->type = CLIENT_UNKNOWN;
                   1400:        c->conn_id = NONE;
                   1401:        c->hops = -1;
                   1402:        c->token = -1;
                   1403:        c->mytoken = -1;
                   1404:
                   1405:        return c;
                   1406: }
                   1407:
                   1408: /**
                   1409:  * Free a CLIENT structure and its member variables.
                   1410:  */
                   1411: static void
                   1412: Free_Client(CLIENT **Client)
                   1413: {
                   1414:        assert(Client != NULL);
                   1415:        assert(*Client != NULL);
                   1416:
                   1417:        if ((*Client)->account_name)
                   1418:                free((*Client)->account_name);
                   1419:        if ((*Client)->away)
                   1420:                free((*Client)->away);
                   1421:        if ((*Client)->cloaked)
                   1422:                free((*Client)->cloaked);
                   1423:        if ((*Client)->ipa_text)
                   1424:                free((*Client)->ipa_text);
                   1425:
                   1426:        free(*Client);
                   1427:        *Client = NULL;
                   1428: }
                   1429:
                   1430: static void
                   1431: Generate_MyToken( CLIENT *Client )
                   1432: {
                   1433:        CLIENT *c;
                   1434:        int token;
                   1435:
                   1436:        c = My_Clients;
                   1437:        token = 2;
                   1438:        while( c )
                   1439:        {
                   1440:                if( c->mytoken == token )
                   1441:                {
                   1442:                        /* The token is already in use */
                   1443:                        token++;
                   1444:                        c = My_Clients;
                   1445:                        continue;
                   1446:                }
                   1447:                else c = (CLIENT *)c->next;
                   1448:        }
                   1449:        Client->mytoken = token;
                   1450:        LogDebug("Assigned token %d to server \"%s\".", token, Client->id);
                   1451: } /* Generate_MyToken */
                   1452:
                   1453:
                   1454: static void
                   1455: Adjust_Counters( CLIENT *Client )
                   1456: {
                   1457:        long count;
                   1458:
                   1459:        assert( Client != NULL );
                   1460:
                   1461:        if( Client->type != CLIENT_USER ) return;
                   1462:
                   1463:        if( Client->conn_id != NONE )
                   1464:        {
                   1465:                /* Local connection */
                   1466:                count = Client_MyUserCount( );
                   1467:                if( count > My_Max_Users ) My_Max_Users = count;
                   1468:        }
                   1469:        count = Client_UserCount( );
                   1470:        if( count > Max_Users ) Max_Users = count;
                   1471: } /* Adjust_Counters */
                   1472:
                   1473:
                   1474: /**
                   1475:  * Register client in My_Whowas structure for further recall by WHOWAS.
                   1476:  * Note: Only clients that have been connected at least 30 seconds will be
                   1477:  * registered to prevent automated IRC bots to "destroy" a nice server
                   1478:  * history database.
                   1479:  */
                   1480: GLOBAL void
                   1481: Client_RegisterWhowas( CLIENT *Client )
                   1482: {
                   1483:        int slot;
                   1484:        time_t now;
                   1485:
                   1486:        assert( Client != NULL );
                   1487:
                   1488:        /* Don't register WHOWAS information when "MorePrivacy" is enabled. */
                   1489:        if (Conf_MorePrivacy)
                   1490:                return;
                   1491:
                   1492:        now = time(NULL);
                   1493:        /* Don't register clients that were connected less than 30 seconds. */
                   1494:        if( now - Client->starttime < 30 )
                   1495:                return;
                   1496:
                   1497:        slot = Last_Whowas + 1;
                   1498:        if( slot >= MAX_WHOWAS || slot < 0 ) slot = 0;
                   1499:
                   1500: #ifdef DEBUG
                   1501:        Log( LOG_DEBUG, "Saving WHOWAS information to slot %d ...", slot );
                   1502: #endif
                   1503:
                   1504:        My_Whowas[slot].time = now;
                   1505:        strlcpy( My_Whowas[slot].id, Client_ID( Client ),
                   1506:                 sizeof( My_Whowas[slot].id ));
                   1507:        strlcpy( My_Whowas[slot].user, Client_User( Client ),
                   1508:                 sizeof( My_Whowas[slot].user ));
                   1509:        strlcpy( My_Whowas[slot].host, Client_HostnameDisplayed( Client ),
                   1510:                 sizeof( My_Whowas[slot].host ));
                   1511:        strlcpy( My_Whowas[slot].info, Client_Info( Client ),
                   1512:                 sizeof( My_Whowas[slot].info ));
                   1513:        strlcpy( My_Whowas[slot].server, Client_ID( Client_Introducer( Client )),
                   1514:                 sizeof( My_Whowas[slot].server ));
                   1515:
                   1516:        Last_Whowas = slot;
                   1517: } /* Client_RegisterWhowas */
                   1518:
                   1519:
                   1520: GLOBAL const char *
                   1521: Client_TypeText(CLIENT *Client)
                   1522: {
                   1523:        assert(Client != NULL);
                   1524:        switch (Client_Type(Client)) {
                   1525:                case CLIENT_USER:
                   1526:                        return "User";
                   1527:                        break;
                   1528:                case CLIENT_SERVICE:
                   1529:                        return "Service";
                   1530:                        break;
                   1531:                case CLIENT_SERVER:
                   1532:                        return "Server";
                   1533:                        break;
                   1534:                default:
                   1535:                        return "Client";
                   1536:        }
                   1537: } /* Client_TypeText */
                   1538:
                   1539:
                   1540: /**
                   1541:  * Destroy user or service client.
                   1542:  */
                   1543: static void
                   1544: Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool SendQuit)
                   1545: {
                   1546:        if(Client->conn_id != NONE) {
                   1547:                /* Local (directly connected) client */
                   1548:                Log(LOG_NOTICE,
                   1549:                    "%s \"%s\" unregistered (connection %d): %s.",
                   1550:                    Client_TypeText(Client), Client_Mask(Client),
                   1551:                    Client->conn_id, Txt);
                   1552:                Log_ServerNotice('c', "Client exiting: %s (%s@%s) [%s]",
                   1553:                                 Client_ID(Client), Client_User(Client),
                   1554:                                 Client_Hostname(Client), Txt);
                   1555:
                   1556:                if (SendQuit) {
                   1557:                        /* Inforam all the other servers */
                   1558:                        if (FwdMsg)
                   1559:                                IRC_WriteStrServersPrefix(NULL,
                   1560:                                                Client, "QUIT :%s", FwdMsg );
                   1561:                        else
                   1562:                                IRC_WriteStrServersPrefix(NULL,
                   1563:                                                Client, "QUIT :");
                   1564:                }
                   1565:        } else {
                   1566:                /* Remote client */
                   1567:                LogDebug("%s \"%s\" unregistered: %s.",
                   1568:                         Client_TypeText(Client), Client_Mask(Client), Txt);
                   1569:
                   1570:                if(SendQuit) {
                   1571:                        /* Inform all the other servers, but the ones in the
                   1572:                         * direction we got the QUIT from */
                   1573:                        if(FwdMsg)
                   1574:                                IRC_WriteStrServersPrefix(Client_NextHop(Client),
                   1575:                                                Client, "QUIT :%s", FwdMsg );
                   1576:                        else
                   1577:                                IRC_WriteStrServersPrefix(Client_NextHop(Client),
                   1578:                                                Client, "QUIT :" );
                   1579:                }
                   1580:        }
                   1581:
                   1582:        /* Unregister client from channels */
                   1583:        Channel_Quit(Client, FwdMsg ? FwdMsg : Client->id);
                   1584:
                   1585:        /* Register client in My_Whowas structure */
                   1586:        Client_RegisterWhowas(Client);
                   1587: } /* Destroy_UserOrService */
                   1588:
                   1589:
                   1590: /**
                   1591:  * Introduce a new user or service client to a remote server.
                   1592:  *
                   1593:  * @param To           The remote server to inform.
                   1594:  * @param Prefix       Prefix for the generated commands.
                   1595:  * @param data         CLIENT structure of the new client.
                   1596:  */
                   1597: static void
                   1598: cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data)
                   1599: {
                   1600:        CLIENT *c = (CLIENT *)data;
                   1601:
                   1602:        (void)Client_Announce(To, Prefix, c);
                   1603:
                   1604: } /* cb_introduceClient */
                   1605:
                   1606:
                   1607: /**
                   1608:  * Announce an user or service to a server.
                   1609:  *
                   1610:  * This function differentiates between RFC1459 and RFC2813 server links and
                   1611:  * generates the appropriate commands to register the user or service.
                   1612:  *
                   1613:  * @param Client       Server
                   1614:  * @param Prefix       Prefix for the generated commands
                   1615:  * @param User         User to announce
                   1616:  */
                   1617: GLOBAL bool
                   1618: Client_Announce(CLIENT * Client, CLIENT * Prefix, CLIENT * User)
                   1619: {
                   1620:        CONN_ID conn;
                   1621:        char *modes, *user, *host;
                   1622:
                   1623:        modes = Client_Modes(User);
                   1624:        user = Client_User(User) ? Client_User(User) : "-";
                   1625:        host = Client_Hostname(User) ? Client_Hostname(User) : "-";
                   1626:
                   1627:        conn = Client_Conn(Client);
                   1628:        if (Conn_Options(conn) & CONN_RFC1459) {
                   1629:                /* RFC 1459 mode: separate NICK and USER commands */
                   1630:                if (! Conn_WriteStr(conn, "NICK %s :%d",
                   1631:                                    Client_ID(User), Client_Hops(User) + 1))
                   1632:                        return DISCONNECTED;
                   1633:                if (! Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
                   1634:                                     Client_ID(User), user, host,
                   1635:                                     Client_ID(Client_Introducer(User)),
                   1636:                                     Client_Info(User)))
                   1637:                        return DISCONNECTED;
                   1638:                if (modes[0]) {
                   1639:                        if (! Conn_WriteStr(conn, ":%s MODE %s +%s",
                   1640:                                     Client_ID(User), Client_ID(User),
                   1641:                                     modes))
                   1642:                                return DISCONNECTED;
                   1643:                }
                   1644:        } else {
                   1645:                /* RFC 2813 mode: one combined NICK or SERVICE command */
                   1646:                if (Client_Type(User) == CLIENT_SERVICE
                   1647:                    && Client_HasFlag(Client, 'S')) {
                   1648:                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                   1649:                                        "SERVICE %s %d * +%s %d :%s",
                   1650:                                        Client_Mask(User),
                   1651:                                        Client_MyToken(Client_Introducer(User)),
                   1652:                                        modes, Client_Hops(User) + 1,
                   1653:                                        Client_Info(User)))
                   1654:                                return DISCONNECTED;
                   1655:                } else {
                   1656:                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                   1657:                                        "NICK %s %d %s %s %d +%s :%s",
                   1658:                                        Client_ID(User), Client_Hops(User) + 1,
                   1659:                                        user, host,
                   1660:                                        Client_MyToken(Client_Introducer(User)),
                   1661:                                        modes, Client_Info(User)))
                   1662:                                return DISCONNECTED;
                   1663:                }
                   1664:        }
                   1665:
                   1666:        if (Client_HasFlag(Client, 'M')) {
                   1667:                /* Synchronize metadata */
                   1668:                if (Client_HostnameCloaked(User)) {
                   1669:                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                   1670:                                        "METADATA %s cloakhost :%s",
                   1671:                                        Client_ID(User),
                   1672:                                        Client_HostnameCloaked(User)))
                   1673:                                return DISCONNECTED;
                   1674:                }
                   1675:
                   1676:                if (Client_AccountName(User)) {
                   1677:                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                   1678:                                        "METADATA %s accountname :%s",
                   1679:                                        Client_ID(User),
                   1680:                                        Client_AccountName(User)))
                   1681:                                return DISCONNECTED;
                   1682:                }
                   1683:
                   1684:                if (Conn_GetCertFp(Client_Conn(User))) {
                   1685:                        if (!IRC_WriteStrClientPrefix(Client, Prefix,
                   1686:                                        "METADATA %s certfp :%s",
                   1687:                                        Client_ID(User),
                   1688:                                        Conn_GetCertFp(Client_Conn(User))))
                   1689:                                return DISCONNECTED;
                   1690:                }
                   1691:        }
                   1692:
                   1693:        return CONNECTED;
                   1694: } /* Client_Announce */
                   1695:
                   1696:
                   1697: #ifdef DEBUG
                   1698:
                   1699: GLOBAL void
                   1700: Client_DebugDump(void)
                   1701: {
                   1702:        CLIENT *c;
                   1703:
                   1704:        Log(LOG_DEBUG, "Client status:");
                   1705:        c = My_Clients;
                   1706:        while (c) {
                   1707:                Log(LOG_DEBUG,
                   1708:                    " - %s: type=%d, host=%s, user=%s, conn=%d, start=%ld, flags=%s",
                   1709:                    Client_ID(c), Client_Type(c), Client_Hostname(c),
                   1710:                    Client_User(c), Client_Conn(c), Client_StartTime(c),
                   1711:                    Client_Flags(c));
                   1712:                c = (CLIENT *)c->next;
                   1713:        }
                   1714: } /* Client_DumpClients */
                   1715:
                   1716: #endif
                   1717:
                   1718:
                   1719: /* -eof- */

CVSweb