mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
DNSAgent configuration options within .json
This commit is contained in:
@@ -17,3 +17,57 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package agents
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/engine"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/rpcclient"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// NewDNSAgent is the constructor for DNSAgent
|
||||
func NewDNSAgent(cgrCfg *config.CGRConfig, fltrS *engine.FilterS,
|
||||
sS rpcclient.RpcClientConnection) (da *DNSAgent, err error) {
|
||||
da = &DNSAgent{cgrCfg: cgrCfg, fltrS: fltrS, sS: sS}
|
||||
return
|
||||
}
|
||||
|
||||
// DNSAgent translates DNS requests towards CGRateS infrastructure
|
||||
type DNSAgent struct {
|
||||
cgrCfg *config.CGRConfig // loaded CGRateS configuration
|
||||
fltrS *engine.FilterS // connection towards FilterS
|
||||
sS rpcclient.RpcClientConnection // connection towards CGR-SessionS component
|
||||
}
|
||||
|
||||
// ListenAndServe will run the DNS handler doing also the connection to listen address
|
||||
func (da *DNSAgent) ListenAndServe() error {
|
||||
if strings.HasSuffix(da.cgrCfg.DNSAgentCfg().ListenNet, utils.TLSNoCaps) {
|
||||
return dns.ListenAndServeTLS(
|
||||
da.cgrCfg.DNSAgentCfg().Listen,
|
||||
da.cgrCfg.TlsCfg().ServerCerificate,
|
||||
da.cgrCfg.TlsCfg().ServerKey,
|
||||
dns.HandlerFunc(
|
||||
func(w ResponseWriter, m *Msg) {
|
||||
go da.handleMessage(w, m)
|
||||
}),
|
||||
)
|
||||
}
|
||||
return dns.ListenAndServe(
|
||||
da.cgrCfg.DNSAgentCfg().Listen,
|
||||
da.cgrCfg.DNSAgentCfg().ListenNet,
|
||||
dns.HandlerFunc(
|
||||
func(w ResponseWriter, m *Msg) {
|
||||
go da.handleMessage(w, m)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// handleMessage is the entry point of all DNS requests
|
||||
// requests are reaching here asynchronously
|
||||
func (da *DNSAgent) handleMessage(w ResponseWriter, m *dns.Msg) {
|
||||
fmt.Printf("got message: %+v\n", m)
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ func NewDefaultCGRConfig() (*CGRConfig, error) {
|
||||
cfg.asteriskAgentCfg = new(AsteriskAgentCfg)
|
||||
cfg.diameterAgentCfg = new(DiameterAgentCfg)
|
||||
cfg.radiusAgentCfg = new(RadiusAgentCfg)
|
||||
cfg.dnsAgentCfg = new(DNSAgentCfg)
|
||||
cfg.attributeSCfg = new(AttributeSCfg)
|
||||
cfg.chargerSCfg = new(ChargerSCfg)
|
||||
cfg.resourceSCfg = new(ResourceSConfig)
|
||||
@@ -324,6 +325,7 @@ type CGRConfig struct {
|
||||
asteriskAgentCfg *AsteriskAgentCfg // AsteriskAgent config
|
||||
diameterAgentCfg *DiameterAgentCfg // DiameterAgent config
|
||||
radiusAgentCfg *RadiusAgentCfg // RadiusAgent config
|
||||
dnsAgentCfg *DNSAgentCfg // DNSAgent config
|
||||
attributeSCfg *AttributeSCfg // AttributeS config
|
||||
chargerSCfg *ChargerSCfg // ChargerS config
|
||||
resourceSCfg *ResourceSConfig // ResourceS config
|
||||
@@ -605,6 +607,13 @@ func (self *CGRConfig) checkConfigSanity() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.dnsAgentCfg.Enabled && !self.sessionSCfg.Enabled {
|
||||
for _, sSConn := range self.dnsAgentCfg.SessionSConns {
|
||||
if sSConn.Address == utils.MetaInternal {
|
||||
return fmt.Errorf("%s not enabled but referenced by %s", utils.SessionS, utils.DNSAgent)
|
||||
}
|
||||
}
|
||||
}
|
||||
// HTTPAgent checks
|
||||
for _, httpAgentCfg := range self.httpAgentCfg {
|
||||
// httpAgent checks
|
||||
@@ -840,6 +849,14 @@ func (self *CGRConfig) loadFromJsonCfg(jsnCfg *CgrJsonCfg) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnDNSCfg, err := jsnCfg.DNSAgentJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := self.dnsAgentCfg.loadFromJsonCfg(jsnDNSCfg, self.generalCfg.RsrSepatarot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsnHttpAgntCfg, err := jsnCfg.HttpAgentJsonCfg()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1050,6 +1067,10 @@ func (self *CGRConfig) RadiusAgentCfg() *RadiusAgentCfg {
|
||||
return self.radiusAgentCfg
|
||||
}
|
||||
|
||||
func (self *CGRConfig) DNSAgentCfg() *DNSAgentCfg {
|
||||
return self.dnsAgentCfg
|
||||
}
|
||||
|
||||
func (cfg *CGRConfig) AttributeSCfg() *AttributeSCfg {
|
||||
return cfg.attributeSCfg
|
||||
}
|
||||
|
||||
@@ -453,6 +453,19 @@ const CGRATES_CFG_JSON = `
|
||||
],
|
||||
|
||||
|
||||
"dns_agent": {
|
||||
"enabled": false, // enables the DNS agent: <true|false>
|
||||
"listen_net": "udp", // network to listen on <udp|tcp|tcp-tls>
|
||||
"listen": "127.0.0.1:53", // address where to listen for DNS requests <x.y.z.y:1234>
|
||||
"sessions_conns": [ // connections to SessionS for session management and CDR posting
|
||||
{"address": "*internal"}
|
||||
],
|
||||
"timezone": "", // timezone of the events if not specified <UTC|Local|$IANA_TZ_DB>
|
||||
"request_processors": [ // request processors to be applied to DNS messages
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
"attributes": { // AttributeS config
|
||||
"enabled": false, // starts attribute service: <true|false>.
|
||||
"indexed_selects":true, // enable profile matching exclusively on indexes
|
||||
|
||||
@@ -66,6 +66,7 @@ const (
|
||||
TlsCfgJson = "tls"
|
||||
AnalyzerCfgJson = "analyzers"
|
||||
Apier = "apier"
|
||||
DNSAgentJson = "dns_agent"
|
||||
)
|
||||
|
||||
// Loads the json config out of io.Reader, eg other sources than file, maybe over http
|
||||
@@ -320,6 +321,16 @@ func (self CgrJsonCfg) HttpAgentJsonCfg() (*[]*HttpAgentJsonCfg, error) {
|
||||
return &httpAgnt, nil
|
||||
}
|
||||
|
||||
func (self CgrJsonCfg) DNSAgentJsonCfg() (da *DNSAgentJsonCfg, err error) {
|
||||
rawCfg, hasKey := self[DNSAgentJson]
|
||||
if !hasKey {
|
||||
return
|
||||
}
|
||||
da = new(DNSAgentJsonCfg)
|
||||
err = json.Unmarshal(*rawCfg, da)
|
||||
return
|
||||
}
|
||||
|
||||
func (cgrJsn CgrJsonCfg) AttributeServJsonCfg() (*AttributeSJsonCfg, error) {
|
||||
rawCfg, hasKey := cgrJsn[ATTRIBUTE_JSN]
|
||||
if !hasKey {
|
||||
|
||||
@@ -737,6 +737,26 @@ func TestHttpAgentJsonCfg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDNSAgentJsonCfg(t *testing.T) {
|
||||
eCfg := &DNSAgentJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
Listen_net: utils.StringPointer("udp"),
|
||||
Listen: utils.StringPointer("127.0.0.1:53"),
|
||||
Sessions_conns: &[]*HaPoolJsonCfg{
|
||||
{
|
||||
Address: utils.StringPointer(utils.MetaInternal),
|
||||
}},
|
||||
Timezone: utils.StringPointer(""),
|
||||
Request_processors: &[]*ReqProcessorJsnCfg{},
|
||||
}
|
||||
if cfg, err := dfCgrJsonCfg.DNSAgentJsonCfg(); err != nil {
|
||||
t.Error(err)
|
||||
} else if !reflect.DeepEqual(eCfg, cfg) {
|
||||
rcv := *cfg.Request_processors
|
||||
t.Errorf("Received: %+v", rcv)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDfAttributeServJsonCfg(t *testing.T) {
|
||||
eCfg := &AttributeSJsonCfg{
|
||||
Enabled: utils.BoolPointer(false),
|
||||
|
||||
122
config/dnsagntcfg.go
Normal file
122
config/dnsagntcfg.go
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
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 DNSAgentCfg struct {
|
||||
Enabled bool
|
||||
ListenNet string // udp or tcp
|
||||
Listen string
|
||||
SessionSConns []*RemoteHost
|
||||
Timezone string
|
||||
RequestProcessors []*RequestProcessor
|
||||
}
|
||||
|
||||
func (da *DNSAgentCfg) loadFromJsonCfg(jsnCfg *DNSAgentJsonCfg, sep string) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.Enabled != nil {
|
||||
da.Enabled = *jsnCfg.Enabled
|
||||
}
|
||||
if jsnCfg.Listen_net != nil {
|
||||
da.ListenNet = *jsnCfg.Listen_net
|
||||
}
|
||||
if jsnCfg.Listen != nil {
|
||||
da.Listen = *jsnCfg.Listen
|
||||
}
|
||||
if jsnCfg.Sessions_conns != nil {
|
||||
da.SessionSConns = make([]*RemoteHost, len(*jsnCfg.Sessions_conns))
|
||||
for idx, jsnHaCfg := range *jsnCfg.Sessions_conns {
|
||||
da.SessionSConns[idx] = NewDfltRemoteHost()
|
||||
da.SessionSConns[idx].loadFromJsonCfg(jsnHaCfg)
|
||||
}
|
||||
}
|
||||
if jsnCfg.Request_processors != nil {
|
||||
for _, reqProcJsn := range *jsnCfg.Request_processors {
|
||||
rp := new(RequestProcessor)
|
||||
var haveID bool
|
||||
for _, rpSet := range da.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, sep); err != nil {
|
||||
return nil
|
||||
}
|
||||
if !haveID {
|
||||
da.RequestProcessors = append(da.RequestProcessors, rp)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// One request processor configuration
|
||||
type RequestProcessor struct {
|
||||
ID string
|
||||
Tenant RSRParsers
|
||||
Filters []string
|
||||
Flags utils.StringMap
|
||||
ContinueOnSuccess bool
|
||||
RequestFields []*FCTemplate
|
||||
ReplyFields []*FCTemplate
|
||||
}
|
||||
|
||||
func (rp *RequestProcessor) loadFromJsonCfg(jsnCfg *ReqProcessorJsnCfg, sep string) (err error) {
|
||||
if jsnCfg == nil {
|
||||
return nil
|
||||
}
|
||||
if jsnCfg.ID != nil {
|
||||
rp.ID = *jsnCfg.ID
|
||||
}
|
||||
if jsnCfg.Filters != nil {
|
||||
rp.Filters = make([]string, len(*jsnCfg.Filters))
|
||||
for i, fltr := range *jsnCfg.Filters {
|
||||
rp.Filters[i] = fltr
|
||||
}
|
||||
}
|
||||
if jsnCfg.Flags != nil {
|
||||
rp.Flags = utils.StringMapFromSlice(*jsnCfg.Flags)
|
||||
}
|
||||
if jsnCfg.Continue_on_success != nil {
|
||||
rp.ContinueOnSuccess = *jsnCfg.Continue_on_success
|
||||
}
|
||||
if jsnCfg.Tenant != nil {
|
||||
if rp.Tenant, err = NewRSRParsers(*jsnCfg.Tenant, true, sep); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if jsnCfg.Request_fields != nil {
|
||||
if rp.RequestFields, err = FCTemplatesFromFCTemplatesJsonCfg(*jsnCfg.Request_fields, sep); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if jsnCfg.Reply_fields != nil {
|
||||
if rp.ReplyFields, err = FCTemplatesFromFCTemplatesJsonCfg(*jsnCfg.Reply_fields, sep); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -360,7 +360,6 @@ type RadiusAgentJsonCfg struct {
|
||||
Client_secrets *map[string]string
|
||||
Client_dictionaries *map[string]string
|
||||
Sessions_conns *[]*HaPoolJsonCfg
|
||||
Tenant *string
|
||||
Timezone *string
|
||||
Request_processors *[]*RAReqProcessorJsnCfg
|
||||
}
|
||||
@@ -397,11 +396,25 @@ type HttpAgentProcessorJsnCfg struct {
|
||||
Reply_fields *[]*FcTemplateJsonCfg
|
||||
}
|
||||
|
||||
// History server config section
|
||||
type HistServJsonCfg struct {
|
||||
Enabled *bool
|
||||
History_dir *string
|
||||
Save_interval *string
|
||||
// DNSAgentJsonCfg
|
||||
type DNSAgentJsonCfg struct {
|
||||
Enabled *bool
|
||||
Listen *string
|
||||
Listen_net *string
|
||||
Sessions_conns *[]*HaPoolJsonCfg
|
||||
Timezone *string
|
||||
Request_processors *[]*ReqProcessorJsnCfg
|
||||
}
|
||||
|
||||
type ReqProcessorJsnCfg struct {
|
||||
ID *string
|
||||
Filters *[]string
|
||||
Tenant *string
|
||||
Timezone *string
|
||||
Flags *[]string
|
||||
Continue_on_success *bool
|
||||
Request_fields *[]*FcTemplateJsonCfg
|
||||
Reply_fields *[]*FcTemplateJsonCfg
|
||||
}
|
||||
|
||||
// Attribute service config section
|
||||
|
||||
@@ -562,6 +562,8 @@ const (
|
||||
MetaRemove = "*remove"
|
||||
MetaClear = "*clear"
|
||||
LoadIDs = "load_ids"
|
||||
DNSAgent = "DNSAgent"
|
||||
TLSNoCaps = "tls"
|
||||
)
|
||||
|
||||
// Migrator Action
|
||||
|
||||
Reference in New Issue
Block a user