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