Changeset 17876 for src/router/proftpd/src/modules.c
- Timestamp:
- 11/11/11 13:17:43 (20 months ago)
- File:
-
- 1 edited
-
src/router/proftpd/src/modules.c (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/router/proftpd/src/modules.c
r14672 r17876 2 2 * ProFTPD - FTP server daemon 3 3 * Copyright (c) 1997, 1998 Public Flood Software 4 * Copyright (c) 2001-20 08The ProFTPD Project team4 * Copyright (c) 2001-2010 The ProFTPD Project team 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify … … 16 16 * You should have received a copy of the GNU General Public License 17 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 5 9 Temple Place, Suite 330, Boston, MA 02111-1307, USA.18 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. 19 19 * 20 20 * As a special exemption, Public Flood Software/MacGyver aka Habeeb J. Dihu … … 24 24 */ 25 25 26 /* 27 * Module handling routines 28 * $Id: modules.c,v 1.58 2010/02/14 00:19:06 castaglia Exp $ 26 /* Module handling routines 27 * $Id: modules.c,v 1.62 2011/05/23 21:22:24 castaglia Exp $ 29 28 */ 30 29 31 30 #include "conf.h" 32 33 /* This local structure vastly speeds up symbol lookups. */34 struct stash {35 struct stash *next,*prev;36 pool *sym_pool;37 const char *sym_name;38 pr_stash_type_t sym_type;39 module *sym_module;40 41 union {42 conftable *sym_conf;43 cmdtable *sym_cmd;44 authtable *sym_auth;45 cmdtable *sym_hook;46 void *sym_generic;47 } ptr;48 };49 31 50 32 extern module *static_modules[]; 51 33 extern module *loaded_modules; 52 34 53 /* Symbol hashes for each type */54 static xaset_t *symbol_table[PR_TUNABLE_HASH_TABLE_SIZE];55 static pool *symbol_pool = NULL;56 static struct stash *curr_sym = NULL;57 58 35 /* Currently running module */ 59 36 module *curr_module = NULL; 60 37 61 38 /* Used to track the priority for loaded modules. */ 62 39 static unsigned int curr_module_pri = 0; 63 64 typedef struct mod_cb { 65 struct mod_cb *next, *prev; 66 67 int (*module_cb)(void); 68 } module_cb_t; 69 70 /* Symbol stash lookup code and management */ 71 72 static struct stash *sym_alloc(void) { 73 pool *sub_pool; 74 struct stash *sym; 75 76 /* XXX Use a smaller pool size, since there are lots of sub-pools allocated 77 * for Stash symbols. The default pool size (PR_TUNABLE_POOL_SIZE, 512 78 * by default) is a bit large for symbols. 79 */ 80 sub_pool = pr_pool_create_sz(symbol_pool, 128); 81 82 sym = pcalloc(sub_pool, sizeof(struct stash)); 83 sym->sym_pool = sub_pool; 84 pr_pool_tag(sub_pool, "symbol"); 85 86 return sym; 87 } 88 89 static int sym_cmp(struct stash *s1, struct stash *s2) { 90 int res; 91 92 res = strcmp(s1->sym_name, s2->sym_name); 93 94 /* Higher priority modules must go BEFORE lower priority in the 95 * hash tables. 96 */ 97 98 if (res == 0) { 99 if (s1->sym_module != NULL && 100 s2->sym_module != NULL) { 101 102 if (s1->sym_module->priority > s2->sym_module->priority) { 103 return -1; 104 } 105 106 if (s1->sym_module->priority < s2->sym_module->priority) { 107 return 1; 108 } 109 110 return res; 111 } 112 113 if (s1->sym_module != NULL && 114 s2->sym_module == NULL) { 115 return -1; 116 } 117 118 if (s1->sym_module == NULL && 119 s2->sym_module != NULL) { 120 return 1; 121 } 122 123 /* Both sym_module fields are null. */ 124 return 0; 125 } 126 127 return res; 128 } 129 130 static int symtab_hash(const char *name) { 131 unsigned char *cp = NULL; 132 int total = 0; 133 134 if (!name) 135 return 0; 136 137 for (cp = (unsigned char *)name; *cp; cp++) 138 total += (int)*cp; 139 140 return (total < PR_TUNABLE_HASH_TABLE_SIZE ? total : 141 (total % PR_TUNABLE_HASH_TABLE_SIZE)); 142 } 143 144 int pr_stash_add_symbol(pr_stash_type_t sym_type, void *data) { 145 struct stash *sym = NULL; 146 int idx = 0; 147 148 if (!data) { 149 errno = EINVAL; 150 return -1; 151 } 152 153 switch (sym_type) { 154 case PR_SYM_CONF: 155 sym = sym_alloc(); 156 sym->sym_type = PR_SYM_CONF; 157 sym->sym_name = ((conftable *) data)->directive; 158 sym->sym_module = ((conftable *) data)->m; 159 sym->ptr.sym_conf = data; 160 break; 161 162 case PR_SYM_CMD: 163 sym = sym_alloc(); 164 sym->sym_type = PR_SYM_CMD; 165 sym->sym_name = ((cmdtable *) data)->command; 166 sym->sym_module = ((cmdtable *) data)->m; 167 sym->ptr.sym_cmd = data; 168 break; 169 170 case PR_SYM_AUTH: 171 sym = sym_alloc(); 172 sym->sym_type = PR_SYM_AUTH; 173 sym->sym_name = ((authtable *) data)->name; 174 sym->sym_module = ((authtable *) data)->m; 175 sym->ptr.sym_auth = data; 176 break; 177 178 case PR_SYM_HOOK: 179 sym = sym_alloc(); 180 sym->sym_type = PR_SYM_HOOK; 181 sym->sym_name = ((cmdtable *) data)->command; 182 sym->sym_module = ((cmdtable *) data)->m; 183 sym->ptr.sym_hook = data; 184 break; 185 186 default: 187 errno = ENOENT; 188 return -1; 189 } 190 191 /* XXX Should we check for null sym->sym_module as well? */ 192 if (sym->sym_name == NULL) { 193 destroy_pool(sym->sym_pool); 194 errno = EPERM; 195 return -1; 196 } 197 198 /* XXX Ugly hack to support mixed cases of directives in config files. */ 199 if (sym_type != PR_SYM_CONF) { 200 idx = symtab_hash(sym->sym_name); 201 202 } else { 203 register unsigned int i; 204 char buf[1024]; 205 206 memset(buf, '\0', sizeof(buf)); 207 sstrncpy(buf, sym->sym_name, sizeof(buf)-1); 208 209 for (i = 0; i < strlen(buf); i++) 210 buf[i] = tolower((int) buf[i]); 211 212 idx = symtab_hash(buf); 213 } 214 215 if (!symbol_table[idx]) { 216 symbol_table[idx] = xaset_create(symbol_pool, (XASET_COMPARE) sym_cmp); 217 } 218 219 xaset_insert_sort(symbol_table[idx], (xasetmember_t *) sym, TRUE); 220 return 0; 221 } 222 223 static struct stash *stash_lookup(pr_stash_type_t sym_type, 224 const char *name, int idx) { 225 struct stash *sym = NULL; 226 227 if (symbol_table[idx]) { 228 for (sym = (struct stash *) symbol_table[idx]->xas_list; sym; 229 sym = sym->next) 230 if (sym->sym_type == sym_type && 231 (!name || strcasecmp(sym->sym_name, name) == 0)) 232 break; 233 } 234 235 return sym; 236 } 237 238 static struct stash *stash_lookup_next(pr_stash_type_t sym_type, 239 const char *name, int idx, void *prev) { 240 struct stash *sym = NULL; 241 int last_hit = 0; 242 243 if (symbol_table[idx]) { 244 for (sym = (struct stash *) symbol_table[idx]->xas_list; sym; 245 sym = sym->next) { 246 if (last_hit && sym->sym_type == sym_type && 247 (!name || strcasecmp(sym->sym_name, name) == 0)) 248 break; 249 if (sym->ptr.sym_generic == prev) 250 last_hit++; 251 } 252 } 253 254 return sym; 255 } 256 257 void *pr_stash_get_symbol(pr_stash_type_t sym_type, const char *name, 258 void *prev, int *idx_cache) { 259 int idx; 260 struct stash *sym = NULL; 261 262 if (idx_cache && 263 *idx_cache != -1) { 264 idx = *idx_cache; 265 266 } else { 267 268 /* XXX Ugly hack to support mixed cases of directives in config files. */ 269 if (sym_type != PR_SYM_CONF) { 270 idx = symtab_hash(name); 271 272 } else { 273 register unsigned int i; 274 char buf[1024]; 275 276 memset(buf, '\0', sizeof(buf)); 277 sstrncpy(buf, name, sizeof(buf)-1); 278 279 for (i = 0; i < strlen(buf); i++) 280 buf[i] = tolower((int) buf[i]); 281 282 idx = symtab_hash(buf); 283 } 284 285 if (idx_cache) 286 *idx_cache = idx; 287 } 288 289 if (idx >= PR_TUNABLE_HASH_TABLE_SIZE) { 290 if (*idx_cache) 291 *idx_cache = -1; 292 293 errno = EINVAL; 294 return NULL; 295 } 296 297 if (prev) 298 curr_sym = sym = stash_lookup_next(sym_type, name, idx, prev); 299 else 300 curr_sym = sym = stash_lookup(sym_type, name, idx); 301 302 switch (sym_type) { 303 case PR_SYM_CONF: 304 if (sym) { 305 return sym->ptr.sym_conf; 306 } 307 308 errno = ENOENT; 309 return NULL; 310 311 case PR_SYM_CMD: 312 if (sym) { 313 return sym->ptr.sym_cmd; 314 } 315 316 errno = ENOENT; 317 return NULL; 318 319 case PR_SYM_AUTH: 320 if (sym) { 321 return sym->ptr.sym_auth; 322 } 323 324 errno = ENOENT; 325 return NULL; 326 327 case PR_SYM_HOOK: 328 if (sym) { 329 return sym->ptr.sym_hook; 330 } 331 332 errno = ENOENT; 333 return NULL; 334 } 335 336 errno = EINVAL; 337 return NULL; 338 } 339 340 int pr_stash_remove_symbol(pr_stash_type_t sym_type, const char *sym_name, 341 module *sym_module) { 342 int count = 0, symtab_idx = 0; 343 344 if (!sym_name) { 345 errno = EINVAL; 346 return -1; 347 } 348 349 /* XXX Ugly hack to support mixed cases of directives in config files. */ 350 if (sym_type != PR_SYM_CONF) { 351 symtab_idx = symtab_hash(sym_name); 352 353 } else { 354 register unsigned int i; 355 char buf[1024]; 356 357 memset(buf, '\0', sizeof(buf)); 358 sstrncpy(buf, sym_name, sizeof(buf)-1); 359 360 for (i = 0; i < strlen(buf); i++) 361 buf[i] = tolower((int) buf[i]); 362 363 symtab_idx = symtab_hash(buf); 364 } 365 366 switch (sym_type) { 367 case PR_SYM_CONF: { 368 int idx = -1; 369 conftable *tab; 370 371 tab = pr_stash_get_symbol(PR_SYM_CONF, sym_name, NULL, &idx); 372 373 while (tab) { 374 pr_signals_handle(); 375 376 /* Note: this works because of a hack: the symbol lookup functions 377 * set a static pointer, curr_sym, to point to the struct stash 378 * just looked up. curr_sym will not be NULL if pr_stash_get_symbol() 379 * returns non-NULL. 380 */ 381 382 if (!sym_module || 383 curr_sym->sym_module == sym_module) { 384 xaset_remove(symbol_table[symtab_idx], (xasetmember_t *) curr_sym); 385 destroy_pool(curr_sym->sym_pool); 386 curr_sym = NULL; 387 tab = NULL; 388 count++; 389 } 390 391 tab = pr_stash_get_symbol(PR_SYM_CONF, sym_name, tab, &idx); 392 } 393 394 break; 395 } 396 397 case PR_SYM_CMD: { 398 int idx = -1; 399 cmdtable *tab; 400 401 tab = pr_stash_get_symbol(PR_SYM_CMD, sym_name, NULL, &idx); 402 403 while (tab) { 404 pr_signals_handle(); 405 406 /* Note: this works because of a hack: the symbol lookup functions 407 * set a static pointer, curr_sym, to point to the struct stash 408 * just looked up. 409 */ 410 411 if (!sym_module || 412 curr_sym->sym_module == sym_module) { 413 xaset_remove(symbol_table[symtab_idx], (xasetmember_t *) curr_sym); 414 destroy_pool(curr_sym->sym_pool); 415 tab = NULL; 416 count++; 417 } 418 419 tab = pr_stash_get_symbol(PR_SYM_CMD, sym_name, tab, &idx); 420 } 421 422 break; 423 } 424 425 case PR_SYM_AUTH: { 426 int idx = -1; 427 authtable *tab; 428 429 tab = pr_stash_get_symbol(PR_SYM_AUTH, sym_name, NULL, &idx); 430 431 while (tab) { 432 pr_signals_handle(); 433 434 /* Note: this works because of a hack: the symbol lookup functions 435 * set a static pointer, curr_sym, to point to the struct stash 436 * just looked up. 437 */ 438 439 if (!sym_module || 440 curr_sym->sym_module == sym_module) { 441 xaset_remove(symbol_table[symtab_idx], (xasetmember_t *) curr_sym); 442 destroy_pool(curr_sym->sym_pool); 443 tab = NULL; 444 count++; 445 } 446 447 tab = pr_stash_get_symbol(PR_SYM_AUTH, sym_name, tab, &idx); 448 } 449 450 break; 451 } 452 453 case PR_SYM_HOOK: { 454 int idx = -1; 455 cmdtable *tab; 456 457 tab = pr_stash_get_symbol(PR_SYM_HOOK, sym_name, NULL, &idx); 458 459 while (tab) { 460 pr_signals_handle(); 461 462 if (!sym_module || 463 curr_sym->sym_module == sym_module) { 464 xaset_remove(symbol_table[symtab_idx], (xasetmember_t *) curr_sym); 465 destroy_pool(curr_sym->sym_pool); 466 tab = NULL; 467 count++; 468 } 469 470 tab = pr_stash_get_symbol(PR_SYM_HOOK, sym_name, tab, &idx); 471 } 472 473 break; 474 } 475 476 default: 477 errno = EINVAL; 478 return -1; 479 } 480 481 return count; 482 } 483 40 484 41 modret_t *pr_module_call(module *m, modret_t *(*func)(cmd_rec *), 485 42 cmd_rec *cmd) { … … 817 374 } 818 375 376 /* Remove any callbacks that the module may have registered, i.e.: 377 * 378 * ctrls 379 * events 380 * timers 381 * 382 * Ideally we would also automatically unregister other callbacks that 383 * the module may have registered, such as FSIO, NetIO, variables, and 384 * response handlers. However, these APIs do not yet allow for 385 * removal of all callbacks for a given module. 386 */ 387 388 #ifdef PR_USE_CTRLS 389 pr_ctrls_unregister(m, NULL); 390 #endif /* PR_USE_CTRLS */ 391 pr_event_unregister(m, NULL, NULL); 392 pr_timer_remove(-1, m); 393 819 394 return 0; 820 395 } … … 835 410 return 0; 836 411 } 837 838 int init_stash(void) {839 if (symbol_pool)840 destroy_pool(symbol_pool);841 842 symbol_pool = make_sub_pool(permanent_pool);843 pr_pool_tag(symbol_pool, "Stash Pool");844 memset(symbol_table, '\0', sizeof(symbol_table));845 846 return 0;847 }
Note: See TracChangeset
for help on using the changeset viewer.
