📄 aaa_route_msg_router.cxx
字号:
else { AAA_LOG(LM_INFO, "(%P|%t) DestRealm(%s) in routing table but no matching app Id\n", DestRealm.data()); } } catch (...) { } return (AAA_ROUTE_RESULT_NEXT_CHAIN);}AAA_ROUTE_RESULT AAA_MsgRouter::RcRejected::Lookup(std::auto_ptr<AAAMessage> &msg, AAA_PeerEntry *&dest){ /* 6.1. Diameter Request Routing Overview . . . 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. */ AAA_LOG(LM_INFO, "(%P|%t) Router cannot deliver message, sending back with an error\n"); return (AAA_ROUTE_RESULT_SUCCESS);}AAA_ROUTE_RESULT AAA_MsgRouter::DcLocal::Process(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ if (m_Arg.m_RedirectAgent.IsRedirected(msg)) { return (m_Arg.m_RedirectAgent.Answer(msg, source, dest) == 0) ? AAA_ROUTE_RESULT_SUCCESS: AAA_ROUTE_RESULT_FAILED; } if (msg->hdr.flags.e) { return ErrorHandling(msg, source, dest); } else if (dest) { return (dest->Send(msg) >= 0) ? AAA_ROUTE_RESULT_SUCCESS: AAA_ROUTE_RESULT_FAILED; } else { // original request must have been locally generated m_Arg[AAA_MsgRouterHandlerTable::H_LOCAL]-> Answer(msg, source, dest); } return (AAA_ROUTE_RESULT_SUCCESS);}AAA_ROUTE_RESULT AAA_MsgRouter::DcLocal::ErrorHandling(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ /* Result-Code AVP values that are used to report protocol errors MUST only be present in answer messages whose 'E' bit is set. When a request message is received that causes a protocol error, an answer message is returned with the 'E' bit set, and the Result-Code AVP is set to the appropriate protocol error value. As the answer is sent back towards the originator of the request, each proxy or relay agent MAY take action on the message. 1. Request +---------+ Link Broken +-------------------------->|Diameter |----///----+ | +---------------------| | v +------+--+ | 2. answer + 'E' set | Relay 2 | +--------+ |Diameter |<-+ (Unable to Forward) +---------+ |Diameter| | | | Home | | Relay 1 |--+ +---------+ | Server | +---------+ | 3. Request |Diameter | +--------+ +-------------------->| | ^ | Relay 3 |-----------+ +---------+ Figure 7: Example of Protocol Error causing answer message Figure 7 provides an example of a message forwarded upstream by a Diameter relay. When the message is received by Relay 2, and it detects that it cannot forward the request to the home server, an answer message is returned with the 'E' bit set and the Result-Code AVP set to DIAMETER_UNABLE_TO_DELIVER. */ AAA_MsgResultCode rcode(*msg); switch (rcode.ResultCode()) { case AAA_UNABLE_TO_DELIVER: // TBD: Attempt to re-route default: if (dest) { return (dest->Send(msg) >= 0) ? AAA_ROUTE_RESULT_SUCCESS: AAA_ROUTE_RESULT_FAILED; } else { // original request must have been locally generated m_Arg[AAA_MsgRouterHandlerTable::H_ERROR]-> Answer(msg, source, dest); } break; } return (AAA_ROUTE_RESULT_SUCCESS);}int AAA_MsgRouter::DcLocal::RequestMsg(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ if (source) { Add(msg->hdr.hh, msg, source, dest); m_Arg[AAA_MsgRouterHandlerTable::H_LOCAL]-> Request(msg, source, dest); } else { AAA_LOG(LM_INFO, "(%P|%t) **** Looped back message, discarded ***\n"); AAA_MsgDump::Dump(*msg); } return (0);}AAA_ROUTE_RESULT AAA_MsgRouter::DcForward::Process(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ return m_Arg.m_rcLocal.Delivery().Process(msg, source, dest);}int AAA_MsgRouter::DcForward::LoopDetection(std::auto_ptr<AAAMessage> &msg){ /* A relay or proxy agent MUST check for forwarding loops when receiving requests. A loop is detected if the server finds its own identity in a Route-Record AVP. When such an event occurs, the agent MUST answer with the Result-Code AVP set to AAA_LOOP_DETECTED. */ AAA_IdentityAvpContainerWidget rrecord(msg->acl); diameter_identity_t *rteRec = rrecord.GetAvp(AAA_AVPNAME_ROUTERECORD); for (int p=1; rteRec; p++) { if (*rteRec == (AAA_CFG_TRANSPORT()->identity)) { // send back answer msg->hdr.flags.r = 0; AAA_MsgResultCode rcode(*msg); rcode.ResultCode(AAA_LOOP_DETECTED); AAA_LOG(LM_INFO, "(%P|%t) !!! WARNING !!!: Route record shows a loop in the message, sending back with error\n"); return (0); } rteRec = rrecord.GetAvp(AAA_AVPNAME_ROUTERECORD, p); } return (-1);}int AAA_MsgRouter::DcForward::RequestMsg(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ if (LoopDetection(msg) == 0) { if (source) { return (source->Send(msg) >= 0) ? 0 : (-1); } else { // request must have been locally generated m_Arg[AAA_MsgRouterHandlerTable::H_ERROR]-> Request(msg, source, dest); return (-1); } } /* The Diameter protocol requires that agents maintain transaction state, which is used for failover purposes. Transaction state implies that upon forwarding a request, the Hop-by-Hop identifier is saved; the field is replaced with a locally unique identifier, which is restored to its original value when the corresponding answer is received. The request's state is released upon receipt of the answer. A stateless agent is one that only maintains transaction state. */ int h2hIndex, rcode; if (source) { int localHH = AAA_HOPBYHOP_GEN()->Get(); h2hIndex = Add(localHH, msg, source, dest); msg->hdr.hh = localHH; } else { // locally generated if (msg->hdr.hh == 0) { msg->hdr.hh = AAA_HOPBYHOP_GEN()->Get(); } if (msg->hdr.ee == 0){ msg->hdr.ee = AAA_ENDTOEND_GEN()->Get(); } h2hIndex = Add(msg->hdr.hh, msg, source, dest); } rcode = (dest->Send(msg) >= 0) ? 0 : (-1); if (h2hIndex > 0) { StoreRequestMessage(h2hIndex, msg); } return rcode;}AAA_ROUTE_RESULT AAA_MsgRouter::DcRouted::Process(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ /* 6.2.2. Relaying and Proxying Answers If the answer is for a request which was proxied or relayed, the agent MUST restore the original value of the Diameter header's Hop- by-Hop Identifier field. If the last Proxy-Info AVP in the message is targeted to the local Diameter server, the AVP MUST be removed before the answer is forwarded. If a relay or proxy agent receives an answer with a Result-Code AVP indicating a failure, it MUST NOT modify the contents of the AVP. Any additional local errors detected SHOULD be logged, but not reflected in the Result-Code AVP. If the agent receives an answer message with a Result-Code AVP indicating success, and it wishes to modify the AVP to indicate an error, it MUST modify the Result-Code AVP to contain the appropriate error in the message destined towards the access device as well as include the Error-Reporting-Host AVP and it MUST issue an STR on behalf of the access device. The agent MUST then send the answer to the host that it received the original request from. */ if (m_Arg.m_RedirectAgent.IsRedirected(msg)) { return (m_Arg.m_RedirectAgent.Answer(msg, source, dest) == 0) ? AAA_ROUTE_RESULT_SUCCESS: AAA_ROUTE_RESULT_FAILED; } AAA_ROUTE_RESULT result = AAA_ROUTE_RESULT_SUCCESS; if (! dest) { // original request must have been locally generated AAA_MsgRouterHandlerTable::H_TYPE type = (msg->hdr.flags.e) ? AAA_MsgRouterHandlerTable::H_ERROR : AAA_MsgRouterHandlerTable::H_LOCAL; m_Arg[type]->Answer(msg, source, dest); } else { AAA_MsgRouterHandlerTable::H_TYPE type = (msg->hdr.flags.e) ? AAA_MsgRouterHandlerTable::H_ERROR : AAA_MsgRouterHandlerTable::H_PROXY; m_Arg[type]->Answer(msg, source, dest); result = (dest->Send(msg) >= 0) ? AAA_ROUTE_RESULT_SUCCESS : AAA_ROUTE_RESULT_FAILED; } return result;}int AAA_MsgRouter::DcRouted::RequestMsg(std::auto_ptr<AAAMessage> msg, AAA_PeerEntry *source, AAA_PeerEntry *dest){ AAA_IdentityAvpContainerWidget destRealm(msg->acl); diameter_identity_t *DestRealm = destRealm.GetAvp(AAA_AVPNAME_DESTREALM); if (! DestRealm) { throw (0); } AAA_RouteEntry *route = AAA_ROUTE_TABLE()->Lookup(*DestRealm); if (route == NULL) { throw (0); } if (route->Action() == AAA_ROUTE_ACTION_LOCAL) { return m_Arg.m_rcLocal.Delivery().RequestMsg(msg, source, dest); } else if (route->Action() == AAA_ROUTE_ACTION_REDIRECT) { return m_Arg.m_RedirectAgent.Request(msg, source, dest); } else { /* 6.1.8. Relaying and Proxying Requests A relay or proxy agent MUST append a Route-Record AVP to all requests forwarded. The AVP contains the identity of the peer the request was received from. The Hop-by-Hop identifier in the request is saved, and replaced with a locally unique value. The source of the request is also saved, which includes the IP address, port and protocol. A relay or proxy agent MAY include the Proxy-Info AVP in requests if it requires access to any local state information when the corresponding response is received. Proxy-Info AVP has certain security implications and SHOULD contain an embedded HMAC with a node-local key. Alternatively, it MAY simply use local storage to store state information. The message is then forwarded to the next hop, as identified in the Realm Routing Table. Figure 6 provides an example of message routing using the procedures listed in these sections. (Origin-Host=nas.mno.net) (Origin-Host=nas.mno.net) (Origin-Realm=mno.net) (Origin-Realm=mno.net) (Destination-Realm=example.com) (Destination- Realm=example.com) (Route-Record=nas.example.net) +------+ ------> +------+ ------> +------+ | | (Request) | | (Request) | | | NAS +-------------------+ DRL +-------------------+ HMS | | | | | | | +------+ <------ +------+ <------ +------+ example.net (Answer) example.net (Answer) example.com (Origin-Host=hms.example.com) (Origin-Host=hms.example.com) (Origin-Realm=example.com) (Origin-Realm=example.com) Figure 6: Routing of Diameter messages */ if (m_Arg.m_rcForward.Delivery().LoopDetection(msg) == 0) { return (source->Send(msg) >= 0) ? 0 : (-1); } AAA_IdentityAvpWidget rrecord(AAA_AVPNAME_ROUTERECORD); rrecord.Get() = AAA_CFG_TRANSPORT()->identity; msg->acl.add(rrecord()); if (route->Action() == AAA_ROUTE_ACTION_PROXY) { if (m_Arg[AAA_MsgRouterHandlerTable::H_PROXY]-> Request(msg, source, dest) != 0) { // Proxy has enforced a policy. // Message will not be sent. return (0); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -