Merge tag 'upstream/4.4.1'

Upstream version 4.4.1
changes/38/6038/4
Victor Seva 9 years ago
commit d7a61ec422

@ -15,7 +15,7 @@ branches:
notifications:
irc:
channels:
- "chat.freenode.net#Kamailio"
- "chat.freenode.net#kamailio-dev"
on_success: never
on_failure: always
email:

@ -1,3 +1,895 @@
===================== 2016-05-10 Version 4.4.1 Released =====================
===================== Changes Since Version 4.4.0 ===========================
commit 8ccc17f316731492e668d2de0d07b6eb1e5cb4fc
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:45:21 2016 +0200
Makefile.defs: version set to 4.4.1
commit 5e699d7bcdcffa457e3ff1945c5783e039c57380
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:41:13 2016 +0200
pkg/rpm: spec updated to 4.4.1 for centos, fedora and oracle-el
commit ea95ff497fbeb9742ff7af395e907a94814547c4
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:39:04 2016 +0200
pkg/rpm: version set to 4.4.1 in rpm specs
commit f8449978ff36daba233b21c0017179f55815ebce
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:31:14 2016 +0200
modules: acc_radius, kazoo, misc_radius - regenerated readmes
commit b09fc298bc21248486801c38a60fdb5829ea14e8
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:27:18 2016 +0200
misc_radius: fixed missing ending of docbook tag
(cherry picked from commit 17ebcb3ed9c62302c3950fd378401460bef1a6a0)
commit 436bd786616cdce3b15069eb1ba08aeb853916cd
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 10 16:26:29 2016 +0200
acc_radius: fixed ending docbook tags
(cherry picked from commit a2419ccee9a4d2f0f84fc871dbc8afdd3cf7f471)
commit 4ebbbaeaf3c2a2feb30266a7995fa334e3c0fe7b
Author: Victor Seva <linuxmaniac@torreviejawireless.org>
Date: Tue May 10 12:07:55 2016 +0200
pkg/kamailio/deb: set version to 4.4.1
commit 56bc38856944ca7f8fdbef32c6430b4dac049634
Author: Victor Seva <linuxmaniac@torreviejawireless.org>
Date: Tue May 3 10:18:14 2016 +0200
pkg/kamailio/deb: use libradcli-dev for radius
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=822338
kamailio-radius-modules depends on libfreeradius-client
libfreeradius-client has been deprecated in favor of radcli[1]
(cherry picked from commit e0cb17c329c0f6fa03e55cf041d1ba2a97b6e64f)
commit 25d1ab175d0abd75bf90db6d8bc9d5a10b03d958
Author: Victor Seva <vseva@sipwise.com>
Date: Tue May 10 08:10:51 2016 +0200
[acc|misc]_radius: update documentation related to radius client libs_
(cherry picked from commit d4710de1f4e6009598acdf3d837991346023f30e)
commit 956d7f29bb99dec6d6dbc0fff2f5df72d38679fc
Author: Victor Seva <vseva@sipwise.com>
Date: Tue May 10 08:10:20 2016 +0200
core: support radius radcli lib
(cherry picked from commit 8aae606809be6160dd48708788051bf7a4a6bc42)
commit a164d19bbe74720ac428a2efd6074397cfb5180e
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sun May 8 09:41:15 2016 +0200
smsops: safety checks for pkg malloc in pv get handler
(cherry picked from commit d4a2ba2ef4323b4306109ab5ecccd1368e8c5f82)
commit a588ced38ff3460469e0d46a31c5786cb57fcaf8
Author: Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
Date: Mon May 9 09:31:02 2016 +0200
modules/sipcapture updated modparam description
(cherry picked from commit 6e9f1c045ae827ea4f6bec8ab62187ec41788255)
commit a2697207977e43784fe8eba632b7f88f4c641802
Author: Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
Date: Mon May 9 09:21:32 2016 +0200
updated SQL and docs
(cherry picked from commit 76649e4bced09b45d5c470a696168929e1758111)
commit 1fb9685ea83353a1d32edd7f94f3b4dc7b755258
Author: Tsvetomir Dimitrov <tsv.dimitrov@gmail.com>
Date: Sat May 7 09:10:01 2016 +0200
pkg/rpm: added missing modules to the SPEC file for CentOS 6
- cnxcc added as separate package
- GH #597
(cherry picked from commit 35a861a89e946a771623001f36dc3d17117be602)
commit e16a2373eeb7e9add61058bda3ab2d5c3cee437e
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sat May 7 08:58:16 2016 +0200
smsops: safety check for pkg malloc result
- allocated the biggest possible size to simplify the checks
(cherry picked from commit fd01e587ed115a21284d27d7f402d51dc6f8743a)
commit 31b69ed11536e1dd7ce4baef25d2da91697f1e74
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Fri May 6 14:03:03 2016 +0200
kazoo: added some docs for pua_mode param based on lists discussions
(cherry picked from commit df30b8c7c6021d84f560a6fb7d82a11cd0e1b3d5)
commit fdeba44e840616e08a2309eb3cf1517a34ea29fa
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu May 5 10:10:59 2016 +0200
core: print tos value if socket option for it cannot be set
- to help with GH #598
(cherry picked from commit 0118338d82e2471572990a1ea09593265161e4a4)
commit c5c4610fa293ce8afc15bd6cc04897e34fde797f
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu May 5 10:02:34 2016 +0200
corex: add section ids to docs
(cherry picked from commit cb41e0146a73d9c91b0c590d65094e300ef67933)
commit 316925662a3be833693eba6a2895b41661b4d0db
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu May 5 07:47:36 2016 +0200
cdp: use the function to check if it is shutdown phase
- global variable is not accessible directly, breaking the build - issue
introduced with previous commit
(cherry picked from commit e70283a0b6010e4a4c567a50b9008e0d7c1e27d5)
commit b696390ac29225dd29bdeb1ec8fe01690e1c2608
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed May 4 20:01:37 2016 +0200
cdp: don't lock anymore for session during shutdown callbacks
- if sigterm killed a worker in a locked zone, results in a deadlock at
shutdown. The cleanup is done by a sigle process, no other processes
run, therefore no more race
(cherry picked from commit f3f87ca550d44364e3c6cc1653970258fdffaa2c)
commit f739c6d0a861fce1808a93e4660546c746dc7672
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 3 10:18:11 2016 +0200
sdpops: safety check if sdp pointer is null inside sdp_get()
(cherry picked from commit cd67fbb8ecb83944f458ec8a127adc14d5b38aeb)
commit 2189d14f20cf52c4802baffc258ecd5b9127c0c0
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 3 08:48:02 2016 +0200
sdpops: removed svn $Id$ lines, coherent indentation and whitespacing
- added license header text
(cherry picked from commit c4299225989d9ccf47c18e50b0014025270c65c7)
commit 6f60780e3fa3d8314e77b9960c04a127ede86b1f
Author: Konstantin S. Vishnivetsky <voip-projects@vishnivetsky.ru>
Date: Mon May 2 16:03:50 2016 +0200
pkg/rpm: added folders with rpm specs for oracle el6 and el7
(cherry picked from commit e72c7e068dd510a56033ce422343675aa0fdafe7)
commit c29e524283b50b74f61e704f0e32b86c7941da6b
Author: Jonas Böttner <boettner@sipgate.de>
Date: Mon May 2 14:20:25 2016 +0200
enum: print out malformed uri in enum_query()
- previous error message did not show up the username part of r-uri.
therefor debugging was difficult.
(cherry picked from commit fd3c30f981d97622fb99f2122ce0bc950774edfb)
commit aa39e12bf63a325effa52eae924a946005baee3c
Author: Jonas Böttner <boettner@sipgate.de>
Date: Mon May 2 14:19:30 2016 +0200
enum: single digit is valid in function enum_query
- is_e164() returns true for a single digit (previously two digits)
(cherry picked from commit 86ecdb2ec109af536efa70c2b0e4b93c4072e8b5)
commit 1851ba4c67c8bfa48ae5f65ccecee076960870f8
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 29 13:55:00 2016 +0200
msilo Minor edits to the README
- Move the database field definitions close to the table definition
- Fix typos, rewrite some parts
(cherry picked from commit ceccf4b9d178e895ae5972f2cddf28e3ef108910)
commit e1b8cc38ba493f6de6a3c70519fb327841efad94
Author: Konstantin S. Vishnivetsky <voip-projects@vishnivetsky.ru>
Date: Thu Apr 28 22:55:12 2016 +0200
pkg: added rpm spec file for Oracle Enterprise Linux 7
- includes adding shadow-utils dependency added to make %pre scriplet
work properly
- baed on PR #588
(cherry picked from commit b7ec49886264b52b15d22b80c1c74ac40a6fb314)
commit ea20338f8786fac2bb290a610f938fec8e7ece54
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue May 3 16:59:06 2016 +0200
xmlrpc: user libxml function to get content of node if type not provided for param
- it is considered to be string according to specs
- old implementation was using the pointer inside the xmlNode struct,
which may not be available later to free again by xmlrpc module
garbage collector
- reported by Juha Heinanen
(cherry picked from commit 6b23c27d8406780083a6b7bb774efa2a53aea540)
commit 72ddb3a70dfc88404eacf0a878f36cc56de2e74e
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon May 2 11:46:30 2016 +0200
lib/srdb1: adjust the length of str time representation for no-quotes
- used only by usrloc fix done in previous commit
(cherry picked from commit f54c723d9d8b8dcd0ad09c3787f3bb2e823d82b8)
commit ffbc7449e315847a43e36ceab2cdc3fe05396115
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon May 2 10:26:35 2016 +0200
usrloc: don't quote string representation of time for fetching contacts query
- the db api adds quites around string values
- it results in double quotation, rising db query error
- reported by Giovanni Mele
(cherry picked from commit aeb85ae3d9097bfd6aaad92a1d5b0c682bf5162c)
commit ea7d88c8a857a53f071e85eb6e467b6ca1a52c73
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon May 2 10:25:21 2016 +0200
lib/srdb1: added helper function to convert time to unquoted string
(cherry picked from commit b3da13a1025f4380c4929fd53b619ca7fdd09a9d)
commit 964c05c334b4bba0c2eeac20d9b8cc188927d0f4
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sat Apr 30 09:57:54 2016 +0200
async: fixed list format for dependencies in docs
(cherry picked from commit 4463258d5bb8cb1460f51791d2c3a367ec68e5fb)
commit d82249bb42513e9c06828cae350e01b89a16b77e
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon May 2 08:51:44 2016 +0200
core: pv - coherent indentation and whitespacing
(cherry picked from commit 4ffe8b0f917ec49b3f68afa99d65e384fb011283)
commit f1fc28d0e42980dfc027b6631b1b807deb7f1a98
Author: sergey-vb <sergey.v.basov@gmail.com>
Date: Thu Apr 28 22:32:14 2016 +0200
core: fix leak in case of error to get boundary inside check_boundaries()
- impacted setting multi-part body function
(cherry picked from commit 2b427a33937c6a86ab231de39d5a4574309dbfc6)
commit 3550a23ac6a5845839b114b22077978da95740f2
Author: sergey-vb <sergey.v.basov@gmail.com>
Date: Thu Apr 28 22:31:05 2016 +0200
textops: fix memory leak in when converting body to multipart with set_body_multipart()
(cherry picked from commit 61435f40f0f4ca25521f7f1b8515e47954a69b2d)
commit 3fd830cfe3bea3f5dde50a26f5ae40b835f7aad0
Author: Mikko Lehto <mslehto@iki.fi>
Date: Thu Apr 28 15:02:29 2016 +0300
lib/binrpc modules/ctl utils/kamcmd : set UNIX_PATH_MAX to lowest common value
sockaddr_un.sun_path[] seem to be either 104 or 108 in following Unices:
104 - NetBSD, OpenBSD, FreeBSD, DragonFly BSD, MINIX, XNU(Apple OS X)
108 - illumos, Solaris, Linux
(cherry picked from commit bc783befbda947a7d789eebd70c64ec736892df5)
commit 24c6d38f93bc033cd79b90d4a4a24c99597f777c
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sun Apr 24 20:13:44 2016 +0200
registrar: coherent indentation and whitespacing
(cherry picked from commit 90350e2a71c86e71f81590c80ad714cec6c7ea80)
commit d59d68c367f17e54606e5edac22a1b653b1e91ad
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Sun Apr 24 18:59:38 2016 +0200
siputils: coherent indentation and whitespacing
(cherry picked from commit 5a31031e62f8872eafc79b41e9594f2f1289f8c3)
commit e082fdc7e401d7f719eb6e12d6b57e2e2fd69215
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Thu Apr 21 13:25:33 2016 +0200
auth: coherent indentation and white spacing
(cherry picked from commit c4b6428ce71e6d1b18ba2ea6b99c369864b56710)
commit 2e179048a0ffb26719644f293cfd063b0fd6aad6
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue Apr 19 10:41:02 2016 +0200
htable: refreshed the readme file
(cherry picked from commit 6adb2fac4a59a35fb1238b4eca5fd8e93c3659c9)
commit f583f0751a7e78bc8ba5ed19ff7fbfea68ce4f6e
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue Apr 19 10:40:20 2016 +0200
htable: coherent indentation and whitespacing
(cherry picked from commit 79ad0e2d8a926e867b1f9e69a065e9b1727671ea)
commit 56f5009939e058ac4a9bc356f85b32ca35dc20bd
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue Apr 19 10:39:55 2016 +0200
htable: updated the list of exported variables
(cherry picked from commit 866270a7cc45205deab5b067be68e5c6a66704e8)
commit 2181edd60a2597a75eef7e2529faf0ed7948c1c7
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 18 12:52:25 2016 +0200
app_python: fix of buf memory allocation size for chars
(cherry picked from commit 5042f309739460ad87dc9a064c43e602602da703)
commit 0110a8b55ba9d48aa22123802d2a562fa2e89195
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 18 12:35:36 2016 +0200
app_python: coherent indetation and whitespacing
(cherry picked from commit 8d7c12ab295fdb41390dd56744cc0b012851788b)
commit d8a893d45d891bc3f8d00e3e76c9cd92195e164c
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Tue Apr 12 13:48:22 2016 +0200
core: receive.c coherent indentation
(cherry picked from commit 7de8a92fd805b73495cc929cf9ca981ecd509c9a)
commit 3616af6b5f2aae383c93507563a33913e3f723e9
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 11 12:57:31 2016 +0200
Makefile.rules: added target tags as alias for target TAGS
(cherry picked from commit b024f5aea72f172b39dd4d8947934be52f07dbe4)
commit 74052b4a0f50b19d42a6fbcae3df38136046f993
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 4 08:53:12 2016 +0200
core: declare function parameter type to get rid of compile warning
(cherry picked from commit ad2f899c1ad75c2b636cb17b6c1c49cb38daab27)
commit 66e1479260a3a657c86e0a9d0ae3fd5c71954f95
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Tue Apr 26 15:49:00 2016 +0200
erlang: fix where is registered pseudo process
- check is event route exist for queried registered process
- check argument type and function arity
- ensure error message proper formatted
(cherry picked from commit 0f52906f28fdf38e56fd37e6ed34155b2deee505)
commit d29ff6a5f31f76ab9fb4e423c88b8c1cc9d4627d
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Tue Apr 26 14:04:41 2016 +0200
erlang: extend error message function with variable number of arguments
- wrap around vsnprintf
(cherry picked from commit 3d002d8f42eb24e978bc86cd3b4565872e65eb1e)
commit dc58d67e400334759185b0eb672160482e067c74
Author: Victor Seva <linuxmaniac@torreviejawireless.org>
Date: Tue Apr 26 10:57:34 2016 +0200
travis-ci: IRC notifications to #kamailio-dev channel
(cherry picked from commit 0dfd44a0502abbf20269d73a230be983cbb97b8d)
commit 3fdf0463e2290ae891587dbac8cbd6b2d0e722fd
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Tue Apr 26 09:55:43 2016 +0200
erlang: fix function call in event route
- allow call functions for RPC and message send in event route
- detect RPC loop
- function/api call is possible in event route if event route is not
triggered by handling REX call (avoid deadlock)
(cherry picked from commit b0c04dd2eff3f288ac98c0074683db150727227a)
commit 615b252510cee01dc6f24ac7d12f07dcb6b50366
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed Apr 20 12:02:09 2016 +0200
Makefile.defs: detect kfreebsd OS and set its default compile flags
- combine the options of Linux with FreeBSD to use kqueue if available
- reported by Victor Seva, GH #576
(cherry picked from commit 4c6f879563adbbdee7c730549533a0d852e6cbef)
commit 71f329c971d6ad18f7eda16a2b50b25e9efd3236
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed Apr 20 11:59:25 2016 +0200
core: remove ending parenthesis in ifdef condition
warning: ISO C99 requires whitespace after the macro name
sched_yield.h:34:20: warning: extra tokens at end of #ifndef directive
#ifndef sched_yield()
- reported by Victore Seva, GH #576
(cherry picked from commit 34b67125424da7ce86b5cac77e30af0711fafac1)
commit 528842d4dfea3d6785e6cee0cd3fb6411ee3dc7d
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 25 08:56:00 2016 +0200
jsonrpc-c: replaced use of obsolete function json_object_object_get()
(cherry picked from commit be02b3f11c269d3eeeb52e1cd0056d7d77be2e4c)
commit 2700d7b8df738f9e5db82dca87cbab5549f2e0d1
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Mon Apr 25 08:54:45 2016 +0200
json: replaced use of obsolete function json_object_object_get()
- reported by Olle E. Johansson, GH #579
(cherry picked from commit 8b9fd4fa40abfc40ecd537948036aa91b908615d)
commit bf76f94e939c0d96ca25a2d75623e7fcff78c01e
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Wed Apr 20 11:36:40 2016 +0200
erlang: fix parsing function params
- remove double parsing function params
- free memory used in parsing params
(cherry picked from commit 28b320088fcad8b8875f0528873a49cba9c74619)
commit 2c650622cf7cd37dc1c5177ad314681113ac324d
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Wed Apr 20 11:10:39 2016 +0200
erlang: fix memory leak in debug macro
- free temporary used encoding buffer
(cherry picked from commit 2b11990929ae1d097bfb66848136bd247130263b)
commit 8d07ef72e8280b4367e430bf081d54e0a0b5f4c1
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Mon Apr 18 11:30:23 2016 +0200
erlang: fix uninitialized member variable
- avoid conditional jump on uninitialized value
(cherry picked from commit 0e3b19f4b99ea0b9e4eff2decb641e5da2488573)
commit c302b9e920342869721342c42f9014bd079fb456
Author: Olle E. Johansson <oej@edvina.net>
Date: Tue Apr 19 21:24:31 2016 +0200
dialog Update README with explanation of in-dialog request behaviour
(cherry picked from commit 19ef4f6ec8c22848eb4386f5f4996d5091c65688)
commit 19d4d3f5a1a49335377c9befd238b729b957f42b
Author: Olle E. Johansson <oej@edvina.net>
Date: Tue Apr 19 14:11:33 2016 +0200
dialog Document shortest ka_interval
(cherry picked from commit 9710f1c92baee8ec379d64b75531bed5cf7695fb)
commit 22003d5cba54b5c0d0f0af06f62be24190bef231
Author: Olle E. Johansson <oej@edvina.net>
Date: Mon Apr 18 13:43:15 2016 +0200
http_client Clarify DNS resolver use for CURL
(cherry picked from commit e85706b549e691404e3caf401fa4cf86c5ab90de)
commit 3356d6aca4c85e7c086b1d46cf06e56635fd4739
Author: Victor Seva <linuxmaniac@torreviejawireless.org>
Date: Fri Apr 15 09:09:08 2016 +0200
app_perl: Fix "use UNIVERSAL" is a fatal error since perl 5.22
* Author: Julián Moreno Patiño <julian@debian.org>
* Fix #516
* from: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=821039
(cherry picked from commit b77ed54d33f171d170ca89252f0a31a0d23996fa)
commit 3e29e0bcfb14f0e95639eb99b777da84d46becf1
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Wed Apr 13 00:34:41 2016 +0200
erlang: fix compile warning unused but set variable
- get rid of this variable
(cherry picked from commit 32c3435c8122903958834002ba843b93c49495f0)
commit 297d9732504290a1209ae7cf883127fadc1156aa
Author: Seudin Kasumovic <seudin.kasumovic@gmail.com>
Date: Wed Apr 13 00:15:56 2016 +0200
erlang: fix register server process with the local name server epmd
- use correct alive name when number of C nodes greater then 1
- fix error check on register server process
(cherry picked from commit 6f268b5a9d0bd07e689c401cb7221bb0f2c5f8be)
commit 02b17b881d63fe91221f5673dd3418831c943bd0
Author: Camille Oudot <camille.oudot@orange.com>
Date: Mon Apr 11 18:53:05 2016 +0200
dialog: fix $dlg(from_bindaddr) getter
commit 1ec385ccd9054952b86cc976ae1debe70dc8d297
Author: Camille Oudot <camille.oudot@orange.com>
Date: Mon Apr 11 17:02:03 2016 +0200
dialog: fix $dlg(from_bindaddr) name parsing
(cherry picked from commit f95789fd39fcce7b3aa3a0ab8665664afd8bc196)
commit b21b9cd9cb6a08b9bfc9d025b4e6a64a12e50d65
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Fri Apr 8 15:10:55 2016 +0200
Makefile.defs: re-enable mem join define
- lost when introduced the option to select the memory manager by
command line parameter -x
(cherry picked from commit 33c6aafcd46269ce283908f49fbf70b9d73624b1)
commit 49ec5fa5d9bb939b80ef3994b5f0c04e7525ab9f
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed Apr 6 19:22:58 2016 +0200
core: common check for ifa->ifa_addr in add_intefaces
- if no ip address associated with the network interface, it is not
useful anyhow
(cherry picked from commit c395ae00d7970be0a857265e9324a50bcb00f4d0)
commit 6684be6b4c405ab24dd6a5a19267ceef6aa95503
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Wed Apr 6 18:55:57 2016 +0200
core: check if ifa_addr field is set while trying to skip AF_PACKET interfaces
- reported by Juha Heinanen
(cherry picked from commit 1545b8de396e8e5d0ef24c9102beff18b3cf36e5)
commit 87af066010ca0b89a4752fe593c091253b842d6c
Author: Olle E. Johansson <oej@edvina.net>
Date: Sun Apr 3 21:45:37 2016 +0200
evapi Fix URL to library home page in README
commit cf3457fd35909993c3e354e726d243f137dfe227
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:28:50 2016 +0200
Revert "db_flatstore Edit source code headers - change product name to Kamailio etc"
This reverts commit 9ecf2492b1952d71d4ec89ba4df5fde428a86a94.
commit 5d1f2e8ca6c44f35b070157c06811a8834615e47
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:28:39 2016 +0200
Revert "db_flatstore Rename core module file to match module name"
This reverts commit ddb1069e7c03544f80fc728503b7df1005ccf54d.
commit cb8fd2fa94599dd37607c511c7dac2d12188cc57
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:28:27 2016 +0200
Revert "registrar Rename core file to match module name"
This reverts commit 932a08610b6d3d3537414d4dc401cf8a8942282c.
commit eb6254b9e82e650f2471ba4a5f58636580cd66cd
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:28:15 2016 +0200
Revert "db_postgres Rename core files to match module name, rename SER to Kamailio and remove svn ID's"
This reverts commit a4b3dfd711af986f3992ded4bf608eb0f60dea6f.
commit 26aa3b6c27e3598b075d923203af5af31f7c0efc
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:27:59 2016 +0200
Revert "db_text Change core source code file name to match module name"
This reverts commit 44c2ebd7ae7e744880af0397703dd405e8eb5d52.
commit 947b86ca81d8f0205205f3bb8328b8110eb1daa2
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:27:44 2016 +0200
Revert "db_mysql Rename core source code file to match module name"
This reverts commit 29fda7288eba52ca73c893cb534bd14c66749827.
commit 7c62633751f6405ab183f054701280ab32b444ae
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:27:30 2016 +0200
Revert "auth_identity Change product name"
This reverts commit 9aaff8933f4f4ee0da6accbf7773334fb187274b.
commit d1b906d0c2acbec5f9daa22805d0a45211d60486
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:27:19 2016 +0200
Revert "lcr Change name of software, remove SVN ID and history"
This reverts commit 853fadd1cd90460d78e8563d611e444dc786e654.
commit 53a75276dec8d274b0ca843ce1e6773cfca3828f
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:27:05 2016 +0200
Revert "Dispatcher Minor edit to have proper name in source code file"
This reverts commit 651407857d129f464515c5cf80ce687257066395.
commit d6abbc8e86ec43c216ba78197dfcf082507d6ca4
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:26:55 2016 +0200
Revert "mediaproxy Rename SIP-router to Kamailio"
This reverts commit 38a9ae753b4d68d8c229366fd4254839536e5669.
commit 7371ed72e20b7d25aa527d78a1fd50366e61a2ed
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:26:32 2016 +0200
Revert "auth_identity Remove SVN ID's"
This reverts commit 39360d98a6c1f80daa67fd1348fdab63bd8a5822.
commit 22ac262cc88cdb78fba1329333412c7f7447128f
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:26:20 2016 +0200
Revert "auth_radius Remove SVN ID's and history comments"
This reverts commit 706e58ff60003a6dca09ad79efef7f1a423d232e.
commit 52160709baae08cde3902410a9a7b579d40445cd
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:26:10 2016 +0200
Revert "auth_radius Rename module core file"
This reverts commit db4b4b68ff91a8e2f00864b29af010514eadf233.
commit 5534237dd155474932a518366b5f1c63f15bdef7
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:26:00 2016 +0200
Revert "websocket Rename core module name for consistensy"
This reverts commit ac2043d1c0a4c921c0d41e5a1a9ff33530449bb6.
commit 4bb26a40f9a14e9d703d899abe76abee0fd5057d
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 20:25:44 2016 +0200
Revert "permissions remove svn ID's and history from source code"
This reverts commit 1538ba701438bf0bfc610af284d67987b9b47bb6.
commit 9ecf2492b1952d71d4ec89ba4df5fde428a86a94
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:25:42 2016 +0200
db_flatstore Edit source code headers - change product name to Kamailio etc
commit ddb1069e7c03544f80fc728503b7df1005ccf54d
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:22:39 2016 +0200
db_flatstore Rename core module file to match module name
Issue #82
commit 932a08610b6d3d3537414d4dc401cf8a8942282c
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:17:06 2016 +0200
registrar Rename core file to match module name
Issue #82
commit a4b3dfd711af986f3992ded4bf608eb0f60dea6f
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:14:04 2016 +0200
db_postgres Rename core files to match module name, rename SER to Kamailio and remove svn ID's
Issue #82
commit 44c2ebd7ae7e744880af0397703dd405e8eb5d52
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:05:33 2016 +0200
db_text Change core source code file name to match module name
Issue #82
commit 29fda7288eba52ca73c893cb534bd14c66749827
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 18:03:10 2016 +0200
db_mysql Rename core source code file to match module name
Issue #82
commit 9aaff8933f4f4ee0da6accbf7773334fb187274b
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:59:59 2016 +0200
auth_identity Change product name
commit 853fadd1cd90460d78e8563d611e444dc786e654
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:58:38 2016 +0200
lcr Change name of software, remove SVN ID and history
commit 651407857d129f464515c5cf80ce687257066395
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:54:48 2016 +0200
Dispatcher Minor edit to have proper name in source code file
commit 38a9ae753b4d68d8c229366fd4254839536e5669
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:53:04 2016 +0200
mediaproxy Rename SIP-router to Kamailio
commit 39360d98a6c1f80daa67fd1348fdab63bd8a5822
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:51:52 2016 +0200
auth_identity Remove SVN ID's
commit 706e58ff60003a6dca09ad79efef7f1a423d232e
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:47:59 2016 +0200
auth_radius Remove SVN ID's and history comments
commit db4b4b68ff91a8e2f00864b29af010514eadf233
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:46:36 2016 +0200
auth_radius Rename module core file
Issue #82
commit ac2043d1c0a4c921c0d41e5a1a9ff33530449bb6
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:42:31 2016 +0200
websocket Rename core module name for consistensy
Issue #82
commit 1538ba701438bf0bfc610af284d67987b9b47bb6
Author: Olle E. Johansson <oej@edvina.net>
Date: Fri Apr 1 17:36:39 2016 +0200
permissions remove svn ID's and history from source code
commit e6dd2c172be3712e8c468cbe7e55ba94d81a7b62
Author: Daniel-Constantin Mierla <miconda@gmail.com>
Date: Fri Apr 1 11:10:46 2016 +0200
core: test if AF_PACKET is defined at compile time
- mac os x (and perhaps *BSDs) doesn't have it
(cherry picked from commit 8543993e1f702aef80887c0e72b9bf67c62c1617)
commit 4992dfbb9f15cfb8ade99be4e6d3087146cb8e22
Author: schoberw <walter.schober@neotel.at>
Date: Fri Apr 1 10:34:11 2016 +0200
core: skip address family AF_PACKET on -l iface_name
- socket_info.c: getifaddrs() returns AF_PACKET, AF_INET and AF_INET6 addressed of an interface.
AF_PACKET are of no use and breaks startup with an -l eth0:5060 cmd line param
(cherry picked from commit d7fca53e8c5409849ec044098a143e7254129c00)
===================== 2016-03-30 Version 4.4.0 Released =====================
===================== Changes Since Version 4.3.0 ===========================

@ -96,7 +96,7 @@ INSTALL_FLAVOUR=$(FLAVOUR)
# version number
VERSION = 4
PATCHLEVEL = 4
SUBLEVEL = 0
SUBLEVEL = 1
# memory manager switcher
# 0 - f_malloc (fast malloc)
@ -112,7 +112,7 @@ SER_VER = $(shell expr $(VERSION) \* 1000000 + $(PATCHLEVEL) \* 1000 + \
$(SUBLEVEL) )
RELEASE:=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
OS := $(shell uname -s | sed -e s/SunOS/solaris/ -e s/CYGWIN.*/cygwin/ \
| tr "[A-Z]" "[a-z]")
| tr "[A-Z]" "[a-z]" | tr "/" "_")
ifeq ($(OS),solaris)
GETARCH=isainfo -n
@ -391,6 +391,13 @@ ifeq ($(OS), linux)
LOCALBASE ?= /usr/local
endif
ifeq ($(OS), gnu_kfreebsd)
doc_dir = share/doc/$(MAIN_NAME)/
man_dir = share/man/
data_dir = share/$(MAIN_NAME)/
LOCALBASE ?= /usr/local
endif
ifeq ($(OS), freebsd)
doc_dir = share/doc/$(MAIN_NAME)/
man_dir = man/
@ -663,6 +670,7 @@ C_DEFS= $(extra_defs) \
# debugging symbols in all cases (-g). --andrei
# memory managers and related debug mode
C_DEFS+= -DMEM_JOIN_FREE
# enable f_malloc
C_DEFS+= -DF_MALLOC
# enable q_malloc
@ -1743,6 +1751,38 @@ ifeq ($(OS), linux)
endif
endif
ifeq ($(OS), gnu_kfreebsd)
# by default use futexes if available
use_futex= yes
C_DEFS+=-DHAVE_GETHOSTBYNAME2 -DHAVE_UNION_SEMUN -DHAVE_SCHED_YIELD \
-DHAVE_MSG_NOSIGNAL -DHAVE_MSGHDR_MSG_CONTROL -DHAVE_ALLOCA_H \
-DHAVE_TIMEGM -DHAVE_SCHED_SETSCHEDULER -DUSE_RAW_SOCKS
ifneq ($(found_lock_method), yes)
#C_DEFS+= -DUSE_POSIX_SEM
C_DEFS+=-DUSE_PTHREAD_MUTEX
LIBS+= -lpthread
#C_DEFS+= -DUSE_SYSV_SEM # try posix sems
found_lock_method=yes
else
ifneq (,$(findstring -DUSE_POSIX_SEM, $(C_DEFS)))
LIBS+=-lpthread
endif
ifneq (,$(findstring -DUSE_PTHREAD_MUTEX, $(C_DEFS)))
LIBS+=-lpthread
endif
endif
# check for ver >= 4.1
ifeq ($(shell [ $(OSREL_N) -gt 4001 ] && echo has_kqueue), has_kqueue)
ifeq ($(NO_KQUEUE),)
C_DEFS+=-DHAVE_KQUEUE
endif
endif
ifeq ($(NO_SELECT),)
C_DEFS+=-DHAVE_SELECT
endif
endif
ifeq ($(OS), solaris)
C_DEFS+= -DHAVE_GETIPNODEBYNAME -DHAVE_SYS_SOCKIO_H -DHAVE_SCHED_YIELD \
-DHAVE_ALLOCA_H -DUSE_SIGACTION

@ -28,7 +28,13 @@ DEFS+= -DUSE_FREERADIUS
RADIUSCLIENT_LIB=freeradius-client
else
ifeq ($(RADCLI),1)
# - radcli library
DEFS+= -DUSE_RADCLI
RADIUSCLIENT_LIB=radcli
else
# - radiusclient-ng v5 or v4 library
ifneq ($(radiusclient_ng), 4)
@ -41,6 +47,7 @@ else
DEFS+=-DRADIUSCLIENT_NG_4
RADIUSCLIENT_LIB=radiusclient
endif
endif
endif

@ -270,11 +270,13 @@ clean_doxygen:
.PHONY: TAGS
TAGS:
.PHONY: tags
TAGS tags:
$(MKTAGS) --exclude="obsolete/*" -R .
.PHONY: TAGS-ALL
TAGS-ALL:
.PHONY: tags-all
TAGS-ALL tags-all:
$(MKTAGS) -R .

@ -2,6 +2,6 @@
* DO NOT EDIT IT
*/
#define REPO_VER "d4f23c"
#define REPO_HASH "d4f23c"
#define REPO_VER "90be8b"
#define REPO_HASH "90be8b"
#define REPO_STATE ""

@ -53,7 +53,7 @@
#define binrpc_free internal_free
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#define UNIX_PATH_MAX 104
#endif
#ifndef INT2STR_MAX_LEN

@ -32,9 +32,14 @@
#define _RADIUS_CORE_H
#ifndef USE_FREERADIUS
#include <radiusclient-ng.h>
#define DEFAULT_RADIUSCLIENT_CONF \
"/usr/local/etc/radiusclient-ng/radiusclient.conf"
#ifdef USE_RADCLI
#include <radcli/radcli.h>
#define DEFAULT_RADIUSCLIENT_CONF ""
#else
#include <radiusclient-ng.h>
#define DEFAULT_RADIUSCLIENT_CONF \
"/usr/local/etc/radiusclient-ng/radiusclient.conf"
#endif
#else
#include <freeradius-client.h>
#define DEFAULT_RADIUSCLIENT_CONF ""

