[Devel] Inaccurate Radius Accounting
Lenir
lenirsantiago at yahoo.com
Wed Jan 4 04:25:47 CET 2006
Can you guys implement this patch (written by Jan Janak) for acc radius to
CVS?
It's been implemented to SER CVS.
Thanks,
Lenir
-----Original Message-----
From: 'Jan Janak' [mailto:jan at iptel.org]
Sent: Sunday, December 25, 2005 12:56 PM
To: Lenir
Cc: 'Klaus Darilion'; serdev at iptel.org; serusers at iptel.org;
devel at openser.org; users at openser.org
Subject: Re: [Users] RE: [Serusers] Re: [Serdev] Inaccurate Radius
Accounting
Hello,
Attached is a patch that implements "swap_direction" parameter of acc
module. If you turn the parameter on in the configuration file:
modparam("acc", "swap_direction", 1)
then the acc module will swap Calling-Station-ID and Called-Station-ID
values when necessary (in this case BYE comming from the callee).
Put the patch in top level source directory (ser-0.9.x) and type:
patch -p0 < swap.patch
The patch should work with any 0.9.x release.
Note that Alan DeKok is wrong in thinking that this is a bug in SER.
This particular problem is a result of incomplete specification of
RADIUS use with SIP. I will commit the patch in CVS so it will be
included in future SER releases.
Jan.
On 23-12-2005 17:10, Lenir wrote:
> Please read the reply below from one of the maintainers of freeradius:
>
> "Lenir" <lenirsantiago at yahoo.com> wrote:
> > But if UserB hangs up on UserA: SER generates a stop-record where the
> > Calling-Station-Id is UserB and the Called-Station-Id is UserA, this
> > is the undesired and incorrect behavior.
>
> It would appear to be a bug in SER.
>
> > To me the Calling-Station-Id and the Called-Station-Id should be the
> > same for both start and stop records, am I right by thinking that?
>
> Yes.
>
> > According to the developers of SER/OpenSER, this is the correct
> > behavior, whoever sends the hangup signal (BYE or CANCEL) is
> > considered the Calling-Station-Id, and they are unwilling to modify or
> > create a patch to "fix" this.
>
> What they do for something inside of SER is their business. When they
> generate RADIUS packets, they should follow RADIUS standards and
> interoperability. The expectation, as you said, is that the
> Calling/Called-Station-Id doesn't change during a session. If it does,
it's
> a bug and they should fix it.
>
> Alan DeKok.
> -
> List info/subscribe/unsubscribe? See
> http://www.freeradius.org/list/users.html
>
>
>
> -----Original Message-----
> From: 'Jan Janak' [mailto:jan at iptel.org]
> Sent: Thursday, November 17, 2005 10:33 AM
> To: Lenir
> Cc: 'Klaus Darilion'; serdev at iptel.org; serusers at iptel.org;
> devel at openser.org; users at openser.org
> Subject: Re: [Users] RE: [Serusers] Re: [Serdev] Inaccurate Radius
> Accounting
>
> On 17-11-2005 10:21, Lenir wrote:
> > In this case the radius proxy wont work, because you never can
anticipate
> > who hangs up the call, thus radius wont know who hung up the
> call...Besides
> > all other voice applications/hardware (SIP and H323) that use radius do
> not
> > behave like that, the Called-Station-ID ALWAYS remains the same, as with
> the
> > Calling-Station-ID.
>
> Could you name those SIP applications that behave the way you describe ?
>
> Jan.
>
-------------- next part --------------
RCS file: /cvsroot/ser/sip_router/modules/acc/Attic/acc.c,v
retrieving revision 1.26.2.1
diff -u -r1.26.2.1 acc.c
--- modules/acc/acc.c 14 Jun 2005 20:25:19 -0000 1.26.2.1
+++ modules/acc/acc.c 25 Dec 2005 17:35:19 -0000
@@ -49,6 +49,9 @@
#include "acc_mod.h"
#include "acc.h"
#include "dict.h"
+#include "../../parser/parse_rr.h"
+#include "../../trim.h"
+#include "../../parser/parse_uri.h"
#ifdef RAD_ACC
# ifdef RADIUSCLIENT_NG_4
# include <radiusclient.h>
@@ -71,6 +74,8 @@
#define M_NAME "acc"
#endif
+extern int swap_dir;
+
#define ATR(atr) atr_arr[cnt].s=A_##atr;\
atr_arr[cnt].len=A_##atr##_LEN;
@@ -101,6 +106,94 @@
#endif
+static int check_ftag(struct sip_msg* msg, str* uri)
+{
+ param_hooks_t hooks;
+ param_t* params;
+ char* semi;
+ struct to_body* from;
+ str t;
+
+ t = *uri;
+ params = 0;
+ semi = q_memchr(t.s, ';', t.len);
+ if (!semi) {
+ DBG("No ftag parameter found\n");
+ return -1;
+ }
+
+ t.len -= semi - uri->s + 1;
+ t.s = semi + 1;
+ trim_leading(&t);
+
+ if (parse_params(&t, CLASS_URI, &hooks, ¶ms) < 0) {
+ LOG(L_ERR, "Error while parsing parameters\n");
+ return -1;
+ }
+
+ if (!hooks.uri.ftag) {
+ DBG("No ftag parameter found\n");
+ goto err;
+ }
+
+ from = get_from(msg);
+
+ if (!from || !from->tag_value.len || !from->tag_value.s) {
+ DBG("No from tag parameter found\n");
+ goto err;
+ }
+
+ if (from->tag_value.len == hooks.uri.ftag->body.len &&
+ !strncmp(from->tag_value.s, hooks.uri.ftag->body.s, hooks.uri.ftag->body.len)) {
+ DBG("Route ftag and From tag are same\n");
+ free_params(params);
+ return 0;
+ } else {
+ DBG("Route ftag and From tag are NOT same\n");
+ free_params(params);
+ return 1;
+ }
+
+ err:
+ if (params) free_params(params);
+ return -1;
+}
+
+static int get_direction(struct sip_msg* msg)
+{
+ int ret;
+ if (parse_orig_ruri(msg) < 0) {
+ return -1;
+ }
+
+ if (!msg->parsed_orig_ruri_ok) {
+ LOG(L_ERR, "Error while parsing original Request-URI\n");
+ return -1;
+ }
+
+ ret = check_self(&msg->parsed_orig_ruri.host,
+ msg->parsed_orig_ruri.port_no ? msg->parsed_orig_ruri.port_no : SIP_PORT, 0);/* match all protos*/
+ if (ret < 0) return -1;
+ if (ret > 0) {
+ /* Route is in ruri */
+ return check_ftag(msg, &msg->first_line.u.request.uri);
+ } else {
+ if (msg->route) {
+ if (parse_rr(msg->route) < 0) {
+ LOG(L_ERR, "Error while parsing Route HF\n");
+ return -1;
+ }
+ ret = check_ftag(msg, &((rr_t*)msg->route->parsed)->nameaddr.uri);
+ if (msg->route->parsed) free_rr((rr_t**)&msg->route->parsed);
+ return ret;
+ } else {
+ DBG("No Route headers found\n");
+ return -1;
+ }
+ }
+}
+
+
static inline struct hdr_field *valid_to( struct cell *t,
struct sip_msg *reply)
{
@@ -156,9 +249,10 @@
static str mycode;
str *cr;
struct cseq_body *cseq;
+ int dir;
cnt=tl=al=0;
-
+ dir = -2;
/* we don't care about parsing here; either the function
* was called from script, in which case the wrapping function
* is supposed to parse, or from reply processing in which case
@@ -218,10 +312,19 @@
}
/* fallback to from-uri if digest unavailable ... */
case 'F': /* from-uri */
- if (rq->from && (from=get_from(rq))
- && from->uri.len) {
+
+ if (swap_dir && dir == -2) dir = get_direction(rq);
+ if (dir <= 0) {
+ if (rq->from && (from=get_from(rq))
+ && from->uri.len) {
val_arr[cnt]=&from->uri;
- } else val_arr[cnt]=&na;
+ } else val_arr[cnt]=&na;
+ } else {
+ if (rq->to && (pto=get_to(rq))
+ && pto->uri.len) {
+ val_arr[cnt]=&pto->uri;
+ } else val_arr[cnt]=&na;
+ }
ATR(FROMURI);
break;
case '0': /* from user */
@@ -255,10 +358,19 @@
ATR(TOTAG);
break;
case 'T': /* to-uri */
- if (rq->to && (pto=get_to(rq))
- && pto->uri.len) {
+
+ if (swap_dir && dir == -2) dir = get_direction(rq);
+ if (dir <= 0) {
+ if (rq->to && (pto=get_to(rq))
+ && pto->uri.len) {
val_arr[cnt]=&pto->uri;
- } else val_arr[cnt]=&na;
+ } else val_arr[cnt]=&na;
+ } else {
+ if (rq->from && (from=get_from(rq))
+ && from->uri.len) {
+ val_arr[cnt]=&from->uri;
+ } else val_arr[cnt]=&na;
+ }
ATR(TOURI);
break;
case '1': /* to user */
Index: modules/acc/acc_mod.c
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/acc/Attic/acc_mod.c,v
retrieving revision 1.39.2.3
diff -u -r1.39.2.3 acc_mod.c
--- modules/acc/acc_mod.c 20 Sep 2005 16:03:14 -0000 1.39.2.3
+++ modules/acc/acc_mod.c 25 Dec 2005 17:35:20 -0000
@@ -115,6 +115,7 @@
int radius_flag = 0;
int radius_missed_flag = 0;
static int service_type = -1;
+int swap_dir = 0;
void *rh;
struct attr attrs[A_MAX];
struct val vals[V_MAX];
@@ -206,6 +207,7 @@
{"radius_flag", INT_PARAM, &radius_flag },
{"radius_missed_flag", INT_PARAM, &radius_missed_flag },
{"service_type", INT_PARAM, &service_type },
+ {"swap_direction", INT_PARAM, &swap_dir},
#endif
/* DIAMETER */
#ifdef DIAM_ACC
@@ -414,7 +416,7 @@
* don't be worried about parsing outcome -- if it failed,
* we will report N/A
*/
- parse_headers(rq, HDR_CALLID| HDR_FROM| HDR_TO, 0 );
+ parse_headers(rq, HDR_CALLID| HDR_FROM| HDR_TO| HDR_ROUTE, 0 );
parse_from_header(rq);
if (strchr(log_fmt, 'p') || strchr(log_fmt, 'D')) {
Index: modules/acc/acc_mod.h
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/acc/Attic/acc_mod.h,v
retrieving revision 1.14
diff -u -r1.14 acc_mod.h
--- modules/acc/acc_mod.h 24 Aug 2004 08:58:23 -0000 1.14
+++ modules/acc/acc_mod.h 25 Dec 2005 17:35:21 -0000
@@ -87,6 +87,7 @@
extern char* acc_totag_col;
extern char* acc_fromtag_col;
+extern int swap_dir;
#endif /* SQL_ACC */
Index: parser/parse_param.c
===================================================================
RCS file: /cvsroot/ser/sip_router/parser/parse_param.c,v
retrieving revision 1.21
diff -u -r1.21 parse_param.c
--- parser/parse_param.c 1 Sep 2004 12:50:40 -0000 1.21
+++ parser/parse_param.c 25 Dec 2005 17:35:26 -0000
@@ -144,6 +144,15 @@
_h->uri.maddr = _p;
}
break;
+
+ case 'f':
+ case 'F':
+ if ((_p->name.len == 4) &&
+ (!strncasecmp(_p->name.s + 1, "tag", 3))) {
+ _p->type = P_FTAG;
+ _h->uri.ftag = _p;
+ }
+ break;
}
}
@@ -475,6 +484,7 @@
case P_MADDR: type = "P_MADDR"; break;
case P_TTL: type = "P_TTL"; break;
case P_RECEIVED: type = "P_RECEIVED"; break;
+ case P_FTAG: type = "P_FTAG"; break;
default: type = "UNKNOWN"; break;
}
Index: parser/parse_param.h
===================================================================
RCS file: /cvsroot/ser/sip_router/parser/parse_param.h,v
retrieving revision 1.11
diff -u -r1.11 parse_param.h
--- parser/parse_param.h 1 Sep 2004 11:56:59 -0000 1.11
+++ parser/parse_param.h 25 Dec 2005 17:35:26 -0000
@@ -53,6 +53,7 @@
P_R2, /* URI: r2 parameter (ser specific) */
P_MADDR, /* URI: maddr parameter */
P_TTL, /* URI: ttl parameter */
+ P_FTAG /* URI: ftag parameter */
} ptype_t;
@@ -98,6 +99,7 @@
struct param* r2; /* r2 parameter */
struct param* maddr; /* maddr parameter */
struct param* ttl; /* ttl parameter */
+ struct param* ftag; /* ftag parameter */
};
More information about the Devel
mailing list