client.c 24 KB

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