/* * Asterisk -- A telephony toolkit for Linux. * * This program is free software, distributed under the terms of * the GNU General Public License * * Version: 2.1.1 - 07/3/05 * * Clod Patry for inner usage */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../asterisk.h" #include #include #include #include #include #include int limit_achieved(struct ast_channel *chan, char *argument); char* get_action(char *app_id); static char *synopsis = "Check Blacklist"; static char *app = "CheckBlacklist"; static char *tdesc = "Check Blacklist"; static char *descrip = "Usage: CheckBlacklist(app_id[,iso_country])\n" " To see if a specific caller_id is on a blacklist in our systems\n" " If yes, it's fetch his application.cid_action\n" " Otherwise, it will go at priority N+1\n" " iso_country is the iso code for a specific country, if not specified, 'ca' will be used.\n"; static char *config = "cdr_pgsql.conf"; static char *pghostname = NULL, *pgdbname = NULL, *pgdbuser = NULL, *pgpassword = NULL, *pgdbsock = NULL, *pgdbport = NULL; static int hostname_alloc = 0, dbname_alloc = 0, dbuser_alloc = 0, password_alloc = 0, dbport_alloc = 0; //static int dbsock_alloc = 0; static int connected = 0; STANDARD_LOCAL_USER; LOCAL_USER_DECL; PGconn *conn; PGresult *result; static void wait_for_hangup(struct ast_channel *chan, void *data) { int res; struct ast_frame *f; int waittime; if (!data || !strlen(data) || (sscanf(data, "%i", &waittime) != 1) || (waittime < 0)) waittime = -1; if (waittime > -1) { ast_safe_sleep(chan, waittime * 1000); } else do { res = ast_waitfor(chan, -1); if (res < 0) return; f = ast_read(chan); if (f) ast_frfree(f); } while(f); } static int my_load_config(void){ /* Connection to the database */ struct ast_config *cfg_file; struct ast_variable *var; char *tmp; cfg_file = ast_load(config); if (!cfg_file) { ast_log(LOG_WARNING, "Unable to load config for PostgreSQL CDR's: %s\n", config); return 0; } var = ast_variable_browse(cfg_file, "global"); if (!var) { // nothing configured return 0; } tmp = ast_variable_retrieve(cfg_file,"global","hostname"); if (tmp) { pghostname = malloc(strlen(tmp) + 1); if (pghostname != NULL) { memset(pghostname, 0, strlen(tmp) + 1); hostname_alloc = 1; strncpy(pghostname, tmp, strlen(tmp)); } else { ast_log(LOG_ERROR,"Out of memory error.\n"); return -1; } } else { ast_log(LOG_WARNING,"PostgreSQL server hostname not specified. Assuming localhost\n"); pghostname = "localhost"; } tmp = ast_variable_retrieve(cfg_file,"global","dbname"); if (tmp) { pgdbname = malloc(strlen(tmp) + 1); if (pgdbname != NULL) { memset(pgdbname, 0, strlen(tmp) + 1); dbname_alloc = 1; strncpy(pgdbname, tmp, strlen(tmp)); } else { ast_log(LOG_ERROR,"Out of memory error.\n"); return -1; } } else { ast_log(LOG_WARNING,"PostgreSQL database not specified. Assuming asterisk\n"); pgdbname = "asteriskcdrdb"; } tmp = ast_variable_retrieve(cfg_file,"global","user"); if (tmp) { pgdbuser = malloc(strlen(tmp) + 1); if (pgdbuser != NULL) { memset(pgdbuser, 0, strlen(tmp) + 1); dbuser_alloc = 1; strncpy(pgdbuser, tmp, strlen(tmp)); } else { ast_log(LOG_ERROR,"Out of memory error.\n"); return -1; } } else { ast_log(LOG_WARNING,"PostgreSQL database user not specified. Assuming root\n"); pgdbuser = "root"; } tmp = ast_variable_retrieve(cfg_file,"global","password"); if (tmp) { pgpassword = malloc(strlen(tmp) + 1); if (pgpassword != NULL) { memset(pgpassword, 0, strlen(tmp) + 1); password_alloc = 1; strncpy(pgpassword, tmp, strlen(tmp)); } else { ast_log(LOG_ERROR,"Out of memory error.\n"); return -1; } } else { ast_log(LOG_WARNING,"PostgreSQL database password not specified. Assuming blank\n"); pgpassword = ""; } tmp = ast_variable_retrieve(cfg_file,"global","port"); if (tmp) { pgdbport = malloc(strlen(tmp) + 1); if (pgdbport != NULL) { memset(pgdbport, 0, strlen(tmp) + 1); dbport_alloc = 1; strncpy(pgdbport, tmp, strlen(tmp)); } else { ast_log(LOG_ERROR,"Out of memory error.\n"); return -1; } } else { ast_log(LOG_WARNING,"PostgreSQL database port not specified. Using default 5432.\n"); pgdbport = "5432"; } ast_destroy(cfg_file); return 1; } static int checkblacklist_exec(struct ast_channel *chan, void *data) { char sqlcmd[200]; char *pgerror; int count = 0; char *cid_num = chan->cid.cid_num; char *option; char *app_id; if ( !data ) { ast_log(LOG_WARNING, "1.CheckBlacklist requires an argument (app_id)\n"); return -1; } if (ast_strlen_zero((char *) data)) { ast_log(LOG_WARNING, "CheckBlacklist requires an argument (app_id)\n"); return -1; } if (!(app_id = ast_strdupa(data))) { ast_log(LOG_WARNING, "Unable to dupe data :(\n"); return -1; } option = strchr(app_id, '|'); if (option) { *option = '\0'; option++; } ast_log(LOG_WARNING, "app_id=%s\n",app_id); //ast_log(LOG_WARNING, "caller_id = %s\n", cid_num); if (pgdbsock) ast_log(LOG_DEBUG,"cdr_pgsql: got sock file of %s\n",pgdbsock); conn = PQsetdbLogin(pghostname, pgdbport, NULL, NULL, pgdbname, pgdbuser, pgpassword); if (PQstatus(conn) != CONNECTION_BAD) { //ast_log(LOG_WARNING,"Successfully connected to PostgreSQL database.\n"); connected = 1; } else { pgerror = PQerrorMessage(conn); ast_log(LOG_WARNING, "CheckBlacklist: Unable to connect to database server %s.\n", pghostname); ast_log(LOG_WARNING, "CheckBlacklist: Reason: %s.\n", pgerror); connected = 0; PQfinish(conn); return 0; } if ( !conn ) { ast_log(LOG_WARNING, "CheckBlacklist: NO CONNECTION\n"); } if ( !cid_num ) { ast_log(LOG_WARNING, "NO CID_NUM => caller_id = %s\n", cid_num); sprintf(sqlcmd, "SELECT cid_action FROM application WHERE application_id='%s' AND active='TRUE'",app_id); ast_log(LOG_WARNING, "no_cid => query=%s\n",sqlcmd); result = PQexec(conn,sqlcmd); ast_log(LOG_WARNING, "%d results\n",PQntuples(result) ); char *action; if ( PQntuples(result) > 0 ) { action = PQgetvalue(result,0,0); } else { ast_log(LOG_NOTICE, "Check the arguments of CheckBlacklist() of app_id=%s\n",app_id); PQclear(result); PQfinish(conn); limit_achieved(chan, "BUSY"); return -1; } PQclear(result); if ( action ) { ast_log(LOG_WARNING, "no CID; action=%s\n",action); PQfinish(conn); if ( limit_achieved(chan, action) ) { return -1; } } } char *country_code = "ca"; sprintf(sqlcmd, "SELECT COUNT(*) FROM blacklist WHERE caller_id='%s' AND application_id=0 AND country='%s';", cid_num, country_code); ast_log(LOG_WARNING, "query=%s\n",sqlcmd); result = PQexec(conn,sqlcmd); count = atoi(PQgetvalue(result,0,0)); PQclear(result); PQfinish(conn); //ast_log(LOG_WARNING, "answer = %d\n",count); if ( count < 1 ) { //ast_log(LOG_WARNING, "%s is not blacklisted ...continue\n",(char *)data); return 0; } else { ast_log(LOG_WARNING, "%s is blacklisted!!\n", (char *)data); if (chan->cdr && data) { ast_cdr_appenduserfield(chan, "call=blacklist"); } ast_indicate(chan, AST_CONTROL_BUSY); wait_for_hangup(chan, "16"); return -1; } } char* get_action(char *app_id) { return "vm-intro"; } int limit_achieved(struct ast_channel *chan, char *action) { ast_log(LOG_DEBUG, "in limit_achieved arg = %s\n", action); if ( chan->cdr ) { ast_cdr_appenduserfield(chan, "call=blacklist"); } if ( !strcmp(action,"BUSY") ) { ast_log(LOG_WARNING, "action is BUSY\n"); ast_indicate(chan, AST_CONTROL_BUSY); wait_for_hangup(chan, action); } else if ( !strcmp(action,"HANGUP") ) { ast_log(LOG_WARNING, "action is HANGUP\n"); } else if ( !strcmp(action,"") ) { ast_log(LOG_WARNING, "action is Nothing, set it to BUSY\n"); ast_indicate(chan, AST_CONTROL_BUSY); wait_for_hangup(chan, action); } else { ast_log(LOG_WARNING, "action is STREAM\n"); //Streaming this file int res = ast_streamfile(chan, action, chan->language); res = ast_waitstream(chan, ""); } return -1; } int unload_module(void) { STANDARD_HANGUP_LOCALUSERS; return ast_unregister_application(app); } int load_module(void) { /* Loading config file once */ my_load_config(); return ast_register_application(app, checkblacklist_exec, synopsis, descrip); } char *description(void) { return tdesc; } int usecount(void) { int res; STANDARD_USECOUNT(res); return res; } char *key() { return ASTERISK_GPL_KEY; }