Fix various problems with adding and removing module DCC bindings

Change remove_all_dcc_binds() so that it only removes DCC binds for the module supplied, as it's supposed to.

get_dcc_type() should ignore the first entry in dcc_types[] ("<none>") otherwise the client will try to
respond to DCC requests with that name.

Explicitly track the number of entries in the dcc_types[] array rather than using a NULL terminator.  This
allows us to change dcc_types[] to use NULL entries to mark unused slots in the array, rather than pointers
to entries with a NULL .name element.  Together, this means that the dcc_types[] array is only resized when it
actually needs to be grown and removal works correctly (without eg. prematurely marking the end of the array).

Make add_dcc_bind() fail if the requested DCC type has already been bound by a module (this still allows one
module at a time to rebind a built-in DCC type).  Previously the behaviour was ill-defined in this case.
This commit is contained in:
Kevin Easton
2018-02-20 23:27:32 +11:00
parent 5ae42802ec
commit 9e7fc85ae1
4 changed files with 84 additions and 42 deletions

View File

@@ -1,5 +1,10 @@
[Changes 1.2.2] [Changes 1.2.2]
* Fix various problems with adding and removing module DCC bindings. The
same DCC type cannot be bound by more than one module simultaneously. The
remove_all_dcc_binds() function now only removes all DCC bindings for the
given module. (caf)
* Fix crash when unloading the arcfour module. (caf) * Fix crash when unloading the arcfour module. (caf)
* Change add_dcc_bind() to collect all function pointer arguments into a * Change add_dcc_bind() to collect all function pointer arguments into a

View File

