Navigation


Changeset 738:d666051658bd in freeDiameter


Ignore:
Timestamp:
Mar 2, 2011, 6:21:59 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Fix broken 'almostcasecmp' logic

Files:
11 edited

Legend:

Unmodified
Added
Removed
  • extensions/app_radgw/rgw_clients.c

    r718 r738  
    732732               
    733733                /* first, check if the nas_id is the fqdn of the peer or a known alias */
    734                 if (!fd_os_almostcasecmp(nas_id + 1, nas_id_len,
    735                                                 cli->fqdn, cli->fqdn_len)) {
     734                if (!fd_os_almostcasesrch(nas_id + 1, nas_id_len,
     735                                                cli->fqdn, cli->fqdn_len, NULL)) {
    736736                        TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client");
    737737                        found = 1;
  • extensions/app_redirect/ard_rules.c

    r723 r738  
    9494       
    9595        if (c->is_regex == 0) {
    96                 if ( ! fd_os_almostcasecmp(c->s, c->sl, s, l) )
     96                if ( ! fd_os_almostcasesrch(c->s, c->sl, s, l, NULL) )
    9797                        *match = 1;
    9898        } else {
  • extensions/rt_redirect/redir_fwd.c

    r717 r738  
    150150                                                for (li = task.rh.next; li != &task.rh; li = li->next) {
    151151                                                        struct redir_host * nhost = li->o;
    152                                                         if ( fd_os_almostcasecmp(id, len, nhost->id, nhost->len) <= 0 )
     152                                                        if ( fd_os_cmp(id, len, nhost->id, nhost->len) <= 0 )
    153153                                                                break;
    154154                                                }
  • extensions/rt_redirect/redir_out.c

    r717 r738  
    171171                /* Special case: ALL_HOST rules: we decrease the score of the Origin-Host if present */
    172172                if (e->type == ALL_HOST) {
    173                         cmp = fd_os_almostcasecmp(cand->diamid, cand->diamidlen, e->data.host.s, e->data.host.l);
     173                        cmp = fd_os_almostcasesrch(cand->diamid, cand->diamidlen, e->data.host.s, e->data.host.l, NULL);
    174174                        if (!cmp) {
    175175                                TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (previous ALL_HOST Redirect originated from this peer)", msg, cand->diamidlen, cand->diamid, FD_SCORE_SENT_REDIRECT);
     
    198198                struct rtd_candidate * cand = (struct rtd_candidate *) lic;
    199199               
    200                 /* Is this candidate in the "Redirect-Host" list ? */
     200                /* Is this candidate in the "Redirect-Host" list ? We must search caseinsentive here. */
    201201                for (lirh = e->target_peers_list.next; lirh != &e->target_peers_list; lirh = lirh->next) {
    202202                        struct redir_host * host = lirh->o;
    203                        
    204                         cmp = fd_os_cmp( cand->diamid, cand->diamidlen, host->id, host->len );
    205                        
    206                         if (cmp < 0)
    207                                 break; /* targets are ordered */
     203                        int cont;
     204                       
     205                        cmp = fd_os_almostcasesrch( cand->diamid, cand->diamidlen, host->id, host->len, &cont );
    208206                       
    209207                        if (cmp == 0) {
    210208                                TRACE_DEBUG(FULL, "Redirect msg %p: peer '%.*s' += %d (rule t:%d @%p)", msg, cand->diamidlen, cand->diamid, redirects_usages[e->type].score, e->type, e);
    211209                                cand->score += redirects_usages[e->type].score;
    212                         }
     210                                break;
     211                        }
     212                        if (!cont)
     213                                break;
    213214                }
    214215        }
  • include/freeDiameter/libfdproto.h

    r736 r738  
    621621
    622622/* A roughly case-insensitive variant, which actually only compares ASCII chars (0-127) in a case-insentitive maneer
    623   -- this should be OK with (old) DNS names. Not sure how it works with IDN...
    624   -- it also clearly does not support locales where a lowercase letter uses more space than upper case, such as ß -> ss
    625  It is slower than fd_os_cmp...
    626  This function should give the same order as fd_os_cmp, except when it finds 2 strings to be equal.
     623  -- it does not support locales where a lowercase letter uses more space than upper case, such as ß -> ss
     624 It is slower than fd_os_cmp.
    627625 Note that the result is NOT the same as strcasecmp !!!
    628  */
    629 int fd_os_almostcasecmp_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz);
    630 #define fd_os_almostcasecmp(_o1, _l1, _o2, _l2)  fd_os_almostcasecmp_int((os0_t)(_o1), _l1, (os0_t)(_o2), _l2)
     626 
     627 This function gives the same order as fd_os_cmp, except when it finds 2 strings to be equal.
     628 However this is not always sufficient:
     629        for example fd_os_cmp gives: "Ac" < "aB" < "aa"
     630        if you attempt to fd_os_almostcasesrch "Aa" you will actually have to go past "aB" which is > "Aa".
     631        Therefore you can use the maybefurther parameter.
     632        This parameter is 1 on return if os1 may have been stored further that os2 (assuming os2 values are ordered by fd_os_cmp)
     633        and 0 if we are sure that it is not the case.
     634        When looping through a list of fd_os_cmp classified values, this parameter must be used to stop looping, in addition to the comp result.
     635 */
     636int fd_os_almostcasesrch_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz, int * maybefurther);
     637#define fd_os_almostcasesrch(_o1, _l1, _o2, _l2, _mb)  fd_os_almostcasesrch_int((os0_t)(_o1), _l1, (os0_t)(_o2), _l2, _mb)
    631638
    632639/* Analyze a DiameterURI and return its components.
  • libfdcore/p_ce.c

    r725 r738  
    304304                               
    305305                                /* We check that the value matches what we know, otherwise disconnect the peer */
    306                                 if (fd_os_almostcasecmp(hdr->avp_value->os.data, hdr->avp_value->os.len,
    307                                                         peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen)) {
     306                                if (fd_os_almostcasesrch(hdr->avp_value->os.data, hdr->avp_value->os.len,
     307                                                        peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, NULL)) {
    308308                                        TRACE_DEBUG(INFO, "Received a message with Origin-Host set to '%.*s' while expecting '%s'\n",
    309309                                                        hdr->avp_value->os.len, hdr->avp_value->os.data, peer->p_hdr.info.pi_diamid);
     
    813813        if (peer->p_hdr.info.config.pic_realm) {
    814814                size_t len = strlen(peer->p_hdr.info.config.pic_realm);
    815                 if (fd_os_almostcasecmp(peer->p_hdr.info.config.pic_realm, len, peer->p_hdr.info.runtime.pir_realm, peer->p_hdr.info.runtime.pir_realmlen)) {
     815                if (fd_os_almostcasesrch(peer->p_hdr.info.config.pic_realm, len, peer->p_hdr.info.runtime.pir_realm, peer->p_hdr.info.runtime.pir_realmlen, NULL)) {
    816816                        TRACE_DEBUG(INFO, "Rejected CER from peer '%s', realm mismatch with configured value (returning DIAMETER_UNKNOWN_PEER).\n", peer->p_hdr.info.pi_diamid);
    817817                        pei.pei_errcode = "DIAMETER_UNKNOWN_PEER"; /* maybe AVP_NOT_ALLOWED would be better fit? */
  • libfdcore/peers.c

    r725 r738  
    9494{
    9595        struct fd_peer *p = NULL;
    96         struct fd_list * li;
     96        struct fd_list * li, *li_inf;
    9797        int ret = 0;
    9898       
     
    143143        /* Ok, now check if we don't already have an entry with the same Diameter Id, and insert this one */
    144144        CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
    145        
     145        li_inf = &fd_g_peers;
    146146        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
    147147                struct fd_peer * next = (struct fd_peer *)li;
    148                 int cmp = fd_os_almostcasecmp( p->p_hdr.info.pi_diamid, p->p_hdr.info.pi_diamidlen,
    149                                                 next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen );
    150                 if (cmp > 0)
    151                         continue;
    152                 if (cmp == 0)
     148                int cont;
     149                int cmp = fd_os_almostcasesrch( p->p_hdr.info.pi_diamid, p->p_hdr.info.pi_diamidlen,
     150                                                next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen,
     151                                                &cont );
     152                if (cmp < 0)
     153                        li_inf = li;
     154               
     155                if (cmp == 0) {
    153156                        ret = EEXIST;
    154                 break;
     157                        break;
     158                }
     159                if (!cont)
     160                        break;
    155161        }
    156162       
     
    162168
    163169                        /* Insert the new element in the list */
    164                         fd_list_insert_before( li, &p->p_hdr.chain );
     170                        fd_list_insert_after( li_inf, &p->p_hdr.chain );
    165171                } while (0);
    166172
     
    185191        /* Search in the list */
    186192        CHECK_POSIX( pthread_rwlock_rdlock(&fd_g_peers_rw) );
    187         for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
    188                 struct fd_peer * next = (struct fd_peer *)li;
    189                 int cmp;
    190                 if (igncase)
    191                         cmp = fd_os_almostcasecmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen );
    192                 else
    193                         cmp = fd_os_cmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen );
    194                 if (cmp > 0)
    195                         continue;
    196                 if (cmp == 0)
    197                         *peer = &next->p_hdr;
    198                 break;
    199         }
     193        if (igncase)
     194                for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     195                        struct fd_peer * next = (struct fd_peer *)li;
     196                        int cmp, cont;
     197                        cmp = fd_os_almostcasesrch( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen, &cont );
     198                        if (cmp == 0) {
     199                                *peer = &next->p_hdr;
     200                                break;
     201                        }
     202                        if (!cont)
     203                                break;
     204                }
     205        else
     206                for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
     207                        struct fd_peer * next = (struct fd_peer *)li;
     208                        int cmp = fd_os_cmp( diamid, diamidlen, next->p_hdr.info.pi_diamid, next->p_hdr.info.pi_diamidlen );
     209                        if (cmp > 0)
     210                                continue;
     211                        if (cmp == 0)
     212                                *peer = &next->p_hdr;
     213                        break;
     214                }
    200215        CHECK_POSIX( pthread_rwlock_unlock(&fd_g_peers_rw) );
    201216       
     
    429444        struct avp *avp_oh;
    430445        struct avp_hdr * avp_hdr;
    431         struct fd_list * li;
     446        struct fd_list * li, *li_inf;
    432447        int found = 0;
    433448        int ret = 0;
     
    470485        CHECK_POSIX( pthread_rwlock_wrlock(&fd_g_peers_rw) );
    471486       
     487        li_inf = &fd_g_peers;
    472488        for (li = fd_g_peers.next; li != &fd_g_peers; li = li->next) {
    473                 int cmp;
     489                int cmp, cont;
    474490                peer = (struct fd_peer *)li->o;
    475                 cmp = fd_os_almostcasecmp( avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen );
    476                 if (cmp > 0)
     491                cmp = fd_os_almostcasesrch( avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len, peer->p_hdr.info.pi_diamid, peer->p_hdr.info.pi_diamidlen, &cont );
     492                if (cmp < 0) {
     493                        li_inf = li;
    477494                        continue;
    478                 if (cmp == 0)
     495                }
     496                if (cmp == 0) {
    479497                        found = 1;
    480                 break;
     498                        break;
     499                }
     500                if (!cont)
     501                        break;
    481502        }
    482503       
     
    500521               
    501522                /* Insert the new peer in the list (the PSM will take care of setting the expiry after validation) */
    502                 fd_list_insert_before( li, &peer->p_hdr.chain );
     523                fd_list_insert_after( li_inf, &peer->p_hdr.chain );
    503524               
    504525                /* Start the PSM, which will receive the event bellow */
  • libfdcore/routing_dispatch.c

    r717 r738  
    274274               
    275275                /* In the AVPs, the value comes from the network, so let's be case permissive */
    276                 if (dh && !fd_os_almostcasecmp(dh->os.data, dh->os.len, c->diamid, c->diamidlen) ) {
     276                if (dh && !fd_os_almostcasesrch(dh->os.data, dh->os.len, c->diamid, c->diamidlen, NULL) ) {
    277277                        /* The candidate is the Destination-Host */
    278278                        c->score += FD_SCORE_FINALDEST;
    279279                } else {
    280                         if (dr && !fd_os_almostcasecmp(dr->os.data, dr->os.len, c->realm, c->realmlen) ) {
     280                        if (dr && !fd_os_almostcasesrch(dr->os.data, dr->os.len, c->realm, c->realmlen, NULL) ) {
    281281                                /* The candidate's realm matchs the Destination-Realm */
    282282                                c->score += FD_SCORE_REALM;
     
    592592                                                ASSERT( ahdr->avp_value );
    593593                                                /* Compare the Destination-Host AVP of the message with our identity */
    594                                                 if (!fd_os_almostcasecmp(ahdr->avp_value->os.data, ahdr->avp_value->os.len, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len)) {
     594                                                if (!fd_os_almostcasesrch(ahdr->avp_value->os.data, ahdr->avp_value->os.len, fd_g_config->cnf_diamid, fd_g_config->cnf_diamid_len, NULL)) {
    595595                                                        is_dest_host = YES;
    596596                                                } else {
     
    613613                                                dr_val = ahdr->avp_value;
    614614                                                /* Compare the Destination-Realm AVP of the message with our identity */
    615                                                 if (!fd_os_almostcasecmp(dr_val->os.data, dr_val->os.len, fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len)) {
     615                                                if (!fd_os_almostcasesrch(dr_val->os.data, dr_val->os.len, fd_g_config->cnf_diamrlm, fd_g_config->cnf_diamrlm_len, NULL)) {
    616616                                                        is_dest_realm = YES;
    617617                                                } else {
  • libfdproto/ostr.c

    r730 r738  
    6969}
    7070
    71 /* a little less sensitive to case, slower. */
    72 int fd_os_almostcasecmp_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz)
     71/* less sensitive to case, slower. */
     72int fd_os_almostcasesrch_int(uint8_t * os1, size_t os1sz, uint8_t * os2, size_t os2sz, int *maybefurther)
    7373{
    7474        int i;
     75        int res = 0;
     76       
    7577        ASSERT( os1 && os2);
     78        if (maybefurther)
     79                *maybefurther = 0;
     80       
    7681        if (os1sz < os2sz)
    7782                return -1;
     83       
     84        if (maybefurther)
     85                *maybefurther = 1;
     86       
    7887        if (os1sz > os2sz)
    7988                return 1;
     
    8392                        continue;
    8493               
     94                if (!res)
     95                        res = os1[i] < os2[i] ? -1 : 1;
     96               
    8597                if (asciitolower(os1[i]) == asciitolower(os2[i]))
    8698                        continue;
    8799               
    88                 return os1[i] < os2[i] ? -1 : 1;
     100                return res;
    89101        }
    90102       
  • libfdproto/rt_data.c

    r717 r738  
    160160        for (li = rtd->candidates.next; li != &rtd->candidates; li = li->next) {
    161161                struct rtd_candidate * c = (struct rtd_candidate *) li;
    162                
    163                 int cmp = fd_os_almostcasecmp(id, idsz, c->diamid, c->diamidlen);
     162                int cont;
     163                int cmp = fd_os_almostcasesrch(id, idsz, c->diamid, c->diamidlen, &cont);
    164164               
    165165                if (!cmp) {
     
    172172                }
    173173               
    174                 if (cmp > 0)
     174                if (cont)
    175175                        continue;
    176176               
  • tests/testostr.c

    r717 r738  
    9999                CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
    100100                CHECK( 0, fd_os_cmp(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8)) );
    101                 CHECK( 0, fd_os_almostcasecmp(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8)) );
     101                CHECK( 0, fd_os_almostcasesrch(res, len, TEST_IDN_UTF8, CONSTSTRLEN(TEST_IDN_UTF8), NULL) );
    102102                CHECK( 0, fd_os_validate_DiameterIdentity(&res, &len, 0) );
    103103                CHECK( 0, strcasecmp(res, TEST_IDN_UTF8) );
     
    128128        }
    129129       
     130        {
     131                /* test fd_os_cmp and fd_os_almostcasesrch and that they are compatible */
     132                char *t1 = "a";
     133                char *t2 = "b";
     134                char *t3 = "C";
     135                char *t4 = "d";
     136                char *t5 = "aa";
     137                char *t6 = "aB";
     138                char *t7 = "Ac";
     139                char *t8 = "aD";
     140                char *t9 = "AAA";
     141               
     142                char *t5b = "Aa";
     143                char *t6b = "ab";
     144               
     145                /* First, create a list with all the elements in order given by fd_os_cmp */
     146                char *t[] = { t1, t2, t3, t4, t5, t6,t7, t8, t9 };
     147                int i;
     148                struct fd_list *li, l = FD_LIST_INITIALIZER(l);
     149                for (i = 0; i < sizeof(t) / sizeof(t[0]); i++) {
     150                        /* insert t[i] */
     151                        struct fd_list *n = malloc(sizeof(struct fd_list));
     152                        CHECK( 1, n ? 1 : 0 );
     153                        fd_list_init(n, t[i]);
     154                        for (li = l.next; li != &l; li = li->next) {
     155                                if ( fd_os_cmp(t[i], strlen(t[i]), li->o, strlen(li->o)) < 0 )
     156                                        break;
     157                        }
     158                        fd_list_insert_before(li, n);
     159                }
     160                /* in principle the result is: [ "C", "a", "b", "d", "Ac", "aB", "aD", "aa", "AAA" ] */
     161               
     162                /* Since there is no equal value in the list (even case-insensitive), check that the order is valid also for the caseinsensitive variant */
     163                for (li = l.next; li != l.prev; li = li->next) {
     164                        CHECK( 1, fd_os_almostcasesrch(li->o, strlen(li->o), li->next->o, strlen(li->next->o), NULL) < 0 ? 1 : 0 );
     165                }
     166               
     167                /* Now check that we can case-insentively find t5b and t6b to be equal to t5 and t6 resp. (this is how we use it in the daemon) */
     168                for (li = l.next; li != &l; li = li->next) {
     169                        int cont, cmp;
     170                        cmp = fd_os_almostcasesrch(t5b, strlen(t5b), li->o, strlen(li->o), &cont);
     171                        TRACE_DEBUG(FULL, "Comp '%s' : %d, %d", (char *)li->o, cmp, cont);
     172                        if (cmp == 0)
     173                                break;
     174                        if (!cont)
     175                                break;
     176                }
     177                CHECK( li->o, t5 );
     178               
     179                for (li = l.next; li != &l; li = li->next) {
     180                        int cont, cmp;
     181                        cmp = fd_os_almostcasesrch(t6b, strlen(t6b), li->o, strlen(li->o), &cont);
     182                        TRACE_DEBUG(FULL, "Comp '%s' : %d, %d", (char *)li->o, cmp, cont);
     183                        if (cmp == 0)
     184                                break;
     185                        if (!cont)
     186                                break;
     187                }
     188                CHECK( li->o, t6 );
     189               
     190               
     191                /* done */
     192                while (!FD_IS_LIST_EMPTY(&l)) {
     193                        li = l.next;
     194                        fd_list_unlink(li);
     195                        free(li);
     196                }
     197        }
     198       
    130199        /* That's all for the tests yet */
    131200        PASSTEST();
Note: See TracChangeset for help on using the changeset viewer.