summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xchannels/Makefile11
-rwxr-xr-xchannels/chan_sip.c222
2 files changed, 202 insertions, 31 deletions
diff --git a/channels/Makefile b/channels/Makefile
index 0c04a1629..3819e27e6 100755
--- a/channels/Makefile
+++ b/channels/Makefile
@@ -13,7 +13,7 @@
OSARCH=$(shell uname -s)
-USE_MYSQL_FRIENDS=0
+USE_MYSQL_FRIENDS=1
CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \
chan_modem_aopen.so \
@@ -113,7 +113,7 @@ endif
chan_iax.so: chan_iax.o
ifeq ($(USE_MYSQL_FRIENDS),1)
- $(CC) $(SOLINK) -o $@ chan_iax.o -lmysqlclient -lz
+ $(CC) $(SOLINK) -o $@ chan_iax.o -L/usr/lib/mysql -lmysqlclient -lz
else
$(CC) $(SOLINK) -o $@ chan_iax.o
endif
@@ -124,6 +124,13 @@ chan_zap.o: chan_zap.c
chan_zap.so: chan_zap.o
$(CC) $(SOLINK) -o $@ $< $(ZAPPRI) $(ZAPR2) -ltonezone
+chan_sip.so: chan_sip.o
+ifeq ($(USE_MYSQL_FRIENDS),1)
+ $(CC) $(SOLINK) -o $@ chan_sip.o -L/usr/lib/mysql -lmysqlclient -lz
+else
+ $(CC) $(SOLINK) -o $@ chan_sip.o
+endif
+
chan_alsa.o: $(ALSA_SRC)
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 1f3541f32..ad034c891 100755
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -52,6 +52,10 @@
#include <netinet/in_systm.h>
#include <netinet/ip.h>
+#ifdef MYSQL_FRIENDS
+#include <mysql/mysql.h>
+#endif
+
#ifndef IPTOS_MINCOST
#define IPTOS_MINCOST 0x02
#endif
@@ -79,6 +83,15 @@ static int default_expiry = DEFAULT_DEFAULT_EXPIRY;
#define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
#define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
+#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 = "Session Initiation Protocol (SIP)";
static char *type = "SIP";
static char *tdesc = "Session Initiation Protocol (SIP)";
@@ -341,6 +354,7 @@ struct sip_peer {
int delme;
int selfdestruct;
int lastmsg;
+ int temponly;
struct sip_peer *next;
};
@@ -661,6 +675,102 @@ static int sip_sendtext(struct ast_channel *ast, char *text)
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 sipfriends 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 sip_peer *mysql_peer(char *peer, struct sockaddr_in *sin)
+{
+ struct sip_peer *p;
+ int success = 0;
+
+ p = malloc(sizeof(struct sip_peer));
+ memset(p, 0, sizeof(struct sip_peer));
+ if (mysql && (!peer || (strlen(peer) < 128))) {
+ char query[512];
+ char *name = NULL;
+ int numfields, x;
+ int port;
+ time_t regseconds, nowtime;
+ MYSQL_RES *result;
+ MYSQL_FIELD *fields;
+ MYSQL_ROW rowval;
+ if (peer) {
+ name = alloca(strlen(peer) * 2 + 1);
+ mysql_real_escape_string(mysql, name, peer, strlen(peer));
+ }
+ if (sin)
+ snprintf(query, sizeof(query), "SELECT * FROM sipfriends WHERE ipaddr=\"%s\" AND port=\"%d\"", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
+ else
+ snprintf(query, sizeof(query), "SELECT * FROM sipfriends 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, "name")) {
+ strncpy(p->name, rowval[x], sizeof(p->name) - 1);
+ } 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) > default_expiry)
+ memset(&p->addr, 0, sizeof(p->addr));
+ }
+ }
+ ast_mutex_unlock(&mysqllock);
+ }
+ if (!success) {
+ free(p);
+ p = NULL;
+ } else {
+ p->dynamic = 1;
+ p->capability = capability;
+ p->nat = globalnat;
+ p->dtmfmode = globaldtmfmode;
+ p->insecure = 1;
+ p->expire = -1;
+ p->temponly = 1;
+
+ }
+ return p;
+}
+#endif /* MYSQL_FRIENDS */
+
static int create_addr(struct sip_pvt *r, char *peer)
{
struct hostent *hp;
@@ -674,7 +784,16 @@ static int create_addr(struct sip_pvt *r, char *peer)
ast_mutex_lock(&peerl.lock);
p = peerl.peers;
while(p) {
- if (!strcasecmp(p->name, peer)) {
+ if (!strcasecmp(p->name, peer))
+ break;
+ p = p->next;
+ }
+#ifdef MYSQL_FRIENDS
+ if (!p)
+ p = mysql_peer(peer, NULL);
+#endif
+
+ if (p) {
found++;
r->capability = p->capability;
r->nat = p->nat;
@@ -724,10 +843,7 @@ static int create_addr(struct sip_pvt *r, char *peer)
r->sa.sin_port = p->defaddr.sin_port;
}
memcpy(&r->recv, &r->sa, sizeof(r->recv));
- break;
}
- }
- p = p->next;
}
ast_mutex_unlock(&peerl.lock);
if (!p && !found) {
@@ -764,8 +880,11 @@ static int create_addr(struct sip_pvt *r, char *peer)
}
} else if (!p)
return -1;
- else
+ else {
+ if (p->temponly)
+ free(p);
return 0;
+ }
}
static int auto_congest(void *nothing)
@@ -3355,9 +3474,14 @@ static int parse_contact(struct sip_pvt *pvt, struct sip_peer *p, struct sip_req
ast_sched_del(sched, p->expire);
if ((expiry < 1) || (expiry > max_expiry))
expiry = max_expiry;
- p->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, p);
+ if (!p->temponly)
+ p->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, p);
pvt->expiry = expiry;
if (inaddrcmp(&p->addr, &oldsin)) {
+#ifdef MYSQL_FRIENDS
+ if (p->temponly)
+ mysql_update_peer(p->name, &p->addr);
+#endif
sip_poke_peer(p);
snprintf(data, sizeof(data), "%s:%d:%d:%s", inet_ntoa(p->addr.sin_addr), ntohs(p->addr.sin_port), expiry, p->username);
ast_db_put("SIP/Registry", p->name, data);
@@ -3630,27 +3754,33 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
ast_mutex_lock(&peerl.lock);
peer = peerl.peers;
while(peer) {
- if (!strcasecmp(peer->name, name) && ast_apply_ha(peer->ha,sin)) {
+ if (!strcasecmp(peer->name, name) && ast_apply_ha(peer->ha,sin))
+ break;
+ peer = peer->next;
+ }
+ ast_mutex_unlock(&peerl.lock);
+#ifdef MYSQL_FRIENDS
+ if (!peer)
+ peer = mysql_peer(name, NULL);
+#endif
+ if (peer) {
if (!peer->dynamic) {
ast_log(LOG_NOTICE, "Peer '%s' isn't dynamic\n", peer->name);
- break;
+ } else {
+ p->nat = peer->nat;
+ transmit_response(p, "100 Trying", req);
+ if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, "REGISTER", uri, 0))) {
+ sip_cancel_destroy(p);
+ if (parse_contact(p, peer, req)) {
+ ast_log(LOG_WARNING, "Failed to parse contact info\n");
+ } else {
+ /* Say OK and ask subsystem to retransmit msg counter */
+ transmit_response_with_date(p, "200 OK", req);
+ peer->lastmsgssent = -1;
+ res = 0;
+ }
+ }
}
- p->nat = peer->nat;
- transmit_response(p, "100 Trying", req);
- if (!(res = check_auth(p, req, p->randdata, sizeof(p->randdata), peer->name, peer->secret, peer->md5secret, "REGISTER", uri, 0))) {
- sip_cancel_destroy(p);
- if (parse_contact(p, peer, req)) {
- ast_log(LOG_WARNING, "Failed to parse contact info\n");
- } else {
- /* Say OK and ask subsystem to retransmit msg counter */
- transmit_response_with_date(p, "200 OK", req);
- peer->lastmsgssent = -1;
- res = 0;
- }
- }
- break;
- }
- peer = peer->next;
}
if (!peer && autocreatepeer) {
/* Create peer if we have autocreate mode enabled */
@@ -3670,12 +3800,13 @@ static int register_verify(struct sip_pvt *p, struct sockaddr_in *sin, struct si
}
}
}
- ast_mutex_unlock(&peerl.lock);
if (!res) {
ast_device_state_changed("SIP/%s", peer->name);
}
if (res < 0)
transmit_response(p, "401 Unauthorized", &p->initreq);
+ if (peer && peer->temponly)
+ free(peer);
return res;
}
@@ -4096,6 +4227,16 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
while(peer) {
if (!inaddrcmp(&peer->addr, &p->recv) ||
(peer->insecure && (peer->addr.sin_addr.s_addr == p->recv.sin_addr.s_addr))) {
+ break;
+ }
+ peer = peer->next;
+ }
+ ast_mutex_unlock(&peerl.lock);
+#ifdef MYSQL_FRIENDS
+ if (!peer)
+ peer = mysql_peer(NULL, sin);
+#endif
+ if (peer) {
/* Take the peer */
p->nat = peer->nat;
if (p->rtp) {
@@ -4125,11 +4266,9 @@ static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, cha
else
p->noncodeccapability &= ~AST_RTP_DTMF;
}
- break;
- }
- peer = peer->next;
+ if (peer->temponly)
+ free(peer);
}
- ast_mutex_unlock(&peerl.lock);
}
return res;
}
@@ -6272,6 +6411,16 @@ static int reload_config(void)
} else {
ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
}
+#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;
@@ -6357,6 +6506,21 @@ static int reload_config(void)
ast_mutex_unlock(&netlock);
ast_destroy(cfg);
+#ifdef MYSQL_FRIENDS
+ /* Connect to db if appropriate */
+ if (!mysql && 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 0;
}