📄 aaa_route_msg_router.cxx
字号:
/* BEGIN_COPYRIGHT *//* *//* Open Diameter: Open-source software for the Diameter and *//* Diameter related protocols *//* *//* Copyright (C) 2002-2004 Open Diameter Project *//* *//* This library is free software; you can redistribute it and/or modify *//* it under the terms of the GNU Lesser General Public License as *//* published by the Free Software Foundation; either version 2.1 of the *//* License, or (at your option) any later version. *//* *//* This library is distributed in the hope that it will be useful, *//* but WITHOUT ANY WARRANTY; without even the implied warranty of *//* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *//* Lesser General Public License for more details. *//* *//* You should have received a copy of the GNU Lesser General Public *//* License along with this library; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *//* USA. *//* *//* In addition, when you copy and redistribute some or the entire part of *//* the source code of this software with or without modification, you *//* MUST include this copyright notice in each copy. *//* *//* If you make any changes that are appeared to be useful, please send *//* sources that include the changed part to *//* diameter-developers@lists.sourceforge.net so that we can reflect your *//* changes to one unified version of this software. *//* *//* END_COPYRIGHT */#include "aaa_data_defs.h"#include "aaa_route_table.h"#include "aaa_peer_table.h"#include "aaa_route_msg_router.h"#include "resultcodes.h"/* 6.1. Diameter Request Routing Overview A request is sent towards its final destination using a combination of the Destination-Realm and Destination-Host AVPs, in one of these three combinations: - a request that is not able to be proxied (such as CER) MUST NOT contain either Destination-Realm or Destination-Host AVPs. - a request that needs to be sent to a home server serving a specific realm, but not to a specific server (such as the first request of a series of round-trips), MUST contain a Destination- Realm AVP, but MUST NOT contain a Destination-Host AVP. - otherwise, a request that needs to be sent to a specific home server among those serving a given realm, MUST contain both the Destination-Realm and Destination-Host AVPs. The Destination-Host AVP is used as described above when the destination of the request is fixed, which includes: - Authentication requests that span multiple round trips - A Diameter message that uses a security mechanism that makes use of a pre-established session key shared between the source and the final destination of the message. - Server initiated messages that MUST be received by a specific Diameter client (e.g., access device), such as the Abort-Session- Request message, which is used to request that a particular user's session be terminated. Note that an agent can forward a request to a host described in the Destination-Host AVP only if the host in question is included in its peer table (see Section 2.7). Otherwise, the request is routed based on the Destination-Realm only (see Sections 6.1.6). The Destination-Realm AVP MUST be present if the message is proxiable. Request messages that may be forwarded by Diameter agents (proxies, redirects or relays) MUST also contain an Acct- Application-Id AVP, an Auth-Application-Id AVP or a Vendor-Specific- Application-Id AVP. A message that MUST NOT be forwarded by Diameter agents (proxies, redirects or relays) MUST not include the Destination-Realm in its ABNF. The value of the Destination-Realm AVP MAY be extracted from the User-Name AVP, or other application- specific methods. When a message is received, the message is processed in the following order: 1. If the message is destined for the local host, the procedures listed in Section 6.1.4 are followed. 2. If the message is intended for a Diameter peer with whom the local host is able to directly communicate, the procedures listed in Section 6.1.5 are followed. This is known as Request Forwarding. 3. The procedures listed in Section 6.1.6 are followed, which is known as Request Routing. 4. If none of the above is successful, an answer is returned with the Result-Code set to AAA_UNABLE_TO_DELIVER, with the E-bit set. For routing of Diameter messages to work within an administrative domain, all Diameter nodes within the realm MUST be peers. Note the processing rules contained in this section are intended to be used as general guidelines to Diameter developers. Certain implementations MAY use different methods than the ones described here, and still comply with the protocol specification. See Section 7 for more detail on error handling.*/AAA_ROUTE_RESULT AAA_MsgRouter::RcLocal::Lookup(std::auto_ptr<AAAMessage> &msg, AAA_PeerEntry *&dest){ /* 6.1.4. Processing Local Requests A request is known to be for local consumption when one of the following conditions occur: - The Destination-Host AVP contains the local host's identity, - The Destination-Host AVP is not present, the Destination-Realm AVP contains a realm the server is configured to process locally, and the Diameter application is locally supported, or - Both the Destination-Host and the Destination-Realm are not present. When a request is locally processed, the rules in Section 6.2 should be used to generate the corresponding answer. */ AAA_IdentityAvpContainerWidget destHost(msg->acl); AAA_IdentityAvpContainerWidget destRealm(msg->acl); diameter_identity_t *DestHost = destHost.GetAvp(AAA_AVPNAME_DESTHOST); diameter_identity_t *DestRealm = destRealm.GetAvp(AAA_AVPNAME_DESTREALM); if (DestHost) { if (*DestHost == AAA_CFG_TRANSPORT()->identity) { return (AAA_ROUTE_RESULT_SUCCESS); } AAA_LOG(LM_INFO, "(%P|%t) DestHost(%s) present but not ours so try realm routing\n", DestHost->data()); // next chain } else if (DestRealm) { if (*DestRealm == AAA_CFG_TRANSPORT()->realm) { AAA_ApplicationIdLst *idList[] = { &AAA_CFG_GENERAL()->supportedVendorIdLst, &AAA_CFG_GENERAL()->authAppIdLst, &AAA_CFG_GENERAL()->acctAppIdLst }; for (int i=0; i<sizeof(idList)/sizeof(AAA_ApplicationIdLst*); i++) { AAA_ApplicationIdLst::iterator x = idList[i]->begin(); for (; x != idList[i]->end(); x++) { if (*x == msg->hdr.appId) { return (AAA_ROUTE_RESULT_SUCCESS); } } } AAA_VendorSpecificIdLst::iterator y = AAA_CFG_GENERAL()->vendorSpecificId.begin(); for (; y != AAA_CFG_GENERAL()->vendorSpecificId.end(); y++) { if (((*y).authAppId == msg->hdr.appId) || ((*y).acctAppId == msg->hdr.appId)) { return (AAA_ROUTE_RESULT_SUCCESS); } } } AAA_LOG(LM_INFO, "(%P|%t) DestRealm(%s) present but no ours or no supported id\n", DestRealm->data()); // next chain } else { return (AAA_ROUTE_RESULT_SUCCESS); } return (AAA_ROUTE_RESULT_NEXT_CHAIN);}AAA_ROUTE_RESULT AAA_MsgRouter::RcForwarded::Lookup(std::auto_ptr<AAAMessage> &msg, AAA_PeerEntry *&dest){ /* 6.1.5. Request Forwarding Request forwarding is done using the Diameter Peer Table. The Diameter peer table contains all of the peers that the local node is able to directly communicate with. When a request is received, and the host encoded in the Destination- Host AVP is one that is present in the peer table, the message SHOULD be forwarded to the peer. */ AAA_IdentityAvpContainerWidget destHost(msg->acl); diameter_identity_t *DestHost = destHost.GetAvp(AAA_AVPNAME_DESTHOST); if (DestHost) { AAA_PeerEntry *peer = AAA_PEER_TABLE()->Lookup(*DestHost); if (peer) { if (peer->IsOpen()) { dest = peer; return (AAA_ROUTE_RESULT_SUCCESS); } // try routing it } AAA_LOG(LM_INFO, "(%P|%t) DestHost(%s) does not match any peer\n", DestHost->data()); } return (AAA_ROUTE_RESULT_NEXT_CHAIN);}AAA_ROUTE_RESULT AAA_MsgRouter::RcRouted::Lookup(std::auto_ptr<AAAMessage> &msg, AAA_PeerEntry *&dest){ /* 6.1.6. Request Routing Diameter request message routing is done via realms and applications. A Diameter message that may be forwarded by Diameter agents (proxies, redirects or relays) MUST include the target realm in the Destination-Realm AVP and one of the application identification AVPs Auth-Application-Id, Acct-Application-Id or Vendor-Specific- Application-Id. The realm MAY be retrieved from the User-Name AVP, which is in the form of a Network Access Identifier (NAI). The realm portion of the NAI is inserted in the Destination-Realm AVP. Diameter agents MAY have a list of locally supported realms and applications, and MAY have a list of externally supported realms and applications. When a request is received that includes a realm and/or application that is not locally supported, the message is routed to the peer configured in the Realm Routing Table (see Section 2.7). */ try { diameter_identity_t DestRealm; AAA_IdentityAvpContainerWidget destRealm(msg->acl); diameter_identity_t *LookupRealm = destRealm.GetAvp(AAA_AVPNAME_DESTREALM); if (! LookupRealm) { AAA_Utf8AvpContainerWidget username(msg->acl); diameter_utf8string_t *UserName = username.GetAvp(AAA_AVPNAME_USERNAME); if (! UserName) { AAA_LOG(LM_INFO, "(%P|%t) Can't determin DestRealm during realm routing\n"); throw (0); } DestRealm = UserName->substr(UserName->find("@",0), UserName->length()-1); } else { DestRealm.assign(LookupRealm->data(), LookupRealm->length()); } AAA_RouteEntry *route = AAA_ROUTE_TABLE()->Lookup(DestRealm); if (route == NULL) { AAA_LOG(LM_INFO, "(%P|%t) DestRealm(%s) not in routing table\n", DestRealm.data()); throw (0); } diameter_unsigned32_t *idPtr; char *avpNames[] = { AAA_AVPNAME_AUTHAPPID, AAA_AVPNAME_ACCTAPPID }; AAA_UInt32AvpContainerWidget id(msg->acl); for (int i=0; i<sizeof(avpNames)/sizeof(char*); i++) { if ((idPtr = id.GetAvp(avpNames[i]))) { break; } } AAA_RouteApplication *app = NULL; if (idPtr) { app = route->Lookup(*idPtr, 0); // base protocol only } else { AAA_GroupedAvpContainerWidget vendorSpecificId(msg->acl); diameter_grouped_t *grouped = vendorSpecificId.GetAvp (AAA_AVPNAME_VENDORAPPID); if (grouped) { AAA_ApplicationIdLst vendorIdLst; AAA_UInt32AvpContainerWidget gVendorId(*grouped); diameter_unsigned32_t *value = gVendorId.GetAvp(AAA_AVPNAME_VENDORID); for (int p=1; value; p++) { vendorIdLst.push_back(*value); value = gVendorId.GetAvp(AAA_AVPNAME_VENDORID, p); } char *avpNames[] = { AAA_AVPNAME_AUTHAPPID, AAA_AVPNAME_ACCTAPPID }; AAA_UInt32AvpContainerWidget gId(*grouped); for (int i=0; i<sizeof(avpNames)/sizeof(char*); i++) { if ((value = gId.GetAvp(avpNames[i]))) { break; } } if (value) { AAA_ApplicationIdLst::iterator i = vendorIdLst.begin(); for (; (app == NULL) && (i != vendorIdLst.end()); i++) { if ((app = route->Lookup(*value, *i))) { break; } } } } } if (app) { // get the first available/open peer AAA_PeerEntry *peer = NULL; AAA_RouteServerEntry *server = app->Servers().First(); while (server) { peer = AAA_PEER_TABLE()->Lookup(server->Server()); if (peer && peer->IsOpen()) { dest = peer; return (AAA_ROUTE_RESULT_SUCCESS); } server = app->Servers().Next(*server); } AAA_LOG(LM_INFO, "(%P|%t) DestRealm(%s) in routing table but no open peers support it\n", DestRealm.data()); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -