X-Git-Url: https://jfr.im/git/solanum.git/blobdiff_plain/79435744c7b57fa830b8e4e7c7c8a9adf63f52b5..c33da0d24ed3cd737263e0469fa600681ec75d42:/ircd/channel.c diff --git a/ircd/channel.c b/ircd/channel.c index 717df263..0a01f972 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -38,7 +38,6 @@ #include "s_conf.h" /* ConfigFileEntry, ConfigChannel */ #include "s_newconf.h" #include "logger.h" -#include "ipv4_from_ipv6.h" #include "s_assert.h" struct config_channel_entry ConfigChannel; @@ -127,10 +126,10 @@ send_channel_join(struct Channel *chptr, struct Client *client_p) if (!IsClient(client_p)) return; - sendto_channel_local_with_capability(ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN, chptr, ":%s!%s@%s JOIN %s", + sendto_channel_local_with_capability(client_p, ALL_MEMBERS, NOCAPS, CLICAP_EXTENDED_JOIN, chptr, ":%s!%s@%s JOIN %s", client_p->name, client_p->username, client_p->host, chptr->chname); - sendto_channel_local_with_capability(ALL_MEMBERS, CLICAP_EXTENDED_JOIN, NOCAPS, chptr, ":%s!%s@%s JOIN %s %s :%s", + sendto_channel_local_with_capability(client_p, ALL_MEMBERS, CLICAP_EXTENDED_JOIN, NOCAPS, chptr, ":%s!%s@%s JOIN %s %s :%s", client_p->name, client_p->username, client_p->host, chptr->chname, EmptyString(client_p->user->suser) ? "*" : client_p->user->suser, client_p->info); @@ -222,6 +221,7 @@ void add_user_to_channel(struct Channel *chptr, struct Client *client_p, int flags) { struct membership *msptr; + rb_dlink_node *p; s_assert(client_p->user != NULL); if(client_p->user == NULL) @@ -233,7 +233,17 @@ add_user_to_channel(struct Channel *chptr, struct Client *client_p, int flags) msptr->client_p = client_p; msptr->flags = flags; - rb_dlinkAdd(msptr, &msptr->usernode, &client_p->user->channel); + RB_DLINK_FOREACH(p, client_p->user->channel.head) + { + struct membership *ms2 = p->data; + if (irccmp(chptr->chname, ms2->chptr->chname) < 0) + break; + } + if (p == NULL) + rb_dlinkAddTail(msptr, &msptr->usernode, &client_p->user->channel); + else + rb_dlinkAddBefore(p, msptr, &msptr->usernode, &client_p->user->channel); + rb_dlinkAdd(msptr, &msptr->channode, &chptr->members); if(MyClient(client_p)) @@ -336,23 +346,23 @@ invalidate_bancache_user(struct Client *client_p) /* check_channel_name() * * input - channel name - * output - 1 if valid channel name, else 0 + * output - true if valid channel name, else false * side effects - */ -int +bool check_channel_name(const char *name) { s_assert(name != NULL); if(name == NULL) - return 0; + return false; for (; *name; ++name) { if(!IsChanChar(*name)) - return 0; + return false; } - return 1; + return true; } /* free_channel_list() @@ -424,6 +434,47 @@ channel_pub_or_secret(struct Channel *chptr) return ("*"); } +int +iter_comm_channels_step(rb_dlink_node *pos1, rb_dlink_node *pos2, + struct membership **ms1, struct membership **ms2, + struct Channel **chptr) +{ + *ms1 = pos1 ? pos1->data : NULL; + *ms2 = pos2 ? pos2->data : NULL; + + /* we're at the end */ + if (*ms1 == NULL && *ms2 == NULL) + return 0; + + /* one side is at the end, keep stepping the other one */ + if (*ms1 == NULL || *ms2 == NULL) + { + *chptr = *ms1 != NULL ? (*ms1)->chptr : (*ms2)->chptr; + return 1; + } + + /* common channel */ + if ((*ms1)->chptr == (*ms2)->chptr) + { + *chptr = (*ms1)->chptr; + return 1; + } + + /* null out the channel that's further ahead; we'll get to it later */ + if (irccmp((*ms1)->chptr->chname, (*ms2)->chptr->chname) > 0) + { + *ms1 = NULL; + *chptr = (*ms2)->chptr; + return 1; + } + else + { + *ms2 = NULL; + *chptr = (*ms1)->chptr; + return 1; + } +} + /* channel_member_names() * * input - channel to list, client to list to, show endofnames @@ -436,11 +487,6 @@ channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eo struct membership *msptr; struct Client *target_p; rb_dlink_node *ptr; - char lbuf[BUFSIZE]; - char *t; - int mlen; - int tlen; - int cur_len; int is_member; int stack = IsCapable(client_p, CLICAP_MULTI_PREFIX); @@ -448,11 +494,11 @@ channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eo { is_member = IsMember(client_p, chptr); - cur_len = mlen = sprintf(lbuf, form_str(RPL_NAMREPLY), - me.name, client_p->name, - channel_pub_or_secret(chptr), chptr->chname); - - t = lbuf + cur_len; + send_multiline_init(client_p, " ", form_str(RPL_NAMREPLY), + me.name, + client_p->name, + channel_pub_or_secret(chptr), + chptr->chname); RB_DLINK_FOREACH(ptr, chptr->members.head) { @@ -464,49 +510,21 @@ channel_member_names(struct Channel *chptr, struct Client *client_p, int show_eo if (IsCapable(client_p, CLICAP_USERHOST_IN_NAMES)) { - /* space, possible "@+" prefix */ - if (cur_len + strlen(target_p->name) + strlen(target_p->username) + strlen(target_p->host) + 5 >= BUFSIZE - 5) - { - *(t - 1) = '\0'; - sendto_one(client_p, "%s", lbuf); - cur_len = mlen; - t = lbuf + mlen; - } - - tlen = sprintf(t, "%s%s!%s@%s ", find_channel_status(msptr, stack), - target_p->name, target_p->username, target_p->host); + send_multiline_item(client_p, "%s%s!%s@%s", + find_channel_status(msptr, stack), + target_p->name, + target_p->username, + target_p->host); } else { - /* space, possible "@+" prefix */ - if(cur_len + strlen(target_p->name) + 3 >= BUFSIZE - 3) - { - *(t - 1) = '\0'; - sendto_one(client_p, "%s", lbuf); - cur_len = mlen; - t = lbuf + mlen; - } - - tlen = sprintf(t, "%s%s ", find_channel_status(msptr, stack), - target_p->name); + send_multiline_item(client_p, "%s%s", + find_channel_status(msptr, stack), + target_p->name); } - - cur_len += tlen; - t += tlen; } - /* The old behaviour here was to always output our buffer, - * even if there are no clients we can show. This happens - * when a client does "NAMES" with no parameters, and all - * the clients on a -sp channel are +i. I dont see a good - * reason for keeping that behaviour, as it just wastes - * bandwidth. --anfl - */ - if(cur_len != mlen) - { - *(t - 1) = '\0'; - sendto_one(client_p, "%s", lbuf); - } + send_multiline_fini(client_p, NULL); } if(show_eon) @@ -538,89 +556,41 @@ del_invite(struct Channel *chptr, struct Client *who) static int is_banned_list(struct Channel *chptr, rb_dlink_list *list, struct Client *who, struct membership *msptr, - const char *s, const char *s2, const char **forward) + const struct matchset *ms, const char **forward) { - char src_host[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_althost[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_ip4host[NICKLEN + USERLEN + HOSTLEN + 6]; - char *s3 = NULL; - char *s4 = NULL; - struct sockaddr_in ip4; + struct matchset ms_; rb_dlink_node *ptr; struct Ban *actualBan = NULL; struct Ban *actualExcept = NULL; - if(!MyClient(who)) + if (!MyClient(who)) return 0; - /* if the buffers havent been built, do it here */ - if(s == NULL) + if (ms == NULL) { - sprintf(src_host, "%s!%s@%s", who->name, who->username, who->host); - sprintf(src_iphost, "%s!%s@%s", who->name, who->username, who->sockhost); - - s = src_host; - s2 = src_iphost; + matchset_for_client(who, &ms_); + ms = &ms_; } - if(who->localClient->mangledhost != NULL) - { - /* if host mangling mode enabled, also check their real host */ - if(!strcmp(who->host, who->localClient->mangledhost)) - { - sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->orighost); - s3 = src_althost; - } - /* if host mangling mode not enabled and no other spoof, - * also check the mangled form of their host */ - else if (!IsDynSpoof(who)) - { - sprintf(src_althost, "%s!%s@%s", who->name, who->username, who->localClient->mangledhost); - s3 = src_althost; - } - } -#ifdef RB_IPV6 - if(GET_SS_FAMILY(&who->localClient->ip) == AF_INET6 && - ipv4_from_ipv6((const struct sockaddr_in6 *)&who->localClient->ip, &ip4)) - { - sprintf(src_ip4host, "%s!%s@", who->name, who->username); - s4 = src_ip4host + strlen(src_ip4host); - rb_inet_ntop_sock((struct sockaddr *)&ip4, - s4, src_ip4host + sizeof src_ip4host - s4); - s4 = src_ip4host; - } -#endif RB_DLINK_FOREACH(ptr, list->head) { actualBan = ptr->data; - if(match(actualBan->banstr, s) || - match(actualBan->banstr, s2) || - match_cidr(actualBan->banstr, s2) || - match_extban(actualBan->banstr, who, chptr, CHFL_BAN) || - (s3 != NULL && match(actualBan->banstr, s3)) -#ifdef RB_IPV6 - || - (s4 != NULL && (match(actualBan->banstr, s4) || match_cidr(actualBan->banstr, s4))) -#endif - ) + if (matches_mask(ms, actualBan->banstr)) break; - else - actualBan = NULL; + if (match_extban(actualBan->banstr, who, chptr, CHFL_BAN)) + break; + actualBan = NULL; } - if((actualBan != NULL) && ConfigChannel.use_except) + if ((actualBan != NULL) && ConfigChannel.use_except) { RB_DLINK_FOREACH(ptr, chptr->exceptlist.head) { actualExcept = ptr->data; /* theyre exempted.. */ - if(match(actualExcept->banstr, s) || - match(actualExcept->banstr, s2) || - match_cidr(actualExcept->banstr, s2) || - match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION) || - (s3 != NULL && match(actualExcept->banstr, s3))) + if (matches_mask(ms, actualExcept->banstr) || + match_extban(actualExcept->banstr, who, chptr, CHFL_EXCEPTION)) { /* cache the fact theyre not banned */ if(msptr != NULL) @@ -666,8 +636,9 @@ is_banned_list(struct Channel *chptr, rb_dlink_list *list, */ int is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr, - const char *s, const char *s2, const char **forward) + const struct matchset *ms, const char **forward) { +#if 0 if (chptr->last_checked_client != NULL && who == chptr->last_checked_client && chptr->last_checked_type == CHFL_BAN && @@ -680,6 +651,9 @@ is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr, chptr->last_checked_ts = rb_current_time(); return chptr->last_checked_result; +#else + return is_banned_list(chptr, &chptr->banlist, who, msptr, ms, forward); +#endif } /* is_quieted() @@ -691,8 +665,9 @@ is_banned(struct Channel *chptr, struct Client *who, struct membership *msptr, */ int is_quieted(struct Channel *chptr, struct Client *who, struct membership *msptr, - const char *s, const char *s2) + const struct matchset *ms) { +#if 0 if (chptr->last_checked_client != NULL && who == chptr->last_checked_client && chptr->last_checked_type == CHFL_QUIET && @@ -705,6 +680,9 @@ is_quieted(struct Channel *chptr, struct Client *who, struct membership *msptr, chptr->last_checked_ts = rb_current_time(); return chptr->last_checked_result; +#else + return is_banned_list(chptr, &chptr->quietlist, who, msptr, ms, NULL); +#endif } /* can_join() @@ -720,10 +698,7 @@ can_join(struct Client *source_p, struct Channel *chptr, const char *key, const rb_dlink_node *invite = NULL; rb_dlink_node *ptr; struct Ban *invex = NULL; - char src_host[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_althost[NICKLEN + USERLEN + HOSTLEN + 6]; - int use_althost = 0; + struct matchset ms; int i = 0; hook_data_channel moduledata; @@ -733,26 +708,9 @@ can_join(struct Client *source_p, struct Channel *chptr, const char *key, const moduledata.chptr = chptr; moduledata.approved = 0; - sprintf(src_host, "%s!%s@%s", source_p->name, source_p->username, source_p->host); - sprintf(src_iphost, "%s!%s@%s", source_p->name, source_p->username, source_p->sockhost); - if(source_p->localClient->mangledhost != NULL) - { - /* if host mangling mode enabled, also check their real host */ - if(!strcmp(source_p->host, source_p->localClient->mangledhost)) - { - sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->orighost); - use_althost = 1; - } - /* if host mangling mode not enabled and no other spoof, - * also check the mangled form of their host */ - else if (!IsDynSpoof(source_p)) - { - sprintf(src_althost, "%s!%s@%s", source_p->name, source_p->username, source_p->localClient->mangledhost); - use_althost = 1; - } - } + matchset_for_client(source_p, &ms); - if((is_banned(chptr, source_p, NULL, src_host, src_iphost, forward)) == CHFL_BAN) + if((is_banned(chptr, source_p, NULL, &ms, forward)) == CHFL_BAN) { moduledata.approved = ERR_BANNEDFROMCHAN; goto finish_join_check; @@ -782,11 +740,8 @@ can_join(struct Client *source_p, struct Channel *chptr, const char *key, const RB_DLINK_FOREACH(ptr, chptr->invexlist.head) { invex = ptr->data; - if(match(invex->banstr, src_host) - || match(invex->banstr, src_iphost) - || match_cidr(invex->banstr, src_iphost) - || match_extban(invex->banstr, source_p, chptr, CHFL_INVEX) - || (use_althost && match(invex->banstr, src_althost))) + if (matches_mask(&ms, invex->banstr) || + match_extban(invex->banstr, source_p, chptr, CHFL_INVEX)) break; } if(ptr == NULL) @@ -877,8 +832,8 @@ can_send(struct Channel *chptr, struct Client *source_p, struct membership *mspt if(can_send_banned(msptr)) moduledata.approved = CAN_SEND_NO; } - else if(is_banned(chptr, source_p, msptr, NULL, NULL, NULL) == CHFL_BAN - || is_quieted(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN) + else if(is_banned(chptr, source_p, msptr, NULL, NULL) == CHFL_BAN + || is_quieted(chptr, source_p, msptr, NULL) == CHFL_BAN) moduledata.approved = CAN_SEND_NO; } @@ -901,12 +856,12 @@ can_send(struct Channel *chptr, struct Client *source_p, struct membership *mspt * inputs - flag 0 if PRIVMSG 1 if NOTICE. RFC * says NOTICE must not auto reply * - pointer to source Client - * - pointer to target channel - * output - 1 if target is under flood attack + * - pointer to target channel + * output - true if target is under flood attack * side effects - check for flood attack on target chptr */ -int -flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr, char *chname) +bool +flood_attack_channel(enum message_type msgtype, struct Client *source_p, struct Channel *chptr, char *chname) { int delta; @@ -939,17 +894,17 @@ flood_attack_channel(int p_or_n, struct Client *source_p, struct Channel *chptr, /* Add a bit of penalty */ chptr->received_number_of_privmsgs += 2; } - if(MyClient(source_p) && (p_or_n != 1)) + if(MyClient(source_p) && (msgtype != MESSAGE_TYPE_NOTICE)) sendto_one(source_p, ":%s NOTICE %s :*** Message to %s throttled due to flooding", me.name, source_p->name, chptr->chname); - return 1; + return true; } else chptr->received_number_of_privmsgs++; } - return 0; + return false; } /* find_bannickchange_channel() @@ -962,14 +917,12 @@ find_bannickchange_channel(struct Client *client_p) struct Channel *chptr; struct membership *msptr; rb_dlink_node *ptr; - char src_host[NICKLEN + USERLEN + HOSTLEN + 6]; - char src_iphost[NICKLEN + USERLEN + HOSTLEN + 6]; + struct matchset ms; if (!MyClient(client_p)) return NULL; - sprintf(src_host, "%s!%s@%s", client_p->name, client_p->username, client_p->host); - sprintf(src_iphost, "%s!%s@%s", client_p->name, client_p->username, client_p->sockhost); + matchset_for_client(client_p, &ms); RB_DLINK_FOREACH(ptr, client_p->user->channel.head) { @@ -983,8 +936,8 @@ find_bannickchange_channel(struct Client *client_p) if (can_send_banned(msptr)) return chptr; } - else if (is_banned(chptr, client_p, msptr, src_host, src_iphost, NULL) == CHFL_BAN - || is_quieted(chptr, client_p, msptr, src_host, src_iphost) == CHFL_BAN) + else if (is_banned(chptr, client_p, msptr, &ms, NULL) == CHFL_BAN + || is_quieted(chptr, client_p, msptr, &ms) == CHFL_BAN) return chptr; } return NULL; @@ -1188,7 +1141,7 @@ channel_modes(struct Channel *chptr, struct Client *client_p) for (i = 0; i < 256; i++) { - if(chmode_table[i].set_func == chm_hidden && (!IsOper(client_p) || !IsClient(client_p))) + if(chmode_table[i].set_func == chm_hidden && !HasPrivilege(client_p, "auspex:cmodes") && IsClient(client_p)) continue; if(chptr->mode.mode & chmode_flags[i]) *mbuf++ = i; @@ -1260,7 +1213,7 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p, char *pbuf; const char *arg; int dir; - int arglen; + int arglen = 0; /* Now send to servers... */ mc = 0; @@ -1376,7 +1329,7 @@ resv_chan_forcepart(const char *name, const char *reason, int temp_time) sendto_server(target_p, chptr, CAP_TS6, NOCAPS, ":%s PART %s", target_p->id, chptr->chname); - sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", + sendto_channel_local(target_p, ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", target_p->name, target_p->username, target_p->host, chptr->chname, target_p->name);