PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/client.c

https://bitbucket.org/rizon/ircd/
C | 1525 lines | 927 code | 204 blank | 394 comment | 208 complexity | fe555583ec2f3cb417e19da60b82e733 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. /*
  2. * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
  3. * client.c: Controls clients.
  4. *
  5. * Copyright (C) 2002 by the past and present ircd coders, and others.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  20. * USA
  21. *
  22. * $Id: client.c 469 2007-03-17 02:59:20Z jon $
  23. */
  24. #include "stdinc.h"
  25. #include "tools.h"
  26. #include "client.h"
  27. #include "channel_mode.h"
  28. #include "common.h"
  29. #include "event.h"
  30. #include "fdlist.h"
  31. #include "hash.h"
  32. #include "irc_string.h"
  33. #include "sprintf_irc.h"
  34. #include "ircd.h"
  35. #include "list.h"
  36. #include "s_gline.h"
  37. #include "numeric.h"
  38. #include "packet.h"
  39. #include "s_auth.h"
  40. #include "s_bsd.h"
  41. #include "s_conf.h"
  42. #include "s_log.h"
  43. #include "s_misc.h"
  44. #include "s_serv.h"
  45. #include "send.h"
  46. #include "whowas.h"
  47. #include "s_user.h"
  48. #include "dbuf.h"
  49. #include "memory.h"
  50. #include "hostmask.h"
  51. #include "balloc.h"
  52. #include "listener.h"
  53. #include "irc_res.h"
  54. #include "userhost.h"
  55. #include "dnsbl.h"
  56. dlink_list listing_client_list = { NULL, NULL, 0 };
  57. /* Pointer to beginning of Client list */
  58. dlink_list global_client_list = { NULL, NULL, 0 };
  59. /* unknown/client pointer lists */
  60. dlink_list unknown_list = { NULL, NULL, 0 };
  61. dlink_list local_client_list = { NULL, NULL, 0 };
  62. dlink_list serv_list = { NULL, NULL, 0 };
  63. dlink_list global_serv_list = { NULL, NULL, 0 };
  64. dlink_list oper_list = { NULL, NULL, 0 };
  65. static EVH check_pings;
  66. static BlockHeap *client_heap = NULL;
  67. static BlockHeap *lclient_heap = NULL;
  68. static dlink_list dead_list = { NULL, NULL, 0 };
  69. static dlink_list abort_list = { NULL, NULL, 0 };
  70. static dlink_node *eac_next; /* next aborted client to exit */
  71. static void check_pings_list(dlink_list *);
  72. static void check_unknowns_list(void);
  73. /* init_client()
  74. *
  75. * inputs - NONE
  76. * output - NONE
  77. * side effects - initialize client free memory
  78. */
  79. void
  80. init_client(void)
  81. {
  82. /* start off the check ping event .. -- adrian
  83. * Every 30 seconds is plenty -- db
  84. */
  85. client_heap = BlockHeapCreate("client", sizeof(struct Client), CLIENT_HEAP_SIZE);
  86. lclient_heap = BlockHeapCreate("local client", sizeof(struct LocalUser), LCLIENT_HEAP_SIZE);
  87. eventAdd("check_pings", check_pings, NULL, 5);
  88. }
  89. /*
  90. * make_client - create a new Client struct and set it to initial state.
  91. *
  92. * from == NULL, create local client (a client connected
  93. * to a socket).
  94. * WARNING: This leaves the client in a dangerous
  95. * state where fd == -1, dead flag is not set and
  96. * the client is on the unknown_list; therefore,
  97. * the first thing to do after calling make_client(NULL)
  98. * is setting fd to something reasonable. -adx
  99. *
  100. * from, create remote client (behind a socket
  101. * associated with the client defined by
  102. * 'from'). ('from' is a local client!!).
  103. */
  104. struct Client *
  105. make_client(struct Client *from)
  106. {
  107. struct Client *client_p = BlockHeapAlloc(client_heap);
  108. if(from == NULL)
  109. {
  110. client_p->from = client_p; /* 'from' of local client is self! */
  111. client_p->since = client_p->lasttime = client_p->firsttime = CurrentTime;
  112. client_p->localClient = BlockHeapAlloc(lclient_heap);
  113. client_p->localClient->registration = REG_INIT;
  114. /* as good a place as any... */
  115. dlinkAdd(client_p, make_dlink_node(), &unknown_list);
  116. }
  117. else
  118. client_p->from = from; /* 'from' of local client is self! */
  119. client_p->hnext = client_p;
  120. client_p->status = STAT_UNKNOWN;
  121. strcpy(client_p->username, "unknown");
  122. return client_p;
  123. }
  124. /*
  125. * free_client
  126. *
  127. * inputs - pointer to client
  128. * output - NONE
  129. * side effects - client pointed to has its memory freed
  130. */
  131. static void
  132. free_client(struct Client *client_p)
  133. {
  134. assert(client_p != NULL);
  135. assert(client_p != &me);
  136. assert(client_p->hnext == client_p);
  137. assert(client_p->channel.head == NULL);
  138. assert(dlink_list_length(&client_p->channel) == 0);
  139. MyFree(client_p->away);
  140. MyFree(client_p->serv);
  141. if(MyConnect(client_p))
  142. {
  143. assert(client_p->localClient->invited.head == NULL);
  144. assert(dlink_list_length(&client_p->localClient->invited) == 0);
  145. assert(IsClosing(client_p) && IsDead(client_p));
  146. MyFree(client_p->localClient->response);
  147. MyFree(client_p->localClient->auth_oper);
  148. /*
  149. * clean up extra sockets from P-lines which have been discarded.
  150. */
  151. if(client_p->localClient->listener)
  152. {
  153. assert(0 < client_p->localClient->listener->ref_count);
  154. if(0 == --client_p->localClient->listener->ref_count &&
  155. !client_p->localClient->listener->active)
  156. free_listener(client_p->localClient->listener);
  157. }
  158. dbuf_clear(&client_p->localClient->buf_recvq);
  159. dbuf_clear(&client_p->localClient->buf_sendq);
  160. BlockHeapFree(lclient_heap, client_p->localClient);
  161. }
  162. BlockHeapFree(client_heap, client_p);
  163. }
  164. /*
  165. * check_pings - go through the local client list and check activity
  166. * kill off stuff that should die
  167. *
  168. * inputs - NOT USED (from event)
  169. * output - next time_t when check_pings() should be called again
  170. * side effects -
  171. *
  172. *
  173. * A PING can be sent to clients as necessary.
  174. *
  175. * Client/Server ping outs are handled.
  176. */
  177. /*
  178. * Addon from adrian. We used to call this after nextping seconds,
  179. * however I've changed it to run once a second. This is only for
  180. * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
  181. * run once a second makes life a lot easier - when a new client connects
  182. * and they need a ping in 4 seconds, if nextping was set to 20 seconds
  183. * we end up waiting 20 seconds. This is stupid. :-)
  184. * I will optimise (hah!) check_pings() once I've finished working on
  185. * tidying up other network IO evilnesses.
  186. * -- adrian
  187. */
  188. static void
  189. check_pings(void *notused)
  190. {
  191. check_pings_list(&local_client_list);
  192. check_pings_list(&serv_list);
  193. check_unknowns_list();
  194. }
  195. /* check_pings_list()
  196. *
  197. * inputs - pointer to list to check
  198. * output - NONE
  199. * side effects -
  200. */
  201. static void
  202. check_pings_list(dlink_list * list)
  203. {
  204. char scratch[32]; /* way too generous but... */
  205. struct Client *client_p; /* current local client_p being examined */
  206. int ping, pingwarn; /* ping time value from client */
  207. dlink_node *ptr, *next_ptr;
  208. DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
  209. {
  210. client_p = ptr->data;
  211. /*
  212. ** Note: No need to notify opers here. It's
  213. ** already done when "FLAGS_DEADSOCKET" is set.
  214. */
  215. if(IsDead(client_p))
  216. {
  217. /* Ignore it, its been exited already */
  218. continue;
  219. }
  220. if(client_p->localClient->reject_delay > 0)
  221. {
  222. if(client_p->localClient->reject_delay <= CurrentTime)
  223. exit_client(client_p, &me, "Rejected");
  224. continue;
  225. }
  226. if(GlobalSetOptions.idletime && IsClient(client_p))
  227. {
  228. if(!IsExemptKline(client_p) && !IsOper(client_p) &&
  229. !IsIdlelined(client_p) &&
  230. ((CurrentTime - client_p->localClient->last) >
  231. GlobalSetOptions.idletime))
  232. {
  233. struct ConfItem *conf;
  234. struct AccessItem *aconf;
  235. conf = make_conf_item(KLINE_TYPE);
  236. aconf = (struct AccessItem *) map_to_conf(conf);
  237. DupString(aconf->host, client_p->realhost);
  238. DupString(aconf->reason, "idle exceeder");
  239. DupString(aconf->user, client_p->username);
  240. aconf->hold = CurrentTime + 60;
  241. add_temp_line(conf);
  242. sendto_realops_flags(UMODE_ALL, L_ALL,
  243. "Idle time limit exceeded for %s - temp k-lining",
  244. get_client_name(client_p, HIDE_IP));
  245. exit_client(client_p, &me, aconf->reason);
  246. continue;
  247. }
  248. }
  249. if(!IsRegistered(client_p))
  250. ping = CONNECTTIMEOUT, pingwarn = 0;
  251. else
  252. ping = get_client_ping(client_p, &pingwarn);
  253. if(ping < CurrentTime - client_p->lasttime)
  254. {
  255. if(!IsPingSent(client_p))
  256. {
  257. /*
  258. * if we havent PINGed the connection and we havent
  259. * heard from it in a while, PING it to make sure
  260. * it is still alive.
  261. */
  262. SetPingSent(client_p);
  263. ClearPingWarning(client_p);
  264. client_p->lasttime = CurrentTime - ping;
  265. sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
  266. }
  267. else
  268. {
  269. if(CurrentTime - client_p->lasttime >= 2 * ping)
  270. {
  271. /*
  272. * If the client/server hasn't talked to us in 2*ping seconds
  273. * and it has a ping time, then close its connection.
  274. */
  275. if(IsServer(client_p) || IsHandshake(client_p))
  276. {
  277. sendto_realops_flags(UMODE_ALL, L_ADMIN,
  278. "No response from %s, closing link",
  279. get_client_name(client_p,
  280. HIDE_IP));
  281. sendto_realops_flags(UMODE_ALL, L_OPER,
  282. "No response from %s, closing link",
  283. get_client_name(client_p,
  284. MASK_IP));
  285. ilog(L_NOTICE, "No response from %s, closing link",
  286. get_client_name(client_p, HIDE_IP));
  287. }
  288. ircsprintf(scratch, "Ping timeout: %d seconds",
  289. (int) (CurrentTime - client_p->lasttime));
  290. exit_client(client_p, &me, scratch);
  291. }
  292. else if(!IsPingWarning(client_p) && pingwarn > 0 &&
  293. (IsServer(client_p) || IsHandshake(client_p)) &&
  294. CurrentTime - client_p->lasttime >= ping + pingwarn)
  295. {
  296. /*
  297. * If the server hasn't replied in pingwarn seconds after sending
  298. * the PING, notify the opers so that they are aware of the problem.
  299. */
  300. SetPingWarning(client_p);
  301. sendto_realops_flags(UMODE_ALL, L_ADMIN,
  302. "Warning, no response from %s in %d seconds",
  303. get_client_name(client_p, HIDE_IP),
  304. pingwarn);
  305. sendto_realops_flags(UMODE_ALL, L_OPER,
  306. "Warning, no response from %s in %d seconds",
  307. get_client_name(client_p, MASK_IP),
  308. pingwarn);
  309. ilog(L_NOTICE, "No response from %s in %d seconds",
  310. get_client_name(client_p, HIDE_IP), pingwarn);
  311. }
  312. }
  313. }
  314. }
  315. }
  316. /* check_unknowns_list()
  317. *
  318. * inputs - pointer to list of unknown clients
  319. * output - NONE
  320. * side effects - unknown clients get marked for termination after n seconds
  321. */
  322. static void
  323. check_unknowns_list(void)
  324. {
  325. dlink_node *ptr, *next_ptr;
  326. DLINK_FOREACH_SAFE(ptr, next_ptr, unknown_list.head)
  327. {
  328. struct Client *client_p = ptr->data;
  329. if(client_p->localClient->reject_delay > 0)
  330. {
  331. if(client_p->localClient->reject_delay <= CurrentTime)
  332. exit_client(client_p, &me, "Rejected");
  333. continue;
  334. }
  335. /*
  336. * Check UNKNOWN connections - if they have been in this state
  337. * for > 30s, close them.
  338. */
  339. if(IsAuthFinished(client_p) && (CurrentTime - client_p->firsttime) > 30)
  340. exit_client(client_p, &me, "Registration timed out");
  341. }
  342. }
  343. /* check_conf_klines()
  344. *
  345. * inputs - NONE
  346. * output - NONE
  347. * side effects - Check all connections for a pending kline against the
  348. * client, exit the client if a kline matches.
  349. */
  350. void
  351. check_conf_klines(void)
  352. {
  353. struct Client *client_p = NULL; /* current local client_p being examined */
  354. struct AccessItem *aconf = NULL;
  355. struct ConfItem *conf = NULL;
  356. dlink_node *ptr, *next_ptr;
  357. DLINK_FOREACH_SAFE(ptr, next_ptr, local_client_list.head)
  358. {
  359. client_p = ptr->data;
  360. /* If a client is already being exited
  361. */
  362. if(IsDead(client_p) || !IsClient(client_p))
  363. continue;
  364. /* if there is a returned struct ConfItem then kill it */
  365. if((aconf = find_dline_conf(&client_p->localClient->ip,
  366. client_p->localClient->aftype)) != NULL)
  367. {
  368. if(aconf->status & CONF_EXEMPTDLINE)
  369. continue;
  370. if(IsExemptKline(client_p))
  371. {
  372. sendto_realops_flags(UMODE_ALL, L_ALL,
  373. "DLINE over-ruled for %s, client is kline_exempt",
  374. get_client_name(client_p, HIDE_IP));
  375. continue;
  376. }
  377. conf = unmap_conf_item(aconf);
  378. ban_them(client_p, conf);
  379. continue; /* and go examine next fd/client_p */
  380. }
  381. if(ConfigFileEntry.glines && (aconf = find_gline(client_p)))
  382. {
  383. if(IsExemptKline(client_p) || IsExemptGline(client_p))
  384. {
  385. sendto_realops_flags(UMODE_ALL, L_ALL,
  386. "GLINE over-ruled for %s, client is %sline_exempt",
  387. get_client_name(client_p, HIDE_IP),
  388. IsExemptKline(client_p) ? "k" : "g");
  389. continue;
  390. }
  391. conf = unmap_conf_item(aconf);
  392. ban_them(client_p, conf);
  393. /* and go examine next fd/client_p */
  394. continue;
  395. }
  396. if((aconf = find_kill(client_p)) != NULL)
  397. {
  398. /* if there is a returned struct AccessItem.. then kill it */
  399. if(IsExemptKline(client_p))
  400. {
  401. sendto_realops_flags(UMODE_ALL, L_ALL,
  402. "KLINE over-ruled for %s, client is kline_exempt",
  403. get_client_name(client_p, HIDE_IP));
  404. continue;
  405. }
  406. conf = unmap_conf_item(aconf);
  407. ban_them(client_p, conf);
  408. continue;
  409. }
  410. /* if there is a returned struct MatchItem then kill it */
  411. if((conf = find_matching_name_conf(XLINE_TYPE, client_p->info,
  412. NULL, NULL, 0)) != NULL ||
  413. (conf = find_matching_name_conf(RXLINE_TYPE, client_p->info,
  414. NULL, NULL, 0)) != NULL)
  415. {
  416. if(IsExemptKline(client_p))
  417. {
  418. sendto_realops_flags(UMODE_ALL, L_ALL,
  419. "XLINE over-ruled for %s, client is kline_exempt",
  420. get_client_name(client_p, HIDE_IP));
  421. continue;
  422. }
  423. ban_them(client_p, conf);
  424. continue;
  425. }
  426. }
  427. /* also check the unknowns list for new dlines */
  428. DLINK_FOREACH_SAFE(ptr, next_ptr, unknown_list.head)
  429. {
  430. client_p = ptr->data;
  431. if((aconf = find_dline_conf(&client_p->localClient->ip,
  432. client_p->localClient->aftype)))
  433. {
  434. if(aconf->status & CONF_EXEMPTDLINE)
  435. continue;
  436. exit_client(client_p, &me, aconf->reason ? aconf->reason : "D-lined");
  437. }
  438. }
  439. }
  440. /*
  441. * ban_them
  442. *
  443. * inputs - pointer to client to ban
  444. * - pointer to ConfItem
  445. * output - NONE
  446. * side effects - given client_p is banned
  447. */
  448. void
  449. ban_them(struct Client *client_p, struct ConfItem *conf)
  450. {
  451. const char *user_reason = NULL; /* What is sent to user */
  452. const char *channel_reason = NULL; /* What is sent to channel */
  453. struct AccessItem *aconf = NULL;
  454. struct MatchItem *xconf = NULL;
  455. const char *type_string = NULL;
  456. const char dline_string[] = "D-line";
  457. const char kline_string[] = "K-line";
  458. const char gline_string[] = "G-line";
  459. const char xline_string[] = "X-line";
  460. switch (conf->type)
  461. {
  462. case RKLINE_TYPE:
  463. case KLINE_TYPE:
  464. type_string = kline_string;
  465. aconf = map_to_conf(conf);
  466. break;
  467. case DLINE_TYPE:
  468. type_string = dline_string;
  469. aconf = map_to_conf(conf);
  470. break;
  471. case GLINE_TYPE:
  472. type_string = gline_string;
  473. aconf = map_to_conf(conf);
  474. break;
  475. case RXLINE_TYPE:
  476. case XLINE_TYPE:
  477. type_string = xline_string;
  478. xconf = map_to_conf(conf);
  479. ++xconf->count;
  480. break;
  481. default:
  482. assert(0);
  483. break;
  484. }
  485. if(ConfigFileEntry.kline_with_reason)
  486. {
  487. if(aconf != NULL)
  488. user_reason = aconf->reason ? aconf->reason : type_string;
  489. if(xconf != NULL)
  490. user_reason = xconf->reason ? xconf->reason : type_string;
  491. }
  492. else
  493. user_reason = type_string;
  494. if(ConfigFileEntry.kline_reason != NULL)
  495. channel_reason = ConfigFileEntry.kline_reason;
  496. else
  497. channel_reason = user_reason;
  498. sendto_realops_flags(UMODE_ALL, L_ALL, "%s active for %s",
  499. type_string, get_client_name(client_p, HIDE_IP));
  500. if(IsClient(client_p))
  501. sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
  502. me.name, client_p->name, user_reason);
  503. exit_client(client_p, &me, channel_reason);
  504. }
  505. /* update_client_exit_stats()
  506. *
  507. * input - pointer to client
  508. * output - NONE
  509. * side effects -
  510. */
  511. static void
  512. update_client_exit_stats(struct Client *client_p)
  513. {
  514. if(IsServer(client_p))
  515. {
  516. sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
  517. "Server %s split from %s",
  518. client_p->name, client_p->servptr->name);
  519. }
  520. else if(IsClient(client_p))
  521. {
  522. --Count.total;
  523. if(IsOper(client_p))
  524. --Count.oper;
  525. if(IsInvisible(client_p))
  526. --Count.invisi;
  527. }
  528. if(splitchecking && !splitmode)
  529. check_splitmode(NULL);
  530. }
  531. /* find_person()
  532. *
  533. * inputs - pointer to name
  534. * output - return client pointer
  535. * side effects - find person by (nick)name
  536. */
  537. /* XXX - ugly wrapper */
  538. struct Client *
  539. find_person(const struct Client *client_p, const char *name)
  540. {
  541. struct Client *c2ptr;
  542. if(IsDigit(*name))
  543. {
  544. if((c2ptr = hash_find_id(name)) != NULL)
  545. {
  546. /* invisible users shall not be found by UID guessing */
  547. if(IsInvisible(c2ptr) && !IsServer(client_p))
  548. c2ptr = NULL;
  549. }
  550. }
  551. else
  552. c2ptr = find_client(name);
  553. return ((c2ptr != NULL && IsClient(c2ptr)) ? c2ptr : NULL);
  554. }
  555. /*
  556. * find_chasing - find the client structure for a nick name (user)
  557. * using history mechanism if necessary. If the client is not found,
  558. * an error message (NO SUCH NICK) is generated. If the client was found
  559. * through the history, chasing will be 1 and otherwise 0.
  560. */
  561. struct Client *
  562. find_chasing(struct Client *client_p, struct Client *source_p, const char *user, int *chasing)
  563. {
  564. struct Client *who = find_person(client_p, user);
  565. if(chasing)
  566. *chasing = 0;
  567. if(who)
  568. return (who);
  569. if(IsDigit(*user))
  570. return (NULL);
  571. if((who = get_history(user, (time_t) ConfigFileEntry.kill_chase_time_limit)) == NULL)
  572. {
  573. sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, user);
  574. return (NULL);
  575. }
  576. if(chasing)
  577. *chasing = 1;
  578. return (who);
  579. }
  580. /*
  581. * get_client_name - Return the name of the client
  582. * for various tracking and
  583. * admin purposes. The main purpose of this function is to
  584. * return the "socket host" name of the client, if that
  585. * differs from the advertised name (other than case).
  586. * But, this can be used to any client structure.
  587. *
  588. * NOTE 1:
  589. * Watch out the allocation of "nbuf", if either source_p->name
  590. * or source_p->sockhost gets changed into pointers instead of
  591. * directly allocated within the structure...
  592. *
  593. * NOTE 2:
  594. * Function return either a pointer to the structure (source_p) or
  595. * to internal buffer (nbuf). *NEVER* use the returned pointer
  596. * to modify what it points!!!
  597. */
  598. const char *
  599. get_client_name(struct Client *client, int showip)
  600. {
  601. static char nbuf[HOSTLEN * 2 + USERLEN + 5];
  602. assert(client != NULL);
  603. if(irccmp(client->name, client->host) == 0)
  604. return (client->name);
  605. if(ConfigServerHide.hide_server_ips)
  606. if(IsServer(client) || IsConnecting(client) || IsHandshake(client))
  607. showip = MASK_IP;
  608. if(ConfigFileEntry.hide_spoof_ips)
  609. if(showip == SHOW_IP && IsIPSpoof(client))
  610. showip = MASK_IP;
  611. /* And finally, let's get the host information, ip or name */
  612. switch (showip)
  613. {
  614. case SHOW_IP:
  615. if(MyConnect(client))
  616. {
  617. ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username,
  618. client->sockhost);
  619. break;
  620. }
  621. case MASK_IP:
  622. ircsprintf(nbuf, "%s[%s@255.255.255.255]", client->name, client->username);
  623. break;
  624. case HIDE_REALHOST:
  625. ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username, client->host);
  626. break;
  627. default:
  628. ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username, client->realhost);
  629. }
  630. return (nbuf);
  631. }
  632. void
  633. free_exited_clients(void)
  634. {
  635. dlink_node *ptr, *next;
  636. struct Client *target_p;
  637. DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
  638. {
  639. target_p = ptr->data;
  640. if(ptr->data == NULL)
  641. {
  642. sendto_realops_flags(UMODE_ALL, L_ALL,
  643. "Warning: null client on dead_list!");
  644. dlinkDelete(ptr, &dead_list);
  645. free_dlink_node(ptr);
  646. continue;
  647. }
  648. free_client(target_p);
  649. dlinkDelete(ptr, &dead_list);
  650. free_dlink_node(ptr);
  651. }
  652. }
  653. /*
  654. * Exit one client, local or remote. Assuming all dependents have
  655. * been already removed, and socket closed for local client.
  656. *
  657. * The only messages generated are QUITs on channels.
  658. */
  659. static void
  660. exit_one_client(struct Client *source_p, const char *quitmsg)
  661. {
  662. dlink_node *lp = NULL, *next_lp = NULL;
  663. assert(!IsMe(source_p));
  664. if(IsServer(source_p))
  665. {
  666. dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
  667. if((lp = dlinkFindDelete(&global_serv_list, source_p)) != NULL)
  668. free_dlink_node(lp);
  669. if(!MyConnect(source_p))
  670. {
  671. source_p->from->serv->dep_servers--;
  672. assert(source_p->from->serv->dep_servers > 0);
  673. }
  674. }
  675. else if(IsClient(source_p))
  676. {
  677. if(source_p->servptr->serv != NULL)
  678. dlinkDelete(&source_p->lnode, &source_p->servptr->serv->users);
  679. /* If a person is on a channel, send a QUIT notice
  680. ** to every client (person) on the same channel (so
  681. ** that the client can show the "**signoff" message).
  682. ** (Note: The notice is to the local clients *only*)
  683. */
  684. sendto_common_channels_local(source_p, 0, ":%s!%s@%s QUIT :%s",
  685. source_p->name, source_p->username,
  686. source_p->host, quitmsg);
  687. DLINK_FOREACH_SAFE(lp, next_lp, source_p->channel.head)
  688. remove_user_from_channel(lp->data);
  689. /* Clean up allow lists */
  690. del_all_accepts(source_p);
  691. add_history(source_p, 0);
  692. off_history(source_p);
  693. if(!MyConnect(source_p))
  694. {
  695. source_p->from->serv->dep_users--;
  696. assert(source_p->from->serv->dep_users >= 0);
  697. }
  698. else
  699. {
  700. /* Clean up invitefield */
  701. DLINK_FOREACH_SAFE(lp, next_lp, source_p->localClient->invited.head)
  702. del_invite(lp->data, source_p);
  703. }
  704. }
  705. /* Remove source_p from the client lists */
  706. if(HasID(source_p))
  707. hash_del_id(source_p);
  708. if(source_p->name[0])
  709. hash_del_client(source_p);
  710. if(IsUserHostIp(source_p))
  711. delete_user_host(source_p->username, source_p->realhost, !MyConnect(source_p));
  712. /* remove from global client list
  713. * NOTE: source_p->node.next cannot be NULL if the client is added
  714. * to global_client_list (there is always &me at its end)
  715. */
  716. if(source_p != NULL && source_p->node.next != NULL)
  717. dlinkDelete(&source_p->node, &global_client_list);
  718. update_client_exit_stats(source_p);
  719. /* Check to see if the client isn't already on the dead list */
  720. assert(dlinkFind(&dead_list, source_p) == NULL);
  721. /* add to dead client dlist */
  722. SetDead(source_p);
  723. dlinkAdd(source_p, make_dlink_node(), &dead_list);
  724. }
  725. /* Recursively send QUITs and SQUITs for source_p and all its dependent clients
  726. * and servers to those servers that need them. A server needs the client
  727. * QUITs if it can't figure them out from the SQUIT (ie pre-TS4) or if it
  728. * isn't getting the SQUIT because of @#(*&@)# hostmasking. With TS4, once
  729. * a link gets a SQUIT, it doesn't need any QUIT/SQUITs for clients depending
  730. * on that one -orabidoo
  731. *
  732. * This is now called on each local server -adx
  733. */
  734. static void
  735. recurse_send_quits(struct Client *original_source_p, struct Client *source_p,
  736. struct Client *from, struct Client *to, const char *comment,
  737. const char *splitstr, const char *myname)
  738. {
  739. dlink_node *ptr, *next;
  740. struct Client *target_p;
  741. int hidden = match(myname, source_p->name);
  742. assert(to != source_p); /* should be already removed from serv_list */
  743. /* If this server can handle quit storm (QS) removal
  744. * of dependents, just send the SQUIT
  745. *
  746. * Always check *all* dependent servers if some of them are
  747. * hidden behind fakename. If so, send out the QUITs -adx
  748. */
  749. if(hidden || !IsCapable(to, CAP_QS))
  750. DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
  751. {
  752. target_p = ptr->data;
  753. sendto_one(to, ":%s QUIT :%s", target_p->name, splitstr);
  754. }
  755. DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
  756. recurse_send_quits(original_source_p, ptr->data, from, to,
  757. comment, splitstr, myname);
  758. if(!hidden && ((source_p == original_source_p && to != from) || !IsCapable(to, CAP_QS)))
  759. {
  760. /* don't use a prefix here - we have to be 100% sure the message
  761. * will be accepted without Unknown prefix etc.. */
  762. sendto_one(to, "SQUIT %s :%s", ID_or_name(source_p, to), comment);
  763. }
  764. }
  765. /*
  766. * Remove all clients that depend on source_p; assumes all (S)QUITs have
  767. * already been sent. we make sure to exit a server's dependent clients
  768. * and servers before the server itself; exit_one_client takes care of
  769. * actually removing things off llists. tweaked from +CSr31 -orabidoo
  770. */
  771. static void
  772. recurse_remove_clients(struct Client *source_p, const char *quitmsg)
  773. {
  774. dlink_node *ptr, *next;
  775. DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
  776. exit_one_client(ptr->data, quitmsg);
  777. DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
  778. {
  779. recurse_remove_clients(ptr->data, quitmsg);
  780. exit_one_client(ptr->data, quitmsg);
  781. }
  782. assert(source_p->serv->dep_servers == 1);
  783. assert(source_p->serv->dep_users == 0);
  784. }
  785. /*
  786. ** Remove *everything* that depends on source_p, from all lists, and sending
  787. ** all necessary QUITs and SQUITs. source_p itself is still on the lists,
  788. ** and its SQUITs have been sent except for the upstream one -orabidoo
  789. */
  790. static void
  791. remove_dependents(struct Client *source_p, struct Client *from,
  792. const char *comment, const char *splitstr)
  793. {
  794. struct Client *to;
  795. struct ConfItem *conf;
  796. static char myname[HOSTLEN + 1];
  797. dlink_node *ptr;
  798. DLINK_FOREACH(ptr, serv_list.head)
  799. {
  800. to = ptr->data;
  801. if((conf = to->serv->sconf) != NULL)
  802. strlcpy(myname, my_name_for_link(conf), sizeof(myname));
  803. else
  804. strlcpy(myname, me.name, sizeof(myname));
  805. recurse_send_quits(source_p, source_p, from, to, comment, splitstr, myname);
  806. }
  807. recurse_remove_clients(source_p, splitstr);
  808. }
  809. /*
  810. * exit_client - exit a client of any type. Generally, you can use
  811. * this on any struct Client, regardless of its state.
  812. *
  813. * Note, you shouldn't exit remote _users_ without first doing
  814. * SetKilled and propagating a kill or similar message. However,
  815. * it is perfectly correct to call exit_client to force a _server_
  816. * quit (either local or remote one).
  817. *
  818. * inputs: - a client pointer that is going to be exited
  819. * - for servers, the second argument is a pointer to who
  820. * is firing the server. This side won't get any generated
  821. * messages. NEVER NULL!
  822. * output: none
  823. * side effects: the client is delinked from all lists, disconnected,
  824. * and the rest of IRC network is notified of the exit.
  825. * Client memory is scheduled to be freed
  826. */
  827. void
  828. exit_client(struct Client *source_p, struct Client *from, const char *comment)
  829. {
  830. dlink_node *m;
  831. if(MyConnect(source_p))
  832. {
  833. /* DO NOT REMOVE. exit_client can be called twice after a failed
  834. * read/write.
  835. */
  836. if(IsClosing(source_p))
  837. return;
  838. SetClosing(source_p);
  839. if(IsIpHash(source_p))
  840. remove_one_ip(&source_p->localClient->ip);
  841. delete_auth(source_p);
  842. clear_dnsbl_lookup(source_p);
  843. /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
  844. * STAT_HANDSHAKE or STAT_UNKNOWN
  845. * all of which are lumped together into unknown_list
  846. *
  847. * In all above cases IsRegistered() will not be true.
  848. */
  849. if(!IsRegistered(source_p))
  850. {
  851. if((m = dlinkFindDelete(&unknown_list, source_p)) != NULL)
  852. free_dlink_node(m);
  853. }
  854. else if(IsClient(source_p))
  855. {
  856. Count.local--;
  857. if(IsOper(source_p))
  858. {
  859. if((m = dlinkFindDelete(&oper_list, source_p)) != NULL)
  860. free_dlink_node(m);
  861. }
  862. dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
  863. if(source_p->localClient->list_task != NULL)
  864. free_list_task(source_p->localClient->list_task, source_p);
  865. sendto_realops_flags(UMODE_CCONN, L_ALL,
  866. "Client exiting: %s (%s@%s) [%s] [%s]", source_p->name,
  867. source_p->username, source_p->realhost, comment,
  868. ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
  869. "255.255.255.255" : source_p->sockhost);
  870. }
  871. /* As soon as a client is known to be a server of some sort
  872. * it has to be put on the serv_list, or SJOIN's to this new server
  873. * from the connect burst will not be seen.
  874. */
  875. if(IsServer(source_p) || IsConnecting(source_p) || IsHandshake(source_p))
  876. {
  877. if((m = dlinkFindDelete(&serv_list, source_p)) != NULL)
  878. {
  879. free_dlink_node(m);
  880. unset_chcap_usage_counts(source_p);
  881. }
  882. if(IsServer(source_p))
  883. {
  884. Count.myserver--;
  885. if(ServerInfo.hub)
  886. remove_lazylink_flags(source_p->localClient->serverMask);
  887. else
  888. uplink = NULL;
  889. }
  890. }
  891. log_user_exit(source_p);
  892. if(!IsDead(source_p))
  893. {
  894. if(IsServer(source_p))
  895. {
  896. /* for them, we are exiting the network */
  897. sendto_one(source_p, ":%s SQUIT %s :%s",
  898. ID_or_name(from, source_p), me.name, comment);
  899. }
  900. sendto_one(source_p, "ERROR :Closing Link: %s (%s)",
  901. source_p->host, comment);
  902. }
  903. /*
  904. ** Currently only server connections can have
  905. ** depending remote clients here, but it does no
  906. ** harm to check for all local clients. In
  907. ** future some other clients than servers might
  908. ** have remotes too...
  909. **
  910. ** Close the Client connection first and mark it
  911. ** so that no messages are attempted to send to it.
  912. ** Remember it makes source_p->from == NULL.
  913. */
  914. close_connection(source_p);
  915. }
  916. if(IsServer(source_p))
  917. {
  918. char splitstr[HOSTLEN + HOSTLEN + 2];
  919. /* This shouldn't ever happen */
  920. assert(source_p->serv != NULL && source_p->servptr != NULL);
  921. if(ConfigServerHide.hide_servers)
  922. /* set netsplit message to "*.net *.split" to still show
  923. * that its a split, but hide the servers splitting
  924. */
  925. strcpy(splitstr, "*.net *.split");
  926. else
  927. snprintf(splitstr, sizeof(splitstr), "%s %s",
  928. source_p->servptr->name, source_p->name);
  929. remove_dependents(source_p, from->from, comment, splitstr);
  930. if(source_p->servptr == &me)
  931. {
  932. sendto_realops_flags(UMODE_ALL, L_ALL,
  933. "%s was connected for %d seconds. %llu/%llu sendK/recvK.",
  934. source_p->name,
  935. (int) (CurrentTime - source_p->firsttime),
  936. source_p->localClient->send.bytes >> 10,
  937. source_p->localClient->recv.bytes >> 10);
  938. ilog(L_NOTICE, "%s was connected for %d seconds. %llu/%llu sendK/recvK.",
  939. source_p->name, (int) (CurrentTime - source_p->firsttime),
  940. source_p->localClient->send.bytes >> 10,
  941. source_p->localClient->recv.bytes >> 10);
  942. }
  943. }
  944. else if(IsClient(source_p) && !IsKilled(source_p))
  945. {
  946. sendto_server(from->from, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS,
  947. ":%s QUIT :%s", ID(source_p), comment);
  948. sendto_server(from->from, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS,
  949. ":%s QUIT :%s", source_p->name, comment);
  950. }
  951. /* The client *better* be off all of the lists */
  952. assert(dlinkFind(&unknown_list, source_p) == NULL);
  953. assert(dlinkFind(&local_client_list, source_p) == NULL);
  954. assert(dlinkFind(&serv_list, source_p) == NULL);
  955. assert(dlinkFind(&oper_list, source_p) == NULL);
  956. exit_one_client(source_p, comment);
  957. }
  958. /*
  959. * dead_link_on_write - report a write error if not already dead,
  960. * mark it as dead then exit it
  961. */
  962. void
  963. dead_link_on_write(struct Client *client_p, int ierrno)
  964. {
  965. dlink_node *ptr;
  966. if(IsDefunct(client_p))
  967. return;
  968. dbuf_clear(&client_p->localClient->buf_recvq);
  969. dbuf_clear(&client_p->localClient->buf_sendq);
  970. assert(dlinkFind(&abort_list, client_p) == NULL);
  971. ptr = make_dlink_node();
  972. /* don't let exit_aborted_clients() finish yet */
  973. dlinkAddTail(client_p, ptr, &abort_list);
  974. if(eac_next == NULL)
  975. eac_next = ptr;
  976. SetDead(client_p); /* You are dead my friend */
  977. }
  978. /*
  979. * dead_link_on_read - report a read error if not already dead,
  980. * mark it as dead then exit it
  981. */
  982. void
  983. dead_link_on_read(struct Client *client_p, int error)
  984. {
  985. char errmsg[255];
  986. int current_error;
  987. if(IsDefunct(client_p))
  988. return;
  989. dbuf_clear(&client_p->localClient->buf_recvq);
  990. dbuf_clear(&client_p->localClient->buf_sendq);
  991. current_error = get_sockerr(client_p->localClient->fd.fd);
  992. if(IsServer(client_p) || IsHandshake(client_p))
  993. {
  994. int connected = CurrentTime - client_p->firsttime;
  995. if(error == 0)
  996. {
  997. /* Admins get the real IP */
  998. sendto_realops_flags(UMODE_ALL, L_ADMIN,
  999. "Server %s closed the connection",
  1000. get_client_name(client_p, SHOW_IP));
  1001. /* Opers get a masked IP */
  1002. sendto_realops_flags(UMODE_ALL, L_OPER,
  1003. "Server %s closed the connection",
  1004. get_client_name(client_p, MASK_IP));
  1005. ilog(L_NOTICE, "Server %s closed the connection",
  1006. get_client_name(client_p, SHOW_IP));
  1007. }
  1008. else
  1009. {
  1010. report_error(L_ADMIN, "Lost connection to %s: %s",
  1011. get_client_name(client_p, SHOW_IP), current_error);
  1012. report_error(L_OPER, "Lost connection to %s: %s",
  1013. get_client_name(client_p, MASK_IP), current_error);
  1014. }
  1015. sendto_realops_flags(UMODE_ALL, L_ALL,
  1016. "%s had been connected for %d day%s, %2d:%02d:%02d",
  1017. client_p->name, connected / 86400,
  1018. (connected / 86400 == 1) ? "" : "s",
  1019. (connected % 86400) / 3600, (connected % 3600) / 60,
  1020. connected % 60);
  1021. }
  1022. if(error == 0)
  1023. strlcpy(errmsg, "Remote host closed the connection", sizeof(errmsg));
  1024. else
  1025. ircsprintf(errmsg, "Read error: %s", strerror(current_error));
  1026. exit_client(client_p, &me, errmsg);
  1027. }
  1028. void
  1029. exit_aborted_clients(void)
  1030. {
  1031. dlink_node *ptr;
  1032. struct Client *target_p;
  1033. const char *notice;
  1034. DLINK_FOREACH_SAFE(ptr, eac_next, abort_list.head)
  1035. {
  1036. target_p = ptr->data;
  1037. eac_next = ptr->next;
  1038. if(target_p == NULL)
  1039. {
  1040. sendto_realops_flags(UMODE_ALL, L_ALL,
  1041. "Warning: null client on abort_list!");
  1042. dlinkDelete(ptr, &abort_list);
  1043. free_dlink_node(ptr);
  1044. continue;
  1045. }
  1046. dlinkDelete(ptr, &abort_list);
  1047. if(IsSendQExceeded(target_p))
  1048. notice = "Max SendQ exceeded";
  1049. else
  1050. notice = "Write error: connection closed";
  1051. exit_client(target_p, &me, notice);
  1052. free_dlink_node(ptr);
  1053. }
  1054. }
  1055. /*
  1056. * accept processing, this adds a form of "caller ID" to ircd
  1057. *
  1058. * If a client puts themselves into "caller ID only" mode,
  1059. * only clients that match a client pointer they have put on
  1060. * the accept list will be allowed to message them.
  1061. *
  1062. * [ source.on_allow_list ] -> [ target1 ] -> [ target2 ]
  1063. *
  1064. * [target.allow_list] -> [ source1 ] -> [source2 ]
  1065. *
  1066. * i.e. a target will have a link list of source pointers it will allow
  1067. * each source client then has a back pointer pointing back
  1068. * to the client that has it on its accept list.
  1069. * This allows for exit_one_client to remove these now bogus entries
  1070. * from any client having an accept on them.
  1071. */
  1072. /* accept_message()
  1073. *
  1074. * inputs - pointer to source client
  1075. * - pointer to target client
  1076. * output - 1 if accept this message 0 if not
  1077. * side effects - See if source is on target's allow list
  1078. */
  1079. int
  1080. accept_message(struct Client *source, struct Client *target)
  1081. {
  1082. dlink_node *ptr;
  1083. DLINK_FOREACH(ptr, target->allow_list.head)
  1084. {
  1085. struct Client *target_p = ptr->data;
  1086. if(source == target_p)
  1087. return (1);
  1088. }
  1089. if(IsSoftCallerId(target) && !IsCallerId(target))
  1090. {
  1091. DLINK_FOREACH(ptr, target->channel.head)
  1092. if(IsMember(source, ((struct Membership *) ptr->data)->chptr))
  1093. return (1);
  1094. }
  1095. return (0);
  1096. }
  1097. /* del_from_accept()
  1098. *
  1099. * inputs - pointer to source client
  1100. * - pointer to target client
  1101. * output - NONE
  1102. * side effects - Delete's source pointer to targets allow list
  1103. *
  1104. * Walk through the target's accept list, remove if source is found,
  1105. * Then walk through the source's on_accept_list remove target if found.
  1106. */
  1107. void
  1108. del_from_accept(struct Client *source, struct Client *target)
  1109. {
  1110. dlink_node *ptr;
  1111. dlink_node *ptr2;
  1112. dlink_node *next_ptr;
  1113. dlink_node *next_ptr2;
  1114. struct Client *target_p;
  1115. DLINK_FOREACH_SAFE(ptr, next_ptr, target->allow_list.head)
  1116. {
  1117. target_p = ptr->data;
  1118. if(source == target_p)
  1119. {
  1120. dlinkDelete(ptr, &target->allow_list);
  1121. free_dlink_node(ptr);
  1122. DLINK_FOREACH_SAFE(ptr2, next_ptr2, source->on_allow_list.head)
  1123. {
  1124. target_p = ptr2->data;
  1125. if(target == target_p)
  1126. {
  1127. dlinkDelete(ptr2, &source->on_allow_list);
  1128. free_dlink_node(ptr2);
  1129. }
  1130. }
  1131. }
  1132. }
  1133. }
  1134. /* del_all_accepts()
  1135. *
  1136. * inputs - pointer to exiting client
  1137. * output - NONE
  1138. * side effects - Walk through given clients allow_list and on_allow_list
  1139. * remove all references to this client
  1140. */
  1141. void
  1142. del_all_accepts(struct Client *client_p)
  1143. {
  1144. dlink_node *ptr, *next_ptr;
  1145. DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->allow_list.head)
  1146. del_from_accept(ptr->data, client_p);
  1147. DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
  1148. del_from_accept(client_p, ptr->data);
  1149. }
  1150. /* del_all_their_accepts()
  1151. *
  1152. * inputs - pointer to exiting client
  1153. * output - NONE
  1154. * side effects - Walk through given clients on_allow_list
  1155. * remove all references to this client,
  1156. * allow this client to keep their own allow_list
  1157. */
  1158. void
  1159. del_all_their_accepts(struct Client *client_p)
  1160. {
  1161. dlink_node *ptr, *next_ptr;
  1162. DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
  1163. del_from_accept(client_p, ptr->data);
  1164. }
  1165. /* set_initial_nick()
  1166. *
  1167. * inputs
  1168. * output
  1169. * side effects -
  1170. *
  1171. * This function is only called to set up an initially registering
  1172. * client.
  1173. */
  1174. void
  1175. set_initial_nick(struct Client *client_p, struct Client *source_p, const char *nick)
  1176. {
  1177. char buf[USERLEN + 1];
  1178. /* Client setting NICK the first time */
  1179. /* This had to be copied here to avoid problems.. */
  1180. source_p->tsinfo = CurrentTime;
  1181. source_p->localClient->registration &= ~REG_NEED_NICK;
  1182. if(source_p->name[0])
  1183. hash_del_client(source_p);
  1184. strlcpy(source_p->name, nick, sizeof(source_p->name));
  1185. hash_add_client(source_p);
  1186. /* fd_desc is long enough */
  1187. fd_note(&client_p->localClient->fd, "Nick: %s", nick);
  1188. /* They have the nick they want now.. */
  1189. client_p->llname[0] = '\0';
  1190. if(!source_p->localClient->registration)
  1191. {
  1192. strlcpy(buf, source_p->username, sizeof(buf));
  1193. /*
  1194. * USER already received, now we have NICK.
  1195. * *NOTE* For servers "NICK" *must* precede the
  1196. * user message (giving USER before NICK is possible
  1197. * only for local client connection!). register_user
  1198. * may reject the client and call exit_client for it
  1199. * --must test this and exit m_nick too!!!
  1200. */
  1201. register_local_user(client_p, source_p, nick, buf);
  1202. }
  1203. }
  1204. /* change_local_nick()
  1205. *
  1206. * inputs - pointer to server
  1207. * - pointer to client
  1208. * - nick
  1209. * output -
  1210. * side effects - changes nick of a LOCAL user
  1211. */
  1212. void
  1213. change_local_nick(struct Client *client_p, struct Client *source_p, const char *nick)
  1214. {
  1215. if(ConfigChannel.quiet_on_ban && !IsOper(source_p))
  1216. {
  1217. dlink_node *lp = NULL, *next_lp = NULL;
  1218. DLINK_FOREACH_SAFE(lp, next_lp, source_p->channel.head)
  1219. {
  1220. struct Channel *chptr = ((struct Membership *) lp->data)->chptr;
  1221. if(can_send(chptr, source_p, NULL, NULL, NO) < 1)
  1222. {
  1223. sendto_one(source_p, form_str(ERR_BANNICKCHANGE),
  1224. me.name, source_p->name, chptr->chname);
  1225. return;
  1226. }
  1227. }
  1228. }
  1229. /*
  1230. ** Client just changing his/her nick. If he/she is
  1231. ** on a channel, send note of change to all clients
  1232. ** on that channel. Propagate notice to other servers.
  1233. */
  1234. if((source_p->localClient->last_nick_change + ConfigFileEntry.max_nick_time) < CurrentTime)
  1235. source_p->localClient->number_of_nick_changes = 0;
  1236. source_p->localClient->last_nick_change = CurrentTime;
  1237. source_p->localClient->number_of_nick_changes++;
  1238. if((ConfigFileEntry.anti_nick_flood &&
  1239. (source_p->localClient->number_of_nick_changes
  1240. <= ConfigFileEntry.max_nick_changes)) ||
  1241. !ConfigFileEntry.anti_nick_flood || (IsOper(source_p) && ConfigFileEntry.no_oper_flood))
  1242. {
  1243. if(irccmp(source_p->name, nick))
  1244. {
  1245. /*
  1246. * Make sure everyone that has this client on its accept list
  1247. * loses that reference.
  1248. */
  1249. del_all_their_accepts(source_p);
  1250. source_p->tsinfo = CurrentTime;
  1251. clear_ban_cache_client(source_p);
  1252. /* If it changed nicks, -r it */
  1253. if(IsRegNick(source_p))
  1254. {
  1255. unsigned int oldumodes;
  1256. char umodebuf[IRCD_BUFSIZE];
  1257. oldumodes = source_p->umodes;
  1258. ClearRegNick(source_p);
  1259. send_umode(source_p, source_p, oldumodes, 0xffffffff, umodebuf);
  1260. }
  1261. }
  1262. /* XXX - the format of this notice should eventually be changed
  1263. * to either %s[%s@%s], or even better would be get_client_name() -bill
  1264. */
  1265. sendto_realops_flags(UMODE_NCHANGE, L_ALL, "Nick change: From %s to %s [%s@%s]",
  1266. source_p->name, nick, source_p->username, source_p->realhost);
  1267. sendto_common_channels_local(source_p, 1, ":%s!%s@%s NICK :%s",
  1268. source_p->name, source_p->username,
  1269. source_p->host, nick);
  1270. add_history(source_p, 1);
  1271. /*
  1272. * Only hubs care about lazy link nicks not being sent on yet
  1273. * lazylink leafs/leafs always send their nicks up to hub,
  1274. * hence must always propagate nick changes.
  1275. * hubs might not propagate a nick change, if the leaf
  1276. * does not know about that client yet.
  1277. */
  1278. sendto_server(client_p, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS,
  1279. ":%s NICK %s :%lu",
  1280. ID(source_p), nick, (unsigned long) source_p->tsinfo);
  1281. sendto_server(client_p, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS,
  1282. ":%s NICK %s :%lu",
  1283. source_p->name, nick, (unsigned long) source_p->tsinfo);
  1284. }
  1285. else
  1286. {
  1287. sendto_one(source_p, form_str(ERR_NICKTOOFAST),
  1288. me.name, source_p->name, source_p->name,
  1289. nick, ConfigFileEntry.max_nick_time);
  1290. return;
  1291. }
  1292. /* Finally, add to hash */
  1293. if(source_p->name[0])
  1294. hash_del_client(source_p);
  1295. strcpy(source_p->name, nick);
  1296. hash_add_client(source_p);
  1297. /* fd_desc is long enough */
  1298. fd_note(&client_p->localClient->fd, "Nick: %s", nick);
  1299. }
  1300. /* change_local_host()
  1301. *
  1302. * inputs - pointer to client
  1303. * - new username
  1304. * - new hostname
  1305. * output -
  1306. * side effects - changes username and/or hostname of a LOCAL user
  1307. */
  1308. void change_local_host(struct Client *client_p, const char *username, const char *hostname)
  1309. {
  1310. if(!client_p || (!username && !hostname))
  1311. return;
  1312. if(ConfigChannel.cycle_on_hostchange)
  1313. do_hostchange_quits(client_p);
  1314. if(username)
  1315. strlcpy(client_p->username, username, sizeof(client_p->username));
  1316. if(hostname)
  1317. strlcpy(client_p->host, hostname, sizeof(client_p->host));
  1318. clear_ban_cache_client(client_p);
  1319. if(ConfigChannel.cycle_on_hostchange)
  1320. do_hostchange_joins(client_p);
  1321. }