- Timestamp:
- 05/31/07 15:15:23 (5 years ago)
- Location:
- trunk/ithildin/modules/ircd
- Files:
-
- 20 edited
- 4 copied
-
addons/cmode_operonly.c (modified) (1 diff)
-
addons/cmode_private.c (modified) (1 diff)
-
addons/hostcrypt.c (modified) (1 diff)
-
addons/umode_helper.c (modified) (1 diff)
-
chanmode.c (copied) (copied from trunk/ithildin/modules/ircd/channel.c) (3 diffs)
-
chanmode.h (copied) (copied from trunk/ithildin/modules/ircd/channel.h) (4 diffs)
-
channel.c (modified) (2 diffs)
-
channel.h (modified) (3 diffs)
-
client.c (modified) (2 diffs)
-
client.h (modified) (2 diffs)
-
command.c (modified) (2 diffs)
-
commands/names.c (modified) (1 diff)
-
commands/notice.c (modified) (1 diff)
-
commands/trace.c (modified) (2 diffs)
-
commands/userhost.c (modified) (1 diff)
-
commands/who.c (modified) (8 diffs)
-
commands/whois.c (modified) (1 diff)
-
commands/xinfo.c (modified) (5 diffs)
-
ircd.c (modified) (8 diffs)
-
ircd.h (modified) (8 diffs)
-
send.c (modified) (2 diffs)
-
send.h (modified) (2 diffs)
-
usermode.c (copied) (copied from trunk/ithildin/modules/ircd/client.c) (5 diffs)
-
usermode.h (copied) (copied from trunk/ithildin/modules/ircd/client.h) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/ithildin/modules/ircd/addons/cmode_operonly.c
r613 r803 52 52 struct channel_check_args *ccap = (struct channel_check_args *)data; 53 53 54 if (chanmode_isset(ccap->chan, chanmode_operonly) && !OPER(ccap->cli)) { 54 if (chanmode_isset(ccap->chan, chanmode_operonly) && 55 !CLIENT_OPERATOR(ccap->cli)) { 55 56 /* send them the error and return. */ 56 57 sendto_one(ccap->cli, RPL_FMT(ccap->cli, ERR_NOPRIVILEGES)); -
trunk/ithildin/modules/ircd/addons/cmode_private.c
r787 r803 55 55 return (void *)HOOK_COND_OK; 56 56 else if (chanmode_isset(ccap->chan, chanmode_private)) { 57 if (OPER(ccap->cli) && BPRIV(ccap->cli, core.privs.see_hidden_chan)) 57 if (CLIENT_OPERATOR(ccap->cli) && 58 BPRIV(ccap->cli, ircd.privileges.priv_shc)) 58 59 return (void *)HOOK_COND_ALWAYSOK; /* okay, but sketchy. */ 59 60 else -
trunk/ithildin/modules/ircd/addons/hostcrypt.c
r787 r803 258 258 static void hostcrypt_encrypt(client_t *cli) { 259 259 260 if ( OPER(cli) && hostcrypt.operhost != NULL)260 if (CLIENT_OPERATOR(cli) && hostcrypt.operhost != NULL) 261 261 strlcpy(cli->host, hostcrypt.operhost, HOSTLEN + 1); 262 262 else -
trunk/ithildin/modules/ircd/addons/umode_helper.c
r579 r803 75 75 USERMODE_FUNC(helper_usermode_handler) { 76 76 77 if (set && !CLIENT_MASTER(cli) && ! OPER(cli) &&77 if (set && !CLIENT_MASTER(cli) && !CLIENT_OPERATOR(cli) && 78 78 (by != NULL && !CLIENT_MASTER(by))) 79 79 return 0; -
trunk/ithildin/modules/ircd/chanmode.c
r801 r803 1 1 /* 2 * chan nel.c: channel structure management code2 * chanmode.c: channel mode management code 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * 7 * This file provides the basic functions necessary to create/destroy/manage8 * channel structures, and lists of people with channels. It also provides the9 * basics of channel mode management.7 * This file provides both the basic functions necessary to manage channel 8 * modes and some of the intrinsic channel modes for IRC (mostly as defined 9 * in rfc1459). Additional modes can be created through other modules. 10 10 */ 11 11 … … 16 16 IDSTRING(rcsid, "$Id$"); 17 17 18 channel_t *create_channel(char *name) { 19 channel_t *chan = calloc(1, sizeof(channel_t)); 20 21 /* allocate space for mode data too */ 22 chan->mdext = mdext_alloc(ircd.mdext.channel); 23 24 strncpy(chan->name, name, ircd.limits.chanlen); 25 chan->created = me.now; 26 27 LIST_INSERT_HEAD(ircd.lists.channels, chan, lp); 28 hash_insert(ircd.hashes.channel, chan); 29 30 ircd.stats.channels++; 31 32 hook_event(ircd.events.channel_create, chan); 33 34 return chan; 35 } 36 37 void add_to_channel(client_t *cli, channel_t *chan, bool hook) { 38 struct chanlink *clp; 39 40 /* insert user to channel list, and vice versa */ 41 clp = malloc(sizeof(struct chanlink)); 42 clp->cli = cli; 43 clp->chan = chan; 44 clp->flags = clp->bans = 0; 45 LIST_INSERT_HEAD(&chan->users, clp, lpchan); 46 LIST_INSERT_HEAD(&cli->chans, clp, lpcli); 47 48 chan->onchannel++; 49 50 if (hook) 51 hook_event(ircd.events.channel_add, clp); 52 } 53 54 void del_from_channel(client_t *cli, channel_t *chan, bool hook) { 55 struct chanlink *clp = clp = find_chan_link(cli, chan); 56 57 if (clp != NULL) { 58 /* hook the del call first */ 59 if (hook) 60 hook_event(ircd.events.channel_del, clp); 61 62 /* remove from channel/client lists */ 63 LIST_REMOVE(clp, lpchan); 64 LIST_REMOVE(clp, lpcli); 65 free(clp); 66 chan->onchannel--; 67 } 68 69 if (chan->onchannel == 0) 70 destroy_channel(chan); 71 } 72 73 void destroy_channel(channel_t *chan) { 74 unsigned char *s; 75 int dummy; 76 77 hook_event(ircd.events.channel_destroy, chan); 78 79 /* clear out all the data possibly left over from channel modes. */ 80 s = ircd.cmodes.avail; 81 while (*s) { 82 ircd.cmodes.modes[*s].changefunc(NULL, chan, *s, CHANMODE_CLEAR, NULL, &dummy); 83 s++; 84 } 85 86 /* we only expect to be called on an empty channel! */ 87 hash_delete(ircd.hashes.channel, chan); 88 LIST_REMOVE(chan, lp); 89 ircd.stats.channels--; 90 mdext_free(ircd.mdext.channel, chan->mdext); 91 free(chan); 92 } 93 94 struct chanlink *find_chan_link(client_t *cli, channel_t *chan) { 95 struct chanlink *clp; 96 97 LIST_FOREACH(clp, &cli->chans, lpcli) { 98 if (clp->chan == chan) 99 return clp; 100 } 101 102 return NULL; 103 } 104 105 int channel_check_access(client_t *cli, channel_t *chan, char *ext, 106 event_t *ep) { 107 struct channel_check_args cca; 108 109 cca.cli = cli; 110 cca.chan = chan; 111 cca.clp = find_chan_link(cli, chan); 112 cca.extra = ext; 113 114 return hook_cond_event(ep, &cca); 115 } 116 117 /******************************************************************************* 118 * channel mode goodies here. 119 ******************************************************************************/ 18 /* lots of static functions here */ 120 19 static void chanmode_build_lists(void); 20 static int check_bans(const struct channel_ban_list *, const char *, 21 const char *, const char *, const char *, const char *); 22 static CHANMODE_FUNC(chanmode_ban); 23 static CHANMODE_QUERY_FUNC(chanmode_ban_query); 24 static HOOK_FUNCTION(can_join_mode_b); 25 static HOOK_FUNCTION(can_send_mode_b); 26 static HOOK_FUNCTION(can_nick_mode_b); 27 28 static HOOK_FUNCTION(can_send_mode_m); 29 static HOOK_FUNCTION(can_send_mode_n); 30 static HOOK_FUNCTION(can_show_mode_s); 31 32 static HOOK_FUNCTION(can_act_mode_ov); 33 34 static CHANMODE_FUNC(chanmode_key); 35 static CHANMODE_QUERY_FUNC(chanmode_key_query); 36 static HOOK_FUNCTION(can_join_mode_k); 37 38 static CHANMODE_FUNC(chanmode_limit); 39 static CHANMODE_QUERY_FUNC(chanmode_limit_query); 40 static HOOK_FUNCTION(can_join_mode_l); 41 42 /* This function either initializes the chanmode system or handles updates 43 * in the case of a reload. */ 44 void chanmode_init(bool reload) { 45 uint64_t ui64 = 1; 46 unsigned char c; 47 48 #define MODELOOP(from, to) do { \ 49 for (c = from;c <= to;c++, ui64 <<= 1) { \ 50 ircd.cmodes.modes[c].mode = c; \ 51 ircd.cmodes.modes[c].mask = ui64; \ 52 ircd.cmodes.modes[c].avail = 1; \ 53 } \ 54 } while (0) 55 56 if (reload == false) { 57 MODELOOP('a', 'z'); /* set a-z modes */ 58 MODELOOP('A', 'Z'); /* and A-Z modes */ 59 MODELOOP('0', '9'); /* and 0-9 modes */ 60 61 /* now allocate our various channel modes */ 62 ui64 = 0; 63 ircd.cmodes.mode_ban = chanmode_request('b', &c, CHANMODE_FL_A, 64 chanmode_ban, chanmode_ban_query, 65 sizeof(struct channel_ban_list), NULL); 66 ircd.cmodes.mode_key = chanmode_request('k', &c, CHANMODE_FL_B, 67 chanmode_key, chanmode_key_query, PASSWDLEN + 1, NULL); 68 ircd.cmodes.mode_limit = chanmode_request('l', &c, CHANMODE_FL_C, 69 chanmode_limit, chanmode_limit_query, sizeof(uint32_t), NULL); 70 ircd.cmodes.mode_mod = chanmode_request('m', &c, CHANMODE_FL_D, 71 chanmode_flag, chanmode_flag_query, 0, NULL); 72 ircd.cmodes.mode_nextern = chanmode_request('n', &c, CHANMODE_FL_D, 73 chanmode_flag, chanmode_flag_query, 0, NULL); 74 ircd.cmodes.mode_op = chanmode_request('o', &c, CHANMODE_FL_PREFIX, 75 chanmode_uflag, chanmode_uflag_query, 0, "@"); 76 ircd.cmodes.mode_secret = chanmode_request('s', &c, CHANMODE_FL_D, 77 chanmode_flag, chanmode_flag_query, 0, NULL); 78 ircd.cmodes.mode_voice = chanmode_request('v', &c, CHANMODE_FL_PREFIX, 79 chanmode_uflag, chanmode_uflag_query, 0, "+"); 80 } else { 81 chanmode_update_funcs(ircd.cmodes.mode_ban, chanmode_ban, 82 chanmode_ban_query); 83 chanmode_update_funcs(ircd.cmodes.mode_key, chanmode_key, 84 chanmode_key_query); 85 chanmode_update_funcs(ircd.cmodes.mode_limit, chanmode_limit, 86 chanmode_limit_query); 87 chanmode_update_funcs(ircd.cmodes.mode_mod, chanmode_flag, 88 chanmode_flag_query); 89 chanmode_update_funcs(ircd.cmodes.mode_nextern, chanmode_flag, 90 chanmode_flag_query); 91 chanmode_update_funcs(ircd.cmodes.mode_op, chanmode_uflag, 92 chanmode_uflag_query); 93 chanmode_update_funcs(ircd.cmodes.mode_mod, chanmode_flag, 94 chanmode_flag_query); 95 chanmode_update_funcs(ircd.cmodes.mode_voice, chanmode_uflag, 96 chanmode_uflag_query); 97 } 98 99 add_hook(ircd.events.can_join_channel, can_join_mode_b); 100 add_hook(ircd.events.can_send_channel, can_send_mode_b); 101 add_hook(ircd.events.can_nick_channel, can_nick_mode_b); 102 103 add_hook(ircd.events.can_send_channel, can_send_mode_m); 104 105 add_hook(ircd.events.can_send_channel, can_send_mode_n); 106 107 add_hook(ircd.events.can_see_channel, can_show_mode_s); 108 109 add_hook(ircd.events.can_join_channel, can_join_mode_k); 110 add_hook(ircd.events.can_join_channel, can_join_mode_l); 111 112 add_hook(ircd.events.can_send_channel, can_act_mode_ov); 113 add_hook(ircd.events.can_nick_channel, can_act_mode_ov); 114 115 ui64 = MAX_BANS_PER_CHANNEL; 116 add_isupport("MAXBANS", ISUPPORT_FL_INT, (char *)&ui64); 117 } 118 119 void chanmode_deinit(bool reload) { 120 121 if (reload == false) { 122 chanmode_release(ircd.cmodes.mode_ban); 123 chanmode_release(ircd.cmodes.mode_key); 124 chanmode_release(ircd.cmodes.mode_limit); 125 chanmode_release(ircd.cmodes.mode_mod); 126 chanmode_release(ircd.cmodes.mode_nextern); 127 chanmode_release(ircd.cmodes.mode_op); 128 chanmode_release(ircd.cmodes.mode_secret); 129 chanmode_release(ircd.cmodes.mode_voice); 130 } 131 132 remove_hook(ircd.events.can_join_channel, can_join_mode_b); 133 remove_hook(ircd.events.can_send_channel, can_send_mode_b); 134 remove_hook(ircd.events.can_nick_channel, can_nick_mode_b); 135 136 remove_hook(ircd.events.can_send_channel, can_send_mode_m); 137 138 remove_hook(ircd.events.can_send_channel, can_send_mode_n); 139 140 remove_hook(ircd.events.can_see_channel, can_show_mode_s); 141 142 remove_hook(ircd.events.can_join_channel, can_join_mode_k); 143 remove_hook(ircd.events.can_join_channel, can_join_mode_l); 144 145 remove_hook(ircd.events.can_send_channel, can_act_mode_ov); 146 remove_hook(ircd.events.can_nick_channel, can_act_mode_ov); 147 148 del_isupport(find_isupport("MAXBANS")); 149 } 121 150 122 151 uint64_t chanmode_request(unsigned char suggested, unsigned char *actual, … … 431 460 } 432 461 433 char **channel_mdext_iter(char **last) { 434 static int started = 0; 435 channel_t *cp = *(channel_t **)last; 436 462 /* Below are four convenience functions for modes which fit the generic 463 * category of either channel 'flags' (on/off or type 'D') or channel user 464 * 'prefixes' (uflags like +o/+v). If your flags don't need special 465 * behavior to be set/unset use these. */ 466 CHANMODE_FUNC(chanmode_flag) { 467 468 *argused = 0; 469 if (cli != NULL && !CHANOP(cli, chan) && !CLIENT_MASTER(cli)) 470 return ERR_CHANOPRIVSNEEDED; 471 472 switch (set) { 473 case CHANMODE_SET: 474 chanmode_setflag(chan, mode); 475 break; 476 case CHANMODE_UNSET: 477 chanmode_unsetflag(chan, mode); 478 break; 479 } 480 return CHANMODE_OK; 481 } 482 483 CHANMODE_QUERY_FUNC(chanmode_flag_query) { 484 *argused = 0; 485 486 if (*state == NULL) 487 *state = (void *)0x1; /* dummy pointer to nowhere */ 488 else 489 return CHANMODE_FAIL; /* they already asked */ 490 491 if (!chanmode_isset(chan, mode)) 492 return CHANMODE_FAIL; /* not set */ 493 return CHANMODE_OK; /* it's set */ 494 } 495 496 CHANMODE_FUNC(chanmode_uflag) { 497 struct chanlink *clp; 498 client_t *cp; 499 500 if (cli != NULL && !CHANOP(cli, chan) && !CLIENT_MASTER(cli)) 501 return ERR_CHANOPRIVSNEEDED; 502 503 /* error check stuff first */ 504 if (set != CHANMODE_CLEAR) { 505 if (arg == NULL) 506 return CHANMODE_NOARG; 507 *argused = 1; /* otherwise we use the argument */ 508 } else 509 return CHANMODE_OK; /* we don't have anything to clear */ 510 511 /* chase for +o/+v to avoid desynchs */ 512 cp = client_get_history(arg, 0); 437 513 if (cp == NULL) { 438 if (started) { 439 started = 0; 440 return NULL; 514 if (cli != NULL) 515 sendto_one(cli, RPL_FMT(cli, ERR_NOSUCHNICK), arg); 516 return CHANMODE_FAIL; 517 } 518 if (arg != cp->nick) 519 strcpy(arg, cp->nick); /* Maintain exact case of nickname if the arg 520 came from somewhere but the client's nick */ 521 522 clp = find_chan_link(cp, chan); 523 if (clp == NULL) { 524 if (cli != NULL) 525 sendto_one(cli, RPL_FMT(cli, ERR_USERNOTINCHANNEL), cp->nick, 526 chan->name); 527 return CHANMODE_FAIL; 528 } 529 530 switch (set) { 531 case CHANMODE_SET: 532 clp->flags |= ircd.cmodes.modes[mode].umask; 533 return CHANMODE_OK; 534 case CHANMODE_UNSET: 535 clp->flags &= ~ircd.cmodes.modes[mode].umask; 536 return CHANMODE_OK; 537 } 538 539 return CHANMODE_FAIL; 540 } 541 542 CHANMODE_QUERY_FUNC(chanmode_uflag_query) { 543 *argused = 0; 544 545 return CHANMODE_FAIL; /* you can't query these.. */ 546 } 547 548 /******************************************************************************* 549 * RFC1459 mode functions here 550 ******************************************************************************/ 551 552 /* Function to count how many bans in a channel a user matches against. 553 * We try to do the least number of comparisons possible (always 2, 554 * maybe 3). */ 555 556 static int check_bans(const struct channel_ban_list *list, const char *nick, 557 const char *user, const char *host, const char *ip, 558 const char *orighost) { 559 struct channel_ban *cbp; 560 bool check_orighost = false; 561 int bans = 0; 562 563 if (orighost != NULL && *orighost != '\0' && strcasecmp(host, orighost)) 564 check_orighost = true; 565 566 /* Walk the list only once, checking each ban against the various 567 * pieces of data provided. If the nick or username don't match we skip 568 * right away, then do two (or three) host checks. First we check the 569 * "display" host, then we do ip matching on the ip, and then we check 570 * the orighost if required. */ 571 572 LIST_FOREACH(cbp, list, lp) { 573 if (!match(cbp->nick, nick) || !match(cbp->user, user)) 574 continue; /* not a match */ 575 if (match(cbp->host, host) || ipmatch(cbp->host, ip)) { 576 bans++; 577 continue; 578 } else if (check_orighost && match(cbp->host, orighost)) { 579 bans++; 580 continue; 441 581 } 442 cp = LIST_FIRST(ircd.lists.channels); 443 started = 1; 444 } 445 if (cp == NULL) 446 return NULL; 447 448 *(channel_t **)last = LIST_NEXT(cp, lp); 449 return (char **)&cp->mdext; 450 } 451 452 int chancmp(char *one, char *two, size_t len __UNUSED) { 453 return istrcmp(ircd.maps.channel, one, two); 454 } 582 } 583 584 return bans; 585 } 586 587 /* bans. rather complicated! */ 588 static CHANMODE_FUNC(chanmode_ban) { 589 struct channel_ban_list *banlist = 590 (struct channel_ban_list *)chanmode_getdata(chan, mode); 591 struct channel_ban *cbp; 592 struct chanlink *clp; 593 char nick[NICKLEN + 1]; 594 char user[USERLEN + 1]; 595 char host[HOSTLEN + 1]; 596 597 int cnt = 0; 598 599 /* if we're not just clearing the data, check arg, and make sure they know 600 * the argument is being used. */ 601 if (set != CHANMODE_CLEAR) { 602 char *bang, *at; 603 size_t nicklen, userlen, hostlen; 604 605 if (arg == NULL) { 606 /* if this is a client, send them the list of bans. */ 607 if (cli != NULL && MYCLIENT(cli)) { 608 LIST_FOREACH(cbp, banlist, lp) { 609 sendto_one(cli, RPL_FMT(cli, RPL_BANLIST), chan->name, 610 cbp->nick, cbp->user, cbp->host, cbp->who, 611 cbp->when); 612 } 613 sendto_one(cli, RPL_FMT(cli, RPL_ENDOFBANLIST), chan->name); 614 } 615 return CHANMODE_NOP; 616 } 617 618 *argused = 1; 619 /* if they're not ops, deny deny deny. */ 620 if (cli != NULL && !CHANOP(cli, chan) && !CLIENT_MASTER(cli)) 621 return ERR_CHANOPRIVSNEEDED; 622 623 bang = strchr(arg, '!'); 624 at = strchr(arg, '@'); 625 /* here's the scoop: the bang can't be the first character of the 626 * mask. the at can't be the last character, and there has to be 627 * something between the bang and the at. */ 628 if (bang == NULL || at == NULL || bang == arg || 629 *(at + 1) == '\0' || (bang + 1) == at || at < bang) 630 return CHANMODE_FAIL; /* bogus mask */ 631 632 nicklen = bang - arg; /* length of text from beginning of the string 633 to the '!' symbol. */ 634 userlen = at - (bang + 1); /* length from after the '!' to the '@' 635 symbol */ 636 hostlen = strlen(at + 1); /* length from after the '@' to the end */ 637 638 /* Make sure nothing is too long, too */ 639 if (nicklen > NICKLEN || userlen > USERLEN || hostlen > HOSTLEN) 640 return CHANMODE_FAIL; /* arguments are too long */ 641 642 strlcpy(nick, arg, nicklen + 1); 643 strlcpy(user, bang + 1, userlen + 1); 644 strlcpy(host, at + 1, hostlen + 1); 645 } 646 647 switch (set) { 648 case CHANMODE_SET: 649 LIST_FOREACH(cbp, banlist, lp) { 650 if (++cnt > MAX_BANS_PER_CHANNEL && cli != NULL && 651 MYCLIENT(cli)) { 652 sendto_one(cli, RPL_FMT(cli, ERR_BANLISTFULL), 653 chan->name, arg); 654 return CHANMODE_FAIL; /* no siree bob */ 655 } 656 /* Previously I had tried to match the ban being set against 657 * other bans, but I'm not sure this behavior is desired so 658 * I'm taking it out for now... */ 659 #if 0 660 /* we only want to know if current bans cover this ban, not 661 * if this ban covers current ones, since it may cover 662 * other things too. */ 663 if (match(cbp->nick, nick) && match(cbp->user, user) && 664 match(cbp->host, host)) 665 return CHANMODE_FAIL; /* already set. */ 666 #else 667 if (!strcasecmp(cbp->nick, nick) && 668 !strcasecmp(cbp->user, user) && 669 !strcasecmp(cbp->host, host)) 670 return CHANMODE_FAIL; 671 #endif 672 } 673 674 cbp = calloc(1, sizeof(struct channel_ban)); 675 strlcpy(cbp->nick, nick, NICKLEN + 1); 676 strlcpy(cbp->user, user, USERLEN + 1); 677 strlcpy(cbp->host, host, HOSTLEN + 1); 678 if (cli != NULL) 679 sprintf(cbp->who, "%s!%s@%s", cli->nick, cli->user, cli->host); 680 else 681 strcpy(cbp->who, ircd.me->name); 682 cbp->when = me.now; 683 cbp->type = CHANNEL_BAN_BAN; 684 685 LIST_INSERT_HEAD(banlist, cbp, lp); 686 687 /* count bans against all users in the channel. */ 688 LIST_FOREACH(clp, &chan->users, lpchan) { 689 clp->bans = check_bans(banlist, clp->cli->nick, 690 clp->cli->user, clp->cli->host, clp->cli->ip, 691 clp->cli->orighost); 692 } 693 694 break; 695 case CHANMODE_UNSET: 696 LIST_FOREACH(cbp, banlist, lp) { 697 if (!strcasecmp(cbp->nick, nick) && 698 !strcasecmp(cbp->user, user) && 699 !strcasecmp(cbp->host, host)) { 700 /* a winner. */ 701 LIST_REMOVE(cbp, lp); 702 free(cbp); 703 704 /* count bans against all users in the channel. */ 705 LIST_FOREACH(clp, &chan->users, lpchan) { 706 clp->bans = check_bans(banlist, clp->cli->nick, 707 clp->cli->user, clp->cli->host, clp->cli->ip, 708 clp->cli->orighost); 709 } 710 break; 711 } 712 } 713 break; 714 case CHANMODE_CLEAR: 715 while ((cbp = LIST_FIRST(banlist)) != NULL) { 716 LIST_REMOVE(cbp, lp); 717 free(cbp); 718 } 719 break; 720 } 721 722 return CHANMODE_OK; /* a-okay. */ 723 } 724 725 struct ban_query_state { 726 bool started; 727 struct channel_ban *curban; 728 }; 729 730 CHANMODE_QUERY_FUNC(chanmode_ban_query) { 731 struct channel_ban_list *banlist = 732 (struct channel_ban_list *)chanmode_getdata(chan, mode); 733 struct channel_ban *cbp; 734 struct ban_query_state *bqs; 735 char mask[BAN_MASK_LEN]; 736 size_t len; 737 738 if (*state == NULL) 739 *state = calloc(1, sizeof(struct ban_query_state)); 740 bqs = *state; 741 742 if (bqs->started == false) { 743 bqs->curban = LIST_FIRST(banlist); 744 bqs->started = true; 745 } 746 747 /* always run this check because we might be done when we start.. */ 748 if (bqs->curban == NULL) { 749 /* we're done here.. free bqs and let them leave the loop */ 750 free(bqs); 751 *argused = 0; 752 return CHANMODE_FAIL; /* all done! */ 753 } 754 755 /* okay, we know we've either started or we finished and went home.. */ 756 cbp = bqs->curban; 757 758 len = sprintf(mask, "%s!%s@%s", cbp->nick, cbp->user, cbp->host); 759 if (len > (size_t)*argused) { 760 *argused = -(len - *argused); 761 /* do not advance the list as the consumer is expected not to use 762 * this mode since they have no room for it. */ 763 } else { 764 strcpy(arg, mask); 765 *argused = len; 766 /* advance the list since they promised us enough space! */ 767 bqs->curban = LIST_NEXT(cbp, lp); 768 } 769 770 return CHANMODE_OK; 771 } 772 773 static HOOK_FUNCTION(can_join_mode_b) { 774 struct channel_check_args *ccap = (struct channel_check_args *)data; 775 struct channel_ban_list *banlist = 776 (struct channel_ban_list *)chanmode_getdata(ccap->chan, 777 ircd.cmodes.mode_ban); 778 void *ret = (void *)HOOK_COND_OK; /* deny by default. */ 779 780 ccap->clp->bans = check_bans(banlist, ccap->cli->nick, ccap->cli->user, 781 ccap->cli->host, ccap->cli->ip, ccap->cli->orighost); 782 783 if (ccap->clp->bans) 784 return (void *)ERR_BANNEDFROMCHAN; 785 786 return ret; /* and return.. */ 787 } 788 789 static HOOK_FUNCTION(can_send_mode_b) { 790 struct channel_check_args *ccap = (struct channel_check_args *)data; 791 792 if (ccap->clp == NULL) 793 return (void *)HOOK_COND_NEUTRAL; /* doesn't effect us */ 794 if (ccap->clp->bans) 795 return (void *)ERR_CANNOTSENDTOCHAN; /* banned, cannot send */ 796 797 return (void *)HOOK_COND_NEUTRAL; 798 } 799 800 static HOOK_FUNCTION(can_nick_mode_b) { 801 struct channel_check_args *ccap = (struct channel_check_args *)data; 802 struct channel_ban_list *banlist = 803 (struct channel_ban_list *)chanmode_getdata(ccap->chan, 804 ircd.cmodes.mode_ban); 805 806 if (ccap->clp == NULL) { 807 log_debug("can_nick_mode_b() called when client wasn't in channel!"); 808 return (void *)HOOK_COND_NEUTRAL; /* not interested.. */ 809 } 810 if (ccap->clp->bans) 811 return (void *)ERR_BANNICKCHANGE; /* hope they handle this right. :) */ 812 813 /* if they're not banned, make sure the nickname change wouldn't result in 814 * a ban either. */ 815 if (check_bans(banlist, ccap->extra, ccap->cli->user, ccap->cli->host, 816 ccap->cli->ip, ccap->cli->orighost)) 817 return (void *)ERR_BANONCHAN; 818 819 return (void *)HOOK_COND_NEUTRAL; /* eh. */ 820 } 821 822 static HOOK_FUNCTION(can_send_mode_m) { 823 struct channel_check_args *ccap = (struct channel_check_args *)data; 824 825 if (chanmode_isset(ccap->chan, ircd.cmodes.mode_mod)) 826 return (void *)ERR_CANNOTSENDTOCHAN; /* unless overriden, no. */ 827 return (void *)HOOK_COND_NEUTRAL; 828 } 829 830 static HOOK_FUNCTION(can_send_mode_n) { 831 struct channel_check_args *ccap = (struct channel_check_args *)data; 832 833 /* if we're +n and they're not in the channel, don't let them send. */ 834 if (chanmode_isset(ccap->chan, ircd.cmodes.mode_nextern) && 835 ccap->clp == NULL) 836 return (void *)ERR_CANNOTSENDTOCHAN; 837 return (void *)HOOK_COND_NEUTRAL; 838 } 839 840 static HOOK_FUNCTION(can_show_mode_s) { 841 struct channel_check_args *ccap = (struct channel_check_args *)data; 842 843 /* if they're in the channel, it's always okay. if the channel is +s it's 844 * not okay unless they've got the see-hidden-channels privilege, and then 845 * it's okay if they're opered. if the channel isn't +s it's always okay 846 * too. */ 847 if (ccap->clp != NULL) 848 return (void *)HOOK_COND_OK; /* s'not a problem. */ 849 else if (chanmode_isset(ccap->chan, ircd.cmodes.mode_secret)) { 850 if (CLIENT_OPERATOR(ccap->cli) && 851 BPRIV(ccap->cli, ircd.privileges.priv_shc)) 852 return (void *)HOOK_COND_ALWAYSOK; /* okay, but sketchy. */ 853 else 854 return (void *)ERR_NOTONCHANNEL; 855 } else 856 return (void *)HOOK_COND_OK; /* it's not +s, okay by us. */ 857 } 858 859 static CHANMODE_FUNC(chanmode_key) { 860 861 if (set != CHANMODE_CLEAR) { 862 if (arg == NULL) 863 return CHANMODE_NOARG; 864 if (cli != NULL && !CHANOP(cli, chan) && !CLIENT_MASTER(cli)) 865 return ERR_CHANOPRIVSNEEDED; 866 *argused = 1; 867 } 868 869 switch (set) { 870 case CHANMODE_SET: 871 if (strchr(arg, ' ') != NULL || strchr(arg, ',') != NULL) 872 return CHANMODE_FAIL; /* no spaces or commas in keys */ 873 if (cli == NULL && chanmode_isset(chan, mode)) { 874 /* this is coming from a server... we do something silly here. 875 * if we have a key currently, we compare the two keys and use 876 * the one which is lexocographically greater (pretty 877 * arbitrary, eh?) */ 878 if (strcmp(arg, chanmode_getstrdata(chan, mode)) <= 0) 879 strncpy(chanmode_getstrdata(chan, mode), arg, PASSWDLEN); 880 return CHANMODE_OK; 881 } 882 883 strncpy(chanmode_getstrdata(chan, mode), arg, PASSWDLEN); 884 chanmode_setflag(chan, mode); 885 break; 886 case CHANMODE_UNSET: 887 memset(chanmode_getstrdata(chan, mode), 0, PASSWDLEN + 1); 888 chanmode_unsetflag(chan, mode); 889 break; 890 } 891 892 return CHANMODE_OK; 893 } 894 static CHANMODE_QUERY_FUNC(chanmode_key_query) { 895 size_t len; 896 897 if (*state == NULL) 898 *state = (void *)0x1; /* set it so we don't return more than once */ 899 else 900 return CHANMODE_FAIL; /* already queried */ 901 902 if (!chanmode_isset(chan, mode)) { 903 *argused = 0; 904 return CHANMODE_FAIL; /* not set */ 905 } else { 906 if ((len = strlen(chanmode_getstrdata(chan, mode))) > 907 (size_t)*argused) { 908 *argused = -(len - *argused); 909 *state = NULL; /* they will have to ask again.. */ 910 } else { 911 strncpy(arg, chanmode_getstrdata(chan, mode), PASSWDLEN); 912 *argused = len; 913 } 914 } 915 return CHANMODE_OK; /* it's set */ 916 } 917 918 919 /* this function is hooked by the can_join event. just compare the arg (if 920 * any) to the key, and see if it's okay. */ 921 static HOOK_FUNCTION(can_join_mode_k) { 922 struct channel_check_args *ccap = (struct channel_check_args *)data; 923 char *key = chanmode_getstrdata(ccap->chan, ircd.cmodes.mode_key); 924 char *next, *cur; 925 926 /* ccap->extra should be a comma separated list of keys (or NULL). we try 927 * each one in succession. */ 928 if (*key != '\0') { 929 if (ccap->extra == NULL || *ccap->extra == '\0') 930 return (void *)ERR_BADCHANNELKEY; 931 cur = ccap->extra; 932 next = strchr(cur, ','); 933 while (cur != NULL) { 934 if (!strncasecmp(key, cur, 935 (next == NULL ? PASSWDLEN : next - cur))) 936 return (void *)HOOK_COND_OK; /* a match */ 937 if (next != NULL && *(next + 1) != '\0') { 938 cur = next + 1; 939 next = strchr(cur, ','); 940 } else 941 break; 942 } 943 return (void *)ERR_BADCHANNELKEY; /* no match, or no key */ 944 } 945 946 return (void *)HOOK_COND_OK; /* okay to join. */ 947 } 948 949 static CHANMODE_FUNC(chanmode_limit) { 950 uint32_t limit; 951 uint32_t *chl = (uint32_t *)chanmode_getdata(chan, mode); 952 953 if (cli != NULL && !CHANOP(cli, chan) && !CLIENT_MASTER(cli)) 954 return ERR_CHANOPRIVSNEEDED; 955 switch (set) { 956 case CHANMODE_SET: 957 if (arg == NULL) 958 return CHANMODE_NOARG; 959 *argused = 1; 960 limit = str_conv_int(arg, 0); 961 962 /* if the limit is bogus don't bother. */ 963 if (limit == 0) 964 return CHANMODE_FAIL; /* bad number */ 965 966 *chl = limit; 967 chanmode_setflag(chan, mode); 968 break; 969 case CHANMODE_UNSET: 970 *chl = 0; 971 chanmode_unsetflag(chan, mode); 972 *argused = 0; 973 } 974 975 return CHANMODE_OK; 976 } 977 978 static CHANMODE_QUERY_FUNC(chanmode_limit_query) { 979 char buf[16]; 980 size_t len; 981 uint32_t *chl = (uint32_t *)chanmode_getdata(chan, mode); 982 983 if (*state == NULL) 984 *state = (void *)0x1; /* set it so we don't return more than once */ 985 else 986 return CHANMODE_FAIL; /* already queried */ 987 if (!chanmode_isset(chan, mode)) 988 return CHANMODE_FAIL; /* not set */ 989 len = sprintf(buf, "%u", *chl); 990 if (len > (uint32_t)*argused) { 991 *argused = -(len - *argused); 992 *state = NULL; /* they must ask again */ 993 return CHANMODE_OK; 994 } 995 strcpy(arg, buf); 996 *argused = len; 997 return CHANMODE_OK; /* it's set */ 998 } 999 1000 1001 static HOOK_FUNCTION(can_join_mode_l) { 1002 struct channel_check_args *ccap = (struct channel_check_args *)data; 1003 1004 /* if a limit is set and the number of people in the channel is greater 1005 * than the limit, don't let them in. */ 1006 if (chanmode_getintdata(ccap->chan, ircd.cmodes.mode_limit) && 1007 ccap->chan->onchannel > 1008 chanmode_getintdata(ccap->chan, ircd.cmodes.mode_limit)) 1009 return (void *)ERR_CHANNELISFULL; 1010 1011 return (void *)HOOK_COND_OK; 1012 } 1013 1014 static HOOK_FUNCTION(can_act_mode_ov) { 1015 struct channel_check_args *ccap = (struct channel_check_args *)data; 1016 1017 if (ccap->clp == NULL) 1018 return (void *)HOOK_COND_NEUTRAL; 1019 if (CLINKOP(ccap->clp) || CLINKVOICE(ccap->clp)) 1020 return (void *)HOOK_COND_ALWAYSOK; /* if they're op'd or voiced, 1021 they can always change nicks 1022 or send. */ 1023 return (void *)HOOK_COND_NEUTRAL; /* not interested. */ 1024 } 1025 455 1026 /* vi:set ts=8 sts=4 sw=4 tw=76 et: */ -
trunk/ithildin/modules/ircd/chanmode.h
r801 r803 1 1 /* 2 * chan nel.h: channel (mode)structures and prototypes2 * chanmode.h: channel mode structures and prototypes 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * … … 8 8 */ 9 9 10 #ifndef IRCD_CHAN NEL_H11 #define IRCD_CHAN NEL_H10 #ifndef IRCD_CHANMODE_H 11 #define IRCD_CHANMODE_H 12 12 13 13 /* … … 76 76 int *, void **); 77 77 78 #define CHANMODE_FL_A 0x0179 #define CHANMODE_FL_B 0x0280 #define CHANMODE_FL_C 0x0481 #define CHANMODE_FL_D 0x0882 #define CHANMODE_FL_E 0x1078 #define CHANMODE_FL_A 0x01 79 #define CHANMODE_FL_B 0x02 80 #define CHANMODE_FL_C 0x04 81 #define CHANMODE_FL_D 0x08 82 #define CHANMODE_FL_E 0x10 83 83 #define CHANMODE_FL_PREFIX 0x20 84 84 85 #define CHANMODE_SET 186 #define CHANMODE_UNSET 087 #define CHANMODE_CLEAR -185 #define CHANMODE_SET 1 86 #define CHANMODE_UNSET 0 87 #define CHANMODE_CLEAR -1 88 88 89 89 #define CHANMODE_OK 0 90 #define CHANMODE_FAIL -1 91 #define CHANMODE_NOP -2 92 #define CHANMODE_NONEX -3 93 #define CHANMODE_NOARG -4 94 90 #define CHANMODE_FAIL -1 91 #define CHANMODE_NOP -2 92 #define CHANMODE_NONEX -3 93 #define CHANMODE_NOARG -4 94 95 void chanmode_init(bool); 96 void chanmode_deinit(bool); 95 97 uint64_t chanmode_request(unsigned char, unsigned char *, int, 96 98 chanmode_func, chanmode_query_func, size_t, void *); … … 183 185 }; 184 186 185 LIST_HEAD(chanusers, chanlink); 186 LIST_HEAD(userchans, chanlink); 187 188 /* this structure is used to glue users and channels together. one structure 189 * is allocated per user/chan relationship, and is saved in a linked list on 190 * the user's side, and on the channel's side. */ 191 struct chanlink { 192 client_t *cli; 193 channel_t *chan; 194 short flags; 195 short bans; /* for users only, stores how many bans they have against 196 them */ 197 198 LIST_ENTRY(chanlink) lpcli; 199 LIST_ENTRY(chanlink) lpchan; 187 /* some functions for generic channel mode handling */ 188 CHANMODE_FUNC(chanmode_flag); 189 CHANMODE_QUERY_FUNC(chanmode_flag_query); 190 CHANMODE_FUNC(chanmode_uflag); 191 CHANMODE_QUERY_FUNC(chanmode_uflag_query); 192 193 /* this structure is used to hold bans on a channel. */ 194 #define MAX_BANS_PER_CHANNEL 100 195 #define BAN_MASK_LEN NICKLEN + USERLEN + HOSTLEN + 3 196 LIST_HEAD(channel_ban_list, channel_ban); 197 struct channel_ban { 198 char nick[NICKLEN + 1]; /* the three components of ban, split up for easier 199 processing. */ 200 char user[USERLEN + 1]; 201 char host[HOSTLEN + 1]; 202 char who[BAN_MASK_LEN + 1]; 203 time_t when; /* when the ban was set */ 204 #define CHANNEL_BAN_BAN 0x01 205 unsigned char type; /* reserved for various uses */ 206 207 LIST_ENTRY(channel_ban) lp; 200 208 }; 201 209 202 char **channel_mdext_iter(char **); 203 204 struct channel { 205 char name[CHANLEN + 1]; /* our channel's name. */ 206 time_t created; /* the timestamp as well as creation time */ 207 208 unsigned int onchannel; /* number of people on channel */ 209 int flags; 210 struct chanusers users; /* list of users in channel */ 211 uint64_t modes; /* the flag-modes for the channel. */ 212 char *mdext; /* mdext data */ 213 214 LIST_ENTRY(channel) lp; 215 }; 216 217 /* create a channel. give it a name, initially the channel will be empty, 218 * so you use...*/ 219 channel_t *create_channel(char *); 220 221 /* add_to_channel. adds the given client to the given channel, fixes up all 222 * structures properly. the third argument is set if the caller wishes the 223 * channel_add event to be hooked. this is *almost* always the case. */ 224 void add_to_channel(client_t *, channel_t *, bool); 225 226 /* del_from_channel. removes the user from the given channel, if the 227 * channel becomes empty, it is destroyed with... the third argument is the 228 * same as above. */ 229 void del_from_channel(client_t *, channel_t *, bool); 230 231 /* destroy_channel. destroys a channel and returns all the good stuff to 232 * memory */ 233 void destroy_channel(channel_t *); 234 235 /* find a channel by name */ 236 #define find_channel(name) hash_find(ircd.hashes.channel, name) 237 238 /* finds a channel/user's chanlink entity and returns it (or NULL if it doesn't 239 * exist). Also, onchannel() is a wraparound checker to give a boolean return 240 * based on this info. */ 241 struct chanlink *find_chan_link(client_t *, channel_t *); 242 #define onchannel(cli, chan) \ 243 (find_chan_link(cli, chan) != NULL ? 1 : 0) 244 245 #define check_channame(name) \ 246 (name && (*name == '#') && \ 247 istr_okay(ircd.maps.channel, name)) 248 249 /* this structure is used by channel_check_access to pass to its various hook 250 * functions when checking if a channel can have an action performed on it (or 251 * something.. */ 252 struct channel_check_args { 253 channel_t *chan; /* the channel */ 254 client_t *cli; /* the client */ 255 struct chanlink *clp; /* if they're in the channel, this is the link. */ 256 char *extra; /* extra data */ 257 }; 258 259 /* this function determines whether a client (cli) can perform some action 260 * related to a channel (chan). it can be used in various manners and with 261 * various events. it calls the hooks for the specified event, which should 262 * return one of the five CHANNEL_ statuses above, or an error numeric to send 263 * to the user (which should be of the format '%s :...' unless your function is 264 * going to have some special handling). */ 265 266 /* these three are synonyms for the definitions in event.h */ 267 #define CHANNEL_CHECK_OVERRIDE HOOK_COND_SPASS 268 #define CHANNEL_CHECK_OK HOOK_COND_PASS 269 #define CHANNEL_CHECK_NO HOOK_COND_FAIL 270 int channel_check_access(client_t *, channel_t *, char *, event_t *); 271 272 /* this lets you check to see if a user can enter a channel. */ 273 #define can_can_join_channel(cli, chan, arg) \ 274 channel_check_access(cli, chan, arg, ircd.events.can_join_channel) 275 /* this lets you check to see if a user can see a channel's details. */ 276 #define can_can_see_channel(cli, chan) \ 277 channel_check_access(cli, chan, NULL, ircd.events.can_see_channel) 278 279 /* this is like the above two, except that you also pass the message the user 280 * is attempting to send to the channel. */ 281 #define can_can_send_channel(cli, chan, msg) \ 282 channel_check_access(cli, chan, msg, ircd.events.can_send_channel) 283 284 /* this is like the above three, except for nick changes in the channel. 285 * hopefully this is it. :) */ 286 #define can_can_nick_channel(cli, chan, nick) \ 287 channel_check_access(cli, chan, nick, ircd.events.can_nick_channel); 288 289 /* chancmp, like nickcmp in client.c */ 290 int chancmp(char *, char *, size_t); 210 /* some macros... the link variety are a lot faster if you've already taken 211 * the time to see if they're in the channel (and have saved the chanlink 212 * entry). */ 213 #define CHANOP(cli, chan) chanmode_isprefix(chan, cli, '@') 214 #define CLINKOP(clp) chanlink_ismode(clp, ircd.cmodes.mode_op) 215 #define CHANVOICE(cli, chan) chanmode_isprefix(chan, cli, '+') 216 #define CLINKVOICE(clp) chanlink_ismode(clp, ircd.cmodes.mode_voice) 291 217 292 218 #endif -
trunk/ithildin/modules/ircd/channel.c
r801 r803 2 2 * channel.c: channel structure management code 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * 7 7 * This file provides the basic functions necessary to create/destroy/manage 8 * channel structures, and lists of people with channels. It also provides the 9 * basics of channel mode management. 8 * channel structures, and lists of people with channels. 10 9 */ 11 10 … … 115 114 } 116 115 117 /*******************************************************************************118 * channel mode goodies here.119 ******************************************************************************/120 static void chanmode_build_lists(void);121 122 uint64_t chanmode_request(unsigned char suggested, unsigned char *actual,123 int flags, chanmode_func changefn, chanmode_query_func queryfn,124 size_t extra, void *extdata) {125 struct chanmode *md = NULL;126 int i, j;127 unsigned char c;128 129 /* try and find the first/best available mode */130 if (ircd.cmodes.modes[suggested].avail)131 md = &ircd.cmodes.modes[suggested];132 else {133 if (islower(suggested))134 c = toupper(suggested);135 else136 c = tolower(suggested);137 138 if (ircd.cmodes.modes[c].avail)139 md = &ircd.cmodes.modes[c];140 else {141 for (i = 0;i < 256;i++) {142 if (ircd.cmodes.modes[i].avail && ircd.umodes.modes[i].mask) {143 md = &ircd.cmodes.modes[i];144 break;145 }146 }147 148 if (md == NULL)149 return 0;150 }151 }152 153 /* fill in the stuff */154 md->avail = 0;155 md->umask = 0;156 md->prefix = '\0';157 md->changefunc = changefn;158 md->queryfunc = queryfn;159 md->flags = flags;160 md->mdi = NULL;161 162 if (flags == CHANMODE_FL_PREFIX) {163 /* we have to find the first free flag, if any, to use. to do164 * this, for each value from 0x1 to 0x80 moving in powers of two,165 * we have to check if any of the channel modes are using it. fun166 * stuff. */167 for (i = 0;i < 16;i++) {168 for (j = 0;j < 256;j++) {169 if (ircd.cmodes.modes[j].umask == 1 << i)170 break;171 }172 if (j == 256)173 break; /* we have a weiner */174 }175 if (i == 16) {176 /* couldn't get a mode. yuck. */177 md->avail = 1;178 return 0;179 }180 md->umask = 1 << i;181 md->prefix = *(unsigned char *)extdata;182 ircd.cmodes.pfxmap[md->prefix] = md; /* map back */183 }184 185 if (extra > 0)186 md->mdi = create_mdext_item(ircd.mdext.channel, extra);187 188 chanmode_build_lists();189 190 *actual = md->mode;191 return md->mask;192 }193 194 /* this function very simply releases a mode and calls the list rebuilder. */195 void chanmode_release(unsigned char mode) {196 channel_t *chan;197 int dummy;198 199 /* clear the mode from all the channels .. */200 LIST_FOREACH(chan, ircd.lists.channels, lp)201 ircd.cmodes.modes[mode].changefunc(NULL, chan, mode, CHANMODE_CLEAR, NULL, &dummy);202 203 /* we don't touch the mode or mask members because those are set elsewhere204 * and need to be kept the way they are. */205 ircd.cmodes.modes[mode].avail = 1; /* mark it as available */206 207 ircd.cmodes.modes[mode].umask = 0;208 if (ircd.cmodes.modes[mode].prefix != '\0') {209 ircd.cmodes.pfxmap[ircd.cmodes.modes[mode].prefix] = NULL;210 ircd.cmodes.modes[mode].prefix = '\0';211 }212 ircd.cmodes.modes[mode].changefunc = NULL;213 ircd.cmodes.modes[mode].queryfunc = NULL;214 ircd.cmodes.modes[mode].flags = 0;215 if (ircd.cmodes.modes[mode].mdi != NULL)216 destroy_mdext_item(ircd.mdext.channel, ircd.cmodes.modes[mode].mdi);217 chanmode_build_lists();218 }219 220 void chanmode_update_funcs(unsigned char mode, chanmode_func changefunc,221 chanmode_query_func queryfunc) {222 struct chanmode *cmp = &ircd.cmodes.modes[mode];223 224 if (cmp->avail || !cmp->mask) /* only if it exists.. */225 return;226 227 cmp->changefunc = changefunc;228 cmp->queryfunc = queryfunc;229 }230 231 static void chanmode_build_lists(void) {232 int i;233 unsigned char imodes[256];234 unsigned char *s;235 236 /* fill in the 'avail' modestring thing. */237 s = ircd.cmodes.avail;238 for (i = 0;i < 256;i++) {239 if (!ircd.cmodes.modes[i].avail && ircd.cmodes.modes[i].mask)240 *s++ = ircd.cmodes.modes[i].mode;241 }242 *s = '\0';243 244 /* now do the prefix thing. we make two passes to make it easier. */245 s = ircd.cmodes.pmodes;246 for (i = 0;i < 256;i++) {247 if (!ircd.cmodes.modes[i].avail && ircd.cmodes.modes[i].prefix)248 *s++ = ircd.cmodes.modes[i].mode;249 }250 *s = '\0';251 252 s = ircd.cmodes.prefix;253 *s++ = '(';254 for (i = 0;i < 256;i++) {255 if (!ircd.cmodes.modes[i].avail && ircd.cmodes.modes[i].prefix)256 *s++ = ircd.cmodes.modes[i].mode;257 }258 *s++ = ')';259 for (i = 0;i < 256;i++) {260 if (!ircd.cmodes.modes[i].avail && ircd.cmodes.modes[i].prefix)261 *s++ = ircd.cmodes.modes[i].prefix;262 }263 *s = '\0';264 265 /* now do a/b/c/d/e */266 s = imodes;267 #define CHANMODE_BUILD_TYPE(_flg) do { \268 for (i = 0;i < 256;i++) { \269 if (!ircd.cmodes.modes[i].avail && \270 ircd.cmodes.modes[i].flags & _flg) \271 *s++ = ircd.cmodes.modes[i].mode; \272 } \273 *s++ = ','; \274 } while (0)275 276 CHANMODE_BUILD_TYPE(CHANMODE_FL_A);277 CHANMODE_BUILD_TYPE(CHANMODE_FL_B);278 CHANMODE_BUILD_TYPE(CHANMODE_FL_C);279 CHANMODE_BUILD_TYPE(CHANMODE_FL_D);280 CHANMODE_BUILD_TYPE(CHANMODE_FL_E);281 *--s = '\0'; /* wipe out that last comma */282 /* also, if s - 1 is a comma (meaning we have no 'E' modes, delete that283 * comma since 'E' is non-standard */284 if (*(s - 1) == ',')285 *--s = '\0';286 287 /* add these two in for special mode support stuff */288 add_isupport("PREFIX", ISUPPORT_FL_STR, (char *)ircd.cmodes.prefix);289 add_isupport("CHANMODES", ISUPPORT_FL_STR, (char *)imodes);290 }291 292 int chanmode_set(unsigned char mode, client_t *cli, channel_t *chan, char *arg,293 int *argused) {294 struct chanmode *cmp = &ircd.cmodes.modes[mode];295 296 if (cmp->avail || !cmp->mask) /* only if it exists.. */297 return CHANMODE_NONEX;298 299 /* otherwise, just try and set the mode with the given functions, returning300 * the value as requested */301 return cmp->changefunc(cli, chan, mode, CHANMODE_SET, arg, argused);302 }303 304 int chanmode_setprefix(unsigned char prefix, channel_t *chan, char *arg,305 int *argused) {306 struct chanmode *cmp = ircd.cmodes.pfxmap[prefix];307 308 if (cmp == NULL)309 return CHANMODE_NONEX;310 311 /* found it, now set it */312 return cmp->changefunc(NULL, chan, cmp->mode, CHANMODE_SET, arg, argused);313 }314 315 int chanmode_unset(unsigned char mode, client_t *cli, channel_t *chan,316 char *arg, int *argused) {317 struct chanmode *cmp = &ircd.cmodes.modes[mode];318 319 if (cmp->avail || !cmp->mask) /* only if it exists.. */320 return CHANMODE_NONEX;321 322 /* otherwise, just try and set the mode with the given functions, returning323 * the value as requested */324 return cmp->changefunc(cli, chan, mode, CHANMODE_UNSET, arg, argused);325 }326 327 int chanmode_unsetprefix(unsigned char prefix, channel_t *chan, char *arg,328 int *argused) {329 struct chanmode *cmp = ircd.cmodes.pfxmap[prefix];330 331 if (cmp == NULL)332 return CHANMODE_NONEX;333 334 /* found it, now unset it */335 return cmp->changefunc(NULL, chan, cmp->mode, CHANMODE_UNSET, arg, argused);336 }337 338 int chanmode_query(unsigned char mode, channel_t *chan, char *arg,339 int *argused, void **state) {340 struct chanmode *cmp = &ircd.cmodes.modes[mode];341 342 if (cmp->avail || !cmp->mask) /* only if it exists.. */343 return CHANMODE_NONEX;344 345 /* let's ask 'em about it. */346 return cmp->queryfunc(chan, mode, arg, argused, state);347 }348 349 int chanmode_isprefix(channel_t *chan, client_t *cli, unsigned char prefix) {350 struct chanlink *clp;351 struct chanmode *cmp = ircd.cmodes.pfxmap[prefix];352 353 if (cmp == NULL)354 return 0; /* no such mode. */355 356 /* found it, now see if it's set */357 LIST_FOREACH(clp, &chan->users, lpchan) {358 if (clp->cli == cli)359 return chanlink_ismode(clp, cmp->mode);360 }361 362 /* not found, no status */363 return 0;364 }365 366 char *chanmode_getprefixes(channel_t *chan, client_t *cli) {367 static unsigned char pfx[64];368 struct chanlink *clp = find_chan_link(cli, chan);369 unsigned char *s = ircd.cmodes.pmodes;370 int i = 0;371 372 if (clp != NULL) {373 while (*s != '\0') {374 if (clp->flags & ircd.cmodes.modes[*s].umask)375 pfx[i++] = ircd.cmodes.modes[*s].prefix;376 s++;377 }378 }379 380 pfx[i] = '\0';381 return (char *)pfx;382 }383 384 /* this function returns two strings. the first is all the modes set on the385 * channel. the second is any arguments for the modes, but may or may not be386 * truncated. */387 const char **chanmode_getmodes(channel_t *chan) {388 static const char *ret[2];389 static unsigned char modes[64];390 static char *modebuf = NULL;391 static size_t mbsize = 64;392 int optused, len = 0, m = 1;393 unsigned char *i = ircd.cmodes.avail;394 void *state;395 396 if (modebuf == NULL)397 modebuf = malloc(mbsize);398 399 modes[0] = '+';400 *modebuf = '\0';401 402 while (*i != '\0') {403 state = NULL;404 405 if (chan->modes & ircd.cmodes.modes[*i].mask) {406 optused = mbsize - len;407 while (!chanmode_query(*i, chan, modebuf + len, &optused, &state)) {408 if (optused < 0) {409 mbsize += -optused + 2;410 modebuf = realloc(modebuf, mbsize);411 optused = mbsize - len;412 continue;413 }414 modes[m++] = *i;415 if (optused > 0) {416 len += optused;417 modebuf[len++] = ' ';418 modebuf[len] = '\0';419 }420 }421 }422 i++;423 }424 modes[m] = '\0';425 if (len > 0)426 modebuf[--len] = '\0'; /* nerf that extra space */427 428 ret[0] = (char *)modes;429 ret[1] = modebuf;430 return ret;431 }432 433 116 char **channel_mdext_iter(char **last) { 434 117 static int started = 0; -
trunk/ithildin/modules/ircd/channel.h
r801 r803 2 2 * channel.h: channel (mode) structures and prototypes 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * … … 10 10 #ifndef IRCD_CHANNEL_H 11 11 #define IRCD_CHANNEL_H 12 13 /*14 * channel mode fun. this is a lot like the usermode request/release system,15 * except that it's a bit more complicated. There are effectively six (yes,16 * six) types of channel modes. The first are types A-E, and work as follows:17 * Modes of type A add or remove an item from a list. They always have18 * parameters. Modes of type B change a setting. They always have a19 * parameter. Modes of type C change a setting, but only have a parameter when20 * being set. Modes of type E (yes E) change a setting, but only have a21 * parameter when being *unset*, and modes of type D change a boolean setting22 * and never take a parameter. Last but not least are 'PREFIX' modes which23 * change a flag on a user in the channel. All modes should take handler24 * functions which will be called when the mode is set/unset. The handler25 * functions should be:26 * int func(client *, channel *, unsigned char, int, char *, int *)27 * the first argument should be the client changing the mode (if any, there28 * won't always be one!) this is handy for passing errors or providing custom29 * behavior.30 * the next argument is the channel on which the mode is being set, the third31 * is the mode character given (this allows several modes to all coalesce into32 * one function if that behavior is desired), the fourth will be one of five33 * values:34 * - CHANMODE_SET to set the mode normally35 * - CHANMODE_UNSET to unset the * mode normally36 * - CHANMODE_CLEAR to clear any data held by the mode (free allocated data,37 * etc. called when a channel or mode is being destroyed/release)38 * the fifth argument is the next argument in the mode command. the final holds39 * a return value which specifies whether the argument was used or not. the40 * int should be set to 1 if the argument is used, and 0 if it isn't.41 *42 * return values:43 * CHANMODE_OK: Change/request was successfully made44 * CHANMODE_NOP: This was an n-op (nothing happened)45 * CHANMODE_FAIL: The change or request failed46 * CHANMODE_NONEX: The mode does not exist47 * CHANMODE_NOARG: The mode needed an argument and none was given48 * number > 0: Equivalent to CHANMODE_FAIL with the value of a numeric to49 * return to the user.50 */51 52 #define CHANMODE_FUNC(x) \53 int x(client_t *cli, channel_t *chan, unsigned char mode, int set, \54 char *arg __UNUSED, int *argused __UNUSED)55 typedef int (*chanmode_func)(client_t *, channel_t *, unsigned char,56 int, char *, int *);57 58 /*59 * Channel mode queries: These work a lot like the chanmode_func stuff but60 * do not expect a client. They exist simply to return state to people who61 * want to know. The important item is the fifth argument, a private state62 * variable. When querying begins the pointer value pointed to be state63 * must be NULL. The value may never be changed, and any memory allocations64 * occuring on behalf of the queryer will be freed on the final query when65 * no more data can be reset/queried.66 *67 * return values:68 * CHANMODE_OK: Change/request was successfully made69 * CHANMODE_FAIL: The change or request failed70 * CHANMODE_NONEX: The mode does not exist71 */72 #define CHANMODE_QUERY_FUNC(x) \73 int x(channel_t *chan, unsigned char mode, char *arg __UNUSED, \74 int *argused __UNUSED, void **state)75 typedef int (*chanmode_query_func)(channel_t *, unsigned char, char *,76 int *, void **);77 78 #define CHANMODE_FL_A 0x0179 #define CHANMODE_FL_B 0x0280 #define CHANMODE_FL_C 0x0481 #define CHANMODE_FL_D 0x0882 #define CHANMODE_FL_E 0x1083 #define CHANMODE_FL_PREFIX 0x2084 85 #define CHANMODE_SET 186 #define CHANMODE_UNSET 087 #define CHANMODE_CLEAR -188 89 #define CHANMODE_OK 090 #define CHANMODE_FAIL -191 #define CHANMODE_NOP -292 #define CHANMODE_NONEX -393 #define CHANMODE_NOARG -494 95 uint64_t chanmode_request(unsigned char, unsigned char *, int,96 chanmode_func, chanmode_query_func, size_t, void *);97 void chanmode_release(unsigned char);98 void chanmode_update_funcs(unsigned char, chanmode_func,99 chanmode_query_func);100 /* ways to set and unset channel modes. channel modes are typically set by101 * their mode character, but can also be set by prefix in the case of userflag102 * types. */103 int chanmode_set(unsigned char, client_t *, channel_t *, char *, int *);104 int chanmode_setprefix(unsigned char, channel_t *, char *, int *);105 106 int chanmode_unset(unsigned char, client_t *, channel_t *, char *, int *);107 int chanmode_unsetprefix(unsigned char, channel_t *, char *, int *);108 109 int chanmode_query(unsigned char, channel_t *, char *, int *, void **);110 111 #define chanmode_setflag(chan, themode) \112 (chan->modes |= ircd.cmodes.modes[themode].mask)113 #define chanmode_unsetflag(chan, themode) \114 (chan->modes &= ~ircd.cmodes.modes[themode].mask)115 116 /* various checks to see if channel modes are set in specific ways. you can117 * check to see if a flag-type mode is set on a channel, or you can check to118 * see if a user has a certain prefix. lastly, you can get the data for a119 * specific mode (data type) */120 #define chanmode_isset(chan, themode) \121 ((ircd.cmodes.modes[themode].avail == 0 && \122 ircd.cmodes.modes[themode].mask) ? \123 (chan->modes & ircd.cmodes.modes[themode].mask) : \124 0)125 126 int chanmode_isprefix(channel_t *, client_t *, unsigned char);127 128 #define chanlink_ismode(clp, mode) \129 (clp->flags & ircd.cmodes.modes[mode].umask)130 131 #define chanmode_getdata(chan, themode) \132 ((ircd.cmodes.modes[themode].avail == 0 && \133 ircd.cmodes.modes[themode].mdi != NULL) ? \134 (chan->mdext + ircd.cmodes.modes[themode].mdi->offset) : \135 NULL)136 137 #define chanmode_getintdata(chan, themode) \138 ((ircd.cmodes.modes[themode].avail == 0 && \139 ircd.cmodes.modes[themode].mdi != NULL) ? \140 *(((uint32_t *)(chan->mdext + \141 ircd.cmodes.modes[themode].mdi->offset))) : \142 0xFFFFFFFF)143 144 #define chanmode_getstrdata(chan, themode) \145 ((ircd.cmodes.modes[themode].avail == 0 && \146 ircd.cmodes.modes[themode].mdi != NULL) ? \147 ((char *)chan->mdext) + ircd.cmodes.modes[themode].mdi->offset : \148 NULL)149 150 /* this function returns a \0 terminated list of a client's prefixes in a151 * channel, in a static character array. */152 char *chanmode_getprefixes(channel_t *, client_t *);153 154 /* These two map prefixes to channel modes and vice versa. */155 #define chanmode_prefixtomode(c) \156 (ircd.cmodes.pfxmap[(unsigned char)c] != NULL ? \157 ircd.cmodes.pfxmap[(unsigned char)c]->mode : '\0')158 159 #define chanmode_modetoprefix(c) \160 (ircd.cmodes.modes[(unsigned char)c].umask ? \161 ircd.cmodes.modes[(unsigned char)c].prefix : '\0')162 163 const char **chanmode_getmodes(channel_t *);164 165 /* grab the offset of a mode. */166 #define modeoffset(mode) ircd.cmodes.modes[mode].mdi->offset167 168 struct chanmode {169 unsigned char mode; /* the mode character */170 char avail; /* whether it is available or not */171 172 uint64_t mask; /* the mask for this mode */173 short umask; /* the mask for a chanlink setting, if this is a174 chanuser mode */175 unsigned char prefix; /* if this is a user-flag, it has a prefix, this is176 the prefix (specified by the caller in extdata).177 no error checking is done on this value. */178 chanmode_func changefunc; /* the symbol/function to change the mode */179 chanmode_query_func queryfunc; /* the symbol/function to query the mode */180 int flags; /* flags given for this mode */181 struct mdext_item *mdi; /* the mdext_item which describes the channel mode.182 allocated automatically. */183 };184 12 185 13 LIST_HEAD(chanusers, chanlink); … … 207 35 208 36 unsigned int onchannel; /* number of people on channel */ 209 int flags;37 int flags; 210 38 struct chanusers users; /* list of users in channel */ 211 39 uint64_t modes; /* the flag-modes for the channel. */ -
trunk/ithildin/modules/ircd/client.c
r801 r803 2 2 * client.c: client structure management functions 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * 7 * This file provides mechanisms for creating/destroy client structures, as8 * well as registering them on the server and setting/unsetting user modeson9 * the m.7 * This file provides mechanisms for creating/destroying/manipulating 8 * user structures as well as registering them on the server. In addition 9 * the client history is kept here. 10 10 */ 11 11 … … 313 313 } 314 314 315 /* mode goodies below here */316 uint64_t usermode_request(unsigned char suggested, unsigned char *actual,317 int flags, int sflag, usermode_func changefunc) {318 struct usermode *md = NULL;319 uint64_t allmodes = 0;320 int i;321 unsigned char c;322 323 /* build a list of all our currently in-use modes (some modes are324 * inaccessible, so only do it for modes which have been initialized and325 * are unavailable */326 for (i = 0;i < 256;i++) {327 if (!ircd.umodes.modes[i].avail && ircd.umodes.modes[i].mask)328 allmodes |= ircd.umodes.modes[i].mask;329 }330 331 if (ircd.umodes.modes[suggested].avail)332 md = &ircd.umodes.modes[suggested];333 else {334 if (islower(suggested))335 c = toupper(suggested);336 else337 c = tolower(suggested);338 339 if (ircd.umodes.modes[c].avail)340 md = &ircd.umodes.modes[c];341 else {342 for (i = 0;i < 256;i++) {343 if (ircd.umodes.modes[i].avail && ircd.umodes.modes[i].mask) {344 md = &ircd.umodes.modes[i];345 break;346 }347 }348 349 /* *still* NULL? nothing free */350 if (md == NULL)351 return 0;352 }353 }354 355 md->avail = 0; /* mark it used */356 md->flags = flags;357 md->changefunc = changefunc;358 md->sflag = sflag;359 *actual = md->mode;360 361 allmodes |= md->mask;362 363 /* rebuild our mode string */364 strcpy(ircd.umodes.avail, usermode_getstr(allmodes, 0) + 1);365 366 return md->mask;367 }368 369 void usermode_release(unsigned char mode) {370 uint64_t allmodes = 0;371 int i;372 373 /* same as above, see what is available to rebuild the modestring */374 for (i = 0;i < 256;i++) {375 if (!ircd.umodes.modes[i].avail && ircd.umodes.modes[i].mask)376 allmodes |= ircd.umodes.modes[i].mask;377 }378 379 /* mark our released mode available, and remove it from the potential list380 * of modes */381 ircd.umodes.modes[mode].avail = 1;382 ircd.umodes.modes[mode].flags = 0;383 ircd.umodes.modes[mode].changefunc = NULL;384 allmodes &= ~ircd.umodes.modes[mode].mask;385 386 strcpy(ircd.umodes.avail, usermode_getstr(allmodes, 0) + 1);387 }388 389 void usermode_update_func(unsigned char mode, usermode_func changefunc) {390 struct usermode *md = &ircd.umodes.modes[mode];391 392 if (md->avail || !md->mask)393 return 0;394 395 md->changefunc = changefunc;396 }397 398 unsigned char *usermode_getstr(uint64_t modes, char global) {399 int i;400 int si; /* index to string */401 static unsigned char string[66];402 403 string[0] = '+'; /* prefix with a + */404 405 for (i = 0, si = 1;i < 256;i++) {406 if (modes & ircd.umodes.modes[i].mask &&407 (!global || ircd.umodes.modes[i].flags & USERMODE_FL_GLOBAL))408 string[si++] = ircd.umodes.modes[i].mode;409 }410 string[si] = '\0';411 412 return string;413 }414 415 uint64_t usermode_getmask(unsigned char *str, char global) {416 uint64_t mask = 0;417 unsigned char *s = str;418 419 while (*s) {420 if (!global || ircd.umodes.modes[*s].flags & USERMODE_FL_GLOBAL)421 mask |= ircd.umodes.modes[*s++].mask;422 else423 s++;424 }425 426 427 return mask;428 }429 430 void usermode_diff(uint64_t old, uint64_t new, char *result, char global) {431 int i;432 char *s = result;433 434 /* first see if they set anything */435 *s++ = '+';436 for (i = 0;i < 256;i++) {437 /* if this is a valid mode, see if it changed positively */438 if ((!global || ircd.umodes.modes[i].flags & USERMODE_FL_GLOBAL) &&439 !(old & ircd.umodes.modes[i].mask) &&440 (new & ircd.umodes.modes[i].mask))441 *s++ = ircd.umodes.modes[i].mode;442 }443 /* see if any changes were done positively, if not, dike the '+' */444 if (*(s - 1) == '+')445 s = s - 1;446 /* now see if they unset anything */447 *s++ = '-';448 for (i = 0;i < 256;i++) {449 /* if this is a valid mode, see if it changed negatively */450 if ((!global || ircd.umodes.modes[i].flags & USERMODE_FL_GLOBAL) &&451 (old & ircd.umodes.modes[i].mask) &&452 !(new & ircd.umodes.modes[i].mask))453 *s++ = ircd.umodes.modes[i].mode;454 }455 /* see if any changes were done negatively, if not, dike the '-' as done456 * above. */457 if (*(s - 1) == '-')458 s = s - 1;459 460 *s = '\0'; /* and terminate. */461 }462 463 int usermode_set(unsigned char mode, client_t *cli, client_t *on, char *arg,464 int *argused) {465 struct usermode *md = &ircd.umodes.modes[mode];466 467 if (md->avail || !md->mask)468 return 0;469 470 if (on->modes & md->mask)471 return 1; /* they already did it... */472 473 /* always call the set function. if they're not our client, we ignore the474 * return value. */475 if ((md->changefunc != NULL &&476 !md->changefunc(cli, on, mode, 1, arg, argused)) && MYCLIENT(on))477 return 0;478 /* if they're local, not opered, and the mode is an oper mode, don't let479 * them set it. */480 if (MYCLIENT(on) && !OPER(on) && md->flags & USERMODE_FL_OPER)481 return 0; /* no no. */482 483 /* okay, so, it's fine then, add away */484 on->modes |= md->mask;485 486 /* if the mode has a send flag, add them to the group for it (force the add487 * no matter what the settings for the sflag) */488 if (md->sflag > -1 && MYCLIENT(on))489 add_to_send_flag(md->sflag, on, true);490 491 return 1;492 }493 494 495 int usermode_unset(unsigned char mode, client_t *cli, client_t *on, char *arg,496 int *argused) {497 struct usermode *md = &ircd.umodes.modes[mode];498 499 if (md->avail || !md->mask)500 return 0;501 502 if (!(on->modes & md->mask))503 return 1; /* they're not set to that mode */504 505 /* always call the unset function. if they're not our client, we ignore506 * the return value. */507 if ((md->changefunc != NULL &&508 !md->changefunc(cli, on, mode, 0, arg, argused)) && MYCLIENT(on))509 return 0;510 511 /* approved for removal */512 on->modes &= ~md->mask;513 514 /* if the mode has a send flag, remove them from the group for it */515 if (md->sflag > -1 && MYCLIENT(on))516 remove_from_send_flag(md->sflag, on, true);517 518 return 1;519 }520 521 315 static void client_remove_history(client_t *); 522 316 -
trunk/ithildin/modules/ircd/client.h
r801 r803 2 2 * client.h: client structure declarations 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * … … 78 78 char *make_client_mask(char *mask); 79 79 80 /* mode stuff here. modules/systems should acquire and release modes as they81 * need them. You may not get the mode you asked for, if something else is82 * already using it, so don't assume that you did. The function will return83 * the bitmask used to check for the mode on a user's structure, and also place84 * the actual mode letter in a character, passed as a pointer. If you don't85 * care what mode you get specify '\0' as the suggested field. Also, if you86 * want all users who set your specific mode to be placed in a 'send flag'87 * group (see send.[ch]) pass the value of the flag to use, if not pass -1.88 * The last argument is the name of the function used to determine whether a89 * user can set/unset the node. The arguments are the client setting the mode,90 * the client on which the mode is being set, the mode character, an integer91 * specifying whether the mode is being set or unset, a pointer to an argument92 * (may be NULL), and a pointer to allow the function to specify whether the93 * mode used the argument or not. */94 #define USERMODE_FUNC(x) \95 int x(client_t *by __UNUSED, client_t *cli, unsigned char mode __UNUSED, \96 int set __UNUSED, char *arg __UNUSED, int *argused __UNUSED)97 typedef int (*usermode_func)(client_t *, client_t *, unsigned char, int,98 char *, int *);99 100 uint64_t usermode_request(unsigned char, unsigned char *, int, int,101 usermode_func);102 103 /* use this function to release a mode if you no longer care about it being set104 * on users. You are still responsible for clearing out the group if the mode105 * had one */106 void usermode_release(unsigned char);107 108 /* this function provides a way to update the assigned function for a109 * usermode */110 void usermode_update_func(unsigned char, usermode_func);111 112 /* this function returns a mode string from the passed 64bit integer. the113 * string is statically allocated inside the function, if global is unset, get114 * all usermodes, otherwise, get only global modes */115 unsigned char *usermode_getstr(uint64_t, char);116 117 /* this does the opposite of the above, it returns a mask from a given string118 * of modes, if global is non-false, the mask will only contain 'global' flags,119 * otherwise, all flags are returned. */120 uint64_t usermode_getmask(unsigned char *, char);121 122 /* this performs a 'diff' on the modes, and returns a string reflecting the123 * change from old modes to new modes, and places the result in 'result' */124 void usermode_diff(uint64_t, uint64_t, char *, char);125 126 /* this does all the work to set a mode on a user. it checks to see if they127 * can set it, and places them in any appropriate groups. if the function128 * succeeds it returns 1, if the user cannot set the mode it returns 0 */129 int usermode_set(unsigned char, client_t *, client_t *, char *, int *);130 131 /* this does like above, but unsetting instead of setting. */132 int usermode_unset(unsigned char, client_t *, client_t *, char *, int *);133 134 /* returns positive if a given mode is valid and set on a client */135 #define usermode_isset(client, themode) \136 ((ircd.umodes.modes[themode].avail == 0) ? \137 (client->modes & ircd.umodes.modes[themode].mask) : \138 0)139 140 /* we know we will create some modes, create special macros to check them */141 #define INVIS(client) (client->modes & ircd.umodes.modes['i'].mask)142 #define OPER(client) (client->modes & ircd.umodes.modes['o'].mask)143 144 struct usermode {145 unsigned char mode; /* the actual mode */146 char avail; /* 1 if available, 0 otherwise */147 #define USERMODE_FL_GLOBAL 0x1 /* the usermode is spread across the148 network */149 #define USERMODE_FL_OPER 0x2 /* the usermode is operator only */150 #define USERMODE_FL_PRESERVE 0x4 /* preserve the mode once set unless151 explicitly unset by the user */152 int flags; /* flags for the usermode */153 uint64_t mask; /* the bitmask for the mode */154 usermode_func changefunc; /* the changer function for the mode */155 int sflag; /* send flag (if any) for this mode. */156 };157 158 80 TAILQ_HEAD(client_history_list, client_history); 159 81 struct client_history { -
trunk/ithildin/modules/ircd/command.c
r787 r803 267 267 } 268 268 269 270 271 269 int command_add_hook(char *name, int client, hook_function_t hook, 272 270 int flags) { … … 406 404 * is. Without a distributed privilege understanding we have to 407 405 * assume positive intent. */ 408 if ((cmd->client.flags & COMMAND_FL_OPERATOR && !OPER(cli)) ||409 !BPRIV(cli, cmd->priv)) {406 if ((cmd->client.flags & COMMAND_FL_OPERATOR && 407 !CLIENT_OPERATOR(cli)) || !BPRIV(cli, cmd->priv)) { 410 408 sendto_one(cli, RPL_FMT(cli, ERR_NOPRIVILEGES)); 411 409 return ERR_NOPRIVILEGES; -
trunk/ithildin/modules/ircd/commands/names.c
r579 r803 80 80 * command for large channels :/ */ 81 81 LIST_FOREACH(clp, &chan->users, lpchan) { 82 if ( INVIS(clp->cli) && !see)82 if (CLIENT_INVISIBLE(clp->cli) && !see) 83 83 continue; 84 84 if (NAMEBUFLEN < len + ircd.limits.nicklen) { -
trunk/ithildin/modules/ircd/commands/notice.c
r579 r803 170 170 */ 171 171 if (*to == '$') { 172 if (cli != NULL && MYCLIENT(cli) && ! OPER(cli))172 if (cli != NULL && MYCLIENT(cli) && !CLIENT_OPERATOR(cli)) 173 173 sendto_one(cli, RPL_FMT(cli, ERR_NOPRIVILEGES)); 174 174 else -
trunk/ithildin/modules/ircd/commands/trace.c
r801 r803 100 100 /* non-operator traces must specify an exact client. other traces might do 101 101 * this too. if you remember we found cp up above. ;) */ 102 if (! OPER(cli) || cp != NULL) {102 if (!CLIENT_OPERATOR(cli) || cp != NULL) { 103 103 if (cp != NULL) { 104 104 /* found a client. Send the info */ 105 if ( OPER(cp))105 if (CLIENT_OPERATOR(cp)) 106 106 sendto_one(cli, RPL_FMT(cli, RPL_TRACEOPERATOR), 107 107 (cp->conn != NULL ? cp->conn->cls->name : "*"), … … 133 133 LIST_FOREACH(connp, ircd.connections.clients, lp) { 134 134 cp = connp->cli; 135 if ( OPER(cp))135 if (CLIENT_OPERATOR(cp)) 136 136 sendto_one(cli, RPL_FMT(cli, RPL_TRACEOPERATOR), connp->cls->name, 137 137 cli->nick, me.now - connp->last); -
trunk/ithildin/modules/ircd/commands/userhost.c
r579 r803 58 58 if ((target = find_client(cur)) != NULL) 59 59 len += snprintf(buf + len, 512 - len, "%s%s=%c%s@%s ", 60 target->nick, OPER(target) ? "*" : "",60 target->nick, CLIENT_OPERATOR(target) ? "*" : "", 61 61 AWAYMSG(target) ? '-' : '+', target->user, target->host); 62 62 -
trunk/ithildin/modules/ircd/commands/who.c
r579 r803 212 212 break; 213 213 case 'g': /* gcos field search */ 214 if (! OPER(cli) || oarg >= argc)214 if (!CLIENT_OPERATOR(cli) || oarg >= argc) 215 215 WHO_PARSE_SERROR(argv[0]); 216 216 who_opts.gcos = argv[oarg++]; … … 224 224 break; 225 225 case 'i': /* IP address search */ 226 if (! OPER(cli) || oarg >= argc)226 if (!CLIENT_OPERATOR(cli) || oarg >= argc) 227 227 WHO_PARSE_SERROR(argv[0]); 228 228 who_opts.ip = argv[oarg++]; … … 239 239 s++; 240 240 } 241 if (! OPER(cli)) /* restrict them to only +o */241 if (!CLIENT_OPERATOR(cli)) /* restrict them to only +o */ 242 242 who_opts.usermodes = (who_opts.usermodes & 243 243 ircd.umodes.modes['o'].mask); … … 325 325 static int who_check(client_t *cli, int showall) { 326 326 327 if ( INVIS(cli) && !showall)327 if (CLIENT_INVISIBLE(cli) && !showall) 328 328 return 0; /* can't see them. sneak sneak. */ 329 329 if (who_opts.flags.check_umode) { … … 460 460 continue; /* don't show them */ 461 461 sprintf(status, "%c%s%s", AWAYMSG(cp) != NULL ? 'G' : 'H', 462 OPER(cp) ? "*" : (INVIS(cp) && OPER(cli) ? "%" : ""), 462 CLIENT_OPERATOR(cp) ? "*" : 463 (CLIENT_INVISIBLE(cp) && CLIENT_OPERATOR(cli) ? "%" : ""), 463 464 chanmode_getprefixes(who_opts.channel, cp)); 464 465 sendto_one(cli, RPL_FMT(cli, RPL_WHOREPLY), … … 481 482 if (cp != NULL && who_check(cp, 1)) { 482 483 sprintf(status, "%c%s", AWAYMSG(cp) != NULL ? 'G' : 'H', 483 OPER(cp) ? "*" : (INVIS(cp) && OPER(cli) ? "%" : "")); 484 CLIENT_OPERATOR(cp) ? "*" : 485 (CLIENT_INVISIBLE(cp) && CLIENT_OPERATOR(cli) ? "%" : "")); 484 486 sendto_one(cli, RPL_FMT(cli, RPL_WHOREPLY), 485 487 who_opts.flags.show_chan ? who_first_visible(cli, cp) : … … 509 511 } else { 510 512 sprintf(status, "%c%s%s", AWAYMSG(cp) != NULL ? 'G' : 'H', 511 OPER(cp) ? "*" : (INVIS(cp) && 512 OPER(cli) ? "%" : ""), 513 CLIENT_OPERATOR(cp) ? "*" : 514 (CLIENT_INVISIBLE(cp) && 515 CLIENT_OPERATOR(cli) ? "%" : ""), 513 516 chanmode_getprefixes(who_opts.channel, cp)); 514 517 sendto_one(cli, RPL_FMT(cli, RPL_WHOREPLY), … … 535 538 } else { 536 539 sprintf(status, "%c%s", AWAYMSG(cp) != NULL ? 'G' : 'H', 537 OPER(cp) ? "*" : (INVIS(cp) && OPER(cli) ? "%" : "")); 540 CLIENT_OPERATOR(cp) ? "*" : 541 (CLIENT_INVISIBLE(cp) && 542 CLIENT_OPERATOR(cli) ? "%" : "")); 538 543 sendto_one(cli, RPL_FMT(cli, RPL_WHOREPLY), 539 544 who_opts.flags.show_chan ? who_first_visible(cli, cp) : -
trunk/ithildin/modules/ircd/commands/whois.c
r787 r803 113 113 sendto_one(cli, RPL_FMT(cli, RPL_WHOISSERVER), target->nick, 114 114 target->server->name, target->server->info); 115 if ( OPER(target))115 if (CLIENT_OPERATOR(target)) 116 116 sendto_one(cli, RPL_FMT(cli, RPL_WHOISOPERATOR), target->nick); 117 117 -
trunk/ithildin/modules/ircd/commands/xinfo.c
r787 r803 135 135 if (xhp->flags & XINFO_HANDLER_LOCAL && !MYCLIENT(cli)) 136 136 return COMMAND_WEIGHT_LOW; /* silently ignore these */ 137 if ((xhp->flags & XINFO_HANDLER_OPER && ! OPER(cli)) ||137 if ((xhp->flags & XINFO_HANDLER_OPER && !CLIENT_OPERATOR(cli)) || 138 138 !BPRIV(cli, xhp->priv)) { 139 139 sendto_one(cli, RPL_FMT(cli, ERR_NOPRIVILEGES)); … … 399 399 sendto_one(cli, RPL_FMT(cli, RPL_XINFO), "UPTIME", 400 400 time_conv_str(me.now - me.started)); 401 } else if (sp->conn != NULL && OPER(cli)) {401 } else if (sp->conn != NULL && CLIENT_OPERATOR(cli)) { 402 402 sendto_one(cli, RPL_FMT(cli, RPL_XINFO), "CONNECTED", 403 403 int_conv_str(sp->conn->signon)); … … 408 408 /* I'm restricting info about server connects to operators. I'm not sure 409 409 * what else would be amicable. */ 410 if ( OPER(cli) && scp != NULL) {410 if (CLIENT_OPERATOR(cli) && scp != NULL) { 411 411 sent++; 412 412 snprintf(rpl, XINFO_LEN, "ADDRESS %s PORT %s LAST %d INTERVAL %s", … … 419 419 /* last, but not least, report on interesting configuration bits about the 420 420 * server, if it has interesting configuration bits. */ 421 if ( OPER(cli) && clp != NULL) {421 if (CLIENT_OPERATOR(cli) && clp != NULL) { 422 422 char *s; 423 423 if (sp == NULL && (s = conf_find_entry("protocol", clp, 1)) != NULL) … … 440 440 if (xhp->flags & XINFO_HANDLER_LOCAL && !MYCLIENT(cli)) 441 441 continue; /* non-local */ 442 if ((xhp->flags & XINFO_HANDLER_OPER && ! OPER(cli)) ||442 if ((xhp->flags & XINFO_HANDLER_OPER && !CLIENT_OPERATOR(cli)) || 443 443 !BPRIV(cli, xhp->priv)) 444 444 continue; /* not privileged */ -
trunk/ithildin/modules/ircd/ircd.c
r801 r803 25 25 HOOK_FUNCTION(ircd_reload_hook); 26 26 HOOK_FUNCTION(ircd_loadmodule_hook); 27 28 /* this handles counting the default modes for stats, and ensuring +o is29 * maintained correctly. */30 USERMODE_FUNC(mode_set_counter);31 27 32 28 struct ircd_struct ircd; … … 115 111 else if ((now - cp->last) > (int)((float)cp->cls->freq * 0.5) && 116 112 !CONN_PINGSENT(cp)) { 117 /* use sendto_one_from here so that there is no prefix added,118 * apparently most clients balk at the prefix */119 113 sendto_serv_from(cp->srv, NULL, NULL, NULL, "PING", ":%s", 120 114 ircd.me->name); … … 179 173 } 180 174 181 /* the i/o counter goodies */182 USERMODE_FUNC(mode_set_counter) {183 int i;184 185 switch (mode) {186 case 'i':187 if (set)188 ircd.stats.net.visclients--;189 else190 ircd.stats.net.visclients++;191 break;192 case 'o':193 /* if this is our client, isn't set +o, and doesn't have the194 * privilege to do, deny. */195 if (MYCLIENT(cli) && by == cli && !OPER(cli) &&196 !BPRIV(cli, ircd.privileges.priv_operator))197 return 0;198 if (set) {199 ircd.stats.opers++;200 if (!MYCLIENT(cli))201 /* change them to the default operator privilege set */202 cli->pset = ircd.privileges.oper_set;203 hook_event(ircd.events.client_oper, cli);204 } else {205 /* remove them from any operator-only send flags, also remove206 * any operator-only modes they might have set */207 if (MYCLIENT(cli)) {208 unsigned char *s;209 for (s = ircd.umodes.avail;*s != '\0';s++) {210 if (ircd.umodes.modes[*s].flags & USERMODE_FL_OPER &&211 !(ircd.umodes.modes[*s].flags &212 USERMODE_FL_PRESERVE))213 usermode_unset(*s, cli, cli, NULL, NULL);214 }215 for (i = 0;i < ircd.sflag.size;i++) {216 if (ircd.sflag.flags[i].flags &217 SEND_LEVEL_OPERATOR &&218 !(ircd.sflag.flags[i].flags &219 SEND_LEVEL_PRESERVE))220 remove_from_send_flag(i, cli, true);221 }222 }223 ircd.stats.opers--;224 hook_event(ircd.events.client_deoper, cli);225 }226 break;227 }228 229 return 1;230 }231 232 175 MODULE_LOADER(ircd) { 233 176 conf_list_t *conf = *confdata; 234 177 int i; 235 unsigned char c;236 178 uint64_t ui64; 237 179 struct tm *tmtime; … … 330 272 ircd.privileges.priv_shs = create_privilege("see-hidden-servers", 331 273 PRIVILEGE_FL_BOOL, &ui64, NULL); 274 ircd.privileges.priv_shc = create_privilege("see-hidden-channels", 275 PRIVILEGE_FL_BOOL, &ui64, NULL); 332 276 ircd.privileges.priv_srch = create_privilege("see-real-client-host", 333 PRIVILEGE_FL_BOOL, &ui64, NULL); 334 } 335 336 /* set up our mode structures and acquire some modes */ 337 #define MODELOOP(from, to, array) do { \ 338 for (c = from;c <= to;c++, ui64 <<= 1) { \ 339 ircd.array.modes[c].mode = c; \ 340 ircd.array.modes[c].mask = ui64; \ 341 ircd.array.modes[c].avail = 1; \ 342 } \ 343 } while (0) 344 345 if (!get_module_savedata(savelist, "ircd.umodes", &ircd.umodes)) { 346 ui64 = 1; 347 MODELOOP('a', 'z', umodes); /* set a-z modes */ 348 MODELOOP('A', 'Z', umodes); /* and A-Z modes */ 349 MODELOOP('0', '9', umodes); /* and 0-9 modes */ 350 351 /* we know that all modes are free. grab i, o, and s */ 352 ircd.umodes.i = usermode_request('i', &c, USERMODE_FL_GLOBAL, -1, 353 mode_set_counter); 354 ircd.umodes.o = usermode_request('o', &c, USERMODE_FL_GLOBAL, 355 ircd.sflag.ops, mode_set_counter); 356 ircd.umodes.s = usermode_request('s', &c, 0, ircd.sflag.servmsg, 357 NULL); 358 } else { 359 /* Be sure to update the function address for this channel mode in 360 * case it moved.. */ 361 usermode_update_func(ircd.umodes.i, mode_set_counter); 362 usermode_update_func(ircd.umodes.o, mode_set_counter); 363 usermode_update_func(ircd.umodes.s, mode_set_counter); 364 } 365 366 if (!get_module_savedata(savelist, "ircd.cmodes", &ircd.cmodes)) { 367 ui64 = 1; 368 MODELOOP('a', 'z', cmodes); /* do the same for channel modes */ 369 MODELOOP('A', 'Z', cmodes); 370 MODELOOP('0', '9', cmodes); 371 } 277 PRIVILEGE_FL_BOOL, &ui64, NULL); 278 } 279 280 /* Initialize our modes. Pass the success of the savedata request in to 281 * the loader to tell it what to do. */ 282 usermode_init(get_module_savedata(savelist, "ircd.umodes", 283 &ircd.umodes)); 284 chanmode_init(get_module_savedata(savelist, "ircd.cmodes", 285 &ircd.cmodes)); 372 286 373 287 /* setup our events. started is always created, since it is destroyed … … 455 369 /* create numerics for messages (lazy-style) */ 456 370 /* common numerics */ 457 CMSG("001", ":Welcome to %s %s!%s@%s"); /* rpl_welcome */371 CMSG("001", ":Welcome to %s %s!%s@%s"); /* rpl_welcome */ 458 372 CMSG("002", ":Your host is %s, running version %s");/* rpl_yourhost */ 459 373 CMSG("003", ":This server was created %s"); /* rpl_created */ … … 465 379 "while and try again."); /* rpl_loadtoohigh */ 466 380 467 /* the error numerics */ 381 CMSG("334", ":%s"); /* rpl_commandsyntax */ 382 CMSG("367", "%s %s!%s@%s %s %lu"); /* rpl_banlist */ 383 CMSG("368", "%s :End of Channel Ban List"); /* rpl_endofbanlist */ 384 385 /* the error numerics */ 468 386 CMSG("401", "%s :No such nick/channel"); /* err_nosuchnick */ 469 387 CMSG("402", "%s :No such server"); /* err_nosuchserver */ 470 388 CMSG("403", "%s :No such channel"); /* err_nosuchchannel */ 389 CMSG("404", "%s :Cannot send to channel"); /* err_cannotsendtochan */ 471 390 /* err_toomanytargets */ 472 391 CMSG("407", "%s :Duplicate recipients, no message delivered."); 473 392 CMSG("421", "%s :Unknown command."); /* err_unknowncommand */ 474 393 CMSG("432", "%s :%s [%s]"); /* err_erroneousnickname */ 394 /* err_banonchan */ 395 CMSG("435", "%s %s :Cannot change to a banned nickname"); 396 /* err_bannickchange */ 397 CMSG("437", "%s :Cannot change nickname while banned or moderated on " 398 "channel."); 475 399 CMSG("441", "%s %s :They aren't on that channel."); 476 400 CMSG("442", "%s :You're not on that channel"); /* err_notonchannel */ … … 479 403 CMSG("462", ":You may not reregister"); /* err_alreadyregistered */ 480 404 CMSG("464", ":Password Incorrect"); /* err_passwdmismatch */ 405 CMSG("471", "%s :Cannot join channel (+l)"); /* err_channelisfull */ 406 CMSG("474", "%s :Cannot join channel (+b)"); /* err_bannedfromchan */ 407 CMSG("475", "%s :Cannot join channel (+k)"); /* err_badchannelkey */ 408 CMSG("478", "%s %s :Channel ban list is full"); /* err_banlistfull */ 481 409 CMSG("479", "%s :Channel name contains illegal characters"); 410 /* err_noprivileges */ 482 411 CMSG("481", ":Permission denied. " 483 412 "You do not have the correct privileges"); 413 /* err_chanoprivsneeded */ 414 CMSG("482", "%s :You're not a channel operator"); 415 /* err_chanbanreason */ 484 416 CMSG("485", "%s :Cannot %s channel (%s)"); 485 417 418 /* rpl_xinfo */ 486 419 CMSG("771", "%s :%s"); 487 420 } … … 608 541 isp = isp2; 609 542 } 543 544 usermode_deinit(reload); 545 chanmode_deinit(reload); 610 546 611 547 /* if we're reloading, do lots of preservation (we could just preserve the -
trunk/ithildin/modules/ircd/ircd.h
r801 r803 3 3 * holder 4 4 * 5 * Copyright 2002 the Ithildin Project.5 * Copyright 2002-2007 the Ithildin Project. 6 6 * See the COPYING file for more information on licensing and use. 7 7 * … … 36 36 37 37 #include "channel.h" 38 #include "chanmode.h" 38 39 #include "class.h" 39 40 #include "client.h" … … 47 48 #include "server.h" 48 49 #include "support.h" 50 #include "usermode.h" 49 51 50 52 HOOK_FUNCTION(ircd_listen_hook); … … 57 59 server_t *me; /* our server structure, not linked anywhere! */ 58 60 59 char address[HOSTLEN + 1];/* our server's address (for listen()) */60 char network[GCOSLEN + 1];/* the name of our network */61 char network_full[TOPICLEN + 1];/* the full network name. */62 const char *realversion; /* the version number in the module. */63 char version[GCOSLEN + 1];/* user defined server version */64 char vercomment[TOPICLEN + 1];/* user defined version 'comment' */65 char statsfile[PATH_MAX];/* stats file */66 int started; /* this is set to 1 once the daemon has61 char address[HOSTLEN + 1]; /* our server's address (for listen()) */ 62 char network[GCOSLEN + 1]; /* the name of our network */ 63 char network_full[TOPICLEN + 1];/* the full network name. */ 64 const char *realversion; /* the version number in the module. */ 65 char version[GCOSLEN + 1]; /* user defined server version */ 66 char vercomment[TOPICLEN + 1]; /* user defined version 'comment' */ 67 char statsfile[PATH_MAX]; /* stats file */ 68 int started; /* this is set to 1 once the daemon has 67 69 actually started */ 68 char ascstart[48];/* time started, used in RPL_CREATED and70 char ascstart[48]; /* time started, used in RPL_CREATED and 69 71 others, made once to save time */ 70 conf_list_t **confhead; /* the head of our configuration tree */71 72 char **argv; /* argv/argc for commands */73 int argc;72 conf_list_t **confhead; /* the head of our configuration tree */ 73 74 char **argv; /* argv/argc for commands */ 75 int argc; 74 76 75 77 /* XXX(?): (see 'triple-x inre 'tmpmsg' in the protocol structure, too). … … 86 88 struct { 87 89 struct { 88 int curclients;/* network-wide current/max clients */89 int maxclients;90 int visclients;/* -i clients */90 int curclients; /* network-wide current/max clients */ 91 int maxclients; 92 int visclients; /* -i clients */ 91 93 } net; 92 94 struct { 93 int curclients;/* server current/max clients */94 int maxclients;95 int unkclients;/* unknown clients */96 int servers;/* servers we have on us */95 int curclients; /* server current/max clients */ 96 int maxclients; 97 int unkclients; /* unknown clients */ 98 int servers; /* servers we have on us */ 97 99 } serv; 98 int channels;99 int servers;100 int opers;100 int channels; 101 int servers; 102 int opers; 101 103 } stats; 102 104 103 105 struct { 104 char line1[GCOSLEN + 1];105 char line2[GCOSLEN + 1];106 char line3[GCOSLEN + 3];106 char line1[GCOSLEN + 1]; 107 char line2[GCOSLEN + 1]; 108 char line3[GCOSLEN + 3]; 107 109 } admininfo; 108 110 109 111 struct { 110 int nicklen;111 int chanlen;112 int nicklen; 113 int chanlen; 112 114 } limits; 113 115 114 116 /* usermode data */ 115 117 struct { 116 unsigned char avail[64]; /* the available usermodes in string117 form (available for use, not for118 registering new modes with ;) */119 uint64_t i;/* the mask for +i */120 uint64_t o;/* the mask for +o */121 uint64_t s;/* the mask for +s */122 123 struct usermode modes[256];/* mode structures. a mode can be124 found by doing ircd.umodes.modes[c],125 where 'c' is the mode character126 you're after */118 unsigned char avail[64]; /* the available usermodes in string 119 form (available for use, not for 120 registering new modes with ;) */ 121 uint64_t mode_invis; /* the mask for +i */ 122 uint64_t mode_oper; /* the mask for +o */ 123 uint64_t mode_servmsg; /* the mask for +s */ 124 125 struct usermode modes[256]; /* mode structures. a mode can be 126 found by doing ircd.umodes.modes[c], 127 where 'c' is the mode character 128 you're after */ 127 129 } umodes; 128 130 129 131 /* channel mode data */ 130 132 struct { 131 unsigned char avail[64 + 5]; /* available channel modes */ 132 unsigned char prefix[64]; /* available prefix goodies */ 133 unsigned char pmodes[32]; /* modes which are prefixes, this is 134 mostly for internal use */ 135 136 struct chanmode modes[256]; /* mode structures. a mode can be 137 found by doing ircd.cmodes.modes[c], 138 where 'c' is the mode character 139 you're after. */ 140 struct chanmode *pfxmap[256]; /* map to chanmodes from their 141 prefixes. useful for fast lookups 142 and such. */ 133 unsigned char avail[64 + 5];/* available channel modes */ 134 unsigned char prefix[64]; /* available prefix goodies */ 135 unsigned char pmodes[32]; /* modes which are prefixes, this is 136 mostly for internal use */ 137 138 struct chanmode modes[256]; /* mode structures. a mode can be 139 found by doing ircd.cmodes.modes[c], 140 where 'c' is the mode character 141 you're after. */ 142 struct chanmode *pfxmap[256];/* map to chanmodes from their 143 prefixes. useful for fast lookups 144 and such. */ 145 146 unsigned char mode_ban; /* +b (ban) */ 147 unsigned char mode_key; /* +k (key) */ 148 unsigned char mode_limit; /* +l (limit) */ 149 unsigned char mode_mod; /* +m (moderated) */ 150 unsigned char mode_nextern; /* +n (no external msgs) */ 151 unsigned char mode_op; /* +o (chanop) */ 152 unsigned char mode_secret; /* +s (secret) */ 153 unsigned char mode_voice; /* +v (chan 'voice') */ 143 154 } cmodes; 144 155 … … 146 157 /* called once when the server is completely started, this allows 147 158 * necessary functions to be called when everything is ready */ 148 event_t *started;159 event_t *started; 149 160 150 161 /* the three connection stage events, used by the acl system, and 151 162 * maybe others. connection_registered only fires for CLIENTS 152 163 * which are registered. */ 153 event_t *connection_connected;154 event_t *connection_unregistered;155 event_t *connection_registered;164 event_t *connection_connected; 165 event_t *connection_unregistered; 166 event_t *connection_registered; 156 167 157 168 /* other events */ … … 164 175 event_t *unregister_client; /* called from destroy_client() for all 165 176 clients being destroyed */ 166 event_t *client_nick; /* hooked when a client changes its177 event_t *client_nick; /* hooked when a client changes its 167 178 nickname. */ 168 event_t *client_oper; /* hooked when a client goes +o */169 event_t *client_deoper; /* hooked when a client goes -o */179 event_t *client_oper; /* hooked when a client goes +o */ 180 event_t *client_deoper; /* hooked when a client goes -o */ 170 181 event_t *channel_create; /* hooked when a channel record is 171 182 initially created. */ 172 183 event_t *channel_destroy; /* same, but for destruction. */ 173 event_t *channel_add; /* hooked when a client joins a channel */174 event_t *channel_del; /* same, but with part */184 event_t *channel_add; /* hooked when a client joins a channel */ 185 event_t *channel_del; /* same, but with part */ 175 186 176 187 event_t *server_introduce; /* called when server_introduce() is … … 233 244 234 245 struct { 235 LIST_HEAD(, message_set) *sets; /* our list of message sets */236 message_t *msgs; /* array of different messages */237 int count;238 int size;/* size of the 'msgs' array */246 LIST_HEAD(, message_set) *sets;/* our list of message sets */ 247 message_t *msgs; /* array of different messages */ 248 int count; 249 int size; /* size of the 'msgs' array */ 239 250 } messages; 240 251 241 252 struct { 242 253 struct send_flag *flags; /* array of 'send_flag' structures */ 243 int size; /* size of the array */254 int size; /* size of the array */ 244 255 245 256 int ops; /* +o users */ 246 int servmsg; /* +s users */257 int servmsg; /* +s users */ 247 258 } sflag; 248 259 249 260 struct { 250 LIST_HEAD(, privilege_set) *sets; /* our list of privilege sets */261 LIST_HEAD(, privilege_set) *sets;/* our list of privilege sets */ 251 262 privilege_set_t *oper_set; /* default operator privileges */ 252 privilege_t *privs; /* array of privileges */253 int count;254 int size;/* size of the privs array */263 privilege_t *privs; /* array of privileges */ 264 int count; 265 int size; /* size of the privs array */ 255 266 256 267 /* actual privileges created by the daemon are here */ 257 int priv_operator;/* the 'operator' privilege, allows268 int priv_operator; /* the 'operator' privilege, allows 258 269 changing of the 'o' usermode */ 259 int priv_shs;/* this privilege allows users to see270 int priv_shs; /* this privilege allows users to see 260 271 information about hidden servers */ 261 int priv_srch; /* this privilege allows users to see the 272 int priv_shc; /* this privilege allows users to see 273 hidden channels */ 274 int priv_srch; /* this privilege allows users to see the 262 275 original host of users (if it has been 263 changed) */276 changed) (see real client host) */ 264 277 #define CAN_SEE_SERVER(cli, srv) \ 265 278 (srv->flags & IRCD_SERVER_HIDDEN ? BPRIV(cli, ircd.privileges.priv_shs) : 1) -
trunk/ithildin/modules/ircd/send.c
r787 r803 140 140 /* this macro is used below to clear out temporary structures after doing a 141 141 * round of sends. */ 142 #define CLEAR_SEND_TEMPS() do { \143 protocol_t *_pp; \144 LIST_FOREACH(_pp, ircd.lists.protocols, lp) { \145 _pp->tmpmsg = NULL; \146 } \142 #define CLEAR_SEND_TEMPS() do { \ 143 protocol_t *_pp; \ 144 LIST_FOREACH(_pp, ircd.lists.protocols, lp) { \ 145 _pp->tmpmsg = NULL; \ 146 } \ 147 147 memset(ircd.sends, 0, maxsockets); \ 148 148 } while (0) … … 629 629 !BPRIV(cli, ircd.sflag.flags[flg].priv)) || 630 630 (ircd.sflag.flags[flg].flags & SEND_LEVEL_OPERATOR && 631 ! OPER(cli))))631 !CLIENT_OPERATOR(cli)))) 632 632 return ERR_NOPRIVILEGES; 633 633 -
trunk/ithildin/modules/ircd/send.h
r787 r803 177 177 #define RPL_LOADTOOHIGH 263 178 178 179 #define RPL_COMMANDSYNTAX 334 180 #define RPL_BANLIST 367 181 #define RPL_ENDOFBANLIST 368 182 179 183 #define ERR_NOSUCHNICK 401 180 184 #define ERR_NOSUCHSERVER 402 181 185 #define ERR_NOSUCHCHANNEL 403 186 #define ERR_CANNOTSENDTOCHAN 404 182 187 #define ERR_TOOMANYTARGETS 407 183 188 #define ERR_UNKNOWNCOMMAND 421 184 189 #define ERR_ERRONEOUSNICKNAME 432 190 #define ERR_BANONCHAN 435 191 #define ERR_BANNICKCHANGE 437 185 192 #define ERR_USERNOTINCHANNEL 441 186 193 #define ERR_NOTONCHANNEL 442 … … 189 196 #define ERR_ALREADYREGISTERED 462 190 197 #define ERR_PASSWDMISMATCH 464 198 #define ERR_CHANNELISFULL 471 199 #define ERR_BANNEDFROMCHAN 474 200 #define ERR_BADCHANNELKEY 475 201 #define ERR_BANLISTFULL 478 191 202 #define ERR_BADCHANNAME 479 192 203 #define ERR_NOPRIVILEGES 481 204 #define ERR_CHANOPRIVSNEEDED 482 193 205 #define ERR_CHANBANREASON 485 194 206 -
trunk/ithildin/modules/ircd/usermode.c
r801 r803 1 1 /* 2 * client.c: client structure management functions2 * usermode.c: client (user) mode management functions 3 3 * 4 * Copyright 2002 the Ithildin Project.4 * Copyright 2002-2007 the Ithildin Project. 5 5 * See the COPYING file for more information on licensing and use. 6 6 * 7 * This file provides mechanisms for creating/destroy client structures, as 8 * well as registering them on the server and setting/unsetting user modes on 9 * them. 7 * This file contains the generic code for manipulating user modes, as well 8 * as some base usermodes supported by the server. 10 9 */ 11 10 … … 16 15 IDSTRING(rcsid, "$Id$"); 17 16 18 /* this creates a new client structure and places it in the 'conn' structure 19 * passed, if any. If there is no conn structure, then this is either a remote 20 * client or a pseudo-client. */ 21 client_t *create_client(connection_t *conn) { 22 client_t *cp = calloc(1, sizeof(client_t)); 23 cp->conn = conn; 24 25 /* set connection time/etc */ 26 cp->ts = cp->last = me.now; 27 cp->orighost = cp->host; /* don't forget this one */ 28 29 cp->mdext = mdext_alloc(ircd.mdext.client); 30 31 if (conn != NULL) { 32 conn->cli = cp; 33 cp->pset = conn->cls->pset; 34 get_socket_address(isock_raddr(conn->sock), cp->ip, IPADDR_MAXLEN + 1, 35 NULL); 36 ircd.stats.serv.unkclients++; 37 } else 38 cp->pset = LIST_FIRST(ircd.privileges.sets); 39 40 LIST_INSERT_HEAD(ircd.lists.clients, cp, lp); 41 return cp; 42 } 43 44 /* this destroys a client, and if it is our connection, also destroys the 45 * client's connection. do *NOT* try to destroy connections after 46 * destroying their clients. */ 47 void destroy_client(client_t *cli, char *msg) { 48 struct chanlink *clp; 49 unsigned char *s; 50 51 if (cli->flags & IRCD_CLIENT_HISTORY) { 52 /* just return the memory */ 53 mdext_free(ircd.mdext.client, cli->mdext); 54 free(cli); 55 return; 56 } 57 58 if (CLIENT_REGISTERED(cli)) { /* only do this stuff for registered 59 clients */ 60 if (MYCLIENT(cli)) 61 hook_event(ircd.events.client_disconnect, cli); 62 hook_event(ircd.events.unregister_client, cli); 63 64 /* if the client hasn't been flagged as 'killed' (that is, destroyed by 65 * some other action) we propogate the quit message to other servers. 66 * whatever betide we send the quit to all local users! */ 67 if (!(cli->flags & IRCD_CLIENT_KILLED)) 68 sendto_serv_butone(cli->server, cli, NULL, NULL, "QUIT", ":%s", 69 msg); 70 71 clp = LIST_FIRST(&cli->chans); 72 if (clp != NULL) { 73 /* if we are in channels */ 74 /* don't send a message to our user */ 75 if (MYCLIENT(cli)) 76 ircd.sends[cli->conn->sock->fd] = 1; 77 sendto_common_channels(cli, NULL, "QUIT", ":%s", msg); 78 while (clp != NULL) { 79 del_from_channel(cli, clp->chan, true); 80 clp = LIST_FIRST(&cli->chans); 81 } 82 } 83 84 /* add them to the client history, and also sign them off. */ 85 client_add_history(cli); 86 /* and mark the client structure as a 'history' structure */ 87 cli->flags |= IRCD_CLIENT_HISTORY; 88 89 /* unset all their modes. this allows any resource cleanup to be 90 * handled by individual mode handlers. */ 91 s = ircd.umodes.avail; 92 while (*s) 93 usermode_unset(*s++, cli, cli, NULL, NULL); 94 95 if (MYCLIENT(cli)) { 96 int i; 97 98 ircd.stats.serv.curclients--; 99 for (i = 0;i < ircd.sflag.size;i++) 100 remove_from_send_flag(i, cli, true); 101
