2 * IRC - Internet Relay Chat, ircd/m_burst.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 * m_functions execute protocol messages on this server:
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
84 * No need to include handlers.h here the signatures must match
85 * and we don't need to force a rebuild of all the handlers everytime
86 * we add a new one to the list. --Bleep
94 #include "ircd_alloc.h"
95 #include "ircd_reply.h"
96 #include "ircd_string.h"
100 #include "numnicks.h"
111 * ms_burst - server message handler
113 * -- by Run carlo@runaway.xs4all.nl december 1995 till march 1997
115 * parv[0] = sender prefix
116 * parv[1] = channel name
117 * parv[2] = channel timestamp
118 * The meaning of the following parv[]'s depend on their first character:
119 * If parv[n] starts with a '+':
120 * Net burst, additive modes
122 * parv[n+1] = <param> (optional)
123 * parv[n+2] = <param> (optional)
124 * If parv[n] starts with a '%', then n will be parc-1:
125 * parv[n] = %<ban> <ban> <ban> ...
126 * If parv[n] starts with another character:
127 * parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
128 * where <mode> is the channel mode (ov) of nick and all following nicks.
131 * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
133 * Anti net.ride code.
135 * When the channel already exist, and its TS is larger then
136 * the TS in the BURST message, then we cancel all existing modes.
137 * If its is smaller then the received BURST message is ignored.
138 * If it's equal, then the received modes are just added.
140 int ms_burst(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
142 struct Channel* chptr;
148 int add_banid_not_called = 1;
149 struct Mode* current_mode;
156 char prev_key[KEYLEN + 1];
157 struct Membership* member;
159 char modebuf[MODEBUFLEN];
160 char parabuf[MODEBUFLEN];
161 char bmodebuf[MODEBUFLEN];
162 char bparambuf[MODEBUFLEN];
164 /* BURST is only for servers and has at least 4 parameters */
165 if (!IsServer(cptr) || parc < 4)
172 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD))
176 ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
177 sptr->name, parv[1], parv[2]);
178 for (i = 3; i < parc - 1; ++i)
179 p = sprintf_irc(p, " %s", parv[i]);
180 sprintf_irc(p, " :%s", parv[parc - 1]);
181 sendbufto_op_mask(SNO_HACK4);
185 #if 1 /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
189 return exit_client_msg(cptr, cptr, &me,
190 "HACK: BURST message outside net.burst from %s", sptr->name);
194 /* Find the channel, or create it - note that the creation time
195 * will be 0 if it has to be created */
196 chptr = get_channel(sptr, parv[1], CGT_CREATE);
197 current_mode = &chptr->mode;
198 prev_mode = chptr->mode.mode;
199 if (*chptr->mode.key)
201 prev_mode |= MODE_KEY;
202 strcpy(prev_key, chptr->mode.key);
204 if (chptr->mode.limit)
205 prev_mode |= MODE_LIMIT;
207 timestamp = atoi(parv[2]);
209 /* Copy the new TS when the received creationtime appears to be older */
210 if (!chptr->creationtime || chptr->creationtime > timestamp)
212 /* Set the new timestamp */
213 chptr->creationtime = timestamp;
214 send_it = 1; /* Make sure we pass on the different timestamp ! */
215 /* Mark all bans as needed to be wiped out */
216 for (lp = chptr->banlist; lp; lp = lp->next)
217 lp->flags |= CHFL_BURST_BAN_WIPEOUT;
219 * Only the first BURST for this channel can have creationtime > timestamp,
220 * so at this moment ALL members are on OUR side, and thus all net.riders:
224 for (member = chptr->members; member; member = member->next_member)
225 member->status &= ~CHFL_BURST_JOINED; /* Set later for nicks in the BURST msg */
226 /* If `wipeout' is set then these will be deopped later. */
228 /* If the entering creationtime is younger, ignore the modes */
229 if (chptr->creationtime < timestamp)
230 netride = 1; /* Only pass on the nicks (so they JOIN) */
232 /* Prepare buffers to pass the message */
233 *bparambuf = *bmodebuf = *parabuf = '\0';
238 sblen = sprintf_irc(sendbuf, "%s B %s " TIME_T_FMT,
239 NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
241 /* Run over all remaining parameters */
242 for (n = 3; n < parc; n++)
243 switch (*parv[n]) /* What type is it ? mode, nicks or bans ? */
245 case '+': /* modes */
248 while (*(++p)) /* Run over all mode characters */
250 switch (*p) /* which mode ? */
253 * The following cases all do the following:
254 * - In case wipeout needed, reset 'prev_mode' to indicate this
255 * mode should not be cancelled.
256 * - If wipeout or (not netride and the new mode is a change),
257 * add it to bmodebuf and bparabuf for propagation.
259 * - Add it to modebuf and parabuf for propagation to the
260 * clients when not netride and the new mode is a change.
262 * - If a +s is received, cancel a +p and sent a -p to the
263 * clients too (if +p was set).
264 * - If a +p is received and +s is set, ignore the +p.
269 prev_mode &= ~MODE_INVITEONLY;
270 if (!(tmp = netride ||
271 (current_mode->mode & MODE_INVITEONLY)) || wipeout)
273 bmodebuf[mblen++] = 'i';
274 current_mode->mode |= MODE_INVITEONLY;
277 modebuf[mblen2++] = 'i';
283 char *param = parv[++n];
284 prev_mode &= ~MODE_KEY;
285 if (!(tmp = netride || (*current_mode->key &&
286 (!strcmp(current_mode->key, param) ||
287 (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
290 bmodebuf[mblen++] = 'k';
291 strcat(bparambuf, " ");
292 strcat(bparambuf, param);
293 ircd_strncpy(current_mode->key, param, KEYLEN);
295 if (!tmp && !wipeout)
297 modebuf[mblen2++] = 'k';
298 parabuf[pblen2++] = ' ';
299 strcpy(parabuf + pblen2, param);
300 pblen2 += strlen(param);
308 unsigned int param = atoi(parv[++n]);
309 prev_mode &= ~MODE_LIMIT;
310 if (!(tmp = netride || (current_mode->limit &&
311 (current_mode->limit == param ||
312 (!wipeout && current_mode->limit < param)))) || wipeout)
314 bmodebuf[mblen++] = 'l';
315 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
316 current_mode->limit = param;
320 modebuf[mblen2++] = 'l';
321 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
329 prev_mode &= ~MODE_MODERATED;
330 if (!(tmp = netride ||
331 (current_mode->mode & MODE_MODERATED)) || wipeout)
333 bmodebuf[mblen++] = 'm';
334 current_mode->mode |= MODE_MODERATED;
337 modebuf[mblen2++] = 'm';
343 prev_mode &= ~MODE_NOPRIVMSGS;
344 if (!(tmp = netride ||
345 (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
347 bmodebuf[mblen++] = 'n';
348 current_mode->mode |= MODE_NOPRIVMSGS;
351 modebuf[mblen2++] = 'n';
359 if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
362 prev_mode &= ~MODE_PRIVATE;
363 if (!(tmp = netride ||
364 (current_mode->mode & MODE_PRIVATE)) || wipeout)
366 bmodebuf[mblen++] = 'p';
367 current_mode->mode |= MODE_PRIVATE;
370 modebuf[mblen2++] = 'p';
376 prev_mode &= ~MODE_SECRET;
377 if (!(tmp = netride ||
378 (current_mode->mode & MODE_SECRET)) || wipeout)
380 bmodebuf[mblen++] = 's';
381 current_mode->mode |= MODE_SECRET;
384 modebuf[mblen2++] = 's';
387 if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
390 for (i = mblen2 - 1; i >= 0; --i)
391 modebuf[i + 2] = modebuf[i];
395 current_mode->mode &= ~MODE_PRIVATE;
403 prev_mode &= ~MODE_TOPICLIMIT;
404 if (!(tmp = netride ||
405 (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
407 bmodebuf[mblen++] = 't';
408 current_mode->mode |= MODE_TOPICLIMIT;
411 modebuf[mblen2++] = 't';
415 } /* <-- while over all modes */
417 bmodebuf[mblen] = '\0';
418 sendbuf[sblen] = '\0';
419 if (mblen) /* Anything to send at all ? */
422 strcpy(sendbuf + sblen, " +");
424 strcpy(sendbuf + sblen, bmodebuf);
426 strcpy(sendbuf + sblen, bparambuf);
427 sblen += strlen(bparambuf);
429 break; /* Done mode part */
433 char *pv, *p = 0, *ban;
436 break; /* Ignore bans */
437 /* Run over all bans */
438 for (pv = parv[n] + 1; (ban = ircd_strtok(&p, pv, " ")); pv = 0)
442 * The following part should do the following:
443 * - If the new (un)ban is not a _change_ it is ignored.
444 * - Else, add it to sendbuf for later use.
445 * - If sendbuf is full, send it, and prepare a new
446 * message in sendbuf.
448 ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
451 add_banid_not_called = 0;
452 /* Mark this new ban so we can send it to the clients later */
453 chptr->banlist->flags |= CHFL_BURST_BAN;
456 /* A new ban was added or an existing one needs to be passed on.
457 * Also add it to sendbuf: */
458 add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
460 break; /* Done bans part */
464 char *pv, *p = 0, *nick, *ptr;
467 int default_mode = CHFL_DEOPPED;
468 /* Run over all nicks */
469 for (pv = parv[n]; (nick = ircd_strtok(&p, pv, ",")); pv = 0)
471 struct Client *acptr;
472 if ((ptr = strchr(nick, ':'))) /* New default mode ? */
474 *ptr = '\0'; /* Fix 'nick' */
475 acptr = findNUser(nick);
478 /* Calculate new mode change: */
479 default_mode = CHFL_DEOPPED;
483 default_mode |= CHFL_CHANOP;
484 default_mode &= ~CHFL_DEOPPED;
486 else if (*ptr == 'v')
487 default_mode |= CHFL_VOICE;
493 acptr = findNUser(nick);
495 * Note that at this point we already received a 'NICK' for any
496 * <nick> numeric that is joining (and possibly opped) here.
497 * Therefore we consider the following situations:
498 * - The <nick> numeric exists and is from the direction of cptr: ok
499 * - The <nick> numeric does not exist:
500 * Apparently this previous <nick> numeric was killed (upstream)
501 * or it collided with an existing <nick> name.
502 * - The <nick> numeric exists but is from another direction:
503 * Apparently this previous <nick> numeric was killed,
504 * and due to a reroute it signed on via another link (probably
505 * a nick [numeric] collision).
506 * Note that it can't be a QUIT or SQUIT, because a QUIT would
507 * come from the same direction as the BURST (cptr) while an
508 * upstream SQUIT removes the source (server) and we would thus
509 * have this BURST ignored already.
510 * This means that if we find the nick and it is from the correct
511 * direction, it joins. If it doesn't exist or is from another
512 * direction, we have to ignore it. If all nicks are ignored, we
513 * remove the channel again when it is empty and don't propagate
516 if (acptr && acptr->from == cptr)
519 * The following should do the following:
520 * - Add it to sendbuf for later use.
521 * - If sendbuf is full, send it, and prepare a new
522 * message in sendbuf.
524 add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
526 /* Let is take effect: (Note that in the case of a netride
527 * 'default_mode' is always CHFL_DEOPPED here). */
528 add_user_to_channel(chptr, acptr, default_mode | CHFL_BURST_JOINED);
530 } /* <-- Next nick */
531 if (!chptr->members) /* All nicks collided and channel is empty ? */
533 sub1_from_channel(chptr);
534 return 0; /* Forget about the (rest of the) message... */
536 break; /* Done nicks part */
538 } /* <-- Next parameter if any */
539 if (!chptr->members) /* This message only contained bans (then the previous
540 message only contained collided nicks, see above) */
542 sub1_from_channel(chptr);
543 if (!add_banid_not_called)
544 while (next_removed_overlapped_ban());
545 return 0; /* Forget about the (rest of the) message... */
548 /* The last (possibly only) message is always send here */
549 if (send_it) /* Anything (left) to send ? */
552 struct Membership* member;
554 /* send 'sendbuf' to all downlinks */
555 for (lp = me.serv->down; lp; lp = lp->next)
557 if (lp->value.cptr == cptr)
559 if (Protocol(lp->value.cptr) > 9)
560 sendbufto_one(lp->value.cptr);
564 * Now we finally can screw sendbuf again...
565 * Send all changes to the local clients:
567 * First send all joins and op them, because 2.9 servers
568 * would protest with a HACK if we first de-opped people.
569 * However, we don't send the +b bans yes, because we
570 * DO first want to -b the old bans (otherwise it's confusing).
573 /* Send all joins: */
574 for (member = chptr->members; member; member = member->next_member)
575 if (IsBurstJoined(member))
577 sendto_channel_butserv(chptr, member->user, ":%s JOIN :%s",
578 member->user->name, chptr->chname);
583 /* Send all +o and +v modes: */
584 for (member = chptr->members; member; member = member->next_member)
586 if (IsBurstJoined(member))
588 int mode = CHFL_CHANOP;
591 if ((member->status & mode))
593 modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
594 parabuf[pblen2++] = ' ';
595 strcpy(parabuf + pblen2, member->user->name);
596 pblen2 += strlen(member->user->name);
600 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
601 parv[0], chptr->chname, modebuf, parabuf);
608 if (mode == CHFL_CHANOP)
616 if (cnt > 0 || mblen2 > 1)
619 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
620 parv[0], chptr->chname, modebuf, parabuf);
627 struct Membership* member;
633 /* Now cancel all previous simple modes */
634 if ((prev_mode & MODE_SECRET))
635 cancel_mode(sptr, chptr, 's', 0, &count);
636 if ((prev_mode & MODE_PRIVATE))
637 cancel_mode(sptr, chptr, 'p', 0, &count);
638 if ((prev_mode & MODE_MODERATED))
639 cancel_mode(sptr, chptr, 'm', 0, &count);
640 if ((prev_mode & MODE_TOPICLIMIT))
641 cancel_mode(sptr, chptr, 't', 0, &count);
642 if ((prev_mode & MODE_INVITEONLY))
643 cancel_mode(sptr, chptr, 'i', 0, &count);
644 if ((prev_mode & MODE_NOPRIVMSGS))
645 cancel_mode(sptr, chptr, 'n', 0, &count);
646 if ((prev_mode & MODE_LIMIT))
648 current_mode->limit = 0;
649 cancel_mode(sptr, chptr, 'l', 0, &count);
651 if ((prev_mode & MODE_KEY))
653 *current_mode->key = 0;
654 cancel_mode(sptr, chptr, 'k', prev_key, &count);
656 current_mode->mode &= ~prev_mode;
658 /* And deop and devoice all net.riders on my side */
663 struct Membership* member_next = 0;
665 for (member = chptr->members; member; member = member_next)
667 member_next = member->next_member;
668 if (IsBurstJoined(member))
669 continue; /* This is not a net.rider from
670 this side of the net.junction */
671 #if defined(NO_INVITE_NETRIDE)
673 * Kick net riding users from invite only channels.
674 * - Isomer 25-11-1999
676 if (chptr->mode.mode & MODE_INVITEONLY) {
677 /* kick is magical - lotsa zombies and other undead.
678 * I'm hoping this is the right idea, comments anyone?
679 * Set everyone to a zombie, remove ops, and then send kicks
682 if (IsZombie(member)) { /* don't kick ppl twice */
683 member->status = member->status & ~mode;
687 sendto_highprot_butone(0, 10, "%s " TOK_KICK " %s %s%s :Net Rider",
688 NumServ(&me), chptr->chname, NumNick(member->user));
689 sendto_channel_butserv(chptr, sptr,
690 ":%s KICK %s %s :Net Rider", me.name, chptr->chname,
693 if (MyUser(member->user)) {
694 sendto_lowprot_butone(0, 9, ":%s PART %s",
695 member->user->name, chptr->chname, member->user->name);
696 sendto_highprot_butone(0, 10, "%s%s PART %s",
697 NumNick(member->user), chptr->chname);
698 remove_user_from_channel(member->user, chptr);
701 member->status = (member->status & ~mode) | CHFL_ZOMBIE;
705 #endif /* defined(NO_INVITE_NETRIDE) */
706 if ((member->status & mode))
708 member->status &= ~mode;
709 if (mode == CHFL_CHANOP)
711 cancel_mode(sptr, chptr, m, member->user->name, &count);
714 if (mode == CHFL_VOICE)
720 /* And finally wipeout all bans that are left */
721 for (ban = &chptr->banlist; *ban; ) {
722 struct SLink* tmp = *ban;
723 if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT)) {
724 struct Membership* member_z;
727 cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
729 /* Copied from del_banid(): */
730 MyFree(tmp->value.ban.banstr);
731 MyFree(tmp->value.ban.who);
734 /* Erase ban-valid-bit, for channel members that are banned */
735 for (member_z = chptr->members; member_z; member_z = member_z->next_member)
736 if ((member_z->status & CHFL_BANVALIDMASK) == CHFL_BANVALIDMASK)
737 ClearBanValid(member_z);
742 /* Also wipeout overlapped bans */
743 if (!add_banid_not_called)
746 while ((ban = next_removed_overlapped_ban()))
747 cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
749 cancel_mode(sptr, chptr, 0, 0, &count); /* flush */
752 if (send_it && !netride)
757 if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
776 nblen = strlen(bl->value.ban.banstr);
777 if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
778 that the receiving 2.9 will
779 still process this */
781 /* Time to send buffer */
783 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
784 parv[0], chptr->chname, modebuf, parabuf);
785 *modebuf = deban ? '-' : '+';
790 if (!bl) /* Done ? */
792 if (deban || (bl->flags & CHFL_BURST_BAN))
794 /* Add ban to buffers and remove it */
795 modebuf[mblen2++] = 'b';
796 parabuf[pblen2++] = ' ';
797 strcpy(parabuf + pblen2, bl->value.ban.banstr);
800 bl->flags &= ~CHFL_BURST_BAN;
804 if (!(bl = next_removed_overlapped_ban()))
807 modebuf[mblen2++] = '+';
814 /* Flush MODE [-b]+b ...: */
815 if (cnt > 0 || mblen2 > 1)
818 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
819 parv[0], chptr->chname, modebuf, parabuf);
828 * m_burst -- by Run carlo@runaway.xs4all.nl december 1995 till march 1997
830 * parv[0] = sender prefix
831 * parv[1] = channel name
832 * parv[2] = channel timestamp
833 * The meaning of the following parv[]'s depend on their first character:
834 * If parv[n] starts with a '+':
835 * Net burst, additive modes
837 * parv[n+1] = <param> (optional)
838 * parv[n+2] = <param> (optional)
839 * If parv[n] starts with a '%', then n will be parc-1:
840 * parv[n] = %<ban> <ban> <ban> ...
841 * If parv[n] starts with another character:
842 * parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
843 * where <mode> is the channel mode (ov) of nick and all following nicks.
846 * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
848 * Anti net.ride code.
850 * When the channel already exist, and its TS is larger then
851 * the TS in the BURST message, then we cancel all existing modes.
852 * If its is smaller then the received BURST message is ignored.
853 * If it's equal, then the received modes are just added.
855 int m_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
857 struct Channel* chptr;
863 int add_banid_not_called = 1;
864 struct Mode* current_mode;
871 char prev_key[KEYLEN + 1];
872 struct Membership* member;
874 char modebuf[MODEBUFLEN];
875 char parabuf[MODEBUFLEN];
876 char bmodebuf[MODEBUFLEN];
877 char bparambuf[MODEBUFLEN];
879 /* BURST is only for servers and has at least 4 parameters */
880 if (!IsServer(cptr) || parc < 4)
887 if (find_conf_byhost(cptr->confs, sptr->name, CONF_UWORLD))
891 ":%s NOTICE * :*** Notice -- HACK(4): %s BURST %s %s", me.name,
892 sptr->name, parv[1], parv[2]);
893 for (i = 3; i < parc - 1; ++i)
894 p = sprintf_irc(p, " %s", parv[i]);
895 sprintf_irc(p, " :%s", parv[parc - 1]);
896 sendbufto_op_mask(SNO_HACK4);
900 #if 1 /* FIXME: This should be removed after all HUBs upgraded to ircu2.10.05 */
904 return exit_client_msg(cptr, cptr, &me,
905 "HACK: BURST message outside net.burst from %s", sptr->name);
909 /* Find the channel, or create it - note that the creation time
910 * will be 0 if it has to be created */
911 chptr = get_channel(sptr, parv[1], CGT_CREATE);
912 current_mode = &chptr->mode;
913 prev_mode = chptr->mode.mode;
914 if (*chptr->mode.key)
916 prev_mode |= MODE_KEY;
917 strcpy(prev_key, chptr->mode.key);
919 if (chptr->mode.limit)
920 prev_mode |= MODE_LIMIT;
922 timestamp = atoi(parv[2]);
924 /* Copy the new TS when the received creationtime appears to be older */
925 if (!chptr->creationtime || chptr->creationtime > timestamp)
927 /* Set the new timestamp */
928 chptr->creationtime = timestamp;
929 send_it = 1; /* Make sure we pass on the different timestamp ! */
930 /* Mark all bans as needed to be wiped out */
931 for (lp = chptr->banlist; lp; lp = lp->next)
932 lp->flags |= CHFL_BURST_BAN_WIPEOUT;
934 * Only the first BURST for this channel can have creationtime > timestamp,
935 * so at this moment ALL members are on OUR side, and thus all net.riders:
939 for (member = chptr->members; member; member = member->next_member)
940 member->status &= ~CHFL_BURST_JOINED; /* Set later for nicks in the BURST msg */
941 /* If `wipeout' is set then these will be deopped later. */
943 /* If the entering creationtime is younger, ignore the modes */
944 if (chptr->creationtime < timestamp)
945 netride = 1; /* Only pass on the nicks (so they JOIN) */
947 /* Prepare buffers to pass the message */
948 *bparambuf = *bmodebuf = *parabuf = '\0';
953 sblen = sprintf_irc(sendbuf, "%s B %s " TIME_T_FMT,
954 NumServ(sptr), chptr->chname, chptr->creationtime) - sendbuf;
956 /* Run over all remaining parameters */
957 for (n = 3; n < parc; n++)
958 switch (*parv[n]) /* What type is it ? mode, nicks or bans ? */
960 case '+': /* modes */
963 while (*(++p)) /* Run over all mode characters */
965 switch (*p) /* which mode ? */
968 * The following cases all do the following:
969 * - In case wipeout needed, reset 'prev_mode' to indicate this
970 * mode should not be cancelled.
971 * - If wipeout or (not netride and the new mode is a change),
972 * add it to bmodebuf and bparabuf for propagation.
974 * - Add it to modebuf and parabuf for propagation to the
975 * clients when not netride and the new mode is a change.
977 * - If a +s is received, cancel a +p and sent a -p to the
978 * clients too (if +p was set).
979 * - If a +p is received and +s is set, ignore the +p.
984 prev_mode &= ~MODE_INVITEONLY;
985 if (!(tmp = netride ||
986 (current_mode->mode & MODE_INVITEONLY)) || wipeout)
988 bmodebuf[mblen++] = 'i';
989 current_mode->mode |= MODE_INVITEONLY;
992 modebuf[mblen2++] = 'i';
998 char *param = parv[++n];
999 prev_mode &= ~MODE_KEY;
1000 if (!(tmp = netride || (*current_mode->key &&
1001 (!strcmp(current_mode->key, param) ||
1002 (!wipeout && strcmp(current_mode->key, param) < 0)))) ||
1005 bmodebuf[mblen++] = 'k';
1006 strcat(bparambuf, " ");
1007 strcat(bparambuf, param);
1008 ircd_strncpy(current_mode->key, param, KEYLEN);
1010 if (!tmp && !wipeout)
1012 modebuf[mblen2++] = 'k';
1013 parabuf[pblen2++] = ' ';
1014 strcpy(parabuf + pblen2, param);
1015 pblen2 += strlen(param);
1023 unsigned int param = atoi(parv[++n]);
1024 prev_mode &= ~MODE_LIMIT;
1025 if (!(tmp = netride || (current_mode->limit &&
1026 (current_mode->limit == param ||
1027 (!wipeout && current_mode->limit < param)))) || wipeout)
1029 bmodebuf[mblen++] = 'l';
1030 sprintf_irc(bparambuf + strlen(bparambuf), " %d", param);
1031 current_mode->limit = param;
1035 modebuf[mblen2++] = 'l';
1036 pblen2 = sprintf_irc(parabuf + pblen2, " %d", param) - parabuf;
1044 prev_mode &= ~MODE_MODERATED;
1045 if (!(tmp = netride ||
1046 (current_mode->mode & MODE_MODERATED)) || wipeout)
1048 bmodebuf[mblen++] = 'm';
1049 current_mode->mode |= MODE_MODERATED;
1052 modebuf[mblen2++] = 'm';
1058 prev_mode &= ~MODE_NOPRIVMSGS;
1059 if (!(tmp = netride ||
1060 (current_mode->mode & MODE_NOPRIVMSGS)) || wipeout)
1062 bmodebuf[mblen++] = 'n';
1063 current_mode->mode |= MODE_NOPRIVMSGS;
1066 modebuf[mblen2++] = 'n';
1074 if (!netride && !wipeout && (current_mode->mode & MODE_SECRET))
1077 prev_mode &= ~MODE_PRIVATE;
1078 if (!(tmp = netride ||
1079 (current_mode->mode & MODE_PRIVATE)) || wipeout)
1081 bmodebuf[mblen++] = 'p';
1082 current_mode->mode |= MODE_PRIVATE;
1085 modebuf[mblen2++] = 'p';
1091 prev_mode &= ~MODE_SECRET;
1092 if (!(tmp = netride ||
1093 (current_mode->mode & MODE_SECRET)) || wipeout)
1095 bmodebuf[mblen++] = 's';
1096 current_mode->mode |= MODE_SECRET;
1099 modebuf[mblen2++] = 's';
1102 if (!netride && !wipeout && (current_mode->mode & MODE_PRIVATE))
1105 for (i = mblen2 - 1; i >= 0; --i)
1106 modebuf[i + 2] = modebuf[i];
1110 current_mode->mode &= ~MODE_PRIVATE;
1118 prev_mode &= ~MODE_TOPICLIMIT;
1119 if (!(tmp = netride ||
1120 (current_mode->mode & MODE_TOPICLIMIT)) || wipeout)
1122 bmodebuf[mblen++] = 't';
1123 current_mode->mode |= MODE_TOPICLIMIT;
1126 modebuf[mblen2++] = 't';
1130 } /* <-- while over all modes */
1132 bmodebuf[mblen] = '\0';
1133 sendbuf[sblen] = '\0';
1134 if (mblen) /* Anything to send at all ? */
1137 strcpy(sendbuf + sblen, " +");
1139 strcpy(sendbuf + sblen, bmodebuf);
1141 strcpy(sendbuf + sblen, bparambuf);
1142 sblen += strlen(bparambuf);
1144 break; /* Done mode part */
1146 case '%': /* bans */
1148 char *pv, *p = 0, *ban;
1151 break; /* Ignore bans */
1152 /* Run over all bans */
1153 for (pv = parv[n] + 1; (ban = ircd_strtok(&p, pv, " ")); pv = 0)
1157 * The following part should do the following:
1158 * - If the new (un)ban is not a _change_ it is ignored.
1159 * - Else, add it to sendbuf for later use.
1160 * - If sendbuf is full, send it, and prepare a new
1161 * message in sendbuf.
1163 ret = add_banid(sptr, chptr, ban, 1, add_banid_not_called);
1166 add_banid_not_called = 0;
1167 /* Mark this new ban so we can send it to the clients later */
1168 chptr->banlist->flags |= CHFL_BURST_BAN;
1171 /* A new ban was added or an existing one needs to be passed on.
1172 * Also add it to sendbuf: */
1173 add_token_to_sendbuf(ban, &sblen, &first, &send_it, '%', 0);
1175 break; /* Done bans part */
1177 default: /* nicks */
1179 char *pv, *p = 0, *nick, *ptr;
1182 int default_mode = CHFL_DEOPPED;
1183 /* Run over all nicks */
1184 for (pv = parv[n]; (nick = ircd_strtok(&p, pv, ",")); pv = 0)
1186 struct Client *acptr;
1187 if ((ptr = strchr(nick, ':'))) /* New default mode ? */
1189 *ptr = '\0'; /* Fix 'nick' */
1190 acptr = findNUser(nick);
1193 /* Calculate new mode change: */
1194 default_mode = CHFL_DEOPPED;
1198 default_mode |= CHFL_CHANOP;
1199 default_mode &= ~CHFL_DEOPPED;
1201 else if (*ptr == 'v')
1202 default_mode |= CHFL_VOICE;
1208 acptr = findNUser(nick);
1210 * Note that at this point we already received a 'NICK' for any
1211 * <nick> numeric that is joining (and possibly opped) here.
1212 * Therefore we consider the following situations:
1213 * - The <nick> numeric exists and is from the direction of cptr: ok
1214 * - The <nick> numeric does not exist:
1215 * Apparently this previous <nick> numeric was killed (upstream)
1216 * or it collided with an existing <nick> name.
1217 * - The <nick> numeric exists but is from another direction:
1218 * Apparently this previous <nick> numeric was killed,
1219 * and due to a reroute it signed on via another link (probably
1220 * a nick [numeric] collision).
1221 * Note that it can't be a QUIT or SQUIT, because a QUIT would
1222 * come from the same direction as the BURST (cptr) while an
1223 * upstream SQUIT removes the source (server) and we would thus
1224 * have this BURST ignored already.
1225 * This means that if we find the nick and it is from the correct
1226 * direction, it joins. If it doesn't exist or is from another
1227 * direction, we have to ignore it. If all nicks are ignored, we
1228 * remove the channel again when it is empty and don't propagate
1229 * the BURST message.
1231 if (acptr && acptr->from == cptr)
1234 * The following should do the following:
1235 * - Add it to sendbuf for later use.
1236 * - If sendbuf is full, send it, and prepare a new
1237 * message in sendbuf.
1239 add_token_to_sendbuf(nick, &sblen, &first, &send_it, 0,
1241 /* Let is take effect: (Note that in the case of a netride
1242 * 'default_mode' is always CHFL_DEOPPED here). */
1243 add_user_to_channel(chptr, acptr, default_mode | CHFL_BURST_JOINED);
1245 } /* <-- Next nick */
1246 if (!chptr->members) /* All nicks collided and channel is empty ? */
1248 sub1_from_channel(chptr);
1249 return 0; /* Forget about the (rest of the) message... */
1251 break; /* Done nicks part */
1253 } /* <-- Next parameter if any */
1254 if (!chptr->members) /* This message only contained bans (then the previous
1255 message only contained collided nicks, see above) */
1257 sub1_from_channel(chptr);
1258 if (!add_banid_not_called)
1259 while (next_removed_overlapped_ban());
1260 return 0; /* Forget about the (rest of the) message... */
1263 /* The last (possibly only) message is always send here */
1264 if (send_it) /* Anything (left) to send ? */
1267 struct Membership* member;
1269 /* send 'sendbuf' to all downlinks */
1270 for (lp = me.serv->down; lp; lp = lp->next)
1272 if (lp->value.cptr == cptr)
1274 if (Protocol(lp->value.cptr) > 9)
1275 sendbufto_one(lp->value.cptr);
1279 * Now we finally can screw sendbuf again...
1280 * Send all changes to the local clients:
1282 * First send all joins and op them, because 2.9 servers
1283 * would protest with a HACK if we first de-opped people.
1284 * However, we don't send the +b bans yes, because we
1285 * DO first want to -b the old bans (otherwise it's confusing).
1288 /* Send all joins: */
1289 for (member = chptr->members; member; member = member->next_member)
1290 if (IsBurstJoined(member))
1292 sendto_channel_butserv(chptr, member->user, ":%s JOIN :%s",
1293 member->user->name, chptr->chname);
1298 /* Send all +o and +v modes: */
1299 for (member = chptr->members; member; member = member->next_member)
1301 if (IsBurstJoined(member))
1303 int mode = CHFL_CHANOP;
1306 if ((member->status & mode))
1308 modebuf[mblen2++] = (mode == CHFL_CHANOP) ? 'o' : 'v';
1309 parabuf[pblen2++] = ' ';
1310 strcpy(parabuf + pblen2, member->user->name);
1311 pblen2 += strlen(member->user->name);
1314 modebuf[mblen2] = 0;
1315 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1316 parv[0], chptr->chname, modebuf, parabuf);
1323 if (mode == CHFL_CHANOP)
1331 if (cnt > 0 || mblen2 > 1)
1333 modebuf[mblen2] = 0;
1334 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1335 parv[0], chptr->chname, modebuf, parabuf);
1342 struct Membership* member;
1348 /* Now cancel all previous simple modes */
1349 if ((prev_mode & MODE_SECRET))
1350 cancel_mode(sptr, chptr, 's', 0, &count);
1351 if ((prev_mode & MODE_PRIVATE))
1352 cancel_mode(sptr, chptr, 'p', 0, &count);
1353 if ((prev_mode & MODE_MODERATED))
1354 cancel_mode(sptr, chptr, 'm', 0, &count);
1355 if ((prev_mode & MODE_TOPICLIMIT))
1356 cancel_mode(sptr, chptr, 't', 0, &count);
1357 if ((prev_mode & MODE_INVITEONLY))
1358 cancel_mode(sptr, chptr, 'i', 0, &count);
1359 if ((prev_mode & MODE_NOPRIVMSGS))
1360 cancel_mode(sptr, chptr, 'n', 0, &count);
1361 if ((prev_mode & MODE_LIMIT))
1363 current_mode->limit = 0;
1364 cancel_mode(sptr, chptr, 'l', 0, &count);
1366 if ((prev_mode & MODE_KEY))
1368 *current_mode->key = 0;
1369 cancel_mode(sptr, chptr, 'k', prev_key, &count);
1371 current_mode->mode &= ~prev_mode;
1373 /* And deop and devoice all net.riders on my side */
1378 struct Membership* member_next = 0;
1380 for (member = chptr->members; member; member = member_next)
1382 member_next = member->next_member;
1383 if (IsBurstJoined(member))
1384 continue; /* This is not a net.rider from
1385 this side of the net.junction */
1386 #if defined(NO_INVITE_NETRIDE)
1388 * Kick net riding users from invite only channels.
1389 * - Isomer 25-11-1999
1391 if (chptr->mode.mode & MODE_INVITEONLY) {
1392 /* kick is magical - lotsa zombies and other undead.
1393 * I'm hoping this is the right idea, comments anyone?
1394 * Set everyone to a zombie, remove ops, and then send kicks
1397 if (IsZombie(member)) { /* don't kick ppl twice */
1398 member->status = member->status & ~mode;
1401 member->status = (member->status & ~mode) | CHFL_ZOMBIE;
1403 sendto_highprot_butone(0, 10, "%s " TOK_KICK "%s %s%s :Net Rider",
1404 NumServ(&me), chptr->chname, NumNick(member->user));
1405 sendto_channel_butserv(chptr, sptr,
1406 ":%s KICK %s %s :Net Rider", me.name, chptr->chname,
1407 member->user->name);
1409 if (MyUser(member->user)) {
1410 sendto_lowprot_butone(0, 9, ":%s PART %s",
1411 member->user->name, chptr->chname, member->user->name);
1412 sendto_highprot_butone(0, 10, "%s%s PART %s",
1413 NumNick(member->user), chptr->chname);
1414 remove_user_from_channel(member->user, chptr);
1417 member->status = (member->status & ~mode) | CHFL_ZOMBIE;
1421 #endif /* defined(NO_INVITE_NETRIDE) */
1422 if ((member->status & mode))
1424 member->status &= ~mode;
1425 if (mode == CHFL_CHANOP)
1427 cancel_mode(sptr, chptr, m, member->user->name, &count);
1430 if (mode == CHFL_VOICE)
1436 /* And finally wipeout all bans that are left */
1437 for (ban = &chptr->banlist; *ban; ) {
1438 struct SLink* tmp = *ban;
1439 if ((tmp->flags & CHFL_BURST_BAN_WIPEOUT)) {
1440 struct Membership* member_z;
1443 cancel_mode(sptr, chptr, 'b', tmp->value.ban.banstr, &count);
1445 /* Copied from del_banid(): */
1446 MyFree(tmp->value.ban.banstr);
1447 MyFree(tmp->value.ban.who);
1450 /* Erase ban-valid-bit, for channel members that are banned */
1451 for (member_z = chptr->members; member_z; member_z = member_z->next_member)
1452 if ((member_z->status & CHFL_BANVALIDMASK) == CHFL_BANVALIDMASK)
1453 ClearBanValid(member_z);
1458 /* Also wipeout overlapped bans */
1459 if (!add_banid_not_called)
1462 while ((ban = next_removed_overlapped_ban()))
1463 cancel_mode(sptr, chptr, 'b', ban->value.ban.banstr, &count);
1465 cancel_mode(sptr, chptr, 0, 0, &count); /* flush */
1468 if (send_it && !netride)
1473 if (add_banid_not_called || !(bl = next_removed_overlapped_ban()))
1476 bl = chptr->banlist;
1492 nblen = strlen(bl->value.ban.banstr);
1493 if (cnt == 6 || (!bl && cnt) || pblen2 + nblen + 12 > MODEBUFLEN) /* The last check is to make sure
1494 that the receiving 2.9 will
1495 still process this */
1497 /* Time to send buffer */
1498 modebuf[mblen2] = 0;
1499 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1500 parv[0], chptr->chname, modebuf, parabuf);
1501 *modebuf = deban ? '-' : '+';
1506 if (!bl) /* Done ? */
1508 if (deban || (bl->flags & CHFL_BURST_BAN))
1510 /* Add ban to buffers and remove it */
1511 modebuf[mblen2++] = 'b';
1512 parabuf[pblen2++] = ' ';
1513 strcpy(parabuf + pblen2, bl->value.ban.banstr);
1516 bl->flags &= ~CHFL_BURST_BAN;
1520 if (!(bl = next_removed_overlapped_ban()))
1523 modebuf[mblen2++] = '+';
1524 bl = chptr->banlist;
1530 /* Flush MODE [-b]+b ...: */
1531 if (cnt > 0 || mblen2 > 1)
1533 modebuf[mblen2] = 0;
1534 sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s%s",
1535 parv[0], chptr->chname, modebuf, parabuf);