client.c 24 KB

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