#include "inspircd_config.h"
#include "channels.h"
#include "inspstring.h"
#include "connection.h"
#include <string>
#include "hashcomp.h"
Include dependency graph for users.h:
This graph shows which files directly or indirectly include this file:
Go to the source code of this file.
Classes | |
class | Invited |
Holds a channel name to which a user has been invited. More... | |
class | ConnectClass |
Holds information relevent to <connect allow> and <connect deny> tags in the config file. More... | |
class | userrec |
Holds all information about a user This class stores all information about a user connected to the irc server. More... | |
class | WhoWasUser |
A lightweight userrec used by WHOWAS. More... | |
Defines | |
#define | STATUS_OP 4 |
#define | STATUS_HOP 2 |
#define | STATUS_VOICE 1 |
#define | STATUS_NORMAL 0 |
#define | CC_ALLOW 0 |
#define | CC_DENY 1 |
Typedefs | |
typedef std::vector< Invited > | InvitedList |
Holds a complete list of all channels to which a user has been invited and has not yet joined. | |
typedef std::vector< ConnectClass > | ClassVector |
Holds a complete list of all allow and deny tags from the configuration file (connection classes). | |
Functions | |
template<typename T> | |
string | ConvToStr (const T &in) |
void | AddOper (userrec *user) |
void | DeleteOper (userrec *user) |
void | kill_link (userrec *user, const char *r) |
void | kill_link_silent (userrec *user, const char *r) |
void | AddWhoWas (userrec *u) |
void | AddClient (int socket, char *host, int port, bool iscached, char *ip) |
void | FullConnectUser (userrec *user) |
void | ConnectUser (userrec *user) |
userrec * | ReHashNick (char *Old, char *New) |
void | force_nickchange (userrec *user, const char *newnick) |
|
Definition at line 36 of file users.h. Referenced by AddClient(). |
|
|
|
Definition at line 32 of file users.h. Referenced by kick_channel(). |
|
|
|
|
|
|
|
Holds a complete list of all allow and deny tags from the configuration file (connection classes).
|
|
Holds a complete list of all channels to which a user has been invited and has not yet joined.
|
|
Definition at line 524 of file users.cpp. References SocketEngine::AddFd(), CC_ALLOW, ucrec::channel, ServerConfig::Classes, clientlist, ConvToStr(), DEBUG, ServerConfig::dns_timeout, FindServerNamePtr(), kill_link(), local_users, log(), matches_exception(), matches_zline(), InspIRCd::SE, ServerConfig::ServerName, ServerConfig::SoftLimit, TIME, ucrec::uc_modes, and X_ESTAB_CLIENT. 00525 { 00526 string tempnick; 00527 char tn2[MAXBUF]; 00528 user_hash::iterator iter; 00529 00530 tempnick = ConvToStr(socket) + "-unknown"; 00531 sprintf(tn2,"%lu-unknown",(unsigned long)socket); 00532 00533 iter = clientlist.find(tempnick); 00534 00535 // fix by brain. 00536 // as these nicknames are 'RFC impossible', we can be sure nobody is going to be 00537 // using one as a registered connection. As theyre per fd, we can also safely assume 00538 // that we wont have collisions. Therefore, if the nick exists in the list, its only 00539 // used by a dead socket, erase the iterator so that the new client may reclaim it. 00540 // this was probably the cause of 'server ignores me when i hammer it with reconnects' 00541 // issue in earlier alphas/betas 00542 if (iter != clientlist.end()) 00543 { 00544 userrec* goner = iter->second; 00545 delete goner; 00546 clientlist.erase(iter); 00547 } 00548 00549 /* 00550 * It is OK to access the value here this way since we know 00551 * it exists, we just created it above. 00552 * 00553 * At NO other time should you access a value in a map or a 00554 * hash_map this way. 00555 */ 00556 clientlist[tempnick] = new userrec(); 00557 00558 log(DEBUG,"AddClient: %lu %s %d %s",(unsigned long)socket,host,port,ip); 00559 00560 clientlist[tempnick]->fd = socket; 00561 strlcpy(clientlist[tempnick]->nick, tn2,NICKMAX); 00562 strlcpy(clientlist[tempnick]->host, host,160); 00563 strlcpy(clientlist[tempnick]->dhost, host,160); 00564 clientlist[tempnick]->server = (char*)FindServerNamePtr(Config->ServerName); 00565 strlcpy(clientlist[tempnick]->ident, "unknown",IDENTMAX); 00566 clientlist[tempnick]->registered = 0; 00567 clientlist[tempnick]->signon = TIME + Config->dns_timeout; 00568 clientlist[tempnick]->lastping = 1; 00569 clientlist[tempnick]->port = port; 00570 strlcpy(clientlist[tempnick]->ip,ip,16); 00571 00572 // set the registration timeout for this user 00573 unsigned long class_regtimeout = 90; 00574 int class_flood = 0; 00575 long class_threshold = 5; 00576 long class_sqmax = 262144; // 256kb 00577 long class_rqmax = 4096; // 4k 00578 00579 for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++) 00580 { 00581 if (match(clientlist[tempnick]->host,i->host) && (i->type == CC_ALLOW)) 00582 { 00583 class_regtimeout = (unsigned long)i->registration_timeout; 00584 class_flood = i->flood; 00585 clientlist[tempnick]->pingmax = i->pingtime; 00586 class_threshold = i->threshold; 00587 class_sqmax = i->sendqmax; 00588 class_rqmax = i->recvqmax; 00589 break; 00590 } 00591 } 00592 00593 clientlist[tempnick]->nping = TIME+clientlist[tempnick]->pingmax + Config->dns_timeout; 00594 clientlist[tempnick]->timeout = TIME+class_regtimeout; 00595 clientlist[tempnick]->flood = class_flood; 00596 clientlist[tempnick]->threshold = class_threshold; 00597 clientlist[tempnick]->sendqmax = class_sqmax; 00598 clientlist[tempnick]->recvqmax = class_rqmax; 00599 00600 ucrec a; 00601 a.channel = NULL; 00602 a.uc_modes = 0; 00603 for (int i = 0; i < MAXCHANS; i++) 00604 clientlist[tempnick]->chans.push_back(a); 00605 00606 if (clientlist.size() > Config->SoftLimit) 00607 { 00608 kill_link(clientlist[tempnick],"No more connections allowed"); 00609 return; 00610 } 00611 00612 if (clientlist.size() >= MAXCLIENTS) 00613 { 00614 kill_link(clientlist[tempnick],"No more connections allowed"); 00615 return; 00616 } 00617 00618 // this is done as a safety check to keep the file descriptors within range of fd_ref_table. 00619 // its a pretty big but for the moment valid assumption: 00620 // file descriptors are handed out starting at 0, and are recycled as theyre freed. 00621 // therefore if there is ever an fd over 65535, 65536 clients must be connected to the 00622 // irc server at once (or the irc server otherwise initiating this many connections, files etc) 00623 // which for the time being is a physical impossibility (even the largest networks dont have more 00624 // than about 10,000 users on ONE server!) 00625 if ((unsigned)socket > 65534) 00626 { 00627 kill_link(clientlist[tempnick],"Server is full"); 00628 return; 00629 } 00630 char* e = matches_exception(ip); 00631 if (!e) 00632 { 00633 char* r = matches_zline(ip); 00634 if (r) 00635 { 00636 char reason[MAXBUF]; 00637 snprintf(reason,MAXBUF,"Z-Lined: %s",r); 00638 kill_link(clientlist[tempnick],reason); 00639 return; 00640 } 00641 } 00642 fd_ref_table[socket] = clientlist[tempnick]; 00643 local_users.push_back(clientlist[tempnick]); 00644 ServerInstance->SE->AddFd(socket,true,X_ESTAB_CLIENT); 00645 }
|
|
Definition at line 330 of file users.cpp. References all_opers, DEBUG, and log(). 00331 { 00332 log(DEBUG,"Oper added to optimization list"); 00333 all_opers.push_back(user); 00334 }
|
|
Definition at line 471 of file users.cpp. References DEBUG, userrec::dhost, WhoWasUser::dhost, userrec::fullname, WhoWasUser::fullname, connection::host, WhoWasUser::host, userrec::ident, WhoWasUser::ident, log(), WhoWasUser::nick, userrec::nick, userrec::server, WhoWasUser::server, connection::signon, WhoWasUser::signon, TIME, whowas, WHOWAS_MAX, and WHOWAS_STALE. Referenced by kill_link(). 00472 { 00473 whowas_hash::iterator iter = whowas.find(u->nick); 00474 WhoWasUser *a = new WhoWasUser(); 00475 strlcpy(a->nick,u->nick,NICKMAX); 00476 strlcpy(a->ident,u->ident,IDENTMAX); 00477 strlcpy(a->dhost,u->dhost,160); 00478 strlcpy(a->host,u->host,160); 00479 strlcpy(a->fullname,u->fullname,MAXGECOS); 00480 strlcpy(a->server,u->server,256); 00481 a->signon = u->signon; 00482 00483 /* MAX_WHOWAS: max number of /WHOWAS items 00484 * WHOWAS_STALE: number of hours before a WHOWAS item is marked as stale and 00485 * can be replaced by a newer one 00486 */ 00487 00488 if (iter == whowas.end()) 00489 { 00490 if (whowas.size() >= (unsigned)WHOWAS_MAX) 00491 { 00492 for (whowas_hash::iterator i = whowas.begin(); i != whowas.end(); i++) 00493 { 00494 // 3600 seconds in an hour ;) 00495 if ((i->second->signon)<(TIME-(WHOWAS_STALE*3600))) 00496 { 00497 // delete the old one 00498 if (i->second) delete i->second; 00499 // replace with new one 00500 i->second = a; 00501 log(DEBUG,"added WHOWAS entry, purged an old record"); 00502 return; 00503 } 00504 } 00505 // no space left and user doesnt exist. Don't leave ram in use! 00506 log(DEBUG,"Not able to update whowas (list at WHOWAS_MAX entries and trying to add new?), freeing excess ram"); 00507 delete a; 00508 } 00509 else 00510 { 00511 log(DEBUG,"added fresh WHOWAS entry"); 00512 whowas[a->nick] = a; 00513 } 00514 } 00515 else 00516 { 00517 log(DEBUG,"updated WHOWAS entry"); 00518 if (iter->second) delete iter->second; 00519 iter->second = a; 00520 } 00521 }
|
|
Definition at line 731 of file users.cpp. References userrec::dns_done, FullConnectUser(), and connection::registered. 00732 { 00733 // dns is already done, things are fast. no need to wait for dns to complete just pass them straight on 00734 if ((user->dns_done) && (user->registered >= 3) && (AllModulesReportReady(user))) 00735 { 00736 FullConnectUser(user); 00737 } 00738 }
|
|
Definition at line 56 of file users.cpp. Referenced by AddClient(). 00057 { 00058 stringstream tmp; 00059 if (!(tmp << in)) return string(); 00060 return tmp.str(); 00061 }
|
|
Definition at line 336 of file users.cpp. References all_opers, DEBUG, and log(). 00337 { 00338 for (std::vector<userrec*>::iterator a = all_opers.begin(); a < all_opers.end(); a++) 00339 { 00340 if (*a == user) 00341 { 00342 log(DEBUG,"Oper removed from optimization list"); 00343 all_opers.erase(a); 00344 return; 00345 } 00346 } 00347 }
|
|
Definition at line 769 of file users.cpp. References FOREACH_RESULT, kill_link(), matches_qline(), InspIRCd::Parser, connection::registered, InspIRCd::stats, and serverstats::statsCollisions. Referenced by Server::ChangeUserNick(). 00770 { 00771 char nick[MAXBUF]; 00772 int MOD_RESULT = 0; 00773 00774 strcpy(nick,""); 00775 00776 FOREACH_RESULT(OnUserPreNick(user,newnick)); 00777 if (MOD_RESULT) { 00778 ServerInstance->stats->statsCollisions++; 00779 kill_link(user,"Nickname collision"); 00780 return; 00781 } 00782 if (matches_qline(newnick)) 00783 { 00784 ServerInstance->stats->statsCollisions++; 00785 kill_link(user,"Nickname collision"); 00786 return; 00787 } 00788 00789 if (user) 00790 { 00791 if (newnick) 00792 { 00793 strncpy(nick,newnick,MAXBUF); 00794 } 00795 if (user->registered == 7) 00796 { 00797 char* pars[1]; 00798 pars[0] = nick; 00799 std::string cmd = "NICK"; 00800 ServerInstance->Parser->CallHandler(cmd,pars,1,user); 00801 } 00802 } 00803 }
|
|
Definition at line 647 of file users.cpp. References DEBUG, connection::fd, FOREACH_MOD, connection::haspassed, connection::host, userrec::ident, connection::idle_lastmsg, connection::ip, kill_link(), kill_link_silent(), log(), matches_exception(), matches_gline(), matches_kline(), ServerConfig::Network, userrec::nick, connection::port, connection::registered, ServerConfig::ServerName, InspIRCd::stats, serverstats::statsConnects, TIME, WriteOpers(), and WriteServ(). Referenced by ConnectUser(). 00648 { 00649 ServerInstance->stats->statsConnects++; 00650 user->idle_lastmsg = TIME; 00651 log(DEBUG,"ConnectUser: %s",user->nick); 00652 00653 if ((strcmp(Passwd(user),"")) && (!user->haspassed)) 00654 { 00655 kill_link(user,"Invalid password"); 00656 return; 00657 } 00658 if (IsDenied(user)) 00659 { 00660 kill_link(user,"Unauthorised connection"); 00661 return; 00662 } 00663 00664 char match_against[MAXBUF]; 00665 snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host); 00666 char* e = matches_exception(match_against); 00667 if (!e) 00668 { 00669 char* r = matches_gline(match_against); 00670 if (r) 00671 { 00672 char reason[MAXBUF]; 00673 snprintf(reason,MAXBUF,"G-Lined: %s",r); 00674 kill_link_silent(user,reason); 00675 return; 00676 } 00677 r = matches_kline(user->host); 00678 if (r) 00679 { 00680 char reason[MAXBUF]; 00681 snprintf(reason,MAXBUF,"K-Lined: %s",r); 00682 kill_link_silent(user,reason); 00683 return; 00684 } 00685 } 00686 00687 00688 WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Config->Network); 00689 WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Config->Network,user->nick,user->ident,user->host); 00690 WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,Config->ServerName,VERSION); 00691 WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__); 00692 WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,Config->ServerName,VERSION); 00693 // the neatest way to construct the initial 005 numeric, considering the number of configure constants to go in it... 00694 std::stringstream v; 00695 v << "WALLCHOPS MODES=13 CHANTYPES=# PREFIX=(ohv)@%+ MAP SAFELIST MAXCHANNELS=" << MAXCHANS; 00696 v << " MAXBANS=60 NICKLEN=" << NICKMAX; 00697 v << " TOPICLEN=" << MAXTOPIC << " KICKLEN=" << MAXKICK << " MAXTARGETS=20 AWAYLEN=" << MAXAWAY << " CHANMODES=ohvb,k,l,psmnti NETWORK="; 00698 v << Config->Network; 00699 std::string data005 = v.str(); 00700 FOREACH_MOD On005Numeric(data005); 00701 // anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line... 00702 // so i'd better split it :) 00703 std::stringstream out(data005); 00704 std::string token = ""; 00705 std::string line5 = ""; 00706 int token_counter = 0; 00707 while (!out.eof()) 00708 { 00709 out >> token; 00710 line5 = line5 + token + " "; 00711 token_counter++; 00712 if ((token_counter >= 13) || (out.eof() == true)) 00713 { 00714 WriteServ(user->fd,"005 %s %s:are supported by this server",user->nick,line5.c_str()); 00715 line5 = ""; 00716 token_counter = 0; 00717 } 00718 } 00719 ShowMOTD(user); 00720 00721 // fix 3 by brain, move registered = 7 below these so that spurious modes and host changes dont go out 00722 // onto the network and produce 'fake direction' 00723 FOREACH_MOD OnUserConnect(user); 00724 FOREACH_MOD OnGlobalConnect(user); 00725 user->registered = 7; 00726 WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,user->ip); 00727 }
|
|
Definition at line 349 of file users.cpp. References AddWhoWas(), clientlist, userrec::CloseSocket(), DEBUG, SocketEngine::DelFd(), connection::fd, userrec::FlushWriteBuf(), FOREACH_MOD, ServerConfig::GetIOHook(), connection::host, userrec::ident, local_users, log(), userrec::nick, Module::OnRawSocketClose(), connection::port, connection::registered, InspIRCd::SE, Write(), WriteCommonExcept(), and WriteOpers(). Referenced by AddClient(), force_nickchange(), FullConnectUser(), Server::PseudoToUser(), and Server::QuitUser(). 00350 { 00351 user_hash::iterator iter = clientlist.find(user->nick); 00352 00353 char reason[MAXBUF]; 00354 00355 strncpy(reason,r,MAXBUF); 00356 00357 if (strlen(reason)>MAXQUIT) 00358 { 00359 reason[MAXQUIT-1] = '\0'; 00360 } 00361 00362 log(DEBUG,"kill_link: %s '%s'",user->nick,reason); 00363 Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason); 00364 log(DEBUG,"closing fd %lu",(unsigned long)user->fd); 00365 00366 if (user->registered == 7) { 00367 FOREACH_MOD OnUserQuit(user,reason); 00368 WriteCommonExcept(user,"QUIT :%s",reason); 00369 } 00370 00371 user->FlushWriteBuf(); 00372 00373 FOREACH_MOD OnUserDisconnect(user); 00374 00375 if (user->fd > -1) 00376 { 00377 if (Config->GetIOHook(user->port)) 00378 { 00379 Config->GetIOHook(user->port)->OnRawSocketClose(user->fd); 00380 } 00381 ServerInstance->SE->DelFd(user->fd); 00382 user->CloseSocket(); 00383 } 00384 00385 // this must come before the WriteOpers so that it doesnt try to fill their buffer with anything 00386 // if they were an oper with +s. 00387 if (user->registered == 7) { 00388 purge_empty_chans(user); 00389 // fix by brain: only show local quits because we only show local connects (it just makes SENSE) 00390 if (user->fd > -1) 00391 WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason); 00392 AddWhoWas(user); 00393 } 00394 00395 if (iter != clientlist.end()) 00396 { 00397 log(DEBUG,"deleting user hash value %lu",(unsigned long)user); 00398 if (user->fd > -1) 00399 { 00400 fd_ref_table[user->fd] = NULL; 00401 if (find(local_users.begin(),local_users.end(),user) != local_users.end()) 00402 { 00403 local_users.erase(find(local_users.begin(),local_users.end(),user)); 00404 log(DEBUG,"Delete local user"); 00405 } 00406 } 00407 clientlist.erase(iter); 00408 } 00409 delete user; 00410 }
|
|
Definition at line 412 of file users.cpp. References clientlist, userrec::CloseSocket(), DEBUG, SocketEngine::DelFd(), connection::fd, userrec::FlushWriteBuf(), FOREACH_MOD, ServerConfig::GetIOHook(), connection::host, userrec::ident, local_users, log(), userrec::nick, Module::OnRawSocketClose(), connection::port, connection::registered, InspIRCd::SE, Write(), and WriteCommonExcept(). Referenced by FullConnectUser(). 00413 { 00414 user_hash::iterator iter = clientlist.find(user->nick); 00415 00416 char reason[MAXBUF]; 00417 00418 strncpy(reason,r,MAXBUF); 00419 00420 if (strlen(reason)>MAXQUIT) 00421 { 00422 reason[MAXQUIT-1] = '\0'; 00423 } 00424 00425 log(DEBUG,"kill_link: %s '%s'",user->nick,reason); 00426 Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason); 00427 log(DEBUG,"closing fd %lu",(unsigned long)user->fd); 00428 00429 user->FlushWriteBuf(); 00430 00431 if (user->registered == 7) { 00432 FOREACH_MOD OnUserQuit(user,reason); 00433 WriteCommonExcept(user,"QUIT :%s",reason); 00434 } 00435 00436 FOREACH_MOD OnUserDisconnect(user); 00437 00438 if (user->fd > -1) 00439 { 00440 if (Config->GetIOHook(user->port)) 00441 { 00442 Config->GetIOHook(user->port)->OnRawSocketClose(user->fd); 00443 } 00444 ServerInstance->SE->DelFd(user->fd); 00445 user->CloseSocket(); 00446 } 00447 00448 if (user->registered == 7) { 00449 purge_empty_chans(user); 00450 } 00451 00452 if (iter != clientlist.end()) 00453 { 00454 log(DEBUG,"deleting user hash value %lu",(unsigned long)user); 00455 if (user->fd > -1) 00456 { 00457 fd_ref_table[user->fd] = NULL; 00458 if (find(local_users.begin(),local_users.end(),user) != local_users.end()) 00459 { 00460 log(DEBUG,"Delete local user"); 00461 local_users.erase(find(local_users.begin(),local_users.end(),user)); 00462 } 00463 } 00464 clientlist.erase(iter); 00465 } 00466 delete user; 00467 }
|
|
Definition at line 743 of file users.cpp. References clientlist, DEBUG, and log(). 00744 { 00745 //user_hash::iterator newnick; 00746 user_hash::iterator oldnick = clientlist.find(Old); 00747 00748 log(DEBUG,"ReHashNick: %s %s",Old,New); 00749 00750 if (!strcasecmp(Old,New)) 00751 { 00752 log(DEBUG,"old nick is new nick, skipping"); 00753 return oldnick->second; 00754 } 00755 00756 if (oldnick == clientlist.end()) return NULL; /* doesnt exist */ 00757 00758 log(DEBUG,"ReHashNick: Found hashed nick %s",Old); 00759 00760 userrec* olduser = oldnick->second; 00761 clientlist[New] = olduser; 00762 clientlist.erase(oldnick); 00763 00764 log(DEBUG,"ReHashNick: Nick rehashed as %s",New); 00765 00766 return clientlist[New]; 00767 }
|