- more intensive testst for NULL pointers
- added knowledge base for SIP URI rewriting (UA dependent)
This commit is contained in:
parent
b4e7511ec6
commit
d829f79971
@ -23,10 +23,10 @@ CFLAGS =@CFLAGS@ -Wall -DBUILDSTR=\"`cat .buildno`\" -D_GNU_SOURCE
|
||||
|
||||
bin_PROGRAMS = siproxd
|
||||
siproxd_SOURCES = siproxd.c proxy.c register.c sock.c utils.c \
|
||||
log.c readconf.c rtpproxy.c accessctl.c \
|
||||
sip_utils.c log.c readconf.c rtpproxy.c accessctl.c \
|
||||
security.c auth.c
|
||||
|
||||
noinst_HEADERS = log.h siproxd.h digcalc.h
|
||||
noinst_HEADERS = log.h rewrite_rules.h siproxd.h digcalc.h
|
||||
|
||||
EXTRA_DIST = .buildno
|
||||
|
||||
|
||||
@ -51,9 +51,12 @@ int process_aclist (char *aclist, struct sockaddr_in from);
|
||||
int accesslist_check (struct sockaddr_in from) {
|
||||
int access = 0;
|
||||
|
||||
DEBUGC(DBCLASS_ACCESS,"deny list (SIP):%s",configuration.hosts_deny_sip);
|
||||
DEBUGC(DBCLASS_ACCESS,"allow list (SIP):%s",configuration.hosts_allow_sip);
|
||||
DEBUGC(DBCLASS_ACCESS,"allow list (REG):%s",configuration.hosts_allow_reg);
|
||||
DEBUGC(DBCLASS_ACCESS,"deny list (SIP):%s",
|
||||
configuration.hosts_deny_sip? configuration.hosts_deny_sip : "*NULL*");
|
||||
DEBUGC(DBCLASS_ACCESS,"allow list (SIP):%s",
|
||||
configuration.hosts_allow_sip? configuration.hosts_allow_sip : "*NULL*");
|
||||
DEBUGC(DBCLASS_ACCESS,"allow list (REG):%s",
|
||||
configuration.hosts_allow_reg? configuration.hosts_allow_reg : "*NULL*");
|
||||
|
||||
/*
|
||||
* check DENY list
|
||||
|
||||
@ -61,7 +61,7 @@ int authenticate_proxy(sip_t *request) {
|
||||
proxy_authorization_t *proxy_auth;
|
||||
|
||||
/* required by config? */
|
||||
if (configuration.proxy_auth_realm==NULL) {
|
||||
if (configuration.proxy_auth_realm == NULL) {
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -72,9 +72,8 @@ int authenticate_proxy(sip_t *request) {
|
||||
return STS_NEED_AUTH;
|
||||
}
|
||||
|
||||
|
||||
/* verify supplied authentication */
|
||||
if (auth_check(proxy_auth) == 0) {
|
||||
if (auth_check(proxy_auth) == STS_SUCCESS) {
|
||||
DEBUGC(DBCLASS_AUTH,"proxy-auth succeeded");
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
223
src/proxy.c
223
src/proxy.c
@ -86,8 +86,8 @@ int proxy_request (sip_t *request) {
|
||||
if (compare_url(request->to->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=REQTYP_INCOMING;
|
||||
DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound",
|
||||
request->from->url->username,
|
||||
request->from->url->host);
|
||||
request->from->url->username? request->from->url->username:"*NULL*",
|
||||
request->from->url->host? request->from->url->host: "*NULL*");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -95,8 +95,8 @@ int proxy_request (sip_t *request) {
|
||||
if (compare_url(request->from->url, urlmap[i].reg_url)==STS_SUCCESS) {
|
||||
type=REQTYP_OUTGOING;
|
||||
DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound",
|
||||
request->from->url->username,
|
||||
request->from->url->host);
|
||||
request->from->url->username? request->from->url->username:"*NULL*",
|
||||
request->from->url->host? request->from->url->host: "*NULL*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -105,6 +105,34 @@ int proxy_request (sip_t *request) {
|
||||
/*
|
||||
* ok, we got a request that we are allowed to process.
|
||||
*/
|
||||
#ifdef HACK1
|
||||
/* linphone-0.9.0pre4
|
||||
take To address and place it into URI (at least the host part)
|
||||
Linphone-0.9.0pre4 puts the proxy host in the request URI
|
||||
if OUTBOUND proxy is activated!
|
||||
This is only a hack to recreate the proper final request URI.
|
||||
This issue has been fixed in 0.9.1pre1
|
||||
*/
|
||||
{
|
||||
header_t *header_ua;
|
||||
|
||||
url=msg_geturi(request);
|
||||
msg_getuser_agent(request,0,&header_ua);
|
||||
|
||||
if ( header_ua && header_ua->hvalue &&
|
||||
(strcmp(header_ua->hvalue,"oSIP/Linphone-0.8.0")==0) ) {
|
||||
/* if an outgoing request, try to fix the SIP URI */
|
||||
if (type == REQTYP_OUTGOING) {
|
||||
WARN("broken linphone-0.8.0: restoring SIP URI");
|
||||
free (url->host);
|
||||
url->host=malloc(strlen(request->to->url->host));
|
||||
strcpy(url->host,request->to->url->host);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (type) {
|
||||
/*
|
||||
* from an external host to the internal masqueraded host
|
||||
@ -112,31 +140,10 @@ int proxy_request (sip_t *request) {
|
||||
case REQTYP_INCOMING:
|
||||
/* rewrite request URI to point to the real host */
|
||||
/* i still holds the valid index into the URLMAP table */
|
||||
|
||||
/* THIS IS UGLY!!! I dont like it */
|
||||
DEBUGC(DBCLASS_PROXY,"rewriting incoming Request URI");
|
||||
url=msg_geturi(request);
|
||||
free(url->host);url->host=NULL;
|
||||
{
|
||||
char *host;
|
||||
char *port;
|
||||
/* set the true host */
|
||||
if(urlmap[i].true_url->host) {
|
||||
host = (char *)malloc(strlen(urlmap[i].true_url->host)+1);
|
||||
memcpy(host, urlmap[i].true_url->host, strlen(urlmap[i].true_url->host));
|
||||
host[strlen(urlmap[i].true_url->host)]='\0';
|
||||
url_sethost(url, host);
|
||||
if (check_rewrite_rq_uri(request)) {
|
||||
proxy_rewrite_request_uri(request, i);
|
||||
}
|
||||
|
||||
/* set the true port */
|
||||
if(urlmap[i].true_url->port) {
|
||||
port = (char *)malloc(strlen(urlmap[i].true_url->port)+1);
|
||||
memcpy(port, urlmap[i].true_url->port, strlen(urlmap[i].true_url->port));
|
||||
port[strlen(urlmap[i].true_url->port)]='\0';
|
||||
url_setport(url, port);
|
||||
}
|
||||
}
|
||||
|
||||
/* add my Via header line (inbound interface)*/
|
||||
sts = proxy_add_myvia(request, 1);
|
||||
if (sts == STS_FAILURE) {
|
||||
@ -155,6 +162,23 @@ int proxy_request (sip_t *request) {
|
||||
* from the internal masqueraded host to an external host
|
||||
*/
|
||||
case REQTYP_OUTGOING:
|
||||
/* if it is addressed to myself, then it must be some request
|
||||
* method that I as a proxy do not support. Reject */
|
||||
if (is_sipuri_local(request) == STS_TRUE) {
|
||||
url=msg_geturi(request);
|
||||
WARN("unsupported request [%s] directed to proxy from %s@%s -> %s@%s",
|
||||
request->strtline->sipmethod? request->strtline->sipmethod:"*NULL*",
|
||||
request->from->url->username? request->from->url->username:"*NULL*",
|
||||
request->from->url->host? request->from->url->host : "*NULL*",
|
||||
url->username? url->username : "*NULL*",
|
||||
url->host? url->host : "*NULL*");
|
||||
|
||||
proxy_gen_response(request, 403 /*forbidden*/);
|
||||
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
/* if an INVITE, rewrite body */
|
||||
if (MSG_IS_INVITE(request)) {
|
||||
sts = proxy_rewrite_invitation_body(request);
|
||||
@ -171,8 +195,8 @@ int proxy_request (sip_t *request) {
|
||||
/* found a mapping entry */
|
||||
if (i<URLMAP_SIZE) {
|
||||
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
|
||||
(contact->url->username) ? contact->url->username : "*NULL*",
|
||||
(contact->url->host) ? contact->url->host : "*NULL*",
|
||||
(contact->url->username)? contact->url->username : "*NULL*",
|
||||
(contact->url->host)? contact->url->host : "*NULL*",
|
||||
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
|
||||
/* remove old entry */
|
||||
list_remove(request->contacts,0);
|
||||
@ -201,17 +225,21 @@ int proxy_request (sip_t *request) {
|
||||
default:
|
||||
url=msg_geturi(request);
|
||||
DEBUGC(DBCLASS_PROXY,"proxy_request: refused to proxy");
|
||||
WARN("request from/to unregistered UA (RQ: %s@%s -> %s@%s)",
|
||||
request->from->url->username,
|
||||
request->from->url->host,
|
||||
url->username,
|
||||
url->host);
|
||||
/* some clients seem to run amok when passing back a negative response
|
||||
* so we simply drop the request silently
|
||||
WARN("request [%s] from/to unregistered UA (RQ: %s@%s -> %s@%s)",
|
||||
request->strtline->sipmethod? request->strtline->sipmethod:"*NULL*",
|
||||
request->from->url->username? request->from->url->username:"*NULL*",
|
||||
request->from->url->host? request->from->url->host : "*NULL*",
|
||||
url->username? url->username : "*NULL*",
|
||||
url->host? url->host : "*NULL*");
|
||||
|
||||
/*
|
||||
* if we end up here, we deal with a request that we have
|
||||
* no proxy entry - so it must be ment to be for the proxy itself.
|
||||
* As we only deal with REGISTER requests, we will anser this one
|
||||
* with FORBIDDEN
|
||||
*/
|
||||
#if 0
|
||||
proxy_gen_response(request, 403 /*forbidden*/);
|
||||
#endif
|
||||
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
@ -219,33 +247,12 @@ int proxy_request (sip_t *request) {
|
||||
/* get target address from request URL */
|
||||
url=msg_geturi(request);
|
||||
|
||||
#ifdef HACK1
|
||||
/* linphone-0.9.0pre4
|
||||
take To address and place it into URI (at least the host part)
|
||||
Linphone-0.9.0pre4 puts the proxy host in the request URI
|
||||
if OUTBOUND proxy is activated!
|
||||
This is only a hack to recreate the proper final request URI.
|
||||
This issue has been fixed in 0.9.1pre1
|
||||
*/
|
||||
{
|
||||
header_t *header_ua;
|
||||
msg_getuser_agent(request,0,&header_ua);
|
||||
|
||||
if ( header_ua && header_ua->hvalue &&
|
||||
(strcmp(header_ua->hvalue,"oSIP/Linphone-0.8.0")==0) ) {
|
||||
/* if an outgoing request, try to fix the SIP URI */
|
||||
if (type == REQTYP_OUTGOING) {
|
||||
WARN("broken linphone-0.8.0: restoring SIP URI");
|
||||
free (url->host);
|
||||
url->host=malloc(strlen(request->to->url->host));
|
||||
strcpy(url->host,request->to->url->host);
|
||||
|
||||
}
|
||||
if (url) {
|
||||
sts = get_ip_by_host(url->host, &addr);
|
||||
} else {
|
||||
ERROR("proxy_request: got NULL URL");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sts = get_ip_by_host(url->host, &addr);
|
||||
|
||||
sts = msg_2char(request, &buffer);
|
||||
if (sts != 0) {
|
||||
@ -257,7 +264,7 @@ int proxy_request (sip_t *request) {
|
||||
if (url->port) {
|
||||
port=atoi(url->port);
|
||||
} else {
|
||||
port=configuration.sip_listen_port;
|
||||
port=SIP_PORT;
|
||||
}
|
||||
|
||||
sipsock_send_udp(&sip_socket, addr, port, buffer, strlen(buffer), 1);
|
||||
@ -324,8 +331,8 @@ int proxy_response (sip_t *response) {
|
||||
if (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=RESTYP_INCOMING;
|
||||
DEBUGC(DBCLASS_PROXY,"incoming response for %s@%s from outbound",
|
||||
response->from->url->username,
|
||||
response->from->url->host);
|
||||
response->from->url->username? response->from->url->username:"*NULL*",
|
||||
response->from->url->host? response->from->url->host : "*NULL*");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -333,8 +340,8 @@ int proxy_response (sip_t *response) {
|
||||
if (compare_url(response->to->url, urlmap[i].masq_url)==STS_SUCCESS) {
|
||||
type=RESTYP_OUTGOING;
|
||||
DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound",
|
||||
response->from->url->username,
|
||||
response->from->url->host);
|
||||
response->from->url->username? response->from->url->username:"*NULL*",
|
||||
response->from->url->host? response->from->url->host : "*NULL*");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -371,7 +378,7 @@ int proxy_response (sip_t *response) {
|
||||
/* found a mapping entry */
|
||||
if (i<URLMAP_SIZE) {
|
||||
DEBUGC(DBCLASS_PROXY, "rewrote Contact header %s@%s -> %s@%s",
|
||||
(contact->url->username) ? contact->url->username : "*NULL*",
|
||||
(contact->url->username) ? contact->url->username:"*NULL*",
|
||||
(contact->url->host) ? contact->url->host : "*NULL*",
|
||||
urlmap[i].masq_url->username, urlmap[i].masq_url->host);
|
||||
/* remove old entry */
|
||||
@ -390,23 +397,23 @@ int proxy_response (sip_t *response) {
|
||||
default:
|
||||
DEBUGC(DBCLASS_PROXY,"proxy_response: refused to proxy");
|
||||
WARN("response from/to unregistered UA (%s@%s)",
|
||||
response->from->url->username,
|
||||
response->from->url->host);
|
||||
/* some clients seem to run amok when passing back a negative response */
|
||||
#if 0
|
||||
proxy_gen_response(response, 403 /*forbidden*/);
|
||||
#endif
|
||||
response->from->url->username? response->from->url->username:"*NULL*",
|
||||
response->from->url->host? response->from->url->host : "*NULL*");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* get target address from VIA header */
|
||||
via = (via_t *) list_get (response->vias, 0);
|
||||
if (via == NULL) {
|
||||
ERROR("proxy_response: list_get via failed");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
sts = get_ip_by_host(via->host, &addr);
|
||||
|
||||
sts = msg_2char(response, &buffer);
|
||||
if (sts != 0) {
|
||||
ERROR("proxy_request: msg_2char failed");
|
||||
ERROR("proxy_response: msg_2char failed");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
@ -414,7 +421,7 @@ int proxy_response (sip_t *response) {
|
||||
if (via->port) {
|
||||
port=atoi(via->port);
|
||||
} else {
|
||||
port=configuration.sip_listen_port;
|
||||
port=SIP_PORT;
|
||||
}
|
||||
|
||||
sipsock_send_udp(&sip_socket, addr, port, buffer, strlen(buffer), 1);
|
||||
@ -438,6 +445,7 @@ int proxy_gen_response(sip_t *request, int code) {
|
||||
sip_t *response;
|
||||
int sts;
|
||||
via_t *via;
|
||||
int port;
|
||||
char *buffer;
|
||||
struct in_addr addr;
|
||||
|
||||
@ -471,8 +479,15 @@ DEBUGC(DBCLASS_PROXY,"response=%p",response);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
if (via->port) {
|
||||
port=atoi(via->port);
|
||||
} else {
|
||||
port=SIP_PORT;
|
||||
}
|
||||
|
||||
/* send to destination */
|
||||
sipsock_send_udp(&sip_socket, addr, atoi(via->port),
|
||||
sipsock_send_udp(&sip_socket, addr, port,
|
||||
buffer, strlen(buffer), 1);
|
||||
|
||||
/* free the resources */
|
||||
@ -617,10 +632,16 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
if (sdp_m_port_get(sdp, media_stream_no) == NULL) break;
|
||||
|
||||
/* start an RTP proxying stream */
|
||||
inb_clnt_port = atoi(sdp_m_port_get(sdp, media_stream_no));
|
||||
rtp_start_fwd(msg_getcall_id(mymsg), media_stream_no,
|
||||
outb_addr, &outb_rtp_port,
|
||||
lcl_clnt_addr, inb_clnt_port);
|
||||
if (sdp_m_port_get(sdp, media_stream_no)) {
|
||||
inb_clnt_port=atoi(sdp_m_port_get(sdp, media_stream_no));
|
||||
rtp_start_fwd(msg_getcall_id(mymsg), media_stream_no,
|
||||
outb_addr, &outb_rtp_port,
|
||||
lcl_clnt_addr, inb_clnt_port);
|
||||
} else {
|
||||
/* no port defined - skip entry */
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -769,3 +790,39 @@ int proxy_rewrite_invitation_body(sip_t *mymsg){
|
||||
free(oldbody);
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* PROXY_REWRITE_INVITATION_BODY
|
||||
*
|
||||
* rewrites the outgoing INVITATION packet
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS on success
|
||||
*/
|
||||
int proxy_rewrite_request_uri(sip_t *mymsg, int idx){
|
||||
char *host;
|
||||
char *port;
|
||||
url_t *url;
|
||||
|
||||
DEBUGC(DBCLASS_PROXY,"rewriting incoming Request URI");
|
||||
url=msg_geturi(mymsg);
|
||||
free(url->host);url->host=NULL;
|
||||
|
||||
/* set the true host */
|
||||
if(urlmap[idx].true_url->host) {
|
||||
host = (char *)malloc(strlen(urlmap[idx].true_url->host)+1);
|
||||
memcpy(host, urlmap[idx].true_url->host, strlen(urlmap[idx].true_url->host));
|
||||
host[strlen(urlmap[idx].true_url->host)]='\0';
|
||||
url_sethost(url, host);
|
||||
}
|
||||
|
||||
/* set the true port */
|
||||
if(urlmap[idx].true_url->port) {
|
||||
port = (char *)malloc(strlen(urlmap[idx].true_url->port)+1);
|
||||
memcpy(port, urlmap[idx].true_url->port, strlen(urlmap[idx].true_url->port));
|
||||
port[strlen(urlmap[idx].true_url->port)]='\0';
|
||||
url_setport(url, port);
|
||||
}
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -72,7 +72,8 @@ int register_client(sip_t *my_msg) {
|
||||
if (sts == STS_FAILURE) {
|
||||
/* failed */
|
||||
WARN("proxy authentication failed for %s@%s",
|
||||
my_msg->to->url->username,my_msg->to->url->host);
|
||||
(my_msg->to->url->username)? my_msg->to->url->username : "*NULL*",
|
||||
my_msg->to->url->host);
|
||||
return STS_FAILURE;
|
||||
} else if (sts == STS_NEED_AUTH) {
|
||||
/* needed */
|
||||
@ -99,7 +100,7 @@ int register_client(sip_t *my_msg) {
|
||||
/* evaluate Expires Header field */
|
||||
msg_getexpires(my_msg, 0, &expires_hdr);
|
||||
|
||||
if (expires_hdr) {
|
||||
if (expires_hdr && expires_hdr->hvalue) {
|
||||
expires=atoi(expires_hdr->hvalue);
|
||||
} else {
|
||||
/* it seems the expires filed in not present everywhere... */
|
||||
|
||||
66
src/rewrite_rules.h
Normal file
66
src/rewrite_rules.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright (C) 2002 Thomas Ries <tries@gmx.net>
|
||||
|
||||
This file is part of Siproxd.
|
||||
|
||||
Siproxd is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Siproxd 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Siproxd; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* SIP Method 'knowledg base'
|
||||
* This table tells siproxd what incomming requests (which methods)
|
||||
* it shell rewite and which not. E.g. kphone behaves silly
|
||||
* if a incoming SUBSCRIBE request is rewritten to the local host...
|
||||
*/
|
||||
static struct {
|
||||
char *UAstring;
|
||||
int action[12];
|
||||
} RQ_rewrite[] =
|
||||
{
|
||||
/*
|
||||
1 means: rewrite, 0 means don't rewrite, -1 means default
|
||||
UA string I A R B O I C R N S M P
|
||||
N C E Y P N A E O U E R
|
||||
V K G E T F N F T B S A
|
||||
I I I O C E I S S C
|
||||
T S O E R F C A K
|
||||
E T N L Y R G
|
||||
*/
|
||||
{"Linphone", {-1, -1, -1, -1, -1, -1. -1, -1, -1, -1, -1, -1}},
|
||||
{"Windows RTC", {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
|
||||
{"KPhone", {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}},
|
||||
/* the following line holds the default entries */
|
||||
{NULL, { 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1}}
|
||||
};
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int size;
|
||||
} RQ_method[] = {
|
||||
{ "INVITE", 6 },
|
||||
{ "ACK", 3 },
|
||||
{ "REGISTER", 8 },
|
||||
{ "BYE", 3 },
|
||||
{ "OPTIONS", 7 },
|
||||
{ "INFO", 4 },
|
||||
{ "CANCEL", 6 },
|
||||
{ "REFER", 5 },
|
||||
{ "NOTIFY", 6 },
|
||||
{ "SUBSCRIBE", 9 },
|
||||
{ "MESSAGE", 7 },
|
||||
{ "PRACK", 5 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
@ -125,7 +125,7 @@ void *rtpproxy_main(void *arg) {
|
||||
memcpy(&fdset, &master_fdset, sizeof(fdset));
|
||||
fd_max=master_fd_max;
|
||||
|
||||
/* test */
|
||||
/* loop forever... */
|
||||
for (;;) {
|
||||
|
||||
tv.tv_sec = 5;
|
||||
@ -148,10 +148,6 @@ void *rtpproxy_main(void *arg) {
|
||||
FD_ISSET(rtp_proxytable[i].sock, &fdset) ) {
|
||||
/* yup, have some data to send */
|
||||
|
||||
/* don't... it is a mess on the screen...
|
||||
DEBUGC(DBCLASS_RTP,"got data on sock=%i",rtp_proxytable[i].sock);
|
||||
*/
|
||||
|
||||
/* read from sock rtp_proxytable[i].sock*/
|
||||
count=read(rtp_proxytable[i].sock, rtp_buff, RTP_BUFFER_SIZE);
|
||||
|
||||
@ -202,9 +198,9 @@ DEBUGC(DBCLASS_RTP,"got data on sock=%i",rtp_proxytable[i].sock);
|
||||
|
||||
|
||||
|
||||
/******
|
||||
/*
|
||||
* helper routines to control the RTP proxy thread
|
||||
******/
|
||||
*/
|
||||
|
||||
/*
|
||||
* start an rtp stream on the proxy
|
||||
|
||||
@ -35,13 +35,71 @@
|
||||
|
||||
/*
|
||||
* do security and integrity checks on the received packet
|
||||
* (raw buffer)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS if ok
|
||||
* STS_FAILURE if the packed did not pass the checks
|
||||
*/
|
||||
int security_check(char *sip_buffer, int size){
|
||||
int security_check_raw(char *sip_buffer, int size){
|
||||
|
||||
/* TODO: still way to go here ... */
|
||||
/* TODO: still way to go here ... */
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* do security and integrity checks on the received packet
|
||||
* (parsed buffer)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS if ok
|
||||
* STS_FAILURE if the packed did not pass the checks
|
||||
*/
|
||||
int security_check_sip(sip_t *sip){
|
||||
|
||||
/* check for existing SIP URI */
|
||||
if (sip->strtline == NULL) {
|
||||
ERROR("security check failed: NULL SIP URI");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing TO */
|
||||
if (sip->to == NULL) {
|
||||
ERROR("security check failed: NULL To Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing TO URL */
|
||||
if (sip->to->url == NULL) {
|
||||
ERROR("security check failed: NULL To->url Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing TO URL host*/
|
||||
if (sip->to->url->host == NULL) {
|
||||
ERROR("security check failed: NULL To->url->host Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing FROM */
|
||||
if (sip->from == NULL) {
|
||||
ERROR("security check failed: NULL From Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing FROM URL */
|
||||
if (sip->from->url == NULL) {
|
||||
ERROR("security check failed: NULL From->url Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* check for existing FROM URL host*/
|
||||
if (sip->from->url->host == NULL) {
|
||||
ERROR("security check failed: NULL From->url->host Header");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* TODO: still way to go here ... */
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
378
src/sip_utils.c
Normal file
378
src/sip_utils.c
Normal file
@ -0,0 +1,378 @@
|
||||
/*
|
||||
Copyright (C) 2002 Thomas Ries <tries@gmx.net>
|
||||
|
||||
This file is part of Siproxd.
|
||||
|
||||
Siproxd is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Siproxd 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Siproxd; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <osip/smsg.h>
|
||||
#include <osip/port.h>
|
||||
|
||||
#include "siproxd.h"
|
||||
#include "rewrite_rules.h"
|
||||
#include "log.h"
|
||||
|
||||
static char const ident[]="$Id: " __FILE__ ": " PACKAGE "-" VERSION "-"\
|
||||
BUILDSTR " $";
|
||||
|
||||
/* configuration storage */
|
||||
extern struct siproxd_config configuration;
|
||||
|
||||
extern int h_errno;
|
||||
|
||||
|
||||
/*
|
||||
* create a reply template from an given SIP request
|
||||
*
|
||||
* RETURNS a pointer to sip_t
|
||||
*/
|
||||
sip_t *msg_make_template_reply (sip_t * request, int code) {
|
||||
sip_t *response;
|
||||
char *tmp;
|
||||
int pos;
|
||||
|
||||
msg_init (&response);
|
||||
msg_setversion (response, sgetcopy ("SIP/2.0"));
|
||||
tmp = malloc(STATUSCODE_SIZE);
|
||||
snprintf (tmp, STATUSCODE_SIZE, "%i", code);
|
||||
msg_setstatuscode (response, tmp);
|
||||
msg_setreasonphrase (response, msg_getreason (code));
|
||||
|
||||
if (request->to==NULL) {
|
||||
ERROR("msg_make_template_reply: empty To in request header");
|
||||
}
|
||||
|
||||
if (request->from==NULL) {
|
||||
ERROR("msg_make_template_reply: empty From in request header");
|
||||
}
|
||||
|
||||
to_clone (request->to, &response->to);
|
||||
from_clone (request->from, &response->from);
|
||||
|
||||
|
||||
/* via headers */
|
||||
pos = 0;
|
||||
while (!list_eol (request->vias, pos)) {
|
||||
via_t *via;
|
||||
via = (via_t *) list_get (request->vias, pos);
|
||||
via_2char (via, &tmp);
|
||||
|
||||
msg_setvia (response, tmp);
|
||||
free (tmp);
|
||||
pos++;
|
||||
}
|
||||
|
||||
call_id_clone(request->call_id,&response->call_id);
|
||||
cseq_clone(request->cseq,&response->cseq);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check for a via loop.
|
||||
* It checks for the presense of a via entry that holds one of
|
||||
* my IP addresses and is *not* the topmost via.
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if loop detected
|
||||
* STS_FALSE if no loop
|
||||
*/
|
||||
int check_vialoop (sip_t *my_msg) {
|
||||
int sts;
|
||||
int pos;
|
||||
int found_own_via;
|
||||
|
||||
found_own_via=0;
|
||||
pos = 1; /* for detecting a loop, don't check the first entry
|
||||
as this is my own VIA! */
|
||||
while (!list_eol (my_msg->vias, pos)) {
|
||||
via_t *via;
|
||||
via = (via_t *) list_get (my_msg->vias, pos);
|
||||
sts = is_via_local (via);
|
||||
if (sts == STS_TRUE) found_own_via=1;
|
||||
pos++;
|
||||
}
|
||||
return (found_own_via)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check if a given via_t is local. I.e. its address is owned
|
||||
* by my inbound or outbound interface
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if the given VIA is one of my interfaces
|
||||
* STS_FALSE otherwise
|
||||
*/
|
||||
int is_via_local (via_t *via) {
|
||||
int sts, found;
|
||||
struct in_addr addr_via, addr_myself;
|
||||
char *my_interfaces[]=
|
||||
{ configuration.inbound_if, configuration.outbound_if, (char*)-1 };
|
||||
int port;
|
||||
int i;
|
||||
char *ptr;
|
||||
|
||||
if (via==NULL) {
|
||||
ERROR("called is_via_local with NULL via");
|
||||
return STS_FALSE;
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE,"via name %s",via->host);
|
||||
if (inet_aton(via->host,&addr_via) == 0) {
|
||||
/* need name resolution */
|
||||
get_ip_by_host(via->host, &addr_via);
|
||||
}
|
||||
|
||||
found=0;
|
||||
for (i=0; ; i++) {
|
||||
/*
|
||||
* try to search by interface name first
|
||||
*/
|
||||
ptr=my_interfaces[i];
|
||||
if (ptr==(char*)-1) break; /* end of list mark */
|
||||
|
||||
if (ptr) {
|
||||
DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",ptr);
|
||||
sts = get_ip_by_ifname(ptr, &addr_myself);
|
||||
}
|
||||
|
||||
/* check the extracted VIA against my own host addresses */
|
||||
if (via->port) port=atoi(via->port);
|
||||
else port=SIP_PORT;
|
||||
|
||||
if ( (memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) &&
|
||||
(port == configuration.sip_listen_port) ) {
|
||||
DEBUG("address match [%s] <-> [%s]", inet_ntoa(addr_myself),
|
||||
inet_ntoa(addr_via));
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (found)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* compares two URLs
|
||||
* (by now, only hostname and username are compared)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS if equal
|
||||
* STS_FAILURE if non equal or error
|
||||
*/
|
||||
int compare_url(url_t *url1, url_t *url2) {
|
||||
int sts;
|
||||
struct in_addr addr1, addr2;
|
||||
|
||||
/* sanity checks */
|
||||
if ((url1 == NULL) || (url2 == NULL)) {
|
||||
ERROR("compare_url: NULL ptr: url1=0x%p, url2=0x%p",url1, url2);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* sanity checks: host part is a MUST */
|
||||
if ((url1->host == NULL) || (url2->host == NULL)) {
|
||||
ERROR("compare_url: NULL ptr: url1->host=0x%p, url2->host=0x%p",
|
||||
url1->host, url2->host);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* get the IP addresses from the (possible) hostnames */
|
||||
get_ip_by_host(url1->host, &addr1);
|
||||
get_ip_by_host(url2->host, &addr2);
|
||||
|
||||
/* Broken(?) MSN messenger - does not supply a user name part.
|
||||
So we simply compare the host part then */
|
||||
if ((url1->username == NULL) || (url2->username == NULL)) {
|
||||
WARN("compare_url: NULL username pointer: MSN messenger is known to "
|
||||
"trigger this one!");
|
||||
DEBUGC(DBCLASS_DNS, "comparing broken urls (no user): "
|
||||
"%s[%s] -> %s[%s]",
|
||||
url1->host, inet_ntoa(addr1), url2->host, inet_ntoa(addr2));
|
||||
if (memcmp(&addr1, &addr2, sizeof(addr1))==0) {
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* we have a proper URL */
|
||||
/* comparison of hosts should be based on IP addresses, no? */
|
||||
DEBUGC(DBCLASS_DNS, "comparing urls: %s@%s[%s] -> %s@%s[%s]",
|
||||
url1->username, url1->host, inet_ntoa(addr1),
|
||||
url2->username, url2->host, inet_ntoa(addr2));
|
||||
if ((strcmp(url1->username, url2->username)==0) &&
|
||||
(memcmp(&addr1, &addr2, sizeof(addr1))==0)) {
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check if a given request is addressed to local. I.e. it is addressed
|
||||
* to the porxy itself (IP of my inbound or outbound interface, same port)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if the request is addressed local
|
||||
* STS_FALSE otherwise
|
||||
*/
|
||||
int is_sipuri_local (sip_t *sip) {
|
||||
int sts, found;
|
||||
struct in_addr addr_uri, addr_myself;
|
||||
char *my_interfaces[]=
|
||||
{ configuration.inbound_if, configuration.outbound_if, (char*)-1 };
|
||||
int port;
|
||||
int i;
|
||||
char *ptr;
|
||||
|
||||
if (sip==NULL) {
|
||||
ERROR("called is_sipuri_local with NULL sip");
|
||||
return STS_FALSE;
|
||||
}
|
||||
|
||||
if (!sip || !sip->strtline || !sip->strtline->rquri) {
|
||||
ERROR("is_sipuri_local: no request URI present");
|
||||
return STS_FALSE;
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_DNS,"check for local SIP URI %s:%s",
|
||||
sip->strtline->rquri->host? sip->strtline->rquri->host : "*NULL*",
|
||||
sip->strtline->rquri->port? sip->strtline->rquri->port : "*NULL*");
|
||||
|
||||
if (inet_aton(sip->strtline->rquri->host, &addr_uri) == 0) {
|
||||
/* need name resolution */
|
||||
get_ip_by_host(sip->strtline->rquri->host, &addr_uri);
|
||||
}
|
||||
|
||||
found=0;
|
||||
for (i=0; ; i++) {
|
||||
/*
|
||||
* try to search by interface name first
|
||||
*/
|
||||
ptr=my_interfaces[i];
|
||||
if (ptr==(char*)-1) break; /* end of list mark */
|
||||
|
||||
if (ptr) {
|
||||
DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",ptr);
|
||||
sts = get_ip_by_ifname(ptr, &addr_myself);
|
||||
}
|
||||
|
||||
/* check the extracted HOST against my own host addresses */
|
||||
if (sip->strtline->rquri->port) {
|
||||
port=atoi(sip->strtline->rquri->port);
|
||||
} else {
|
||||
port=SIP_PORT;
|
||||
}
|
||||
|
||||
if ( (memcmp(&addr_myself, &addr_uri, sizeof(addr_myself))==0) &&
|
||||
(port == configuration.sip_listen_port) ) {
|
||||
DEBUG("address match [%s] <-> [%s]", inet_ntoa(addr_myself),
|
||||
inet_ntoa(addr_uri));
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DEBUGC(DBCLASS_DNS, "SIP URI is %slocal", found? "":"not ");
|
||||
return (found)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check if a given request (outbound -> inbound) shall its
|
||||
* request URI get rewritten based upon our UA knowledge
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if to be rewritten
|
||||
* STS_FALSE otherwise
|
||||
*/
|
||||
int check_rewrite_rq_uri (sip_t *sip) {
|
||||
int i, j, sts;
|
||||
int dflidx;
|
||||
header_t *ua_hdr;
|
||||
|
||||
/* get index of default entry */
|
||||
dflidx=(sizeof(RQ_rewrite)/sizeof(RQ_rewrite[0])) - 1;
|
||||
|
||||
/* check fort existence of method */
|
||||
if ((sip==NULL) || (sip->strtline==NULL) ||
|
||||
(sip->strtline->sipmethod)) {
|
||||
ERROR("check_rewrite_rq_uri: got NULL method");
|
||||
return STS_FALSE;
|
||||
}
|
||||
|
||||
/* extract UA string */
|
||||
msg_getuser_agent (sip, 0, &ua_hdr);
|
||||
if ((ua_hdr==NULL) || (ua_hdr->hvalue==NULL)) {
|
||||
WARN("check_rewrite_rq_uri: NULL UA in Header, using default");
|
||||
i=dflidx;
|
||||
} else {
|
||||
/* loop through the knowledge base */
|
||||
for (i=0; RQ_rewrite[i].UAstring; i++) {
|
||||
if (strncmp(RQ_rewrite[i].UAstring, ua_hdr->hvalue,
|
||||
sizeof(RQ_rewrite[i].UAstring))==0) {
|
||||
DEBUGC(DBCLASS_SIP, "got knowledge entry for [%s]",
|
||||
ua_hdr->hvalue);
|
||||
break;
|
||||
}
|
||||
} /* for i */
|
||||
} /* if ua_hdr */
|
||||
|
||||
for (j=0; RQ_method[j].name; j++) {
|
||||
if (strncmp(RQ_method[j].name,
|
||||
sip->strtline->sipmethod, RQ_method[j].size)==0) {
|
||||
if (RQ_rewrite[i].action[j] >= 0) {
|
||||
sts = (RQ_rewrite[i].action[j])? STS_TRUE: STS_FALSE;
|
||||
} else {
|
||||
sts = (RQ_rewrite[dflidx].action[j])? STS_TRUE: STS_FALSE;
|
||||
}
|
||||
DEBUGC(DBCLASS_SIP, "check_rewrite_rq_uri: [%s/%s] got action %i",
|
||||
sip->strtline->sipmethod, ua_hdr->hvalue);
|
||||
return sts;
|
||||
}
|
||||
} /* for j */
|
||||
|
||||
WARN("check_rewrite_rq_uri: did'nt get a hit of the method [%s]",
|
||||
sip->strtline->sipmethod);
|
||||
return STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -196,7 +196,7 @@ int main (int argc, char *argv[])
|
||||
if (access == 0) continue; /* there are no resources to free */
|
||||
|
||||
/* integrity checks */
|
||||
sts=security_check(buff, i);
|
||||
sts=security_check_raw(buff, i);
|
||||
if (sts != STS_SUCCESS) continue; /* there are no resources to free */
|
||||
|
||||
/* parse the received message */
|
||||
@ -212,9 +212,14 @@ int main (int argc, char *argv[])
|
||||
goto end_loop; /* skip and free resources */
|
||||
}
|
||||
|
||||
/* integrity checks - parsed buffer*/
|
||||
sts=security_check_sip(my_msg);
|
||||
if (sts != STS_SUCCESS) continue; /* there are no resources to free */
|
||||
|
||||
DEBUGC(DBCLASS_SIP,"received SIP type %s:%s",
|
||||
(MSG_IS_REQUEST(my_msg))? "REQ" : "RES",
|
||||
my_msg->strtline->sipmethod);
|
||||
(my_msg->strtline->sipmethod)?
|
||||
my_msg->strtline->sipmethod : "NULL") ;
|
||||
|
||||
/* if RQ REGISTER, just register and send an answer */
|
||||
if (MSG_IS_REGISTER(my_msg) && MSG_IS_REQUEST(my_msg)) {
|
||||
|
||||
@ -41,15 +41,20 @@ int proxy_gen_response(sip_t *request, int code); /*X*/
|
||||
int proxy_add_myvia (sip_t *request, int interface); /*X*/
|
||||
int proxy_del_myvia (sip_t *response); /*X*/
|
||||
int proxy_rewrite_invitation_body(sip_t *mymsg); /*X*/
|
||||
int proxy_rewrite_request_uri(sip_t *mymsg, int idx); /*X*/
|
||||
|
||||
/* utils.c */
|
||||
sip_t * msg_make_template_reply (sip_t * request, int code);
|
||||
int check_vialoop (sip_t *my_msg); /*X*/
|
||||
int is_via_local (via_t *via); /*X*/
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr); /*X*/
|
||||
int compare_url(url_t *url1, url_t *url2); /*X*/
|
||||
int get_ip_by_host(char *hostname, struct in_addr *addr); /*X*/
|
||||
void secure_enviroment (void);
|
||||
int get_ip_by_ifname(char *ifname, struct in_addr *retaddr); /*X*/
|
||||
int get_ip_by_ifname(char *ifname, struct in_addr *retaddr); /*X*/
|
||||
|
||||
/* sip_utils.c */
|
||||
sip_t * msg_make_template_reply (sip_t * request, int code);
|
||||
int check_vialoop (sip_t *my_msg); /*X*/
|
||||
int is_via_local (via_t *via); /*X*/
|
||||
int compare_url(url_t *url1, url_t *url2); /*X*/
|
||||
int is_sipuri_local (sip_t *sip); /*X*/
|
||||
int check_rewrite_rq_uri (sip_t *sip); /*X*/
|
||||
|
||||
/* readconf.c */
|
||||
int read_config(char *name, int search); /*X*/
|
||||
@ -65,7 +70,8 @@ int rtp_stop_fwd (call_id_t *callid, int nolock); /*X*/
|
||||
int accesslist_check(struct sockaddr_in from);
|
||||
|
||||
/* security.c */
|
||||
int security_check(char *sip_buffer, int size); /*X*/
|
||||
int security_check_raw(char *sip_buffer, int size); /*X*/
|
||||
int security_check_sip(sip_t *sip); /*X*/
|
||||
|
||||
/* auth.c */
|
||||
int authenticate_proxy(sip_t *request); /*X*/
|
||||
@ -154,6 +160,7 @@ struct siproxd_config {
|
||||
#define STS_FALSE 1 /* FALSE */
|
||||
#define STS_NEED_AUTH 1001 /* need authentication */
|
||||
|
||||
|
||||
/*
|
||||
* optional hacks
|
||||
*/
|
||||
|
||||
@ -130,11 +130,15 @@ int sipsock_send_udp(int *sock, struct in_addr addr, int port,
|
||||
DEBUGC(DBCLASS_NET,"allocated send socket %i",*sock);
|
||||
}
|
||||
|
||||
if (buffer == NULL) {
|
||||
ERROR("sipsock_send_udp go tNULL buffer");
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
dst_addr.sin_family = AF_INET;
|
||||
memcpy(&dst_addr.sin_addr.s_addr, &addr, sizeof(struct in_addr));
|
||||
dst_addr.sin_port= htons(port);
|
||||
|
||||
|
||||
if (allowdump) {
|
||||
DEBUGC(DBCLASS_NET,"send UDP packet to %s: %i",
|
||||
inet_ntoa(addr),port);
|
||||
|
||||
184
src/utils.c
184
src/utils.c
@ -49,134 +49,6 @@ extern struct siproxd_config configuration;
|
||||
|
||||
extern int h_errno;
|
||||
|
||||
/*
|
||||
* create a reply template from an given SIP request
|
||||
*
|
||||
* RETURNS a pointer to sip_t
|
||||
*/
|
||||
sip_t *msg_make_template_reply (sip_t * request, int code) {
|
||||
sip_t *response;
|
||||
char *tmp;
|
||||
int pos;
|
||||
|
||||
msg_init (&response);
|
||||
msg_setversion (response, sgetcopy ("SIP/2.0"));
|
||||
tmp = malloc(STATUSCODE_SIZE);
|
||||
snprintf (tmp, STATUSCODE_SIZE, "%i", code);
|
||||
msg_setstatuscode (response, tmp);
|
||||
msg_setreasonphrase (response, msg_getreason (code));
|
||||
|
||||
if (request->to==NULL) {
|
||||
ERROR("msg_make_template_reply: empty To in request header");
|
||||
}
|
||||
|
||||
if (request->from==NULL) {
|
||||
ERROR("msg_make_template_reply: empty From in request header");
|
||||
}
|
||||
|
||||
to_clone (request->to, &response->to);
|
||||
from_clone (request->from, &response->from);
|
||||
|
||||
|
||||
/* via headers */
|
||||
pos = 0;
|
||||
while (!list_eol (request->vias, pos)) {
|
||||
via_t *via;
|
||||
via = (via_t *) list_get (request->vias, pos);
|
||||
via_2char (via, &tmp);
|
||||
|
||||
msg_setvia (response, tmp);
|
||||
free (tmp);
|
||||
pos++;
|
||||
}
|
||||
|
||||
call_id_clone(request->call_id,&response->call_id);
|
||||
cseq_clone(request->cseq,&response->cseq);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check for a via loop.
|
||||
* It checks for the presense of a via entry that holds one of
|
||||
* my IP addresses and is *not* the topmost via.
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if loop detected
|
||||
* STS_FALSE if no loop
|
||||
*/
|
||||
int check_vialoop (sip_t *my_msg) {
|
||||
int sts;
|
||||
int pos;
|
||||
int found_own_via;
|
||||
|
||||
found_own_via=0;
|
||||
pos = 1; /* for detecting a loop, don't check the first entry
|
||||
as this is my own VIA! */
|
||||
while (!list_eol (my_msg->vias, pos)) {
|
||||
via_t *via;
|
||||
via = (via_t *) list_get (my_msg->vias, pos);
|
||||
sts = is_via_local (via);
|
||||
if (sts == STS_TRUE) found_own_via=1;
|
||||
pos++;
|
||||
}
|
||||
return (found_own_via)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* check if a given via_t is local. I.e. its address is owned
|
||||
* by my inbound or outbound interface
|
||||
*
|
||||
* RETURNS
|
||||
* STS_TRUE if the given VIA is one of my interfaces
|
||||
* STS_FALSE otherwise
|
||||
*/
|
||||
int is_via_local (via_t *via) {
|
||||
int sts, found;
|
||||
struct in_addr addr_via, addr_myself;
|
||||
char *my_interfaces[]=
|
||||
{ configuration.inbound_if, configuration.outbound_if, (char*)-1 };
|
||||
int port;
|
||||
int i;
|
||||
char *ptr;
|
||||
|
||||
DEBUGC(DBCLASS_BABBLE,"via name %s",via->host);
|
||||
if (inet_aton(via->host,&addr_via) == 0) {
|
||||
/* need name resolution */
|
||||
get_ip_by_host(via->host, &addr_via);
|
||||
}
|
||||
|
||||
found=0;
|
||||
for (i=0; ; i++) {
|
||||
/*
|
||||
* try to search by interface name first
|
||||
*/
|
||||
ptr=my_interfaces[i];
|
||||
if (ptr==(char*)-1) break; /* end of list mark */
|
||||
|
||||
if (ptr) {
|
||||
DEBUGC(DBCLASS_BABBLE,"resolving IP of interface %s",ptr);
|
||||
sts = get_ip_by_ifname(ptr, &addr_myself);
|
||||
}
|
||||
|
||||
/* check the extracted VIA against my own host addresses */
|
||||
if (via->port) port=atoi(via->port);
|
||||
else port=SIP_PORT;
|
||||
|
||||
if ( (memcmp(&addr_myself, &addr_via, sizeof(addr_myself))==0) &&
|
||||
(port == configuration.sip_listen_port) ) {
|
||||
DEBUG("address match [%s] <-> [%s]", inet_ntoa(addr_myself),
|
||||
inet_ntoa(addr_via));
|
||||
found=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (found)? STS_TRUE : STS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* resolve a hostname and return in_addr
|
||||
@ -279,60 +151,6 @@ int get_ip_by_host(char *hostname, struct in_addr *addr) {
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* compares two URLs
|
||||
* (by now, only hostname and username are compared)
|
||||
*
|
||||
* RETURNS
|
||||
* STS_SUCCESS if equal
|
||||
* STS_FAILURE if non equal or error
|
||||
*/
|
||||
int compare_url(url_t *url1, url_t *url2) {
|
||||
int sts;
|
||||
|
||||
/* sanity checks */
|
||||
if ((url1 == NULL) || (url2 == NULL)) {
|
||||
ERROR("compare_url: NULL ptr: url1=0x%p, url2=0x%p",url1, url2);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* sanity checks: host part is a MUST */
|
||||
if ((url1->host == NULL) || (url2->host == NULL)) {
|
||||
ERROR("compare_url: NULL ptr: url1->host=0x%p, url2->host=0x%p",
|
||||
url1->host, url2->host);
|
||||
return STS_FAILURE;
|
||||
}
|
||||
|
||||
/* Broken(?) MSN messenger - does not supply a user name part.
|
||||
So we simply compare the host part then */
|
||||
if ((url1->username == NULL) || (url2->username == NULL)) {
|
||||
WARN("compare_url: NULL username pointer: MSN messenger is known to "
|
||||
"trigger this one! [url1->username=0x%p, url2->username=0x%p]",
|
||||
url1->username, url2->username);
|
||||
DEBUGC(DBCLASS_BABBLE, "comparing broken urls (no user): %s -> %s",
|
||||
url1->host, url2->host);
|
||||
if (strcmp(url1->host, url2->host)==0) {
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
return sts;
|
||||
}
|
||||
|
||||
/* we have a proper URL */
|
||||
/* comparison of hosts should be based on IP addresses, no? */
|
||||
DEBUGC(DBCLASS_BABBLE, "comparing urls: %s@%s -> %s@%s",
|
||||
url1->username, url1->host, url2->username, url2->host);
|
||||
if ((strcmp(url1->username, url2->username)==0) &&
|
||||
(strcmp(url1->host, url2->host)==0)) {
|
||||
sts = STS_SUCCESS;
|
||||
} else {
|
||||
sts = STS_FAILURE;
|
||||
}
|
||||
|
||||
return sts;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Secure enviroment:
|
||||
@ -428,3 +246,5 @@ int get_ip_by_ifname(char *ifname, struct in_addr *retaddr) {
|
||||
if (retaddr) memcpy(retaddr, &sin->sin_addr, sizeof(sin->sin_addr));
|
||||
return STS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user