From 03eff44767f0cd06d5bd727369872e068c8bb92a Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Wed, 6 Mar 2024 14:18:34 -0500 Subject: [PATCH] Cache RADIUS packets during accounting instead of auth --- agents/radagent.go | 130 +++++++++--------- .../radius_coa_disconnect/accounting.json | 4 +- .../samples/radius_coa_disconnect/auth.json | 4 +- 3 files changed, 71 insertions(+), 67 deletions(-) diff --git a/agents/radagent.go b/agents/radagent.go index d898bd208..efc1076cf 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -151,22 +151,6 @@ func (ra *RadiusAgent) handleAuth(reqPacket *radigo.Packet) (*radigo.Packet, err }, } radDP := newRADataProvider(reqPacket) - sessionID, err := radDP.FieldAsString([]string{"Acct-Session-Id"}) - if err == nil { - _, err = varsDataNode.Set([]string{utils.MetaSessionID}, []*utils.DataNode{ - { - Type: utils.NMDataType, Value: &utils.DataLeaf{ - Data: sessionID, - }, - }, - }) - } - if err != nil { - utils.Logger.Warning(fmt.Sprintf( - "<%s> setting default *vars.*sessionID (used to track packets of active sessions) failed: %v", - utils.RadiusAgent, err)) - } - var processed bool var processReqErr error for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { @@ -193,6 +177,70 @@ func (ra *RadiusAgent) handleAuth(reqPacket *radigo.Packet) (*radigo.Packet, err utils.RadiusAgent, utils.ToJSON(reqPacket))) return nil, nil } + if err := radAppendAttributes(replyPacket, replyNM); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> err: %v, replying to message: %+v", + utils.RadiusAgent, err, utils.ToIJSON(reqPacket))) + return nil, err + } + return replyPacket, nil +} + +// handleAcct handles RADIUS Accounting request +// supports: Acct-Status-Type = Start, Interim-Update, Stop +func (ra *RadiusAgent) handleAcct(reqPacket *radigo.Packet) (*radigo.Packet, error) { + reqPacket.SetAVPValues() // populate string values in AVPs + replyPacket := reqPacket.Reply() + replyPacket.Code = radigo.AccountingResponse + cgrRplyNM := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} + rplyNM := utils.NewOrderedNavigableMap() + opts := utils.MapStorage{} + varsDataNode := &utils.DataNode{ + Type: utils.NMMapType, + Map: map[string]*utils.DataNode{ + utils.RemoteHost: utils.NewLeafNode(reqPacket.RemoteAddr().String()), + }, + } + radDP := newRADataProvider(reqPacket) + sessionID, err := radDP.FieldAsString([]string{"Acct-Session-Id"}) + if err == nil { + _, err = varsDataNode.Set([]string{utils.MetaSessionID}, []*utils.DataNode{ + { + Type: utils.NMDataType, Value: &utils.DataLeaf{ + Data: sessionID, + }, + }, + }) + } + if err != nil { + utils.Logger.Warning(fmt.Sprintf( + "<%s> setting default *vars.*sessionID (used to track packets of active sessions) failed: %v", + utils.RadiusAgent, err)) + } + var processed bool + var processedReqErr error + for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { + agReq := NewAgentRequest(radDP, varsDataNode, cgrRplyNM, rplyNM, opts, + reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, + utils.FirstNonEmpty(reqProcessor.Timezone, + config.CgrConfig().GeneralCfg().DefaultTimezone), + ra.filterS, nil) + var lclProcessed bool + if lclProcessed, processedReqErr = ra.processRequest(reqPacket, reqProcessor, agReq, replyPacket); lclProcessed { + processed = lclProcessed + } + if processedReqErr != nil || (lclProcessed && !reqProcessor.Flags.GetBool(utils.MetaContinue)) { + break + } + } + if processedReqErr != nil { + utils.Logger.Err(fmt.Sprintf("<%s> error: <%v> ignoring request: %s", + utils.RadiusAgent, processedReqErr, utils.ToJSON(reqPacket))) + return nil, nil + } else if !processed { + utils.Logger.Err(fmt.Sprintf("<%s> no request processor enabled, ignoring request %s", + utils.RadiusAgent, utils.ToIJSON(reqPacket))) + return nil, nil + } // Cache the RADIUS Packet for future CoA/Disconnect Requests. if ra.cgrCfg.RadiusAgentCfg().DMRTemplate != "" || ra.cgrCfg.RadiusAgentCfg().CoATemplate != "" { @@ -211,58 +259,14 @@ func (ra *RadiusAgent) handleAuth(reqPacket *radigo.Packet) (*radigo.Packet, err } } - if err := radAppendAttributes(replyPacket, replyNM); err != nil { - utils.Logger.Err(fmt.Sprintf("<%s> err: %v, replying to message: %+v", - utils.RadiusAgent, err, utils.ToIJSON(reqPacket))) + if err := radAppendAttributes(replyPacket, rplyNM); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> err: %v, replying to message: %s", + utils.RadiusAgent, err, utils.ToJSON(reqPacket))) return nil, err } return replyPacket, nil } -// handleAcct handles RADIUS Accounting request -// supports: Acct-Status-Type = Start, Interim-Update, Stop -func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err error) { - req.SetAVPValues() // populate string values in AVPs - dcdr := newRADataProvider(req) // dcdr will provide information from request - rpl = req.Reply() - rpl.Code = radigo.AccountingResponse - cgrRplyNM := &utils.DataNode{Type: utils.NMMapType, Map: map[string]*utils.DataNode{}} - rplyNM := utils.NewOrderedNavigableMap() - opts := utils.MapStorage{} - var processed bool - reqVars := &utils.DataNode{Type: utils.NMMapType, - Map: map[string]*utils.DataNode{utils.RemoteHost: utils.NewLeafNode(req.RemoteAddr().String())}} - for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors { - agReq := NewAgentRequest(dcdr, reqVars, cgrRplyNM, rplyNM, opts, - reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant, - utils.FirstNonEmpty(reqProcessor.Timezone, - config.CgrConfig().GeneralCfg().DefaultTimezone), - ra.filterS, nil) - var lclProcessed bool - if lclProcessed, err = ra.processRequest(req, reqProcessor, agReq, rpl); lclProcessed { - processed = lclProcessed - } - if err != nil || (lclProcessed && !reqProcessor.Flags.GetBool(utils.MetaContinue)) { - break - } - } - if err != nil { - utils.Logger.Err(fmt.Sprintf("<%s> error: <%s> ignoring request: %s, ", - utils.RadiusAgent, err.Error(), utils.ToIJSON(req))) - return nil, nil - } else if !processed { - utils.Logger.Err(fmt.Sprintf("<%s> no request processor enabled, ignoring request %s", - utils.RadiusAgent, utils.ToIJSON(req))) - return nil, nil - } - if err := radAppendAttributes(rpl, rplyNM); err != nil { - utils.Logger.Err(fmt.Sprintf("<%s> err: %s, replying to message: %+v", - utils.RadiusAgent, err.Error(), utils.ToIJSON(req))) - return nil, err - } - return -} - // processRequest represents one processor processing the request func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.RequestProcessor, agReq *AgentRequest, rpl *radigo.Packet) (processed bool, err error) { diff --git a/data/conf/samples/radius_coa_disconnect/accounting.json b/data/conf/samples/radius_coa_disconnect/accounting.json index d4c4047ec..3ed3931c2 100644 --- a/data/conf/samples/radius_coa_disconnect/accounting.json +++ b/data/conf/samples/radius_coa_disconnect/accounting.json @@ -25,7 +25,9 @@ {"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*composed", "value": "~*req.Event-Timestamp", "mandatory": true}, {"tag": "RemoteAddr" , "path": "*cgreq.RemoteAddr", "type": "*variable", - "value": "~*vars.RemoteHost:s/(.*):\\d+/${1}/"} + "value": "~*vars.RemoteHost:s/(.*):\\d+/${1}/"}, + {"tag": "SessionID", "path": "*vars.*sessionID", "type": "*variable", + "value": "~*req.Acct-Session-Id;-;modified"} ], "reply_fields":[] } diff --git a/data/conf/samples/radius_coa_disconnect/auth.json b/data/conf/samples/radius_coa_disconnect/auth.json index 704c407a2..b7fa85d28 100644 --- a/data/conf/samples/radius_coa_disconnect/auth.json +++ b/data/conf/samples/radius_coa_disconnect/auth.json @@ -24,9 +24,7 @@ {"tag": "AnswerTime", "path": "*cgreq.AnswerTime", "type": "*composed", "value": "~*req.Event-Timestamp", "mandatory": true}, {"tag": "PasswordFromAttributes", "path": "*cgreq.PasswordFromAttributes", "type": "*constant", - "value": "*attributes"}, - {"tag": "SessionID", "path": "*vars.*sessionID", "type": "*variable", - "value": "~*req.Acct-Session-Id;-;modified"} + "value": "*attributes"} ], "reply_fields":[ {"tag": "MaxUsage", "path": "*rep.SIP-AVP", "type": "*composed",