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 4187 by michael, Sun Jul 6 16:14:34 2014 UTC vs.
Revision 5556 by michael, Fri Feb 13 19:25:36 2015 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-2015 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 49 | Line 49
49   #include "watch.h"
50   #include "rng_mt.h"
51   #include "parse.h"
52 + #include "ipcache.h"
53  
53 dlink_list listing_client_list = { NULL, NULL, 0 };
54 /* Pointer to beginning of Client list */
55 dlink_list global_client_list = {NULL, NULL, 0};
56 /* unknown/client pointer lists */
57 dlink_list unknown_list = {NULL, NULL, 0};
58 dlink_list local_client_list = {NULL, NULL, 0};
59 dlink_list serv_list = {NULL, NULL, 0};
60 dlink_list global_serv_list = {NULL, NULL, 0};
61 dlink_list oper_list = {NULL, NULL, 0};
54  
55 < static void check_pings(void *);
56 <
57 < static mp_pool_t *client_pool  = NULL;
58 < static mp_pool_t *lclient_pool = NULL;
59 <
60 < static dlink_list dead_list  = { NULL, NULL, 0};
61 < static dlink_list abort_list = { NULL, NULL, 0};
55 > dlink_list listing_client_list;
56 > dlink_list unknown_list;
57 > dlink_list local_client_list;
58 > dlink_list local_server_list;
59 > dlink_list global_client_list;
60 > dlink_list global_server_list;
61 > dlink_list oper_list;
62  
63 + static mp_pool_t *client_pool, *connection_pool;
64 + static dlink_list dead_list, abort_list;
65   static dlink_node *eac_next;  /* next aborted client to exit */
66  
73 static void check_pings_list(dlink_list *);
74 static void check_unknowns_list(void);
75
76
77 /* client_init()
78 *
79 * inputs       - NONE
80 * output       - NONE
81 * side effects - initialize client free memory
82 */
83 void
84 client_init(void)
85 {
86  static struct event event_ping =
87  {
88    .name = "check_pings",
89    .handler = check_pings,
90    .when = 5
91  };
92
93  client_pool = mp_pool_new(sizeof(struct Client), MP_CHUNK_SIZE_CLIENT);
94  lclient_pool = mp_pool_new(sizeof(struct LocalUser), MP_CHUNK_SIZE_LCLIENT);
95  event_add(&event_ping, NULL);
96 }
67  
68   /*
69   * make_client - create a new Client struct and set it to initial state.
# Line 113 | Line 83 | client_init(void)
83   struct Client *
84   make_client(struct Client *from)
85   {
86 <  struct Client *client_p = mp_pool_get(client_pool);
86 >  struct Client *const client_p = mp_pool_get(client_pool);
87  
88    if (!from)
89    {
90 <    client_p->from                      = client_p; /* 'from' of local client is self! */
91 <    client_p->localClient               = mp_pool_get(lclient_pool);
92 <    client_p->localClient->since        = CurrentTime;
93 <    client_p->localClient->lasttime     = CurrentTime;
94 <    client_p->localClient->firsttime    = CurrentTime;
95 <    client_p->localClient->registration = REG_INIT;
90 >    client_p->from = client_p;  /* 'from' of local client is self! */
91 >    client_p->connection = mp_pool_get(connection_pool);
92 >    client_p->connection->since = CurrentTime;
93 >    client_p->connection->lasttime = CurrentTime;
94 >    client_p->connection->firsttime = CurrentTime;
95 >    client_p->connection->registration = REG_INIT;
96  
97      /* as good a place as any... */
98 <    dlinkAdd(client_p, &client_p->localClient->lclient_node, &unknown_list);
98 >    dlinkAdd(client_p, &client_p->connection->lclient_node, &unknown_list);
99    }
100    else
101 <    client_p->from = from; /* 'from' of local client is self! */
101 >    client_p->from = from;
102  
103    client_p->idhnext = client_p;
104 <  client_p->hnext  = client_p;
104 >  client_p->hnext = client_p;
105    SetUnknown(client_p);
106    strcpy(client_p->username, "unknown");
107 <  strcpy(client_p->svid, "0");
107 >  strcpy(client_p->account, "0");
108  
109    return client_p;
110   }
# Line 149 | Line 119 | make_client(struct Client *from)
119   static void
120   free_client(struct Client *client_p)
121   {
152  assert(client_p);
122    assert(client_p != &me);
123    assert(client_p->hnext == client_p);
124    assert(client_p->idhnext == client_p);
# Line 163 | Line 132 | free_client(struct Client *client_p)
132  
133    if (MyConnect(client_p))
134    {
135 <    assert(client_p->localClient->invited.head == NULL);
136 <    assert(dlink_list_length(&client_p->localClient->invited) == 0);
137 <    assert(dlink_list_length(&client_p->localClient->watches) == 0);
135 >    assert(client_p->connection->invited.head == NULL);
136 >    assert(dlink_list_length(&client_p->connection->invited) == 0);
137 >    assert(dlink_list_length(&client_p->connection->watches) == 0);
138      assert(IsClosing(client_p) && IsDead(client_p));
139  
140 <    MyFree(client_p->localClient->response);
141 <    MyFree(client_p->localClient->auth_oper);
140 >    MyFree(client_p->connection->challenge_response);
141 >    client_p->connection->challenge_response = NULL;
142 >    MyFree(client_p->connection->challenge_operator);
143 >    client_p->connection->challenge_operator = NULL;
144  
145      /*
146 <     * clean up extra sockets from P-lines which have been discarded.
146 >     * Clean up extra sockets from listen{} blocks which have been discarded.
147       */
148 <    if (client_p->localClient->listener)
148 >    if (client_p->connection->listener)
149      {
150 <      assert(0 < client_p->localClient->listener->ref_count);
151 <      if (0 == --client_p->localClient->listener->ref_count &&
181 <          !client_p->localClient->listener->active)
182 <        free_listener(client_p->localClient->listener);
150 >      listener_release(client_p->connection->listener);
151 >      client_p->connection->listener = NULL;
152      }
153  
154 <    dbuf_clear(&client_p->localClient->buf_recvq);
155 <    dbuf_clear(&client_p->localClient->buf_sendq);
154 >    dbuf_clear(&client_p->connection->buf_recvq);
155 >    dbuf_clear(&client_p->connection->buf_sendq);
156  
157 <    mp_pool_release(client_p->localClient);
157 >    mp_pool_release(client_p->connection);
158    }
159  
160    mp_pool_release(client_p);
161   }
162  
163 < /*
164 < * check_pings - go through the local client list and check activity
165 < * kill off stuff that should die
166 < *
167 < * inputs       - NOT USED (from event)
199 < * output       - next time_t when check_pings() should be called again
200 < * side effects -
201 < *
202 < *
203 < * A PING can be sent to clients as necessary.
204 < *
205 < * Client/Server ping outs are handled.
206 < */
163 > void
164 > client_attach_svstag(struct Client *client_p, unsigned int numeric,
165 >                     unsigned int privilege, const char *const tag)
166 > {
167 >  struct ServicesTag *svstag = NULL;
168  
169 < /*
170 < * Addon from adrian. We used to call this after nextping seconds,
210 < * however I've changed it to run once a second. This is only for
211 < * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
212 < * run once a second makes life a lot easier - when a new client connects
213 < * and they need a ping in 4 seconds, if nextping was set to 20 seconds
214 < * we end up waiting 20 seconds. This is stupid. :-)
215 < * I will optimise (hah!) check_pings() once I've finished working on
216 < * tidying up other network IO evilnesses.
217 < *     -- adrian
218 < */
169 >  if (numeric >= ERR_LAST_ERR_MSG || privilege > 2)
170 >    return;
171  
172 < static void
173 < check_pings(void *notused)
172 >  svstag = MyCalloc(sizeof(*svstag));
173 >  svstag->numeric = numeric;
174 >  svstag->privilege = privilege;
175 >  svstag->tag = xstrdup(tag);
176 >
177 >  if (numeric != RPL_WHOISOPERATOR)
178 >    dlinkAddTail(svstag, &svstag->node, &client_p->svstags);
179 >  else
180 >    dlinkAdd(svstag, &svstag->node, &client_p->svstags);
181 > }
182 >
183 > void
184 > client_clear_svstags(struct Client *client_p)
185   {
186 <  check_pings_list(&local_client_list);
187 <  check_pings_list(&serv_list);
188 <  check_unknowns_list();
186 >  dlink_node *node = NULL, *node_next = NULL;
187 >
188 >  DLINK_FOREACH_SAFE(node, node_next, client_p->svstags.head)
189 >  {
190 >    struct ServicesTag *svstag = node->data;
191 >
192 >    dlinkDelete(&svstag->node, &client_p->svstags);
193 >    MyFree(svstag->tag);
194 >    MyFree(svstag);
195 >  }
196   }
197  
198   /* check_pings_list()
# Line 234 | Line 204 | check_pings(void *notused)
204   static void
205   check_pings_list(dlink_list *list)
206   {
207 <  char scratch[IRCD_BUFSIZE];
207 >  char buf[IRCD_BUFSIZE] = "";
208    int ping = 0;      /* ping time value from client */
209 <  dlink_node *ptr = NULL, *next_ptr = NULL;
209 >  dlink_node *node = NULL, *node_next = NULL;
210  
211 <  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
211 >  DLINK_FOREACH_SAFE(node, node_next, list->head)
212    {
213 <    struct Client *client_p = ptr->data;
213 >    struct Client *client_p = node->data;
214  
245    /*
246    ** Note: No need to notify opers here. It's
247    ** already done when "FLAGS_DEADSOCKET" is set.
248    */
215      if (IsDead(client_p))
216 <    {
251 <      /* Ignore it, its been exited already */
252 <      continue;
253 <    }
216 >      continue;  /* Ignore it, its been exited already */
217  
218      if (!IsRegistered(client_p))
219        ping = CONNECTTIMEOUT;
220      else
221 <      ping = get_client_ping(&client_p->localClient->confs);
221 >      ping = get_client_ping(&client_p->connection->confs);
222  
223 <    if (ping < CurrentTime - client_p->localClient->lasttime)
223 >    if (ping < CurrentTime - client_p->connection->lasttime)
224      {
225        if (!IsPingSent(client_p))
226        {
227          /*
228 <         * if we havent PINGed the connection and we havent
228 >         * If we haven't PINGed the connection and we haven't
229           * heard from it in a while, PING it to make sure
230           * it is still alive.
231           */
232          SetPingSent(client_p);
233 <        client_p->localClient->lasttime = CurrentTime - ping;
233 >        client_p->connection->lasttime = CurrentTime - ping;
234          sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
235        }
236        else
237        {
238 <        if (CurrentTime - client_p->localClient->lasttime >= 2 * ping)
238 >        if (CurrentTime - client_p->connection->lasttime >= 2 * ping)
239          {
240            /*
241             * If the client/server hasn't talked to us in 2*ping seconds
# Line 290 | Line 253 | check_pings_list(dlink_list *list)
253                   get_client_name(client_p, HIDE_IP));
254            }
255  
256 <          snprintf(scratch, sizeof(scratch), "Ping timeout: %d seconds",
257 <                   (int)(CurrentTime - client_p->localClient->lasttime));
258 <          exit_client(client_p, scratch);
256 >          snprintf(buf, sizeof(buf), "Ping timeout: %d seconds",
257 >                   (int)(CurrentTime - client_p->connection->lasttime));
258 >          exit_client(client_p, buf);
259          }
260        }
261      }
# Line 308 | Line 271 | check_pings_list(dlink_list *list)
271   static void
272   check_unknowns_list(void)
273   {
274 <  dlink_node *ptr = NULL, *ptr_next = NULL;
274 >  dlink_node *node = NULL, *node_next = NULL;
275  
276 <  DLINK_FOREACH_SAFE(ptr, ptr_next, unknown_list.head)
276 >  DLINK_FOREACH_SAFE(node, node_next, unknown_list.head)
277    {
278 <    struct Client *client_p = ptr->data;
278 >    struct Client *client_p = node->data;
279  
280      /*
281       * Check UNKNOWN connections - if they have been in this state
282       * for > 30s, close them.
283       */
284 <    if (IsAuthFinished(client_p) && (CurrentTime - client_p->localClient->firsttime) > 30)
284 >    if (IsAuthFinished(client_p) && (CurrentTime - client_p->connection->firsttime) > 30)
285        exit_client(client_p, "Registration timed out");
286    }
287   }
288  
289 + /*
290 + * check_pings - go through the local client list and check activity
291 + * kill off stuff that should die
292 + *
293 + * inputs       - NOT USED (from event)
294 + * output       - next time_t when check_pings() should be called again
295 + * side effects -
296 + *
297 + *
298 + * A PING can be sent to clients as necessary.
299 + *
300 + * Client/Server ping outs are handled.
301 + */
302 +
303 + /*
304 + * Addon from adrian. We used to call this after nextping seconds,
305 + * however I've changed it to run once a second. This is only for
306 + * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
307 + * run once a second makes life a lot easier - when a new client connects
308 + * and they need a ping in 4 seconds, if nextping was set to 20 seconds
309 + * we end up waiting 20 seconds. This is stupid. :-)
310 + * I will optimise (hah!) check_pings() once I've finished working on
311 + * tidying up other network IO evilnesses.
312 + *     -- adrian
313 + */
314 +
315 + static void
316 + check_pings(void *unused)
317 + {
318 +  check_pings_list(&local_client_list);
319 +  check_pings_list(&local_server_list);
320 +  check_unknowns_list();
321 + }
322 +
323   /* check_conf_klines()
324   *
325   * inputs       - NONE
# Line 334 | Line 331 | void
331   check_conf_klines(void)
332   {
333    struct MaskItem *conf = NULL;
334 <  dlink_node *ptr = NULL, *ptr_next = NULL;
334 >  dlink_node *node = NULL, *node_next = NULL;
335  
336 <  DLINK_FOREACH_SAFE(ptr, ptr_next, local_client_list.head)
336 >  DLINK_FOREACH_SAFE(node, node_next, local_client_list.head)
337    {
338 <    struct Client *client_p = ptr->data;
338 >    struct Client *client_p = node->data;
339  
340 <    /* If a client is already being exited
341 <     */
345 <    if (IsDead(client_p) || !IsClient(client_p))
340 >    /* If a client is already being exited */
341 >    if (IsDead(client_p))
342        continue;
343  
344 <    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
345 <                                     client_p->localClient->aftype, NULL, NULL, 1)))
344 >    if ((conf = find_conf_by_address(NULL, &client_p->connection->ip, CONF_DLINE,
345 >                                     client_p->connection->aftype, NULL, NULL, 1)))
346      {
347        conf_try_ban(client_p, conf);
348        continue; /* and go examine next fd/client_p */
349      }
350  
351 <    if (ConfigFileEntry.glines)
351 >    if (ConfigGeneral.glines)
352      {
353 <      if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
354 <                                       CONF_GLINE, client_p->localClient->aftype,
353 >      if ((conf = find_conf_by_address(client_p->host, &client_p->connection->ip,
354 >                                       CONF_GLINE, client_p->connection->aftype,
355                                         client_p->username, NULL, 1)))
356        {
357          conf_try_ban(client_p, conf);
# Line 364 | Line 360 | check_conf_klines(void)
360        }
361      }
362  
363 <    if ((conf = find_conf_by_address(client_p->host, &client_p->localClient->ip,
364 <                                     CONF_KLINE, client_p->localClient->aftype,
363 >    if ((conf = find_conf_by_address(client_p->host, &client_p->connection->ip,
364 >                                     CONF_KLINE, client_p->connection->aftype,
365                                       client_p->username, NULL, 1)))
366      {
367        conf_try_ban(client_p, conf);
# Line 381 | Line 377 | check_conf_klines(void)
377    }
378  
379    /* also check the unknowns list for new dlines */
380 <  DLINK_FOREACH_SAFE(ptr, ptr_next, unknown_list.head)
380 >  DLINK_FOREACH_SAFE(node, node_next, unknown_list.head)
381    {
382 <    struct Client *client_p = ptr->data;
382 >    struct Client *client_p = node->data;
383  
384 <    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
385 <                                     client_p->localClient->aftype, NULL, NULL, 1)))
384 >    if ((conf = find_conf_by_address(NULL, &client_p->connection->ip, CONF_DLINE,
385 >                                     client_p->connection->aftype, NULL, NULL, 1)))
386      {
387        conf_try_ban(client_p, conf);
388        continue; /* and go examine next fd/client_p */
# Line 426 | Line 422 | conf_try_ban(struct Client *client_p, st
422        type_string = kline_string;
423        break;
424      case CONF_DLINE:
425 <      if (find_conf_by_address(NULL, &client_p->localClient->ip, CONF_EXEMPT,
426 <                               client_p->localClient->aftype, NULL, NULL, 1))
425 >      if (find_conf_by_address(NULL, &client_p->connection->ip, CONF_EXEMPT,
426 >                               client_p->connection->aftype, NULL, NULL, 1))
427          return;
428        type_string = dline_string;
429        break;
# Line 475 | Line 471 | update_client_exit_stats(struct Client *
471    if (IsClient(client_p))
472    {
473      assert(Count.total > 0);
474 +
475      --Count.total;
476      if (HasUMode(client_p, UMODE_OPER))
477        --Count.oper;
# Line 520 | Line 517 | find_person(const struct Client *const s
517   struct Client *
518   find_chasing(struct Client *source_p, const char *name)
519   {
520 <  struct Client *who = find_person(source_p, name);
520 >  struct Client *target_p = find_person(source_p, name);
521  
522 <  if (who)
523 <    return who;
522 >  if (target_p)
523 >    return target_p;
524  
525    if (IsDigit(*name))
526      return NULL;
527  
528 <  if ((who = whowas_get_history(name,
529 <                         (time_t)ConfigFileEntry.kill_chase_time_limit))
530 <                         == NULL)
528 >  target_p = whowas_get_history(name, (time_t)ConfigGeneral.kill_chase_time_limit);
529 >
530 >  if (!target_p)
531    {
532      sendto_one_numeric(source_p, &me, ERR_NOSUCHNICK, name);
533      return NULL;
534    }
535  
536 <  return who;
536 >  return target_p;
537   }
538  
539   /*
# Line 548 | Line 545 | find_chasing(struct Client *source_p, co
545   *        But, this can be used to any client structure.
546   *
547   * NOTE 1:
548 < *        Watch out the allocation of "nbuf", if either source_p->name
548 > *        Watch out the allocation of "buf", if either source_p->name
549   *        or source_p->sockhost gets changed into pointers instead of
550   *        directly allocated within the structure...
551   *
552   * NOTE 2:
553   *        Function return either a pointer to the structure (source_p) or
554 < *        to internal buffer (nbuf). *NEVER* use the returned pointer
554 > *        to internal buffer (buf). *NEVER* use the returned pointer
555   *        to modify what it points!!!
556   */
557   const char *
558   get_client_name(const struct Client *client_p, enum addr_mask_type type)
559   {
560 <  static char nbuf[HOSTLEN * 2 + USERLEN + 5];
564 <
565 <  assert(client_p);
560 >  static char buf[HOSTLEN * 2 + USERLEN + 5];
561  
562    if (!MyConnect(client_p))
563      return client_p->name;
# Line 575 | Line 570 | get_client_name(const struct Client *cli
570        type = MASK_IP;
571    }
572  
578  if (ConfigFileEntry.hide_spoof_ips)
579    if (IsIPSpoof(client_p) && type == SHOW_IP)
580      type = MASK_IP;
581
573    /* And finally, let's get the host information, ip or name */
574    switch (type)
575    {
576      case SHOW_IP:
577 <      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
577 >      snprintf(buf, sizeof(buf), "%s[%s@%s]",
578                 client_p->name,
579                 client_p->username, client_p->sockhost);
580        break;
581      case MASK_IP:
582 <      if (client_p->localClient->aftype == AF_INET)
583 <        snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
582 >      if (client_p->connection->aftype == AF_INET)
583 >        snprintf(buf, sizeof(buf), "%s[%s@255.255.255.255]",
584                   client_p->name, client_p->username);
585        else
586 <        snprintf(nbuf, sizeof(nbuf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
586 >        snprintf(buf, sizeof(buf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
587                   client_p->name, client_p->username);
588        break;
589      default:
590 <      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
590 >      snprintf(buf, sizeof(buf), "%s[%s@%s]",
591                 client_p->name,
592                 client_p->username, client_p->host);
593    }
594  
595 <  return nbuf;
595 >  return buf;
596   }
597  
598   void
599   free_exited_clients(void)
600   {
601 <  dlink_node *ptr = NULL, *next = NULL;
601 >  dlink_node *node = NULL, *node_next = NULL;
602  
603 <  DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
603 >  DLINK_FOREACH_SAFE(node, node_next, dead_list.head)
604    {
605 <    free_client(ptr->data);
606 <    dlinkDelete(ptr, &dead_list);
607 <    free_dlink_node(ptr);
605 >    free_client(node->data);
606 >    dlinkDelete(node, &dead_list);
607 >    free_dlink_node(node);
608    }
609   }
610  
# Line 624 | Line 615 | free_exited_clients(void)
615   * The only messages generated are QUITs on channels.
616   */
617   static void
618 < exit_one_client(struct Client *source_p, const char *quitmsg)
618 > exit_one_client(struct Client *source_p, const char *comment)
619   {
620 <  dlink_node *ptr = NULL, *ptr_next = NULL;
620 >  dlink_node *node = NULL, *node_next = NULL;
621  
622    assert(!IsMe(source_p));
623 +  assert(source_p != &me);
624  
625    if (IsClient(source_p))
626    {
627      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->client_list);
628 +    dlinkDelete(&source_p->node, &global_client_list);
629  
630      /*
631       * If a person is on a channel, send a QUIT notice
# Line 642 | Line 635 | exit_one_client(struct Client *source_p,
635       */
636      sendto_common_channels_local(source_p, 0, 0, ":%s!%s@%s QUIT :%s",
637                                   source_p->name, source_p->username,
638 <                                 source_p->host, quitmsg);
639 <    DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
640 <      remove_user_from_channel(ptr->data);
638 >                                 source_p->host, comment);
639 >
640 >    DLINK_FOREACH_SAFE(node, node_next, source_p->channel.head)
641 >      remove_user_from_channel(node->data);
642  
643      whowas_add_history(source_p, 0);
644      whowas_off_history(source_p);
# Line 654 | Line 648 | exit_one_client(struct Client *source_p,
648      if (MyConnect(source_p))
649      {
650        /* Clean up invitefield */
651 <      DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->localClient->invited.head)
652 <        del_invite(ptr->data, source_p);
651 >      DLINK_FOREACH_SAFE(node, node_next, source_p->connection->invited.head)
652 >        del_invite(node->data, source_p);
653  
654        del_all_accepts(source_p);
655      }
# Line 663 | Line 657 | exit_one_client(struct Client *source_p,
657    else if (IsServer(source_p))
658    {
659      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
660 +    dlinkDelete(&source_p->node, &global_client_list);
661  
662 <    if ((ptr = dlinkFindDelete(&global_serv_list, source_p)))
663 <      free_dlink_node(ptr);
662 >    if ((node = dlinkFindDelete(&global_server_list, source_p)))
663 >      free_dlink_node(node);
664    }
665  
666    /* Remove source_p from the client lists */
667    if (source_p->id[0])
668      hash_del_id(source_p);
669 +
670    if (source_p->name[0])
671      hash_del_client(source_p);
672  
673    if (IsUserHostIp(source_p))
674      delete_user_host(source_p->username, source_p->host, !MyConnect(source_p));
675  
680  if (source_p->node.next)
681    dlinkDelete(&source_p->node, &global_client_list);
682
676    update_client_exit_stats(source_p);
677  
678    /* Check to see if the client isn't already on the dead list */
# Line 697 | Line 690 | exit_one_client(struct Client *source_p,
690   * actually removing things off llists.   tweaked from +CSr31  -orabidoo
691   */
692   static void
693 < recurse_remove_clients(struct Client *source_p, const char *quitmsg)
693 > recurse_remove_clients(struct Client *source_p, const char *comment)
694   {
695 <  dlink_node *ptr = NULL, *ptr_next = NULL;
695 >  dlink_node *node = NULL, *node_next = NULL;
696  
697 <  DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->client_list.head)
698 <    exit_one_client(ptr->data, quitmsg);
697 >  DLINK_FOREACH_SAFE(node, node_next, source_p->serv->client_list.head)
698 >    exit_one_client(node->data, comment);
699  
700 <  DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->server_list.head)
700 >  DLINK_FOREACH_SAFE(node, node_next, source_p->serv->server_list.head)
701    {
702 <    recurse_remove_clients(ptr->data, quitmsg);
703 <    exit_one_client(ptr->data, quitmsg);
702 >    recurse_remove_clients(node->data, comment);
703 >    exit_one_client(node->data, comment);
704    }
705   }
706  
# Line 731 | Line 724 | recurse_remove_clients(struct Client *so
724   void
725   exit_client(struct Client *source_p, const char *comment)
726   {
727 <  dlink_node *m = NULL;
727 >  dlink_node *node = NULL;
728 >
729 >  assert(!IsMe(source_p));
730 >  assert(source_p != &me);
731  
732    if (MyConnect(source_p))
733    {
# Line 743 | Line 739 | exit_client(struct Client *source_p, con
739  
740      SetClosing(source_p);
741  
742 <    if (IsIpHash(source_p))
743 <      remove_one_ip(&source_p->localClient->ip);
742 >    if (HasFlag(source_p, FLAGS_IPHASH))
743 >    {
744 >      DelFlag(source_p, FLAGS_IPHASH);
745 >      ipcache_remove_address(&source_p->connection->ip);
746 >    }
747  
748 <    delete_auth(&source_p->localClient->auth);
748 >    delete_auth(&source_p->connection->auth);
749  
750      /*
751       * This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
# Line 759 | Line 758 | exit_client(struct Client *source_p, con
758      {
759        assert(dlinkFind(&unknown_list, source_p));
760  
761 <      dlinkDelete(&source_p->localClient->lclient_node, &unknown_list);
761 >      dlinkDelete(&source_p->connection->lclient_node, &unknown_list);
762      }
763      else if (IsClient(source_p))
764      {
765 <      time_t on_for = CurrentTime - source_p->localClient->firsttime;
765 >      time_t on_for = CurrentTime - source_p->connection->firsttime;
766 >
767        assert(Count.local > 0);
768 <      Count.local--;
768 >
769 >      --Count.local;
770  
771        if (HasUMode(source_p, UMODE_OPER))
772 <        if ((m = dlinkFindDelete(&oper_list, source_p)))
773 <          free_dlink_node(m);
772 >        if ((node = dlinkFindDelete(&oper_list, source_p)))
773 >          free_dlink_node(node);
774  
775        assert(dlinkFind(&local_client_list, source_p));
776 <      dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
776 >      dlinkDelete(&source_p->connection->lclient_node, &local_client_list);
777  
778 <      if (source_p->localClient->list_task)
778 >      if (source_p->connection->list_task)
779          free_list_task(source_p);
780  
781        watch_del_watch_list(source_p);
782 +      client_clear_svstags(source_p);
783 +
784        sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE,
785                             "Client exiting: %s (%s@%s) [%s] [%s]",
786                             source_p->name, source_p->username, source_p->host, comment,
787 <                           ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
788 <                           "255.255.255.255" : source_p->sockhost);
787 >                           source_p->sockhost);
788 >
789        ilog(LOG_TYPE_USER, "%s (%3u:%02u:%02u): %s!%s@%s %llu/%llu",
790 <           myctime(source_p->localClient->firsttime), (unsigned int)(on_for / 3600),
790 >           myctime(source_p->connection->firsttime), (unsigned int)(on_for / 3600),
791             (unsigned int)((on_for % 3600)/60), (unsigned int)(on_for % 60),
792             source_p->name, source_p->username, source_p->host,
793 <           source_p->localClient->send.bytes>>10,
794 <           source_p->localClient->recv.bytes>>10);
793 >           source_p->connection->send.bytes>>10,
794 >           source_p->connection->recv.bytes>>10);
795      }
796      else if (IsServer(source_p))
797      {
798        assert(Count.myserver > 0);
799 +
800        --Count.myserver;
801  
802 <      assert(dlinkFind(&serv_list, source_p));
803 <      dlinkDelete(&source_p->localClient->lclient_node, &serv_list);
802 >      assert(dlinkFind(&local_server_list, source_p));
803 >      dlinkDelete(&source_p->connection->lclient_node, &local_server_list);
804      }
805  
806      if (!IsDead(source_p))
# Line 840 | Line 844 | exit_client(struct Client *source_p, con
844        snprintf(splitstr, sizeof(splitstr), "%s %s",
845                 source_p->servptr->name, source_p->name);
846  
847 <    /* Send SQUIT for source_p in every direction. source_p is already off of serv_list here */
847 >    /* Send SQUIT for source_p in every direction. source_p is already off of local_server_list here */
848      if (!HasFlag(source_p, FLAGS_SQUIT))
849 <      sendto_server(NULL, NOCAPS, NOCAPS, "SQUIT %s :%s", source_p->id, comment);
849 >      sendto_server(NULL, 0, 0, "SQUIT %s :%s", source_p->id, comment);
850  
851      /* Now exit the clients internally */
852      recurse_remove_clients(source_p, splitstr);
853  
854      if (MyConnect(source_p))
855      {
856 +      int connected = CurrentTime - source_p->connection->firsttime;
857        sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
858 <                           "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
859 <                           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
860 <                           source_p->localClient->send.bytes >> 10,
861 <                           source_p->localClient->recv.bytes >> 10);
862 <      ilog(LOG_TYPE_IRCD, "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
863 <           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
864 <           source_p->localClient->send.bytes >> 10,
865 <           source_p->localClient->recv.bytes >> 10);
858 >                           "%s was connected for %d day%s, %2d:%02d:%02d. %llu/%llu sendK/recvK.",
859 >                           source_p->name, connected/86400, (connected/86400 == 1) ? "" : "s",
860 >                           (connected % 86400) / 3600, (connected % 3600) / 60, connected % 60,
861 >                           source_p->connection->send.bytes >> 10,
862 >                           source_p->connection->recv.bytes >> 10);
863 >      ilog(LOG_TYPE_IRCD, "%s was connected for %d day%s, %2d:%02d:%02d. %llu/%llu sendK/recvK.",
864 >           source_p->name, connected/86400, (connected/86400 == 1) ? "" : "s",
865 >          (connected % 86400) / 3600, (connected % 3600) / 60, connected % 60,
866 >          source_p->connection->send.bytes >> 10,
867 >          source_p->connection->recv.bytes >> 10);
868      }
869    }
870    else if (IsClient(source_p) && !HasFlag(source_p, FLAGS_KILLED))
871 <    sendto_server(source_p->from, NOCAPS, NOCAPS, ":%s QUIT :%s",
871 >    sendto_server(source_p->from, 0, 0, ":%s QUIT :%s",
872                    source_p->id, comment);
873  
874    /* The client *better* be off all of the lists */
875    assert(dlinkFind(&unknown_list, source_p) == NULL);
876    assert(dlinkFind(&local_client_list, source_p) == NULL);
877 <  assert(dlinkFind(&serv_list, source_p) == NULL);
877 >  assert(dlinkFind(&local_server_list, source_p) == NULL);
878    assert(dlinkFind(&oper_list, source_p) == NULL);
879  
880    exit_one_client(source_p, comment);
# Line 880 | Line 887 | exit_client(struct Client *source_p, con
887   void
888   dead_link_on_write(struct Client *client_p, int ierrno)
889   {
890 <  dlink_node *ptr;
890 >  dlink_node *node;
891  
892    if (IsDefunct(client_p))
893      return;
894  
895 <  dbuf_clear(&client_p->localClient->buf_recvq);
896 <  dbuf_clear(&client_p->localClient->buf_sendq);
895 >  dbuf_clear(&client_p->connection->buf_recvq);
896 >  dbuf_clear(&client_p->connection->buf_sendq);
897  
898    assert(dlinkFind(&abort_list, client_p) == NULL);
899 <  ptr = make_dlink_node();
899 >  node = make_dlink_node();
900    /* don't let exit_aborted_clients() finish yet */
901 <  dlinkAddTail(client_p, ptr, &abort_list);
901 >  dlinkAddTail(client_p, node, &abort_list);
902  
903    if (eac_next == NULL)
904 <    eac_next = ptr;
904 >    eac_next = node;
905  
906    SetDead(client_p); /* You are dead my friend */
907   }
# Line 912 | Line 919 | dead_link_on_read(struct Client *client_
919    if (IsDefunct(client_p))
920      return;
921  
922 <  dbuf_clear(&client_p->localClient->buf_recvq);
923 <  dbuf_clear(&client_p->localClient->buf_sendq);
922 >  dbuf_clear(&client_p->connection->buf_recvq);
923 >  dbuf_clear(&client_p->connection->buf_sendq);
924  
925 <  current_error = get_sockerr(client_p->localClient->fd.fd);
925 >  current_error = get_sockerr(client_p->connection->fd.fd);
926  
927    if (IsServer(client_p) || IsHandshake(client_p))
928    {
929 <    int connected = CurrentTime - client_p->localClient->firsttime;
929 >    int connected = CurrentTime - client_p->connection->firsttime;
930  
931      if (error == 0)
932      {
# Line 945 | Line 952 | dead_link_on_read(struct Client *client_
952      }
953  
954      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
955 <                         "%s had been connected for %d day%s, %2d:%02d:%02d",
955 >                         "%s was connected for %d day%s, %2d:%02d:%02d",
956                           client_p->name, connected/86400,
957                           (connected/86400 == 1) ? "" : "s",
958                           (connected % 86400) / 3600, (connected % 3600) / 60,
# Line 1008 | Line 1015 | exit_aborted_clients(void)
1015   void
1016   del_accept(struct split_nuh_item *accept_p, struct Client *client_p)
1017   {
1018 <  dlinkDelete(&accept_p->node, &client_p->localClient->acceptlist);
1018 >  dlinkDelete(&accept_p->node, &client_p->connection->acceptlist);
1019  
1020    MyFree(accept_p->nickptr);
1021    MyFree(accept_p->userptr);
# Line 1021 | Line 1028 | find_accept(const char *nick, const char
1028              const char *host, struct Client *client_p,
1029              int (*cmpfunc)(const char *, const char *))
1030   {
1031 <  dlink_node *ptr = NULL;
1031 >  dlink_node *node = NULL;
1032  
1033 <  DLINK_FOREACH(ptr, client_p->localClient->acceptlist.head)
1033 >  DLINK_FOREACH(node, client_p->connection->acceptlist.head)
1034    {
1035 <    struct split_nuh_item *accept_p = ptr->data;
1035 >    struct split_nuh_item *accept_p = node->data;
1036  
1037      if (!cmpfunc(accept_p->nickptr, nick) &&
1038          !cmpfunc(accept_p->userptr, user) &&
# Line 1047 | Line 1054 | int
1054   accept_message(struct Client *source,
1055                 struct Client *target)
1056   {
1057 <  dlink_node *ptr = NULL;
1057 >  dlink_node *node = NULL;
1058 >
1059 >  if (HasFlag(source, FLAGS_SERVICE) ||
1060 >      (HasUMode(source, UMODE_OPER) && ConfigGeneral.opers_bypass_callerid))
1061 >    return 1;
1062  
1063    if (source == target || find_accept(source->name, source->username,
1064                                        source->host, target, match))
1065      return 1;
1066  
1067 <  if (HasUMode(target, UMODE_SOFTCALLERID))
1068 <    DLINK_FOREACH(ptr, target->channel.head)
1069 <      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1067 >  if (!HasUMode(target, UMODE_CALLERID) && HasUMode(target, UMODE_SOFTCALLERID))
1068 >    DLINK_FOREACH(node, target->channel.head)
1069 >      if (IsMember(source, ((struct Membership *)node->data)->chptr))
1070          return 1;
1071  
1072    return 0;
# Line 1070 | Line 1081 | accept_message(struct Client *source,
1081   void
1082   del_all_accepts(struct Client *client_p)
1083   {
1084 <  dlink_node *ptr = NULL, *ptr_next = NULL;
1084 >  dlink_node *node = NULL, *node_next = NULL;
1085  
1086 <  DLINK_FOREACH_SAFE(ptr, ptr_next, client_p->localClient->acceptlist.head)
1087 <    del_accept(ptr->data, client_p);
1086 >  DLINK_FOREACH_SAFE(node, node_next, client_p->connection->acceptlist.head)
1087 >    del_accept(node->data, client_p);
1088   }
1089  
1090   unsigned int
1091 < idle_time_get(const struct Client *source_p, const struct Client *target_p)
1091 > client_get_idle_time(const struct Client *source_p,
1092 >                     const struct Client *target_p)
1093   {
1094    unsigned int idle = 0;
1095    unsigned int min_idle = 0;
1096    unsigned int max_idle = 0;
1097 <  const struct ClassItem *class = get_class_ptr(&target_p->localClient->confs);
1097 >  const struct ClassItem *const class = get_class_ptr(&target_p->connection->confs);
1098  
1099    if (!(class->flags & CLASS_FLAGS_FAKE_IDLE) || target_p == source_p)
1100 <    return CurrentTime - target_p->localClient->last_privmsg;
1100 >    return CurrentTime - target_p->connection->last_privmsg;
1101 >
1102    if (HasUMode(source_p, UMODE_OPER) &&
1103        !(class->flags & CLASS_FLAGS_HIDE_IDLE_FROM_OPERS))
1104 <    return CurrentTime - target_p->localClient->last_privmsg;
1104 >    return CurrentTime - target_p->connection->last_privmsg;
1105  
1106    min_idle = class->min_idle;
1107    max_idle = class->max_idle;
# Line 1099 | Line 1112 | idle_time_get(const struct Client *sourc
1112    if (class->flags & CLASS_FLAGS_RANDOM_IDLE)
1113      idle = genrand_int32();
1114    else
1115 <    idle = CurrentTime - target_p->localClient->last_privmsg;
1115 >    idle = CurrentTime - target_p->connection->last_privmsg;
1116  
1117    if (!max_idle)
1118      idle = 0;
# Line 1111 | Line 1124 | idle_time_get(const struct Client *sourc
1124  
1125    return idle;
1126   }
1127 +
1128 + /* client_init()
1129 + *
1130 + * inputs       - NONE
1131 + * output       - NONE
1132 + * side effects - initialize client free memory
1133 + */
1134 + void
1135 + client_init(void)
1136 + {
1137 +  static struct event event_ping =
1138 +  {
1139 +    .name = "check_pings",
1140 +    .handler = check_pings,
1141 +    .when = 5
1142 +  };
1143 +
1144 +  client_pool = mp_pool_new(sizeof(struct Client), MP_CHUNK_SIZE_CLIENT);
1145 +  connection_pool = mp_pool_new(sizeof(struct Connection), MP_CHUNK_SIZE_CONNECTION);
1146 +  event_add(&event_ping, NULL);
1147 + }

Diff Legend

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