Mercurial > hg > freeDiameter
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 |