aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax2.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-11-12 08:58:55 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2003-11-12 08:58:55 +0000
commit54ff0e853dd333b5d85ae2401fc0d1e31851ee74 (patch)
tree1353f4d3d6f128cddac37f528cf1486e3cf019ee /channels/chan_iax2.c
parentf888cca3ec848656035bccae3b9fb4b3e324f4b7 (diff)
Preliminary support for iax2 friends in mysql database
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@1728 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax2.c')
-rwxr-xr-xchannels/chan_iax2.c321
1 files changed, 249 insertions, 72 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index c34d016f7..8f0e40fb6 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -51,7 +51,9 @@
#include <sys/ioctl.h>
#include <linux/zaptel.h>
#endif
-
+#ifdef MYSQL_FRIENDS
+#include <mysql/mysql.h>
+#endif
#include "iax2.h"
#include "iax2-parser.h"
@@ -82,6 +84,14 @@
/* Sample over last 100 units to determine historic jitter */
#define GAMMA (0.01)
+#ifdef MYSQL_FRIENDS
+static ast_mutex_t mysqllock = AST_MUTEX_INITIALIZER;
+static MYSQL *mysql;
+static char mydbuser[80];
+static char mydbpass[80];
+static char mydbhost[80];
+static char mydbname[80];
+#endif
static char *desc = "Inter Asterisk eXchange (Ver 2)";
static char *tdesc = "Inter Asterisk eXchange Driver (Ver 2)";
static char *type = "IAX2";
@@ -192,7 +202,6 @@ struct iax2_peer {
/* Dynamic Registration fields */
int dynamic; /* If this is a dynamic peer */
struct sockaddr_in defaddr; /* Default address if there is one */
- char challenge[80]; /* Challenge used to authenticate the secret */
int authmethods; /* Authentication methods (IAX_AUTH_*) */
char inkeys[80]; /* Key(s) this peer can use to authenticate to us */
@@ -1507,6 +1516,92 @@ static int iax2_fixup(struct ast_channel *oldchannel, struct ast_channel *newcha
return 0;
}
+#ifdef MYSQL_FRIENDS
+
+static void mysql_update_peer(char *peer, struct sockaddr_in *sin)
+{
+ if (mysql && (strlen(peer) < 128)) {
+ char query[512];
+ char *name;
+ time_t nowtime;
+ name = alloca(strlen(peer) * 2 + 1);
+ time(&nowtime);
+ mysql_real_escape_string(mysql, name, peer, strlen(peer));
+ snprintf(query, sizeof(query), "UPDATE iaxfriends SET ipaddr=\"%s\", port=\"%d\", regseconds=\"%ld\" WHERE name=\"%s\"",
+ inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), nowtime, name);
+ ast_mutex_lock(&mysqllock);
+ if (mysql_real_query(mysql, query, strlen(query)))
+ ast_log(LOG_WARNING, "Unable to update database\n");
+
+ ast_mutex_unlock(&mysqllock);
+ }
+}
+
+static struct iax2_peer *mysql_peer(char *peer)
+{
+ struct iax2_peer *p;
+ int success = 0;
+
+ p = malloc(sizeof(struct iax2_peer));
+ memset(p, 0, sizeof(struct iax2_peer));
+ if (mysql && (strlen(peer) < 128)) {
+ char query[512];
+ char *name;
+ int numfields, x;
+ int port;
+ time_t regseconds, nowtime;
+ MYSQL_RES *result;
+ MYSQL_FIELD *fields;
+ MYSQL_ROW rowval;
+ name = alloca(strlen(peer) * 2 + 1);
+ mysql_real_escape_string(mysql, name, peer, strlen(peer));
+ snprintf(query, sizeof(query), "SELECT * FROM iaxfriends WHERE name=\"%s\"", name);
+ ast_mutex_lock(&mysqllock);
+ mysql_query(mysql, query);
+ if ((result = mysql_store_result(mysql))) {
+ if ((rowval = mysql_fetch_row(result))) {
+ numfields = mysql_num_fields(result);
+ fields = mysql_fetch_fields(result);
+ success = 1;
+ for (x=0;x<numfields;x++) {
+ if (rowval[x]) {
+ if (!strcasecmp(fields[x].name, "secret")) {
+ strncpy(p->secret, rowval[x], sizeof(p->secret));
+ } else if (!strcasecmp(fields[x].name, "context")) {
+ strncpy(p->context, rowval[x], sizeof(p->context) - 1);
+ } else if (!strcasecmp(fields[x].name, "ipaddr")) {
+ inet_aton(rowval[x], &p->addr.sin_addr);
+ } else if (!strcasecmp(fields[x].name, "port")) {
+ if (sscanf(rowval[x], "%i", &port) != 1)
+ port = 0;
+ p->addr.sin_port = htons(port);
+ } else if (!strcasecmp(fields[x].name, "regseconds")) {
+ if (sscanf(rowval[x], "%li", &regseconds) != 1)
+ regseconds = 0;
+ }
+ }
+ }
+ time(&nowtime);
+ if ((nowtime - regseconds) > IAX_DEFAULT_REG_EXPIRE)
+ memset(&p->addr, 0, sizeof(p->addr));
+ }
+ }
+ ast_mutex_unlock(&mysqllock);
+ }
+ if (!success) {
+ free(p);
+ p = NULL;
+ } else {
+ strncpy(p->name, peer, sizeof(p->name) - 1);
+ p->dynamic = 1;
+ p->delme = 1;
+ p->capability = iax2_capability;
+ p->authmethods = IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT;
+ }
+ return p;
+}
+#endif /* MYSQL_FRIENDS */
+
static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, int *maxtime, char *peer, char *context, int *trunk, int *notransfer, char *secret, int seclen)
{
struct hostent *hp;
@@ -1523,36 +1618,46 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i
p = peerl.peers;
while(p) {
if (!strcasecmp(p->name, peer)) {
- found++;
- if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
- (!p->maxms || ((p->lastms > 0) && (p->lastms <= p->maxms)))) {
- if (sendani)
- *sendani = p->sendani; /* Whether we transmit ANI */
- if (maxtime)
- *maxtime = p->maxms; /* Max time they should take */
- if (context)
- strncpy(context, p->context, AST_MAX_EXTENSION - 1);
- if (trunk)
- *trunk = p->trunk;
- if (capability)
- *capability = p->capability;
- if (secret)
- strncpy(secret, p->secret, seclen);
- if (p->addr.sin_addr.s_addr) {
- sin->sin_addr = p->addr.sin_addr;
- sin->sin_port = p->addr.sin_port;
- } else {
- sin->sin_addr = p->defaddr.sin_addr;
- sin->sin_port = p->defaddr.sin_port;
- }
- if (notransfer)
- *notransfer=p->notransfer;
- break;
- }
+ break;
}
p = p->next;
}
ast_mutex_unlock(&peerl.lock);
+#ifdef MYSQL_FRIENDS
+ if (!p)
+ p = mysql_peer(peer);
+#endif
+ if (p) {
+ found++;
+ if ((p->addr.sin_addr.s_addr || p->defaddr.sin_addr.s_addr) &&
+ (!p->maxms || ((p->lastms > 0) && (p->lastms <= p->maxms)))) {
+ if (sendani)
+ *sendani = p->sendani; /* Whether we transmit ANI */
+ if (maxtime)
+ *maxtime = p->maxms; /* Max time they should take */
+ if (context)
+ strncpy(context, p->context, AST_MAX_EXTENSION - 1);
+ if (trunk)
+ *trunk = p->trunk;
+ if (capability)
+ *capability = p->capability;
+ if (secret)
+ strncpy(secret, p->secret, seclen);
+ if (p->addr.sin_addr.s_addr) {
+ sin->sin_addr = p->addr.sin_addr;
+ sin->sin_port = p->addr.sin_port;
+ } else {
+ sin->sin_addr = p->defaddr.sin_addr;
+ sin->sin_port = p->defaddr.sin_port;
+ }
+ if (notransfer)
+ *notransfer=p->notransfer;
+ } else {
+ if (p->delme)
+ free(p);
+ p = NULL;
+ }
+ }
if (!p && !found) {
hp = gethostbyname(peer);
if (hp) {
@@ -1565,8 +1670,9 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i
}
} else if (!p)
return -1;
- else
- return 0;
+ if (p->delme)
+ free(p);
+ return 0;
}
static int auto_congest(void *nothing)
@@ -2849,9 +2955,15 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies *
return -1;
}
+ ast_mutex_lock(&peerl.lock);
for (p = peerl.peers; p ; p = p->next)
if (!strcasecmp(p->name, peer))
break;
+ ast_mutex_unlock(&peerl.lock);
+#ifdef MYSQL_FRIENDS
+ if (!p)
+ p = mysql_peer(peer);
+#endif
if (!p) {
ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, inet_ntoa(sin->sin_addr));
@@ -2860,17 +2972,21 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies *
if (!p->dynamic) {
ast_log(LOG_NOTICE, "Peer '%s' is not dynamic (from %s)\n", peer, inet_ntoa(sin->sin_addr));
+ if (p->delme)
+ free(p);
return -1;
}
if (!ast_apply_ha(p->ha, sin)) {
ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", inet_ntoa(sin->sin_addr), p->name);
+ if (p->delme)
+ free(p);
return -1;
}
strncpy(iaxs[callno]->secret, p->secret, sizeof(iaxs[callno]->secret)-1);
strncpy(iaxs[callno]->inkeys, p->inkeys, sizeof(iaxs[callno]->inkeys)-1);
/* Check secret against what we have on file */
- if (strlen(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && strlen(p->challenge)) {
+ if (strlen(rsasecret) && (p->authmethods & IAX_AUTH_RSA) && strlen(iaxs[callno]->challenge)) {
if (strlen(p->inkeys)) {
char tmpkeys[256];
char *stringp=NULL;
@@ -2879,7 +2995,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies *
keyn = strsep(&stringp, ":");
while(keyn) {
key = ast_key_get(keyn, AST_KEY_PUBLIC);
- if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
+ if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
iaxs[callno]->state |= IAX_STATE_AUTHENTICATED;
break;
} else if (!key)
@@ -2888,24 +3004,30 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies *
}
if (!keyn) {
ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
+ if (p->delme)
+ free(p);
return -1;
}
} else {
ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
+ if (p->delme)
+ free(p);
return -1;
}
} else if (strlen(secret) && (p->authmethods & IAX_AUTH_PLAINTEXT)) {
/* They've provided a plain text password and we support that */
if (strcmp(secret, p->secret)) {
ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", inet_ntoa(sin->sin_addr), p->name);
+ if (p->delme)
+ free(p);
return -1;
} else
iaxs[callno]->state |= IAX_STATE_AUTHENTICATED;
- } else if (strlen(md5secret) && (p->authmethods & IAX_AUTH_MD5) && strlen(p->challenge)) {
+ } else if (strlen(md5secret) && (p->authmethods & IAX_AUTH_MD5) && strlen(iaxs[callno]->challenge)) {
struct MD5Context md5;
unsigned char digest[16];
MD5Init(&md5);
- MD5Update(&md5, p->challenge, strlen(p->challenge));
+ MD5Update(&md5, iaxs[callno]->challenge, strlen(iaxs[callno]->challenge));
MD5Update(&md5, p->secret, strlen(p->secret));
MD5Final(digest, &md5);
for (x=0;x<16;x++)
@@ -2917,12 +3039,16 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies *
iaxs[callno]->state |= IAX_STATE_AUTHENTICATED;
} else if (strlen(md5secret) || strlen(secret)) {
ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
+ if (p->delme)
+ free(p);
return -1;
}
strncpy(iaxs[callno]->peer, peer, sizeof(iaxs[callno]->peer)-1);
/* Choose lowest expirey number */
if (expire && (expire < iaxs[callno]->expirey))
iaxs[callno]->expirey = expire;
+ if (p->delme)
+ free(p);
return 0;
}
@@ -3343,35 +3469,48 @@ static int update_registry(char *name, struct sockaddr_in *sin, int callno)
memset(&ied, 0, sizeof(ied));
for (p = peerl.peers;p;p = p->next) {
if (!strcasecmp(name, p->name)) {
- if (inaddrcmp(&p->addr, sin)) {
- if (iax2_regfunk)
- iax2_regfunk(p->name, 1);
- snprintf(data, sizeof(data), "%s:%d:%d", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expirey);
- ast_db_put("IAX/Registry", p->name, data);
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Registered '%s' (%s) at %s:%d\n", p->name,
- iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
- iax2_poke_peer(p);
- }
- /* Update the host */
- memcpy(&p->addr, sin, sizeof(p->addr));
- /* Setup the expirey */
- if (p->expire > -1)
- ast_sched_del(sched, p->expire);
- p->expire = ast_sched_add(sched, p->expirey * 1000, expire_registry, (void *)p);
- iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
- iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expirey);
- iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
- if (strlen(p->mailbox)) {
- msgcount = ast_app_has_voicemail(p->mailbox);
- if (msgcount)
- msgcount = 65535;
- iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
- }
- if (p->hascallerid)
- iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->callerid);
- return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);;
+ break;
+ }
+ }
+#ifdef MYSQL_FRIENDS
+ if (!p)
+ p = mysql_peer(name);
+#endif
+ if (p) {
+#ifdef MYSQL_FRIENDS
+ if (p->delme)
+ mysql_update_peer(name, sin);
+#endif
+ if (inaddrcmp(&p->addr, sin)) {
+ if (iax2_regfunk)
+ iax2_regfunk(p->name, 1);
+ snprintf(data, sizeof(data), "%s:%d:%d", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), p->expirey);
+ ast_db_put("IAX/Registry", p->name, data);
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Registered '%s' (%s) at %s:%d\n", p->name,
+ iaxs[callno]->state & IAX_STATE_AUTHENTICATED ? "AUTHENTICATED" : "UNAUTHENTICATED", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ iax2_poke_peer(p);
+ }
+ /* Update the host */
+ memcpy(&p->addr, sin, sizeof(p->addr));
+ /* Setup the expirey */
+ if (p->expire > -1)
+ ast_sched_del(sched, p->expire);
+ p->expire = ast_sched_add(sched, p->expirey * 1000, expire_registry, (void *)p);
+ iax_ie_append_str(&ied, IAX_IE_USERNAME, p->name);
+ iax_ie_append_short(&ied, IAX_IE_REFRESH, p->expirey);
+ iax_ie_append_addr(&ied, IAX_IE_APPARENT_ADDR, &p->addr);
+ if (strlen(p->mailbox)) {
+ msgcount = ast_app_has_voicemail(p->mailbox);
+ if (msgcount)
+ msgcount = 65535;
+ iax_ie_append_short(&ied, IAX_IE_MSGCOUNT, msgcount);
}
+ if (p->hascallerid)
+ iax_ie_append_str(&ied, IAX_IE_CALLING_NAME, p->callerid);
+ if (p->delme)
+ free(p);
+ return send_command_final(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGACK, 0, ied.buf, ied.pos, -1);;
}
ast_log(LOG_WARNING, "No such peer '%s'\n", name);
return -1;
@@ -3381,19 +3520,30 @@ static int registry_authrequest(char *name, int callno)
{
struct iax_ie_data ied;
struct iax2_peer *p;
+ ast_mutex_lock(&peerl.lock);
for (p = peerl.peers;p;p = p->next) {
if (!strcasecmp(name, p->name)) {
- memset(&ied, 0, sizeof(ied));
- iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
- if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
- /* Build the challenge */
- snprintf(p->challenge, sizeof(p->challenge), "%d", rand());
- iax_ie_append_str(&ied, IAX_IE_CHALLENGE, p->challenge);
- }
- iax_ie_append_str(&ied, IAX_IE_USERNAME, name);
- return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
+ break;
}
}
+ ast_mutex_unlock(&peerl.lock);
+#ifdef MYSQL_FRIENDS
+ if (!p)
+ p = mysql_peer(name);
+#endif
+ if (p) {
+ memset(&ied, 0, sizeof(ied));
+ iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, p->authmethods);
+ if (p->authmethods & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
+ /* Build the challenge */
+ snprintf(iaxs[callno]->challenge, sizeof(iaxs[callno]->challenge), "%d", rand());
+ iax_ie_append_str(&ied, IAX_IE_CHALLENGE, iaxs[callno]->challenge);
+ }
+ iax_ie_append_str(&ied, IAX_IE_USERNAME, name);
+ if (p->delme)
+ free(p);
+ return send_command(iaxs[callno], AST_FRAME_IAX, IAX_COMMAND_REGAUTH, 0, ied.buf, ied.pos, -1);;
+ }
ast_log(LOG_WARNING, "No such peer '%s'\n", name);
return 0;
}
@@ -5245,7 +5395,19 @@ static int set_config(char *config_file, struct sockaddr_in* sin){
} else {
amaflags = format;
}
- } //else if (strcasecmp(v->name,"type"))
+ }
+#ifdef MYSQL_FRIENDS
+ else if (!strcasecmp(v->name, "dbuser")) {
+ strncpy(mydbuser, v->value, sizeof(mydbuser) - 1);
+ } else if (!strcasecmp(v->name, "dbpass")) {
+ strncpy(mydbpass, v->value, sizeof(mydbpass) - 1);
+ } else if (!strcasecmp(v->name, "dbhost")) {
+ strncpy(mydbhost, v->value, sizeof(mydbhost) - 1);
+ } else if (!strcasecmp(v->name, "dbname")) {
+ strncpy(mydbname, v->value, sizeof(mydbname) - 1);
+ }
+#endif
+ //else if (strcasecmp(v->name,"type"))
// ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
v = v->next;
}
@@ -5282,6 +5444,21 @@ static int set_config(char *config_file, struct sockaddr_in* sin){
}
ast_destroy(cfg);
set_timing();
+#ifdef MYSQL_FRIENDS
+ /* Connect to db if appropriate */
+ if (strlen(mydbname)) {
+ mysql = mysql_init(NULL);
+ if (!mysql_real_connect(mysql, mydbhost[0] ? mydbhost : NULL, mydbuser, mydbpass, mydbname, 0, NULL, 0)) {
+ memset(mydbpass, '*', strlen(mydbpass));
+ ast_log(LOG_WARNING, "Database connection failed (db=%s, host=%s, user=%s, pass=%s)!\n",
+ mydbname, mydbhost, mydbuser, mydbpass);
+ free(mysql);
+ mysql = NULL;
+ } else
+ ast_verbose(VERBOSE_PREFIX_1 "Connected to database '%s' on '%s' as '%s'\n",
+ mydbname, mydbhost, mydbuser);
+ }
+#endif
return capability;
}