00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdinc.h"
00026 #include "tools.h"
00027 #include "s_conf.h"
00028 #include "channel.h"
00029 #include "channel_mode.h"
00030 #include "client.h"
00031 #include "common.h"
00032 #include "handlers.h"
00033 #include "list.h"
00034 #include "modules.h"
00035 #include "hash.h"
00036 #include "resv.h"
00037 #include "userhost.h"
00038 #include "irc_string.h"
00039 #include "ircd.h"
00040 #include "numeric.h"
00041 #include "send.h"
00042 #include "memory.h"
00043 #include "dbuf.h"
00044 #include "s_user.h"
00045
00046
00047 static BlockHeap *userhost_heap = NULL;
00048 static BlockHeap *namehost_heap = NULL;
00049 static struct UserHost *find_or_add_userhost(const char *);
00050
00051 static unsigned int ircd_random_key = 0;
00052
00053
00054
00055
00056
00057
00058 static struct Client *idTable[HASHSIZE];
00059 static struct Client *clientTable[HASHSIZE];
00060 static struct Channel *channelTable[HASHSIZE];
00061 static struct UserHost *userhostTable[HASHSIZE];
00062 static struct ResvChannel *resvchannelTable[HASHSIZE];
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 void
00073 init_hash(void)
00074 {
00075 unsigned int i;
00076
00077
00078
00079
00080
00081 userhost_heap = BlockHeapCreate("userhost", sizeof(struct UserHost), CLIENT_HEAP_SIZE);
00082 namehost_heap = BlockHeapCreate("namehost", sizeof(struct NameHost), CLIENT_HEAP_SIZE);
00083
00084 ircd_random_key = rand() % 256;
00085
00086
00087 for (i = 0; i < HASHSIZE; ++i)
00088 {
00089 idTable[i] = NULL;
00090 clientTable[i] = NULL;
00091 channelTable[i] = NULL;
00092 userhostTable[i] = NULL;
00093 resvchannelTable[i] = NULL;
00094 }
00095 }
00096
00097
00098
00099
00100
00101
00102
00103
00104 unsigned int
00105 strhash(const char *name)
00106 {
00107 const unsigned char *p = (const unsigned char *)name;
00108 unsigned int hval = FNV1_32_INIT;
00109
00110 if (*p == '\0')
00111 return 0;
00112 for (; *p != '\0'; ++p)
00113 {
00114 hval += (hval << 1) + (hval << 4) + (hval << 7) +
00115 (hval << 8) + (hval << 24);
00116 hval ^= (ToLower(*p) ^ ircd_random_key);
00117 }
00118
00119 return (hval >> FNV1_32_BITS) ^ (hval & ((1 << FNV1_32_BITS) -1));
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 void
00142 hash_add_client(struct Client *client_p)
00143 {
00144 unsigned int hashv = strhash(client_p->name);
00145
00146 client_p->hnext = clientTable[hashv];
00147 clientTable[hashv] = client_p;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void
00161 hash_add_channel(struct Channel *chptr)
00162 {
00163 unsigned int hashv = strhash(chptr->chname);
00164
00165 chptr->hnextch = channelTable[hashv];
00166 channelTable[hashv] = chptr;
00167 }
00168
00169 void
00170 hash_add_resv(struct ResvChannel *chptr)
00171 {
00172 unsigned int hashv = strhash(chptr->name);
00173
00174 chptr->hnext = resvchannelTable[hashv];
00175 resvchannelTable[hashv] = chptr;
00176 }
00177
00178 void
00179 hash_add_userhost(struct UserHost *userhost)
00180 {
00181 unsigned int hashv = strhash(userhost->host);
00182
00183 userhost->next = userhostTable[hashv];
00184 userhostTable[hashv] = userhost;
00185 }
00186
00187 void
00188 hash_add_id(struct Client *client_p)
00189 {
00190 unsigned int hashv = strhash(client_p->id);
00191
00192 client_p->idhnext = idTable[hashv];
00193 idTable[hashv] = client_p;
00194 }
00195
00196
00197
00198
00199
00200
00201
00202 void
00203 hash_del_id(struct Client *client_p)
00204 {
00205 unsigned int hashv = strhash(client_p->id);
00206 struct Client *tmp = idTable[hashv];
00207
00208 if (tmp != NULL)
00209 {
00210 if (tmp == client_p)
00211 {
00212 idTable[hashv] = client_p->idhnext;
00213 client_p->idhnext = client_p;
00214 }
00215 else
00216 {
00217 while (tmp->idhnext != client_p)
00218 {
00219 if ((tmp = tmp->idhnext) == NULL)
00220 return;
00221 }
00222
00223 tmp->idhnext = tmp->idhnext->idhnext;
00224 client_p->idhnext = client_p;
00225 }
00226 }
00227 }
00228
00229
00230
00231
00232
00233
00234
00235 void
00236 hash_del_client(struct Client *client_p)
00237 {
00238 unsigned int hashv = strhash(client_p->name);
00239 struct Client *tmp = clientTable[hashv];
00240
00241 if (tmp != NULL)
00242 {
00243 if (tmp == client_p)
00244 {
00245 clientTable[hashv] = client_p->hnext;
00246 client_p->hnext = client_p;
00247 }
00248 else
00249 {
00250 while (tmp->hnext != client_p)
00251 {
00252 if ((tmp = tmp->hnext) == NULL)
00253 return;
00254 }
00255
00256 tmp->hnext = tmp->hnext->hnext;
00257 client_p->hnext = client_p;
00258 }
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268 void
00269 hash_del_userhost(struct UserHost *userhost)
00270 {
00271 unsigned int hashv = strhash(userhost->host);
00272 struct UserHost *tmp = userhostTable[hashv];
00273
00274 if (tmp != NULL)
00275 {
00276 if (tmp == userhost)
00277 {
00278 userhostTable[hashv] = userhost->next;
00279 userhost->next = userhost;
00280 }
00281 else
00282 {
00283 while (tmp->next != userhost)
00284 {
00285 if ((tmp = tmp->next) == NULL)
00286 return;
00287 }
00288
00289 tmp->next = tmp->next->next;
00290 userhost->next = userhost;
00291 }
00292 }
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302 void
00303 hash_del_channel(struct Channel *chptr)
00304 {
00305 unsigned int hashv = strhash(chptr->chname);
00306 struct Channel *tmp = channelTable[hashv];
00307
00308 if (tmp != NULL)
00309 {
00310 if (tmp == chptr)
00311 {
00312 channelTable[hashv] = chptr->hnextch;
00313 chptr->hnextch = chptr;
00314 }
00315 else
00316 {
00317 while (tmp->hnextch != chptr)
00318 {
00319 if ((tmp = tmp->hnextch) == NULL)
00320 return;
00321 }
00322
00323 tmp->hnextch = tmp->hnextch->hnextch;
00324 chptr->hnextch = chptr;
00325 }
00326 }
00327 }
00328
00329 void
00330 hash_del_resv(struct ResvChannel *chptr)
00331 {
00332 unsigned int hashv = strhash(chptr->name);
00333 struct ResvChannel *tmp = resvchannelTable[hashv];
00334
00335 if (tmp != NULL)
00336 {
00337 if (tmp == chptr)
00338 {
00339 resvchannelTable[hashv] = chptr->hnext;
00340 chptr->hnext = chptr;
00341 }
00342 else
00343 {
00344 while (tmp->hnext != chptr)
00345 {
00346 if ((tmp = tmp->hnext) == NULL)
00347 return;
00348 }
00349
00350 tmp->hnext = tmp->hnext->hnext;
00351 chptr->hnext = chptr;
00352 }
00353 }
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364 struct Client *
00365 find_client(const char *name)
00366 {
00367 unsigned int hashv = strhash(name);
00368 struct Client *client_p;
00369
00370 if ((client_p = clientTable[hashv]) != NULL)
00371 {
00372 if (irccmp(name, client_p->name))
00373 {
00374 struct Client *prev;
00375
00376 while (prev = client_p, (client_p = client_p->hnext) != NULL)
00377 {
00378 if (!irccmp(name, client_p->name))
00379 {
00380 prev->hnext = client_p->hnext;
00381 client_p->hnext = clientTable[hashv];
00382 clientTable[hashv] = client_p;
00383 break;
00384 }
00385 }
00386 }
00387 }
00388
00389 return client_p;
00390 }
00391
00392 struct Client *
00393 hash_find_id(const char *name)
00394 {
00395 unsigned int hashv = strhash(name);
00396 struct Client *client_p;
00397
00398 if ((client_p = idTable[hashv]) != NULL)
00399 {
00400 if (irccmp(name, client_p->id))
00401 {
00402 struct Client *prev;
00403
00404 while (prev = client_p, (client_p = client_p->idhnext) != NULL)
00405 {
00406 if (!irccmp(name, client_p->id))
00407 {
00408 prev->idhnext = client_p->idhnext;
00409 client_p->idhnext = idTable[hashv];
00410 idTable[hashv] = client_p;
00411 break;
00412 }
00413 }
00414 }
00415 }
00416
00417 return client_p;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430 static struct Client *
00431 hash_find_masked_server(const char *name)
00432 {
00433 char buf[HOSTLEN + 1];
00434 char *p = buf;
00435 char *s = NULL;
00436 struct Client *server = NULL;
00437
00438 if (*name == '*' || *name == '.')
00439 return NULL;
00440
00441
00442
00443
00444 strlcpy(buf, name, sizeof(buf));
00445
00446 while ((s = strchr(p, '.')) != NULL)
00447 {
00448 *--s = '*';
00449
00450
00451
00452
00453 if ((server = find_client(s)) != NULL)
00454 return server;
00455 p = s + 2;
00456 }
00457
00458 return NULL;
00459 }
00460
00461 struct Client *
00462 find_server(const char *name)
00463 {
00464 unsigned int hashv = strhash(name);
00465 struct Client *client_p = NULL;
00466
00467 if (IsDigit(*name) && strlen(name) == IRC_MAXSID)
00468 client_p = hash_find_id(name);
00469
00470 if ((client_p == NULL) && (client_p = clientTable[hashv]) != NULL)
00471 {
00472 if ((!IsServer(client_p) && !IsMe(client_p)) ||
00473 irccmp(name, client_p->name))
00474 {
00475 struct Client *prev;
00476
00477 while (prev = client_p, (client_p = client_p->hnext) != NULL)
00478 {
00479 if ((IsServer(client_p) || IsMe(client_p)) &&
00480 !irccmp(name, client_p->name))
00481 {
00482 prev->hnext = client_p->hnext;
00483 client_p->hnext = clientTable[hashv];
00484 clientTable[hashv] = client_p;
00485 break;
00486 }
00487 }
00488 }
00489 }
00490
00491 return (client_p != NULL) ? client_p : hash_find_masked_server(name);
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502 struct Channel *
00503 hash_find_channel(const char *name)
00504 {
00505 unsigned int hashv = strhash(name);
00506 struct Channel *chptr = NULL;
00507
00508 if ((chptr = channelTable[hashv]) != NULL)
00509 {
00510 if (irccmp(name, chptr->chname))
00511 {
00512 struct Channel *prev;
00513
00514 while (prev = chptr, (chptr = chptr->hnextch) != NULL)
00515 {
00516 if (!irccmp(name, chptr->chname))
00517 {
00518 prev->hnextch = chptr->hnextch;
00519 chptr->hnextch = channelTable[hashv];
00520 channelTable[hashv] = chptr;
00521 break;
00522 }
00523 }
00524 }
00525 }
00526
00527 return chptr;
00528 }
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540 void *
00541 hash_get_bucket(int type, unsigned int hashv)
00542 {
00543 assert(hashv < HASHSIZE);
00544 if (hashv >= HASHSIZE)
00545 return NULL;
00546
00547 switch (type)
00548 {
00549 case HASH_TYPE_ID:
00550 return idTable[hashv];
00551 break;
00552 case HASH_TYPE_CHANNEL:
00553 return channelTable[hashv];
00554 break;
00555 case HASH_TYPE_CLIENT:
00556 return clientTable[hashv];
00557 break;
00558 case HASH_TYPE_USERHOST:
00559 return userhostTable[hashv];
00560 break;
00561 case HASH_TYPE_RESERVED:
00562 return resvchannelTable[hashv];
00563 break;
00564 default:
00565 assert(0);
00566 }
00567
00568 return NULL;
00569 }
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 struct ResvChannel *
00580 hash_find_resv(const char *name)
00581 {
00582 unsigned int hashv = strhash(name);
00583 struct ResvChannel *chptr;
00584
00585 if ((chptr = resvchannelTable[hashv]) != NULL)
00586 {
00587 if (irccmp(name, chptr->name))
00588 {
00589 struct ResvChannel *prev;
00590
00591 while (prev = chptr, (chptr = chptr->hnext) != NULL)
00592 {
00593 if (!irccmp(name, chptr->name))
00594 {
00595 prev->hnext = chptr->hnext;
00596 chptr->hnext = resvchannelTable[hashv];
00597 resvchannelTable[hashv] = chptr;
00598 break;
00599 }
00600 }
00601 }
00602 }
00603
00604 return chptr;
00605 }
00606
00607 struct UserHost *
00608 hash_find_userhost(const char *host)
00609 {
00610 unsigned int hashv = strhash(host);
00611 struct UserHost *userhost;
00612
00613 if ((userhost = userhostTable[hashv]))
00614 {
00615 if (irccmp(host, userhost->host))
00616 {
00617 struct UserHost *prev;
00618
00619 while (prev = userhost, (userhost = userhost->next) != NULL)
00620 {
00621 if (!irccmp(host, userhost->host))
00622 {
00623 prev->next = userhost->next;
00624 userhost->next = userhostTable[hashv];
00625 userhostTable[hashv] = userhost;
00626 break;
00627 }
00628 }
00629 }
00630 }
00631
00632 return userhost;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 void
00647 count_user_host(const char *user, const char *host, int *global_p,
00648 int *local_p, int *icount_p)
00649 {
00650 dlink_node *ptr;
00651 struct UserHost *found_userhost;
00652 struct NameHost *nameh;
00653
00654 if ((found_userhost = hash_find_userhost(host)) == NULL)
00655 return;
00656
00657 DLINK_FOREACH(ptr, found_userhost->list.head)
00658 {
00659 nameh = ptr->data;
00660
00661 if (!irccmp(user, nameh->name))
00662 {
00663 if (global_p != NULL)
00664 *global_p = nameh->gcount;
00665 if (local_p != NULL)
00666 *local_p = nameh->lcount;
00667 if (icount_p != NULL)
00668 *icount_p = nameh->icount;
00669 return;
00670 }
00671 }
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682 void
00683 add_user_host(const char *user, const char *host, int global)
00684 {
00685 dlink_node *ptr;
00686 struct UserHost *found_userhost;
00687 struct NameHost *nameh;
00688 int hasident = 1;
00689
00690 if (*user == '~')
00691 {
00692 hasident = 0;
00693 ++user;
00694 }
00695
00696 if ((found_userhost = find_or_add_userhost(host)) == NULL)
00697 return;
00698
00699 DLINK_FOREACH(ptr, found_userhost->list.head)
00700 {
00701 nameh = ptr->data;
00702
00703 if (!irccmp(user, nameh->name))
00704 {
00705 nameh->gcount++;
00706 if (!global)
00707 {
00708 if (hasident)
00709 nameh->icount++;
00710 nameh->lcount++;
00711 }
00712 return;
00713 }
00714 }
00715
00716 nameh = BlockHeapAlloc(namehost_heap);
00717 strlcpy(nameh->name, user, sizeof(nameh->name));
00718
00719 nameh->gcount = 1;
00720 if (!global)
00721 {
00722 if (hasident)
00723 nameh->icount = 1;
00724 nameh->lcount = 1;
00725 }
00726
00727 dlinkAdd(nameh, &nameh->node, &found_userhost->list);
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 void
00739 delete_user_host(const char *user, const char *host, int global)
00740 {
00741 dlink_node *ptr = NULL, *next_ptr = NULL;
00742 struct UserHost *found_userhost;
00743 struct NameHost *nameh;
00744 int hasident = 1;
00745
00746 if (*user == '~')
00747 {
00748 hasident = 0;
00749 ++user;
00750 }
00751
00752 if ((found_userhost = hash_find_userhost(host)) == NULL)
00753 return;
00754
00755 DLINK_FOREACH_SAFE(ptr, next_ptr, found_userhost->list.head)
00756 {
00757 nameh = ptr->data;
00758
00759 if (!irccmp(user, nameh->name))
00760 {
00761 if (nameh->gcount > 0)
00762 nameh->gcount--;
00763 if (!global)
00764 {
00765 if (nameh->lcount > 0)
00766 nameh->lcount--;
00767 if (hasident && nameh->icount > 0)
00768 nameh->icount--;
00769 }
00770
00771 if (nameh->gcount == 0 && nameh->lcount == 0)
00772 {
00773 dlinkDelete(&nameh->node, &found_userhost->list);
00774 BlockHeapFree(namehost_heap, nameh);
00775 }
00776
00777 if (dlink_list_length(&found_userhost->list) == 0)
00778 {
00779 hash_del_userhost(found_userhost);
00780 BlockHeapFree(userhost_heap, found_userhost);
00781 }
00782
00783 return;
00784 }
00785 }
00786 }
00787
00788
00789
00790
00791
00792
00793
00794 static struct UserHost *
00795 find_or_add_userhost(const char *host)
00796 {
00797 struct UserHost *userhost;
00798
00799 if ((userhost = hash_find_userhost(host)) != NULL)
00800 return userhost;
00801
00802 userhost = BlockHeapAlloc(userhost_heap);
00803 strlcpy(userhost->host, host, sizeof(userhost->host));
00804 hash_add_userhost(userhost);
00805
00806 return userhost;
00807 }
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 static int
00832 exceeding_sendq(struct Client *to)
00833 {
00834 if (dbuf_length(&to->localClient->buf_sendq) > (get_sendq(to) / 2))
00835 return 1;
00836 else
00837 return 0;
00838 }
00839
00840 void
00841 free_list_task(struct ListTask *lt, struct Client *source_p)
00842 {
00843 dlink_node *dl, *dln;
00844
00845 if ((dl = dlinkFindDelete(&listing_client_list, source_p)) != NULL)
00846 free_dlink_node(dl);
00847
00848 DLINK_FOREACH_SAFE(dl, dln, lt->show_mask.head)
00849 {
00850 MyFree(dl->data);
00851 free_dlink_node(dl);
00852 }
00853
00854 DLINK_FOREACH_SAFE(dl, dln, lt->hide_mask.head)
00855 {
00856 MyFree(dl->data);
00857 free_dlink_node(dl);
00858 }
00859
00860 MyFree(lt);
00861
00862 if (MyConnect(source_p))
00863 source_p->localClient->list_task = NULL;
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874 static int
00875 list_allow_channel(const char *chname, struct ListTask *lt)
00876 {
00877 dlink_node *dl = NULL;
00878
00879 DLINK_FOREACH(dl, lt->show_mask.head)
00880 if (!match_chan(dl->data, chname))
00881 return 0;
00882
00883 DLINK_FOREACH(dl, lt->hide_mask.head)
00884 if (match_chan(dl->data, chname))
00885 return 0;
00886
00887 return 1;
00888 }
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898 static void
00899 list_one_channel(struct Client *source_p, struct Channel *chptr,
00900 struct ListTask *list_task, int remote_request)
00901 {
00902 if ((remote_request && chptr->chname[0] == '&') ||
00903 (SecretChannel(chptr) && !IsMember(source_p, chptr)))
00904 return;
00905 if ((unsigned int)dlink_list_length(&chptr->members) < list_task->users_min ||
00906 (unsigned int)dlink_list_length(&chptr->members) > list_task->users_max ||
00907 (chptr->channelts != 0 &&
00908 ((unsigned int)chptr->channelts < list_task->created_min ||
00909 (unsigned int)chptr->channelts > list_task->created_max)) ||
00910 (unsigned int)chptr->topic_time < list_task->topicts_min ||
00911 (chptr->topic_time ? (unsigned int)chptr->topic_time : UINT_MAX) >
00912 list_task->topicts_max)
00913 return;
00914
00915 if (!list_allow_channel(chptr->chname, list_task))
00916 return;
00917 sendto_one(source_p, form_str(RPL_LIST), me.name, source_p->name,
00918 chptr->chname, dlink_list_length(&chptr->members),
00919 chptr->topic == NULL ? "" : chptr->topic);
00920 }
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 void
00937 safe_list_channels(struct Client *source_p, struct ListTask *list_task,
00938 int only_unmasked_channels, int remote_request)
00939 {
00940 struct Channel *chptr = NULL;
00941
00942 if (!only_unmasked_channels)
00943 {
00944 int i;
00945
00946 for (i = list_task->hash_index; i < HASHSIZE; i++)
00947 {
00948 if (exceeding_sendq(source_p->from))
00949 {
00950 list_task->hash_index = i;
00951 return;
00952 }
00953
00954 for (chptr = channelTable[i]; chptr; chptr = chptr->hnextch)
00955 list_one_channel(source_p, chptr, list_task, remote_request);
00956 }
00957 }
00958 else
00959 {
00960 dlink_node *dl;
00961
00962 DLINK_FOREACH(dl, list_task->show_mask.head)
00963 if ((chptr = hash_find_channel(dl->data)) != NULL)
00964 list_one_channel(source_p, chptr, list_task, remote_request);
00965 }
00966
00967 free_list_task(list_task, source_p);
00968 sendto_one(source_p, form_str(RPL_LISTEND),
00969 me.name, source_p->name);
00970 }