mod.c

Go to the documentation of this file.
00001 
00055 #include <stdio.h>
00056 #include <string.h>
00057 #include <sys/stat.h>
00058 #include <unistd.h>
00059 #include <fcntl.h>
00060 #include <signal.h>
00061 
00062 #include "mod.h"
00063 #include "../tm/tm_load.h"
00064 #include "../scscf/scscf_load.h"
00065 
00066 #include "sip.h"
00067 #include "checker.h"
00068 #include "mark.h"
00069 #include "isc.h"
00070 #include "third_party_reg.h"
00071 #include "ims_pm.h"
00072 #include "../../dset.h"
00073 
00074 MODULE_VERSION
00075 
00076 static int isc_init( void );
00077 static int isc_child_init( int rank );
00078 static int isc_destroy( void );
00079 
00080 int isc_appserver_forward(struct sip_msg *msg,char *str1,char *str2 );
00081 
00082 int ISC_match_filter(struct sip_msg *msg,char *str1,char *str2);
00083 int ISC_match_filter_reg(struct sip_msg *msg,char *str1,char *str2);
00084 int ISC_from_AS(struct sip_msg *msg,char *str1,char *str2);
00085 int ISC_is_session_continued(struct sip_msg *msg,char *str1,char *str2);
00086 
00091 char *isc_my_uri_c = "scscf.open-ims.test:6060";                
00092 str isc_my_uri={0,0};               
00093 str isc_my_uri_sip={0,0};           
00094 int isc_fr_timeout=5000;            
00095 int isc_fr_inv_timeout=20000;       
00096 int isc_expires_grace=120;          
00099 #ifdef WITH_IMS_PM
00100 
00101     char* ims_pm_node_type="S-CSCF.ISC";
00102     char* ims_pm_logfile="/opt/OpenIMSCore/default_ims_pm.log";
00103 #endif /* WITH_IMS_PM */
00104 
00105 
00110 struct tm_binds isc_tmb;            
00111 struct scscf_binds isc_scscfb;      
00125 static cmd_export_t isc_cmds[] = {
00126     {"isc_appserver_forward",   isc_appserver_forward,      2, 0, REQUEST_ROUTE},   
00127     
00128     {"ISC_match_filter",        ISC_match_filter,           1, 0, REQUEST_ROUTE|FAILURE_ROUTE},
00129     {"ISC_match_filter_reg",    ISC_match_filter_reg,       1, 0, REQUEST_ROUTE},
00130     {"ISC_from_AS",             ISC_from_AS,                1, 0, REQUEST_ROUTE|FAILURE_ROUTE},
00131     {"ISC_is_session_continued",ISC_is_session_continued,   0, 0, FAILURE_ROUTE},
00132     
00133     { 0, 0, 0, 0, 0 }
00134 };
00135 
00136 
00144 static param_export_t isc_params[] = {
00145     {"my_uri",              STR_PARAM, &isc_my_uri_c},      
00147     {"isc_fr_timeout",      INT_PARAM, &isc_fr_timeout},    
00151     {"isc_fr_inv_timeout",  INT_PARAM, &isc_fr_timeout},    
00155     {"expires_grace",       INT_PARAM, & isc_expires_grace},
00157 #ifdef WITH_IMS_PM
00158     {"ims_pm_node_type",                STR_PARAM, &ims_pm_node_type},
00159     {"ims_pm_logfile",                  STR_PARAM, &ims_pm_logfile},
00160 #endif /* WITH_IMS_PM */
00161                                          
00162     { 0, 0, 0 }
00163 };
00164 
00165 
00169 struct module_exports exports = {
00170     "isc",
00171     isc_cmds,                       
00172     0,
00173     isc_params,                     
00174     isc_init,                   
00175     (response_function) 0,
00176     (destroy_function) isc_destroy,
00177     0,
00178     (child_init_function) isc_child_init 
00179 };
00180 
00181 
00182 
00183 
00188 static int isc_init( void )
00189 {
00190     load_tm_f load_tm;
00191     load_scscf_f load_scscf;
00192     LOG( L_INFO, "INFO:"M_NAME": - init\n" );
00193 
00194     /* import the TM auto-loading function */
00195     if (!(load_tm = (load_tm_f)find_export("load_tm",NO_SCRIPT,0))) {
00196         LOG(L_ERR,"ERROR:"M_NAME":isc_init: cannot import load_tm\n");
00197         goto error;
00198     }
00199     /* let the auto-loading function load all TM stuff */
00200     if (load_tm(&isc_tmb) == -1)
00201         goto error;
00202 
00203     /* import the SCSCF auto-loading function */
00204     if (!(load_scscf = (load_scscf_f)find_export("load_scscf",NO_SCRIPT,0))) {
00205         LOG(L_ERR,"ERROR:"M_NAME":isc_init: cannot import load_scscf\n");
00206         goto error;
00207     }
00208     /* let the auto-loading function load all TM stuff */
00209     if (load_scscf(&isc_scscfb) == -1)
00210         goto error;
00211 
00212     /* Init the isc_my_uri parameter */
00213     if (!isc_my_uri_c) {
00214         LOG( L_CRIT, "ERROR:"M_NAME":isc_init: mandatory parameter \"isc_my_uri\" found empty\n" );
00215         goto error;
00216     }
00217     isc_my_uri.s = isc_my_uri_c;
00218     isc_my_uri.len = strlen(isc_my_uri_c);  
00219     isc_my_uri_sip.len = 4+isc_my_uri.len;
00220     isc_my_uri_sip.s = shm_malloc(isc_my_uri_sip.len+1);    
00221     memcpy(isc_my_uri_sip.s,"sip:",4);
00222     memcpy(isc_my_uri_sip.s+4,isc_my_uri.s,isc_my_uri.len); 
00223     isc_my_uri_sip.s[isc_my_uri_sip.len]=0; 
00224 
00225     #ifdef WITH_IMS_PM
00226         ims_pm_init(isc_my_uri_sip,ims_pm_node_type, ims_pm_logfile);
00227     #endif /* WITH_IMS_PM */
00228 
00229     return 0;
00230 error:
00231     return -1;
00232 }
00233 
00234 
00239 static int isc_child_init( int rank )
00240 {
00241     LOG( L_INFO, "INFO:"M_NAME": - child init [%d]\n", rank );
00242 
00243 /* don't do anything for main process and TCP manager process */
00244     if ( rank == PROC_MAIN || rank == PROC_TCP_MAIN )
00245         return 0;
00246 
00247     // also nothing for the rest of processes
00248     return 0;
00249 }
00250 
00251 
00256 static int isc_destroy( void )
00257 {
00258     LOG( L_INFO, "INFO:"M_NAME": - child exit\n" );
00259     
00260     #ifdef WITH_IMS_PM
00261         ims_pm_destroy();   
00262     #endif /* WITH_IMS_PM */    
00263     return 0;   
00264 }
00265 
00266 
00267 
00268 
00269 
00270 
00281 int isc_appserver_forward(struct sip_msg *msg,char *str1,char *str2 )
00282 {
00283     struct hdr_field *last,*hdr;
00284     struct lump* anchor;
00285     str header_mark;
00286     rr_t *rr;
00287 
00288     LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Forward-back request reached\n");
00289     parse_headers(msg,HDR_EOH_F,0);
00290     last = msg->headers;
00291     while(last->next)
00292         last = last->next;
00293 
00294     LOG(L_INFO,"INFO:"M_NAME":isc_appserver_forward: New header: [%s]\n%.*s",str2,msg->len,msg->buf);
00295     
00296     /* Put header marking */
00297 
00298     if (strlen(str2)){
00299     
00300         header_mark.s = pkg_malloc(256);//36 should be enough
00301         sprintf(header_mark.s,"%.*s\n",strlen(str2),str2);
00302         header_mark.len =strlen(header_mark.s);
00303     
00304         anchor = anchor_lump(msg, last->name.s + last->len - msg->buf, 0 , 0);
00305         if (anchor == NULL) {
00306                 LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: anchor_lump failed\n");
00307         }
00308     
00309         if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){
00310                 LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for header_mark\n" );
00311         }
00312         //pkg_free(header_mark.s);
00313     }
00314     LOG(L_ERR, "INFO:"M_NAME":isc_appserver_forward: Searching Route header to rewrite\n");
00315     /* Search for the Route */
00316     hdr = msg->headers;
00317     while(hdr){
00318         if (hdr->type == HDR_ROUTE_T){
00319             if (!hdr->parsed){
00320                 if (parse_rr(hdr) < 0) {
00321                     LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Error while parsing Route HF\n");
00322                     continue;
00323                 }
00324             }
00325             rr = (rr_t*)hdr->parsed;
00326             while(rr){
00327                 if (rr->nameaddr.uri.len >= ISC_MARK_USERNAME_LEN &&
00328                     strncasecmp(rr->nameaddr.uri.s,ISC_MARK_USERNAME,ISC_MARK_USERNAME_LEN)==0) {
00329                         LOG(L_INFO,"DEBUG:"M_NAME":isc_appserver_forward: Found S-CSCF marking <%.*s> \n",rr->nameaddr.uri.len,rr->nameaddr.uri.s);
00330                         /* delete the header */                 
00331                         if (!del_lump(msg, hdr->name.s - msg->buf, hdr->len, 0)) {
00332                             LOG(L_ERR, "ERROR:"M_NAME":isc_appserver_forward: Can't remove Route HF\n");
00333                         }  
00334                                         
00335                         /* add the new header */
00336                         anchor = anchor_lump(msg, msg->headers->name.s - msg->buf, 0 , 0);
00337                         header_mark.s = pkg_malloc(256);//36 should be enough
00338                         sprintf(header_mark.s,"Route: <%.*s>\n",rr->nameaddr.uri.len,rr->nameaddr.uri.s);
00339                         header_mark.len =strlen(header_mark.s); 
00340                         if (!insert_new_lump_before(anchor, header_mark.s,header_mark.len,0)){
00341                             LOG( L_ERR, "ERROR:"M_NAME":isc_appserver_forward: error creting lump for route header\n" );
00342                         }   
00343                     /* send the message */
00344                     msg->dst_uri.s = pkg_malloc(rr->nameaddr.uri.len);
00345                     memcpy(msg->dst_uri.s,rr->nameaddr.uri.s,rr->nameaddr.uri.len);
00346                     msg->dst_uri.len=rr->nameaddr.uri.len;
00347                     isc_tmb.t_relay(msg,0,0);
00348                     return 0;
00349                 }                   
00350                 rr = rr->next;
00351             }           
00352         }
00353         hdr = hdr->next;
00354     }
00355     
00356     /* In case no suitable route header found, just fwd to the given parameter */
00357     msg->dst_uri.len = strlen(str1);
00358     msg->dst_uri.s = str1;
00359     isc_tmb.t_relay(msg,0,0);
00360     LOG(L_DBG,"DEBUG:"M_NAME":isc_appserver_forward: Mirror request finished\n");
00361     return 0;
00362 }
00363 
00364 
00371 static inline enum dialog_direction get_dialog_direction(char *direction)
00372 {
00373     switch(direction[0]){
00374         case 'o':
00375         case 'O':
00376         case '0':
00377             return DLG_MOBILE_ORIGINATING;
00378         case 't':
00379         case 'T':
00380         case '1':
00381             return DLG_MOBILE_TERMINATING;
00382         default:
00383             LOG(L_ERR,"ERR:"M_NAME":get_dialog_direction(): Unknown direction %s",direction);
00384             return DLG_MOBILE_UNKNOWN;
00385     }
00386 }
00387 
00388 
00397 int ISC_match_filter(struct sip_msg *msg,char *str1,char *str2)
00398 {
00399     int k = 0;
00400     isc_match *m = NULL;
00401     str s={0,0};
00402     int ret = ISC_RETURN_FALSE;
00403     isc_mark new_mark,old_mark;
00404     
00405     enum dialog_direction dir = get_dialog_direction(str1);
00406     
00407     LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Checking triggers\n",str1);
00408     
00409     if (dir==DLG_MOBILE_UNKNOWN) 
00410         return ISC_RETURN_BREAK;
00411     
00412     if (!isc_is_initial_request(msg)) return ISC_RETURN_FALSE;
00413         
00414     /* starting or resuming? */
00415     memset(&old_mark,0,sizeof(isc_mark));
00416     memset(&new_mark,0,sizeof(isc_mark));
00417     if (isc_mark_get_from_msg(msg,&old_mark)){      
00418         LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Message returned s=%d;h=%d;d=%d;a=%.*s\n",
00419             str1,old_mark.skip,old_mark.handling,old_mark.direction,old_mark.aor.len,old_mark.aor.s);
00420     }
00421     else {
00422         LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Starting triggering\n",str1);               
00423     }
00424     
00425 
00426     if (*isc_tmb.route_mode==MODE_ONFAILURE) {
00427         LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): failure\n",str1);
00428         
00429         /* need to find the handling for the failed trigger */
00430         if (dir==DLG_MOBILE_ORIGINATING){
00431             k = isc_get_originating_user(msg,&old_mark,&s);
00432             if (k){
00433                 k = isc_is_registered(&s);
00434                 if (k==NOT_REGISTERED) {
00435                     ret = ISC_MSG_NOT_FORWARDED;
00436                     goto done;
00437                 }
00438                 new_mark.direction = IFC_ORIGINATING_SESSION;
00439                 LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Orig User <%.*s> [%d]\n",str1,
00440                     s.len,s.s,k);
00441             } else goto done;
00442         }
00443         if (dir==DLG_MOBILE_TERMINATING){
00444             k = isc_get_terminating_user(msg,&old_mark,&s);
00445             if (k){
00446                 k = isc_is_registered(&s);
00447                 //LOG(L_DBG,"after isc_is_registered in ISC_match_filter\n");
00448                 if (k==REGISTERED) {
00449                     new_mark.direction = IFC_TERMINATING_SESSION;
00450                 } else {
00451                     new_mark.direction = IFC_TERMINATING_UNREGISTERED;
00452                 }
00453                 LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Term User <%.*s> [%d]\n",str1,
00454                     s.len,s.s,k);
00455             } else {
00456                 goto done;
00457             }
00458         }
00459         struct cell * t = isc_tmb.t_gett();
00460         LOG(L_CRIT,"SKIP: %d\n",old_mark.skip);
00461         int index = old_mark.skip;
00462         for (k=0;k<t->nr_of_outgoings;k++) {
00463             m = isc_checker_find(s,new_mark.direction,index,msg,isc_is_registered(&s));
00464             if (m) {
00465                 index = m->index;
00466                 if (k < t->nr_of_outgoings - 1) isc_free_match(m);
00467             } else {
00468                 LOG(L_ERR,"ERR:"M_NAME":ISC_match_filter(%s): On failure, previously matched trigger no longer matches?!\n", str1);
00469                 ret = ISC_RETURN_BREAK;
00470                 goto done;
00471             }
00472         }
00473         if (m->default_handling==IFC_SESSION_TERMINATED) {
00474             /* Terminate the session */
00475             DBG("DEBUG:"M_NAME":ISC_match_filter(%s): Terminating session.\n", str1);
00476             isc_tmb.t_reply(msg,IFC_AS_UNAVAILABLE_STATUS_CODE,
00477                 "AS Contacting Failed - iFC terminated dialog");
00478             LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Responding with %d "
00479                 "to URI: %.*s\n",str1, IFC_AS_UNAVAILABLE_STATUS_CODE,
00480                 msg->first_line.u.request.uri.len,
00481                 msg->first_line.u.request.uri.s);
00482             isc_free_match(m);
00483             ret = ISC_RETURN_BREAK;
00484             goto done;
00485         }
00486         
00487         /* skip the failed triggers (IFC_SESSION_CONTINUED) */
00488         old_mark.skip = index + 1;
00489         
00490         isc_free_match(m);
00491         isc_mark_drop_route(msg);
00492     }
00493 
00494     /* originating leg */
00495     if (dir==DLG_MOBILE_ORIGINATING){
00496         k = isc_get_originating_user(msg,&old_mark,&s);
00497         if (k){
00498             k = isc_is_registered(&s);
00499             if (k==NOT_REGISTERED) return ISC_MSG_NOT_FORWARDED;
00500             
00501             LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Orig User <%.*s> [%d]\n",str1,
00502                 s.len,s.s,k);
00503             m = isc_checker_find(s,old_mark.direction,old_mark.skip,msg,isc_is_registered(&s));
00504             if (m){
00505                 new_mark.direction = IFC_ORIGINATING_SESSION;
00506                 new_mark.skip = m->index+1;
00507                 new_mark.handling = m->default_handling;
00508                 new_mark.aor = s;
00509                 ret = isc_forward(msg,m,&new_mark);
00510                 isc_free_match(m);
00511                 goto done;
00512             }
00513         }
00514         goto done;
00515     }
00516 
00517     /* terminating leg */
00518     if (dir==DLG_MOBILE_TERMINATING){
00519         k = isc_get_terminating_user(msg,&old_mark,&s);
00520         if (k){
00521             k = isc_is_registered(&s);
00522             if (k==REGISTERED) {
00523                 new_mark.direction = IFC_TERMINATING_SESSION;
00524             } else {
00525                 new_mark.direction = IFC_TERMINATING_UNREGISTERED;
00526             }
00527             LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter(%s): Term User <%.*s> [%d]\n",str1,
00528                 s.len,s.s,k);
00529             
00530             m = isc_checker_find(s,new_mark.direction,old_mark.skip,msg,isc_is_registered(&s));
00531             if (m){
00532                 new_mark.skip = m->index+1;
00533                 new_mark.handling = m->default_handling;
00534                 new_mark.aor = s;
00535                 ret = isc_forward(msg,m,&new_mark);
00536                 isc_free_match(m);
00537                 goto done;
00538             }
00539         }
00540         goto done;
00541     }               
00542     
00543 done:
00544     if (old_mark.aor.s) pkg_free(old_mark.aor.s);       
00545     return ret;
00546 }
00547 
00556 int ISC_match_filter_reg(struct sip_msg *msg,char *str1,char *str2)
00557 {
00558     int k;
00559     isc_match *m;
00560     str s={0,0};
00561     int ret = ISC_RETURN_FALSE;
00562     isc_mark old_mark;
00563     
00564     enum dialog_direction dir = DLG_MOBILE_ORIGINATING;
00565     
00566     LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter_reg(): Checking triggers\n");
00567     
00568     if (!isc_is_register(msg)) return ISC_RETURN_FALSE;
00569         
00570     /* starting or resuming? */
00571     memset(&old_mark,0,sizeof(isc_mark));
00572     LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter_reg(): Starting triggering\n");              
00573 
00574     /* originating leg */
00575 
00576     if (dir==DLG_MOBILE_ORIGINATING){
00577         k = isc_get_originating_user(msg,&old_mark,&s);
00578         if (k){
00579             if (str1==0||strlen(str1)!=1){
00580                 LOG(L_ERR,"ERR:"M_NAME":ISC_match_filter_reg(): wrong parameter - must be \"0\" (initial registration) or \"1\"(previously registered) \n");
00581                 return ret;
00582             }else
00583             if (str1[0]=='0') k = 0;
00584             else k=1;               
00585                 
00586             LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter_reg(): Orig User <%.*s> [%d]\n",s.len,s.s,k);
00587             m = isc_checker_find(s,old_mark.direction,old_mark.skip,msg,k);
00588             while (m){ 
00589                 LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter_reg(): REGISTER match found in filter criteria\n");
00590                 ret = isc_third_party_reg(msg,m,&old_mark);
00591                 old_mark.skip = m->index+1;
00592                 isc_free_match(m);
00593                 m = isc_checker_find(s,old_mark.direction,old_mark.skip,msg,k);
00594             }
00595 
00596             if(ret == ISC_RETURN_FALSE)
00597                 LOG(L_INFO,"INFO:"M_NAME":ISC_match_filter_reg(): No REGISTER match found in filter criteria\n");
00598         }
00599     }
00600     return ret;
00601 }
00602 
00611 int ISC_from_AS(struct sip_msg *msg,char *str1,char *str2)
00612 {
00613     int ret = ISC_RETURN_FALSE;
00614     isc_mark old_mark;
00615     
00616     enum dialog_direction dir = get_dialog_direction(str1);
00617         
00618     if (dir==DLG_MOBILE_UNKNOWN) 
00619         return ISC_RETURN_BREAK;
00620     
00621     if (!isc_is_initial_request(msg)) return ISC_RETURN_FALSE;
00622         
00623     /* starting or resuming? */
00624     if (isc_mark_get_from_msg(msg,&old_mark)){      
00625         LOG(L_INFO,"INFO:"M_NAME":ISC_from_AS(%s): Message returned s=%d;h=%d;d=%d\n",
00626             str1,old_mark.skip,old_mark.handling,old_mark.direction);
00627         if (old_mark.direction==IFC_ORIGINATING_SESSION && dir!=DLG_MOBILE_ORIGINATING)
00628             ret = ISC_RETURN_FALSE;
00629         else
00630         if ((old_mark.direction==IFC_TERMINATING_SESSION||old_mark.direction==IFC_TERMINATING_UNREGISTERED)
00631              && dir!=DLG_MOBILE_TERMINATING)
00632             ret = ISC_RETURN_FALSE;
00633         else
00634             ret = ISC_RETURN_TRUE;
00635     } else {
00636         ret = ISC_RETURN_FALSE;
00637     }
00638     return ret;
00639 }
00640 
00649 int ISC_is_session_continued(struct sip_msg *msg,char *str1,char *str2)
00650 {
00651     int ret = ISC_RETURN_FALSE;
00652     isc_mark old_mark;
00653     struct sip_msg *req;
00654 
00655     req = cscf_get_request_from_reply(msg);
00656     
00657     if (!req) {
00658         LOG(L_ERR,"ERR:"M_NAME":ISC_is_session_continued(): There is no transaction \n");           
00659         return ISC_RETURN_FALSE;
00660     }
00661     
00662     if (!isc_is_initial_request(req)) {
00663         LOG(L_ERR,"ERR:"M_NAME":ISC_is_session_continued(): This is no initial request \n");            
00664         return ISC_RETURN_FALSE;
00665     }
00666         
00667     /* starting or resuming? */
00668     if (isc_mark_get_from_lump(req,&old_mark)){     
00669         LOG(L_INFO,"INFO:"M_NAME":ISC_is_session_continued(): Message returned handling [%d] \n",old_mark.handling);
00670         if (old_mark.handling == IFC_SESSION_CONTINUED) 
00671             ret = ISC_RETURN_TRUE;
00672         else 
00673             ret = ISC_RETURN_FALSE;
00674     } else {
00675         LOG(L_ERR,"ERR:"M_NAME":ISC_is_session_continued(): mark not found in lump \n");                    
00676         ret = ISC_RETURN_ERROR;
00677     }
00678     return ret;
00679 }
00680 

Generated on Thu Oct 23 04:14:37 2008 for Open IMS Core CSCFs by  doxygen 1.5.2