@@ -156,7 +156,7 @@ struct dcc_offer {
int check_dcc_socket(int); int check_dcc_socket(int);
char *get_dcc_info(SocketList *, DCC_int *, int); char *get_dcc_info(SocketList *, DCC_int *, int);
void init_dcc_table(void); void init_dcc_table(void);
int BX_remove_all_dcc_binds(char *); int BX_remove_all_dcc_binds(const char *);
int BX_remove_dcc_bind(char *, int); int BX_remove_dcc_bind(char *, int);
/* Function pointers for the operations implementing a DCC type. /* Function pointers for the operations implementing a DCC type.

View File

@@ -606,7 +606,7 @@ extern Function_ptr *global;
#define erase_dcc_info (*(void (*)(int, int, char *, ...))global[ERASE_DCC_INFO]) #define erase_dcc_info (*(void (*)(int, int, char *, ...))global[ERASE_DCC_INFO])
#define add_dcc_bind (*(int (*)(char *, char *, const struct dcc_ops *))global[ADD_DCC_BIND]) #define add_dcc_bind (*(int (*)(char *, char *, const struct dcc_ops *))global[ADD_DCC_BIND])
#define remove_dcc_bind (*(int (*)(char *, int ))global[REMOVE_DCC_BIND]) #define remove_dcc_bind (*(int (*)(char *, int ))global[REMOVE_DCC_BIND])
#define remove_all_dcc_binds (*(int (*)(char *))global[REMOVE_ALL_DCC_BINDS]) #define remove_all_dcc_binds (*(int (*)(const char *))global[REMOVE_ALL_DCC_BINDS])
#define get_active_count (*(int (*)(void ))global[GET_ACTIVE_COUNT]) #define get_active_count (*(int (*)(void ))global[GET_ACTIVE_COUNT])
#define get_num_queue (*(int (*)(void ))global[GET_NUM_QUEUE]) #define get_num_queue (*(int (*)(void ))global[GET_NUM_QUEUE])
#define add_to_queue (*(int (*)(char *, char *, pack *))global[ADD_TO_QUEUE]) #define add_to_queue (*(int (*)(char *, char *, pack *))global[ADD_TO_QUEUE])

View File

@@ -74,7 +74,7 @@ extern int use_socks;
#define DCC_HASHSIZE 11 #define DCC_HASHSIZE 11
static HashEntry dcc_no_flood[DCC_HASHSIZE]; static HashEntry dcc_no_flood[DCC_HASHSIZE];
struct _dcc_types_ struct dcc_type
{ {
char *name; char *name;
char *module; char *module;
@@ -84,7 +84,7 @@ struct _dcc_types_
static const struct dcc_ops null_ops = { NULL, NULL, NULL, NULL, NULL }; static const struct dcc_ops null_ops = { NULL, NULL, NULL, NULL, NULL };
static struct _dcc_types_ _dcc_types[] = static struct dcc_type builtin_dcc_types[] =
{ {
{"<none>", NULL, 0, NULL}, {"<none>", NULL, 0, NULL},
{"CHAT", NULL, DCC_CHAT, &null_ops}, {"CHAT", NULL, DCC_CHAT, &null_ops},
@@ -98,10 +98,11 @@ static struct _dcc_types_ _dcc_types[] =
{"FTP", NULL, DCC_FTPOPEN, &null_ops}, {"FTP", NULL, DCC_FTPOPEN, &null_ops},
{"FTPGET", NULL, DCC_FTPGET, &null_ops}, {"FTPGET", NULL, DCC_FTPGET, &null_ops},
{"FTPSEND", NULL, DCC_FTPSEND, &null_ops}, {"FTPSEND", NULL, DCC_FTPSEND, &null_ops},
{NULL, NULL, 0, NULL}
}; };
static struct _dcc_types_ **dcc_types = NULL; static const size_t n_builtin_dcc_types = sizeof builtin_dcc_types / sizeof builtin_dcc_types[0];
static struct dcc_type **dcc_types = NULL;
static size_t n_dcc_types = 0;
static char DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4]; static char DCC_current_transfer_buffer[BIG_BUFFER_SIZE/4];
unsigned int send_count_stat = 0; unsigned int send_count_stat = 0;
@@ -286,9 +287,10 @@ static int get_dcc_type(const char *name)
{ {
int i; int i;
for (i = 0; dcc_types[i]->name; i++) /* Start at 1 to ignore the <none> type */
for (i = 1; i < n_dcc_types; i++)
{ {
if (!my_stricmp(name, dcc_types[i]->name)) if (dcc_types[i] && !my_stricmp(name, dcc_types[i]->name))
return i; return i;
} }
@@ -4255,53 +4257,89 @@ char *nick,
} }
} }
/* add_dcc_bind()
*
* Bind a new set of DCC operations to a DCC name. This can either be a completely new DCC type,
* or a new set of operations for a builtin DCC type. This fails if the given DCC name is already
* bound by another module.
*/
int BX_add_dcc_bind(char *name, char *module, const struct dcc_ops *dcc_ops) int BX_add_dcc_bind(char *name, char *module, const struct dcc_ops *dcc_ops)
{ {
int i; int i;
for (i = 0; dcc_types[i]->name; i++)
i = get_dcc_type(name);
if (i < 0)
{ {
if (!my_stricmp(dcc_types[i]->name, name)) /* New DCC type, requires a new entry in the list */
break; for (i = 0; i < n_dcc_types; i++)
} {
if (i >= 0xfe) return 0; if (!dcc_types[i])
if (!dcc_types[i]) break;
{ }
RESIZE(dcc_types, struct _dcc_types_ *, i + 2);
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_)); if (i & ~DCC_TYPES)
} {
if (!dcc_types[i]->name) yell("Failed to add DCC binding [%s] for module [%s], too many DCC bindings.",
name, module);
return 0;
}
if (i >= n_dcc_types)
{
n_dcc_types = i + 1;
RESIZE(dcc_types, struct dcc_type *, n_dcc_types);
}
dcc_types[i] = new_malloc(sizeof(struct dcc_type));
malloc_strcpy(&dcc_types[i]->name, name); malloc_strcpy(&dcc_types[i]->name, name);
dcc_types[i]->type = i;
}
else
{
if (dcc_types[i]->module)
{
yell("Failed to add DCC binding [%s] for module [%s], already bound by module [%s].",
name, module, dcc_types[i]->module);
return 0;
}
}
malloc_strcpy(&dcc_types[i]->module, module); malloc_strcpy(&dcc_types[i]->module, module);
dcc_types[i]->dcc_ops = dcc_ops; dcc_types[i]->dcc_ops = dcc_ops;
dcc_types[i]->type = i;
return i; return i;
} }
int BX_remove_dcc_bind(char *name, int type) int BX_remove_dcc_bind(char *name, int type)
{ {
int i = type & DCC_TYPES; if (type >= n_dcc_types || !dcc_types[type] || !dcc_types[type]->module)
if (!dcc_types[i]->module)
return 0; return 0;
new_free(&dcc_types[i]->module);
dcc_types[i]->dcc_ops = &null_ops; new_free(&dcc_types[type]->module);
if (i > DCC_FTPSEND) dcc_types[type]->dcc_ops = &null_ops;
if (type >= n_builtin_dcc_types)
{ {
new_free(&dcc_types[i]->name); new_free(&dcc_types[type]->name);
new_free(&dcc_types[i]); new_free(&dcc_types[type]);
/* RESIZE(dcc_types, struct _dcc_types *, i - 1);*/
} }
return 1; return 1;
} }
int BX_remove_all_dcc_binds(char *name) /* remove_all_dcc_binds()
*
* Remove all DCC bindings added by a given module.
*/
int BX_remove_all_dcc_binds(const char *module)
{ {
int ret = 0; int ret = 0;
int i, j; int i;
/* scan to end of list */
for (i = 0; dcc_types[i]->name; i++); for (i = 0; i < n_dcc_types; i++)
i--; {
for (j = i; j > 0; j--) if (dcc_types[i] && dcc_types[i]->module && !strcasecmp(dcc_types[i]->module, module))
ret += remove_dcc_bind(dcc_types[j]->name, dcc_types[j]->type); ret += remove_dcc_bind(dcc_types[i]->name, i);
}
return ret; return ret;
} }
@@ -4309,13 +4347,12 @@ void init_dcc_table(void)
{ {
int i; int i;
for (i = 0; _dcc_types[i].name; i++); n_dcc_types = n_builtin_dcc_types;
RESIZE(dcc_types, struct _dcc_types_ *, i + 1); RESIZE(dcc_types, struct dcc_type *, n_dcc_types);
for (i = 0; _dcc_types[i].name; i++) for (i = 0; i < n_dcc_types; i++)
{ {
dcc_types[i] = &_dcc_types[i]; dcc_types[i] = &builtin_dcc_types[i];
} }
dcc_types[i] = new_malloc(sizeof(struct _dcc_types_));
} }
char *get_dcc_info(SocketList *s, DCC_int *n, int i) char *get_dcc_info(SocketList *s, DCC_int *n, int i)