2011-10-06 19:53:39 -07:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Kestrel Signal Processing, Inc.
|
|
|
|
* Copyright 2011 Range Networks, Inc.
|
|
|
|
*
|
|
|
|
* This software is distributed under the terms of the GNU Affero Public License.
|
|
|
|
* See the COPYING file in the main directory for details.
|
|
|
|
*
|
|
|
|
* This use of this software may be subject to additional restrictions.
|
|
|
|
* See the LEGAL file in the main directory for details.
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <osip2/osip.h>
|
|
|
|
#include <osipparser2/osip_message.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <Logger.h>
|
|
|
|
#include <Configuration.h>
|
|
|
|
#include "servershare.h"
|
|
|
|
#include "SubscriberRegistry.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2011-11-18 14:09:44 -08:00
|
|
|
ConfigurationTable gConfig("/etc/OpenBTS/sipauthserve.db");
|
2011-10-06 19:53:39 -07:00
|
|
|
|
|
|
|
int my_udp_port;
|
|
|
|
|
|
|
|
// just using this for the database access
|
|
|
|
SubscriberRegistry gSubscriberRegistry;
|
|
|
|
|
|
|
|
void prettyPrint(const char *label, osip_message_t *sip)
|
|
|
|
{
|
|
|
|
char *dest=NULL;
|
|
|
|
size_t length=0;
|
|
|
|
int i = osip_message_to_str(sip, &dest, &length);
|
|
|
|
if (i!=0) {
|
|
|
|
LOG(ERR) << "cannot get printable message";
|
|
|
|
} else {
|
|
|
|
LOG(INFO) << label << ":\n" << dest;
|
|
|
|
osip_free(dest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
string imsiFromSip(osip_message_t *sip)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *dest;
|
|
|
|
osip_uri_t *fromUri = osip_from_get_url(sip->from);
|
|
|
|
if (!fromUri) {
|
|
|
|
LOG(ERR) << "osip_from_get_url problem";
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
i = osip_uri_to_str(fromUri, &dest);
|
|
|
|
string imsi = dest;
|
|
|
|
osip_free(dest);
|
|
|
|
return imsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
string imsiToSip(osip_message_t *sip)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *dest;
|
|
|
|
osip_uri_t *toUri = osip_to_get_url(sip->to);
|
|
|
|
if (!toUri) {
|
|
|
|
LOG(ERR) << "osip_to_get_url problem";
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
i = osip_uri_to_str(toUri, &dest);
|
|
|
|
string imsi = dest;
|
|
|
|
osip_free(dest);
|
|
|
|
return imsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
// is imsi in the database?
|
|
|
|
bool imsiFound(string imsi)
|
|
|
|
{
|
|
|
|
string x = imsiGet(imsi, "id");
|
|
|
|
return x.length() != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
string imsiClean(string imsi)
|
|
|
|
{
|
|
|
|
// remove leading sip:
|
|
|
|
if (0 == strncasecmp(imsi.c_str(), "sip:", 4)) {
|
|
|
|
imsi = imsi.substr(4);
|
|
|
|
}
|
|
|
|
// remove trailing @...
|
|
|
|
size_t p = imsi.find("@");
|
|
|
|
if (p != string::npos) {
|
|
|
|
imsi = imsi.substr(0, p);
|
|
|
|
}
|
|
|
|
// remove leading IMSI
|
|
|
|
if (0 == strncasecmp(imsi.c_str(), "imsi", 4)) {
|
|
|
|
imsi = imsi.substr(4);
|
|
|
|
}
|
|
|
|
return imsi;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char *processBuffer(char *buffer)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
// parse sip message
|
|
|
|
osip_message_t *sip;
|
|
|
|
i=osip_message_init(&sip);
|
|
|
|
if (i!=0) {
|
|
|
|
LOG(ERR) << "cannot allocate";
|
|
|
|
osip_message_free(sip);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
i=osip_message_parse(sip, buffer, strlen(buffer));
|
|
|
|
if (i!=0) {
|
|
|
|
LOG(ERR) << "cannot parse sip message";
|
|
|
|
osip_message_free(sip);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
prettyPrint("request", sip);
|
|
|
|
|
|
|
|
// response starts as clone of message
|
|
|
|
osip_message_t *response;
|
|
|
|
osip_message_clone(sip, &response);
|
|
|
|
|
|
|
|
osip_from_t * contact_header = (osip_from_t*)osip_list_get(&sip->contacts,0);
|
|
|
|
osip_uri_t* contact_url = contact_header->url;
|
|
|
|
char *remote_host = contact_url->host;
|
2012-03-24 16:33:46 -07:00
|
|
|
//char *remote_port = contact_url->port;
|
|
|
|
//this is an smqueue hack, will not be needed with FS -kurtis
|
|
|
|
char *remote_port = "5062";
|
2011-10-06 19:53:39 -07:00
|
|
|
|
|
|
|
// return via
|
|
|
|
ostringstream newvia;
|
|
|
|
// newvia << "SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar";
|
|
|
|
const char *my_ipaddress = "localhost";
|
|
|
|
newvia << "SIP/2.0/UDP " << my_ipaddress << ":" << my_udp_port << ";branch=1;received="
|
|
|
|
<< "string_address@foo.bar"; // << my_network.string_addr((struct sockaddr *)netaddr, netaddrlen, false);
|
|
|
|
osip_message_append_via(response, newvia.str().c_str());
|
|
|
|
|
|
|
|
// no method
|
|
|
|
osip_message_set_method(response, NULL);
|
|
|
|
|
|
|
|
string imsi = imsiClean(imsiFromSip(sip));
|
|
|
|
string imsiTo = imsiClean(imsiToSip(sip));
|
|
|
|
if ((imsi == "EXIT") && (imsiTo == "EXIT")) exit(0); // for testing only
|
|
|
|
if (!imsiFound(imsi)) {
|
|
|
|
LOG(NOTICE) << "imsi unknown";
|
|
|
|
// imsi problem => 404 IMSI Not Found
|
|
|
|
osip_message_set_status_code (response, 404);
|
|
|
|
osip_message_set_reason_phrase (response, osip_strdup("IMSI Not Found"));
|
|
|
|
} else {
|
|
|
|
// sres matches rand => 200 OK
|
|
|
|
osip_message_set_status_code (response, 200);
|
|
|
|
osip_message_set_reason_phrase (response, osip_strdup("OK"));
|
|
|
|
// And register it.
|
2012-03-24 16:33:46 -07:00
|
|
|
LOG(INFO) << "success, registering for IP address " << remote_host << ":" << remote_port;
|
2011-10-06 19:53:39 -07:00
|
|
|
imsiSet(imsi,"ipaddr",remote_host);
|
2012-03-24 16:33:46 -07:00
|
|
|
imsiSet(imsi,"port",remote_port);
|
2011-10-06 19:53:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
prettyPrint("response", response);
|
|
|
|
size_t length = 0;
|
|
|
|
char *dest;
|
|
|
|
int ii = osip_message_to_str(response, &dest, &length);
|
|
|
|
if (ii != 0) {
|
|
|
|
LOG(ERR) << "cannot get printable message";
|
|
|
|
}
|
|
|
|
|
|
|
|
osip_message_free(sip);
|
|
|
|
osip_message_free(response);
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define BUFLEN 5000
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
|
|
|
sockaddr_in si_me;
|
|
|
|
sockaddr_in si_other;
|
|
|
|
int aSocket;
|
|
|
|
char buf[BUFLEN];
|
|
|
|
|
|
|
|
gLogInit("sipauthserve", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);
|
|
|
|
LOG(ALERT) << argv[0] << " (re)starting";
|
|
|
|
srand ( time(NULL) + (int)getpid() );
|
|
|
|
my_udp_port = gConfig.getNum("SubscriberRegistry.Port");
|
2012-02-09 17:45:41 -08:00
|
|
|
gSubscriberRegistry.init();
|
2011-10-06 19:53:39 -07:00
|
|
|
|
|
|
|
// init osip lib
|
|
|
|
osip_t *osip;
|
|
|
|
int i=osip_init(&osip);
|
|
|
|
if (i!=0) {
|
|
|
|
LOG(ALERT) << "cannot init sip lib";
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
|
|
|
LOG(ALERT) << "can't initialize socket";
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
memset((char *) &si_me, 0, sizeof(si_me));
|
|
|
|
si_me.sin_family = AF_INET;
|
|
|
|
si_me.sin_port = htons(my_udp_port);
|
|
|
|
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
if (bind(aSocket, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
|
|
|
|
LOG(ALERT) << "can't bind socket on port " << my_udp_port;
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG(NOTICE) << "binding on port " << my_udp_port;
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
gConfig.purge();
|
|
|
|
socklen_t slen = sizeof(si_other);
|
|
|
|
memset(buf, 0, BUFLEN);
|
|
|
|
if (recvfrom(aSocket, buf, BUFLEN, 0, (sockaddr*)&si_other, &slen) == -1) {
|
|
|
|
LOG(ERR) << "recvfrom problem";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOG(INFO) << " receiving " << buf;
|
|
|
|
|
|
|
|
char *dest = processBuffer(buf);
|
|
|
|
if (dest == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sendto(aSocket, dest, strlen(dest), 0, (sockaddr*)&si_other, sizeof(si_other)) == -1) {
|
|
|
|
LOG(ERR) << "sendto problem";
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
osip_free(dest);
|
|
|
|
}
|
|
|
|
|
|
|
|
close(aSocket);
|
|
|
|
return 0;
|
|
|
|
}
|