client.c 23 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /*
  2. * ngIRCd -- The Next Generation IRC Daemon
  3. * Copyright (c)2001-2005 by Alexander Barton (alex@barton.de)
  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. * Client management.
  12. */
  13. #define __client_c__
  14. #include "portab.h"
  15. static char UNUSED id[] = "$Id: client.c,v 1.91.2.2 2007/04/03 22:08:52 fw Exp $";
  16. #include "imp.h"
  17. #include <assert.h>
  18. #include <unistd.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <strings.h>
  23. #include <netdb.h>
  24. #include "defines.h"
  25. #include "conn.h"
  26. #include "exp.h"
  27. #include "client.h"
  28. #include <imp.h>
  29. #include "ngircd.h"
  30. #include "channel.h"
  31. #include "resolve.h"
  32. #include "conf.h"
  33. #include "hash.h"
  34. #include "irc-write.h"
  35. #include "log.h"
  36. #include "messages.h"
  37. #include <exp.h>
  38. #define GETID_LEN (CLIENT_NICK_LEN-1) + 1 + (CLIENT_USER_LEN-1) + 1 + (CLIENT_HOST_LEN-1) + 1
  39. static CLIENT *This_Server, *My_Clients;
  40. static char GetID_Buffer[GETID_LEN];
  41. static WHOWAS My_Whowas[MAX_WHOWAS];
  42. static int Last_Whowas = -1;
  43. static unsigned long Count PARAMS(( CLIENT_TYPE Type ));
  44. static unsigned long MyCount PARAMS(( CLIENT_TYPE Type ));
  45. static CLIENT *New_Client_Struct PARAMS(( void ));
  46. static void Generate_MyToken PARAMS(( CLIENT *Client ));
  47. static void Adjust_Counters PARAMS(( CLIENT *Client ));
  48. static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
  49. CLIENT *TopServer, int Type, char *ID, char *User, char *Hostname,
  50. char *Info, int Hops, int Token, char *Modes, bool Idented));
  51. long Max_Users = 0, My_Max_Users = 0;
  52. GLOBAL void
  53. Client_Init( void )
  54. {
  55. struct hostent *h;
  56. This_Server = New_Client_Struct( );
  57. if( ! This_Server )
  58. {
  59. Log( LOG_EMERG, "Can't allocate client structure for server! Going down." );
  60. Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
  61. exit( 1 );
  62. }
  63. /* Client-Struktur dieses Servers */
  64. This_Server->next = NULL;
  65. This_Server->type = CLIENT_SERVER;
  66. This_Server->conn_id = NONE;
  67. This_Server->introducer = This_Server;
  68. This_Server->mytoken = 1;
  69. This_Server->hops = 0;
  70. gethostname( This_Server->host, CLIENT_HOST_LEN );
  71. h = gethostbyname( This_Server->host );
  72. if( h ) strlcpy( This_Server->host, h->h_name, sizeof( This_Server->host ));
  73. Client_SetID( This_Server, Conf_ServerName );
  74. Client_SetInfo( This_Server, Conf_ServerInfo );
  75. My_Clients = This_Server;
  76. memset( &My_Whowas, 0, sizeof( My_Whowas ));
  77. } /* Client_Init */
  78. GLOBAL void
  79. Client_Exit( void )
  80. {
  81. CLIENT *c, *next;
  82. int cnt;
  83. if( NGIRCd_SignalRestart ) Client_Destroy( This_Server, "Server going down (restarting).", NULL, false );
  84. else Client_Destroy( This_Server, "Server going down.", NULL, false );
  85. cnt = 0;
  86. c = My_Clients;
  87. while( c )
  88. {
  89. cnt++;
  90. next = (CLIENT *)c->next;
  91. free( c );
  92. c = next;
  93. }
  94. if( cnt ) Log( LOG_INFO, "Freed %d client structure%s.", cnt, cnt == 1 ? "" : "s" );
  95. } /* Client_Exit */
  96. GLOBAL CLIENT *
  97. Client_ThisServer( void )
  98. {
  99. return This_Server;
  100. } /* Client_ThisServer */
  101. /**
  102. * Initialize new local client; wrapper function for Init_New_Client().
  103. * @return New CLIENT structure.
  104. */
  105. GLOBAL CLIENT *
  106. Client_NewLocal(CONN_ID Idx, char *Hostname, int Type, bool Idented)
  107. {
  108. return Init_New_Client(Idx, This_Server, NULL, Type, NULL, NULL,
  109. Hostname, NULL, 0, 0, NULL, Idented);
  110. } /* Client_NewLocal */
  111. /**
  112. * Initialize new remote server; wrapper function for Init_New_Client().
  113. * @return New CLIENT structure.
  114. */
  115. GLOBAL CLIENT *
  116. Client_NewRemoteServer(CLIENT *Introducer, char *Hostname, CLIENT *TopServer,
  117. int Hops, int Token, char *Info, bool Idented)
  118. {
  119. return Init_New_Client(NONE, Introducer, TopServer, CLIENT_SERVER,
  120. Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented);
  121. } /* Client_NewRemoteServer */
  122. /**
  123. * Initialize new remote client; wrapper function for Init_New_Client().
  124. * @return New CLIENT structure.
  125. */
  126. GLOBAL CLIENT *
  127. Client_NewRemoteUser(CLIENT *Introducer, char *Nick, int Hops, char *User,
  128. char *Hostname, int Token, char *Modes, char *Info, bool Idented)
  129. {
  130. return Init_New_Client(NONE, Introducer, NULL, CLIENT_USER, Nick,
  131. User, Hostname, Info, Hops, Token, Modes, Idented);
  132. } /* Client_NewRemoteUser */
  133. /**
  134. * Initialize new client and set up the given parameters like client type,
  135. * user name, host name, introducing server etc. ...
  136. * @return New CLIENT structure.
  137. */
  138. static CLIENT *
  139. Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
  140. int Type, char *ID, char *User, char *Hostname, char *Info, int Hops,
  141. int Token, char *Modes, bool Idented)
  142. {
  143. CLIENT *client;
  144. assert( Idx >= NONE );
  145. assert( Introducer != NULL );
  146. assert( Hostname != NULL );
  147. client = New_Client_Struct( );
  148. if( ! client ) return NULL;
  149. /* Initialisieren */
  150. client->starttime = time(NULL);
  151. client->conn_id = Idx;
  152. client->introducer = Introducer;
  153. client->topserver = TopServer;
  154. client->type = Type;
  155. if( ID ) Client_SetID( client, ID );
  156. if( User ) Client_SetUser( client, User, Idented );
  157. if( Hostname ) Client_SetHostname( client, Hostname );
  158. if( Info ) Client_SetInfo( client, Info );
  159. client->hops = Hops;
  160. client->token = Token;
  161. if( Modes ) Client_SetModes( client, Modes );
  162. if( Type == CLIENT_SERVER ) Generate_MyToken( client );
  163. if( strchr( client->modes, 'a' ))
  164. strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away ));
  165. /* Verketten */
  166. client->next = (POINTER *)My_Clients;
  167. My_Clients = client;
  168. /* Adjust counters */
  169. Adjust_Counters( client );
  170. return client;
  171. } /* Init_New_Client */
  172. GLOBAL void
  173. Client_Destroy( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit )
  174. {
  175. /* Client entfernen. */
  176. CLIENT *last, *c;
  177. char msg[LINE_LEN], *txt;
  178. assert( Client != NULL );
  179. if( LogMsg ) txt = LogMsg;
  180. else txt = FwdMsg;
  181. if( ! txt ) txt = "Reason unknown.";
  182. /* Netz-Split-Nachricht vorbereiten (noch nicht optimal) */
  183. if( Client->type == CLIENT_SERVER ) {
  184. strlcpy(msg, This_Server->id, sizeof (msg));
  185. strlcat(msg, " ", sizeof (msg));
  186. strlcat(msg, Client->id, sizeof (msg));
  187. }
  188. last = NULL;
  189. c = My_Clients;
  190. while( c )
  191. {
  192. if(( Client->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c != Client ))
  193. {
  194. /* der Client, der geloescht wird ist ein Server. Der Client, den wir gerade
  195. * pruefen, ist ein Child von diesem und muss daher auch entfernt werden */
  196. Client_Destroy( c, NULL, msg, false );
  197. last = NULL;
  198. c = My_Clients;
  199. continue;
  200. }
  201. if( c == Client )
  202. {
  203. /* Wir haben den Client gefunden: entfernen */
  204. if( last ) last->next = c->next;
  205. else My_Clients = (CLIENT *)c->next;
  206. if( c->type == CLIENT_USER )
  207. {
  208. if( c->conn_id != NONE )
  209. {
  210. /* Ein lokaler User */
  211. Log( LOG_NOTICE, "User \"%s\" unregistered (connection %d): %s", Client_Mask( c ), c->conn_id, txt );
  212. if( SendQuit )
  213. {
  214. /* Alle andere Server informieren! */
  215. if( FwdMsg ) IRC_WriteStrServersPrefix( NULL, c, "QUIT :%s", FwdMsg );
  216. else IRC_WriteStrServersPrefix( NULL, c, "QUIT :" );
  217. }
  218. }
  219. else
  220. {
  221. /* Remote User */
  222. Log( LOG_DEBUG, "User \"%s\" unregistered: %s", Client_Mask( c ), txt );
  223. if( SendQuit )
  224. {
  225. /* Andere Server informieren, ausser denen, die "in
  226. * Richtung dem liegen", auf dem der User registriert
  227. * ist. Von denen haben wir das QUIT ja wohl bekommen. */
  228. if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :%s", FwdMsg );
  229. else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :" );
  230. }
  231. }
  232. /* Unregister client from channels */
  233. Channel_Quit( c, FwdMsg ? FwdMsg : c->id );
  234. /* Register client in My_Whowas structure */
  235. Client_RegisterWhowas( c );
  236. }
  237. else if( c->type == CLIENT_SERVER )
  238. {
  239. if( c != This_Server )
  240. {
  241. if( c->conn_id != NONE ) Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
  242. else Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" unregistered: %s", c->id, txt );
  243. }
  244. /* andere Server informieren */
  245. if( ! NGIRCd_SignalQuit )
  246. {
  247. if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
  248. else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
  249. }
  250. }
  251. else
  252. {
  253. if( c->conn_id != NONE )
  254. {
  255. if( c->id[0] ) Log( LOG_NOTICE, "Client \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
  256. else Log( LOG_NOTICE, "Client unregistered (connection %d): %s", c->conn_id, txt );
  257. } else {
  258. Log(LOG_WARNING, "Unregistered unknown client \"%s\": %s",
  259. c->id[0] ? c->id : "(No Nick)", txt );
  260. }
  261. }
  262. free( c );
  263. break;
  264. }
  265. last = c;
  266. c = (CLIENT *)c->next;
  267. }
  268. } /* Client_Destroy */
  269. GLOBAL void
  270. Client_SetHostname( CLIENT *Client, char *Hostname )
  271. {
  272. /* Hostname eines Clients setzen */
  273. assert( Client != NULL );
  274. assert( Hostname != NULL );
  275. strlcpy( Client->host, Hostname, sizeof( Client->host ));
  276. } /* Client_SetHostname */
  277. GLOBAL void
  278. Client_SetID( CLIENT *Client, char *ID )
  279. {
  280. /* Hostname eines Clients setzen, Hash-Wert berechnen */
  281. assert( Client != NULL );
  282. assert( ID != NULL );
  283. strlcpy( Client->id, ID, sizeof( Client->id ));
  284. /* Hash */
  285. Client->hash = Hash( Client->id );
  286. } /* Client_SetID */
  287. GLOBAL void
  288. Client_SetUser( CLIENT *Client, char *User, bool Idented )
  289. {
  290. /* Username eines Clients setzen */
  291. assert( Client != NULL );
  292. assert( User != NULL );
  293. if( Idented ) strlcpy( Client->user, User, sizeof( Client->user ));
  294. else
  295. {
  296. Client->user[0] = '~';
  297. strlcpy( Client->user + 1, User, sizeof( Client->user ) - 1 );
  298. }
  299. } /* Client_SetUser */
  300. GLOBAL void
  301. Client_SetInfo( CLIENT *Client, char *Info )
  302. {
  303. /* Hostname eines Clients setzen */
  304. assert( Client != NULL );
  305. assert( Info != NULL );
  306. strlcpy( Client->info, Info, sizeof( Client->info ));
  307. } /* Client_SetInfo */
  308. GLOBAL void
  309. Client_SetModes( CLIENT *Client, char *Modes )
  310. {
  311. /* Modes eines Clients setzen */
  312. assert( Client != NULL );
  313. assert( Modes != NULL );
  314. strlcpy( Client->modes, Modes, sizeof( Client->modes ));
  315. } /* Client_SetModes */
  316. GLOBAL void
  317. Client_SetFlags( CLIENT *Client, char *Flags )
  318. {
  319. /* Flags eines Clients setzen */
  320. assert( Client != NULL );
  321. assert( Flags != NULL );
  322. strlcpy( Client->flags, Flags, sizeof( Client->flags ));
  323. } /* Client_SetFlags */
  324. GLOBAL void
  325. Client_SetPassword( CLIENT *Client, char *Pwd )
  326. {
  327. /* Von einem Client geliefertes Passwort */
  328. assert( Client != NULL );
  329. assert( Pwd != NULL );
  330. strlcpy( Client->pwd, Pwd, sizeof( Client->pwd ));
  331. } /* Client_SetPassword */
  332. GLOBAL void
  333. Client_SetAway( CLIENT *Client, char *Txt )
  334. {
  335. /* Set AWAY reason of client */
  336. assert( Client != NULL );
  337. assert( Txt != NULL );
  338. strlcpy( Client->away, Txt, sizeof( Client->away ));
  339. Log( LOG_DEBUG, "User \"%s\" is away: %s", Client_Mask( Client ), Txt );
  340. } /* Client_SetAway */
  341. GLOBAL void
  342. Client_SetType( CLIENT *Client, int Type )
  343. {
  344. assert( Client != NULL );
  345. Client->type = Type;
  346. if( Type == CLIENT_SERVER ) Generate_MyToken( Client );
  347. Adjust_Counters( Client );
  348. } /* Client_SetType */
  349. GLOBAL void
  350. Client_SetHops( CLIENT *Client, int Hops )
  351. {
  352. assert( Client != NULL );
  353. Client->hops = Hops;
  354. } /* Client_SetHops */
  355. GLOBAL void
  356. Client_SetToken( CLIENT *Client, int Token )
  357. {
  358. assert( Client != NULL );
  359. Client->token = Token;
  360. } /* Client_SetToken */
  361. GLOBAL void
  362. Client_SetIntroducer( CLIENT *Client, CLIENT *Introducer )
  363. {
  364. assert( Client != NULL );
  365. assert( Introducer != NULL );
  366. Client->introducer = Introducer;
  367. } /* Client_SetIntroducer */
  368. GLOBAL void
  369. Client_SetOperByMe( CLIENT *Client, bool OperByMe )
  370. {
  371. assert( Client != NULL );
  372. Client->oper_by_me = OperByMe;
  373. } /* Client_SetOperByMe */
  374. GLOBAL bool
  375. Client_ModeAdd( CLIENT *Client, char Mode )
  376. {
  377. /* Set Mode.
  378. * If Client already alread had Mode, return false.
  379. * If the Mode was newly set, return true.
  380. */
  381. char x[2];
  382. assert( Client != NULL );
  383. x[0] = Mode; x[1] = '\0';
  384. if( ! strchr( Client->modes, x[0] ))
  385. {
  386. /* Client hat den Mode noch nicht -> setzen */
  387. strlcat( Client->modes, x, sizeof( Client->modes ));
  388. return true;
  389. }
  390. else return false;
  391. } /* Client_ModeAdd */
  392. GLOBAL bool
  393. Client_ModeDel( CLIENT *Client, char Mode )
  394. {
  395. /* Delete Mode.
  396. * If Mode was removed, return true.
  397. * If Client did not have Mode, return false.
  398. */
  399. char x[2], *p;
  400. assert( Client != NULL );
  401. x[0] = Mode; x[1] = '\0';
  402. p = strchr( Client->modes, x[0] );
  403. if( ! p ) return false;
  404. /* Client has Mode -> delete */
  405. while( *p )
  406. {
  407. *p = *(p + 1);
  408. p++;
  409. }
  410. return true;
  411. } /* Client_ModeDel */
  412. GLOBAL CLIENT *
  413. Client_Search( char *Nick )
  414. {
  415. /* return Client-Structure that has the corresponding Nick.
  416. * If none is found, return NULL.
  417. */
  418. char search_id[CLIENT_ID_LEN], *ptr;
  419. CLIENT *c = NULL;
  420. UINT32 search_hash;
  421. assert( Nick != NULL );
  422. /* copy Nick and truncate hostmask if necessary */
  423. strlcpy( search_id, Nick, sizeof( search_id ));
  424. ptr = strchr( search_id, '!' );
  425. if( ptr ) *ptr = '\0';
  426. search_hash = Hash( search_id );
  427. c = My_Clients;
  428. while( c )
  429. {
  430. if( c->hash == search_hash )
  431. {
  432. /* lt. Hash-Wert: Treffer! */
  433. if( strcasecmp( c->id, search_id ) == 0 ) return c;
  434. }
  435. c = (CLIENT *)c->next;
  436. }
  437. return NULL;
  438. } /* Client_Search */
  439. GLOBAL CLIENT *
  440. Client_GetFromToken( CLIENT *Client, int Token )
  441. {
  442. /* Client-Struktur, die den entsprechenden Introducer (=Client)
  443. * und das gegebene Token hat, liefern. Wird keine gefunden,
  444. * so wird NULL geliefert. */
  445. CLIENT *c;
  446. assert( Client != NULL );
  447. assert( Token > 0 );
  448. c = My_Clients;
  449. while( c )
  450. {
  451. if(( c->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c->token == Token )) return c;
  452. c = (CLIENT *)c->next;
  453. }
  454. return NULL;
  455. } /* Client_GetFromToken */
  456. GLOBAL int
  457. Client_Type( CLIENT *Client )
  458. {
  459. assert( Client != NULL );
  460. return Client->type;
  461. } /* Client_Type */
  462. GLOBAL CONN_ID
  463. Client_Conn( CLIENT *Client )
  464. {
  465. assert( Client != NULL );
  466. return Client->conn_id;
  467. } /* Client_Conn */
  468. GLOBAL char *
  469. Client_ID( CLIENT *Client )
  470. {
  471. assert( Client != NULL );
  472. #ifdef DEBUG
  473. if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN );
  474. #endif
  475. if( Client->id[0] ) return Client->id;
  476. else return "*";
  477. } /* Client_ID */
  478. GLOBAL char *
  479. Client_Info( CLIENT *Client )
  480. {
  481. assert( Client != NULL );
  482. return Client->info;
  483. } /* Client_Info */
  484. GLOBAL char *
  485. Client_User( CLIENT *Client )
  486. {
  487. assert( Client != NULL );
  488. return Client->user[0] ? Client->user : "~";
  489. } /* Client_User */
  490. GLOBAL char *
  491. Client_Hostname( CLIENT *Client )
  492. {
  493. assert( Client != NULL );
  494. return Client->host;
  495. } /* Client_Hostname */
  496. GLOBAL char *
  497. Client_Password( CLIENT *Client )
  498. {
  499. assert( Client != NULL );
  500. return Client->pwd;
  501. } /* Client_Password */
  502. GLOBAL char *
  503. Client_Modes( CLIENT *Client )
  504. {
  505. assert( Client != NULL );
  506. return Client->modes;
  507. } /* Client_Modes */
  508. GLOBAL char *
  509. Client_Flags( CLIENT *Client )
  510. {
  511. assert( Client != NULL );
  512. return Client->flags;
  513. } /* Client_Flags */
  514. GLOBAL bool
  515. Client_OperByMe( CLIENT *Client )
  516. {
  517. assert( Client != NULL );
  518. return Client->oper_by_me;
  519. } /* Client_OperByMe */
  520. GLOBAL int
  521. Client_Hops( CLIENT *Client )
  522. {
  523. assert( Client != NULL );
  524. return Client->hops;
  525. } /* Client_Hops */
  526. GLOBAL int
  527. Client_Token( CLIENT *Client )
  528. {
  529. assert( Client != NULL );
  530. return Client->token;
  531. } /* Client_Token */
  532. GLOBAL int
  533. Client_MyToken( CLIENT *Client )
  534. {
  535. assert( Client != NULL );
  536. return Client->mytoken;
  537. } /* Client_MyToken */
  538. GLOBAL CLIENT *
  539. Client_NextHop( CLIENT *Client )
  540. {
  541. CLIENT *c;
  542. assert( Client != NULL );
  543. c = Client;
  544. while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server ))
  545. c = c->introducer;
  546. return c;
  547. } /* Client_NextHop */
  548. GLOBAL char *
  549. Client_Mask( CLIENT *Client )
  550. {
  551. /* Client-"ID" liefern, wie sie z.B. fuer
  552. * Prefixe benoetigt wird. */
  553. assert( Client != NULL );
  554. if( Client->type == CLIENT_SERVER ) return Client->id;
  555. snprintf( GetID_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, Client->host );
  556. return GetID_Buffer;
  557. } /* Client_Mask */
  558. GLOBAL CLIENT *
  559. Client_Introducer( CLIENT *Client )
  560. {
  561. assert( Client != NULL );
  562. return Client->introducer;
  563. } /* Client_Introducer */
  564. GLOBAL CLIENT *
  565. Client_TopServer( CLIENT *Client )
  566. {
  567. assert( Client != NULL );
  568. return Client->topserver;
  569. } /* Client_TopServer */
  570. GLOBAL bool
  571. Client_HasMode( CLIENT *Client, char Mode )
  572. {
  573. assert( Client != NULL );
  574. return strchr( Client->modes, Mode ) != NULL;
  575. } /* Client_HasMode */
  576. GLOBAL char *
  577. Client_Away( CLIENT *Client )
  578. {
  579. /* AWAY-Text liefern */
  580. assert( Client != NULL );
  581. return Client->away;
  582. } /* Client_Away */
  583. GLOBAL bool
  584. Client_CheckNick( CLIENT *Client, char *Nick )
  585. {
  586. assert( Client != NULL );
  587. assert( Nick != NULL );
  588. if( ! Client_IsValidNick( Nick ))
  589. {
  590. IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
  591. return false;
  592. }
  593. /* Nick bereits vergeben? */
  594. if( Client_Search( Nick ))
  595. {
  596. /* den Nick gibt es bereits */
  597. IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick );
  598. return false;
  599. }
  600. return true;
  601. } /* Client_CheckNick */
  602. GLOBAL bool
  603. Client_CheckID( CLIENT *Client, char *ID )
  604. {
  605. /* Nick ueberpruefen */
  606. char str[COMMAND_LEN];
  607. CLIENT *c;
  608. assert( Client != NULL );
  609. assert( Client->conn_id > NONE );
  610. assert( ID != NULL );
  611. /* Nick zu lang? */
  612. if( strlen( ID ) > CLIENT_ID_LEN )
  613. {
  614. IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), ID );
  615. return false;
  616. }
  617. /* ID bereits vergeben? */
  618. c = My_Clients;
  619. while( c )
  620. {
  621. if( strcasecmp( c->id, ID ) == 0 )
  622. {
  623. /* die Server-ID gibt es bereits */
  624. snprintf( str, sizeof( str ), "ID \"%s\" already registered", ID );
  625. if( Client->conn_id != c->conn_id ) Log( LOG_ERR, "%s (on connection %d)!", str, c->conn_id );
  626. else Log( LOG_ERR, "%s (via network)!", str );
  627. Conn_Close( Client->conn_id, str, str, true);
  628. return false;
  629. }
  630. c = (CLIENT *)c->next;
  631. }
  632. return true;
  633. } /* Client_CheckID */
  634. GLOBAL CLIENT *
  635. Client_First( void )
  636. {
  637. /* Ersten Client liefern. */
  638. return My_Clients;
  639. } /* Client_First */
  640. GLOBAL CLIENT *
  641. Client_Next( CLIENT *c )
  642. {
  643. /* Naechsten Client liefern. Existiert keiner,
  644. * so wird NULL geliefert. */
  645. assert( c != NULL );
  646. return (CLIENT *)c->next;
  647. } /* Client_Next */
  648. GLOBAL long
  649. Client_UserCount( void )
  650. {
  651. return Count( CLIENT_USER );
  652. } /* Client_UserCount */
  653. GLOBAL long
  654. Client_ServiceCount( void )
  655. {
  656. return Count( CLIENT_SERVICE );;
  657. } /* Client_ServiceCount */
  658. GLOBAL long
  659. Client_ServerCount( void )
  660. {
  661. return Count( CLIENT_SERVER );
  662. } /* Client_ServerCount */
  663. GLOBAL long
  664. Client_MyUserCount( void )
  665. {
  666. return MyCount( CLIENT_USER );
  667. } /* Client_MyUserCount */
  668. GLOBAL long
  669. Client_MyServiceCount( void )
  670. {
  671. return MyCount( CLIENT_SERVICE );
  672. } /* Client_MyServiceCount */
  673. GLOBAL unsigned long
  674. Client_MyServerCount( void )
  675. {
  676. CLIENT *c;
  677. unsigned long cnt = 0;
  678. c = My_Clients;
  679. while( c )
  680. {
  681. if(( c->type == CLIENT_SERVER ) && ( c->hops == 1 )) cnt++;
  682. c = (CLIENT *)c->next;
  683. }
  684. return cnt;
  685. } /* Client_MyServerCount */
  686. GLOBAL unsigned long
  687. Client_OperCount( void )
  688. {
  689. CLIENT *c;
  690. unsigned long cnt = 0;
  691. c = My_Clients;
  692. while( c )
  693. {
  694. if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
  695. c = (CLIENT *)c->next;
  696. }
  697. return cnt;
  698. } /* Client_OperCount */
  699. GLOBAL unsigned long
  700. Client_UnknownCount( void )
  701. {
  702. CLIENT *c;
  703. unsigned long cnt = 0;
  704. c = My_Clients;
  705. while( c )
  706. {
  707. if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
  708. c = (CLIENT *)c->next;
  709. }
  710. return cnt;
  711. } /* Client_UnknownCount */
  712. GLOBAL long
  713. Client_MaxUserCount( void )
  714. {
  715. return Max_Users;
  716. } /* Client_MaxUserCount */
  717. GLOBAL long
  718. Client_MyMaxUserCount( void )
  719. {
  720. return My_Max_Users;
  721. } /* Client_MyMaxUserCount */
  722. GLOBAL bool
  723. Client_IsValidNick( const char *Nick )
  724. {
  725. const char *ptr;
  726. static const char goodchars[] = ";0123456789-";
  727. assert( Nick != NULL );
  728. if( Nick[0] == '#' ) return false;
  729. if( strchr( goodchars, Nick[0] )) return false;
  730. if( strlen( Nick ) >= CLIENT_NICK_LEN ) return false;
  731. ptr = Nick;
  732. while( *ptr )
  733. {
  734. if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false;
  735. if ( *ptr > '}' ) return false;
  736. ptr++;
  737. }
  738. return true;
  739. } /* Client_IsValidNick */
  740. /**
  741. * Return pointer to "My_Whowas" structure.
  742. */
  743. GLOBAL WHOWAS *
  744. Client_GetWhowas( void )
  745. {
  746. return My_Whowas;
  747. } /* Client_GetWhowas */
  748. /**
  749. * Return the index of the last used WHOWAS entry.
  750. */
  751. GLOBAL int
  752. Client_GetLastWhowasIndex( void )
  753. {
  754. return Last_Whowas;
  755. } /* Client_GetLastWhowasIndex */
  756. /**
  757. * Get the start time of this client.
  758. * The result is the start time in seconds since 1970-01-01, as reported
  759. * by the C function time(NULL).
  760. */
  761. GLOBAL time_t
  762. Client_StartTime(CLIENT *Client)
  763. {
  764. assert( Client != NULL );
  765. return Client->starttime;
  766. } /* Client_Uptime */
  767. static unsigned long
  768. Count( CLIENT_TYPE Type )
  769. {
  770. CLIENT *c;
  771. unsigned long cnt = 0;
  772. c = My_Clients;
  773. while( c )
  774. {
  775. if( c->type == Type ) cnt++;
  776. c = (CLIENT *)c->next;
  777. }
  778. return cnt;
  779. } /* Count */
  780. static unsigned long
  781. MyCount( CLIENT_TYPE Type )
  782. {
  783. CLIENT *c;
  784. unsigned long cnt = 0;
  785. c = My_Clients;
  786. while( c )
  787. {
  788. if(( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
  789. c = (CLIENT *)c->next;
  790. }
  791. return cnt;
  792. } /* MyCount */
  793. static CLIENT *
  794. New_Client_Struct( void )
  795. {
  796. /* Neue CLIENT-Struktur pre-initialisieren */
  797. CLIENT *c;
  798. c = (CLIENT *)malloc( sizeof( CLIENT ));
  799. if( ! c )
  800. {
  801. Log( LOG_EMERG, "Can't allocate memory! [New_Client_Struct]" );
  802. return NULL;
  803. }
  804. memset( c, 0, sizeof ( CLIENT ));
  805. c->type = CLIENT_UNKNOWN;
  806. c->conn_id = NONE;
  807. c->oper_by_me = false;
  808. c->hops = -1;
  809. c->token = -1;
  810. c->mytoken = -1;
  811. return c;
  812. } /* New_Client */
  813. static void
  814. Generate_MyToken( CLIENT *Client )
  815. {
  816. CLIENT *c;
  817. int token;
  818. c = My_Clients;
  819. token = 2;
  820. while( c )
  821. {
  822. if( c->mytoken == token )
  823. {
  824. /* Das Token wurde bereits vergeben */
  825. token++;
  826. c = My_Clients;
  827. continue;
  828. }
  829. else c = (CLIENT *)c->next;
  830. }
  831. Client->mytoken = token;
  832. Log( LOG_DEBUG, "Assigned token %d to server \"%s\".", token, Client->id );
  833. } /* Generate_MyToken */
  834. static void
  835. Adjust_Counters( CLIENT *Client )
  836. {
  837. long count;
  838. assert( Client != NULL );
  839. if( Client->type != CLIENT_USER ) return;
  840. if( Client->conn_id != NONE )
  841. {
  842. /* Local connection */
  843. count = Client_MyUserCount( );
  844. if( count > My_Max_Users ) My_Max_Users = count;
  845. }
  846. count = Client_UserCount( );
  847. if( count > Max_Users ) Max_Users = count;
  848. } /* Adjust_Counters */
  849. /**
  850. * Register client in My_Whowas structure for further recall by WHOWAS.
  851. * Note: Only clients that have been connected at least 30 seconds will be
  852. * registered to prevent automated IRC bots to "destroy" a nice server
  853. * history database.
  854. */
  855. GLOBAL void
  856. Client_RegisterWhowas( CLIENT *Client )
  857. {
  858. int slot;
  859. time_t now;
  860. assert( Client != NULL );
  861. now = time(NULL);
  862. /* Don't register clients that were connected less than 30 seconds. */
  863. if( now - Client->starttime < 30 )
  864. return;
  865. slot = Last_Whowas + 1;
  866. if( slot >= MAX_WHOWAS || slot < 0 ) slot = 0;
  867. #ifdef DEBUG
  868. Log( LOG_DEBUG, "Saving WHOWAS information to slot %d ...", slot );
  869. #endif
  870. My_Whowas[slot].time = now;
  871. strlcpy( My_Whowas[slot].id, Client_ID( Client ),
  872. sizeof( My_Whowas[slot].id ));
  873. strlcpy( My_Whowas[slot].user, Client_User( Client ),
  874. sizeof( My_Whowas[slot].user ));
  875. strlcpy( My_Whowas[slot].host, Client_Hostname( Client ),
  876. sizeof( My_Whowas[slot].host ));
  877. strlcpy( My_Whowas[slot].info, Client_Info( Client ),
  878. sizeof( My_Whowas[slot].info ));
  879. strlcpy( My_Whowas[slot].server, Client_ID( Client_Introducer( Client )),
  880. sizeof( My_Whowas[slot].server ));
  881. Last_Whowas = slot;
  882. } /* Client_RegisterWhowas */
  883. /* -eof- */