diff --git a/ChangeLog b/ChangeLog index 9f75b9f..100d55d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +0.5.3 +===== + 31-Jan-2004: - Allow 2 of my vias in header to let 2 UA's sitting + behind the same siproxd to have conversation together + UA1 -->--\ /-->--\ + siproxd Registrar + UA2 --<--/ \--<--/ + - Redone code for evaluation if a received packet + if coming from inbound or outbound interface + - RTP stream are now identified by call_id AND + USERNAME of the contact header. This provides + support for RTP proxying between 2 UAs sitting on the + inbound network. -> Calls between local UAs going via + siproxd should now work. + UA1 -->--\ + siproxd + UA2 --<--/ + - Rewriting of SUBSCRIBE should now work. + - Removed obsolete prototypes from rtpproxy.h + - If the RTP stream in one direction is found to be + stopped (sendto()) also stop the opposite direction + 0.5.2 ===== 30-Jan-2004: - If RTP proxy is disabled, don't rewrite incomming diff --git a/src/proxy.c b/src/proxy.c index bc90c8c..d676731 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -77,7 +77,7 @@ extern int sip_socket; /* sending SIP datagrams */ * 10. Forward the new request * 11. Set timer C */ -int proxy_request (osip_message_t *request) { +int proxy_request (osip_message_t *request, struct sockaddr_in *from) { int i; int sts; int type; @@ -160,6 +160,8 @@ int proxy_request (osip_message_t *request) { * figure out whether this is an incoming or outgoing request * by doing a lookup in the registration table. */ +#define _OLD_DIRECTION_EVALUATION 0 +#if _OLD_DIRECTION_EVALUATION type = 0; for (i=0; i it must be an OUTGOING request + */ + for (i=0; ihost, &tmp_addr) == STS_FAILURE) { + DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve host [%s]", + urlmap[i].true_url); + } else { + DEBUGC(DBCLASS_PROXY, "proxy_request: reghost:%s ip:%s", + urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); + if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) { + type=REQTYP_OUTGOING; + break; + } + } + } + + /* + * is the telegram directed to an internal registered host? + * -> it must be an INCOMING request + */ + if (type == 0) for (i=0; ito->url, urlmap[i].masq_url)==STS_SUCCESS) || + (!MSG_IS_REGISTER(request) && + (compare_url(request->to->url, urlmap[i].reg_url)==STS_SUCCESS))) { + type=REQTYP_INCOMING; + break; + } + } +#endif /* @@ -224,7 +264,7 @@ int proxy_request (osip_message_t *request) { if (configuration.log_calls) { osip_uri_t *cont_url = NULL; if (!osip_list_eol(request->contacts, 0)) - cont_url = ((osip_contact_t*)(request->contacts->node->element))->url; + cont_url = ((osip_contact_t*)(request->contacts->node->element))->url; /* INVITE */ if (MSG_IS_INVITE(request)) { @@ -267,6 +307,10 @@ int proxy_request (osip_message_t *request) { * from an external host to the internal masqueraded host */ case REQTYP_INCOMING: + DEBUGC(DBCLASS_PROXY,"incoming request from %s@%s from outbound", + request->from->url->username? request->from->url->username:"*NULL*", + request->from->url->host? request->from->url->host: "*NULL*"); + /* * RFC 3261, Section 16.6 step 2 * Proxy Behavior - Request Forwarding - Request-URI @@ -313,6 +357,10 @@ int proxy_request (osip_message_t *request) { * from the internal masqueraded host to an external host */ case REQTYP_OUTGOING: + DEBUGC(DBCLASS_PROXY,"outgoing request from %s@%s from inbound", + request->from->url->username? request->from->url->username:"*NULL*", + request->from->url->host? request->from->url->host: "*NULL*"); + /* * RFC 3261, Section 16.6 step 2 * Proxy Behavior - Request Forwarding - Request-URI @@ -322,6 +370,7 @@ int proxy_request (osip_message_t *request) { /* if it is addressed to myself, then it must be some request * method that I as a proxy do not support. Reject */ +#if 0 if (is_sipuri_local(request) == STS_TRUE) { WARN("unsupported request [%s] directed to proxy from %s@%s -> %s@%s", request->sip_method? request->sip_method:"*NULL*", @@ -334,6 +383,7 @@ int proxy_request (osip_message_t *request) { return STS_FAILURE; } +#endif /* if an INVITE, rewrite body */ if (MSG_IS_INVITE(request)) { @@ -355,6 +405,7 @@ int proxy_request (osip_message_t *request) { /* if this is CANCEL/BYE request, stop RTP proxying */ if (MSG_IS_BYE(request) || MSG_IS_CANCEL(request)) { + /* stop the RTP proxying stream(s) */ rtp_stop_fwd(osip_message_get_call_id(request), DIR_INCOMING); rtp_stop_fwd(osip_message_get_call_id(request), DIR_OUTGOING); } @@ -457,7 +508,7 @@ int proxy_request (osip_message_t *request) { * STS_SUCCESS on success * STS_FAILURE on error */ -int proxy_response (osip_message_t *response) { +int proxy_response (osip_message_t *response, struct sockaddr_in *from) { int i; int sts; int type; @@ -493,6 +544,7 @@ int proxy_response (osip_message_t *response) { * they are swapped in their meaning for a response... */ +#if _OLD_DIRECTION_EVALUATION type = 0; for (i=0; i it must be an OUTGOING response + */ + for (i=0; ihost, &tmp_addr) == STS_FAILURE) { + DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve host [%s]", + urlmap[i].true_url); + } else { + DEBUGC(DBCLASS_PROXY, "proxy_request: reghost:%s ip:%s", + urlmap[i].true_url->host, utils_inet_ntoa(from->sin_addr)); + if (memcmp(&tmp_addr, &from->sin_addr, sizeof(tmp_addr)) == 0) { + type=RESTYP_OUTGOING; + break; + } + } + } + /* + * is the telegram directed to an internal registered host? + * -> it must be an INCOMING response + */ + if (type == 0) for (i=0; ifrom->url, urlmap[i].reg_url)==STS_SUCCESS) || + (compare_url(response->from->url, urlmap[i].masq_url)==STS_SUCCESS)) { + type=RESTYP_INCOMING; + break; + } + } +#endif /* @@ -529,6 +617,10 @@ int proxy_response (osip_message_t *response) { * from an external host to the internal masqueraded host */ case RESTYP_INCOMING: + DEBUGC(DBCLASS_PROXY,"incoming response for %s@%s from outbound", + response->from->url->username? response->from->url->username:"*NULL*", + response->from->url->host? response->from->url->host : "*NULL*"); + if ((MSG_IS_RESPONSE_FOR(response,"INVITE")) && ((MSG_TEST_CODE(response, 200)) || (MSG_TEST_CODE(response, 183)))) { @@ -554,6 +646,12 @@ int proxy_response (osip_message_t *response) { * from the internal masqueraded host to an external host */ case RESTYP_OUTGOING: + DEBUGC(DBCLASS_PROXY,"outgoing response for %s@%s from inbound", + response->from->url->username ? + response->from->url->username : "*NULL*", + response->from->url->host ? + response->from->url->host : "*NULL*"); + #define satoi atoi /* used in MSG_TEST_CODE macro ... */ /* If an 200 OK or 183 Trying answer to an INVITE request, * rewrite body */ @@ -762,7 +860,15 @@ if (configuration.debuglevel) msg_port=atoi(sdp_message_m_port_get(sdp, media_stream_no)); if (msg_port > 0) { - rtp_start_fwd(osip_message_get_call_id(mymsg), direction, + osip_uri_t *cont_url = NULL; + char *user=NULL; + if (!osip_list_eol(mymsg->contacts, 0)) + cont_url = ((osip_contact_t*)(mymsg->contacts->node->element))->url; + if (cont_url) user=cont_url->username; + + rtp_start_fwd(osip_message_get_call_id(mymsg), + user, + direction, media_stream_no, map_addr, &map_port, msg_addr, msg_port); @@ -837,6 +943,11 @@ int proxy_rewrite_request_uri(osip_message_t *mymsg, int idx){ char *port; osip_uri_t *url; + if ((idx >= URLMAP_SIZE) || (idx < 0)) { + WARN("proxy_rewrite_request_uri: called with invalid index"); + return STS_FAILURE; + } + DEBUGC(DBCLASS_PROXY,"rewriting incoming Request URI"); url=osip_message_get_uri(mymsg); diff --git a/src/register.c b/src/register.c index 0125e4e..0190826 100644 --- a/src/register.c +++ b/src/register.c @@ -104,6 +104,7 @@ void register_init(void) { R(urlmap[i].reg_url->port); } } + fclose(stream); } } return; diff --git a/src/rewrite_rules.h b/src/rewrite_rules.h index 6ee0087..d8e840f 100644 --- a/src/rewrite_rules.h +++ b/src/rewrite_rules.h @@ -43,7 +43,7 @@ static struct { {"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, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1}} +{NULL, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}} }; static struct { diff --git a/src/rtpproxy.c b/src/rtpproxy.c index ed3b686..9cabb3e 100644 --- a/src/rtpproxy.c +++ b/src/rtpproxy.c @@ -64,8 +64,8 @@ int rtpproxy_init( void ) { * STS_SUCCESS on success * STS_FAILURE on error */ -int rtp_start_fwd (osip_call_id_t *callid, int direction, - int media_stream_no, +int rtp_start_fwd (osip_call_id_t *callid, char *client_id, + int direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, int remote_port) { int sts=STS_FAILURE; @@ -73,9 +73,10 @@ int rtp_start_fwd (osip_call_id_t *callid, int direction, if (configuration.rtp_proxy_enable == 0) { sts = STS_SUCCESS; } else if (configuration.rtp_proxy_enable == 1) { // Relay - sts = rtp_relay_start_fwd (callid, direction, media_stream_no, - local_ipaddr, local_port, - remote_ipaddr, remote_port); + sts = rtp_relay_start_fwd (callid, client_id, + direction, media_stream_no, + local_ipaddr, local_port, + remote_ipaddr, remote_port); } else { ERROR("CONFIG: rtp_proxy_enable has invalid value", configuration.rtp_proxy_enable); diff --git a/src/rtpproxy.h b/src/rtpproxy.h index 2776176..716ae3a 100644 --- a/src/rtpproxy.h +++ b/src/rtpproxy.h @@ -26,6 +26,7 @@ typedef struct { int rtp_tx_sock; /* tx socket */ char callid_number[CALLIDNUM_SIZE]; /* call ID */ char callid_host[CALLIDHOST_SIZE]; /* --"-- */ + char client_id[USERNAME_SIZE]; int direction; /* Direction of RTP stream */ int media_stream_no; struct in_addr local_ipaddr; /* local IP */ @@ -39,35 +40,8 @@ typedef struct { * RTP relay */ int rtp_relay_init(void); -int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, - int media_stream_no, +int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, + int direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, int remote_port); int rtp_relay_stop_fwd (osip_call_id_t *callid, int direction, int nolock); - - -/* - * RTP masquerading - */ -int rtp_masq_init(void); -int rtp_masq_start_fwd (osip_call_id_t *callid, int direction, - int media_stream_no, - struct in_addr local_ipaddr, int *local_port, - struct in_addr remote_ipaddr, int remote_port); -int rtp_masq_stop_fwd (osip_call_id_t *callid, int direction); - -/* - * RTP masquerading (ipchains part) - */ -int rtp_mchains_create (struct in_addr lcl_addr, int lcl_port, - struct in_addr msq_addr, int msq_port); -int rtp_mchains_delete (struct in_addr lcl_addr, int lcl_port, - struct in_addr msq_addr, int msq_port); - -/* - * RTP masquerading (netfilter part) - */ -int rtp_mnetfltr_create (struct in_addr lcl_addr, int lcl_port, - struct in_addr msq_addr, int msq_port); -int rtp_mnetfltr_delete (struct in_addr lcl_addr, int lcl_port, - struct in_addr msq_addr, int msq_port); diff --git a/src/rtpproxy_relay.c b/src/rtpproxy_relay.c index 5177765..d864d7c 100644 --- a/src/rtpproxy_relay.c +++ b/src/rtpproxy_relay.c @@ -155,6 +155,9 @@ static void *rtpproxy_main(void *arg) { /* read from sock rtp_proxytable[i].sock*/ count=read(rtp_proxytable[i].rtp_rx_sock, rtp_buff, RTP_BUFFER_SIZE); +#if 0 +/* looks like for some reason sometimes the socket + is not yet ready (right after start of rtp stream) */ if (count<0) { int j; WARN("read() [fd=%i, %s:%i] returned error [%s]", @@ -162,14 +165,19 @@ static void *rtpproxy_main(void *arg) { utils_inet_ntoa(rtp_proxytable[i].local_ipaddr), rtp_proxytable[i].local_port, strerror(errno)); for (j=0; j 0) @@ -206,6 +214,18 @@ static void *rtpproxy_main(void *arg) { rtp_proxytable[i].remote_ipaddr, rtp_proxytable[i].remote_port, rtp_buff, count, 0); /* don't dump it */ + + if (sts != STS_SUCCESS) { + /* if sendto() fails with bad filedescriptor, + * this means that the opposite stream has been + * canceled or timed out. + * we should then cancel this stream as well.*/ + + WARN("stopping opposite stream"); + /* don't lock the mutex, as we own the lock */ + rtp_relay_stop_fwd(&callid, + rtp_proxytable[i].direction, 1); + } } } /* count > 0 */ @@ -259,7 +279,8 @@ static void *rtpproxy_main(void *arg) { * STS_SUCCESS on success * STS_FAILURE on error */ -int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, +int rtp_relay_start_fwd (osip_call_id_t *callid, char *client_id, + int direction, int media_stream_no, struct in_addr local_ipaddr, int *local_port, struct in_addr remote_ipaddr, int remote_port) { @@ -268,12 +289,17 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, int freeidx; int sts=STS_SUCCESS; osip_call_id_t cid; + if (callid == NULL) { ERROR("rtp_relay_start_fwd: callid is NULL!"); return STS_FAILURE; } + if (client_id == NULL) { + ERROR("rtp_relay_start_fwd: contact header is NULL!"); + return STS_FAILURE; + } /* * life insurance: check size of received call_id strings @@ -293,6 +319,12 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, strlen(callid->host),CALLIDHOST_SIZE); return STS_FAILURE; } + if (client_id && strlen(client_id) > USERNAME_SIZE) { + ERROR("rtp_relay_start_fwd: received contact user " + "has too many characters (%i, max=%i)", + strlen(client_id),USERNAME_SIZE); + return STS_FAILURE; + } DEBUGC(DBCLASS_RTP,"rtp_relay_start_fwd: starting RTP proxy " "stream for: %s@%s (%s) #=%i", @@ -314,9 +346,9 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, /* * figure out, if this is an request to start an RTP proxy stream - * that is already existing (identified by SIP Call-ID, direction and - * media_stream_no). This can be due to UDP repetitions of the - * INVITE request... + * that is already existing (identified by SIP Call-ID, direction, + * media_stream_no and some other client unique thing). + * This can be due to UDP repetitions of the INVITE request... */ for (i=0; i RTP port pool fully allocated */ if ((port == 0) || (sock == 0)) { @@ -415,6 +450,12 @@ int rtp_relay_start_fwd (osip_call_id_t *callid, int direction, rtp_proxytable[freeidx].callid_host[0]='\0'; } + if (client_id) { + strcpy(rtp_proxytable[freeidx].client_id, client_id); + } else { + rtp_proxytable[freeidx].client_id[0]='\0'; + } + rtp_proxytable[freeidx].direction = direction; rtp_proxytable[freeidx].media_stream_no = media_stream_no; memcpy(&rtp_proxytable[freeidx].local_ipaddr, @@ -450,8 +491,8 @@ unlock_and_exit: * STS_SUCCESS on success * STS_FAILURE on error */ -int rtp_relay_stop_fwd (osip_call_id_t *callid, int direction, - int nolock) { +int rtp_relay_stop_fwd (osip_call_id_t *callid, + int direction, int nolock) { int i, sts; int retsts=STS_SUCCESS; int got_match=0; diff --git a/src/sip_utils.c b/src/sip_utils.c index 92a2d6f..6115902 100644 --- a/src/sip_utils.c +++ b/src/sip_utils.c @@ -124,8 +124,10 @@ int check_vialoop (osip_message_t *my_msg) { 3) What happens if we have 'clashes' with private addresses?? From that point of view, siproxd *should* not try to - check against it's local IF addresses if thei are private. + check against it's local IF addresses if they are private. this then of course again can lead to a endless loop... + -> Use a fixed unique part of branch parameter to identify that it + is MY via can we use something like a Tag in via headers?? (a veriy likely to-be-unique ID) @@ -142,10 +144,21 @@ int check_vialoop (osip_message_t *my_msg) { osip_via_t *via; via = (osip_via_t *) osip_list_get (my_msg->vias, pos); sts = is_via_local (via); - if (sts == STS_TRUE) found_own_via=1; + if (sts == STS_TRUE) found_own_via+=1; pos++; } - return (found_own_via)? STS_TRUE : STS_FALSE; + + /* + * what happens if a message is coming back to me legally? + * UA1 -->--\ /-->--\ + * siproxd Registrar + * UA2 --<--/ \--<--/ + * + * This may also lead to a VIA loop - so I probably must take the branch + * parameter into count (or a unique part of it) OR just allow at least 2 + * vias of my own. + */ + return (found_own_via>2)? STS_TRUE : STS_FALSE; } diff --git a/src/siproxd.c b/src/siproxd.c index 51292c1..13115f0 100644 --- a/src/siproxd.c +++ b/src/siproxd.c @@ -355,7 +355,7 @@ int main (int argc, char *argv[]) /* I'm just the outbound proxy */ DEBUGC(DBCLASS_SIP,"proxying REGISTER request to:%s",url->host); sts = register_client(my_msg, 1); - sts = proxy_request(my_msg); + sts = proxy_request(my_msg, &from); } } else { WARN("non-authorized registration attempt from %s", @@ -382,7 +382,7 @@ int main (int argc, char *argv[]) */ } else if (MSG_IS_REQUEST(my_msg)) { if (access & ACCESSCTL_SIP) { - sts = proxy_request(my_msg); + sts = proxy_request(my_msg, &from); } else { INFO("non-authorized request received from %s", utils_inet_ntoa(from.sin_addr)); @@ -394,7 +394,7 @@ int main (int argc, char *argv[]) */ } else if (MSG_IS_RESPONSE(my_msg)) { if (access & ACCESSCTL_SIP) { - sts = proxy_response(my_msg); + sts = proxy_response(my_msg, &from); } else { INFO("non-authorized response received from %s", utils_inet_ntoa(from.sin_addr)); diff --git a/src/siproxd.h b/src/siproxd.h index 18badb0..d8f52e9 100644 --- a/src/siproxd.h +++ b/src/siproxd.h @@ -41,8 +41,8 @@ void register_agemap(void); int register_response(osip_message_t *request, int flag); /*X*/ /* proxy.c */ -int proxy_request (osip_message_t *request); /*X*/ -int proxy_response (osip_message_t *response); /*X*/ +int proxy_request (osip_message_t *request, struct sockaddr_in *from); /*X*/ +int proxy_response (osip_message_t *response, struct sockaddr_in *from);/*X*/ int proxy_rewrite_invitation_body(osip_message_t *m, int direction); /*X*/ int proxy_rewrite_request_uri(osip_message_t *mymsg, int idx); /*X*/ @@ -74,11 +74,11 @@ int read_config(char *name, int search); /*X*/ /* rtpproxy.c */ int rtpproxy_init( void ); /*X*/ -int rtp_start_fwd (osip_call_id_t *callid, int direction, /*X*/ - int media_stream_no, +int rtp_start_fwd (osip_call_id_t *callid, char *client_id, /*X*/ + int direction, int media_stream_no, struct in_addr outbound_ipaddr, int *outboundport, struct in_addr lcl_client_ipaddr, int lcl_clientport); -int rtp_stop_fwd (osip_call_id_t *callid, int direction); /*X*/ +int rtp_stop_fwd (osip_call_id_t *callid, int direction); /*X*/ void rtpproxy_kill( void ); /*X*/ /* accessctl.c */ @@ -104,7 +104,6 @@ struct urlmap_s { osip_uri_t *true_url; // true URL of UA (inbound URL) osip_uri_t *masq_url; // masqueraded URL (outbound URL) osip_uri_t *reg_url; // registered URL (masq URL as wished by UA) -// osip_via_t *via; }; /* * the difference between masq_url and reg_url is,