[Devel] Inaccurate Radius Accounting

Bogdan-Andrei Iancu bogdan at voice-system.ro
Wed Jan 4 17:31:00 CET 2006


Hi Lenir, Hi Klaus,

sure - no problem integrating the functionality, but the patch needs to 
be completely re-written as most of the newly functions added by Jan 
already exists in openser - functions related to RR, like determining 
the direction of a request.

regards,
bogdan

Klaus Darilion wrote:

> I'm on it - just testing at the moment.
>
> regards
> klaus
>
> Lenir wrote:
>
>> 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.
>>>
>>>
>>>
>>> ------------------------------------------------------------------------ 
>>>
>>>
>>> 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, &params) < 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 */
>>> };
>>>
>>>
>>>
>>>
>>> ------------------------------------------------------------------------ 
>>>
>>>
>>> _______________________________________________
>>> Devel mailing list
>>> Devel at openser.org
>>> http://openser.org/cgi-bin/mailman/listinfo/devel
>>
>
> _______________________________________________
> Devel mailing list
> Devel at openser.org
> http://openser.org/cgi-bin/mailman/listinfo/devel
>




More information about the Devel mailing list