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 3247 by michael, Sun Mar 30 17:54:34 2014 UTC vs.
Revision 4298 by michael, Sun Jul 20 13:51:16 2014 UTC

# Line 27 | Line 27
27   #include "stdinc.h"
28   #include "list.h"
29   #include "client.h"
30 #include "channel_mode.h"
30   #include "event.h"
32 #include "fdlist.h"
31   #include "hash.h"
32   #include "irc_string.h"
33   #include "ircd.h"
36 #include "s_gline.h"
34   #include "numeric.h"
35 < #include "packet.h"
39 < #include "s_auth.h"
35 > #include "auth.h"
36   #include "s_bsd.h"
37   #include "conf.h"
38   #include "log.h"
39 < #include "s_misc.h"
40 < #include "s_serv.h"
39 > #include "misc.h"
40 > #include "server.h"
41   #include "send.h"
42   #include "whowas.h"
43 < #include "s_user.h"
48 < #include "dbuf.h"
43 > #include "user.h"
44   #include "memory.h"
45   #include "mempool.h"
46   #include "hostmask.h"
47   #include "listener.h"
53 #include "irc_res.h"
48   #include "userhost.h"
49   #include "watch.h"
50   #include "rng_mt.h"
51   #include "parse.h"
52  
59 dlink_list listing_client_list = { NULL, NULL, 0 };
60 /* Pointer to beginning of Client list */
61 dlink_list global_client_list = {NULL, NULL, 0};
62 /* unknown/client pointer lists */
63 dlink_list unknown_list = {NULL, NULL, 0};
64 dlink_list local_client_list = {NULL, NULL, 0};
65 dlink_list serv_list = {NULL, NULL, 0};
66 dlink_list global_serv_list = {NULL, NULL, 0};
67 dlink_list oper_list = {NULL, NULL, 0};
53  
54 < static EVH check_pings;
55 <
56 < static mp_pool_t *client_pool  = NULL;
57 < static mp_pool_t *lclient_pool = NULL;
58 <
59 < static dlink_list dead_list  = { NULL, NULL, 0};
60 < static dlink_list abort_list = { NULL, NULL, 0};
54 > dlink_list listing_client_list;
55 > dlink_list unknown_list;
56 > dlink_list local_client_list;
57 > dlink_list local_server_list;
58 > dlink_list global_client_list;
59 > dlink_list global_server_list;
60 > dlink_list oper_list;
61  
62 + 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  
79 static void check_pings_list(dlink_list *);
80 static void check_unknowns_list(void);
81
82
83 /* client_init()
84 *
85 * inputs       - NONE
86 * output       - NONE
87 * side effects - initialize client free memory
88 */
89 void
90 client_init(void)
91 {
92  /* start off the check ping event ..  -- adrian
93   * Every 30 seconds is plenty -- db
94   */
95  client_pool = mp_pool_new(sizeof(struct Client), MP_CHUNK_SIZE_CLIENT);
96  lclient_pool = mp_pool_new(sizeof(struct LocalUser), MP_CHUNK_SIZE_LCLIENT);
97  eventAdd("check_pings", check_pings, NULL, 5);
98 }
66  
67   /*
68   * make_client - create a new Client struct and set it to initial state.
# Line 117 | Line 84 | make_client(struct Client *from)
84   {
85    struct Client *client_p = mp_pool_get(client_pool);
86  
120  memset(client_p, 0, sizeof(*client_p));
121
87    if (!from)
88    {
89      client_p->from                      = client_p; /* 'from' of local client is self! */
90      client_p->localClient               = mp_pool_get(lclient_pool);
126
127    memset(client_p->localClient, 0, sizeof(*client_p->localClient));
128
91      client_p->localClient->since        = CurrentTime;
92      client_p->localClient->lasttime     = CurrentTime;
93      client_p->localClient->firsttime    = CurrentTime;
# Line 163 | Line 125 | free_client(struct Client *client_p)
125    assert(client_p->channel.head == NULL);
126    assert(dlink_list_length(&client_p->channel) == 0);
127    assert(dlink_list_length(&client_p->whowas) == 0);
128 <  assert(!IsServer(client_p) || (IsServer(client_p) && client_p->serv));
128 >  assert(!IsServer(client_p) || client_p->serv);
129  
130    MyFree(client_p->serv);
131    MyFree(client_p->certfp);
# Line 198 | Line 160 | free_client(struct Client *client_p)
160    mp_pool_release(client_p);
161   }
162  
201 /*
202 * check_pings - go through the local client list and check activity
203 * kill off stuff that should die
204 *
205 * inputs       - NOT USED (from event)
206 * output       - next time_t when check_pings() should be called again
207 * side effects -
208 *
209 *
210 * A PING can be sent to clients as necessary.
211 *
212 * Client/Server ping outs are handled.
213 */
214
215 /*
216 * Addon from adrian. We used to call this after nextping seconds,
217 * however I've changed it to run once a second. This is only for
218 * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
219 * run once a second makes life a lot easier - when a new client connects
220 * and they need a ping in 4 seconds, if nextping was set to 20 seconds
221 * we end up waiting 20 seconds. This is stupid. :-)
222 * I will optimise (hah!) check_pings() once I've finished working on
223 * tidying up other network IO evilnesses.
224 *     -- adrian
225 */
226
227 static void
228 check_pings(void *notused)
229 {
230  check_pings_list(&local_client_list);
231  check_pings_list(&serv_list);
232  check_unknowns_list();
233 }
234
163   /* check_pings_list()
164   *
165   * inputs       - pointer to list to check
# Line 241 | Line 169 | check_pings(void *notused)
169   static void
170   check_pings_list(dlink_list *list)
171   {
172 <  char scratch[IRCD_BUFSIZE];
172 >  char buf[IRCD_BUFSIZE] = "";
173    int ping = 0;      /* ping time value from client */
174 <  dlink_node *ptr = NULL, *next_ptr = NULL;
174 >  dlink_node *ptr = NULL, *ptr_next = NULL;
175  
176 <  DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
176 >  DLINK_FOREACH_SAFE(ptr, ptr_next, list->head)
177    {
178      struct Client *client_p = ptr->data;
179  
252    /*
253    ** Note: No need to notify opers here. It's
254    ** already done when "FLAGS_DEADSOCKET" is set.
255    */
180      if (IsDead(client_p))
181 <    {
258 <      /* Ignore it, its been exited already */
259 <      continue;
260 <    }
181 >      continue;  /* Ignore it, its been exited already */
182  
183      if (!IsRegistered(client_p))
184        ping = CONNECTTIMEOUT;
# Line 269 | Line 190 | check_pings_list(dlink_list *list)
190        if (!IsPingSent(client_p))
191        {
192          /*
193 <         * if we havent PINGed the connection and we havent
193 >         * If we haven't PINGed the connection and we haven't
194           * heard from it in a while, PING it to make sure
195           * it is still alive.
196           */
# Line 297 | Line 218 | check_pings_list(dlink_list *list)
218                   get_client_name(client_p, HIDE_IP));
219            }
220  
221 <          snprintf(scratch, sizeof(scratch), "Ping timeout: %d seconds",
221 >          snprintf(buf, sizeof(buf), "Ping timeout: %d seconds",
222                     (int)(CurrentTime - client_p->localClient->lasttime));
223 <          exit_client(client_p, scratch);
223 >          exit_client(client_p, buf);
224          }
225        }
226      }
# Line 330 | Line 251 | check_unknowns_list(void)
251    }
252   }
253  
254 + /*
255 + * check_pings - go through the local client list and check activity
256 + * kill off stuff that should die
257 + *
258 + * inputs       - NOT USED (from event)
259 + * output       - next time_t when check_pings() should be called again
260 + * side effects -
261 + *
262 + *
263 + * A PING can be sent to clients as necessary.
264 + *
265 + * Client/Server ping outs are handled.
266 + */
267 +
268 + /*
269 + * Addon from adrian. We used to call this after nextping seconds,
270 + * however I've changed it to run once a second. This is only for
271 + * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
272 + * run once a second makes life a lot easier - when a new client connects
273 + * and they need a ping in 4 seconds, if nextping was set to 20 seconds
274 + * we end up waiting 20 seconds. This is stupid. :-)
275 + * I will optimise (hah!) check_pings() once I've finished working on
276 + * tidying up other network IO evilnesses.
277 + *     -- adrian
278 + */
279 +
280 + static void
281 + check_pings(void *notused)
282 + {
283 +  check_pings_list(&local_client_list);
284 +  check_pings_list(&local_server_list);
285 +  check_unknowns_list();
286 + }
287 +
288   /* check_conf_klines()
289   *
290   * inputs       - NONE
# Line 340 | Line 295 | check_unknowns_list(void)
295   void
296   check_conf_klines(void)
297   {
343  struct Client *client_p = NULL;       /* current local client_p being examined */
298    struct MaskItem *conf = NULL;
299 <  dlink_node *ptr, *next_ptr;
299 >  dlink_node *ptr = NULL, *ptr_next = NULL;
300  
301 <  DLINK_FOREACH_SAFE(ptr, next_ptr, local_client_list.head)
301 >  DLINK_FOREACH_SAFE(ptr, ptr_next, local_client_list.head)
302    {
303 <    client_p = ptr->data;
303 >    struct Client *client_p = ptr->data;
304  
305      /* If a client is already being exited
306       */
307      if (IsDead(client_p) || !IsClient(client_p))
308        continue;
309  
310 <    if ((conf = find_dline_conf(&client_p->localClient->ip,
311 <                                  client_p->localClient->aftype)))
310 >    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
311 >                                     client_p->localClient->aftype, NULL, NULL, 1)))
312      {
359      if (conf->type == CONF_EXEMPT)
360        continue;
361
313        conf_try_ban(client_p, conf);
314        continue; /* and go examine next fd/client_p */
315      }
# Line 392 | Line 343 | check_conf_klines(void)
343    }
344  
345    /* also check the unknowns list for new dlines */
346 <  DLINK_FOREACH_SAFE(ptr, next_ptr, unknown_list.head)
346 >  DLINK_FOREACH_SAFE(ptr, ptr_next, unknown_list.head)
347    {
348 <    client_p = ptr->data;
348 >    struct Client *client_p = ptr->data;
349  
350 <    if ((conf = find_dline_conf(&client_p->localClient->ip,
351 <                                 client_p->localClient->aftype)))
350 >    if ((conf = find_conf_by_address(NULL, &client_p->localClient->ip, CONF_DLINE,
351 >                                     client_p->localClient->aftype, NULL, NULL, 1)))
352      {
353 <      if (conf->type == CONF_EXEMPT)
354 <        continue;
404 <
405 <      exit_client(client_p, "D-lined");
353 >      conf_try_ban(client_p, conf);
354 >      continue; /* and go examine next fd/client_p */
355      }
356    }
357   }
# Line 439 | Line 388 | conf_try_ban(struct Client *client_p, st
388        type_string = kline_string;
389        break;
390      case CONF_DLINE:
391 +      if (find_conf_by_address(NULL, &client_p->localClient->ip, CONF_EXEMPT,
392 +                               client_p->localClient->aftype, NULL, NULL, 1))
393 +        return;
394        type_string = dline_string;
395        break;
396      case CONF_GLINE:
# Line 558 | Line 510 | find_chasing(struct Client *source_p, co
510   *        But, this can be used to any client structure.
511   *
512   * NOTE 1:
513 < *        Watch out the allocation of "nbuf", if either source_p->name
513 > *        Watch out the allocation of "buf", if either source_p->name
514   *        or source_p->sockhost gets changed into pointers instead of
515   *        directly allocated within the structure...
516   *
517   * NOTE 2:
518   *        Function return either a pointer to the structure (source_p) or
519 < *        to internal buffer (nbuf). *NEVER* use the returned pointer
519 > *        to internal buffer (buf). *NEVER* use the returned pointer
520   *        to modify what it points!!!
521   */
522   const char *
523   get_client_name(const struct Client *client_p, enum addr_mask_type type)
524   {
525 <  static char nbuf[HOSTLEN * 2 + USERLEN + 5];
525 >  static char buf[HOSTLEN * 2 + USERLEN + 5];
526  
527    assert(client_p);
528  
# Line 586 | Line 538 | get_client_name(const struct Client *cli
538    }
539  
540    if (ConfigFileEntry.hide_spoof_ips)
541 <    if (type == SHOW_IP && IsIPSpoof(client_p))
541 >    if (IsIPSpoof(client_p) && type == SHOW_IP)
542        type = MASK_IP;
543  
544    /* And finally, let's get the host information, ip or name */
545    switch (type)
546    {
547      case SHOW_IP:
548 <      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
548 >      snprintf(buf, sizeof(buf), "%s[%s@%s]",
549                 client_p->name,
550                 client_p->username, client_p->sockhost);
551        break;
552      case MASK_IP:
553        if (client_p->localClient->aftype == AF_INET)
554 <        snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
554 >        snprintf(buf, sizeof(buf), "%s[%s@255.255.255.255]",
555                   client_p->name, client_p->username);
556        else
557 <        snprintf(nbuf, sizeof(nbuf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
557 >        snprintf(buf, sizeof(buf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
558                   client_p->name, client_p->username);
559        break;
560      default:
561 <      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
561 >      snprintf(buf, sizeof(buf), "%s[%s@%s]",
562                 client_p->name,
563                 client_p->username, client_p->host);
564    }
565  
566 <  return nbuf;
566 >  return buf;
567   }
568  
569   void
# Line 634 | Line 586 | free_exited_clients(void)
586   * The only messages generated are QUITs on channels.
587   */
588   static void
589 < exit_one_client(struct Client *source_p, const char *quitmsg)
589 > exit_one_client(struct Client *source_p, const char *comment)
590   {
591    dlink_node *ptr = NULL, *ptr_next = NULL;
592  
593    assert(!IsMe(source_p));
594 +  assert(source_p != &me);
595  
596    if (IsClient(source_p))
597    {
598      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->client_list);
599 +    dlinkDelete(&source_p->node, &global_client_list);
600  
601      /*
602       * If a person is on a channel, send a QUIT notice
# Line 652 | Line 606 | exit_one_client(struct Client *source_p,
606       */
607      sendto_common_channels_local(source_p, 0, 0, ":%s!%s@%s QUIT :%s",
608                                   source_p->name, source_p->username,
609 <                                 source_p->host, quitmsg);
609 >                                 source_p->host, comment);
610      DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->channel.head)
611        remove_user_from_channel(ptr->data);
612  
# Line 673 | Line 627 | exit_one_client(struct Client *source_p,
627    else if (IsServer(source_p))
628    {
629      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
630 +    dlinkDelete(&source_p->node, &global_client_list);
631  
632 <    if ((ptr = dlinkFindDelete(&global_serv_list, source_p)))
632 >    if ((ptr = dlinkFindDelete(&global_server_list, source_p)))
633        free_dlink_node(ptr);
634    }
635  
# Line 687 | Line 642 | exit_one_client(struct Client *source_p,
642    if (IsUserHostIp(source_p))
643      delete_user_host(source_p->username, source_p->host, !MyConnect(source_p));
644  
690  /* remove from global client list
691   * NOTE: source_p->node.next cannot be NULL if the client is added
692   *       to global_client_list (there is always &me at its end)
693   */
694  if (source_p->node.next) /* XXX: not needed? */
695    dlinkDelete(&source_p->node, &global_client_list);
696
645    update_client_exit_stats(source_p);
646  
647    /* Check to see if the client isn't already on the dead list */
# Line 711 | Line 659 | exit_one_client(struct Client *source_p,
659   * actually removing things off llists.   tweaked from +CSr31  -orabidoo
660   */
661   static void
662 < recurse_remove_clients(struct Client *source_p, const char *quitmsg)
662 > recurse_remove_clients(struct Client *source_p, const char *comment)
663   {
664    dlink_node *ptr = NULL, *ptr_next = NULL;
665  
666    DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->client_list.head)
667 <    exit_one_client(ptr->data, quitmsg);
667 >    exit_one_client(ptr->data, comment);
668  
669    DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->server_list.head)
670    {
671 <    recurse_remove_clients(ptr->data, quitmsg);
672 <    exit_one_client(ptr->data, quitmsg);
671 >    recurse_remove_clients(ptr->data, comment);
672 >    exit_one_client(ptr->data, comment);
673    }
674   }
675  
# Line 747 | Line 695 | exit_client(struct Client *source_p, con
695   {
696    dlink_node *m = NULL;
697  
698 +  assert(!IsMe(source_p));
699 +  assert(source_p != &me);
700 +
701    if (MyConnect(source_p))
702    {
703      /* DO NOT REMOVE. exit_client can be called twice after a failed
# Line 789 | Line 740 | exit_client(struct Client *source_p, con
740        dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
741  
742        if (source_p->localClient->list_task)
743 <        free_list_task(source_p->localClient->list_task, source_p);
743 >        free_list_task(source_p);
744  
745        watch_del_watch_list(source_p);
746        sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE,
# Line 809 | Line 760 | exit_client(struct Client *source_p, con
760        assert(Count.myserver > 0);
761        --Count.myserver;
762  
763 <      assert(dlinkFind(&serv_list, source_p));
764 <      dlinkDelete(&source_p->localClient->lclient_node, &serv_list);
763 >      assert(dlinkFind(&local_server_list, source_p));
764 >      dlinkDelete(&source_p->localClient->lclient_node, &local_server_list);
765      }
766  
767      if (!IsDead(source_p))
# Line 829 | Line 780 | exit_client(struct Client *source_p, con
780                   source_p->host, comment);
781      }
782  
832    /*
833    ** Currently only server connections can have
834    ** depending remote clients here, but it does no
835    ** harm to check for all local clients. In
836    ** future some other clients than servers might
837    ** have remotes too...
838    **
839    ** Close the Client connection first and mark it
840    ** so that no messages are attempted to send to it.
841    ** Remember it makes source_p->from == NULL.
842    */
783      close_connection(source_p);
784    }
785    else if (IsClient(source_p) && HasFlag(source_p->servptr, FLAGS_EOB))
# Line 865 | Line 805 | exit_client(struct Client *source_p, con
805        snprintf(splitstr, sizeof(splitstr), "%s %s",
806                 source_p->servptr->name, source_p->name);
807  
808 <    /* Send SQUIT for source_p in every direction. source_p is already off of serv_list here */
808 >    /* Send SQUIT for source_p in every direction. source_p is already off of local_server_list here */
809      if (!HasFlag(source_p, FLAGS_SQUIT))
810        sendto_server(NULL, NOCAPS, NOCAPS, "SQUIT %s :%s", source_p->id, comment);
811  
# Line 892 | Line 832 | exit_client(struct Client *source_p, con
832    /* The client *better* be off all of the lists */
833    assert(dlinkFind(&unknown_list, source_p) == NULL);
834    assert(dlinkFind(&local_client_list, source_p) == NULL);
835 <  assert(dlinkFind(&serv_list, source_p) == NULL);
835 >  assert(dlinkFind(&local_server_list, source_p) == NULL);
836    assert(dlinkFind(&oper_list, source_p) == NULL);
837  
838    exit_one_client(source_p, comment);
# Line 1136 | Line 1076 | idle_time_get(const struct Client *sourc
1076  
1077    return idle;
1078   }
1079 +
1080 + /* client_init()
1081 + *
1082 + * inputs       - NONE
1083 + * output       - NONE
1084 + * side effects - initialize client free memory
1085 + */
1086 + void
1087 + client_init(void)
1088 + {
1089 +  static struct event event_ping =
1090 +  {
1091 +    .name = "check_pings",
1092 +    .handler = check_pings,
1093 +    .when = 5
1094 +  };
1095 +
1096 +  client_pool = mp_pool_new(sizeof(struct Client), MP_CHUNK_SIZE_CLIENT);
1097 +  lclient_pool = mp_pool_new(sizeof(struct LocalUser), MP_CHUNK_SIZE_LCLIENT);
1098 +  event_add(&event_ping, NULL);
1099 + }

Diff Legend

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