[Asterisk-cvs] asterisk/channels Makefile,1.15,1.16 chan_iax2.c,1.55,1.56

markster at lists.digium.com markster at lists.digium.com
Wed Nov 12 02:32:42 CST 2003


Update of /usr/cvsroot/asterisk/channels
In directory mongoose.digium.com:/tmp/cvs-serv23792/channels

Modified Files:
	Makefile chan_iax2.c 
Log Message:
Preliminary support for iax2 friends in mysql database


Index: Makefile
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/Makefile,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- Makefile	26 Oct 2003 18:50:49 -0000	1.15
+++ Makefile	12 Nov 2003 08:58:55 -0000	1.16
@@ -13,6 +13,8 @@
 
 OSARCH=$(shell uname -s)
 
+USE_MYSQL_FRIENDS=0
+
 CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \
 	     chan_modem_aopen.so \
              chan_modem_bestdata.so chan_modem_i4l.so \
@@ -50,6 +52,10 @@
 CFLAGS+=-DCRYPTO
 CFLAGS+=-fPIC
 
+ifeq ($(USE_MYSQL_FRIENDS),1)
+CFLAGS+=-DMYSQL_FRIENDS
+endif
+
 CFLAGS+=#-DVOFRDUMPER
 
 ZAPDIR=/usr/lib
@@ -101,7 +107,11 @@
 endif
 
 chan_iax2.so: chan_iax2.o iax2-parser.o
+ifeq ($(USE_MYSQL_FRIENDS),1)
+	$(CC) $(SOLINK) -o $@ chan_iax2.o iax2-parser.o -lmysqlclient -lz
+else
 	$(CC) $(SOLINK) -o $@ chan_iax2.o iax2-parser.o
+endif
 
 chan_zap.o: $(CHANZAP)
 	$(CC) -c $(CFLAGS) -o chan_zap.o $(CHANZAP)

Index: chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- chan_iax2.c	4 Nov 2003 02:40:09 -0000	1.55
+++ chan_iax2.c	12 Nov 2003 08:58:55 -0000	1.56
@@ -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 @@
 	/* 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 @@
 	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 @@
 	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 @@
 		}
 	} 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 @@
 		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 @@
 
 	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 @@
 			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 @@
 			}
 			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 @@
 			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 @@
 	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 @@
 {
 	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 @@
 			} 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 @@
 	}
 	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;
 }
 




More information about the svn-commits mailing list