Kamailio and Cisco Unity Connection Integration

| 2 Comments | No TrackBacks
Scenario: We have production phones that are attached to CUCM and softphone clients that are attached to Kamailio. I would like to use the same voicemail mailbox (CUCX) for both endpoints. All systems are connected via sip trunks to cisco call manager.

Solution: Reverse engineer the way call manager sends mailbox requests to cisco unity. Then apply this method to kamailio.

I ran the built in packet capture tool on the call manager box using these instructions: http://www.netcraftsmen.net/resources/blogs/networktraces-cisco-uc.html

What I found out is that when CUCM sends a forwarded call to a unity mailbox, it uses the diversion header in SIP to accomplish this.

cucmunity.png


In the capture above, you can see that ext 36939 called 36909. The ext 36909 didnt answer and the call was forwarded to Unity at ext 36930 (pilot number for unity). Since its against rfc3261 to mangle the To: header, cucm inserts a diversion header to tell unity which mailbox greeting it should play. Thanks Cisco, for not breaking the rules!

So now I just need kamailio to insert a diversion header into the failure route when a user doesnt answer their softphone. Kamailio will use LDAP to find out a users mailbox id and insert that 5 digit extension into the diversion header.

So, the failure route will look like this:

failure_route[1] {

        if (t_check_status("408") || t_check_status("480"))
        {
                avp_subst("$avp(s:telephone)", "/.{6}/\1/g");
                append_hf("Diversion: <sip:$avp(s:telephone)@ccm.example.com>;reason=unconditional;privacy=off;screen=yes\r\n");
                rewritehost("ccm.example.com");
                xlog("Forwarding to <$rU> on CCM via failure route");
                t_relay();
                exit;
        };

Now kamailio will include the callee's 5 digit mailbox id in the diversion header. This will force unity to play the callee's mailbox greeting and you can leave a message.

The last step is to check the inbound diversion check box on the inbound sip trunk from kamailio to CUCM.

cucmsiptrunk.png

         


Configuring SNMPstats for Kamailio Openser

| No Comments | No TrackBacks

Here is a quick how-to on how to setup snmpstats module. This was on kamailio-1.4.4 and CentOS. Should also work for opensips.


Make sure you install the prerequisites

yum install lm_sensors-devel net-snmp net-snmp-devel net-snmp-utils

Complile kamailio with snmpstats module


Add this to kamailio.cfg file

loadmodule "snmpstats.so"

..

# ----- snmpstats params ----
modparam("snmpstats", "sipEntityType", "registrarServer")
modparam("snmpstats", "snmpgetPath", "/usr/bin/")

Create a bare-bones /etc/snmp/snmpd.conf file

rocommunity public
master agentx
agentXSocket tcp:localhost:705

Create a /etc/snmp/snmpstats.conf file (this tells the snmpstats module where to send its snmp data).


 agentXSocket tcp:localhost:705

If you are using a snmp.conf file, make sure this is in it

defVersion	2c
defCommunity public
mibdirs /usr/share/snmp/mibs
mibs +ALL

Inside the /usr/share/snmp/mibs/ directory, append all OPENSER-* files with a .txt extension.


Test.


Start the snmpd daemon manually

snmpd -f -Dagentx -x tcp:localhost:705 2>&1

Restart kamailio and enjoy!

 snmpwalk localhost openser

Should output something like this

OPENSER-SIP-COMMON-MIB::openserSIPProtocolVersion.0 = STRING: SIP/2.0
OPENSER-SIP-COMMON-MIB::openserSIPServiceStartTime.0 = Timeticks: (692) 0:00:06.92
OPENSER-SIP-COMMON-MIB::openserSIPEntityType.0 = BITS: 08 registrarServer(4)
OPENSER-SIP-COMMON-MIB::openserSIPTransportRcv.ipv4."127.0.0.1".5060 = BITS: 60 udp(1) tcp(2)
OPENSER-SIP-COMMON-MIB::openserSIPTransportRcv.ipv4."146.186.8.100".5060 = BITS: 60 udp(1) tcp(2)
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.1 = STRING: METHOD_INVITE
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.2 = STRING: METHOD_CANCEL
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.3 = STRING: METHOD_ACK
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.4 = STRING: METHOD_BYE
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.5 = STRING: METHOD_INFO
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.8 = STRING: METHOD_REGISTER
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.9 = STRING: METHOD_MESSAGE
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.10 = STRING: METHOD_SUBSCRIBE
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.11 = STRING: METHOD_NOTIFY
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.12 = STRING: METHOD_PRACK
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.13 = STRING: METHOD_REFER
OPENSER-SIP-COMMON-MIB::openserSIPMethodName.14 = STRING: METHOD_PUBLISH
OPENSER-SIP-COMMON-MIB::openserSIPSummaryInRequests.0 = Counter32: 28
OPENSER-SIP-COMMON-MIB::openserSIPSummaryOutRequests.0 = Counter32: 0
OPENSER-SIP-COMMON-MIB::openserSIPSummaryInResponses.0 = Counter32: 0
OPENSER-SIP-COMMON-MIB::openserSIPSummaryOutResponses.0 = Counter32: 28
OPENSER-SIP-COMMON-MIB::openserSIPSummaryTotalTransactions.0 = Counter32: 4
OPENSER-SIP-COMMON-MIB::openserSIPCurrentTransactions.0 = Gauge32: 0
OPENSER-SIP-COMMON-MIB::openserSIPNumUnsupportedUris.0 = Counter32: 0
OPENSER-SIP-COMMON-MIB::openserSIPNumUnsupportedMethods.0 = Counter32: 0
OPENSER-SIP-COMMON-MIB::openserSIPOtherwiseDiscardedMsgs.0 = Counter32: 0
OPENSER-SIP-SERVER-MIB::openserSIPProxyStatefulness.0 = INTEGER: transactionStateful(2)
OPENSER-SIP-SERVER-MIB::openserSIPProxyRecordRoute.0 = INTEGER: true(1)
OPENSER-SIP-SERVER-MIB::openserSIPProxyAuthMethod.0 = BITS: 20 digest(2)
OPENSER-SIP-SERVER-MIB::openserSIPNumProxyRequireFailures.0 = Counter32: 0
OPENSER-SIP-SERVER-MIB::openserSIPRegMaxContactExpiryDuration.0 = Gauge32: 0 seconds
OPENSER-SIP-SERVER-MIB::openserSIPRegMaxUsers.0 = Gauge32: 4294967295
OPENSER-SIP-SERVER-MIB::openserSIPRegCurrentUsers.0 = Gauge32: 0
OPENSER-SIP-SERVER-MIB::openserSIPRegDfltRegActiveInterval.0 = Gauge32: 3600 seconds
OPENSER-SIP-SERVER-MIB::openserSIPUserUri.1 = STRING: DefaultUser
OPENSER-SIP-SERVER-MIB::openserSIPUserUri.3 = STRING: sus21
OPENSER-SIP-SERVER-MIB::openserSIPUserAuthenticationFailures.1 = Counter32: 0
OPENSER-SIP-SERVER-MIB::openserSIPUserAuthenticationFailures.3 = Counter32: 0
OPENSER-SIP-SERVER-MIB::openserSIPContactDisplayName.1.1 = STRING: DefaultUser
OPENSER-SIP-SERVER-MIB::openserSIPContactDisplayName.3.3 = STRING: sip:sus21@146.186.115.180:57044;rinstance=fffd4ead92eef4f3
OPENSER-SIP-SERVER-MIB::openserSIPContactURI.1.1 = STRING: DefaultUser
OPENSER-SIP-SERVER-MIB::openserSIPContactURI.3.3 = STRING: sip:sus21@146.186.115.180:57044;rinstance=fffd4ead92eef4f3
OPENSER-SIP-SERVER-MIB::openserSIPContactLastUpdated.1.1 = STRING: 0-0-0,0:0:0.0
OPENSER-SIP-SERVER-MIB::openserSIPContactLastUpdated.3.3 = STRING: 2009-9-15,14:12:20.0
OPENSER-SIP-SERVER-MIB::openserSIPContactExpiry.1.1 = STRING: 0-0-0,0:0:0.0
OPENSER-SIP-SERVER-MIB::openserSIPContactExpiry.3.3 = STRING: 2009-9-15,15:12:20.0
OPENSER-SIP-SERVER-MIB::openserSIPContactPreference.1.1 = STRING: -0.01
OPENSER-SIP-SERVER-MIB::openserSIPContactPreference.3.3 = STRING: -0.01
OPENSER-SIP-SERVER-MIB::openserSIPRegUserLookupCounter.0 = Counter32: 10
OPENSER-SIP-SERVER-MIB::openserSIPRegAcceptedRegistrations.0 = Counter32: 12
OPENSER-SIP-SERVER-MIB::openserSIPRegRejectedRegistrations.0 = Counter32: 0
OPENSER-MIB::openserMsgQueueDepth.0 = Gauge32: 0
OPENSER-MIB::openserMsgQueueMinorThreshold.0 = INTEGER: -1
OPENSER-MIB::openserMsgQueueMajorThreshold.0 = INTEGER: -1
OPENSER-MIB::openserMsgQueueDepthAlarmStatus.0 = BITS: 00
OPENSER-MIB::openserMsgQueueDepthMinorAlarm.0 = INTEGER: clear(0)
OPENSER-MIB::openserMsgQueueDepthMajorAlarm.0 = INTEGER: clear(0)
OPENSER-MIB::openserCurNumDialogs.0 = Gauge32: 0
OPENSER-MIB::openserCurNumDialogsInProgress.0 = Gauge32: 0
OPENSER-MIB::openserCurNumDialogsInSetup.0 = Gauge32: 0
OPENSER-MIB::openserTotalNumFailedDialogSetups.0 = Counter32: 0
OPENSER-MIB::openserDialogLimitMinorThreshold.0 = INTEGER: -1
OPENSER-MIB::openserDialogLimitMajorThreshold.0 = INTEGER: -1
OPENSER-MIB::openserDialogUsageState.0 = INTEGER: idle(0)
OPENSER-MIB::openserDialogLimitAlarmStatus.0 = BITS: 00
OPENSER-MIB::openserDialogLimitMinorAlarm.0 = INTEGER: clear(0)
OPENSER-MIB::openserDialogLimitMajorAlarm.0 = INTEGER: clear(0)

WRT54G Linksys Router on Steroids

| No Comments | No TrackBacks
Ive had this linksys router for years, in fact its one of the first versions of this model. The problem I had is that it cant handle VoIP calls through it. I tried port forwarding, other SIP clients, STUN, no STUN, you name it.

So the easy thing to do is go out and buy a new Linksys router and be done with it, right? Sure, that will work but this is cheaper, better, faster!  DD-WRT is an open source based linux firmware that you load onto your "stock" linksys router. It basically adds a ton of new features and functionality. The feature that interests me, is the Milkfish sip router module that runs a small version of SER (Sip Express Router). It can run on a bunch of different variants of the linksys WRT54G and other manufacturers too, here's the list.

So here's how I did it:

Goto the supported devices database page and enter your model #. Mine is a WRT54G revision v1.1. According to the database, they recommended the VINT version. So I downloaded the file desribed as "VINTAGE: micro". The micro version has to be loaded first if your router still has the linksys firmware on it. Then you can add the other files later. I chose to load "VINTAGE: voip" later.

Using your web browser, goto the admin interface of your linksys router and do a firmware update. Point the updater to the .bin file you downloaded from dd-wrt. Some good info here on installation. Read that first before you do anything.

When the linksys upgrades and reboots, you will get a new admin interface. The first thing you're supposed to do is a hard reset: Unplug the unit, wait a few minutes. Hold the reset bottom while plugging the power back in. Hold teh reset button for 30 seconds. Done.  

Now you can login as "root", passwd "admin. Look around the web interface and look at all the cool stuff. Most of it is self explanitory or you can read this. You should change the admin password too.

After I did the "micro" firmware upgrade I was able to open up my X-Lite client and successfully register to the Penn State sip server and make test VoIP calls. This was never possible with the original linksys firmware.  Cool!

Now that I had that working, I downloaded the "VINTAGE: voip" file and upgraded the existing firmware. After it reboots, do the whole hard reset thing again. I didnt do this the second time and I had alot of issues...so dont skip that step.

So with the new VoIP firmware and the hard reset completed you can now customize the router to your needs. You can also back the config up once you're done and give it a final reboot to make sure it works.

Enjoy your "new" router.

 

 

Penn State Facebook Group for SIP Softphone

| No Comments | No TrackBacks
I created a facebook group to share ideas, problems, whatever on the SIP softphone project. Anyone can join, post, etc.

I'll post updates, new features, user counts and other interesting stats. Please feel free to ask questions, comments.


Sip-Router.org

| No Comments | No TrackBacks
Have a look at this site here. Looks a step in the right direction for both Kamailio and SER. I just wonder if Opensips will join in too. Opensips has Mediaproxy 2.0 which I'm interested in.  I guess we'll have to wait and see.

Xlite 4.0 Beta

| No Comments | No TrackBacks
I've tried the pre-release of Xlite 4.0 for windows. Seems to work fine for me. They put some banner ads across the bottom which I found annoying. You can download it here.

PSU LDAP Authentication with Openser

| No Comments | No TrackBacks

I've been throwing the idea around about using our Openser sip servers to register users and grab the username and password from PennStates LDAP servers. Doing this allows us not to have to store passwords locally.

I did a quick LDAP search and figured I'd use some preexisting attributes; uid=username and pslanguages=password. This is just an experiment and pslanguages was the only thing that jumped out to me as being sort of unique for my ldap entry. Remember, this is just a test.

First make sure these modules are loaded (openser.cfg):

loadmodule "ldap.so"

loadmodule "auth.so"

Then set the module parameters:

modparam("ldap", "config_file", "/etc/openser/ldap.cfg")

modparam("auth", "username_spec", "$avp(s:username)")

modparam("auth", "password_spec", "$avp(s:password)")

modparam("auth", "calculate_ha1", 1)

Create the /etc/openser/ldap.cfg file:

[psu]

ldap_server_url = "ldap://ldap.psu.edu"

Replace the existing registration portion (openser.cfg) with this:

        if (is_method("REGISTER"))
        {
        if(is_present_hf("Authorization"))
        {
            # ldap search
            if (!ldap_search("ldap://psu/dc=psu,dc=edu?uid,pslanguages?one?(uid=$fU)"))
            {
                switch ($retcode)
                {
                    case -1:
                       # no LDAP entry found
                       sl_send_reply("404", "User Not Found");
                       exit;
                    case -2:
                       # internal error
                       sl_send_reply("500", "Internal server error");
                       exit;
                    default:
                       exit;
                }
            }
            ldap_result("uid/$avp(s:username)");
            ldap_result("pslanguages/$avp(s:password)");
            xlog("L_INFO", "ldap_search: found [$retcode] entries for (uid=$fU)");
            if(!pv_www_authorize(""))
            {
                 www_challenge(""/*realm*/,"0"/*qop*/);
                 exit;
            }
            save("location");
            sl_send_reply("200", "ok");
            exit;
        } else {
            www_challenge("","0");
            exit;


This registration code will compare the username portion of the URI ($fU) with the uid attribute in LDAP. When it finds a match, it will challenge the registration and compare the password with the pslanguages attribute in LDAP. If successful, the sip users contact info will be stored on the opensers "location" table. In other words, you're registered.

If there is no matching username in LDAP, the client gets a 404 "User not found". If the openser server cannot communicate with LDAP, you get a 500 "Internal server error".

Then restart openser...

service openser restart

Now I use my xlite client and register with my PSU username (sus21) and use my 2nd language as the password (German), and now I'm registered.

xlitereg.png







Giving this blog thing a whirl...

| No Comments

Well after months of making fun of my coworkers who blog, I figured that I'd give it a shot. So I hope you enjoy the ride! See you later bye.

Recent Comments

  • SVEN B SCHULZ: As yes, good catch. Not by default, but that can read more
  • Bill: Does Kamailio include the Remote-Party-ID field also, by default? If read more

Recent Assets

  • cucmsiptrunk.png
  • cucmunity.png

Find recent content on the main index or look in the archives to find all content.