/*
* Copyright (C) 2001, 2002, and 2003 Roy Keene
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* email: dact@rkeene.org
*/
#include "dact.h"
#include "module.h"
#ifdef HAVE_DLOPEN
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include "algorithms.h"
#include "ciphers.h"
#include "parse.h"
#include "net.h"
#include "ui.h"
char moduledirectory[2048] = "@@HOME@@/.dact/@@OSNM@@-@@ARCH@@/";
void *modules[256];
int modules_initialized = 0;
int modules_count = 0;
int init_modules (void) {
int i;
if (modules_initialized!=0) return(DACT_MOD_FAIL);
modules_initialized=1;
for (i=0;i<256;i++) {
modules[i]=NULL;
}
return(DACT_MOD_OK);
}
int unload_modules (void) {
int i;
if (modules_initialized==0) return(DACT_MOD_FAIL);
for (i=0;i<256;i++) {
if (modules[i]!=NULL)
dlclose(modules[i]);
}
return(DACT_MOD_OK);
}
int load_modules_all(const char *options) {
#ifdef HAVE_DIRENT_H
struct dirent *dinfo;
char *mdircpy, *tmpbuf, *mbuf, *fname, fullfname[1024];
DIR *dirtype;
mdircpy=parse_url_subst(moduledirectory, "");
mbuf=mdircpy;
while ((tmpbuf=strsep(&mbuf, ":"))) {
if ((dirtype=opendir(tmpbuf))==NULL) continue;
while ((dinfo=readdir(dirtype))!=NULL) {
fname=dinfo->d_name;
if (strcmp(fname+strlen(fname)-3,".so")==0) {
strncpy(fullfname, tmpbuf, sizeof(fullfname));
strncat(fullfname, "/", sizeof(fullfname)-strlen(fullfname));
strncat(fullfname, fname, sizeof(fullfname)-strlen(fullfname));
load_module(fullfname, options);
}
}
closedir(dirtype);
}
free(mdircpy);
#else
PRINTERR("I don't know how to handle this.")
#endif
return(DACT_MOD_OK);
}
int load_module (char *modulename, const char *options) {
char modulefile[256], *tmpbuf, *mbuf, *mdircpy;
void *mh=NULL;
uint32_t algo_num, module_type=DACT_MOD_TYPE_COMP;
uint32_t dc_ver=0, dc_req=0, dact_ver;
char *dc_url_get=NULL, *dc_url_ver=NULL, *dc_sign=NULL;
if (strchr(modulename,'/')==NULL) {
mdircpy=parse_url_subst(moduledirectory, "");
mbuf=mdircpy;
while ((tmpbuf=strsep(&mbuf, ":"))) {
snprintf(modulefile, sizeof(modulefile)-1, "%s/%s.so",tmpbuf,modulename);
if ((mh=dlopen(modulefile, RTLD_GLOBAL|RTLD_LAZY))!=NULL) break;
}
free(mdircpy);
} else {
strncpy(modulefile, modulename, sizeof(modulefile)-1);
if ((mh=dlopen(modulefile, RTLD_GLOBAL|RTLD_LAZY))==NULL) {
PRINTERR("Could not load module.");
return(DACT_MOD_FAIL);
}
}
if (!mh) return(DACT_MOD_FAIL);
if (dlsym(mh,"DC_NUM")==NULL \
|| dlsym(mh, "DC_NAME")==NULL \
|| dlsym(mh, "DC_ALGO")==NULL) {
dact_ui_status(DACT_UI_LVL_SPEC, modulefile);
dact_ui_status_append(DACT_UI_LVL_SPEC, " is not a dact module.");
dlclose(mh);
return(DACT_MOD_FAIL);
}
if (dlsym(mh, "DC_TYPE")!=NULL) {
memcpy(&module_type,dlsym(mh,"DC_TYPE"),sizeof(module_type));
}
memcpy(&algo_num,dlsym(mh,"DC_NUM"),sizeof(algo_num));
if (dlsym(mh, "DC_VER")!=NULL) memcpy(&dc_ver, dlsym(mh, "DC_VER"), sizeof(dc_ver));
if (dlsym(mh, "DC_REQUIRE")!=NULL) memcpy(&dc_req, dlsym(mh, "DC_REQUIRE"), sizeof(dc_req));
if (dlsym(mh, "DC_URL_GET")!=NULL) memcpy(&dc_url_get, dlsym(mh, "DC_URL_GET"), sizeof(dc_url_get));
if (dlsym(mh, "DC_URL_VER")!=NULL) memcpy(&dc_url_ver, dlsym(mh, "DC_URL_VER"), sizeof(dc_url_ver));
if (dlsym(mh, "DC_SIGN")!=NULL) memcpy(&dc_sign, dlsym(mh, "DC_SIGN"), sizeof(dc_sign));
if (dc_url_get!=NULL && dc_url_ver!=NULL && dc_ver!=0 && modulename[0]!='/') {
dact_upgrade_file(modulename, dc_url_get, dc_url_ver, dc_ver, NULL, options);
}
if (dc_req!=0) {
dact_ver=(DACT_VER_MAJOR<<16)|(DACT_VER_MINOR<<8)|(DACT_VER_REVISION);
switch (dc_req&0xff000000) {
case DACT_MOD_REQ_ATLEAST:
if (dact_ver<(dc_req&0xffffff)) {
fprintf(stderr, "%s requires atleast DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile,DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
dlclose(mh);
return(DACT_MOD_FAIL);
}
break;
case DACT_MOD_REQ_EXACTLY:
if ((dc_req&0xffffff)!=dact_ver) {
fprintf(stderr, "%s requires DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile, DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
dlclose(mh);
return(DACT_MOD_FAIL);
}
break;
case DACT_MOD_REQ_ATMOST:
if (dact_ver>(dc_req&0xffffff)) {
fprintf(stderr, "%s requires atmost DACT %i.%i.%i, this is DACT %i.%i.%i\n",modulefile,DACT_VER_PARTS(dc_req), DACT_VER_MAJOR, DACT_VER_MINOR, DACT_VER_REVISION);
dlclose(mh);
return(DACT_MOD_FAIL);
}
break;
}
}
if (modules_count>255) {
modules[modules_count++]=mh;
}
switch (module_type) {
case DACT_MOD_TYPE_COMP:
if (algo_num>=((sizeof(algorithms))/(sizeof(*algorithms)))) return(DACT_MOD_FAIL);
if (algorithms[algo_num]!=DACT_FAILED_ALGO && algorithms[algo_num]!=NULL) {
dlclose(mh);
return(DACT_MOD_FAIL);
}
memcpy(&algorithms[algo_num],dlsym(mh, "DC_ALGO"),sizeof(algorithms[0]));
memcpy(&algorithm_names[algo_num],dlsym(mh,"DC_NAME"),sizeof(algorithm_names[0]));
return(DACT_MOD_OK);
case DACT_MOD_TYPE_ENC:
if (algo_num>=CIPHER_COUNT) {
printf("Encryption algorithm number too high, ignoring %i\n", algo_num);
return(DACT_MOD_FAIL);
}
if (ciphers[algo_num]!=DACT_FAILED_ALGO && ciphers[algo_num]!=NULL) {
return(DACT_MOD_FAIL);
}
memcpy(&ciphers[algo_num],dlsym(mh, "DC_ALGO"),sizeof(algorithms[0]));
memcpy(&ciphers_name[algo_num],dlsym(mh, "DC_NAME"),sizeof(ciphers_name[0]));
return(DACT_MOD_OK);
}
return(DACT_MOD_FAIL);
}
#else
char moduledirectory[2048] = ".";
void *modules[256];
int modules_initialized = 0;
int modules_count = 0;
int init_modules(void) { return(DACT_MOD_FAIL); }
int unload_modules(void) { return(DACT_MOD_FAIL); }
int load_module(char *modulename, const char *options) { return(DACT_MOD_FAIL); }
int load_modules_all(const char *options) { return(DACT_MOD_FAIL); }
#endif