*** ../irc2.8.21/ircd/channel.c Sun Nov 6 11:02:38 1994 --- ircd/channel.c Fri Jun 13 10:49:11 1997 *************** *** 59,64 **** --- 59,75 ---- void clean_channelname PROTO((char *)); void del_invite PROTO((aClient *, aChannel *)); + #ifdef ORATIMING + struct timeval tsdnow, tsdthen; + unsigned long tsdms; + #endif + + /* + ** number of seconds to add to all readings of time() when making TS's + ** -orabidoo + */ + ts_val timedelta = 0; + static char *PartFmt = ":%s PART %s"; /* * some buffers for rebuilding channel/nick lists with ,'s *************** *** 303,313 **** --- 314,339 ---- if ((tmp = find_user_link(chptr->members, lp->value.cptr))) if (lp->flags & MODE_ADD) + { tmp->flags |= lp->flags & MODE_FLAGS; + if (lp->flags & MODE_CHANOP) + tmp->flags &= ~MODE_DEOPPED; + } else tmp->flags &= ~lp->flags & MODE_FLAGS; } + static void set_deopped(lp, chptr) + Link *lp; + aChannel *chptr; + { + Reg1 Link *tmp; + + if ((tmp = find_user_link(chptr->members, lp->value.cptr))) + if ((tmp->flags & MODE_CHANOP) == 0) + tmp->flags |= MODE_DEOPPED; + } + int is_chan_op(cptr, chptr) aClient *cptr; aChannel *chptr; *************** *** 321,326 **** --- 347,365 ---- return 0; } + int is_deopped(cptr, chptr) + aClient *cptr; + aChannel *chptr; + { + Reg1 Link *lp; + + if (chptr) + if ((lp = find_user_link(chptr->members, cptr))) + return (lp->flags & CHFL_DEOPPED); + + return 0; + } + int has_voice(cptr, chptr) aClient *cptr; aChannel *chptr; *************** *** 462,487 **** *modebuf = *parabuf = '\0'; channel_modes(cptr, modebuf, parabuf, chptr); ! send_mode_list(cptr, chptr->chname, chptr->members, CHFL_CHANOP, 'o'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! *parabuf = '\0'; ! *modebuf = '+'; ! modebuf[1] = '\0'; ! send_mode_list(cptr, chptr->chname, chptr->banlist, CHFL_BAN, 'b'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! *parabuf = '\0'; ! *modebuf = '+'; ! modebuf[1] = '\0'; ! send_mode_list(cptr, chptr->chname, chptr->members, CHFL_VOICE, 'v'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); } /* --- 501,607 ---- *modebuf = *parabuf = '\0'; channel_modes(cptr, modebuf, parabuf, chptr); ! if (DoesTS(cptr)) ! { ! Link *l, *anop = NULL, *skip = NULL; ! int n = 0; ! char *t; ! ! if (*parabuf) ! strcat(parabuf, " "); ! sprintf(buf, ":%s SJOIN %ld %s %s %s:", me.name, ! chptr->channelts, chptr->chname, modebuf, parabuf); ! t = buf + strlen(buf); ! for (l = chptr->members; l && l->value.cptr; l = l->next) ! if (l->flags & MODE_CHANOP) ! { ! anop = l; ! break; ! } ! /* follow the channel, but doing anop first if it's defined ! ** -orabidoo ! */ ! l = NULL; ! for (;;) ! { ! if (anop) ! { ! l = skip = anop; ! anop = NULL; ! } ! else ! { ! if (l == NULL || l == skip) ! l = chptr->members; ! else ! l = l->next; ! if (l && l == skip) ! l = l->next; ! if (l == NULL) ! break; ! } ! if (l->flags & MODE_CHANOP) ! *t++ = '@'; ! if (l->flags & MODE_VOICE) ! *t++ = '+'; ! strcpy(t, l->value.cptr->name); ! t += strlen(t); ! *t++ = ' '; ! n++; ! if (t - buf > BUFSIZE - 80) ! { ! *t++ = '\0'; ! if (t[-1] == ' ') t[-1] = '\0'; ! sendto_one(cptr, "%s", buf); ! sprintf(buf, ":%s SJOIN %ld %s 0 :", ! me.name, chptr->channelts, ! chptr->chname); ! t = buf + strlen(buf); ! n = 0; ! } ! } ! ! if (n) ! { ! *t++ = '\0'; ! if (t[-1] == ' ') t[-1] = '\0'; ! sendto_one(cptr, "%s", buf); ! } ! *parabuf = '\0'; ! *modebuf = '+'; ! modebuf[1] = '\0'; ! send_mode_list(cptr, chptr->chname, chptr->banlist, CHFL_BAN, ! 'b'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! } ! else ! { ! send_mode_list(cptr, chptr->chname, chptr->members, ! CHFL_CHANOP, 'o'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! *parabuf = '\0'; ! *modebuf = '+'; ! modebuf[1] = '\0'; ! send_mode_list(cptr, chptr->chname, chptr->banlist, CHFL_BAN, ! 'b'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! *parabuf = '\0'; ! *modebuf = '+'; ! modebuf[1] = '\0'; ! send_mode_list(cptr, chptr->chname, chptr->members, CHFL_VOICE, ! 'v'); ! if (modebuf[1] || *parabuf) ! sendto_one(cptr, ":%s MODE %s %s %s", ! me.name, chptr->chname, modebuf, parabuf); ! } } /* *************** *** 528,561 **** channel_modes(sptr, modebuf, parabuf, chptr); sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0], chptr->chname, modebuf, parabuf); return 0; } mcount = set_mode(cptr, sptr, chptr, parc - 2, parv + 2, modebuf, parabuf); - if ((mcount < 0) && MyConnect(sptr) && !IsServer(sptr)) - { - sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), - me.name, parv[0], chptr->chname); - return 0; - } if (strlen(modebuf) > (size_t)1) ! { ! if ((IsServer(cptr) && !IsServer(sptr) && !chanop) || ! (mcount < 0)) { ! sendto_ops("Fake: %s MODE %s %s %s", ! parv[0], parv[1], modebuf, parabuf); ! ircstp->is_fake++; ! } ! else ! sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", parv[0], chptr->chname, modebuf, parabuf); ! sendto_match_servs(chptr, cptr, ":%s MODE %s %s %s", ! parv[0], chptr->chname, modebuf, parabuf); ! } return 0; } --- 648,687 ---- channel_modes(sptr, modebuf, parabuf, chptr); sendto_one(sptr, rpl_str(RPL_CHANNELMODEIS), me.name, parv[0], chptr->chname, modebuf, parabuf); + sendto_one(sptr, rpl_str(RPL_CREATIONTIME), me.name, parv[0], + chptr->chname, chptr->channelts); return 0; } mcount = set_mode(cptr, sptr, chptr, parc - 2, parv + 2, modebuf, parabuf); if (strlen(modebuf) > (size_t)1) ! switch (mcount) { ! case 0: ! break; ! case -1: ! if (MyClient(sptr)) ! sendto_one(sptr, ! err_str(ERR_CHANOPRIVSNEEDED), ! me.name, parv[0], chptr->chname); ! else ! { ! sendto_ops("Fake: %s MODE %s %s %s", ! parv[0], parv[1], modebuf, parabuf); ! ircstp->is_fake++; ! } ! break; ! default: ! sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", parv[0], chptr->chname, modebuf, parabuf); ! sendto_match_servs(chptr, cptr, ! ":%s MODE %s %s %s", ! parv[0], chptr->chname, ! modebuf, parabuf); ! } return 0; } *************** *** 575,581 **** MODE_PRIVATE, 'p', MODE_SECRET, 's', MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n', MODE_TOPICLIMIT, 't', MODE_INVITEONLY, 'i', - MODE_VOICE, 'v', MODE_KEY, 'k', 0x0, 0x0 }; Reg1 Link *lp; --- 701,706 ---- *************** *** 583,589 **** Reg3 int *ip; u_int whatt = MODE_ADD; int limitset = 0, count = 0, chasing = 0; ! int nusers, ischop, new, len, keychange = 0, opcnt = 0; char fm = '\0'; aClient *who; Mode *mode, oldm; --- 708,715 ---- Reg3 int *ip; u_int whatt = MODE_ADD; int limitset = 0, count = 0, chasing = 0; ! int nusers, ischop, isok, isdeop, new, len; ! int keychange = 0, opcnt = 0; char fm = '\0'; aClient *who; Mode *mode, oldm; *************** *** 595,600 **** --- 721,729 ---- mode = &(chptr->mode); bcopy((char *)mode, (char *)&oldm, sizeof(Mode)); ischop = IsServer(sptr) || is_chan_op(sptr, chptr); + isdeop = !ischop && !IsServer(sptr) && is_deopped(sptr, chptr); + isok = ischop || (!isdeop && IsServer(cptr) && DoesTS(cptr) && + chptr->channelts); new = mode->mode; while (curr && *curr && count >= 0) *************** *** 636,646 **** ** just some extra messages if nick appeared more than ** once in the MODE message... --msa */ ! if (chasing && ischop) ! sendto_one(cptr, ":%s MODE %s %c%c %s", ! me.name, chptr->chname, ! whatt == MODE_ADD ? '+' : '-', ! *curr, who->name); if (who == cptr && whatt == MODE_ADD && *curr == 'o') break; --- 765,778 ---- ** just some extra messages if nick appeared more than ** once in the MODE message... --msa */ ! /* ! ** This is actually useless - if we notice a nick ! ** change it means the server the mode comes from ! ** dealt with the mode with the old nick, and already ! ** applied it, and the nick change must be coming ! ** from another server; besides, we don't want to ! ** be resetting the channel's TS -orabidoo ! */ if (who == cptr && whatt == MODE_ADD && *curr == 'o') break; *************** *** 679,688 **** break; *parv = check_string(*parv); { ! u_char *s; ! for (s = (u_char *)*parv; *s; s++) *s &= 0x7f; } if (MyClient(sptr) && opcnt >= MAXMODEPARAMS) break; --- 811,833 ---- break; *parv = check_string(*parv); { ! u_char *s, *t; ! int abuse = 0; ! for (s = t = (u_char *)*parv; *s; s++) ! { ! if (*s > 0x7f && *s <= 0xa0) ! abuse++; *s &= 0x7f; + if (*s > (u_char)' ' && *s != ':') + *t++ = *s; + } + *t = '\0'; + if (abuse) + sendto_ops("User %s trying to abuse +k bug", + sptr->name); + if (t == (u_char *)*parv) + break; } if (MyClient(sptr) && opcnt >= MAXMODEPARAMS) break; *************** *** 766,771 **** --- 911,917 ---- { limitset = 1; nusers = 0; + count++; break; } if (--parc > 0) *************** *** 827,832 **** --- 973,996 ---- whatt = 0; + /* if it's a non-deopped non-op on a TS channel from a TS + ** server, allow only ops and deops and ignore everything + ** else (to avoid having desynched ops) -orabidoo + */ + if (!ischop && isok) + { + Reg1 int i; + Reg2 int j; + + new = oldm.mode; + for (i = 0, j = 0; i < opcnt; i++) + if (chops[i].flags & (MODE_CHANOP|MODE_VOICE)) + chops[j++] = chops[i]; + else + count--; + opcnt = j; + } + for (ip = flags; *ip; ip += 2) if ((*ip & new) && !(*ip & oldm.mode)) { *************** *** 974,981 **** len += strlen(cp); (void)strcat(pbuf, " "); len++; ! if (ischop) change_chan_flag(lp, chptr); break; case MODE_BAN : if (ischop && ((whatt & MODE_ADD) && --- 1138,1157 ---- len += strlen(cp); (void)strcat(pbuf, " "); len++; ! if (isok) change_chan_flag(lp, chptr); + if (IsServer(sptr) && c == 'o' && + whatt == MODE_ADD) + { + chptr->channelts = 0; + #ifdef TS_WARNINGS + ts_warn("Server %s setting +o and blasting TS on %s", sptr->name, + chptr->chname); + #endif + } + if (c == 'o' && whatt == MODE_ADD && isdeop && + !is_chan_op(lp->value.cptr, chptr)) + set_deopped(lp, chptr); break; case MODE_BAN : if (ischop && ((whatt & MODE_ADD) && *************** *** 996,1002 **** *mbuf++ = '\0'; ! return ischop ? count : -count; } static int can_join(sptr, chptr, key) --- 1172,1190 ---- *mbuf++ = '\0'; ! /* returns: ! ** -1 = mode changes were generated but ignored, and a FAKE ! ** must be sent for remote clients and a CHANOPRIVSNEEDED ! ** for local ones ! ** 0 = ignore whatever was generated, do not propagate anything ! ** >0 = modes were accepted, propagate ! */ ! if (isok) ! return count; ! if (isdeop && !MyClient(sptr)) ! return 0; ! else ! return -1; } static int can_join(sptr, chptr, key) *************** *** 1304,1309 **** --- 1492,1509 ---- return 0; } } + else + { + #ifdef TS_WARNINGS + /* + ** complain for remote JOINs to existing channels + ** (they should be SJOINs) -orabidoo + */ + if (!ChannelExists(name) && sptr->user) + ts_warn("User on %s remotely JOINing new channel", + sptr->user->server); + #endif + } chptr = get_channel(sptr, name, CREATE); *************** *** 1323,1341 **** */ add_user_to_channel(chptr, sptr, flags); /* ** notify all other users on the new channel */ sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name); - sendto_match_servs(chptr, cptr, ":%s JOIN :%s", parv[0], name); if (MyClient(sptr)) { del_invite(sptr, chptr); if (flags == CHFL_CHANOP) ! sendto_match_servs(chptr, cptr, ":%s MODE %s +o %s", me.name, name, parv[0]); if (chptr->topic[0] != '\0') sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, parv[0], name, chptr->topic); --- 1523,1579 ---- */ add_user_to_channel(chptr, sptr, flags); /* + ** Set timestamp if appropriate, and propagate + */ + if (MyClient(sptr) && flags == CHFL_CHANOP) + { + chptr->channelts = time(NULL) + timedelta; + #ifdef TS_ONLY + sendto_match_servs(chptr, cptr, + ":%s SJOIN %ld %s + :@%s", me.name, + chptr->channelts, name, parv[0]); + #else + sendto_match_TS_servs(0, chptr, cptr, ":%s JOIN :%s", + parv[0], name); + sendto_match_TS_servs(1, chptr, cptr, + ":%s SJOIN %ld %s + :@%s", me.name, + chptr->channelts, name, parv[0]); + #endif + } + else if (MyClient(sptr)) + { + #ifdef TS_ONLY + sendto_match_servs(chptr, cptr, + ":%s SJOIN %ld %s + :%s", me.name, + chptr->channelts, name, parv[0]); + #else + sendto_match_TS_servs(0, chptr, cptr, ":%s JOIN :%s", + parv[0], name); + sendto_match_TS_servs(1, chptr, cptr, + ":%s SJOIN %ld %s + :%s", me.name, + chptr->channelts, name, parv[0]); + #endif + } + else + sendto_match_servs(chptr, cptr, ":%s JOIN :%s", parv[0], + name); + + + /* ** notify all other users on the new channel */ sendto_channel_butserv(chptr, sptr, ":%s JOIN :%s", parv[0], name); if (MyClient(sptr)) { del_invite(sptr, chptr); + #ifndef TS_ONLY if (flags == CHFL_CHANOP) ! sendto_match_TS_servs(0, chptr, cptr, ":%s MODE %s +o %s", me.name, name, parv[0]); + #endif if (chptr->topic[0] != '\0') sendto_one(sptr, rpl_str(RPL_TOPIC), me.name, parv[0], name, chptr->topic); *************** *** 1462,1468 **** } if (check_channelmask(sptr, cptr, name)) continue; ! if (!IsServer(sptr) && !is_chan_op(sptr, chptr)) { sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0], chptr->chname); --- 1700,1707 ---- } if (check_channelmask(sptr, cptr, name)) continue; ! if (!IsServer(sptr) && !is_chan_op(sptr, chptr) && ! (MyConnect(sptr) || !DoesTS(cptr) || !chptr->channelts)) { sendto_one(sptr, err_str(ERR_CHANOPRIVSNEEDED), me.name, parv[0], chptr->chname); *************** *** 1966,1968 **** --- 2205,2674 ---- return; } + + static void sjoin_sendit(cptr, sptr, chptr, from) + aClient *cptr; + aClient *sptr; + aChannel *chptr; + char *from; + { + sendto_channel_butserv(chptr, sptr, ":%s MODE %s %s %s", from, + chptr->chname, modebuf, parabuf); + #ifndef TS_ONLY + sendto_match_TS_servs(0, chptr, cptr, ":%s MODE %s %s %s", + from, chptr->chname, modebuf, parabuf); + #endif + } + + /* + * m_sjoin + * parv[0] - sender + * parv[1] - TS + * parv[2] - channel + * parv[3] - modes + n arguments (key and/or limit) + * parv[4+n] - flags+nick list (all in one parameter) + + * + * process a SJOIN, taking the TS's into account to either ignore the + * incomign modes or undo the existing ones or merge them, and JOIN + * all the specified users while sending JOIN/MODEs to non-TS servers + * and to clients + */ + + int m_sjoin(cptr, sptr, parc, parv) + aClient *cptr; + aClient *sptr; + int parc; + char *parv[]; + { + aChannel *chptr; + aClient *acptr; + ts_val newts, oldts, tstosend; + static Mode mode, *oldmode; + Link *l; + int args = 0, haveops = 0, keepourmodes = 1, keepnewmodes = 1, + doesop = 0, what = 0, pargs = 0, *ip, fl, people = 0, isnew; + Reg1 char *s, *s0; + static char numeric[16], sjbuf[BUFSIZE]; + char *mbuf = modebuf, *t = sjbuf, *p; + + static int flags[] = { + MODE_PRIVATE, 'p', MODE_SECRET, 's', + MODE_MODERATED, 'm', MODE_NOPRIVMSGS, 'n', + MODE_TOPICLIMIT, 't', MODE_INVITEONLY, 'i', + 0x0, 0x0 }; + + if (check_registered(sptr) || IsClient(sptr) || parc < 5) + return 0; + if (!IsChannelName(parv[2]) || + check_channelmask(sptr, cptr, parv[2]) == -1) + return 0; + newts = atol(parv[1]); + bzero((char *)&mode, sizeof(mode)); + + s = parv[3]; + while (*s) + switch(*(s++)) + { + case 'i': + mode.mode |= MODE_INVITEONLY; + break; + case 'n': + mode.mode |= MODE_NOPRIVMSGS; + break; + case 'p': + mode.mode |= MODE_PRIVATE; + break; + case 's': + mode.mode |= MODE_SECRET; + break; + case 'm': + mode.mode |= MODE_MODERATED; + break; + case 't': + mode.mode |= MODE_TOPICLIMIT; + break; + case 'k': + strncpyzt(mode.key, parv[4+args], KEYLEN+1); + args++; + if (parc < 5+args) return 0; + break; + case 'l': + mode.limit = atoi(parv[4+args]); + args++; + if (parc < 5+args) return 0; + break; + } + + *parabuf = '\0'; + + isnew = ChannelExists(parv[2]) ? 0 : 1; + chptr = get_channel(sptr, parv[2], CREATE); + oldts = chptr->channelts; + + /* we only look if any ops are introduced if we'll actually need + * to use the info + */ + if (!isnew && newts > 0 && oldts > 0 && newts != oldts) + { + static char nicks[BUFSIZE]; + + strcpy(nicks, parv[4+args]); + for (s=strtoken(&p, nicks, " "); s; s=strtoken(&p, NULL, " ")) + if (*s == '@' || s[1] == '@') + { + while (*s == '@' || *s == '+') + s++; + if (!(acptr = find_chasing(sptr, s, NULL))) + continue; + if (acptr->from != cptr) + continue; + doesop = 1; + break; + } + } + + for (l = chptr->members; l && l->value.cptr; l = l->next) + if (l->flags & MODE_CHANOP) + { + haveops++; + break; + } + + oldmode = &chptr->mode; + + if (isnew) + chptr->channelts = tstosend = newts; + else if (newts == 0 || oldts == 0) + chptr->channelts = tstosend = 0; + else if (newts == oldts) + tstosend = oldts; + else if (newts < oldts) + { + if (doesop) + keepourmodes = 0; + if (haveops && !doesop) + tstosend = oldts; + else + chptr->channelts = tstosend = newts; + } + else + { + if (haveops) + keepnewmodes = 0; + if (doesop && !haveops) + { + chptr->channelts = tstosend = newts; + if (MyConnect(sptr)) + ts_warn("Hacked ops on opless channel: %s", + chptr->chname); + } + else + tstosend = oldts; + } + + if (!keepnewmodes) + mode = *oldmode; + else if (keepourmodes) + { + mode.mode |= oldmode->mode; + if (oldmode->limit > mode.limit) + mode.limit = oldmode->limit; + if (strcmp(mode.key, oldmode->key) < 0) + strcpy(mode.key, oldmode->key); + } + + for (ip = flags; *ip; ip += 2) + if ((*ip & mode.mode) && !(*ip & oldmode->mode)) + { + if (what != 1) + { + *mbuf++ = '+'; + what = 1; + } + *mbuf++ = *(ip+1); + } + for (ip = flags; *ip; ip += 2) + if ((*ip & oldmode->mode) && !(*ip & mode.mode)) + { + if (what != -1) + { + *mbuf++ = '-'; + what = -1; + } + *mbuf++ = *(ip+1); + } + if (oldmode->limit && !mode.limit) + { + if (what != -1) + { + *mbuf++ = '-'; + what = -1; + } + *mbuf++ = 'l'; + } + if (oldmode->key[0] && !mode.key[0]) + { + if (what != -1) + { + *mbuf++ = '-'; + what = -1; + } + *mbuf++ = 'k'; + strcat(parabuf, oldmode->key); + strcat(parabuf, " "); + pargs++; + } + if (mode.limit && oldmode->limit != mode.limit) + { + if (what != 1) + { + *mbuf++ = '+'; + what = 1; + } + *mbuf++ = 'l'; + (void)sprintf(numeric, "%-15d", mode.limit); + if ((s = index(numeric, ' '))) + *s = '\0'; + strcat(parabuf, numeric); + strcat(parabuf, " "); + pargs++; + } + if (mode.key[0] && strcmp(oldmode->key, mode.key)) + { + if (what != 1) + { + *mbuf++ = '+'; + what = 1; + } + *mbuf++ = 'k'; + strcat(parabuf, mode.key); + strcat(parabuf, " "); + pargs++; + } + + chptr->mode = mode; + + if (!keepourmodes) + { + what = 0; + for (l = chptr->members; l && l->value.cptr; l = l->next) + { + if (l->flags & MODE_CHANOP) + { + if (what != -1) + { + *mbuf++ = '-'; + what = -1; + } + *mbuf++ = 'o'; + strcat(parabuf, l->value.cptr->name); + strcat(parabuf, " "); + pargs++; + if (pargs >= (MAXMODEPARAMS-2)) + { + *mbuf = '\0'; + sjoin_sendit(cptr, sptr, chptr, + parv[0]); + mbuf = modebuf; + *mbuf = parabuf[0] = '\0'; + pargs = what = 0; + } + l->flags &= ~MODE_CHANOP; + } + if (l->flags & MODE_VOICE) + { + if (what != -1) + { + *mbuf++ = '-'; + what = -1; + } + *mbuf++ = 'v'; + strcat(parabuf, l->value.cptr->name); + strcat(parabuf, " "); + pargs++; + if (pargs >= (MAXMODEPARAMS-2)) + { + *mbuf = '\0'; + sjoin_sendit(cptr, sptr, chptr, + parv[0]); + mbuf = modebuf; + *mbuf = parabuf[0] = '\0'; + pargs = what = 0; + } + l->flags &= ~MODE_VOICE; + } + } + } + if (mbuf != modebuf) + { + *mbuf = '\0'; + sjoin_sendit(cptr, sptr, chptr, parv[0]); + } + + *modebuf = *parabuf = '\0'; + if (parv[3][0] != '0' && keepnewmodes) + channel_modes(sptr, modebuf, parabuf, chptr); + else + { + modebuf[0] = '0'; + modebuf[1] = '\0'; + } + + sprintf(t, ":%s SJOIN %ld %s %s %s :", parv[0], tstosend, parv[2], + modebuf, parabuf); + t += strlen(t); + + mbuf = modebuf; + parabuf[0] = '\0'; + pargs = 0; + *mbuf++ = '+'; + + for (s = s0 = strtoken(&p, parv[args+4], " "); s; + s = s0 = strtoken(&p, NULL, " ")) + { + fl = 0; + if (*s == '@' || s[1] == '@') + fl |= MODE_CHANOP; + if (*s == '+' || s[1] == '+') + fl |= MODE_VOICE; + if (!keepnewmodes) + if (fl & MODE_CHANOP) + fl = MODE_DEOPPED; + else + fl = 0; + while (*s == '@' || *s == '+') + s++; + if (!(acptr = find_chasing(sptr, s, NULL))) + continue; + if (acptr->from != cptr) + continue; + people++; + if (!IsMember(acptr, chptr)) + { + add_user_to_channel(chptr, acptr, fl); + sendto_channel_butserv(chptr, acptr, ":%s JOIN :%s", + s, parv[2]); + #ifndef TS_ONLY + sendto_match_TS_servs(0, chptr, cptr, ":%s JOIN :%s", + s, parv[2]); + #endif + } + if (keepnewmodes) + strcpy(t, s0); + else + strcpy(t, s); + t += strlen(t); + *t++ = ' '; + if (fl & MODE_CHANOP) + { + *mbuf++ = 'o'; + strcat(parabuf, s); + strcat(parabuf, " "); + pargs++; + if (pargs >= (MAXMODEPARAMS-2)) + { + *mbuf = '\0'; + sjoin_sendit(cptr, sptr, chptr, parv[0]); + mbuf = modebuf; + *mbuf++ = '+'; + parabuf[0] = '\0'; + pargs = 0; + } + } + if (fl & MODE_VOICE) + { + *mbuf++ = 'v'; + strcat(parabuf, s); + strcat(parabuf, " "); + pargs++; + if (pargs >= (MAXMODEPARAMS-2)) + { + *mbuf = '\0'; + sjoin_sendit(cptr, sptr, chptr, parv[0]); + mbuf = modebuf; + *mbuf++ = '+'; + parabuf[0] = '\0'; + pargs = 0; + } + } + } + + *mbuf = '\0'; + if (pargs) + sjoin_sendit(cptr, sptr, chptr, parv[0]); + if (people) + { + if (t[-1] == ' ') + t[-1] = '\0'; + else + *t = '\0'; + #ifdef TS_ONLY + sendto_match_servs(chptr, cptr, "%s", sjbuf); + #else + sendto_match_TS_servs(1, chptr, cptr, "%s", sjbuf); + #endif + } + } + + + #ifdef TSDEBUG + /* this code is for debugging purposes only and should be removed in the + ** definitive version of TSora... besides, it's illegible -orabidoo + */ + int m_ts(cptr, sptr, parc, parv) + aClient *cptr, *sptr; + int parc; + char *parv[]; + { + aClient *acptr; + aChannel *chptr; + + if (check_registered_user(sptr)) + return 0; + sendto_one(sptr, ":%s 999 %s :Time delta is: %ld", me.name, sptr->name, timedelta); + if (parc > 1) + { + if (*parv[1] == '#' || *parv[1] == '&') + { + chptr = get_channel(sptr, parv[1], 0); + if (!chptr) + { + sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), + me.name, parv[0], parv[1]); + return 0; + } + sendto_one(sptr, ":%s 999 %s :Channel - %s : %ld", + me.name, sptr->name, chptr->chname, + chptr->channelts); + } + else + { + acptr = find_chasing(sptr, parv[1], NULL); + if (!acptr) + return 0; + sendto_one(sptr, ":%s 999 %s :User - %s : %ld", + me.name, sptr->name, acptr->name, + acptr->tsinfo); + } + return 0; + } + for (acptr = client; acptr; acptr = acptr->next) + { + if (IsPerson(acptr)) + sendto_one(sptr, ":%s 999 %s :User - %s : %ld", me.name, + sptr->name, acptr->name, acptr->tsinfo); + else if (IsServer(acptr) && MyConnect(acptr)) + sendto_one(sptr, ":%s 999 %s :Server - %s (%s)", me.name, + sptr->name, acptr->name, + (DoesTS(acptr) ? "does TS" : "no TS")); + } + for (chptr = channel; chptr; chptr = chptr->nextch) + sendto_one(sptr, ":%s 999 %s :Channel - %s : %ld", me.name, + sptr->name, chptr->chname, chptr->channelts); + return 0; + } + + #endif + + *** ../irc2.8.21/ircd/s_bsd.c Sun Nov 6 12:03:35 1994 --- ircd/s_bsd.c Thu Dec 21 10:55:09 1995 *************** *** 92,97 **** --- 92,99 ---- #endif static char readbuf[8192]; + extern ts_val timedelta; + /* * Try and find the correct name to use with getrlimit() for setting the max. * number of files allowed to be open by this process. *************** *** 910,916 **** return -1; } if (!BadPtr(aconf->passwd)) ! sendto_one(cptr, "PASS :%s", aconf->passwd); aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER); if (!aconf) --- 912,918 ---- return -1; } if (!BadPtr(aconf->passwd)) ! sendto_one(cptr, "PASS %s :TS", aconf->passwd); aconf = find_conf(cptr->confs, cptr->name, CONF_NOCONNECT_SERVER); if (!aconf) *** ../irc2.8.21/ircd/s_debug.c Mon Oct 31 12:48:04 1994 --- ircd/s_debug.c Sun May 18 22:35:26 1997 *************** *** 116,121 **** --- 116,136 ---- #ifdef V28PlusOnly '8', #endif + ' ', + 'T', + 'S', + #ifdef TS_CURRENT + '0' + TS_CURRENT, + #endif + #ifdef TSDEBUG + 'd', + #endif + #ifdef TS_ONLY + 'o', + #endif + #ifdef TS_WARNINGS + 'w', + #endif '\0'}; #include "numeric.h" *** ../irc2.8.21/ircd/s_err.c Mon May 2 13:50:24 1994 --- ircd/s_err.c Fri May 16 07:53:34 1997 *************** *** 153,159 **** /* 323 */ RPL_LISTEND, ":End of /LIST", /* 324 */ RPL_CHANNELMODEIS, "%s %s %s", 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL, ! 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL, /* 331 */ RPL_NOTOPIC, "%s :No topic is set.", /* 332 */ RPL_TOPIC, "%s :%s", 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL, --- 153,161 ---- /* 323 */ RPL_LISTEND, ":End of /LIST", /* 324 */ RPL_CHANNELMODEIS, "%s %s %s", 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL, ! 0, (char *)NULL, ! /* 329 */ RPL_CREATIONTIME, "%s %lu", ! 0, (char *)NULL, /* 331 */ RPL_NOTOPIC, "%s :No topic is set.", /* 332 */ RPL_TOPIC, "%s :%s", 0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL, *** ../irc2.8.21/ircd/s_misc.c Mon May 2 13:50:22 1994 --- ircd/s_misc.c Mon Dec 18 11:34:34 1995 *************** *** 212,223 **** else { if (showip) ! (void)sprintf(nbuf, "%s[%s@%s.%u]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : sptr->username, ! inetntoa((char *)&sptr->ip), ! (unsigned int)sptr->port); else { if (mycmp(sptr->name, sptr->sockhost)) --- 212,222 ---- else { if (showip) ! (void)sprintf(nbuf, "%s[%s@%s]", sptr->name, (!(sptr->flags & FLAGS_GOTID)) ? "" : sptr->username, ! inetntoa((char *)&sptr->ip)); else { if (mycmp(sptr->name, sptr->sockhost)) *** ../irc2.8.21/ircd/s_serv.c Thu Nov 10 16:38:26 1994 --- ircd/s_serv.c Sun May 18 22:51:50 1997 *************** *** 42,47 **** --- 42,49 ---- static char buf[BUFSIZE]; + extern ts_val timedelta; + /* ** m_functions execute protocol messages on this server: ** *************** *** 243,248 **** --- 245,312 ---- } /* + ** ts_servcount + ** returns the number of TS servers that are connected to us + */ + int ts_servcount() + { + Reg1 int i; + Reg2 aClient *acptr; + Reg3 int r = 0; + + for (i = 0; i <= highest_fd; i++) + if ((acptr = local[i]) && IsServer(acptr) && DoesTS(acptr)) + r++; + return r; + } + + /* + ** m_svinfo + ** parv[0] = sender prefix + ** parv[1] = TS_CURRENT for the server + ** parv[2] = TS_MIN for the server + ** parv[3] = server is standalone or connected to non-TS only + ** parv[4] = server's idea of UTC time + */ + int m_svinfo(cptr, sptr, parc, parv) + aClient *cptr, *sptr; + int parc; + char *parv[]; + { + Reg1 ts_val v; + + if (!IsServer(sptr) || !MyConnect(sptr) || !DoesTS(sptr) || parc < 5) + return 0; + + if (TS_CURRENT < atoi(parv[2]) || atoi(parv[1]) < TS_MIN) + { + #ifdef TS_ONLY + /* + ** a server with the wrong TS version connected; since we're + ** TS_ONLY we can't fall back to the non-TS protocol so + ** we drop the link -orabidoo + */ + sendto_ops("Link %s dropped, wrong TS protocol version (%s,%s)", + get_client_name(sptr, TRUE), parv[1], parv[2]); + return exit_client(sptr, sptr, sptr, "Incompatible TS version"); + #else + sptr->tsinfo = 0; + return 0; + #endif + } + + if (atoi(parv[3])) + v = (atol(parv[4]) - (ts_val)time(NULL) - timedelta) / 2; + else + v = atol(parv[4]) - (ts_val)time(NULL) - timedelta; + + if (ts_servcount() == 1) + timedelta += v; + + return 0; + } + + /* ** m_server ** parv[0] = sender prefix ** parv[1] = servername *************** *** 468,473 **** --- 532,550 ---- ** to be a SERVER. Check if this is allowed and change ** status accordingly... */ + + #ifdef TS_ONLY + /* + ** Reject a direct nonTS server connection if we're TS_ONLY -orabidoo + */ + if (!DoesTS(cptr)) + { + sendto_ops("Link %s dropped, non-TS server", + get_client_name(cptr, TRUE)); + return exit_client(cptr, cptr, cptr, "Non-TS server"); + } + #endif + strncpyzt(cptr->name, host, sizeof(cptr->name)); strncpyzt(cptr->info, info[0] ? info:me.name, sizeof(cptr->info)); cptr->hopcount = hop; *************** *** 489,497 **** --- 566,601 ---- } + static void sendnick_TS(cptr, acptr) + aClient *cptr, *acptr; + { + static char ubuf[12]; + + if (IsPerson(acptr)) + { + send_umode(NULL, acptr, 0, SEND_UMODES, + ubuf); + if (!*ubuf) + strcpy(ubuf, "+"); + sendto_one(cptr, "NICK %s %d %ld %s %s %s %s :%s", acptr->name, + acptr->hopcount + 1, acptr->tsinfo, ubuf, + acptr->user->username, acptr->user->host, + acptr->user->server, acptr->info); + } + else if (IsService(acptr)) + { + sendto_one(cptr,"NICK %s :%d", + acptr->name, + acptr->hopcount + 1); + sendto_one(cptr,":%s SERVICE * * :%s", acptr->name, + acptr->info); + } + } + int m_server_estab(cptr) Reg1 aClient *cptr; { + Reg1 aChannel *chptr; Reg2 aClient *acptr; Reg3 aConfItem *aconf, *bconf; char *inpath, *host, *s, *encr; *************** *** 560,566 **** if (IsUnknown(cptr)) { if (bconf->passwd[0]) ! sendto_one(cptr,"PASS :%s",bconf->passwd); /* ** Pass my info to the new server */ --- 664,670 ---- if (IsUnknown(cptr)) { if (bconf->passwd[0]) ! sendto_one(cptr,"PASS %s :TS", bconf->passwd); /* ** Pass my info to the new server */ *************** *** 587,592 **** --- 691,701 ---- *s = '@'; } + if (DoesTS(cptr)) + sendto_one(cptr, "SVINFO %d %d %d :%ld", TS_CURRENT, TS_MIN, + (ts_servcount() == 0 ? 1 : 0), + (ts_val)time(NULL) + timedelta); + det_confs_butmask(cptr, CONF_LEAF|CONF_HUB|CONF_NOCONNECT_SERVER); /* ** *WARNING* *************** *** 679,720 **** } } ! for (acptr = &me; acptr; acptr = acptr->prev) { ! /* acptr->from == acptr for acptr == cptr */ ! if (acptr->from == cptr) ! continue; ! if (IsPerson(acptr)) { /* ** IsPerson(x) is true only when IsClient(x) is true. ** These are only true when *BOTH* NICK and USER have ** been received. -avalon */ ! sendto_one(cptr,"NICK %s :%d",acptr->name, ! acptr->hopcount + 1); ! sendto_one(cptr,":%s USER %s %s %s :%s", acptr->name, ! acptr->user->username, acptr->user->host, ! acptr->user->server, acptr->info); ! send_umode(cptr, acptr, 0, SEND_UMODES, buf); ! send_user_joins(cptr, acptr); ! } ! else if (IsService(acptr)) ! { ! sendto_one(cptr,"NICK %s :%d", ! acptr->name, acptr->hopcount + 1); ! sendto_one(cptr,":%s SERVICE * * :%s", ! acptr->name, acptr->info); } ! } ! /* ! ** Last, pass all channels plus statuses ! */ ! { ! Reg1 aChannel *chptr; for (chptr = channel; chptr; chptr = chptr->nextch) send_channel_modes(cptr, chptr); ! } return 0; } --- 788,880 ---- } } ! if (DoesTS(cptr)) { ! Link *l; ! static char nickissent = 1; ! ! /* ! ** Send it in the shortened format with the TS, if ! ** it's a TS server; walk the list of channels, sending ! ** all the nicks that haven't been sent yet for each ! ** channel, then send the channel itself -- it's less ! ** obvious than sending all nicks first, but on the ! ** receiving side memory will be allocated more nicely ! ** saving a few seconds in the handling of a split ! ** -orabidoo ! */ ! ! nickissent = 3 - nickissent; ! /* flag used for each nick to check if we've sent it ! yet - must be different each time and !=0, so we ! alternate between 1 and 2 -orabidoo ! */ ! for (chptr = channel; chptr; chptr = chptr->nextch) ! { ! for (l = chptr->members; l; l = l->next) ! { ! acptr = l->value.cptr; ! if (acptr->nicksent != nickissent) ! { ! acptr->nicksent = nickissent; ! if (acptr->from != cptr) ! sendnick_TS(cptr, acptr); ! } ! } ! send_channel_modes(cptr, chptr); ! } ! /* ! ** also send out those that are not on any channel ! */ ! for (acptr = &me; acptr; acptr = acptr->prev) ! if (acptr->nicksent != nickissent) ! { ! acptr->nicksent = nickissent; ! if (acptr->from != cptr) ! sendnick_TS(cptr, acptr); ! } ! ! } ! else ! { ! /* ! ** do it the usual way, for non-TS servers -orabidoo ! */ ! for (acptr = &me; acptr; acptr = acptr->prev) { + /* acptr->from == acptr for acptr == cptr */ + if (acptr->from == cptr) + continue; + if (IsPerson(acptr)) + { /* ** IsPerson(x) is true only when IsClient(x) is true. ** These are only true when *BOTH* NICK and USER have ** been received. -avalon */ ! sendto_one(cptr,"NICK %s :%d",acptr->name, ! acptr->hopcount + 1); ! sendto_one(cptr, ! ":%s USER %s %s %s :%s", acptr->name, ! acptr->user->username, acptr->user->host, ! acptr->user->server, acptr->info); ! send_umode(cptr, acptr, 0, SEND_UMODES, buf); ! send_user_joins(cptr, acptr); ! } ! else if (IsService(acptr)) ! { ! sendto_one(cptr,"NICK %s :%d", ! acptr->name, acptr->hopcount + 1); ! sendto_one(cptr,":%s SERVICE * * :%s", ! acptr->name, acptr->info); ! } } ! /* ! ** Last, pass all channels plus statuses ! */ for (chptr = channel; chptr; chptr = chptr->nextch) send_channel_modes(cptr, chptr); ! } return 0; } *** ../irc2.8.21/ircd/s_user.c Sat Sep 17 15:32:14 1994 --- ircd/s_user.c Wed Jun 25 00:48:24 1997 *************** *** 37,47 **** #include #include "h.h" ! void send_umode_out PROTO((aClient*, aClient *, int)); void send_umode PROTO((aClient *, aClient *, int, int, char *)); static char buf[BUFSIZE], buf2[BUFSIZE]; /* ** m_functions execute protocol messages on this server: ** --- 37,58 ---- #include #include "h.h" ! void send_umode_out PROTO((aClient*, aClient *, int, int)); void send_umode PROTO((aClient *, aClient *, int, int, char *)); + int do_user PROTO((char *, aClient *, aClient*, char *, char *, char *, + char *)); + + extern ts_val timedelta; static char buf[BUFSIZE], buf2[BUFSIZE]; + static int user_modes[] = { FLAGS_OPER, 'o', + FLAGS_LOCOP, 'O', + FLAGS_INVISIBLE, 'i', + FLAGS_WALLOP, 'w', + FLAGS_SERVNOTICE, 's', + 0, 0 }; + /* ** m_functions execute protocol messages on this server: ** *************** *** 302,307 **** --- 313,320 ---- ** available. Doing it is not so simple though, would have ** to implement the following: ** + ** (actually it has been implemented already for a while) -orabidoo + ** ** 1) user telnets in and gives only "NICK foobar" and waits ** 2) another user far away logs in normally with the nick ** "foobar" (quite legal, as this server didn't propagate *************** *** 320,325 **** --- 333,339 ---- { Reg1 aConfItem *aconf; char *parv[3]; + static char ubuf[12]; short oldstatus = sptr->status; anUser *user = sptr->user; int i; *************** *** 432,443 **** } } ! sendto_serv_butone(cptr, "NICK %s :%d", nick, sptr->hopcount+1); ! sendto_serv_butone(cptr, ":%s USER %s %s %s :%s", nick, user->username, user->host, user->server, sptr->info); ! if (MyConnect(sptr)) ! send_umode_out(cptr, sptr, 0); #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_NICK, sptr, "NICK %s :%d", nick, sptr->hopcount); --- 446,472 ---- } } ! send_umode(NULL, sptr, 0, SEND_UMODES, ubuf); ! if (!*ubuf) ! strcpy(ubuf, "+"); ! ! #ifdef TS_ONLY ! sendto_serv_butone(cptr, "NICK %s %d %ld %s %s %s %s :%s", ! nick, sptr->hopcount+1, sptr->tsinfo, ubuf, ! user->username, user->host, user->server, ! sptr->info); ! #else ! sendto_TS_serv_butone(0, cptr, "NICK %s :%d", nick, sptr->hopcount+1); ! sendto_TS_serv_butone(0, cptr, ":%s USER %s %s %s :%s", nick, user->username, user->host, user->server, sptr->info); ! sendto_TS_serv_butone(1, cptr, "NICK %s %d %ld %s %s %s %s :%s", ! nick, sptr->hopcount+1, sptr->tsinfo, ubuf, ! user->username, user->host, user->server, ! sptr->info); ! #endif ! if (ubuf[1]) ! send_umode_out(cptr, sptr, 0, 0); #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_NICK, sptr, "NICK %s :%d", nick, sptr->hopcount); *************** *** 453,458 **** --- 482,494 ---- ** m_nick ** parv[0] = sender prefix ** parv[1] = nickname + ** parv[2] = optional hopcount when new user; TS when nick change + ** parv[3] = optional TS + ** parv[4] = optional umode + ** parv[5] = optional username + ** parv[6] = optional hostname + ** parv[7] = optional server + ** parv[8] = optional ircname */ int m_nick(cptr, sptr, parc, parv) aClient *cptr, *sptr; *************** *** 461,473 **** { aClient *acptr; char nick[NICKLEN+2], *s; ! if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (MyConnect(sptr) && (s = (char *)index(parv[1], '~'))) *s = '\0'; strncpyzt(nick, parv[1], NICKLEN+1); --- 497,518 ---- { aClient *acptr; char nick[NICKLEN+2], *s; ! ts_val newts = 0; ! int doests, sameuser = 0; ! if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } + if (!IsServer(sptr) && IsServer(cptr) && parc > 2) + newts = atol(parv[2]); + else if (IsServer(sptr) && parc > 3) + newts = atol(parv[3]); + + doests = (IsServer(cptr) && DoesTS(cptr)); + if (MyConnect(sptr) && (s = (char *)index(parv[1], '~'))) *s = '\0'; strncpyzt(nick, parv[1], NICKLEN+1); *************** *** 610,646 **** ** same time, or net reconnecting) or just two net fragmens becoming ** joined and having same nicks in use. We cannot have TWO users with ** same nick--purge this NICK from the system with a KILL... >;) - ** - ** The client indicated by 'acptr' is dead meat, give at least some - ** indication of the reason why we are just dropping it cold. */ - sendto_one(acptr, err_str(ERR_NICKCOLLISION), - me.name, acptr->name, acptr->name); /* ** This seemingly obscure test (sptr == cptr) differentiates ** between "NICK new" (TRUE) and ":old NICK new" (FALSE) forms. */ ! if (sptr == cptr) { ! sendto_ops("Nick collision on %s(%s <- %s)", ! acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! /* ! ** A new NICK being introduced by a neighbouring ! ** server (e.g. message type "NICK new" received) ! */ ! ircstp->is_kill++; ! sendto_serv_butone(NULL, /* all servers */ ! ":%s KILL %s :%s (%s <- %s)", ! me.name, acptr->name, me.name, ! acptr->from->name, /* NOTE: Cannot use get_client_name twice ** here, it returns static string pointer: ** the other info would be lost */ get_client_name(cptr, FALSE)); ! acptr->flags |= FLAGS_KILLED; ! return exit_client(cptr, acptr, &me, "Nick collision"); } /* ** A NICK change has collided (e.g. message type --- 655,730 ---- ** same time, or net reconnecting) or just two net fragmens becoming ** joined and having same nicks in use. We cannot have TWO users with ** same nick--purge this NICK from the system with a KILL... >;) */ /* ** This seemingly obscure test (sptr == cptr) differentiates ** between "NICK new" (TRUE) and ":old NICK new" (FALSE) forms. */ ! /* ! ** Changed to something reasonable like IsServer(sptr) ! ** (true if "NICK new", false if ":old NICK new") -orabidoo ! */ ! ! if (IsServer(sptr)) { ! /* ! ** A new NICK being introduced by a neighbouring ! ** server (e.g. message type "NICK new" received) ! */ ! if (acptr->user) ! sameuser = (parc > 6) && ! mycmp(acptr->user->username, parv[5]) == 0 && ! mycmp(acptr->user->host, parv[6]) == 0; ! else ! newts = 0; /* force both kills */ ! ! if (!doests || !newts || !acptr->tsinfo ! || (newts == acptr->tsinfo)) ! { ! sendto_ops("Nick collision on %s(%s <- %s)(both killed)", ! acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_one(acptr, err_str(ERR_NICKCOLLISION), ! me.name, acptr->name, acptr->name); ! sendto_serv_butone(NULL, /* all servers */ ! ":%s KILL %s :%s (%s <- %s)", ! me.name, acptr->name, me.name, ! acptr->from->name, /* NOTE: Cannot use get_client_name twice ** here, it returns static string pointer: ** the other info would be lost */ + get_client_name(cptr, FALSE)); + acptr->flags |= FLAGS_KILLED; + return exit_client(cptr, acptr, &me, "Nick collision"); + } + else if ((sameuser && newts < acptr->tsinfo) || + (!sameuser && newts > acptr->tsinfo)) + return 0; + else + { + if (sameuser) + sendto_ops("Nick collision on %s(%s <- %s)(older killed)", + acptr->name, acptr->from->name, get_client_name(cptr, FALSE)); ! else ! sendto_ops("Nick collision on %s(%s <- %s)(newer killed)", ! acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ! ircstp->is_kill++; ! sendto_one(acptr, err_str(ERR_NICKCOLLISION), ! me.name, acptr->name, acptr->name); ! sendto_serv_butone(sptr, /* all servers but sptr */ ! ":%s KILL %s :%s (%s <- %s)", ! me.name, acptr->name, me.name, ! acptr->from->name, ! get_client_name(cptr, FALSE)); ! acptr->flags |= FLAGS_KILLED; ! (void)exit_client(cptr, acptr, &me, "Nick collision"); ! goto nickkilldone; ! } } /* ** A NICK change has collided (e.g. message type *************** *** 649,671 **** ** must be killed from the incoming connection, and "old" must ** be purged from all outgoing connections. */ ! sendto_ops("Nick change collision from %s to %s(%s <- %s)", ! sptr->name, acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_serv_butone(NULL, /* KILL old from outgoing servers */ ! ":%s KILL %s :%s (%s(%s) <- %s)", me.name, sptr->name, me.name, acptr->from->name, ! acptr->name, get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_serv_butone(NULL, /* Kill new from incoming link */ ! ":%s KILL %s :%s (%s <- %s(%s))", ! me.name, acptr->name, me.name, acptr->from->name, ! get_client_name(cptr, FALSE), sptr->name); ! acptr->flags |= FLAGS_KILLED; ! (void)exit_client(NULL, acptr, &me, "Nick collision(new)"); ! sptr->flags |= FLAGS_KILLED; ! return exit_client(cptr, sptr, &me, "Nick collision(old)"); nickkilldone: if (IsServer(sptr)) --- 733,812 ---- ** must be killed from the incoming connection, and "old" must ** be purged from all outgoing connections. */ ! if (acptr->user && sptr->user) ! sameuser = mycmp(acptr->user->username, sptr->user->username) ! == 0 && ! mycmp(acptr->user->host, sptr->user->host) == 0; ! else ! newts = 0; /* force both kills */ ! ! if (!doests || !newts || !acptr->tsinfo || (newts == acptr->tsinfo)) ! { ! sendto_ops("Nick change collision from %s to %s(%s <- %s)(both killed)", ! sptr->name, acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_one(acptr, err_str(ERR_NICKCOLLISION), ! me.name, acptr->name, acptr->name); ! sendto_serv_butone(NULL, /* KILL old from outgoing servers */ ! ":%s KILL %s :%s (%s(%s) <- %s)", ! me.name, sptr->name, me.name, acptr->from->name, ! acptr->name, get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_serv_butone(NULL, /* Kill new from incoming link */ ! ":%s KILL %s :%s (%s <- %s(%s))", ! me.name, acptr->name, me.name, acptr->from->name, ! get_client_name(cptr, FALSE), sptr->name); ! acptr->flags |= FLAGS_KILLED; ! (void)exit_client(NULL, acptr, &me, "Nick collision(new)"); ! sptr->flags |= FLAGS_KILLED; ! return exit_client(cptr, sptr, &me, "Nick collision(old)"); ! } ! else if ((sameuser && newts < acptr->tsinfo) || ! (!sameuser && newts > acptr->tsinfo)) ! { ! if (sameuser) ! sendto_ops("Nick change collision from %s to %s(%s <- %s)(older killed)", ! sptr->name, acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! else ! sendto_ops("Nick change collision from %s to %s(%s <- %s)(newer killed)", ! sptr->name, acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ircstp->is_kill++; ! sendto_serv_butone(cptr, /* KILL old from outgoing servers */ ! ":%s KILL %s :%s (%s(%s) <- %s)", me.name, sptr->name, me.name, acptr->from->name, ! acptr->name, get_client_name(cptr, FALSE)); ! sptr->flags |= FLAGS_KILLED; ! if (sameuser) ! return exit_client(cptr, sptr, &me, "Nick collision(old)"); ! else ! return exit_client(cptr, sptr, &me, "Nick collision(new)"); ! } ! else ! { ! if (sameuser) ! sendto_ops("Nick collision on %s(%s <- %s)(older killed)", ! acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! else ! sendto_ops("Nick collision on %s(%s <- %s)(newer killed)", ! acptr->name, acptr->from->name, ! get_client_name(cptr, FALSE)); ! ! ircstp->is_kill++; ! sendto_one(acptr, err_str(ERR_NICKCOLLISION), ! me.name, acptr->name, acptr->name); ! sendto_serv_butone(sptr, /* all servers but sptr */ ! ":%s KILL %s :%s (%s <- %s)", ! me.name, acptr->name, me.name, ! acptr->from->name, ! get_client_name(cptr, FALSE)); ! acptr->flags |= FLAGS_KILLED; ! (void)exit_client(cptr, acptr, &me, "Nick collision"); ! /* goto nickkilldone; */ ! } nickkilldone: if (IsServer(sptr)) *************** *** 676,681 **** --- 817,857 ---- add_client_to_list(sptr); if (parc > 2) sptr->hopcount = atoi(parv[2]); + if (newts) + sptr->tsinfo = newts; + else + { + newts = sptr->tsinfo = (ts_val)time(NULL) + timedelta; + #ifdef TS_WARNINGS + ts_warn("Remote nick %s introduced without a TS", nick); + #endif + } + /* copy the nick in place */ + (void)strcpy(sptr->name, nick); + (void)add_to_client_hash_table(nick, sptr); + if (parc > 8) + { + Reg1 int *s, flag; + Reg2 char *m; + + /* + ** parse the usermodes -orabidoo + */ + m = &parv[4][1]; + while (*m) + { + for (s = user_modes; (flag = *s); s += 2) + if (*m == *(s+1)) + { + sptr->flags |= flag&SEND_UMODES; + break; + } + m++; + } + + return do_user(nick, cptr, sptr, parv[5], parv[6], + parv[7], parv[8]); + } } else if (sptr->name[0]) { *************** *** 684,693 **** ** on a channel, send note of change to all clients ** on that channel. Propagate notice to other servers. */ sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); if (sptr->user) add_history(sptr); ! sendto_serv_butone(cptr, ":%s NICK :%s", parv[0], nick); #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_NICK, sptr, ":%s NICK :%s", parv[0], nick); --- 860,882 ---- ** on a channel, send note of change to all clients ** on that channel. Propagate notice to other servers. */ + if (mycmp(parv[0], nick)) + sptr->tsinfo = newts ? newts : (ts_val)time(NULL) + + timedelta; sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick); if (sptr->user) + { add_history(sptr); ! #ifdef TS_ONLY ! sendto_serv_butone(cptr, ":%s NICK %s :%ld", ! parv[0], nick, sptr->tsinfo); ! #else ! sendto_TS_serv_butone(1, cptr, ":%s NICK %s :%ld", ! parv[0], nick, sptr->tsinfo); ! sendto_TS_serv_butone(0, cptr, ":%s NICK :%s", parv[0], ! nick); ! #endif ! } #ifdef USE_SERVICES check_services_butone(SERVICE_WANT_NICK, sptr, ":%s NICK :%s", parv[0], nick); *************** *** 699,704 **** --- 888,894 ---- /* This had to be copied here to avoid problems.. */ (void)strcpy(sptr->name, nick); + sptr->tsinfo = time(NULL) + timedelta; if (sptr->user) /* ** USER already received, now we have NICK. *************** *** 869,874 **** --- 1059,1066 ---- *server = '@'; if (host) *--host = '%'; + if (acptr && IsInvisible(acptr)) + acptr = NULL; if (acptr) { if (count == 1) *************** *** 1208,1213 **** --- 1400,1409 ---- *buf = '\0'; len = 0; } + #ifdef TSDEBUG + if (is_deopped(acptr, chptr)) + *(buf + len++) = '-'; + #endif if (is_chan_op(acptr, chptr)) *(buf + len++) = '@'; else if (has_voice(acptr, chptr)) *************** *** 1267,1273 **** { #define UFLAGS (FLAGS_INVISIBLE|FLAGS_WALLOP|FLAGS_SERVNOTICE) char *username, *host, *server, *realname; - anUser *user; if (parc > 2 && (username = (char *)index(parv[1],'@'))) *username = '\0'; --- 1463,1468 ---- *************** *** 1290,1295 **** --- 1485,1503 ---- server = (parc < 4 || BadPtr(parv[3])) ? "" : parv[3]; realname = (parc < 5 || BadPtr(parv[4])) ? "" : parv[4]; + return do_user(parv[0], cptr, sptr, username, host, server, realname); + } + + + /* + ** do_user + */ + int do_user(nick, cptr, sptr, username, host, server, realname) + aClient *cptr, *sptr; + char *nick, *username, *host, *server, *realname; + { + anUser *user; + user = make_user(sptr); if (!MyConnect(sptr)) *************** *** 1302,1308 **** if (!IsUnknown(sptr)) { sendto_one(sptr, err_str(ERR_ALREADYREGISTRED), ! me.name, parv[0]); return 0; } #ifndef NO_DEFAULT_INVISIBLE --- 1510,1516 ---- if (!IsUnknown(sptr)) { sendto_one(sptr, err_str(ERR_ALREADYREGISTRED), ! me.name, nick); return 0; } #ifndef NO_DEFAULT_INVISIBLE *************** *** 1791,1797 **** sptr->user->username, sptr->user->host, IsOper(sptr) ? 'O' : 'o'); sptr->flags |= (FLAGS_SERVNOTICE|FLAGS_WALLOP); ! send_umode_out(cptr, sptr, old); sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]); #if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\ (defined(USE_SYSLOG) && defined(SYSLOG_OPER))) --- 1999,2005 ---- sptr->user->username, sptr->user->host, IsOper(sptr) ? 'O' : 'o'); sptr->flags |= (FLAGS_SERVNOTICE|FLAGS_WALLOP); ! send_umode_out(cptr, sptr, old, 1); sendto_one(sptr, rpl_str(RPL_YOUREOPER), me.name, parv[0]); #if !defined(CRYPT_OPER_PASSWORD) && (defined(FNAME_OPERLOG) ||\ (defined(USE_SYSLOG) && defined(SYSLOG_OPER))) *************** *** 1853,1858 **** --- 2061,2067 ---- ** m_pass ** parv[0] = sender prefix ** parv[1] = password + ** parv[2] = optional extra version information */ int m_pass(cptr, sptr, parc, parv) aClient *cptr, *sptr; *************** *** 1874,1879 **** --- 2083,2097 ---- return 0; } strncpyzt(cptr->passwd, password, sizeof(cptr->passwd)); + if (parc > 2) + { + int l = strlen(parv[2]); + + if (l < 2) + return 0; + if (strcmp(parv[2]+l-2, "TS") == 0) + cptr->tsinfo = (ts_val)TS_DOESTS; + } return 0; } *************** *** 2020,2032 **** } #endif - static int user_modes[] = { FLAGS_OPER, 'o', - FLAGS_LOCOP, 'O', - FLAGS_INVISIBLE, 'i', - FLAGS_WALLOP, 'w', - FLAGS_SERVNOTICE, 's', - 0, 0 }; - /* * m_umode() added 15/10/91 By Darren Reed. * parv[0] - sender --- 2238,2243 ---- *************** *** 2156,2162 **** * compare new flags with old flags and send string which * will cause servers to update correctly. */ ! send_umode_out(cptr, sptr, setflags); return 0; } --- 2367,2373 ---- * compare new flags with old flags and send string which * will cause servers to update correctly. */ ! send_umode_out(cptr, sptr, setflags, 1); return 0; } *************** *** 2216,2224 **** /* * added Sat Jul 25 07:30:42 EST 1992 */ ! void send_umode_out(cptr, sptr, old) aClient *cptr, *sptr; ! int old; { Reg1 int i; Reg2 aClient *acptr; --- 2427,2438 ---- /* * added Sat Jul 25 07:30:42 EST 1992 */ ! /* ! * extra argument evenTS added to send to TS servers or not -orabidoo ! */ ! void send_umode_out(cptr, sptr, old, evenTS) aClient *cptr, *sptr; ! int old, evenTS; { Reg1 int i; Reg2 aClient *acptr; *************** *** 2229,2238 **** # endif for (i = highest_fd; i >= 0; i--) if ((acptr = local[i]) && IsServer(acptr) && ! (acptr != cptr) && (acptr != sptr) && *buf) sendto_one(acptr, ":%s MODE %s :%s", sptr->name, sptr->name, buf); if (cptr && MyClient(cptr)) send_umode(cptr, sptr, old, ALL_UMODES, buf); } --- 2443,2454 ---- # endif for (i = highest_fd; i >= 0; i--) if ((acptr = local[i]) && IsServer(acptr) && ! (acptr != cptr) && (acptr != sptr) && *buf && ! (evenTS || !DoesTS(acptr))) sendto_one(acptr, ":%s MODE %s :%s", sptr->name, sptr->name, buf); if (cptr && MyClient(cptr)) send_umode(cptr, sptr, old, ALL_UMODES, buf); } + *** ../irc2.8.21/common/parse.c Sat May 28 20:40:56 1994 --- common/parse.c Sun Dec 10 04:33:38 1995 *************** *** 490,498 **** * I'm not sure I've got this all right... * - avalon */ ! sendto_ops("Message (%s) for %s[%s!%s@%s] from %s", cmd, ! sptr->name, sptr->from->name, sptr->from->username, ! sptr->from->sockhost, get_client_name(cptr, TRUE)); /* * Incorrect prefix for a server from some connection. If it is a * client trying to be annoying, just QUIT them, if it is a server --- 490,511 ---- * I'm not sure I've got this all right... * - avalon */ ! ! /* ! ** with TS, fake prefixes are a common thing, during the ! ** connect burst when there's a nick collision, and they ! ** must be ignored rather than killed because one of the ! ** two is surviving.. so we don't bother sending them to ! ** all ops everytime, as this could send 'private' stuff ! ** from lagged clients. we do send the ones that cause ! ** servers to be dropped though, as well as the ones from ! ** non-TS servers -orabidoo ! */ ! if (IsServer(sptr) || IsMe(sptr) || (IsServer(cptr) && ! !DoesTS(cptr))) ! sendto_ops("Message (%s) for %s[%s!%s@%s] from %s", cmd, ! sptr->name, sptr->from->name, sptr->from->username, ! sptr->from->sockhost, get_client_name(cptr, TRUE)); /* * Incorrect prefix for a server from some connection. If it is a * client trying to be annoying, just QUIT them, if it is a server *************** *** 509,522 **** * kill, else just exit the lame client. */ if (IsServer(cptr)) ! { ! sendto_serv_butone(NULL, ":%s KILL %s :%s (%s[%s] != %s)", ! me.name, sptr->name, me.name, ! sptr->name, sptr->from->name, ! get_client_name(cptr, TRUE)); ! sptr->flags |= FLAGS_KILLED; ! return exit_client(cptr, sptr, &me, "Fake Prefix"); ! } return exit_client(cptr, cptr, &me, "Fake prefix"); } --- 522,543 ---- * kill, else just exit the lame client. */ if (IsServer(cptr)) ! /* ! ** If the fake prefix is coming from a TS server, discard it ! ** silently -orabidoo ! */ ! if (DoesTS(cptr)) ! return 0; ! else ! { ! sendto_serv_butone(NULL, ! ":%s KILL %s :%s (%s[%s] != %s)", ! me.name, sptr->name, me.name, ! sptr->name, sptr->from->name, ! get_client_name(cptr, TRUE)); ! sptr->flags |= FLAGS_KILLED; ! return exit_client(cptr, sptr, &me, "Fake Prefix"); ! } return exit_client(cptr, cptr, &me, "Fake prefix"); } *** ../irc2.8.21/common/send.c Mon May 2 13:50:11 1994 --- common/send.c Sun May 18 22:03:21 1997 *************** *** 428,433 **** --- 428,489 ---- return; } + + #ifndef TS_ONLY + + /* + * sendto_TS_server_butone + * + * Send a message to all connected TS servers except the 'one', if ts==1, + * and to all connected non-TS servers except the 'one', if ts==0. + */ + # ifndef USE_VARARGS + /*VARARGS*/ + void sendto_TS_serv_butone(ts, one, pattern, p1, p2, p3, p4, p5, p6, p7, p8) + int ts; + aClient *one; + char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8; + { + # else + void sendto_TS_serv_butone(ts, one, pattern, va_alist) + int ts; + aClient *one; + char *pattern; + va_dcl + { + va_list vl; + # endif + Reg1 int i; + Reg2 aClient *cptr; + + # ifdef USE_VARARGS + va_start(vl); + # endif + + # ifdef NPATH + check_command((long)2, pattern, p1, p2, p3); + # endif + + for (i = 0; i <= highest_fd; i++) + { + if (!(cptr = local[i]) || (one && cptr == one->from)) + continue; + if (IsServer(cptr) && (DoesTS(cptr) != 0) == (ts != 0)) + # ifdef USE_VARARGS + sendto_one(cptr, pattern, vl); + } + va_end(vl); + # else + sendto_one(cptr, pattern, p1, p2, p3, p4, + p5, p6, p7, p8); + } + # endif + return; + } + + #endif /* TS_ONLY */ + + /* * sendto_common_channels() * *************** *** 613,618 **** --- 669,747 ---- #endif } + + #ifndef TS_ONLY + + /* + * sendto_match_TS_servs + * + * if ts==0, send to all non-TS servers matching the mask + * if ts==1, send to all TS servers matching the mask + * (or to all if no mask) + */ + #ifndef USE_VARARGS + /*VARARGS*/ + void sendto_match_TS_servs(ts, chptr, from, format, + p1,p2,p3,p4,p5,p6,p7,p8,p9) + int ts; + aChannel *chptr; + aClient *from; + char *format, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9; + { + #else + void sendto_match_TS_servs(ts, chptr, from, format, va_alist) + int ts; + aChannel *chptr; + aClient *from; + char *format; + va_dcl + { + va_list vl; + #endif + Reg1 int i; + Reg2 aClient *cptr; + char *mask; + + #ifdef USE_VARARGS + va_start(vl); + #endif + + # ifdef NPATH + check_command((long)3, format, p1, p2, p3); + # endif + if (chptr) + { + if (*chptr->chname == '&') + return; + if ((mask = (char *)rindex(chptr->chname, ':'))) + mask++; + } + else + mask = (char *)NULL; + + for (i = 0; i <= highest_fd; i++) + { + if (!(cptr = local[i])) + continue; + if ((cptr == from) || !IsServer(cptr) || + (DoesTS(cptr) != 0) != (ts != 0)) + continue; + if (!BadPtr(mask) && IsServer(cptr) && + matches(mask, cptr->name)) + continue; + #ifdef USE_VARARGS + sendto_one(cptr, format, vl); + } + va_end(vl); + #else + sendto_one(cptr, format, p1, p2, p3, p4, p5, p6, p7, p8, p9); + } + #endif + } + + #endif /* TS_ONLY */ + + /* * sendto_match_butone * *************** *** 770,775 **** --- 899,956 ---- sendto_one(cptr, nbuf, p1, p2, p3, p4, p5, p6, p7, p8); } # endif + #endif + return; + } + + /* + ** ts_warn + ** Call sendto_ops, with some flood checking (at most 5 warnings + ** every 5 seconds) + */ + + #ifndef USE_VARARGS + /*VARARGS*/ + void ts_warn(pattern, p1, p2, p3, p4, p5, p6, p7, p8) + char *pattern, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8; + { + #else + void ts_warn(pattern, va_alist) + char *pattern; + va_dcl + { + va_list vl; + #endif + static ts_val last = 0; + static warnings = 0; + register ts_val now; + + #ifdef USE_VARARGS + va_start(vl); + #endif + + /* + ** if we're runnign with TS_WARNINGS enabled and someone does + ** something silly like (remotely) connecting a nonTS server, + ** we'll get a ton of warnings, so we make sure we don't send + ** more than 5 every 5 seconds. -orabidoo + */ + now = time(NULL); + if (now - last < 5) + { + if (++warnings > 5) + return; + } + else + { + last = now; + warnings = 0; + } + + #ifdef USE_VARARGS + sendto_ops(pattern, va_alist); + #else + sendto_ops(pattern, p1, p2, p3, p4, p5, p6, p7, p8); #endif return; } *** ../irc2.8.21/include/h.h Mon May 2 13:50:15 1994 --- include/h.h Sun May 18 22:03:41 1997 *************** *** 118,123 **** --- 118,131 ---- extern void sendto_channel_butone(); /*VARARGS2*/ extern void sendto_serv_butone(); + + #ifndef TS_ONLY + /*VARARGS2*/ + extern void sendto_TS_serv_butone(); + /*VARARGS3*/ + extern void sendto_match_TS_servs(); + #endif + /*VARARGS2*/ extern void sendto_common_channels(); /*VARARGS3*/ *************** *** 130,135 **** --- 138,145 ---- extern void sendto_all_butone(); /*VARARGS1*/ extern void sendto_ops(); + /*VARARGS1*/ + extern void ts_warn(); /*VARARGS3*/ extern void sendto_ops_butone(); /*VARARGS3*/ *************** *** 156,162 **** extern int m_names PROTO((aClient *, aClient *, int, char **)); extern int m_server_estab PROTO((aClient *)); extern void send_umode PROTO((aClient *, aClient *, int, int, char *)); ! extern void send_umode_out PROTO((aClient*, aClient *, int)); #endif extern void free_client PROTO((aClient *)); --- 166,172 ---- extern int m_names PROTO((aClient *, aClient *, int, char **)); extern int m_server_estab PROTO((aClient *)); extern void send_umode PROTO((aClient *, aClient *, int, int, char *)); ! extern void send_umode_out PROTO((aClient*, aClient *, int, int)); #endif extern void free_client PROTO((aClient *)); *** ../irc2.8.21/include/msg.h Mon Nov 14 15:29:49 1994 --- include/msg.h Sat Dec 16 22:51:13 1995 *************** *** 70,75 **** --- 70,80 ---- #define MSG_REHASH "REHASH" /* REHA */ #define MSG_RESTART "RESTART" /* REST */ #define MSG_CLOSE "CLOSE" /* CLOS */ + #define MSG_SVINFO "SVINFO" /* SVINFO */ + #define MSG_SJOIN "SJOIN" /* SJOIN */ + #ifdef TSDEBUG + #define MSG_TS "TS" /* TS */ + #endif #define MSG_DIE "DIE" #define MSG_HASH "HSAH" /* HASH */ #define MSG_DNS "DNS" /* DNS -> DNSS */ *************** *** 89,96 **** extern int m_time(), m_names(), m_admin(); extern int m_lusers(), m_umode(), m_note(), m_close(); extern int m_motd(), m_whowas(); ! extern int m_service(), m_userhost(), m_ison(); extern int m_service(), m_servset(), m_servlist(), m_squery(); #if defined(OPER_REHASH) || defined(LOCOP_REHASH) extern int m_rehash(); #endif --- 94,104 ---- extern int m_time(), m_names(), m_admin(); extern int m_lusers(), m_umode(), m_note(), m_close(); extern int m_motd(), m_whowas(); ! extern int m_service(), m_userhost(), m_ison(), m_svinfo(), m_sjoin(); extern int m_service(), m_servset(), m_servlist(), m_squery(); + #ifdef TSDEBUG + extern int m_ts(); + #endif #if defined(OPER_REHASH) || defined(LOCOP_REHASH) extern int m_rehash(); #endif *************** *** 148,153 **** --- 156,166 ---- { MSG_INFO, m_info, 0, MAXPARA, 1 ,0L }, { MSG_MOTD, m_motd, 0, MAXPARA, 1 ,0L }, { MSG_CLOSE, m_close, 0, MAXPARA, 1 ,0L }, + { MSG_SVINFO, m_svinfo, 0, MAXPARA, 1, 0L }, + { MSG_SJOIN, m_sjoin, 0, MAXPARA, 1, 0L }, + #ifdef TSDEBUG + { MSG_TS, m_ts, 0, MAXPARA, 1, 0L }, + #endif #if defined(NPATH) && !defined(CLIENT_COMPILE) { MSG_NOTE, m_note, 0, 1, 1 ,0L }, #endif *** ../irc2.8.21/include/numeric.h Mon May 2 13:50:13 1994 --- include/numeric.h Fri May 16 07:55:59 1997 *************** *** 220,225 **** --- 220,227 ---- #define RPL_LISTEND 323 #define RPL_CHANNELMODEIS 324 + #define RPL_CREATIONTIME 329 + #define RPL_NOTOPIC 331 #define RPL_TOPIC 332 *** ../irc2.8.21/include/patchlevel.h Sat Dec 3 12:16:18 1994 --- include/patchlevel.h Sat Dec 16 15:57:18 1995 *************** *** 17,21 **** */ #ifndef PATCHLEVEL ! #define PATCHLEVEL "2.8.21" #endif --- 17,21 ---- */ #ifndef PATCHLEVEL ! #define PATCHLEVEL "2.8.21+TSora" #endif *** ../irc2.8.21/include/struct.h Mon May 2 13:50:15 1994 --- include/struct.h Sun May 18 20:25:09 1997 *************** *** 30,35 **** --- 30,38 ---- #ifdef STDDEFH # include #endif + #ifdef ORATIMING + #include + #endif #ifdef USE_SYSLOG # include *************** *** 48,53 **** --- 51,57 ---- typedef struct Server aServer; typedef struct SLink Link; typedef struct SMode Mode; + typedef long ts_val; #ifndef VMSP #include "class.h" *************** *** 309,319 **** --- 313,325 ---- time_t lasttime; /* ...should be only LOCAL clients? --msa */ time_t firsttime; /* time client was created */ time_t since; /* last time we parsed something */ + ts_val tsinfo; /* TS on the nick, SVINFO on servers */ long flags; /* client flags */ aClient *from; /* == self, if Local Client, *NEVER* NULL! */ int fd; /* >= 0, for local clients */ int hopcount; /* number of servers to this 0 = local */ short status; /* Client type */ + char nicksent; char name[HOSTLEN+1]; /* Unique name of the client, nick or host */ char username[USERLEN+1]; /* username here now for auth stuff */ char info[REALLEN+1]; /* Free form additional client information */ *************** *** 431,439 **** --- 437,451 ---- Link *members; Link *invites; Link *banlist; + ts_val channelts; char chname[1]; }; + #define TS_CURRENT 3 /* current TS protocol version */ + #define TS_MIN 1 /* minimum supported TS protocol version */ + #define TS_DOESTS 0x20000000 + #define DoesTS(x) ((x)->tsinfo == TS_DOESTS) + /* ** Channel Related macros follow */ *************** *** 442,463 **** #define CHFL_CHANOP 0x0001 /* Channel operator */ #define CHFL_VOICE 0x0002 /* the power to speak */ ! #define CHFL_BAN 0x0004 /* ban channel flag */ /* Channel Visibility macros */ #define MODE_CHANOP CHFL_CHANOP #define MODE_VOICE CHFL_VOICE ! #define MODE_PRIVATE 0x0004 ! #define MODE_SECRET 0x0008 ! #define MODE_MODERATED 0x0010 ! #define MODE_TOPICLIMIT 0x0020 ! #define MODE_INVITEONLY 0x0040 ! #define MODE_NOPRIVMSGS 0x0080 ! #define MODE_KEY 0x0100 ! #define MODE_BAN 0x0200 ! #define MODE_LIMIT 0x0400 ! #define MODE_FLAGS 0x07ff /* * mode flags which take another parameter (With PARAmeterS) */ --- 454,477 ---- #define CHFL_CHANOP 0x0001 /* Channel operator */ #define CHFL_VOICE 0x0002 /* the power to speak */ ! #define CHFL_DEOPPED 0x0004 /* deopped by us, modes need to be bounced */ ! #define CHFL_BAN 0x0008 /* ban channel flag */ /* Channel Visibility macros */ #define MODE_CHANOP CHFL_CHANOP #define MODE_VOICE CHFL_VOICE ! #define MODE_DEOPPED CHFL_DEOPPED ! #define MODE_PRIVATE 0x0008 ! #define MODE_SECRET 0x0010 ! #define MODE_MODERATED 0x0020 ! #define MODE_TOPICLIMIT 0x0040 ! #define MODE_INVITEONLY 0x0080 ! #define MODE_NOPRIVMSGS 0x0100 ! #define MODE_KEY 0x0200 ! #define MODE_BAN 0x0400 ! #define MODE_LIMIT 0x0800 ! #define MODE_FLAGS 0x0fff /* * mode flags which take another parameter (With PARAmeterS) */ *************** *** 534,539 **** --- 548,572 ---- #define FLUSH_BUFFER -2 #define UTMP "/etc/utmp" #define COMMA "," + + #ifdef ORATIMING + /* Timing stuff (for performance measurements): compile with -DORATIMING + and put a TMRESET where you want the counter of time spent set to 0, + a TMPRINT where you want the accumulated results, and TMYES/TMNO pairs + around the parts you want timed -orabidoo + */ + extern struct timeval tsdnow, tsdthen; + extern unsigned long tsdms; + #define TMRESET tsdms=0; + #define TMYES gettimeofday(&tsdthen, NULL); + #define TMNO gettimeofday(&tsdnow, NULL); if (tsdnow.tv_sec!=tsdthen.tv_sec) tsdms+=1000000*(tsdnow.tv_sec-tsdthen.tv_sec); tsdms+=tsdnow.tv_usec; tsdms-=tsdthen.tv_usec; + #define TMPRINT sendto_ops("Time spent: %ld ms", tsdms); + #else + #define TMRESET + #define TMYES + #define TMNO + #define TMPRINT + #endif /* IRC client structures */