Navigation


Changeset 717:571b3abaa5df in freeDiameter


Ignore:
Timestamp:
Feb 18, 2011, 2:50:37 PM (13 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Support for Diameter Redirects through rt_redirect.fdx extension (EXPERIMENTAL)

Files:
7 added
10 edited

Legend:

Unmodified
Added
Removed
  • contrib/debian/changelog

    r706 r717  
    2020  * Improved peer state machine algorithm to counter SCTP multistream race
    2121    condition.
     22  * New extension rt_redirect.fdx that handles the Diameter Redirect errors.
    2223
    23  -- Sebastien Decugis <sdecugis@nict.go.jp>  Mon, 07 Feb 2011 17:24:20 +0900
     24 -- Sebastien Decugis <sdecugis@nict.go.jp>  Fri, 18 Feb 2011 14:47:24 +0900
    2425
    2526freediameter (1.0.4) UNRELEASED; urgency=low
  • extensions/CMakeLists.txt

    r667 r717  
    6262# Routing extensions
    6363
    64 FD_EXTENSION_SUBDIR(rt_default "Configurable routing rules for freeDiameter"                 ON)
    65 FD_EXTENSION_SUBDIR(rt_ereg    "Configurable routing based on regexp matching of AVP values" OFF)
     64FD_EXTENSION_SUBDIR(rt_default   "Configurable routing rules for freeDiameter"                  ON)
     65FD_EXTENSION_SUBDIR(rt_redirect  "Handling of Diameter Redirect messages"                       ON)
     66FD_EXTENSION_SUBDIR(rt_ereg      "Configurable routing based on regexp matching of AVP values" OFF)
    6667
    6768
  • extensions/app_radgw/rgw_clients.c

    r706 r717  
    215215        struct rgw_client *tmp = NULL;
    216216        DiamId_t fqdn;
    217         size_t fqdn_len;
     217        size_t fqdn_len = 0;
    218218        int ret, i;
    219219        int loc = 0;
     
    550550        struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL;
    551551        size_t nas_id_len;
    552         char * oh_str = NULL; size_t oh_strlen; int oh_free = 0;
    553         char * or_str = NULL; size_t or_strlen;
    554         char * rr_str = NULL; size_t rr_strlen;
     552        char * oh_str = NULL; size_t oh_strlen = 0; int oh_free = 0;
     553        char * or_str = NULL; size_t or_strlen = 0;
     554        char * rr_str = NULL; size_t rr_strlen = 0;
    555555        char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */
    556556       
     
    789789                                        }
    790790                                        oh_str = &buf[0]; /* The canonname resolved */
     791                                        oh_strlen = 0;
    791792                                        CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
    792793                                                {
  • extensions/app_radgw/rgwx_sip.c

    r709 r717  
    595595                                //We extract Realm from Digest_URI
    596596                                DiamId_t realm=NULL;
    597                                 size_t realm_len;
     597                                size_t realm_len = 0;
    598598                                os0_t temp;
    599599                               
  • include/freeDiameter/libfdcore.h

    r706 r717  
    658658enum fd_rt_out_score {
    659659        FD_SCORE_NO_DELIVERY     = -70, /* We should not send this message to this candidate */
     660        FD_SCORE_SENT_REDIRECT   = -60, /* If this peer previously sent a Redirect indication that applies to this message */
    660661        FD_SCORE_INI             =  -2, /* All candidates are initialized with this value */
    661662        FD_SCORE_LOAD_BALANCE    =   1, /* Use this to differentiate between several peers with the same score */
     
    669670        FD_SCORE_REDIR_USER      =  45, /* If there is a redirect rule with ALL_USER for these message and peer */
    670671        FD_SCORE_REDIR_SESSION   =  50, /* If there is a redirect rule with ALL_SESSION for these message and peer */
     672        FD_SCORE_REDIR_ONCE      =  55, /* If there is a redirect rule with DONT_CACHE for these message and peer */
    671673        FD_SCORE_FINALDEST       = 100  /* If the peer is the final recipient of the message (i.e. matching Destination-Host), it receives a big score. */
    672674};
  • include/freeDiameter/libfdproto.h

    r706 r717  
    607607int fd_os_is_valid_DiameterIdentity(uint8_t * os, size_t ossz);
    608608
    609 /* This checks a string is a valid DiameterIdentity and applies IDNA transformations otherwise (xn--...) */
    610 int fd_os_validate_DiameterIdentity(char ** id, size_t * outsz, int memory /* 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static) */ );
     609/* The following function validates a string as a Diameter Identity or applies the IDNA transformation on it
     610 if *inoutsz is != 0 on entry, *id may not be \0-terminated.
     611 memory has the following meaning: 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static)
     612*/
     613int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory);
    611614
    612615/* Create an order relationship for binary strings (not needed to be \0 terminated).
     
    627630#define fd_os_almostcasecmp(_o1, _l1, _o2, _l2)  fd_os_almostcasecmp_int((os0_t)(_o1), _l1, (os0_t)(_o2), _l2)
    628631
     632/* Analyze a DiameterURI and return its components.
     633  Return EINVAL if the URI is not valid.
     634  *diamid is malloc'd on function return and must be freed (it is processed by fd_os_validate_DiameterIdentity).
     635  *secure is 0 (no security) or 1 (security enabled) on return.
     636  *port is 0 (default) or a value in host byte order on return.
     637  *transport is 0 (default) or IPPROTO_* on return.
     638  *proto is 0 (default) or 'd' (diameter), 'r' (radius), or 't' (tacacs+) on return.
     639  */
     640int fd_os_parse_DiameterURI(uint8_t * uri, size_t urisz, DiamId_t * diamid, size_t * diamidlen, int * secure, uint16_t * port, int * transport, char *proto);
    629641
    630642/*============================================================*/
  • libfdcore/routing_dispatch.c

    r715 r717  
    722722                        return 0;
    723723                }
    724 
     724               
    725725                /* From that point, for answers, we will call the registered callbacks, then pass it to the dispatch module or forward it */
    726726        }
     
    11061106        CHECK_FCT( fd_rt_out_register( score_destination_avp, NULL, 10, NULL ) );
    11071107       
    1108         TODO("built-in callbacks for Redirect messages?");
    1109        
    11101108        return 0;
    11111109}
  • libfdproto/ostr.c

    r707 r717  
    167167}
    168168
    169 /* The following function validates a string as a Diameter Identity or applies the IDNA transformation on it */
    170 int fd_os_validate_DiameterIdentity(char ** id, size_t * outsz, int memory /* 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static) */)
    171 {
    172         TRACE_ENTRY("%p %p", id, outsz);
    173        
    174         *outsz = strlen(*id);
     169/* The following function validates a string as a Diameter Identity or applies the IDNA transformation on it
     170 if *inoutsz is != 0 on entry, *id may not be \0-terminated.
     171 memory has the following meaning: 0: *id can be realloc'd. 1: *id must be malloc'd on output (was static)
     172*/
     173int fd_os_validate_DiameterIdentity(char ** id, size_t * inoutsz, int memory)
     174{
     175        int gotsize = 0;
     176       
     177        TRACE_ENTRY("%p %p", id, inoutsz);
     178        CHECK_PARAMS( id && *id && inoutsz );
     179       
     180        if (!*inoutsz)
     181                *inoutsz = strlen(*id);
     182        else
     183                gotsize = 1;
    175184       
    176185#ifndef DIAMID_IDNA_IGNORE
    177186       
    178         if (!fd_os_is_valid_DiameterIdentity((os0_t)*id, *outsz)) {
     187        if (!fd_os_is_valid_DiameterIdentity((os0_t)*id, *inoutsz)) {
    179188       
    180189#ifdef DIAMID_IDNA_REJECT
     
    188197                char *processed;
    189198                int ret;
     199               
     200                if (gotsize) { /* make it \0-terminated */
     201                        if (memory) {
     202                                CHECK_MALLOC( *id = os0dup(*id, *inoutsz) );
     203                                memory = 0;
     204                        } else {
     205                                CHECK_MALLOC( *id = realloc(*id, *inoutsz + 1) );
     206                                (*id)[*inoutsz] = '0';
     207                        }
     208                }
    190209               
    191210                ret = idna_to_ascii_8z ( *id, &processed, IDNA_USE_STD3_ASCII_RULES );
     
    195214                                free(*id);
    196215                        *id = processed;
    197                         *outsz = strlen(processed);
     216                        *inoutsz = strlen(processed);
    198217                        /* Done! */
    199218                } else {
     
    207226        {
    208227                if (memory == 1) {
    209                         CHECK_MALLOC( *id = os0dup(*id, *outsz) );
     228                        CHECK_MALLOC( *id = os0dup(*id, *inoutsz) );
    210229                }
    211230        }
     
    213232}
    214233
     234/* Analyze a DiameterURI and return its components.
     235  Return EINVAL if the URI is not valid.
     236  *diamid is malloc'd on function return and must be freed (it is processed by fd_os_validate_DiameterIdentity).
     237  *secure is 0 (no security) or 1 (security enabled) on return.
     238  *port is 0 (default) or a value in host byte order on return.
     239  *transport is 0 (default) or IPPROTO_* on return.
     240  *proto is 0 (default) or 'd' (diameter), 'r' (radius), or 't' (tacacs+) on return.
     241  */
     242int fd_os_parse_DiameterURI(uint8_t * uri, size_t urisz, DiamId_t * diamid, size_t * diamidlen, int * secure, uint16_t * port, int * transport, char *proto)
     243{
     244        size_t offset = 0;
     245        DiamId_t fqdn = NULL;
     246        size_t   fqdnlen;
     247        TRACE_ENTRY("%p %zd %p %p %p %p %p %p", uri, urisz, diamid, diamidlen, secure, port, transport, proto);
     248        CHECK_PARAMS( uri && urisz );
     249       
     250        CHECK_PARAMS( urisz > 7 ); /* "aaa" + "://" + something else at least */
     251       
     252        /* Initialize values */
     253        if (secure)
     254                *secure = 0;
     255        if (port)
     256                *port = 0;
     257        if (transport)
     258                *transport = 0;
     259        if (proto)
     260                *proto = 0;
     261       
     262        /* Check the beginning */
     263        if (memcmp( uri, "aaa", 3)) {
     264                TRACE_DEBUG(INFO, "Invalid DiameterURI prefix: got '%.*s', expected 'aaa'", 3, uri);
     265                return EINVAL;
     266        }
     267        offset += 3;
     268       
     269        /* Secure? */
     270        if (uri[offset] == (uint8_t)'s') {
     271                if (secure)
     272                        *secure = 1;
     273                offset += 1;
     274        }
     275       
     276        /* Remaining of URI marker */
     277        if (memcmp( uri + offset, "://", 3)) {
     278                TRACE_DEBUG(INFO, "Invalid DiameterURI prefix: got '%.*s', expected 'aaa://' or 'aaas://'", offset + 3, uri);
     279                return EINVAL;
     280        }
     281        offset += 3;
     282       
     283        /* This is the start of the FQDN */
     284        fqdn = (DiamId_t)uri + offset;
     285        for ( ; offset < urisz ; offset++ ) {
     286                /* Stop only when we find ':' or ';' */
     287                if ((uri[offset] == (uint8_t)':') || (uri[offset] == (uint8_t)';'))
     288                        break;
     289        }
     290        fqdnlen = offset - (fqdn - (DiamId_t)uri);
     291        CHECK_FCT(fd_os_validate_DiameterIdentity(&fqdn, &fqdnlen, 1));
     292        if (diamid)
     293                *diamid = fqdn;
     294        else
     295                free(fqdn);
     296        if (diamidlen)
     297                *diamidlen = fqdnlen;
     298       
     299        if (offset == urisz)
     300                return 0; /* Finished */
     301       
     302        /* Is there a port ? */
     303        if (uri[offset] == ':') {
     304                uint16_t p = 0;
     305                do {
     306                        offset++;
     307
     308                        if (offset == urisz)
     309                                break;
     310
     311                        uint32_t t = (uint32_t)((char)uri[offset] - '0');
     312                        if (t > 9)
     313                                break; /* we did not get a digit */
     314
     315                        t += p * 10; /* the port is specified in decimal base */
     316                       
     317                        if (t >= (1<<16)) {
     318                                TRACE_DEBUG(INFO, "Invalid DiameterURI: port value is too big, ignored.");
     319                                p = 0;
     320                                break;
     321                        }
     322
     323                        p = t;
     324                } while (1);
     325
     326                if (port)
     327                        *port = p;
     328        }
     329       
     330        if (offset == urisz)
     331                return 0; /* Finished */
     332       
     333        /* Is there a transport? */
     334        if ( (urisz - offset > CONSTSTRLEN(";transport="))
     335                && !strncasecmp((char *)uri + offset, ";transport=", CONSTSTRLEN(";transport=")) ) {
     336       
     337                offset += CONSTSTRLEN(";transport=");
     338
     339                if (urisz - offset < 3) {
     340                        TRACE_DEBUG(INFO, "Invalid DiameterURI: transport string is too short, ignored.");
     341                        return 0;
     342                }               
     343                if (!strncasecmp((char *)uri + offset, "tcp", CONSTSTRLEN("tcp"))) {
     344                        if (transport)
     345                                *transport = IPPROTO_TCP;
     346                        offset += CONSTSTRLEN("tcp");
     347                        goto after_transport;
     348                }
     349                if (!strncasecmp((char *)uri + offset, "udp", CONSTSTRLEN("udp"))) {
     350                        if (transport)
     351                                *transport = IPPROTO_UDP;
     352                        offset += CONSTSTRLEN("udp");
     353                        goto after_transport;
     354                }
     355                if ((urisz - offset > 3) && !strncasecmp((char *)uri + offset, "sctp", CONSTSTRLEN("sctp"))) {
     356                        if (transport) {
     357#ifndef DISABLE_SCTP
     358                                *transport = IPPROTO_SCTP;
     359#else /* DISABLE_SCTP */
     360                                TRACE_DEBUG(INFO, "Received DiameterURI with 'transport=sctp' but DISABLE_SCTP was selected");
     361                                *transport = 0;
     362#endif /* DISABLE_SCTP */
     363                        }
     364                        offset += CONSTSTRLEN("sctp");
     365                        goto after_transport;
     366                }
     367               
     368                TRACE_DEBUG(INFO, "Invalid DiameterURI: transport string is not recognized ('%.*s'), ignored.", urisz - offset, uri + offset);
     369               
     370                /* eat the remaining of invalid transport until a ';' */
     371                for (; (offset < urisz) && ((char)uri[offset] != ';'); offset++);
     372        }
     373after_transport:
     374        if (offset == urisz)
     375                return 0; /* Finished */
     376       
     377        /* Is there a protocol? */
     378        if ( ((urisz - offset) > CONSTSTRLEN(";protocol="))
     379                && (!strncasecmp((char *)uri + offset, ";protocol=", CONSTSTRLEN(";protocol="))) ) {
     380       
     381                offset += CONSTSTRLEN(";protocol=");
     382
     383                if ( ((urisz - offset) >= CONSTSTRLEN("diameter"))
     384                    && (!strncasecmp((char *)uri + offset, "diameter", CONSTSTRLEN("diameter"))) ) {
     385                        if (proto)
     386                                *proto = 'd';
     387                        offset += CONSTSTRLEN("diameter");
     388                        goto after_proto;
     389                }
     390               
     391                if ( ((urisz - offset) >= CONSTSTRLEN("radius"))
     392                    && (!strncasecmp((char *)uri + offset, "radius", CONSTSTRLEN("radius"))) ) {
     393                        if (proto)
     394                                *proto = 'r';
     395                        offset += CONSTSTRLEN("radius");
     396                        goto after_proto;
     397                }
     398               
     399                if ( ((urisz - offset) >= CONSTSTRLEN("tacacs+"))
     400                    && (!strncasecmp((char *)uri + offset, "tacacs+", CONSTSTRLEN("tacacs+"))) ) {
     401                        if (proto)
     402                                *proto = 't';
     403                        offset += CONSTSTRLEN("tacacs+");
     404                        goto after_proto;
     405                }
     406               
     407                TRACE_DEBUG(INFO, "Invalid DiameterURI: protocol string is not recognized ('%.*s'), ignored.", urisz - offset, uri + offset);
     408               
     409                /* eat the remaining of invalid transport until a ';' */
     410                for (; (offset < urisz) && ((char)uri[offset] != ';'); offset++);
     411        }
     412after_proto:
     413        if (offset == urisz)
     414                return 0; /* Finished */
     415       
     416        TRACE_DEBUG(INFO, "Invalid DiameterURI: string is not recognized ('%.*s'), ignored.", urisz - offset, uri + offset);
     417        return 0;
     418}
    215419
    216420
  • libfdproto/rt_data.c

    r706 r717  
    132132        CHECK_MALLOC( new = malloc(sizeof(struct rtd_candidate)) );
    133133        memset(new, 0, sizeof(struct rtd_candidate) );
    134         fd_list_init(&new->chain, NULL);
     134        fd_list_init(&new->chain, new);
    135135        CHECK_MALLOC( new->diamid = os0dup(peerid, peeridlen) )
    136136        new->diamidlen = peeridlen;
  • tests/testostr.c

    r709 r717  
    7575        {
    7676                char * res;
    77                 size_t len;
     77                size_t len=0;
    7878               
    7979                /* A valid ASCII domain name */
     
    8888                /* Now, an invalid string */
    8989                res = TEST_IDN_UTF8;
     90                len = 0;
    9091               
    9192                #ifdef DIAMID_IDNA_IGNORE
Note: See TracChangeset for help on using the changeset viewer.