RADIUS radReplyAppendAttributes

This commit is contained in:
DanB
2017-06-11 13:13:39 +02:00
parent a98bf56562
commit e1b1484572
4 changed files with 68 additions and 18 deletions

View File

@@ -111,17 +111,6 @@ func radMetaHandler(pkt *radigo.Packet, processorVars map[string]string,
// radFieldOutVal formats the field value retrieved from RADIUS packet
func radFieldOutVal(pkt *radigo.Packet, processorVars map[string]string,
cfgFld *config.CfgCdrField) (outVal string, err error) {
// make sure filters are passing
passedAllFilters := true
for _, fldFilter := range cfgFld.FieldFilter {
if !radPassesFieldFilter(pkt, processorVars, fldFilter) {
passedAllFilters = false
break
}
}
if !passedAllFilters {
return "", ErrFilterNotPassing // Not matching field filters, will have it empty
}
// different output based on cgrFld.Type
switch cfgFld.Type {
case utils.META_FILLER:
@@ -150,11 +139,18 @@ func radReqAsSMGEvent(radPkt *radigo.Packet, procVars map[string]string, procFla
outMap := make(map[string]string) // work with it so we can append values to keys
outMap[utils.EVENT_NAME] = EvRadiusReq
for _, cfgFld := range cfgFlds {
passedAllFilters := true
for _, fldFilter := range cfgFld.FieldFilter {
if !radPassesFieldFilter(radPkt, procVars, fldFilter) {
passedAllFilters = false
break
}
}
if !passedAllFilters {
continue
}
fmtOut, err := radFieldOutVal(radPkt, procVars, cfgFld)
if err != nil {
if err == ErrFilterNotPassing {
continue // Do nothing in case of Filter not passing
}
return nil, err
}
if _, hasKey := outMap[cfgFld.FieldId]; hasKey && cfgFld.Append {
@@ -171,6 +167,32 @@ func radReqAsSMGEvent(radPkt *radigo.Packet, procVars map[string]string, procFla
// radReplyAppendAttributes appends attributes to a RADIUS reply based on predefined template
func radReplyAppendAttributes(reply *radigo.Packet, procVars map[string]string,
tplFlds []*config.CfgCdrField, procFlags utils.StringMap) (err error) {
cfgFlds []*config.CfgCdrField) (err error) {
for _, cfgFld := range cfgFlds {
passedAllFilters := true
for _, fldFilter := range cfgFld.FieldFilter {
if !radPassesFieldFilter(reply, procVars, fldFilter) {
passedAllFilters = false
break
}
}
if !passedAllFilters {
continue
}
fmtOut, err := radFieldOutVal(reply, procVars, cfgFld)
if err != nil {
return err
}
if cfgFld.FieldId == MetaRadReplyCode { // Special case used to control the reply code of RADIUS reply
if err = reply.SetCodeWithName(fmtOut); err != nil {
return err
}
continue
}
attrName, vendorName := attrVendorFromPath(cfgFld.FieldId)
if err = reply.AddAVPWithName(attrName, fmtOut, vendorName); err != nil {
return err
}
}
return
}

View File

@@ -250,3 +250,24 @@ func TestRadReqAsSMGEvent(t *testing.T) {
t.Errorf("Expecting: %+v\n, received: %+v", eSMGEv, smgEv)
}
}
func TestRadReplyAppendAttributes(t *testing.T) {
rply := radigo.NewPacket(radigo.AccessRequest, 2, dictRad, coder, "CGRateS.org").Reply()
rplyFlds := []*config.CfgCdrField{
&config.CfgCdrField{Tag: "ReplyCode", FieldId: MetaRadReplyCode, Type: utils.META_CONSTANT,
Value: utils.ParseRSRFieldsMustCompile("AccessAccept", utils.INFIELD_SEP)},
&config.CfgCdrField{Tag: "Acct-Session-Time", FieldId: "Acct-Session-Time", Type: utils.META_COMPOSED,
Value: utils.ParseRSRFieldsMustCompile("~*cgrMaxUsage:s/(\\d*)\\d{9}$/$1/", utils.INFIELD_SEP)},
}
if err := radReplyAppendAttributes(rply, map[string]string{MetaCGRMaxUsage: "30000000000"}, rplyFlds); err != nil {
t.Error(err)
}
if rply.Code != radigo.AccessAccept {
t.Errorf("Wrong reply code: %d", rply.Code)
}
if avps := rply.AttributesWithName("Acct-Session-Time", ""); len(avps) == 0 {
t.Error("Cannot find Acct-Session-Time in reply")
} else if avps[0].GetStringValue() != "30" {
t.Errorf("Expecting: 30, received: %s", avps[0].GetStringValue())
}
}

View File

@@ -36,7 +36,9 @@ const (
MetaRadAcctUpdate = "*radAcctUpdate"
MetaRadAcctStop = "*radAcctStop"
MetaRadAcctEvent = "*radAcctEvent"
MetaCGRReply = "*cgrReply"
MetaCGRMaxUsage = "*cgrMaxUsage"
MetaCGRError = "*cgrError"
MetaRadReqType = "*radReqType"
EvRadiusReq = "RADIUS_REQUEST"
MetaUsageDifference = "*usage_difference"
@@ -157,6 +159,7 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RARequestProcessor,
}
var maxUsage time.Duration
var cgrReply interface{} // so we can store it in processorsVars
switch processorVars[MetaRadReqType] {
case MetaRadAuth: // auth attempt, make sure that MaxUsage is enough
if err = ra.smg.Call("SMGenericV2.GetMaxUsage", smgEv, &maxUsage); err != nil {
@@ -171,20 +174,24 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RARequestProcessor,
}
case MetaRadAcctStart:
err = ra.smg.Call("SMGenericV2.InitiateSession", smgEv, &maxUsage)
cgrReply = maxUsage
case MetaRadAcctUpdate:
err = ra.smg.Call("SMGenericV2.UpdateSession", smgEv, &maxUsage)
cgrReply = maxUsage
case MetaRadAcctStop:
var rpl string
err = ra.smg.Call("SMGenericV1.TerminateSession", smgEv, &rpl)
cgrReply = rpl
default:
err = fmt.Errorf("unsupported radius request type: <%s>", processorVars[MetaRadReqType])
}
if err != nil {
processorVars[MetaCGRError] = err.Error()
return false, err
}
processorVars[MetaCGRReply] = utils.ToJSON(cgrReply)
processorVars[MetaCGRMaxUsage] = strconv.Itoa(int(maxUsage))
if err := radReplyAppendAttributes(reply, processorVars, reqProcessor.ReplyFields, reqProcessor.Flags); err != nil {
if err := radReplyAppendAttributes(reply, processorVars, reqProcessor.ReplyFields); err != nil {
return false, err
}
return true, nil

2
glide.lock generated
View File

@@ -18,7 +18,7 @@ imports:
- name: github.com/cgrates/osipsdagram
version: 3d6beed663452471dec3ca194137a30d379d9e8f
- name: github.com/cgrates/radigo
version: 44900e0407cbc7cb713f6c2b06b843f1d22b2370
version: 57ecc46930a17563f6ba6d3a46280b102e9366d4
- name: github.com/cgrates/rpcclient
version: dddae42e9344e877627cd4b7aba075d63b452c0b
- name: github.com/ChrisTrenkamp/goxpath