Migrate capability negotiation code to new dynamic capability management API.
This needs a lot of testing, obviously.
This commit is contained in:
parent
ec3a9055f2
commit
346fba9252
7 changed files with 175 additions and 309 deletions
|
@ -28,6 +28,7 @@
|
||||||
#define INCLUDED_serv_h
|
#define INCLUDED_serv_h
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "capability.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The number of seconds between calls to try_connections(). Fiddle with
|
* The number of seconds between calls to try_connections(). Fiddle with
|
||||||
|
@ -47,40 +48,35 @@ struct server_conf;
|
||||||
struct Channel;
|
struct Channel;
|
||||||
|
|
||||||
/* Capabilities */
|
/* Capabilities */
|
||||||
struct Capability
|
extern struct CapabilityIndex *serv_capindex;
|
||||||
{
|
|
||||||
const char *name; /* name of capability */
|
|
||||||
unsigned int cap; /* mask value */
|
|
||||||
unsigned int required; /* 1 if required, 0 if not */
|
|
||||||
};
|
|
||||||
|
|
||||||
#define CAP_CAP 0x00001 /* received a CAP to begin with */
|
/*
|
||||||
#define CAP_QS 0x00002 /* Can handle quit storm removal */
|
* XXX: this is kind of ugly, but this allows us to have backwards
|
||||||
#define CAP_EX 0x00004 /* Can do channel +e exemptions */
|
* API-compatibility.
|
||||||
#define CAP_CHW 0x00008 /* Can do channel wall @# */
|
*/
|
||||||
#define CAP_IE 0x00010 /* Can do invite exceptions */
|
extern unsigned int CAP_CAP; /* received a CAP to begin with */
|
||||||
#define CAP_KLN 0x00040 /* Can do KLINE message */
|
extern unsigned int CAP_QS; /* Can handle quit storm removal */
|
||||||
#define CAP_ZIP 0x00100 /* Can do ZIPlinks */
|
extern unsigned int CAP_EX; /* Can do channel +e exemptions */
|
||||||
#define CAP_KNOCK 0x00400 /* supports KNOCK */
|
extern unsigned int CAP_CHW; /* Can do channel wall @# */
|
||||||
#define CAP_TB 0x00800 /* supports TBURST */
|
extern unsigned int CAP_IE; /* Can do invite exceptions */
|
||||||
#define CAP_UNKLN 0x01000 /* supports remote unkline */
|
extern unsigned int CAP_KLN; /* Can do KLINE message */
|
||||||
#define CAP_CLUSTER 0x02000 /* supports cluster stuff */
|
extern unsigned int CAP_ZIP; /* Can do ZIPlinks */
|
||||||
#define CAP_ENCAP 0x04000 /* supports ENCAP */
|
extern unsigned int CAP_KNOCK; /* supports KNOCK */
|
||||||
#define CAP_TS6 0x08000 /* supports TS6 or above */
|
extern unsigned int CAP_TB; /* supports TBURST */
|
||||||
#define CAP_SERVICE 0x10000
|
extern unsigned int CAP_UNKLN; /* supports remote unkline */
|
||||||
#define CAP_RSFNC 0x20000 /* rserv FNC */
|
extern unsigned int CAP_CLUSTER; /* supports cluster stuff */
|
||||||
#define CAP_SAVE 0x40000 /* supports SAVE (nick collision FNC) */
|
extern unsigned int CAP_ENCAP; /* supports ENCAP */
|
||||||
#define CAP_EUID 0x80000 /* supports EUID (ext UID + nonencap CHGHOST) */
|
extern unsigned int CAP_TS6; /* supports TS6 or above */
|
||||||
#define CAP_EOPMOD 0x100000 /* supports EOPMOD (ext +z + ext topic) */
|
extern unsigned int CAP_SERVICE; /* supports services */
|
||||||
#define CAP_BAN 0x200000 /* supports propagated bans */
|
extern unsigned int CAP_RSFNC; /* rserv FNC */
|
||||||
#define CAP_MLOCK 0x400000 /* supports MLOCK messages */
|
extern unsigned int CAP_SAVE; /* supports SAVE (nick collision FNC) */
|
||||||
|
extern unsigned int CAP_EUID; /* supports EUID (ext UID + nonencap CHGHOST) */
|
||||||
|
extern unsigned int CAP_EOPMOD; /* supports EOPMOD (ext +z + ext topic) */
|
||||||
|
extern unsigned int CAP_BAN; /* supports propagated bans */
|
||||||
|
extern unsigned int CAP_MLOCK; /* supports MLOCK messages */
|
||||||
|
|
||||||
#define CAP_MASK (CAP_QS | CAP_EX | CAP_CHW | \
|
/* XXX: added for backwards compatibility. --nenolod */
|
||||||
CAP_IE | CAP_KLN | CAP_SERVICE |\
|
#define CAP_MASK (capability_index_mask(serv_capindex) & ~(CAP_TS6 | CAP_CAP))
|
||||||
CAP_CLUSTER | CAP_ENCAP | \
|
|
||||||
CAP_ZIP | CAP_KNOCK | CAP_UNKLN | \
|
|
||||||
CAP_RSFNC | CAP_SAVE | CAP_EUID | CAP_EOPMOD | \
|
|
||||||
CAP_BAN | CAP_MLOCK)
|
|
||||||
|
|
||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
#define CAP_ZIP_SUPPORTED CAP_ZIP
|
||||||
|
@ -103,8 +99,6 @@ struct Capability
|
||||||
* because all servers that we talk to already do TS, and the kludged
|
* because all servers that we talk to already do TS, and the kludged
|
||||||
* extra argument to "PASS" takes care of checking that. -orabidoo
|
* extra argument to "PASS" takes care of checking that. -orabidoo
|
||||||
*/
|
*/
|
||||||
extern struct Capability captab[];
|
|
||||||
|
|
||||||
extern int MaxClientCount; /* GLOBAL - highest number of clients */
|
extern int MaxClientCount; /* GLOBAL - highest number of clients */
|
||||||
extern int MaxConnectionCount; /* GLOBAL - highest number of connections */
|
extern int MaxConnectionCount; /* GLOBAL - highest number of connections */
|
||||||
|
|
||||||
|
@ -117,11 +111,12 @@ extern int refresh_user_links;
|
||||||
#define HUNTED_ISME 0 /* if this server should execute the command */
|
#define HUNTED_ISME 0 /* if this server should execute the command */
|
||||||
#define HUNTED_PASS 1 /* if message passed onwards successfully */
|
#define HUNTED_PASS 1 /* if message passed onwards successfully */
|
||||||
|
|
||||||
|
extern void init_builtin_capabs(void);
|
||||||
|
|
||||||
extern int hunt_server(struct Client *client_pt,
|
extern int hunt_server(struct Client *client_pt,
|
||||||
struct Client *source_pt,
|
struct Client *source_pt,
|
||||||
const char *command, int server, int parc, const char **parv);
|
const char *command, int server, int parc, const char **parv);
|
||||||
extern void send_capabilities(struct Client *, int);
|
extern void send_capabilities(struct Client *, unsigned int);
|
||||||
extern const char *show_capabilities(struct Client *client);
|
extern const char *show_capabilities(struct Client *client);
|
||||||
extern void try_connections(void *unused);
|
extern void try_connections(void *unused);
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef NOTYET
|
||||||
/* check to ensure any "required" caps are set. --nenolod */
|
/* check to ensure any "required" caps are set. --nenolod */
|
||||||
for (cap = captab; cap->name; cap++)
|
for (cap = captab; cap->name; cap++)
|
||||||
{
|
{
|
||||||
|
@ -125,6 +126,7 @@ mr_server(struct Client *client_p, struct Client *source_p, int parc, const char
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Now we just have to call check_server and everything should be
|
/* Now we just have to call check_server and everything should be
|
||||||
* check for us... -A1kmm. */
|
* check for us... -A1kmm. */
|
||||||
|
|
|
@ -56,7 +56,6 @@ DECLARE_MODULE_AV1(capab, NULL, NULL, capab_clist, NULL, NULL, "$Revision: 1295
|
||||||
static int
|
static int
|
||||||
mr_capab(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
mr_capab(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
|
||||||
{
|
{
|
||||||
struct Capability *cap;
|
|
||||||
int i;
|
int i;
|
||||||
char *p;
|
char *p;
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -84,16 +83,7 @@ mr_capab(struct Client *client_p, struct Client *source_p, int parc, const char
|
||||||
{
|
{
|
||||||
char *t = LOCAL_COPY(parv[i]);
|
char *t = LOCAL_COPY(parv[i]);
|
||||||
for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
|
for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
|
||||||
{
|
client_p->localClient->caps |= capability_get(serv_capindex, s);
|
||||||
for (cap = captab; cap->name; cap++)
|
|
||||||
{
|
|
||||||
if(!irccmp(cap->name, s))
|
|
||||||
{
|
|
||||||
client_p->localClient->caps |= cap->cap;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -103,7 +93,6 @@ static int
|
||||||
me_gcap(struct Client *client_p, struct Client *source_p,
|
me_gcap(struct Client *client_p, struct Client *source_p,
|
||||||
int parc, const char *parv[])
|
int parc, const char *parv[])
|
||||||
{
|
{
|
||||||
struct Capability *cap;
|
|
||||||
char *t = LOCAL_COPY(parv[1]);
|
char *t = LOCAL_COPY(parv[1]);
|
||||||
char *s;
|
char *s;
|
||||||
char *p;
|
char *p;
|
||||||
|
@ -121,16 +110,7 @@ me_gcap(struct Client *client_p, struct Client *source_p,
|
||||||
source_p->serv->fullcaps = rb_strdup(parv[1]);
|
source_p->serv->fullcaps = rb_strdup(parv[1]);
|
||||||
|
|
||||||
for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
|
for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
|
||||||
{
|
source_p->serv->caps |= capability_get(serv_capindex, s);
|
||||||
for (cap = captab; cap->name; cap++)
|
|
||||||
{
|
|
||||||
if(!irccmp(cap->name, s))
|
|
||||||
{
|
|
||||||
source_p->serv->caps |= cap->cap;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
270
src/channel.c
270
src/channel.c
|
@ -50,16 +50,6 @@ static rb_bh *ban_heap;
|
||||||
static rb_bh *topic_heap;
|
static rb_bh *topic_heap;
|
||||||
static rb_bh *member_heap;
|
static rb_bh *member_heap;
|
||||||
|
|
||||||
static int channel_capabs[] = { CAP_EX, CAP_IE,
|
|
||||||
CAP_SERVICE,
|
|
||||||
CAP_TS6
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NCHCAPS (sizeof(channel_capabs)/sizeof(int))
|
|
||||||
#define NCHCAP_COMBOS (1 << NCHCAPS)
|
|
||||||
|
|
||||||
static struct ChCapCombo chcap_combos[NCHCAP_COMBOS];
|
|
||||||
|
|
||||||
static void free_topic(struct Channel *chptr);
|
static void free_topic(struct Channel *chptr);
|
||||||
|
|
||||||
static int h_can_join;
|
static int h_can_join;
|
||||||
|
@ -1198,102 +1188,6 @@ channel_modes(struct Channel *chptr, struct Client *client_p)
|
||||||
return final;
|
return final;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now lets do some stuff to keep track of what combinations of
|
|
||||||
* servers exist...
|
|
||||||
* Note that the number of combinations doubles each time you add
|
|
||||||
* something to this list. Each one is only quick if no servers use that
|
|
||||||
* combination, but if the numbers get too high here MODE will get too
|
|
||||||
* slow. I suggest if you get more than 7 here, you consider getting rid
|
|
||||||
* of some and merging or something. If it wasn't for irc+cs we would
|
|
||||||
* probably not even need to bother about most of these, but unfortunately
|
|
||||||
* we do. -A1kmm
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* void init_chcap_usage_counts(void)
|
|
||||||
*
|
|
||||||
* Inputs - none
|
|
||||||
* Output - none
|
|
||||||
* Side-effects - Initialises the usage counts to zero. Fills in the
|
|
||||||
* chcap_yes and chcap_no combination tables.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
init_chcap_usage_counts(void)
|
|
||||||
{
|
|
||||||
unsigned long m, c, y, n;
|
|
||||||
|
|
||||||
memset(chcap_combos, 0, sizeof(chcap_combos));
|
|
||||||
|
|
||||||
/* For every possible combination */
|
|
||||||
for (m = 0; m < NCHCAP_COMBOS; m++)
|
|
||||||
{
|
|
||||||
/* Check each capab */
|
|
||||||
for (c = y = n = 0; c < NCHCAPS; c++)
|
|
||||||
{
|
|
||||||
if((m & (1 << c)) == 0)
|
|
||||||
n |= channel_capabs[c];
|
|
||||||
else
|
|
||||||
y |= channel_capabs[c];
|
|
||||||
}
|
|
||||||
chcap_combos[m].cap_yes = y;
|
|
||||||
chcap_combos[m].cap_no = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void set_chcap_usage_counts(struct Client *serv_p)
|
|
||||||
* Input: serv_p; The client whose capabs to register.
|
|
||||||
* Output: none
|
|
||||||
* Side-effects: Increments the usage counts for the correct capab
|
|
||||||
* combination.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
set_chcap_usage_counts(struct Client *serv_p)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; n < NCHCAP_COMBOS; n++)
|
|
||||||
{
|
|
||||||
if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
|
|
||||||
NotCapable(serv_p, chcap_combos[n].cap_no))
|
|
||||||
{
|
|
||||||
chcap_combos[n].count++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This should be impossible -A1kmm. */
|
|
||||||
s_assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void set_chcap_usage_counts(struct Client *serv_p)
|
|
||||||
*
|
|
||||||
* Inputs - serv_p; The client whose capabs to register.
|
|
||||||
* Output - none
|
|
||||||
* Side-effects - Decrements the usage counts for the correct capab
|
|
||||||
* combination.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
unset_chcap_usage_counts(struct Client *serv_p)
|
|
||||||
{
|
|
||||||
int n;
|
|
||||||
|
|
||||||
for (n = 0; n < NCHCAP_COMBOS; n++)
|
|
||||||
{
|
|
||||||
if(IsCapable(serv_p, chcap_combos[n].cap_yes) &&
|
|
||||||
NotCapable(serv_p, chcap_combos[n].cap_no))
|
|
||||||
{
|
|
||||||
/* Hopefully capabs can't change dynamically or anything... */
|
|
||||||
s_assert(chcap_combos[n].count > 0);
|
|
||||||
|
|
||||||
if(chcap_combos[n].count > 0)
|
|
||||||
chcap_combos[n].count--;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This should be impossible -A1kmm. */
|
|
||||||
s_assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* void send_cap_mode_changes(struct Client *client_p,
|
/* void send_cap_mode_changes(struct Client *client_p,
|
||||||
* struct Client *source_p,
|
* struct Client *source_p,
|
||||||
* struct Channel *chptr, int cap, int nocap)
|
* struct Channel *chptr, int cap, int nocap)
|
||||||
|
@ -1305,6 +1199,9 @@ unset_chcap_usage_counts(struct Client *serv_p)
|
||||||
* Reverted back to my original design, except that we now keep a count
|
* Reverted back to my original design, except that we now keep a count
|
||||||
* of the number of servers which each combination as an optimisation, so
|
* of the number of servers which each combination as an optimisation, so
|
||||||
* the capabs combinations which are not needed are not worked out. -A1kmm
|
* the capabs combinations which are not needed are not worked out. -A1kmm
|
||||||
|
*
|
||||||
|
* Removed most code here because we don't need to be compatible with ircd
|
||||||
|
* 2.8.21+CSr and stuff. --nenolod
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
|
send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
|
||||||
|
@ -1315,109 +1212,100 @@ send_cap_mode_changes(struct Client *client_p, struct Client *source_p,
|
||||||
int i, mbl, pbl, nc, mc, preflen, len;
|
int i, mbl, pbl, nc, mc, preflen, len;
|
||||||
char *pbuf;
|
char *pbuf;
|
||||||
const char *arg;
|
const char *arg;
|
||||||
int dir;
|
|
||||||
int j;
|
|
||||||
int cap;
|
int cap;
|
||||||
int nocap;
|
int nocap;
|
||||||
|
int dir;
|
||||||
int arglen;
|
int arglen;
|
||||||
|
|
||||||
/* Now send to servers... */
|
/* Now send to servers... */
|
||||||
for (j = 0; j < NCHCAP_COMBOS; j++)
|
mc = 0;
|
||||||
|
nc = 0;
|
||||||
|
pbl = 0;
|
||||||
|
parabuf[0] = 0;
|
||||||
|
pbuf = parabuf;
|
||||||
|
dir = MODE_QUERY;
|
||||||
|
|
||||||
|
mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
|
||||||
|
use_id(source_p), (long) chptr->channelts,
|
||||||
|
chptr->chname);
|
||||||
|
|
||||||
|
/* loop the list of - modes we have */
|
||||||
|
for (i = 0; i < mode_count; i++)
|
||||||
{
|
{
|
||||||
if(chcap_combos[j].count == 0)
|
/* if they dont support the cap we need, or they do support a cap they
|
||||||
|
* cant have, then dont add it to the modebuf.. that way they wont see
|
||||||
|
* the mode
|
||||||
|
*/
|
||||||
|
if (mode_changes[i].letter == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
mc = 0;
|
cap = mode_changes[i].caps;
|
||||||
nc = 0;
|
nocap = mode_changes[i].nocaps;
|
||||||
pbl = 0;
|
|
||||||
parabuf[0] = 0;
|
|
||||||
pbuf = parabuf;
|
|
||||||
dir = MODE_QUERY;
|
|
||||||
|
|
||||||
cap = chcap_combos[j].cap_yes;
|
if (!EmptyString(mode_changes[i].id))
|
||||||
nocap = chcap_combos[j].cap_no;
|
arg = mode_changes[i].id;
|
||||||
|
else
|
||||||
|
arg = mode_changes[i].arg;
|
||||||
|
|
||||||
mbl = preflen = rb_sprintf(modebuf, ":%s TMODE %ld %s ",
|
if(arg)
|
||||||
use_id(source_p), (long) chptr->channelts,
|
|
||||||
chptr->chname);
|
|
||||||
|
|
||||||
/* loop the list of - modes we have */
|
|
||||||
for (i = 0; i < mode_count; i++)
|
|
||||||
{
|
{
|
||||||
/* if they dont support the cap we need, or they do support a cap they
|
arglen = strlen(arg);
|
||||||
* cant have, then dont add it to the modebuf.. that way they wont see
|
|
||||||
* the mode
|
/* dont even think about it! --fl */
|
||||||
*/
|
if(arglen > MODEBUFLEN - 5)
|
||||||
if((mode_changes[i].letter == 0) ||
|
|
||||||
((cap & mode_changes[i].caps) != mode_changes[i].caps)
|
|
||||||
|| ((nocap & mode_changes[i].nocaps) != mode_changes[i].nocaps))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(!EmptyString(mode_changes[i].id))
|
|
||||||
arg = mode_changes[i].id;
|
|
||||||
else
|
|
||||||
arg = mode_changes[i].arg;
|
|
||||||
|
|
||||||
if(arg)
|
|
||||||
{
|
|
||||||
arglen = strlen(arg);
|
|
||||||
|
|
||||||
/* dont even think about it! --fl */
|
|
||||||
if(arglen > MODEBUFLEN - 5)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if we're creeping past the buf size, we need to send it and make
|
|
||||||
* another line for the other modes
|
|
||||||
* XXX - this could give away server topology with uids being
|
|
||||||
* different lengths, but not much we can do, except possibly break
|
|
||||||
* them as if they were the longest of the nick or uid at all times,
|
|
||||||
* which even then won't work as we don't always know the uid -A1kmm.
|
|
||||||
*/
|
|
||||||
if(arg && ((mc == MAXMODEPARAMSSERV) ||
|
|
||||||
((mbl + pbl + arglen + 4) > (BUFSIZE - 3))))
|
|
||||||
{
|
|
||||||
if(nc != 0)
|
|
||||||
sendto_server(client_p, chptr, cap, nocap,
|
|
||||||
"%s %s", modebuf, parabuf);
|
|
||||||
nc = 0;
|
|
||||||
mc = 0;
|
|
||||||
|
|
||||||
mbl = preflen;
|
|
||||||
pbl = 0;
|
|
||||||
pbuf = parabuf;
|
|
||||||
parabuf[0] = 0;
|
|
||||||
dir = MODE_QUERY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dir != mode_changes[i].dir)
|
|
||||||
{
|
|
||||||
modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
|
|
||||||
dir = mode_changes[i].dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
modebuf[mbl++] = mode_changes[i].letter;
|
|
||||||
modebuf[mbl] = 0;
|
|
||||||
nc++;
|
|
||||||
|
|
||||||
if(arg != NULL)
|
|
||||||
{
|
|
||||||
len = rb_sprintf(pbuf, "%s ", arg);
|
|
||||||
pbuf += len;
|
|
||||||
pbl += len;
|
|
||||||
mc++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pbl && parabuf[pbl - 1] == ' ')
|
/* if we're creeping past the buf size, we need to send it and make
|
||||||
parabuf[pbl - 1] = 0;
|
* another line for the other modes
|
||||||
|
* XXX - this could give away server topology with uids being
|
||||||
|
* different lengths, but not much we can do, except possibly break
|
||||||
|
* them as if they were the longest of the nick or uid at all times,
|
||||||
|
* which even then won't work as we don't always know the uid -A1kmm.
|
||||||
|
*/
|
||||||
|
if(arg && ((mc == MAXMODEPARAMSSERV) ||
|
||||||
|
((mbl + pbl + arglen + 4) > (BUFSIZE - 3))))
|
||||||
|
{
|
||||||
|
if(nc != 0)
|
||||||
|
sendto_server(client_p, chptr, cap, nocap,
|
||||||
|
"%s %s", modebuf, parabuf);
|
||||||
|
nc = 0;
|
||||||
|
mc = 0;
|
||||||
|
|
||||||
if(nc != 0)
|
mbl = preflen;
|
||||||
sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
|
pbl = 0;
|
||||||
|
pbuf = parabuf;
|
||||||
|
parabuf[0] = 0;
|
||||||
|
dir = MODE_QUERY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dir != mode_changes[i].dir)
|
||||||
|
{
|
||||||
|
modebuf[mbl++] = (mode_changes[i].dir == MODE_ADD) ? '+' : '-';
|
||||||
|
dir = mode_changes[i].dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
modebuf[mbl++] = mode_changes[i].letter;
|
||||||
|
modebuf[mbl] = 0;
|
||||||
|
nc++;
|
||||||
|
|
||||||
|
if(arg != NULL)
|
||||||
|
{
|
||||||
|
len = rb_sprintf(pbuf, "%s ", arg);
|
||||||
|
pbuf += len;
|
||||||
|
pbl += len;
|
||||||
|
mc++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pbl && parabuf[pbl - 1] == ' ')
|
||||||
|
parabuf[pbl - 1] = 0;
|
||||||
|
|
||||||
|
if(nc != 0)
|
||||||
|
sendto_server(client_p, chptr, cap, nocap, "%s %s", modebuf, parabuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
resv_chan_forcepart(const char *name, const char *reason, int temp_time)
|
resv_chan_forcepart(const char *name, const char *reason, int temp_time)
|
||||||
{
|
{
|
||||||
rb_dlink_node *ptr;
|
rb_dlink_node *ptr;
|
||||||
|
|
|
@ -1326,7 +1326,6 @@ exit_local_server(struct Client *client_p, struct Client *source_p, struct Clien
|
||||||
rb_dlinkDelete(&source_p->localClient->tnode, &serv_list);
|
rb_dlinkDelete(&source_p->localClient->tnode, &serv_list);
|
||||||
rb_dlinkFindDestroy(source_p, &global_serv_list);
|
rb_dlinkFindDestroy(source_p, &global_serv_list);
|
||||||
|
|
||||||
unset_chcap_usage_counts(source_p);
|
|
||||||
sendk = source_p->localClient->sendK;
|
sendk = source_p->localClient->sendK;
|
||||||
recvk = source_p->localClient->receiveK;
|
recvk = source_p->localClient->receiveK;
|
||||||
|
|
||||||
|
|
12
src/ircd.c
12
src/ircd.c
|
@ -112,7 +112,7 @@ int zlib_ok = 1;
|
||||||
int testing_conf = 0;
|
int testing_conf = 0;
|
||||||
time_t startup_time;
|
time_t startup_time;
|
||||||
|
|
||||||
int default_server_capabs = CAP_MASK;
|
int default_server_capabs;
|
||||||
|
|
||||||
int splitmode;
|
int splitmode;
|
||||||
int splitchecking;
|
int splitchecking;
|
||||||
|
@ -546,7 +546,7 @@ main(int argc, char *argv[])
|
||||||
ConfigFileEntry.dpath = DPATH;
|
ConfigFileEntry.dpath = DPATH;
|
||||||
ConfigFileEntry.configfile = CPATH; /* Server configuration file */
|
ConfigFileEntry.configfile = CPATH; /* Server configuration file */
|
||||||
ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
|
ConfigFileEntry.connect_timeout = 30; /* Default to 30 */
|
||||||
|
|
||||||
umask(077); /* better safe than sorry --SRB */
|
umask(077); /* better safe than sorry --SRB */
|
||||||
|
|
||||||
myargv = argv;
|
myargv = argv;
|
||||||
|
@ -584,9 +584,6 @@ main(int argc, char *argv[])
|
||||||
memset(&AdminInfo, 0, sizeof(AdminInfo));
|
memset(&AdminInfo, 0, sizeof(AdminInfo));
|
||||||
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
|
memset(&ServerStats, 0, sizeof(struct ServerStatistics));
|
||||||
|
|
||||||
/* Initialise the channel capability usage counts... */
|
|
||||||
init_chcap_usage_counts();
|
|
||||||
|
|
||||||
if(printVersion)
|
if(printVersion)
|
||||||
{
|
{
|
||||||
printf("ircd: version %s(%s)\n", ircd_version, serno);
|
printf("ircd: version %s(%s)\n", ircd_version, serno);
|
||||||
|
@ -597,8 +594,6 @@ main(int argc, char *argv[])
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
setup_signals();
|
setup_signals();
|
||||||
|
|
||||||
if (testing_conf)
|
if (testing_conf)
|
||||||
|
@ -637,6 +632,9 @@ main(int argc, char *argv[])
|
||||||
|
|
||||||
seed_random(NULL);
|
seed_random(NULL);
|
||||||
|
|
||||||
|
init_builtin_capabs();
|
||||||
|
default_server_capabs = CAP_MASK;
|
||||||
|
|
||||||
init_main_logfile();
|
init_main_logfile();
|
||||||
newconf_init();
|
newconf_init();
|
||||||
init_s_conf();
|
init_s_conf();
|
||||||
|
|
110
src/s_serv.c
110
src/s_serv.c
|
@ -54,6 +54,7 @@
|
||||||
#include "msg.h"
|
#include "msg.h"
|
||||||
#include "reject.h"
|
#include "reject.h"
|
||||||
#include "sslproc.h"
|
#include "sslproc.h"
|
||||||
|
#include "capability.h"
|
||||||
|
|
||||||
#ifndef INADDR_NONE
|
#ifndef INADDR_NONE
|
||||||
#define INADDR_NONE ((unsigned int) 0xffffffff)
|
#define INADDR_NONE ((unsigned int) 0xffffffff)
|
||||||
|
@ -70,28 +71,56 @@ static char buf[BUFSIZE];
|
||||||
* because all servers that we talk to already do TS, and the kludged
|
* because all servers that we talk to already do TS, and the kludged
|
||||||
* extra argument to "PASS" takes care of checking that. -orabidoo
|
* extra argument to "PASS" takes care of checking that. -orabidoo
|
||||||
*/
|
*/
|
||||||
struct Capability captab[] = {
|
struct CapabilityIndex *serv_capindex = NULL;
|
||||||
/* name cap */
|
|
||||||
{ "QS", CAP_QS },
|
unsigned int CAP_CAP;
|
||||||
{ "EX", CAP_EX },
|
unsigned int CAP_QS;
|
||||||
{ "CHW", CAP_CHW},
|
unsigned int CAP_EX;
|
||||||
{ "IE", CAP_IE},
|
unsigned int CAP_CHW;
|
||||||
{ "KLN", CAP_KLN},
|
unsigned int CAP_IE;
|
||||||
{ "KNOCK", CAP_KNOCK},
|
unsigned int CAP_KLN;
|
||||||
{ "ZIP", CAP_ZIP},
|
unsigned int CAP_ZIP;
|
||||||
{ "TB", CAP_TB},
|
unsigned int CAP_KNOCK;
|
||||||
{ "UNKLN", CAP_UNKLN},
|
unsigned int CAP_TB;
|
||||||
{ "CLUSTER", CAP_CLUSTER},
|
unsigned int CAP_UNKLN;
|
||||||
{ "ENCAP", CAP_ENCAP },
|
unsigned int CAP_CLUSTER;
|
||||||
{ "SERVICES", CAP_SERVICE },
|
unsigned int CAP_ENCAP;
|
||||||
{ "RSFNC", CAP_RSFNC },
|
unsigned int CAP_TS6;
|
||||||
{ "SAVE", CAP_SAVE },
|
unsigned int CAP_SERVICE;
|
||||||
{ "EUID", CAP_EUID },
|
unsigned int CAP_RSFNC;
|
||||||
{ "EOPMOD", CAP_EOPMOD },
|
unsigned int CAP_SAVE;
|
||||||
{ "BAN", CAP_BAN },
|
unsigned int CAP_EUID;
|
||||||
{ "MLOCK", CAP_MLOCK },
|
unsigned int CAP_EOPMOD;
|
||||||
{0, 0}
|
unsigned int CAP_BAN;
|
||||||
};
|
unsigned int CAP_MLOCK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize our builtin capability table. --nenolod
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
init_builtin_capabs(void)
|
||||||
|
{
|
||||||
|
serv_capindex = capability_index_create();
|
||||||
|
|
||||||
|
CAP_QS = capability_put(serv_capindex, "QS");
|
||||||
|
CAP_EX = capability_put(serv_capindex, "EX");
|
||||||
|
CAP_CHW = capability_put(serv_capindex, "CHW");
|
||||||
|
CAP_IE = capability_put(serv_capindex, "IE");
|
||||||
|
CAP_KLN = capability_put(serv_capindex, "KLN");
|
||||||
|
CAP_KNOCK = capability_put(serv_capindex, "KNOCK");
|
||||||
|
CAP_ZIP = capability_put(serv_capindex, "ZIP");
|
||||||
|
CAP_TB = capability_put(serv_capindex, "TB");
|
||||||
|
CAP_UNKLN = capability_put(serv_capindex, "UNKLN");
|
||||||
|
CAP_CLUSTER = capability_put(serv_capindex, "CLUSTER");
|
||||||
|
CAP_ENCAP = capability_put(serv_capindex, "ENCAP");
|
||||||
|
CAP_SERVICE = capability_put(serv_capindex, "SERVICES");
|
||||||
|
CAP_RSFNC = capability_put(serv_capindex, "RSFNC");
|
||||||
|
CAP_SAVE = capability_put(serv_capindex, "SAVE");
|
||||||
|
CAP_EUID = capability_put(serv_capindex, "EUID");
|
||||||
|
CAP_EOPMOD = capability_put(serv_capindex, "EOPMOD");
|
||||||
|
CAP_BAN = capability_put(serv_capindex, "BAN");
|
||||||
|
CAP_MLOCK = capability_put(serv_capindex, "MLOCK");
|
||||||
|
}
|
||||||
|
|
||||||
static CNCB serv_connect_callback;
|
static CNCB serv_connect_callback;
|
||||||
static CNCB serv_connect_ssl_callback;
|
static CNCB serv_connect_ssl_callback;
|
||||||
|
@ -131,7 +160,7 @@ hunt_server(struct Client *client_p, struct Client *source_p,
|
||||||
if(parc <= server || EmptyString(parv[server]) ||
|
if(parc <= server || EmptyString(parv[server]) ||
|
||||||
match(parv[server], me.name) || (strcmp(parv[server], me.id) == 0))
|
match(parv[server], me.name) || (strcmp(parv[server], me.id) == 0))
|
||||||
return (HUNTED_ISME);
|
return (HUNTED_ISME);
|
||||||
|
|
||||||
new = LOCAL_COPY(parv[server]);
|
new = LOCAL_COPY(parv[server]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -380,28 +409,9 @@ check_server(const char *name, struct Client *client_p)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
send_capabilities(struct Client *client_p, int cap_can_send)
|
send_capabilities(struct Client *client_p, unsigned int cap_can_send)
|
||||||
{
|
{
|
||||||
struct Capability *cap;
|
sendto_one(client_p, "CAPAB :%s", capability_index_list(serv_capindex, cap_can_send));
|
||||||
char msgbuf[BUFSIZE];
|
|
||||||
char *t;
|
|
||||||
int tl;
|
|
||||||
|
|
||||||
t = msgbuf;
|
|
||||||
|
|
||||||
for (cap = captab; cap->name; ++cap)
|
|
||||||
{
|
|
||||||
if(cap->cap & cap_can_send)
|
|
||||||
{
|
|
||||||
tl = rb_sprintf(t, "%s ", cap->name);
|
|
||||||
t += tl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t--;
|
|
||||||
*t = '\0';
|
|
||||||
|
|
||||||
sendto_one(client_p, "CAPAB :%s", msgbuf);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -693,7 +703,8 @@ const char *
|
||||||
show_capabilities(struct Client *target_p)
|
show_capabilities(struct Client *target_p)
|
||||||
{
|
{
|
||||||
static char msgbuf[BUFSIZE];
|
static char msgbuf[BUFSIZE];
|
||||||
struct Capability *cap;
|
|
||||||
|
*msgbuf = '\0';
|
||||||
|
|
||||||
if(has_id(target_p))
|
if(has_id(target_p))
|
||||||
rb_strlcpy(msgbuf, " TS6", sizeof(msgbuf));
|
rb_strlcpy(msgbuf, " TS6", sizeof(msgbuf));
|
||||||
|
@ -704,11 +715,7 @@ show_capabilities(struct Client *target_p)
|
||||||
if(!IsServer(target_p) || !target_p->serv->caps) /* short circuit if no caps */
|
if(!IsServer(target_p) || !target_p->serv->caps) /* short circuit if no caps */
|
||||||
return msgbuf + 1;
|
return msgbuf + 1;
|
||||||
|
|
||||||
for (cap = captab; cap->cap; ++cap)
|
rb_strlcat(msgbuf, capability_index_list(serv_capindex, target_p->serv->caps), sizeof(msgbuf));
|
||||||
{
|
|
||||||
if(cap->cap & target_p->serv->caps)
|
|
||||||
rb_snprintf_append(msgbuf, sizeof(msgbuf), " %s", cap->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
return msgbuf + 1;
|
return msgbuf + 1;
|
||||||
}
|
}
|
||||||
|
@ -804,9 +811,6 @@ server_estab(struct Client *client_p)
|
||||||
|
|
||||||
SetServer(client_p);
|
SetServer(client_p);
|
||||||
|
|
||||||
/* Update the capability combination usage counts */
|
|
||||||
set_chcap_usage_counts(client_p);
|
|
||||||
|
|
||||||
rb_dlinkAdd(client_p, &client_p->lnode, &me.serv->servers);
|
rb_dlinkAdd(client_p, &client_p->lnode, &me.serv->servers);
|
||||||
rb_dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &serv_list);
|
rb_dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &serv_list);
|
||||||
rb_dlinkAddTailAlloc(client_p, &global_serv_list);
|
rb_dlinkAddTailAlloc(client_p, &global_serv_list);
|
||||||
|
|
Loading…
Reference in a new issue