@ -14,8 +14,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@ -41,8 +41,8 @@
#ifndef __OS_solaris
#define _XOPEN_SOURCE 600 /* glibc2 on linux, bsd */
#define _BSD_SOURCE 1 /* needed on linux to "fix" the effect
of the above define on
features.h/unistd.h syscall() */
* of the above define on
* features.h/unistd.h syscall() */
#else
#define _XOPEN_SOURCE_EXTENDED 1 /* solaris */
#endif
@ -74,13 +74,13 @@ inline int db_str2int(const char* _s, int* _v)
char* p = NULL;
if (!_s || !_v) {
LM_ERR("Invalid parameter value\n");
return -1;
LM_ERR("Invalid parameter value\n");
return -1;
}
tmp = strtoul(_s, &p, 10);
if ((tmp == ULONG_MAX && errno == ERANGE) ||
(tmp < INT_MIN) || (tmp > UINT_MAX)) {
if ((tmp == ULONG_MAX && errno == ERANGE) ||
(tmp < INT_MIN) || (tmp > UINT_MAX)) {
LM_ERR("Value out of range\n");
return -1;
}
@ -100,8 +100,8 @@ inline int db_str2longlong(const char* _s, long long * _v)
char* p = NULL;
if (!_s || !_v) {
LM_ERR("Invalid parameter value\n");
return -1;
LM_ERR("Invalid parameter value\n");
return -1;
}
tmp = strtoll(_s, &p, 10);
@ -204,7 +204,7 @@ inline int db_double2str(double _v, char* _s, int* _l)
}
/*
/*
* Convert a string to time_t
*/
inline int db_str2time(const char* _s, time_t* _v)
@ -217,7 +217,7 @@ inline int db_str2time(const char* _s, time_t* _v)
}
/* Convert database time representation to time_t structure
It is necessary to zero tm structure first */
* It is necessary to zero tm structure first */
memset(&time, '\0', sizeof(struct tm));
if (strptime(_s, "%Y-%m-%d %H:%M:%S", &time) == NULL) {
LM_ERR("Error during time conversion\n");
@ -228,7 +228,7 @@ inline int db_str2time(const char* _s, time_t* _v)
* so let mktime to guess it. This eliminates the bug when
* contacts reloaded from the database have different time
* of expiration by one hour when daylight saving is used
*/
*/
time.tm_isdst = -1;
*_v = mktime(&time);
@ -236,7 +236,10 @@ inline int db_str2time(const char* _s, time_t* _v)
}
inline int db_time2str(time_t _v, char* _s, int* _l)
/**
*
*/
inline int db_time2str_ex(time_t _v, char* _s, int* _l, int _qmode)
{
struct tm* t;
int l;
@ -246,7 +249,7 @@ inline int db_time2str(time_t _v, char* _s, int* _l)
return -1;
}
*_s++ = '\'';
if(_qmode) *_s++ = '\'';
/* Convert time_t structure to format accepted by the database */
t = localtime(&_v);
@ -261,11 +264,20 @@ inline int db_time2str(time_t _v, char* _s, int* _l)
}
*_l = l;
*(_s + l) = '\'';
*_l = l + 2;
if(_qmode) {
*(_s + l) = '\'';
*_l = l + 2;
}
return 0;
}
/**
*
*/
inline int db_time2str(time_t _v, char* _s, int* _l)
{
return db_time2str_ex(_v, _s, _l, 1);
}
/*
* Print list of columns separated by comma
@ -382,7 +394,7 @@ int db_print_where(const db1_con_t* _c, char* _b, const int _l, const db_key_t*
}
return len;
error:
error:
LM_ERR("Error in snprintf\n");
return -1;
}
@ -422,7 +434,7 @@ int db_print_set(const db1_con_t* _c, char* _b, const int _l, const db_key_t* _k
}
return len;
error:
error:
LM_ERR("Error in snprintf\n");
return -1;
}
@ -484,7 +496,7 @@ int db_val2pv_spec(struct sip_msg* msg, db_val_t *dbval, pv_spec_t *pvs)
break;
default:
LM_NOTICE("unknown field type: %d, setting value to null\n",
dbval->type);
dbval->type);
pv.flags = PV_VAL_NULL;
}
}

@ -14,8 +14,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@ -113,6 +113,7 @@ int db_double2str(double _v, char* _s, int* _l);
*/
int db_time2str(time_t _v, char* _s, int* _l);
int db_time2str_ex(time_t _v, char* _s, int* _l, int _qmode);
/**
* Converts a char into a time_t value.
@ -189,7 +190,7 @@ int db_print_set(const db1_con_t* _c, char* _b, const int _l,
/**
* Convert db_val_t to pv_spec_t
*
*
* \param msg sip msg structure
* \param dbval database value
* \param pvs pv_spec where to put the database value

@ -509,10 +509,10 @@ char *sr_memmng_pkg = NULL;
char *sr_memmng_shm = NULL;
/* call it before exiting; if show_status==1, mem status is displayed */
void cleanup(show_status)
void cleanup(int show_status)
{
int memlog;
/*clean-up*/
#ifndef SHM_SAFE_MALLOC
if (_shm_lock)

@ -16,7 +16,7 @@ Daniel-Constantin Mierla
asipto.com
<miconda@gmail.com>
Copyright © 2002, 2003 FhG FOKUS
Copyright © 2002, 2003 FhG FOKUS
__________________________________________________________________
Table of Contents
@ -36,6 +36,7 @@ Daniel-Constantin Mierla
3.3. radius_missed_flag (integer)
3.4. service_type (integer)
3.5. radius_extra (string)
3.6. rad_time_mode(integer)
4. Functions
@ -48,7 +49,8 @@ Daniel-Constantin Mierla
1.3. radius_missed_flag example
1.4. service_type example
1.5. radius_extra example
1.6. acc_rad_request usage
1.6. rad_time_mode example
1.7. acc_rad_request usage
Chapter 1. Admin Guide
@ -67,6 +69,7 @@ Chapter 1. Admin Guide
3.3. radius_missed_flag (integer)
3.4. service_type (integer)
3.5. radius_extra (string)
3.6. rad_time_mode(integer)
4. Functions
@ -97,8 +100,13 @@ Chapter 1. Admin Guide
The following libraries or applications must be installed before
running Kamailio with this module loaded:
* radiusclient-ng 0.5.0 or higher. See
http://developer.berlios.de/projects/radiusclient-ng/.
* radiusclient-ng 0.5.0 or higher, freeradius-client
https://github.com/FreeRADIUS/freeradius-client/ or radcli
http://radcli.github.io/radcli/.
* freeradius-client library can be used after setting FREERADIUS
variable in source code with 'export FREERADIUS=1' before compile.
* radcli library can be used after setting RADCLI variable in source
code with 'export RADCLI=1' before compile.
3. Parameters
@ -107,6 +115,7 @@ Chapter 1. Admin Guide
3.3. radius_missed_flag (integer)
3.4. service_type (integer)
3.5. radius_extra (string)
3.6. rad_time_mode(integer)
3.1. radius_config (string)
@ -119,7 +128,7 @@ Chapter 1. Admin Guide
If the parameter is set to empty string, the RADIUS accounting support
will be disabled (even if compiled).
Default value is “NULL”.
Default value is "NULL".
Example 1.1. radius_config example
...
@ -172,22 +181,41 @@ modparam("acc_radius", "service_type", 16)
modparam("acc_radius", "radius_extra", "via=$hdr(Via[*]); email=$avp(s:email)")
...
3.6. rad_time_mode(integer)
Radius Event-Timestamp for accounting.
Values can be:
* 0 - (default), format is only unix timestamp for Event-Timestamp
(For example: 1445590624)
* 1 - format is unix timestamp with microseconds in Addition, it
needs to change Event-Timestamp attribute type in dictionary to
string both radius server and client (For example:
1445590624.377372)
Default value is 0 (Unix timestamp).
Example 1.6. rad_time_mode example
...
modparam("acc_radius", "rad_time_mode", 1)
...
4. Functions
4.1. acc_rad_request(comment)
4.1. acc_rad_request(comment)
4.1. acc_rad_request(comment)
Like acc_log_request of acc module, acc_rad_request reports on a SIP
request event. It reports to radius server as configured in
“radius_config”.
"radius_config".
Meaning of the parameters is as follows:
* comment - Comment to be appended.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
Example 1.6. acc_rad_request usage
Example 1.7. acc_rad_request usage
...
acc_rad_request("Some comment");
...

@ -50,11 +50,13 @@
</para>
<itemizedlist>
<listitem>
<para><emphasis>radiusclient-ng</emphasis> 0.5.0 or freeradius-client
or higher.
See <ulink
<para><emphasis>radiusclient-ng</emphasis> 0.5.0 or higher,
<emphasis>freeradius-client</emphasis> <ulink
url='https://github.com/FreeRADIUS/freeradius-client/'>
https://github.com/FreeRADIUS/freeradius-client/</ulink>.
https://github.com/FreeRADIUS/freeradius-client/</ulink> or
<emphasis>radcli</emphasis> <ulink
url='http://radcli.github.io/radcli/'>
http://radcli.github.io/radcli/</ulink>.
</para>
</listitem>
<listitem>
@ -64,6 +66,13 @@
<emphasis>'export FREERADIUS=1'</emphasis> before compile.
</para>
</listitem>
<listitem>
<para>
<emphasis>radcli</emphasis> library can be used after
setting RADCLI variable in source code with
<emphasis>'export RADCLI=1'</emphasis> before compile.
</para>
</listitem>
</itemizedlist>
</section>
</section>

@ -52,7 +52,6 @@ package Kamailio::LDAPUtils::LDAPConnection;
use Kamailio::LDAPUtils::LDAPConf;
use Net::LDAP;
use Authen::SASL;
use UNIVERSAL qw( isa );
my $ldap_singleton = undef;
@ -185,7 +184,7 @@ sub search {
my $ldap = undef;
if( isa($conf ,"Kamailio::LDAPUtils::LDAPConnection") ) {
if( $conf->isa("Kamailio::LDAPUtils::LDAPConnection") ) {
$ldap = $conf;
} else {
if( ! $ldap_singleton ) {

@ -45,7 +45,6 @@ use Kamailio::VDB::Result;
use Kamailio::VDB::Value;
use Kamailio::VDB::VTab;
use UNIVERSAL qw ( can );
our @ISA = qw ( Kamailio::Utils::Debug );
@ -87,12 +86,12 @@ sub use_table {
Kamailio::log(L_DBG, "perlvdb:VDB: Setting VTab: v is $v (pkg is $pkg, func/method is $3)\n");
if (can($pkg, $3)) {
if ($pkg->can($3)) {
$self->{vtabs}->{$v} = new Kamailio::VDB::VTab( func => $pkg . "::" . $3);
} elsif (can($v, "init")) {
} elsif ($v->can("init")) {
$v->init();
$self->{vtabs}->{$v} = new Kamailio::VDB::VTab( obj => $v );
} elsif (can($v, "new")) {
} elsif ($v->can("new")) {
my $obj = $v->new();
$self->{vtabs}->{$v} = new Kamailio::VDB::VTab( obj => $obj );
} else {

@ -42,27 +42,27 @@
#include "mod_Core.h"
PyMethodDef CoreMethods[] = {
{NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
};
void init_mod_Core(void)
{
core_module = Py_InitModule("Router.Core", CoreMethods);
PyDict_SetItemString(main_module_dict, "Core", core_module);
core_module = Py_InitModule("Router.Core", CoreMethods);
PyDict_SetItemString(main_module_dict, "Core", core_module);
Py_INCREF(core_module);
Py_INCREF(core_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Core' has been initialized\n");
LM_ERR("Module 'Router.Core' has been initialized\n");
#endif
}
void destroy_mod_Core(void)
{
Py_XDECREF(core_module);
Py_XDECREF(core_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Core' has been destroyed\n");
LM_ERR("Module 'Router.Core' has been destroyed\n");
#endif
}

@ -46,16 +46,16 @@
*/
static PyObject *logger_LM_GEN1(PyObject *self, PyObject *args)
{
int log_level;
char *msg;
int log_level;
char *msg;
if (!PyArg_ParseTuple(args, "is:LM_GEN1", &log_level, &msg))
return NULL;
if (!PyArg_ParseTuple(args, "is:LM_GEN1", &log_level, &msg))
return NULL;
LM_GEN1(log_level, "%s", msg);
LM_GEN1(log_level, "%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -63,17 +63,17 @@ static PyObject *logger_LM_GEN1(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_GEN2(PyObject *self, PyObject *args)
{
int log_facility;
int log_level;
char *msg;
int log_facility;
int log_level;
char *msg;
if(!PyArg_ParseTuple(args, "iis:LM_GEN2", &log_facility, &log_level, &msg))
return NULL;
if(!PyArg_ParseTuple(args, "iis:LM_GEN2", &log_facility, &log_level, &msg))
return NULL;
LM_GEN2(log_facility, log_level, "%s", msg);
LM_GEN2(log_facility, log_level, "%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -81,15 +81,15 @@ static PyObject *logger_LM_GEN2(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_ALERT(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_ALERT", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_ALERT", &msg))
return NULL;
LM_ALERT("%s", msg);
LM_ALERT("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
@ -98,15 +98,15 @@ static PyObject *logger_LM_ALERT(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_CRIT(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_CRIT", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_CRIT", &msg))
return NULL;
LM_CRIT("%s", msg);
LM_CRIT("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -114,15 +114,15 @@ static PyObject *logger_LM_CRIT(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_WARN(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_WARN", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_WARN", &msg))
return NULL;
LM_WARN("%s", msg);
LM_WARN("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -130,15 +130,15 @@ static PyObject *logger_LM_WARN(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_NOTICE(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_NOTICE", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_NOTICE", &msg))
return NULL;
LM_NOTICE("%s", msg);
LM_NOTICE("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -146,15 +146,15 @@ static PyObject *logger_LM_NOTICE(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_ERR(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_ERR", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_ERR", &msg))
return NULL;
LM_ERR("%s", msg);
LM_ERR("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -162,15 +162,15 @@ static PyObject *logger_LM_ERR(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_INFO(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_INFO", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_INFO", &msg))
return NULL;
LM_INFO("%s", msg);
LM_INFO("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
/*
@ -178,69 +178,69 @@ static PyObject *logger_LM_INFO(PyObject *self, PyObject *args)
*/
static PyObject *logger_LM_DBG(PyObject *self, PyObject *args)
{
char *msg;
char *msg;
if(!PyArg_ParseTuple(args, "s:LM_DBG", &msg))
return NULL;
if(!PyArg_ParseTuple(args, "s:LM_DBG", &msg))
return NULL;
LM_DBG("%s", msg);
LM_DBG("%s", msg);
Py_INCREF(Py_None);
return Py_None;
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef LoggerMethods[] = {
{"LM_GEN1", (PyCFunction)logger_LM_GEN1, METH_VARARGS, "Print GEN1 message."},
{"LM_GEN2", (PyCFunction)logger_LM_GEN2, METH_VARARGS, "Print GEN2 message."},
{"LM_ALERT", (PyCFunction)logger_LM_ALERT, METH_VARARGS, "Print alert message."},
{"LM_CRIT", (PyCFunction)logger_LM_CRIT, METH_VARARGS, "Print critical message."},
{"LM_ERR", (PyCFunction)logger_LM_ERR, METH_VARARGS, "Print error message."},
{"LM_WARN", (PyCFunction)logger_LM_WARN, METH_VARARGS, "Print warning message."},
{"LM_NOTICE", (PyCFunction)logger_LM_NOTICE, METH_VARARGS, "Print notice message."},
{"LM_INFO", (PyCFunction)logger_LM_INFO, METH_VARARGS, "Print info message."},
{"LM_DBG", (PyCFunction)logger_LM_DBG, METH_VARARGS, "Print debug message."},
{NULL, NULL, 0, NULL}
{"LM_GEN1", (PyCFunction)logger_LM_GEN1, METH_VARARGS, "Print GEN1 message."},
{"LM_GEN2", (PyCFunction)logger_LM_GEN2, METH_VARARGS, "Print GEN2 message."},
{"LM_ALERT", (PyCFunction)logger_LM_ALERT, METH_VARARGS, "Print alert message."},
{"LM_CRIT", (PyCFunction)logger_LM_CRIT, METH_VARARGS, "Print critical message."},
{"LM_ERR", (PyCFunction)logger_LM_ERR, METH_VARARGS, "Print error message."},
{"LM_WARN", (PyCFunction)logger_LM_WARN, METH_VARARGS, "Print warning message."},
{"LM_NOTICE", (PyCFunction)logger_LM_NOTICE, METH_VARARGS, "Print notice message."},
{"LM_INFO", (PyCFunction)logger_LM_INFO, METH_VARARGS, "Print info message."},
{"LM_DBG", (PyCFunction)logger_LM_DBG, METH_VARARGS, "Print debug message."},
{NULL, NULL, 0, NULL}
};
void init_mod_Logger(void)
{
logger_module = Py_InitModule("Router.Logger", LoggerMethods);
PyDict_SetItemString(main_module_dict, "Logger", logger_module);
/*
* Log levels
* Reference: dprint.h
*/
PyModule_AddObject(logger_module, "L_ALERT", PyInt_FromLong((long)L_ALERT));
PyModule_AddObject(logger_module, "L_BUG", PyInt_FromLong((long)L_BUG));
PyModule_AddObject(logger_module, "L_CRIT2", PyInt_FromLong((long)L_CRIT2)); /* like L_CRIT, but adds prefix */
PyModule_AddObject(logger_module, "L_CRIT", PyInt_FromLong((long)L_CRIT)); /* no prefix added */
PyModule_AddObject(logger_module, "L_ERR", PyInt_FromLong((long)L_ERR));
PyModule_AddObject(logger_module, "L_WARN", PyInt_FromLong((long)L_WARN));
PyModule_AddObject(logger_module, "L_NOTICE", PyInt_FromLong((long)L_NOTICE));
PyModule_AddObject(logger_module, "L_INFO", PyInt_FromLong((long)L_INFO));
PyModule_AddObject(logger_module, "L_DBG", PyInt_FromLong((long)L_DBG));
/*
* Facility
* Reference: dprint.h
*/
PyModule_AddObject(logger_module, "DEFAULT_FACILITY", PyInt_FromLong((long)DEFAULT_FACILITY));
Py_INCREF(logger_module);
logger_module = Py_InitModule("Router.Logger", LoggerMethods);
PyDict_SetItemString(main_module_dict, "Logger", logger_module);
/*
* Log levels
* Reference: dprint.h
*/
PyModule_AddObject(logger_module, "L_ALERT", PyInt_FromLong((long)L_ALERT));
PyModule_AddObject(logger_module, "L_BUG", PyInt_FromLong((long)L_BUG));
PyModule_AddObject(logger_module, "L_CRIT2", PyInt_FromLong((long)L_CRIT2)); /* like L_CRIT, but adds prefix */
PyModule_AddObject(logger_module, "L_CRIT", PyInt_FromLong((long)L_CRIT)); /* no prefix added */
PyModule_AddObject(logger_module, "L_ERR", PyInt_FromLong((long)L_ERR));
PyModule_AddObject(logger_module, "L_WARN", PyInt_FromLong((long)L_WARN));
PyModule_AddObject(logger_module, "L_NOTICE", PyInt_FromLong((long)L_NOTICE));
PyModule_AddObject(logger_module, "L_INFO", PyInt_FromLong((long)L_INFO));
PyModule_AddObject(logger_module, "L_DBG", PyInt_FromLong((long)L_DBG));
/*
* Facility
* Reference: dprint.h
*/
PyModule_AddObject(logger_module, "DEFAULT_FACILITY", PyInt_FromLong((long)DEFAULT_FACILITY));
Py_INCREF(logger_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Logger' has been initialized\n");
LM_ERR("Module 'Router.Logger' has been initialized\n");
#endif
}
void destroy_mod_Logger(void)
{
Py_XDECREF(logger_module);
Py_XDECREF(logger_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Logger' has been destroyed\n");
LM_ERR("Module 'Router.Logger' has been destroyed\n");
#endif
}

@ -42,41 +42,41 @@
#include "mod_Ranks.h"
PyMethodDef RanksMethods[] = {
{NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
};
void init_mod_Ranks(void)
{
ranks_module = Py_InitModule("Router.Ranks", RanksMethods);
PyDict_SetItemString(main_module_dict, "Ranks", ranks_module);
ranks_module = Py_InitModule("Router.Ranks", RanksMethods);
PyDict_SetItemString(main_module_dict, "Ranks", ranks_module);
PyModule_AddObject(ranks_module, "PROC_MAIN", PyInt_FromLong((long)PROC_MAIN));
PyModule_AddObject(ranks_module, "PROC_TIMER", PyInt_FromLong((long)PROC_TIMER));
PyModule_AddObject(ranks_module, "PROC_RPC", PyInt_FromLong((long)PROC_RPC));
PyModule_AddObject(ranks_module, "PROC_FIFO", PyInt_FromLong((long)PROC_FIFO));
PyModule_AddObject(ranks_module, "PROC_TCP_MAIN", PyInt_FromLong((long)PROC_TCP_MAIN));
PyModule_AddObject(ranks_module, "PROC_UNIXSOCK", PyInt_FromLong((long)PROC_UNIXSOCK));
PyModule_AddObject(ranks_module, "PROC_ATTENDANT", PyInt_FromLong((long)PROC_ATTENDANT));
PyModule_AddObject(ranks_module, "PROC_INIT", PyInt_FromLong((long)PROC_INIT));
PyModule_AddObject(ranks_module, "PROC_NOCHLDINIT", PyInt_FromLong((long)PROC_NOCHLDINIT));
PyModule_AddObject(ranks_module, "PROC_SIPINIT", PyInt_FromLong((long)PROC_SIPINIT));
PyModule_AddObject(ranks_module, "PROC_SIPRPC", PyInt_FromLong((long)PROC_SIPRPC));
PyModule_AddObject(ranks_module, "PROC_MIN", PyInt_FromLong((long)PROC_MIN));
PyModule_AddObject(ranks_module, "PROC_MAIN", PyInt_FromLong((long)PROC_MAIN));
PyModule_AddObject(ranks_module, "PROC_TIMER", PyInt_FromLong((long)PROC_TIMER));
PyModule_AddObject(ranks_module, "PROC_RPC", PyInt_FromLong((long)PROC_RPC));
PyModule_AddObject(ranks_module, "PROC_FIFO", PyInt_FromLong((long)PROC_FIFO));
PyModule_AddObject(ranks_module, "PROC_TCP_MAIN", PyInt_FromLong((long)PROC_TCP_MAIN));
PyModule_AddObject(ranks_module, "PROC_UNIXSOCK", PyInt_FromLong((long)PROC_UNIXSOCK));
PyModule_AddObject(ranks_module, "PROC_ATTENDANT", PyInt_FromLong((long)PROC_ATTENDANT));
PyModule_AddObject(ranks_module, "PROC_INIT", PyInt_FromLong((long)PROC_INIT));
PyModule_AddObject(ranks_module, "PROC_NOCHLDINIT", PyInt_FromLong((long)PROC_NOCHLDINIT));
PyModule_AddObject(ranks_module, "PROC_SIPINIT", PyInt_FromLong((long)PROC_SIPINIT));
PyModule_AddObject(ranks_module, "PROC_SIPRPC", PyInt_FromLong((long)PROC_SIPRPC));
PyModule_AddObject(ranks_module, "PROC_MIN", PyInt_FromLong((long)PROC_MIN));
Py_INCREF(ranks_module);
Py_INCREF(ranks_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Ranks' has been initialized\n");
LM_ERR("Module 'Router.Ranks' has been initialized\n");
#endif
}
void destroy_mod_Ranks(void)
{
Py_XDECREF(ranks_module);
Py_XDECREF(ranks_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router.Ranks' has been destroyed\n");
LM_ERR("Module 'Router.Ranks' has been destroyed\n");
#endif
}

@ -41,29 +41,29 @@
PyMethodDef RouterMethods[] = {
{NULL, NULL, 0, NULL}
{NULL, NULL, 0, NULL}
};
void init_mod_Router(void)
{
main_module = Py_InitModule("Router", RouterMethods);
main_module_dict = PyModule_GetDict(main_module);
main_module = Py_InitModule("Router", RouterMethods);
main_module_dict = PyModule_GetDict(main_module);
Py_INCREF(main_module);
Py_INCREF(main_module);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router' has been initialized\n");
LM_ERR("Module 'Router' has been initialized\n");
#endif
}
void destroy_mod_Router(void)
{
Py_XDECREF(main_module);
Py_XDECREF(main_module_dict);
Py_XDECREF(main_module);
Py_XDECREF(main_module_dict);
#ifdef WITH_EXTRA_DEBUG
LM_ERR("Module 'Router' has been destroyed\n");
LM_ERR("Module 'Router' has been destroyed\n");
#endif
}

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
*
* This file is part of Kamailio, a free SIP server.
@ -38,11 +38,11 @@
int ap_init_modules(void)
{
init_mod_Router();
init_mod_Core();
init_mod_Ranks();
init_mod_Logger();
init_mod_Router();
init_mod_Core();
init_mod_Ranks();
init_mod_Logger();
return 0;
return 0;
}

@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
*/
#include <Python.h>
#include <libgen.h>
@ -55,330 +55,330 @@ PyThreadState *myThreadState;
/** module parameters */
static param_export_t params[]={
{"script_name", PARAM_STR, &script_name },
{"mod_init_function", PARAM_STR, &mod_init_fname },
{"child_init_method", PARAM_STR, &child_init_mname },
{0,0,0}
{"script_name", PARAM_STR, &script_name },
{"mod_init_function", PARAM_STR, &mod_init_fname },
{"child_init_method", PARAM_STR, &child_init_mname },
{0,0,0}
};
/*
* Exported functions
*/
static cmd_export_t cmds[] = {
{ "python_exec", (cmd_function)python_exec1, 1, NULL, 0, ANY_ROUTE },
{ "python_exec", (cmd_function)python_exec2, 2, NULL, 0, ANY_ROUTE },
{ 0, 0, 0, 0, 0, 0 }
{ "python_exec", (cmd_function)python_exec1, 1, NULL, 0, ANY_ROUTE },
{ "python_exec", (cmd_function)python_exec2, 2, NULL, 0, ANY_ROUTE },
{ 0, 0, 0, 0, 0, 0 }
};
/** module exports */
struct module_exports exports = {
"app_python", /* module name */
RTLD_NOW | RTLD_GLOBAL, /* dlopen flags */
cmds, /* exported functions */
params, /* exported parameters */
0, /* exported statistics */
0, /* exported MI functions */
0, /* exported pseudo-variables */
0, /* extra processes */
mod_init, /* module initialization function */
(response_function) NULL, /* response handling function */
(destroy_function) mod_destroy, /* destroy function */
child_init /* per-child init function */
"app_python", /* module name */
RTLD_NOW | RTLD_GLOBAL, /* dlopen flags */
cmds, /* exported functions */
params, /* exported parameters */
0, /* exported statistics */
0, /* exported MI functions */
0, /* exported pseudo-variables */
0, /* extra processes */
mod_init, /* module initialization function */
(response_function) NULL, /* response handling function */
(destroy_function) mod_destroy, /* destroy function */
child_init /* per-child init function */
};
static int mod_init(void)
{
char *dname_src, *bname_src;
int i;
PyObject *sys_path, *pDir, *pModule, *pFunc, *pArgs;
PyThreadState *mainThreadState;
dname_src = as_asciiz(&script_name);
bname_src = as_asciiz(&script_name);
if(dname_src==NULL || bname_src==NULL)
{
LM_ERR("no more pkg memory\n");
return -1;
}
dname = strdup(dirname(dname_src));
if (strlen(dname) == 0)
dname = ".";
bname = strdup(basename(bname_src));
i = strlen(bname);
if (bname[i - 1] == 'c' || bname[i - 1] == 'o')
i -= 1;
if (bname[i - 3] == '.' && bname[i - 2] == 'p' && bname[i - 1] == 'y') {
bname[i - 3] = '\0';
} else {
LM_ERR("%s: script_name doesn't look like a python script\n",
script_name.s);
return -1;
}
Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyThreadState_Get();
format_exc_obj = InitTracebackModule();
if (format_exc_obj == NULL || !PyCallable_Check(format_exc_obj))
{
Py_XDECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
sys_path = PySys_GetObject("path");
/* PySys_GetObject doesn't pass reference! No need to DEREF */
if (sys_path == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' object 'sys' has no attribute 'path'");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pDir = PyString_FromString(dname);
if (pDir == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "PyString_FromString() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
PyList_Insert(sys_path, 0, pDir);
Py_DECREF(pDir);
if (ap_init_modules() != 0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_AttributeError, "init_modules() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (python_msgobj_init() != 0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_AttributeError, "python_msgobj_init() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pModule = PyImport_ImportModule(bname);
if (pModule == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_ImportError, "No module named '%s'", bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pkg_free(dname_src);
pkg_free(bname_src);
pFunc = PyObject_GetAttrString(pModule, mod_init_fname.s);
Py_DECREF(pModule);
/* pFunc is a new reference */
if (pFunc == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' object '%s' has no attribute '%s'", bname, mod_init_fname.s);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
if (!PyCallable_Check(pFunc)) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "module object '%s' has is not callable attribute '%s'", bname, mod_init_fname.s);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
pArgs = PyTuple_New(0);
if (pArgs == NULL) {
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
handler_obj = PyObject_CallObject(pFunc, pArgs);
Py_XDECREF(pFunc);
Py_XDECREF(pArgs);
if (handler_obj == Py_None) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "Function '%s' of module '%s' has returned None. Should be a class instance.", mod_init_fname.s, bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (PyErr_Occurred()) {
python_handle_exception("mod_init");
Py_XDECREF(handler_obj);
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (handler_obj == NULL) {
LM_ERR("PyObject_CallObject() returned NULL but no exception!\n");
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "Function '%s' of module '%s' has returned not returned object. Should be a class instance.", mod_init_fname.s, bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
myThreadState = PyThreadState_New(mainThreadState->interp);
PyEval_ReleaseLock();
return 0;
}
char *dname_src, *bname_src;
int i;
PyObject *sys_path, *pDir, *pModule, *pFunc, *pArgs;
PyThreadState *mainThreadState;
dname_src = as_asciiz(&script_name);
bname_src = as_asciiz(&script_name);
if(dname_src==NULL || bname_src==NULL)
{
LM_ERR("no more pkg memory\n");
return -1;
}
dname = strdup(dirname(dname_src));
if (strlen(dname) == 0)
dname = ".";
bname = strdup(basename(bname_src));
i = strlen(bname);
if (bname[i - 1] == 'c' || bname[i - 1] == 'o')
i -= 1;
if (bname[i - 3] == '.' && bname[i - 2] == 'p' && bname[i - 1] == 'y') {
bname[i - 3] = '\0';
} else {
LM_ERR("%s: script_name doesn't look like a python script\n",
script_name.s);
return -1;
}
Py_Initialize();
PyEval_InitThreads();
mainThreadState = PyThreadState_Get();
format_exc_obj = InitTracebackModule();
if (format_exc_obj == NULL || !PyCallable_Check(format_exc_obj))
{
Py_XDECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
sys_path = PySys_GetObject("path");
/* PySys_GetObject doesn't pass reference! No need to DEREF */
if (sys_path == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' object 'sys' has no attribute 'path'");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pDir = PyString_FromString(dname);
if (pDir == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "PyString_FromString() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
PyList_Insert(sys_path, 0, pDir);
Py_DECREF(pDir);
if (ap_init_modules() != 0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_AttributeError, "init_modules() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (python_msgobj_init() != 0) {
if (!PyErr_Occurred())
PyErr_SetString(PyExc_AttributeError, "python_msgobj_init() has failed");
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pModule = PyImport_ImportModule(bname);
if (pModule == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_ImportError, "No module named '%s'", bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
pkg_free(dname_src);
pkg_free(bname_src);
pFunc = PyObject_GetAttrString(pModule, mod_init_fname.s);
Py_DECREF(pModule);
/* pFunc is a new reference */
if (pFunc == NULL) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' object '%s' has no attribute '%s'", bname, mod_init_fname.s);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
if (!PyCallable_Check(pFunc)) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "module object '%s' has is not callable attribute '%s'", bname, mod_init_fname.s);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
pArgs = PyTuple_New(0);
if (pArgs == NULL) {
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pFunc);
PyEval_ReleaseLock();
return -1;
}
handler_obj = PyObject_CallObject(pFunc, pArgs);
static int child_init(int rank)
{
PyObject *pFunc, *pArgs, *pValue, *pResult;
int rval;
char *classname;
PyEval_AcquireLock();
PyThreadState_Swap(myThreadState);
// get instance class name
classname = get_instance_class_name(handler_obj);
if (classname == NULL)
{
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' instance has no class name");
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
PyThreadState_Swap(NULL);
Py_XDECREF(pFunc);
Py_XDECREF(pArgs);
if (handler_obj == Py_None) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "Function '%s' of module '%s' has returned None. Should be a class instance.", mod_init_fname.s, bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (PyErr_Occurred()) {
python_handle_exception("mod_init");
Py_XDECREF(handler_obj);
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
if (handler_obj == NULL) {
LM_ERR("PyObject_CallObject() returned NULL but no exception!\n");
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "Function '%s' of module '%s' has returned not returned object. Should be a class instance.", mod_init_fname.s, bname);
python_handle_exception("mod_init");
Py_DECREF(format_exc_obj);
PyEval_ReleaseLock();
return -1;
}
myThreadState = PyThreadState_New(mainThreadState->interp);
PyEval_ReleaseLock();
return -1;
}
pFunc = PyObject_GetAttrString(handler_obj, child_init_mname.s);
return 0;
}
if (pFunc == NULL) {
python_handle_exception("child_init");
Py_XDECREF(pFunc);
Py_DECREF(format_exc_obj);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (!PyCallable_Check(pFunc)) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "class object '%s' has is not callable attribute '%s'", !classname ? "None" : classname, mod_init_fname.s);
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
pArgs = PyTuple_New(1);
if (pArgs == NULL) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
pValue = PyInt_FromLong((long)rank);
if (pValue == NULL) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pArgs);
Py_DECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
PyTuple_SetItem(pArgs, 0, pValue);
/* pValue has been stolen */
pResult = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pFunc);
Py_DECREF(pArgs);
if (PyErr_Occurred()) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pResult);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (pResult == NULL) {
LM_ERR("PyObject_CallObject() returned NULL but no exception!\n");
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (!PyInt_Check(pResult))
{
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "method '%s' of class '%s' should return 'int' type", child_init_mname.s, !classname ? "None" : classname);
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pResult);
static int child_init(int rank)
{
PyObject *pFunc, *pArgs, *pValue, *pResult;
int rval;
char *classname;
PyEval_AcquireLock();
PyThreadState_Swap(myThreadState);
// get instance class name
classname = get_instance_class_name(handler_obj);
if (classname == NULL)
{
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "'module' instance has no class name");
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
pFunc = PyObject_GetAttrString(handler_obj, child_init_mname.s);
if (pFunc == NULL) {
python_handle_exception("child_init");
Py_XDECREF(pFunc);
Py_DECREF(format_exc_obj);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (!PyCallable_Check(pFunc)) {
if (!PyErr_Occurred())
PyErr_Format(PyExc_AttributeError, "class object '%s' has is not callable attribute '%s'", !classname ? "None" : classname, mod_init_fname.s);
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
pArgs = PyTuple_New(1);
if (pArgs == NULL) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
pValue = PyInt_FromLong((long)rank);
if (pValue == NULL) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_DECREF(pArgs);
Py_DECREF(pFunc);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
PyTuple_SetItem(pArgs, 0, pValue);
/* pValue has been stolen */
pResult = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pFunc);
Py_DECREF(pArgs);
if (PyErr_Occurred()) {
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pResult);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (pResult == NULL) {
LM_ERR("PyObject_CallObject() returned NULL but no exception!\n");
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
if (!PyInt_Check(pResult))
{
if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, "method '%s' of class '%s' should return 'int' type", child_init_mname.s, !classname ? "None" : classname);
python_handle_exception("child_init");
Py_DECREF(format_exc_obj);
Py_XDECREF(pResult);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
rval = PyInt_AsLong(pResult);
Py_DECREF(pResult);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return -1;
}
rval = PyInt_AsLong(pResult);
Py_DECREF(pResult);
PyThreadState_Swap(NULL);
PyEval_ReleaseLock();
return rval;
return rval;
}
static void mod_destroy(void)
{
if (dname)
free(dname); // dname was strdup'ed
if (bname)
free(bname); // bname was strdup'ed
destroy_mod_Core();
destroy_mod_Ranks();
destroy_mod_Logger();
destroy_mod_Router();
if (dname)
free(dname); // dname was strdup'ed
if (bname)
free(bname); // bname was strdup'ed
destroy_mod_Core();
destroy_mod_Ranks();
destroy_mod_Logger();
destroy_mod_Router();
}

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
*
* This file is part of Kamailio, a free SIP server.
@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
*/
#include <Python.h>
@ -30,8 +30,8 @@
#include "structmember.h"
typedef struct {
PyObject_HEAD
struct sip_msg *msg;
PyObject_HEAD
struct sip_msg *msg;
} msgobject;
static PyTypeObject MSGtype;
@ -40,453 +40,453 @@ static PyTypeObject MSGtype;
msgobject *newmsgobject(struct sip_msg *msg)
{
msgobject *msgp;
msgobject *msgp;
msgp = PyObject_New(msgobject, &MSGtype);
if (msgp == NULL)
return NULL;
msgp = PyObject_New(msgobject, &MSGtype);
if (msgp == NULL)
return NULL;
msgp->msg = msg;
return msgp;
msgp->msg = msg;
return msgp;
}
void msg_invalidate(msgobject *self)
{
self->msg = NULL;
self->msg = NULL;
}
static void msg_dealloc(msgobject *msgp)
{
PyObject_Del(msgp);
PyObject_Del(msgp);
}
static PyObject *msg_copy(msgobject *self)
{
msgobject *msgp;
msgobject *msgp;
if ((msgp = newmsgobject(self->msg)) == NULL)
return NULL;
if ((msgp = newmsgobject(self->msg)) == NULL)
return NULL;
return (PyObject *)msgp;
return (PyObject *)msgp;
}
static PyObject *msg_rewrite_ruri(msgobject *self, PyObject *args)
{
char *ruri;
struct action act;
struct run_act_ctx ra_ctx;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - rewrite is not possible.\n");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:rewrite_ruri", &ruri))
return NULL;
memset(&act, '\0', sizeof(act));
act.type = SET_URI_T;
act.val[0].type = STRING_ST;
act.val[0].u.str.s = ruri;
act.val[0].u.str.len = strlen(ruri);
init_run_actions_ctx(&ra_ctx);
if (do_action(&ra_ctx, &act, self->msg) < 0) {
LM_ERR("Error in do_action\n");
}
Py_INCREF(Py_None);
return Py_None;
char *ruri;
struct action act;
struct run_act_ctx ra_ctx;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - rewrite is not possible.\n");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:rewrite_ruri", &ruri))
return NULL;
memset(&act, '\0', sizeof(act));
act.type = SET_URI_T;
act.val[0].type = STRING_ST;
act.val[0].u.str.s = ruri;
act.val[0].u.str.len = strlen(ruri);
init_run_actions_ctx(&ra_ctx);
if (do_action(&ra_ctx, &act, self->msg) < 0) {
LM_ERR("Error in do_action\n");
}
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *msg_set_dst_uri(msgobject *self, PyObject *args)
{
str ruri;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - set destination is not possible.\n");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:set_dst_uri", &ruri.s))
return NULL;
ruri.len = strlen(ruri.s);
if (set_dst_uri(self->msg, &ruri) < 0) {
LM_ERR("Error in set_dst_uri\n");
PyErr_SetString(PyExc_RuntimeError, "Error in set_dst_uri\n");
}
/* dst_uri changes, so it makes sense to re-use the current uri for
forking */
ruri_mark_new(); /* re-use uri for serial forking */
Py_INCREF(Py_None);
return Py_None;
str ruri;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - set destination is not possible.\n");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:set_dst_uri", &ruri.s))
return NULL;
ruri.len = strlen(ruri.s);
if (set_dst_uri(self->msg, &ruri) < 0) {
LM_ERR("Error in set_dst_uri\n");
PyErr_SetString(PyExc_RuntimeError, "Error in set_dst_uri\n");
}
/* dst_uri changes, so it makes sense to re-use the current uri for
* forking */
ruri_mark_new(); /* re-use uri for serial forking */
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *msg_getHeader(msgobject *self, PyObject *args)
{
struct hdr_field *hf;
str hname, *hbody;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:getHeader", &hname.s))
return NULL;
hname.len = strlen(hname.s);
parse_headers(self->msg, ~0, 0);
hbody = NULL;
for (hf = self->msg->headers; hf != NULL; hf = hf->next) {
if (hname.len == hf->name.len &&
strncasecmp(hname.s, hf->name.s, hname.len) == 0) {
hbody = &(hf->body);
break;
}
}
if (hbody == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromStringAndSize(hbody->s, hbody->len);
struct hdr_field *hf;
str hname, *hbody;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s:getHeader", &hname.s))
return NULL;
hname.len = strlen(hname.s);
parse_headers(self->msg, ~0, 0);
hbody = NULL;
for (hf = self->msg->headers; hf != NULL; hf = hf->next) {
if (hname.len == hf->name.len &&
strncasecmp(hname.s, hf->name.s, hname.len) == 0) {
hbody = &(hf->body);
break;
}
}
if (hbody == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return PyString_FromStringAndSize(hbody->s, hbody->len);
}
static PyObject *msg_call_function(msgobject *self, PyObject *args)
{
int i, rval;
char *fname, *arg1, *arg2;
sr31_cmd_export_t* fexport;
struct action *act;
struct run_act_ctx ra_ctx;
unsigned mod_ver;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
i = PySequence_Size(args);
if (i < 1 || i > 3) {
PyErr_SetString(PyExc_RuntimeError, "call_function() should " \
"have from 1 to 3 arguments");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s|ss:call_function", &fname, &arg1, &arg2))
return NULL;
fexport = find_export_record(fname, i - 1, 0, &mod_ver);
if (fexport == NULL) {
PyErr_SetString(PyExc_RuntimeError, "no such function");
Py_INCREF(Py_None);
return Py_None;
}
act = mk_action(MODULE2_T, 4 /* number of (type, value) pairs */,
MODEXP_ST, fexport, /* function */
NUMBER_ST, 2, /* parameter number */
STRING_ST, arg1, /* param. 1 */
STRING_ST, arg2 /* param. 2 */
);
if (act == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"action structure could not be created");
Py_INCREF(Py_None);
return Py_None;
}
if (fexport->fixup != NULL) {
if (i >= 3) {
rval = fexport->fixup(&(act->val[3].u.data), 2);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (2)");
Py_INCREF(Py_None);
return Py_None;
}
act->val[3].type = MODFIXUP_ST;
}
if (i >= 2) {
rval = fexport->fixup(&(act->val[2].u.data), 1);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (1)");
Py_INCREF(Py_None);
return Py_None;
}
act->val[2].type = MODFIXUP_ST;
}
if (i == 1) {
rval = fexport->fixup(0, 0);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (0)");
Py_INCREF(Py_None);
return Py_None;
}
}
}
init_run_actions_ctx(&ra_ctx);
rval = do_action(&ra_ctx, act, self->msg);
if ((act->val[3].type == MODFIXUP_ST) && (act->val[3].u.data)) {
pkg_free(act->val[3].u.data);
}
if ((act->val[2].type == MODFIXUP_ST) && (act->val[2].u.data)) {
pkg_free(act->val[2].u.data);
}
pkg_free(act);
return PyInt_FromLong(rval);
int i, rval;
char *fname, *arg1, *arg2;
sr31_cmd_export_t* fexport;
struct action *act;
struct run_act_ctx ra_ctx;
unsigned mod_ver;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
i = PySequence_Size(args);
if (i < 1 || i > 3) {
PyErr_SetString(PyExc_RuntimeError, "call_function() should " \
"have from 1 to 3 arguments");
Py_INCREF(Py_None);
return Py_None;
}
if(!PyArg_ParseTuple(args, "s|ss:call_function", &fname, &arg1, &arg2))
return NULL;
fexport = find_export_record(fname, i - 1, 0, &mod_ver);
if (fexport == NULL) {
PyErr_SetString(PyExc_RuntimeError, "no such function");
Py_INCREF(Py_None);
return Py_None;
}
act = mk_action(MODULE2_T, 4 /* number of (type, value) pairs */,
MODEXP_ST, fexport, /* function */
NUMBER_ST, 2, /* parameter number */
STRING_ST, arg1, /* param. 1 */
STRING_ST, arg2 /* param. 2 */
);
if (act == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"action structure could not be created");
Py_INCREF(Py_None);
return Py_None;
}
if (fexport->fixup != NULL) {
if (i >= 3) {
rval = fexport->fixup(&(act->val[3].u.data), 2);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (2)");
Py_INCREF(Py_None);
return Py_None;
}
act->val[3].type = MODFIXUP_ST;
}
if (i >= 2) {
rval = fexport->fixup(&(act->val[2].u.data), 1);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (1)");
Py_INCREF(Py_None);
return Py_None;
}
act->val[2].type = MODFIXUP_ST;
}
if (i == 1) {
rval = fexport->fixup(0, 0);
if (rval < 0) {
PyErr_SetString(PyExc_RuntimeError, "Error in fixup (0)");
Py_INCREF(Py_None);
return Py_None;
}
}
}
init_run_actions_ctx(&ra_ctx);
rval = do_action(&ra_ctx, act, self->msg);
if ((act->val[3].type == MODFIXUP_ST) && (act->val[3].u.data)) {
pkg_free(act->val[3].u.data);
}
if ((act->val[2].type == MODFIXUP_ST) && (act->val[2].u.data)) {
pkg_free(act->val[2].u.data);
}
pkg_free(act);
return PyInt_FromLong(rval);
}
PyDoc_STRVAR(copy_doc,
"copy() -> msg object\n\
\n\
Return a copy (``clone'') of the msg object.");
"copy() -> msg object\n\
\n\
Return a copy (``clone'') of the msg object.");
static PyMethodDef msg_methods[] = {
{"copy", (PyCFunction)msg_copy, METH_NOARGS, copy_doc},
{"rewrite_ruri", (PyCFunction)msg_rewrite_ruri, METH_VARARGS, "Rewrite Request-URI."},
{"set_dst_uri", (PyCFunction)msg_set_dst_uri, METH_VARARGS, "Set destination URI."},
{"getHeader", (PyCFunction)msg_getHeader, METH_VARARGS, "Get SIP header field by name."},
{"call_function", (PyCFunction)msg_call_function, METH_VARARGS, "Invoke function exported by the other module."},
{NULL, NULL, 0, NULL} /* sentinel */
{"copy", (PyCFunction)msg_copy, METH_NOARGS, copy_doc},
{"rewrite_ruri", (PyCFunction)msg_rewrite_ruri, METH_VARARGS, "Rewrite Request-URI."},
{"set_dst_uri", (PyCFunction)msg_set_dst_uri, METH_VARARGS, "Set destination URI."},
{"getHeader", (PyCFunction)msg_getHeader, METH_VARARGS, "Get SIP header field by name."},
{"call_function", (PyCFunction)msg_call_function, METH_VARARGS, "Invoke function exported by the other module."},
{NULL, NULL, 0, NULL} /* sentinel */
};
static PyObject *msg_getType(msgobject *self, PyObject *unused)
{
const char *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
switch ((self->msg->first_line).type)
{
case SIP_REQUEST:
rval = "SIP_REQUEST";
break;
case SIP_REPLY:
rval = "SIP_REPLY";
break;
default:
rval = "SIP_INVALID";
break;
}
return PyString_FromString(rval);
const char *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
switch ((self->msg->first_line).type)
{
case SIP_REQUEST:
rval = "SIP_REQUEST";
break;
case SIP_REPLY:
rval = "SIP_REPLY";
break;
default:
rval = "SIP_INVALID";
break;
}
return PyString_FromString(rval);
}
static PyObject *msg_getMethod(msgobject *self, PyObject *unused)
{
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - no method available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.request.method);
return PyString_FromStringAndSize(rval->s, rval->len);
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - no method available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.request.method);
return PyString_FromStringAndSize(rval->s, rval->len);
}
static PyObject *msg_getStatus(msgobject *self, PyObject *unused)
{
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REPLY) {
PyErr_SetString(PyExc_RuntimeError, "Not a non-reply message - no status available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.reply.status);
return PyString_FromStringAndSize(rval->s, rval->len);
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REPLY) {
PyErr_SetString(PyExc_RuntimeError, "Not a non-reply message - no status available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.reply.status);
return PyString_FromStringAndSize(rval->s, rval->len);
}
static PyObject *msg_getRURI(msgobject *self, PyObject *unused)
{
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - RURI is not available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.request.uri);
return PyString_FromStringAndSize(rval->s, rval->len);
str *rval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
if ((self->msg->first_line).type != SIP_REQUEST) {
PyErr_SetString(PyExc_RuntimeError, "Not a request message - RURI is not available.\n");
Py_INCREF(Py_None);
return Py_None;
}
rval = &((self->msg->first_line).u.request.uri);
return PyString_FromStringAndSize(rval->s, rval->len);
}
static PyObject *msg_get_src_address(msgobject *self, PyObject *unused)
{
PyObject *src_ip, *src_port, *pyRval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
src_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.src_ip));
if (src_ip == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
src_port = PyInt_FromLong(self->msg->rcv.src_port);
if (src_port == NULL) {
Py_DECREF(src_ip);
Py_INCREF(Py_None);
return Py_None;
}
pyRval = PyTuple_Pack(2, src_ip, src_port);
Py_DECREF(src_ip);
Py_DECREF(src_port);
if (pyRval == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return pyRval;
PyObject *src_ip, *src_port, *pyRval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
src_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.src_ip));
if (src_ip == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
src_port = PyInt_FromLong(self->msg->rcv.src_port);
if (src_port == NULL) {
Py_DECREF(src_ip);
Py_INCREF(Py_None);
return Py_None;
}
pyRval = PyTuple_Pack(2, src_ip, src_port);
Py_DECREF(src_ip);
Py_DECREF(src_port);
if (pyRval == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return pyRval;
}
static PyObject *msg_get_dst_address(msgobject *self, PyObject *unused)
{
PyObject *dst_ip, *dst_port, *pyRval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
dst_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.dst_ip));
if (dst_ip == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
dst_port = PyInt_FromLong(self->msg->rcv.dst_port);
if (dst_port == NULL) {
Py_DECREF(dst_ip);
Py_INCREF(Py_None);
return Py_None;
}
pyRval = PyTuple_Pack(2, dst_ip, dst_port);
Py_DECREF(dst_ip);
Py_DECREF(dst_port);
if (pyRval == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return pyRval;
PyObject *dst_ip, *dst_port, *pyRval;
if (self->msg == NULL) {
PyErr_SetString(PyExc_RuntimeError, "self->msg is NULL");
Py_INCREF(Py_None);
return Py_None;
}
dst_ip = PyString_FromString(ip_addr2a(&self->msg->rcv.dst_ip));
if (dst_ip == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
dst_port = PyInt_FromLong(self->msg->rcv.dst_port);
if (dst_port == NULL) {
Py_DECREF(dst_ip);
Py_INCREF(Py_None);
return Py_None;
}
pyRval = PyTuple_Pack(2, dst_ip, dst_port);
Py_DECREF(dst_ip);
Py_DECREF(dst_port);
if (pyRval == NULL) {
Py_INCREF(Py_None);
return Py_None;
}
return pyRval;
}
static PyGetSetDef msg_getseters[] = {
{"Type", (getter)msg_getType, NULL, NULL, "Get message type - \"SIP_REQUEST\" or \"SIP_REPLY\"."},
{"Method", (getter)msg_getMethod, NULL, NULL, "Get SIP method name."},
{"Status", (getter)msg_getStatus, NULL, NULL, "Get SIP status code string."},
{"RURI", (getter)msg_getRURI, NULL, NULL, "Get SIP Request-URI."},
{"src_address", (getter)msg_get_src_address, NULL, NULL, "Get (IP, port) tuple representing source address of the message."},
{"dst_address", (getter)msg_get_dst_address, NULL, NULL, "Get (IP, port) tuple representing destination address of the message."},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
{"Type", (getter)msg_getType, NULL, NULL, "Get message type - \"SIP_REQUEST\" or \"SIP_REPLY\"."},
{"Method", (getter)msg_getMethod, NULL, NULL, "Get SIP method name."},
{"Status", (getter)msg_getStatus, NULL, NULL, "Get SIP status code string."},
{"RURI", (getter)msg_getRURI, NULL, NULL, "Get SIP Request-URI."},
{"src_address", (getter)msg_get_src_address, NULL, NULL, "Get (IP, port) tuple representing source address of the message."},
{"dst_address", (getter)msg_get_dst_address, NULL, NULL, "Get (IP, port) tuple representing destination address of the message."},
{NULL, NULL, NULL, NULL, NULL} /* Sentinel */
};
static PyTypeObject MSGtype = {
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6
PyVarObject_HEAD_INIT(NULL, 0)
PyVarObject_HEAD_INIT(NULL, 0)
#else
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
#endif
"Router.msg", /*tp_name*/
sizeof(msgobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)msg_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
msg_methods, /*tp_methods*/
0, /*tp_members*/
msg_getseters, /*tp_getset*/
"Router.msg", /*tp_name*/
sizeof(msgobject), /*tp_size*/
0, /*tp_itemsize*/
/* methods */
(destructor)msg_dealloc, /*tp_dealloc*/
0, /*tp_print*/
0, /*tp_getattr*/
0, /*tp_setattr*/
0, /*tp_compare*/
0, /*tp_repr*/
0, /*tp_as_number*/
0, /*tp_as_sequence*/
0, /*tp_as_mapping*/
0, /*tp_hash*/
0, /*tp_call*/
0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
0, /*tp_as_buffer*/
Py_TPFLAGS_DEFAULT, /*tp_flags*/
0, /*tp_doc*/
0, /*tp_traverse*/
0, /*tp_clear*/
0, /*tp_richcompare*/
0, /*tp_weaklistoffset*/
0, /*tp_iter*/
0, /*tp_iternext*/
msg_methods, /*tp_methods*/
0, /*tp_members*/
msg_getseters, /*tp_getset*/
};
int python_msgobj_init(void)
{
MSGtype.ob_type = &PyType_Type;
if (PyType_Ready(&MSGtype) < 0)
return -1;
return 0;
MSGtype.ob_type = &PyType_Type;
if (PyType_Ready(&MSGtype) < 0)
return -1;
return 0;
}

@ -1,4 +1,4 @@
/*
/*
* Copyright (C) 2009 Sippy Software, Inc., http://www.sippysoft.com
*
* This file is part of Kamailio, a free SIP server.
@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
*/
#include <Python.h>
#include <stdio.h>
@ -31,223 +31,223 @@
void python_handle_exception(const char *fmt, ...)
{
PyObject *pResult;
const char *msg;
char *buf;
size_t buflen, msglen;
PyObject *exception, *v, *tb, *args;
PyObject *line;
int i;
char *srcbuf;
// We don't want to generate traceback when no errors occured
if (!PyErr_Occurred())
return;
if (fmt == NULL)
srcbuf = NULL;
else
srcbuf = make_message(fmt);
PyErr_Fetch(&exception, &v, &tb);
PyErr_Clear();
if (exception == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyErr_Fetch() has failed.\n");
return;
}
PyErr_NormalizeException(&exception, &v, &tb);
if (exception == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyErr_NormalizeException() has failed.\n");
return;
}
args = PyTuple_Pack(3, exception, v, tb ? tb : Py_None);
Py_XDECREF(exception);
Py_XDECREF(v);
Py_XDECREF(tb);
if (args == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyTuple_Pack() has failed.\n");
return;
}
pResult = PyObject_CallObject(format_exc_obj, args);
Py_DECREF(args);
if (pResult == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, traceback.format_exception() has failed.\n");
return;
}
buflen = 1;
buf = (char *)pkg_realloc(NULL, buflen * sizeof(char *));
if (!buf)
{
LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
return;
}
memset(buf, 0, sizeof(char *));
for (i = 0; i < PySequence_Size(pResult); i++) {
line = PySequence_GetItem(pResult, i);
if (line == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PySequence_GetItem() has failed.\n");
Py_DECREF(pResult);
if (buf)
pkg_free(buf);
return;
}
PyObject *pResult;
const char *msg;
char *buf;
size_t buflen, msglen;
PyObject *exception, *v, *tb, *args;
PyObject *line;
int i;
char *srcbuf;
// We don't want to generate traceback when no errors occured
if (!PyErr_Occurred())
return;
if (fmt == NULL)
srcbuf = NULL;
else
srcbuf = make_message(fmt);
msg = PyString_AsString(line);
PyErr_Fetch(&exception, &v, &tb);
PyErr_Clear();
if (exception == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyErr_Fetch() has failed.\n");
return;
}
if (msg == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyString_AsString() has failed.\n");
Py_DECREF(line);
Py_DECREF(pResult);
if (buf)
pkg_free(buf);
return;
}
PyErr_NormalizeException(&exception, &v, &tb);
if (exception == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyErr_NormalizeException() has failed.\n");
return;
}
msglen = strlen(msg);
buflen += ++msglen;
args = PyTuple_Pack(3, exception, v, tb ? tb : Py_None);
Py_XDECREF(exception);
Py_XDECREF(v);
Py_XDECREF(tb);
if (args == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyTuple_Pack() has failed.\n");
return;
}
pResult = PyObject_CallObject(format_exc_obj, args);
Py_DECREF(args);
if (pResult == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, traceback.format_exception() has failed.\n");
return;
}
buf = (char *)pkg_realloc(buf, buflen * sizeof(char *));
buflen = 1;
buf = (char *)pkg_realloc(NULL, buflen * sizeof(char));
if (!buf)
{
LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
Py_DECREF(line);
Py_DECREF(pResult);
return;
LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
return;
}
memset(buf, 0, buflen * sizeof(char));
for (i = 0; i < PySequence_Size(pResult); i++) {
line = PySequence_GetItem(pResult, i);
if (line == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PySequence_GetItem() has failed.\n");
Py_DECREF(pResult);
if (buf)
pkg_free(buf);
return;
}
msg = PyString_AsString(line);
if (msg == NULL) {
LM_ERR("python_handle_exception(): Can't get traceback, PyString_AsString() has failed.\n");
Py_DECREF(line);
Py_DECREF(pResult);
if (buf)
pkg_free(buf);
return;
}
msglen = strlen(msg);
buflen += ++msglen;
buf = (char *)pkg_realloc(buf, buflen * sizeof(char *));
if (!buf)
{
LM_ERR("python_handle_exception(): Can't allocate memory (%lu bytes), pkg_realloc() has failed. Not enough memory.\n", (unsigned long)(buflen * sizeof(char *)));
Py_DECREF(line);
Py_DECREF(pResult);
return;
}
strncat(buf, msg, msglen >= buflen ? buflen-1 : msglen);
Py_DECREF(line);
}
strncat(buf, msg, msglen >= buflen ? buflen-1 : msglen);
Py_DECREF(line);
}
if (srcbuf == NULL)
LM_ERR("Unhandled exception in the Python code:\n%s", buf);
else
LM_ERR("%s: Unhandled exception in the Python code:\n%s", srcbuf, buf);
if (srcbuf == NULL)
LM_ERR("Unhandled exception in the Python code:\n%s", buf);
else
LM_ERR("%s: Unhandled exception in the Python code:\n%s", srcbuf, buf);
if (buf)
pkg_free(buf);
if (buf)
pkg_free(buf);
if (srcbuf)
pkg_free(srcbuf);
if (srcbuf)
pkg_free(srcbuf);
Py_DECREF(pResult);
Py_DECREF(pResult);
}
PyObject *InitTracebackModule()
{
PyObject *pModule, *pTracebackObject;
pModule = PyImport_ImportModule("traceback");
if (pModule == NULL) {
LM_ERR("InitTracebackModule(): Cannot import module 'traceback'.\n");
return NULL;
}
pTracebackObject = PyObject_GetAttrString(pModule, "format_exception");
Py_DECREF(pModule);
if (pTracebackObject == NULL || !PyCallable_Check(pTracebackObject)) {
LM_ERR("InitTracebackModule(): AttributeError: 'module' object 'traceback' has no attribute 'format_exception'.\n");
Py_XDECREF(pTracebackObject);
return NULL;
}
return pTracebackObject;
PyObject *pModule, *pTracebackObject;
pModule = PyImport_ImportModule("traceback");
if (pModule == NULL) {
LM_ERR("InitTracebackModule(): Cannot import module 'traceback'.\n");
return NULL;
}
pTracebackObject = PyObject_GetAttrString(pModule, "format_exception");
Py_DECREF(pModule);
if (pTracebackObject == NULL || !PyCallable_Check(pTracebackObject)) {
LM_ERR("InitTracebackModule(): AttributeError: 'module' object 'traceback' has no attribute 'format_exception'.\n");
Py_XDECREF(pTracebackObject);
return NULL;
}
return pTracebackObject;
}
char *make_message(const char *fmt, ...)
{
int n;
size_t size;
char *p, *np;
va_list ap;
size = 100; /* Guess we need no more than 100 bytes. */
p = (char *)pkg_realloc(NULL, size * sizeof(char *));
if (!p)
{
LM_ERR("make_message(): Can't allocate memory (%lu bytes), pkg_malloc() has failed: Not enough memory.\n", (unsigned long)(size * sizeof(char *)));
return NULL;
}
memset(p, 0, size * sizeof(char *));
while (1)
{
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n > -1 && n < size)
return p;
if (n > -1) /* glibc 2.1 */
size = n+1;
else /* glibc 2.0 */
size *= 2;
np = (char *)pkg_realloc(p, size * sizeof(char *));
if (!np)
int n;
size_t size;
char *p, *np;
va_list ap;
size = 100; /* Guess we need no more than 100 bytes. */
p = (char *)pkg_realloc(NULL, size * sizeof(char *));
if (!p)
{
LM_ERR("make_message(): Can't allocate memory (%lu bytes), pkg_realloc() has failed: Not enough memory.\n", (unsigned long)size * sizeof(char *));
if (p)
pkg_free(p);
return NULL;
}
else
p = np;
}
LM_ERR("make_message(): Can't allocate memory (%lu bytes), pkg_malloc() has failed: Not enough memory.\n", (unsigned long)(size * sizeof(char *)));
return NULL;
}
memset(p, 0, size * sizeof(char *));
while (1)
{
va_start(ap, fmt);
n = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (n > -1 && n < size)
return p;
if (n > -1) /* glibc 2.1 */
size = n+1;
else /* glibc 2.0 */
size *= 2;
np = (char *)pkg_realloc(p, size * sizeof(char *));
if (!np)
{
LM_ERR("make_message(): Can't allocate memory (%lu bytes), pkg_realloc() has failed: Not enough memory.\n", (unsigned long)size * sizeof(char *));
if (p)
pkg_free(p);
return NULL;
}
else
p = np;
}
return NULL; // shall not happened, but who knows ;)
return NULL; // shall not happened, but who knows ;)
}
char *get_class_name(PyObject *y)
{
PyObject *p;
char *name;
PyObject *p;
char *name;
p = PyObject_GetAttrString(y, "__name__");
if (p == NULL || p == Py_None)
{
Py_XDECREF(p);
return NULL;
}
p = PyObject_GetAttrString(y, "__name__");
if (p == NULL || p == Py_None)
{
Py_XDECREF(p);
return NULL;
}
name = PyString_AsString(p);
Py_XDECREF(p);
name = PyString_AsString(p);
Py_XDECREF(p);
return name;
return name;
}
char *get_instance_class_name(PyObject *y)
{
PyObject *p, *n;
char *name;
PyObject *p, *n;
char *name;
n = PyObject_GetAttrString(y, "__class__");
if (n == NULL || n == Py_None)
{
Py_XDECREF(n);
return NULL;
}
n = PyObject_GetAttrString(y, "__class__");
if (n == NULL || n == Py_None)
{
Py_XDECREF(n);
return NULL;
}
p = PyObject_GetAttrString(n, "__name__");
if (p == NULL || p == Py_None)
{
Py_XDECREF(p);
return NULL;
}
p = PyObject_GetAttrString(n, "__name__");
if (p == NULL || p == Py_None)
{
Py_XDECREF(p);
return NULL;
}
name = PyString_AsString(p);
Py_XDECREF(p);
Py_XDECREF(n);
name = PyString_AsString(p);
Py_XDECREF(p);
Py_XDECREF(n);
return name;
return name;
}

@ -83,7 +83,7 @@ Chapter 1. Admin Guide
The following modules must be loaded before this module:
* tm - transaction management.
tmx - transaction management extensions.
* tmx - transaction management extensions.
2.2. External Libraries or Applications

@ -8,7 +8,7 @@
]>
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<book>
<bookinfo>
<title>ASYNC Module</title>
<productname class="trade">sip-router.org</productname>
@ -30,8 +30,7 @@
</copyright>
</bookinfo>
<toc></toc>
<xi:include href="async_admin.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="async_admin.xml"/>
</book>

@ -42,6 +42,8 @@
<para>
<emphasis>tm</emphasis> - transaction management.
</para>
</listitem>
<listitem>
<para>
<emphasis>tmx</emphasis> - transaction management extensions.
</para>

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -42,28 +42,28 @@ static int auth_check_hdr_md5(struct sip_msg* msg, auth_body_t* auth_body,
* @param check_hdr pointer to the function checking Authorization header field
*/
auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype,
struct hdr_field** hdr,
check_auth_hdr_t check_auth_hdr)
struct hdr_field** hdr,
check_auth_hdr_t check_auth_hdr)
{
int ret;
auth_body_t* c;
check_auth_hdr_t check_hf;
auth_result_t auth_rv;
/* ACK and CANCEL must be always authenticated, there is
* no way how to challenge ACK and CANCEL cannot be
* challenged because it must have the same CSeq as
* the request to be canceled.
* PRACK is also not authenticated
*/
/* ACK and CANCEL must be always authenticated, there is
* no way how to challenge ACK and CANCEL cannot be
* challenged because it must have the same CSeq as
* the request to be canceled.
* PRACK is also not authenticated
*/
if (msg->REQ_METHOD & (METHOD_ACK|METHOD_CANCEL|METHOD_PRACK))
return AUTHENTICATED;
/* Try to find credentials with corresponding realm
* in the message, parse them and return pointer to
* parsed structure
*/
/* Try to find credentials with corresponding realm
* in the message, parse them and return pointer to
* parsed structure
*/
strip_realm(realm);
ret = find_credentials(msg, realm, hftype, hdr);
if (ret < 0) {
@ -75,10 +75,10 @@ auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype,
return NO_CREDENTIALS;
}
/* Pointer to the parsed credentials */
/* Pointer to the parsed credentials */
c = (auth_body_t*)((*hdr)->parsed);
/* digest headers are in c->digest */
/* digest headers are in c->digest */
DBG("auth: digest-algo: %.*s parsed value: %d\n",
c->digest.alg.alg_str.len, c->digest.alg.alg_str.s,
c->digest.alg.alg_parsed);
@ -88,7 +88,7 @@ auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype,
return ERROR;
}
/* check authorization header field's validity */
/* check authorization header field's validity */
if (check_auth_hdr == NULL) {
check_hf = auth_check_hdr_md5;
} else { /* use check function of external authentication module */
@ -98,23 +98,23 @@ auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype,
if (!check_hf(msg, c, &auth_rv)) {
return auth_rv;
}
return DO_AUTHENTICATION;
}
/**
* TODO move it to rfc2617.c
*
* TODO move it to rfc2617.c
*
* @param auth_res return value of authentication. Maybe the it will be not affected.
* @result if authentication should continue (1) or not (0)
*
*
*/
static int auth_check_hdr_md5(struct sip_msg* msg, auth_body_t* auth,
auth_result_t* auth_res)
{
int ret;
/* Check credentials correctness here */
/* Check credentials correctness here */
if (check_dig_cred(&auth->digest) != E_DIG_OK) {
LOG(L_ERR, "auth:pre_auth: Credentials are not filled properly\n");
*auth_res = BAD_CREDENTIALS;
@ -125,8 +125,8 @@ static int auth_check_hdr_md5(struct sip_msg* msg, auth_body_t* auth,
if (ret!=0){
if (ret==3 || ret==4){
/* failed auth_extra_checks or stale */
auth->stale=1; /* we mark the nonce as stale
(hack that makes our life much easier) */
auth->stale=1; /* we mark the nonce as stale
* (hack that makes our life much easier) */
*auth_res = STALE_NONCE;
return 0;
} else if (ret==6) {
@ -153,14 +153,14 @@ auth_result_t post_auth(struct sip_msg* msg, struct hdr_field* hdr)
c = (auth_body_t*)((hdr)->parsed);
if (c->stale ) {
if ((msg->REQ_METHOD == METHOD_ACK) ||
(msg->REQ_METHOD == METHOD_CANCEL)) {
/* Method is ACK or CANCEL, we must accept stale
* nonces because there is no way how to challenge
* with new nonce (ACK has no response associated
* and CANCEL must have the same CSeq as the request
* to be canceled)
*/
if ((msg->REQ_METHOD == METHOD_ACK) ||
(msg->REQ_METHOD == METHOD_CANCEL)) {
/* Method is ACK or CANCEL, we must accept stale
* nonces because there is no way how to challenge
* with new nonce (ACK has no response associated
* and CANCEL must have the same CSeq as the request
* to be canceled)
*/
} else {
c->stale = 1;
res = NOT_AUTHENTICATED;
@ -192,9 +192,9 @@ int auth_check_response(dig_cred_t* cred, str* method, char* ha1)
* from the user agent
*/
calc_response(ha1, &(cred->nonce),
&(cred->nc), &(cred->cnonce),
&(cred->qop.qop_str), cred->qop.qop_parsed == QOP_AUTHINT,
method, &(cred->uri), hent, resp);
&(cred->nc), &(cred->cnonce),
&(cred->qop.qop_str), cred->qop.qop_parsed == QOP_AUTHINT,
method, &(cred->uri), hent, resp);
DBG("check_response: Our result = \'%s\'\n", resp);

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -69,10 +69,10 @@ typedef enum auth_result {
AUTHENTICATED, /* Authenticated by default, no digest authentication necessary */
BAD_CREDENTIALS, /* Digest credentials are malformed */
CREATE_CHALLENGE, /* when AKAv1-MD5 is used first request does not contain credentials,
* only usename, realm and algorithm. Server should get Authentication
* Vector from AuC/HSS, create challenge and send it to the UE. */
* only usename, realm and algorithm. Server should get Authentication
* Vector from AuC/HSS, create challenge and send it to the UE. */
DO_RESYNCHRONIZATION /* When AUTS is received we need do resynchronization
* of sequnce numbers with mobile station. */
* of sequnce numbers with mobile station. */
} auth_result_t;
@ -88,10 +88,10 @@ int check_auth_hdr(struct sip_msg* msg, auth_body_t* auth_body,
* ACK and CANCEL
*/
typedef auth_result_t (*pre_auth_t)(struct sip_msg* msg, str* realm,
hdr_types_t hftype, struct hdr_field** hdr,
hdr_types_t hftype, struct hdr_field** hdr,
check_auth_hdr_t check_auth_hdr);
auth_result_t pre_auth(struct sip_msg* msg, str* realm, hdr_types_t hftype,
struct hdr_field** hdr, check_auth_hdr_t check_auth_hdr);
struct hdr_field** hdr, check_auth_hdr_t check_auth_hdr);
/*
@ -122,10 +122,10 @@ int consume_credentials(struct sip_msg* msg);
* Auth module API
*/
typedef struct auth_api_s {
pre_auth_t pre_auth; /* The function to be called before authentication */
post_auth_t post_auth; /* The function to be called after authentication */
build_challenge_hf_t build_challenge; /* Function to build digest challenge header */
struct qp* qop; /* qop module parameter */
pre_auth_t pre_auth; /* The function to be called before authentication */
post_auth_t post_auth; /* The function to be called after authentication */
build_challenge_hf_t build_challenge; /* Function to build digest challenge header */
struct qp* qop; /* qop module parameter */
calc_HA1_t calc_HA1;
calc_response_t calc_response;
check_response_t check_response;

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -118,18 +118,18 @@ str proxy_challenge_header = STR_STATIC_INIT("Proxy-Authenticate");
str www_challenge_header = STR_STATIC_INIT("WWW-Authenticate");
struct qp auth_qop = {
STR_STATIC_INIT("auth"),
QOP_AUTH
STR_STATIC_INIT("auth"),
QOP_AUTH
};
static struct qp auth_qauth = {
STR_STATIC_INIT("auth"),
QOP_AUTH
STR_STATIC_INIT("auth"),
QOP_AUTH
};
static struct qp auth_qauthint = {
STR_STATIC_INIT("auth-int"),
QOP_AUTHINT
STR_STATIC_INIT("auth-int"),
QOP_AUTHINT
};
/*! SL API structure */
@ -139,32 +139,32 @@ sl_api_t slb;
* Exported functions
*/
static cmd_export_t cmds[] = {
{"consume_credentials", w_consume_credentials, 0,
0, REQUEST_ROUTE},
{"www_challenge", (cmd_function)www_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"proxy_challenge", (cmd_function)proxy_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"auth_challenge", (cmd_function)w_auth_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"pv_www_authorize", (cmd_function)pv_www_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_www_authenticate", (cmd_function)pv_www_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_www_authenticate", (cmd_function)pv_www_authenticate2, 4,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_proxy_authorize", (cmd_function)pv_proxy_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_proxy_authenticate", (cmd_function)pv_proxy_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"auth_get_www_authenticate", (cmd_function)w_auth_get_www_authenticate, 3,
fixup_auth_get_www_authenticate, REQUEST_ROUTE},
{"has_credentials", w_has_credentials, 1,
fixup_spve_null, REQUEST_ROUTE},
{"pv_auth_check", (cmd_function)pv_auth_check, 4,
fixup_pv_auth_check, REQUEST_ROUTE},
{"bind_auth_s", (cmd_function)bind_auth_s, 0, 0, 0 },
{0, 0, 0, 0, 0}
{"consume_credentials", w_consume_credentials, 0,
0, REQUEST_ROUTE},
{"www_challenge", (cmd_function)www_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"proxy_challenge", (cmd_function)proxy_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"auth_challenge", (cmd_function)w_auth_challenge, 2,
fixup_auth_challenge, REQUEST_ROUTE},
{"pv_www_authorize", (cmd_function)pv_www_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_www_authenticate", (cmd_function)pv_www_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_www_authenticate", (cmd_function)pv_www_authenticate2, 4,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_proxy_authorize", (cmd_function)pv_proxy_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"pv_proxy_authenticate", (cmd_function)pv_proxy_authenticate, 3,
fixup_pv_auth, REQUEST_ROUTE},
{"auth_get_www_authenticate", (cmd_function)w_auth_get_www_authenticate, 3,
fixup_auth_get_www_authenticate, REQUEST_ROUTE},
{"has_credentials", w_has_credentials, 1,
fixup_spve_null, REQUEST_ROUTE},
{"pv_auth_check", (cmd_function)pv_auth_check, 4,
fixup_pv_auth_check, REQUEST_ROUTE},
{"bind_auth_s", (cmd_function)bind_auth_s, 0, 0, 0 },
{0, 0, 0, 0, 0}
};
@ -172,14 +172,14 @@ static cmd_export_t cmds[] = {
* Exported parameters
*/
static param_export_t params[] = {
{"secret", PARAM_STRING, &sec_param },
{"nonce_expire", PARAM_INT, &nonce_expire },
{"secret", PARAM_STRING, &sec_param },
{"nonce_expire", PARAM_INT, &nonce_expire },
{"nonce_auth_max_drift", PARAM_INT, &nonce_auth_max_drift },
{"protect_contacts", PARAM_INT, &protect_contacts },
{"challenge_attr", PARAM_STR, &challenge_attr },
{"proxy_challenge_header", PARAM_STR, &proxy_challenge_header},
{"www_challenge_header", PARAM_STR, &www_challenge_header },
{"qop", PARAM_STR, &auth_qop.qop_str },
{"protect_contacts", PARAM_INT, &protect_contacts },
{"challenge_attr", PARAM_STR, &challenge_attr },
{"proxy_challenge_header", PARAM_STR, &proxy_challenge_header},
{"www_challenge_header", PARAM_STR, &www_challenge_header },
{"qop", PARAM_STR, &auth_qop.qop_str },
{"auth_checks_register", PARAM_INT, &auth_checks_reg },
{"auth_checks_no_dlg", PARAM_INT, &auth_checks_ood },
{"auth_checks_in_dlg", PARAM_INT, &auth_checks_ind },
@ -190,10 +190,10 @@ static param_export_t params[] = {
{"otn_in_flight_no", PARAM_INT, &otn_in_flight_no },
{"otn_in_flight_order", PARAM_INT, &otn_in_flight_k },
{"nid_pool_no", PARAM_INT, &nid_pool_no },
{"force_stateless_reply", PARAM_INT, &force_stateless_reply },
{"force_stateless_reply", PARAM_INT, &force_stateless_reply },
{"realm_prefix", PARAM_STRING, &auth_realm_prefix.s },
{"use_domain", PARAM_INT, &auth_use_domain },
{0, 0, 0}
{"use_domain", PARAM_INT, &auth_use_domain },
{0, 0, 0}
};
@ -201,15 +201,15 @@ static param_export_t params[] = {
* Module interface
*/
struct module_exports exports = {
"auth",
cmds,
0, /* RPC methods */
params,
mod_init, /* module initialization function */
0, /* response function */
destroy, /* destroy function */
0, /* oncancel function */
0 /* child initialization function */
"auth",
cmds,
0, /* RPC methods */
params,
mod_init, /* module initialization function */
0, /* response function */
destroy, /* destroy function */
0, /* oncancel function */
0 /* child initialization function */
};
@ -219,47 +219,47 @@ struct module_exports exports = {
*/
static inline int generate_random_secret(void)
{
int i;
sec_rand1 = (char*)pkg_malloc(RAND_SECRET_LEN);
sec_rand2 = (char*)pkg_malloc(RAND_SECRET_LEN);
if (!sec_rand1 || !sec_rand2) {
LOG(L_ERR, "auth:generate_random_secret: No memory left\n");
if (sec_rand1){
pkg_free(sec_rand1);
sec_rand1=0;
int i;
sec_rand1 = (char*)pkg_malloc(RAND_SECRET_LEN);
sec_rand2 = (char*)pkg_malloc(RAND_SECRET_LEN);
if (!sec_rand1 || !sec_rand2) {
LOG(L_ERR, "auth:generate_random_secret: No memory left\n");
if (sec_rand1){
pkg_free(sec_rand1);
sec_rand1=0;
}
return -1;
}
return -1;
}
/* srandom(time(0)); -- seeded by core */
for(i = 0; i < RAND_SECRET_LEN; i++) {
sec_rand1[i] = 32 + (int)(95.0 * rand() / (RAND_MAX + 1.0));
}
secret1.s = sec_rand1;
secret1.len = RAND_SECRET_LEN;
for(i = 0; i < RAND_SECRET_LEN; i++) {
sec_rand2[i] = 32 + (int)(95.0 * rand() / (RAND_MAX + 1.0));
}
secret2.s = sec_rand2;
secret2.len = RAND_SECRET_LEN;
/* DBG("Generated secret: '%.*s'\n", secret.len, secret.s); */
return 0;
/* srandom(time(0)); -- seeded by core */
for(i = 0; i < RAND_SECRET_LEN; i++) {
sec_rand1[i] = 32 + (int)(95.0 * rand() / (RAND_MAX + 1.0));
}
secret1.s = sec_rand1;
secret1.len = RAND_SECRET_LEN;
for(i = 0; i < RAND_SECRET_LEN; i++) {
sec_rand2[i] = 32 + (int)(95.0 * rand() / (RAND_MAX + 1.0));
}
secret2.s = sec_rand2;
secret2.len = RAND_SECRET_LEN;
/* DBG("Generated secret: '%.*s'\n", secret.len, secret.s); */
return 0;
}
static int mod_init(void)
{
str attr;
DBG("auth module - initializing\n");
str attr;
DBG("auth module - initializing\n");
auth_realm_prefix.len = strlen(auth_realm_prefix.s);
/* bind the SL API */
@ -269,17 +269,17 @@ static int mod_init(void)
}
/* If the parameter was not used */
if (sec_param == 0) {
if (sec_param == 0) {
/* Generate secret using random generator */
if (generate_random_secret() < 0) {
LOG(L_ERR, "auth:mod_init: Error while generating random secret\n");
return -3;
}
} else {
} else {
/* Otherwise use the parameter's value */
secret1.s = sec_param;
secret1.len = strlen(secret1.s);
if (auth_checks_reg || auth_checks_ind || auth_checks_ood) {
/* divide the secret in half: one half for secret1 and one half for
* secret2 */
@ -288,27 +288,27 @@ static int mod_init(void)
secret2.s = secret1.s + secret1.len;
if (secret2.len < 16) {
WARN("auth: consider a longer secret when extra auth checks are"
" enabled (the config secret is divided in 2!)\n");
" enabled (the config secret is divided in 2!)\n");
}
}
}
if ((!challenge_attr.s || challenge_attr.len == 0) ||
challenge_attr.s[0] != '$') {
}
if ((!challenge_attr.s || challenge_attr.len == 0) ||
challenge_attr.s[0] != '$') {
ERR("auth: Invalid value of challenge_attr module parameter\n");
return -1;
}
attr.s = challenge_attr.s + 1;
attr.len = challenge_attr.len - 1;
if (parse_avp_ident(&attr, &challenge_avpid) < 0) {
}
attr.s = challenge_attr.s + 1;
attr.len = challenge_attr.len - 1;
if (parse_avp_ident(&attr, &challenge_avpid) < 0) {
ERR("auth: Error while parsing value of challenge_attr module"
" parameter\n");
return -1;
}
parse_qop(&auth_qop);
}
parse_qop(&auth_qop);
switch(auth_qop.qop_parsed){
case QOP_OTHER:
ERR("auth: Unsupported qop parameter value\n");
@ -318,7 +318,7 @@ static int mod_init(void)
if (nc_enabled){
#ifndef USE_NC
WARN("auth: nounce count support enabled from config, but"
" disabled at compile time (recompile with -DUSE_NC)\n");
" disabled at compile time (recompile with -DUSE_NC)\n");
nc_enabled=0;
#else
if (nid_crt==0)
@ -344,7 +344,7 @@ static int mod_init(void)
if (otn_enabled){
#ifdef USE_OT_NONCE
if (nid_crt==0) init_nonce_id();
if (init_ot_nonce()!=0)
if (init_ot_nonce()!=0)
return -1;
#else
WARN("auth: one-time-nonce support enabled from config, but "
@ -353,14 +353,14 @@ static int mod_init(void)
#endif /* USE_OT_NONCE */
}
return 0;
return 0;
}
static void destroy(void)
{
if (sec_rand1) pkg_free(sec_rand1);
if (sec_rand2) pkg_free(sec_rand2);
if (sec_rand1) pkg_free(sec_rand1);
if (sec_rand2) pkg_free(sec_rand2);
#ifdef USE_NC
destroy_nonce_count();
#endif
@ -378,30 +378,30 @@ static void destroy(void)
*/
int consume_credentials(struct sip_msg* msg)
{
struct hdr_field* h;
int len;
struct hdr_field* h;
int len;
/* skip requests that can't be authenticated */
if (msg->REQ_METHOD & (METHOD_ACK|METHOD_CANCEL|METHOD_PRACK))
return -1;
get_authorized_cred(msg->authorization, &h);
if (!h) {
get_authorized_cred(msg->authorization, &h);
if (!h) {
get_authorized_cred(msg->proxy_auth, &h);
if (!h) {
if (!h) {
LOG(L_ERR, "auth:consume_credentials: No authorized "
"credentials found (error in scripts)\n");
return -1;
}
}
len = h->len;
if (del_lump(msg, h->name.s - msg->buf, len, 0) == 0) {
}
len = h->len;
if (del_lump(msg, h->name.s - msg->buf, len, 0) == 0) {
LOG(L_ERR, "auth:consume_credentials: Can't remove credentials\n");
return -1;
}
return 1;
}
return 1;
}
/**
@ -417,7 +417,7 @@ int w_consume_credentials(struct sip_msg* msg, char* s1, char* s2)
*/
int w_has_credentials(sip_msg_t *msg, char* realm, char* s2)
{
str srealm = {0, 0};
str srealm = {0, 0};
hdr_field_t *hdr = NULL;
int ret;
@ -450,8 +450,8 @@ int pv_authenticate(struct sip_msg *msg, str *realm, str *passwd,
struct hdr_field* h;
auth_body_t* cred;
int ret;
str hf = {0, 0};
avp_value_t val;
str hf = {0, 0};
avp_value_t val;
static char ha1[256];
struct qp *qop = NULL;
@ -537,13 +537,13 @@ end:
qop = &auth_qauth;
}
if (get_challenge_hf(msg, (cred ? cred->stale : 0),
realm, NULL, NULL, qop, hftype, &hf) < 0) {
realm, NULL, NULL, qop, hftype, &hf) < 0) {
ERR("Error while creating challenge\n");
ret = AUTH_ERROR;
} else {
val.s = hf;
if(add_avp(challenge_avpid.flags | AVP_VAL_STR,
challenge_avpid.name, val) < 0) {
challenge_avpid.name, val) < 0) {
LM_ERR("Error while creating attribute with challenge\n");
ret = AUTH_ERROR;
}
@ -560,9 +560,9 @@ end:
static int pv_proxy_authenticate(struct sip_msg *msg, char* realm,
char *passwd, char *flags)
{
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
LM_ERR("failed to get realm value\n");
@ -589,7 +589,7 @@ static int pv_proxy_authenticate(struct sip_msg *msg, char* realm,
goto error;
}
return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T,
&msg->first_line.u.request.method);
&msg->first_line.u.request.method);
error:
return AUTH_ERROR;
@ -601,9 +601,9 @@ error:
static int pv_www_authenticate(struct sip_msg *msg, char* realm,
char *passwd, char *flags)
{
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
LM_ERR("failed to get realm value\n");
@ -630,7 +630,7 @@ static int pv_www_authenticate(struct sip_msg *msg, char* realm,
goto error;
}
return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T,
&msg->first_line.u.request.method);
&msg->first_line.u.request.method);
error:
return AUTH_ERROR;
@ -639,10 +639,10 @@ error:
static int pv_www_authenticate2(struct sip_msg *msg, char* realm,
char *passwd, char *flags, char *method)
{
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
str smethod = {0, 0};
int vflags = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
str smethod = {0, 0};
if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
LM_ERR("failed to get realm value\n");
@ -680,7 +680,7 @@ static int pv_www_authenticate2(struct sip_msg *msg, char* realm,
}
return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T,
&smethod);
&smethod);
error:
return AUTH_ERROR;
@ -692,10 +692,10 @@ error:
static int pv_auth_check(sip_msg_t *msg, char *realm,
char *passwd, char *flags, char *checks)
{
int vflags = 0;
int vchecks = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
int vflags = 0;
int vchecks = 0;
str srealm = {0, 0};
str spasswd = {0, 0};
int ret;
hdr_field_t *hdr;
sip_uri_t *uri = NULL;
@ -750,10 +750,10 @@ static int pv_auth_check(sip_msg_t *msg, char *realm,
if(msg->REQ_METHOD==METHOD_REGISTER)
ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T,
&msg->first_line.u.request.method);
&msg->first_line.u.request.method);
else
ret = pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T,
&msg->first_line.u.request.method);
&msg->first_line.u.request.method);
if(ret==AUTH_OK && (vchecks&AUTH_CHECK_ID_F)) {
hdr = (msg->proxy_auth==0)?msg->authorization:msg->proxy_auth;
@ -770,7 +770,7 @@ static int pv_auth_check(sip_msg_t *msg, char *realm,
uri = furi;
}
if(srealm.len!=uri->user.len
|| strncmp(srealm.s, uri->user.s, srealm.len)!=0)
|| strncmp(srealm.s, uri->user.s, srealm.len)!=0)
return AUTH_USER_MISMATCH;
if(msg->REQ_METHOD==METHOD_REGISTER || msg->REQ_METHOD==METHOD_PUBLISH) {
@ -779,7 +779,7 @@ static int pv_auth_check(sip_msg_t *msg, char *realm,
|| strncmp(furi->user.s, turi->user.s, furi->user.len)!=0)
return AUTH_USER_MISMATCH;
if(auth_use_domain!=0 && (furi->host.len!=turi->host.len
|| strncmp(furi->host.s, turi->host.s, furi->host.len)!=0))
|| strncmp(furi->host.s, turi->host.s, furi->host.len)!=0))
return AUTH_USER_MISMATCH;
/* check r-uri==from for publish */
if(msg->REQ_METHOD==METHOD_PUBLISH) {
@ -790,9 +790,9 @@ static int pv_auth_check(sip_msg_t *msg, char *realm,
|| strncmp(furi->user.s, uri->user.s, furi->user.len)!=0)
return AUTH_USER_MISMATCH;
if(auth_use_domain!=0 && (furi->host.len!=uri->host.len
|| strncmp(furi->host.s, uri->host.s, furi->host.len)!=0))
|| strncmp(furi->host.s, uri->host.s, furi->host.len)!=0))
return AUTH_USER_MISMATCH;
}
}
}
return AUTH_OK;
}
@ -848,9 +848,9 @@ static int fixup_pv_auth_check(void **param, int param_no)
*
*/
static int auth_send_reply(struct sip_msg *msg, int code, char *reason,
char *hdr, int hdr_len)
char *hdr, int hdr_len)
{
str reason_str;
str reason_str;
/* Add new headers if there are any */
if ((hdr!=NULL) && (hdr_len>0)) {
@ -864,8 +864,8 @@ static int auth_send_reply(struct sip_msg *msg, int code, char *reason,
reason_str.len = strlen(reason);
return force_stateless_reply ?
slb.sreply(msg, code, &reason_str) :
slb.freply(msg, code, &reason_str);
slb.sreply(msg, code, &reason_str) :
slb.freply(msg, code, &reason_str);
}
/**
@ -874,8 +874,8 @@ static int auth_send_reply(struct sip_msg *msg, int code, char *reason,
int auth_challenge_helper(struct sip_msg *msg, str *realm, int flags, int hftype,
str *res)
{
int ret, stale;
str hf = {0, 0};
int ret, stale;
str hf = {0, 0};
struct qp *qop = NULL;
ret = -1;
@ -886,17 +886,17 @@ int auth_challenge_helper(struct sip_msg *msg, str *realm, int flags, int hftype
qop = &auth_qauth;
}
if (flags & 16) {
stale = 1;
stale = 1;
} else {
stale = 0;
stale = 0;
}
if (get_challenge_hf(msg, stale, realm, NULL, NULL, qop, hftype, &hf)
< 0) {
< 0) {
ERR("Error while creating challenge\n");
ret = -2;
goto error;
}
ret = 1;
if(res!=NULL)
{
@ -908,12 +908,12 @@ int auth_challenge_helper(struct sip_msg *msg, str *realm, int flags, int hftype
if(auth_send_reply(msg, 401, "Unauthorized",
hf.s, hf.len) <0 )
ret = -3;
break;
break;
case HDR_PROXYAUTH_T:
if(auth_send_reply(msg, 407, "Proxy Authentication Required",
hf.s, hf.len) <0 )
ret = -3;
break;
break;
}
if(hf.s) pkg_free(hf.s);
return ret;
@ -1130,15 +1130,15 @@ static int fixup_auth_get_www_authenticate(void **param, int param_no)
case 2:
return fixup_var_int_12(param, 1);
case 3:
if (fixup_pvar_null(param, 1) != 0) {
LM_ERR("failed to fixup result pvar\n");
return -1;
}
if (((pv_spec_t *)(*param))->setf == NULL) {
LM_ERR("result pvar is not writeble\n");
return -1;
}
return 0;
if (fixup_pvar_null(param, 1) != 0) {
LM_ERR("failed to fixup result pvar\n");
return -1;
}
if (((pv_spec_t *)(*param))->setf == NULL) {
LM_ERR("result pvar is not writeble\n");
return -1;
}
return 0;
}
return 0;
}

@ -15,8 +15,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -80,19 +80,19 @@ void strip_realm(str* _realm)
* @param algorithm algorithm value
* @param qop qop value
* @return -1 on error, 0 on success
*
*
* The result is stored in param ahf.
* If nonce is not null that it is used, instead of call calc_nonce.
* If algorithm is not null that it is used irrespective of _PRINT_MD5
*
* Major usage of nonce and algorithm params is AKA authentication.
*
* Major usage of nonce and algorithm params is AKA authentication.
*/
int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
str* nonce, str* algorithm, struct qp* qop, int hftype, str *ahf)
{
char *p;
str* hfn, hf;
int nonce_len, l, cfg;
char *p;
str* hfn, hf;
int nonce_len, l, cfg;
int t;
#if defined USE_NC || defined USE_OT_NONCE
unsigned int n_id;
@ -107,82 +107,82 @@ int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
}
strip_realm(realm);
if (realm) {
DEBUG("build_challenge_hf: realm='%.*s'\n", realm->len, realm->s);
}
if (nonce) {
DEBUG("build_challenge_hf: nonce='%.*s'\n", nonce->len, nonce->s);
}
if (algorithm) {
DEBUG("build_challenge_hf: algorithm='%.*s'\n", algorithm->len,
if (realm) {
DEBUG("build_challenge_hf: realm='%.*s'\n", realm->len, realm->s);
}
if (nonce) {
DEBUG("build_challenge_hf: nonce='%.*s'\n", nonce->len, nonce->s);
}
if (algorithm) {
DEBUG("build_challenge_hf: algorithm='%.*s'\n", algorithm->len,
algorithm->s);
}
if (qop && qop->qop_parsed != QOP_UNSPEC) {
DEBUG("build_challenge_hf: qop='%.*s'\n", qop->qop_str.len,
}
if (qop && qop->qop_parsed != QOP_UNSPEC) {
DEBUG("build_challenge_hf: qop='%.*s'\n", qop->qop_str.len,
qop->qop_str.s);
}
}
if (hftype == HDR_PROXYAUTH_T) {
if (hftype == HDR_PROXYAUTH_T) {
hfn = &proxy_challenge_header;
} else {
} else {
hfn = &www_challenge_header;
}
}
cfg = get_auth_checks(msg);
nonce_len = get_nonce_len(cfg, nc_enabled || otn_enabled);
nonce_len = get_nonce_len(cfg, nc_enabled || otn_enabled);
hf.len = hfn->len;
if (realm) {
hf.len = hfn->len;
if (realm) {
hf.len += DIGEST_REALM_LEN
+ realm->len;
}
+ realm->len;
}
hf.len += DIGEST_NONCE_LEN;
hf.len += DIGEST_NONCE_LEN;
if (nonce) {
hf.len += nonce->len
+ 1; /* '"' */
}
else {
hf.len += nonce_len
+ 1; /* '"' */
}
if (nonce) {
hf.len += nonce->len
+ 1; /* '"' */
}
else {
hf.len += nonce_len
+ 1; /* '"' */
}
hf.len += ((stale) ? STALE_PARAM_LEN : 0);
if (algorithm) {
hf.len += DIGEST_ALGORITHM_LEN + algorithm->len;
}
else {
hf.len += 0
if (algorithm) {
hf.len += DIGEST_ALGORITHM_LEN + algorithm->len;
}
else {
hf.len += 0
#ifdef _PRINT_MD5
+DIGEST_MD5_LEN
+DIGEST_MD5_LEN
#endif
;
}
if (qop && qop->qop_parsed != QOP_UNSPEC) {
;
}
if (qop && qop->qop_parsed != QOP_UNSPEC) {
hf.len += QOP_PARAM_START_LEN + qop->qop_str.len + QOP_PARAM_END_LEN;
}
}
hf.len += CRLF_LEN;
p = hf.s = pkg_malloc(hf.len);
if (!hf.s) {
p = hf.s = pkg_malloc(hf.len);
if (!hf.s) {
ERR("auth: No memory left (%d bytes)\n", hf.len);
return -1;
}
}
memcpy(p, hfn->s, hfn->len); p += hfn->len;
memcpy(p, hfn->s, hfn->len); p += hfn->len;
if(realm){
memcpy(p, DIGEST_REALM, DIGEST_REALM_LEN); p += DIGEST_REALM_LEN;
memcpy(p, realm->s, realm->len); p += realm->len;
}
if(realm){
memcpy(p, DIGEST_REALM, DIGEST_REALM_LEN); p += DIGEST_REALM_LEN;
memcpy(p, realm->s, realm->len); p += realm->len;
}
memcpy(p, DIGEST_NONCE, DIGEST_NONCE_LEN); p += DIGEST_NONCE_LEN;
if (nonce) {
memcpy(p, nonce->s, nonce->len); p += nonce->len;
}
else {
l=nonce_len;
memcpy(p, DIGEST_NONCE, DIGEST_NONCE_LEN); p += DIGEST_NONCE_LEN;
if (nonce) {
memcpy(p, nonce->s, nonce->len); p += nonce->len;
}
else {
l=nonce_len;
t=time(0);
#if defined USE_NC || defined USE_OT_NONCE
if (nc_enabled || otn_enabled){
@ -207,34 +207,34 @@ int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
n_id=0;
}
if (calc_nonce(p, &l, cfg, t, t + nonce_expire, n_id,
pool | pool_flags,
&secret1, &secret2, msg) != 0)
pool | pool_flags,
&secret1, &secret2, msg) != 0)
#else /* USE_NC || USE_OT_NONCE*/
if (calc_nonce(p, &l, cfg, t, t + nonce_expire,
&secret1, &secret2, msg) != 0)
if (calc_nonce(p, &l, cfg, t, t + nonce_expire,
&secret1, &secret2, msg) != 0)
#endif /* USE_NC || USE_OT_NONCE */
{
ERR("auth: calc_nonce failed (len %d, needed %d)\n",
nonce_len, l);
pkg_free(hf.s);
return -1;
}
p += l;
}
*p = '"'; p++;
{
ERR("auth: calc_nonce failed (len %d, needed %d)\n",
nonce_len, l);
pkg_free(hf.s);
return -1;
}
p += l;
}
*p = '"'; p++;
if (qop && qop->qop_parsed != QOP_UNSPEC) {
if (qop && qop->qop_parsed != QOP_UNSPEC) {
memcpy(p, QOP_PARAM_START, QOP_PARAM_START_LEN);
p += QOP_PARAM_START_LEN;
memcpy(p, qop->qop_str.s, qop->qop_str.len);
p += qop->qop_str.len;
memcpy(p, QOP_PARAM_END, QOP_PARAM_END_LEN);
p += QOP_PARAM_END_LEN;
}
if (stale) {
}
if (stale) {
memcpy(p, STALE_PARAM, STALE_PARAM_LEN);
p += STALE_PARAM_LEN;
}
}
if (algorithm) {
memcpy(p, DIGEST_ALGORITHM, DIGEST_ALGORITHM_LEN);
p += DIGEST_ALGORITHM_LEN;
@ -243,16 +243,16 @@ int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
}
else {
#ifdef _PRINT_MD5
memcpy(p, DIGEST_MD5, DIGEST_MD5_LEN ); p += DIGEST_MD5_LEN;
memcpy(p, DIGEST_MD5, DIGEST_MD5_LEN ); p += DIGEST_MD5_LEN;
#endif
}
memcpy(p, CRLF, CRLF_LEN); p += CRLF_LEN;
hf.len=(int)(p-hf.s); /* fix len, it might be smaller due to a smaller
nonce */
DBG("auth: '%.*s'\n", hf.len, ZSW(hf.s));
memcpy(p, CRLF, CRLF_LEN); p += CRLF_LEN;
hf.len=(int)(p-hf.s); /* fix len, it might be smaller due to a smaller
* nonce */
DBG("auth: '%.*s'\n", hf.len, ZSW(hf.s));
*ahf = hf;
return 0;
return 0;
}
/**
@ -271,22 +271,22 @@ int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
int build_challenge_hf(struct sip_msg* msg, int stale, str* realm,
str* nonce, str* algorithm, int hftype)
{
str hf = {0, 0};
avp_value_t val;
str hf = {0, 0};
avp_value_t val;
int ret;
ret = get_challenge_hf(msg, stale, realm, nonce, algorithm, &auth_qop,
hftype, &hf);
hftype, &hf);
if(ret < 0)
return ret;
val.s = hf;
if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val)
if(add_avp(challenge_avpid.flags | AVP_VAL_STR, challenge_avpid.name, val)
< 0) {
ERR("auth: Error while creating attribute with challenge\n");
pkg_free(hf.s);
return -1;
}
}
pkg_free(hf.s);
return 0;
}

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -32,12 +32,12 @@
* @param nonce nonce value
* @param algorithm algorithm value
* @return -1 on error, 0 on success
*
*
* The result is stored in an attribute.
* If nonce is not null that it is used, instead of call calc_nonce.
* If algorithm is not null that it is used irrespective of _PRINT_MD5
*
* Major usage of nonce and algorithm params is AKA authentication.
*
* Major usage of nonce and algorithm params is AKA authentication.
*/
typedef int (*build_challenge_hf_t)(struct sip_msg* msg, int stale,
str* realm, str* nonce, str* algorithm, int hftype);

@ -1,21 +1,21 @@
/*
* Digest Authentication Module
*
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -23,8 +23,8 @@
int nc_enabled=0;
unsigned nc_array_k; /* array size bits (k in 2^k) */
unsigned nc_array_size; /* 2^k == 1<<nc_array_bits (in nc_t and not
unsigned ints)*/
unsigned nc_array_size; /* 2^k == 1<<nc_array_bits (in nc_t and not
* unsigned ints)*/
#ifdef USE_NC
@ -45,7 +45,7 @@ static unsigned int* nc_array=0;
unsigned nc_partition_size; /* array partition == nc_array_size/nc_pool_no*/
unsigned nc_partition_k; /* k such that 2^k==nc_partition_size */
unsigned nc_partition_mask; /* mask for computing the real idx. inside
one partition */
* one partition */
/* returns -1 on error, 0 on success */
@ -97,7 +97,7 @@ int init_nonce_count()
" memory(%ld bytes)\n", size, max_mem);
}
nc_array_size=size;
if (nid_pool_no>=nc_array_size){
ERR("auth: nid_pool_no (%d) too high for the configured "
"nc_array_size (%d)\n", nid_pool_no, nc_array_size);
@ -108,7 +108,7 @@ int init_nonce_count()
nc_partition_mask=(1<<nc_partition_k)-1;
assert(nc_partition_size == nc_array_size/nid_pool_no);
assert(1<<(nc_partition_k+nid_pool_k) == nc_array_size);
if ((nid_t)nc_partition_size >= ((nid_t)(-1)/NID_INC)){
ERR("auth: nc_array_size too big, try decreasing it or increasing"
"the number of pools/partitions\n");
@ -121,8 +121,7 @@ int init_nonce_count()
"nc_array_size/nid_pool_no >= %d\n",
nid_pool_no, orig_array_size, MIN_NC_ARRAY_PARTITION);
}
/* array size should be multiple of sizeof(unsigned int) since we
* access it as an uint array */
nc_array=shm_malloc(sizeof(nc_t)*ROUND_INT(nc_array_size));
@ -182,7 +181,7 @@ void destroy_nonce_count()
* WARNING: NID_INC * nc_partition_size must fit inside an nidx_t*/
#define nc_id_check_overflow(id, pool) \
((nid_t)(nid_get((pool))-(id)) >= \
((nid_t)NID_INC*nc_partition_size))
((nid_t)NID_INC*nc_partition_size))
/* re-init the stored nc for nonce id in pool p */
nid_t nc_new(nid_t id, unsigned char p)
@ -190,7 +189,7 @@ nid_t nc_new(nid_t id, unsigned char p)
unsigned int i;
unsigned n, r;
unsigned int v, new_v;
n=get_nc_array_raw_idx(id, p); /* n-th nc_t */
i=get_nc_array_uint_idx(n); /* aray index i, corresponding to n */
r=get_nc_int_pos(n); /* byte/short inside the uint corresponding to n */
@ -205,7 +204,7 @@ nid_t nc_new(nid_t id, unsigned char p)
/* check if nonce-count nc w/ index i is expected/valid and if so it
/* check if nonce-count nc w/ index i is expected/valid and if so it
* updated the stored nonce-count
* returns: 0 - ok, < 0 some error:
* NC_INV_POOL (pool number is invalid/corrupted)
@ -219,7 +218,7 @@ enum nc_check_ret nc_check_val(nid_t id, unsigned pool, unsigned int nc)
unsigned int i;
unsigned n, r;
unsigned int v, crt_nc, new_v;
if (unlikely(pool>=nid_pool_no))
return NC_INV_POOL;
if (unlikely(nc_id_check_overflow(id, pool)))

@ -3,27 +3,27 @@
* nonce-count (nc) tracking
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Defines:
* Defines:
* USE_NC - if not defined no NC specific code will be compiled
*/
@ -57,9 +57,9 @@ int init_nonce_count();
void destroy_nonce_count();
enum nc_check_ret{
NC_OK=0, NC_INV_POOL=-1, NC_ID_OVERFLOW=-2, NC_TOO_BIG=-3,
NC_REPLAY=-4
enum nc_check_ret{
NC_OK=0, NC_INV_POOL=-1, NC_ID_OVERFLOW=-2, NC_TOO_BIG=-3,
NC_REPLAY=-4
};
/* check if nonce-count nc w/ index i is expected/valid and record its

@ -4,28 +4,28 @@
* time nonces)
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Defines:
* USE_NC, USE_OT_NONCE - if neither of them defined no code will be
* Defines:
* USE_NC, USE_OT_NONCE - if neither of them defined no code will be
* compiled
*/
@ -51,8 +51,7 @@ unsigned int nid_pool_mask; /* mask for computing the current pool*/
int init_nonce_id()
{
unsigned pool_no, r;
if (nid_crt!=0)
return 0; /* already init */
if (nid_pool_no==0){
@ -70,7 +69,7 @@ int init_nonce_id()
INFO("auth: nid_pool_no rounded down to %d\n", pool_no);
}
nid_pool_no=pool_no;
nid_crt=shm_malloc(sizeof(*nid_crt)*nid_pool_no);
if (nid_crt==0){
ERR("auth: init_nonce_id: memory allocation failure\n");

@ -4,28 +4,28 @@
* time nonces)
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Defines:
* USE_NC, USE_OT_NONCE - if neither of them defined no code will be
* Defines:
* USE_NC, USE_OT_NONCE - if neither of them defined no code will be
* compiled
*/

@ -1,22 +1,22 @@
/*
* Digest Authentication Module
* Nonce related functions
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -71,7 +71,7 @@ int get_auth_checks(struct sip_msg* msg)
if (msg->REQ_METHOD == METHOD_REGISTER) {
return auth_checks_reg;
}
if (!msg->to && parse_headers(msg, HDR_TO_F, 0) == -1) {
DBG("auth: Error while parsing To header field\n");
return auth_checks_ood;
@ -89,16 +89,16 @@ int get_auth_checks(struct sip_msg* msg)
* MD5s and returns the length of the binary nonce (cannot return error).
* See calc_nonce below for more details.*/
inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg,
str* secret1, str* secret2,
struct sip_msg* msg)
str* secret1, str* secret2,
struct sip_msg* msg)
{
MD5_CTX ctx;
str* s;
int len;
MD5Init(&ctx);
U_MD5Update(&ctx, &b_nonce->raw[0], 4 + 4);
if (cfg && msg){
/* auth extra checks => 2 md5s */
@ -107,7 +107,7 @@ inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg,
if (b_nonce->n.nid_pf & (NF_VALID_NC_ID | NF_VALID_OT_ID)){
/* if extra auth checks enabled, nid & pf are after the 2nd md5 */
U_MD5Update(&ctx, (unsigned char*)&b_nonce->n.nid_i,
nonce_nid_extra_size);
nonce_nid_extra_size);
len+=nonce_nid_extra_size;
}
#endif /* USE_NC || USE_OT_NONCE */
@ -119,14 +119,14 @@ inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg,
s = GET_RURI(msg);
MD5Update(&ctx, s->s, s->len);
}
if ((cfg & AUTH_CHECK_CALLID) &&
!(parse_headers(msg, HDR_CALLID_F, 0) < 0 || msg->callid == 0)) {
if ((cfg & AUTH_CHECK_CALLID) &&
!(parse_headers(msg, HDR_CALLID_F, 0) < 0 || msg->callid == 0)) {
MD5Update(&ctx, msg->callid->body.s, msg->callid->body.len);
}
if ((cfg & AUTH_CHECK_FROMTAG) &&
!(parse_from_header(msg) < 0 )) {
MD5Update(&ctx, get_from(msg)->tag_value.s,
get_from(msg)->tag_value.len);
!(parse_from_header(msg) < 0 )) {
MD5Update(&ctx, get_from(msg)->tag_value.s,
get_from(msg)->tag_value.len);
}
if (cfg & AUTH_CHECK_SRC_IP) {
U_MD5Update(&ctx, msg->rcv.src_ip.u.addr, msg->rcv.src_ip.len);
@ -141,14 +141,14 @@ inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg,
/* if extra auth checks are not enabled, nid & pf are after the
* 1st md5 */
U_MD5Update(&ctx, (unsigned char*)&b_nonce->n_small.nid_i,
nonce_nid_extra_size);
nonce_nid_extra_size);
len+=nonce_nid_extra_size;
}
#endif /* USE_NC || USE_OT_NONCE*/
MD5Update(&ctx, secret1->s, secret1->len);
MD5Final(&b_nonce->n.md5_1[0], &ctx);
}
return len;
}
@ -170,45 +170,45 @@ inline static int calc_bin_nonce_md5(union bin_nonce* b_nonce, int cfg,
* of the SIP request:
* <expire_time> <valid_since> MD5(<expire_time>, <valid_since>, secret1) MD5(<extra_checks>, secret2)
* @param nonce Pointer to a buffer of *nonce_len. It must have enough
* space to hold the nonce. MAX_NONCE_LEN should be always
* space to hold the nonce. MAX_NONCE_LEN should be always
* safe.
* @param nonce_len A value/result parameter. Initially it contains the
* nonce buffer length. If the length is too small, it
* will be set to the needed length and the function will
* return error immediately. After a succesfull call it will
* contain the size of nonce written into the buffer,
* nonce buffer length. If the length is too small, it
* will be set to the needed length and the function will
* return error immediately. After a succesfull call it will
* contain the size of nonce written into the buffer,
* without the terminating 0.
* @param cfg This is the value of one of the tree module parameters that
* control which optional checks are enabled/disabled and which
* parts of the message will be included in the nonce string.
* @param since Time when nonce was created, i.e. nonce is valid since <valid_since> up to <expires>
* @param expires Time in seconds after which the nonce will be considered
* @param expires Time in seconds after which the nonce will be considered
* stale.
* @param n_id Nounce count and/or one-time nonce index value
* (32 bit counter)
* @param pf First 2 bits are flags, the rest is the index pool number
* used if nonce counts or one-time nonces are enabled.
* The possible flags values are: NF_VALID_NC_ID which means
* the nonce-count support is enabled and NF_VALID_OT_ID
* the nonce-count support is enabled and NF_VALID_OT_ID
* which means the one-time nonces support is enabled.
* The pool number can be obtained by and-ing with
* NF_POOL_NO_MASK
* @param secret1 A secret used for the nonce expires integrity check:
* MD5(<expire_time>, <valid_since>, secret1).
* @param secret2 A secret used for integrity check of the message parts
* @param secret2 A secret used for integrity check of the message parts
* selected by auth_extra_checks (if any):
* MD5(<msg_parts(auth_extra_checks)>, secret2).
* @param msg The message for which the nonce is computed. If
* @param msg The message for which the nonce is computed. If
* auth_extra_checks is set, the MD5 of some fields of the
* message will be included in the generated nonce.
* @return 0 on success and -1 on error
*/
int calc_nonce(char* nonce, int *nonce_len, int cfg, int since, int expires,
#if defined USE_NC || defined USE_OT_NONCE
unsigned int n_id, unsigned char pf,
unsigned int n_id, unsigned char pf,
#endif /* USE_NC || USE_OT_NONCE */
str* secret1, str* secret2,
struct sip_msg* msg)
str* secret1, str* secret2,
struct sip_msg* msg)
{
union bin_nonce b_nonce;
int len;
@ -222,8 +222,8 @@ int calc_nonce(char* nonce, int *nonce_len, int cfg, int since, int expires,
BIN_NONCE_PREPARE(&b_nonce, expires, since, n_id, pf, cfg, msg);
len=calc_bin_nonce_md5(&b_nonce, cfg, secret1, secret2, msg);
*nonce_len=base64_enc(&b_nonce.raw[0], len,
(unsigned char*)nonce, *nonce_len);
*nonce_len=base64_enc(&b_nonce.raw[0], len,
(unsigned char*)nonce, *nonce_len);
assert(*nonce_len>=0); /*FIXME*/
return 0;
}
@ -250,7 +250,7 @@ int calc_nonce(char* nonce, int *nonce_len, int cfg, int since, int expires,
/** Checks if nonce is stale.
* This function checks if a nonce given to it in the parameter is stale.
* This function checks if a nonce given to it in the parameter is stale.
* A nonce is stale if the expire time stored in the nonce is in the past.
* @param b_nonce a pointer to a union bin_nonce to be checked.
* @return 1 the nonce is stale, 0 the nonce is not stale.
@ -262,21 +262,21 @@ int calc_nonce(char* nonce, int *nonce_len, int cfg, int since, int expires,
/** Utility to convert 8 hex digit string to int */
static inline int l8hex2int(char* _s, unsigned int *_r)
{
unsigned int i, res = 0;
for(i = 0; i < 8; i++) {
res *= 16;
if ((_s[i] >= '0') && (_s[i] <= '9')) {
res += _s[i] - '0';
} else if ((_s[i] >= 'a') && (_s[i] <= 'f')) {
res += _s[i] - 'a' + 10;
} else if ((_s[i] >= 'A') && (_s[i] <= 'F')) {
res += _s[i] - 'A' + 10;
} else return -1;
}
*_r = res;
return 0;
unsigned int i, res = 0;
for(i = 0; i < 8; i++) {
res *= 16;
if ((_s[i] >= '0') && (_s[i] <= '9')) {
res += _s[i] - '0';
} else if ((_s[i] >= 'a') && (_s[i] <= 'f')) {
res += _s[i] - 'a' + 10;
} else if ((_s[i] >= 'A') && (_s[i] <= 'F')) {
res += _s[i] - 'A' + 10;
} else return -1;
}
*_r = res;
return 0;
}
@ -291,11 +291,11 @@ static inline int l8hex2int(char* _s, unsigned int *_r)
* @param nonce A nonce string to be verified.
* @param secret1 A secret used for the nonce expires integrity check:
* MD5(<expire_time>,, secret1).
* @param secret2 A secret used for integrity check of the message parts
* @param secret2 A secret used for integrity check of the message parts
* selected by auth_extra_checks (if any):
* MD5(<msg_parts(auth_extra_checks)>, secret2).
* @param msg The message which contains the nonce being verified.
* @return 0 - success (the nonce was not tampered with and if
* @param msg The message which contains the nonce being verified.
* @return 0 - success (the nonce was not tampered with and if
* auth_extra_checks are enabled - the selected message fields
* have not changes from the time the nonce was generated)
* -1 - invalid nonce
@ -307,7 +307,7 @@ static inline int l8hex2int(char* _s, unsigned int *_r)
* 6 - nonce reused
*/
int check_nonce(auth_body_t* auth, str* secret1, str* secret2,
struct sip_msg* msg)
struct sip_msg* msg)
{
str * nonce;
int since, b_nonce2_len, b_nonce_len, cfg;
@ -328,42 +328,42 @@ int check_nonce(auth_body_t* auth, str* secret1, str* secret2,
if (unlikely(nonce->s == 0)) {
return -1; /* Invalid nonce */
}
if (unlikely(nonce->len<MIN_NONCE_LEN)){
if (unlikely(nonce->len<MIN_NONCE_LEN)){
return 1; /* length musth be >= then minimum length */
}
#if defined USE_NC || defined USE_OT_NONCE
/* clear all possible nonce flags positions prior to decoding,
* to make sure they can be used even if the nonce is shorter */
b_nonce.n.nid_pf=0;
b_nonce.n_small.nid_pf=0;
#endif /* USE_NC || USE_OT_NONCE */
/* decode nonce */
b_nonce_len=base64_dec((unsigned char*)nonce->s, nonce->len,
&b_nonce.raw[0], sizeof(b_nonce));
&b_nonce.raw[0], sizeof(b_nonce));
if (unlikely(b_nonce_len < MIN_BIN_NONCE_LEN)){
DBG("auth: check_nonce: base64_dec failed\n");
return -1; /* error decoding the nonce (invalid nonce since we checked
the len of the base64 enc. nonce above)*/
* the len of the base64 enc. nonce above)*/
}
since = get_bin_nonce_since(&b_nonce);
if (unlikely(since < up_since)) {
/* if valid_since time is time pointing before ser was started
* then we consider nonce as stalled.
It may be the nonce generated by previous ser instance having
different length (for example because of different auth.
checks).. Therefore we force credentials to be rebuilt by UAC
without prompting for password */
/* if valid_since time is time pointing before ser was started
* then we consider nonce as stalled.
* It may be the nonce generated by previous ser instance having
* different length (for example because of different auth.
* checks).. Therefore we force credentials to be rebuilt by UAC
* without prompting for password */
/* if current time is less than start time, reset the start time
* (e.g., after start, the system clock was set in the past) */
t=time(0);
if (t < up_since)
up_since = t;
if (since < t)
return 4;
return 4;
}
t=time(0);
if (unlikely((since > t) && ((since-t) > nonce_auth_max_drift) )){
@ -393,72 +393,72 @@ int check_nonce(auth_body_t* auth, str* secret1, str* secret2,
* or is too short => either an old nonce (should
* be caught by the ser start time check) or truncated nonce */
return 4; /* return stale for now */
}
}
#endif /* USE_NC */
#ifdef USE_OT_NONCE
if (unlikely(otn_enabled && !(pf & NF_VALID_OT_ID))){
/* same as above for one-time-nonce */
return 4; /* return stale for now */
}
if (unlikely(otn_enabled && !(pf & NF_VALID_OT_ID))){
/* same as above for one-time-nonce */
return 4; /* return stale for now */
}
#endif /* USE_OT_NONCE */
/* don't check if we got the expected length, if the length is smaller
* then expected then the md5 check below will fail (since the nid
* members of the bin_nonce struct will be 0); if the length is bigger
* and it was not caught by the base64_dec above, and the md5 matches,
* we ignore the extra stuff */
/* don't check if we got the expected length, if the length is smaller
* then expected then the md5 check below will fail (since the nid
* members of the bin_nonce struct will be 0); if the length is bigger
* and it was not caught by the base64_dec above, and the md5 matches,
* we ignore the extra stuff */
#endif /* USE_NC || USE_OT_NONCE */
b_nonce2_len=calc_bin_nonce_md5(&b_nonce2, cfg, secret1, secret2, msg);
if (!memcmp(&b_nonce.n.md5_1[0], &b_nonce2.n.md5_1[0], 16)) {
b_nonce2_len=calc_bin_nonce_md5(&b_nonce2, cfg, secret1, secret2, msg);
if (!memcmp(&b_nonce.n.md5_1[0], &b_nonce2.n.md5_1[0], 16)) {
#ifdef USE_NC
/* if nounce-count checks enabled & auth. headers has nc */
if (nc_enabled && (pf & NF_VALID_NC_ID) && auth->digest.nc.s &&
auth->digest.nc.len){
if ((auth->digest.nc.len != 8) ||
l8hex2int(auth->digest.nc.s, &nc) != 0) {
ERR("check_nonce: bad nc value %.*s\n",
auth->digest.nc.len, auth->digest.nc.s);
return 5; /* invalid nc */
}
switch(nc_check_val(n_id, pf & NF_POOL_NO_MASK, nc)){
case NC_OK:
/* don't perform extra checks or one-time nonce checks
* anymore, if we have nc */
goto check_stale;
case NC_ID_OVERFLOW: /* id too old => stale */
case NC_TOO_BIG: /* nc overlfow => force re-auth => stale */
case NC_REPLAY: /* nc seen before => re-auth => stale */
case NC_INV_POOL: /* pool-no too big, maybe ser restart?*/
return 4; /* stale */
}
/* if nounce-count checks enabled & auth. headers has nc */
if (nc_enabled && (pf & NF_VALID_NC_ID) && auth->digest.nc.s &&
auth->digest.nc.len){
if ((auth->digest.nc.len != 8) ||
l8hex2int(auth->digest.nc.s, &nc) != 0) {
ERR("check_nonce: bad nc value %.*s\n",
auth->digest.nc.len, auth->digest.nc.s);
return 5; /* invalid nc */
}
switch(nc_check_val(n_id, pf & NF_POOL_NO_MASK, nc)){
case NC_OK:
/* don't perform extra checks or one-time nonce checks
* anymore, if we have nc */
goto check_stale;
case NC_ID_OVERFLOW: /* id too old => stale */
case NC_TOO_BIG: /* nc overlfow => force re-auth => stale */
case NC_REPLAY: /* nc seen before => re-auth => stale */
case NC_INV_POOL: /* pool-no too big, maybe ser restart?*/
return 4; /* stale */
}
}
#endif /* USE_NC */
#ifdef USE_OT_NONCE
if (otn_enabled && (pf & NF_VALID_OT_ID)){
switch(otn_check_id(n_id, pf & NF_POOL_NO_MASK)){
case OTN_OK:
/* continue in case auth extra checks are enabled */
break;
case OTN_ID_OVERFLOW:
case OTN_INV_POOL:
case OTN_REPLAY:
return 6; /* reused */
}
if (otn_enabled && (pf & NF_VALID_OT_ID)){
switch(otn_check_id(n_id, pf & NF_POOL_NO_MASK)){
case OTN_OK:
/* continue in case auth extra checks are enabled */
break;
case OTN_ID_OVERFLOW:
case OTN_INV_POOL:
case OTN_REPLAY:
return 6; /* reused */
}
}
#endif
if (cfg) {
if (unlikely(b_nonce_len != b_nonce2_len))
return 2; /* someone truncated our nonce? */
if (memcmp(&b_nonce.n.md5_2[0], &b_nonce2.n.md5_2[0], 16))
return 3; /* auth_extra_checks failed */
}
if (cfg) {
if (unlikely(b_nonce_len != b_nonce2_len))
return 2; /* someone truncated our nonce? */
if (memcmp(&b_nonce.n.md5_2[0], &b_nonce2.n.md5_2[0], 16))
return 3; /* auth_extra_checks failed */
}
#ifdef USE_NC
check_stale:
#endif /* USE_NC */
if (unlikely(is_bin_nonce_stale(&b_nonce, t)))
return 4;
return 0;
}
return 2;
if (unlikely(is_bin_nonce_stale(&b_nonce, t)))
return 4;
return 0;
}
return 2;
}

@ -1,22 +1,22 @@
/*
* Digest Authentication Module
* Nonce related functions
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -44,17 +44,17 @@
* MD5(expire | since | secret1) (16) \
* [| MD5(info(auth_extra_checks) | secret2) (16) ]
* if nonce-count or one-time nonces are enabled, the format changes to:
* bin_nonce =
* bin_nonce = expire_timestamp(4) | since_timestamp(4) |
* MD5(expire | since | nid | pf | secret1) [ | MD5... ] | nid(4) | pf(1)
* where pf is 1 byte, first 2 bits are flags, and the other 6 are
* bin_nonce =
* bin_nonce = expire_timestamp(4) | since_timestamp(4) |
* MD5(expire | since | nid | pf | secret1) [ | MD5... ] | nid(4) | pf(1)
* where pf is 1 byte, first 2 bits are flags, and the other 6 are
* the pool no:
* bit7 : on => nid & pool are valid for nonce-count
* bit6 : on => nid & pool are valid for one-time nonce
*/
#if defined USE_NC || defined USE_OT_NONCE
#define NF_VALID_NC_ID 128
#define NF_VALID_OT_ID 64
#define NF_VALID_NC_ID 128
#define NF_VALID_OT_ID 64
#define NF_POOL_NO_MASK 63
#endif
@ -76,7 +76,7 @@ struct bin_nonce_str{
#if defined USE_NC || defined USE_OT_NONCE
unsigned int nid_i;
unsigned char nid_pf; /* pool no & flags:
bits 7, 6 = flags, bits 5..0 pool no*/
* bits 7, 6 = flags, bits 5..0 pool no*/
#endif /* USE_NC || USE_OT_NONCE */
};
@ -88,7 +88,7 @@ struct bin_nonce_small_str{
#if defined USE_NC || defined USE_OT_NONCE
unsigned int nid_i;
unsigned char nid_pf; /* pool no & flags:
bits 7, 6 = flags, bits 5..0 pool no*/
* bits 7, 6 = flags, bits 5..0 pool no*/
#endif /* USE_NC || USE_OT_NONCE */
};
@ -153,9 +153,9 @@ union bin_nonce{
#endif /* USE_NC || USE_OT_NONCE */
/* minimum nonce length in binary form (not converted to base64/hex):
* expires_t | since_t | MD5(expires_t | since_t | s1) => 4 + 4 + 16 = 24
* expires_t | since_t | MD5(expires_t | since_t | s1) => 4 + 4 + 16 = 24
* If nc_enabled the nonce will be bigger:
* expires_t | since_t | MD5... | nonce_id | flag+pool_no(1 byte)
* expires_t | since_t | MD5... | nonce_id | flag+pool_no(1 byte)
* => 4 + 4 + 16 + 4 + 1 = 29, but we always return the minimum */
#define MIN_BIN_NONCE_LEN (4 + 4 + 16)
@ -170,7 +170,7 @@ union bin_nonce{
#define MAX_NONCE_LEN base64_enc_len(MAX_BIN_NONCE_LEN)
/*
* Minimum length of the nonce string
* nonce = expires_TIMESTAMP[4 chars] since_TIMESTAMP[4 chars]
* nonce = expires_TIMESTAMP[4 chars] since_TIMESTAMP[4 chars]
* MD5SUM(expires_TIMESTAMP, since_TIMESTAMP, SECRET1)[16 chars]
*/
#define MIN_NONCE_LEN base64_enc_len(MIN_BIN_NONCE_LEN)

@ -1,23 +1,23 @@
/*
* Digest Authentication Module
*
*
* one-time nonce support
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -46,7 +46,7 @@ static otn_cell_t * otn_array=0;
unsigned otn_partition_size; /* partition==otn_in_flight_no/nid_pool_no*/
unsigned otn_partition_k; /* k such that 2^k==otn_partition_size */
unsigned otn_partition_mask; /* mask for computing the real idx. inside
one partition */
* one partition */
/* returns -1 on error, 0 on success */
@ -97,7 +97,7 @@ int init_ot_nonce()
" memory(%ld bytes)\n", size, max_mem);
}
otn_in_flight_no=size;
if (nid_pool_no>=otn_in_flight_no/(8*sizeof(otn_cell_t))){
ERR("auth: nid_pool_no (%d) too high for the configured "
"otn_in_flight_no (%d)\n", nid_pool_no, otn_in_flight_no);
@ -108,7 +108,7 @@ int init_ot_nonce()
otn_partition_mask=(1<<otn_partition_k)-1;
assert(otn_partition_size == otn_in_flight_no/nid_pool_no);
assert(1<<(otn_partition_k+nid_pool_k) == otn_in_flight_no);
if ((nid_t)otn_partition_size >= ((nid_t)(-1)/NID_INC)){
ERR("auth: otn_in_flight_no too big, try decreasing it or increasing"
"the number of pools/partitions, such that "
@ -123,8 +123,7 @@ int init_ot_nonce()
"otn_array_size/nid_pool_no >= %d\n",
nid_pool_no, orig_array_size, MIN_OTN_PARTITION);
}
/* array size should be multiple of sizeof(otn_cell_t) since we
* access it as an otn_cell_t array */
otn_array=shm_malloc(ROUND2TYPE((otn_in_flight_no+7)/8, otn_cell_t));
@ -174,14 +173,14 @@ void destroy_ot_nonce()
* WARNING: NID_INC * otn_partition_size must fit inside an nidx_t*/
#define otn_id_check_overflow(id, pool) \
((nid_t)(nid_get((pool))-(id)) >= \
((nid_t)NID_INC*otn_partition_size))
((nid_t)NID_INC*otn_partition_size))
/* re-init the stored nc for nonce id in pool p */
nid_t otn_new(nid_t id, unsigned char p)
{
unsigned int i;
unsigned n, b;
n=get_otn_array_bit_idx(id, p); /* n-th bit */
i=get_otn_array_cell_idx(n); /* aray index i, corresponding to n */
b=get_otn_cell_bit(n); /* bit pos corresponding to n */
@ -208,7 +207,7 @@ enum otn_check_ret otn_check_id(nid_t id, unsigned pool)
unsigned int i;
unsigned n, b;
otn_cell_t v, b_mask;
if (unlikely(pool>=nid_pool_no))
return OTN_INV_POOL;
if (unlikely(otn_id_check_overflow(id, pool)))
@ -217,7 +216,7 @@ enum otn_check_ret otn_check_id(nid_t id, unsigned pool)
i=get_otn_array_cell_idx(n); /* aray index i, corresponding to n */
b=get_otn_cell_bit(n); /* bit pos corresponding to n */
b_mask= (otn_cell_t)1<<b;
#ifdef OTN_CELL_T_LONG
v=atomic_get_long(&oth_array[i]);
if (unlikely(v & b_mask))

@ -1,29 +1,29 @@
/*
* Digest Authentication Module
*
*
* one-time nonce support
*
* Copyright (C) 2008 iptelorg GmbH
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*
* Defines:
* Defines:
* USE_OT_NONCE - if not defined no one-time nonce specific code will be
* compiled
* OTN_CELL_T_LONG - uses unsigned long instead os unsigned int for the
@ -65,8 +65,8 @@ int init_ot_nonce();
void destroy_ot_nonce();
enum otn_check_ret{
OTN_OK=0, OTN_INV_POOL=-1, OTN_ID_OVERFLOW=-2, OTN_REPLAY=-3
enum otn_check_ret{
OTN_OK=0, OTN_INV_POOL=-1, OTN_ID_OVERFLOW=-2, OTN_REPLAY=-3
};
/* check if nonce w/ index i is valid & expected and record receiving it */

@ -1,22 +1,22 @@
/*
* Digest Authentication Module
* Digest response calculation as per RFC2617
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -36,7 +36,7 @@ inline void cvt_hex(HASH _b, HASHHEX _h)
{
unsigned short i;
unsigned char j;
for (i = 0; i < HASHLEN; i++) {
j = (_b[i] >> 4) & 0xf;
if (j <= 9) {
@ -58,15 +58,15 @@ inline void cvt_hex(HASH _b, HASHHEX _h)
}
/*
* calculate H(A1) as per spec
/*
* calculate H(A1) as per spec
*/
void calc_HA1(ha_alg_t _alg, str* _username, str* _realm, str* _password,
str* _nonce, str* _cnonce, HASHHEX _sess_key)
str* _nonce, str* _cnonce, HASHHEX _sess_key)
{
MD5_CTX Md5Ctx;
HASH HA1;
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, _username->s, _username->len);
MD5Update(&Md5Ctx, ":", 1);
@ -89,26 +89,26 @@ void calc_HA1(ha_alg_t _alg, str* _username, str* _realm, str* _password,
}
/*
* calculate request-digest/response-digest as per HTTP Digest spec
/*
* calculate request-digest/response-digest as per HTTP Digest spec
*/
void calc_response(HASHHEX _ha1, /* H(A1) */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response) /* request-digest or response-digest */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response) /* request-digest or response-digest */
{
MD5_CTX Md5Ctx;
HASH HA2;
HASH RespHash;
HASHHEX HA2Hex;
/* calculate H(A2) */
/* calculate H(A2) */
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, _method->s, _method->len);
MD5Update(&Md5Ctx, ":", 1);
@ -122,7 +122,7 @@ void calc_response(HASHHEX _ha1, /* H(A1) */
MD5Final(HA2, &Md5Ctx);
cvt_hex(HA2, HA2Hex);
/* calculate response */
/* calculate response */
MD5Init(&Md5Ctx);
MD5Update(&Md5Ctx, _ha1, HASHHEXLEN);
MD5Update(&Md5Ctx, ":", 1);

@ -1,22 +1,22 @@
/*
* Digest Authentication Module
* Digest response calculation as per RFC2617
*
*
* Copyright (C) 2001-2003 FhG Fokus
*
*
* This file is part of Kamailio, a free SIP server.
*
*
* Kamailio 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 2 of the License, or
* (at your option) any later version
*
*
* Kamailio 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
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
@ -52,46 +52,45 @@ typedef enum {
void cvt_hex(HASH Bin, HASHHEX Hex);
/*
* calculate H(A1) as per HTTP Digest spec
/*
* calculate H(A1) as per HTTP Digest spec
*/
typedef void (*calc_HA1_t)(ha_alg_t _alg, /* Type of algorithm */
str* _username, /* username */
str* _realm, /* realm */
str* _password, /* password */
str* _nonce, /* nonce string */
str* _cnonce, /* cnonce */
HASHHEX _sess_key); /* Result will be stored here */
str* _username, /* username */
str* _realm, /* realm */
str* _password, /* password */
str* _nonce, /* nonce string */
str* _cnonce, /* cnonce */
HASHHEX _sess_key); /* Result will be stored here */
void calc_HA1(ha_alg_t _alg, /* Type of algorithm */
str* _username, /* username */
str* _realm, /* realm */
str* _password, /* password */
str* _nonce, /* nonce string */
str* _cnonce, /* cnonce */
HASHHEX _sess_key); /* Result will be stored here */
str* _username, /* username */
str* _realm, /* realm */
str* _password, /* password */
str* _nonce, /* nonce string */
str* _cnonce, /* cnonce */
HASHHEX _sess_key); /* Result will be stored here */
/* calculate request-digest/response-digest as per HTTP Digest spec */
typedef void (*calc_response_t)(HASHHEX _ha1, /* H(A1) */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response); /* request-digest or response-digest */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response); /* request-digest or response-digest */
void calc_response(HASHHEX _ha1, /* H(A1) */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response); /* request-digest or response-digest */
str* _nonce, /* nonce from server */
str* _nc, /* 8 hex digits */
str* _cnonce, /* client nonce */
str* _qop, /* qop-value: "", "auth", "auth-int" */
int _auth_int, /* 1 if auth-int is used */
str* _method, /* method from the request */
str* _uri, /* requested URL */
HASHHEX _hentity, /* H(entity body) if qop="auth-int" */
HASHHEX _response); /* request-digest or response-digest */
#endif /* RFC2617_H */

@ -47,6 +47,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "../../sr_module.h"
#include "session.h"
#include "diameter.h"
#include "config.h"
@ -73,6 +74,7 @@ unsigned int *session_id2; /**< counter for second part of the session id */
*/
inline void AAASessionsLock(unsigned int hash)
{
if(destroy_modules_phase()) return;
if ( hash >=0 && hash < sessions_hash_size ){
lock_get(sessions[hash].lock);
}
@ -86,6 +88,7 @@ inline void AAASessionsLock(unsigned int hash)
*/
inline void AAASessionsUnlock(unsigned int hash)
{
if(destroy_modules_phase()) return;
if ( hash >=0 && hash < sessions_hash_size ){
lock_release(sessions[hash].lock);

@ -10,8 +10,6 @@ Daniel-Constantin Mierla
<miconda@gmail.com>
Edited by
Muhammad Shahzad Shafi
<shahzad@voip-demos.com>

@ -73,7 +73,7 @@
<section>
<title>Parameters</title>
<section>
<section id="corex.p.alias_subdomains">
<title><varname>alias_subdomains</varname> (string)</title>
<para>
Register a domain and all its sub-domains to match the <quote>myself</quote>
@ -96,7 +96,7 @@ modparam("corex", "alias_subdomains", "udp:sip-router.org:5060")
</programlisting>
</example>
</section>
<section>
<section id="corex.p.network_io_intercept">
<title><varname>network_io_intercept</varname> (int)</title>
<para>
If set to non-zero then raw data received from a remote host or about to
@ -118,7 +118,7 @@ modparam("corex", "network_io_intercept", 1)
</programlisting>
</example>
</section>
<section>
<section id="corex.p.min_msg_len">
<title><varname>min_msg_len</varname> (int)</title>
<para>
Minimum content length of the packet to execute the event_route[network:msg].
@ -138,7 +138,7 @@ modparam("corex", "min_msg_len", 32)
</programlisting>
</example>
</section>
<section>
<section id="corex.p.msg_avp">
<title><varname>msg_avp</varname> (string)</title>
<para>
AVP name to store modified content to be set in the packet. If not set in
@ -163,7 +163,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
<section>
<title>Functions</title>
<section>
<section id="corex.f.append_branch">
<title>
<function moreinfo="none">append_branch([ uri, [ q ] ])</function>
</title>
@ -205,7 +205,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
</example>
</section>
<section>
<section id="corex.f.send">
<title>
<function moreinfo="none">send([ host [ :port ] ])</function>
</title>
@ -240,7 +240,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
</example>
</section>
<section>
<section id="corex.f.send_tcp">
<title>
<function moreinfo="none">send_tcp([ host [ :port ] ])</function>
</title>
@ -251,7 +251,7 @@ modparam("corex", "msg_avp", "$avp(msg)")
</para>
</section>
<section>
<section id="corex.f.send_data">
<title>
<function moreinfo="none">send_data(uri, data)</function>
</title>
@ -272,14 +272,14 @@ modparam("corex", "msg_avp", "$avp(msg)")
</programlisting>
</example>
</section>
<section>
<section id="corex.f.is_incoming">
<title>
<function moreinfo="none">is_incoming()</function>
</title>
<para>
Returns true if contents of message buffer $mb are the data received from
remote host, otherwise false indicating that the contents of $mb are data
that is about to be sent out to remote host. This only works if
that is about to be sent out to remote host. This only works if
network_io_intercept parameter is set to non-zero.
</para>
<para>
@ -414,7 +414,7 @@ if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
<section>
<title>RPC Commands</title>
<section>
<section id="corex.rpc.list_sockets">
<title>
<function moreinfo="none">corex.list_sockets</function>
</title>
@ -428,7 +428,7 @@ if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
&sercmd; corex.list_sockets
</programlisting>
</section>
<section>
<section id="corex.rpc.list_aliases">
<title>
<function moreinfo="none">corex.list_aliases</function>
</title>
@ -443,7 +443,7 @@ if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
&sercmd; corex.list_aliases
</programlisting>
</section>
<section>
<section id="corex.rpc.shm_status">
<title>
<function moreinfo="none">corex.shm_status</function>
</title>
@ -457,7 +457,7 @@ if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
&sercmd; corex.shm_status
</programlisting>
</section>
<section>
<section id="corex.rpc.shm_summary">
<title>
<function moreinfo="none">corex.shm_summary</function>
</title>
@ -471,7 +471,7 @@ if(file_write("/tmp/data.txt", "Data is: $var(data)")) { ... }
&sercmd; corex.shm_summary
</programlisting>
</section>
<section>
<section id="corex.rpc.pkg_summary">
<title>
<function moreinfo="none">corex.pkg_summary</function>
</title>

@ -37,7 +37,7 @@
#include <fcntl.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 108
#define UNIX_PATH_MAX 104
#endif

@ -1147,7 +1147,13 @@ modparam("dialog", "ka_timer", 10)
dialog setup or previous keep-alive. The value represents the number of
seconds.
Default value is "0" (no keep alive).
If the requests times out (generating a 408) or if the UA responds with
481 the lifetime is set to 10 seconds. When lifetime expires the dialog
will be terminated. Any other response (including error responses) will
reset the timers.
Default value is "0" (no keep alive). The lowest settable interval is
30 seconds.
Example 1.49. Set ka_interval parameter
...

@ -877,8 +877,8 @@ int pv_parse_dlg_name(pv_spec_p sp, str *in)
else goto error;
break;
case 13:
if(strncmp(in->s, "from_bindaddr", 20)==0)
sp->pvp.pvn.u.isname.name.n = 2;
if(strncmp(in->s, "from_bindaddr", 13)==0)
sp->pvp.pvn.u.isname.name.n = 20;
else goto error;
break;
default:

@ -1247,9 +1247,17 @@ modparam("dialog", "ka_timer", 10)
the ka_interval elapsed from dialog setup or previous keep-alive.
The value represents the number of seconds.
</para>
<para>
If the requests times out (generating a 408) or if the
UA responds with 481 the lifetime is set to 10 seconds.
When lifetime expires the dialog will be terminated.
Any other response (including error responses) will
reset the timers.
</para>
<para>
<emphasis>
Default value is <quote>0</quote> (no keep alive).
Default value is <quote>0</quote> (no keep alive). The lowest
settable interval is 30 seconds.
</emphasis>
</para>
<example>

@ -254,7 +254,7 @@ static inline int is_e164(str* _user)
int i;
char c;
if ((_user->len > 2) && (_user->len < MAX_NUM_LEN) && ((_user->s)[0] == '+')) {
if ((_user->len > 1) && (_user->len < MAX_NUM_LEN) && ((_user->s)[0] == '+')) {
for (i = 1; i < _user->len; i++) {
c = (_user->s)[i];
if ((c < '0') || (c > '9')) return -1;
@ -762,14 +762,15 @@ int enum_query(struct sip_msg* _msg, str* suffix, str* service)
return -1;
}
user_s = _msg->parsed_uri.user.s;
user_len = _msg->parsed_uri.user.len;
if (is_e164(&(_msg->parsed_uri.user)) == -1) {
LM_ERR("R-URI user is not an E164 number\n");
LM_ERR("R-URI user '<%.*s>' is not an E164 number\n",
user_len, user_s);
return -1;
}
user_s = _msg->parsed_uri.user.s;
user_len = _msg->parsed_uri.user.len;
memcpy(&(string[0]), user_s, user_len);
string[user_len] = (char)0;

@ -226,7 +226,7 @@ int init_cnode_sockets(int cnode_id)
io_handler_ins(phandler);
/* start epmd handler - publish Kamailo C node */
if (epmd_init((epmd_handler_t*)phandler) < 0 ) {
if (epmd_init((epmd_handler_t*)phandler, &alivename) < 0 ) {
return -1;
}

@ -39,9 +39,9 @@
/**
* \brief Initialize EPMD handler
*/
int epmd_init(epmd_handler_t *epmd)
int epmd_init(epmd_handler_t *epmd, str *alivename)
{
epmd->sockfd = erl_init_node(&epmd->ec, &cnode_alivename, &cnode_host, &cookie);
epmd->sockfd = erl_init_node(&epmd->ec, alivename, &cnode_host, &cookie);
epmd->handle_f = handle_epmd;
epmd->wait_tmo_f = NULL;
epmd->destroy_f = NULL;

@ -55,7 +55,7 @@ typedef struct epmd_handler_s
} epmd_handler_t;
int epmd_init(epmd_handler_t *epmd);
int epmd_init(epmd_handler_t *epmd, str *alivename);
int handle_epmd(handler_common_t *phandler);
#endif /* EPMD_H_ */

@ -83,6 +83,48 @@ int _impl_api_rpc_call(ei_x_buff *reply, const str *module,const str *function,
int buffsz=0;
int rc;
if (!csockfd) {
if (!enode) {
LM_NOTICE("there is no connected Erlang node\n");
/* reply up with error */
ei_x_format(reply, "{error,cnode,~a}", "no_erlang_node");
return -1;
}
if (rex_call_in_progress) {
LM_ERR("RPC loop detected\n");
ei_x_format(reply, "{badrpc,cnode,~a}", "rpc_loop_detected");
return -1;
}
/* do RPC from event route */
if (ei_rpc(&enode->ec,enode->sockfd,module->s,function->s,args->buff,args->index,reply) == ERL_ERROR)
{
reply->index = 0; /* re-use reply buffer */
if (erl_errno)
{
ei_x_format(reply, "{error,cnode,~s}", strerror(erl_errno));
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
}
else if (errno)
{
ei_x_format(reply, "{error,cnode,~s}", strerror(errno));
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
}
else
{
ei_x_format(reply, "{error,cnode,~s}", "Unknown error.");
LM_ERR("ei_rpc failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd);
}
return -1;
}
/* reset response */
enode->response.index = 0;
return 0;
}
memset(&msgh, 0, sizeof(msgh));
memset(&cnt, 0, sizeof(cnt));
@ -187,6 +229,39 @@ int _impl_reg_send(const str *server, const ei_x_buff *msg)
return -1;
}
if (!csockfd) {
if (!enode) {
LM_NOTICE("there is no connected Erlang node\n");
return -1;
}
if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}
/* do ERL_REG_SEND in event route */
if ((rc = ei_reg_send(&enode->ec,enode->sockfd,server->s,msg->buff,msg->buffsz)) == ERL_ERROR)
{
if (erl_errno)
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(erl_errno));
}
else if (errno)
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>: %s\n",enode->conn.nodename,enode->sockfd,strerror(errno));
}
else
{
LM_ERR("ei_reg_send failed on node=<%s> socket=<%d>, Unknown error.\n",enode->ec.thisalivename,enode->sockfd);
}
}
/* reset response */
enode->response.index = 0;
return 0;
}
/* Kamailio PID */
cnt[0].iov_base = (void*)&pid_no;
cnt[0].iov_len = sizeof(pid_no);
@ -245,6 +320,12 @@ int _impl_reply(const ei_x_buff *msg)
LM_ERR("not connected\n");
return -1;
}
if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}
/* copy into reply */
if (enode->response.buffsz < msg->buffsz) {
/* realocate */
@ -277,11 +358,16 @@ int _impl_send(const erlang_pid *pid, const ei_x_buff *msg)
return -1;
}
if (rex_call_in_progress) {
LM_ERR("RPC in progress detected\n");
return -1;
}
if (enode) {
/* copy into reply */
if (enode->response.buffsz < msg->buffsz) {
/* realocate */
/* reallocate */
enode->response.buff=realloc(enode->response.buff,msg->buffsz);
if (!enode->response.buff) {
LM_ERR("realloc failed: not enough memory\n");

@ -235,7 +235,6 @@ int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const s
char nodename[MAXNODELEN];
int result;
int port;
/* copy the nodename into something we can modify */
if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) {
@ -256,8 +255,6 @@ int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const s
return -1;
}
port = sockaddr_port(addr);
LM_DBG("initialized ec for cnode '%s' on %.*s[%s] creation %d.\n", nodename, STR_FMT(hostname), ip_addr2strz(&ip), creation);
freeaddrinfo(ai);
@ -307,9 +304,9 @@ int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const
sockaddr2ip_addr(&ip, addr);
/* publish */
if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) == -1) {
if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) < 0) {
LM_ERR("Failed to publish port %u to epmd, check is epmd started\n", port);
LM_DBG("Failed publish %s:%u[%u] as %s: %s (%d)\n",ip_addr2strz(&ip),port,listen_fd,nodename, strerror(erl_errno), epmdfd);
erl_close_socket(listen_fd);
return -1;

@ -141,6 +141,7 @@ do { \
ei_s_print_term(&pbuf, pidbuf.buff, &i); \
ei_x_print_reg_msg(buf, pbuf, send); \
free(pbuf); \
ei_x_free(&pidbuf); \
} while(0)
int ei_decode_strorbin(char *buf, int *index, int maxlen, char *dst);

@ -22,6 +22,7 @@
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ei.h>
@ -43,7 +44,7 @@ int handle_req_ref_tuple(cnode_handler_t *phandler, erlang_msg * msg);
int handle_rpc_response(cnode_handler_t *phandler, erlang_msg * msg, int arity);
int handle_rex_call(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid);
int handle_net_kernel(cnode_handler_t *phandler, erlang_msg * msg);
void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg );
void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg, ...);
int handle_reg_send(cnode_handler_t *phandler, erlang_msg * msg)
{
@ -414,6 +415,36 @@ int handle_net_kernel(cnode_handler_t *phandler, erlang_msg * msg)
int erlang_whereis(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *pid)
{
ei_x_buff *response = &phandler->response;
ei_x_buff *request = &phandler->request;
char route[sizeof("erlang:")+MAXATOMLEN] = "erlang:";
int arity;
int type;
int rt;
ei_decode_list_header(request->buff,&request->index,&arity);
if (arity != 1) {
response->index = 1;
encode_error_msg(response, ref, "badarith", "undefined function erlang:whereis/%d",arity);
return 0;
}
ei_get_type(request->buff,&request->index,&type,&arity);
if (type != ERL_ATOM_EXT) {
response->index = 1;
encode_error_msg(response, ref, "badarg", "bad argument");
return 0;
}
ei_decode_atom(request->buff,&request->index,route+sizeof("erlang:")-1);
rt = route_get(&event_rt, route);
if (rt < 0 || event_rt.rlist[rt] == NULL) {
LM_WARN("can't find pseudo process %s\n", route);
ei_x_encode_atom(response,"undefined");
return 0;
}
ei_x_encode_pid(response,&phandler->ec.self);
@ -429,6 +460,7 @@ static int handle_erlang_calls(cnode_handler_t *phandler,erlang_ref_ex_t *ref, e
return erlang_whereis(phandler,ref,pid);
}
else {
response->index = 1;
encode_error_msg(response, ref, "badrpc", "Method Not Found");
}
@ -571,7 +603,9 @@ int handle_rex_call(cnode_handler_t *phandler,erlang_ref_ex_t *ref, erlang_pid *
ctx.size = arity;
/* call rpc */
rex_call_in_progress = 1;
exp->function(&erl_rpc_func_param,(void*)&ctx);
rex_call_in_progress = 0;
if (ctx.no_params)
{
@ -813,23 +847,27 @@ int handle_erlang_msg(cnode_handler_t *phandler, erlang_msg * msg)
LM_ERR("ei_send failed on node=<%s> socket=<%d>, %s\n",
phandler->ec.thisnodename,phandler->sockfd, strerror(erl_errno));
}
/* reset pid */
cnode_reply_to_pid = NULL;
return ret;
}
else
{
LM_DBG("** no reply **\n");
/* reset pid */
cnode_reply_to_pid = NULL;
return 0;
}
/* reset pid */
cnode_reply_to_pid = NULL;
return 0;
}
void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg )
void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *type, const char *msg, ... )
{
char buffer[256];
va_list args;
va_start (args, msg);
vsnprintf (buffer, 255, msg, args);
va_end (args);
ei_x_encode_tuple_header(response, 2);
if (ref->with_node)
@ -844,5 +882,5 @@ void encode_error_msg(ei_x_buff *response, erlang_ref_ex_t *ref, const char *typ
ei_x_encode_tuple_header(response,2);
ei_x_encode_atom(response, type);
ei_x_encode_string(response, msg);
ei_x_encode_string(response, buffer);
}

@ -27,6 +27,8 @@
#include "erl_helpers.h"
#include "cnode.h"
extern int rex_in_progress;
int handle_erlang_msg(cnode_handler_t *handler, erlang_msg * msg);
#endif /* HANDLE_EMSG_H_ */

@ -72,6 +72,11 @@ static int fixup_send(void** param, int param_no);
static int fixup_reg(void** param, int param_no);
static int fixup_reply(void** param, int param_no);
int fixup_free_rpc(void** param, int param_no);
int fixup_free_reg(void** param, int param_no);
int fixup_free_send(void** param, int param_no);
int fixup_free_reply(void** param, int param_no);
/* initialize common vars */
str cookie = STR_NULL;
int trace_level = 0;
@ -83,6 +88,8 @@ int rpc_reply_with_struct = 0;
str erlang_nodename = STR_NULL;
str erlang_node_sname = STR_NULL;
int rex_call_in_progress = 0;
int *usocks[2];
int csockfd;
@ -176,10 +183,10 @@ static param_export_t parameters[] =
static cmd_export_t commands[] =
{
{"erl_rpc", (cmd_function)erl_rpc, 4, fixup_rpc, 0, ANY_ROUTE},
{"erl_send", (cmd_function)erl_send_k, 2, fixup_send, 0, ANY_ROUTE},
{"erl_reg_send", (cmd_function)erl_reg_send_k, 2, fixup_reg, 0, ANY_ROUTE},
{"erl_reply", (cmd_function)erl_reply_k, 1, fixup_reply, 0, EVENT_ROUTE},
{"erl_rpc", (cmd_function)erl_rpc, 4, fixup_rpc, fixup_free_rpc, ANY_ROUTE},
{"erl_send", (cmd_function)erl_send_k, 2, fixup_send, fixup_free_send, ANY_ROUTE},
{"erl_reg_send", (cmd_function)erl_reg_send_k, 2, fixup_reg, fixup_free_reg, ANY_ROUTE},
{"erl_reply", (cmd_function)erl_reply_k, 1, fixup_reply, fixup_free_reply, EVENT_ROUTE},
{"load_erl",(cmd_function)load_erl,0, 0, 0, 0}, /* API loader */
{ 0, 0, 0, 0, 0, 0 }
};
@ -434,7 +441,7 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
sr_xavp_t *xreq=NULL;
sr_xavp_t *xrepl=NULL;
pv_spec_t sp;
pv_spec_t *nsp = NULL;
pv_spec_t *nsp;
pv_param_t pvp;
pv_name_t *pvn;
pv_index_t *pvi;
@ -446,7 +453,7 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
switch (m->type) {
case ERL_PARAM_FPARAM:
if(get_str_fparam(&module,msg,&m->value.fp)) {
if(get_str_fparam(&module,msg,m->value.fp)) {
LM_ERR("can't get module name\n");
}
break;
@ -457,7 +464,7 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
switch (f->type) {
case ERL_PARAM_FPARAM:
if(get_str_fparam(&function,msg,&f->value.fp)) {
if(get_str_fparam(&function,msg,f->value.fp)) {
LM_ERR("can't get function name\n");
}
break;
@ -468,7 +475,7 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
switch(a->type){
case ERL_PARAM_FPARAM:
if(get_str_fparam(&vname,msg,&a->value.fp)){
if(get_str_fparam(&vname,msg,a->value.fp)){
LM_ERR("can't get name of arguments parameter\n");
return -1;
}
@ -482,13 +489,8 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
}
break;
case ERL_PARAM_XBUFF_SPEC:
sp = a->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of list\n");
return -1;
}
nsp = NULL;
pvp = a->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -497,9 +499,11 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = a->value.sp;
}
if (sp.setf == pv_list_set ) {
@ -512,7 +516,6 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
/* fix index */
attr = xbuff_get_attr_flags(pvi->type);
pvi->type = xbuff_fix_index(pvi->type);
/* get the index */
if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
@ -553,20 +556,15 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
switch(r->type){
case ERL_PARAM_FPARAM:
if(get_str_fparam(&vname,msg,&r->value.fp)){
if(get_str_fparam(&vname,msg,r->value.fp)){
LM_ERR("can't get name of arguments parameter\n");
return -1;
}
xrepl = pv_xbuff_get_xbuff(&vname);
break;
case ERL_PARAM_XBUFF_SPEC:
sp = r->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of xbuff\n");
return -1;
}
nsp = NULL;
pvp = r->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -575,9 +573,11 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = a->value.sp;
}
if (sp.setf == pv_xbuff_set ) {
@ -589,7 +589,6 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
/* fix index */
attr = xbuff_get_attr_flags(pvi->type);
pvi->type = xbuff_fix_index(pvi->type);
/* get the index */
if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
@ -653,6 +652,7 @@ static int erl_rpc(struct sip_msg *msg, char *_m, char *_f, char *_a, char *_r)
static int fixup_rpc(void** param, int param_no)
{
erl_param_t *erl_param;
pv_spec_p psp;
str s;
@ -669,7 +669,7 @@ static int fixup_rpc(void** param, int param_no)
return -1;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
erl_param->value.fp = (fparam_t*)*param;
}
if (param_no==3 || param_no==4) {
@ -689,22 +689,19 @@ static int fixup_rpc(void** param, int param_no)
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL || erl_param->value.sp.type!=PVT_OTHER) {
/* only XBUFF is accepted for args and reply */
LM_ERR("wrong parameter #%d: accepted types are list of xbuff\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
erl_param->value.fp = (fparam_t*)*param;
} else {
/* lets check what is acceptable */
if (erl_param->value.sp.setf != pv_list_set && erl_param->value.sp.setf != pv_xbuff_set) {
LM_ERR("wrong parameter #%d: accepted types are list of xbuff\n",param_no);
psp = (pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname;
if (psp->setf != pv_list_set && psp->setf != pv_xbuff_set) {
LM_ERR("wrong parameter #%d: accepted types are list or xbuff\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_XBUFF_SPEC;
LM_ERR("erl_param->value.sp.type=%d\n",erl_param->value.sp.type);
}
}
@ -713,6 +710,28 @@ static int fixup_rpc(void** param, int param_no)
return 0;
}
int fixup_free_rpc(void** param, int param_no) {
erl_param_t *erl_param;
erl_param = (erl_param_t*)*param;
if(param_no==1 || param_no==2) {
return fixup_free_fparam_2((void**)&erl_param->value.fp,param_no);
}
if (param_no==3 || param_no==4) {
LM_ERR("erl_param->value.sp.type=%d\n",erl_param->value.sp.type);
if (erl_param->value.sp.type == PVT_OTHER) {
pv_spec_free((pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname);
} else if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
return fixup_free_fparam_2((void**)&erl_param->value.fp,param_no);
}
}
return 0;
}
static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
{
erl_param_t *param_server=(erl_param_t*)_server;
@ -733,7 +752,7 @@ static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
switch (param_server->type) {
case ERL_PARAM_FPARAM:
if(get_str_fparam(&server,msg,&param_server->value.fp)) {
if(get_str_fparam(&server,msg,param_server->value.fp)) {
LM_ERR("can't get server process name\n");
}
break;
@ -746,7 +765,7 @@ static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
switch(param_emsg->type){
case ERL_PARAM_FPARAM:
if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
if(get_str_fparam(&str_msg,msg,param_emsg->value.fp)){
LM_ERR("can't get emsg parameter\n");
goto err;
}
@ -755,13 +774,7 @@ static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
break;
case ERL_PARAM_XBUFF_SPEC:
sp = param_emsg->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of list\n");
return -1;
}
pvp = param_emsg->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -770,9 +783,11 @@ static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = param_emsg->value.sp;
}
if (sp.setf == pv_list_set ) {
@ -785,7 +800,6 @@ static int erl_reg_send_k(struct sip_msg *msg, char *_server, char *_emsg)
/* fix index */
attr = xbuff_get_attr_flags(pvi->type);
pvi->type = xbuff_fix_index(pvi->type);
/* get the index */
if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
@ -843,6 +857,7 @@ err:
static int fixup_reg(void** param, int param_no)
{
erl_param_t *erl_param;
pv_spec_p psp;
str s;
@ -861,7 +876,7 @@ static int fixup_reg(void** param, int param_no)
return -1;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
erl_param->value.fp = (fparam_t*)*param;
}
if (param_no==2) {
@ -881,30 +896,27 @@ static int fixup_reg(void** param, int param_no)
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
/* only XBUFF is accepted for emsg and reply */
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
erl_param->value.fp = (fparam_t*)*param;
} else {
if (erl_param->value.sp.type ==PVT_XAVP) {
if (erl_param->value.sp.type == PVT_XAVP) {
LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
if (erl_param->value.sp.setf == pv_list_set
|| erl_param->value.sp.setf == pv_xbuff_set
|| erl_param->value.sp.setf == pv_tuple_set
|| erl_param->value.sp.setf == pv_atom_set) {
psp = (pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname;
if (psp->setf == pv_list_set
|| psp->setf == pv_xbuff_set
|| psp->setf == pv_tuple_set
|| psp->setf == pv_atom_set) {
erl_param->type = ERL_PARAM_XBUFF_SPEC;
} else {
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
}
}
@ -914,6 +926,28 @@ static int fixup_reg(void** param, int param_no)
return 0;
}
int fixup_free_reg(void** param, int param_no) {
erl_param_t *erl_param;
erl_param = (erl_param_t*)*param;
if(param_no==1) {
return fixup_free_fparam_1((void**)&erl_param->value.fp,param_no);
}
if (param_no==2) {
LM_ERR("erl_param->value.sp.type=%d\n",erl_param->value.sp.type);
if (erl_param->value.sp.type == PVT_OTHER) {
pv_spec_free((pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname);
} else if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
return fixup_free_fparam_2((void**)&erl_param->value.fp,param_no);
}
}
return 0;
}
static int erl_reply_k(struct sip_msg *msg, char *_emsg)
{
erl_param_t *param_emsg=(erl_param_t*)_emsg;
@ -934,7 +968,7 @@ static int erl_reply_k(struct sip_msg *msg, char *_emsg)
switch(param_emsg->type){
case ERL_PARAM_FPARAM:
if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
if(get_str_fparam(&str_msg,msg,param_emsg->value.fp)){
LM_ERR("can't get emsg parameter\n");
goto err;
}
@ -943,13 +977,7 @@ static int erl_reply_k(struct sip_msg *msg, char *_emsg)
break;
case ERL_PARAM_XBUFF_SPEC:
sp = param_emsg->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of list\n");
return -1;
}
pvp = param_emsg->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -958,9 +986,11 @@ static int erl_reply_k(struct sip_msg *msg, char *_emsg)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = param_emsg->value.sp;
}
if (sp.setf == pv_list_set ) {
@ -1031,6 +1061,7 @@ err:
static int fixup_reply(void** param, int param_no)
{
erl_param_t *erl_param;
pv_spec_p psp;
str s;
@ -1060,14 +1091,7 @@ static int fixup_reply(void** param, int param_no)
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
/* only XBUFF is accepted for emsg and reply */
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
erl_param->value.fp = (fparam_t*)*param;
} else {
if (erl_param->value.sp.type ==PVT_XAVP) {
LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
@ -1075,15 +1099,19 @@ static int fixup_reply(void** param, int param_no)
return E_UNSPEC;
}
if (erl_param->value.sp.setf == pv_list_set
|| erl_param->value.sp.setf == pv_xbuff_set
|| erl_param->value.sp.setf == pv_tuple_set
|| erl_param->value.sp.setf == pv_atom_set) {
psp = (pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname;
if (psp->setf == pv_list_set
|| psp->setf == pv_xbuff_set
|| psp->setf == pv_tuple_set
|| psp->setf == pv_atom_set) {
erl_param->type = ERL_PARAM_XBUFF_SPEC;
} else {
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
}
}
@ -1093,6 +1121,24 @@ static int fixup_reply(void** param, int param_no)
return 0;
}
int fixup_free_reply(void** param, int param_no) {
erl_param_t *erl_param;
erl_param = (erl_param_t*)*param;
if (param_no==1) {
LM_ERR("erl_param->value.sp.type=%d\n",erl_param->value.sp.type);
if (erl_param->value.sp.type == PVT_OTHER) {
pv_spec_free((pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname);
} else if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
return fixup_free_fparam_2((void**)&erl_param->value.fp,param_no);
}
}
return 0;
}
static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
{
erl_param_t *param_pid=(erl_param_t*)_pid;
@ -1101,7 +1147,7 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
str str_msg;
sr_xavp_t *xmsg=NULL;
pv_spec_t sp;
pv_spec_t *nsp = NULL;
pv_spec_t *nsp;
pv_param_t pvp;
pv_name_t *pvn;
pv_index_t *pvi;
@ -1113,13 +1159,8 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
switch (param_pid->type) {
case ERL_PARAM_XBUFF_SPEC:
sp = param_pid->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of pid\n");
return -1;
}
nsp = NULL;
pvp = param_pid->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -1128,9 +1169,11 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = param_pid->value.sp;
}
if (sp.getf == pv_pid_get ) {
@ -1144,7 +1187,6 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
/* fix index */
attr = xbuff_get_attr_flags(pvi->type);
pvi->type = xbuff_fix_index(pvi->type);
/* get the index */
if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
@ -1190,7 +1232,7 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
switch(param_emsg->type){
case ERL_PARAM_FPARAM:
if(get_str_fparam(&str_msg,msg,&param_emsg->value.fp)){
if(get_str_fparam(&str_msg,msg,param_emsg->value.fp)){
LM_ERR("can't get emsg parameter\n");
goto err;
}
@ -1199,13 +1241,8 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
break;
case ERL_PARAM_XBUFF_SPEC:
sp = param_emsg->value.sp;
pvp = sp.pvp; /* work on copy */
if (pvp.pvn.type != PV_NAME_INTSTR || !(pvp.pvn.u.isname.type & AVP_NAME_STR)) {
LM_ERR("unsupported name of list\n");
return -1;
}
nsp = NULL;
pvp = param_emsg->value.sp.pvp; /* work on copy */
if( pvp.pvn.type == PV_NAME_PVAR) {
nsp = pvp.pvn.u.dname;
@ -1214,9 +1251,11 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
if (nsp) {
pvi = &nsp->pvp.pvi;
pvn = &nsp->pvp.pvn;
sp = *nsp;
} else {
pvi = &pvp.pvi;
pvn = &pvp.pvn;
sp = param_emsg->value.sp;
}
if (sp.getf == pv_list_get ) {
@ -1233,7 +1272,6 @@ static int erl_send_k(struct sip_msg *msg, char *_pid, char *_emsg)
/* fix index */
attr = xbuff_get_attr_flags(pvi->type);
pvi->type = xbuff_fix_index(pvi->type);
/* get the index */
if(pv_get_spec_index(msg, &pvp, &idx, &idxf))
@ -1291,6 +1329,7 @@ err:
static int fixup_send(void** param, int param_no)
{
erl_param_t *erl_param;
pv_spec_p psp;
str s;
@ -1320,27 +1359,24 @@ static int fixup_send(void** param, int param_no)
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
/* only XBUFF is accepted for emsg */
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
} else {
if (erl_param->value.sp.type ==PVT_XAVP) {
erl_param->value.fp = (fparam_t*)*param;
}
else {
if (erl_param->value.sp.type == PVT_XAVP) {
LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
if (erl_param->value.sp.getf == pv_pid_get
|| erl_param->value.sp.getf == pv_xbuff_get) {
psp = (pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname;
if (psp->getf == pv_pid_get || psp->getf == pv_xbuff_get) {
erl_param->type = ERL_PARAM_XBUFF_SPEC;
} else {
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
}
}
@ -1362,14 +1398,7 @@ static int fixup_send(void** param, int param_no)
return E_UNSPEC;
}
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
} else if(pv_parse_spec( &s, &erl_param->value.sp)==NULL) {
/* only XBUFF is accepted for emsg */
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
erl_param->value.fp = (fparam_t*)*param;
} else {
if (erl_param->value.sp.type ==PVT_XAVP) {
LM_ERR("XAVP not acceptable for parameter #%d\n",param_no);
@ -1377,16 +1406,20 @@ static int fixup_send(void** param, int param_no)
return E_UNSPEC;
}
if (erl_param->value.sp.getf == pv_list_get
|| erl_param->value.sp.getf == pv_xbuff_get
|| erl_param->value.sp.getf == pv_tuple_get
|| erl_param->value.sp.getf == pv_atom_get
|| erl_param->value.sp.getf == pv_pid_get) {
psp = (pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname;
if (psp->getf == pv_list_get
|| psp->getf == pv_xbuff_get
|| psp->getf == pv_tuple_get
|| psp->getf == pv_atom_get
|| psp->getf == pv_pid_get) {
erl_param->type = ERL_PARAM_XBUFF_SPEC;
} else {
erl_param->type = ERL_PARAM_FPARAM;
erl_param->value.fp = *(fparam_t*)*param;
LM_ERR("wrong parameter #%d\n",param_no);
pv_spec_free(&erl_param->value.sp);
pkg_free((void*)erl_param);
return E_UNSPEC;
}
}
}
@ -1395,3 +1428,20 @@ static int fixup_send(void** param, int param_no)
return 0;
}
int fixup_free_send(void** param, int param_no) {
erl_param_t *erl_param;
erl_param = (erl_param_t*)*param;
if (param_no==1 || param_no==2) {
if (erl_param->value.sp.type == PVT_OTHER) {
pv_spec_free((pv_spec_p)erl_param->value.sp.pvp.pvn.u.dname);
} else if (erl_param->value.sp.pvp.pvn.type == PV_NAME_INTSTR) {
return fixup_free_fparam_2((void**)&erl_param->value.fp,param_no);
}
}
return 0;
}

@ -39,6 +39,8 @@ extern int rpc_reply_with_struct;
extern str erlang_nodename;
extern str erlang_node_sname;
extern int rex_call_in_progress;
/* sockets kamailio <-> cnode */
extern int *usocks[2];
@ -63,7 +65,7 @@ typedef enum {
typedef struct erl_param_s {
erl_param_type type;
union {
fparam_t fp;
fparam_t *fp;
pv_spec_t sp;
} value;
} erl_param_t;

@ -44,6 +44,7 @@ int worker_init(worker_handler_t *phandler, int fd, const ei_cnode *ec)
phandler->sockfd = fd;
phandler->ec = *ec;
phandler->next = NULL;
phandler->new = NULL;
return 0;
}

@ -10,7 +10,7 @@ Daniel-Constantin Mierla
<miconda@gmail.com>
Copyright © 2014 asipto.com
Copyright © 2014 asipto.com
__________________________________________________________________
Table of Contents
@ -109,7 +109,7 @@ Chapter 1. Admin Guide
The following libraries or applications must be installed before
running Kamailio with this module loaded:
* libev - http://software.schmorp.de/pkg/libev
* libev - http://software.schmorp.de/pkg/libev.html
3. Parameters
@ -158,7 +158,7 @@ modparam("evapi", "netstring_format", 0)
4.2. evapi_async_relay(evdata)
4.3. evapi_close()
4.1. evapi_relay(evdata)
4.1. evapi_relay(evdata)
Relay the event data given as parameter to connected applications.
@ -188,7 +188,7 @@ evapi_relay("{ \"event\": \"test\",\n \"data\": { \"fU\": \"$fU\" }\n}");
},
...
4.2. evapi_async_relay(evdata)
4.2. evapi_async_relay(evdata)
Relay the event data given as parameter to connected applications.
Before evaluating the parameter, the request processing is suspended
@ -210,7 +210,7 @@ evapi_async_relay("{ \"event\": \"suspend\",\n \"data\":"
" { \"index\": \"$T(id_index)\", \"label\": \"$T(id_label)\" }\n}");
...
4.3. evapi_close()
4.3. evapi_close()
Close evapi current client connection.
@ -232,7 +232,7 @@ event_route[evapi:connection-new] {
5.2. evapi:connection-closed
5.3. evapi:message-received
5.1. evapi:connection-new
5.1. evapi:connection-new
If defined, the module calls event_route[evapi:connection-new] when a
new client is connected.
@ -242,7 +242,7 @@ event_route[evapi:connection-new] {
}
...
5.2. evapi:connection-closed
5.2. evapi:connection-closed
If defined, the module calls event_route[evapi:connection-closed] when
a client connection is closed.
@ -252,7 +252,7 @@ event_route[evapi:connection-closed] {
}
...
5.3. evapi:message-received
5.3. evapi:message-received
If defined, the module calls event_route[evapi:message-received] when a
message is received from a client.

@ -54,7 +54,7 @@
<itemizedlist>
<listitem>
<para>
<emphasis>libev</emphasis> - <ulink url="http://software.schmorp.de/pkg/libev">http://software.schmorp.de/pkg/libev</ulink>
<emphasis>libev</emphasis> - <ulink url="http://software.schmorp.de/pkg/libev.html">http://software.schmorp.de/pkg/libev.html</ulink>
</para>
</listitem>
</itemizedlist>

@ -778,7 +778,8 @@ sht_iterator_end("i1");
* $shtcn(htable=>key)
* $shtcv(htable=>key)
* $shtinc(htable=>key)
* $shtval(htable=>key)
* $shtitkey(iname)
* $shtitval(iname)
* $shtrecord(attribute)
Exported pseudo-variables are documented at

@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

@ -913,7 +913,10 @@ sht_iterator_end("i1");
<emphasis>$shtinc(htable=>key)</emphasis>
</para></listitem>
<listitem><para>
<emphasis>$shtval(htable=>key)</emphasis>
<emphasis>$shtitkey(iname)</emphasis>
</para></listitem>
<listitem><para>
<emphasis>$shtitval(iname)</emphasis>
</para></listitem>
<listitem><para>
<emphasis>$shtrecord(attribute)</emphasis>

@ -240,7 +240,7 @@ ht_t* ht_get_table(str *name)
ht = _ht_root;
while(ht!=NULL)
{
if(htid == ht->htid && name->len==ht->name.len
if(htid == ht->htid && name->len==ht->name.len
&& strncmp(name->s, ht->name.s, name->len)==0)
{
LM_DBG("htable found [%.*s]\n", name->len, name->s);
@ -266,7 +266,7 @@ int ht_add_table(str *name, int autoexp, str *dbtable, str *dbcols, int size,
ht = _ht_root;
while(ht!=NULL)
{
if(htid == ht->htid && name->len==ht->name.len
if(htid == ht->htid && name->len==ht->name.len
&& strncmp(name->s, ht->name.s, name->len)==0)
{
LM_ERR("htable already configured [%.*s]\n", name->len, name->s);
@ -461,7 +461,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
return -1;
hid = ht_compute_hash(name);
idx = ht_get_entry(hid, ht->htsize);
now = 0;
@ -477,7 +477,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
}
while(it!=NULL && it->cellid == hid)
{
if(name->len==it->name.len
if(name->len==it->name.len
&& strncmp(name->s, it->name.s, name->len)==0)
{
/* update value */
@ -491,7 +491,7 @@ int ht_set_cell(ht_t *ht, str *name, int type, int_str *val, int mode)
it->value.s.len = val->s.len;
memcpy(it->value.s.s, val->s.s, val->s.len);
it->value.s.s[it->value.s.len] = '\0';
if(ht->updateexpire)
it->expire = now + ht->htexpire;
} else {
@ -602,20 +602,20 @@ int ht_del_cell(ht_t *ht, str *name)
return -1;
hid = ht_compute_hash(name);
idx = ht_get_entry(hid, ht->htsize);
/* head test and return */
if(ht->entries[idx].first==NULL)
return 0;
ht_slot_lock(ht, idx);
it = ht->entries[idx].first;
while(it!=NULL && it->cellid < hid)
it = it->next;
while(it!=NULL && it->cellid == hid)
{
if(name->len==it->name.len
if(name->len==it->name.len
&& strncmp(name->s, it->name.s, name->len)==0)
{
/* found */
@ -781,20 +781,20 @@ ht_cell_t* ht_cell_pkg_copy(ht_t *ht, str *name, ht_cell_t *old)
return NULL;
hid = ht_compute_hash(name);
idx = ht_get_entry(hid, ht->htsize);
/* head test and return */
if(ht->entries[idx].first==NULL)
return NULL;
ht_slot_lock(ht, idx);
it = ht->entries[idx].first;
while(it!=NULL && it->cellid < hid)
it = it->next;
while(it!=NULL && it->cellid == hid)
{
if(name->len==it->name.len
if(name->len==it->name.len
&& strncmp(name->s, it->name.s, name->len)==0)
{
/* found */
@ -938,12 +938,12 @@ int ht_table_spec(char *spec)
if(str2int(&tok, &updateexpire) != 0)
goto error;
LM_DBG("htable [%.*s] - updateexpire [%u]\n", name.len, name.s, updateexpire);
LM_DBG("htable [%.*s] - updateexpire [%u]\n", name.len, name.s, updateexpire);
} else if(pit->name.len == 12 && strncmp(pit->name.s, "dmqreplicate", 12) == 0) {
if(str2int(&tok, &dmqreplicate) != 0)
goto error;
LM_DBG("htable [%.*s] - dmqreplicate [%u]\n", name.len, name.s, dmqreplicate);
LM_DBG("htable [%.*s] - dmqreplicate [%u]\n", name.len, name.s, dmqreplicate);
} else { goto error; }
}
@ -1129,7 +1129,7 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
return 0;
hid = ht_compute_hash(name);
idx = ht_get_entry(hid, ht->htsize);
now = 0;
@ -1144,7 +1144,7 @@ int ht_set_cell_expire(ht_t *ht, str *name, int type, int_str *val)
it = it->next;
while(it!=NULL && it->cellid == hid)
{
if(name->len==it->name.len
if(name->len==it->name.len
&& strncmp(name->s, it->name.s, name->len)==0)
{
/* update value */
@ -1174,7 +1174,7 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
return 0;
hid = ht_compute_hash(name);
idx = ht_get_entry(hid, ht->htsize);
now = time(NULL);
@ -1184,7 +1184,7 @@ int ht_get_cell_expire(ht_t *ht, str *name, unsigned int *val)
it = it->next;
while(it!=NULL && it->cellid == hid)
{
if(name->len==it->name.len
if(name->len==it->name.len
&& strncmp(name->s, it->name.s, name->len)==0)
{
/* update value */
@ -1410,18 +1410,18 @@ int ht_count_cells_re(str *sre, ht_t *ht, int mode)
cnt++;
break;
case 2: /* rlike */
if(sval.len<=tval.len
if(sval.len<=tval.len
&& strncmp(sval.s,
tval.s+tval.len-sval.len, sval.len)==0)
cnt++;
break;
case 3: /* llike */
if(sval.len<=tval.len
if(sval.len<=tval.len
&& strncmp(sval.s, tval.s, sval.len)==0)
cnt++;
break;
case 4: /* str eq */
if(sval.len==tval.len
if(sval.len==tval.len
&& strncmp(sval.s, tval.s, sval.len)==0)
cnt++;
break;

@ -74,7 +74,7 @@ int ht_db_init_con(void)
if (!DB_CAPABILITY(ht_dbf, DB_CAP_ALL))
{
LM_ERR("database module does not "
"implement all functions needed by the module\n");
"implement all functions needed by the module\n");
return -1;
}
return 0;
@ -89,10 +89,10 @@ int ht_db_open_con(void)
ht_db_con = ht_dbf.init(&ht_db_url);
if(ht_db_con==NULL)
{
LM_ERR("failed to connect to the database\n");
LM_ERR("failed to connect to the database\n");
return -1;
}
LM_DBG("database connection opened successfully\n");
return 0;
}
@ -435,7 +435,7 @@ int ht_db_load_table(ht_t *ht, str *dbtable, int mode)
goto error;
}
}
if(ht_set_cell(ht, &hname, (vtype)?0:AVP_VAL_STR, &val, mode))
{
LM_ERR("error adding to hash table\n");
@ -451,7 +451,7 @@ int ht_db_load_table(ht_t *ht, str *dbtable, int mode)
}
}
}
}
}
if (DB_CAPABILITY(ht_dbf, DB_CAP_FETCH)) {
if(ht_dbf.fetch_result(ht_db_con, &db_res, ht_fetch_rows)<0) {
LM_ERR("Error while fetching!\n");

@ -1,5 +1,5 @@
/**
*
*
* Copyright (C) 2013 Charles Chance (Sipcentric Ltd)
*
* This file is part of Kamailio, a free SIP server.
@ -14,8 +14,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -50,13 +50,13 @@ int ht_dmq_initialize()
{
dmq_peer_t not_peer;
/* load the DMQ API */
if (dmq_load_api(&ht_dmqb)!=0) {
LM_ERR("cannot load dmq api\n");
return -1;
} else {
LM_DBG("loaded dmq api\n");
}
/* load the DMQ API */
if (dmq_load_api(&ht_dmqb)!=0) {
LM_ERR("cannot load dmq api\n");
return -1;
} else {
LM_DBG("loaded dmq api\n");
}
not_peer.callback = ht_dmq_handle_msg;
not_peer.init_callback = NULL;
@ -76,14 +76,15 @@ error:
return -1;
}
int ht_dmq_broadcast(str* body) {
if (!ht_dmq_peer) {
LM_ERR("ht_dmq_peer is null!\n");
return -1;
}
LM_DBG("sending broadcast...\n");
ht_dmqb.bcast_message(ht_dmq_peer, body, 0, &ht_dmq_resp_callback, 1, &ht_dmq_content_type);
return 0;
int ht_dmq_broadcast(str* body)
{
if (!ht_dmq_peer) {
LM_ERR("ht_dmq_peer is null!\n");
return -1;
}
LM_DBG("sending broadcast...\n");
ht_dmqb.bcast_message(ht_dmq_peer, body, 0, &ht_dmq_resp_callback, 1, &ht_dmq_content_type);
return 0;
}
/**
@ -102,7 +103,7 @@ int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq
/* received dmq message */
LM_DBG("dmq message received\n");
if(!msg->content_length) {
LM_ERR("no content length header found\n");
goto invalid;
@ -122,7 +123,7 @@ int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq
}
/* parse body */
LM_DBG("body: %.*s\n", body.len, body.s);
LM_DBG("body: %.*s\n", body.len, body.s);
srjson_InitDoc(&jdoc, NULL);
jdoc.buf = body;
@ -160,7 +161,7 @@ int ht_dmq_handle_msg(struct sip_msg* msg, peer_reponse_t* resp, dmq_node_t* dmq
LM_ERR("unrecognized field in json object\n");
goto invalid;
}
}
}
if (ht_dmq_replay_action(action, &htname, &cname, type, &val, mode)!=0) {
LM_ERR("failed to replay action\n");
@ -181,7 +182,7 @@ invalid:
error:
srjson_DestroyDoc(&jdoc);
resp->reason = dmq_500_rpl;
resp->resp_code = 500;
resp->resp_code = 500;
return 0;
}
@ -189,7 +190,7 @@ int ht_dmq_replicate_action(ht_dmq_action_t action, str* htname, str* cname, int
srjson_doc_t jdoc;
LM_DBG("replicating action to dmq peers...\n");
LM_DBG("replicating action to dmq peers...\n");
srjson_InitDoc(&jdoc, NULL);
@ -214,7 +215,7 @@ int ht_dmq_replicate_action(ht_dmq_action_t action, str* htname, str* cname, int
}
}
srjson_AddNumberToObject(&jdoc, jdoc.root, "mode", mode);
srjson_AddNumberToObject(&jdoc, jdoc.root, "mode", mode);
jdoc.buf.s = srjson_PrintUnformatted(&jdoc, jdoc.root);
if(jdoc.buf.s!=NULL) {
@ -251,7 +252,7 @@ int ht_dmq_replay_action(ht_dmq_action_t action, str* htname, str* cname, int ty
return -1;
}
LM_DBG("replaying action %d on %.*s=>%.*s...\n", action, htname->len, htname->s, cname->len, cname->s);
LM_DBG("replaying action %d on %.*s=>%.*s...\n", action, htname->len, htname->s, cname->len, cname->s);
if (action==HT_DMQ_SET_CELL) {
return ht_set_cell(ht, cname, type, val, mode);

@ -18,7 +18,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "ht_api.h"
#include "ht_var.h"
#include "ht_dmq.h"
@ -62,7 +62,7 @@ int pv_get_ht_cell(struct sip_msg *msg, pv_param_t *param,
if(htc->flags&AVP_VAL_STR)
return pv_get_strval(msg, param, res, &htc->value.s);
/* integer */
return pv_get_sintval(msg, param, res, htc->value.n);
}
@ -241,7 +241,7 @@ int pv_set_ht_cell_expire(struct sip_msg* msg, pv_param_t *param,
}
if (hpv->ht->dmqreplicate>0 && ht_dmq_replicate_action(HT_DMQ_SET_CELL_EXPIRE, &hpv->htname, &htname, 0, &isval, 0)!=0) {
LM_ERR("dmq relication failed\n");
}
}
if(ht_set_cell_expire(hpv->ht, &htname, 0, &isval)!=0)
{
LM_ERR("cannot set $sht(%.*s)\n", htname.len, htname.s);
@ -271,7 +271,7 @@ int pv_get_ht_cn(struct sip_msg *msg, pv_param_t *param,
LM_ERR("cannot get $sht name\n");
return -1;
}
cnt = ht_count_cells_re(&htname, hpv->ht, 0);
/* integer */
@ -298,7 +298,7 @@ int pv_get_ht_cv(struct sip_msg *msg, pv_param_t *param,
LM_ERR("cannot get $sht name\n");
return -1;
}
cnt = ht_count_cells_re(&htname, hpv->ht, 1);
/* integer */
@ -344,7 +344,7 @@ int pv_get_ht_add(struct sip_msg *msg, pv_param_t *param,
if (ht_dmq_replicate_action(HT_DMQ_SET_CELL, &hpv->htname, &htname, 0, &htc->value, 1)!=0) {
LM_ERR("dmq relication failed\n");
}
}
}
return pv_get_sintval(msg, param, res, htc->value.n);
}
@ -363,7 +363,7 @@ int pv_get_ht_dec(struct sip_msg *msg, pv_param_t *param,
int pv_parse_ht_expired_cell(pv_spec_t *sp, str *in)
{
if ((in->len != 3 || strncmp(in->s, "key", in->len) != 0) &&
(in->len != 5 || strncmp(in->s, "value", in->len) != 0))
(in->len != 5 || strncmp(in->s, "value", in->len) != 0))
{
return -1;
}

@ -13,8 +13,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@ -250,7 +250,7 @@ static int child_init(int rank)
if (rank!=PROC_INIT)
return 0;
rt = route_get(&event_rt, "htable:mod-init");
if(rt>=0 && event_rt.rlist[rt]!=NULL) {
LM_DBG("executing event_route[htable:mod-init] (%d)\n", rt);
@ -573,7 +573,7 @@ static struct mi_root* ht_mi_reload(struct mi_root* cmd_tree, void* param)
if(ht_db_url.len<=0)
return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
if(ht_db_init_con()!=0)
return init_mi_tree(500, MI_ERR_RELOAD, MI_ERR_RELOAD_LEN);
if(ht_db_open_con()!=0)
@ -884,7 +884,7 @@ static void htable_rpc_get(rpc_t* rpc, void* c) {
goto error;
}
}
error:
/* Release the allocated memory */
ht_cell_pkg_free(htc);
@ -910,7 +910,7 @@ static void htable_rpc_sets(rpc_t* rpc, void* c) {
rpc->fault(c, 500, "No such htable");
return;
}
if (ht->dmqreplicate>0 && ht_dmq_replicate_action(HT_DMQ_SET_CELL, &ht->name, &keyname, AVP_VAL_STR, &keyvalue, 1)!=0) {
LM_ERR("dmq relication failed\n");
}
@ -948,7 +948,7 @@ static void htable_rpc_seti(rpc_t* rpc, void* c) {
if (ht->dmqreplicate>0 && ht_dmq_replicate_action(HT_DMQ_SET_CELL, &ht->name, &keyname, 0, &keyvalue, 1)!=0) {
LM_ERR("dmq relication failed\n");
}
if(ht_set_cell(ht, &keyname, 0, &keyvalue, 1)!=0)
{
LM_ERR("cannot set $sht(%.*s=>%.*s)\n", htname.len, htname.s,

@ -171,6 +171,12 @@ Chapter 1. Admin Guide
and get access to parts of the reply. This function has been ported
from the utils module and now use the same libcurl functions.
The http_client module use the CURL library setting up connections. The
CURL library by default use the system configured DNS resolvers, not
the Kamailio resolver.
The module is limited to using HTTP and HTTPS protocols.
2. Dependencies
2.1. Kamailio Modules

@ -43,6 +43,14 @@
been ported from the utils module and now use the same libcurl
functions.
</para>
<para>
The http_client module use the CURL library setting up connections.
The CURL library by default use the system configured DNS resolvers,
not the Kamailio resolver.
</para>
<para>
The module is limited to using HTTP and HTTPS protocols.
</para>
</section>
<section>
<title>Dependencies</title>

@ -39,6 +39,8 @@ int json_get_field(struct sip_msg* msg, char* json, char* field, char* dst)
pv_value_t dst_val;
char *value;
struct json_object *j = NULL;
struct json_object *oj = NULL;
int ret;
if (fixup_get_svalue(msg, (gparam_p)json, &json_s) != 0) {
LM_ERR("cannot get json string value\n");
@ -61,13 +63,18 @@ int json_get_field(struct sip_msg* msg, char* json, char* field, char* dst)
return -1;
}
value = (char*)json_object_to_json_string(json_object_object_get(j, field_s.s));
dst_val.rs.s = value;
dst_val.rs.len = strlen(value);
dst_val.flags = PV_VAL_STR;
dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
json_object_object_get_ex(j, field_s.s, &oj);
if(oj!=NULL) {
value = (char*)json_object_to_json_string(oj);
dst_val.rs.s = value;
dst_val.rs.len = strlen(value);
dst_val.flags = PV_VAL_STR;
dst_pv->setf(msg, &dst_pv->pvp, (int)EQ_T, &dst_val);
ret = 1;
} else {
ret = -1;
}
if(j!=NULL) json_object_put(j);
return 1;
return ret;
}

@ -70,34 +70,38 @@ jsonrpc_request_t* build_jsonrpc_request(char *method, json_object *params, char
return req;
}
json_object* build_jsonrpc_notification(char *method, json_object *params)
json_object* build_jsonrpc_notification(char *method, json_object *params)
{
json_object *req = json_object_new_object();
json_object_object_add(req, "jsonrpc", json_object_new_string("2.0"));
json_object_object_add(req, "method", json_object_new_string(method));
json_object_object_add(req, "params", params);
return req;
return req;
}
int handle_jsonrpc_response(json_object *response)
{
jsonrpc_request_t *req;
json_object *_id = json_object_object_get(response, "id");
int id = json_object_get_int(_id);
jsonrpc_request_t *req;
json_object *_id = NULL;
int id = 0;
json_object *result = NULL;
json_object_object_get_ex(response, "id", &_id);
id = json_object_get_int(_id);
if (!(req = get_request(id))) {
json_object_put(response);
return -1;
}
json_object *result = json_object_object_get(response, "result");
json_object_object_get_ex(response, "result", &result);
if (result) {
req->cbfunc(result, req->cbdata, 0);
} else {
json_object *error = json_object_object_get(response, "error");
json_object *error = NULL;
json_object_object_get_ex(response, "error", &error);
if (error) {
req->cbfunc(error, req->cbdata, 1);
} else {
@ -105,7 +109,7 @@ int handle_jsonrpc_response(json_object *response)
return -1;
}
}
if (req->timer_ev) {
close(req->timerfd);
event_del(req->timer_ev);
@ -125,14 +129,14 @@ jsonrpc_request_t* get_request(int id) {
int key = id_hash(id);
jsonrpc_request_t *req, *prev_req = NULL;
req = request_table[key];
while (req && req->id != id) {
prev_req = req;
if (!(req = req->next)) {
break;
};
}
if (req && req->id == id) {
if (prev_req != NULL) {
prev_req-> next = req->next;

@ -10,7 +10,7 @@ Luis Azedo
<luis@2600hz.com>
Copyright © 2010, 2014 2600hz
Copyright © 2010, 2014 2600hz
__________________________________________________________________
Table of Contents
@ -51,13 +51,15 @@ Luis Azedo
4.3.1. amqp_consumer_ack_timeout(str)
4.3.2. amqp_interprocess_timeout(str)
4.3.3. amqp_waitframe_timout(str)
4.3.4. amqp_query_timout(str)
4.3.3. amqp_waitframe_tiemout(str)
4.3.4. amqp_query_timeout(str)
4.3.5. amqp_query_timeout_avp(str)
4.4. presence related
4.4.1. db_url(str)
4.4.2. presentity_table(str)
4.4.3. pua_mode(int)
5. Functions
@ -102,19 +104,21 @@ Luis Azedo
1.12. Set single_consumer_on_reconnect parameter
1.13. Set amqp_consumer_ack_timeout parameter
1.14. Set amqp_interprocess_timeout parameter
1.15. Set amqp_waitframe_timout parameter
1.16. Set amqp_query_timout parameter
1.17. Set db_url parameter
1.18. Set presentity_table parameter
1.19. kazoo_publish usage
1.20. kazoo_query usage
1.21. kazoo_subscribe usage
1.22. kazoo_subscribe usage
1.23. kazoo_pua_publish usage
1.24. kazoo_encode usage
1.25. kazoo_json usage
1.26. kz.json usage
1.27. kz.encode usage
1.15. Set amqp_waitframe_timeout parameter
1.16. Set amqp_query_timeout parameter
1.17. >Set amqp_query_timeout_avp parameter
1.18. Set db_url parameter
1.19. Set presentity_table parameter
1.20. Set pua_mode parameter
1.21. kazoo_publish usage
1.22. kazoo_query usage
1.23. kazoo_subscribe usage
1.24. kazoo_subscribe usage
1.25. kazoo_pua_publish usage
1.26. kazoo_encode usage
1.27. kazoo_json usage
1.28. kz.json usage
1.29. kz.encode usage
Chapter 1. Admin Guide
@ -154,13 +158,15 @@ Chapter 1. Admin Guide
4.3.1. amqp_consumer_ack_timeout(str)
4.3.2. amqp_interprocess_timeout(str)
4.3.3. amqp_waitframe_timout(str)
4.3.4. amqp_query_timout(str)
4.3.3. amqp_waitframe_tiemout(str)
4.3.4. amqp_query_timeout(str)
4.3.5. amqp_query_timeout_avp(str)
4.4. presence related
4.4.1. db_url(str)
4.4.2. presentity_table(str)
4.4.3. pua_mode(int)
5. Functions
@ -246,16 +252,16 @@ event_route[kazoo:consumer-event-presence-update]
{
# presence is the value extracted from Event-Category field in json payload
# update is the value extracted from Event-Name field in json payload
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json
,From})");
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,
From})");
...
}
event_route[kazoo:consumer-event-presence]
{
# presence is the value extracted from Event-Category field in json payload
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json
,From})");
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.json,
From})");
...
}
@ -324,13 +330,15 @@ event_route[kazoo:consumer-event]
4.3.1. amqp_consumer_ack_timeout(str)
4.3.2. amqp_interprocess_timeout(str)
4.3.3. amqp_waitframe_timout(str)
4.3.4. amqp_query_timout(str)
4.3.3. amqp_waitframe_tiemout(str)
4.3.4. amqp_query_timeout(str)
4.3.5. amqp_query_timeout_avp(str)
4.4. presence related
4.4.1. db_url(str)
4.4.2. presentity_table(str)
4.4.3. pua_mode(int)
4.1. amqp related
@ -362,7 +370,7 @@ modparam("kazoo", "amqp_consumer_processes", 10)
The default name of the field in json payload to compose the event name
1st part
Default value is “Event-Category”.
Default value is "Event-Category".
Example 1.4. Set amqp_consumer_event_key parameter
...
@ -374,7 +382,7 @@ modparam("kazoo", "amqp_consumer_event_key", "My-JSON-Field-Name")
The default name of the field in json payload to compose the event name
2nd part
Default value is “Event-Name”.
Default value is "Event-Name".
Example 1.5. Set amqp_consumer_event_subkey parameter
...
@ -510,29 +518,48 @@ modparam("kazoo", "amqp_interprocess_timeout_sec", 1)
modparam("kazoo", "amqp_interprocess_timeout_micro", 200000)
...
4.3.3. amqp_waitframe_timout(str)
4.3.3. amqp_waitframe_tiemout(str)
Timeout when checking for messages from rabbitmq.
Default value is 100000 micro.
Example 1.15. Set amqp_waitframe_timout parameter
Example 1.15. Set amqp_waitframe_timeout parameter
...
modparam("kazoo", "amqp_waitframe_timout_sec", 1)
modparam("kazoo", "amqp_waitframe_timout_micro", 200000)
modparam("kazoo", "amqp_waitframe_timeout_sec", 1)
modparam("kazoo", "amqp_waitframe_timeout_micro", 200000)
...
4.3.4. amqp_query_timout(str)
4.3.4. amqp_query_timeout(str)
Timeout when checking for reply messages from rabbitmq for kazoo_query
commands.
Default value is 2 sec.
Example 1.16. Set amqp_query_timout parameter
Example 1.16. Set amqp_query_timeout parameter
...
modparam("kazoo", "amqp_query_timout_sec", 1)
modparam("kazoo", "amqp_query_timout_micro", 200000)
modparam("kazoo", "amqp_query_timeout_sec", 1)
modparam("kazoo", "amqp_query_timeout_micro", 200000)
...
4.3.5. amqp_query_timeout_avp(str)
avp holding the value in seconds for Timeout when checking for reply
messages from rabbitmq for kazoo_query commands.
Default value is NULL (no value).
Example 1.17. >Set amqp_query_timeout_avp parameter
...
modparam("kazoo", "amqp_query_timeout_avp", "$var(kz_timeout)")
route[SOME_ROUTE]
{
$var(kz_timeout) = 12;
kazoo_query(exchange, routingkey, payload);
}
...
4.4. presence related
@ -544,9 +571,9 @@ modparam("kazoo", "amqp_query_timout_micro", 200000)
If set, the kazoo_ppua_publish function will update the presentity
status in the database.
Default value is “NULL”.
Default value is "NULL".
Example 1.17. Set db_url parameter
Example 1.18. Set db_url parameter
...
modparam("kazoo", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
...
@ -555,13 +582,25 @@ modparam("kazoo", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio")
The name of the presentity table in the database.
Default value is “presentity”.
Default value is "presentity".
Example 1.18. Set presentity_table parameter
Example 1.19. Set presentity_table parameter
...
modparam("kazoo", "presentity_table", "my_presentity_table")
...
4.4.3. pua_mode(int)
Control if the module has to connect to presence database tables. Set
it to 0 to not connect to database.
Default value is "1".
Example 1.20. Set pua_mode parameter
...
modparam("kazoo", "pua_mode", 0)
...
5. Functions
5.1. amqp related
@ -586,26 +625,25 @@ modparam("kazoo", "presentity_table", "my_presentity_table")
5.1. amqp related
5.1.1. kazoo_publish(exchange, routing_key, json_payload)
5.1.1. kazoo_publish(exchange, routing_key, json_payload)
The function publishes a json payload to rabbitmq. The routing_key
parameter should be encoded.
This function can be used from ANY ROUTE.
Example 1.19. kazoo_publish usage
Example 1.21. kazoo_publish usage
...
$var(amqp_payload_request) = "{'Event-Category' : 'directory', 'Event-Name' : '
reg_success', 'Contact' : '" + $var(fs_contact) + "', 'Call-ID' : '" + $ci + "'
, 'Realm' : '" + $fd +"', 'Username' : '" + $fU + "', 'From-User' : '" + $fU +
"', 'From-Host' : '" + $fd + "', 'To-User' : '" + $tU +"', 'To-Host' : '" + $td
+ "', 'User-Agent' : '" + $ua +"' ," + $var(register_contants)+ " }";
$var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $fU
;
$var(amqp_payload_request) = "{'Event-Category' : 'directory', 'Event-Name' : 'r
eg_success', 'Contact' : '" + $var(fs_contact) + "', 'Call-ID' : '" + $ci + "',
'Realm' : '" + $fd +"', 'Username' : '" + $fU + "', 'From-User' : '" + $fU + "',
'From-Host' : '" + $fd + "', 'To-User' : '" + $tU +"', 'To-Host' : '" + $td + "
', 'User-Agent' : '" + $ua +"' ," + $var(register_contants)+ " }";
$var(amqp_routing_key) = "registration.success." + $(fd{kz.encode}) + "." + $fU;
kazoo_publish("callmgr", $var(amqp_routing_key), $var(amqp_payload_request));
...
5.1.2. kazoo_query(exchange, routing_key, json_payload [, target_var])
5.1.2. kazoo_query(exchange, routing_key, json_payload [, target_var])
The function publishes a json payload to rabbitmq, waits for a
correlated messageand puts the result in target_var. The routing_key
@ -614,15 +652,15 @@ kazoo_publish("callmgr", $var(amqp_routing_key), $var(amqp_payload_request));
This function can be used from ANY ROUTE.
Example 1.20. kazoo_query usage
Example 1.22. kazoo_query usage
...
$var(amqp_payload_request) = "{'Event-Category' : 'call_event' , 'Event-Name' :
'query_user_channels_req', 'Realm' : '" + $fd + "', 'Username' : '" + $fU + "'
, 'Active-Only' : false }";
'query_user_channels_req', 'Realm' : '" + $fd + "', 'Username' : '" + $fU + "',
'Active-Only' : false }";
kazoo_encode("$ci", "$var(callid_encoded)");
$var(amqp_routing_key) = "call.status_req.$var(callid_encoded)";
if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request), "
$var(amqp_result)")) {
if(kazoo_query("callevt", $var(amqp_routing_key), $var(amqp_payload_request), "$
var(amqp_result)")) {
kazoo_json("$var(amqp_result)", "Channels[0].switch_url", "$du");
if($du != $null) {
xlog("L_INFO", "$ci|log|user channels found redirecting call to $du");
@ -631,19 +669,19 @@ $var(amqp_result)")) {
}
...
5.1.3. kazoo_subscribe(exchange, exchange_type, queue, routing_key)
5.1.3. kazoo_subscribe(exchange, exchange_type, queue, routing_key)
The function subscribes to exchange/type on queue with routing_key. The
routing_key parameter should be encoded.
This function must be called from event_route[kazoo:mod-init].
Example 1.21. kazoo_subscribe usage
Example 1.23. kazoo_subscribe usage
...
event_route[kazoo:mod-init]
{
kazoo_subscribe("dialoginfo", "direct", "BLF-QUEUE-MY_HOSTNAME", "BLF-MY_HOS
TNAME");
kazoo_subscribe("dialoginfo", "direct", "BLF-QUEUE-MY_HOSTNAME", "BLF-MY_HOST
NAME");
}
event_route[kazoo:consumer-event]
@ -652,7 +690,7 @@ event_route[kazoo:consumer-event]
}
...
5.1.4. kazoo_subscribe(json_description)
5.1.4. kazoo_subscribe(json_description)
The function takes additional parameters to the subscribe function.
@ -670,13 +708,13 @@ event_route[kazoo:consumer-event]
This function must be called from event_route[kazoo:mod-init].
Example 1.22. kazoo_subscribe usage
Example 1.24. kazoo_subscribe usage
...
event_route[kazoo:mod-init]
{
$var(payload) = "{ 'exchange' : 'dialoginfo' , 'type' : 'direct', 'queue' :
'BLF-QUEUE-MY_HOSTNAME', 'routing' : 'BLF-MY_HOSTNAME', 'auto_delete' : 0, 'du
rable' : 1, 'no_ack' : 0, 'wait_for_consumer_ack' : 1 }";
'BLF-QUEUE-MY_HOSTNAME', 'routing' : 'BLF-MY_HOSTNAME', 'auto_delete' : 0, 'dura
ble' : 1, 'no_ack' : 0, 'wait_for_consumer_ack' : 1 }";
kazoo_subscribe("$var(payload)");
}
@ -688,48 +726,48 @@ event_route[kazoo:consumer-event]
5.2. presence related
5.2.1. kazoo_pua_publish(json_payload)
5.2.1. kazoo_pua_publish(json_payload)
The function build presentity state from json_payload and updates
presentity table.
This function can be used from ANY ROUTE.
Example 1.23. kazoo_pua_publish usage
Example 1.25. kazoo_pua_publish usage
...
event_route[kazoo:consumer-event-presence-update]
{
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.
json,From})");
xlog("L_INFO", "received $(kzE{kz.json,Event-Package}) update for $(kzE{kz.j
son,From})");
kazoo_pua_publish($kzE);
pres_refresh_watchers("$(kzE{kz.json,From})", "$(kzE{kz.json,Event-Package}
)", 1);
pres_refresh_watchers("$(kzE{kz.json,From})", "$(kzE{kz.json,Event-Package})
", 1);
}
...
5.3. other
5.3.1. kazoo_encode(to_encode, target_var)
5.3.1. kazoo_encode(to_encode, target_var)
The function encodes the 1st parameter for amqp and puts the result in
the 2nd parameter.
This function can be used from ANY ROUTE.
Example 1.24. kazoo_encode usage
Example 1.26. kazoo_encode usage
...
kazoo_encode("$ci", "$var(callid_encoded)");
$var(amqp_routing_key) = "call.status_req.$var(callid_encoded)";
...
5.3.2. kazoo_json(json_payload, field, target_var)
5.3.2. kazoo_json(json_payload, field, target_var)
The function extracts the value from a json payload and puts the result
in the 3rd parameter. It can use nested values for the query part.
This function can be used from ANY ROUTE.
Example 1.25. kazoo_json usage
Example 1.27. kazoo_json usage
...
kazoo_json("$var(amqp_result)", "Channels[0].switch_url", "$du");
if($du != $null) {
@ -747,7 +785,7 @@ if($du != $null) {
The prefix for kazoo transformations is kz.
* json
Example 1.26. kz.json usage
Example 1.28. kz.json usage
...
#kazoo_json("$var(amqp_result)", "Channels[0].switch_url", "$du");
$du = $kzR{kz.json,Channels[0].switch_url};
@ -757,7 +795,7 @@ if($du != $null) {
}
...
* encode
Example 1.27. kz.encode usage
Example 1.29. kz.encode usage
...
#kazoo_encode("$ci", "$var(callid_encoded)");
#$var(amqp_routing_key) = "call.status_req.$var(callid_encoded)";

@ -556,7 +556,25 @@ modparam("kazoo", "presentity_table", "my_presentity_table")
</example>
</section>
<section id="kazoo.p.pua_mode">
<title><varname>pua_mode</varname>(int)</title>
<para>
Control if the module has to connect to presence database tables.
Set it to 0 to not connect to database.
</para>
<para>
<emphasis>Default value is <quote>1</quote>.</emphasis>
</para>
<example>
<title>Set <varname>pua_mode</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("kazoo", "pua_mode", 0)
...
</programlisting>
</example>
</section>
</section>

@ -149,9 +149,14 @@ Chapter 1. Admin Guide
2.2. External Libraries or Applications
The following libraries or applications must be installed before
compilling Kamailio with this module loaded:
* radiusclient-ng 0.5.6 or higher -- library and development files.
See http://developer.berlios.de/projects/radiusclient-ng/.
running Kamailio with this module loaded:
* radiusclient-ng 0.5.0 or higher, freeradius-client
https://github.com/FreeRADIUS/freeradius-client/ or radcli
http://radcli.github.io/radcli/.
* freeradius-client library can be used after setting FREERADIUS
variable in source code with 'export FREERADIUS=1' before compile.
* radcli library can be used after setting RADCLI variable in source
code with 'export RADCLI=1' before compile.
3. Parameters

@ -89,25 +89,34 @@
<section>
<title>External Libraries or Applications</title>
<para>
The following libraries or applications must be installed
before compilling &kamailio; with this module loaded:
The following libraries or applications must be installed
before running &kamailio; with this module loaded:
</para>
<itemizedlist>
<listitem>
<para><emphasis>radiusclient-ng</emphasis> 0.5.0 or freeradius-client
+ or higher.
library and development files. See <ulink
<para><emphasis>radiusclient-ng</emphasis> 0.5.0 or higher,
<emphasis>freeradius-client</emphasis> <ulink
url='https://github.com/FreeRADIUS/freeradius-client/'>
+ https://github.com/FreeRADIUS/freeradius-client/</ulink>.
https://github.com/FreeRADIUS/freeradius-client/</ulink> or
<emphasis>radcli</emphasis> <ulink
url='http://radcli.github.io/radcli/'>
http://radcli.github.io/radcli/</ulink>.
</para>
</listitem>
<listitem>
+ <para>
+ <emphasis>freeradius-client</emphasis> library can be used after
+ setting FREERADIUS variable in source code with
+ <emphasis>'export FREERADIUS=1'</emphasis> command before compile.
</para>
</listitem>
<para>
<emphasis>freeradius-client</emphasis> library can be used after
setting FREERADIUS variable in source code with
<emphasis>'export FREERADIUS=1'</emphasis> before compile.
</para>
</listitem>
<listitem>
<para>
<emphasis>radcli</emphasis> library can be used after
setting RADCLI variable in source code with
<emphasis>'export RADCLI=1'</emphasis> before compile.
</para>
</listitem>
</itemizedlist>
</section>
</section>

@ -39,28 +39,28 @@ Juha Heinanen
3.1. db_url (string)
3.2. db_table (string)
3.3. from_address (string)
3.4. contact_hdr (string)
3.5. extra_hdrs (string)
3.6. offline_message (string)
3.7. content_type_hdr (string)
3.8. reminder (string)
3.9. outbound_proxy (string)
3.10. expire_time (int)
3.11. check_time (int)
3.12. send_time (int)
3.13. clean_period (int)
3.14. use_contact (int)
3.15. sc_mid (string)
3.16. sc_from (string)
3.17. sc_to (string)
3.18. sc_uri_user (string)
3.19. sc_uri_host (string)
3.20. sc_body (string)
3.21. sc_ctype (string)
3.22. sc_exp_time (string)
3.23. sc_inc_time (string)
3.24. sc_snd_time (string)
3.3. sc_mid (string)
3.4. sc_from (string)
3.5. sc_to (string)
3.6. sc_uri_user (string)
3.7. sc_uri_host (string)
3.8. sc_body (string)
3.9. sc_ctype (string)
3.10. sc_exp_time (string)
3.11. sc_inc_time (string)
3.12. sc_snd_time (string)
3.13. from_address (string)
3.14. contact_hdr (string)
3.15. extra_hdrs (string)
3.16. offline_message (string)
3.17. content_type_hdr (string)
3.18. reminder (string)
3.19. outbound_proxy (string)
3.20. expire_time (int)
3.21. check_time (int)
3.22. send_time (int)
3.23. clean_period (int)
3.24. use_contact (int)
3.25. snd_time_avp (str)
3.26. add_date (int)
3.27. max_messages (int)
@ -89,28 +89,28 @@ Juha Heinanen
1.1. Set the "db_url" parameter
1.2. Set the "db_table" parameter
1.3. Set the "from_address" parameter
1.4. Set the "contact_hdr" parameter
1.5. Set the "extra_hdrs" parameter
1.6. Set the "offline_message" parameter
1.7. Set the "content_type_hdr" parameter
1.8. Set the "reminder" parameter
1.9. Set the "outbound_proxy" parameter
1.10. Set the "expire_time" parameter
1.11. Set the "check_time" parameter
1.12. Set the "send_time" parameter
1.13. Set the "clean_period" parameter
1.14. Set the "use_contact" parameter
1.15. Set the "sc_mid" parameter
1.16. Set the "sc_from" parameter
1.17. Set the "sc_to" parameter
1.18. Set the "sc_uri_user" parameter
1.19. Set the "sc_uri_host" parameter
1.20. Set the "sc_body" parameter
1.21. Set the "sc_ctype" parameter
1.22. Set the "sc_exp_time" parameter
1.23. Set the "sc_inc_time" parameter
1.24. Set the "sc_snd_time" parameter
1.3. Set the "sc_mid" parameter
1.4. Set the "sc_from" parameter
1.5. Set the "sc_to" parameter
1.6. Set the "sc_uri_user" parameter
1.7. Set the "sc_uri_host" parameter
1.8. Set the "sc_body" parameter
1.9. Set the "sc_ctype" parameter
1.10. Set the "sc_exp_time" parameter
1.11. Set the "sc_inc_time" parameter
1.12. Set the "sc_snd_time" parameter
1.13. Set the "from_address" parameter
1.14. Set the "contact_hdr" parameter
1.15. Set the "extra_hdrs" parameter
1.16. Set the "offline_message" parameter
1.17. Set the "content_type_hdr" parameter
1.18. Set the "reminder" parameter
1.19. Set the "outbound_proxy" parameter
1.20. Set the "expire_time" parameter
1.21. Set the "check_time" parameter
1.22. Set the "send_time" parameter
1.23. Set the "clean_period" parameter
1.24. Set the "use_contact" parameter
1.25. Set the "snd_time_avp" parameter
1.26. Set the "add_date" parameter
1.27. Set the "max_messages" parameter
@ -135,28 +135,28 @@ Chapter 1. Admin Guide
3.1. db_url (string)
3.2. db_table (string)
3.3. from_address (string)
3.4. contact_hdr (string)
3.5. extra_hdrs (string)
3.6. offline_message (string)
3.7. content_type_hdr (string)
3.8. reminder (string)
3.9. outbound_proxy (string)
3.10. expire_time (int)
3.11. check_time (int)
3.12. send_time (int)
3.13. clean_period (int)
3.14. use_contact (int)
3.15. sc_mid (string)
3.16. sc_from (string)
3.17. sc_to (string)
3.18. sc_uri_user (string)
3.19. sc_uri_host (string)
3.20. sc_body (string)
3.21. sc_ctype (string)
3.22. sc_exp_time (string)
3.23. sc_inc_time (string)
3.24. sc_snd_time (string)
3.3. sc_mid (string)
3.4. sc_from (string)
3.5. sc_to (string)
3.6. sc_uri_user (string)
3.7. sc_uri_host (string)
3.8. sc_body (string)
3.9. sc_ctype (string)
3.10. sc_exp_time (string)
3.11. sc_inc_time (string)
3.12. sc_snd_time (string)
3.13. from_address (string)
3.14. contact_hdr (string)
3.15. extra_hdrs (string)
3.16. offline_message (string)
3.17. content_type_hdr (string)
3.18. reminder (string)
3.19. outbound_proxy (string)
3.20. expire_time (int)
3.21. check_time (int)
3.22. send_time (int)
3.23. clean_period (int)
3.24. use_contact (int)
3.25. snd_time_avp (str)
3.26. add_date (int)
3.27. max_messages (int)
@ -183,9 +183,10 @@ Chapter 1. Admin Guide
1. Overview
This modules provides offline message storage for the Kamailio SIP
Server Platform. It stores received messages for an offline user and
sends them when the user becomes online.
This module provides offline message storage for Kamailio SIP Server
Platform. It stores received messages for an offline user and sends
them when the user comes back online. It can also send reminders and
auto-expire messages.
For each message, the modules stores "Request-URI" ("R-URI") only if it
is a complete address of record ("username@hostname"), URI from "To"
@ -194,20 +195,21 @@ Chapter 1. Admin Guide
(it might be the contact address for current SIP session) the URI from
"To" header will be used as R-URI.
When the expiration time passed, the message is discarded from
When the expiration time is passed, the message is discarded from
database. Expiration time is computed based on incoming time and one of
the module's parameters.
Every time when a user registers with Kamailio, the module is looking
in database for offline messages intended for that user. All of them
will be sent to contact address provided in REGISTER request.
will be sent to contact address provided in REGISTER request and then
be deleted.
It may happen that the SIP user to be registered use a SIP User Agent
that has no support for MESSAGE requests. In this case the
"failure_route" should be used to re-store the undelivered requests.
It may happen that the SIP user registering use a SIP User Agent that
has no support for MESSAGE requests. In this case the "failure_route"
should be used to re-store the undelivered requests.
Another functionality provided by the module is to send messages at a
certain time -- the reminder functionality. Using config logic, a
Another functionality provided by the MSILO module is to send messages
at a certain time -- the reminder functionality. Using config logic, a
received message can be stored and delivered at a time specified while
storing with the 'snd_time_avp'.
@ -234,28 +236,28 @@ Chapter 1. Admin Guide
3.1. db_url (string)
3.2. db_table (string)
3.3. from_address (string)
3.4. contact_hdr (string)
3.5. extra_hdrs (string)
3.6. offline_message (string)
3.7. content_type_hdr (string)
3.8. reminder (string)
3.9. outbound_proxy (string)
3.10. expire_time (int)
3.11. check_time (int)
3.12. send_time (int)
3.13. clean_period (int)
3.14. use_contact (int)
3.15. sc_mid (string)
3.16. sc_from (string)
3.17. sc_to (string)
3.18. sc_uri_user (string)
3.19. sc_uri_host (string)
3.20. sc_body (string)
3.21. sc_ctype (string)
3.22. sc_exp_time (string)
3.23. sc_inc_time (string)
3.24. sc_snd_time (string)
3.3. sc_mid (string)
3.4. sc_from (string)
3.5. sc_to (string)
3.6. sc_uri_user (string)
3.7. sc_uri_host (string)
3.8. sc_body (string)
3.9. sc_ctype (string)
3.10. sc_exp_time (string)
3.11. sc_inc_time (string)
3.12. sc_snd_time (string)
3.13. from_address (string)
3.14. contact_hdr (string)
3.15. extra_hdrs (string)
3.16. offline_message (string)
3.17. content_type_hdr (string)
3.18. reminder (string)
3.19. outbound_proxy (string)
3.20. expire_time (int)
3.21. check_time (int)
3.22. send_time (int)
3.23. clean_period (int)
3.24. use_contact (int)
3.25. snd_time_avp (str)
3.26. add_date (int)
3.27. max_messages (int)
@ -285,273 +287,273 @@ modparam("msilo", "db_url", "mysql://user:passwd@host.com/dbname")
modparam("msilo", "db_table", "silo")
...
3.3. from_address (string)
3.3. sc_mid (string)
The SIP address used to inform users that destination of their message
is not online and the message will be delivered next time when that
user goes online. If the parameter is not set, the module will not send
any notification. It can contain pseudo-variables.
The name of the column in silo table used to store the message id.
Default value is "NULL".
Default value is "mid".
Example 1.3. Set the "from_address" parameter
Example 1.3. Set the "sc_mid" parameter
...
modparam("msilo", "from_address", "sip:registrar@example.org")
modparam("msilo", "from_address", "sip:$rU@example.org")
modparam("msilo", "sc_mid", "other_mid")
...
3.4. contact_hdr (string)
3.4. sc_from (string)
The value of the "Contact" header (including header name and ending
\r\n) to be added in notification messages. It can contain
pseudo-variables.
The name of the column in silo table, storing the source address.
Default value is "NULL".
Default value is "src_addr".
Example 1.4. Set the "contact_hdr" parameter
Example 1.4. Set the "sc_from" parameter
...
modparam("msilo", "contact_hdr", "Contact: <sip:null@example.com>\r\n")
modparam("msilo", "sc_from", "source_address")
...
3.5. extra_hdrs (string)
3.5. sc_to (string)
Extra headers (each ending with \r\n) to be added in messages sent from
silo by m_dump. It can contain pseudo-variables.
The name of the column in silo table, storing the destination address.
Default value is "NULL".
Default value is "dst_addr".
Example 1.5. Set the "extra_hdrs" parameter
Example 1.5. Set the "sc_to" parameter
...
modparam("msilo", "extra_hdrs", "X-Extra: $tu\r\nY-Extra: foo\r\n")
modparam("msilo", "sc_to", "destination_address")
...
3.6. offline_message (string)
3.6. sc_uri_user (string)
The body of the notification message. It can contain pseudo-variables.
The name of the column in silo table, storing the user name.
Default value is "NULL".
Default value is "username".
Example 1.6. Set the "offline_message" parameter
Example 1.6. Set the "sc_uri_user" parameter
...
modparam("msilo", "offline_message", "*** User $rU is offline!")
modparam("msilo", "offline_message", "<em>I am offline!</em>")
modparam("msilo", "sc_uri_user", "user")
...
3.7. content_type_hdr (string)
3.7. sc_uri_host (string)
The value of the Content-Type header (including header name and ending
\r\n) to be added in notification messages. It must reflect what the
'offline_message' contains. It can contain pseudo-variables.
The name of the column in silo table, storing the domain.
Default value is "NULL".
Default value is "domain".
Example 1.7. Set the "content_type_hdr" parameter
Example 1.7. Set the "sc_uri_host" parameter
...
modparam("msilo", "content_type_hdr", "Content-Type: text/plain\r\n")
modparam("msilo", "content_type_hdr", "Content-Type: text/html\r\n")
modparam("msilo", "sc_uri_host", "domain")
...
3.8. reminder (string)
3.8. sc_body (string)
The SIP address used to send reminder messages. If this value is not
set, the reminder feature is disabled.
The name of the column storing the message body in silo table.
Default value is "NULL".
Default value is "body".
Example 1.8. Set the "reminder" parameter
Example 1.8. Set the "sc_body" parameter
...
modparam("msilo", "reminder", "sip:registrar@example.org")
modparam("msilo", "sc_body", "message_body")
...
3.9. outbound_proxy (string)
3.9. sc_ctype (string)
The SIP address used as next hop when sending the message. Very useful
when using Kamailio with a domain name not in DNS, or when using a
separate Kamailio instance for msilo processing. If not set, the
message will be sent to the address in destination URI.
The name of the column in silo table, storing content type.
Default value is "NULL".
Default value is "ctype".
Example 1.9. Set the "outbound_proxy" parameter
Example 1.9. Set the "sc_ctype" parameter
...
modparam("msilo", "outbound_proxy", "sip:kamailio.org;transport=tcp")
modparam("msilo", "sc_ctype", "content_type")
...
3.10. expire_time (int)
3.10. sc_exp_time (string)
Expire time of stored messages - seconds. When this time passed, the
message is silently discarded from database.
The name of the column in silo table, storing the expire time of the
message.
Default value is "259200 (72 hours = 3 days)".
Default value is "exp_time".
Example 1.10. Set the "expire_time" parameter
Example 1.10. Set the "sc_exp_time" parameter
...
modparam("msilo", "expire_time", 36000)
modparam("msilo", "sc_exp_time", "expire_time")
...
3.11. check_time (int)
3.11. sc_inc_time (string)
Timer interval to check if dumped messages are sent OK - seconds. The
module keeps each request send by itself for a new online user and if
the reply is 2xx then the message is deleted from database.
The name of the column in silo table, storing the incoming time of the
message.
Default value is "30".
Default value is "inc_time".
Example 1.11. Set the "check_time" parameter
Example 1.11. Set the "sc_inc_time" parameter
...
modparam("msilo", "check_time", 10)
modparam("msilo", "sc_inc_time", "incoming_time")
...
3.12. send_time (int)
3.12. sc_snd_time (string)
Timer interval in seconds to check if there are reminder messages. The
module takes all reminder messages that must be sent at that moment or
before that moment.
If the value is 0, the reminder feature is disabled.
The name of the column in silo table, storing the send time for the
reminder.
Default value is "0".
Default value is "snd_time".
Example 1.12. Set the "send_time" parameter
Example 1.12. Set the "sc_snd_time" parameter
...
modparam("msilo", "send_time", 60)
modparam("msilo", "sc_snd_time", "send_reminder_time")
...
3.13. clean_period (int)
3.13. from_address (string)
Number of "check_time" cycles when to check if there are expired
messages in database.
The SIP address used to inform users that destination of their message
is not online and the message will be delivered next time when that
user goes online. If the parameter is not set, the module will not send
any notification. This parameter may contain pseudo-variables.
Default value is "5".
Default value is "NULL".
Example 1.13. Set the "clean_period" parameter
Example 1.13. Set the "from_address" parameter
...
modparam("msilo", "clean_period", 3)
modparam("msilo", "from_address", "sip:registrar@example.org")
modparam("msilo", "from_address", "sip:$rU@example.org")
...
3.14. use_contact (int)
3.14. contact_hdr (string)
Turns on/off the usage of the "Contact" address to send notification
back to sender whose message is stored by MSILO.
The value of the "Contact" header (including header name and ending
\r\n) to be added in notification messages. It can contain
pseudo-variables.
Default value is "1 (0 = off, 1 = on)".
Default value is "NULL".
Example 1.14. Set the "use_contact" parameter
Example 1.14. Set the "contact_hdr" parameter
...
modparam("msilo", "use_contact", 0)
modparam("msilo", "contact_hdr", "Contact: <sip:null@example.com>\r\n")
...
3.15. sc_mid (string)
3.15. extra_hdrs (string)
The name of the column in silo table, storing message id.
Extra headers (each ending with \r\n) to be added in messages sent from
silo by m_dump. It can contain pseudo-variables.
Default value is "mid".
Default value is "NULL".
Example 1.15. Set the "sc_mid" parameter
Example 1.15. Set the "extra_hdrs" parameter
...
modparam("msilo", "sc_mid", "other_mid")
modparam("msilo", "extra_hdrs", "X-Extra: $tu\r\nY-Extra: foo\r\n")
...
3.16. sc_from (string)
3.16. offline_message (string)
The name of the column in silo table, storing the source address.
The body of the notification message. It can contain pseudo-variables.
Default value is "src_addr".
Default value is "NULL".
Example 1.16. Set the "sc_from" parameter
Example 1.16. Set the "offline_message" parameter
...
modparam("msilo", "sc_from", "source_address")
modparam("msilo", "offline_message", "*** User $rU is offline!")
modparam("msilo", "offline_message", "<em>I am offline!</em>")
...
3.17. sc_to (string)
3.17. content_type_hdr (string)
The name of the column in silo table, storing the destination address.
The value of the Content-Type header (including header name and ending
\r\n) to be added in notification messages. It must reflect what the
'offline_message' contains. It can contain pseudo-variables.
Default value is "dst_addr".
Default value is "NULL".
Example 1.17. Set the "sc_to" parameter
Example 1.17. Set the "content_type_hdr" parameter
...
modparam("msilo", "sc_to", "destination_address")
modparam("msilo", "content_type_hdr", "Content-Type: text/plain\r\n")
modparam("msilo", "content_type_hdr", "Content-Type: text/html\r\n")
...
3.18. sc_uri_user (string)
3.18. reminder (string)
The name of the column in silo table, storing the user name.
The SIP address used to send reminder messages. If this value is not
set, the reminder feature is disabled.
Default value is "username".
Default value is "NULL".
Example 1.18. Set the "sc_uri_user" parameter
Example 1.18. Set the "reminder" parameter
...
modparam("msilo", "sc_uri_user", "user")
modparam("msilo", "reminder", "sip:registrar@example.org")
...
3.19. sc_uri_host (string)
3.19. outbound_proxy (string)
The name of the column in silo table, storing the domain.
The SIP address used as next hop when sending the message. Very useful
when using Kamailio with a domain name not in DNS, or when using a
separate Kamailio instance for msilo processing. If not set, the
message will be sent to the address in destination URI.
Default value is "domain".
Default value is "NULL".
Example 1.19. Set the "sc_uri_host" parameter
Example 1.19. Set the "outbound_proxy" parameter
...
modparam("msilo", "sc_uri_host", "domain")
modparam("msilo", "outbound_proxy", "sip:kamailio.org;transport=tcp")
...
3.20. sc_body (string)
3.20. expire_time (int)
The name of the column storing the message body in silo table.
Expire time of stored messages - seconds. When this time passed, the
message is silently discarded from database.
Default value is "body".
Default value is "259200 (72 hours = 3 days)".
Example 1.20. Set the "sc_body" parameter
Example 1.20. Set the "expire_time" parameter
...
modparam("msilo", "sc_body", "message_body")
modparam("msilo", "expire_time", 36000)
...
3.21. sc_ctype (string)
3.21. check_time (int)
The name of the column in silo table, storing content type.
Timer interval to check if dumped messages are sent OK - seconds. The
module keeps each request send by itself for a new online user and if
the reply is 2xx then the message is deleted from database.
Default value is "ctype".
Default value is "30".
Example 1.21. Set the "sc_ctype" parameter
Example 1.21. Set the "check_time" parameter
...
modparam("msilo", "sc_ctype", "content_type")
modparam("msilo", "check_time", 10)
...
3.22. sc_exp_time (string)
3.22. send_time (int)
The name of the column in silo table, storing the expire time of the
message.
Timer interval in seconds to check if there are reminder messages. The
module takes all reminder messages that must be sent at that moment or
before that moment.
Default value is "exp_time".
If the value is 0, the reminder feature is disabled.
Default value is "0".
Example 1.22. Set the "sc_exp_time" parameter
Example 1.22. Set the "send_time" parameter
...
modparam("msilo", "sc_exp_time", "expire_time")
modparam("msilo", "send_time", 60)
...
3.23. sc_inc_time (string)
3.23. clean_period (int)
The name of the column in silo table, storing the incoming time of the
message.
Number of "check_time" cycles when to check if there are expired
messages in database.
Default value is "inc_time".
Default value is "5".
Example 1.23. Set the "sc_inc_time" parameter
Example 1.23. Set the "clean_period" parameter
...
modparam("msilo", "sc_inc_time", "incoming_time")
modparam("msilo", "clean_period", 3)
...
3.24. sc_snd_time (string)
3.24. use_contact (int)
The name of the column in silo table, storing the send time for the
reminder.
Turns on/off the usage of the "Contact" address to send notification
back to sender whose message is stored by MSILO.
Default value is "snd_time".
Default value is "1 (0 = off, 1 = on)".
Example 1.24. Set the "sc_snd_time" parameter
Example 1.24. Set the "use_contact" parameter
...
modparam("msilo", "sc_snd_time", "send_reminder_time")
modparam("msilo", "use_contact", 0)
...
3.25. snd_time_avp (str)
@ -573,7 +575,7 @@ modparam("msilo", "snd_time_avp", "$avp(i:123)")
3.26. add_date (int)
Wheter to add as prefix the date when the message was stored.
Whether to add as prefix the date when the message was stored.
Default value is "1" (1==on/0==off).
@ -666,8 +668,8 @@ m_store("$tu");
4.2. m_dump([owner])
The method sends stored messages for the SIP user that is going to
register to his actual contact address. The method should be called
The method sends stored messages for the SIP user that has registerered
to the contact address in the registration. The method should be called
when a REGISTER request is received and the "Expire" header has a value
greater than zero.
@ -722,7 +724,6 @@ m_dump("$fu");
Example 1.33. Kamailio config script - sample msilo usage
...
# $Id$
#
# MSILO usage example
#

@ -1,4 +1,3 @@
# $Id$
#
# MSILO usage example
#

@ -16,9 +16,10 @@
<section>
<title>Overview</title>
<para>
This modules provides offline message storage for the &kamailioname;. It
This module provides offline message storage for &kamailioname;. It
stores received messages for an offline user and sends them when the
user becomes online.
user comes back online. It can also send reminders and auto-expire
messages.
</para>
<para>
For each message, the modules stores <quote>Request-URI</quote>
@ -31,22 +32,22 @@
from <quote>To</quote> header will be used as <abbrev>R-URI</abbrev>.
</para>
<para>
When the expiration time passed, the message is discarded from
When the expiration time is passed, the message is discarded from
database. Expiration time is computed based on incoming time and
one of the module's parameters.
</para>
<para>
Every time when a user registers with &kamailio;, the module is looking in
database for offline messages intended for that user. All of them will
be sent to contact address provided in REGISTER request.
be sent to contact address provided in REGISTER request and then be deleted.
</para>
<para>
It may happen that the &sip; user to be registered use a &sip; User Agent
It may happen that the &sip; user registering use a &sip; User Agent
that has no support for MESSAGE requests. In this case the <quote>failure_route</quote>
should be used to re-store the undelivered requests.
</para>
<para>
Another functionality provided by the module is to send messages at
Another functionality provided by the MSILO module is to send messages at
a certain time -- the reminder functionality. Using config logic, a
received message can be stored and delivered at a time specified while
storing with the 'snd_time_avp'.
@ -132,13 +133,165 @@ modparam("msilo", "db_table", "silo")
</programlisting>
</example>
</section>
<section id="msilo.p.sc_mid">
<title><varname>sc_mid</varname> (string)</title>
<para>
The name of the column in silo table used to store the message id.
</para>
<para>Default value is <quote>mid</quote>.</para>
<example>
<title>Set the <quote>sc_mid</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_mid", "other_mid")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_from">
<title><varname>sc_from</varname> (string)</title>
<para>
The name of the column in silo table, storing the source address.
</para>
<para>Default value is <quote>src_addr</quote>.</para>
<example>
<title>Set the <quote>sc_from</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_from", "source_address")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_to">
<title><varname>sc_to</varname> (string)</title>
<para>
The name of the column in silo table, storing the destination address.
</para>
<para>Default value is <quote>dst_addr</quote>.</para>
<example>
<title>Set the <quote>sc_to</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_to", "destination_address")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_uri_user">
<title><varname>sc_uri_user</varname> (string)</title>
<para>
The name of the column in silo table, storing the user name.
</para>
<para>Default value is <quote>username</quote>.</para>
<example>
<title>Set the <quote>sc_uri_user</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_uri_user", "user")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_uri_host">
<title><varname>sc_uri_host</varname> (string)</title>
<para>
The name of the column in silo table, storing the domain.
</para>
<para>Default value is <quote>domain</quote>.</para>
<example>
<title>Set the <quote>sc_uri_host</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_uri_host", "domain")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_body">
<title><varname>sc_body</varname> (string)</title>
<para>
The name of the column storing the message body in silo table.
</para>
<para>Default value is <quote>body</quote>.</para>
<example>
<title>Set the <quote>sc_body</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_body", "message_body")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_ctype">
<title><varname>sc_ctype</varname> (string)</title>
<para>
The name of the column in silo table, storing content type.
</para>
<para>Default value is <quote>ctype</quote>.</para>
<example>
<title>Set the <quote>sc_ctype</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_ctype", "content_type")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_exp_time">
<title><varname>sc_exp_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the expire time of the message.
</para>
<para>Default value is <quote>exp_time</quote>.</para>
<example>
<title>Set the <quote>sc_exp_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_exp_time", "expire_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_inc_time">
<title><varname>sc_inc_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the incoming time of the message.
</para>
<para>Default value is <quote>inc_time</quote>.</para>
<example>
<title>Set the <quote>sc_inc_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_inc_time", "incoming_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_snd_time">
<title><varname>sc_snd_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the send time for the reminder.
</para>
<para>Default value is <quote>snd_time</quote>.</para>
<example>
<title>Set the <quote>sc_snd_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_snd_time", "send_reminder_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.from_address">
<title><varname>from_address</varname> (string)</title>
<para>
The &sip; address used to inform users that destination of their
message is not online and the message will be delivered next time
when that user goes online. If the parameter is not set, the module
will not send any notification. It can contain pseudo-variables.
will not send any notification. This parameter may contain pseudo-variables.
</para>
<para>
<emphasis>
@ -180,7 +333,7 @@ modparam("msilo", "contact_hdr", "Contact: &lt;sip:null@example.com&gt;\r\n")
<title><varname>extra_hdrs</varname> (string)</title>
<para>
Extra headers (each ending with \r\n) to be added in
messages sent from silo by m_dump.
messages sent from silo by m_dump.
It can contain pseudo-variables.
</para>
<para>
@ -389,158 +542,6 @@ modparam("msilo", "use_contact", 0)
</example>
</section>
<section id="msilo.p.sc_mid">
<title><varname>sc_mid</varname> (string)</title>
<para>
The name of the column in silo table, storing message id.
</para>
<para>Default value is <quote>mid</quote>.</para>
<example>
<title>Set the <quote>sc_mid</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_mid", "other_mid")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_from">
<title><varname>sc_from</varname> (string)</title>
<para>
The name of the column in silo table, storing the source address.
</para>
<para>Default value is <quote>src_addr</quote>.</para>
<example>
<title>Set the <quote>sc_from</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_from", "source_address")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_to">
<title><varname>sc_to</varname> (string)</title>
<para>
The name of the column in silo table, storing the destination address.
</para>
<para>Default value is <quote>dst_addr</quote>.</para>
<example>
<title>Set the <quote>sc_to</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_to", "destination_address")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_uri_user">
<title><varname>sc_uri_user</varname> (string)</title>
<para>
The name of the column in silo table, storing the user name.
</para>
<para>Default value is <quote>username</quote>.</para>
<example>
<title>Set the <quote>sc_uri_user</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_uri_user", "user")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_uri_host">
<title><varname>sc_uri_host</varname> (string)</title>
<para>
The name of the column in silo table, storing the domain.
</para>
<para>Default value is <quote>domain</quote>.</para>
<example>
<title>Set the <quote>sc_uri_host</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_uri_host", "domain")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_body">
<title><varname>sc_body</varname> (string)</title>
<para>
The name of the column storing the message body in silo table.
</para>
<para>Default value is <quote>body</quote>.</para>
<example>
<title>Set the <quote>sc_body</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_body", "message_body")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_ctype">
<title><varname>sc_ctype</varname> (string)</title>
<para>
The name of the column in silo table, storing content type.
</para>
<para>Default value is <quote>ctype</quote>.</para>
<example>
<title>Set the <quote>sc_ctype</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_ctype", "content_type")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_exp_time">
<title><varname>sc_exp_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the expire time of the message.
</para>
<para>Default value is <quote>exp_time</quote>.</para>
<example>
<title>Set the <quote>sc_exp_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_exp_time", "expire_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_inc_time">
<title><varname>sc_inc_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the incoming time of the message.
</para>
<para>Default value is <quote>inc_time</quote>.</para>
<example>
<title>Set the <quote>sc_inc_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_inc_time", "incoming_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.sc_snd_time">
<title><varname>sc_snd_time</varname> (string)</title>
<para>
The name of the column in silo table, storing the send time for the reminder.
</para>
<para>Default value is <quote>snd_time</quote>.</para>
<example>
<title>Set the <quote>sc_snd_time</quote> parameter</title>
<programlisting format="linespecific">
...
modparam("msilo", "sc_snd_time", "send_reminder_time")
...
</programlisting>
</example>
</section>
<section id="msilo.p.snd_time_avp">
<title><varname>snd_time_avp</varname> (str)</title>
<para>
@ -570,7 +571,7 @@ modparam("msilo", "snd_time_avp", "$avp(i:123)")
<section id="msilo.p.add_date">
<title><varname>add_date</varname> (int)</title>
<para>
Wheter to add as prefix the date when the message was stored.
Whether to add as prefix the date when the message was stored.
</para>
<para>
<emphasis>
@ -721,10 +722,10 @@ m_store("$tu");
<section id="msilo.f.m_dump">
<title><function moreinfo="none">m_dump([owner])</function></title>
<para>
The method sends stored messages for the &sip; user that is going to
register to his actual contact address. The method should be called
when a REGISTER request is received and the <quote>Expire</quote>
header has a value greater than zero.
The method sends stored messages for the &sip; user that has
registerered to the contact address in the registration.
The method should be called when a REGISTER request is received
and the <quote>Expire</quote> header has a value greater than zero.
</para>
<para>Meaning of the parameters is as follows:</para>
<itemizedlist>

@ -1,5 +1,5 @@
/*
* Functions that process REGISTER message
* Functions that process REGISTER message
* and store data in usrloc
*
* Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
@ -16,8 +16,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

@ -1,5 +1,5 @@
/*
* Functions that process REGISTER message
* Functions that process REGISTER message
* and store data in usrloc
*
* Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
@ -16,8 +16,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

@ -15,10 +15,10 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*
*/
/*!
@ -27,7 +27,7 @@
* \ingroup registrar
*/
#include <string.h>
#include <string.h>
#include "../../dprint.h"
#include "rerrno.h"
#include "reg_mod.h"
@ -48,7 +48,7 @@ int extract_aor(str* _uri, str* _a, sip_uri_t *_pu)
int user_len;
str *uri;
str realm_prefix = {0};
memset(aor_buf, 0, MAX_AOR_LEN);
uri=_uri;
@ -62,7 +62,7 @@ int extract_aor(str* _uri, str* _a, sip_uri_t *_pu)
LM_ERR("failed to parse AoR [%.*s]\n", uri->len, uri->s);
return -1;
}
if ( (puri->user.len + puri->host.len + 1) > MAX_AOR_LEN
|| puri->user.len > USERNAME_MAX_SIZE
|| puri->host.len > DOMAIN_MAX_SIZE ) {
@ -86,7 +86,7 @@ int extract_aor(str* _uri, str* _a, sip_uri_t *_pu)
if (user_len)
aor_buf[_a->len++] = '@';
/* strip prefix (if defined) */
realm_prefix.len = cfg_get(registrar, registrar_cfg, realm_pref).len;
realm_prefix.len = cfg_get(registrar, registrar_cfg, realm_pref).len;
if(realm_prefix.len>0) {
realm_prefix.s = cfg_get(registrar, registrar_cfg, realm_pref).s;
LM_DBG("realm prefix is [%.*s]\n", realm_prefix.len,

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - common stuff
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef COMMON_H

@ -18,7 +18,7 @@
*/
/*!
* \file
* \file
* \brief Registrar :: Configuration
* \ingroup Registrar
*/
@ -41,7 +41,7 @@ struct cfg_group_registrar default_registrar_cfg = {
0, /* case_sensitive */
Q_UNSPECIFIED, /* default_q */
1 /* append_branches */
};
};
void *registrar_cfg = &default_registrar_cfg;

@ -4,13 +4,13 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \file
* \brief Registrar :: Configuration
* \ingroup registrar
*/

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*!
* \file
* \brief SIP registrar module - lookup contacts in usrloc
* \ingroup registrar
*/
* \ingroup registrar
*/
#include <string.h>
@ -82,14 +82,14 @@ int reg_cmp_instances(str *i1, str *i2)
* Lookup a contact in usrloc and rewrite R-URI if found
*/
int lookup(struct sip_msg* _m, udomain_t* _d, str* _uri) {
return lookup_helper(_m, _d, _uri, 0);
return lookup_helper(_m, _d, _uri, 0);
}
/*! \brief
* Lookup a contact in usrloc and add the records to the dset structure
*/
int lookup_to_dset(struct sip_msg* _m, udomain_t* _d, str* _uri) {
return lookup_helper(_m, _d, _uri, 1);
return lookup_helper(_m, _d, _uri, 1);
}
/*! \brief
@ -168,7 +168,7 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
if (_m->new_uri.s) uri = _m->new_uri;
else uri = _m->first_line.u.request.uri;
if (extract_aor((_uri)?_uri:&uri, &aor, &puri) < 0) {
LM_ERR("failed to extract address of record\n");
return -3;
@ -340,26 +340,26 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
}
if (ptr->instance.len) {
if (set_instance(_m, &(ptr->instance)) < 0) {
if (set_instance(_m, &(ptr->instance)) < 0) {
ret = -3;
goto done;
}
}
}
_m->reg_id = ptr->reg_id;
if (ptr->ruid.len) {
if (set_ruid(_m, &(ptr->ruid)) < 0) {
if (set_ruid(_m, &(ptr->ruid)) < 0) {
ret = -3;
goto done;
}
}
}
if (ptr->user_agent.len) {
if (set_ua(_m, &(ptr->user_agent)) < 0) {
if (set_ua(_m, &(ptr->user_agent)) < 0) {
ret = -3;
goto done;
}
}
}
set_ruri_q(ptr->q);
@ -422,18 +422,18 @@ int lookup_helper(struct sip_msg* _m, udomain_t* _d, str* _uri, int _mode)
path_dst.len = 0;
}
/* The same as for the first contact applies for branches
/* The same as for the first contact applies for branches
* regarding path vs. received. */
LM_DBG("instance is %.*s\n",
ptr->instance.len, ptr->instance.s);
ptr->instance.len, ptr->instance.s);
if (append_branch(_m, &ptr->c,
path_dst.len?&path_dst:&ptr->received,
path_dst.len?&path_str:0, ptr->q, ptr->cflags,
ptr->sock,
ptr->instance.len?&(ptr->instance):0,
ptr->instance.len?ptr->reg_id:0,
&ptr->ruid, &ptr->user_agent)
== -1) {
path_dst.len?&path_dst:&ptr->received,
path_dst.len?&path_str:0, ptr->q, ptr->cflags,
ptr->sock,
ptr->instance.len?&(ptr->instance):0,
ptr->instance.len?ptr->reg_id:0,
&ptr->ruid, &ptr->user_agent)
== -1) {
LM_ERR("failed to append a branch\n");
/* Also give a chance to the next branches*/
continue;
@ -484,19 +484,19 @@ int clear_ruri_branch(sip_msg_t *msg)
*/
int reset_ruri_branch(sip_msg_t *msg)
{
if(msg==NULL)
return -1;
reset_dst_uri(msg);
reset_path_vector(msg);
set_ruri_q(Q_UNSPECIFIED);
reset_force_socket(msg);
setbflagsval(0, 0);
reset_instance(msg);
msg->reg_id = 0;
reset_ruid(msg);
reset_ua(msg);
return 0;
if(msg==NULL)
return -1;
reset_dst_uri(msg);
reset_path_vector(msg);
set_ruri_q(Q_UNSPECIFIED);
reset_force_socket(msg);
setbflagsval(0, 0);
reset_instance(msg);
msg->reg_id = 0;
reset_ruid(msg);
reset_ua(msg);
return 0;
}
/*! \brief
@ -681,12 +681,12 @@ int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, in
else uri = _m->first_line.u.request.uri;
}
}
if (extract_aor(&uri, &aor, NULL) < 0) {
LM_ERR("failed to extract address of record\n");
return -1;
}
ul.lock_udomain(_d, &aor);
res = ul.get_urecord(_d, &aor, &r);
@ -726,17 +726,17 @@ int registered4(struct sip_msg* _m, udomain_t* _d, str* _uri, int match_flag, in
if(!VALID_CONTACT(ptr, act_time)) continue;
if (match_callid.s && /* optionally enforce tighter matching w/ Call-ID */
match_callid.len > 0 &&
(match_callid.len != ptr->callid.len ||
(match_callid.len != ptr->callid.len ||
memcmp(match_callid.s, ptr->callid.s, match_callid.len)))
continue;
if (match_received.s && /* optionally enforce tighter matching w/ ip:port */
match_received.len > 0 &&
(match_received.len != ptr->received.len ||
(match_received.len != ptr->received.len ||
memcmp(match_received.s, ptr->received.s, match_received.len)))
continue;
if (match_contact.s && /* optionally enforce tighter matching w/ Contact */
match_contact.len > 0 &&
(match_contact.len != ptr->c.len ||
(match_contact.len != ptr->c.len ||
memcmp(match_contact.s, ptr->c.s, match_contact.len)))
continue;

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - lookup contacts in usrloc
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef LOOKUP_H

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
/*!
* \file
* \brief SIP registrar module - Helper functions for Path support
* \ingroup registrar
*/
* \ingroup registrar
*/
#include "../../data_lump.h"
@ -98,11 +98,11 @@ int build_path_vector(struct sip_msg *_m, str *path, str *received)
free_params(params);
if (hooks.contact.received) {
uri_str.s = uri_buf;
uri_str.s = uri_buf;
uri_str.len = MAX_URI_SIZE;
if (unescape_user(&(hooks.contact.received->body), &uri_str) < 0) {
LM_ERR("unescaping received failed\n");
goto error;
if (unescape_user(&(hooks.contact.received->body), &uri_str) < 0) {
LM_ERR("unescaping received failed\n");
goto error;
}
*received = uri_str;
LM_DBG("received is <%.*s>\n", received->len, received->s);

@ -23,8 +23,8 @@
/*!
* \file
* \brief SIP registrar module - helper functions for Path support
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef REG_PATH_H
#define REG_PATH_H

@ -15,8 +15,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -24,15 +24,15 @@
/*!
* \defgroup registrar Registrar :: SIP Registrar support
* The module contains REGISTER processing logic.
*/
*/
/*!
* \file
* \brief SIP registrar module - interface
* \ingroup registrar
* \ingroup registrar
*
* - Module: \ref registrar
*/
*/
#include <stdio.h>
#include "../../sr_module.h"
@ -89,12 +89,12 @@ int tcp_persistent_flag = -1; /*!< if the TCP connection should be kept open *
int method_filtering = 0; /*!< if the looked up contacts should be filtered based on supported methods */
int path_enabled = 0; /*!< if the Path HF should be handled */
int path_mode = PATH_MODE_STRICT; /*!< if the Path HF should be inserted in the reply.
* - STRICT (2): always insert, error if no support indicated in request
* - LAZY (1): insert only if support indicated in request
* - OFF (0): never insert */
* - STRICT (2): always insert, error if no support indicated in request
* - LAZY (1): insert only if support indicated in request
* - OFF (0): never insert */
int path_use_params = 0; /*!< if the received- and nat-parameters of last Path uri should be used
* to determine if UAC is nat'ed */
* to determine if UAC is nat'ed */
int path_check_local = 0;
/* sruid to get internal uid */
@ -179,7 +179,7 @@ static cmd_export_t cmds[] = {
REQUEST_ROUTE| FAILURE_ROUTE },
{"unregister", (cmd_function)w_unregister2, 3, unreg_fixup, 0,
REQUEST_ROUTE| FAILURE_ROUTE },
{"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3,
{"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3,
fetchc_fixup, 0,
REQUEST_ROUTE| FAILURE_ROUTE },
{"reg_free_contacts", (cmd_function)pv_free_contacts, 1,
@ -246,7 +246,7 @@ stat_export_t mod_stats[] = {
* Module exports structure
*/
struct module_exports exports = {
"registrar",
"registrar",
DEFAULT_DLFLAGS, /* dlopen flags */
cmds, /* Exported functions */
params, /* Exported parameters */
@ -288,13 +288,11 @@ static int mod_init(void)
LM_ERR("cannot bind to SL API\n");
return -1;
}
if(cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, cfg_sizeof(registrar), &registrar_cfg)){
LM_ERR("Fail to declare the configuration\n");
return -1;
return -1;
}
if (rcv_avp_param && *rcv_avp_param) {
s.s = rcv_avp_param; s.len = strlen(s.s);
@ -539,11 +537,11 @@ static int w_unregister(struct sip_msg* _m, char* _d, char* _uri)
static int w_unregister2(struct sip_msg* _m, char* _d, char* _uri, char *_ruid)
{
str uri = {0, 0};
str uri = {0, 0};
str ruid = {0};
if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0)
{
LM_ERR("invalid uri parameter\n");
LM_ERR("invalid uri parameter\n");
return -1;
}
if(fixup_get_svalue(_m, (gparam_p)_ruid, &ruid)!=0 || ruid.len<=0)

@ -1,4 +1,4 @@
/*
/*
* registrar module interface
*
* Copyright (C) 2001-2003 FhG Fokus
@ -15,8 +15,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
@ -24,8 +24,8 @@
/*!
* \file
* \brief SIP registrar module - interface
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef REG_MOD_H
@ -37,7 +37,7 @@
#include "../usrloc/usrloc.h"
#include "../../modules/sl/sl.h"
/* if DB support is used, this values must not exceed the
/* if DB support is used, this values must not exceed the
* storage capacity of the DB columns! See db/schema/entities.xml */
#define CONTACT_MAX_SIZE 255
#define RECEIVED_MAX_SIZE 255
@ -62,8 +62,8 @@
#define REG_REGID_ALWAYS 1
/* Maximum of 999 to keep flow-timer to 3 digits
- make sure to update reply.c:add_flow_timer() if the number of digits
increases! */
* - make sure to update reply.c:add_flow_timer() if the number of digits
* increases! */
#define REG_FLOW_TIMER_MAX 999
extern int nat_flag;

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - export contacts as PV
* \ingroup registrar
*/
* \ingroup registrar
*/
#include <string.h>
@ -301,7 +301,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
break;
pa.s++;
}
if(pa.s >= in->s + in->len - 2)
{
LM_ERR("invalid contact pv name %.*s\n", in->len, in->s);
@ -339,17 +339,17 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
switch(pa.len)
{
case 1:
case 1:
if(strncmp(pa.s, "q", 1)==0)
rp->attr = 8;
else goto error;
break;
case 3:
case 3:
if(strncmp(pa.s, "aor", 3)==0)
rp->attr = 0;
else goto error;
break;
case 4:
case 4:
if(strncmp(pa.s, "addr", 4)==0)
rp->attr = 3;
else if(strncmp(pa.s, "path", 4)==0)
@ -360,7 +360,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
rp->attr = 18;
else goto error;
break;
case 5:
case 5:
if(strncmp(pa.s, "flags", 5)==0)
rp->attr = 10;
else if(strncmp(pa.s, "count", 5)==0)
@ -371,7 +371,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
rp->attr = 21;
else goto error;
break;
case 6:
case 6:
if(strncmp(pa.s, "domain", 6)==0)
rp->attr = 1;
else if(strncmp(pa.s, "callid", 6)==0)
@ -382,7 +382,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
rp->attr = 14;
else goto error;
break;
case 7:
case 7:
if(strncmp(pa.s, "aorhash", 7)==0)
rp->attr = 2;
else if(strncmp(pa.s, "expires", 7)==0)
@ -391,7 +391,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
rp->attr = 16;
else goto error;
break;
case 8:
case 8:
if(strncmp(pa.s, "received", 8)==0)
rp->attr = 5;
else if(strncmp(pa.s, "modified", 8)==0)
@ -400,7 +400,7 @@ int pv_parse_ulc_name(pv_spec_p sp, str *in)
rp->attr = 20;
else goto error;
break;
case 10:
case 10:
if(strncmp(pa.s, "user_agent", 10)==0)
rp->attr = 12;
else goto error;
@ -504,7 +504,7 @@ int pv_fetch_contacts(struct sip_msg* msg, char* table, char* uri,
memcpy(c0->c.s, ptr->c.s, ptr->c.len);
c0->c.len = ptr->c.len;
p = c0->c.s + c0->c.len;
if(ptr->received.s!=NULL)
{
c0->received.s = p;

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - export contacts as PV
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef _REGPV_H_

@ -15,8 +15,8 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - time related functions
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef REGTIME_H

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - send a reply
* \ingroup registrar
*/
* \ingroup registrar
*/
#ifndef REPLY_H

@ -15,16 +15,16 @@
* 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, write to the Free Software
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
* \file
* \brief SIP registrar module - registrar errno
* \ingroup registrar
*/
* \ingroup registrar
*/
#include "rerrno.h"

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save