comparison extensions/app_radgw/rgw_clients.c @ 706:4ffbc9f1e922

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.
author Sebastien Decugis <sdecugis@nict.go.jp>
date Wed, 09 Feb 2011 15:26:58 +0900
parents 25440e53a48e
children 571b3abaa5df
comparison
equal deleted inserted replaced
705:f0cb8f465763 706:4ffbc9f1e922
83 }; 83 };
84 84
85 /* The FQDN, realm, and optional aliases */ 85 /* The FQDN, realm, and optional aliases */
86 int is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */ 86 int is_local; /* true if the RADIUS client runs on the same host -- we use Diameter Identity in that case */
87 enum rgw_cli_type type; /* is it a proxy ? */ 87 enum rgw_cli_type type; /* is it a proxy ? */
88 char *fqdn; 88 DiamId_t fqdn; /* malloc'd here */
89 size_t fqdn_len; 89 size_t fqdn_len;
90 char *realm; 90 DiamId_t realm; /* references another string, do not free */
91 char **aliases; 91 size_t realm_len;
92 struct {
93 os0_t name;
94 size_t len;
95 } *aliases; /* Received aliases */
92 size_t aliases_nb; 96 size_t aliases_nb;
93 97
94 /* The secret key data. */ 98 /* The secret key data. */
95 struct { 99 struct {
96 unsigned char * data; 100 unsigned char * data;
207 211
208 /* create a new rgw_client. the arguments are MOVED into the structure (to limit malloc & free calls). */ 212 /* create a new rgw_client. the arguments are MOVED into the structure (to limit malloc & free calls). */
209 static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type ) 213 static int client_create(struct rgw_client ** res, struct sockaddr ** ip_port, unsigned char ** key, size_t keylen, enum rgw_cli_type type )
210 { 214 {
211 struct rgw_client *tmp = NULL; 215 struct rgw_client *tmp = NULL;
212 char buf[255]; 216 DiamId_t fqdn;
217 size_t fqdn_len;
213 int ret, i; 218 int ret, i;
214 int loc = 0; 219 int loc = 0;
215 220
216 /* Check if the IP address is local */ 221 /* Check if the IP address is local */
217 if ( ( ((*ip_port)->sa_family == AF_INET ) && ( IN_IS_ADDR_LOOPBACK( &((struct sockaddr_in *)(*ip_port))->sin_addr ) ) ) 222 if ( ( ((*ip_port)->sa_family == AF_INET ) && ( IN_IS_ADDR_LOOPBACK( &((struct sockaddr_in *)(*ip_port))->sin_addr ) ) )
218 ||( ((*ip_port)->sa_family == AF_INET6) && ( IN6_IS_ADDR_LOOPBACK( &((struct sockaddr_in6 *)(*ip_port))->sin6_addr) ) )) { 223 ||( ((*ip_port)->sa_family == AF_INET6) && ( IN6_IS_ADDR_LOOPBACK( &((struct sockaddr_in6 *)(*ip_port))->sin6_addr) ) )) {
219 /* The client is local */ 224 /* The client is local */
220 loc = 1; 225 loc = 1;
221 } else { 226 } else {
227 char buf[255];
222 228
223 /* Search FQDN for the client */ 229 /* Search FQDN for the client */
224 ret = getnameinfo( *ip_port, sizeof(struct sockaddr_storage), &buf[0], sizeof(buf), NULL, 0, 0 ); 230 ret = getnameinfo( *ip_port, sizeof(struct sockaddr_storage), &buf[0], sizeof(buf), NULL, 0, 0 );
225 if (ret) { 231 if (ret) {
226 TRACE_DEBUG(INFO, "Unable to resolve peer name: %s", gai_strerror(ret)); 232 TRACE_DEBUG(INFO, "Unable to resolve peer name: %s", gai_strerror(ret));
227 return EINVAL; 233 return EINVAL;
228 } 234 }
235 fqdn = &buf[0];
236 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&fqdn, &fqdn_len, 1),
237 {
238 TRACE_DEBUG(INFO, "Unable to use resolved peer name '%s' as DiameterIdentity: %s", buf, strerror(ret));
239 return ret;
240 } );
229 } 241 }
230 242
231 /* Create the new object */ 243 /* Create the new object */
232 CHECK_MALLOC( tmp = malloc(sizeof (struct rgw_client)) ); 244 CHECK_MALLOC( tmp = malloc(sizeof (struct rgw_client)) );
233 memset(tmp, 0, sizeof(struct rgw_client)); 245 memset(tmp, 0, sizeof(struct rgw_client));
243 255
244 if (loc) { 256 if (loc) {
245 tmp->is_local = 1; 257 tmp->is_local = 1;
246 } else { 258 } else {
247 /* Copy the fqdn */ 259 /* Copy the fqdn */
248 CHECK_MALLOC( tmp->fqdn = strdup(buf) ); 260 tmp->fqdn = fqdn;
249 tmp->fqdn_len = strlen(tmp->fqdn); 261 tmp->fqdn_len = fqdn_len;
262
250 /* Find an appropriate realm */ 263 /* Find an appropriate realm */
251 tmp->realm = strchr(tmp->fqdn, '.'); 264 tmp->realm = strchr(fqdn, '.');
252 if (tmp->realm) 265 if (tmp->realm) {
253 tmp->realm += 1; 266 tmp->realm += 1;
254 if ((!tmp->realm) || (*tmp->realm == '\0')) /* in case the fqdn was "localhost." for example, if it is possible... */ 267 tmp->realm_len = tmp->fqdn_len - (tmp->realm - fqdn);
268 }
269 if ((!tmp->realm) || (*tmp->realm == '\0')) { /* in case the fqdn was "localhost." for example, if it is possible... */
255 tmp->realm = fd_g_config->cnf_diamrlm; 270 tmp->realm = fd_g_config->cnf_diamrlm;
271 tmp->realm_len = fd_g_config->cnf_diamrlm_len;
272 }
256 } 273 }
257 274
258 /* move the sa info reference */ 275 /* move the sa info reference */
259 tmp->sa = *ip_port; 276 tmp->sa = *ip_port;
260 *ip_port = NULL; 277 *ip_port = NULL;
279 /* to be sure: the refcount should be 0 only when client_fini is called */ 296 /* to be sure: the refcount should be 0 only when client_fini is called */
280 ASSERT( FD_IS_LIST_EMPTY(&client->chain) ); 297 ASSERT( FD_IS_LIST_EMPTY(&client->chain) );
281 298
282 /* Free the data */ 299 /* Free the data */
283 for (idx = 0; idx < client->aliases_nb; idx++) 300 for (idx = 0; idx < client->aliases_nb; idx++)
284 free(client->aliases[idx]); 301 free(client->aliases[idx].name);
285 free(client->aliases); 302 free(client->aliases);
286 free(client->fqdn); 303 free(client->fqdn);
287 free(client->sa); 304 free(client->sa);
288 free(client->key.data); 305 free(client->key.data);
289 306
529 int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client * cli, struct msg ** diam) 546 int rgw_clients_create_origin(struct rgw_radius_msg_meta *msg, struct rgw_client * cli, struct msg ** diam)
530 { 547 {
531 int idx; 548 int idx;
532 int valid_nas_info = 0; 549 int valid_nas_info = 0;
533 struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL; 550 struct radius_attr_hdr *nas_ip = NULL, *nas_ip6 = NULL, *nas_id = NULL;
534 char * oh_str = NULL; 551 size_t nas_id_len;
535 char * or_str = NULL; 552 char * oh_str = NULL; size_t oh_strlen; int oh_free = 0;
536 char * rr_str = NULL; 553 char * or_str = NULL; size_t or_strlen;
554 char * rr_str = NULL; size_t rr_strlen;
537 char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */ 555 char buf[REVERSE_DNS_SIZE_MAX]; /* to store DNS lookups results */
538 556
539 struct avp *avp = NULL; 557 struct avp *avp = NULL;
540 union avp_value avp_val; 558 union avp_value avp_val;
541 559
552 continue; 570 continue;
553 } 571 }
554 572
555 if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) { 573 if ((attr->type == RADIUS_ATTR_NAS_IDENTIFIER) && (attr_len > 0)) {
556 nas_id = attr; 574 nas_id = attr;
575 nas_id_len = attr_len;
557 continue; 576 continue;
558 } 577 }
559 578
560 if ((attr->type == RADIUS_ATTR_NAS_IPV6_ADDRESS) && (attr_len = 16)) { 579 if ((attr->type == RADIUS_ATTR_NAS_IPV6_ADDRESS) && (attr_len = 16)) {
561 nas_ip6 = attr; 580 nas_ip6 = attr;
565 584
566 if (!nas_ip && !nas_ip6 && !nas_id) { 585 if (!nas_ip && !nas_ip6 && !nas_id) {
567 TRACE_DEBUG(FULL, "The message does not contain any NAS identification attribute."); 586 TRACE_DEBUG(FULL, "The message does not contain any NAS identification attribute.");
568 587
569 /* Get information on this peer */ 588 /* Get information on this peer */
570 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 589 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
571 590
572 goto diameter; 591 goto diameter;
573 } 592 }
574 593
575 /* Check if the message was received from the IP in NAS-IP-Address attribute */ 594 /* Check if the message was received from the IP in NAS-IP-Address attribute */
616 if (!valid_nas_info) { 635 if (!valid_nas_info) {
617 if ((!cli->is_local) && (cli->type == RGW_CLI_NAS)) { 636 if ((!cli->is_local) && (cli->type == RGW_CLI_NAS)) {
618 TRACE_DEBUG(INFO, "Message received with a NAS-IP-Address or NAS-IPv6-Address different \nfrom the sender's. Please configure as Proxy if this is expected.\n Message discarded."); 637 TRACE_DEBUG(INFO, "Message received with a NAS-IP-Address or NAS-IPv6-Address different \nfrom the sender's. Please configure as Proxy if this is expected.\n Message discarded.");
619 return EINVAL; 638 return EINVAL;
620 } else { 639 } else {
640 int ret;
641 sSS ss;
621 /* the peer is configured as a proxy, or running on localhost, so accept the message */ 642 /* the peer is configured as a proxy, or running on localhost, so accept the message */
622 sSS ss;
623 643
624 /* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */ 644 /* In that case, the cli will be stored as Route-Record and the NAS-IP-Address as origin */
625 if (!cli->is_local) { 645 if (!cli->is_local) {
626 rr_str = cli->fqdn; 646 rr_str = cli->fqdn;
647 rr_strlen = cli->fqdn_len;
627 } 648 }
628 649
629 /* We must DNS-reverse the NAS-IP*-Address */ 650 /* We must DNS-reverse the NAS-IP*-Address */
630 memset(&ss, 0 , sizeof(sSS)); 651 memset(&ss, 0 , sizeof(sSS));
631 if (nas_ip) { 652 if (nas_ip) {
638 memcpy(&sin6->sin6_addr, nas_ip6 + 1, sizeof(struct in6_addr)); 659 memcpy(&sin6->sin6_addr, nas_ip6 + 1, sizeof(struct in6_addr));
639 } 660 }
640 CHECK_SYS_DO( getnameinfo( (sSA *)&ss, sSAlen(&ss), &buf[0], sizeof(buf), NULL, 0, NI_NAMEREQD), 661 CHECK_SYS_DO( getnameinfo( (sSA *)&ss, sSAlen(&ss), &buf[0], sizeof(buf), NULL, 0, NI_NAMEREQD),
641 { 662 {
642 if (cli->is_local) { 663 if (cli->is_local) {
643 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 664 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
644 goto diameter; 665 goto diameter;
645 } 666 }
646 667
647 TRACE_DEBUG(INFO, "The NAS-IP*-Address cannot be DNS reversed in order to create the Origin-Host AVP; rejecting the message (translation is impossible)."); 668 TRACE_DEBUG(INFO, "The NAS-IP*-Address cannot be DNS reversed in order to create the Origin-Host AVP; rejecting the message (translation is impossible).");
648 return EINVAL; 669 return EINVAL;
649 } ); 670 } );
671
672 oh_str = &buf[0];
673 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
674 {
675 if (cli->is_local) {
676 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
677 goto diameter;
678 }
679
680 TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
681 return ret;
682 } );
683 oh_free = 1;
650 684
651 oh_str = &buf[0];
652 or_str = strchr(oh_str, '.'); 685 or_str = strchr(oh_str, '.');
653 if (or_str) { 686 if (or_str) {
654 or_str ++; /* move after the first dot */ 687 or_str ++; /* move after the first dot */
655 if (*or_str == '\0') 688 if (*or_str == '\0')
656 or_str = NULL; /* Discard this realm, we will use the local realm later */ 689 or_str = NULL; /* Discard this realm, we will use the local realm later */
690 else
691 or_strlen = oh_strlen - (or_str - oh_str);
657 } 692 }
658 } 693 }
659 } else { 694 } else {
660 /* The attribute matches the source address, just use this in origin-host */ 695 /* The attribute matches the source address, just use this in origin-host */
661 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 696 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
662 } 697 }
663 698
664 goto diameter; /* we ignore the nas_id in that case */ 699 goto diameter; /* we ignore the nas_id in that case */
665 } 700 }
666 701
667 /* We don't have a NAS-IP*-Address attribute if we are here */ 702 /* We don't have a NAS-IP*-Address attribute if we are here */
668 if (cli->is_local) { 703 if (cli->is_local) {
669 /* Simple: we use our own configuration */ 704 /* Simple: we use our own configuration */
670 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 705 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
671 goto diameter; 706 goto diameter;
672 } 707 }
673 708
674 /* At this point, we only have nas_id, and the client is not local */ 709 /* At this point, we only have nas_id, and the client is not local */
675 ASSERT(nas_id); 710 ASSERT(nas_id);
694 corresponds to an entry in the Route-Record AVP. If no match is 729 corresponds to an entry in the Route-Record AVP. If no match is
695 found, then an error is logged, but no other action is taken. 730 found, then an error is logged, but no other action is taken.
696 */ 731 */
697 732
698 /* first, check if the nas_id is the fqdn of the peer or a known alias */ 733 /* first, check if the nas_id is the fqdn of the peer or a known alias */
699 if ((cli->fqdn_len == (nas_id->length - sizeof(struct radius_attr_hdr))) 734 if (!fd_os_almostcasecmp(nas_id + 1, nas_id_len,
700 && (!strncasecmp((char *)(nas_id + 1), cli->fqdn, nas_id->length - sizeof(struct radius_attr_hdr)))) { 735 cli->fqdn, cli->fqdn_len)) {
701 TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client"); 736 TRACE_DEBUG(FULL, "NAS-Identifier contains the fqdn of the client");
702 found = 1; 737 found = 1;
703 } else { 738 } else {
704 for (idx = 0; idx < cli->aliases_nb; idx++) { 739 for (idx = 0; idx < cli->aliases_nb; idx++) {
705 if (((nas_id->length - sizeof(struct radius_attr_hdr)) == strlen(cli->aliases[idx])) 740 if (!fd_os_cmp(nas_id + 1, nas_id_len,
706 && (!strncasecmp((char *)(nas_id + 1), cli->aliases[idx], nas_id->length - sizeof(struct radius_attr_hdr)))) { 741 cli->aliases[idx].name, cli->aliases[idx].len)) {
707 TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache"); 742 TRACE_DEBUG(FULL, "NAS-Identifier valid value found in the cache");
708 found = 1; 743 found = 1;
709 break; 744 break;
710 } 745 }
711 } 746 }
712 } 747 }
713 748
714 if (found) { 749 if (found) {
715 /* The NAS-Identifier matches the source IP */ 750 /* The NAS-Identifier matches the source IP */
716 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 751 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
717 752
718 goto diameter; 753 goto diameter;
719 } 754 }
720 755
721 /* Attempt DNS resolution of the identifier */ 756 /* Attempt DNS resolution of the identifier */
722 ASSERT( nas_id->length - sizeof(struct radius_attr_hdr) < sizeof(buf) ); 757 ASSERT( nas_id_len < sizeof(buf) );
723 memcpy(buf, nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr)); 758 memcpy(buf, nas_id + 1, nas_id_len);
724 buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0'; 759 buf[nas_id->length - sizeof(struct radius_attr_hdr)] = '\0';
725 760
726 /* Now check if this alias is valid for this peer */ 761 /* Now check if this alias is valid for this peer */
727 memset(&hint, 0, sizeof(hint)); 762 memset(&hint, 0, sizeof(hint));
728 hint.ai_flags = AI_CANONNAME; 763 hint.ai_flags = AI_CANONNAME;
742 freeaddrinfo(res); 777 freeaddrinfo(res);
743 778
744 if (!found) { 779 if (!found) {
745 if (cli->type == RGW_CLI_NAS) { 780 if (cli->type == RGW_CLI_NAS) {
746 TRACE_DEBUG(INFO, "The NAS-Identifier value '%.*s' resolves to a different IP than the client's, discarding the message. \nConfigure this client as a Proxy if this message should be valid.", 781 TRACE_DEBUG(INFO, "The NAS-Identifier value '%.*s' resolves to a different IP than the client's, discarding the message. \nConfigure this client as a Proxy if this message should be valid.",
747 nas_id->length - sizeof(struct radius_attr_hdr), nas_id + 1); 782 nas_id_len, nas_id + 1);
748 return EINVAL; 783 return EINVAL;
749 } else { 784 } else {
750 /* This identifier matches a different IP, assume it is a proxied message */ 785 /* This identifier matches a different IP, assume it is a proxied message */
751 if (!cli->is_local) { 786 if (!cli->is_local) {
752 rr_str = cli->fqdn; 787 rr_str = cli->fqdn;
788 rr_strlen = cli->fqdn_len;
753 } 789 }
754 oh_str = &buf[0]; /* The canonname resolved */ 790 oh_str = &buf[0]; /* The canonname resolved */
791 CHECK_FCT_DO( ret = fd_os_validate_DiameterIdentity(&oh_str, &oh_strlen, 1),
792 {
793 TRACE_DEBUG(INFO, "Unable to use resolved client name '%s' as DiameterIdentity: %s", buf, strerror(ret));
794 return ret;
795 } );
796 oh_free = 1;
755 or_str = strchr(oh_str, '.'); 797 or_str = strchr(oh_str, '.');
756 if (or_str) { 798 if (or_str) {
757 or_str ++; /* move after the first dot */ 799 or_str ++; /* move after the first dot */
758 if (*or_str == '\0') 800 if (*or_str == '\0')
759 or_str = NULL; /* Discard this realm, we will use the local realm later */ 801 or_str = NULL; /* Discard this realm, we will use the local realm later */
802 else
803 or_strlen = oh_strlen - (or_str - oh_str);
760 } 804 }
761 } 805 }
762 } else { 806 } else {
763 /* It is a valid alias, save it */ 807 /* It is a valid alias, save it */
764 CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(char *)) ); 808 CHECK_MALLOC( cli->aliases = realloc(cli->aliases, (cli->aliases_nb + 1) * sizeof(cli->aliases[0])) );
765 CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1] = malloc( 1 + nas_id->length - sizeof(struct radius_attr_hdr) )); 809
766 memcpy( cli->aliases[cli->aliases_nb + 1], nas_id + 1, nas_id->length - sizeof(struct radius_attr_hdr)); 810 CHECK_MALLOC( cli->aliases[cli->aliases_nb + 1].name = os0dup(nas_id + 1, nas_id_len ) );
767 *(cli->aliases[cli->aliases_nb + 1] + nas_id->length - sizeof(struct radius_attr_hdr)) = '\0'; 811 cli->aliases[cli->aliases_nb + 1].len = nas_id_len;
812
768 cli->aliases_nb ++; 813 cli->aliases_nb ++;
769 TRACE_DEBUG(FULL, "Saved valid alias for client: '%s' -> '%s'", cli->aliases[cli->aliases_nb + 1], cli->fqdn); 814 TRACE_DEBUG(FULL, "Saved valid alias for client: '%.*s' -> '%s'", nas_id_len, nas_id + 1, cli->fqdn);
770 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 815 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
771 } 816 }
772 } else { 817 } else {
773 /* Error resolving the name */ 818 /* Error resolving the name */
774 TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret)); 819 TRACE_DEBUG(INFO, "NAS-Identifier '%s' cannot be resolved: %s. Ignoring...", buf, gai_strerror(ret));
775 /* Assume this is a valid identifier for the client */ 820 /* Assume this is a valid identifier for the client */
776 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &or_str) ); 821 CHECK_FCT( rgw_clients_get_origin(cli, &oh_str, &oh_strlen, &or_str, &or_strlen) );
777 } 822 }
778 } 823 }
779 824
780 /* Now, let's create the empty Diameter message with Origin-Host, -Realm, and Route-Record if needed. */ 825 /* Now, let's create the empty Diameter message with Origin-Host, -Realm, and Route-Record if needed. */
781 diameter: 826 diameter:
782 ASSERT(oh_str); /* If it is not defined here, there is a bug... */ 827 ASSERT(oh_str); /* If it is not defined here, there is a bug... */
783 if (!or_str) 828 if (!or_str) {
784 or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */ 829 or_str = fd_g_config->cnf_diamrlm; /* Use local realm in that case */
830 or_strlen = fd_g_config->cnf_diamrlm_len;
831 }
785 832
786 /* Create an empty Diameter message so that extensions can store their AVPs */ 833 /* Create an empty Diameter message so that extensions can store their AVPs */
787 CHECK_FCT( fd_msg_new ( NULL, MSGFL_ALLOC_ETEID, diam ) ); 834 CHECK_FCT( fd_msg_new ( NULL, MSGFL_ALLOC_ETEID, diam ) );
788 835
789 /* Add the Origin-Host as next AVP */ 836 /* Add the Origin-Host as next AVP */
790 CHECK_FCT( fd_msg_avp_new ( cache_orig_host, 0, &avp ) ); 837 CHECK_FCT( fd_msg_avp_new ( cache_orig_host, 0, &avp ) );
791 memset(&avp_val, 0, sizeof(avp_val)); 838 memset(&avp_val, 0, sizeof(avp_val));
792 avp_val.os.data = (unsigned char *)oh_str; 839 avp_val.os.data = (unsigned char *)oh_str;
793 avp_val.os.len = strlen(oh_str); 840 avp_val.os.len = oh_strlen;
794 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 841 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
795 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); 842 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
796 843
797 /* Add the Origin-Realm as next AVP */ 844 /* Add the Origin-Realm as next AVP */
798 CHECK_FCT( fd_msg_avp_new ( cache_orig_realm, 0, &avp ) ); 845 CHECK_FCT( fd_msg_avp_new ( cache_orig_realm, 0, &avp ) );
799 memset(&avp_val, 0, sizeof(avp_val)); 846 memset(&avp_val, 0, sizeof(avp_val));
800 avp_val.os.data = (unsigned char *)or_str; 847 avp_val.os.data = (unsigned char *)or_str;
801 avp_val.os.len = strlen(or_str); 848 avp_val.os.len = or_strlen;
802 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 849 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
803 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); 850 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
804 851
805 if (rr_str) { 852 if (rr_str) {
806 CHECK_FCT( fd_msg_avp_new ( cache_route_record, 0, &avp ) ); 853 CHECK_FCT( fd_msg_avp_new ( cache_route_record, 0, &avp ) );
807 memset(&avp_val, 0, sizeof(avp_val)); 854 memset(&avp_val, 0, sizeof(avp_val));
808 avp_val.os.data = (unsigned char *)rr_str; 855 avp_val.os.data = (unsigned char *)rr_str;
809 avp_val.os.len = strlen(rr_str); 856 avp_val.os.len = rr_strlen;
810 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) ); 857 CHECK_FCT( fd_msg_avp_setvalue ( avp, &avp_val ) );
811 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) ); 858 CHECK_FCT( fd_msg_avp_add ( *diam, MSG_BRW_LAST_CHILD, avp) );
812 } 859 }
813 860
861 if (oh_free)
862 free(oh_str);
863
814 /* Done! */ 864 /* Done! */
815 return 0; 865 return 0;
816 } 866 }
817 867
818 int rgw_clients_get_origin(struct rgw_client *cli, char **fqdn, char **realm) 868 int rgw_clients_get_origin(struct rgw_client *cli, DiamId_t *fqdn, size_t *fqdnlen, DiamId_t *realm, size_t *realmlen)
819 { 869 {
820 TRACE_ENTRY("%p %p %p", cli, fqdn, realm); 870 TRACE_ENTRY("%p %p %p %p %p", cli, fqdn, fqdnlen, realm, realmlen);
821 CHECK_PARAMS(cli && fqdn); 871 CHECK_PARAMS(cli && fqdn && fqdnlen);
822 872
823 if (cli->is_local) { 873 if (cli->is_local) {
824 *fqdn = fd_g_config->cnf_diamid; 874 *fqdn = fd_g_config->cnf_diamid;
875 *fqdnlen = fd_g_config->cnf_diamid_len;
825 if (realm) 876 if (realm)
826 *realm= fd_g_config->cnf_diamrlm; 877 *realm= fd_g_config->cnf_diamrlm;
878 if (realmlen)
879 *realmlen= fd_g_config->cnf_diamrlm_len;
827 } else { 880 } else {
828 *fqdn = cli->fqdn; 881 *fqdn = cli->fqdn;
882 *fqdnlen = cli->fqdn_len;
829 if (realm) 883 if (realm)
830 *realm= cli->realm; 884 *realm= cli->realm;
885 if (realmlen)
886 *realmlen= cli->realm_len;
831 } 887 }
832 888
833 return 0; 889 return 0;
834 } 890 }
835 891
"Welcome to our mercurial repository"