Hi guys,
I'd like to propose another possibility for a highly-available and
scalable system design based on SER:
The problems I've encountered for scalable systems are:
- Distribution of the user location and alias location among the nodes
(user location is based on registrations, alias location comes from
web interfaces and is used for call forwarding).
- Reloading up to date location tables after breakdown and recovery of a
node
So I'm just thinking loud about the following provisioning system:
- Write a client which fulfills the this demands:
- Receive one or more locations from SER via a SER module or from a
web application and distribute them to other
known clients. Take care of retransmissions if a client isn't
reachable or reports a temporary failure.
- Receive one or more locations from other clients and write
them into the SER FIFO. If writing into the FIFO fails, try to
write directly into the database (location-table, alias-table etc.).
Report a temporary failure if this also fails.
Maybe a centralized server should be used which receives the locations
from the clients and distributes them to other clients, so that the
nodes just know about the server and nothing about other nodes. This
would make integration of new nodes easy.
On the other hand, it's another single point of failure, so a
decentralized solution should be considered. But that would mean that
you've to inform every node about the existence of a new node.
The protocol used between the nodes should be simple and fast. So I
think SOAP drops out here. Maybe XMLRPC or ICE
(http://www.zeroc.com/ice.html) could be used.
One might think now why not just use replication on SIP layer, but
t_replicate only supports one peer and you've no possibility to get
locations on a node while it's down. Replication of other location
tables like the alias-table is also not possible.
I'd be willing to release these parts as GPL for creating an open
framework for carrier-grade SER integration, so any feedback,
improvements or flames are highly welcome.
Cheers,
Andy
I am relatively new to SER. My SIP service provider requires me to
present the ANI in the "From" field in my INVITE message header in E.164
format. I am currently sending this information as follows:
From: "2125551212" <sip:2125551212@xxx.xxx.xxx.xxx>
They want it in E.164 format as follows:
From: "+12125551212" <sip:+12125551212@xxx.xxx.xxx.xxx>
I see function only to modify the SIP URI but not the other header or
SDP fields.
Could someone help me with a code snippet that I can use in ser.cfg to
do this conversion?
Regards,
SCM
Does anyone know if there is a way to authenticate SER to MS Active
Directory? I'd like to use an existing user database instead of
having to manage users myself, and most of our users are in Active
Directory.
Has anyone tried this?
What are most SER users using for authentication? Is anyone here
tying into any kind of existing organization user database?
Hi
I just installed ser v0.8.14 from the *.tar.gz distribution and when I
try to run serctl moni it gives me an error saying:
Error opening ser's FIFO /tmp/ser_fifo
Make sure you have line fifo=/tmp/ser_fifo in your config
in the ser.cfg file the line
fifo="/tmp/ser_fifo"
is uncommented.
what am I doing wrong
We are using SER with the PostgreSQL module, so that SER and our
Asterisk PSTN gateway and voice mail system can use the same back-end
database for user records. (Anyone who's interested in how we did this,
let me know -- it's still a little shaky, but it pretty much works.)
Recently we have encountered a problem: it seems that if any database
error occurs, SER hangs or crashes. We have so far been able to mostly
work around these conditions by being Really Careful with the database,
but it is a little unsettling.
The database schema we're working from is practically identical to the
MySQL schema that ships with SER. Notably for this problem the lengths
of all CHARACTER VARYING fields are the same. The User-Agent field is
CHARACTER VARYING(50), for instance.
So ... today boss got a copy of Xten's "eyeBeam" software, set it up
to register to our SER ... and SER promptly locked up. I looked in the
PostgreSQL database log and found this:
Feb 10 13:39:32 mabell postgres[13058]: [267] ERROR: value too long for
type character varying(50)
Whoops. SER tried to insert eyeBeam's User-Agent data, PostgreSQL
returned a data integrity error, and SER went bye-bye.
So I did a little ALTER TABLE and adjusted the field to length 128 ...
then put this in ser.cfg:
# Disallow long user-agent
if (search("^User-Agent: .{100,}") ) {
log(1, "LOG: User agent too long\n");
sl_send_reply("479", "User agent too long!");
break;
};
But this is obviously a kludge ... and doesn't fix the problem of one of
the *other* fields being over-long.
Anyone have any thoughts on this? Robustness patches for the PostgreSQL
module or usrloc? Better ser.cfg workarounds to protect the world from
malformed or over-long SIP header fields? Should I just change all the
database fields to TEXT instead of CHARACTER VARYING(whatever) ?
--
Karl A. Krueger <kkrueger(a)whoi.edu>
Network Security -- Linux/Unix Systems Support -- Etc.
Woods Hole Oceanographic Institution
Hi,
I´ve configured freeradius and SER according to the Radius HOW TO
document, Accounting works very well but now I am doing some tests
trying to do user authentication however all the authentication
requests coming to the freeradius fails and X-lite sipphone is
receiving an Unauthorized message from SER, please some advice,
thanks
rafael
PS: config files...
in /usr/local/etc/raddb/users :
---------
test Auth-Type := Digest, User-Password == "test"
Reply-Message = "Hello, test with digest"
6609876 Auth-Type := Digest
User-Password := "9876",
Digest-Response = "lalalalala",
Reply-Message = "Hello, ibm1"
6604321 Auth-Type := Digest
User-Password := "4321",
Digest-Response = "lalalalala",
Reply-Message = "Hello, ibm2"
---------
Some relevant data in ser.cfg:
...
modparam("group_radius", "use_domain", 0)
....
if (uri==myself) {
if (method=="REGISTER") {
# Uncomment this if you want to use digest authentication
if (!radius_www_authorize("")) {
www_challenge("", "1");
break;
};
if (!save("location")) {
sl_reply_error();
};
break;
};
lookup("aliases");
if (!uri==myself) {
append_hf("P-hint: outbound alias\r\n");
route(1);
break;
};
# does the user wish redirection on no availability?
(i.e., is he
# in the voicemail group?) -- determine it now and store it in
# flag 4, before we rewrite the flag using UsrLoc
if (radius_is_user_in("Request-URI", "voicemail")) {
log(1, "requested user is in voicemail group");
setflag(4);
};
# native SIP destinations are handled using our USRLOC DB
if (!lookup("location")) {
# sl_send_reply("404", "Not Found");
log(1,"unable to locate user");
route(4);
break;
};
}; # End of "if(uri==myself)"
....
------------------RADIUSD -X Output ---------------------------:
rad_recv: Access-Request packet from host 127.0.0.1:33187, id=79, length=311
User-Name = "6604321(a)10.0.1.22"
Digest-Attributes = 0x0a0936363034333231
Digest-Attributes = 0x010b31302e302e312e3232
Digest-Attributes =
0x022a34323366333163373062336631643261643330383833633238303434316632663133643136613830
Digest-Attributes = 0x040f7369703a31302e302e312e3232
Digest-Attributes = 0x030a5245474953544552
Digest-Attributes = 0x050661757468
Digest-Attributes = 0x090a3030303030303162
Digest-Attributes =
0x08224433343132424232394131453131443939334232303035304241373836433642
Digest-Response = "a6a7812ac0331324f977453c228da2ed"
Service-Type = IAPP-Register
Sip-URI-User = "6604321"
Cisco-AVPair = "call-id=D3412ADB9A1E11D993B20050BA786C6B(a)10.0.1.22"
NAS-IP-Address = 127.0.0.1
NAS-Port = 5060
Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 8
modcall[authorize]: module "preprocess" returns ok for request 8
modcall[authorize]: module "chap" returns noop for request 8
modcall[authorize]: module "mschap" returns noop for request 8
rlm_digest: Converting Digest-Attributes to something sane...
Digest-User-Name = "6604321"
Digest-Realm = "10.0.1.22"
Digest-Nonce = "423f31c70b3f1d2ad30883c280441f2f13d16a80"
Digest-URI = "sip:10.0.1.22"
Digest-Method = "REGISTER"
Digest-QOP = "auth"
Digest-Nonce-Count = "0000001b"
Digest-CNonce = "D3412BB29A1E11D993B20050BA786C6B"
rlm_digest: Adding Auth-Type = DIGEST
modcall[authorize]: module "digest" returns ok for request 8
rlm_realm: Looking up realm "10.0.1.22" for User-Name = "6604321(a)10.0.1.22"
rlm_realm: No such realm "10.0.1.22"
modcall[authorize]: module "suffix" returns noop for request 8
rlm_eap: No EAP-Message, not doing EAP
modcall[authorize]: module "eap" returns noop for request 8
users: Matched DEFAULT at 152
modcall[authorize]: module "files" returns ok for request 8
modcall: group authorize returns ok for request 8
rad_check_password: Found Auth-Type DIGEST
auth: type "digest"
Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 8
rlm_digest: Configuration item "User-Password" is required for authentication.
modcall[authenticate]: module "digest" returns invalid for request 8
modcall: group authenticate returns invalid for request 8
auth: Failed to validate the user.
Delaying request 8 for 1 seconds
Finished request 8
Going to the next request
--- Walking the entire request list ---
Waking up in 1 seconds...
rad_recv: Access-Request packet from host 127.0.0.1:33188, id=80, length=311
User-Name = "6609876(a)10.0.1.22"
Digest-Attributes = 0x0a0936363039383736
Digest-Attributes = 0x010b31302e302e312e3232
Digest-Attributes =
0x022a34323366333163373062336631643261643330383833633238303434316632663133643136613830
Digest-Attributes = 0x040f7369703a31302e302e312e3232
Digest-Attributes = 0x030a5245474953544552
Digest-Attributes = 0x050661757468
Digest-Attributes = 0x090a3030303030303163
Digest-Attributes =
0x08224433343132424235394131453131443939334232303035304241373836433642
Digest-Response = "50fa695654b20e2eec54a1003fe15d9f"
Service-Type = IAPP-Register
Sip-URI-User = "6609876"
Cisco-AVPair = "call-id=D3412ADE9A1E11D993B20050BA786C6B(a)10.0.1.22"
NAS-IP-Address = 127.0.0.1
NAS-Port = 5060
Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 9
modcall[authorize]: module "preprocess" returns ok for request 9
modcall[authorize]: module "chap" returns noop for request 9
modcall[authorize]: module "mschap" returns noop for request 9
rlm_digest: Converting Digest-Attributes to something sane...
Digest-User-Name = "6609876"
Digest-Realm = "10.0.1.22"
Digest-Nonce = "423f31c70b3f1d2ad30883c280441f2f13d16a80"
Digest-URI = "sip:10.0.1.22"
Digest-Method = "REGISTER"
Digest-QOP = "auth"
Digest-Nonce-Count = "0000001c"
Digest-CNonce = "D3412BB59A1E11D993B20050BA786C6B"
rlm_digest: Adding Auth-Type = DIGEST
modcall[authorize]: module "digest" returns ok for request 9
rlm_realm: Looking up realm "10.0.1.22" for User-Name = "6609876(a)10.0.1.22"
rlm_realm: No such realm "10.0.1.22"
modcall[authorize]: module "suffix" returns noop for request 9
rlm_eap: No EAP-Message, not doing EAP
modcall[authorize]: module "eap" returns noop for request 9
users: Matched DEFAULT at 152
modcall[authorize]: module "files" returns ok for request 9
modcall: group authorize returns ok for request 9
rad_check_password: Found Auth-Type DIGEST
auth: type "digest"
Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 9
rlm_digest: Configuration item "User-Password" is required for authentication.
modcall[authenticate]: module "digest" returns invalid for request 9
modcall: group authenticate returns invalid for request 9
auth: Failed to validate the user.
Delaying request 9 for 1 seconds
Finished request 9
Going to the next request
--- Walking the entire request list ---
Waking up in 1 seconds...
--- Walking the entire request list ---
Sending Access-Reject of id 79 to 127.0.0.1:33187
Waking up in 1 seconds...
rad_recv: Access-Request packet from host 127.0.0.1:33189, id=81, length=311
User-Name = "6609876(a)10.0.1.22"
Digest-Attributes = 0x0a0936363039383736
Digest-Attributes = 0x010b31302e302e312e3232
Digest-Attributes =
0x022a34323366333163373062336631643261643330383833633238303434316632663133643136613830
Digest-Attributes = 0x040f7369703a31302e302e312e3232
Digest-Attributes = 0x030a5245474953544552
Digest-Attributes = 0x050661757468
Digest-Attributes = 0x090a3030303030303163
Digest-Attributes =
0x08224433343132424236394131453131443939334232303035304241373836433642
Digest-Response = "e4f68760f2b3eed0ad45942b32542c92"
Service-Type = IAPP-Register
Sip-URI-User = "6609876"
Cisco-AVPair = "call-id=D3412ADE9A1E11D993B20050BA786C6B(a)10.0.1.22"
NAS-IP-Address = 127.0.0.1
NAS-Port = 5060
Processing the authorize section of radiusd.conf
modcall: entering group authorize for request 10
modcall[authorize]: module "preprocess" returns ok for request 10
modcall[authorize]: module "chap" returns noop for request 10
modcall[authorize]: module "mschap" returns noop for request 10
rlm_digest: Converting Digest-Attributes to something sane...
Digest-User-Name = "6609876"
Digest-Realm = "10.0.1.22"
Digest-Nonce = "423f31c70b3f1d2ad30883c280441f2f13d16a80"
Digest-URI = "sip:10.0.1.22"
Digest-Method = "REGISTER"
Digest-QOP = "auth"
Digest-Nonce-Count = "0000001c"
Digest-CNonce = "D3412BB69A1E11D993B20050BA786C6B"
rlm_digest: Adding Auth-Type = DIGEST
modcall[authorize]: module "digest" returns ok for request 10
rlm_realm: Looking up realm "10.0.1.22" for User-Name = "6609876(a)10.0.1.22"
rlm_realm: No such realm "10.0.1.22"
modcall[authorize]: module "suffix" returns noop for request 10
rlm_eap: No EAP-Message, not doing EAP
modcall[authorize]: module "eap" returns noop for request 10
users: Matched DEFAULT at 152
modcall[authorize]: module "files" returns ok for request 10
modcall: group authorize returns ok for request 10
rad_check_password: Found Auth-Type DIGEST
auth: type "digest"
Processing the authenticate section of radiusd.conf
modcall: entering group authenticate for request 10
rlm_digest: Configuration item "User-Password" is required for authentication.
modcall[authenticate]: module "digest" returns invalid for request 10
modcall: group authenticate returns invalid for request 10
auth: Failed to validate the user.
Delaying request 10 for 1 seconds
Finished request 10
Going to the next request
Sending Access-Reject of id 80 to 127.0.0.1:33188
Waking up in 1 seconds...
--- Walking the entire request list ---
Waking up in 1 seconds...
--- Walking the entire request list ---
Sending Access-Reject of id 81 to 127.0.0.1:33189
Waking up in 2 seconds...
--- Walking the entire request list ---
Cleaning up request 8 ID 79 with timestamp 423f309b
Waking up in 1 seconds...
--- Walking the entire request list ---
Cleaning up request 9 ID 80 with timestamp 423f309c
Waking up in 1 seconds...
--- Walking the entire request list ---
Cleaning up request 10 ID 81 with timestamp 423f309d
Nothing to do. Sleeping until we see a request.
--
rrgv
We are all aware of SER limitation due the fact it is *only* transaction
statefull at proxy level, any dialog support being missing. There are
many features/services which actually requires a dialog awareness, like
storing the information in the dialog creation stage, information which
will be used during the whole dialog existence.
The most urging example is NAT traversal, in dealing with the within the
dialog INVITEs (re-INVITEs). When processing the initial INVITE, the
proxy detects if the caller or callee is behind some NAT and fixes the
signalling and media parts - since not all the detection mechanism are
available for within the dialog requests (like usrloc), to be able to
fix correspondingly the sequential requests, the proxy must remember
that the original request was NAT processed.
There are many other cases where dialog awareness fixes or helps....it's
not my goal to make a list here....
The solution is to store additional dialog-related information in the
routing set, headers which show up in all sequential requests; by
routing set I would say the Route hdrs and RURI; the routing set is
build based on Record-Route and Contact hdrs.
So far, the way to go was using the Contact header (via parameters) as
carrier. In most of the cases works, but this mechanism is not RFC
reinforced - I had a talk with Juha and he found some phones which
actually ignore the Contact hdr parameters, which is perfect allowed by
RFC....Not to mention that which Contact hdr (UAC or UAS) appear in
routing info depends on the request direction (UAC->UAS or UAS->UAC) and
Record-Route parameters are re-infonced by RFC (see 12.1.1 UAS behavior)
So the next try is to add this information in the Record-Route header
inserted by the proxy. Within the dialog, this information can be found
(with no direction dependencies) in Route header (with or proxy address)...
And here is a patch for the RR module which adds this functionality:
1) adding parameters to Record-Route; since RR is inserted during req.
processing (as lump), no textops function can be apply to it. So use the
add_rr_param("param") function - it can be called also before or after
the record_route() call; I would say it's more convenient from scripting
point of view (no dependencies between doing record_route() and adding
params);
2) checking Route parameters: this could be done via textops, but it
would be dangerous -> you have to identify the Route header
corresponding to your proxy (which will be quite difficult to put as
regexp), So use check_route_param("regexp") function which will check
the proper Route parameters against the given regexp. Must be call after
loose_route().
Basic scenario (example):
UAC SER
PROXY UAS
------ INVITE ----------> record_route() ---------
INVITE -------->
add_rr_param(";foo=true")
----- reINVITE ---------> loose_route() --------
reINVITE ------->
check_route_param(";foo=true")
<---- reINVITE ---------- loose_route() <-------
reINVITE --------
check_route_param(";foo=true")
<-------- BYE ----------- loose_route() <--------- BYE
-----------
check_route_param(";foo=true")
The patch doesn't alter any of the previous functionality.
Jan take a look and let's put it on CVS.
bogdan
Index: modules/rr/loose.c
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/rr/loose.c,v
retrieving revision 1.36
diff -u -r1.36 loose.c
--- modules/rr/loose.c 23 Feb 2005 17:16:05 -0000 1.36
+++ modules/rr/loose.c 15 Apr 2005 14:52:55 -0000
@@ -30,6 +30,8 @@
* ---------
* 2003-02-28 scratchpad compatibility abandoned (jiri)
* 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
+ * 2005-04-10 check_route_param() and all hooks for keeping reference to
+ * Route params added (bogdan)
*/
@@ -57,6 +59,10 @@
#define ROUTE_SUFFIX ">\r\n"
#define ROUTE_SUFFIX_LEN (sizeof(ROUTE_SUFFIX)-1)
+/* variables used to hook the param part of the local route -bogdan */
+static unsigned int routed_msg_id;
+static str routed_params = {0,0};
+
/*
* Test whether we are processing pre-loaded route set
@@ -511,12 +517,16 @@
if (is_myself(&puri.host, puri.port_no))
#endif
{
- /* if (enable_double_rr && is_2rr(&_ruri->params)) { */
- /* DBG("ras(): Removing 2nd URI of mine: '%.*s'\n", rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); */
+ /*if (enable_double_rr && is_2rr(&_ruri->params)) {
+ * DBG("ras(): Removing 2nd URI of mine: '%.*s'\n",
+ * rt->nameaddr.uri.len, ZSW(rt->nameaddr.uri.s)); */
+ /* set the hooks for the params -bogdan */
+ routed_msg_id = _m->id;
+ routed_params = puri.params;
if (!rt->next) {
- /* No next route in the same header, remove the whole header
- * field immediately
- */
+ /* No next route in the same header, remove the whole header
+ * field immediately
+ */
if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
LOG(L_ERR, "after_strict: Cannot remove Route HF\n");
return RR_ERROR;
@@ -661,11 +671,15 @@
if (is_myself(&puri.host, puri.port_no))
#endif
{
- DBG("after_loose: Topmost route URI: '%.*s' is me\n", uri->len, ZSW(uri->s));
+ DBG("after_loose: Topmost route URI: '%.*s' is me\n",
+ uri->len, ZSW(uri->s));
+ /* set the hooks for the params -bogdan */
+ routed_msg_id = _m->id;
+ routed_params = puri.params;
if (!rt->next) {
- /* No next route in the same header, remove the whole header
- * field immediately
- */
+ /* No next route in the same header, remove the whole header
+ * field immediately
+ */
if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
LOG(L_ERR, "after_loose: Can't remove Route HF\n");
return RR_ERROR;
@@ -684,16 +698,16 @@
if (enable_double_rr && is_2rr(&puri.params)) {
if (!rt->next) {
- /* No next route in the same header, remove the whole header
- * field immediately
- */
+ /* No next route in the same header, remove the whole header
+ * field immediately
+ */
if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
LOG(L_ERR, "after_loose: Can't remove Route HF\n");
return RR_ERROR;
}
res = find_next_route(_m, &hdr);
if (res < 0) {
- LOG(L_ERR, "after_loose: Error while finding next route\n");
+ LOG(L_ERR,"after_loose: Error while finding next route\n");
return RR_ERROR;
}
if (res > 0) { /* No next route found */
@@ -783,3 +797,32 @@
}
}
}
+
+
+
+int check_route_param(struct sip_msg * msg, char *re, char *foo)
+{
+ regmatch_t pmatch;
+ char bk;
+
+ /* check if the hooked params belong to the same message */
+ if (routed_msg_id != msg->id)
+ return -1;
+
+ /* check if params are present */
+ if ( !routed_params.s || !routed_params.len )
+ return -1;
+
+ /* do the well-known trick to convert to null terminted */
+ bk = routed_params.s[routed_params.len];
+ routed_params.s[routed_params.len] = 0;
+ DBG("DEBUG:rr:check_route_param: params are <%s>\n", routed_params.s);
+ if (regexec( (regex_t*)re, routed_params.s, 1, &pmatch, 0)!=0) {
+ routed_params.s[routed_params.len] = bk;
+ return -1;
+ } else {
+ routed_params.s[routed_params.len] = bk;
+ return 1;
+ }
+}
+
Index: modules/rr/loose.h
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/rr/loose.h,v
retrieving revision 1.3
diff -u -r1.3 loose.h
--- modules/rr/loose.h 24 Aug 2004 09:00:38 -0000 1.3
+++ modules/rr/loose.h 15 Apr 2005 14:52:56 -0000
@@ -40,4 +40,6 @@
int loose_route(struct sip_msg* _m, char* _s1, char* _s2);
+int check_route_param(struct sip_msg * msg, char *re, char *foo);
+
#endif /* LOOSE_H */
Index: modules/rr/record.c
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/rr/record.c,v
retrieving revision 1.14
diff -u -r1.14 record.c
--- modules/rr/record.c 24 Aug 2004 09:00:38 -0000 1.14
+++ modules/rr/record.c 15 Apr 2005 14:52:56 -0000
@@ -29,6 +29,7 @@
* History:
* -------
* 2003-04-04 Extracted from common.[ch] (janakj)
+ * 2005-04-10 add_rr_param() function and all corresponing hooks added (bogdan)
*/
#include <string.h>
@@ -63,6 +64,22 @@
#define INBOUND 1 /* Insert inbound Record-Route */
#define OUTBOUND 0 /* Insert outbound Record-Route */
+#define RR_PARAM_BUF_SIZE 512
+
+static unsigned int last_rr_msg;
+
+/* RR suffix lump and offset - used for inserting RR params
+ * after RR was done; use a two values array for INBOUND and
+ * OUTBOUND RR -bogdan */
+static struct lump *rr_suffix_lump[2] = {0,0};
+static int rr_suffix_end_offset[2] = {0,0};
+
+/* RR param buffer - usd for storing RR param which are
+ * added before RR insertion -bogdan */
+static char rr_param_buf_ptr[RR_PARAM_BUF_SIZE];
+static str rr_param_buf = {rr_param_buf_ptr,0};
+static unsigned int rr_param_msg;
+
/*
* Extract username from the Request URI
@@ -104,16 +121,20 @@
{
char* prefix, *suffix, *crlf, *r2;
int suffix_len, prefix_len;
+ char *p;
prefix_len = RR_PREFIX_LEN + (user->len ? (user->len + 1) : 0);
prefix = pkg_malloc(prefix_len);
if (enable_full_lr) {
suffix_len = (_lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN) +
- ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
+ ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0) +
+ rr_param_buf.len;
} else {
suffix_len = (_lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN) +
- ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0);
+ ((tag && tag->len) ? (RR_FROMTAG_LEN + tag->len) : 0) +
+ rr_param_buf.len;
}
+ rr_suffix_end_offset[_inbound] = RR_SR_TERM_LEN;
suffix = pkg_malloc(suffix_len);
crlf = pkg_malloc(2);
@@ -145,21 +166,24 @@
#endif
prefix[RR_PREFIX_LEN + user->len] = '@';
}
-
+
+ p = suffix;
if (tag && tag->len) {
- memcpy(suffix, RR_FROMTAG, RR_FROMTAG_LEN);
- memcpy(suffix + RR_FROMTAG_LEN, tag->s, tag->len);
- if (enable_full_lr) {
- memcpy(suffix + RR_FROMTAG_LEN + tag->len, _lr ? RR_LR_FULL_TERM : RR_SR_TERM, _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN);
- } else {
- memcpy(suffix + RR_FROMTAG_LEN + tag->len, _lr ? RR_LR_TERM : RR_SR_TERM, _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN);
- }
+ memcpy(p, RR_FROMTAG, RR_FROMTAG_LEN);
+ p += RR_FROMTAG_LEN;
+ memcpy(p, tag->s, tag->len);
+ p += tag->len;
+ }
+ if (rr_param_buf.len) {
+ memcpy( p, rr_param_buf.s, rr_param_buf.len);
+ p += rr_param_buf.len;
+ }
+ if (enable_full_lr) {
+ memcpy( p, _lr ? RR_LR_FULL_TERM : RR_SR_TERM,
+ _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN);
} else {
- if (enable_full_lr) {
- memcpy(suffix, _lr ? RR_LR_FULL_TERM : RR_SR_TERM, _lr ? RR_LR_FULL_TERM_LEN : RR_SR_TERM_LEN);
- } else {
- memcpy(suffix, _lr ? RR_LR_TERM : RR_SR_TERM, _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN);
- }
+ memcpy( p, _lr ? RR_LR_TERM : RR_SR_TERM,
+ _lr ? RR_LR_TERM_LEN : RR_SR_TERM_LEN);
}
memcpy(crlf, CRLF, 2);
@@ -177,6 +201,7 @@
r2 = 0;
}
if (!(_l2 = insert_new_lump_before(_l2, suffix, suffix_len, 0))) goto lump_err;
+ rr_suffix_lump[_inbound] = _l2;
suffix = 0;
if (!(_l2 = insert_new_lump_before(_l2, crlf, 2, 0))) goto lump_err;
crlf = 0;
@@ -225,6 +250,12 @@
tag = 0;
}
+ if (rr_param_buf.len && rr_param_msg!=_m->id) {
+ /* rr_params were set for a different message -> reset buffer */
+ rr_param_buf.len = 0;
+ DBG("----> reset rr_param_buf\n");
+ }
+
if (enable_double_rr) {
l = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
l2 = anchor_lump(_m, _m->headers->name.s - _m->buf, 0, 0);
@@ -256,6 +287,8 @@
return -4;
}
+ /* reset the rr_param buffer */
+ rr_param_buf.len = 0;
return 0;
}
@@ -266,8 +299,6 @@
*/
static inline int do_RR(struct sip_msg* _m, int _lr)
{
- static unsigned int last_rr_msg;
-
if (_m->id == last_rr_msg) {
LOG(L_ERR, "record_route(): Double attempt to record-route\n");
return -1;
@@ -395,3 +426,72 @@
{
return do_RR(_m, 0);
}
+
+
+/*
+ * Appends a string to an existent lump
+ */
+static inline int append_to_lump( struct lump *l, str *s, int end_offset)
+{
+ char *p;
+
+ /* update buffer */
+ p = pkg_realloc( l->u.value, l->len+s->len);
+ if (p==0) {
+ LOG(L_ERR,"ERROR:rr:add_rr_param: no more pkg memory\n");
+ return -1;
+ }
+ memmove(p+l->len-end_offset+s->len, p+l->len-end_offset, end_offset);
+ memcpy( p+l->len-end_offset, s->s, s->len);
+ /* update lump structure */
+ l->len += s->len;
+ l->u.value = p;
+ return 0;
+}
+
+
+/*
+ * Appends a new Record-Route parameter
+ */
+int add_rr_param(struct sip_msg* msg, char* param, char* foo)
+{
+ str *rr_param;
+ int i;
+
+ rr_param = (str*)param;
+
+ if (last_rr_msg==msg->id) {
+ /* RR was already done -> have to modify the RR-sufix lump */
+ for( i=OUTBOUND ; i<=INBOUND ; i++ ) {
+ if ( !rr_suffix_lump[i] || !rr_suffix_end_offset[i] )
+ continue;
+ if (append_to_lump( rr_suffix_lump[i], rr_param,
+ rr_suffix_end_offset[i])!=0) {
+ LOG(L_ERR,"ERROR:rr:add_rr_param: failed to update lump\n");
+ goto error;
+ }
+ }
+ } else {
+ /* RR not done yet -> store the param in the static buffer */
+ if (rr_param_msg!=msg->id) {
+ /* it's about a different messge -> reset buffer */
+ rr_param_buf.len = 0;
+ rr_param_msg = msg->id;
+ }
+ if (rr_param_buf.len+rr_param->len>RR_PARAM_BUF_SIZE) {
+ LOG(L_ERR,"ERROR:rr:add_rr_param: maximum size of "
+ "rr_param_buf exceeded\n");
+ goto error;
+ }
+ memcpy( rr_param_buf.s+rr_param_buf.len, rr_param->s, rr_param->len);
+ rr_param_buf.len += rr_param->len;
+ DBG("DEBUG:rr:add_rr_param: rr_param_buf=<%.*s>\n",rr_param_buf.len,
+ rr_param_buf.s);
+ }
+ return 1;
+
+error:
+ return -1;
+}
+
+
Index: modules/rr/record.h
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/rr/record.h,v
retrieving revision 1.2
diff -u -r1.2 record.h
--- modules/rr/record.h 24 Aug 2004 09:00:38 -0000 1.2
+++ modules/rr/record.h 15 Apr 2005 14:52:56 -0000
@@ -56,4 +56,10 @@
int record_route_strict(struct sip_msg* _m, char* _s1, char* _s2);
+/*
+ * Appends a new Record-Route parameter
+ */
+int add_rr_param(struct sip_msg* msg, char* param, char* foo);
+
+
#endif /* RECORD_H */
Index: modules/rr/rr_mod.c
===================================================================
RCS file: /cvsroot/ser/sip_router/modules/rr/rr_mod.c,v
retrieving revision 1.33
diff -u -r1.33 rr_mod.c
--- modules/rr/rr_mod.c 24 Aug 2004 09:00:38 -0000 1.33
+++ modules/rr/rr_mod.c 15 Apr 2005 14:52:57 -0000
@@ -33,11 +33,14 @@
* 2003-03-19 all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
* 2003-04-01 Added record_route with ip address parameter (janakj)
* 2003-04-14 enable_full_lr parameter introduced (janakj)
+ * 2005-04-10 add_rr_param() and check_route_param() added (bogdan)
*/
#include <stdio.h>
#include <stdlib.h>
+#include <regex.h>
+
#include "../../sr_module.h"
#include "../../ut.h"
#include "../../error.h"
@@ -61,6 +64,7 @@
static int mod_init(void);
static int str_fixup(void** param, int param_no);
+static int regexp_fixup(void** param, int param_no);
/*
@@ -74,10 +78,18 @@
* Oh, BTW, have I mentioned already that you shouldn't use strict routing ?
*/
static cmd_export_t cmds[] = {
- {"loose_route", loose_route, 0, 0, REQUEST_ROUTE},
- {"record_route", record_route, 0, 0, REQUEST_ROUTE},
- {"record_route_preset", record_route_preset, 1, str_fixup, REQUEST_ROUTE},
- {"record_route_strict" , record_route_strict, 0, 0, 0 },
+ {"loose_route", loose_route, 0, 0,
+ REQUEST_ROUTE},
+ {"record_route", record_route, 0, 0,
+ REQUEST_ROUTE},
+ {"record_route_preset", record_route_preset, 1, str_fixup,
+ REQUEST_ROUTE},
+ {"record_route_strict" , record_route_strict, 0, 0,
+ 0},
+ {"add_rr_param", add_rr_param, 1, str_fixup,
+ REQUEST_ROUTE},
+ {"check_route_param", check_route_param, 1, regexp_fixup,
+ REQUEST_ROUTE},
{0, 0, 0, 0, 0}
};
@@ -149,3 +161,29 @@
return 0;
}
+
+
+static int regexp_fixup(void** param, int param_no)
+{
+ regex_t* re;
+
+ if (param_no==1) {
+ if ((re=pkg_malloc(sizeof(regex_t)))==0) {
+ LOG(L_ERR,"ERROR:rr:regexp_fixup: no more pkg memory\n");
+ return E_OUT_OF_MEM;
+ }
+ if (regcomp(re, *param, REG_EXTENDED|REG_ICASE|REG_NEWLINE) ) {
+ pkg_free(re);
+ LOG(L_ERR, "ERROR:rr:regexp_fixup: bad regexp %s\n",(char*)*param);
+ return E_BAD_RE;
+ }
+ /* free string */
+ pkg_free(*param);
+ /* replace it with the compiled re */
+ *param=re;
+ }
+ return 0;
+}
+
+
+
I have same problem in xmpp messages , I can not understand well those module's configure (jabber.so ,pa.so),Can I used the jid as a ser account?
Thanks
Zhaomin
----- Original Message -----
From: "Steven Poveda" <stepoca(a)hotmail.com>
To: <serusers(a)iptel.org>
Sent: Wednesday, May 25, 2005 6:42 AM
Subject: [Serusers] How to configure pa?
> Hi,
>
> I have just installed SER and I can see the server is not supporting PUBLISH method. I have loaded pa module but the reject to PUBLISH method is stil there.
>
> Where can I find information regarding pa configuration ?
>
> Regards,
>
> Steven
>
>
>
>
> --------------------------------------------------------------------------------
> Don't just search. Find. MSN Search Check out the new MSN Search!
--------------------------------------------------------------------------------
> _______________________________________________
> Serusers mailing list
> Serusers(a)iptel.org
> http://mail.iptel.org/mailman/listinfo/serusers
>
Hello,
is it possible to use add_rcv_param() also for Contact-HF of INVITEs,
instead of fix_nated_contact()?
This would make sure that the NATed End Device gets fed exactly the
contact as R-URI that it announced in the INVITE:
Example R-URI in Loose-Route Requests for fix_nated_contact():
Ser (1.2.3.4):
INVITE device(a)4.5.6.7
Route: 1.2.3.4;lr=on
Device (10.0.0.1, NAT 4.5.6.7):
INVITE device(a)123.123.123.123
With add_rcv_param():
Ser:
INVITE device(a)10.0.0.1;rcv_param=4.5.6.7
Route: 1.2.3.4;lr=on
Device:
INVITE device(a)10.0.0.1
The problem is that the End-Device, in the fix_nated_contact() callflow,
has to accept a Request that is not really for this device (IP in
Request-URI != IP of the Device). Imagine a Ser checkip uri == myself.
This would fail without knowing the public IP of the NAT and
hard-conding it into Ser.cfg.
Does Ser support the rcv_param in Request-URI also?
What do you think? Any experience on this?
Regards,
Martin