mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-12 02:26:26 +05:00
radius_agent configuration options in cgrates.json
This commit is contained in:
@@ -69,6 +69,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
|
||||
cfg.SmOsipsConfig = new(SmOsipsConfig)
|
||||
cfg.smAsteriskCfg = new(SMAsteriskCfg)
|
||||
cfg.diameterAgentCfg = new(DiameterAgentCfg)
|
||||
cfg.radiusAgentCfg = new(RadiusAgentCfg)
|
||||
cfg.ConfigReloads = make(map[string]chan struct{})
|
||||
cfg.ConfigReloads[utils.CDRC] = make(chan struct{}, 1)
|
||||
cfg.ConfigReloads[utils.CDRC] <- struct{}{} // Unlock the channel
|
||||
@@ -249,6 +250,7 @@ type CGRConfig struct {
|
||||
SmOsipsConfig *SmOsipsConfig // SMOpenSIPS Configuration
|
||||
smAsteriskCfg *SMAsteriskCfg // SMAsterisk Configuration
|
||||
diameterAgentCfg *DiameterAgentCfg // DiameterAgent configuration
|
||||
radiusAgentCfg *RadiusAgentCfg // RadiusAgent configuration
|
||||
HistoryServerEnabled bool // Starts History as server: <true|false>.
|
||||
HistoryDir string // Location on disk where to store history files.
|
||||
HistorySaveInterval time.Duration // The timout duration between pubsub writes
|
||||
@@ -469,6 +471,13 @@ func (self *CGRConfig) checkConfigSanity() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.radiusAgentCfg.Enabled {
|
||||
for _, raSMGConn := range self.radiusAgentCfg.SMGenericConns {
|
||||
if raSMGConn.Address == utils.MetaInternal && !self.SmGenericConfig.Enabled {
|
||||
return errors.New("SMGeneric not enabled but referenced by RadiusAgent component")
|
||||
}
|
||||
}
|
||||
}
|
||||
// ResourceLimiter checks
|
||||
if self.resourceLimiterCfg != nil && self.resourceLimiterCfg.Enabled {
|
||||
for _, connCfg := range self.resourceLimiterCfg.CDRStatConns {
|
||||
@@ -575,6 +584,11 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnRACfg, err := jsnCfg.RadiusAgentJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnHistServCfg, err := jsnCfg.HistServJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -983,6 +997,12 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) error {
|
||||
}
|
||||
}
|
||||
|
||||
if jsnRACfg != nil {
|
||||
if err := self.radiusAgentCfg.loadFromJsonCfg(jsnRACfg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if jsnHistServCfg != nil {
|
||||
if jsnHistServCfg.Enabled != nil {
|
||||
self.HistoryServerEnabled = *jsnHistServCfg.Enabled
|
||||
@@ -1067,6 +1087,10 @@ func (self *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg {
|
||||
return self.diameterAgentCfg
|
||||
}
|
||||
|
||||
func (self *CGRConfig) RadiusAgentCfg() *RadiusAgentCfg {
|
||||
return self.radiusAgentCfg
|
||||
}
|
||||
|
||||
// ToDo: fix locking here
|
||||
func (self *CGRConfig) ResourceLimiterCfg() *ResourceLimiterConfig {
|
||||
return self.resourceLimiterCfg
|
||||
|
||||
@@ -358,8 +358,8 @@ const CGRATES_CFG_JSON = `
|
||||
"request_filter": "Subscription-Id>Subscription-Id-Type(0)", // filter requests processed by this processor
|
||||
"flags": [], // flags to influence processing behavior
|
||||
"continue_on_success": false, // continue to the next template if executed
|
||||
"append_cca": true, // when continuing will append cca fields to the previous ones
|
||||
"ccr_fields":[ // import content_fields template, tag will match internally CDR field, in case of .csv value will be represented by index of the field value
|
||||
"append_cca": true, // when continuing will append cca fields of the the previous one
|
||||
"ccr_fields":[ // import content_fields template, tag will match internally CDR field
|
||||
{"tag": "TOR", "field_id": "ToR", "type": "*composed", "value": "^*voice", "mandatory": true},
|
||||
{"tag": "OriginID", "field_id": "OriginID", "type": "*composed", "value": "Session-Id", "mandatory": true},
|
||||
{"tag": "RequestType", "field_id": "RequestType", "type": "*composed", "value": "^*users", "mandatory": true},
|
||||
@@ -382,6 +382,34 @@ const CGRATES_CFG_JSON = `
|
||||
},
|
||||
|
||||
|
||||
"radius_agent": {
|
||||
"enabled": false, // enables the radius agent: <true|false>
|
||||
"listen_auth": "127.0.0.1:1812", // address where to listen for radius authentication requests <x.y.z.y:1234>
|
||||
"listen_acct": "127.0.0.1:1813", // address where to listen for radius accounting requests <x.y.z.y:1234>
|
||||
"dictionaries_dir": "/usr/share/cgrates/radius/dict/", // path towards directory holding additional dictionaries to load (extra to RFC)
|
||||
"sm_generic_conns": [
|
||||
{"address": "*internal"} // connection towards SMG component for session management
|
||||
],
|
||||
"create_cdr": true, // create CDR out of Accounting-Stop and send it to SMG component
|
||||
"cdr_requires_session": false, // only create CDR if there is an active session at terminate
|
||||
"timezone": "", // timezone for timestamps where not specified, empty for general defaults <""|UTC|Local|$IANA_TZ_DB>
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "*default", // formal identifier of this processor
|
||||
"dry_run": false, // do not send the events to SMG, just log them
|
||||
"request_filter": "", // filter requests processed by this processor
|
||||
"flags": [], // flags to influence processing behavior
|
||||
"continue_on_success": false, // continue to the next template if executed
|
||||
"append_reply": true, // when continuing will append reply fields to the next template
|
||||
"request_fields":[ // import content_fields template, tag will match internally CDR field
|
||||
],
|
||||
"reply_fields":[ // fields returned in radius reply
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
"historys": {
|
||||
"enabled": false, // starts History service: <true|false>.
|
||||
"history_dir": "/var/lib/cgrates/history", // location on disk where to store history files.
|
||||
|
||||
@@ -49,6 +49,7 @@ const (
|
||||
KAMAILIO_JSN = "kamailio"
|
||||
OSIPS_JSN = "opensips"
|
||||
DA_JSN = "diameter_agent"
|
||||
RA_JSN = "radius_agent"
|
||||
HISTSERV_JSN = "historys"
|
||||
PUBSUBSERV_JSN = "pubsubs"
|
||||
ALIASESSERV_JSN = "aliases"
|
||||
@@ -285,6 +286,18 @@ func (self CgrJsonCfg) DiameterAgentJsonCfg() (*DiameterAgentJsonCfg, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) RadiusAgentJsonCfg() (*RadiusAgentJsonCfg, error) {
|
||||
rawCfg, hasKey := self[RA_JSN]
|
||||
if !hasKey {
|
||||
return nil, nil
|
||||
}
|
||||
cfg := new(RadiusAgentJsonCfg)
|
||||
if err := json.Unmarshal(*rawCfg, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) HistServJsonCfg() (*HistServJsonCfg, error) {
|
||||
rawCfg, hasKey := self[HISTSERV_JSN]
|
||||
if !hasKey {
|
||||
|
||||
@@ -605,6 +605,40 @@ func TestDiameterAgentJsonCfg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRadiusAgentJsonCfg(t *testing.T) {
|
||||
eCfg := &RadiusAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
Listen_auth: utils.StringPointer("127.0.0.1:1812"),
|
||||
Listen_acct: utils.StringPointer("127.0.0.1:1813"),
|
||||
Dictionaries_dir: utils.StringPointer("/usr/share/cgrates/radius/dict/"),
|
||||
Sm_generic_conns: &[]*HaPoolJsonCfg{
|
||||
&HaPoolJsonCfg{
|
||||
Address: utils.StringPointer(utils.MetaInternal),
|
||||
}},
|
||||
Create_cdr: utils.BoolPointer(true),
|
||||
Cdr_requires_session: utils.BoolPointer(false),
|
||||
Timezone: utils.StringPointer(""),
|
||||
Request_processors: &[]*RAReqProcessorJsnCfg{
|
||||
&RAReqProcessorJsnCfg{
|
||||
Id: utils.StringPointer("*default"),
|
||||
Dry_run: utils.BoolPointer(false),
|
||||
Request_filter: utils.StringPointer(""),
|
||||
Flags: utils.StringSlicePointer([]string{}),
|
||||
Continue_on_success: utils.BoolPointer(false),
|
||||
Append_reply: utils.BoolPointer(true),
|
||||
Request_fields: &[]*CdrFieldJsonCfg{},
|
||||
Reply_fields: &[]*CdrFieldJsonCfg{},
|
||||
},
|
||||
},
|
||||
}
|
||||
if cfg, err := dfCgrJsonCfg.RadiusAgentJsonCfg(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCfg, cfg) {
|
||||
rcv := *cfg.Request_processors
|
||||
t.Errorf("Received: %+v", rcv[0].Reply_fields)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDfHistServJsonCfg(t *testing.T) {
|
||||
eCfg := &HistServJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
|
||||
@@ -339,6 +339,30 @@ type DARequestProcessorJsnCfg struct {
|
||||
CCA_fields *[]*CdrFieldJsonCfg
|
||||
}
|
||||
|
||||
// Radius Agent configuration section
|
||||
type RadiusAgentJsonCfg struct {
|
||||
Enabled *bool
|
||||
Listen_auth *string
|
||||
Listen_acct *string
|
||||
Dictionaries_dir *string
|
||||
Sm_generic_conns *[]*HaPoolJsonCfg
|
||||
Create_cdr *bool
|
||||
Cdr_requires_session *bool
|
||||
Timezone *string
|
||||
Request_processors *[]*RAReqProcessorJsnCfg
|
||||
}
|
||||
|
||||
type RAReqProcessorJsnCfg struct {
|
||||
Id *string
|
||||
Dry_run *bool
|
||||
Request_filter *string
|
||||
Flags *[]string
|
||||
Continue_on_success *bool
|
||||
Append_reply *bool
|
||||
Request_fields *[]*CdrFieldJsonCfg
|
||||
Reply_fields *[]*CdrFieldJsonCfg
|
||||
}
|
||||
|
||||
// History server config section
|
||||
type HistServJsonCfg struct {
|
||||
Enabled *bool
|
||||
|
||||
138
config/raconfig.go
Normal file
138
config/raconfig.go
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
|
||||
Copyright (C) ITsysCOM GmbH
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
)
|
||||
|
||||
type RadiusAgentCfg struct {
|
||||
Enabled bool
|
||||
ListenAuth string
|
||||
ListenAcct string
|
||||
DictionariesDir string
|
||||
SMGenericConns []*HaPoolConfig
|
||||
CreateCDR bool
|
||||
CDRRequiresSession bool
|
||||
Timezone string
|
||||
RequestProcessors []*RARequestProcessor
|
||||
}
|
||||
|
||||
func (self *RadiusAgentCfg) loadFromJsonCfg(jsnCfg *RadiusAgentJsonCfg) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
self.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Listen_auth != nil {
|
||||
self.ListenAuth = *jsnCfg.Listen_auth
|
||||
}
|
||||
if jsnCfg.Listen_acct != nil {
|
||||
self.ListenAcct = *jsnCfg.Listen_acct
|
||||
}
|
||||
if jsnCfg.Dictionaries_dir != nil {
|
||||
self.DictionariesDir = *jsnCfg.Dictionaries_dir
|
||||
}
|
||||
if jsnCfg.Sm_generic_conns != nil {
|
||||
self.SMGenericConns = make([]*HaPoolConfig, len(*jsnCfg.Sm_generic_conns))
|
||||
for idx, jsnHaCfg := range *jsnCfg.Sm_generic_conns {
|
||||
self.SMGenericConns[idx] = NewDfltHaPoolConfig()
|
||||
self.SMGenericConns[idx].loadFromJsonCfg(jsnHaCfg)
|
||||
}
|
||||
}
|
||||
if jsnCfg.Create_cdr != nil {
|
||||
self.CreateCDR = *jsnCfg.Create_cdr
|
||||
}
|
||||
if jsnCfg.Cdr_requires_session != nil {
|
||||
self.CDRRequiresSession = *jsnCfg.Cdr_requires_session
|
||||
}
|
||||
if jsnCfg.Timezone != nil {
|
||||
self.Timezone = *jsnCfg.Timezone
|
||||
}
|
||||
if jsnCfg.Request_processors != nil {
|
||||
for _, reqProcJsn := range *jsnCfg.Request_processors {
|
||||
rp := new(RARequestProcessor)
|
||||
var haveID bool
|
||||
for _, rpSet := range self.RequestProcessors {
|
||||
if reqProcJsn.Id != nil && rpSet.Id == *reqProcJsn.Id {
|
||||
rp = rpSet // Will load data into the one set
|
||||
haveID = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if err := rp.loadFromJsonCfg(reqProcJsn); err != nil {
|
||||
return nil
|
||||
}
|
||||
if !haveID {
|
||||
self.RequestProcessors = append(self.RequestProcessors, rp)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// One Diameter request processor configuration
|
||||
type RARequestProcessor struct {
|
||||
Id string
|
||||
DryRun bool
|
||||
RequestFilter utils.RSRFields
|
||||
Flags utils.StringMap // Various flags to influence behavior
|
||||
ContinueOnSuccess bool
|
||||
AppendReply bool
|
||||
RequestFields []*CfgCdrField
|
||||
ReplyFields []*CfgCdrField
|
||||
}
|
||||
|
||||
func (self *RARequestProcessor) loadFromJsonCfg(jsnCfg *RAReqProcessorJsnCfg) error {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Id != nil {
|
||||
self.Id = *jsnCfg.Id
|
||||
}
|
||||
if jsnCfg.Dry_run != nil {
|
||||
self.DryRun = *jsnCfg.Dry_run
|
||||
}
|
||||
var err error
|
||||
if jsnCfg.Request_filter != nil {
|
||||
if self.RequestFilter, err = utils.ParseRSRFields(*jsnCfg.Request_filter, utils.INFIELD_SEP); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if jsnCfg.Flags != nil {
|
||||
self.Flags = utils.StringMapFromSlice(*jsnCfg.Flags)
|
||||
}
|
||||
if jsnCfg.Continue_on_success != nil {
|
||||
self.ContinueOnSuccess = *jsnCfg.Continue_on_success
|
||||
}
|
||||
if jsnCfg.Append_reply != nil {
|
||||
self.AppendReply = *jsnCfg.Append_reply
|
||||
}
|
||||
if jsnCfg.Request_fields != nil {
|
||||
if self.RequestFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Request_fields); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if jsnCfg.Reply_fields != nil {
|
||||
if self.ReplyFields, err = CfgCdrFieldsFromCdrFieldsJsonCfg(*jsnCfg.Reply_fields); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user