ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/client.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/client.c (file contents):
Revision 4400 by michael, Tue Aug 5 17:42:56 2014 UTC vs.
Revision 8688 by michael, Sun Dec 2 12:46:22 2018 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2014 ircd-hybrid development team
4 > *  Copyright (c) 1997-2018 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 15 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20   */
21  
# Line 27 | Line 27
27   #include "stdinc.h"
28   #include "list.h"
29   #include "client.h"
30 + #include "client_svstag.h"
31   #include "event.h"
32   #include "hash.h"
33   #include "irc_string.h"
# Line 35 | Line 36
36   #include "auth.h"
37   #include "s_bsd.h"
38   #include "conf.h"
39 + #include "conf_gecos.h"
40   #include "log.h"
41   #include "misc.h"
42   #include "server.h"
# Line 42 | Line 44
44   #include "whowas.h"
45   #include "user.h"
46   #include "memory.h"
45 #include "mempool.h"
47   #include "hostmask.h"
48   #include "listener.h"
48 #include "userhost.h"
49   #include "watch.h"
50   #include "rng_mt.h"
51   #include "parse.h"
# Line 60 | Line 60 | dlink_list global_client_list;
60   dlink_list global_server_list;
61   dlink_list oper_list;
62  
63 static mp_pool_t *client_pool, *lclient_pool;
63   static dlink_list dead_list, abort_list;
64   static dlink_node *eac_next;  /* next aborted client to exit */
65  
66  
67   /*
68 < * make_client - create a new Client struct and set it to initial state.
68 > * client_make - create a new Client struct and set it to initial state.
69   *
70   *      from == NULL,   create local client (a client connected
71   *                      to a socket).
# Line 81 | Line 80 | static dlink_node *eac_next;  /* next ab
80   *                      'from'). ('from' is a local client!!).
81   */
82   struct Client *
83 < make_client(struct Client *from)
83 > client_make(struct Client *from)
84   {
85 <  struct Client *client_p = mp_pool_get(client_pool);
85 >  struct Client *client_p = xcalloc(sizeof(*client_p));
86  
87 <  if (!from)
87 >  if (from)
88 >    client_p->from = from;
89 >  else
90    {
91 <    client_p->from                      = client_p; /* 'from' of local client is self! */
92 <    client_p->localClient               = mp_pool_get(lclient_pool);
93 <    client_p->localClient->since        = CurrentTime;
94 <    client_p->localClient->lasttime     = CurrentTime;
95 <    client_p->localClient->firsttime    = CurrentTime;
96 <    client_p->localClient->registration = REG_INIT;
91 >    client_p->from = client_p;  /* 'from' of local client is self! */
92 >    client_p->connection = xcalloc(sizeof(*client_p->connection));
93 >    client_p->connection->since = CurrentTime;
94 >    client_p->connection->lasttime = CurrentTime;
95 >    client_p->connection->firsttime = CurrentTime;
96 >    client_p->connection->registration = REG_INIT;
97  
98      /* as good a place as any... */
99 <    dlinkAdd(client_p, &client_p->localClient->lclient_node, &unknown_list);
99 >    dlinkAdd(client_p, &client_p->connection->lclient_node, &unknown_list);
100    }
100  else
101    client_p->from = from; /* 'from' of local client is self! */
101  
102    client_p->idhnext = client_p;
103 <  client_p->hnext  = client_p;
103 >  client_p->hnext = client_p;
104    SetUnknown(client_p);
105    strcpy(client_p->username, "unknown");
106 <  strcpy(client_p->svid, "0");
106 >  strcpy(client_p->account, "*");
107  
108    return client_p;
109   }
110  
111   /*
112 < * free_client
112 > * client_free
113   *
114   * inputs       - pointer to client
115   * output       - NONE
116   * side effects - client pointed to has its memory freed
117   */
118   static void
119 < free_client(struct Client *client_p)
119 > client_free(struct Client *client_p)
120   {
121 <  assert(client_p);
121 >  assert(!IsMe(client_p));
122    assert(client_p != &me);
123    assert(client_p->hnext == client_p);
124    assert(client_p->idhnext == client_p);
125 <  assert(client_p->channel.head == NULL);
125 >
126 >  assert(client_p->node.prev == NULL);
127 >  assert(client_p->node.next == NULL);
128 >
129 >  assert(client_p->lnode.prev == NULL);
130 >  assert(client_p->lnode.next == NULL);
131 >
132 >  assert(dlink_list_length(&client_p->whowas_list) == 0);
133 >  assert(client_p->whowas_list.head == NULL);
134 >  assert(client_p->whowas_list.tail == NULL);
135 >
136    assert(dlink_list_length(&client_p->channel) == 0);
137 <  assert(dlink_list_length(&client_p->whowas) == 0);
138 <  assert(!IsServer(client_p) || client_p->serv);
137 >  assert(client_p->channel.head == NULL);
138 >  assert(client_p->channel.tail == NULL);
139 >
140 >  assert(dlink_list_length(&client_p->svstags) == 0);
141 >  assert(client_p->svstags.head == NULL);
142 >  assert(client_p->svstags.tail == NULL);
143  
144 <  MyFree(client_p->serv);
145 <  MyFree(client_p->certfp);
144 >
145 >  xfree(client_p->serv);
146 >  xfree(client_p->certfp);
147  
148    if (MyConnect(client_p))
149    {
150 <    assert(client_p->localClient->invited.head == NULL);
151 <    assert(dlink_list_length(&client_p->localClient->invited) == 0);
152 <    assert(dlink_list_length(&client_p->localClient->watches) == 0);
153 <    assert(IsClosing(client_p) && IsDead(client_p));
150 >    assert(client_p->connection->lclient_node.prev == NULL);
151 >    assert(client_p->connection->lclient_node.next == NULL);
152 >
153 >    assert(client_p->connection->list_task == NULL);
154 >    assert(client_p->connection->auth == NULL);
155 >
156 >    assert(dlink_list_length(&client_p->connection->acceptlist) == 0);
157 >    assert(client_p->connection->acceptlist.head == NULL);
158 >    assert(client_p->connection->acceptlist.tail == NULL);
159 >
160 >
161 >    assert(dlink_list_length(&client_p->connection->watches) == 0);
162 >    assert(client_p->connection->watches.head == NULL);
163 >    assert(client_p->connection->watches.tail == NULL);
164  
165 <    MyFree(client_p->localClient->response);
166 <    MyFree(client_p->localClient->auth_oper);
165 >    assert(dlink_list_length(&client_p->connection->confs) == 0);
166 >    assert(client_p->connection->confs.head == NULL);
167 >    assert(client_p->connection->confs.tail == NULL);
168 >
169 >    assert(dlink_list_length(&client_p->connection->invited) == 0);
170 >    assert(client_p->connection->invited.head == NULL);
171 >    assert(client_p->connection->invited.tail == NULL);
172 >
173 >    assert(client_p->connection->fd == NULL);
174 >
175 >    assert(HasFlag(client_p, FLAGS_CLOSING) && IsDead(client_p));
176  
177      /*
178 <     * clean up extra sockets from P-lines which have been discarded.
178 >     * Clean up extra sockets from listen {} blocks which have been discarded.
179       */
180 <    if (client_p->localClient->listener)
180 >    if (client_p->connection->listener)
181      {
182 <      assert(0 < client_p->localClient->listener->ref_count);
183 <      if (0 == --client_p->localClient->listener->ref_count &&
151 <          !client_p->localClient->listener->active)
152 <        free_listener(client_p->localClient->listener);
182 >      listener_release(client_p->connection->listener);
183 >      client_p->connection->listener = NULL;
184      }
185  
186 <    dbuf_clear(&client_p->localClient->buf_recvq);
187 <    dbuf_clear(&client_p->localClient->buf_sendq);
186 >    dbuf_clear(&client_p->connection->buf_recvq);
187 >    dbuf_clear(&client_p->connection->buf_sendq);
188  
189 <    mp_pool_release(client_p->localClient);
189 >    xfree(client_p->connection);
190 >    client_p->connection = NULL;
191    }
192  
193 <  mp_pool_release(client_p);
193 >  xfree(client_p);
194   }
195  
196   /* check_pings_list()
# Line 170 | Line 202 | free_client(struct Client *client_p)
202   static void
203   check_pings_list(dlink_list *list)
204   {
205 <  char buf[IRCD_BUFSIZE] = "";
206 <  int ping = 0;      /* ping time value from client */
207 <  dlink_node *ptr = NULL, *ptr_next = NULL;
205 >  char buf[32] = "";  /* 32 = sizeof("Ping timeout: 999999999 seconds") */
206 >  unsigned int ping = 0;      /* ping time value from client */
207 >  dlink_node *node, *node_next;
208  
209 <  DLINK_FOREACH_SAFE(ptr, ptr_next, list->head)
209 >  DLINK_FOREACH_SAFE(node, node_next, list->head)
210    {
211 <    struct Client *client_p = ptr->data;
211 >    struct Client *client_p = node->data;
212  
213      if (IsDead(client_p))
214 <      continue;  /* Ignore it, its been exited already */
214 >      continue;  /* Ignore it, it's been exited already */
215  
216 <    if (!IsRegistered(client_p))
217 <      ping = CONNECTTIMEOUT;
216 >    if (IsClient(client_p) || IsServer(client_p))
217 >      ping = get_client_ping(&client_p->connection->confs);
218      else
219 <      ping = get_client_ping(&client_p->localClient->confs);
219 >      ping = CONNECTTIMEOUT;
220  
221 <    if (ping < CurrentTime - client_p->localClient->lasttime)
221 >    if (ping < CurrentTime - client_p->connection->lasttime)
222      {
223 <      if (!IsPingSent(client_p))
223 >      if (!HasFlag(client_p, FLAGS_PINGSENT))
224        {
225          /*
226           * If we haven't PINGed the connection and we haven't
227           * heard from it in a while, PING it to make sure
228           * it is still alive.
229           */
230 <        SetPingSent(client_p);
231 <        client_p->localClient->lasttime = CurrentTime - ping;
230 >        AddFlag(client_p, FLAGS_PINGSENT);
231 >        client_p->connection->lasttime = CurrentTime - ping;
232          sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
233        }
234        else
235        {
236 <        if (CurrentTime - client_p->localClient->lasttime >= 2 * ping)
236 >        if (CurrentTime - client_p->connection->lasttime >= 2 * ping)
237          {
238            /*
239             * If the client/server hasn't talked to us in 2*ping seconds
# Line 209 | Line 241 | check_pings_list(dlink_list *list)
241             */
242            if (IsServer(client_p) || IsHandshake(client_p))
243            {
244 <            sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
244 >            sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
245                                   "No response from %s, closing link",
246 <                                 get_client_name(client_p, HIDE_IP));
247 <            sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
246 >                                 client_get_name(client_p, SHOW_IP));
247 >            sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
248                                   "No response from %s, closing link",
249 <                                 get_client_name(client_p, MASK_IP));
249 >                                 client_get_name(client_p, MASK_IP));
250              ilog(LOG_TYPE_IRCD, "No response from %s, closing link",
251 <                 get_client_name(client_p, HIDE_IP));
251 >                 client_get_name(client_p, SHOW_IP));
252            }
253  
254 <          snprintf(buf, sizeof(buf), "Ping timeout: %d seconds",
255 <                   (int)(CurrentTime - client_p->localClient->lasttime));
254 >          snprintf(buf, sizeof(buf), "Ping timeout: %ji seconds",
255 >                   (CurrentTime - client_p->connection->lasttime));
256            exit_client(client_p, buf);
257          }
258        }
# Line 237 | Line 269 | check_pings_list(dlink_list *list)
269   static void
270   check_unknowns_list(void)
271   {
272 <  dlink_node *ptr = NULL, *ptr_next = NULL;
272 >  dlink_node *node, *node_next;
273  
274 <  DLINK_FOREACH_SAFE(ptr, ptr_next, unknown_list.head)
274 >  DLINK_FOREACH_SAFE(node, node_next, unknown_list.head)
275    {
276 <    struct Client *client_p = ptr->data;
276 >    struct Client *client_p = node->data;
277  
278      /*
279       * Check UNKNOWN connections - if they have been in this state
280       * for > 30s, close them.
281       */
282 <    if (IsAuthFinished(client_p) && (CurrentTime - client_p->localClient->firsttime) > 30)
282 >    if (HasFlag(client_p, FLAGS_FINISHED_AUTH) && (CurrentTime - client_p->connection->firsttime) > 30)
283        exit_client(client_p, "Registration timed out");
284    }
285   }
# Line 257 | Line 289 | check_unknowns_list(void)
289   * kill off stuff that should die
290   *
291   * inputs       - NOT USED (from event)
260 * output       - next time_t when check_pings() should be called again
292   * side effects -
293   *
294   *
# Line 279 | Line 310 | check_unknowns_list(void)
310   */
311  
312   static void
313 < check_pings(void *notused)
313 > check_pings(void *unused)
314   {
315    check_pings_list(&local_client_list);
316    check_pings_list(&local_server_list);
# Line 296 | Line 327 | check_pings(void *notused)
327   void
328   check_conf_klines(void)
329   {
330 <  struct MaskItem *conf = NULL;
331 <  dlink_node *ptr = NULL, *ptr_next = NULL;
330 >  dlink_node *node = NULL, *node_next = NULL;
331 >  const void *ptr;
332  
333 <  DLINK_FOREACH_SAFE(ptr, ptr_next, local_client_list.head)
333 >  DLINK_FOREACH_SAFE(node, node_next, local_client_list.head)
334    {
335 <    struct Client *client_p = ptr->data;
335 >    struct Client *client_p = node->data;
336  
337 <    /* If a client is already being exited
338 <     */
308 <    if (IsDead(client_p) || !IsClient(client_p))
337 >    /* If a client is already being exited */
338 >    if (IsDead(client_p))
339        continue;
340  
341 <    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
342 <                                     client_p->localClient->aftype, NULL, NULL, 1)))
341 >    if ((ptr = find_conf_by_address(NULL, &client_p->ip, CONF_DLINE,
342 >                                    client_p->ip.ss.ss_family, NULL, NULL, 1)))
343      {
344 <      conf_try_ban(client_p, conf);
345 <      continue; /* and go examine next fd/client_p */
346 <    }
317 <
318 <    if (ConfigGeneral.glines)
319 <    {
320 <      if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
321 <                                       CONF_GLINE, client_p->localClient->aftype,
322 <                                       client_p->username, NULL, 1)))
323 <      {
324 <        conf_try_ban(client_p, conf);
325 <        /* and go examine next fd/client_p */
326 <        continue;
327 <      }
344 >      const struct MaskItem *conf = ptr;
345 >      conf_try_ban(client_p, CLIENT_BAN_DLINE, conf->reason);
346 >      continue;  /* and go examine next Client */
347      }
348  
349 <    if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
350 <                                     CONF_KLINE, client_p->localClient->aftype,
351 <                                     client_p->username, NULL, 1)))
349 >    if ((ptr = find_conf_by_address(client_p->host, &client_p->ip,
350 >                                    CONF_KLINE, client_p->ip.ss.ss_family,
351 >                                    client_p->username, NULL, 1)))
352      {
353 <      conf_try_ban(client_p, conf);
354 <      continue;
353 >      const struct MaskItem *conf = ptr;
354 >      conf_try_ban(client_p, CLIENT_BAN_KLINE, conf->reason);
355 >      continue;  /* and go examine next Client */
356      }
357  
358 <    if ((conf = find_matching_name_conf(CONF_XLINE,  client_p->info,
339 <                                        NULL, NULL, 0)))
358 >    if ((ptr = gecos_find(client_p->info, match)))
359      {
360 <      conf_try_ban(client_p, conf);
361 <      continue;
360 >      const struct GecosItem *conf = ptr;
361 >      conf_try_ban(client_p, CLIENT_BAN_XLINE, conf->reason);
362 >      continue;  /* and go examine next Client */
363      }
364    }
365  
366 <  /* also check the unknowns list for new dlines */
367 <  DLINK_FOREACH_SAFE(ptr, ptr_next, unknown_list.head)
366 >  /* Also check the unknowns list for new dlines */
367 >  DLINK_FOREACH_SAFE(node, node_next, unknown_list.head)
368    {
369 <    struct Client *client_p = ptr->data;
369 >    struct Client *client_p = node->data;
370  
371 <    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
372 <                                     client_p->localClient->aftype, NULL, NULL, 1)))
371 >    if ((ptr = find_conf_by_address(NULL, &client_p->ip, CONF_DLINE,
372 >                                    client_p->ip.ss.ss_family, NULL, NULL, 1)))
373      {
374 <      conf_try_ban(client_p, conf);
375 <      continue; /* and go examine next fd/client_p */
374 >      const struct MaskItem *conf = ptr;
375 >      conf_try_ban(client_p, CLIENT_BAN_DLINE, conf->reason);
376 >      continue;  /* and go examine next Client */
377      }
378    }
379   }
# Line 366 | Line 387 | check_conf_klines(void)
387   * side effects - given client_p is banned
388   */
389   void
390 < conf_try_ban(struct Client *client_p, struct MaskItem *conf)
390 > conf_try_ban(struct Client *client_p, int type, const char *reason)
391   {
392 <  const char *user_reason = NULL;  /* What is sent to user */
372 <  const char *type_string = NULL;
373 <  const char dline_string[] = "D-line";
374 <  const char kline_string[] = "K-line";
375 <  const char gline_string[] = "G-line";
376 <  const char xline_string[] = "X-line";
392 >  char ban_type = '?';
393  
394 <  switch (conf->type)
394 >  switch (type)
395    {
396 <    case CONF_KLINE:
397 <      if (IsExemptKline(client_p))
396 >    case CLIENT_BAN_KLINE:
397 >      if (HasFlag(client_p, FLAGS_EXEMPTKLINE))
398        {
399 <        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
399 >        sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
400                               "KLINE over-ruled for %s, client is kline_exempt",
401 <                             get_client_name(client_p, HIDE_IP));
401 >                             client_get_name(client_p, HIDE_IP));
402          return;
403        }
404  
405 <      type_string = kline_string;
405 >      ban_type = 'K';
406        break;
407 <    case CONF_DLINE:
408 <      if (find_conf_by_address(NULL, &client_p->localClient->ip, CONF_EXEMPT,
409 <                               client_p->localClient->aftype, NULL, NULL, 1))
407 >    case CLIENT_BAN_DLINE:
408 >      if (find_conf_by_address(NULL, &client_p->ip, CONF_EXEMPT,
409 >                               client_p->ip.ss.ss_family, NULL, NULL, 1))
410          return;
411 <      type_string = dline_string;
411 >      ban_type = 'D';
412        break;
413 <    case CONF_GLINE:
414 <      if (IsExemptKline(client_p) ||
399 <          IsExemptGline(client_p))
413 >    case CLIENT_BAN_XLINE:
414 >      if (HasFlag(client_p, FLAGS_EXEMPTXLINE))
415        {
416 <        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
417 <                             "GLINE over-ruled for %s, client is %sline_exempt",
418 <                             get_client_name(client_p, HIDE_IP), IsExemptKline(client_p) ? "k" : "g");
416 >        sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
417 >                             "XLINE over-ruled for %s, client is xline_exempt",
418 >                             client_get_name(client_p, HIDE_IP));
419          return;
420        }
421  
422 <      type_string = gline_string;
408 <      break;
409 <    case CONF_XLINE:
410 <      type_string = xline_string;
411 <      ++conf->count;
422 >      ban_type = 'X';
423        break;
424      default:
425        assert(0);
426        break;
427    }
428  
429 <  user_reason = conf->reason ? conf->reason : type_string;
430 <
420 <  sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s active for %s",
421 <                       type_string, get_client_name(client_p, HIDE_IP));
422 <
423 <  if (IsClient(client_p))
424 <    sendto_one_numeric(client_p, &me, ERR_YOUREBANNEDCREEP, user_reason);
425 <
426 <  exit_client(client_p, user_reason);
427 < }
429 >  sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%c-line active for %s",
430 >                       ban_type, client_get_name(client_p, HIDE_IP));
431  
429 /* update_client_exit_stats()
430 *
431 * input        - pointer to client
432 * output       - NONE
433 * side effects -
434 */
435 static void
436 update_client_exit_stats(struct Client *client_p)
437 {
432    if (IsClient(client_p))
433 <  {
440 <    assert(Count.total > 0);
441 <    --Count.total;
442 <    if (HasUMode(client_p, UMODE_OPER))
443 <      --Count.oper;
444 <    if (HasUMode(client_p, UMODE_INVISIBLE))
445 <      --Count.invisi;
446 <  }
447 <  else if (IsServer(client_p))
448 <    sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
449 <                         "Server %s split from %s",
450 <                         client_p->name, client_p->servptr->name);
433 >    sendto_one_numeric(client_p, &me, ERR_YOUREBANNEDCREEP, reason);
434  
435 <  if (splitchecking && !splitmode)
453 <    check_splitmode(NULL);
435 >  exit_client(client_p, reason);
436   }
437  
438   /* find_person()
# Line 460 | Line 442 | update_client_exit_stats(struct Client *
442   * side effects - find person by (nick)name
443   */
444   struct Client *
445 < find_person(const struct Client *const source_p, const char *name)
445 > find_person(const struct Client *source_p, const char *name)
446   {
447    struct Client *target_p = NULL;
448  
# Line 483 | Line 465 | find_person(const struct Client *const s
465   struct Client *
466   find_chasing(struct Client *source_p, const char *name)
467   {
468 <  struct Client *who = find_person(source_p, name);
468 >  struct Client *target_p = find_person(source_p, name);
469  
470 <  if (who)
471 <    return who;
470 >  if (target_p)
471 >    return target_p;
472  
473    if (IsDigit(*name))
474      return NULL;
475  
476 <  if ((who = whowas_get_history(name,
477 <                         (time_t)ConfigGeneral.kill_chase_time_limit))
496 <                         == NULL)
497 <  {
476 >  target_p = whowas_get_history(name, ConfigGeneral.kill_chase_time_limit);
477 >  if (target_p == NULL)
478      sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
499    return NULL;
500  }
479  
480 <  return who;
480 >  return target_p;
481   }
482  
483   /*
484 < * get_client_name -  Return the name of the client
484 > * client_get_name -  Return the name of the client
485   *    for various tracking and
486   *      admin purposes. The main purpose of this function is to
487   *      return the "socket host" name of the client, if that
# Line 521 | Line 499 | find_chasing(struct Client *source_p, co
499   *        to modify what it points!!!
500   */
501   const char *
502 < get_client_name(const struct Client *client_p, enum addr_mask_type type)
502 > client_get_name(const struct Client *client_p, enum addr_mask_type type)
503   {
504 <  static char buf[HOSTLEN * 2 + USERLEN + 5];
527 <
528 <  assert(client_p);
504 >  static char buf[HOSTLEN * 2 + USERLEN + 4];  /* +4 for [,@,],\0 */
505  
506    if (!MyConnect(client_p))
507      return client_p->name;
508  
509    if (IsServer(client_p) || IsConnecting(client_p) || IsHandshake(client_p))
510    {
511 <    if (!irccmp(client_p->name, client_p->host))
511 >    if (irccmp(client_p->name, client_p->host) == 0)
512        return client_p->name;
513      else if (ConfigServerHide.hide_server_ips)
514        type = MASK_IP;
515    }
516  
541  if (ConfigGeneral.hide_spoof_ips)
542    if (IsIPSpoof(client_p) && type == SHOW_IP)
543      type = MASK_IP;
544
517    /* And finally, let's get the host information, ip or name */
518    switch (type)
519    {
# Line 551 | Line 523 | get_client_name(const struct Client *cli
523                 client_p->username, client_p->sockhost);
524        break;
525      case MASK_IP:
526 <      if (client_p->localClient->aftype == AF_INET)
526 >      if (client_p->ip.ss.ss_family == AF_INET)
527          snprintf(buf, sizeof(buf), "%s[%s@255.255.255.255]",
528                   client_p->name, client_p->username);
529        else
530          snprintf(buf, sizeof(buf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
531                   client_p->name, client_p->username);
532        break;
533 <    default:
533 >    default:  /* HIDE_IP */
534        snprintf(buf, sizeof(buf), "%s[%s@%s]",
535                 client_p->name,
536                 client_p->username, client_p->host);
# Line 570 | Line 542 | get_client_name(const struct Client *cli
542   void
543   free_exited_clients(void)
544   {
545 <  dlink_node *ptr = NULL, *next = NULL;
545 >  dlink_node *node, *node_next;
546  
547 <  DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
547 >  DLINK_FOREACH_SAFE(node, node_next, dead_list.head)
548    {
549 <    free_client(ptr->data);
550 <    dlinkDelete(ptr, &dead_list);
551 <    free_dlink_node(ptr);
549 >    client_free(node->data);
550 >    dlinkDelete(node, &dead_list);
551 >    free_dlink_node(node);
552 >  }
553 > }
554 >
555 > /*
556 > * client_close_connection
557 > *        Close the physical connection. This function must make
558 > *        MyConnect(client_p) == FALSE, and set client_p->from == NULL.
559 > */
560 > static void
561 > client_close_connection(struct Client *client_p)
562 > {
563 >  assert(client_p);
564 >
565 >  if (!IsDead(client_p))
566 >  {
567 >    /* Attempt to flush any pending dbufs. Evil, but .. -- adrian */
568 >    /*
569 >     * There is still a chance that we might send data to this socket
570 >     * even if it is marked as blocked (COMM_SELECT_READ handler is called
571 >     * before COMM_SELECT_WRITE). Let's try, nothing to lose.. -adx
572 >     */
573 >    DelFlag(client_p, FLAGS_BLOCKED);
574 >    send_queued_write(client_p);
575 >  }
576 >
577 >  if (IsClient(client_p))
578 >  {
579 >    ++ServerStats.is_cl;
580 >    ServerStats.is_cbs += client_p->connection->send.bytes;
581 >    ServerStats.is_cbr += client_p->connection->recv.bytes;
582 >    ServerStats.is_cti += CurrentTime - client_p->connection->firsttime;
583    }
584 +  else if (IsServer(client_p))
585 +  {
586 +    dlink_node *node;
587 +
588 +    ++ServerStats.is_sv;
589 +    ServerStats.is_sbs += client_p->connection->send.bytes;
590 +    ServerStats.is_sbr += client_p->connection->recv.bytes;
591 +    ServerStats.is_sti += CurrentTime - client_p->connection->firsttime;
592 +
593 +    DLINK_FOREACH(node, connect_items.head)
594 +    {
595 +      struct MaskItem *conf = node->data;
596 +
597 +      if (irccmp(conf->name, client_p->name))
598 +        continue;
599 +
600 +      /*
601 +       * Reset next-connect cycle of all connect{} blocks that match
602 +       * this servername.
603 +       */
604 +      conf->until = CurrentTime + conf->class->con_freq;
605 +    }
606 +  }
607 +  else
608 +    ++ServerStats.is_ni;
609 +
610 +  if (tls_isusing(&client_p->connection->fd->ssl))
611 +    tls_shutdown(&client_p->connection->fd->ssl);
612 +
613 +  if (client_p->connection->fd)
614 +  {
615 +    fd_close(client_p->connection->fd);
616 +    client_p->connection->fd = NULL;
617 +  }
618 +
619 +  dbuf_clear(&client_p->connection->buf_sendq);
620 +  dbuf_clear(&client_p->connection->buf_recvq);
621 +
622 +  xfree(client_p->connection->password);
623 +  client_p->connection->password = NULL;
624 +
625 +  conf_detach(client_p, CONF_CLIENT | CONF_OPER | CONF_SERVER);
626   }
627  
628   /*
# Line 589 | Line 634 | free_exited_clients(void)
634   static void
635   exit_one_client(struct Client *source_p, const char *comment)
636   {
637 <  dlink_node *ptr = NULL, *ptr_next = NULL;
637 >  dlink_node *node, *node_next;
638  
639    assert(!IsMe(source_p));
640    assert(source_p != &me);
641  
642    if (IsClient(source_p))
643    {
644 +    if (HasUMode(source_p, UMODE_OPER))
645 +      --Count.oper;
646 +    if (HasUMode(source_p, UMODE_INVISIBLE))
647 +      --Count.invisi;
648 +
649      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->client_list);
650      dlinkDelete(&source_p->node, &global_client_list);
651  
# Line 605 | Line 655 | exit_one_client(struct Client *source_p,
655       * that the client can show the "**signoff" message).
656       * (Note: The notice is to the local clients *only*)
657       */
658 <    sendto_common_channels_local(source_p, 0, 0, ":%s!%s@%s QUIT :%s",
658 >    sendto_common_channels_local(source_p, false, 0, 0, ":%s!%s@%s QUIT :%s",
659                                   source_p->name, source_p->username,
660                                   source_p->host, comment);
611    DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
612      remove_user_from_channel(ptr->data);
661  
662 <    whowas_add_history(source_p, 0);
663 <    whowas_off_history(source_p);
662 >    DLINK_FOREACH_SAFE(node, node_next, source_p->channel.head)
663 >      remove_user_from_channel(node->data);
664  
665 <    watch_check_hash(source_p, RPL_LOGOFF);
665 >    svstag_clear_list(&source_p->svstags);
666  
667 <    if (MyConnect(source_p))
668 <    {
621 <      /* Clean up invitefield */
622 <      DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->localClient->invited.head)
623 <        del_invite(ptr->data, source_p);
667 >    whowas_add_history(source_p, false);
668 >    whowas_off_history(source_p);
669  
670 <      del_all_accepts(source_p);
626 <    }
670 >    watch_check_hash(source_p, RPL_LOGOFF);
671    }
672    else if (IsServer(source_p))
673    {
674 <    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
675 <    dlinkDelete(&source_p->node, &global_client_list);
674 >    sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
675 >                         "Server %s split from %s",
676 >                         source_p->name, source_p->servptr->name);
677  
678 <    if ((ptr = dlinkFindDelete(&global_server_list, source_p)))
679 <      free_dlink_node(ptr);
678 >    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
679 >    dlinkDelete(&source_p->node, &global_server_list);
680    }
681  
682    /* Remove source_p from the client lists */
683    if (source_p->id[0])
684      hash_del_id(source_p);
685 +
686    if (source_p->name[0])
687      hash_del_client(source_p);
688  
689 <  if (IsUserHostIp(source_p))
690 <    delete_user_host(source_p->username, source_p->host, !MyConnect(source_p));
691 <
692 <  update_client_exit_stats(source_p);
689 >  if (HasFlag(source_p, FLAGS_IPHASH))
690 >  {
691 >    DelFlag(source_p, FLAGS_IPHASH);
692 >    ipcache_record_remove(&source_p->ip, MyConnect(source_p));
693 >  }
694  
695    /* Check to see if the client isn't already on the dead list */
696    assert(dlinkFind(&dead_list, source_p) == NULL);
697  
698 <  /* add to dead client dlist */
698 >  /* Add to dead client dlist */
699    SetDead(source_p);
700    dlinkAdd(source_p, make_dlink_node(), &dead_list);
701   }
# Line 662 | Line 709 | exit_one_client(struct Client *source_p,
709   static void
710   recurse_remove_clients(struct Client *source_p, const char *comment)
711   {
712 <  dlink_node *ptr = NULL, *ptr_next = NULL;
712 >  dlink_node *node, *node_next;
713  
714 <  DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->client_list.head)
715 <    exit_one_client(ptr->data, comment);
714 >  DLINK_FOREACH_SAFE(node, node_next, source_p->serv->client_list.head)
715 >    exit_one_client(node->data, comment);
716  
717 <  DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->server_list.head)
717 >  DLINK_FOREACH_SAFE(node, node_next, source_p->serv->server_list.head)
718    {
719 <    recurse_remove_clients(ptr->data, comment);
720 <    exit_one_client(ptr->data, comment);
719 >    recurse_remove_clients(node->data, comment);
720 >    exit_one_client(node->data, comment);
721    }
722   }
723  
# Line 694 | Line 741 | recurse_remove_clients(struct Client *so
741   void
742   exit_client(struct Client *source_p, const char *comment)
743   {
697  dlink_node *m = NULL;
698
744    assert(!IsMe(source_p));
745    assert(source_p != &me);
746  
747    if (MyConnect(source_p))
748    {
749 <    /* DO NOT REMOVE. exit_client can be called twice after a failed
750 <     * read/write.
749 >    /*
750 >     * DO NOT REMOVE. exit_client can be called twice after a failed read/write.
751       */
752 <    if (IsClosing(source_p))
752 >    if (HasFlag(source_p, FLAGS_CLOSING))
753        return;
754  
755 <    SetClosing(source_p);
755 >    AddFlag(source_p, FLAGS_CLOSING);
756  
757 <    if (HasFlag(source_p, FLAGS_IPHASH))
757 >    if (source_p->connection->auth)
758      {
759 <      DelFlag(source_p, FLAGS_IPHASH);
760 <      ipcache_remove_address(&source_p->localClient->ip);
759 >      auth_delete(source_p->connection->auth);
760 >      source_p->connection->auth = NULL;
761      }
762  
763 <    delete_auth(&source_p->localClient->auth);
719 <
720 <    /*
721 <     * This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
722 <     * STAT_HANDSHAKE or STAT_UNKNOWN
723 <     * all of which are lumped together into unknown_list
724 <     *
725 <     * In all above cases IsRegistered() will not be true.
726 <     */
727 <    if (!IsRegistered(source_p))
763 >    if (IsClient(source_p))
764      {
765 <      assert(dlinkFind(&unknown_list, source_p));
730 <
731 <      dlinkDelete(&source_p->localClient->lclient_node, &unknown_list);
732 <    }
733 <    else if (IsClient(source_p))
734 <    {
735 <      time_t on_for = CurrentTime - source_p->localClient->firsttime;
736 <      assert(Count.local > 0);
737 <      Count.local--;
765 >      dlink_node *node;
766  
767        if (HasUMode(source_p, UMODE_OPER))
768 <        if ((m = dlinkFindDelete(&oper_list, source_p)))
769 <          free_dlink_node(m);
768 >        if ((node = dlinkFindDelete(&oper_list, source_p)))
769 >          free_dlink_node(node);
770  
771        assert(dlinkFind(&local_client_list, source_p));
772 <      dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
772 >      dlinkDelete(&source_p->connection->lclient_node, &local_client_list);
773  
774 <      if (source_p->localClient->list_task)
774 >      if (source_p->connection->list_task)
775          free_list_task(source_p);
776  
777 +      clear_invite_list(&source_p->connection->invited);
778 +      del_all_accepts(source_p);
779        watch_del_watch_list(source_p);
780 +
781        sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE,
782                             "Client exiting: %s (%s@%s) [%s] [%s]",
783 <                           source_p->name, source_p->username, source_p->host, comment,
784 <                           ConfigGeneral.hide_spoof_ips && IsIPSpoof(source_p) ?
785 <                           "255.255.255.255" : source_p->sockhost);
786 <      ilog(LOG_TYPE_USER, "%s (%3u:%02u:%02u): %s!%s@%s %llu/%llu",
787 <           myctime(source_p->localClient->firsttime), (unsigned int)(on_for / 3600),
788 <           (unsigned int)((on_for % 3600)/60), (unsigned int)(on_for % 60),
783 >                           source_p->name, source_p->username, source_p->realhost,
784 >                           source_p->sockhost, comment);
785 >
786 >      ilog(LOG_TYPE_USER, "%s (%ju): %s!%s@%s %s %s %ju/%ju :%s",
787 >           date_ctime(source_p->connection->firsttime),
788 >           CurrentTime - source_p->connection->firsttime,
789             source_p->name, source_p->username, source_p->host,
790 <           source_p->localClient->send.bytes>>10,
791 <           source_p->localClient->recv.bytes>>10);
790 >           source_p->sockhost, source_p->account,
791 >           source_p->connection->send.bytes >> 10,
792 >           source_p->connection->recv.bytes >> 10, source_p->info);
793      }
794      else if (IsServer(source_p))
795      {
764      assert(Count.myserver > 0);
765      --Count.myserver;
766
796        assert(dlinkFind(&local_server_list, source_p));
797 <      dlinkDelete(&source_p->localClient->lclient_node, &local_server_list);
797 >      dlinkDelete(&source_p->connection->lclient_node, &local_server_list);
798 >    }
799 >    else
800 >    {
801 >      assert(dlinkFind(&unknown_list, source_p));
802 >      dlinkDelete(&source_p->connection->lclient_node, &unknown_list);
803      }
804  
805      if (!IsDead(source_p))
# Line 774 | Line 808 | exit_client(struct Client *source_p, con
808        {
809          if (!HasFlag(source_p, FLAGS_SQUIT))
810          {
811 <          /* for them, we are exiting the network */
811 >          /* For them, we are exiting the network */
812            sendto_one(source_p, ":%s SQUIT %s :%s",
813                       me.id, me.id, comment);
814          }
# Line 784 | Line 818 | exit_client(struct Client *source_p, con
818                   source_p->host, comment);
819      }
820  
821 <    close_connection(source_p);
821 >    client_close_connection(source_p);
822    }
823    else if (IsClient(source_p) && HasFlag(source_p->servptr, FLAGS_EOB))
824      sendto_realops_flags(UMODE_FARCONNECT, L_ALL, SEND_NOTICE,
825 <                         "Client exiting at %s: %s (%s@%s) [%s]",
825 >                         "Client exiting at %s: %s (%s@%s) [%s] [%s]",
826                           source_p->servptr->name, source_p->name,
827 <                         source_p->username, source_p->host, comment);
827 >                         source_p->username, source_p->realhost, source_p->sockhost, comment);
828  
829    if (IsServer(source_p))
830    {
831      char splitstr[HOSTLEN + HOSTLEN + 2] = "";
832  
833 <    /* This shouldn't ever happen */
834 <    assert(source_p->serv && source_p->servptr);
833 >    assert(source_p->serv);
834 >    assert(source_p->servptr);
835  
836      if (ConfigServerHide.hide_servers)
837        /*
838 <       * Set netsplit message to "*.net *.split" to still show
839 <       * that its a split, but hide the servers splitting
838 >       * Set netsplit message to "*.net *.split" to still show that it's a split,
839 >       * but hide the servers splitting.
840         */
841        strlcpy(splitstr, "*.net *.split", sizeof(splitstr));
842      else
# Line 811 | Line 845 | exit_client(struct Client *source_p, con
845  
846      /* Send SQUIT for source_p in every direction. source_p is already off of local_server_list here */
847      if (!HasFlag(source_p, FLAGS_SQUIT))
848 <      sendto_server(NULL, NOCAPS, NOCAPS, "SQUIT %s :%s", source_p->id, comment);
848 >      sendto_server(NULL, 0, 0, "SQUIT %s :%s", source_p->id, comment);
849  
850      /* Now exit the clients internally */
851      recurse_remove_clients(source_p, splitstr);
852  
853      if (MyConnect(source_p))
854      {
855 <      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
856 <                           "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
857 <                           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
858 <                           source_p->localClient->send.bytes >> 10,
859 <                           source_p->localClient->recv.bytes >> 10);
860 <      ilog(LOG_TYPE_IRCD, "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
861 <           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
862 <           source_p->localClient->send.bytes >> 10,
863 <           source_p->localClient->recv.bytes >> 10);
855 >      sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
856 >                           "%s was connected for %s. %ju/%ju sendK/recvK.",
857 >                           source_p->name, time_dissect(CurrentTime - source_p->connection->firsttime),
858 >                           source_p->connection->send.bytes >> 10,
859 >                           source_p->connection->recv.bytes >> 10);
860 >      ilog(LOG_TYPE_IRCD, "%s was connected for %s. %ju/%ju sendK/recvK.",
861 >           source_p->name, time_dissect(CurrentTime - source_p->connection->firsttime),
862 >           source_p->connection->send.bytes >> 10,
863 >           source_p->connection->recv.bytes >> 10);
864      }
865    }
866    else if (IsClient(source_p) && !HasFlag(source_p, FLAGS_KILLED))
867 <    sendto_server(source_p->from, NOCAPS, NOCAPS, ":%s QUIT :%s",
834 <                  source_p->id, comment);
867 >    sendto_server(source_p->from, 0, 0, ":%s QUIT :%s", source_p->id, comment);
868  
869    /* The client *better* be off all of the lists */
870    assert(dlinkFind(&unknown_list, source_p) == NULL);
871    assert(dlinkFind(&local_client_list, source_p) == NULL);
872    assert(dlinkFind(&local_server_list, source_p) == NULL);
873    assert(dlinkFind(&oper_list, source_p) == NULL);
874 +  assert(dlinkFind(&listing_client_list, source_p) == NULL);
875  
876    exit_one_client(source_p, comment);
877   }
# Line 849 | Line 883 | exit_client(struct Client *source_p, con
883   void
884   dead_link_on_write(struct Client *client_p, int ierrno)
885   {
886 <  dlink_node *ptr;
886 >  dlink_node *node;
887  
888    if (IsDefunct(client_p))
889      return;
890  
891 <  dbuf_clear(&client_p->localClient->buf_recvq);
892 <  dbuf_clear(&client_p->localClient->buf_sendq);
891 >  dbuf_clear(&client_p->connection->buf_recvq);
892 >  dbuf_clear(&client_p->connection->buf_sendq);
893  
894    assert(dlinkFind(&abort_list, client_p) == NULL);
895 <  ptr = make_dlink_node();
895 >  node = make_dlink_node();
896    /* don't let exit_aborted_clients() finish yet */
897 <  dlinkAddTail(client_p, ptr, &abort_list);
897 >  dlinkAddTail(client_p, node, &abort_list);
898  
899    if (eac_next == NULL)
900 <    eac_next = ptr;
900 >    eac_next = node;
901  
902    SetDead(client_p); /* You are dead my friend */
903   }
# Line 881 | Line 915 | dead_link_on_read(struct Client *client_
915    if (IsDefunct(client_p))
916      return;
917  
918 <  dbuf_clear(&client_p->localClient->buf_recvq);
919 <  dbuf_clear(&client_p->localClient->buf_sendq);
918 >  dbuf_clear(&client_p->connection->buf_recvq);
919 >  dbuf_clear(&client_p->connection->buf_sendq);
920  
921 <  current_error = get_sockerr(client_p->localClient->fd.fd);
921 >  current_error = comm_get_sockerr(client_p->connection->fd->fd);
922  
923    if (IsServer(client_p) || IsHandshake(client_p))
924    {
891    int connected = CurrentTime - client_p->localClient->firsttime;
892
925      if (error == 0)
926      {
927 <      /* Admins get the real IP */
896 <      sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
927 >      sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
928                             "Server %s closed the connection",
929 <                           get_client_name(client_p, SHOW_IP));
930 <
900 <      /* Opers get a masked IP */
901 <      sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
929 >                           client_get_name(client_p, SHOW_IP));
930 >      sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
931                             "Server %s closed the connection",
932 <                           get_client_name(client_p, MASK_IP));
904 <
932 >                           client_get_name(client_p, MASK_IP));
933        ilog(LOG_TYPE_IRCD, "Server %s closed the connection",
934 <           get_client_name(client_p, SHOW_IP));
934 >           client_get_name(client_p, SHOW_IP));
935      }
936      else
937      {
938 <      report_error(L_ADMIN, "Lost connection to %s: %s",
939 <                   get_client_name(client_p, SHOW_IP), current_error);
940 <      report_error(L_OPER, "Lost connection to %s: %s",
941 <                   get_client_name(client_p, MASK_IP), current_error);
938 >      sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
939 >                           "Lost connection to %s: %s",
940 >                           client_get_name(client_p, SHOW_IP), strerror(current_error));
941 >      sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
942 >                           "Lost connection to %s: %s",
943 >                           client_get_name(client_p, MASK_IP), strerror(current_error));
944 >      ilog(LOG_TYPE_IRCD, "Lost connection to %s: %s",
945 >           client_get_name(client_p, SHOW_IP), strerror(current_error));
946      }
947  
948 <    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
949 <                         "%s had been connected for %d day%s, %2d:%02d:%02d",
950 <                         client_p->name, connected/86400,
919 <                         (connected/86400 == 1) ? "" : "s",
920 <                         (connected % 86400) / 3600, (connected % 3600) / 60,
921 <                         connected % 60);
948 >    sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
949 >                         "%s was connected for %s",
950 >                         client_p->name, time_dissect(CurrentTime - client_p->connection->firsttime));
951    }
952  
953    if (error == 0)
# Line 943 | Line 972 | exit_aborted_clients(void)
972      target_p = ptr->data;
973      eac_next = ptr->next;
974  
975 +    dlinkDelete(ptr, &abort_list);
976 +    free_dlink_node(ptr);
977 +
978      if (target_p == NULL)
979      {
980 <      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
980 >      sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
981                             "Warning: null client on abort_list!");
950      dlinkDelete(ptr, &abort_list);
951      free_dlink_node(ptr);
982        continue;
983      }
984  
985 <    dlinkDelete(ptr, &abort_list);
956 <
957 <    if (IsSendQExceeded(target_p))
985 >    if (HasFlag(target_p, FLAGS_SENDQEX))
986        notice = "Max SendQ exceeded";
987      else
988        notice = "Write error: connection closed";
989  
990      exit_client(target_p, notice);
963    free_dlink_node(ptr);
991    }
992   }
993  
# Line 977 | Line 1004 | exit_aborted_clients(void)
1004   void
1005   del_accept(struct split_nuh_item *accept_p, struct Client *client_p)
1006   {
1007 <  dlinkDelete(&accept_p->node, &client_p->localClient->acceptlist);
1007 >  dlinkDelete(&accept_p->node, &client_p->connection->acceptlist);
1008  
1009 <  MyFree(accept_p->nickptr);
1010 <  MyFree(accept_p->userptr);
1011 <  MyFree(accept_p->hostptr);
1012 <  MyFree(accept_p);
1009 >  xfree(accept_p->nickptr);
1010 >  xfree(accept_p->userptr);
1011 >  xfree(accept_p->hostptr);
1012 >  xfree(accept_p);
1013   }
1014  
1015   struct split_nuh_item *
1016   find_accept(const char *nick, const char *user,
1017              const char *host, struct Client *client_p,
1018 <            int (*cmpfunc)(const char *, const char *))
1018 >            int (*compare)(const char *, const char *))
1019   {
1020 <  dlink_node *ptr = NULL;
1020 >  dlink_node *node;
1021  
1022 <  DLINK_FOREACH(ptr, client_p->localClient->acceptlist.head)
1022 >  DLINK_FOREACH(node, client_p->connection->acceptlist.head)
1023    {
1024 <    struct split_nuh_item *accept_p = ptr->data;
1024 >    struct split_nuh_item *accept_p = node->data;
1025  
1026 <    if (!cmpfunc(accept_p->nickptr, nick) &&
1027 <        !cmpfunc(accept_p->userptr, user) &&
1028 <        !cmpfunc(accept_p->hostptr, host))
1026 >    if (compare(accept_p->nickptr, nick) == 0 &&
1027 >        compare(accept_p->userptr, user) == 0 &&
1028 >        compare(accept_p->hostptr, host) == 0)
1029        return accept_p;
1030    }
1031  
# Line 1012 | Line 1039 | find_accept(const char *nick, const char
1039   * output       - 1 if accept this message 0 if not
1040   * side effects - See if source is on target's allow list
1041   */
1042 < int
1042 > bool
1043   accept_message(struct Client *source,
1044                 struct Client *target)
1045   {
1046 <  dlink_node *ptr = NULL;
1046 >  dlink_node *node;
1047 >
1048 >  if (HasFlag(source, FLAGS_SERVICE) ||
1049 >      (HasUMode(source, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid))
1050 >    return true;
1051  
1052    if (source == target || find_accept(source->name, source->username,
1053                                        source->host, target, match))
1054 <    return 1;
1054 >    return true;
1055  
1056 <  if (HasUMode(target, UMODE_SOFTCALLERID))
1057 <    DLINK_FOREACH(ptr, target->channel.head)
1058 <      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1059 <        return 1;
1056 >  if (!HasUMode(target, UMODE_CALLERID) && HasUMode(target, UMODE_SOFTCALLERID))
1057 >    DLINK_FOREACH(node, target->channel.head)
1058 >      if (IsMember(source, ((struct Membership *)node->data)->chptr))
1059 >        return true;
1060  
1061 <  return 0;
1061 >  return false;
1062   }
1063  
1064   /* del_all_accepts()
# Line 1039 | Line 1070 | accept_message(struct Client *source,
1070   void
1071   del_all_accepts(struct Client *client_p)
1072   {
1073 <  dlink_node *ptr = NULL, *ptr_next = NULL;
1073 >  dlink_node *node, *node_next;
1074  
1075 <  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->acceptlist.head)
1076 <    del_accept(ptr->data, client_p);
1075 >  DLINK_FOREACH_SAFE(node, node_next, client_p->connection->acceptlist.head)
1076 >    del_accept(node->data, client_p);
1077   }
1078  
1079   unsigned int
1080 < idle_time_get(const struct Client *source_p, const struct Client *target_p)
1080 > client_get_idle_time(const struct Client *source_p,
1081 >                     const struct Client *target_p)
1082   {
1083    unsigned int idle = 0;
1084 <  unsigned int min_idle = 0;
1053 <  unsigned int max_idle = 0;
1054 <  const struct ClassItem *class = get_class_ptr(&target_p->localClient->confs);
1084 >  const struct ClassItem *const class = class_get_ptr(&target_p->connection->confs);
1085  
1086    if (!(class->flags & CLASS_FLAGS_FAKE_IDLE) || target_p == source_p)
1087 <    return CurrentTime - target_p->localClient->last_privmsg;
1087 >    return CurrentTime - target_p->connection->last_privmsg;
1088 >
1089    if (HasUMode(source_p, UMODE_OPER) &&
1090        !(class->flags & CLASS_FLAGS_HIDE_IDLE_FROM_OPERS))
1091 <    return CurrentTime - target_p->localClient->last_privmsg;
1091 >    return CurrentTime - target_p->connection->last_privmsg;
1092  
1093 <  min_idle = class->min_idle;
1094 <  max_idle = class->max_idle;
1093 >  const unsigned int min_idle = class->min_idle;
1094 >  const unsigned int max_idle = class->max_idle;
1095  
1096    if (min_idle == max_idle)
1097      return min_idle;
# Line 1068 | Line 1099 | idle_time_get(const struct Client *sourc
1099    if (class->flags & CLASS_FLAGS_RANDOM_IDLE)
1100      idle = genrand_int32();
1101    else
1102 <    idle = CurrentTime - target_p->localClient->last_privmsg;
1102 >    idle = CurrentTime - target_p->connection->last_privmsg;
1103  
1104 <  if (!max_idle)
1074 <    idle = 0;
1075 <  else
1104 >  if (max_idle)
1105      idle %= max_idle;
1106 +  else
1107 +    idle = 0;
1108  
1109    if (idle < min_idle)
1110      idle = min_idle + (idle % (max_idle - min_idle));
# Line 1097 | Line 1128 | client_init(void)
1128      .when = 5
1129    };
1130  
1100  client_pool = mp_pool_new(sizeof(struct Client), MP_CHUNK_SIZE_CLIENT);
1101  lclient_pool = mp_pool_new(sizeof(struct LocalUser), MP_CHUNK_SIZE_LCLIENT);
1131    event_add(&event_ping, NULL);
1132   }

Comparing ircd-hybrid/trunk/src/client.c (property svn:keywords):
Revision 4400 by michael, Tue Aug 5 17:42:56 2014 UTC vs.
Revision 8688 by michael, Sun Dec 2 12:46:22 2018 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)