# HG changeset patch # User Alexandre Westfahl # Date 1278942993 -32400 # Node ID 9cc48cd22e678666a78568b198c8d4c402166e35 # Parent 1097c885c0650d93a0fad454d9fc5432b22e0094 Finished RTR on Diameter-SIP diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/CMakeLists.txt --- a/extensions/app_sip/CMakeLists.txt Thu Jul 08 18:17:18 2010 +0900 +++ b/extensions/app_sip/CMakeLists.txt Mon Jul 12 22:56:33 2010 +0900 @@ -19,6 +19,7 @@ libdiamsip.c md5.c multimediaauth.c + registrationtermination.c ) # Compile as a module diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/diamsip.c --- a/extensions/app_sip/diamsip.c Thu Jul 08 18:17:18 2010 +0900 +++ b/extensions/app_sip/diamsip.c Mon Jul 12 22:56:33 2010 +0900 @@ -89,6 +89,7 @@ struct dict_object * app=NULL; struct disp_when data; + pthread_t rtr_thread; /* Initialize configuration */ CHECK_FCT( as_conf_init() ); @@ -114,6 +115,8 @@ //We set usefull AVPs CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Session-State", &sip_dict.Auth_Session_State, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Auth-Application-Id", &sip_dict.Auth_Application_Id, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Destination-Host", &sip_dict.Destination_Host, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Session-Id", &sip_dict.Session_Id, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Auth-Data-Item", &sip_dict.SIP_Auth_Data_Item, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authorization", &sip_dict.SIP_Authorization, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Authenticate", &sip_dict.SIP_Authenticate, ENOENT) ); @@ -123,6 +126,9 @@ CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Server-URI", &sip_dict.SIP_Server_URI, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Method", &sip_dict.SIP_Method, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-AOR", &sip_dict.SIP_AOR, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Deregistration-Reason", &sip_dict.SIP_Deregistration_Reason, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Code", &sip_dict.SIP_Reason_Code, ENOENT) ); + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "SIP-Reason-Info", &sip_dict.SIP_Reason_Info, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Realm", &sip_dict.Digest_Realm, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-URI", &sip_dict.Digest_URI, ENOENT) ); CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Digest-Nonce", &sip_dict.Digest_Nonce, ENOENT) ); @@ -163,6 +169,18 @@ CHECK_FCT(fd_sess_handler_create(&ds_sess_hdl, free)); + //Creation of thread for Registration Termination + if(pthread_create(&rtr_thread, NULL,rtr_socket, NULL)) + { + TRACE_DEBUG(INFO,"Creation of thread failed, abort!"); + return 1; + } + + + + + + return 0; } diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/diamsip.h --- a/extensions/app_sip/diamsip.h Thu Jul 08 18:17:18 2010 +0900 +++ b/extensions/app_sip/diamsip.h Mon Jul 12 22:56:33 2010 +0900 @@ -87,6 +87,22 @@ int fd_avp_search_avp ( struct avp * groupedavp, struct dict_object * what, struct avp ** avp ); +//thread procedure +void *rtr_socket(void *); + +struct rtrsipaor +{ + char username[200]; + char sip_aor1[200]; + char sip_aor2[200]; + char sip_aor3[200]; + char strreason[200]; + char desthost[200]; + int reason; +}; +int diamsip_RTR_cb(struct rtrsipaor structure); +#define PORT 666 //TODO:put in conf file + int ds_entry(); void fd_ext_fini(void); int diamsip_default_cb( struct msg ** msg, struct avp * avp, struct session * sess, enum disp_action * act); @@ -120,7 +136,9 @@ struct diamsip_dict{ struct dict_object * Auth_Session_State; struct dict_object * Auth_Application_Id; + struct dict_object * Destination_Host; struct dict_object * User_Name; + struct dict_object * Session_Id; struct dict_object * SIP_Auth_Data_Item; struct dict_object * SIP_Authorization; struct dict_object * SIP_Authenticate; @@ -130,6 +148,9 @@ struct dict_object * SIP_Server_URI; struct dict_object * SIP_Method; struct dict_object * SIP_AOR; + struct dict_object * SIP_Deregistration_Reason; + struct dict_object * SIP_Reason_Code; + struct dict_object * SIP_Reason_Info; struct dict_object * Digest_URI; struct dict_object * Digest_Nonce; struct dict_object * Digest_Nonce_Count; diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/registrationtermination.c --- a/extensions/app_sip/registrationtermination.c Thu Jul 08 18:17:18 2010 +0900 +++ b/extensions/app_sip/registrationtermination.c Mon Jul 12 22:56:33 2010 +0900 @@ -34,10 +34,235 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *********************************************************************************************************/ #include "diamsip.h" +#include +#include +#include +#include +#include +typedef int SOCKET; +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr SOCKADDR; +//Procedure which always wait for data on socket +void *rtr_socket(void *arg) +{ + SOCKET sock; + SOCKADDR_IN sin, csin; + struct rtrsipaor rtrsip; + int rcvbytes=0; + sock = socket(AF_INET, SOCK_STREAM, 0); + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + sin.sin_family = AF_INET; + sin.sin_port = htons(PORT); + socklen_t sinsize = sizeof(csin); + int accepted=0; + TRACE_DEBUG(INFO,"############********************THREAD OPEN \n********************\n********************\n"); + + if(!bind(sock, (SOCKADDR*)&sin, sizeof(sin))) + { + if(listen(sock,1)) + { + TRACE_DEBUG(INFO,"ERROR on listen!"); + } + + while(1) + { + accepted=accept(sock, (struct sockaddr *)&csin,&sinsize); + if(accepted>-1) + { + rcvbytes=recv(accepted, &rtrsip, sizeof(struct rtrsipaor),0); + + + if(rcvbytes>-1) + { + diamsip_RTR_cb(rtrsip); + + + } + } + } + + + } + else + TRACE_DEBUG(INFO,"Can't create socket!"); + + + + + + TRACE_DEBUG(INFO,"############********************THREAD CLOSED \n********************\n********************\n"); + pthread_exit(NULL); + +} +//Called to send a RTR +int diamsip_RTR_cb(struct rtrsipaor structure) +{ + TRACE_ENTRY("%p", structure); + + int got_username=0; + int got_streason=0; + int num_aor=0;//How many SIP-AOR? + struct dict_object * rtr_model=NULL; + struct msg * message=NULL; + struct avp *groupedavp=NULL, *avp=NULL; + struct session *sess=NULL; + union avp_value value; + + //We must check that we have all needed value in structure + if(structure.username[0]!='\0') + got_username=1; + + if(structure.sip_aor1[0]!='\0') + { + num_aor++; + if(structure.sip_aor2[0]!='\0') + { + num_aor++; + if(structure.sip_aor3[0]!='\0') + num_aor++; + } + } + + if(structure.strreason!='\0') + got_streason=1; + + + TRACE_DEBUG(INFO,"We have %d SIP_AOR",num_aor); + + if((got_username + num_aor)==0) + { + //We must have a least a SIP_AOR or a Username + TRACE_DEBUG(INFO,"Can not proceed because there is no SIP_AOR or Username"); + return EINVAL; + } + if(structure.reason<0) + { + //We must have a least a SIP_AOR or a Username + TRACE_DEBUG(INFO,"Incorrect Reason-Code"); + return EINVAL; + } + + if(structure.desthost[0]=='\0') + { + //We must have a least a SIP_AOR or a Username + TRACE_DEBUG(INFO,"No Destination_Host was provided!"); + return EINVAL; + } + //Create the base message for an RTR + CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Registration-Termination-Request", &rtr_model, ENOENT) ); + CHECK_FCT( fd_msg_new (rtr_model, 0, &message)); + + // Create a new session + { + CHECK_FCT( fd_sess_new( &sess, fd_g_config->cnf_diamid, "app_sip", 7 )); + char * sid; + CHECK_FCT( fd_sess_getsid ( sess, &sid )); + CHECK_FCT( fd_msg_avp_new ( sip_dict.Session_Id, 0, &avp )); + value.os.data = (uint8_t *)sid; + value.os.len = strlen(sid); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value )); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_FIRST_CHILD, avp )); + } + + + //Auth_Session_State + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Auth_Session_State, 0, &avp ) ); + value.i32=1; + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + } + + //Origin_Host & Origin_Realm + CHECK_FCT( fd_msg_add_origin ( message, 0 )); + + //Destination_Host + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.Destination_Host, 0, &avp ) ); + value.os.data=(unsigned char *)structure.desthost; + value.os.len=(size_t)strlen(structure.desthost); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + } + + + //SIP Deregistration Reason (Grouped AVP) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Deregistration_Reason, 0, &groupedavp ) ); + + //Reason Code + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Code, 0, &avp ) ); + value.i32=structure.reason; + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) ); + + if(got_streason) + { + //Reason Info + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_Reason_Info, 0, &avp ) ); + value.os.data=(unsigned char *)structure.strreason; + value.os.len=(size_t)strlen(structure.strreason); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( groupedavp, MSG_BRW_LAST_CHILD, avp ) ); + } + + //We add the grouped AVP to the message + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, groupedavp ) ); + } + + //Username + { + if(got_username) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.User_Name, 0, &avp ) ); + value.os.data=(unsigned char *)structure.username; + value.os.len=(size_t)strlen(structure.username); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + } + } + + //SIP_AOR + { + if(num_aor>0) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) ); + value.os.data=(unsigned char *)structure.sip_aor1; + value.os.len=(size_t)strlen(structure.sip_aor1); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + if(num_aor>1) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) ); + value.os.data=(unsigned char *)structure.sip_aor2; + value.os.len=(size_t)strlen(structure.sip_aor2); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + if(num_aor>2) + { + CHECK_FCT( fd_msg_avp_new ( sip_dict.SIP_AOR, 0, &avp ) ); + value.os.data=(unsigned char *)structure.sip_aor3; + value.os.len=(size_t)strlen(structure.sip_aor3); + CHECK_FCT( fd_msg_avp_setvalue( avp, &value ) ); + CHECK_FCT( fd_msg_avp_add( message, MSG_BRW_LAST_CHILD, avp ) ); + } + } + } + } + + fd_msg_dump_walk(INFO,message); + CHECK_FCT( fd_msg_send( &message, NULL, NULL )); + + return 0; +} + +//Called when an RTA arrive int diamsip_RTA_cb( struct msg ** msg, struct avp * paramavp, struct session * sess, enum disp_action * act) { + //TODO: RTA reception +/* //TODO:remove unused variables struct msg *ans, *qry; struct avp *avp, *a2, *authdataitem; @@ -60,13 +285,13 @@ return EINVAL; - /* Create answer header */ + // Create answer header qry = *msg; CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) ); ans = *msg; - /* Add the Auth-Session-State AVP */ + // Add the Auth-Session-State AVP { CHECK_FCT( fd_msg_search_avp ( qry, sip_dict.Auth_Session_State, &avp) ); @@ -92,7 +317,8 @@ + */ + return 0; - return 0; } diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/rtrsipaor Binary file extensions/app_sip/rtrsipaor has changed diff -r 1097c885c065 -r 9cc48cd22e67 extensions/app_sip/rtrsipaor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extensions/app_sip/rtrsipaor.c Mon Jul 12 22:56:33 2010 +0900 @@ -0,0 +1,290 @@ +/********************************************************************************************************* +* Software License Agreement (BSD License) * +* Author: Alexandre Westfahl * +* * +* Copyright (c) 2010, Alexandre Westfahl, Teraoka Laboratory (Keio University), and the WIDE Project. * +* * +* All rights reserved. * +* * +* Redistribution and use of this software in source and binary forms, with or without modification, are * +* permitted provided that the following conditions are met: * +* * +* * Redistributions of source code must retain the above * +* copyright notice, this list of conditions and the * +* following disclaimer. * +* * +* * Redistributions in binary form must reproduce the above * +* copyright notice, this list of conditions and the * +* following disclaimer in the documentation and/or other * +* materials provided with the distribution. * +* * +* * Neither the name of the Teraoka Laboratory nor the * +* names of its contributors may be used to endorse or * +* promote products derived from this software without * +* specific prior written permission of Teraoka Laboratory * +* * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * +* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * +* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +*********************************************************************************************************/ + + +// This file is separated from the source code because it is a separate command which will call registration termination function in Diameter-SIP +#include +#include +#include +#include +#include +typedef int SOCKET; +typedef struct sockaddr_in SOCKADDR_IN; +typedef struct sockaddr SOCKADDR; +#include +#include +#include +#define PORT 666 +#include + +struct rtrsipaor +{ + char username[200]; + char sip_aor1[200]; + char sip_aor2[200]; + char sip_aor3[200]; + char strreason[200]; + char desthost[200]; + int reason; +}; + +int main (int argc, char **argv) +{ + SOCKET sock; + SOCKADDR_IN sin; + struct rtrsipaor rtrsip; + int numaor=0,i=0; + + sock = socket(AF_INET, SOCK_STREAM, 0); + sin.sin_addr.s_addr = inet_addr("127.0.0.1"); + sin.sin_family = AF_INET; + sin.sin_port = htons(PORT); + + //We initialize the structure + rtrsip.username[0]='\0'; + rtrsip.sip_aor1[0]='\0'; + rtrsip.sip_aor2[0]='\0'; + rtrsip.sip_aor3[0]='\0'; + rtrsip.strreason[0]='\0'; + rtrsip.desthost[0]='\0'; + rtrsip.reason=-1; + + + //Start of arguments check + if(argc<3) + { + fprintf(stderr,"Missing arguments! You must at least provide a username.\n"); + return 1; + } + + + for (i=1;i199) + { + fprintf(stderr,"SIP-AOR is too long!\n"); + } + else if(strncmp(argv[i],"sip",3)!=0) + { + //Bad format of SIP-AOR + fprintf(stderr,"A SIP-AOR must start by 'sip:' or 'sips:'. Aborting...\n"); + return 1; + } + else + { + if(numaor<3) + { + switch(numaor) + { + case 0: + strcpy(rtrsip.sip_aor1,argv[i]); + break; + case 1: + strcpy(rtrsip.sip_aor2,argv[i]); + break; + case 2: + strcpy(rtrsip.sip_aor3,argv[i]); + break; + } + numaor++; + } + else + { + fprintf(stderr,"You can not provide more than 3 SIP-AOR at the same time!\n"); + break; + } + } + i=j+1; + } + else + { + //We have a new argument + i--; + break; + } + } + } + else if(strcmp(argv[i],"-r")==0) + { + + if(strlen(argv[i+1])>199) + { + fprintf(stderr,"Deregistration reason is too long!\n"); + } + else + { + strcpy(rtrsip.strreason,argv[i+1]); + } + i++; + } + else if(strcmp(argv[i],"-h")==0) + { + //Remote SIP Server + if(strlen(argv[i+1])>199) + { + fprintf(stderr,"Host is too long!\n"); + } + else if(strlen(argv[i+1])<5) + { + fprintf(stderr,"Host is too short!\n"); + } + else + { + strcpy(rtrsip.desthost,argv[i+1]); + } + i++; + } + else if(strcmp(argv[i],"-pt")==0) + { + //Permanent Termination + rtrsip.reason=0; + } + else if(strcmp(argv[i],"-nssa")==0) + { + //New SIP Server Assigned + rtrsip.reason=1; + } + else if(strcmp(argv[i],"-ssc")==0) + { + //SIP Server Change + rtrsip.reason=2; + } + else if(strcmp(argv[i],"-rss")==0) + { + //Remote SIP Server + rtrsip.reason=3; + } + else + { + fprintf(stderr,"Unknown argument: %s\n",argv[i]); + } + } + else + { + fprintf(stderr,"Unknown argument: %s\n",argv[i]); + i++; + } + + } + + //If no SIP-AOR provided, we remove all + if(numaor<1) + { + fprintf(stderr,"All SIP-AOR of %s will be deregistrated.\n",rtrsip.username); + } + + //We want a username + if(strlen(rtrsip.username)==0) + { + fprintf(stderr,"You must provide a username!\n"); + return 1; + } + + if(rtrsip.desthost[0]=='\0') + { + fprintf(stderr,"You must provide the hostname of SIP-Server!\n"); + return 1; + } + + + + + /* + fprintf(stderr,"*%s*\n",rtrsip.username); + fprintf(stderr,"*%s*\n",rtrsip.sip_aor1); + fprintf(stderr,"*%s*\n",rtrsip.sip_aor2); + fprintf(stderr,"*%s*\n",rtrsip.sip_aor3); + fprintf(stderr,"*%d*\n",rtrsip.reason); + fprintf(stderr,"*%s*\n",rtrsip.strreason); + + //return 0; + */ + + + //TODO: check args + if(!connect(sock, (SOCKADDR*)&sin, sizeof(sin))) + { + fprintf(stderr,"Connexion succeed!\n"); + + + if(send(sock, &rtrsip, sizeof(struct rtrsipaor), 0)) + fprintf(stderr,"sent OK!\n"); + else + fprintf(stderr,"not sent\n"); + + } + else + { + fprintf(stderr,"Unable to connect\n"); + } + + close(sock); + + return 0; +} + + + + + +