mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-15 05:09:54 +05:00
Adding librad, radagent and dictionary.kamailio
This commit is contained in:
41
agents/librad.go
Normal file
41
agents/librad.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
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 agents
|
||||
|
||||
import (
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/cgrates/radigo"
|
||||
)
|
||||
|
||||
/*
|
||||
Various RADIUS helpers here
|
||||
*/
|
||||
|
||||
func radPassesFieldFilter(pkt *radigo.Packet, fieldFilter *utils.RSRField, processorVars map[string]string) (pass bool) {
|
||||
if fieldFilter == nil {
|
||||
return true
|
||||
}
|
||||
if val, hasIt := processorVars[fieldFilter.Id]; hasIt { // ProcessorVars have priority
|
||||
if fieldFilter.FilterPasses(val) {
|
||||
return true, 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
return
|
||||
}
|
||||
36
agents/librad_test.go
Normal file
36
agents/librad_test.go
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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 agents
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cgrates/cgrates/config"
|
||||
"github.com/cgrates/cgrates/sessionmanager"
|
||||
"github.com/cgrates/cgrates/utils"
|
||||
"github.com/fiorix/go-diameter/diam"
|
||||
"github.com/fiorix/go-diameter/diam/avp"
|
||||
"github.com/fiorix/go-diameter/diam/datatype"
|
||||
"github.com/fiorix/go-diameter/diam/dict"
|
||||
)
|
||||
@@ -35,9 +35,9 @@ func NewRadiusAgent(cgrCfg *config.CGRConfig, smg rpcclient.RpcClientConnection)
|
||||
}
|
||||
ra = &RadiusAgent{cgrCfg: cgrCfg, smg: smg}
|
||||
ra.rsAuth = radigo.NewServer(cgrCfg.RadiusAgentCfg().ListenNet, cgrCfg.RadiusAgentCfg().ListenAuth, cgrCfg.RadiusAgentCfg().ClientSecrets, dicts,
|
||||
map[radigo.PacketCode]func(*radigo.Packet) (*radigo.Packet, error){radigo.AccessRequest: ra.handleAuth})
|
||||
map[radigo.PacketCode]func(*radigo.Packet) (*radigo.Packet, error){radigo.AccessRequest: ra.handleAuth}, nil)
|
||||
ra.rsAcct = radigo.NewServer(cgrCfg.RadiusAgentCfg().ListenNet, cgrCfg.RadiusAgentCfg().ListenAcct, cgrCfg.RadiusAgentCfg().ClientSecrets, dicts,
|
||||
map[radigo.PacketCode]func(*radigo.Packet) (*radigo.Packet, error){radigo.AccountingRequest: ra.handleAcct})
|
||||
map[radigo.PacketCode]func(*radigo.Packet) (*radigo.Packet, error){radigo.AccountingRequest: ra.handleAcct}, nil)
|
||||
return
|
||||
|
||||
}
|
||||
@@ -59,12 +59,26 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e
|
||||
return
|
||||
}
|
||||
|
||||
// RadiusAgent handleAcct, received req: &{RWMutex:{w:{state:0 sema:0} writerSem:0 readerSem:0 readerCount:0 readerWait:0} dict:0xc4202e5840 secret:CGRateS.org Code:AccountingRequest Identifier:143 Authenticator:[67 77 204 122 189 209 219 22 9 176 15 228 24 246 183 7] AVPs:[0xc42023c230 0xc42023c2a0 0xc42023c310 0xc42023c460 0xc42023c4d0 0xc42023c540 0xc42023c850 0xc42023ce00 0xc42023d180 0xc42023d1f0 0xc42023d260]}
|
||||
// Identifier:144 Authenticator:[192 197 33 53 203 181 16 117 204 143 172 174 231 245 81 116] AVPs:[0xc42023d5e0 0xc42023d650 0xc42023d880 0xc42023d8f0 0xc42023da40 0xc42023db20 0xc42023dc70 0xc42023dd50 0xc42023ddc0 0xc42023de30 0xc42023dea0]}
|
||||
func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err error) {
|
||||
utils.Logger.Debug(fmt.Sprintf("RadiusAgent handleAcct, received req: %+v", req))
|
||||
req.SetAVPValues()
|
||||
utils.Logger.Debug(fmt.Sprintf("Received request: %s", utils.ToJSON(req)))
|
||||
rpl = req.Reply()
|
||||
rpl.Code = radigo.AccountingResponse
|
||||
for _, avp := range req.AVPs {
|
||||
rpl.AVPs = append(rpl.AVPs, avp)
|
||||
rpl.SetAVPValues()
|
||||
return
|
||||
}
|
||||
|
||||
func (ra *RadiusAgent) processRequest(req *radigo.Packet, reqProcessor *config.RARequestProcessor) (processed bool, err error) {
|
||||
passesAllFilters := true
|
||||
for _, fldFilter := range reqProcessor.RequestFilter {
|
||||
if passes, _ := radPassesFieldFilter(req, fldFilter, nil); !passes {
|
||||
passesAllFilters = false
|
||||
}
|
||||
}
|
||||
if !passesAllFilters { // Not going with this processor further
|
||||
return false, nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
{
|
||||
// CGRateS Configuration file
|
||||
//
|
||||
// Used for cgradmin
|
||||
// Starts rater, scheduler
|
||||
|
||||
"general": {
|
||||
"log_level": 7,
|
||||
},
|
||||
|
||||
|
||||
"listen": {
|
||||
"rpc_json": ":2012", // RPC JSON listening address
|
||||
@@ -74,6 +77,36 @@
|
||||
|
||||
"radius_agent": {
|
||||
"enabled": true,
|
||||
"request_processors": [
|
||||
{
|
||||
"id": "KamailioAccountingStart",
|
||||
"dry_run": false,
|
||||
"request_filter": "Service-Type(Sip-Session);Sip-Method(Invite)",
|
||||
"flags": [],
|
||||
"continue_on_success": false,
|
||||
"append_reply": true,
|
||||
"request_fields":[
|
||||
{"tag": "Account", "field_id": "Account", "type": "*composed", "value": "User-Name", "mandatory": true},
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*composed", "value": "Called-Station-Id", "mandatory": true},
|
||||
],
|
||||
"reply_fields":[],
|
||||
},
|
||||
{
|
||||
"id": "KamailioAccountingStop",
|
||||
"dry_run": false,
|
||||
"request_filter": "Service-Type(Sip-Session);Sip-Method(Bye)",
|
||||
"flags": [],
|
||||
"continue_on_success": false,
|
||||
"append_reply": true,
|
||||
"request_fields":[
|
||||
{"tag": "Account", "field_id": "Account", "type": "*composed", "value": "User-Name", "mandatory": true},
|
||||
{"tag": "Destination", "field_id": "Destination", "type": "*composed", "value": "Called-Station-Id", "mandatory": true},
|
||||
],
|
||||
"reply_fields":[],
|
||||
},
|
||||
|
||||
],
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
86
data/radius/dict/dictionary.kamailio
Normal file
86
data/radius/dict/dictionary.kamailio
Normal file
@@ -0,0 +1,86 @@
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# SIP RADIUS attributes
|
||||
#
|
||||
# Proprietary indicates an attribute that hasn't
|
||||
# been standardized
|
||||
#
|
||||
#
|
||||
# NOTE: All standard (IANA registered) attributes are
|
||||
# defined in the default dictionary of the
|
||||
# radiusclient-ng library.
|
||||
#
|
||||
|
||||
|
||||
#### Attributes ###
|
||||
ATTRIBUTE Sip-Response-Code 102 integer
|
||||
ATTRIBUTE Sip-Method 101 integer
|
||||
ATTRIBUTE Sip-Response-Code 102 integer
|
||||
ATTRIBUTE Sip-CSeq 103 string
|
||||
ATTRIBUTE Sip-To-Tag 104 string
|
||||
ATTRIBUTE Sip-From-Tag 105 string
|
||||
ATTRIBUTE Sip-Branch-ID 106 string
|
||||
ATTRIBUTE Sip-Translated-Request-URI 107 string
|
||||
ATTRIBUTE Sip-Source-IP-Address 108 ipaddr
|
||||
ATTRIBUTE Sip-Source-Port 109 integer
|
||||
ATTRIBUTE Sip-User-ID 110 string
|
||||
ATTRIBUTE Sip-User-Realm 111 string
|
||||
ATTRIBUTE Sip-User-Nonce 112 string
|
||||
ATTRIBUTE Sip-User-Method 113 string
|
||||
ATTRIBUTE Sip-User-Digest-URI 114 string
|
||||
ATTRIBUTE Sip-User-Nonce-Count 115 string
|
||||
ATTRIBUTE Sip-User-QOP 116 string
|
||||
ATTRIBUTE Sip-User-Opaque 117 string
|
||||
ATTRIBUTE Sip-User-Response 118 string
|
||||
ATTRIBUTE Sip-User-CNonce 119 string
|
||||
ATTRIBUTE Sip-URI-User 208 string
|
||||
ATTRIBUTE Sip-Req-URI 210 string
|
||||
ATTRIBUTE Sip-CC 212 string
|
||||
ATTRIBUTE Sip-RPId 213 string
|
||||
ATTRIBUTE Digest-Response 206 string
|
||||
ATTRIBUTE Digest-Attributes 207 string
|
||||
ATTRIBUTE Digest-Realm 1063 string
|
||||
ATTRIBUTE Digest-Nonce 1064 string
|
||||
ATTRIBUTE Digest-Method 1065 string
|
||||
ATTRIBUTE Digest-URI 1066 string
|
||||
ATTRIBUTE Digest-QOP 1067 string
|
||||
ATTRIBUTE Digest-Algorithm 1068 string
|
||||
ATTRIBUTE Digest-Body-Digest 1069 string
|
||||
ATTRIBUTE Digest-CNonce 1070 string
|
||||
ATTRIBUTE Digest-Nonce-Count 1071 string
|
||||
ATTRIBUTE Digest-User-Name 1072 string
|
||||
|
||||
ATTRIBUTE Sip-Uri-User 208 string # Proprietary, auth_radius
|
||||
ATTRIBUTE Sip-Group 211 string # Proprietary, group_radius
|
||||
ATTRIBUTE Sip-Rpid 213 string # Proprietary, auth_radius
|
||||
ATTRIBUTE SIP-AVP 225 string # Proprietary, avp_radius
|
||||
|
||||
### Acct-Status-Type Values ###
|
||||
VALUE Acct-Status-Type Failed 15 # RFC2866, acc
|
||||
|
||||
### Service-Type Values ###
|
||||
#VALUE Service-Type Call-Check 10 # RFC2865, uri_radius
|
||||
VALUE Service-Type Group-Check 12 # Proprietary, group_radius
|
||||
VALUE Service-Type Sip-Session 15 # Schulzrinne, acc, auth_radius
|
||||
VALUE Service-Type SIP-Caller-AVPs 30 # Proprietary, avp_radius
|
||||
VALUE Service-Type SIP-Callee-AVPs 31 # Proprietary, avp_radius
|
||||
|
||||
### Sip-Method Values ###
|
||||
VALUE Sip-Method Undefined 0
|
||||
VALUE Sip-Method Invite 1
|
||||
VALUE Sip-Method Cancel 2
|
||||
VALUE Sip-Method Ack 4
|
||||
VALUE Sip-Method Bye 8
|
||||
VALUE Sip-Method Info 16
|
||||
VALUE Sip-Method Options 32
|
||||
VALUE Sip-Method Update 64
|
||||
VALUE Sip-Method Register 128
|
||||
VALUE Sip-Method Message 256
|
||||
VALUE Sip-Method Subscribe 512
|
||||
VALUE Sip-Method Notify 1024
|
||||
VALUE Sip-Method Prack 2048
|
||||
VALUE Sip-Method Refer 4096
|
||||
VALUE Sip-Method Other 8192
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ import (
|
||||
)
|
||||
|
||||
func TestITCDRsMySQL(t *testing.T) {
|
||||
|
||||
cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "mysql"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -49,7 +48,6 @@ func TestITCDRsMySQL(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestITCDRsPSQL(t *testing.T) {
|
||||
|
||||
cfg, err := config.NewCGRConfigFromFolder(path.Join(*dataDir, "conf", "samples", "storage", "postgres"))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
|
||||
Reference in New Issue
Block a user