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" <[EMAIL PROTECTED]> 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:[EMAIL PROTECTED] 
> Sent: Thursday, November 17, 2005 10:33 AM
> To: Lenir
> Cc: 'Klaus Darilion'; [EMAIL PROTECTED]; [EMAIL PROTECTED];
> [email protected]; [email protected]
> 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 */
 };
 
 
_______________________________________________
Users mailing list
[email protected]
http://openser.org/cgi-bin/mailman/listinfo/users

Reply via email to