From 8def99fde8ed83010706032037277be93dc2494e Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Sat, 3 Jun 2000 03:01:11 +0000 Subject: [PATCH] Author: Kev Log message: GLINE storm fix...yeah, this is pretty complicated :/ Basically, if there's a gline for a user we send a NICK for, we make sure and insert %: after the user modes, if present. Status: compiled, tested Testing needed: Test all the code paths thoroughly; this is a rather complicated change, so take nothing for granted. In particular, make sure bursting servers send the right stuff, especially in the no-usermode case, which is the only part I haven't stringently tested. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@248 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 32 +++++++++++++++++++++++++- include/gline.h | 4 +++- include/s_user.h | 4 +++- ircd/gline.c | 11 ++++++++- ircd/m_nick.c | 1 + ircd/m_pong.c | 4 ++-- ircd/m_user.c | 2 +- ircd/s_conf.c | 2 +- ircd/s_serv.c | 28 ++++++++++++++++------- ircd/s_user.c | 58 +++++++++++++++++++++++++++++++++++++----------- 10 files changed, 117 insertions(+), 29 deletions(-) diff --git a/ChangeLog b/ChangeLog index 70c41e7..715e41d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,35 @@ 2000-06-02 Kevin L. Mitchell + * ircd/s_user.c: add struct Gline * argument to register_user; + look up global glines and repropagate them if necessary; send + acknowledgement of gline to remote servers when registering users + + * ircd/s_serv.c (server_estab): don't send acknowledgement of + local glines to remote servers; do send gline acknowledgement of + bursted users + + * ircd/m_user.c (m_user): pass new struct Gline * argument to + register_user + + * ircd/m_pong.c: pass new struct Gline * argument to register_user + + * ircd/m_nick.c (ms_nick): document protocol change + + * ircd/gline.c: support GLINE_LASTMOD + + * include/s_user.h: add struct Gline * argument to register_user + + * include/gline.h: add GLINE_LASTMOD to look up non-zero lastmods + + * ircd/s_conf.c (find_kill): add unsigned int argument to + gline_lookup() + + * ircd/gline.c: add GLINE_GLOBAL to lookup or find only global + glines; add unsigned int argument to gline_lookup() + + * include/gline.h: add GLINE_GLOBAL flag; add unsigned int + argument to gline_lookup() + * ircd/m_server.c: Resend jupe only when there is no % parameter, or when it falls out of bounds: see comments prior to call to jupe_resend(); call server_estab with struct Jupe @@ -1184,7 +1214,7 @@ # # ChangeLog for ircu2.10.11 # -# $Id: ChangeLog,v 1.142 2000-06-03 00:09:12 kev Exp $ +# $Id: ChangeLog,v 1.143 2000-06-03 03:01:10 kev Exp $ # # Insert new changes at beginning of the change list. # diff --git a/include/gline.h b/include/gline.h index 2409016..d623e85 100644 --- a/include/gline.h +++ b/include/gline.h @@ -54,6 +54,8 @@ struct Gline { #define GLINE_FORCE 0x0020 #define GLINE_EXACT 0x0040 #define GLINE_LDEACT 0x0080 /* locally deactivated */ +#define GLINE_GLOBAL 0x0100 /* find only global glines */ +#define GLINE_LASTMOD 0x0200 /* find only glines with non-zero lastmod */ #define GLINE_MASK (GLINE_ACTIVE | GLINE_BADCHAN | GLINE_LOCAL) #define GLINE_ACTMASK (GLINE_ACTIVE | GLINE_LDEACT) @@ -80,7 +82,7 @@ extern int gline_deactivate(struct Client *cptr, struct Client *sptr, struct Gline *gline, time_t lastmod, unsigned int flags); extern struct Gline *gline_find(char *userhost, unsigned int flags); -extern struct Gline *gline_lookup(struct Client *cptr); +extern struct Gline *gline_lookup(struct Client *cptr, unsigned int flags); extern void gline_free(struct Gline *gline); extern void gline_burst(struct Client *cptr); extern int gline_resend(struct Client *cptr, struct Gline *gline); diff --git a/include/s_user.h b/include/s_user.h index 03d3a39..70da19b 100644 --- a/include/s_user.h +++ b/include/s_user.h @@ -12,6 +12,7 @@ struct Client; struct User; +struct Gline; /* * Macros @@ -55,7 +56,8 @@ typedef char* (*InfoFormatter)(struct Client* who, char* buf); extern struct User* make_user(struct Client *cptr); extern void free_user(struct User *user); extern int register_user(struct Client* cptr, struct Client* sptr, - const char* nick, char* username); + const char* nick, char* username, + struct Gline *agline); extern void user_count_memory(size_t* count_out, size_t* bytes_out); diff --git a/ircd/gline.c b/ircd/gline.c index 50c8773..53bd096 100644 --- a/ircd/gline.c +++ b/ircd/gline.c @@ -381,6 +381,9 @@ gline_find(char *userhost, unsigned int flags) if (gline->gl_expire <= CurrentTime) gline_free(gline); + else if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || + (flags & GLINE_LASTMOD && !gline->gl_lastmod)) + continue; else if ((flags & GLINE_EXACT ? ircd_strcmp(gline->gl_user, userhost) : match(gline->gl_user, userhost)) == 0) return gline; @@ -403,6 +406,9 @@ gline_find(char *userhost, unsigned int flags) if (gline->gl_expire <= CurrentTime) gline_free(gline); + else if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || + (flags & GLINE_LASTMOD && !gline->gl_lastmod)) + continue; else if (flags & GLINE_EXACT) { if (ircd_strcmp(gline->gl_host, host) == 0 && ((!user && ircd_strcmp(gline->gl_user, "*") == 0) || @@ -422,7 +428,7 @@ gline_find(char *userhost, unsigned int flags) } struct Gline * -gline_lookup(struct Client *cptr) +gline_lookup(struct Client *cptr, unsigned int flags) { struct Gline *gline; struct Gline *sgline; @@ -432,6 +438,9 @@ gline_lookup(struct Client *cptr) if (gline->gl_expire <= CurrentTime) gline_free(gline); + else if ((flags & GLINE_GLOBAL && gline->gl_flags & GLINE_LOCAL) || + (flags & GLINE_LASTMOD && !gline->gl_lastmod)) + continue; else if ((GlineIsIpMask(gline) ? match(gline->gl_host, ircd_ntoa((const char *)&cptr->ip)) : match(gline->gl_host, cptr->user->host)) == 0 && diff --git a/ircd/m_nick.c b/ircd/m_nick.c index fe02d16..bf31105 100644 --- a/ircd/m_nick.c +++ b/ircd/m_nick.c @@ -244,6 +244,7 @@ int m_nick(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) * parv[4] = username * parv[5] = hostname * parv[6] = umode (optional) + * parv[parc-4] = %: <- Only if matching GLINE * parv[parc-3] = IP# <- Only Protocol >= 10 * parv[parc-2] = YXX, numeric nick <- Only Protocol >= 10 * parv[parc-1] = info diff --git a/ircd/m_pong.c b/ircd/m_pong.c index 95a411e..bed2412 100644 --- a/ircd/m_pong.c +++ b/ircd/m_pong.c @@ -167,7 +167,7 @@ int mr_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* * NICK and USER OK */ - return register_user(cptr, sptr, sptr->name, sptr->user->username); + return register_user(cptr, sptr, sptr->name, sptr->user->username, 0); } else send_reply(sptr, SND_EXPLICIT | ERR_BADPING, @@ -220,7 +220,7 @@ int m_pong(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) sptr->cookie = COOKIE_VERIFIED; if (sptr->user && *sptr->user->host && sptr->name[0]) /* NICK and USER OK */ - return register_user(cptr, sptr, sptr->name, sptr->user->username); + return register_user(cptr, sptr, sptr->name, sptr->user->username); /* XXX DEAD */ } else sendto_one(sptr, ":%s %d %s :To connect, type /QUOTE PONG %u", /* XXX DEAD */ diff --git a/ircd/m_user.c b/ircd/m_user.c index ee7325e..ad0ce75 100644 --- a/ircd/m_user.c +++ b/ircd/m_user.c @@ -165,7 +165,7 @@ int m_user(struct Client *cptr, struct Client *sptr, int parc, char *parv[]) /* * NICK and PONG already received, now we have USER... */ - return register_user(cptr, sptr, sptr->name, username); + return register_user(cptr, sptr, sptr->name, username, 0); } else { ircd_strncpy(user->username, username, USERLEN); diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 258d4a0..53be6e9 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -1437,7 +1437,7 @@ int find_kill(struct Client *cptr) /* find active glines */ /* added a check against the user's IP address to find_gline() -Kev */ - else if ((agline = gline_lookup(cptr)) && GlineIsActive(agline)) + else if ((agline = gline_lookup(cptr, 0)) && GlineIsActive(agline)) send_reply(cptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s.", GlineReason(agline)); else diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 93e8793..c4cf898 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -237,7 +237,7 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf, split = (MyConnect(acptr) && 0 != ircd_strcmp(acptr->name, acptr->sockhost) && 0 != ircd_strncmp(acptr->info, "JUPE", 4)); - if ((ajupe = jupe_find(acptr->name))) + if ((ajupe = jupe_find(acptr->name)) && !JupeIsLocal(ajupe)) sendcmdto_one(acptr->serv->up, CMD_SERVER, cptr, "%s %d 0 %Tu %s%u %s%s 0 %%%Tu :%s", acptr->name, acptr->hopcount + 1, acptr->serv->timestamp, @@ -261,13 +261,25 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf, { char xxx_buf[8]; char *s = umode_str(acptr); - sendcmdto_one(acptr->user->server, CMD_NICK, cptr, *s ? - "%s %d %Tu %s %s +%s %s %s%s :%s" : - "%s %d %Tu %s %s %s%s %s%s :%s", - acptr->name, acptr->hopcount + 1, acptr->lastnick, - acptr->user->username, acptr->user->host, s, - inttobase64(xxx_buf, ntohl(acptr->ip.s_addr), 6), - NumNick(acptr), acptr->info); + struct Gline *agline = 0; + if ((agline = gline_lookup(acptr, GLINE_GLOBAL | GLINE_LASTMOD))) + sendcmdto_one(acptr->user->server, CMD_NICK, cptr, + "%s %d %Tu %s %s %s%s%s%%%Tu:%s@%s %s %s%s :%s", + acptr->name, acptr->hopcount + 1, acptr->lastnick, + acptr->user->username, acptr->user->host, + *s ? "+" : "", s, *s ? " " : "", + GlineLastMod(agline), GlineUser(agline), + GlineHost(agline), + inttobase64(xxx_buf, ntohl(acptr->ip.s_addr), 6), + NumNick(acptr), acptr->info); + else + sendcmdto_one(acptr->user->server, CMD_NICK, cptr, + "%s %d %Tu %s %s %s%s%s%s %s%s :%s", + acptr->name, acptr->hopcount + 1, acptr->lastnick, + acptr->user->username, acptr->user->host, + *s ? "+" : "", s, *s ? " " : "", + inttobase64(xxx_buf, ntohl(acptr->ip.s_addr), 6), + NumNick(acptr), acptr->info); } } /* diff --git a/ircd/s_user.c b/ircd/s_user.c index d1912d9..4696248 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -407,7 +407,7 @@ static char *clean_user_id(char *dest, char *source, int tilde) * nick from local user or kill him/her... */ int register_user(struct Client *cptr, struct Client *sptr, - const char *nick, char *username) + const char *nick, char *username, struct Gline *agline) { struct ConfItem* aconf; char* parv[3]; @@ -426,7 +426,6 @@ int register_user(struct Client *cptr, struct Client *sptr, struct User* user = sptr->user; char ip_base64[8]; char featurebuf[512]; - struct Gline* gline; user->last = CurrentTime; parv[0] = sptr->name; @@ -594,11 +593,17 @@ int register_user(struct Client *cptr, struct Client *sptr, else { ircd_strncpy(user->username, username, USERLEN); Count_newremoteclient(UserStats, user->server); - if ((gline = gline_lookup(sptr)) && GlineIsActive(gline)) - gline_resend(cptr, gline); } SetUser(sptr); + /* a gline wasn't passed in, so find a matching global one that isn't + * a Uworld-set one, and propagate it if there is such an animal. + */ + if (!agline && + (agline = gline_lookup(sptr, GLINE_GLOBAL | GLINE_LASTMOD)) && + !IsBurstOrBurstAck(cptr)) + gline_resend(cptr, agline); + if (IsInvisible(sptr)) ++UserStats.inv_clients; if (IsOper(sptr)) @@ -664,13 +669,24 @@ int register_user(struct Client *cptr, struct Client *sptr, } tmpstr = umode_str(sptr); - sendcmdto_serv_butone(user->server, CMD_NICK, cptr, *tmpstr ? - "%s %d %d %s %s +%s %s %s%s :%s" : - "%s %d %d %s %s %s%s %s%s :%s", - nick, sptr->hopcount + 1, sptr->lastnick, - user->username, user->host, tmpstr, - inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6), - NumNick(sptr), sptr->info); + if (agline) + sendcmdto_serv_butone(user->server, CMD_NICK, cptr, + "%s %d %Tu %s %s %s%s%s%%%Tu:%s@%s %s %s%s :%s", + nick, sptr->hopcount + 1, sptr->lastnick, + user->username, user->host, + *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "", + GlineLastMod(agline), GlineUser(agline), + GlineHost(agline), + inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6), + NumNick(sptr), sptr->info); + else + sendcmdto_serv_butone(user->server, CMD_NICK, cptr, + "%s %d %Tu %s %s %s%s%s%s %s%s :%s", + nick, sptr->hopcount + 1, sptr->lastnick, + user->username, user->host, + *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "", + inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6), + NumNick(sptr), sptr->info); /* Send umode to client */ if (MyUser(sptr)) @@ -725,6 +741,8 @@ int set_nick_name(struct Client* cptr, struct Client* sptr, if (IsServer(sptr)) { int i; const char* p; + char *t; + struct Gline *agline = 0; /* * A server introducing a new client, change source @@ -763,7 +781,21 @@ int set_nick_name(struct Client* cptr, struct Client* sptr, ircd_strncpy(new_client->username, parv[4], USERLEN); ircd_strncpy(new_client->user->host, parv[5], HOSTLEN); ircd_strncpy(new_client->info, parv[parc - 1], REALLEN); - return register_user(cptr, new_client, new_client->name, parv[4]); + + /* Deal with GLINE parameters... */ + if (*parv[parc - 4] == '%' && (t = strchr(parv[parc - 4] + 1, ':'))) { + time_t lastmod; + + *(t++) = '\0'; + lastmod = atoi(parv[parc - 4] + 1); + + if (lastmod && + (agline = gline_find(t, GLINE_EXACT | GLINE_GLOBAL | GLINE_LASTMOD)) + && GlineLastMod(agline) > lastmod && !IsBurstOrBurstAck(cptr)) + gline_resend(cptr, agline); + } + + return register_user(cptr, new_client, new_client->name, parv[4], agline); } else if (sptr->name[0]) { /* @@ -856,7 +888,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr, * for it - must test this and exit m_nick too ! */ sptr->lastnick = TStime(); /* Always local client */ - if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED) + if (register_user(cptr, sptr, nick, sptr->user->username, 0) == CPTR_KILLED) return CPTR_KILLED; } } -- 2.20.1