Navigation


Changeset 706:4ffbc9f1e922 in freeDiameter for extensions/app_radgw/rgwx_sip.c


Ignore:
Timestamp:
Feb 9, 2011 3:26:58 PM (2 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Message:

Large UNTESTED commit with the following changes:

  • Improved DiameterIdentity? handling (esp. interationalization issues), and improve efficiency of some string operations in peers, sessions, and dictionary modules (closes #7)
  • Cleanup in the session module to free only unreferenced sessions (#16)
  • Removed fd_cpu_flush_cache(), replaced by more robust alternatives.
  • Improved peer state machine algorithm to counter SCTP multistream race condition.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • extensions/app_radgw/rgwx_sip.c

    r705 r706  
    5858/* This macro converts a RADIUS attribute to a Diameter AVP of type OctetString */ 
    5959#define CONV2DIAM_STR( _dictobj_ )      \ 
    60         CHECK_PARAMS( attr->length >= 2 );                                              \ 
     60        CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );                 \ 
    6161        /* Create the AVP with the specified dictionary model */                        \ 
    6262        CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \ 
    63         value.os.len = attr->length - 2;                                                \ 
    64         value.os.data = (unsigned char *)(attr + 1);                                    \ 
     63        value.os.len = attr->length - sizeof(struct radius_attr_hdr);                   \ 
     64        value.os.data = (os0_t)(attr + 1);                                              \ 
    6565        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \ 
    6666        /* Add the AVP in the Diameter message. */                                      \ 
     
    6868 
    6969#define CONV2DIAM_STR_AUTH( _dictobj_ ) \ 
    70         CHECK_PARAMS( attr->length >= 2 );                                              \ 
     70        CHECK_PARAMS( attr->length >= sizeof(struct radius_attr_hdr) );                 \ 
    7171        /* Create the AVP with the specified dictionary model */                        \ 
    7272        CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \ 
    73         value.os.len = attr->length - 2;                                                \ 
    74         value.os.data = (unsigned char *)(attr + 1);                                    \ 
     73        value.os.len = attr->length - sizeof(struct radius_attr_hdr);                   \ 
     74        value.os.data = (os0_t)(attr + 1);                                              \ 
    7575        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \ 
    7676        /* Add the AVP in the Diameter message. */                                      \ 
    77         CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );           \ 
     77        CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );                   \ 
    7878                 
    7979/* Same thing, for scalar AVPs of 32 bits */ 
    8080#define CONV2DIAM_32B( _dictobj_ )      \ 
    81         CHECK_PARAMS( attr->length == 6 );                                              \ 
     81        CHECK_PARAMS( attr->length == sizeof(struct radius_attr_hdr)+sizeof(uint32_t) );\ 
    8282        CHECK_FCT( fd_msg_avp_new ( cs->dict._dictobj_, 0, &avp ) );                    \ 
    8383        {                                                                               \ 
    8484                uint8_t * v = (uint8_t *)(attr + 1);                                    \ 
    8585                value.u32  = (v[0] << 24)                                               \ 
    86                            | (v[1] << 16)                                               \ 
    87                            | (v[2] <<  8)                                               \ 
    88                            |  v[3] ;                                                    \ 
     86                           | (v[1] << 16)                                               \ 
     87                           | (v[2] <<  8)                                               \ 
     88                           |  v[3] ;                                                    \ 
    8989        }                                                                               \ 
    9090        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                               \ 
    91         CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 
     91        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) );               \ 
    9292                                 
    9393                                 
     
    145145{ 
    146146        struct fd_list chain; 
    147     char * sid; 
     147    os0_t sid; 
    148148    size_t sidlen; 
    149     char * nonce; 
     149    os0_t nonce; 
    150150    size_t noncelen; 
    151151     
    152152}; 
    153153 
    154 static int nonce_add_element(char * nonce, size_t noncelen,char * sid, size_t sidlen, struct rgwp_config * state) 
     154static int nonce_add_element(os0_t nonce, size_t noncelen, os0_t sid, size_t sidlen, struct rgwp_config * state) 
    155155{ 
    156156        CHECK_PARAMS(nonce && state && sid && sidlen && noncelen); 
     
    159159        CHECK_MALLOC(newelt=malloc(sizeof(noncechain))); 
    160160         
    161         CHECK_MALLOC(newelt->nonce=malloc(noncelen)); 
    162         memcpy(newelt->nonce,nonce,noncelen); 
     161        CHECK_MALLOC(newelt->nonce= os0dup(nonce, noncelen)); 
    163162        newelt->noncelen=noncelen; 
    164163         
    165         CHECK_MALLOC(newelt->sid=malloc(sidlen)); 
    166         memcpy(newelt->sid,sid,sidlen); 
     164        CHECK_MALLOC(newelt->sid=os0dup(sid, sidlen)); 
    167165        newelt->sidlen=sidlen; 
    168166         
     
    198196*/ 
    199197//Retrieve sid from nonce 
    200 static char * nonce_get_sid(char * nonce, size_t noncelen, size_t * sidlen, struct rgwp_config *state) 
     198static os0_t nonce_get_sid(os0_t nonce, size_t noncelen, size_t * sidlen, struct rgwp_config *state) 
    201199{ 
    202200        struct fd_list * li; 
    203         char *sid=NULL; 
     201        os0_t sid=NULL; 
    204202         
    205203        CHECK_PARAMS_DO(nonce && state && noncelen && sidlen, return NULL); 
    206204        *sidlen=0; 
    207205         
    208         //**Start mutex 
     206        // **Start mutex 
    209207        CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),);  
    210208        for(li=state->listnonce.next;li!=&state->listnonce;li=li->next) 
     
    212210                noncechain *temp=(noncechain *)li; 
    213211                 
    214                 if(temp->noncelen==noncelen && strncmp(temp->nonce,nonce, noncelen)==0) 
     212                if (!fd_os_cmp(temp->nonce, temp->noncelen, nonce, noncelen)) 
    215213                { 
    216214                        fd_list_unlink (li); 
     
    224222        } 
    225223        CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),);  
    226         //***Stop mutex 
     224        // ***Stop mutex 
    227225        return sid; 
    228226} 
     
    230228static void nonce_deletelistnonce(struct rgwp_config *state) 
    231229{ 
    232         //**Start mutex 
     230        // **Start mutex 
    233231        CHECK_POSIX_DO(pthread_mutex_lock(&state->nonce_mutex),);  
    234232        while(!(FD_IS_LIST_EMPTY(&state->listnonce)) ) 
     
    243241        } 
    244242        CHECK_POSIX_DO(pthread_mutex_unlock(&state->nonce_mutex),);  
    245         //***Stop mutex 
     243        // ***Stop mutex 
    246244} 
    247245 
     
    338336        int got_Dresponse = 0; 
    339337        int got_Dalgorithm = 0; 
    340         char * sid = NULL; 
    341         char * un=NULL; 
     338        os0_t sid = NULL; 
     339        size_t sidlen; 
     340        os0_t un=NULL; 
    342341        size_t  un_len; 
    343342        size_t nattr_used = 0; 
     
    352351        if(*session) 
    353352        { 
    354                 TRACE_DEBUG(INFO,"We are not supposed to receive a session in radSIP plugin."); 
     353                TRACE_DEBUG(INFO,"INTERNAL ERROR: We are not supposed to receive a session in radSIP plugin."); 
    355354                return EINVAL; 
    356355        } 
     
    371370                                { 
    372371                                        TRACE_DEBUG(ANNOYING, "Found a User-Name attribute: '%.*s'", attr->length- sizeof(struct radius_attr_hdr), (char *)(attr+1)); 
    373                                         un = (char *)(attr + 1); 
     372                                        un = (os0_t)(attr + 1); 
    374373                                        un_len =attr->length - sizeof(struct radius_attr_hdr); 
    375374                                } 
     
    396395                                got_Dnonce = 1; 
    397396                                 
    398                                 size_t sidlen; 
    399                                  
    400                                 sid=nonce_get_sid((char *)(attr+1),attr->length-2,&sidlen,cs); 
     397                                sid=nonce_get_sid((os0_t)(attr+1), attr->length - sizeof(struct radius_attr_hdr), &sidlen, cs); 
    401398                                if(!sid) 
    402399                                { 
     
    406403                                CHECK_FCT(fd_sess_fromsid (sid, sidlen, session, NULL)); 
    407404                                free(sid); 
    408                                                                  
     405                                                         
    409406                                 
    410407                        break; 
     
    432429        if (!*session) { 
    433430                 
    434                 char * fqdn; 
    435                 char * realm; 
     431                DiamId_t fqdn; 
     432                size_t fqdn_len; 
     433                DiamId_t realm; 
     434                size_t realm_len; 
    436435                 
    437436                 
     
    439438                 
    440439                /* Get information on the RADIUS client */ 
    441                 CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &realm) ); 
    442                  
    443                 int len; 
     440                CHECK_FCT( rgw_clients_get_origin(cli, &fqdn, &fqdn_len, &realm, &realm_len) ); 
     441                 
    444442                /* Create a new Session-Id. The format is: {fqdn;hi32;lo32;username;diamid} */ 
    445443                CHECK_MALLOC( sid = malloc(un_len + 1 /* ';' */ + fd_g_config->cnf_diamid_len + 1 /* '\0' */) ); 
    446                 len = sprintf(sid, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid); 
    447                 CHECK_FCT( fd_sess_new(session, fqdn, sid, len) ); 
     444                sidlen = sprintf((char *)sid, "%.*s;%s", (int)un_len, un, fd_g_config->cnf_diamid); 
     445                CHECK_FCT( fd_sess_new(session, fqdn, fqdn_len, sid, sidlen) ); 
    448446                free(sid); 
    449447        } 
     
    453451         
    454452        int i = 0; 
    455         if (un) { 
    456                 /* Is there an '@' in the user name? We don't care for decorated NAI here */ 
    457                 for (i = un_len - 2; i > 0; i--) { 
    458                         if (un[i] == '@') { 
    459                                 i++; 
    460                                 break; 
    461                         } 
     453         
     454        /* Is there an '@' in the user name? We don't care for decorated NAI here */ 
     455        for (i = un_len - 2; i > 0; i--) { 
     456                if (un[i] == '@') { 
     457                        i++; 
     458                        break; 
    462459                } 
    463460        } 
     461 
    464462        if (i == 0) { 
    465463                /* Not found in the User-Name => we use the local domain of this gateway */ 
    466                 value.os.data = (unsigned char *)fd_g_config->cnf_diamrlm; 
     464                value.os.data = (os0_t)fd_g_config->cnf_diamrlm; 
    467465                value.os.len  = fd_g_config->cnf_diamrlm_len; 
    468466        } else { 
    469                 value.os.data = (unsigned char *)(un + i); 
     467                value.os.data = un + i; 
    470468                value.os.len  = un_len - i; 
    471469        } 
     
    475473         
    476474        /* Now, add the Session-Id AVP at beginning of Diameter message */ 
    477         CHECK_FCT( fd_sess_getsid(*session, &sid) ); 
     475        CHECK_FCT( fd_sess_getsid(*session, &sid, &sidlen) ); 
    478476         
    479477        TRACE_DEBUG(FULL, "[sip.rgwx] Translating new message for session '%s'...", sid); 
     
    481479        /* Add the Session-Id AVP as first AVP */ 
    482480        CHECK_FCT( fd_msg_avp_new ( cs->dict.Session_Id, 0, &avp ) ); 
    483         value.os.data = (unsigned char *)sid; 
    484         value.os.len = strlen(sid); 
     481        value.os.data = sid; 
     482        value.os.len = sidlen; 
    485483        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 
    486484        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_FIRST_CHILD, avp) ); 
     
    552550                CHECK_FCT( fd_msg_avp_add ( auth_data, MSG_BRW_LAST_CHILD, auth) ); 
    553551        } 
    554         char * temp=NULL,*sipuri=NULL; 
    555552 
    556553        for (idx = 0; idx < rad_req->attr_used; idx++)  
     
    597594                        { 
    598595                                //We extract Realm from Digest_URI 
    599                                 char *realm=NULL; 
    600                          
    601                                 CHECK_MALLOC(temp=malloc(attr->length -1)); 
    602                                 strncpy(temp, (char *)(attr + 1), attr->length -2); 
    603                                 temp[attr->length-2] = '\0'; 
    604                          
    605                                 realm = strtok( (char *)(temp), "@" ); 
    606                                 realm = strtok( NULL, "@" ); 
    607                                 free(temp); 
    608                                 temp=NULL; 
     596                                DiamId_t realm=NULL; 
     597                                size_t realm_len; 
     598                                os0_t temp; 
     599                                 
     600                                temp = (os0_t)(attr + 1); 
     601                                 
     602                                for (i=attr->length - sizeof(struct radius_attr_hdr) - 1; i>=0; i--) { 
     603                                        if (temp[i] == '@') { 
     604                                                realm = (DiamId_t)temp + i + 1; 
     605                                                CHECK_FCT_DO( fd_os_validate_DiameterIdentity(&realm, &realm_len, 1), 
     606                                                        realm = NULL ); 
     607                                                break; 
     608                                        } 
     609                                } 
     610                         
    609611                                if(realm!=NULL) 
    610612                                { 
    611613                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Realm, 0, &avp ) ); 
    612                                         value.os.data=(unsigned char *)realm; 
    613                                         value.os.len=strlen(realm); 
     614                                        value.os.data=(os0_t)realm; 
     615                                        value.os.len=realm_len; 
    614616                                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 
    615617                                        CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) ); 
     
    617619                                        //We add SIP-Server-URI AVP because SIP server is registrar (through gateway) 
    618620                                        CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) ); 
    619                                         value.os.data=(unsigned char *)realm; 
    620                                         value.os.len=strlen(realm); 
     621                                        value.os.data=(os0_t)realm; 
     622                                        value.os.len=realm_len; 
    621623                                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 
    622624                                        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 
    623625                                         
     626                                        free(realm); 
    624627                                } 
    625628                                else 
     
    641644                        //We add SIP-Server-URI AVP because SIP server is registrar (through gateway) 
    642645                        CHECK_FCT( fd_msg_avp_new ( cs->dict.SIP_Server_URI, 0, &avp ) ); 
    643                          
    644                          
    645                         CHECK_MALLOC(temp=malloc(attr->length -1)); 
    646                         strncpy(temp, (char *)(attr + 1), attr->length -2); 
    647                          
    648                          
    649                         CHECK_MALLOC(sipuri=malloc(attr->length +3)); 
    650                         strcpy(sipuri,"sip:"); 
    651                         strcat(sipuri,(const char *)temp); 
    652                         value.os.data=(unsigned char *)sipuri; 
    653                         value.os.len=attr->length +2; 
     646                        os0_t temp; 
     647                        #define SIP_PREFIX      "sip:" 
     648                        size_t temp_len = attr->length - sizeof(struct radius_attr_hdr) + CONSTSTRLEN(SIP_PREFIX) + 1; 
     649                        CHECK_MALLOC( temp = malloc(temp_len) ); 
     650                        temp_len = snprintf((char *)temp, temp_len, SIP_PREFIX "%.*s", attr->length - sizeof(struct radius_attr_hdr), (char *)(attr + 1)); 
     651                         
     652                        value.os.data=temp; 
     653                        value.os.len=temp_len; 
    654654                         
    655655                        free(temp); 
    656                         temp=NULL; 
     656                         
    657657                        CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) ); 
    658658                        CHECK_FCT( fd_msg_avp_add ( *diam_fw, MSG_BRW_LAST_CHILD, avp) ); 
     
    689689                        { 
    690690                                //[Note 3] If Digest-Algorithm is missing, 'MD5' is assumed. 
     691                                #define DIGEST_ALGO_MD5 "MD5" 
    691692                                                                                 
    692693                                CHECK_FCT( fd_msg_avp_new ( cs->dict.Digest_Algorithm, 0, &avp ) );                      
    693694                                                                                 
    694                                 value.os.data = (unsigned char *)"MD5"; 
    695                                 value.os.len = strlen((const char *)value.os.data); 
     695                                value.os.data = (os0_t)DIGEST_ALGO_MD5; 
     696                                value.os.len = CONSTSTRLEN(DIGEST_ALGO_MD5) - 1; 
    696697                                CHECK_FCT( fd_msg_avp_setvalue ( avp, &value ) );                                        
    697698                                CHECK_FCT( fd_msg_avp_add ( auth, MSG_BRW_LAST_CHILD, avp) );    
     
    831832                                        /* Retrieve the request identified which was stored in the session */ 
    832833                                        if (session) { 
    833                                                 char *sid=NULL; 
     834                                                os0_t sid=NULL; 
    834835                                                size_t sidlen; 
    835                                                 fd_sess_getsid (session, &sid ); 
    836                                                 sidlen=strlen(sid); 
     836                                                fd_sess_getsid (session, &sid, &sidlen ); 
    837837                                                 
    838                                                 nonce_add_element((char *)ahdr->avp_value->os.data,ahdr->avp_value->os.len, sid,sidlen, cs); 
     838                                                nonce_add_element(ahdr->avp_value->os.data, ahdr->avp_value->os.len, sid, sidlen, cs); 
    839839                                        } 
    840840                                        break; 
Note: See TracChangeset for help on using the changeset viewer.