浏览代码

Merge branch 'master' into websocket

* master:
  modules/lcr: Fixed to/from_gw tests when proto parameter is 0 (ANY)
  cdp_avp: added README file
  CDP: Fixed README
  CDP: A few fixes to docs and location of image files - cleaner organisation
  new modules: CDP (C Diameter Peer) and CDP_AVP 	- These modules were originally written by Fraunhofer and have been 	  ported to Kamailio, with some minor additions and improvements. Examples 	  on using the modules to come shortly - diameter_rx, diameter_ro, etc
Peter Dunkley 13 年之前
父节点
当前提交
1792586578
共有 100 个文件被更改,包括 23729 次插入0 次删除
  1. 12 0
      modules/cdp/Makefile
  2. 845 0
      modules/cdp/README
  3. 114 0
      modules/cdp/acceptor.c
  4. 50 0
      modules/cdp/acceptor.h
  5. 108 0
      modules/cdp/api_process.c
  6. 76 0
      modules/cdp/api_process.h
  7. 873 0
      modules/cdp/authstatemachine.c
  8. 64 0
      modules/cdp/authstatemachine.h
  9. 107 0
      modules/cdp/cdp_load.c
  10. 127 0
      modules/cdp/cdp_load.h
  11. 228 0
      modules/cdp/config.c
  12. 145 0
      modules/cdp/config.h
  13. 100 0
      modules/cdp/configdtd.h
  14. 113 0
      modules/cdp/configexample/ConfigExample.xml
  15. 475 0
      modules/cdp/configparser.c
  16. 288 0
      modules/cdp/diameter.h
  17. 208 0
      modules/cdp/diameter_api.h
  18. 752 0
      modules/cdp/diameter_avp.c
  19. 561 0
      modules/cdp/diameter_code_avp.h
  20. 136 0
      modules/cdp/diameter_code_result.h
  21. 358 0
      modules/cdp/diameter_comm.c
  22. 59 0
      modules/cdp/diameter_epc.h
  23. 62 0
      modules/cdp/diameter_epc_code_app.h
  24. 932 0
      modules/cdp/diameter_epc_code_avp.h
  25. 117 0
      modules/cdp/diameter_epc_code_cmd.h
  26. 71 0
      modules/cdp/diameter_epc_code_result.h
  27. 109 0
      modules/cdp/diameter_ims.h
  28. 58 0
      modules/cdp/diameter_ims_code_app.h
  29. 488 0
      modules/cdp/diameter_ims_code_avp.h
  30. 91 0
      modules/cdp/diameter_ims_code_cmd.h
  31. 98 0
      modules/cdp/diameter_ims_code_result.h
  32. 617 0
      modules/cdp/diameter_msg.c
  33. 480 0
      modules/cdp/diameter_peer.c
  34. 72 0
      modules/cdp/diameter_peer.h
  35. 4 0
      modules/cdp/doc/Makefile
  36. 二进制
      modules/cdp/doc/RFC3588.vsd
  37. 54 0
      modules/cdp/doc/cdp.xml
  38. 274 0
      modules/cdp/doc/cdp_admin.xml
  39. 682 0
      modules/cdp/doc/cdp_devel.xml
  40. 68 0
      modules/cdp/doc/cdp_faq.xml
  41. 108 0
      modules/cdp/globals.c
  42. 74 0
      modules/cdp/globals.h
  43. 二进制
      modules/cdp/images/RFC3588_acct_state_machine_client.png
  44. 二进制
      modules/cdp/images/RFC3588_acct_state_machine_server.png
  45. 二进制
      modules/cdp/images/RFC3588_auth_state_machine_client.png
  46. 二进制
      modules/cdp/images/RFC3588_auth_state_machine_server.png
  47. 二进制
      modules/cdp/images/RFC3588_peer_state_machine_1.png
  48. 二进制
      modules/cdp/images/RFC3588_peer_state_machine_2.png
  49. 211 0
      modules/cdp/mod.c
  50. 54 0
      modules/cdp/mod.h
  51. 109 0
      modules/cdp/peer.c
  52. 128 0
      modules/cdp/peer.h
  53. 346 0
      modules/cdp/peermanager.c
  54. 78 0
      modules/cdp/peermanager.h
  55. 1240 0
      modules/cdp/peerstatemachine.c
  56. 72 0
      modules/cdp/peerstatemachine.h
  57. 1148 0
      modules/cdp/receiver.c
  58. 91 0
      modules/cdp/receiver.h
  59. 182 0
      modules/cdp/routing.c
  60. 51 0
      modules/cdp/routing.h
  61. 93 0
      modules/cdp/sem.h
  62. 671 0
      modules/cdp/session.c
  63. 253 0
      modules/cdp/session.h
  64. 236 0
      modules/cdp/tcp_accept.c
  65. 51 0
      modules/cdp/tcp_accept.h
  66. 221 0
      modules/cdp/timer.c
  67. 78 0
      modules/cdp/timer.h
  68. 244 0
      modules/cdp/transaction.c
  69. 91 0
      modules/cdp/transaction.h
  70. 67 0
      modules/cdp/utils.h
  71. 332 0
      modules/cdp/worker.c
  72. 102 0
      modules/cdp/worker.h
  73. 10 0
      modules/cdp_avp/Makefile
  74. 1688 0
      modules/cdp_avp/README
  75. 134 0
      modules/cdp_avp/avp_add.c
  76. 73 0
      modules/cdp_avp/avp_add.h
  77. 114 0
      modules/cdp_avp/avp_get.c
  78. 74 0
      modules/cdp_avp/avp_get.h
  79. 244 0
      modules/cdp_avp/avp_get_base_data_format.c
  80. 123 0
      modules/cdp_avp/avp_get_base_data_format.h
  81. 60 0
      modules/cdp_avp/avp_new.c
  82. 58 0
      modules/cdp_avp/avp_new.h
  83. 217 0
      modules/cdp_avp/avp_new_base_data_format.c
  84. 174 0
      modules/cdp_avp/avp_new_base_data_format.h
  85. 63 0
      modules/cdp_avp/base.c
  86. 430 0
      modules/cdp_avp/base.h
  87. 63 0
      modules/cdp_avp/ccapp.c
  88. 463 0
      modules/cdp_avp/ccapp.h
  89. 4 0
      modules/cdp_avp/doc/Makefile
  90. 54 0
      modules/cdp_avp/doc/cdp_avp.xml
  91. 93 0
      modules/cdp_avp/doc/cdp_avp_admin.xml
  92. 1018 0
      modules/cdp_avp/doc/cdp_avp_devel.xml
  93. 68 0
      modules/cdp_avp/doc/cdp_avp_faq.xml
  94. 100 0
      modules/cdp_avp/epcapp.c
  95. 931 0
      modules/cdp_avp/epcapp.h
  96. 69 0
      modules/cdp_avp/get_reference.h
  97. 7 0
      modules/cdp_avp/get_reference.sh
  98. 64 0
      modules/cdp_avp/imsapp.c
  99. 486 0
      modules/cdp_avp/imsapp.h
  100. 440 0
      modules/cdp_avp/macros.h

+ 12 - 0
modules/cdp/Makefile

@@ -0,0 +1,12 @@
+include ../../Makefile.defs
+auto_gen=
+NAME=cdp.so
+
+DEFS+=-DSER_MOD_INTERFACE
+
+
+DEFS += -I/usr/include/libxml2 
+LIBS += -L$(LOCALBASE)/lib -lxml2 -lrt
+
+include ../../Makefile.modules
+

+ 845 - 0
modules/cdp/README

@@ -0,0 +1,845 @@
+cdp Module
+
+Dragos Vingarzan
+
+   Fraunhofer
+
+Edited by
+
+Jason Penton
+
+Edited by
+
+Richard Good
+
+   Copyright © 2006 FhG Fokus
+
+   Copyright © 2012 Smile Communications
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. How it works
+        3. Dependencies
+
+              3.1. Kamailio Modules
+              3.2. External Libraries or Applications
+
+        4. Parameters
+
+              4.1. config_file (string)
+              4.2. latency_threshold (int)
+
+        5. Functions
+
+              5.1.
+
+        6. Configuration Examples
+
+              6.1. DiameterPeer.xml example
+              6.2.
+
+   2. Developer Guide
+
+        1. Available Functions
+
+              1.1. load_cdp(struct cdp_binds *cdpb)
+              1.2. AAACreateRequest(AAAApplicationId app_id,
+                      AAACommandCode command_code, AAAMsgFlag flags,
+                      AAASession *session)
+
+              1.3. AAACreateResponse(AAAMessage *request)
+              1.4. AAAReturnCode AAAFreeMessage(AAAMessage **msg)
+              1.5. AAAReturnCode AAASendMessage(AAAMessage *message,
+                      AAATransactionCallback_f *callback_f, void
+                      *callback_param)
+
+              1.6. AAAReturnCode AAASendMessageToPeer(AAAMessage *message,
+                      str *peer_id, AAATransactionCallback_f *callback_f,
+                      void *callback_param)
+
+              1.7. AAAMessage* AAASendRecvMessage(AAAMessage *message)
+              1.8. AAAMessage* AAASendRecvMessageToPeer(AAAMessage
+                      *message, str *peer_id)
+
+              1.9. AAASession* AAACreateSession(void *generic_data)
+              1.10. AAASession* AAAMakeSession(int app_id,int type,str
+                      session_id)
+
+              1.11. AAASession* AAAGetSession(str id)
+              1.12. AAADropSession(AAASession *s)
+              1.13. AAASessionLock(unsigned int hash)
+              1.14. AAASessionUnLock(unsigned int hash)
+              1.15. AAASession* AAACreateClientAuthSession(int
+                      is_statefull,AAASessionCallback_f *cb,void
+                      *generic_data)
+
+              1.16. AAASession* AAACreateServerAuthSession(AAMessage
+                      *msg,int is_statefull,AAASessionCallback_f *cb,void
+                      *generic_data)
+
+              1.17. AAASession* AAAGetAuthSession(str id)
+              1.18. AAADropAuthSession(AAASession *s)
+              1.19. AAATerminateAuthSession(AAASession *s)
+              1.20. AAATransaction* AAACreateTransaction(AAAApplicationId
+                      app_id,AAACommandCode cmd_code)
+
+              1.21. int AAADropTransaction(AAATransaction *trans)
+              1.22. AAA_AVP* AAACreateAVP(AAA_AVPCode code, AAA_AVPFlag
+                      flags, AAAVendorId vendorId, char *data, size_t
+                      length, AVPDataStatus data_status)
+
+              1.23. AAAReturnCode AAAAddAVPToMessage(AAAMessage *msg,
+                      AAA_AVP *avp, AAA_AVP *position)
+
+              1.24. AAA_AVP* AAAFindMatchingAVP(AAAMessage *msg, AAA_AVP
+                      *startAvp, AAA_AVPCode avpCode, AAAVendorId
+                      vendorId, AAASearchType searchType)
+
+              1.25. AAA_AVP * AAAGetNextAVP(AAA_AVP *avp)
+              1.26. AAAReturnCode AAAFreeAVP(AAA_AVP **avp)
+              1.27. str AAAGroupAVPS(AAA_AVP_LIST avps)
+              1.28. AAA_AVP_LIST AAAUnGroupAVPS(str buf)
+              1.29. AAA_AVP* AAAFindMatchingAVPList(AAA_AVP_LIST avpList,
+                      AAA_AVP *startAvp, AAA_AVPCode avpCode, AAAVendorId
+                      vendorId, AAASearchType searchType)
+
+              1.30. AAAFreeAVPList(AAA_AVP_LIST *avpList)
+              1.31. int AAAAddRequestHandler(AAARequestHandler_f *f,void
+                      *param)
+
+              1.32. int AAAAddResponseHandler(AAAResponseHandler_f *f,void
+                      *param)
+
+   3. Frequently Asked Questions
+
+   List of Examples
+
+   1.1. Set config_file parameter
+   1.2. Set latency_threshold parameter
+   1.3. DiameterPeer.xml example
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. How it works
+   3. Dependencies
+
+        3.1. Kamailio Modules
+        3.2. External Libraries or Applications
+
+   4. Parameters
+
+        4.1. config_file (string)
+        4.2. latency_threshold (int)
+
+   5. Functions
+
+        5.1.
+
+   6. Configuration Examples
+
+        6.1. DiameterPeer.xml example
+        6.2.
+
+1. Overview
+
+   CDP (C Diameter Peer) allows Diameter communication to and from
+   sip-router/kamailio. Most of the code is inherited from DISC
+   http://developer.berlios.de/projects/disc/ and OpenIMS and modified for
+   use within Kamailio. A few improvements/new functionality has been
+   added along the way, for example, threshold reporting on Diameter calls
+   that are serviced above a certain threshold.
+
+2. How it works
+
+   CDP forks the following processes:
+     * 1 x Timer
+     * 1 x Acceptor
+     * k x Workers (k configurable through configuration)
+     * i x Receivers (one for each peer plus one for unknown peers)
+
+   CDP is really only an API and offers all of its methods to other
+   modules. No commands are made available to the main Kamailio
+   configuration file. The exported API can be seen in mod.c. The Full
+   Diameter API is in diameter.h and diameter_api.h. IMS-specific
+   constants can be found in diameter_ims.h. The protocol coding is
+   implemented in diameter_avp.c and diameter_msg.c. Diameter state
+   machine is implemented in peerstatemachine.c - there is one of these
+   for each peer which maintains all protocol/application state for each
+   peer. peermanager.c is responsible for peer administration. Diameter
+   transactions are implemented in transaction.c.
+
+   There are 2 configuration areas for CDP. Firstly it must be loaded and
+   conifugred in the Kamailio.cfg file (this is the normal task associated
+   with Kamailio modules). Then, an XML file is required to configure
+   various Diameter parameters and all related peers and the associated
+   routes.
+
+3. Dependencies
+
+   3.1. Kamailio Modules
+   3.2. External Libraries or Applications
+
+3.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * None.
+
+3.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * None.
+
+4. Parameters
+
+   4.1. config_file (string)
+   4.2. latency_threshold (int)
+
+4.1. config_file (string)
+
+   This is the location of the XML configuration file.
+
+   Default value is “DiameterPeer.xml”.
+
+   Example 1.1. Set config_file parameter
+...
+modparam("cdp", "config_file", "/etc/kamailio/diametercfg.xml")
+...
+
+4.2. latency_threshold (int)
+
+   The time in ms above which a log error is wrtten to log file for long
+   CDP transactions.
+
+   Default value is “500”.
+
+   Example 1.2. Set latency_threshold parameter
+...
+modparam("cdp", "latency_threshold", 1000)
+...
+
+5. Functions
+
+   5.1.
+
+   No functions available from configuraion. See API for internal
+   functions.
+
+6. Configuration Examples
+
+   6.1. DiameterPeer.xml example
+   6.2.
+
+6.1. DiameterPeer.xml example
+
+   This is an example CDP configuration file. The location of this file is
+   confiured as a CDP parameter (config_file) - See section 4.1 Above
+
+   Example 1.3. DiameterPeer.xml example
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ DiameterPeer Parameters
+  - FQDN - FQDN of this peer, as it should apper in the Origin-Host AVP
+  - Realm - Realm of this peer, as it should apper in the Origin-Realm AVP
+  - Vendor_Id - Default Vendor-Id to appear in the Capabilities Exchange
+  - Product_Name - Product Name to appear in the Capabilities Exchange
+  - AcceptUnknownPeers - Whether to accept (1) or deny (0) connections from peer
+s with FQDN
+    not configured below
+  - DropUnknownOnDisconnect - Whether to drop (1) or keep (0) and retry connecti
+ons (until restart)
+    unknown peers in the list of peers after a disconnection.
+  - Tc - Value for the RFC3588 Tc timer - default 30 seconds
+  - Workers - Number of incoming messages processing workers forked processes.
+  - Queue - Length of queue of tasks for the workers:
+     - too small and the incoming messages will be blocked too often;
+     - too large and the senders of incoming messages will have a longer feedbac
+k loop to notice that
+     this Diameter peer is overloaded in processing incoming requests;
+     - a good choice is to have it about 2 times the number of workers. This wil
+l mean that each worker
+     will have about 2 tasks in the queue to process before new incoming message
+s will start to block.
+  - ConnectTimeout - time in seconds to wait for an outbound TCP connection to b
+e established.
+  - TransactionTimeout - time in seconds after which the transaction timeout cal
+lback will be fired,
+    when using transactional processing.
+  - SessionsHashSize - size of the hash-table to use for the Diameter sessions.
+When searching for a
+    session, the time required for this operation will be that of sequential sea
+rching in a list of
+    NumberOfActiveSessions/SessionsHashSize. So higher the better, yet each hash
+slot will consume an
+    extra 2xsizeof(void*) bytes (typically 8 or 16 bytes extra).
+  - DefaultAuthSessionTimeout - default value to use when there is no Authorizat
+ion Session Timeout
+  AVP present.
+  - MaxAuthSessionTimeout - maximum Authorization Session Timeout as a cut-out m
+easure meant to
+  enforce session refreshes.
+
+ -->
+<DiameterPeer
+        FQDN="pcscf.ims.smilecoms.com"
+        Realm="ims.smilecoms.com"
+        Vendor_Id="10415"
+        Product_Name="CDiameterPeer"
+        AcceptUnknownPeers="0"
+        DropUnknownOnDisconnect="1"
+        Tc="30"
+        Workers="4"
+        QueueLength="32"
+        ConnectTimeout="5"
+        TransactionTimeout="5"
+        SessionsHashSize="128"
+        DefaultAuthSessionTimeout="60"
+        MaxAuthSessionTimeout="300"
+>
+
+        <!--
+                Definition of peers to connect to and accept connections from. F
+or each peer found in here
+                a dedicated receiver process will be forked. All other unkwnown
+peers will share a single
+                receiver. NB. you must have a peer definition for each peer list
+ed in the realm routing section
+        -->
+        <Peer FQDN="pcrf1.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+        <Peer FQDN="pcrf2.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+        <Peer FQDN="pcrf3.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+        <Peer FQDN="pcrf4.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+        <Peer FQDN="pcrf5.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+        <Peer FQDN="pcrf6.ims.smilecoms.com" Realm="ims.smilecoms.com" port="386
+8"/>
+
+        <!--
+                Definition of incoming connection acceptors. If no bind is speci
+fied, the acceptor will bind
+                on all available interfaces.
+        -->
+        <Acceptor port="3868"  />
+        <Acceptor port="3869" bind="127.0.0.1" />
+        <Acceptor port="3870" bind="192.168.1.1" />
+
+        <!--
+                Definition of Auth (authorization) and Acct (accounting) support
+ed applications. This
+                information is sent as part of the Capabilities Exchange procedu
+res on connecting to
+                peers. If no common application is found, the peers will disconn
+ect. Messages will only
+                be sent to a peer if that peer actually has declared support for
+ the application id of
+                the message.
+        -->
+        <Acct id="16777216" vendor="10415" />
+        <Acct id="16777216" vendor="0" />
+        <Auth id="16777216" vendor="10415"/>
+        <Auth id="16777216" vendor="0" />
+
+        <!--
+                Supported Vendor IDs - list of values which will be sent in the
+CER/CEA in the
+                Supported-Vendor-ID AVPs
+        -->
+        <SupportedVendor vendor="10415" />
+
+        <!--
+                Realm routing definition.
+                Each Realm can have a different table of peers to route towards.
+ In case the Destination
+                Realm AVP contains a Realm not defined here, the DefaultRoute en
+tries will be used.
+
+                Note: In case a message already contains a Destination-Host AVP,
+ Realm Routeing will not be
+                applied.
+                Note: Routing will only happen towards connected and application
+ id supporting peers.
+
+                The metric is used to order the list of prefered peers, while lo
+oking for a connected and
+                application id supporting peer. In the end, of course, just one
+peer will be selected.
+        -->
+        <Realm name="ims.smilecoms.com">
+                <Route FQDN="pcrf1.ims.smilecoms.com" metric="3"/>
+                <Route FQDN="pcrf2.ims.smilecoms.com" metric="5"/>
+        </Realm>
+
+        <Realm name="temp.ims.smilecoms.com">
+                <Route FQDN="pcrf3.ims.smilecoms.com" metric="7"/>
+                <Route FQDN="pcrf4.ims.smilecoms.com" metric="11"/>
+        </Realm>
+        <DefaultRoute FQDN="pcrf5.ims.smilecoms.com" metric="15"/>
+        <DefaultRoute FQDN="pcrf6.ims.smilecoms.com" metric="13"/>
+
+
+</DiameterPeer>
+
+Chapter 2. Developer Guide
+
+   Table of Contents
+
+   1. Available Functions
+
+        1.1. load_cdp(struct cdp_binds *cdpb)
+        1.2. AAACreateRequest(AAAApplicationId app_id, AAACommandCode
+                command_code, AAAMsgFlag flags, AAASession *session)
+
+        1.3. AAACreateResponse(AAAMessage *request)
+        1.4. AAAReturnCode AAAFreeMessage(AAAMessage **msg)
+        1.5. AAAReturnCode AAASendMessage(AAAMessage *message,
+                AAATransactionCallback_f *callback_f, void
+                *callback_param)
+
+        1.6. AAAReturnCode AAASendMessageToPeer(AAAMessage *message, str
+                *peer_id, AAATransactionCallback_f *callback_f, void
+                *callback_param)
+
+        1.7. AAAMessage* AAASendRecvMessage(AAAMessage *message)
+        1.8. AAAMessage* AAASendRecvMessageToPeer(AAAMessage *message, str
+                *peer_id)
+
+        1.9. AAASession* AAACreateSession(void *generic_data)
+        1.10. AAASession* AAAMakeSession(int app_id,int type,str
+                session_id)
+
+        1.11. AAASession* AAAGetSession(str id)
+        1.12. AAADropSession(AAASession *s)
+        1.13. AAASessionLock(unsigned int hash)
+        1.14. AAASessionUnLock(unsigned int hash)
+        1.15. AAASession* AAACreateClientAuthSession(int
+                is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+        1.16. AAASession* AAACreateServerAuthSession(AAMessage *msg,int
+                is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+        1.17. AAASession* AAAGetAuthSession(str id)
+        1.18. AAADropAuthSession(AAASession *s)
+        1.19. AAATerminateAuthSession(AAASession *s)
+        1.20. AAATransaction* AAACreateTransaction(AAAApplicationId
+                app_id,AAACommandCode cmd_code)
+
+        1.21. int AAADropTransaction(AAATransaction *trans)
+        1.22. AAA_AVP* AAACreateAVP(AAA_AVPCode code, AAA_AVPFlag flags,
+                AAAVendorId vendorId, char *data, size_t length,
+                AVPDataStatus data_status)
+
+        1.23. AAAReturnCode AAAAddAVPToMessage(AAAMessage *msg, AAA_AVP
+                *avp, AAA_AVP *position)
+
+        1.24. AAA_AVP* AAAFindMatchingAVP(AAAMessage *msg, AAA_AVP
+                *startAvp, AAA_AVPCode avpCode, AAAVendorId vendorId,
+                AAASearchType searchType)
+
+        1.25. AAA_AVP * AAAGetNextAVP(AAA_AVP *avp)
+        1.26. AAAReturnCode AAAFreeAVP(AAA_AVP **avp)
+        1.27. str AAAGroupAVPS(AAA_AVP_LIST avps)
+        1.28. AAA_AVP_LIST AAAUnGroupAVPS(str buf)
+        1.29. AAA_AVP* AAAFindMatchingAVPList(AAA_AVP_LIST avpList,
+                AAA_AVP *startAvp, AAA_AVPCode avpCode, AAAVendorId
+                vendorId, AAASearchType searchType)
+
+        1.30. AAAFreeAVPList(AAA_AVP_LIST *avpList)
+        1.31. int AAAAddRequestHandler(AAARequestHandler_f *f,void *param)
+        1.32. int AAAAddResponseHandler(AAAResponseHandler_f *f,void
+                *param)
+
+1. Available Functions
+
+   1.1. load_cdp(struct cdp_binds *cdpb)
+   1.2. AAACreateRequest(AAAApplicationId app_id, AAACommandCode
+          command_code, AAAMsgFlag flags, AAASession *session)
+
+   1.3. AAACreateResponse(AAAMessage *request)
+   1.4. AAAReturnCode AAAFreeMessage(AAAMessage **msg)
+   1.5. AAAReturnCode AAASendMessage(AAAMessage *message,
+          AAATransactionCallback_f *callback_f, void *callback_param)
+
+   1.6. AAAReturnCode AAASendMessageToPeer(AAAMessage *message, str
+          *peer_id, AAATransactionCallback_f *callback_f, void
+          *callback_param)
+
+   1.7. AAAMessage* AAASendRecvMessage(AAAMessage *message)
+   1.8. AAAMessage* AAASendRecvMessageToPeer(AAAMessage *message, str
+          *peer_id)
+
+   1.9. AAASession* AAACreateSession(void *generic_data)
+   1.10. AAASession* AAAMakeSession(int app_id,int type,str session_id)
+   1.11. AAASession* AAAGetSession(str id)
+   1.12. AAADropSession(AAASession *s)
+   1.13. AAASessionLock(unsigned int hash)
+   1.14. AAASessionUnLock(unsigned int hash)
+   1.15. AAASession* AAACreateClientAuthSession(int
+          is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+   1.16. AAASession* AAACreateServerAuthSession(AAMessage *msg,int
+          is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+   1.17. AAASession* AAAGetAuthSession(str id)
+   1.18. AAADropAuthSession(AAASession *s)
+   1.19. AAATerminateAuthSession(AAASession *s)
+   1.20. AAATransaction* AAACreateTransaction(AAAApplicationId
+          app_id,AAACommandCode cmd_code)
+
+   1.21. int AAADropTransaction(AAATransaction *trans)
+   1.22. AAA_AVP* AAACreateAVP(AAA_AVPCode code, AAA_AVPFlag flags,
+          AAAVendorId vendorId, char *data, size_t length, AVPDataStatus
+          data_status)
+
+   1.23. AAAReturnCode AAAAddAVPToMessage(AAAMessage *msg, AAA_AVP *avp,
+          AAA_AVP *position)
+
+   1.24. AAA_AVP* AAAFindMatchingAVP(AAAMessage *msg, AAA_AVP *startAvp,
+          AAA_AVPCode avpCode, AAAVendorId vendorId, AAASearchType
+          searchType)
+
+   1.25. AAA_AVP * AAAGetNextAVP(AAA_AVP *avp)
+   1.26. AAAReturnCode AAAFreeAVP(AAA_AVP **avp)
+   1.27. str AAAGroupAVPS(AAA_AVP_LIST avps)
+   1.28. AAA_AVP_LIST AAAUnGroupAVPS(str buf)
+   1.29. AAA_AVP* AAAFindMatchingAVPList(AAA_AVP_LIST avpList, AAA_AVP
+          *startAvp, AAA_AVPCode avpCode, AAAVendorId vendorId,
+          AAASearchType searchType)
+
+   1.30. AAAFreeAVPList(AAA_AVP_LIST *avpList)
+   1.31. int AAAAddRequestHandler(AAARequestHandler_f *f,void *param)
+   1.32. int AAAAddResponseHandler(AAAResponseHandler_f *f,void *param)
+
+1.1. load_cdp(struct cdp_binds *cdpb)
+
+   Find and load the CDiameterPeer function bindings
+
+   Meaning of the parameters is as follows:
+     * struct cdp_binds *cdpb - structure holding function pointers
+
+1.2. AAACreateRequest(AAAApplicationId app_id, AAACommandCode command_code,
+AAAMsgFlag flags, AAASession *session)
+
+   Create a Diameter request
+
+   Meaning of the parameters is as follows:
+     * AAAApplicationId app_id - structure holding function pointers
+     * AAACommandCode command_code - command code for the message
+     * AAAMsgFlag flags - flags to be set
+     * AAASession *session - session id to be set
+
+1.3. AAACreateResponse(AAAMessage *request)
+
+   Create a Diameter response to a give request
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *request - request that this response is for
+
+1.4. AAAReturnCode AAAFreeMessage(AAAMessage **msg)
+
+   Free up memory used by Diameter message
+
+   Meaning of the parameters is as follows:
+     * AAAMessage **msg - pointer to the pointer containing the message
+
+1.5. AAAReturnCode AAASendMessage(AAAMessage *message,
+AAATransactionCallback_f *callback_f, void *callback_param)
+
+   Send Diameter message asynchronously
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *message - request message to be sent
+     * AAATransactionCallback_f *callback_f - When the response is
+       received, the callback_f(callback_param,...) is called
+     * void *callback_param - generic param for callback
+
+1.6. AAAReturnCode AAASendMessageToPeer(AAAMessage *message, str *peer_id,
+AAATransactionCallback_f *callback_f, void *callback_param)
+
+   Send Diameter message to specific peer asynchronously
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *message - request message to send
+     * str *peer_id - FQDN of peer to send to
+     * AAATransactionCallback_f *callback_f - When the response is
+       received, the callback_f(callback_param,...) is called
+     * void *callback_param - generic param for callback
+
+1.7. AAAMessage* AAASendRecvMessage(AAAMessage *message)
+
+   Send Diameter message synchronously. This blocks until a response is
+   received or a transactional time-out happens.
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *message - request message to be sent
+
+1.8. AAAMessage* AAASendRecvMessageToPeer(AAAMessage *message, str *peer_id)
+
+   Send Diameter message to specific peer synchronously. This blocks until
+   a response is received or a transactional time-out happens.
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *message - request message to send
+     * str *peer_id - FQDN of peer to send to.
+
+1.9. AAASession* AAACreateSession(void *generic_data)
+
+   Create a generic Diameter session
+
+   Meaning of the parameters is as follows:
+     * void *generic_data - data to be save to session, useful for
+       attaching app specific data to the session
+
+1.10. AAASession* AAAMakeSession(int app_id,int type,str session_id)
+
+   Create a Diameter session using already known params
+
+   Meaning of the parameters is as follows:
+     * int app_id - app id to use
+     * int type - type of session
+     * str session_id - session ID
+
+1.11. AAASession* AAAGetSession(str id)
+
+   Retrieve a Diameter session. Returns with a lock on AAASession->hash -
+   Unlock when done working with result
+
+   Meaning of the parameters is as follows:
+     * str id - Diameter session ID to search for
+
+1.12. AAADropSession(AAASession *s)
+
+   Drop a Diameter session - deallocating all memory
+
+   Meaning of the parameters is as follows:
+     * AAASession *s - session to drop
+
+1.13. AAASessionLock(unsigned int hash)
+
+   Lock a Diameter session (hash table row)
+
+   Meaning of the parameters is as follows:
+     * unsigned int hash - hash to lock
+
+1.14. AAASessionUnLock(unsigned int hash)
+
+   Unlock a Diameter session (hash table row)
+
+   Meaning of the parameters is as follows:
+     * unsigned int hash - hash to unlock
+
+1.15. AAASession* AAACreateClientAuthSession(int
+is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+   Creates an Authorisation session for the Client. It generate a new ID
+   and adds to the list of CDP sessions. Returns with a lock on
+   AAASession->hash
+
+   Meaning of the parameters is as follows:
+     * int is_statefull - is session stateful or not
+     * AAASessionCallback_f *cb - callback function on session state
+       change
+     * void *generic_data - generic callback data
+
+1.16. AAASession* AAACreateServerAuthSession(AAMessage *msg,int
+is_statefull,AAASessionCallback_f *cb,void *generic_data)
+
+   Create authorisation session for the Server. Generates a new ID and add
+   to CDP list of sessions. Returns with a lock on AAASession->hash.
+
+   Meaning of the parameters is as follows:
+     * AAMessage *msg - request message from which to create server
+       session
+     * int is_statefull - is session stateful or not
+     * AAASessionCallback_f *cb - callback function on session state
+       change
+     * void *generic_data - generic callback data
+
+1.17. AAASession* AAAGetAuthSession(str id)
+
+   Look for an authorisation session. Returns with lock on
+   AAASession->hash
+
+   Meaning of the parameters is as follows:
+     * str id - ID of Auth session to search for
+
+1.18. AAADropAuthSession(AAASession *s)
+
+   Deallocates the memory taken by a Authorisation session
+
+   Meaning of the parameters is as follows:
+     * AAASession *s - Session to drop and deallocate memory for
+
+1.19. AAATerminateAuthSession(AAASession *s)
+
+   Sends a service terminated event to the session
+
+   Meaning of the parameters is as follows:
+     * AAASession *s - authhorisation session to terminate
+
+1.20. AAATransaction* AAACreateTransaction(AAAApplicationId
+app_id,AAACommandCode cmd_code)
+
+   Create a AAATransaction for the given request
+
+   Meaning of the parameters is as follows:
+     * AAAApplicationId app_id - ID of the request's application
+     * AAACommandCode cmd_code - request's code
+
+1.21. int AAADropTransaction(AAATransaction *trans)
+
+   Deallocates the memory taken by AAA transaction
+
+   Meaning of the parameters is as follows:
+     * AAATransaction *trans - transaction to free
+
+1.22. AAA_AVP* AAACreateAVP(AAA_AVPCode code, AAA_AVPFlag flags, AAAVendorId
+vendorId, char *data, size_t length, AVPDataStatus data_status)
+
+   Create new AVP and return pointer to it
+
+   Meaning of the parameters is as follows:
+     * AAA_AVPCode code - code for new AVP
+     * AAA_AVPFlag flags - flags to set
+     * AAAVendorId vendorId - vendor ID for AVP
+     * char *data - generic payload data
+     * size_t length - length of payload data
+     * AVPDataStatus data_status - what to do with the payload, duplicate,
+       free with message, etc
+
+1.23. AAAReturnCode AAAAddAVPToMessage(AAAMessage *msg, AAA_AVP *avp, AAA_AVP
+*position)
+
+   Find and load the CDiameterPeer function bindings
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *msg - the message to add to
+     * AAA_AVP *avp - the AVP to add
+     * AAA_AVP *position - AVP to add after. if NULL, we add at beginning
+
+1.24. AAA_AVP* AAAFindMatchingAVP(AAAMessage *msg, AAA_AVP *startAvp,
+AAA_AVPCode avpCode, AAAVendorId vendorId, AAASearchType searchType)
+
+   Find and load the CDiameterPeer function bindings
+
+   Meaning of the parameters is as follows:
+     * AAAMessage *msg - the message to search in
+     * AAA_AVP *startAvp - at which AVP to start the search. usefull for
+       looking for more of the same name
+     * AAA_AVPCode avpCode - AVP code to match
+     * AAAVendorId vendorId - AVP vendor ID to match
+     * AAASearchType searchType - look forward or backward
+
+1.25. AAA_AVP * AAAGetNextAVP(AAA_AVP *avp)
+
+   Find and load the CDiameterPeer function bindings
+
+   Meaning of the parameters is as follows:
+     * AAA_AVP *avp - reference AVP
+
+1.26. AAAReturnCode AAAFreeAVP(AAA_AVP **avp)
+
+   Find and load the CDiameterPeer function bindings
+
+   Meaning of the parameters is as follows:
+     * AAA_AVP **avp - pointer memory to be freed
+
+1.27. str AAAGroupAVPS(AAA_AVP_LIST avps)
+
+   Groups a list of AVPS into a data buffer
+
+   Meaning of the parameters is as follows:
+     * AAA_AVP_LIST avps - list of AVPS to group
+
+1.28. AAA_AVP_LIST AAAUnGroupAVPS(str buf)
+
+   Ungroup a data buffer into a list of AVPs
+
+   Meaning of the parameters is as follows:
+     * str buf - payload to ungroup list from
+
+1.29. AAA_AVP* AAAFindMatchingAVPList(AAA_AVP_LIST avpList, AAA_AVP
+*startAvp, AAA_AVPCode avpCode, AAAVendorId vendorId, AAASearchType
+searchType)
+
+   Find an AVP in an AVP list
+
+   Meaning of the parameters is as follows:
+     * AAA_AVP_LIST avpList - AVP list to search
+     * AAA_AVP *startAvp - where to start the search
+     * AAA_AVPCode avpCode - AVP code to match
+     * AAAVendorId vendorId - vendor ID to match
+     * AAASearchType searchType - forwards or backwards
+
+1.30. AAAFreeAVPList(AAA_AVP_LIST *avpList)
+
+   Free AVP list and all its members
+
+   Meaning of the parameters is as follows:
+     * AAA_AVP_LIST *avpList - list to be freed
+
+1.31. int AAAAddRequestHandler(AAARequestHandler_f *f,void *param)
+
+   add a #AAARequestHandler_f callback to request being received
+
+   Meaning of the parameters is as follows:
+     * AAARequestHandler_f *f - callback function to be called on incoming
+       requests
+     * void *param - generic data passed to callback function
+
+1.32. int AAAAddResponseHandler(AAAResponseHandler_f *f,void *param)
+
+   add a #AAAResponseHandler_f callback to responses being received
+
+   Meaning of the parameters is as follows:
+     * AAAResponseHandler_f *f - callback function to be called on
+       incoming responses
+     * void *param - generic data to be bassed to callback function
+
+Chapter 3. Frequently Asked Questions
+
+   3.1. Where can I find more about Kamailio?
+   3.2. Where can I post a question about this module?
+   3.3. How can I report a bug?
+
+   3.1.
+
+       Where can I find more about Kamailio?
+
+       Take a look at http://www.kamailio.org/.
+
+   3.2.
+
+       Where can I post a question about this module?
+
+       First at all check if your question was already answered on one of our
+       mailing lists:
+         * User Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
+         * Developer Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
+
+       E-mails regarding any stable Kamailio release should be sent to
+       <[email protected]> and e-mails regarding development
+       versions should be sent to <[email protected]>.
+
+       If you want to keep the mail private, send it to
+       <[email protected]>.
+
+   3.3.
+
+       How can I report a bug?
+
+       Please follow the guidelines provided at:
+       http://sip-router.org/tracker.

+ 114 - 0
modules/cdp/acceptor.c

@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+#include "acceptor.h"
+#include "utils.h"
+#include "globals.h"
+#include "tcp_accept.h"
+#include "config.h"
+#include "worker.h"
+
+
+/* defined in ../diameter_peer.c */
+int dp_add_pid(pid_t pid);
+void dp_del_pid(pid_t pid);
+
+/**
+ * Called from diameter_peer_start, after a process was forked for this.
+ * - opens the listening sockets and binds them to the addresses.
+ * @param cfg - the dp_config file, which contains the list of acceptors
+ * @returns - never. As this is forked, when finished it is expected to exit on itself.
+ */
+void acceptor_process(dp_config *cfg)
+{
+	int i,k;
+	unsigned int sock;
+	
+	LM_INFO("Acceptor process starting up...\n");
+	listening_socks = pkg_malloc((cfg->acceptors_cnt+1)*sizeof(int));
+	if (!listening_socks){
+		LOG_NO_MEM("pkg",(cfg->acceptors_cnt+1)*sizeof(int));
+		goto done;
+	}
+	memset(listening_socks,0,(cfg->acceptors_cnt+1)*sizeof(int));	
+	k=0;
+	for(i=0;i<cfg->acceptors_cnt;i++)
+		if (create_socket(cfg->acceptors[i].port,cfg->acceptors[i].bind,&sock)){
+			listening_socks[k++]=sock;			
+		}	
+
+	
+	LM_INFO("Acceptor opened sockets. Entering accept loop ...\n");		
+	accept_loop();
+
+	for(i=0;listening_socks[i];i++)
+		close(listening_socks[i]);
+	
+	if (listening_socks) pkg_free(listening_socks);
+#ifdef CDP_FOR_SER
+#else
+#ifdef PKG_MALLOC
+	#ifdef PKG_MALLOC
+		LM_DBG("Acceptor Memory status (pkg):\n");
+		//pkg_status();
+		#ifdef pkg_sums
+			pkg_sums();
+		#endif 
+	#endif
+#endif
+		dp_del_pid(getpid());		
+#endif		
+done:		
+	LM_INFO("Acceptor process finished\n");
+	exit(0);
+}

+ 50 - 0
modules/cdp/acceptor.h

@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __ACCEPTOR_H
+#define __ACCEPTOR_H
+
+#include "worker.h"
+#include "config.h"
+
+void acceptor_process(dp_config *cfg);
+
+#endif
+

+ 108 - 0
modules/cdp/api_process.c

@@ -0,0 +1,108 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "api_process.h"
+#include "transaction.h"
+#include "receiver.h"
+#include "peerstatemachine.h"
+
+
+handler_list *handlers = 0; /**< list of handlers */
+gen_lock_t *handlers_lock;	/**< lock for list of handlers */
+
+/**
+ * This callback is added as an internal message listener and used to process
+ * transaction requests. 
+ * - first it calls all the registered handlers for requests and responses
+ * - then it calls the transaction handler
+ * @param p - peer that this message came from
+ * @param msg - the diameter message
+ * @param ptr - not used anymore
+ * @returns 1 always
+ */ 
+int api_callback(peer *p,AAAMessage *msg,void* ptr)
+{
+	cdp_trans_t *t;
+	int auto_drop;	
+	handler *h;
+	handler x;
+	enum handler_types type;
+	AAAMessage *rsp;
+	if (is_req(msg)) type = REQUEST_HANDLER;
+	else type=RESPONSE_HANDLER;
+
+	lock_get(handlers_lock);
+		for(h=handlers->head;h;h=h->next){
+			if (h->type==type){
+				x.handler = h->handler;
+				if (h->type == REQUEST_HANDLER) {
+					lock_release(handlers_lock);
+					rsp = (x.handler.requestHandler)(msg,h->param);
+					if (rsp) {
+						//peer_send_msg(p,rsp);
+						sm_process(p,Send_Message,rsp,0,0);	
+					}
+					lock_get(handlers_lock);
+				}
+				else {
+					lock_release(handlers_lock);
+					(x.handler.responseHandler)(msg,h->param);
+					lock_get(handlers_lock);
+				}
+			}
+		}		
+	lock_release(handlers_lock);
+	
+	if (!is_req(msg)){		
+		/* take care of transactional callback if any */
+		t = cdp_take_trans(msg);
+		if (t){
+			t->ans = msg;
+			auto_drop = t->auto_drop;
+			if (t->cb){
+				(t->cb)(0,*(t->ptr),msg);
+			}
+			if (auto_drop) cdp_free_trans(t);
+		}
+	}
+	return 1;
+}
+
+

+ 76 - 0
modules/cdp/api_process.h

@@ -0,0 +1,76 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __CDP_API_PROCESS_H_
+#define __CDP_API_PROCESS_H_
+
+#include "peer.h"
+#include "diameter.h"
+
+/**
+ * Request types for handler switching.
+ */
+enum handler_types {
+	REQUEST_HANDLER=0, 	/**< the message received is a request */
+	RESPONSE_HANDLER=1  /**< the message received is a response */
+};
+
+/**
+ * Diameter message received handler list element.
+ */ 
+typedef struct handler_t{
+	enum handler_types type;					/**< type of the handler */
+	union {
+		AAARequestHandler_f *requestHandler;	/**< request callback function */
+		AAAResponseHandler_f *responseHandler;  /**< response callback function */
+	} handler;									/**< union for handler callback function */
+	void *param;								/**< transparent parameter to pass to callback */
+	struct handler_t *next;				/**< next handler in the list */
+	struct handler_t *prev;				/**< prev handler in the list */
+} handler;
+		
+typedef struct handler_list_t{
+	handler *head;				/**< first handler in the list */
+	handler *tail;				/**< last handler in the list */
+} handler_list;
+		
+int api_callback(peer *p,AAAMessage *msg,void* ptr);
+
+#endif /*API_PROCESS_H_*/

+ 873 - 0
modules/cdp/authstatemachine.c

@@ -0,0 +1,873 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <time.h>
+ 
+#include "authstatemachine.h"
+#include "diameter_ims.h"
+
+// all this 4 includes are here because of what i do in Send_ASA
+#include "peer.h"
+#include "peermanager.h"
+#include "routing.h"
+#include "receiver.h"
+
+char *auth_states[]={"Idle","Pending","Open","Discon"};
+char *auth_events[]={};
+
+extern dp_config *config;	// because i want to use tc for the expire times...
+
+int get_result_code(AAAMessage* msg)
+{
+	AAA_AVP *avp;
+	AAA_AVP_LIST list;
+	list.head=0;
+	list.tail=0;
+	int rc=-1;
+	
+        if (!msg) goto error;
+        
+        for (avp=msg->avpList.tail;avp;avp=avp->prev)
+		{
+		
+			if (avp->code==AVP_Result_Code)
+			{
+				rc = get_4bytes(avp->data.s);	
+				goto finish;
+			} else if (avp->code==AVP_Experimental_Result)
+			{
+				list=AAAUngroupAVPS(avp->data);
+				for(avp=list.head;avp;avp=avp->next)
+				{
+					if (avp->code==AVP_IMS_Experimental_Result_Code)
+						{
+							rc = get_4bytes(avp->data.s);
+							AAAFreeAVPList(&list);
+							goto finish;
+						}
+			 	}
+				AAAFreeAVPList(&list);			 					
+			}
+		}
+finish:
+		return rc;
+error:
+        LM_ERR("get_result_code(): no AAAMessage or Result Code not found\n");
+        return -1;
+}
+
+/*
+ * Alberto Diez changes the default behaviour on error is going to be to return the default state
+ * that is  STATE_MAINTAINED
+ * this is because in the Rx specification 3GPP TS 29214 v7.1.0 (2007-06)
+ * the AVP Auth Session State is not included in any message exchange, 
+ * therefor we could as well not even check for it, but diameter rfc says to look at this
+ * 
+*/
+
+int get_auth_session_state(AAAMessage* msg)
+{
+        if (!msg) goto error;
+        AAA_AVP* rc = AAAFindMatchingAVP(msg, 0, AVP_Auth_Session_State, 0, 0);
+        if (!rc) goto error;
+        return get_4bytes(rc->data.s);
+
+error:
+        LM_DBG( "get_auth_session_state(): no AAAMessage or Auth Session State not found\n");
+        return STATE_MAINTAINED;
+}
+
+/**
+ * Retrieve the Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs and update the session timers accordingly
+ * @param x
+ * @param msg
+ */
+void update_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg)
+{
+	AAA_AVP *avp;
+	uint32_t session_timeout=0,grace_period=0,auth_lifetime=0;
+	
+	avp = AAAFindMatchingAVP(msg,0,AVP_Auth_Grace_Period,0,0);
+	if (avp &&avp->data.len==4){ 
+		grace_period = get_4bytes(avp->data.s);
+		x->grace_period = grace_period;
+	}
+	avp = AAAFindMatchingAVP(msg,0,AVP_Authorization_Lifetime,0,0);
+	if (avp &&avp->data.len==4) {
+		auth_lifetime = get_4bytes(avp->data.s);
+		switch(auth_lifetime){
+			case 0:
+				x->lifetime = time(0);
+				break;
+			case 0xFFFFFFFF:
+				x->lifetime = -1;
+				break;
+			default:
+				x->lifetime = time(0)+auth_lifetime;
+		}
+		if (x->timeout!=-1 && x->timeout<x->lifetime) x->timeout = x->lifetime+x->grace_period;
+	}
+	avp = AAAFindMatchingAVP(msg,0,AVP_Session_Timeout,0,0);
+	if (avp &&avp->data.len==4) {
+		session_timeout = get_4bytes(avp->data.s);
+		switch(session_timeout){
+			case 0:
+				x->timeout = time(0)+config->default_auth_session_timeout;
+				break;
+			case 0xFFFFFFFF:
+				x->timeout = -1;
+				break;
+			default:
+				x->timeout = time(0)+session_timeout;
+		}
+		if (!x->lifetime) x->lifetime = x->timeout;
+	}
+}
+
+/**
+ * Add Session-Timeout, Auth-Lifetime and Auth-Grace-Period AVPs to outgoing messages in case they are missing
+ * @param x
+ * @param msg
+ */
+void add_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg)
+{
+	AAA_AVP *avp;
+	char data[4];
+	uint32_t v;
+	
+	avp = AAAFindMatchingAVP(msg,0,AVP_Authorization_Lifetime,0,0);
+	if (!avp){ 
+		if (x->lifetime==-1) v=0xFFFFFFFF;
+		else {
+			v = x->lifetime-time(0);
+			if (v<0) v = 0;
+		}
+		set_4bytes(data,v);
+		avp = AAACreateAVP(AVP_Authorization_Lifetime,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
+		if (avp) AAAAddAVPToMessage(msg,avp,0);
+	}
+	if (x->lifetime!=-1){
+		avp = AAAFindMatchingAVP(msg,0,AVP_Auth_Grace_Period,0,0);
+		if (!avp){ 
+			v = x->grace_period;
+			set_4bytes(data,v);
+			avp = AAACreateAVP(AVP_Auth_Grace_Period,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
+			if (avp) AAAAddAVPToMessage(msg,avp,0);
+		}
+	}
+	avp = AAAFindMatchingAVP(msg,0,AVP_Session_Timeout,0,0);
+	if (!avp){ 
+		if (x->timeout==-1) v=0xFFFFFFFF;
+		else {
+			v = x->timeout-time(0);
+			if (v<0) v = 0;
+		}
+		set_4bytes(data,v);
+		avp = AAACreateAVP(AVP_Session_Timeout,AAA_AVP_FLAG_MANDATORY,0,data,4,AVP_DUPLICATE_DATA);
+		if (avp) AAAAddAVPToMessage(msg,avp,0);
+	}
+}
+
+/**
+ * stateful client state machine
+ * \Note - should be called with a lock on the session and will unlock it - do not use it after!
+ * @param auth - AAAAuthSession which uses this state machine
+ * @param ev   - Event
+ * @param msg  - AAAMessage
+ * @returns 0 if msg should be given to the upper layer 1 if not
+ */
+inline int auth_client_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg)
+{
+	cdp_auth_session_t *x;
+	int rc;	
+	int rv=0; //return value
+	
+	if (!s) {
+		switch (event) {
+			case AUTH_EV_RECV_ASR:
+				Send_ASA(0,msg);
+				break;				
+			default:
+				LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d with no session!\n",
+				event);				
+		}
+		return rv;
+	}
+	x = &(s->u.auth);
+	
+	if (s->cb) (s->cb)(event,s);
+	LM_INFO("after callback of event %i\n", event);
+
+	//if (x && x->state && msg) LM_ERR("auth_client_statefull_sm_process [event %i] [state %i] endtoend %u hopbyhop %u\n",event,x->state,msg->endtoendId,msg->hopbyhopId);
+
+	switch(x->state){
+		case AUTH_ST_IDLE:
+			switch (event) {
+				case AUTH_EV_SEND_REQ:
+					s->application_id = msg->applicationId;
+					s->u.auth.state = AUTH_ST_PENDING;
+					update_auth_session_timers(x,msg);
+					add_auth_session_timers(x,msg);
+					//LM_INFO("state machine: i was in idle and i am going to pending\n");
+					break;				
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!(data %p)\n",
+						event,auth_states[x->state],x->generic_data);				
+			}
+			break;
+		
+		case AUTH_ST_PENDING:
+			if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)){
+				rc = get_result_code(msg);
+				if (rc>=2000 && rc<3000 && get_auth_session_state(msg)==STATE_MAINTAINED) 
+					event = AUTH_EV_RECV_ANS_SUCCESS;
+				else
+					event = AUTH_EV_RECV_ANS_UNSUCCESS;
+			}
+			
+			switch(event){
+				case AUTH_EV_RECV_ANS_SUCCESS:
+					x->state = AUTH_ST_OPEN;
+					update_auth_session_timers(x,msg);
+					//LM_INFO("state machine: i was in pending and i am going to open\n");
+					break;
+				case AUTH_EV_RECV_ANS_UNSUCCESS:
+					x->state = AUTH_ST_DISCON;
+					//LM_INFO("state machine: i was in pending and i am going to discon\n");
+					Send_STR(s,msg);
+					break;
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SERVICE_TERMINATED:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:
+					Session_Cleanup(s,NULL);					
+					break;					
+					
+				default:
+					LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+		
+		case AUTH_ST_OPEN:
+			if (event == AUTH_EV_RECV_ANS && msg && !is_req(msg)){
+				rc = get_result_code(msg);
+				if (rc>=2000 && rc<3000 && get_auth_session_state(msg)==STATE_MAINTAINED) 
+					event = AUTH_EV_RECV_ANS_SUCCESS;
+				else
+					event = AUTH_EV_RECV_ANS_UNSUCCESS;
+			}
+
+			switch (event) {
+				case AUTH_EV_SEND_REQ:
+					// if the request is STR i should move to Discon .. 
+					// this is not in the state machine but I (Alberto Diez) need it
+					if (msg->commandCode==IMS_STR) 
+						s->u.auth.state = AUTH_ST_DISCON;
+					else {
+						s->u.auth.state = AUTH_ST_OPEN;
+						add_auth_session_timers(x,msg);
+					}
+					break;		
+					
+				case AUTH_EV_RECV_ANS_SUCCESS:
+					x->state = AUTH_ST_OPEN;
+					update_auth_session_timers(x,msg);					
+					//LM_INFO("state machine: i was in open and i am going to open\n");
+					break;
+					
+				case AUTH_EV_RECV_ANS_UNSUCCESS:
+					x->state = AUTH_ST_DISCON;
+					//LM_INFO("state machine: i was in open and i am going to discon\n");
+					break;
+					
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SERVICE_TERMINATED:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:
+					x->state = AUTH_ST_DISCON;
+					//LM_INFO("state machine: i was in open and i am going to discon\n");
+					
+                                        Send_STR(s,msg);					
+					break;
+					
+				case AUTH_EV_SEND_ASA_SUCCESS:
+					x->state = AUTH_ST_DISCON;
+					//LM_INFO("state machine: i was in open and i am going to discon\n");
+					Send_STR(s,msg);					
+					break;
+					
+				case AUTH_EV_SEND_ASA_UNSUCCESS:
+					x->state = AUTH_ST_OPEN;
+					update_auth_session_timers(x,msg);
+					//LM_INFO("state machine: i was in open and i am going to open\n");
+					break;
+					
+				case AUTH_EV_RECV_ASR: 
+					// two cases , client will comply or will not
+					// our client is very nice and always complys.. because
+					// our brain is in the PCRF... if he says to do this , we do it
+					// Alberto Diez , (again this is not Diameter RFC)
+					x->state = AUTH_ST_DISCON;
+					Send_ASA(s,msg);
+					Send_STR(s,msg);
+					break;
+					
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+		
+		case AUTH_ST_DISCON:
+			switch (event) {
+				case AUTH_EV_RECV_ASR:
+					x->state = AUTH_ST_DISCON;
+					//LM_INFO("state machine: i was in discon and i am going to discon\n");
+					Send_ASA(s,msg);
+					break;
+					
+				// Just added this because it might happen if the other peer doesnt 
+				// send a valid STA, then the session stays open forever...
+				// We dont accept that... we have lifetime+grace_period for that
+				// This is not in the Diameter RFC ...	
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:
+				// thats the addition
+				case AUTH_EV_RECV_STA:
+					x->state = AUTH_ST_IDLE;
+					LM_INFO("state machine: AUTH_EV_RECV_STA about to clean up\n");
+					if (msg) AAAFreeMessage(&msg); // if might be needed in frequency
+					// If I register a ResponseHandler then i Free the STA there not here..
+					// but i dont have interest in that now..				
+					Session_Cleanup(s,NULL);
+					s = 0;
+					rv=1;
+					break;
+					
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+		default:
+			LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
+				event,x->state);
+	}
+	if (s) {
+		if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED,s);
+		AAASessionsUnlock(s->hash);
+	}
+	return rv;
+}
+
+
+/**
+ * Authorization Server State-Machine - Statefull
+ * \Note - should be called with a lock on the session and will unlock it - do not use it after!
+ * @param s
+ * @param event
+ * @param msg
+ */
+inline void auth_server_statefull_sm_process(cdp_session_t* s, int event, AAAMessage* msg)
+{
+	cdp_auth_session_t *x;
+	
+	if (!s) return;
+	x = &(s->u.auth);
+	
+	if (s->cb) (s->cb)(event,s);			
+	LM_DBG("after callback for event %i\n", event);
+
+	switch(x->state){
+		case AUTH_ST_IDLE:
+			switch (event) {
+				case AUTH_EV_RECV_STR:
+					break;
+				case AUTH_EV_RECV_REQ:
+					// The RequestHandler will generate a Send event for the answer
+					// and we will only then now if the user is authorised or not
+					// if its not authorised it will move back to idle and cleanup the session 
+					// so no big deal
+					// but this is not the Diameter RFC...
+					x->state = AUTH_ST_OPEN;
+					// execute the cb here because we won't have a chance later
+					if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED,s);			
+					// Don't unlock the session hash table because the session is returned to the user
+					// This can only be called from the AAACreateServerAuthSession()!
+					s=0;
+					break;
+				case AUTH_EV_SEND_STA:
+					x->state = AUTH_ST_IDLE;
+					Session_Cleanup(s,msg);
+					s = 0;
+					break;
+					
+				/* Just in case we have some lost sessions */	
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:					
+					Session_Cleanup(s,msg);
+					s = 0;
+					break;
+					
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+		
+		case AUTH_ST_OPEN:
+		
+		
+			if (event == AUTH_EV_SEND_ANS && msg && !is_req(msg)){
+				int rc = get_result_code(msg);
+				if (rc>=2000 && rc<3000)
+					event = AUTH_EV_SEND_ANS_SUCCESS;
+				else
+					event = AUTH_EV_SEND_ANS_UNSUCCESS;
+			}
+		
+		
+			switch (event) {
+				case AUTH_EV_RECV_STR:
+					break;
+				case AUTH_EV_SEND_ANS_SUCCESS:
+					x->state = AUTH_ST_OPEN;
+					update_auth_session_timers(x,msg);
+					add_auth_session_timers(x,msg);
+					break;
+				case AUTH_EV_SEND_ANS_UNSUCCESS:
+					x->state = AUTH_ST_IDLE;
+					Session_Cleanup(s,msg);	
+					s = 0;
+					break;
+				case AUTH_EV_SEND_ASR:
+					x->state = AUTH_ST_DISCON;
+					break;
+				case AUTH_EV_SESSION_TIMEOUT:
+				case AUTH_EV_SESSION_GRACE_TIMEOUT:
+					x->state=AUTH_ST_IDLE;
+					LM_DBG("before session cleanup\n");
+					Session_Cleanup(s,msg);
+					s = 0;
+					break;
+				case AUTH_EV_SEND_STA:
+					LM_ERR("SENDING STA!!!\n");
+					x->state = AUTH_ST_IDLE;
+					Session_Cleanup(s,msg);
+					s = 0;
+					break;
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+		
+		case AUTH_ST_DISCON:
+			switch (event) {
+				case AUTH_EV_RECV_STR:
+					break;
+				case AUTH_EV_RECV_ASA:
+				case AUTH_EV_RECV_ASA_SUCCESS:
+					x->state=AUTH_ST_IDLE;
+					//Session_Cleanup(s,msg);
+					break;
+				case AUTH_EV_RECV_ASA_UNSUCCESS:
+					Send_ASR(s,msg);
+					// how many times will this be done?
+					x->state=AUTH_ST_DISCON;
+					break;
+				case AUTH_EV_SEND_STA:
+					x->state = AUTH_ST_IDLE;
+					Session_Cleanup(s,msg);
+					s = 0;
+					break;
+				default:
+					LM_ERR("auth_client_statefull_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+
+		default:
+			LM_ERR("auth_client_statefull_sm_process(): Received event %d while in invalid state %d!\n",
+				event,x->state);
+	}	
+	if (s) {
+		if (s->cb) (s->cb)(AUTH_EV_SESSION_MODIFIED,s);			
+		AAASessionsUnlock(s->hash);
+	}
+}
+
+
+
+
+/** 
+ * Authorization Client State-Machine - Stateless
+ * \Note - should be called with a lock on the session and will unlock it - do not use it after!
+ * @param s
+ * @param event
+ * @param msg
+ */
+inline void auth_client_stateless_sm_process(cdp_session_t* s, int event, AAAMessage *msg)
+{
+	cdp_auth_session_t *x;
+	int rc;
+	if (!s) return;
+	x = &(s->u.auth);
+	switch(x->state){
+		case AUTH_ST_IDLE:
+			switch(event){
+				case AUTH_EV_SEND_REQ:
+					x->state = AUTH_ST_PENDING;
+					break;
+				default:
+					LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+			
+		case AUTH_ST_PENDING:
+			if (!is_req(msg)){
+				rc = get_result_code(msg);
+				if (rc>=2000 && rc<3000 && get_auth_session_state(msg)==NO_STATE_MAINTAINED) 
+					event = AUTH_EV_RECV_ANS_SUCCESS;
+				else
+					event = AUTH_EV_RECV_ANS_UNSUCCESS;
+			}
+			switch(event){
+				case AUTH_EV_RECV_ANS_SUCCESS:
+					x->state = AUTH_ST_OPEN;
+					break;
+				case AUTH_EV_RECV_ANS_UNSUCCESS:
+					x->state = AUTH_ST_IDLE;
+					break;					
+				default:
+					LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+			
+		case AUTH_ST_OPEN:
+			switch(event){
+				case AUTH_EV_SESSION_TIMEOUT:
+					x->state = AUTH_ST_IDLE;
+					break;
+				case AUTH_EV_SERVICE_TERMINATED:
+					x->state = AUTH_ST_IDLE;
+					break;					
+				default:
+					LM_ERR("auth_client_stateless_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_states[x->state]);				
+			}
+			break;
+			
+		default:
+			LM_ERR("auth_client_stateless_sm_process(): Received event %d while in invalid state %d!\n",
+				event,x->state);
+	}	
+	if (s) AAASessionsUnlock(s->hash);
+}
+
+/**
+ * Authorization Server State-Machine - Stateless
+ * \Note - should be called with a lock on the session and will unlock it - do not use it after!
+ * 
+ * @param auth
+ * @param event
+ * @param msg
+ */
+inline void auth_server_stateless_sm_process(cdp_session_t* s, int event, AAAMessage* msg)
+{
+	/* empty - no state change, anyway */
+/*
+	cdp_auth_session_t *x;
+	int rc;
+	if (!s) return;
+	x = &(s->u.auth);
+	switch(x->state){
+		case AUTH_ST_IDLE:
+			switch(event){				
+				default:
+					LM_ERR("auth_server_stateless_sm_process(): Received invalid event %d while in state %s!\n",
+						event,auth_state[x->state]);				
+			}
+			break;
+		default:
+			LM_ERR("auth_server_stateless_sm_process(): Received event %d while in invalid state %d!\n",
+				event,x->state);
+	}
+*/
+	if (s) AAASessionsUnlock(s->hash);
+}
+
+/* copies the Origin-Host AVP from the src message in a Destination-Host AVP in the dest message
+ * copies the Origin-Realm AVP from the src message in a Destination-Realm AVP in the dest message
+ *
+ */
+int dup_routing_avps(AAAMessage* src, AAAMessage *dest){
+
+	AAA_AVP * avp;
+	str dest_host, dest_realm;
+
+	if(!src)
+		return 1;
+
+	/* Removed By Jason to facilitate use of Diameter clustering (MUX) in SLEE architecture (Realm-routing only) - TODO - check spec */
+	/*avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Host,0,AAA_FORWARD_SEARCH);
+	if(avp && avp->data.s && avp->data.len) {
+		LM_DBG("dup_routing_avps: Origin Host AVP present, duplicating %.*s\n",
+				avp->data.len, avp->data.s);
+		dest_host = avp->data;
+		avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
+			dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
+		if (!avp) {
+			LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n");
+			goto error;
+		}
+		if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) {
+			LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n");
+			AAAFreeAVP(&avp);
+			goto error;
+		}
+	}*/
+
+	avp = AAAFindMatchingAVP(src,src->avpList.head,AVP_Origin_Realm,0,AAA_FORWARD_SEARCH);
+	if(avp && avp->data.s && avp->data.len) {
+		LM_DBG("dup_routing_avps: Origin Realm AVP present, duplicating %.*s\n",
+				avp->data.len, avp->data.s);
+		dest_realm = avp->data;
+		avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
+			dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
+		if (!avp) {
+			LM_ERR("dup_routing_avps: Failed creating Destination Host avp\n");
+			goto error;
+		}
+		if (AAAAddAVPToMessage(dest,avp,dest->avpList.tail)!=AAA_ERR_SUCCESS) {
+			LM_ERR("dup_routing_avps: Failed adding Destination Host avp to message\n");
+			AAAFreeAVP(&avp);
+			goto error;
+		}
+	}
+
+	return 1;
+error:
+	return 0;
+
+}
+
+void Send_ASA(cdp_session_t* s, AAAMessage* msg)
+{
+	AAAMessage *asa;
+	char x[4];
+	AAA_AVP *avp;	
+	LM_INFO("Send_ASA():  sending ASA\n");
+	if (!s) {
+	//send an ASA for UNKNOWN_SESSION_ID - use AAASendMessage()
+	// msg is the ASR received
+		asa = AAANewMessage(IMS_ASA,0,0,msg);
+		if (!asa) return;	
+	
+		set_4bytes(x,AAA_SUCCESS);
+		AAACreateAndAddAVPToMessage(asa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
+	
+		AAASendMessage(asa,0,0);
+	}else{
+		// send... many cases... maybe not needed.
+		// for now we do the same
+		asa = AAANewMessage(IMS_ASA,0,0,msg);
+		if (!asa) return;	
+	
+		set_4bytes(x,AAA_SUCCESS);
+		AAACreateAndAddAVPToMessage(asa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
+				
+		avp = AAAFindMatchingAVP(msg,0,AVP_Origin_Host,0,0);	
+		if (avp) {
+				// This is because AAASendMessage is not going to find a route to the 
+				// the PCRF because TS 29.214 says no Destination-Host and no Auth-Application-Id
+				// in the ASA
+			LM_INFO("sending ASA to peer %.*s\n",avp->data.len,avp->data.s); 
+			peer *p;
+			p = get_peer_by_fqdn(&avp->data);
+			if (!peer_send_msg(p,asa)) {
+				if (asa) AAAFreeMessage(&asa);	//needed in frequency
+			} else  
+				LM_INFO("success sending ASA\n");
+		}else if (!AAASendMessage(asa,0,0)) {
+			LM_ERR("Send_ASA() : error sending ASA\n");
+		}	
+	}	
+}
+
+
+int add_vendor_specific_application_id_group(AAAMessage * msg, unsigned int vendor_id, unsigned int auth_app_id)
+{
+	char x[4];
+	AAA_AVP_LIST list_grp={0,0};
+	AAA_AVP *avp;
+	str group = {0,0};
+
+	set_4bytes(x,vendor_id);
+	if(!(avp = AAACreateAVP(AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,
+					x,4, AVP_DUPLICATE_DATA))) goto error;
+	AAAAddAVPToList(&list_grp,avp);
+											
+	set_4bytes(x, auth_app_id);
+	if(!(avp = AAACreateAVP(AVP_Auth_Application_Id, AAA_AVP_FLAG_MANDATORY,0,
+					x,4,AVP_DUPLICATE_DATA))) goto error;
+	AAAAddAVPToList(&list_grp,avp);
+											
+	group = AAAGroupAVPS(list_grp);	
+	if(!group.s || !group.len) goto error;
+								
+	if(!(avp = AAACreateAVP(AVP_Vendor_Specific_Application_Id, AAA_AVP_FLAG_MANDATORY,0,
+					group.s, group.len,AVP_DUPLICATE_DATA))) goto error;
+
+	if(AAAAddAVPToMessage(msg, avp, msg->avpList.tail)!= AAA_ERR_SUCCESS) goto error;
+																	
+	AAAFreeAVPList(&list_grp);
+	shm_free(group.s); group.s = NULL;
+	
+	return 1;
+
+error:
+
+	AAAFreeAVPList(&list_grp);
+	if(group.s) shm_free(group.s);
+	return 0;
+}
+
+void Send_STR(cdp_session_t* s, AAAMessage* msg)
+{
+	AAAMessage *str=0;
+	AAA_AVP *avp=0;
+	peer *p=0;
+	char x[4];
+	LM_DBG( "sending STR\n");
+	//if (msg) LM_DBG("Send_STR() : sending STR for %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId);
+	//else LM_DBG("Send_STR() called from AAATerminateAuthSession or some other event\n");
+	str = AAACreateRequest(s->application_id,IMS_STR,Flag_Proxyable,s);
+	
+	if (!str) {
+		LM_ERR("Send_STR(): error creating STR!\n");
+		return;
+	}
+	if(!dup_routing_avps(msg, str)){
+		LM_ERR("Send_STR(): error duplicating routing AVPs!\n");
+		AAAFreeMessage(&str);
+		return;
+	}
+	if(s->vendor_id!=0 && !add_vendor_specific_application_id_group(str,s->vendor_id,s->application_id)){ 
+		LM_ERR("Send_STR(): error adding Vendor-Id-Specific-Application-Id Group!\n");
+		AAAFreeMessage(&str);
+		return;
+	}
+	
+	set_4bytes(x,s->application_id);
+	avp = AAACreateAVP(AVP_Auth_Application_Id,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);
+	AAAAddAVPToMessage(str,avp,str->avpList.tail);
+	
+	set_4bytes(x,4); // Diameter_administrative
+	avp = AAACreateAVP(AVP_Termination_Cause,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);
+	AAAAddAVPToMessage(str,avp,str->avpList.tail);
+	//todo - add all the other avps
+
+	p = get_routing_peer(str);
+	if (!p) {
+		LM_ERR("unable to get routing peer in Send_STR \n");
+		if (str) AAAFreeMessage(&str); //needed in frequency
+		return;
+	}
+	//if (str) LM_CRIT("Send_STR() : sending STR  %d, flags %#1x endtoend %u hopbyhop %u\n",str->commandCode,str->flags,str->endtoendId,str->hopbyhopId);
+	if (!peer_send_msg(p,str))
+	{
+		LM_DBG("Send_STR peer_send_msg return error!\n");
+		if (str) AAAFreeMessage(&str); //needed in frequency	
+	} else { 
+		LM_DBG("success sending STR\n");
+	}
+}
+
+void Send_ASR(cdp_session_t* s, AAAMessage* msg)
+{
+	AAAMessage *asr=0;
+	AAA_AVP *avp=0;
+	peer *p=0;
+	char x[4];
+	LM_DBG("Send_ASR() : sending ASR\n");
+	asr = AAACreateRequest(s->application_id,IMS_ASR,Flag_Proxyable,s);
+	
+	if (!asr) {
+		LM_ERR("Send_ASR(): error creating ASR!\n");
+		return;
+	}
+	
+	set_4bytes(x,s->application_id);
+	avp = AAACreateAVP(AVP_Auth_Application_Id,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);
+	AAAAddAVPToMessage(asr,avp,asr->avpList.tail);
+	
+	set_4bytes(x,3); // Not specified
+	avp = AAACreateAVP(AVP_IMS_Abort_Cause,AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);
+	AAAAddAVPToMessage(asr,avp,asr->avpList.tail);
+	//todo - add all the other avps
+	
+	p = get_routing_peer(asr);
+	if (!p) {
+		LM_ERR("unable to get routing peer in Send_ASR \n");
+		if (asr) AAAFreeMessage(&asr); //needed in frequency
+	}
+	
+	if (!peer_send_msg(p,asr)) {
+		if (asr) AAAFreeMessage(&asr); //needed in frequency	
+	} else  
+		LM_DBG("success sending ASR\n");
+}
+
+void Session_Cleanup(cdp_session_t* s, AAAMessage* msg)
+{
+	// Here we should drop the session ! and free everything related to it
+	// but the generic_data thing should be freed by the callback function registered
+	// when the auth session was created
+	AAASessionCallback_f *cb;
+	LM_INFO("cleaning up session %.*s\n",s->id.len,s->id.s);
+	if (s->cb) {
+		cb = s->cb;
+		(cb) (AUTH_EV_SERVICE_TERMINATED,s);
+	}
+	
+	AAADropAuthSession(s);
+}

+ 64 - 0
modules/cdp/authstatemachine.h

@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AUTHSTATEMACHINE_H
+#define __AUTHSTATEMACHINE_H
+
+#include "diameter_api.h"
+#include "session.h"
+#include "config.h"
+
+void update_auth_session_timers(cdp_auth_session_t *x,AAAMessage *msg);
+
+inline int auth_client_statefull_sm_process(cdp_session_t* auth, int event, AAAMessage* msg);
+inline void auth_server_statefull_sm_process(cdp_session_t* auth, int event, AAAMessage* msg);
+
+void auth_client_stateless_sm_process(cdp_session_t* s, int event, AAAMessage *msg);
+void auth_server_stateless_sm_process(cdp_session_t* auth, int event, AAAMessage* msg);
+
+void Send_ASA(cdp_session_t* s, AAAMessage* msg);
+
+void Send_STR(cdp_session_t* s, AAAMessage* msg);
+void Send_ASR(cdp_session_t* s, AAAMessage* msg);
+
+void Session_Cleanup(cdp_session_t* s, AAAMessage* msg);
+
+#endif
+

+ 107 - 0
modules/cdp/cdp_load.c

@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "cdp_load.h"
+
+#include "../../sr_module.h"
+
+
+#define LOAD_ERROR "ERROR: cdp_bind: S-CSCF module function "
+
+#define FIND_EXP(NAME) \
+	if (!( cdpb->NAME=(NAME##_f) \
+		find_export(#NAME, NO_SCRIPT, 0)) ) {\
+		LM_ERR("'"LOAD_ERROR "'"#NAME"' not found\n");\
+		return -1;\
+	}
+
+
+/**
+ * Load the CDiameterPeer bindings
+ * @param *cdpb - target structure to load the bindings into
+ * @returns 1 on success, -1 on failure
+ */  
+int load_cdp( struct cdp_binds *cdpb)
+{
+	FIND_EXP(AAACreateRequest);
+	FIND_EXP(AAACreateResponse);
+	FIND_EXP(AAAFreeMessage);
+
+
+	FIND_EXP(AAACreateAVP);
+	FIND_EXP(AAAAddAVPToMessage);
+	FIND_EXP(AAAAddAVPToList);
+	FIND_EXP(AAAFindMatchingAVP);
+	FIND_EXP(AAAFindMatchingAVPList);
+	FIND_EXP(AAAGetNextAVP);
+	FIND_EXP(AAAFreeAVP);
+	FIND_EXP(AAAFreeAVPList);
+	FIND_EXP(AAAGroupAVPS);
+	FIND_EXP(AAAUngroupAVPS);
+
+	FIND_EXP(AAASendMessage);
+	FIND_EXP(AAASendMessageToPeer);
+	FIND_EXP(AAASendRecvMessage);
+	FIND_EXP(AAASendRecvMessageToPeer);
+
+
+	FIND_EXP(AAAAddRequestHandler);
+	FIND_EXP(AAAAddResponseHandler);
+
+
+	FIND_EXP(AAACreateTransaction);
+	FIND_EXP(AAADropTransaction);
+
+
+	FIND_EXP(AAACreateSession);
+	FIND_EXP(AAAMakeSession);
+	FIND_EXP(AAAGetSession);
+	FIND_EXP(AAADropSession);
+	FIND_EXP(AAASessionsLock);
+	FIND_EXP(AAASessionsUnlock);
+
+	FIND_EXP(AAACreateClientAuthSession);
+	FIND_EXP(AAACreateServerAuthSession);
+	FIND_EXP(AAAGetAuthSession);
+	FIND_EXP(AAADropAuthSession);
+	FIND_EXP(AAATerminateAuthSession);
+	
+	return 1;
+}

+ 127 - 0
modules/cdp/cdp_load.h

@@ -0,0 +1,127 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef _CDP_BIND_H
+#define _CDP_BIND_H
+
+#include "../../sr_module.h"
+#include "utils.h"
+#include "diameter.h"
+#include "diameter_api.h"
+#include "diameter_ims.h"
+#include "diameter_epc.h"
+#include "session.h"
+//#include "peer.h"
+
+
+struct cdp_binds {
+	AAACreateRequest_f			AAACreateRequest;
+	AAACreateResponse_f			AAACreateResponse;	
+	AAAFreeMessage_f			AAAFreeMessage;
+	
+	
+	AAACreateAVP_f				AAACreateAVP;
+	AAAAddAVPToMessage_f		AAAAddAVPToMessage;
+	AAAAddAVPToList_f			AAAAddAVPToList;
+	AAAFindMatchingAVP_f		AAAFindMatchingAVP;
+	AAAFindMatchingAVPList_f	AAAFindMatchingAVPList;
+	AAAGetNextAVP_f				AAAGetNextAVP;
+	AAAFreeAVP_f				AAAFreeAVP;
+	AAAFreeAVPList_f			AAAFreeAVPList;
+	AAAGroupAVPS_f				AAAGroupAVPS;
+	AAAUngroupAVPS_f			AAAUngroupAVPS;
+
+	AAASendMessage_f			AAASendMessage;
+	AAASendMessageToPeer_f		AAASendMessageToPeer;
+	AAASendRecvMessage_f		AAASendRecvMessage;
+	AAASendRecvMessageToPeer_f	AAASendRecvMessageToPeer;
+	
+	
+	AAAAddRequestHandler_f		AAAAddRequestHandler;
+	AAAAddResponseHandler_f		AAAAddResponseHandler;
+
+
+	AAACreateTransaction_f		AAACreateTransaction;
+	AAADropTransaction_f		AAADropTransaction;
+	
+	
+	AAACreateSession_f			AAACreateSession;
+	AAAMakeSession_f			AAAMakeSession;
+	AAAGetSession_f				AAAGetSession;
+	AAADropSession_f			AAADropSession;
+	AAASessionsLock_f 			AAASessionsLock;
+	AAASessionsUnlock_f			AAASessionsUnlock;
+
+	AAACreateClientAuthSession_f AAACreateClientAuthSession;
+	AAACreateServerAuthSession_f AAACreateServerAuthSession;
+	AAAGetAuthSession_f			AAAGetAuthSession;
+	AAADropAuthSession_f		AAADropAuthSession;
+	AAATerminateAuthSession_f	AAATerminateAuthSession;
+
+};
+
+
+#define NO_SCRIPT	-1
+
+typedef int(*load_cdp_f)( struct cdp_binds *cdpb );
+int load_cdp( struct cdp_binds *cdpb);
+
+static inline int load_cdp_api(struct cdp_binds* cdpb)
+{
+	load_cdp_f load_cdp;
+
+	/* import the TM auto-loading function */
+	load_cdp = (load_cdp_f)find_export("load_cdp", NO_SCRIPT, 0);
+	
+	if (load_cdp == NULL) {
+		LM_WARN("Cannot import load_cdp function from CDP module\n");
+		return -1;
+	}
+	
+	/* let the auto-loading function load all TM stuff */
+	if (load_cdp(cdpb) == -1) {
+		return -1;
+	}
+	return 0;
+}
+
+
+#endif
+

+ 228 - 0
modules/cdp/config.c

@@ -0,0 +1,228 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "config.h"
+
+/**
+ * Create a new dp_config.
+ */
+inline dp_config *new_dp_config()
+{
+	dp_config *x;	
+	x = shm_malloc(sizeof(dp_config));
+	if (!x) {
+		LOG_NO_MEM("shm",sizeof(dp_config));
+		goto error;
+	}	
+	memset(x,0,sizeof(dp_config));
+	return x;
+error:
+	LM_ERR("%s(): failed to create new dp_config.\n",__FUNCTION__);	
+	return 0;
+}
+
+/**
+ * Create a new dp_config.
+ */
+inline routing_realm *new_routing_realm()
+{
+	routing_realm *x;	
+	x = shm_malloc(sizeof(routing_realm));
+	if (!x) {
+		LOG_NO_MEM("shm",sizeof(routing_realm));
+		goto error;
+	}	
+	memset(x,0,sizeof(routing_realm));
+	return x;
+error:
+	LM_ERR("%s(): failed to create new routing_realm.\n",__FUNCTION__);	
+	return 0;
+}
+
+/**
+ * Create a new dp_config.
+ */
+inline routing_entry *new_routing_entry()
+{
+	routing_entry *x;	
+	x = shm_malloc(sizeof(routing_entry));
+	if (!x) {
+		LOG_NO_MEM("shm",sizeof(routing_entry));
+		goto error;
+	}	
+	memset(x,0,sizeof(routing_entry));
+	return x;
+error:
+	LM_ERR("%s(): failed to create new routing_entry.\n",__FUNCTION__);	
+	return 0;
+}
+
+
+/** 
+ * Free the space claimed by a routing entry
+ */
+inline void free_routing_entry(routing_entry *re)
+{
+	if (!re) return;
+	if (re->fqdn.s) shm_free(re->fqdn.s);
+	shm_free(re);
+}
+
+/** 
+ * Free the space claimed by a routing realm
+ */
+inline void free_routing_realm(routing_realm *rr)
+{
+	routing_entry *re,*ren;
+	if (!rr) return;
+	if (rr->realm.s) shm_free(rr->realm.s);
+	for(re=rr->routes;re;re=ren){
+		ren = re->next;
+		free_routing_entry(re);
+	}
+	shm_free(rr);
+}
+
+
+
+
+/**
+ * Frees the memory held by a dp_config.
+ */
+inline void free_dp_config(dp_config *x)
+{
+	int i;
+	if (!x) return;
+	if (x->fqdn.s) shm_free(x->fqdn.s);
+	if (x->identity.s) shm_free(x->identity.s);
+	if (x->realm.s) shm_free(x->realm.s);
+	if (x->product_name.s) shm_free(x->product_name.s);
+	if (x->peers) {
+		for(i=0;i<x->peers_cnt;i++){
+			if (x->peers[i].fqdn.s) shm_free(x->peers[i].fqdn.s);
+			if (x->peers[i].realm.s) shm_free(x->peers[i].realm.s);
+		}
+		shm_free(x->peers);
+	}
+	if (x->acceptors) {
+		for(i=0;i<x->acceptors_cnt;i++){
+			if (x->acceptors[i].bind.s) shm_free(x->acceptors[i].bind.s);
+		}		
+		shm_free(x->acceptors);
+	}
+	if (x->applications) shm_free(x->applications);
+	
+	if (x->supported_vendors) shm_free(x->supported_vendors);
+	
+	if (x->r_table) {
+		routing_realm *rr,*rrn;
+		routing_entry *re,*ren;
+		for(rr=x->r_table->realms;rr;rr=rrn){
+			rrn = rr->next;
+			free_routing_realm(rr);
+		}
+		for(re=x->r_table->routes;re;re=ren){
+			ren = re->next;
+			free_routing_entry(re);
+		}
+		shm_free(x->r_table);
+	}	
+	shm_free(x);
+}
+
+/**
+ * Log the dp_config to output, for debug purposes.
+ */	
+inline void log_dp_config(int level,dp_config *x)
+{
+	int i;
+	LOG(level,"Diameter Peer Config:\n");
+	LOG(level,"\tFQDN    : %.*s\n",x->fqdn.len,x->fqdn.s);
+	LOG(level,"\tRealm   : %.*s\n",x->realm.len,x->realm.s);
+	LOG(level,"\tVendorID: %d\n",x->vendor_id);
+	LOG(level,"\tProdName: %.*s\n",x->product_name.len,x->product_name.s);
+	LOG(level,"\tAcceptUn: [%c]\n",x->accept_unknown_peers?'X':' ');
+	LOG(level,"\tDropUnkn: [%c]\n",x->drop_unknown_peers?'X':' ');
+	LOG(level,"\tTc      : %d\n",x->tc);
+	LOG(level,"\tWorkers : %d\n",x->workers);
+	LOG(level,"\tQueueLen: %d\n",x->queue_length);
+	LOG(level,"\tConnTime: %d\n",x->connect_timeout);
+	LOG(level,"\tTranTime: %d\n",x->transaction_timeout);
+	LOG(level,"\tSessHash: %d\n",x->sessions_hash_size);
+	LOG(level,"\tDefAuthT: %d\n",x->default_auth_session_timeout);
+	LOG(level,"\tMaxAuthT: %d\n",x->max_auth_session_timeout);
+	LOG(level,"\tPeers   : %d\n",x->peers_cnt);
+	for(i=0;i<x->peers_cnt;i++)
+		LOG(level,"\t\tFQDN:  %.*s \t Realm: %.*s \t Port: %d\n",
+			x->peers[i].fqdn.len,x->peers[i].fqdn.s,
+			x->peers[i].realm.len,x->peers[i].realm.s,
+			x->peers[i].port);
+	LOG(level,"\tAcceptors : %d\n",x->acceptors_cnt);
+	for(i=0;i<x->acceptors_cnt;i++)
+		LOG(level,"\t\tPort:  %d \t Bind: %.*s \n",
+			x->acceptors[i].port,
+			x->acceptors[i].bind.len,x->acceptors[i].bind.s);
+	LOG(level,"\tApplications : %d\n",x->applications_cnt);
+	for(i=0;i<x->applications_cnt;i++)
+		LOG(level,"\t\t%s ID:  %d \t Vendor: %d \n",
+			(x->applications[i].type==DP_AUTHORIZATION)?"Auth":"Acct",
+			x->applications[i].id,
+			x->applications[i].vendor);	
+	LOG(level,"\tSupported Vendors : %d\n",x->supported_vendors_cnt);
+	for(i=0;i<x->supported_vendors_cnt;i++)
+		LOG(level,"\t\t Vendor: %d \n",			
+			x->supported_vendors[i]);	
+	if (x->r_table){
+		routing_realm *rr;
+		routing_entry *re;
+		LOG(level,"\tRouting Table : \n");
+		for(rr=x->r_table->realms;rr;rr=rr->next){
+			LOG(level,"\t\tRealm: %.*s\n",
+				rr->realm.len,rr->realm.s);
+			for(re=rr->routes;re;re=re->next)		
+				LOG(level,"\t\t\tRoute: [%4d] %.*s\n",
+					re->metric,re->fqdn.len,re->fqdn.s);			
+		}
+		for(re=x->r_table->routes;re;re=re->next)		
+			LOG(level,"\t\tDefaultRoute: [%4d] %.*s\n",
+				re->metric,re->fqdn.len,re->fqdn.s);			
+	}
+	
+}

+ 145 - 0
modules/cdp/config.h

@@ -0,0 +1,145 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __CONFIG_H_
+#define __CONFIG_H_
+
+#include "utils.h"
+#include <libxml/parser.h>
+
+/** Peer configuration. */
+typedef struct{
+	str fqdn;	/**< FQDN of the peer */
+	str realm;	/**< Realm of the peer */
+	int port;	/**< TCP port of the peer; the Diameter uri is then aaa://fqdn:port. */
+} peer_config;
+
+
+/** Acceptor socket configuration. */
+typedef struct{
+	int port;	/**< TCP port number to listen on */ 
+	str bind;	/**< IP address to bind to (if null, then :: (0.0.0.0) - all) */
+} acceptor_config;
+
+typedef enum {
+	DP_AUTHORIZATION,	/**< Authorization application */
+	DP_ACCOUNTING		/**< Accounting application */
+} app_type;
+
+/** Application configuration. */
+typedef struct {
+	int id;			/**< integer id of the appication */
+	int vendor;		/**< vendor id of the application */
+	app_type type;			/**< type of the application */
+} app_config;
+
+/** Routing Table Entry */
+typedef struct _routing_entry {
+	str fqdn;				/**< FQDN of the server 				*/
+	int metric;				/**< The metric of the route			*/
+	struct _routing_entry *next;
+} routing_entry;
+
+/** Routing Table realm */
+typedef struct _routing_realm {
+	str realm;				/**< the realm to identify				*/
+	routing_entry *routes;	/**< ordered list of routes				*/
+	struct _routing_realm *next; /**< the next realm in the table	*/
+} routing_realm;
+
+/** Routing Table configuration */
+typedef struct {
+	routing_realm *realms;	/**< list of realms				 	*/
+	routing_entry *routes;	/**< ordered list of default routes 	*/
+} routing_table;
+
+/** Full Diameter Peer configuration. */
+typedef struct {
+	str fqdn;					/**< own FQDN */
+	str realm;					/**< own Realm */
+	str identity;				/**< own diameter URI */
+	int vendor_id;				/**< own vendorid */
+	str product_name;			/**< own product name */
+	int accept_unknown_peers;	/**< if to accept connections from peers that are not configured initially */
+	int drop_unknown_peers;		/**< if to drop the peers that are not initially configured on disconnected;
+									 usually, you want to do this, unless you want your list of peers to
+									 grow and you want to try and connect back to everybody that connected 
+									 to you before */
+	int tc;						/**< Tc timer duration (30 seconds should be) */
+	int workers;				/**< Number of worker-processes to fork */
+	int queue_length;			/**< Length of the message queue; when it is filled, the server part will
+									 block until workers will finish work on at least one item in the queue */
+	int connect_timeout;		/**< Connect timeout for outbound connections */
+	int transaction_timeout;	/**< Transaction timeout duration */
+	
+	int sessions_hash_size;		/**< Size of the sessions hash table */									 
+	int default_auth_session_timeout; /** The default Authorization Session Timeout to use if none other indicated */ 
+	int max_auth_session_timeout;	  /** The max Authorization Session Timeout limit */ 
+	
+	peer_config *peers;			/**< list of peers */
+	int peers_cnt;				/**< size of the list of peers */
+	
+	acceptor_config *acceptors;	/**< list of acceptors */
+	int acceptors_cnt;			/**< size of the list of acceptors */
+	
+	app_config *applications;	/**< list of supporter applications */
+	int applications_cnt;		/**< size of list of supported applications*/
+
+	int *supported_vendors;		/**< list of supported vendor ids */
+	int supported_vendors_cnt;	/**< size of list of supported vendor ids */
+	
+	routing_table *r_table;		/**< realm routing table */
+} dp_config;
+
+
+dp_config *new_dp_config();
+routing_realm *new_routing_realm();
+routing_entry *new_routing_entry();
+void free_dp_config(dp_config *x);
+void free_routing_realm(routing_realm *rr);
+void free_routing_entry(routing_entry *re);
+inline void log_dp_config(int level,dp_config *x);
+
+xmlDocPtr parse_dp_config_file(char* filename);
+xmlDocPtr parse_dp_config_str(str config_str);
+
+dp_config* parse_dp_config(xmlDocPtr);
+
+#endif /*__CONFIG_H_*/

+ 100 - 0
modules/cdp/configdtd.h

@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#define DP_CONFIG_DTD "\
+<?xml version=\"1.0\" encoding=\"UTF-8\"?>\
+<!ELEMENT DiameterPeer (Peer*, Acceptor*, Auth*, Acct*, SupportedVendor*, Realm*, DefaultRoute*)>\
+<!ATTLIST DiameterPeer \
+	FQDN		CDATA				#REQUIRED\
+	Realm		CDATA				#REQUIRED\
+	Vendor_Id	CDATA				#REQUIRED\
+	Product_Name CDATA				#REQUIRED\
+	AcceptUnknownPeers CDATA		#REQUIRED\
+	DropUnknownOnDisconnect CDATA	#REQUIRED\
+	Tc			CDATA				#REQUIRED\
+	Workers		CDATA				#REQUIRED\
+	QueueLength	CDATA				#REQUIRED\
+	ConnectTimeout	   CDATA		#IMPLIED\
+	TransactionTimeout CDATA		#IMPLIED\
+	SessionsHashSize CDATA			#IMPLIED\
+	DefaultAuthSessionTimeout CDATA	#IMPLIED\
+	MaxAuthSessionTimeout CDATA		#IMPLIED\
+>\
+<!ELEMENT Peer (#PCDATA)>\
+<!ATTLIST Peer\
+	FQDN		CDATA				#REQUIRED\
+	realm		CDATA				#REQUIRED\
+	port		CDATA				#REQUIRED\
+>\
+<!ELEMENT Acceptor (#PCDATA)>\
+<!ATTLIST Acceptor\
+	port		CDATA				#REQUIRED\
+	bind		CDATA				#IMPLIED\
+>\
+<!ELEMENT Auth (#PCDATA)>\
+<!ATTLIST Auth\
+	id			CDATA				#REQUIRED\
+	vendor		CDATA				#REQUIRED\
+>\
+<!ELEMENT Acct (#PCDATA)>\
+<!ATTLIST Acct\
+	id			CDATA				#REQUIRED\
+	vendor		CDATA				#REQUIRED\
+>\
+<!ELEMENT SupportedVendor (#PCDATA)>\
+<!ATTLIST SupportedVendor\
+	vendor		CDATA				#REQUIRED\
+>\
+<!ELEMENT Realm (Route*)>\
+<!ATTLIST Realm\
+	name		CDATA				#REQUIRED\
+>\
+<!ELEMENT Route (#PCDATA)>\
+<!ATTLIST Route\
+	FQDN		CDATA				#REQUIRED\
+	metric		CDATA				#REQUIRED\
+>\
+<!ELEMENT DefaultRoute (#PCDATA)>\
+<!ATTLIST DefaultRoute\
+	FQDN		CDATA				#REQUIRED\
+	metric		CDATA				#REQUIRED\
+>\
+";
+

+ 113 - 0
modules/cdp/configexample/ConfigExample.xml

@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+
+ DiameterPeer Parameters 
+  - FQDN - FQDN of this peer, as it should apper in the Origin-Host AVP
+  - Realm - Realm of this peer, as it should apper in the Origin-Realm AVP
+  - Vendor_Id - Default Vendor-Id to appear in the Capabilities Exchange
+  - Product_Name - Product Name to appear in the Capabilities Exchange 
+  - AcceptUnknownPeers - Whether to accept (1) or deny (0) connections from peers with FQDN 
+    not configured below
+  - DropUnknownOnDisconnect - Whether to drop (1) or keep (0) and retry connections (until restart)
+    unknown peers in the list of peers after a disconnection.
+  - Tc - Value for the RFC3588 Tc timer - default 30 seconds
+  - Workers - Number of incoming messages processing workers forked processes.
+    This only matters in ser_ims.
+    In Wharf, the Wharf workers pool are reused for this purpose.
+   - Queue - Length of queue of tasks for the workers:
+     - too small and the incoming messages will be blocked too often;
+     - too large and the senders of incoming messages will have a longer feedback loop to notice that
+     this Diameter peer is overloaded in processing incoming requests;
+     - a good choice is to have it about 2 times the number of workers. This will mean that each worker
+     will have about 2 tasks in the queue to process before new incoming messages will start to block.
+  - ConnectTimeout - time in seconds to wait for an outbound TCP connection to be established.
+  - TransactionTimeout - time in seconds after which the transaction timeout callback will be fired,
+    when using transactional processing.
+  - SessionsHashSize - size of the hash-table to use for the Diameter sessions. When searching for a 
+    session, the time required for this operation will be that of sequential searching in a list of 
+    NumberOfActiveSessions/SessionsHashSize. So higher the better, yet each hashslot will consume an
+    extra 2xsizeof(void*) bytes (typically 8 or 16 bytes extra).
+  - DefaultAuthSessionTimeout - default value to use when there is no Authorization Session Timeout 
+  AVP present.
+  - MaxAuthSessionTimeout - maximum Authorization Session Timeout as a cut-out measure meant to
+  enforce session refreshes.
+      
+ -->
+<DiameterPeer 
+	FQDN="xcscf.open-ims.test"
+	Realm="open-ims.test"
+	Vendor_Id="10415"
+	Product_Name="CDiameterPeer"
+	AcceptUnknownPeers="0"
+	DropUnknownOnDisconnect="1"
+	Tc="30"
+	Workers="4"
+	QueueLength="32"
+	ConnectTimeout="5"
+	TransactionTimeout="5"
+	SessionsHashSize="128"
+	DefaultAuthSessionTimeout="60"
+	MaxAuthSessionTimeout="300"
+>
+	<!--
+		Definition of peers to connect to and accept connections from. For each peer found in here
+		a dedicated receiver process will be forked. All other unkwnown peers will share a single
+		receiver.
+	-->
+	<Peer FQDN="hss.open-ims.test" Realm="open-ims.test" port="3868"/>
+
+	<!--
+		Definition of incoming connection acceptors. If no bind is specified, the acceptor will bind
+		on all available interfaces.
+	-->
+	<Acceptor port="3868"  />
+	<Acceptor port="3869" bind="127.0.0.1" />
+	<Acceptor port="3870" bind="192.168.1.1" />
+	
+	<!--
+		Definition of Auth (authorization) and Acct (accounting) supported applications. This
+		information is sent as part of the Capabilities Exchange procedures on connecting to
+		peers. If no common application is found, the peers will disconnect. Messages will only
+		be sent to a peer if that peer actually has declared support for the application id of 
+		the message.
+	-->
+	<Acct id="16777216" vendor="10415" />
+	<Acct id="16777216" vendor="0" />
+	<Auth id="16777216" vendor="10415"/>
+	<Auth id="16777216" vendor="0" />
+	
+	<!-- 
+		Supported Vendor IDs - list of values which will be sent in the CER/CEA in the
+		Supported-Vendor-ID AVPs
+	-->
+	<SupportedVendor vendor="10415" />
+	
+	<!--
+		Realm routing definition.
+		Each Realm can have a different table of peers to route towards. In case the Destination
+		Realm AVP contains a Realm not defined here, the DefaultRoute entries will be used.
+
+		Note: In case a message already contains a Destination-Host AVP, Realm Routeing will not be
+		applied.
+		Note: Routing will only happen towards connected and application id supporting peers.
+		
+		The metric is used to order the list of prefered peers, while looking for a connected and
+		application id supporting peer. In the end, of course, just one peer will be selected.
+	-->
+	<Realm name="my.open-ims.test">
+		<Route FQDN="blackjack" metric="2"/>
+		<Route FQDN="test1" metric="3"/>
+		<Route FQDN="test2" metric="5"/>
+	</Realm>
+	<Realm name="test1.open-ims.test">
+		<Route FQDN="test3" metric="7"/>
+		<Route FQDN="test4" metric="11"/>
+	</Realm>
+	<Realm name="test2.open-ims.test">
+		<Route FQDN="test5" metric="13"/>
+	</Realm>
+	<DefaultRoute FQDN="test6" metric="15"/>
+	<DefaultRoute FQDN="test7" metric="13"/>
+
+
+</DiameterPeer>

+ 475 - 0
modules/cdp/configparser.c

@@ -0,0 +1,475 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "config.h"
+
+
+#include <libxml/parser.h>
+#include <stdio.h>
+#include <string.h>
+
+extern int errno;
+	
+static xmlValidCtxt	cvp;	/**< XML Validation context */
+
+/**
+ * Initializes the libxml parser
+ * @returns 1 always
+ */
+static inline int parser_init()
+{
+	cvp.userData = (void*)stderr;
+	cvp.error = (xmlValidityErrorFunc) fprintf;
+	cvp.warning = (xmlValidityWarningFunc) fprintf;
+	return 1;
+}
+
+/**
+ * Destroys the parser 
+ */
+static inline void parser_destroy()
+{
+	xmlCleanupParser();
+}
+
+/**
+ * Trim the quotes from a string and duplicate it.
+ * @param dest - destination for the untrimmed and duplicated string
+ * @param src - source string
+ */
+static inline void quote_trim_dup(str *dest, char *src)
+{
+	int i=0;
+	dest->s=0;
+	dest->len=0;
+	if (!src) return;
+	dest->len = strlen(src);
+	if (src[0]=='\"') {i++;dest->len--;}
+	if (src[dest->len-1]=='\"') {dest->len--;}
+
+	dest->s = shm_malloc(dest->len+1);
+	if (!dest->s) {
+		LOG_NO_MEM("shm",dest->len);
+		dest->len=0;
+		return;
+	}
+	memcpy(dest->s,src+i,dest->len);
+	dest->s[dest->len]=0;
+}
+
+/**
+ * Parse the cdp configuration from file to xml
+ * @param filename
+ * @return the xmlDocPtr or null on error
+ */
+xmlDocPtr parse_dp_config_file(char* filename)
+{
+	FILE *f=0;
+	xmlDocPtr doc;
+
+	parser_init();
+
+	if (!filename){
+		LM_ERR("ERROR:parse_dp_config_file(): filename parameter is null\n");
+		goto error;
+	}
+	f = fopen(filename,"r");
+	if (!f){
+		LM_ERR("ERROR:parse_dp_config_file(): Error opening <%s> file > %s\n",filename,strerror(errno));
+		goto error;
+	}
+	fclose(f);
+	
+	doc = xmlParseFile(filename);
+	if (!doc){
+		LM_ERR("parse_dp_config_file():  This is not a valid XML file <%s>\n",
+			filename);
+		goto error;
+	}
+	
+	return doc;
+error:
+	return 0;		
+}
+
+/**
+ * Parse the cdp configuration from str to xml
+ * @param filename
+ * @return the xmlDocPtr or null on error
+ */
+xmlDocPtr parse_dp_config_str(str config_str)
+{
+	xmlDocPtr doc;
+	
+	char c = config_str.s[config_str.len];
+	if (!config_str.len){
+		LM_ERR("ERROR:parse_dp_config_str(): empty string\n");
+		goto error;
+	}
+	parser_init();
+
+	config_str.s[config_str.len] = 0;
+	doc = xmlParseDoc((xmlChar*)config_str.s);
+	config_str.s[config_str.len] = c;
+
+	if (!doc){
+		LM_ERR("parse_dp_config_file():  This is not a valid XML string <%.*s>\n",
+			config_str.len,config_str.s);
+		goto error;
+	}
+	
+	return  doc;
+error:
+	return 0;		
+}
+
+/**
+ * Parses a DiameterPeer configuration file.
+ * @param filename - path to the file
+ * @returns the dp_config* structure containing the parsed configuration  
+ */
+dp_config* parse_dp_config(xmlDocPtr doc)
+{
+	dp_config *x=0;
+	xmlNodePtr root=0,child=0,nephew=0;
+	xmlChar *xc=0;
+	int k;
+	routing_entry *re,*rei;
+	routing_realm *rr,*rri;
+	
+	if (!doc)
+		goto error;
+		
+	x = new_dp_config();
+
+	root = xmlDocGetRootElement(doc);
+	if (!root){
+		LM_ERR("parse_dp_config():  Empty XML \n");
+		goto error;
+	}
+
+	k = xmlStrlen(root->name);
+	if (k>12) k = 12;
+	if (strncasecmp((char*)root->name,"DiameterPeer",k)!=0){
+		LM_ERR("parse_dp_config(): XML Root is not <DiameterPeer>\n");
+		goto error;
+	}
+
+	xc = xmlGetProp(root,(xmlChar*)"FQDN");
+	if (xc){
+		quote_trim_dup(&(x->fqdn),(char*)xc);
+		quote_trim_dup(&(x->identity),(char*)xc);
+		xmlFree(xc);
+	}
+	
+	xc = xmlGetProp(root,(xmlChar*)"Realm");
+	if (xc){
+		quote_trim_dup(&(x->realm),(char*)xc);
+		xmlFree(xc);
+	}
+	
+	xc = xmlGetProp(root,(xmlChar*)"Vendor_Id");
+	if (xc) x->vendor_id = atoi((char*)xc);
+	else x->vendor_id = 0;
+
+	xc = xmlGetProp(root,(xmlChar*)"Product_Name");
+	if (xc){
+		quote_trim_dup(&(x->product_name),(char*)xc);
+		xmlFree(xc);
+	}
+	
+	xc = xmlGetProp(root,(xmlChar*)"AcceptUnknownPeers");
+	if (xc) {x->accept_unknown_peers = atoi((char*)xc);xmlFree(xc);}
+	else x->accept_unknown_peers = 1;
+	
+	xc = xmlGetProp(root,(xmlChar*)"DropUnknownOnDisconnect");
+	if (xc) {x->drop_unknown_peers = atoi((char*)xc);xmlFree(xc);}
+	else x->drop_unknown_peers = 1;
+	
+	xc = xmlGetProp(root,(xmlChar*)"Tc");
+	if (xc) {x->tc = atoi((char*)xc);xmlFree(xc);}
+	else x->tc = 30;
+
+	xc = xmlGetProp(root,(xmlChar*)"Workers");
+	if (xc) {x->workers = atoi((char*)xc);xmlFree(xc);}
+	else x->workers = 4;
+
+	xc = xmlGetProp(root,(xmlChar*)"QueueLength");
+	if (xc) {x->queue_length = atoi((char*)xc);xmlFree(xc);}
+	else x->queue_length = 32;
+
+	xc = xmlGetProp(root,(xmlChar*)"ConnectTimeout");
+	if (xc) {x->connect_timeout= atoi((char*)xc);xmlFree(xc);}
+	else x->connect_timeout = 5;
+
+	xc = xmlGetProp(root,(xmlChar*)"TransactionTimeout");
+	if (xc) {x->transaction_timeout = atoi((char*)xc);xmlFree(xc);}
+	else x->transaction_timeout = 5;
+	
+	xc = xmlGetProp(root,(xmlChar*)"SessionsHashSize");
+	if (xc) {x->sessions_hash_size = atoi((char*)xc);xmlFree(xc);}
+	else x->sessions_hash_size = 128;
+
+	xc = xmlGetProp(root,(xmlChar*)"DefaultAuthSessionTimeout");
+	if (xc) {x->default_auth_session_timeout = atoi((char*)xc);xmlFree(xc);}
+	else x->default_auth_session_timeout = 60;
+
+	xc = xmlGetProp(root,(xmlChar*)"MaxAuthSessionTimeout");
+	if (xc) {x->max_auth_session_timeout = atoi((char*)xc);xmlFree(xc);}
+	else x->max_auth_session_timeout = 300;
+	
+	for(child = root->children; child; child = child->next)
+		if (child->type == XML_ELEMENT_NODE)
+	{
+		if (xmlStrlen(child->name)==4 && strncasecmp((char*)child->name,"Peer",4)==0){
+			//PEER
+			x->peers_cnt++;		
+		}
+		else if (xmlStrlen(child->name)==8 && strncasecmp((char*)child->name,"Acceptor",8)==0){
+			//Acceptor
+			x->acceptors_cnt++;		
+		}
+		else if (xmlStrlen(child->name)==4 && (strncasecmp((char*)child->name,"Auth",4)==0||
+			strncasecmp((char*)child->name,"Acct",4)==0)){
+			//Application
+			x->applications_cnt++;		
+		}	
+		else if (xmlStrlen(child->name)==15 && (strncasecmp((char*)child->name,"SupportedVendor",15)==0)){
+			//SupportedVendor
+			x->supported_vendors_cnt++;		
+		}	
+	}
+	x->peers = shm_malloc(x->peers_cnt*sizeof(peer_config));
+	if (!x->peers){
+		LOG_NO_MEM("shm",x->peers_cnt*sizeof(peer_config));
+		goto error;
+	}
+	memset(x->peers,0,x->peers_cnt*sizeof(peer_config));
+	x->peers_cnt=0;
+	x->acceptors = shm_malloc(x->acceptors_cnt*sizeof(acceptor_config));
+	if (!x->acceptors){
+		LOG_NO_MEM("shm",x->acceptors_cnt*sizeof(acceptor_config));
+		goto error;
+	}
+	memset(x->acceptors,0,x->acceptors_cnt*sizeof(acceptor_config));
+	x->acceptors_cnt=0;
+	x->applications = shm_malloc(x->applications_cnt*sizeof(app_config));
+	if (!x->applications){
+		LOG_NO_MEM("shm",x->applications_cnt*sizeof(app_config));
+		goto error;
+	}
+	memset(x->applications,0,x->applications_cnt*sizeof(app_config));
+	x->applications_cnt=0;
+
+	x->supported_vendors = shm_malloc(x->supported_vendors_cnt*sizeof(int));
+	if (!x->supported_vendors){
+		LOG_NO_MEM("shm",x->supported_vendors_cnt*sizeof(int));
+		goto error;
+	}
+	memset(x->supported_vendors,0,x->supported_vendors_cnt*sizeof(int));
+	x->supported_vendors_cnt=0;
+
+	for(child = root->children; child; child = child->next)
+		if (child->type == XML_ELEMENT_NODE)
+	{
+		if (xmlStrlen(child->name)==4 && strncasecmp((char*)child->name,"Peer",4)==0){
+			//PEER
+			xc = xmlGetProp(child,(xmlChar*)"FQDN");
+			if (xc){
+				quote_trim_dup(&(x->peers[x->peers_cnt].fqdn),(char*)xc);
+				xmlFree(xc);
+			}
+			xc = xmlGetProp(child,(xmlChar*)"Realm");
+			if (xc){
+				quote_trim_dup(&(x->peers[x->peers_cnt].realm),(char*)xc);			
+				xmlFree(xc);
+			}
+			xc = xmlGetProp(child,(xmlChar*)"port");
+			if (xc){
+				x->peers[x->peers_cnt].port = atoi((char*)xc);
+				xmlFree(xc);
+			}
+			x->peers_cnt++;		
+		}
+		else if (xmlStrlen(child->name)==8 && strncasecmp((char*)child->name,"Acceptor",8)==0){
+			//Acceptor
+			xc = xmlGetProp(child,(xmlChar*)"bind");			
+			if (xc){
+				quote_trim_dup(&(x->acceptors[x->acceptors_cnt].bind),(char*)xc);			
+				xmlFree(xc);
+			}
+			xc = xmlGetProp(child,(xmlChar*)"port");
+			if (xc){
+				x->acceptors[x->acceptors_cnt].port = atoi((char*)xc);						
+				xmlFree(xc);
+			}
+			x->acceptors_cnt++;		
+		}
+		else if (xmlStrlen(child->name)==4 && (strncasecmp((char*)child->name,"Auth",4)==0||
+			strncasecmp((char*)child->name,"Acct",4)==0)){
+			//Application
+			xc = xmlGetProp(child,(xmlChar*)"id");	
+			if (xc){
+				x->applications[x->applications_cnt].id = atoi((char*)xc);						
+				xmlFree(xc);
+			}
+			xc = xmlGetProp(child,(xmlChar*)"vendor");
+			if (xc){
+				x->applications[x->applications_cnt].vendor = atoi((char*)xc);						
+				xmlFree(xc);
+			}
+			if (child->name[1]=='u'||child->name[1]=='U')
+				x->applications[x->applications_cnt].type = DP_AUTHORIZATION;						
+			else
+				x->applications[x->applications_cnt].type = DP_ACCOUNTING;										
+			x->applications_cnt++;		
+		}	
+		else if (xmlStrlen(child->name)==15 && (strncasecmp((char*)child->name,"SupportedVendor",15)==0)){
+			//SupportedVendor
+			xc = xmlGetProp(child,(xmlChar*)"vendor");
+			if (xc){
+				x->supported_vendors[x->supported_vendors_cnt] = atoi((char*)xc);						
+				xmlFree(xc);
+			}
+			x->supported_vendors_cnt++;		
+		}	
+		else if (xmlStrlen(child->name)==12 && (strncasecmp((char*)child->name,"DefaultRoute",12)==0)){
+			if (!x->r_table) {
+				x->r_table = shm_malloc(sizeof(routing_table));
+				memset(x->r_table,0,sizeof(routing_table));
+			}
+			re = new_routing_entry();
+			if (re){			
+				xc = xmlGetProp(child,(xmlChar*)"FQDN");
+				if (xc){
+					quote_trim_dup(&(re->fqdn),(char*)xc);			
+					xmlFree(xc);
+				}
+				xc = xmlGetProp(child,(xmlChar*)"metric");			
+				if (xc){
+					re->metric = atoi((char*)xc);			
+					xmlFree(xc);
+				}
+				
+				/* add it the list in ascending order */
+				if (! x->r_table->routes || re->metric <= x->r_table->routes->metric){
+					re->next = x->r_table->routes;
+					x->r_table->routes = re;
+				}else{
+					for(rei=x->r_table->routes;rei;rei=rei->next)
+						if (!rei->next){
+							rei->next = re;
+							break;						
+						}else{
+							if (re->metric <= rei->next->metric){
+								re->next = rei->next;
+								rei->next = re;
+								break;
+							}
+						}				
+				}
+			}					
+		}
+		else if (xmlStrlen(child->name)==5 && (strncasecmp((char*)child->name,"Realm",5)==0)){
+			if (!x->r_table) {
+				x->r_table = shm_malloc(sizeof(routing_table));
+				memset(x->r_table,0,sizeof(routing_table));
+			}
+			rr = new_routing_realm();
+			if (rr){			
+				xc = xmlGetProp(child,(xmlChar*)"name");
+				quote_trim_dup(&(rr->realm),(char*)xc);			
+				
+				if (!x->r_table->realms) {				
+					x->r_table->realms = rr;
+				}else{				
+					for(rri=x->r_table->realms;rri->next;rri=rri->next);
+					rri->next = rr;				
+				}			
+				for(nephew = child->children; nephew; nephew = nephew->next)
+					if (nephew->type == XML_ELEMENT_NODE){
+						if (xmlStrlen(nephew->name)==5 && (strncasecmp((char*)nephew->name,"Route",5)==0))
+						{
+							re = new_routing_entry();
+							if (re) {
+								xc = xmlGetProp(nephew,(xmlChar*)"FQDN");
+								if (xc){
+									quote_trim_dup(&(re->fqdn),(char*)xc);	
+									xmlFree(xc);
+								}
+								xc = xmlGetProp(nephew,(xmlChar*)"metric");
+								if (xc){
+									re->metric = atoi((char*)xc);			
+									xmlFree(xc);
+								}
+								/* add it the list in ascending order */
+								if (! rr->routes || re->metric <= rr->routes->metric){
+									re->next = rr->routes;
+									rr->routes = re;
+								}else{
+									for(rei=rr->routes;rei;rei=rei->next)
+										if (!rei->next){
+											rei->next = re;
+											break;						
+										}else{
+											if (re->metric <= rei->next->metric){
+												re->next = rei->next;
+												rei->next = re;
+												break;
+											}
+										} 					
+								}
+							}
+						}
+					}
+			}		
+		}
+	}
+	
+	if (doc) xmlFreeDoc(doc);	
+	parser_destroy();
+	return x;
+error:
+	if (doc) xmlFreeDoc(doc);
+	parser_destroy();
+	if (x) free_dp_config(x);
+	return 0;	
+}
+

+ 288 - 0
modules/cdp/diameter.h

@@ -0,0 +1,288 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_H_
+#define DIAMETER_H_
+
+
+#include "utils.h"
+#include <ctype.h>
+
+#include "diameter_code_result.h"
+#include "diameter_code_avp.h"
+
+#define get_2bytes(_b) \
+	((((unsigned char)(_b)[0])<<8)|\
+	 (((unsigned char)(_b)[1])))
+
+#define get_3bytes(_b) \
+	((((unsigned char)(_b)[0])<<16)|(((unsigned char)(_b)[1])<<8)|\
+	(((unsigned char)(_b)[2])))
+
+#define get_4bytes(_b) \
+	((((unsigned char)(_b)[0])<<24)|(((unsigned char)(_b)[1])<<16)|\
+	(((unsigned char)(_b)[2])<<8)|(((unsigned char)(_b)[3])))
+
+#define set_2bytes(_b,_v) \
+	{(_b)[0]=((_v)&0x0000ff00)>>8;\
+	(_b)[1]=((_v)&0x000000ff);}
+
+#define set_3bytes(_b,_v) \
+	{(_b)[0]=((_v)&0x00ff0000)>>16;(_b)[1]=((_v)&0x0000ff00)>>8;\
+	(_b)[2]=((_v)&0x000000ff);}
+
+#define set_4bytes(_b,_v) \
+	{(_b)[0]=((_v)&0xff000000)>>24;(_b)[1]=((_v)&0x00ff0000)>>16;\
+	(_b)[2]=((_v)&0x0000ff00)>>8;(_b)[3]=((_v)&0x000000ff);}
+
+#define to_32x_len( _len_ ) \
+	( (_len_)+(((_len_)&3)?4-((_len_)&3):0) )
+	
+	
+/* AAA TYPES */
+
+#define AAA_NO_VENDOR_ID           0
+
+#define VER_SIZE                   1
+#define MESSAGE_LENGTH_SIZE        3
+#define FLAGS_SIZE                 1
+#define COMMAND_CODE_SIZE          3
+#define APPLICATION_ID_SIZE        4
+#define HOP_BY_HOP_IDENTIFIER_SIZE 4
+#define END_TO_END_IDENTIFIER_SIZE 4
+#define AVP_CODE_SIZE      4
+#define AVP_FLAGS_SIZE     1
+#define AVP_LENGTH_SIZE    3
+#define AVP_VENDOR_ID_SIZE 4
+
+#define AAA_MSG_HDR_SIZE  \
+	(VER_SIZE + MESSAGE_LENGTH_SIZE + FLAGS_SIZE + COMMAND_CODE_SIZE +\
+	APPLICATION_ID_SIZE+HOP_BY_HOP_IDENTIFIER_SIZE+END_TO_END_IDENTIFIER_SIZE)
+
+#define AVP_HDR_SIZE(_flags_)  \
+	(AVP_CODE_SIZE+AVP_FLAGS_SIZE+AVP_LENGTH_SIZE+\
+	AVP_VENDOR_ID_SIZE*(((_flags_)&AAA_AVP_FLAG_VENDOR_SPECIFIC)!=0) )
+
+/* mesage codes */
+#ifndef WORDS_BIGENDIAN
+	#define AS_MSG_CODE      0x12010000
+	#define AC_MSG_CODE      0x0f010000
+	#define CE_MSG_CODE      0x01010000
+	#define DW_MSG_CODE      0x18010000
+	#define DP_MSG_CODE      0x1a010000
+	#define RA_MSG_CODE      0x02010000
+	#define ST_MSG_CODE      0x13010000
+	#define MASK_MSG_CODE    0xffffff00
+#else
+	#error BIG endian detected!!
+	#define AS_MSG_CODE      0x00000112
+	#define AC_MSG_CODE      0x0000010f
+	#define CE_MSG_CODE      0x00000101
+	#define DW_MSG_CODE      0x00000118
+	#define DP_MSG_CODE      0x0000011a
+	#define RA_MSG_CODE      0x00000102
+	#define ST_MSG_CODE      0x00000113
+	#define MASK_MSG_CODE    0x00ffffff
+#endif
+
+
+typedef unsigned int    AAACommandCode;		/**< Code for a Diameter Command 	*/
+typedef unsigned int    AAAVendorId;		/**< Vendor identifier				*/
+typedef unsigned int    AAAExtensionId;		/**< Extension identifier			*/
+typedef unsigned int    AAA_AVPCode;		/**< Code for an AVP				*/
+typedef unsigned int    AAAValue;			/**< Value							*/
+typedef unsigned int    AAAApplicationId;	/**< Application Identifier 		*/
+typedef void*           AAAApplicationRef;	/**< Application Reference 			*/
+typedef str             AAASessionId;		/**< Session Identifier				*/
+typedef unsigned int    AAAMsgIdentifier;	/**< Message Identifier				*/
+typedef unsigned char   AAAMsgFlag;			/**< Message flag					*/
+
+#define Flag_Request 	0x80
+#define Flag_Proxyable  0x40
+
+#define Code_CE 	257
+#define Code_DW 	280
+#define Code_DP 	282
+	
+
+/** Status codes returned by functions in the AAA API */
+typedef enum {
+	AAA_ERR_NOT_FOUND = -2,         /**< handle or id not found */
+	AAA_ERR_FAILURE   = -1,         /**< unspecified failure during an AAA op. */
+	AAA_ERR_SUCCESS   =  0,         /**< AAA operation succeeded */
+	AAA_ERR_NOMEM,                  /**< op. caused memory to be exhausted */
+	AAA_ERR_PROTO,                  /**<  AAA protocol error */
+	AAA_ERR_SECURITY,
+	AAA_ERR_PARAMETER,
+	AAA_ERR_CONFIG,
+	AAA_ERR_UNKNOWN_CMD,
+	AAA_ERR_MISSING_AVP,
+	AAA_ERR_ALREADY_INIT,
+	AAA_ERR_TIMED_OUT,
+	AAA_ERR_CANNOT_SEND_MSG,
+	AAA_ERR_ALREADY_REGISTERED,
+	AAA_ERR_CANNOT_REGISTER,
+	AAA_ERR_NOT_INITIALIZED,
+	AAA_ERR_NETWORK_ERROR,
+} AAAReturnCode;
+
+
+/** The following are AVP data type codes. They correspond directly to
+ * the AVP data types outline in the Diameter specification [1]: */
+typedef enum {
+	AAA_AVP_DATA_TYPE,
+	AAA_AVP_STRING_TYPE,
+	AAA_AVP_ADDRESS_TYPE,
+	AAA_AVP_INTEGER32_TYPE,
+	AAA_AVP_INTEGER64_TYPE,
+	AAA_AVP_TIME_TYPE,
+} AAA_AVPDataType;
+
+
+/** The following are used for AVP header flags and for flags in the AVP
+ *  wrapper struct and AVP dictionary definitions. */
+typedef enum {
+	AAA_AVP_FLAG_NONE               = 0x00,
+	AAA_AVP_FLAG_MANDATORY          = 0x40,
+	AAA_AVP_FLAG_RESERVED           = 0x1F,
+	AAA_AVP_FLAG_VENDOR_SPECIFIC    = 0x80,
+	AAA_AVP_FLAG_END_TO_END_ENCRYPT = 0x20,
+} AAA_AVPFlag;
+
+
+/** List with all known application identifiers */
+typedef enum {
+	AAA_APP_DIAMETER_COMMON_MSG  = 0,
+	AAA_APP_NASREQ               = 1,
+	AAA_APP_MOBILE_IP            = 2,
+	AAA_APP_DIAMETER_BASE_ACC    = 3,
+	AAA_APP_RELAY                = 0xffffffff,
+}AAA_APP_IDS;
+
+
+/**   The following type allows the client to specify which direction to
+ *   search for an AVP in the AVP list: */
+typedef enum {
+	AAA_FORWARD_SEARCH = 0,	/**< search forward 	*/
+	AAA_BACKWARD_SEARCH		/**< search backwards 	*/
+} AAASearchType;
+
+/** Hint on what do do with the AVP payload */
+typedef enum {
+	AVP_DUPLICATE_DATA,		/**< Duplicate the payload; the source can be safely removed at any time */
+	AVP_DONT_FREE_DATA,		/**< Don't duplicate and don't free; the source will always be there. */
+	AVP_FREE_DATA,			/**< Don't duplicate, but free when done; this is the only reference to source. */
+} AVPDataStatus;
+
+/** This structure contains a message AVP in parsed format */
+typedef struct avp {
+	struct avp *next;		/**< next AVP if in a list 				*/
+	struct avp *prev;		/**< previous AVP if in a list 			*/
+	AAA_AVPCode code;		/**< AVP code 							*/
+	AAA_AVPFlag flags;		/**< AVP flags 							*/
+	AAA_AVPDataType type;	/**< AVP payload type 					*/
+	AAAVendorId vendorId;	/**< AVP vendor id 						*/
+	str data;				/**< AVP payload						*/
+	unsigned char free_it;	/**< if to free the payload when done	*/
+} AAA_AVP;
+
+
+/**
+ * This structure is used for representing lists of AVPs on the
+ * message or in grouped AVPs. */
+typedef struct _avp_list_t {
+	AAA_AVP *head;			/**< The first AVP in the list 	*/
+	AAA_AVP *tail;			/**< The last AVP in the list 	*/
+} AAA_AVP_LIST;
+
+
+/** This structure contains the full AAA message. */
+typedef struct _message_t {
+	AAACommandCode      commandCode;	/**< command code for the message */
+	AAAMsgFlag          flags;			/**< flags */
+	AAAApplicationId    applicationId;	/**< application identifier */
+	AAAMsgIdentifier    endtoendId;		/**< End-to-end identifier */
+	AAAMsgIdentifier    hopbyhopId;		/**< Hop-by-hop identitfier */
+	AAA_AVP		       	*sessionId;		/**< SessionId 				*/
+	AAA_AVP             *orig_host;		/**< shortcut to Origin Host AVP */
+	AAA_AVP             *orig_realm;	/**< shortcut to Origin Realm AVP */
+	AAA_AVP             *dest_host;		/**< shortcut to Destination Host AVP */
+	AAA_AVP             *dest_realm;	/**< shortcut to Destination Realm AVP */
+	AAA_AVP             *res_code;		/**< shortcut to Result Code AVP */
+	AAA_AVP             *auth_ses_state;/**< shortcut to Authorization Session State AVP */
+	AAA_AVP_LIST        avpList;		/**< list of AVPs in the message */
+	str                 buf;			/**< Diameter network representation */
+	void                *in_peer;		/**< Peer that this message was received from */
+} AAAMessage;
+
+
+
+
+/**************************** AAA MESSAGE FUNCTIONS **************************/
+
+/* MESSAGES */
+
+/** if the message is a request */
+#define is_req(_msg_) \
+	(((_msg_)->flags)&0x80)
+
+
+
+/*************************** AAA Transactions ********************************/
+/**
+ * This structure defines a Diameter Transaction.
+ * This is used to link a response to a request
+ */
+typedef struct _AAATransaction{
+	unsigned int hash,label;
+	AAAApplicationId application_id;
+	AAACommandCode command_code;
+} AAATransaction;
+
+
+/** Function for callback on transaction events: response or time-out for request. */
+typedef void (AAATransactionCallback_f)(int is_timeout,void *param,AAAMessage *ans);
+/** Function for callback on request received */
+typedef AAAMessage* (AAARequestHandler_f)(AAAMessage *req, void *param);
+/** Function for callback on response received */
+typedef void (AAAResponseHandler_f)(AAAMessage *res, void *param);
+
+
+#endif /*DIAMETER_H_*/

+ 208 - 0
modules/cdp/diameter_api.h

@@ -0,0 +1,208 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_API_H_
+#define __DIAMETER_API_H_
+
+#include "diameter.h"
+#include "utils.h"
+#include "session.h"
+#include "transaction.h"
+
+
+/* MESSAGE CREATION */
+				
+AAAMessage *AAACreateRequest(AAAApplicationId app_id,
+							AAACommandCode command_code,
+							AAAMsgFlag flags,
+							AAASession *session);
+typedef AAAMessage* (*AAACreateRequest_f)(AAAApplicationId app_id,
+							AAACommandCode command_code,
+							AAAMsgFlag flags,
+							AAASession *session);
+
+AAAMessage *AAACreateResponse(AAAMessage *request);
+typedef AAAMessage* (*AAACreateResponse_f)(AAAMessage *request);
+
+
+AAAMessage *AAANewMessage(
+		AAACommandCode commandCode,
+		AAAApplicationId appId,
+		AAASession *session,
+		AAAMessage *request);
+
+AAAReturnCode AAAFreeAVPList(AAA_AVP_LIST *avpList);
+typedef AAAReturnCode  (*AAAFreeAVPList_f)(AAA_AVP_LIST *avpList);
+
+
+
+AAAResultCode AAASetMessageResultCode(AAAMessage *message,AAAResultCode resultCode);
+
+void AAAPrintMessage(AAAMessage *msg);
+
+AAAReturnCode AAABuildMsgBuffer(AAAMessage *msg );
+
+AAAMessage* AAATranslateMessage(unsigned char* source,unsigned int sourceLen,int attach_buf );
+
+
+/* AVPS */
+
+/** 
+ * Create and add an AVP to the message, by duplicating the storage space
+ */
+#define AAACreateAndAddAVPToMessage(_msg_,_code_,_flags_,_vdr_,_data_,_len_) \
+	( AAAAddAVPToMessage(_msg_, \
+	AAACreateAVP(_code_,_flags_,_vdr_,_data_,_len_, AVP_DUPLICATE_DATA),\
+	(_msg_)->avpList.tail) )
+
+AAA_AVP* AAACreateAVP(
+			AAA_AVPCode code,
+			AAA_AVPFlag flags,
+			AAAVendorId vendorId,
+			char *data,
+			size_t length,
+			AVPDataStatus data_status);
+typedef AAA_AVP* (*AAACreateAVP_f)(
+				AAA_AVPCode code,
+				AAA_AVPFlag flags,
+				AAAVendorId vendorId,
+				char *data,
+				size_t length,
+				AVPDataStatus data_status);
+
+AAA_AVP* AAACloneAVP(AAA_AVP *avp,unsigned char duplicate_data);
+
+AAAReturnCode AAAAddAVPToMessage(
+			AAAMessage *msg,
+			AAA_AVP *avp,
+			AAA_AVP *position);
+typedef AAAReturnCode (*AAAAddAVPToMessage_f)(
+			AAAMessage *msg,
+			AAA_AVP *avp,
+			AAA_AVP *position);
+
+
+AAA_AVP *AAAFindMatchingAVP(
+			AAAMessage *msg,
+			AAA_AVP *startAvp,
+			AAA_AVPCode avpCode,
+			AAAVendorId vendorId,
+			AAASearchType searchType);				
+typedef AAA_AVP* (*AAAFindMatchingAVP_f)(
+			AAAMessage *msg,
+			AAA_AVP *startAvp,
+			AAA_AVPCode avpCode,
+			AAAVendorId vendorId,
+			AAASearchType searchType);
+
+AAAReturnCode AAARemoveAVPFromMessage(AAAMessage *msg,AAA_AVP *avp);
+
+AAAReturnCode AAAFreeAVP(AAA_AVP **avp);
+typedef AAAReturnCode (*AAAFreeAVP_f)(AAA_AVP **avp);
+
+
+AAA_AVP* AAAGetFirstAVP(AAA_AVP_LIST *avpList);
+
+AAA_AVP* AAAGetLastAVP(AAA_AVP_LIST *avpList);
+
+AAA_AVP* AAAGetNextAVP(AAA_AVP *avp);
+typedef AAA_AVP* (*AAAGetNextAVP_f)(AAA_AVP *avp);
+
+
+AAA_AVP* AAAGetPrevAVP(AAA_AVP *avp);
+
+char *AAAConvertAVPToString(AAA_AVP *avp,char *dest,unsigned int destLen);
+
+ 
+
+str AAAGroupAVPS(AAA_AVP_LIST avps);
+typedef str (*AAAGroupAVPS_f)(AAA_AVP_LIST avps);
+
+AAA_AVP_LIST AAAUngroupAVPS(str buf);
+typedef AAA_AVP_LIST (*AAAUngroupAVPS_f)(str buf);
+
+
+AAA_AVP  *AAAFindMatchingAVPList(
+			AAA_AVP_LIST avpList,
+			AAA_AVP *startAvp,
+			AAA_AVPCode avpCode,
+			AAAVendorId vendorId,
+			AAASearchType searchType);
+typedef AAA_AVP  *(*AAAFindMatchingAVPList_f)(
+			AAA_AVP_LIST avpList,
+			AAA_AVP *startAvp,
+			AAA_AVPCode avpCode,
+			AAAVendorId vendorId,
+			AAASearchType searchType);
+
+
+void AAAAddAVPToList(AAA_AVP_LIST *list,AAA_AVP *avp);
+typedef void (*AAAAddAVPToList_f)(AAA_AVP_LIST *list,AAA_AVP *avp);	
+
+
+/* CALLBACKS */
+
+
+int AAAAddRequestHandler(AAARequestHandler_f *f,void *param);
+typedef int (*AAAAddRequestHandler_f)(AAARequestHandler_f *f,void *param);
+
+int AAAAddResponseHandler(AAAResponseHandler_f *f,void *param);
+typedef int (*AAAAddResponseHandler_f)(AAAResponseHandler_f *f,void *param);
+
+/* MESSAGE SENDING */
+
+AAAReturnCode AAASendMessage(AAAMessage *message,AAATransactionCallback_f *callback_f,void *callback_param);
+typedef AAAReturnCode (*AAASendMessage_f)(AAAMessage *message,AAATransactionCallback_f *callback_f,void *callback_param);
+
+AAAReturnCode AAASendMessageToPeer(AAAMessage *message,str *peer_id,AAATransactionCallback_f *callback_f,void *callback_param);
+typedef AAAReturnCode (*AAASendMessageToPeer_f)(AAAMessage *message,str *peer_id,AAATransactionCallback_f *callback_f,void *callback_param);
+
+AAAMessage* AAASendRecvMessage(AAAMessage *msg);
+typedef AAAMessage* (*AAASendRecvMessage_f)(AAAMessage *msg);
+
+AAAMessage* AAASendRecvMessageToPeer(AAAMessage *msg, str *peer_id);
+typedef AAAMessage* (*AAASendRecvMessageToPeer_f)(AAAMessage *msg, str *peer_id);
+
+AAAReturnCode AAAFreeMessage(AAAMessage **message);
+typedef AAAReturnCode (*AAAFreeMessage_f)(AAAMessage **message);
+
+
+
+#endif /*DIAMETER_API_H_*/

+ 752 - 0
modules/cdp/diameter_avp.c

@@ -0,0 +1,752 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include "diameter.h"
+#include "utils.h"
+
+
+/* Start of disc implementation */
+
+/**
+ * Takes care that each AVP type has the default flags set/reset and a proper data type.
+ * All this default values (for flags and data-type) are correct/set by this
+ * function.
+ * @param code - code of the AVP
+ * @param avp - the actual AVP to set flags
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+inline void set_avp_fields( AAA_AVPCode code, AAA_AVP *avp)
+{
+	switch (code) {
+		case   1: /*AVP_User_Name*/
+		case  25: /*AVP_Class*/
+		case 263: /*AVP_Session_Id*/
+		case 283: /*AVP_Destination_Realm*/
+		case 293: /*AVP Destination Host*/
+		case 264: /*AVP_Origin_Host*/
+		case 296: /*AVP Origin_Realm*/
+			avp->flags = 0x40|(0x20&avp->flags);
+			avp->type = AAA_AVP_STRING_TYPE;
+			break;
+		case  27: /*AVP_Session_Timeout*/
+		case 258: /*AVP_Auth_Aplication_Id*/
+		case 262: /*AVP_Redirect_Max_Cache_Time*/
+		case 265: /*AVP_Supported_Vendor_Id*/
+		case 266: /*AVP_Vendor_Id*/
+		case 268: /*AVP_Result_Code*/
+		case 270: /*AVP_Session_Binding*/
+		case 276: /*AVP_Auth_Grace_Period*/
+		case 278: /*AVP_Origin_State_Id*/
+		case 291: /*AVP_Authorization_Lifetime*/
+			avp->flags = 0x40|(0x20&avp->flags);
+			avp->type = AAA_AVP_INTEGER32_TYPE;
+			break;
+		case 33: /*AVP_Proxy_State*/
+			avp->flags = 0x40;
+			avp->type = AAA_AVP_STRING_TYPE;
+			break;
+		case 257: /*AVP_Host_IP_Address*/
+			avp->flags = 0x40|(0x20&avp->flags);
+			avp->type = AAA_AVP_ADDRESS_TYPE;
+			break;
+		case 269: /*AVP_Product_Name*/
+			avp->flags = 0x00;
+			avp->type = AAA_AVP_STRING_TYPE;
+			break;
+		case 281: /*AVP_Error_Message*/
+			avp->flags = (0x20&avp->flags);
+			avp->type = AAA_AVP_STRING_TYPE;
+			break;
+		default:
+			avp->type = AAA_AVP_DATA_TYPE;
+	};
+}
+
+
+
+/** 
+ * This function creates an AVP and returns a pointer to it.
+ * @param code - the code of the new AVP
+ * @param flags - the flags to set
+ * @param vendorId - vendor id
+ * @param data - the generic payload data
+ * @param length - length of the payload
+ * @param data_status - what to do with the payload: duplicate, free with the message, etc
+ * @returns the AAA_AVP* or null on error
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP*  AAACreateAVP(
+	AAA_AVPCode code,
+	AAA_AVPFlag flags,
+	AAAVendorId vendorId,
+	char   *data,
+	size_t length,
+	AVPDataStatus data_status)
+{
+	AAA_AVP *avp;
+
+	/* first check the params */
+	if( data==0 || length==0) {
+		LM_ERR("AAACreateAVP: NULL value received for"
+			" param data/length (AVP Code %d, VendorId %d)!!\n",code,vendorId);
+		return 0;
+	}
+
+	/* allocated a new AVP struct */
+	avp = 0;
+	avp = (AAA_AVP*)shm_malloc(sizeof(AAA_AVP));
+	if (!avp)
+		goto error;
+	memset( avp, 0, sizeof(AAA_AVP) );
+
+	/* set some fields */
+	//avp->free_it = free_it;
+	avp->code=code;
+	avp->flags=flags;
+	avp->vendorId=vendorId;
+	set_avp_fields( code, avp);
+
+	if ( data_status==AVP_DUPLICATE_DATA ) {
+		/* make a duplicate for data */
+		avp->data.len = length;
+		avp->data.s = (void*)shm_malloc(length);
+		if(!avp->data.s)
+			goto error;
+		memcpy( avp->data.s, data, length);
+		avp->free_it = 1;
+	} else {
+		avp->data.s = data;
+		avp->data.len = length;
+		avp->free_it = (data_status==AVP_FREE_DATA)?1:0;
+	}
+
+	return avp;
+error:
+	LM_ERR("AAACreateAVP: no more free memory!\n");
+	return 0;
+}
+
+
+
+/**
+ *  Insert the AVP avp into the avpList of a message, after a certain position.
+ * @param msg - the AAAMessage to add to
+ * @param avp - the AAA_AVP to add
+ * @param position - AAA_AVP to add after. If NULL, will add at the beginning.
+ * @returns AAA_ERR_SUCCESS on success or AAA_ERR_PARAMETER if the position is not found
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAAReturnCode  AAAAddAVPToMessage(
+	AAAMessage *msg,
+	AAA_AVP *avp,
+	AAA_AVP *position)
+{
+	AAA_AVP *avp_t;
+
+	if ( !msg || !avp ) {
+		LM_ERR("AAAAddAVPToMessage: param msg or avp passed null"
+			" or *avpList=NULL and position!=NULL !!\n");
+		return AAA_ERR_PARAMETER;
+	}
+
+	if (!position) {
+		/* insert at the begining */
+		avp->next = msg->avpList.head;
+		avp->prev = 0;
+		msg->avpList.head = avp;
+		if (avp->next)
+			avp->next->prev = avp;
+		else
+			msg->avpList.tail = avp;
+	} else {
+		/* look after avp from position */
+		for(avp_t=msg->avpList.head;avp_t&&avp_t!=position;avp_t=avp_t->next);
+		if (!avp_t) {
+			LM_ERR("AAAAddAVPToMessage: the \"position\" avp is not in"
+				"\"msg\" message!!\n");
+			return AAA_ERR_PARAMETER;
+		}
+		/* insert after position */
+		avp->next = position->next;
+		position->next = avp;
+		if (avp->next)
+			avp->next->prev = avp;
+		else
+			msg->avpList.tail = avp;
+		avp->prev = position;
+	}
+
+	/* update the short-cuts */
+	switch (avp->code) {
+		case AVP_Session_Id: msg->sessionId = avp;break;
+		case AVP_Origin_Host: msg->orig_host = avp;break;
+		case AVP_Origin_Realm: msg->orig_realm = avp;break;
+		case AVP_Destination_Host: msg->dest_host = avp;break;
+		case AVP_Destination_Realm: msg->dest_realm = avp;break;
+		case AVP_Result_Code: msg->res_code = avp;break;
+		case AVP_Auth_Session_State: msg->auth_ses_state = avp;break;
+	}
+
+	return AAA_ERR_SUCCESS;
+}
+
+
+
+/**
+ *  This function finds an AVP with matching code and vendor id.
+ * @param msg - message to look into
+ * @param startAvp - where to start the search. Usefull when you want to find the next one.
+ * 	Even this one will be checked and can be returned if it fits.
+ * @param avpCode - code of the AVP to match
+ * @param vendorId - vendor id to match
+ * @param searchType - whether to look forward or backward
+ * @returns the AAA_AVP* if found, NULL if not 
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP  *AAAFindMatchingAVP(
+	AAAMessage *msg,
+	AAA_AVP *startAvp,
+	AAA_AVPCode avpCode,
+	AAAVendorId vendorId,
+	AAASearchType searchType)
+{
+	AAA_AVP *avp_t;
+
+	/* param checking */
+	if (!msg) {
+		LM_ERR("FindMatchingAVP: param msg passed null !!\n");
+		goto error;
+	}
+
+	/* where should I start searching from ? */
+	if (startAvp) {
+		/* double-check the startAVP avp */
+		for(avp_t=msg->avpList.head;avp_t&&avp_t!=startAvp;avp_t=avp_t->next);
+		if (!avp_t) {
+			LM_ERR("AAAFindMatchingAVP: the \"position\" avp is not "
+				"in \"avpList\" list!!\n");
+			goto error;
+		}
+		avp_t=startAvp;
+	} else {
+		/* if no startAVP -> start from one of the ends */
+		avp_t=(searchType==AAA_FORWARD_SEARCH)?(msg->avpList.head):
+			(msg->avpList.tail);
+	}
+
+	/* start searching */
+	while(avp_t) {
+		if (avp_t->code==avpCode && avp_t->vendorId==vendorId)
+			return avp_t;
+		avp_t = (searchType==AAA_FORWARD_SEARCH)?(avp_t->next):(avp_t->prev);
+	}
+
+error:
+	return 0;
+}
+
+
+
+/**
+ *  This function removes an AVP from a message.
+ * @param msg - the diameter message 
+ * @param avp - the AVP to remove
+ * @returns AAA_ERR_SUCCESS on success or AAA_ERR_PARAMETER if not found
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAAReturnCode  AAARemoveAVPFromMessage(
+	AAAMessage *msg,
+	AAA_AVP *avp)
+{
+	AAA_AVP *avp_t;
+
+	/* param check */
+	if ( !msg || !avp ) {
+		LM_ERR("AAARemoveAVPFromMessage: param AVP_LIST \"avpList\" or AVP "
+			"\"avp\" passed null !!\n");
+		return AAA_ERR_PARAMETER;
+	}
+
+	/* search the "avp" avp */
+	for(avp_t=msg->avpList.head;avp_t&&avp_t!=avp;avp_t=avp_t->next);
+	if (!avp_t) {
+		LM_ERR("AAARemoveAVPFromMessage: the \"avp\" avp is not in "
+			"\"avpList\" avp list!!\n");
+		return AAA_ERR_PARAMETER;
+	}
+
+	/* remove the avp from list */
+	if (msg->avpList.head==avp)
+		msg->avpList.head = avp->next;
+	else
+		avp->prev->next = avp->next;
+	if (avp->next)
+		avp->next->prev = avp->prev;
+	else
+		msg->avpList.tail = avp->prev;
+	avp->next = avp->prev = 0;
+
+	/* update short-cuts */
+	switch (avp->code) {
+		case AVP_Session_Id: msg->sessionId = 0;break;
+		case AVP_Origin_Host: msg->orig_host = 0;break;
+		case AVP_Origin_Realm: msg->orig_realm = 0;break;
+		case AVP_Destination_Host: msg->dest_host = 0;break;
+		case AVP_Destination_Realm: msg->dest_realm = 0;break;
+		case AVP_Result_Code: msg->res_code = 0;break;
+		case AVP_Auth_Session_State: msg->auth_ses_state = 0;break;
+	}
+
+	return AAA_ERR_SUCCESS;
+}
+
+
+
+/**
+ *  The function frees the memory allocated to an AVP 
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAAReturnCode  AAAFreeAVP(AAA_AVP **avp)
+{
+	/* some checks */
+	if (!avp || !(*avp)) {
+		LM_ERR("AAAFreeAVP: param avp cannot be null!!\n");
+		return AAA_ERR_PARAMETER;
+	}
+
+	/* free all the mem */
+	if ( (*avp)->free_it && (*avp)->data.s )
+		shm_free((*avp)->data.s);
+
+	shm_free( *avp );
+	avp = 0;
+
+	return AAA_ERR_SUCCESS;
+}
+
+
+
+/**
+ *  This function returns the first AVP in the list.
+ * @param avpList - the list 
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP*  AAAGetFirstAVP(AAA_AVP_LIST *avpList){
+	return avpList->head;
+}
+
+
+
+/**
+ *  This function returns the last AVP in the list.
+ * @param avpList - the list  
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP*  AAAGetLastAVP(AAA_AVP_LIST *avpList)
+{
+	return avpList->tail;
+}
+
+
+
+
+/**
+ *  This function returns the next AVP in the list that this AVP was extracted from
+ * @param avp - reference avp
+ * @returns  the next AAA_AVP or NULL if this was the last one
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP*  AAAGetNextAVP(AAA_AVP *avp)
+{
+	return avp->next;
+}
+
+
+
+/**
+ *  This function returns a the previous AVP in the list  that this AVP was extracted from
+ * @param avp - reference avp
+ * @returns  the next AAA_AVP or NULL if this was the first one
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP*  AAAGetPrevAVP(AAA_AVP *avp)
+{
+	return avp->prev;
+}
+
+
+
+/**
+ *  This function converts the data in the AVP to a format suitable for
+ * print, log or display.
+ * @param avp - the AAA_AVP to print
+ * @param dest - preallocated destination buffer. If too short, message will be truncated 
+ * @param destLen - length of the destipation buffer 
+ * @returns dest on success, NULL on failure 
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+char*  AAAConvertAVPToString(AAA_AVP *avp, char *dest, unsigned int destLen)
+{
+	int l;
+	int i;
+
+	if (!avp || !dest || !destLen) {
+		LM_ERR("AAAConvertAVPToString: param AVP, DEST or DESTLEN "
+			"passed as null!!!\n");
+		return 0;
+	}
+	l = snprintf(dest,destLen,"AVP(%p < %p >%p);code=%u,"
+		"flags=%x;\nDataType=%u;VendorID=%u;DataLen=%u;\n",
+		avp->prev,avp,avp->next,avp->code,avp->flags,
+		avp->type,avp->vendorId,avp->data.len);
+	switch(avp->type) {
+		case AAA_AVP_STRING_TYPE:
+			l+=snprintf(dest+l,destLen-l,"String: <%.*s>",avp->data.len,
+				avp->data.s);
+			break;
+		case AAA_AVP_INTEGER32_TYPE:
+			l+=snprintf(dest+l,destLen-l,"Int32: <%u>(%x)",
+				htonl(*((unsigned int*)avp->data.s)),
+				htonl(*((unsigned int*)avp->data.s)));
+			break;
+		case AAA_AVP_ADDRESS_TYPE:
+			i = 1;
+			switch (avp->data.len) {
+				case 4: i=i*0;
+				case 6: i=i*2;
+					l+=snprintf(dest+l,destLen-l,"Address IPv4: <%d.%d.%d.%d>",
+						(unsigned char)avp->data.s[i+0],
+						(unsigned char)avp->data.s[i+1],
+						(unsigned char)avp->data.s[i+2],
+						(unsigned char)avp->data.s[i+3]);
+					break;
+				case 16: i=i*0;
+				case 18: i=i*2;
+					l+=snprintf(dest+l,destLen-l,
+						"Address IPv6: <%x.%x.%x.%x.%x.%x.%x.%x>",
+						((avp->data.s[i+0]<<8)+avp->data.s[i+1]),
+						((avp->data.s[i+2]<<8)+avp->data.s[i+3]),
+						((avp->data.s[i+4]<<8)+avp->data.s[i+5]),
+						((avp->data.s[i+6]<<8)+avp->data.s[i+7]),
+						((avp->data.s[i+8]<<8)+avp->data.s[i+9]),
+						((avp->data.s[i+10]<<8)+avp->data.s[i+11]),
+						((avp->data.s[i+12]<<8)+avp->data.s[i+13]),
+						((avp->data.s[i+14]<<8)+avp->data.s[i+15]));
+					break;
+			break;
+			}
+			break;
+		//case AAA_AVP_INTEGER64_TYPE:
+		case AAA_AVP_TIME_TYPE:
+		default:
+			LM_WARN("AAAConvertAVPToString: don't know how to print"
+				" this data type [%d] -> tryng hexa\n",avp->type);
+		case AAA_AVP_DATA_TYPE:
+			for (i=0;i<avp->data.len&&l<destLen-1;i++)
+			l+=snprintf(dest+l,destLen-l-1,"%x",
+				((unsigned char*)avp->data.s)[i]);
+	}
+	return dest;
+}
+
+
+/**
+ * Duplicate a whole AAA_AVP.
+ * @param avp - original avp
+ * @param clone_data - whether to duplicate also the data payload
+ * @returns the new AAA_AVP* or NULL on error
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAA_AVP* AAACloneAVP( AAA_AVP *avp , unsigned char clone_data)
+{
+	AAA_AVP *n_avp;
+
+	if (!avp || !(avp->data.s) || !(avp->data.len) )
+		goto error;
+
+	/* clone the avp structure */
+	n_avp = (AAA_AVP*)shm_malloc( sizeof(AAA_AVP) );
+	if (!n_avp) {
+		LM_ERR("clone_avp: cannot get free memory!!\n");
+		goto error;
+	}
+	memcpy( n_avp, avp, sizeof(AAA_AVP));
+	n_avp->next = n_avp->prev = 0;
+
+	if (clone_data) {
+		/* clone the avp data */
+		n_avp->data.s = (char*)shm_malloc( avp->data.len );
+		if (!(n_avp->data.s)) {
+			LM_ERR("clone_avp: cannot get free memory!!\n");
+			shm_free( n_avp );
+			goto error;
+		}
+		memcpy( n_avp->data.s, avp->data.s, avp->data.len);
+		n_avp->free_it = 1;
+	} else {
+		/* link the clone's data to the original's data */
+		n_avp->data.s = avp->data.s;
+		n_avp->data.len = avp->data.len;
+		n_avp->free_it = 0;
+	}
+
+	return n_avp;
+error:
+	return 0;
+}
+
+/* End of disc implementation */
+
+/* Simple extension for grouped avp based on the above implementation  */
+
+/**
+ * Adds an AVP to a list of AVPs, at the end.
+ * @param list - the list to add to
+ * @param avp - the avp to add 
+ */ 
+void AAAAddAVPToList(AAA_AVP_LIST *list,AAA_AVP *avp)
+{
+	if (list->tail) {
+		avp->prev=list->tail;
+		avp->next=0;	
+		list->tail->next = avp;
+		list->tail=avp;
+	} else {
+		list->head = avp;
+		list->tail = avp;
+		avp->next=0;
+		avp->prev=0;
+	}	
+}
+ 
+/** 
+ * Groups a list of avps into a data buffer
+ * @param avps 
+ */
+str AAAGroupAVPS(AAA_AVP_LIST avps)
+ {
+ 	AAA_AVP *avp;
+	unsigned char *p;
+	str buf={0,0};
+
+	/* count and add the avps */
+	for(avp=avps.head;avp;avp=avp->next) {
+		buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
+	}
+
+	if (!buf.len) return buf;
+	/* allocate some memory */
+	buf.s = (char*)shm_malloc( buf.len );
+	if (!buf.s) {
+		LM_ERR("hss3g_group_avps: no more free memory!\n");
+		buf.len=0;
+		return buf;
+	}
+	memset(buf.s, 0, buf.len);
+	/* fill in the buffer */
+	p = (unsigned char*) buf.s;
+	for(avp=avps.head;avp;avp=avp->next) {
+		/* AVP HEADER */
+		/* avp code */
+		set_4bytes(p,avp->code);
+		p +=4;
+		/* flags */
+		(*p++) = (unsigned char)avp->flags;
+		/* avp length */
+		set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
+		p += 3;
+		/* vendor id */
+		if ((avp->flags&0x80)!=0) {
+			set_4bytes(p,avp->vendorId);
+			p +=4;
+		}
+		/* data */
+		memcpy( p, avp->data.s, avp->data.len);
+		p += to_32x_len( avp->data.len );
+	}
+	if ((char*)p-buf.s!=buf.len) {
+		LM_ERR("BUG:hss3g_group_avps: mismatch between len and buf!\n");
+		shm_free( buf.s );
+		buf.s = 0;
+		buf.len = 0;
+		return buf;
+	}
+	return buf;
+}
+
+/** 
+ * Ungroup from a data buffer a list of avps
+ * @param buf - payload to ungroup the list from
+ * @returns the AAA_AVP_LIST or an empty one on error 
+ */
+AAA_AVP_LIST AAAUngroupAVPS(str buf)
+{
+	char *ptr;
+	AAA_AVP       *avp;
+	unsigned int  avp_code;
+	unsigned char avp_flags;
+	unsigned int  avp_len;
+	unsigned int  avp_vendorID;
+	unsigned int  avp_data_len;
+	AAA_AVP_LIST	lh;
+
+	lh.head=0;
+	lh.tail=0;
+	ptr = buf.s;
+
+	/* start decoding the AVPS */
+	while (ptr < buf.s+buf.len) {
+		if (ptr+AVP_HDR_SIZE(0x80)>buf.s+buf.len){
+			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
+				"Cannot read the whole AVP header!\n");
+			goto error;
+		}
+		/* avp code */
+		avp_code = get_4bytes( ptr );
+		ptr += AVP_CODE_SIZE;
+		/* avp flags */
+		avp_flags = (unsigned char)*ptr;
+		ptr += AVP_FLAGS_SIZE;
+		/* avp length */
+		avp_len = get_3bytes( ptr );
+		ptr += AVP_LENGTH_SIZE;
+		if (avp_len<1) {
+			LM_ERR("hss3g_ungroup_avps: invalid AVP len [%d]\n",
+				avp_len);
+			goto error;
+		}
+		/* avp vendor-ID */
+		avp_vendorID = 0;
+		if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
+			avp_vendorID = get_4bytes( ptr );
+			ptr += AVP_VENDOR_ID_SIZE;
+		}
+
+		/* data length */
+		avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
+		/*check the data length */
+		if ( buf.s+buf.len<ptr+avp_data_len) {
+			LM_ERR("hss3g_ungroup_avps: source buffer to short!! "
+				"Cannot read a whole data for AVP!\n");
+			goto error;
+		}
+
+		/* create the AVP */
+		avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, ptr,
+			avp_data_len, AVP_DONT_FREE_DATA);
+		if (!avp) {
+			LM_ERR("hss3g_ungroup_avps: can't create avp for member of list\n");
+			goto error;
+		}
+
+		/* link the avp into aaa message to the end */
+  		avp->next = 0;
+		avp->prev = lh.tail;
+		if (lh.tail) {
+			lh.tail->next=avp;
+			lh.tail=avp;
+		}
+		else {
+			lh.tail=avp;
+			lh.head=avp;
+		}
+
+		ptr += to_32x_len( avp_data_len );
+	}
+	return lh;
+
+error:
+	LM_CRIT("AVP:<%.*s>\n",buf.len,buf.s);
+	return lh;
+}
+
+/**
+ * Find an avp into a list of avps.
+ * @param avpList - the list to look into
+ * @param startAvp - where to start the search. Usefull when you want to find the next one. 
+ * Even this one will be checked and can be returned if it fits.
+ * @param avpCode - the AVP code to match
+ * @param vendorId - the vendor id to match
+ * @param searchType - direction of search
+ * @returns the AAA_AVP* if found, NULL if not
+ */
+AAA_AVP  *AAAFindMatchingAVPList(
+	AAA_AVP_LIST avpList,
+	AAA_AVP *startAvp,
+	AAA_AVPCode avpCode,
+	AAAVendorId vendorId,
+	AAASearchType searchType)
+{
+	AAA_AVP *avp_t;
+
+	/* param checking */
+
+	/* where should I start searching from ? */
+	if (startAvp) {
+		/* double-check the startAVP avp */
+		for(avp_t=avpList.head;avp_t&&avp_t!=startAvp;avp_t=avp_t->next);
+		if (!avp_t) {
+			LM_ERR("ndMatchingAVP: the \"position\" avp is not "
+				"in \"avpList\" list!!\n");
+			goto error;
+		}
+		avp_t=startAvp;
+	} else {
+		/* if no startAVP -> start from one of the ends */
+		avp_t=(searchType==AAA_FORWARD_SEARCH)?(avpList.head):
+			(avpList.tail);
+	}
+
+	/* start searching */
+	while(avp_t) {
+		if (avp_t->code==avpCode && avp_t->vendorId==vendorId)
+			return avp_t;
+		avp_t = (searchType==AAA_FORWARD_SEARCH)?(avp_t->next):(avp_t->prev);
+	}
+
+error:
+	return 0;
+}
+ 

+ 561 - 0
modules/cdp/diameter_code_avp.h

@@ -0,0 +1,561 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_CODE_AVP_H_
+#define DIAMETER_CODE_AVP_H_
+
+/** Standard AVP Codes */
+typedef enum {
+	
+	/* RFC 3588 */
+	
+	AVP_User_Name                     =    1,
+	AVP_User_Password				  =    2, //RFC4005
+	AVP_NAS_IP_Addresss				  =    4, //RFC4005
+	AVP_NAS_Port					  =    5, //RFC4005
+	AVP_Service_Type				  =    6, //RFC4005
+	AVP_Framed_Protocol				  =    7, //RFC4005
+	AVP_Framed_IP_Address             =	   8, //RFC4005
+	AVP_Framed_IP_Netmask			  =    9, //RFC4005
+	AVP_Framed_Routing				  =   10, //RFC4005
+	AVP_Filter_Id					  =   11, //RFC4005
+	AVP_Framed_MTU					  =   12, //RFC4005
+	AVP_Framed_Compression			  =   13, //RFC4005
+	AVP_Login_IP_Host				  =   14, //RFC4005
+	AVP_Login_Service				  =   15, //RFC4005
+	AVP_Login_TCP_Port				  =   16, //RFC4005
+	AVP_Reply_Message				  =   18, //RFC4005
+	AVP_Callback_Number				  =   19, //RFC4005
+	AVP_Callback_Id					  =   20, //RFC4005
+	AVP_Framed_Route				  =   22, //RFC4005
+	AVP_Framed_IPX_Network			  =   23, //RFC4005
+	AVP_State						  =   24, //RFC4005
+	AVP_Class                         =   25,
+	AVP_Session_Timeout               =   27,
+	AVP_Idle_Timeout				  =   28, //RFC4005
+	AVP_Called_Station_Id			  =   30, //RFC4005
+	AVP_Calling_Station_Id			  =   31, //RFC4005
+	AVP_NAS_Identifier				  =   32, //RFC4005
+	AVP_Proxy_State                   =   33,
+	AVP_Login_LAT_Service			  =   34, //RFC4005
+	AVP_Login_LAT_Node				  =   35, //RFC4005
+	AVP_Login_LAT_Group				  =   36, //RFC4005
+	AVP_Framed_Appletalk_Link		  =   37, //RFC4005
+	AVP_Framed_Appletalk_Network	  =   38, //RFC4005
+	AVP_Framed_Appletalk_Zone		  =   39, //RFC4005
+	AVP_Acct_Delay_Time				  =   41, //RFC4005
+	AVP_Acct_Session_Id				  =   44,
+	AVP_Acct_Authentic				  =   45, //RFC4005
+	AVP_Acct_Session_Time			  =   46, //RFC4005
+	AVP_Acct_Multi_Session_Id		  =   50,
+	AVP_Link_Count					  =   51, //RFC4005
+	AVP_Event_Timestamp               =   55,
+	AVP_CHAP_Challenge				  =   60, //RFC4005
+	AVP_NAS_Port_Type                 =   61, //RFC4005
+	AVP_Port_Limit					  =   62, //RFC4005
+	AVP_Login_LAT_Port				  =   63, //RFC4005
+	AVP_Tunnel_Type					  =   64, //RFC4005
+	AVP_Tunnel_Medium_Type			  =   65, //RFC4005
+	AVP_Tunnel_Client_Endpoint		  =   66, //RFC4005
+	AVP_Tunnel_Server_Endpoint		  =   67, //RFC4005
+	AVP_Acct_Tunnel_Connection		  =   68, //RFC4005
+	AVP_Tunnel_Password				  =   69, //RFC4005
+	AVP_ARAP_Password				  =   70, //RFC4005
+	AVP_ARAP_Features				  =   71, //RFC4005
+	AVP_ARAP_Zone_Access			  =   72, //RFC4005
+	AVP_ARAP_Security				  =   73, //RFC4005
+	AVP_ARAP_Security_Data			  =   74, //RFC4005
+	AVP_Password_Retry				  =   75, //RFC4005
+	AVP_Prompt						  =   76, //RFC4005
+	AVP_Connect_Info				  =   77, //RFC4005
+	AVP_Configuration_Token			  =   78, //RFC4005
+	AVP_Tunnel_Private_Group_Id		  =   81, //RFC4005
+	AVP_Tunnel_Assignment_Id		  =   82, //RFC4005
+	AVP_Tunnel_Preference			  =   83, //RFC4005
+	AVP_ARAP_Challenge_Response		  =   84, //RFC4005
+	AVP_Acct_Interim_Interval         =   85,
+	AVP_Acct_Tunnel_Packets_Lost	  =   86, //RFC4005
+	AVP_NAS_Port_Id					  =   87, //RFC4005
+	AVP_Framed_Pool					  =   88, //RFC4005
+	AVP_Tunnel_Client_Auth_Id		  =   90, //RFC4005
+	AVP_Tunnel_Server_Auth_Id		  =   91,
+	AVP_Originating_Line_Info		  =   94, //RFC4005
+	AVP_NAS_IPv6_Address			  =   95, //RFC4005
+	AVP_Framed_Interface_Id           =   96, //RFC4005
+	AVP_Framed_IPv6_Prefix            =   97, //RFC4005
+	AVP_Framed_IPv6_Route			  =   98, //RFC4005
+#define AVP_Login_IPv6_Host				  98	
+	AVP_Framed_IPv6_Pool			  =  100, //RFC4005
+	
+	AVP_MIP6_Feature_Vector			  =  124, //RFC5447
+	AVP_MIP6_Home_Link_Prefix		  =  125, //RFC5447
+	
+	AVP_Host_IP_Address               =  257,
+	AVP_Auth_Application_Id           =  258,
+	AVP_Acct_Application_Id           =  259,	
+	AVP_Vendor_Specific_Application_Id=  260,
+	AVP_Redirect_Host_Usage			  =  261,
+	AVP_Redirect_Max_Cache_Time       =  262,
+	AVP_Session_Id                    =  263,
+	AVP_Origin_Host                   =  264,
+	AVP_Supported_Vendor_Id           =  265,
+	AVP_Vendor_Id                     =  266,
+	AVP_Firmware_Revision             =  267,
+	AVP_Result_Code                   =  268,
+	AVP_Product_Name                  =  269,
+	AVP_Session_Binding               =  270,
+	AVP_Session_Server_Failover		  =  271,
+	AVP_Multi_Round_Time_Out          =  272,
+	AVP_Disconnect_Cause              =  273,
+	AVP_Auth_Request_Type             =  274,
+	AVP_Auth_Grace_Period             =  276,
+	AVP_Auth_Session_State            =  277,
+	AVP_Origin_State_Id               =  278,
+	AVP_Failed_AVP					  =  279,
+	AVP_Proxy_Host                    =  280,
+	AVP_Error_Message                 =  281,
+	AVP_Route_Record                  =  282,
+	AVP_Destination_Realm             =  283,
+	AVP_Proxy_Info                    =  284,
+	AVP_Re_Auth_Request_Type          =  285,
+	AVP_Accounting_Sub_Session_Id	  =  287,
+	AVP_Authorization_Lifetime        =  291,
+	AVP_Redirect_Host                 =  292,
+	AVP_Destination_Host              =  293,
+	AVP_Error_Reporting_Host		  =  294,
+	AVP_Termination_Cause             =  295,
+	AVP_Origin_Realm                  =  296,
+	AVP_Experimental_Result			  =  297,
+	AVP_Experimental_Result_Code      =  298,
+	AVP_Inband_Security_Id			  =  299,
+	
+	AVP_E2E_Sequence				  =  300,
+	AVP_Accounting_Input_Octets		  =  363, //RFC4005
+	AVP_Accounting_Output_Octets	  =  364, //RFC4005
+	AVP_Accounting_Input_Packets	  =  365, //RFC4005
+	AVP_Accounting_Output_Packets	  =  366, //RFC4005
+	
+	/* RFC 4004 */
+	AVP_MIP_Reg_Request               =  320, 
+	AVP_MIP_Reg_Reply                 =  321, 
+	AVP_MIP_MN_AAA_Auth               =  322, 
+	AVP_MIP_Mobile_Node_Address       =  333, 
+	AVP_MIP_Home_Agent_Address        =  334, 
+	AVP_MIP_Candidate_Home_Agent_Host =  336, 
+	AVP_MIP_Feature_Vector            =  337, 
+	AVP_MIP_Auth_Input_Data_Length    =  338, 
+	AVP_MIP_Authenticator_Length      =  339, 
+	AVP_MIP_Authenticator_Offset      =  340, 
+	AVP_MIP_MN_AAA_SPI                =  341, 
+	AVP_MIP_Filter_Rule               =  342, 
+	AVP_MIP_FA_Challenge              =  344, 
+	AVP_MIP_Originating_Foreign_AAA   =  347, 
+	AVP_MIP_Home_Agent_Host           =  348, 
+	
+	/* RFC 4005 */
+	AVP_NAS_Filter_Rule				  =  400,
+	AVP_Tunneling					  =  401,
+	AVP_CHAP_Auth					  =  402,
+	AVP_CHAP_Algorithm				  =  403,
+	AVP_CHAP_Ident					  =  404,
+	AVP_CHAP_Response				  =  405,
+	AVP_Accounting_Auth_Method		  =  406,
+	AVP_QoS_Filter_Rule				  =  407,
+	AVP_Origin_AAA_Protocol			  =  408,
+	
+	/* RFC 4006 */
+	AVP_CC_Correlation_Id			  =  411,
+	AVP_CC_Input_Octets				  =  412,
+	AVP_CC_Money                      =  413,
+	AVP_CC_Output_Octets              =  414,
+	AVP_CC_Request_Number             =  415, 
+	AVP_CC_Request_Type               =  416,
+	AVP_CC_Service_Specific_Units     =  417,
+	AVP_CC_Session_Failover           =  418,
+	AVP_CC_Sub_Session_Id             =  419,
+	AVP_CC_Time                       =  420,
+	AVP_CC_Total_Octets               =  421,
+	AVP_Check_Balance_Result          =  422,
+	AVP_Cost_Information              =  423,
+	AVP_Cost_Unit                     =  424,
+	AVP_Currency_Code                 =  425,
+	AVP_Credit_Control                =  426,
+	AVP_Credit_Control_Failure_Handling= 427,
+	AVP_Direct_Debiting_Failure_Handling=428,
+	AVP_Exponent                      =  429,
+	AVP_Final_Unit_Indication		  =  430,
+	AVP_Granted_Service_Unit          =  431,
+	AVP_Rating_Group				  =  432,
+	AVP_Redirect_Address_Type         =  433,
+	AVP_Redirect_Server               =  434,
+	AVP_Redirect_Server_Address       =  435,
+	AVP_Requested_Action              =  436,
+	AVP_Requested_Service_Unit        =  437,
+	AVP_Restriction_Filter_Rule       =  438,
+	AVP_Service_Identifier			  =  439,
+	AVP_Service_Parameter_Info        =  440,
+	AVP_Service_Parameter_Type        =  441,
+	AVP_Service_Parameter_Value       =  442,
+	AVP_Subscription_Id				  =  443, 
+	AVP_Subscription_Id_Data		  =  444,
+	AVP_Unit_Value                    =  445,
+	AVP_Used_Service_Unit             =  446,
+	AVP_Value_Digits                  =  447,
+	AVP_Validity_Time                 =  448,
+	AVP_Final_Unit_Action			  =  449, 
+	AVP_Subscription_Id_Type		  =  450,
+	AVP_Tariff_Time_Change            =  451, 
+	AVP_Tariff_Change_Usage           =  452,
+	AVP_G_S_U_Pool_Identifier         =  453,
+	AVP_CC_Unit_Type                  =  454,
+	AVP_Multiple_Services_Indicator   =  455,
+	AVP_Multiple_Services_Credit_Control=456,
+	AVP_G_S_U_Pool_Reference          =  457,
+	AVP_User_Equipment_Info	          =  458, 
+	AVP_User_Equipment_Info_Type      =  459, 
+	AVP_User_Equipment_Info_Value	  =  460,
+	AVP_Service_Context_Id            =  461,
+	
+	
+	AVP_Accounting_Record_Type        =  480,
+	AVP_Accounting_Realtime_Required  =  483,
+	AVP_Accounting_Record_Number      =  485,
+	AVP_MIP6_Agent_Info				  =  486, //RFC5447
+	
+	AVP_Service_Selection			  =  493, //RFC5778  
+	
+}AAA_AVPCodeNr;
+
+enum {
+	AVP_CC_Request_Type_Initial_Request		= 1,
+	AVP_CC_Request_Type_Update_Request		= 2,
+	AVP_CC_Request_Type_Termination_Request	= 3,
+	AVP_CC_Request_Type_Event_Request		= 4,
+};
+
+enum  {
+	AVP_CC_Session_Failover_Failover_Not_Supported	= 0,
+	AVP_CC_Session_Failover_Failover_Supported		= 1,
+};
+
+enum  {
+	AVP_Check_Balance_Result_Enough_Credit	= 0,
+	AVP_Check_Balance_Result_No_Credit		= 1,
+};
+
+enum  {
+	AVP_Credit_Control_Credit_Authorization	= 0,
+	AVP_Credit_Control_Re_Authorization		= 1,
+};
+
+enum  {
+	AVP_Credit_Control_Failure_Handling_Terminate			= 0,
+	AVP_Credit_Control_Failure_Handling_Continue			= 1,
+	AVP_Credit_Control_Failure_Handling_Retry_And_Terminate	= 2,	
+};
+
+enum  {
+	AVP_Direct_Debiting_Failure_Handling_Terminate_Or_Buffer	= 0,
+	AVP_Direct_Debiting_Failure_Handling_Continue				= 1,
+};
+
+enum  {
+	AVP_Tariff_Change_Usage_Unit_Before_Tariff_Change	= 0,
+	AVP_Tariff_Change_Usage_Unit_After_Tariff_Change	= 1,
+	AVP_Tariff_Change_Usage_Unit_Indeterminate			= 2,
+};
+
+enum  {
+	AVP_CC_Unit_Type_Time					= 0,
+	AVP_CC_Unit_Type_Money					= 1,
+	AVP_CC_Unit_Type_Total_Octets			= 2,
+	AVP_CC_Unit_Type_Input_Octets			= 3,
+	AVP_CC_Unit_Type_Output_Octets			= 4,
+	AVP_CC_Unit_Type_Service_Specific_Units	= 5,
+};
+
+enum  {
+	AVP_Final_Unit_Action_Terminate			= 0,
+	AVP_Final_Unit_Action_Redirect			= 1,
+	AVP_Final_Unit_Action_Restrict_Access	= 2,
+};
+
+enum  {
+	AVP_Redirect_Address_Type_IPv4_Address	= 0,
+	AVP_Redirect_Address_Type_IPv6_Address	= 1,
+	AVP_Redirect_Address_Type_URL			= 2,
+	AVP_Redirect_Address_Type_SIP_URI		= 3
+};
+
+enum  {
+	AVP_Multiple_Services_Indicator_Multiple_Services_Not_Supported	= 0,
+	AVP_Multiple_Services_Indicator_Multiple_Services_Supported		= 1,
+};
+
+enum  {
+	AVP_Redirect_Action_Direct_Debiting	= 0,
+	AVP_Redirect_Action_Refund_Account	= 1,
+	AVP_Redirect_Action_Check_Ballance	= 2,
+	AVP_Redirect_Action_Price_Enquiry	= 3,
+};
+
+enum {
+	AVP_Subscription_Id_Type_E164			= 0,
+	AVP_Subscription_Id_Type_IMSI			= 1,
+	AVP_Subscription_Id_Type_SIP_URI		= 2,
+	AVP_Subscription_Id_Type_NAI			= 3,
+	AVP_Subscription_Id_Type_USER_PRIVATE	= 4
+};
+
+enum {
+	AVP_User_Equipment_Info_Type_IMEISV			= 0,
+	AVP_User_Equipment_Info_Type_MAC			= 1,
+	AVP_User_Equipment_Info_Type_EUI64			= 2,
+	AVP_User_Equipment_Info_Type_MODIFIED_EUI64	= 3,
+};
+
+
+
+typedef enum
+{
+	AVP_NAS_Port_Type_Async					= 0,
+	AVP_NAS_Port_Type_Sync 					= 1, 
+	AVP_NAS_Port_Type_ISDN_Sync 			= 2, 
+	AVP_NAS_Port_Type_ISDN_Async_V120 		= 3,
+	AVP_NAS_Port_Type_ISDN_Async_V110		= 4,
+	AVP_NAS_Port_Type_Virtual				= 5, 
+	AVP_NAS_Port_Type_PIAFS					= 6, 	
+	AVP_NAS_Port_Type_HDLC_Clear_Channel	= 7, 
+	AVP_NAS_Port_Type_X_25					= 8, 
+	AVP_NAS_Port_Type_X_75					= 9, 
+	AVP_NAS_Port_Type_G_3_Fax				=10,
+	AVP_NAS_Port_Type_Symmetric_DSL			=11, 	
+	AVP_NAS_Port_Type_ADSL_CAP				=12,
+	AVP_NAS_Port_Type_ADSL_DMT				=13, 
+	AVP_NAS_Port_Type_IDSL					=14, 
+	AVP_NAS_Port_Type_Ethernet				=15, 
+	AVP_NAS_Port_Type_xDSL					=16, 
+	AVP_NAS_Port_Type_Cable					=17, 
+	AVP_NAS_Port_Type_Wireless_Other		=18,
+	AVP_NAS_Port_Type_Wireless_IEEE_802_11	=19,
+	AVP_NAS_Port_Type_Token_Ring			=20, 
+	AVP_NAS_Port_Type_FDDI					=21,
+	AVP_NAS_Port_Type_Wireless_CDMA2000		=22,
+	AVP_NAS_Port_Type_Wireless_UMTS			=23,
+	AVP_NAS_Port_Type_Wireless_1X_EV		=24,
+	AVP_NAS_Port_Type_IAPP  				=25
+}	nas_port_type;						
+
+enum {
+	AVP_Prompt_No_Echo	= 0,
+	AVP_Prompt_Echo		= 1,
+};
+
+enum {
+	AVP_CHAP_Algorithm_CHAP_with_MD5	= 5,
+};
+
+
+enum {
+	AVP_Service_Type_Login						= 1,
+	AVP_Service_Type_Framed						= 2,
+	AVP_Service_Type_Callback_Login				= 3,
+	AVP_Service_Type_Callback_Framed			= 4,
+	AVP_Service_Type_Outbound					= 5,
+	AVP_Service_Type_Administrative				= 6,
+	AVP_Service_Type_NAS_Prompt					= 7,
+	AVP_Service_Type_Authenticate_Only			= 8,
+	AVP_Service_Type_Callback_NAS_Prompt		= 9,
+	AVP_Service_Type_Call_Check					= 10,
+	AVP_Service_Type_Callback_Administrative	= 11,
+	AVP_Service_Type_Voice						= 12,
+	AVP_Service_Type_Fax						= 13,
+	AVP_Service_Type_Modem_Relay				= 14,
+	AVP_Service_Type_IAPP_Register				= 15,
+	AVP_Service_Type_IAPP_AP_Check				= 16,
+	AVP_Service_Type_Authorize_Only				= 17,
+};
+
+enum {
+	AVP_Framed_Protocol_PPP						= 0,
+	AVP_Framed_Protocol_SLIP					= 1,
+	AVP_Framed_Protocol_ARAP					= 2,
+	AVP_Framed_Protocol_Gandalf					= 3,
+	AVP_Framed_Protocol_Xylogics_IPX_SLIP		= 4,
+	AVP_Framed_Protocol_X_75_Synchronous		= 5,
+};
+
+enum {
+	AVP_Framed_Routing_None							= 0,
+	AVP_Framed_Routing_Send_Routing_Packets			= 1,
+	AVP_Framed_Routing_Listen_for_Routing_Packets	= 2,
+	AVP_Framed_Routing_Send_and_Listen				= 3,
+};
+
+enum {
+	AVP_Framed_Compression_None							= 0,
+	AVP_Framed_Compression_VJ_TCP_IP_Header_Compression	= 1,
+	AVP_Framed_Compression_IPX_Header_Compression		= 2,
+	AVP_Framed_Compression_Stac_LZS_Compression			= 3,
+	AVP_Framed_Compression_
+};
+
+enum {
+	AVP_Login_Service_Telnet			= 0,
+	AVP_Login_Service_Rlogin			= 1,
+	AVP_Login_Service_TCP_Clear			= 2,
+	AVP_Login_Service_PortMaster		= 3,
+	AVP_Login_Service_LAT				= 4,		
+	AVP_Login_Service_X25_PAD			= 5,
+	AVP_Login_Service_X25_T3POS			= 6,
+	AVP_Login_Service_TCP_Clear_Quiet	= 7,
+};
+
+enum {
+	AVP_Tunnel_Type_PPTP					= 1,
+	AVP_Tunnel_Type_L2F						= 2,
+	AVP_Tunnel_Type_L2TP					= 3,
+	AVP_Tunnel_Type_ATMP					= 4,
+	AVP_Tunnel_Type_VTP						= 5,
+	AVP_Tunnel_Type_AH						= 6,
+	AVP_Tunnel_Type_IPIP_Encapsulation		= 7,
+	AVP_Tunnel_Type_MIN_IPIP_Encapsulation	= 8,
+	AVP_Tunnel_Type_ESP						= 9,
+	AVP_Tunnel_Type_GRE						= 10,
+	AVP_Tunnel_Type_DVS						= 11,
+	AVP_Tunnel_Type_IPIP_Tunneling 			= 12,
+	AVP_Tunnel_Type_VLAN					= 13,
+};
+
+enum {
+	AVP_Tunnel_Medium_Type_IPv4			= 1,
+	AVP_Tunnel_Medium_Type_IPv6			= 2,
+	AVP_Tunnel_Medium_Type_NSAP			= 3,
+	AVP_Tunnel_Medium_Type_HDLC			= 4,
+	AVP_Tunnel_Medium_Type_BBN_1822		= 5,
+	AVP_Tunnel_Medium_Type_802			= 6,
+	AVP_Tunnel_Medium_Type_E_163		= 7,
+	AVP_Tunnel_Medium_Type_E_164		= 8,
+	AVP_Tunnel_Medium_Type_F_69			= 9,
+	AVP_Tunnel_Medium_Type_X_121		= 10,
+	AVP_Tunnel_Medium_Type_IPX			= 11,
+	AVP_Tunnel_Medium_Type_Appletalk	= 12,
+	AVP_Tunnel_Medium_Type_Decnet_IV	= 13,
+	AVP_Tunnel_Medium_Type_Banyan_Vines	= 14,
+	AVP_Tunnel_Medium_Type_E_164_NSAP	= 15,
+};
+
+enum {
+	AVP_Acct_Authentic_RADIUS	= 1,
+	AVP_Acct_Authentic_Local	= 2,
+	AVP_Acct_Authentic_Remote	= 3,
+	AVP_Acct_Authentic_Diameter	= 4,
+};
+
+enum {
+	AVP_Accounting_Auth_Method_PAP			= 1,
+	AVP_Accounting_Auth_Method_CHAP			= 2,
+	AVP_Accounting_Auth_Method_MS_CHAP_1	= 3,
+	AVP_Accounting_Auth_Method_MS_CHAP_2	= 4,
+	AVP_Accounting_Auth_Method_EAP			= 5,
+	AVP_Accounting_Auth_Method_None			= 7,
+};
+
+enum {
+	AVP_Termination_Cause_User_Request				= 11,
+	AVP_Termination_Cause_Lost_Carrier				= 12,
+	AVP_Termination_Cause_Lost_Service				= 13,
+	AVP_Termination_Cause_Idle_Timeout				= 14,
+	AVP_Termination_Cause_Session_Timeout			= 15,
+	AVP_Termination_Cause_Admin_Reset				= 16,
+	AVP_Termination_Cause_Admin_Reboot				= 17,
+	AVP_Termination_Cause_Port_Error				= 18,
+	AVP_Termination_Cause_NAS_Error					= 19,
+	AVP_Termination_Cause_NAS_Request				= 20,
+	AVP_Termination_Cause_NAS_Reboot				= 21,
+	AVP_Termination_Cause_Port_Unneeded				= 22,
+	AVP_Termination_Cause_Port_Preempted			= 23,
+	AVP_Termination_Cause_Port_Suspended			= 24,
+	AVP_Termination_Cause_Service_Unavailable		= 25,
+	AVP_Termination_Cause_Callback					= 26,
+	AVP_Termination_Cause_User_Error				= 27,
+	AVP_Termination_Cause_Host_Request				= 28,
+	AVP_Termination_Cause_Supplicant_Restart		= 29,
+	AVP_Termination_Cause_Reauthentication_Failure	= 30,
+};
+
+enum {
+	AVP_Origin_AAA_Protocol_RADIUS	= 1,
+};
+
+enum {
+	AVP_Accounting_Record_Type_Event_Record		= 1,
+	AVP_Accounting_Record_Type_Start_Record		= 2,
+	AVP_Accounting_Record_Type_Interim_Record	= 3,
+	AVP_Accounting_Record_Type_Stop_Record		= 4,			
+};
+
+
+
+
+
+typedef enum {
+        Permanent_Termination   = 0,
+        New_Server_Assigned     = 1,
+        Server_Change           = 2,
+        Remove_S_CSCF           = 3,
+}AAA_AVPReasonCode;
+
+typedef enum {
+	STATE_MAINTAINED			= 0,
+	NO_STATE_MAINTAINED			= 1
+} AAA_AVP_Auth_Session_State;
+
+
+/** Accounting message types */
+typedef enum {
+	AAA_ACCT_EVENT = 1,
+	AAA_ACCT_START = 2,
+	AAA_ACCT_INTERIM = 3,
+	AAA_ACCT_STOP = 4
+} AAAAcctMessageType;
+
+
+#endif /*DIAMETER_H_*/

+ 136 - 0
modules/cdp/diameter_code_result.h

@@ -0,0 +1,136 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_CODE_RESULT_H_
+#define DIAMETER_CODE_RESULT_H_
+
+
+/** The following are the result codes returned from remote servers as
+ * part of messages */
+typedef enum {
+	AAA_MULTI_ROUND_AUTH          = 1001,
+	AAA_SUCCESS                   = 2001,
+	AAA_COMMAND_UNSUPPORTED       = 3001,
+	AAA_UNABLE_TO_DELIVER         = 3002,
+	AAA_REALM_NOT_SERVED          = 3003,
+	AAA_TOO_BUSY                  = 3004,
+	AAA_LOOP_DETECTED             = 3005,
+	AAA_REDIRECT_INDICATION       = 3006,
+	AAA_APPLICATION_UNSUPPORTED   = 3007,
+	AAA_INVALID_HDR_BITS          = 3008,
+	AAA_INVALID_AVP_BITS          = 3009,
+	AAA_UNKNOWN_PEER              = 3010,
+	AAA_AUTHENTICATION_REJECTED   = 4001,
+	AAA_OUT_OF_SPACE              = 4002,
+	AAA_ELECTION_LOST             = 4003,
+	AAA_AVP_UNSUPPORTED           = 5001,
+	AAA_UNKNOWN_SESSION_ID        = 5002,
+	AAA_AUTHORIZATION_REJECTED    = 5003,
+	AAA_INVALID_AVP_VALUE         = 5004,
+	AAA_MISSING_AVP               = 5005,
+	AAA_RESOURCES_EXCEEDED        = 5006,
+	AAA_CONTRADICTING_AVPS        = 5007,
+	AAA_AVP_NOT_ALLOWED           = 5008,
+	AAA_AVP_OCCURS_TOO_MANY_TIMES = 5009,
+	AAA_NO_COMMON_APPLICATION     = 5010,
+	AAA_UNSUPPORTED_VERSION       = 5011,
+	AAA_UNABLE_TO_COMPLY          = 5012,
+	AAA_INVALID_BIT_IN_HEADER     = 5013,
+	AAA_INVALIS_AVP_LENGTH        = 5014,
+	AAA_INVALID_MESSGE_LENGTH     = 5015,
+	AAA_INVALID_AVP_BIT_COMBO     = 5016,
+	AAA_NO_COMMON_SECURITY        = 5017,
+} AAAResultCode;
+
+
+
+/**	Diameter Result Codes				*/
+enum {
+	/* RFC 3588 */
+	DIAMETER_MULTI_ROUND_AUTH							= 1001,	
+	
+	DIAMETER_SUCCESS									= 2001,//7D1
+	DIAMETER_LIMITED_SUCCESS							= 2002,
+	
+	DIAMETER_COMMAND_UNSUPPORTED						= 3001,
+	DIAMETER_UNABLE_TO_DELIVER							= 3002,
+	DIAMETER_REALM_NOT_SERVED							= 3003,//0xBBB
+	DIAMETER_TOO_BUSY									= 3004,
+	DIAMETER_LOOP_DETECTED								= 3005,
+	DIAMETER_REDIRECT_INDICATION						= 3006,
+	DIAMETER_APPLICATION_UNSUPPORTED					= 3007,
+	DIAMETER_INVALID_HDR_BITS							= 3008,
+	DIAMETER_INVALID_AVP_BITS							= 3009,
+	DIAMETER_UNKNOWN_PEER								= 3010,
+	
+	DIAMETER_AUTHENTICATION_REJECTED					= 4001,//FA1
+	DIAMETER_OUT_OF_SPACE								= 4002,
+	DIAMETER_ELECTION_LOST								= 4003,
+	
+	DIAMETER_AVP_UNSUPPORTED							= 5001,
+	DIAMETER_UNKNOWN_SESSION_ID							= 5002,
+	DIAMETER_AUTHORIZATION_REJECTED						= 5003,//138B
+	DIAMETER_INVALID_AVP_VALUE							= 5004,
+	DIAMETER_MISSING_AVP								= 5005,//0x138D
+	DIAMETER_RESOURCES_EXCEEDED							= 5006,
+	DIAMETER_CONTRADICTING_AVPS							= 5007,
+	DIAMETER_AVP_NOT_ALLOWED							= 5008,//0x140
+	DIAMETER_AVP_OCCURS_TOO_MANY_TIMES 					= 5009,
+	DIAMETER_NO_COMMON_APPLICATION						= 5010,//0x1392
+	DIAMETER_UNSUPPORTED_VERSION						= 5011,
+	DIAMETER_UNABLE_TO_COMPLY							= 5012,//0x1394
+	DIAMETER_INVALID_BIT_IN_HEADER						= 5013,
+	DIAMETER_INVALID_AVP_LENGTH							= 5014,
+	DIAMETER_INVALID_MESSAGE_LENGTH						= 5015,
+	DIAMETER_INVALID_AVP_BIT_COMBO						= 5016,
+	DIAMETER_NO_COMMON_SECURITY							= 5017,//0x1399
+	
+	/* RFC 4006 */
+	DIAMETER_END_USER_SERVICE_DENIED					= 4010,
+	DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE				= 4011,
+	DIAMETER_CREDIT_LIMIT_REACHED						= 4012,
+	
+	DIAMETER_USER_UNKNOWN								= 5030,
+	DIAMETER_RATING_FAILED								= 5031
+};
+
+
+
+#endif /*DIAMETER_CODE_RESULT_H_*/

+ 358 - 0
modules/cdp/diameter_comm.c

@@ -0,0 +1,358 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "diameter_api.h"
+#include "peer.h"
+#include "peermanager.h"
+#include "receiver.h"
+#include "transaction.h"
+#include "api_process.h"
+#include "routing.h"
+#include "peerstatemachine.h"
+#include "globals.h"
+
+extern dp_config *config;				/**< Configuration for this diameter peer 	*/
+extern unsigned int latency_threshold;	/**<max delay for Diameter call */
+
+				/* CALLBACKS */
+extern handler_list *handlers; 		/**< list of handlers */
+extern gen_lock_t *handlers_lock;	/**< lock for list of handlers */
+
+/**
+ * Add a handler function for incoming requests.
+ * @param f - the callback function
+ * @param param - generic parameter to be used when calling the callback functions
+ * @returns 1 on success, 0 on failure
+ */
+int AAAAddRequestHandler(AAARequestHandler_f *f,void *param)
+{
+	handler *h = shm_malloc(sizeof(handler));
+	if (!h) {
+		LM_ERR("AAAAddRequestHandler: error allocating %ld bytes in shm\n",
+			(long int)sizeof(handler));
+		return 0;
+	}
+	h->type = REQUEST_HANDLER;
+	h->handler.requestHandler = f;
+	h->param = param;
+	h->next = 0;
+	lock_get(handlers_lock);
+	h->prev = handlers->tail;
+	if (handlers->tail) handlers->tail->next = h;
+	handlers->tail = h;
+	if (!handlers->head) handlers->head = h;
+	lock_release(handlers_lock);
+	return 1;
+}
+
+/**
+ * Add a handler function for incoming responses.
+ * @param f - the callback function
+ * @param param - generic parameter to be used when calling the callback functions
+ * @returns 1 on success, 0 on failure
+ */
+int AAAAddResponseHandler(AAAResponseHandler_f *f,void *param)
+{
+	handler *h = shm_malloc(sizeof(handler));
+	if (!h) {
+		LM_ERR("AAAAddResponseHandler: error allocating %ld bytes in shm\n",
+			(long int)sizeof(handler));
+		return 0;
+	}
+	h->type = RESPONSE_HANDLER;
+	h->handler.responseHandler = f;
+	h->param = param;
+	h->next = 0;
+	lock_get(handlers_lock);
+	h->prev = handlers->tail;
+	if (handlers->tail) handlers->tail->next = h;
+	handlers->tail = h;
+	if (!handlers->head) handlers->head = h;
+	lock_release(handlers_lock);
+	return 1;
+}
+
+
+				/* MESSAGE SENDING */
+
+/**
+ * Send a AAAMessage asynchronously.
+ * When the response is received, the callback_f(callback_param,...) is called.
+ * @param message - the request to be sent
+ * @param peer_id - FQDN of the peer to send
+ * @param callback_f - callback to be called on transactional response or transaction timeout
+ * @param callback_param - generic parameter to call the transactional callback function with
+ * @returns 1 on success, 0 on failure 
+ * \todo remove peer_id and add Realm routing
+ */
+AAAReturnCode AAASendMessage(	
+		AAAMessage *message,
+		AAATransactionCallback_f *callback_f,
+		void *callback_param)
+{
+	peer *p;
+	p = get_routing_peer(message);
+	if (!p) {
+		LM_ERR("AAASendMessage(): Can't find a suitable connected peer in the routing table.\n");
+		goto error;
+	}
+	if (p->state!=I_Open && p->state!=R_Open){
+		LM_ERR("AAASendMessage(): Peer not connected to %.*s\n",p->fqdn.len,p->fqdn.s);
+		goto error;
+	}
+	/* only add transaction following when required */
+	if (callback_f){
+		if (is_req(message))
+			cdp_add_trans(message,callback_f,callback_param,config->transaction_timeout,1);
+		else
+			LM_ERR("AAASendMessage(): can't add transaction callback for answer.\n");
+	}
+	
+//	if (!peer_send_msg(p,message))
+	if (!sm_process(p,Send_Message,message,0,0))	
+		goto error;
+		
+	return 1;
+error:	
+	AAAFreeMessage(&message);
+	return 0;
+}
+
+/**
+ * Send a AAAMessage asynchronously.
+ * When the response is received, the callback_f(callback_param,...) is called.
+ * @param message - the request to be sent
+ * @param peer_id - FQDN of the peer to send
+ * @param callback_f - callback to be called on transactional response or transaction timeout
+ * @param callback_param - generic parameter to call the transactional callback function with
+ * @returns 1 on success, 0 on failure 
+ * \todo remove peer_id and add Realm routing
+ */
+AAAReturnCode AAASendMessageToPeer(	
+		AAAMessage *message,
+		str *peer_id, 
+		AAATransactionCallback_f *callback_f,
+		void *callback_param)
+{
+	peer *p;
+	p = get_peer_by_fqdn(peer_id);
+	if (!p) {
+		LM_ERR("AAASendMessageToPeer(): Peer unknown %.*s\n",peer_id->len,peer_id->s);
+		goto error;
+	}
+	if (p->state!=I_Open && p->state!=R_Open){
+		LM_ERR("AAASendMessageToPeer(): Peer not connected to %.*s\n",peer_id->len,peer_id->s);
+		goto error;
+	}
+	/* only add transaction following when required */
+	if (callback_f){
+		if (is_req(message))
+			cdp_add_trans(message,callback_f,callback_param,config->transaction_timeout,1);
+		else
+			LM_ERR("AAASendMessageToPeer(): can't add transaction callback for answer.\n");
+	}
+		
+//	if (!peer_send_msg(p,message))
+	if (!sm_process(p,Send_Message,message,0,0))	
+		goto error;
+		
+	return 1;
+error:	
+	AAAFreeMessage(&message);
+	return 0;
+}
+
+
+/**
+ * Generic callback used by AAASendRecvMessage() to block until a transactional response
+ * is received.
+ * The AAASendRecvMessage() is basically a AAASendMessage() that has a callback 
+ * (this function) that blocks until a transactional response or timeout is received and 
+ * then it returns that.
+ *  
+ * @param is_timeout - if this is a time-out or response event
+ * @param param - generic parameter to call the transactional callback function with
+ * @param ans - the answer for the callback
+ */
+void sendrecv_cb(int is_timeout,void *param,AAAMessage *ans)
+{
+	if (sem_release((gen_sem_t*)param)<0)
+		LM_ERR("sendrecv_cb(): Failed to unlock a transactional sendrecv! > %s\n",strerror(errno));
+}
+
+/**
+ * Send a AAAMessage synchronously.
+ * This blocks until a response is received or a transactional time-out happens. 
+ * @param message - the request to be sent
+ * @param peer_id - FQDN of the peer to send
+ * @returns 1 on success, 0 on failure 
+ * \todo remove peer_id and add Realm routing
+ * \todo replace the busy-waiting lock in here with one that does not consume CPU
+ */
+AAAMessage* AAASendRecvMessage(AAAMessage *message)
+{
+	peer *p;
+	gen_sem_t *sem=0;
+	cdp_trans_t *t;
+	AAAMessage *ans;
+	unsigned int ms = 0;
+	
+	p = get_routing_peer(message);
+	if (!p) {
+		LM_ERR("AAASendRecvMessage(): Can't find a suitable connected peer in the routing table.\n");
+		goto error;
+	}
+	if (p->state!=I_Open && p->state!=R_Open){
+		LM_ERR("AAASendRecvMessage(): Peer not connected to %.*s\n",p->fqdn.len,p->fqdn.s);
+		goto error;
+	}
+	
+	
+	if (is_req(message)){
+		sem_new(sem,0);
+		t = cdp_add_trans(message,sendrecv_cb,(void*)sem,config->transaction_timeout,0);
+
+		ms = TICKS_TO_MS(get_ticks_raw());
+//		if (!peer_send_msg(p,message)) {
+		if (!sm_process(p,Send_Message,message,0,0)){	
+			sem_free(sem);	
+			goto error;
+		}
+		ms = TICKS_TO_MS(get_ticks_raw()) - ms;
+		if (ms > latency_threshold)
+			LM_ERR("took too long to transition state machine for Send_Message [%dms]\n", ms);
+
+		ms = TICKS_TO_MS(get_ticks_raw());
+
+		/* block until callback is executed */
+		while(sem_get(sem)<0){
+			if (shutdownx&&(*shutdownx)) goto error;
+			LM_WARN("AAASendRecvMessage(): interrupted by signal or something > %s\n",strerror(errno));
+		}
+		sem_free(sem);
+		ms = TICKS_TO_MS(get_ticks_raw()) - ms;
+		if (ms > latency_threshold) {
+			LM_ERR("CDP response to Send_Message took too long (>%dms) - [%dms]\n", latency_threshold, ms);
+		}
+		ans = t->ans;
+		cdp_free_trans(t);
+		return ans;
+	} else {
+		LM_ERR("AAASendRecvMessage(): can't add wait for answer to answer.\n");
+		goto error;
+	}
+
+		
+error:	
+out_of_memory:
+	AAAFreeMessage(&message);
+	return 0;
+}
+
+/**
+ * Send a AAAMessage synchronously.
+ * This blocks until a response is received or a transactional time-out happens. 
+ * @param message - the request to be sent
+ * @param peer_id - FQDN of the peer to send
+ * @returns 1 on success, 0 on failure 
+ * \todo remove peer_id and add Realm routing
+ * \todo replace the busy-waiting lock in here with one that does not consume CPU
+ */
+AAAMessage* AAASendRecvMessageToPeer(AAAMessage *message, str *peer_id)
+{
+	peer *p;
+	gen_sem_t *sem;
+	cdp_trans_t *t;
+	AAAMessage *ans;
+	int ms = 0;
+	
+	p = get_peer_by_fqdn(peer_id);
+	if (!p) {
+		LM_ERR("AAASendRecvMessageToPeer(): Peer unknown %.*s\n",peer_id->len,peer_id->s);
+		goto error;
+	}
+	if (p->state!=I_Open && p->state!=R_Open){
+		LM_ERR("AAASendRecvMessageToPeer(): Peer not connected to %.*s\n",peer_id->len,peer_id->s);
+		goto error;
+	}
+	
+	if (is_req(message)){
+		sem_new(sem,0);
+		t = cdp_add_trans(message,sendrecv_cb,(void*)sem,config->transaction_timeout,0);
+
+		ms = TICKS_TO_MS(get_ticks_raw());
+//		if (!peer_send_msg(p,message)) {
+		if (!sm_process(p,Send_Message,message,0,0)){	
+			sem_free(sem);				
+			goto error;
+		}
+		ms = TICKS_TO_MS(get_ticks_raw()) - ms;
+		if (ms > latency_threshold)
+					LM_ERR("took too long to transition state machine for Send_Message [%dms]\n", ms);
+
+		ms = TICKS_TO_MS(get_ticks_raw());
+		/* block until callback is executed */
+		while(sem_get(sem)<0){
+			if (shutdownx&&(*shutdownx)) goto error;
+			LM_WARN("AAASendRecvMessageToPeer(): interrupted by signal or something > %s\n",strerror(errno));
+		}
+		sem_free(sem);
+
+		ms = TICKS_TO_MS(get_ticks_raw()) - ms;
+		if (ms > latency_threshold) {
+			LM_ERR("CDP response to Send_Message took too long (>%dms) - [%dms]\n", latency_threshold, ms);
+		}
+		ans = t->ans;
+		cdp_free_trans(t);
+		return ans;
+	} else {
+		LM_ERR("AAASendRecvMessageToPeer(): can't add wait for answer to answer.\n");
+		goto error;
+	}
+
+		
+error:	
+out_of_memory:
+	AAAFreeMessage(&message);
+	return 0;
+}
+
+
+

+ 59 - 0
modules/cdp/diameter_epc.h

@@ -0,0 +1,59 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_EPC_H_
+#define DIAMETER_EPC_H_
+
+
+#include "diameter_epc_code_app.h"
+#include "diameter_epc_code_avp.h"
+#include "diameter_epc_code_cmd.h"
+#include "diameter_epc_code_result.h"
+
+// Diameter Application Identifier used in the EPC
+
+#define EPC_vendor_id_3GPP 		10415		/**< Vendor Id for 3GPP */
+#define EPC_vendor_id_3GPP_char "10415" 	/**< char value for 3GPP's Vendor Id */
+#define EPC_vendor_id_3GPP_len	5			/**< len of char value for 3GPP's Vendor Id */
+
+
+
+
+#endif /*DIAMETER_EPC_H_*/

+ 62 - 0
modules/cdp/diameter_epc_code_app.h

@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_EPC_CODE_APP_H_
+#define DIAMETER_EPC_CODE_APP_H_
+
+// Diameter Application Identifier used in the EPC
+
+//this applications are specific to the PCC
+#define EPC_Rx 	16777236
+#define EPC_Gx 	16777238
+#define EPC_STa 16777250
+#define EPC_S6a 16777251
+#define EPC_S6d 16777251
+#define EPC_S13 16777252
+#define EPC_SWm 16777264
+#define EPC_SWx 16777265
+#define EPC_Gxx 16777266
+#define EPC_S9 	16777267
+#define EPC_S6b	16777272
+#define EPC_Sp	16777280 //not in current standards
+#define EPC_PCRF_MC	16777281	//not in current standards
+
+
+#endif /*DIAMETER_EPC_CODE_APP_H_*/

+ 932 - 0
modules/cdp/diameter_epc_code_avp.h

@@ -0,0 +1,932 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_EPC_CODE_AVP_H_
+#define DIAMETER_EPC_CODE_AVP_H_
+
+
+
+/** 3GPP AVP Codes */
+enum {
+/**   1 to 255 reserved for backward compatibility with Radius TS29.061	*/
+
+	AVP_EPC_3GPP_IMSI									= 1,
+	AVP_EPC_3GPP_Charging_Id							= 2,
+	AVP_EPC_3GPP_PDP_Type								= 3,
+	AVP_EPC_3GPP_CG_Address								= 4,
+	AVP_EPC_3GPP_GPRS_Negotiated_QoS_Profile			= 5,
+	AVP_EPC_3GPP_SGSN_Address							= 6,
+	AVP_EPC_3GPP_GGSN_Address							= 7,
+	AVP_EPC_3GPP_IMSI_MCC_MNC							= 8,
+	AVP_EPC_3GPP_GGSN_MCC_MNC							= 9,
+	AVP_EPC_3GPP_NSAPI									= 10,
+	AVP_EPC_3GPP_Session_Stop_Indicator					= 11,// TS32.299
+	AVP_EPC_3GPP_Selection_Mode							= 12,
+	AVP_EPC_3GPP_Charging_Characteristics				= 13,
+	AVP_EPC_3GPP_CG_IPv6_Address						= 14,
+	AVP_EPC_3GPP_SGSN_IPv6_Address						= 15,
+	AVP_EPC_3GPP_GGSN_IPv6_Address						= 16,
+	AVP_EPC_3GPP_IPv6_DNS_Servers						= 17,
+	AVP_EPC_3GPP_SGSN_MCC_MNC							= 18,
+	AVP_EPC_3GPP_IMEISV									= 20,
+	AVP_EPC_TGPP_RAT_Type								= 21,
+	AVP_EPC_3GPP_User_Location_Info						= 22,
+	AVP_EPC_3GPP_MS_TimeZone							= 23,
+	AVP_EPC_3GPP_Allocate_IP_Type						= 27,
+	AVP_EPC_RAI											= 909, //TS29.061
+/** 256 to 299 reserved for future use										*/
+
+
+/** 300 to 399 reserved for TS29.234											*/
+	AVP_EPC_3GPP_AAA_Server_Name	  					= 318, //TS29.234
+	
+/** 400 to 499 reserved for TS29.109 */
+		
+/** 500 to 599 reserved for TS29.209											*/
+	AVP_EPC_Abort_Cause									= 500,
+	AVP_EPC_Access_Network_Charging_Address				= 501,
+	AVP_EPC_Access_Network_Charging_Identifier			= 502,
+	AVP_EPC_Access_Network_Charging_Identifier_Value	= 503,
+	AVP_EPC_AF_Application_Identifier					= 504,
+	AVP_EPC_AF_Charging_Identifier						= 505,
+	AVP_EPC_Authorization_Token							= 506,
+	AVP_EPC_Flow_Description							= 507,
+	AVP_EPC_Flow_Grouping								= 508,
+	AVP_EPC_Flow_Number									= 509,
+	AVP_EPC_Flows										= 510,
+	AVP_EPC_Flow_Status									= 511,
+	AVP_EPC_Flow_Usage									= 512,
+	AVP_EPC_Specific_Action								= 513,
+	AVP_EPC_Max_Requested_Bandwidth_DL					= 515,
+	AVP_EPC_Max_Requested_Bandwidth_UL					= 516,
+	AVP_EPC_Media_Component_Description					= 517,
+	AVP_EPC_Media_Component_Number						= 518,
+	AVP_EPC_Media_Sub_Component							= 519,
+	AVP_EPC_Media_Type									= 520,
+	AVP_EPC_RR_Bandwidth								= 521,
+	AVP_EPC_RS_Bandwidth								= 522,
+	AVP_EPC_SIP_Forking_Indication						= 523,
+	AVP_EPC_Codec_Data									= 524,
+	AVP_EPC_Service_URN									= 525,
+	AVP_EPC_Acceptable_Service_Info						= 526,
+	AVP_EPC_Service_Info_Status							= 527,
+/** 600 to 699 reserved for TS29.229											*/
+/** 700 to 799 reserved for TS29.329											*/
+	
+/** 800 to 899 reserved for TS29.299											*/
+
+/** 32.299 Partial																*/
+	AVP_EPC_Event_Type									= 823,
+	AVP_EPC_SIP_Method									= 824,
+	AVP_EPC_Event										= 825,
+	AVP_EPC_Content_Type								= 826,
+	AVP_EPC_Content_Length								= 827,
+	AVP_EPC_Content_Disposition							= 828,
+	AVP_EPC_Role_Of_Node								= 829,
+	AVP_EPC_User_Session_Id								= 830,
+	AVP_EPC_Calling_Party_Address						= 831,
+	AVP_EPC_Called_Party_Address						= 832,
+	AVP_EPC_Time_Stamps									= 833,
+	AVP_EPC_SIP_Request_Timestamp						= 834,
+	AVP_EPC_SIP_Response_Timestamp						= 835,
+	AVP_EPC_Application_Server							= 836,
+	AVP_EPC_Application_Provided_Called_Party_Address	= 837,
+	AVP_EPC_Inter_Operator_Identifier					= 838,
+	AVP_EPC_Originating_IOI								= 839,
+	AVP_EPC_Terminating_IOI								= 840,
+	AVP_EPC_IMS_Charging_Identifier						= 841,
+	AVP_EPC_SDP_Session_Description						= 842,
+	AVP_EPC_SDP_Media_Component							= 843,
+	AVP_EPC_SDP_Media_Name								= 844,
+	AVP_EPC_SDP_Media_Description						= 845,
+	AVP_EPC_CG_Address									= 846,
+	AVP_EPC_GGSN_Address								= 847,
+	AVP_EPC_Served_Party_IP_Address						= 848,
+	AVP_EPC_Authorized_QoS								= 849,
+	AVP_EPC_Application_Server_Information				= 850,
+	AVP_EPC_Bearer_Service								= 854,
+	AVP_EPC_Service_ID									= 855,
+	AVP_EPC_Associated_URI								= 856,
+	AVP_EPC_Charged_Party								= 857,
+	AVP_EPC_Cause_Code									= 861,
+	AVP_EPC_Node_Functionality							= 862,
+	AVP_EPC_Service_Specific_Data						= 863,
+	AVP_EPC_Originator									= 864,
+	AVP_EPC_Service_Information							= 873,
+	AVP_EPC_PS_Information								= 874,
+	AVP_EPC_IMS_Information								= 876,
+	AVP_EPC_Media_Initiator_Flag						= 882,
+	AVP_EPC_Expires										= 888,
+	AVP_EPC_Message_Body								= 889,
+	AVP_EPC_Address_Data								= 897,
+	AVP_EPC_Address_Domain								= 898,
+	AVP_EPC_Address_Type								= 899,
+	AVP_EPC_CN_IP_Multicast_Distribution				= 921,
+	
+/** 1000   from TS29.212 */
+	AVP_EPC_Bearer_Usage								= 1000,
+ 	AVP_EPC_Charging_Rule_Install						= 1001,
+ 	AVP_EPC_Charging_Rule_Remove						= 1002,
+ 	AVP_EPC_Charging_Rule_Definition					= 1003,
+ 	AVP_EPC_Charging_Rule_Base_Name						= 1004,
+ 	AVP_EPC_Charging_Rule_Name							= 1005,
+ 	AVP_EPC_Event_Trigger								= 1006,
+ 	AVP_EPC_Metering_Method								= 1007,
+ 	AVP_EPC_Offline										= 1008,
+ 	AVP_EPC_Online										= 1009,
+ 	AVP_EPC_Precedence									= 1010,
+ 	AVP_EPC_Reporting_Level								= 1011,
+ 	AVP_EPC_TFT_Filter									= 1012,
+ 	AVP_EPC_TFT_Packet_Filter_Information				= 1013,
+ 	AVP_EPC_ToS_Traffic_Class							= 1014,
+ 	AVP_EPC_QoS_Bandwidth								= 1015,  //Not used in the EPC
+ 	AVP_EPC_QoS_Information								= 1016,
+ 	AVP_EPC_QoS_Jitter									= 1017,  //Not used in the EPC
+ 	AVP_EPC_Charging_Rule_Report						= 1018,
+ 	AVP_EPC_PCC_Rule_Status								= 1019,
+ 	AVP_EPC_Bearer_Identifier							= 1020,
+ 	AVP_EPC_Bearer_Operation							= 1021,
+ 	AVP_EPC_Access_Network_Charging_Identifier_Gx		= 1022,
+ 	AVP_EPC_Bearer_Control_Mode							= 1023,
+ 	AVP_EPC_Network_Request_Support						= 1024,
+ 	AVP_EPC_Guaranteed_Bitrate_DL						= 1025,
+ 	AVP_EPC_Guaranteed_Bitrate_UL						= 1026,
+ 	AVP_EPC_IP_CAN_Type									= 1027,
+ 	AVP_EPC_QoS_Class_Identifier						= 1028,
+ 	AVP_EPC_QoS_Negotiation								= 1029,
+ 	AVP_EPC_QoS_Upgrade									= 1030,
+ 	AVP_EPC_Rule_Failure_Code							= 1031,
+ 	AVP_EPC_RAT_Type									= 1032,
+ 	AVP_EPC_Event_Report_Indication						= 1033,
+ 	AVP_EPC_Allocation_Retention_Priority				= 1034,
+ 	AVP_EPC_CoA_IP_Address								= 1035,
+ 	AVP_EPC_Tunnel_Header_Filter						= 1036,
+ 	AVP_EPC_Tunnel_Header_Length						= 1037,
+ 	AVP_EPC_Tunnel_Information							= 1038,
+ 	AVP_EPC_CoA_Information								= 1039,
+ 	AVP_EPC_APN_Aggregate_Max_Bitrate_DL				= 1040,
+ 	AVP_EPC_APN_Aggregate_Max_Bitrate_UL				= 1041,
+ 	AVP_EPC_Revalidation_Time							= 1042,
+ 	AVP_EPC_Rule_Activation_Time						= 1043,
+ 	AVP_EPC_Rule_DeActivation_Time						= 1044,
+ 	AVP_EPC_Session_Release_Cause						= 1045,
+ 	AVP_EPC_ARP_Value									= 1046, //Depends on the version
+ 	AVP_EPC_Priority_Level								= 1046,
+ 	AVP_EPC_Pre_emption_Capability						= 1047,
+ 	AVP_EPC_Pre_emption_Vulnerability					= 1048,
+ 	AVP_EPC_Default_EPS_Bearer_QoS						= 1049,
+ 	AVP_EPC_AN_GW_Address								= 1050,
+ 	AVP_EPC_QoS_Rule_Install							= 1051, //Gxx
+ 	AVP_EPC_QoS_Rule_Remove								= 1052,
+ 	AVP_EPC_QoS_Rule_Definition							= 1053,
+ 	AVP_EPC_QoS_Rule_Name								= 1054,
+ 	AVP_EPC_QoS_Rule_Report								= 1055,
+ 	AVP_EPC_Security_Parameter_Index					= 1056,
+ 	AVP_EPC_Flow_Label									= 1057,
+ 	AVP_EPC_Flow_Information							= 1058,
+	AVP_EPC_Packet_Filter_Content						= 1059,
+	AVP_EPC_Packet_Filter_Identifier					= 1060,
+	AVP_EPC_Packet_Filter_Information					= 1061,
+	AVP_EPC_Packet_Filter_Operation						= 1062,
+	AVP_EPC_Resource_Allocation_Notification			= 1063, //Gx
+	AVP_EPC_Session_Linking_Indicator					= 1064,
+	AVP_EPC_PDN_Connection_ID							= 1065,
+ 	
+/** TS 32.299  */
+	
+	AVP_EPC_Additional_Type_Information					= 1205,
+	AVP_EPC_Content_Size								= 1206,
+	AVP_EPC_Additional_Content_Information				= 1207,
+	AVP_EPC_Addressee_Type								= 1208,
+	AVP_EPC_Class_Identifier							= 1214,
+	AVP_EPC_Adaptations									= 1217,
+	AVP_EPC_Applic_ID									= 1218,
+	AVP_EPC_Aux_Applic_Info								= 1219,
+	AVP_EPC_Content_Class								= 1220,
+	AVP_EPC_PDP_Address									= 1227,
+	AVP_EPC_SGSN_Address								= 1228,
+	AVP_EPC_Service_Specific_Info						= 1249,
+	AVP_EPC_Called_Asserted_Identity					= 1250,
+	AVP_EPC_Requested_Party_Address						= 1251,
+	AVP_EPC_Service_Specific_Type						= 1257,
+	AVP_EPC_Access_Network_Information					= 1263,
+	AVP_EPC_Base_Time_Interval							= 1265,
+	AVP_EPC_Early_Media_Description						= 1272,
+	AVP_EPC_SDP_TimeStamps								= 1273,
+	AVP_EPC_SDP_Offer_TimeStamp							= 1274,
+	AVP_EPC_SDP_Answer_TimeStamp						= 1275,
+	AVP_EPC_AF_Correlation_Information					= 1276,
+	AVP_EPC_Alternate_Charged_Party_Address				= 1280,
+	AVP_EPC_Media_Initiator_Party						= 1288,
+	
+	
+/** TS 29.272  */
+	AVP_EPC_Subscription_Data							= 1400,
+	AVP_EPC_Terminal_Information						= 1401,
+	AVP_EPC_IMEI										= 1402,
+	AVP_EPC_Software_Version							= 1403,
+	AVP_EPC_QoS_Subscribed								= 1404,
+	AVP_EPC_ULR_Flags									= 1405,
+	AVP_EPC_ULA_Flags									= 1406,
+	AVP_EPC_Visited_PLMN_Id								= 1407,
+	AVP_EPC_Requested_EUTRAN_Authentication_Info		= 1408,
+	AVP_EPC_Requested_UTRAN_GERAN_Authentication_Info	= 1409,
+	AVP_EPC_Number_Of_Requested_Vectors					= 1410,
+	AVP_EPC_Re_Synchronization_Info						= 1411,
+	AVP_EPC_Immediate_Response_Preferred				= 1412,
+	AVP_EPC_Authentication_Info							= 1413,
+	AVP_EPC_E_UTRAN_Vector								= 1414,
+	AVP_EPC_UTRAN_Vector								= 1415,
+	AVP_EPC_GERAN_Vector								= 1416,
+	AVP_EPC_Network_Access_Mode							= 1417,
+	AVP_EPC_HPLMN_ODB									= 1418,
+	AVP_EPC_Item_Number									= 1419,
+	AVP_EPC_Cancellation_Type							= 1420,
+	AVP_EPC_DSR_Flags									= 1421,
+	AVP_EPC_DSA_Flags									= 1422,
+	AVP_EPC_Context_Identifier							= 1423,
+	AVP_EPC_Subscriber_Status							= 1424,
+	AVP_EPC_Operator_Determined_Barring					= 1425,
+	AVP_EPC_Access_Restriction_Data						= 1426,
+	AVP_EPC_APN_OI_Replacement							= 1427,
+	AVP_EPC_All_APN_Configurations_Included_Indicator	= 1428,
+	AVP_EPC_APN_Configuration_Profile					= 1429,
+	AVP_EPC_APN_Configuration							= 1430,
+	AVP_EPC_EPS_Subscribed_QoS_Profile					= 1431,
+	AVP_EPC_VPLMN_Dynamic_Address_Allowed				= 1432,
+	AVP_EPC_STN_SR										= 1433,
+	AVP_EPC_Alert_Reason								= 1434,
+	AVP_EPC_AMBR										= 1435,
+	AVP_EPC_CSG_Subscription_Data						= 1436,
+	AVP_EPC_CSG_Id										= 1437,
+	AVP_EPC_PDN_Gw_Allocation_Type						= 1438,
+	AVP_EPC_Expiration_Date								= 1439,
+	AVP_EPC_RAT_Frequency_Selection_Priority_ID			= 1440,
+	AVP_EPC_IDA_Flags									= 1441,
+	AVP_EPC_PUA_Flags									= 1442,
+	AVP_EPC_NOR_Flags									= 1443,
+	AVP_EPC_User_Id										= 1444,
+	AVP_EPC_Equipment_Status							= 1445,
+	AVP_EPC_Regional_Subscription_Zone_Code				= 1446,
+	AVP_EPC_RAND										= 1447,
+	AVP_EPC_XRES										= 1448,
+	AVP_EPC_AUTN										= 1449,
+	AVP_EPC_KASME										= 1450,
+	
+	AVP_EPC_Trace_Collection_Entity						= 1452,
+	AVP_EPC_Kc											= 1453,
+	AVP_EPC_SRES										= 1454,
+
+	AVP_EPC_PDN_Type									= 1456,
+	AVP_EPC_Roaming_Restricted_Due_To_Unsupported_Feature = 1457,
+	AVP_EPC_Trace_Data									= 1458,
+	AVP_EPC_Trace_Reference								= 1459,
+	
+	AVP_EPC_Trace_Depth									= 1462,
+	AVP_EPC_Trace_NE_Type_List							= 1463,
+	AVP_EPC_Trace_Interface_List						= 1464,
+	AVP_EPC_Trace_Event_List							= 1465,
+	AVP_EPC_OMC_Id										= 1466,
+	AVP_EPC_GPRS_Subscription_Data						= 1467,
+	AVP_EPC_Complete_Data_List_Included_Indicator		= 1468,
+	AVP_EPC_PDP_Context									= 1469,
+	AVP_EPC_PDP_Type									= 1470,
+	AVP_EPC_3GPP2_MEID									= 1471,
+	AVP_EPC_Specific_APN_Info							= 1472,
+	AVP_EPC_LCS_Info									= 1473,
+	AVP_EPC_GMLC_Number									= 1474,
+	AVP_EPC_LCS_Privacy_Exception						= 1475,
+	AVP_EPC_SS_Code										= 1476,
+	AVP_EPC_SS_Status									= 1477,
+	AVP_EPC_Notification_To_UE_User						= 1478,
+	AVP_EPC_External_Client								= 1479,
+	AVP_EPC_Client_Identity								= 1480,
+	AVP_EPC_GMLC_Restriction							= 1481,
+	AVP_EPC_PLMN_Client									= 1482,
+	AVP_EPC_Service_Type								= 1483,
+	AVP_EPC_Sevice_Type_Identity						= 1484,
+	AVP_EPC_MO_LR										= 1485,
+	AVP_EPC_Teleservice_List							= 1486,
+	AVP_EPC_TS_Code										= 1487,
+	AVP_EPC_Call_Barring_Infor_List						= 1488,
+	AVP_EPC_SGSN_Number									= 1489,
+	AVP_EPC_IDR_Flags									= 1490,
+	AVP_EPC_ICS_Indicator								= 1491,
+	AVP_EPC_IMS_Voice_Over_PS_Sessions_Supported		= 1492,
+	AVP_EPC_Homogenous_Support_of_IMS_Over_PS_Sessions	= 1493,
+	AVP_EPC_Last_UE_Activity_Time						= 1494,
+
+/** TS 29.273  */	
+	
+	AVP_EPC_Non_3GPP_User_Data							= 1500,
+	AVP_EPC_Non_3GPP_IP_Access							= 1501,
+	AVP_EPC_Non_3GPP_IP_Access_APN						= 1502,
+	AVP_EPC_ANID										= 1504,
+	AVP_EPC_Trace_Info									= 1505,
+	
+/** TS 32.299  */
+	
+	AVP_EPC_Client_Address								= 2018,
+	AVP_EPC_Carrier_Select_Routing_Information			= 2023,
+	AVP_EPC_Associated_Party_Address					= 2035,
+	AVP_EPC_SDP_Type									= 2036,
+	AVP_EPC_Change_Condition							= 2037,
+	AVP_EPC_Change_Time									= 2038,
+	AVP_EPC_Service_Data_Container						= 2040,
+	AVP_EPC_Time_First_Usage							= 2043,
+	AVP_EPC_Time_Last_Usage								= 2044,
+	AVP_EPC_Time_Usage									= 2045,
+	AVP_EPC_Accumulated_Cost							= 2052,
+	AVP_EPC_AoC_Cost_Information						= 2053,
+	AVP_EPC_AoC_Information								= 2054,
+	AVP_EPC_AoC_Request_Type							= 2055,
+	AVP_EPC_Local_Sequence_Number						= 2063,
+	AVP_EPC_Charging_Characteristics_Selection_Mode		= 2066,
+	AVP_EPC_Application_Server_ID						= 2101,
+	AVP_EPC_Application_Service_Type					= 2102,
+	AVP_EPC_Application_Session_ID						= 2103,
+	AVP_EPC_Content_ID									= 2116,
+	AVP_EPC_Content_Provide_ID							= 2117,
+	AVP_EPC_SIP_Request_Timestamp_Fraction				= 2301,
+	AVP_EPC_SIP_Response_Timestamp_Fraction				= 2302,	
+	AVP_EPC_Account_Expiration							= 2309,
+	AVP_EPC_AoC_Cost_Format								= 2310,
+	AVP_EPC_AoC_Service									= 2311,
+	AVP_EPC_AoC_Service_Obligatory_Type					= 2312,
+	AVP_EPC_AoC_Service_Type							= 2313,
+	AVP_EPC_AoC_Subscription_Information				= 2314,
+	AVP_EPC_Outgoing_Session_Id							= 2320,
+	
+	
+	
+/** 2400 to 2407 reserved for TS29.173											*/
+
+	AVP_EPC_GMLC_Address								= 2405,
+	
+	
+	
+/** Not yet allocated */	
+
+	AVP_EPC_PDN_Gw_Address								= 42002, 
+	AVP_EPC_PDN_Gw_Name									= 42003, 
+	AVP_EPC_PDN_Gw_Identity								= 42004, 
+	AVP_EPC_QoS_Profile_Name							= 42005, 
+	AVP_EPC_GG_Enforce									= 42006, 
+	AVP_EPC_GG_IP										= 42007, 
+	AVP_EPC_UE_Locator									= 42008, 
+	AVP_EPC_UE_Locator_Id_Group							= 42009, 
+};
+
+/** Flow-Usage AVP */
+enum {
+	AVP_EPC_Flow_Usage_No_Information					= 0,
+	AVP_EPC_Flow_Usage_Rtcp								= 1,
+	AVP_EPC_Flow_Usage_AF_Signaling						= 2,
+
+};
+
+/* 3GPP TS 29.212*/
+enum {
+	AVP_EPC_Metering_Method_Duration			=0,
+	AVP_EPC_Metering_Method_Volume				=1,
+	AVP_EPC_Metering_Method_Duration_Volume		=2
+};
+
+enum {
+	AVP_EPC_Offline_Disable 		=0,
+	AVP_EPC_Offline_Enable 			=1
+};
+
+
+enum {
+	AVP_EPC_Online_Disable 			=0,
+	AVP_EPC_Online_Enable 			=1
+};
+
+enum {
+	AVP_EPC_Reporting_Level_Serving_Identifier 	=0,
+	AVP_EPC_Reporting_Level_Rating_Group		=1
+};
+
+enum {
+	AVP_EPC_PCC_Rule_Status_Active					=0,
+	AVP_EPC_PCC_Rule_Status_Inactive				=1,
+	AVP_EPC_PCC_Rule_Status_Temporarily_Inactive 	=2
+};
+enum {
+	AVP_EPC_Bearer_Usage_General 		=0,
+	AVP_EPC_Bearer_Usage_IMS_Signaling 	=1
+};
+enum {
+	AVP_EPC_Bearer_Operation_Termination 		=0,
+	AVP_EPC_Bearer_Operation_Establishment 		=1,
+	AVP_EPC_Bearer_Operation_Modification		=2
+};
+enum {
+	AVP_EPC_Bearer_Control_Mode_UE_Only			=0,
+	AVP_EPC_Bearer_Control_Mode_Reserved		=1,
+	AVP_EPC_Bearer_Control_Mode_UE_NW			=2
+};
+enum {
+	AVP_EPC_Network_Request_Support_Not_Supported			=0,
+	AVP_EPC_Network_Request_Support_Supported				=1
+};
+
+/** IP-CAN Type TS 29.212 */ 
+enum {
+	AVP_EPC_IPCAN_Type_3GPP_GPRS 	= 0,
+	AVP_EPC_IPCAN_Type_DOCSIS 		= 1,
+	AVP_EPC_IPCAN_Type_xDSL 		= 2,
+	AVP_EPC_IPCAN_Type_WiMAX		= 3,
+	AVP_EPC_IPCAN_Type_3GPP2		= 4,
+	AVP_EPC_IPCAN_Type_3GPP_EPS		= 5
+};
+
+enum {
+	AVP_EPC_QoS_Negotiation_No			=0,
+	AVP_EPC_QoS_Negotiation_Supported	=1
+};
+
+enum {
+	AVP_EPC_QoS_Upgrade_No				=0,
+	AVP_EPC_QoS_Upgrade_Supported		=1
+};
+
+enum {
+	AVP_EPC_RAT_Type_WLAN				=0,
+	AVP_EPC_RAT_Type_UTRAN				=1000,
+	AVP_EPC_RAT_Type_GERAN				=1001,
+	AVP_EPC_RAT_Type_GAN				=1002,
+	AVP_EPC_RAT_Type_HSPA_Evolution		=1003,
+	AVP_EPC_RAT_Type_EUTRAN				=1004,
+	AVP_EPC_RAT_Type_CDMA2000_1X		=2000,
+	AVP_EPC_RAT_Type_HRPD				=2001,
+	AVP_EPC_RAT_Type_UMB				=2002 //deprecated
+};
+
+
+enum {
+	AVP_EPC_Rule_Failure_Code_Unknown_Rule_Name				=1,
+	AVP_EPC_Rule_Failure_Code_Rating_Group_Error			=2,
+	AVP_EPC_Rule_Failure_Code_Service_Identifier_Error		=3,
+	AVP_EPC_Rule_Failure_Code_GW_PCEF_Malfunction			=4,
+	AVP_EPC_Rule_Failure_Code_Resources_Limitation			=5,
+	AVP_EPC_Rule_Failure_Code_Max_Nr_Bearers_Reached		=6,
+	AVP_EPC_Rule_Failure_Code_Unkown_Bearer_Id				=7,
+	AVP_EPC_Rule_Failure_Code_Missing_Bearer_Id				=8,
+	AVP_EPC_Rule_Failure_Code_Missing_Flow_Description		=9,
+	AVP_EPC_Rule_Failure_Code_Resource_Allocation_Failure	=10,
+	AVP_EPC_Rule_Failure_Code_Unsuccessful_QoS_Validation	=11
+};
+
+enum {
+	AVP_EPC_Session_Release_Cause_Unespecified				=0,
+	AVP_EPC_Session_Release_Cause_UE_Subscription			=1,
+	AVP_EPC_Session_Release_Cause_Server_Resources			=2
+};
+
+enum {
+	AVP_EPC_PreEmption_Capability_Enabled			=0,
+	AVP_EPC_PreEmption_Capability_Disabled			=1
+};
+
+enum {
+	AVP_EPC_PreEmption_Vulnerability_Enabled			=0,
+	AVP_EPC_PreEmption_Vulnerability_Disabled			=1
+};
+
+/** Event-Trigger TS 29.212*/
+enum {	
+	AVP_EPC_Event_Trigger_SGSN_CHANGE 							=0, 
+	AVP_EPC_Event_Trigger_QOS_CHANGE 							=1,
+	AVP_EPC_Event_Trigger_RAT_CHANGE 							=2,	
+	AVP_EPC_Event_Trigger_TFT_CHANGE 							=3,
+	AVP_EPC_Event_Trigger_PLMN_CHANGE 							=4,
+	AVP_EPC_Event_Trigger_LOSS_OF_BEARER 						=5,
+	AVP_EPC_Event_Trigger_RECOVERY_OF_BEARER					=6,
+	AVP_EPC_Event_Trigger_IP_CAN_CHANGE							=7,
+	AVP_EPC_Event_Trigger_GW_PCEF_MALFUNCTION 					=8, //Release 7
+	AVP_EPC_Event_Trigger_RESOURCES_LIMITATION 					=9, //Release 7
+	AVP_EPC_Event_Trigger_MAX_NR_BEARERS_REACHED 				=10, //Release 7
+	AVP_EPC_Event_Trigger_QOS_CHANGE_EXCEEDING_AUTHORIZATION	=11,
+	AVP_EPC_Event_Trigger_RAI_CHANGE							=12, 
+	AVP_EPC_Event_Trigger_USER_LOCATION_CHANGE 					=13,
+	AVP_EPC_Event_Trigger_NO_EVENT_TRIGGER						=14,	 
+	AVP_EPC_Event_Trigger_OUT_OF_CREDIT							=15, 
+	AVP_EPC_Event_Trigger_RELLOCATION_OF_CREDIT					=16,
+	AVP_EPC_Event_Trigger_REVALIDATION_TIMEOUT					=17,
+	AVP_EPC_Event_Trigger_IP_ADDRESS_ALLOCATE					=18,
+	AVP_EPC_Event_Trigger_IP_ADDRESS_RELEASE					=19,
+	AVP_EPC_Event_Trigger_DEFAULT_EPS_BEARER_QOS_CHANGE			=20,
+	AVP_EPC_Event_Trigger_AN_GW_CHANGE							=21,
+	AVP_EPC_Event_Trigger_Successful_Resource_Allocation		=22,
+	AVP_EPC_Event_Trigger_Resource_Modification_Request			=23,
+	//AVP_EPC_Event_Trigger_PGW_Trace_Control					=24,
+	//AVP_EPC_Event_Trigger_UE_Time_Zone_Change					= 25,
+};
+
+enum {
+	AVP_EPC_Packet_Filter_Operation_Deletion					=0,
+	AVP_EPC_Packet_Filter_Operation_Addition					=1,
+	AVP_EPC_Packet_Filter_Operation_Modification				=2
+};
+
+enum {
+	AVP_EPC_Resource_Allocation_Notification_Enable_Notification = 0
+};
+
+enum {
+	AVP_EPC_Session_Linking_Indicator_Immediate					= 0,
+	AVP_EPC_Session_Linking_Indicator_Deferred					= 1,
+};
+
+/* This extends the AVP_IMS_Data_Reference_* for Sh to Sp which is not yet standardized */
+enum {
+	AVP_EPC_Data_Reference_Subscription_Id_MSISDN				= 101,
+	AVP_EPC_Data_Reference_Subscription_Id_IMSI					= 102,
+	AVP_EPC_Data_Reference_Subscription_Id_IMPU					= 103,
+	AVP_EPC_Data_Reference_Subscription_Data					= 104,
+	AVP_EPC_Data_Reference_APN_Configuration					= 105,
+};
+
+/* from RFC4006 */
+enum {
+	AVP_EPC_Subscription_Id_Type_End_User_E164					= 0,
+	AVP_EPC_Subscription_Id_Type_End_User_IMSI					= 1,
+	AVP_EPC_Subscription_Id_Type_End_User_SIP_URI				= 2,
+	AVP_EPC_Subscription_Id_Type_End_User_NAI					= 3,	
+	AVP_EPC_Subscription_Id_Type_End_User_Private				= 4,	
+};
+
+enum {
+	RC_EPC_DIAMETER_QOS_RULE_EVENT								= 5145,
+	RC_EPC_DIAMETER_BEARER_EVENT								= 5146,
+	RC_EPC_DIAMETER_PCC_RULE_EVENT								= 5142,
+	RC_EPC_DIAMETER_ERROR_INITIAL_PARAMETERS					= 5140,
+	RC_EPC_DIAMETER_ERROR_TRAFFIC_MAPPING_INFO_REJECTED			= 5144,
+	RC_EPC_DIAMETER_ERROR_CONFLICTING_REQUEST					= 5147
+};
+
+enum {
+	RC_EPC_INVALID_SERVICE_INFORMATION							= 5061,
+	RC_EPC_FILTER_RESTRICTIONS									= 5062,
+	RC_EPC_REQUESTED_SERVICE_NOT_AUTHORIZED						= 5063
+};
+/**29.214 */
+enum {
+	AVP_EPC_Specific_Action_Charging_Correlation_Exchange			= 1,
+	AVP_EPC_Specific_Action_Indication_of_Loss_of_Bearer			= 2,
+	AVP_EPC_Specific_Action_Indication_of_Recovery_of_Bearer		= 3,
+	AVP_EPC_Specific_Action_Indication_of_Release_of_Bearer			= 4,
+	AVP_EPC_Specific_Action_Indication_of_Establishment_of_Bearer	= 5,
+	AVP_EPC_Specific_Action_IPCAN_Change							= 6,
+	AVP_EPC_Specific_Action_Indication_of_Out_of_Credit				= 7,
+	AVP_EPC_Specific_Action_Indication_of_Succ_Resource_Allocation			= 8,
+	AVP_EPC_Specific_Action_Indication_of_Failed_Resource_Allocation		= 9,
+	AVP_EPC_Specific_Action_Indication_of_Generic_Gateway_Change			= 10,
+};
+
+enum {
+	AVP_EPC_Service_Info_Status_Final_Service_Information			= 0,
+	AVP_EPC_Service_Info_Status_Preliminary_Service_Information		= 1,
+};
+
+/* TS 29.214 */
+enum {
+	AVP_EPC_Abort_Cause_Bearer_Released								= 0,
+	AVP_EPC_Abort_Cause_Insufficient_Server_Resources				= 1,
+	AVP_ECP_Abort_Cause_Insufficient_Bearer_Resources				= 2
+};
+
+
+/* TS 29.272 */
+
+enum {
+	AVP_EPC_ULR_Flags_Single_Registration_Indication				= 1<<0,
+	AVP_EPC_ULR_Flags_S6a_Indicator									= 1<<1,	
+	AVP_EPC_ULR_Flags_Skip_Subscriber_Data							= 1<<2,			
+	AVP_EPC_ULR_Flags_GPRS_Subscription_Data_Indicator				= 1<<3,			
+	AVP_EPC_ULR_Flags_Node_Type_Indicator							= 1<<4,			
+	AVP_EPC_ULR_Flags_Initial_Attach_Indicator						= 1<<5,			
+	AVP_EPC_ULR_Flags_PS_LCS_Not_Supported_By_UE					= 1<<6,			
+};
+
+enum {
+	AVP_EPC_ULA_Flags_Separation_Indication							= 1<<0,			
+};
+
+enum {
+	AVP_EPC_Feature_List_ODB_all_APN								= 1<<0,
+	AVP_EPC_Feature_List_ODB_HPLMN_APN								= 1<<1,	
+	AVP_EPC_Feature_List_ODB_VPLMN_APN								= 1<<2,			
+	AVP_EPC_Feature_List_ODB_all_OG									= 1<<3,			
+	AVP_EPC_Feature_List_ODB_all_InternationalOG					= 1<<4,			
+	AVP_EPC_Feature_List_ODB_all_InternationalOGNoToHPLMN_Country	= 1<<5,			
+	AVP_EPC_Feature_List_ODB_all_InterzonalIOG						= 1<<6,			
+	AVP_EPC_Feature_List_ODB_all_InterzonalIOGNotToHPLMN_Country	= 1<<7,			
+	AVP_EPC_Feature_List_ODB_all_InterzonalIOGAndInternationalOGNotToHPLMN_Country = 1<<8,			
+	AVP_EPC_Feature_List_RegSub										= 1<<9,			
+	AVP_EPC_Feature_List_Trace										= 1<<10,			
+	AVP_EPC_Feature_List_LCS_all_PrivExcep							= 1<<11,			
+	AVP_EPC_Feature_List_LCS_Universal								= 1<<12,			
+	AVP_EPC_Feature_List_LCS_CallSessionRelated						= 1<<13,			
+	AVP_EPC_Feature_List_LCS_CallSessionUnrelated					= 1<<14,			
+	AVP_EPC_Feature_List_LCS_PLMNOperator							= 1<<15,			
+	AVP_EPC_Feature_List_LCS_Service_Type							= 1<<16,			
+	AVP_EPC_Feature_List_LCS_all_MOLR_SS							= 1<<17,			
+	AVP_EPC_Feature_List_LCS_BasicShelfLocation						= 1<<18,			
+	AVP_EPC_Feature_List_LCS_AutonomousSelfLocation					= 1<<19,			
+	AVP_EPC_Feature_List_LCS_TransferToThirdParty					= 1<<20,			
+	AVP_EPC_Feature_List_SM_Mo_PP									= 1<<21,
+	AVP_EPC_Feature_List_Barring_OutgoingCalls						= 1<<22,			
+	AVP_EPC_Feature_List_BAOC										= 1<<23,			
+	AVP_EPC_Feature_List_BOIC										= 1<<24,			
+	AVP_EPC_Feature_List_BOICExHC									= 1<<25,			
+	AVP_EPC_Feature_List_T_ADSDataRetrieval							= 1<<26,			
+};
+
+enum {
+	AVP_EPC_Network_Access_Mode_Packed_And_Circuit					= 0,
+	AVP_EPC_Network_Access_Mode_Reserved							= 1,
+	AVP_EPC_Network_Access_Mode_Only_Packet							= 2,
+};
+enum {
+	AVP_EPC_HPLMN_OBD_HPLM_Specific_Barring_Type_1					= 1<<0,
+	AVP_EPC_HPLMN_OBD_HPLM_Specific_Barring_Type_2					= 1<<1,
+	AVP_EPC_HPLMN_OBD_HPLM_Specific_Barring_Type_3					= 1<<2,
+	AVP_EPC_HPLMN_OBD_HPLM_Specific_Barring_Type_4					= 1<<3,
+};
+
+enum {
+	AVP_EPC_Cancellation_Type_MME_Update_Procedure					= 0,
+	AVP_EPC_Cancellation_Type_SGSN_Update_Procedure					= 1,
+	AVP_EPC_Cancellation_Type_Subscription_Withdrawal				= 2,
+	AVP_EPC_Cancellation_Type_Update_Procedure_IWF					= 3,
+	AVP_EPC_Cancellation_Type_Initial_Attach_Procedure				= 4,
+};
+
+enum {
+	AVP_EPC_DSR_Flags_Regional_Subscription_Withdrawal				= 1<<0,
+	AVP_EPC_DSR_Flags_Complete_APN_Configuration_Profile_Withdrawal	= 1<<1,	
+	AVP_EPC_DSR_Flags_Subscribed_Charging_Characteristics_Withdrawal= 1<<2,			
+	AVP_EPC_DSR_Flags_PDN_Subscription_Contexts_Withdrawal			= 1<<3,			
+	AVP_EPC_DSR_Flags_STN_SR										= 1<<4,			
+	AVP_EPC_DSR_Flags_Complete_PDP_Context_List_Withdrawal			= 1<<5,			
+	AVP_EPC_DSR_Flags_PDP_Contexts_Withdrawal						= 1<<6,			
+	AVP_EPC_DSR_Flags_Roaming_Restricted_Due_To_Unsupported_Feature	= 1<<7,			
+	AVP_EPC_DSR_Flags_Trace_Data_Withdrawal							= 1<<8,			
+	AVP_EPC_DSR_Flags_CSG_Deleted									= 1<<9,			
+	AVP_EPC_DSR_Flags_APN_OI_Replacement							= 1<<10,			
+	AVP_EPC_DSR_Flags_GMLC_List_Withdrawal							= 1<<11,			
+	AVP_EPC_DSR_Flags_LCS_Withdrawal								= 1<<12,			
+	AVP_EPC_DSR_Flags_SMS_Withdrawal								= 1<<13,			
+};
+
+enum {
+	AVP_EPC_DSA_Flags_Network_Node_Area_Restricted					= 1<<0,
+};
+
+enum {
+	AVP_EPC_Subscriber_Status_Service_Granted						= 0,
+	AVP_EPC_Subscriber_Status_Operator_Determined_Barring			= 1,
+};
+
+enum {
+	AVP_EPC_Operator_Determined_Barring_All_Packet_Oriented_Services_Barred						= 1<<0,
+	AVP_EPC_Operator_Determined_Barring_Roamer_Access_HPLMN_AP_Barred							= 1<<1,	
+	AVP_EPC_Operator_Determined_Barring_Roamer_Access_To_VPLMN_AP_Barred						= 1<<2,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_Calls											= 1<<3,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_International_Calls							= 1<<4,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_International_Calls_Except_To_HPLMN_Country	= 1<<5,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_Inter_zonal_Calls								= 1<<6,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_Inter_zonal_Calls_Except_To_HPLMN_Country		= 1<<7,			
+	AVP_EPC_Operator_Determined_Barring_Outgoing_International_Calls_Except_To_HPLMN_Country_and_All_Inter_zonal_Calls = 1<<8,			
+};
+
+enum {
+	AVP_EPC_Access_Restriction_Data_UTRAN_Not_Allowed					= 1<<0,
+	AVP_EPC_Access_Restriction_Data_GERAN_Not_Allowed					= 1<<1,	
+	AVP_EPC_Access_Restriction_Data_GAN_Not_Allowed 					= 1<<2,			
+	AVP_EPC_Access_Restriction_Data_I_HSPA_Evolution_Not_Allowed		= 1<<3,			
+	AVP_EPC_Access_Restriction_Data_E_UTRA_Not_Allowed					= 1<<4,			
+	AVP_EPC_Access_Restriction_Data_HO_To_Non_3GPP_Access_Not_Allowed 	= 1<<5,		
+};
+
+enum {
+	AVP_EPC_All_APN_Configurations_Included_Indicator_All_Included				= 0,
+	AVP_EPC_All_APN_Configurations_Included_Indicator_Modified_Added_Included	= 1,
+};
+
+enum {
+	AVP_EPC_VPLMN_Dynamic_Address_Allowed_Not_Allowed				= 0,
+	AVP_EPC_VPLMN_Dynamic_Address_Allowed_Allowed					= 1,
+};
+
+enum {
+	AVP_EPC_PDN_Gw_Allocation_Type_Static							= 0,
+	AVP_EPC_PDN_Gw_Allocation_Type_Dynamic							= 1,
+};
+
+enum {
+	AVP_EPC_IDA_Flags_Network_Node_Area_Restricted					= 1<<0,
+};
+
+enum {
+	AVP_EPC_PUA_Flags_Freeze_M_TMSI									= 1<<0,
+	AVP_EPC_PUA_Flags_Freeze_P_TMSI									= 1<<1,
+};
+
+enum {
+	AVP_EPC_NOR_Flags_Single_Registration_Indication				= 1<<0,
+	AVP_EPC_NOR_Flags_SGSN_Area_Restricted							= 1<<1,
+	AVP_EPC_NOR_Flags_Ready_For_SM									= 1<<2,
+	AVP_EPC_NOR_Flags_UE_Reachable									= 1<<3,
+	AVP_EPC_NOR_Flags_Delete_All_APN_and_PDN_Gw_Identity_Pairs		= 1<<4,
+};
+
+enum {
+	AVP_EPC_Equipment_Status_Whitelisted							= 0,
+	AVP_EPC_Equipment_Status_Blacklisted							= 1,
+	AVP_EPC_Equipment_Status_Greylisted								= 2,
+};
+
+enum {
+	AVP_EPC_PDN_Type_IPv4											= 0,
+	AVP_EPC_PDN_Type_IPv6											= 1,
+	AVP_EPC_PDN_Type_IPv4v6											= 2,
+	AVP_EPC_PDN_Type_IPv4_or_IPv6									= 3,
+			
+};
+
+enum {
+	AVP_EPC_Complete_Data_List_Included_Indicator_All_Included				= 0,
+	AVP_EPC_Complete_Data_List_Included_Indicator_Modified_Added_Included	= 1,
+};
+
+enum {
+	AVP_EPC_Alert_Reason_UE_Present									= 0,
+	AVP_EPC_Alert_Reason_UE_Memory_Available						= 1,
+};
+
+enum {
+	AVP_EPC_Notification_To_UE_User_Notify_Location_Allowed					 		= 0,
+	AVP_EPC_Notification_To_UE_User_Notify_And_Verify_Allowed_If_No_Response 		= 1,
+	AVP_EPC_Notification_To_UE_User_Notify_And_Verify_Not_Allowed_If_No_Response 	= 2,
+	AVP_EPC_Notification_To_UE_User_Location_Not_Allowed					 		= 3,
+};
+
+enum {
+	AVP_EPC_GMLC_Restriction_GMLC_List								= 0,
+	AVP_EPC_GMLC_Restriction_Home_Country							= 1,
+};
+
+enum {
+	AVP_EPC_PLMN_Client_Broadcast_Service							= 0,
+	AVP_EPC_PLMN_Client_O_And_M_HPLMN								= 1,
+	AVP_EPC_PLMN_Client_O_And_M_VPLMN								= 2,
+	AVP_EPC_PLMN_Client_Anonymous_Location							= 3,
+	AVP_EPC_PLMN_Client_Target_UE_Subscribed_Services				= 4,		
+};
+
+enum {
+	AVP_EPC_IDR_Flags_UE_Reachability_Request						= 1<<0,
+	AVP_EPC_IDR_Flags_T_ADS_Data_Request							= 1<<1,
+	AVP_EPC_IDR_Flags_EPS_User_State_Request						= 1<<2,
+	AVP_EPC_IDR_Flags_EPS_Location_Information_Request				= 1<<3,
+	AVP_EPC_IDR_Flags_Current_Location_Request						= 1<<4,
+};
+
+enum {
+	AVP_EPC_ICS_Indicator_False										= 0,
+	AVP_EPC_ICS_Indicator_True										= 1,
+};
+
+enum {
+	AVP_EPC_IMS_Voice_Over_PS_Sessions_Supported_Not_Supported		= 0,
+	AVP_EPC_IMS_Voice_Over_PS_Sessions_Supported_Supported			= 1,
+};
+
+enum {
+	AVP_EPC_Homogenous_Support_of_IMS_Over_PS_Sessions_Not_Supported	= 0,
+	AVP_EPC_Homogenous_Support_of_IMS_Over_PS_Sessions_Supported		= 1,
+};
+
+enum {
+	AVP_EPC_User_State_Detached										= 0,
+	AVP_EPC_User_State_Attached_Not_Reachable_For_Paging			= 1,
+	AVP_EPC_User_State_Attached_Reachable_For_Paging				= 2,
+	AVP_EPC_User_State_Connected_Not_Reachable_For_Paging			= 3,
+	AVP_EPC_User_State_Connected_Reachable_For_Paging				= 4,
+	AVP_EPC_User_State_Network_Determined_Not_Reachable				= 5,
+};
+
+enum {
+	AVP_EPC_Current_Location_Retrieved_Active_Location_Retrieval	= 0			
+};
+
+enum {
+	AVP_EPC_Role_Of_Node_Originating_Role	= 0,
+	AVP_EPC_Role_Of_Node_Terminating_Role	= 1,
+};
+
+enum {
+	AVP_EPC_Node_Functionality_S_CSCF	= 0,
+	AVP_EPC_Node_Functionality_P_CSCF	= 1,
+	AVP_EPC_Node_Functionality_I_CSCF	= 2,
+	AVP_EPC_Node_Functionality_MRFC		= 3,
+	AVP_EPC_Node_Functionality_MGCF		= 4,
+	AVP_EPC_Node_Functionality_BGCF		= 5,
+	AVP_EPC_Node_Functionality_AS		= 6,
+	AVP_EPC_Node_Functionality_IBCF		= 7,
+	AVP_EPC_Node_Functionality_S_GW		= 8,
+	AVP_EPC_Node_Functionality_P_GW		= 9,
+	AVP_EPC_Node_Functionality_HSGW		= 10,	
+};
+
+enum {
+	AVP_EPC_Cause_Code_Normal_End_Of_Session		= 0,
+	AVP_EPC_Cause_Code_Successful_Transaction		= -1,
+	AVP_EPC_Cause_Code_End_Of_Subscribe_Dialog		= -2,
+	AVP_EPC_Cause_Code_2xx_Final_Response			= -200, /**< use the actual response code */
+	AVP_EPC_Cause_Code_3xx_Redirection				= -300, /**< use the actual response code */
+	AVP_EPC_Cause_Code_End_Of_REGISTER_Dialog		= -3,
+	AVP_EPC_Cause_Code_Unspecified_Error			= 1,
+	AVP_EPC_Cause_Code_4xx_Request_Failure			= 400, /**< use the actual response code */
+	AVP_EPC_Cause_Code_5xx_Request_Failure			= 500, /**< use the actual response code */
+	AVP_EPC_Cause_Code_6xx_Global_Failure			= 600, /**< use the actual response code */
+	AVP_EPC_Cause_Code_Unsuccessful_Session_Setup	= 2,
+	AVP_EPC_Cause_Code_Internal_Error				= 3,
+};
+
+enum {
+	AVP_EPC_Media_Initiator_Flag_Called_Party		= 0,
+	AVP_EPC_Media_Initiator_Flag_Calling_Party		= 1,
+	AVP_EPC_Media_Initiator_Flag_Unknown			= 2,	
+};
+
+enum {
+	AVP_EPC_Originator_Calling_Party		= 0,
+	AVP_EPC_Originator_Called_Party			= 1,
+};
+
+enum {
+	AVP_EPC_SDP_Type_SDP_Offer				= 0,
+	AVP_EPC_SDP_Type_SDP_Answer				= 1,
+};
+
+enum {
+	AVP_EPC_Non_3GPP_IP_Access_Non_3GPP_Subscription_Allowed	= 0,
+	AVP_EPC_Non_3GPP_IP_Access_Non_3GPP_Subscription_Barred		= 1,
+};
+
+enum {
+	AVP_EPC_Non_3GPP_IP_Access_APN_Non_3GPS_APNS_Enable			= 0,
+	AVP_EPC_Non_3GPP_IP_Access_APN_Non_3GPS_APNS_Disable		= 1,
+};
+
+/* RFC4006 */
+enum {
+	AVP_EPC_User_Equipment_Info_Type_IMEISV							= 0,
+	AVP_EPC_User_Equipment_Info_Type_MAC							= 1,
+	AVP_EPC_User_Equipment_Info_Type_EUI64							= 2,
+	AVP_EPC_User_Equipment_Info_Type_MODIFIED_EUI64					= 3,
+};
+
+#endif /*DIAMETER_EPC_H_*/

+ 117 - 0
modules/cdp/diameter_epc_code_cmd.h

@@ -0,0 +1,117 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_EPC_CODE_CMD_H_
+#define DIAMETER_EPC_CODE_CMD_H_
+/*	Command Codes used in the EPC 	*/
+
+/*		The Rx Interface 			*/
+#define Diameter_AAR		265		/**< Bearer-Authorization		Request	*/
+#define Diameter_AAA		265		/**< Bearer-Authorization		Answer	*/
+#define Diameter_RAR		258		/**< Re-Auth					Request */
+#define Diameter_RAA		258		/**< Re-Auth					Answer	*/
+#define Diameter_STR		275		/**< Session Termination 		Request */
+#define Diameter_STA		275		/**< Session Termination 		Answer	*/
+#define Diameter_ASR		274		/**< Abort-Session-Request		Request */
+#define Diameter_ASA		274		/**< Abort-Session-Request		Answer	*/
+/*		The Rf Interface			*/
+#define Diameter_ACR		271		/**< Accounting Request */
+#define Diameter_ACA		271		/**< Accounting Answer  */
+/* The Gx and Gxx Interface */
+#define Diameter_CCR		272
+#define Diameter_CCA		272
+
+/* The Sh/Sp interface */
+#define Diameter_UDR 		306
+#define Diameter_UDA 		306
+#define Diameter_PUR		307
+#define Diameter_PUA		307
+#define Diameter_SNR		308
+#define Diameter_SNA		308
+#define Diameter_PNR		309
+#define Diameter_PNA		309
+
+
+/* The S6a/S6d Interfaces */
+#define Diameter_ULR		316
+#define Diameter_ULA		316
+#define Diameter_CLR		317
+#define Diameter_CLA		317
+#define Diameter_AIR		318
+#define Diameter_AIA		318
+#define Diameter_IDR		319
+#define Diameter_IDA		319
+#define Diameter_DSR		320
+#define Diameter_DSA		320
+#define Diameter_PurgeUER	321
+#define Diameter_PurgeUEA	321
+#define Diameter_RSR		322
+#define Diameter_RSA		322
+#define Diameter_NOR		323
+#define Diameter_NOA		323
+
+/* The 3GPP EPS AAA Interfaces */
+/* SWa - non-3GPP untrusted AN <-> AAA Server/Proxy */
+/* SWm - non-3GPP untrusted ePDG <-> AAA Server/Proxy */
+/* STa - non-3GPP trusted AN <-> AAA Server/Proxy */
+/* S6b/H2 - PGW/HA <-> AAA Server/Proxy */
+/* SWd - AAA Server <-> AAA Proxy */
+#define Diameter_DER		268
+#define Diameter_DEA		268
+/* SWx - HSS <-> AAA Server/Proxy */
+#define Diameter_SAR		301
+#define Diameter_SAA		301
+#define Diameter_MAR		303
+#define Diameter_MAA		303
+#define Diameter_RTR		304
+#define Diameter_RTA		304
+#define Diameter_PPR		305
+#define Diameter_PPA		305
+
+
+/* The S13 Interface */
+#define Diameter_ECR		324
+#define Diameter_ECA		324
+
+/*not standard interfaces*/
+#define Diameter_MC_AF_ROUTE_UP		400
+#define Diameter_MC_AF_ROUTE_DEL	401
+
+#endif /*DIAMETER_EPC_CODE_CMD_H_*/

+ 71 - 0
modules/cdp/diameter_epc_code_result.h

@@ -0,0 +1,71 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef DIAMETER_EPC_CODE_RESULT_H_
+#define DIAMETER_EPC_CODE_RESULT_H_
+
+/**	EPC Specific Result Codes				*/
+enum{
+/** 1001 to 1999	Informational			*/
+/** 2001 to 2999	Success					*/
+/** 4001 to 4999	Transient Failures		*/
+	RC_EPC_DIAMETER_END_USER_SERVICE_DENIED				= 4010, //TS 32.299
+	RC_EPC_DIAMETER_CREDIT_CONTROL_NOT_APPLICABLE		= 4011, //TS 32.299
+	RC_EPC_DIAMETER_CREDIT_LIMIT_REACHED				= 4012, //TS 32.299
+	RC_EPC_DIAMETER_AUTHENTICATION_DATA_UNAVAILABLE		= 4181,
+/** 5001 to 5999	Permanent Failures		*/
+	RC_EPC_DIAMETER_ERROR_USER_UNKNOWN					= 5001,
+	RC_EPC_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED		= 5003, //TS 29.273
+	RC_EPC_DIAMETER_AUTHORIZATION_REJECTED				= 5003, //TS 32.299
+	RC_EPC_DIAMETER_ERROR_ROAMING_NOT_ALLOWED			= 5004, //TS 29.273
+	RC_EPC_DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED	= 5005, //TS 29.273	
+	RC_EPC_DIAMETER_USER_UNKNOWN						= 5030, //TS 32.299
+	RC_EPC_DIAMETER_RATING_FAILED						= 5031, //TS 32.299
+	RC_EPC_DIAMETER_ERROR_UNKNOWN_EPS_SUBSCRIPTION		= 5420,
+	RC_EPC_DIAMETER_ERROR_RAT_NOT_ALLOWED				= 5421,
+	RC_EPC_DIAMETER_ERROR_EQUIPMENT_UNKNOWN				= 5422,
+	RC_EPC_DIAMETER_ERROR_USER_NO_NON_3GPP_SUBSCRIPTION = 5450, //TS 29.273
+	RC_EPC_DIAMETER_ERROR_USER_NO_APN_SUBSCRIPTION		= 5451, //TS 29.273
+	RC_EPC_DIAMETER_ERROR_RAT_TYPE_NOT_ALLOWED			= 5452, //TS 29.273
+};
+
+
+
+#endif /*DIAMETER_EPC_CODE_RESULT_H_*/

+ 109 - 0
modules/cdp/diameter_ims.h

@@ -0,0 +1,109 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_IMS_H
+#define __DIAMETER_IMS_H
+
+#include "diameter_ims_code_app.h"
+#include "diameter_ims_code_avp.h"
+#include "diameter_ims_code_cmd.h"
+#include "diameter_ims_code_result.h"
+
+/* Vendor ID	*/
+
+#define IMS_vendor_id_3GPP 		10415		/**< Vendor Id for 3GPP */
+#define IMS_vendor_id_3GPP_char "10415" 	/**< char value for 3GPP's Vendor Id */
+#define IMS_vendor_id_3GPP_len	5			/**< len of char value for 3GPP's Vendor Id */
+
+#define IMS_vendor_id_ETSI 		13019		/**< Vendor Id for ETSI */
+#define IMS_vendor_id_ETSI_char "13019" 	/**< char value for ETSI's Vendor Id */
+#define IMS_vendor_id_ETSI_len	5			/**< len of char value for 3GPP's Vendor Id */
+
+#define IMS_vendor_id_CableLabs 	 4491	/**< Vendor Id for CableLabs */
+#define IMS_vendor_id_CableLabs_char "4491"	/**< char value for ETSI's Vendor Id */
+#define IMS_vendor_id_CableLabs_len	 4		/**< len of char value for 3GPP's Vendor Id */
+
+/*	Command Codes alocated for IMS	*/
+/*		The Gq Interface 			*/
+#define IMS_AAR		265		/**< Bearer-Authorization		Request	*/
+#define IMS_AAA		265		/**< Bearer-Authorization		Answer	*/
+#define IMS_RAR		258		/**< Re-Auth					Request */
+#define IMS_RAA		258		/**< Re-Auth					Answer	*/
+#define IMS_STR		275		/**< Session Termination 		Request */
+#define IMS_STA		275		/**< Session Termination 		Answer	*/
+#define IMS_ASR		274		/**< Abort-Session-Request		Request */
+#define IMS_ASA		274		/**< Abort-Session-Request		Answer	*/
+/* The Gx Interface */
+#define IMS_CCR		272
+#define IMS_CCA		272
+/*		The Cx/Dx Interface 			*/
+#define IMS_UAR		300		/**< User-Authorization			Request	*/
+#define IMS_UAA		300		/**< User-Authorization			Answer	*/
+#define IMS_SAR		301		/**< Server-Assignment			Request */
+#define IMS_SAA		301		/**< Server-Assignment			Answer	*/
+#define IMS_LIR		302		/**< Location-Info				Request */
+#define IMS_LIA		302		/**< Location-Info				Answer	*/
+#define IMS_MAR		303		/**< Multimedia-Auth			Request */
+#define IMS_MAA		303		/**< Multimedia-Auth			Answer	*/
+#define IMS_RTR		304		/**< Registration-Termination	Request */
+#define IMS_RTA		304		/**< Registration-Termination	Answer	*/
+#define IMS_PPR		305		/**< Push-Profile				Request */
+#define IMS_PPA		305		/**< Push-Profile				Answer	*/
+/**		The Sh/Ph Interface 			*/
+#define IMS_UDR		306		/**< User-Data					Request */
+#define IMS_UDA		306		/**< User-Data					Answer	*/
+#define IMS_PUR		307		/**< Profile-Update				Request */
+#define IMS_PUA		307		/**< Profile-Update				Answer	*/
+#define IMS_SNR		308		/**< Subscriber-Notifications	Request */
+#define IMS_SNA		308		/**< Subscriber-Notifications	Answer	*/
+#define IMS_PNR		309		/**< Push-Notification			Request */
+#define IMS_PNA		309		/**< Push-Notification			Answer	*/
+/**	Allocated Command Codes, not used yet	*/
+#define IMS_10R		310
+#define IMS_10A		310
+#define IMS_11R		311
+#define IMS_11A		311
+#define IMS_12R		312
+#define IMS_12A		312
+#define IMS_13R		313
+#define IMS_13A		313
+
+
+#endif /* __DIAMETER_IMS_H */

+ 58 - 0
modules/cdp/diameter_ims_code_app.h

@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_IMS_CODE_APP_H
+#define __DIAMETER_IMS_CODE_APP_H
+
+/* Application Identifiers	*/
+#define IMS_Gq	16777222	/**< Gq interface between P-CSCF and PDF 		*/
+#define IMS_Cx	16777216	/**< Cx interface between I/S-CSCF and HSS 		*/
+#define IMS_Dx	16777216	/**< Cx interface between I/S-CSCF and SLF 		*/
+#define IMS_Sh	16777217	/**< Sh interface between AS and HSS	 		*/
+#define IMS_e2	16777231	/**< e2 interface between CLF and AF	 		*/
+#define IMS_Ph	16777217	/**< Sh interface between PresenceServer and HSS*/
+#define IMS_Rx  16777236	/**< Rx interface between P-CSCF and PCRF 		*/
+#define IMS_Gx	16777224	/**< Gx interface between PCRF and PCEF 		*/
+#define IMS_Rf  16777223    /**< Rf interface between P/I/S-CSCF and CDF, 
+								according to TS32.299 R7    */ 
+
+#define IMS_Ro  4               /**< Ro interface between P/I/S-CSCF and OCS, according to TS32.299 R7    */
+
+#endif /* __DIAMETER_IMS_CODE_APP_H */

+ 488 - 0
modules/cdp/diameter_ims_code_avp.h

@@ -0,0 +1,488 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_IMS_CODE_AVP_H
+#define __DIAMETER_IMS_CODE_AVP_H
+
+
+/** 3GPP AVP Codes */ 
+enum {
+/**   1 to 255 reserved for backward compatibility with IMS Radius TS29.061	*/
+	AVP_IMS_Digest_Realm								= 104,
+	AVP_IMS_Digest_QoP									= 110,
+	AVP_IMS_Digest_Algorithm							= 111,
+	AVP_IMS_Digest_Auth_Param							= 117,
+	AVP_IMS_Digest_Domain								= 119,
+	AVP_IMS_Digest_HA1									= 121,
+/** 256 to 299 reserved for future use										*/
+	AVP_IMS_Vendor_Id									= 266,
+	AVP_IMS_Experimental_Result_Code					= 298,
+	AVP_IMS_Experimental_Result							= 297,
+/** 300 to 399 reserved for TS29.234											*/
+
+/** 400 to 499 reserved for TS29.109											*/
+	AVP_IMS_CCR_Number									= 415,
+	AVP_IMS_CCR_Type									= 416,
+ 	AVP_IMS_Service_Identifier							= 439,
+ /**  or   RFC 4006 															*/
+ 	AVP_IMS_Subscription_Id								= 443,
+ 	AVP_IMS_Subscription_Id_Data						= 444,
+ 	AVP_IMS_Subscription_Id_Type						= 450,
+ /* This require ETSI vendor id and are from ETSI TS 183 017*/
+ 	AVP_ETSI_Binding_Information						= 450,
+ 	AVP_ETSI_Binding_Input_List							= 451,
+ 	AVP_ETSI_Binding_Output_List						= 452,
+ 	AVP_ETSI_V6_transport_address						= 453,
+ 	AVP_ETSI_V4_transport_address						= 454,
+ 	AVP_ETSI_Port_Number								= 455,
+ 	AVP_ETSI_Reservation_Class							= 456,
+ 	AVP_ETSI_Latching_Indication						= 457,
+ 	AVP_ETSI_Reservation_Priority						= 458,
+	AVP_ETSI_Service_Class								= 459,
+	AVP_ETSI_Overbooking_Indication						= 460,
+	AVP_ETSI_Authorization_Package_Id  					= 461,
+	AVP_ETSI_Media_Authorization_Context_Id 			= 462,
+
+/** 500 to 599 reserved for TS29.209											*/
+	AVP_IMS_Abort_Cause									= 500,
+	AVP_IMS_Access_Network_Charging_Address				= 501,
+	AVP_IMS_Access_Network_Charging_Identifier			= 502,
+	AVP_IMS_Access_Network_Charging_Identifier_Value	= 503,
+	AVP_IMS_AF_Application_Identifier					= 504,
+	AVP_IMS_AF_Charging_Identifier						= 505,
+	AVP_IMS_Authorization_Token							= 506,
+	AVP_IMS_Flow_Description							= 507,
+	AVP_IMS_Flow_Grouping								= 508,
+	AVP_IMS_Flow_Number									= 509,
+	AVP_IMS_Flows										= 510,
+	AVP_IMS_Flow_Status									= 511,
+	AVP_IMS_Flow_Usage									= 512,
+	AVP_IMS_Specific_Action								= 513,
+	AVP_IMS_Max_Requested_Bandwidth_DL					= 515,
+	AVP_IMS_Max_Requested_Bandwidth_UL					= 516,
+	AVP_IMS_Media_Component_Description					= 517,
+	AVP_IMS_Media_Component_Number						= 518,
+	AVP_IMS_Media_Sub_Component							= 519,
+	AVP_IMS_Media_Type									= 520,
+	AVP_IMS_RR_Bandwidth								= 521,
+	AVP_IMS_RS_Bandwidth								= 522,
+	AVP_IMS_SIP_Forking_Indication						= 523,
+/** Codec-Data is from TS 29.214*/
+	AVP_IMS_Codec_Data									= 524,
+	AVP_IMS_Service_URN									= 525,
+	AVP_IMS_Acceptable_Service_Info						= 526,
+	AVP_IMS_Service_Info_Status							= 527,
+/** 600 to 699 reserved for TS29.229											*/
+	AVP_IMS_Visited_Network_Identifier					= 600,
+	AVP_IMS_Public_Identity								= 601,
+	AVP_IMS_Server_Name									= 602,
+	AVP_IMS_Server_Capabilities							= 603,
+	AVP_IMS_Mandatory_Capability						= 604,
+	AVP_IMS_Optional_Capability							= 605,
+	AVP_IMS_User_Data_Cx								= 606,
+	AVP_IMS_SIP_Number_Auth_Items						= 607,
+	AVP_IMS_SIP_Authentication_Scheme					= 608,
+	AVP_IMS_SIP_Authenticate							= 609,
+	AVP_IMS_SIP_Authorization							= 610,
+	AVP_IMS_SIP_Authentication_Context					= 611,
+	AVP_IMS_SIP_Auth_Data_Item							= 612,
+	AVP_IMS_SIP_Item_Number								= 613,
+	AVP_IMS_Server_Assignment_Type						= 614,
+	AVP_IMS_Deregistration_Reason						= 615,
+	AVP_IMS_Reason_Code									= 616,
+	AVP_IMS_Reason_Info									= 617,
+	AVP_IMS_Charging_Information						= 618,
+	AVP_IMS_Primary_Event_Charging_Function_Name		= 619,
+	AVP_IMS_Secondary_Event_Charging_Function_Name		= 620,
+	AVP_IMS_Primary_Charging_Collection_Function_Name	= 621,
+	AVP_IMS_Secondary_Charging_Collection_Function_Name	= 622,
+	AVP_IMS_User_Authorization_Type						= 623,
+	AVP_IMS_User_Data_Already_Available					= 624,
+	AVP_IMS_Confidentiality_Key							= 625,
+	AVP_IMS_Integrity_Key								= 626,
+	AVP_IMS_User_Data_Request_Type						= 627,
+	AVP_IMS_Supported_Features							= 628,
+	AVP_IMS_Feature_List_ID								= 629,
+	AVP_IMS_Feature_List								= 630,
+	AVP_IMS_Supported_Applications						= 631,
+	AVP_IMS_Associated_Identities						= 632,
+	AVP_IMS_Originating_Request							= 633,
+	AVP_IMS_Wildcarded_PSI								= 634,
+	AVP_IMS_SIP_Digest_Authenticate 					= 635,
+	AVP_IMS_Wildcarded_IMPU								= 636,
+	AVP_IMS_UAR_Flags									= 637,
+	AVP_IMS_Loose_Route_Indication						= 638,
+	AVP_IMS_SCSCF_Restoration_Info						= 639,
+	AVP_IMS_Path										= 640,
+	AVP_IMS_Contact										= 641,
+	AVP_IMS_Subscription_Info							= 642,
+	AVP_IMS_Call_ID_SIP_Header							= 643,
+	AVP_IMS_From_SIP_Header								= 644,
+	AVP_IMS_To_SIP_Header								= 645,
+	AVP_IMS_Record_Route								= 646,
+	AVP_IMS_Associated_Registered_Identities			= 647,
+	AVP_IMS_Multiple_Registration_Indication			= 648,
+	AVP_IMS_Restoration_Info							= 649,
+	
+/** 700 to 799 reserved for TS29.329											*/
+	AVP_IMS_User_Identity								= 700,
+	AVP_IMS_MSISDN										= 701,
+	AVP_IMS_User_Data_Sh								= 702,
+	AVP_IMS_Data_Reference								= 703,
+	AVP_IMS_Service_Indication							= 704,
+	AVP_IMS_Subs_Req_Type								= 705,
+	AVP_IMS_Requested_Domain							= 706,
+	AVP_IMS_Current_Location							= 707,
+	AVP_IMS_Identity_Set								= 708,
+	AVP_IMS_Expiry_Time									= 709,
+	AVP_IMS_Send_Data_Indication						= 710,
+	AVP_IMS_DSAI_Tag									= 711,
+	
+/** 800 to 899 reserved for TS29.299											*/
+	AVP_IMS_Event_Type 									= 823,
+	AVP_IMS_SIP_Method									= 824,
+	AVP_IMS_Event										= 825,
+	AVP_IMS_Content_Type								= 826,
+	AVP_IMS_Content_Length								= 827,
+	AVP_IMS_Content_Disposition							= 828,
+	AVP_IMS_Role_Of_Node 								= 829,
+	AVP_IMS_User_Session_Id								= 830,
+	AVP_IMS_Calling_Party_Address						= 831,
+	AVP_IMS_Called_Party_Address						= 832,
+	AVP_IMS_Time_Stamps									= 833,
+	AVP_IMS_SIP_Request_Timestamp						= 834,
+	AVP_IMS_SIP_Response_Timestamp						= 835,
+	AVP_IMS_Application_Server							= 836,
+	AVP_IMS_Application_Provided_Called_Party_Address	= 837,
+	AVP_IMS_Inter_Operator_Identifier					= 838,
+	AVP_IMS_Originating_IOI								= 839,
+	AVP_IMS_Terminating_IOI								= 840,
+	AVP_IMS_IMS_Charging_identifier						= 841,
+	AVP_IMS_SDP_Session_Description						= 842,
+	AVP_IMS_SDP_Media_Component							= 843,
+	AVP_IMS_SDP_Media_Name								= 844,
+	AVP_IMS_SDP_Media_Description						= 845,
+	AVP_IMS_CG_Address									= 846,
+	AVP_IMS_GGSN_Address								= 847,
+	AVP_IMS_Served_Party_IP_Address						= 848,
+	AVP_IMS_Authorized_QoS								= 849,
+	AVP_IMS_Application_Service_Information				= 850,
+	AVP_IMS_Trunk_Group_Id								= 851,
+	AVP_IMS_Incoming_Trunk_Group_Id						= 852,
+	AVP_IMS_Outgoing_Trunk_Group_Id						= 853,
+	AVP_IMS_Bear_Service								= 854,
+	AVP_IMS_Service_Id									= 855,
+	AVP_IMS_Associated_URI								= 856,
+	AVP_IMS_Charged_Party								= 857,
+	AVP_IMS_PoC_Controlling_Address						= 858,
+	AVP_IMS_PoC_Group_Name								= 859,
+	AVP_IMS_Cause										= 860,
+	AVP_IMS_Cause_Code									= 861,
+	
+	/* TODO finish the list... */
+	AVP_IMS_Node_Functionality							= 862,
+	AVP_IMS_Service_Information							= 873,
+	AVP_IMS_IMS_Information								= 876,
+	AVP_IMS_Expires										= 888,
+	AVP_IMS_Message_Body								= 889,
+/** 1000   from TS29.212 */
+ 	AVP_IMS_Charging_Rule_Install						= 1001,
+ 	AVP_IMS_Charging_Rule_Remove						= 1002,
+ 	AVP_IMS_Charging_Rule_Definition					= 1003,
+ 	AVP_IMS_Charging_Rule_Base_Name						= 1004,
+ 	AVP_IMS_Charging_Rule_Name							= 1005,
+ 	AVP_IMS_Event_Trigger								= 1006,
+ 	AVP_IMS_QoS_Information								= 1016,
+ 	AVP_IMS_Charging_Rule_Report						= 1018,
+ 	AVP_IMS_Pcc_Rule_Status								= 1019,
+ 	AVP_IMS_Bearer_Identifier							= 1020,
+ 	AVP_IMS_QoS_Class_Identifier						= 1028,
+
+	AVP_IMS_Service_Specific_Info						= 1249,
+	AVP_IMS_Requested_Party_Address						= 1251,
+	AVP_IMS_Access_Network_Information					= 1263,
+
+};
+
+/** ETSI AVP Codes */ 
+enum {
+	
+	/*added from ETSI 283 034 */
+	AVP_ETSI_Globally_Unique_Address					=300,
+	AVP_ETSI_Address_Realm								=301,
+	AVP_ETSI_Logical_Access_Id							=302,
+	AVP_ETSI_Initial_Gate_Setting						=303, 
+	AVP_ETSI_QoS_Profile								=304,
+	AVP_ETSI_IP_Connectivity_Status						=305,
+	AVP_ETSI_Access_Network_Type						=306,
+	AVP_ETSI_Aggregation_Network_Type					=307,
+	AVP_ETSI_Maximum_Allowed_Bandwidth_UL				=308,
+	AVP_ETSI_Maximum_Allowed_Bandwidth_DL				=309, 
+	AVP_ETSI_Transport_Class							=311,
+	AVP_ETSI_Application_Class_ID						=312,
+	AVP_ETSI_Physical_Access_ID							=313,
+	AVP_ETSI_Location_Information						=350,
+	AVP_ETSI_RACS_Contact_Point							=351, 
+	AVP_ETSI_Terminal_Type								=352, 
+	AVP_ETSI_Requested_Information						=353,
+	AVP_ETSI_Event_Type									=354,
+	
+	AVP_ETSI_Line_Identifier							= 500,
+	AVP_ETSI_SIP_Authenticate 							= 501, 
+	AVP_ETSI_SIP_Authorization 							= 502, 
+	AVP_ETSI_SIP_Authentication_Info 					= 503, 
+	AVP_ETSI_Digest_Realm 								= 504,  
+	AVP_ETSI_Digest_Nonce 								= 505,  
+	AVP_ETSI_Digest_Domain								= 506,  
+	AVP_ETSI_Digest_Opaque 								= 507,  
+	AVP_ETSI_Digest_Stale 								= 508,  
+	AVP_ETSI_Digest_Algorithm 							= 509,  
+	AVP_ETSI_Digest_QoP 								= 510,  
+	AVP_ETSI_Digest_HA1 								= 511,  
+	AVP_ETSI_Digest_Auth_Param 							= 512,  
+	AVP_ETSI_Digest_Username 							= 513,  
+	AVP_ETSI_Digest_URI 								= 514,  
+	AVP_ETSI_Digest_Response 							= 515,  
+	AVP_ETSI_Digest_CNonce 								= 516,  
+	AVP_ETSI_Digest_Nonce_Count 						= 517,  
+	AVP_ETSI_Digest_Method 								= 518,  
+	AVP_ETSI_Digest_Entity_Body_Hash 					= 519,  
+	AVP_ETSI_Digest_Nextnonce 							= 520,  
+	AVP_ETSI_Digest_Response_Auth						= 521	
+};
+
+/** CableLabs AVP Codes */ 
+enum {
+	AVP_CableLabs_SIP_Digest_Authenticate 				= 228,
+	AVP_CableLabs_Digest_Realm 							= 209,
+	AVP_CableLabs_Digest_Domain 						= 206,
+	AVP_CableLabs_Digest_Algorithm 						= 204,
+	AVP_CableLabs_Digest_QoP 							= 208,
+	AVP_CableLabs_Digest_HA1 							= 207,
+	AVP_CableLabs_Digest_Auth_Param 					= 205
+};
+
+/** Server-Assignment-Type Enumerated AVP */
+enum {
+	AVP_IMS_SAR_ERROR									= -1,
+	AVP_IMS_SAR_NO_ASSIGNMENT							= 0,
+	AVP_IMS_SAR_REGISTRATION							= 1,
+	AVP_IMS_SAR_RE_REGISTRATION							= 2,
+	AVP_IMS_SAR_UNREGISTERED_USER						= 3,
+	AVP_IMS_SAR_TIMEOUT_DEREGISTRATION					= 4,
+	AVP_IMS_SAR_USER_DEREGISTRATION						= 5,
+	AVP_IMS_SAR_TIMEOUT_DEREGISTRATION_STORE_SERVER_NAME= 6,
+	AVP_IMS_SAR_USER_DEREGISTRATION_STORE_SERVER_NAME	= 7,
+	AVP_IMS_SAR_ADMINISTRATIVE_DEREGISTRATION			= 8,
+	AVP_IMS_SAR_AUTHENTICATION_FAILURE					= 9,
+	AVP_IMS_SAR_AUTHENTICATION_TIMEOUT					= 10,
+	AVP_IMS_SAR_DEREGISTRATION_TOO_MUCH_DATA			= 11,
+	AVP_IMS_SAR_AAA_USER_DATA_REQUEST					= 12,
+	AVP_IMS_SAR_PGW_UPDATE								= 13,
+};
+
+/** User-Data-Already-Available Enumerated AVP */
+enum {
+	AVP_IMS_SAR_USER_DATA_NOT_AVAILABLE					= 0,
+	AVP_IMS_SAR_USER_DATA_ALREADY_AVAILABLE				= 1
+};
+
+/** User-Authorization-Type Enumerated AVP */
+enum {
+	AVP_IMS_UAR_REGISTRATION							= 0,
+	AVP_IMS_UAR_DE_REGISTRATION							= 1,
+	AVP_IMS_UAR_REGISTRATION_AND_CAPABILITIES			= 2
+};
+
+/** Originating-Request Enumerated AVP */
+enum {
+	AVP_IMS_LIR_ORIGINATING_REQUEST						= 0	
+};
+
+/** Data-Reference AVP */
+enum {
+	AVP_IMS_Data_Reference_Repository_Data				= 0,
+	AVP_IMS_Data_Reference_IMS_Public_Identity			= 10,
+	AVP_IMS_Data_Reference_IMS_User_State				= 11,
+	AVP_IMS_Data_Reference_SCSCF_Name					= 12,
+	AVP_IMS_Data_Reference_Initial_Filter_Criteria		= 13,
+	AVP_IMS_Data_Reference_Location_Information			= 14,
+	AVP_IMS_Data_Reference_User_State					= 15,
+	AVP_IMS_Data_Reference_Charging_Information			= 16,
+	AVP_IMS_Data_Reference_MSISDN						= 17,	
+	AVP_IMS_Data_Reference_PSI_Activation				= 18,	
+	AVP_IMS_Data_Reference_DSAI							= 19,	
+	AVP_IMS_Data_Reference_Aliases_Repository_Data		= 20,
+	AVP_IMS_Data_Reference_Service_Level_Trace_Info		= 21,
+	AVP_IMS_Data_Reference_IP_Address_Secure_Binding_Information = 22,	
+};
+
+/** Subs-Req-Type AVP */
+enum {
+	AVP_IMS_Subs_Req_Type_Subscribe						= 0,
+	AVP_IMS_Subs_Req_Type_Unsubscribe					= 1
+};
+
+/** Requested-Domain AVP */
+enum {
+	AVP_IMS_Requested_Domain_CS							= 0,
+	AVP_IMS_Requested_Domain_PS							= 1
+};
+
+/** UAR-Flags AVP	*/
+enum{
+	AVP_IMS_UAR_Flags_None								= 0,
+	AVP_IMS_UAR_Flags_Emergency_Registration			= 1 /*(1<<0)*/
+};
+
+/** Loose-Route-Indication AVP */
+enum{
+	AVP_IMS_Loose_Route_Not_Required					= 0,
+	AVP_IMS_Loose_Route_Required						= 1
+};
+
+/** Feature-List-ID AVP for Cx */
+enum{
+	AVP_IMS_Feature_List_ID_Shared_iFC_Sets				= 1<<0,
+	AVP_IMS_Feature_List_ID_Alias_Indication			= 1<<1,
+	AVP_IMS_Feature_List_ID_IMS_Restoration_Indication  = 1<<2, 
+};
+
+/** Feature-List-ID AVP for Sh */
+enum{
+	AVP_IMS_Feature_List_ID_Notif_Eff					= 1<<0,
+};
+
+/** Multiple-Registration-Indication */
+enum{
+	AVP_IMS_Not_Multiple_Registration					= 0,
+	AVP_IMS_Multiple_Registration						= 1,
+};
+
+/** Current-Location AVP */
+enum {
+	AVP_IMS_Current_Location_Do_Not_Need_Initiate_Active_Location_Retrieval	=0,
+	AVP_IMS_Current_Location_Initiate_Active_Location_Retrieval				=1
+};
+
+/** Identity-Set AVP */
+enum {
+	AVP_IMS_Identity_Set_All_Identities					= 0,
+	AVP_IMS_Identity_Set_Registered_Identities			= 1,
+	AVP_IMS_Identity_Set_Implicit_Identities			= 2,	
+	AVP_IMS_Identity_Set_Alias_Identities				= 3	
+};
+
+/** Deregistration-Reason AVP */
+enum {
+	AVP_IMS_Deregistration_Reason_Permanent_Termination	= 0,
+	AVP_IMS_Deregistration_Reason_New_Server_Assigned	= 1,
+	AVP_IMS_Deregistration_Reason_Server_Change			= 2,	
+	AVP_IMS_Deregistration_Reason_Remove_S_CSCF			= 3
+};
+
+
+/** Abort-Cause AVP */
+enum {
+	AVP_IMS_Abort_Cause_Bearer_Released					= 0,
+	AVP_IMS_Abort_Cause_Insufficient_Server_Resources	= 1,
+	AVP_IMS_Abort_Cause_Insufficient_Bearer_Resources	= 2
+};
+/** Flow-Status AVP */
+enum {
+	AVP_IMS_Flow_Status_Enabled_Uplink					= 0,
+	AVP_IMS_Flow_Status_Enabled_Downlink				= 1,
+	AVP_IMS_Flow_Status_Enabled							= 2,
+	AVP_IMS_Flow_Status_Disabled						= 3,
+	AVP_IMS_Flow_Status_Removed							= 4
+};
+
+/** Specific-Action AVP */
+enum {
+	AVP_IMS_Specific_Action_Service_Information_Request						= 0,
+	AVP_IMS_Specific_Action_Charging_Correlation_Exchange					= 1,
+	AVP_IMS_Specific_Action_Indication_Of_Loss_Of_Bearer					= 2,
+	AVP_IMS_Specific_Action_Indication_Of_Recovery_Of_Bearer				= 3,
+	AVP_IMS_Specific_Action_Indication_Of_Release_Of_Bearer					= 4,
+	AVP_IMS_Specific_Action_Indication_Of_Establishment_Of_Bearer			= 5
+};
+
+/** Media-Type AVP */
+enum {
+	AVP_IMS_Media_Type_Audio					= 0,
+	AVP_IMS_Media_Type_Video					= 1,
+	AVP_IMS_Media_Type_Data						= 2,
+	AVP_IMS_Media_Type_Application				= 3,
+	AVP_IMS_Media_Type_Control					= 4,
+	AVP_IMS_Media_Type_Text						= 5,
+	AVP_IMS_Media_Type_Message					= 6,
+	AVP_IMS_Media_Type_Other					= 0xFFFFFFFF
+};
+
+/** Latching Indication AVP **/
+enum {
+	AVP_ETSI_Latching_Indication_Latch 			= 0,
+	AVP_ETSI_Latching_Indication_Relatch		= 1
+};
+
+/** Send-Data-Indication AVP **/
+enum {
+	AVP_IMS_Send_Data_Indication_User_Data_Not_Requested 	= 0,
+	AVP_IMS_Send_Data_Indication_User_Data_Requested		= 1
+};
+
+enum {
+	AVP_Re_Auth_Request_Type_Authorize_Only			=0,
+	AVP_Re_Auth_Request_Type_Authorize_Authenticate	=1,		
+};
+
+
+
+/*
+access-info for each access type  
+"ADSL" / "ADSL2" / "ADSL2+" / "RADSL" / "SDSL" / "HDSL" / "HDSL2" / "G.SHDSL" / "VDSL" / "IDSL"  -> dsl-location
+"3GPP-GERAN" -> cgi-3gpp
+"3GPP-UTRAN-FDD" / "3GPP-UTRAN-TDD" -> utran-cell-id-3gpp
+"3GPP2-1X" / "3GPP2-1X-HRPD" -> ci-3gpp2
+"IEEE-802.11" / "IEEE-802.11a" / "IEEE-802.11b" / "IEEE-802.11g" -> i-wlan-node-id = MAC
+"DOCSIS" -> NULL
+*/
+
+#endif /* __DIAMETER_IMS_CODE_AVP_H */

+ 91 - 0
modules/cdp/diameter_ims_code_cmd.h

@@ -0,0 +1,91 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_IMS_CODE_CMD_H
+#define __DIAMETER_IMS_CODE_CMD_H
+
+
+/*	Command Codes alocated for IMS	*/
+/*		The Gq Interface 			*/
+#define IMS_AAR		265		/**< Bearer-Authorization		Request	*/
+#define IMS_AAA		265		/**< Bearer-Authorization		Answer	*/
+#define IMS_RAR		258		/**< Re-Auth					Request */
+#define IMS_RAA		258		/**< Re-Auth					Answer	*/
+#define IMS_STR		275		/**< Session Termination 		Request */
+#define IMS_STA		275		/**< Session Termination 		Answer	*/
+#define IMS_ASR		274		/**< Abort-Session-Request		Request */
+#define IMS_ASA		274		/**< Abort-Session-Request		Answer	*/
+/* The Gx Interface */
+#define IMS_CCR		272
+#define IMS_CCA		272
+/*		The Cx/Dx Interface 			*/
+#define IMS_UAR		300		/**< User-Authorization			Request	*/
+#define IMS_UAA		300		/**< User-Authorization			Answer	*/
+#define IMS_SAR		301		/**< Server-Assignment			Request */
+#define IMS_SAA		301		/**< Server-Assignment			Answer	*/
+#define IMS_LIR		302		/**< Location-Info				Request */
+#define IMS_LIA		302		/**< Location-Info				Answer	*/
+#define IMS_MAR		303		/**< Multimedia-Auth			Request */
+#define IMS_MAA		303		/**< Multimedia-Auth			Answer	*/
+#define IMS_RTR		304		/**< Registration-Termination	Request */
+#define IMS_RTA		304		/**< Registration-Termination	Answer	*/
+#define IMS_PPR		305		/**< Push-Profile				Request */
+#define IMS_PPA		305		/**< Push-Profile				Answer	*/
+/**		The Sh/Ph Interface 			*/
+#define IMS_UDR		306		/**< User-Data					Request */
+#define IMS_UDA		306		/**< User-Data					Answer	*/
+#define IMS_PUR		307		/**< Profile-Update				Request */
+#define IMS_PUA		307		/**< Profile-Update				Answer	*/
+#define IMS_SNR		308		/**< Subscriber-Notifications	Request */
+#define IMS_SNA		308		/**< Subscriber-Notifications	Answer	*/
+#define IMS_PNR		309		/**< Push-Notification			Request */
+#define IMS_PNA		309		/**< Push-Notification			Answer	*/
+/**	Allocated Command Codes, not used yet	*/
+#define IMS_10R		310
+#define IMS_10A		310
+#define IMS_11R		311
+#define IMS_11A		311
+#define IMS_12R		312
+#define IMS_12A		312
+#define IMS_13R		313
+#define IMS_13A		313
+
+
+#endif /* __DIAMETER_IMS_CODE_CMD_H */

+ 98 - 0
modules/cdp/diameter_ims_code_result.h

@@ -0,0 +1,98 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_IMS_CODE_RESULT_H
+#define __DIAMETER_IMS_CODE_RESULT_H
+
+
+
+/**	IMS Specific Result Codes			*/
+enum{
+/** 1001 to 1999	Informational			*/
+/** 2001 to 2999	Success					*/
+/**	2001 to 2020 Reserved for TS29.229	*/
+	RC_IMS_DIAMETER_FIRST_REGISTRATION 					= 2001,
+	RC_IMS_DIAMETER_SUBSEQUENT_REGISTRATION				= 2002,
+	RC_IMS_DIAMETER_UNREGISTERED_SERVICE				= 2003,
+	RC_IMS_DIAMETER_SUCCESS_SERVER_NAME_NOT_STORED		= 2004,
+	RC_IMS_DIAMETER_SERVER_SELECTION					= 2005,
+/**	2401 to 2420 Reserved for TS29.109	*/
+/** 4001 to 4999	Transient Failures	*/
+/**	4100 to 4120 Reserved for TS29.329	*/
+	RC_IMS_DIAMETER_USER_DATA_NOT_AVAILABLE 			= 4100,
+	RC_IMS_DIAMETER_PRIOR_UPDATE_IN_PROGRESS			= 4101,
+/**	41xx to 41yy Reserved for TS32.299	*/
+/** 5001 to 5999	Permanent Failures		*/
+/**	5001 to 5020 Reserved for TS29.229	*/
+	RC_IMS_DIAMETER_ERROR_USER_UNKNOWN					= 5001,
+	RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH			= 5002,
+	RC_IMS_DIAMETER_ERROR_IDENTITY_NOT_REGISTERED		= 5003,
+	RC_IMS_DIAMETER_ERROR_ROAMING_NOT_ALLOWED			= 5004,
+	RC_IMS_DIAMETER_ERROR_IDENTITY_ALREADY_REGISTERED	= 5005,
+	RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED		= 5006,
+	RC_IMS_DIAMETER_ERROR_IN_ASSIGNMENT_TYPE			= 5007,
+	RC_IMS_DIAMETER_ERROR_TOO_MUCH_DATA					= 5008,
+	RC_IMS_DIAMETER_ERROR_NOT_SUPPORTED_USER_DATA		= 5009,
+	RC_IMS_DIAMETER_MISSING_USER_ID						= 5010,
+	RC_IMS_DIAMETER_ERROR_FEATURE_UNSUPPORTED			= 5011,
+/**	5021 to 5040 Reserved for TS32.299	*/
+/**	5041 to 5060 Reserved for TS29.234	*/
+/**	5061 to 5080 Reserved for TS29.209	*/
+	RC_IMS_DIAMETER_ERROR_INVALID_SERVICE_INFORMATION	= 5061,
+	RC_IMS_DIAMETER_ERROR_FILTER_RESTRICTIONS			= 5062,
+/**	5061 to 5066 Reserved for TS29.214	*/
+	RC_IMS_DIAMETER_ERROR_REQUESTED_SERVICE_NOT_AUTHORIZED		= 5063,
+	RC_IMS_DIAMETER_ERROR_DUPLICATED_AF_SESSION			= 5064,
+	RC_IMS_DIAMETER_ERROR_IPCAN_SESSION_NOT_AVAILABLE		= 5065,
+	RC_IMS_DIAMETER_ERROR_UNAUTHORIZED_NON_EMERGENCY_SESSION	= 5066,
+/**	5100 to 5119 Reserved for TS29.329	*/
+	RC_IMS_DIAMETER_ERROR_USER_DATA_NOT_RECOGNIZED		= 5100,
+	RC_IMS_DIAMETER_ERROR_OPERATION_NOT_ALLOWED			= 5101,
+	RC_IMS_DIAMETER_ERROR_USER_DATA_CANNOT_BE_READ		= 5102,
+	RC_IMS_DIAMETER_ERROR_USER_DATA_CANNOT_BE_MODIFIED	= 5103,
+	RC_IMS_DIAMETER_ERROR_USER_DATA_CANNOT_BE_NOTIFIED	= 5104,
+	RC_IMS_DIAMETER_ERROR_TRANSPARENT_DATA_OUT_OF_SYNC	= 5105,
+	RC_IMS_DIAMETER_ERROR_SUBS_DATA_ABSENT				= 5106,
+	RC_IMS_DIAMETER_ERROR_NO_SUBSCRIPTION_TO_DATA		= 5107,
+	RC_IMS_DIAMETER_ERROR_DSAI_NOT_AVAILABLE 			= 5108
+/** 5400 to 5419 Reserved for TS29.109	*/
+};
+
+#endif /* __DIAMETER_IMS_CODE_RESULT_H */

+ 617 - 0
modules/cdp/diameter_msg.c

@@ -0,0 +1,617 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "diameter.h"
+#include "diameter_api.h"
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+
+#include "utils.h"
+#include "globals.h"
+
+#include "config.h"
+#include "peermanager.h"
+#include "diameter_epc_code_cmd.h"
+
+extern dp_config *config;	/**< Configuration for this diameter peer */
+
+
+/**
+ * This function encodes a AAAMessage to its network representation (encoder).
+ *  From a AAAMessage structure, a buffer to be send is built.
+ * @param msg - the message to encode
+ * @returns 1 on success, -1 on error
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/
+ */
+AAAReturnCode AAABuildMsgBuffer( AAAMessage *msg )
+{
+	unsigned char *p;
+	AAA_AVP       *avp;
+
+	/* first let's comput the length of the buffer */
+	msg->buf.len = AAA_MSG_HDR_SIZE; /* AAA message header size */
+	/* count and add the avps */
+	for(avp=msg->avpList.head;avp;avp=avp->next) {
+		msg->buf.len += AVP_HDR_SIZE(avp->flags)+ to_32x_len( avp->data.len );
+	}
+
+	LM_DBG("AAABuildMsgBuffer(): len=%d\n",msg->buf.len);
+	/* allocate some memory */
+	msg->buf.s = (char*)shm_malloc( msg->buf.len );
+	if (!msg->buf.s) {
+		LM_ERR("AAABuildMsgBuffer: no more free memory!\n");
+		goto error;
+	}
+	memset(msg->buf.s, 0, msg->buf.len);
+
+	/* fill in the buffer */
+	p = (unsigned char*)msg->buf.s;
+	/* DIAMETER HEADER */
+	/* message length */
+	((unsigned int*)p)[0] =htonl(msg->buf.len);
+	/* Diameter Version */
+	*p = 1;
+	p += VER_SIZE + MESSAGE_LENGTH_SIZE;
+	/* command code */
+	((unsigned int*)p)[0] = htonl(msg->commandCode);
+	/* flags */
+	*p = (unsigned char)msg->flags;
+	p += FLAGS_SIZE + COMMAND_CODE_SIZE;
+	/* application-ID */
+	((unsigned int*)p)[0] = htonl(msg->applicationId);
+	p += APPLICATION_ID_SIZE;
+	/* hop by hop id */
+	((unsigned int*)p)[0] = htonl(msg->hopbyhopId);
+	p += HOP_BY_HOP_IDENTIFIER_SIZE;
+	/* end to end id */
+	((unsigned int*)p)[0] = htonl(msg->endtoendId);
+	p += END_TO_END_IDENTIFIER_SIZE;
+
+	/* AVPS */
+	for(avp=msg->avpList.head;avp;avp=avp->next) {
+		/* AVP HEADER */
+		/* avp code */
+		set_4bytes(p,avp->code);
+		p +=4;
+		/* flags */
+		(*p++) = (unsigned char)avp->flags;
+		/* avp length */
+		set_3bytes(p, (AVP_HDR_SIZE(avp->flags)+avp->data.len) );
+		p += 3;
+		/* vendor id */
+		if ((avp->flags&0x80)!=0) {
+			set_4bytes(p,avp->vendorId);
+			p +=4;
+		}
+		/* data */
+		memcpy( p, avp->data.s, avp->data.len);
+		p += to_32x_len( avp->data.len );
+	}
+
+	if ((char*)p-msg->buf.s!=msg->buf.len) {
+		LM_ERR("BUG: build_buf_from_msg: mismatch between len and buf!\n");
+		shm_free( msg->buf.s );
+		msg->buf.s = 0;
+		msg->buf.len = 0;
+		goto error;
+	}
+
+	return 1;
+error:
+	return -1;
+}
+
+
+
+
+/**
+ *  Allocates a new AAAMessage.
+ * @param commandCode - the command code for this message
+ * @param applicationId - application id to be set
+ * @param sessionId - session id to be set
+ * @param request - if you want to create a response, put the request here. If you want a 
+ * request, call with NULL
+ * @returns the AAAMessage* or NULL on error
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
+ */
+AAAMessage *AAANewMessage(
+	AAACommandCode commandCode,
+	AAAApplicationId applicationId,
+	AAASession *session,
+	AAAMessage *request)
+{
+	AAAMessage   *msg;
+	AAA_AVP      *avp;
+	AAA_AVP      *avp_t;
+	str *sessionId=0;
+#if 0
+	unsigned int code;
+#endif
+	// str dest_host={"?",1};
+	str dest_realm={"?",1};
+
+	msg = 0;
+	if (!session||!session->id.s) {
+		if (request){
+			/* copy old session id from AVP */
+			if (request->sessionId) 
+				sessionId = &(request->sessionId->data);
+		}else{
+			if (commandCode!=Code_DW)
+				LM_DBG("AAANewMessage: param session received null and it's a request!!\n");
+		}
+	}else{
+		sessionId = &(session->id);
+	}
+
+	/* allocated a new AAAMessage structure and set it to 0 */
+	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
+	if (!msg) {
+		LM_ERR("AAANewMessage: no more free memory!!\n");
+		goto error;
+	}
+	memset(msg,0,sizeof(AAAMessage));
+
+	/* command code */
+	msg->commandCode = commandCode;
+	/* application ID */
+	msg->applicationId = applicationId;
+
+	/*add session ID */
+	if (sessionId){
+		avp = AAACreateAVP( 263, 0, 0, sessionId->s, sessionId->len,
+			AVP_DUPLICATE_DATA);
+		if ( !avp || AAAAddAVPToMessage(msg,avp,0)!=AAA_ERR_SUCCESS) {
+			LM_ERR("AAANewMessage: cannot create/add Session-Id avp\n");
+			if (avp) AAAFreeAVP( &avp );
+			goto error;
+		}
+		msg->sessionId = avp;
+	}
+
+	/* add origin host AVP */
+	/* changed by cristian to comply with rfc3588: 
+	 * 6.3.  Origin-Host AVP
+	 *
+	 *    The Origin-Host AVP (AVP Code 264) is of type
+	 *    DiameterIdentity... */
+	avp = AAACreateAVP( 264, 0, 0, config->fqdn.s, config->fqdn.len,
+		AVP_DUPLICATE_DATA);
+	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+		LM_ERR("AAANewMessage: cannot create/add Origin-Host avp\n");
+		if (avp) AAAFreeAVP( &avp );
+		goto error;
+	}
+	msg->orig_host = avp;
+	/* add origin realm AVP */
+	avp = AAACreateAVP( 296, 0, 0, config->realm.s, config->realm.len,
+		AVP_DUPLICATE_DATA);
+	if (!avp||AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+		LM_ERR("AAANewMessage: cannot create/add Origin-Realm avp\n");
+		if (avp) AAAFreeAVP( &avp );
+		goto error;
+	}
+	msg->orig_realm = avp;
+
+	if (!request) {
+		/* it's a new request -> set the flag */
+		msg->flags = 0x80;
+	} else {
+		/* link the incoming peer to the answer */
+		msg->in_peer = request->in_peer;
+		/* set the P flag as in request */
+		msg->flags |= request->flags&0x40;
+		/**/
+		msg->endtoendId = request->endtoendId;
+		msg->hopbyhopId = request->hopbyhopId;
+
+		
+		//TODO: aon:move this information in the AAASession structure, do not add these fields for
+		
+	    if (msg->commandCode==Code_CE||msg->commandCode==Code_DP||msg->commandCode==Code_DW ||
+			    msg->commandCode==Diameter_CCR || msg->commandCode==Diameter_RAR){
+	    	// Don't add Destination Host/Realm because some stacks are way to picky and will just refuse it
+	    }else{
+
+			/* Mirror the old originhost/realm to destinationhost/realm*/
+			//avp = AAAFindMatchingAVP(request,0,AVP_Origin_Host,0,0);
+			//if (avp) dest_host = avp->data;
+			/* add destination host and destination realm */
+			//avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
+			//	dest_host.s,dest_host.len,AVP_DUPLICATE_DATA);
+			//if (!avp) {
+		//		LM_ERR("ERR:AAANewMessage: Failed creating Destination Host avp\n");
+		//		goto error;
+		//	}
+		//	if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+		//		LM_ERR("ERR:AAANewMessage: Failed adding Destination Host avp to message\n");
+		//		AAAFreeAVP(&avp);
+		//		goto error;
+		//	}
+	
+			avp = AAAFindMatchingAVP(request,0,AVP_Origin_Realm,0,0);
+			if (avp) dest_realm = avp->data;
+			avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
+				dest_realm.s,dest_realm.len,AVP_DUPLICATE_DATA);
+			if (!avp) {
+				LM_ERR("ERR:AAANewMessage: Failed creating Destination Realm avp\n");
+				goto error;
+			}
+			if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+				LM_ERR("ERR:AAANewMessage: Failed adding Destination Realm avp to message\n");
+				AAAFreeAVP(&avp);
+				goto error;
+			}
+	    }
+
+		msg->res_code=0;
+		/* mirror all the proxy-info avp in the same order */
+		avp_t = request->avpList.head;
+		while ( (avp_t=AAAFindMatchingAVP
+		(request,avp_t,284,0,AAA_FORWARD_SEARCH))!=0 ) {
+			if ( (avp=AAACloneAVP(avp_t,1))==0 || AAAAddAVPToMessage( msg, avp,
+			msg->avpList.tail)!=AAA_ERR_SUCCESS )
+				goto error;
+		}
+	}
+
+	return msg;
+error:
+	LM_ERR("AAANewMessage: failed to create a new AAA message!\n");
+	AAAFreeMessage(&msg);
+	return 0;
+}
+
+/**
+ * Create a Diameter Request.
+ * @param app_id - application id to be set
+ * @param command_code - the command code for this message
+ * @param flags - flags to be set
+ * @param sessId - session id to be set
+ * @returns the AAAMessage* or NULL on error
+ */
+AAAMessage *AAACreateRequest(AAAApplicationId app_id,
+							AAACommandCode command_code,
+							AAAMsgFlag flags,
+							AAASession *session)
+{
+	AAAMessage *msg;
+	AAA_AVP      *avp;
+
+	msg = AAANewMessage(command_code,app_id,session,0);
+	if (!msg) return 0;
+	msg->hopbyhopId = next_hopbyhop();
+	msg->endtoendId = next_endtoend();
+	msg->flags |= flags;	
+
+	if(session){
+		/* add destination host and destination realm */
+		/*if(session->dest_host.s){//TODO: check spec about removing this across the board (jason)
+			avp = AAACreateAVP(AVP_Destination_Host,AAA_AVP_FLAG_MANDATORY,0,
+				session->dest_host.s,session->dest_host.len,AVP_DUPLICATE_DATA);
+			if (!avp) {
+				LM_ERR("ERR:AAACreateRequest: Failed creating Destination Host avp\n");
+				goto error;
+			}
+			if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+				LM_ERR("ERR:AAACreateRequest: Failed adding Destination Host avp to message\n");
+				AAAFreeAVP(&avp);
+				goto error;
+			}
+		}*/
+
+		if(session->dest_realm.s){
+			avp = AAACreateAVP(AVP_Destination_Realm,AAA_AVP_FLAG_MANDATORY,0,
+				session->dest_realm.s,session->dest_realm.len,AVP_DUPLICATE_DATA);
+			if (!avp) {
+				LM_ERR("ERR:AAACreateRequest: Failed creating Destination Realm avp\n");
+				goto error;
+			}
+			if (AAAAddAVPToMessage(msg,avp,msg->avpList.tail)!=AAA_ERR_SUCCESS) {
+				LM_ERR("ERR:AAACreateRequest: Failed adding Destination Realm avp to message\n");
+				AAAFreeAVP(&avp);
+				goto error;
+			}		
+		}
+	}
+
+	return msg;
+error:
+	AAAFreeMessage(&msg);
+	return NULL;
+}
+
+/**
+ * Create a Diameter Response to a given Request. 
+ * @param request - the request that this response is for
+ * @returns the AAAMessage* or NULL on error
+ */
+AAAMessage *AAACreateResponse(AAAMessage *request)
+{
+	AAAMessage *msg;
+	msg = AAANewMessage(request->commandCode,request->applicationId,0,request);
+		
+	return msg;
+}
+
+
+/**
+ *  Frees a AVP List and all the members
+ * @param avpList - list to be freed
+ * @returns AAA_ERR_SUCCESS 
+ */
+AAAReturnCode  AAAFreeAVPList(AAA_AVP_LIST *avpList)
+{
+	AAA_AVP *avp_t;
+	AAA_AVP *avp;
+	/* free the avp list */
+	avp = avpList->head;
+	while (avp) {
+		avp_t = avp;
+		avp = avp->next;
+		/*free the avp*/
+		AAAFreeAVP(&avp_t);
+	}
+	avpList->head = 0;
+	avpList->tail = 0;
+	return AAA_ERR_SUCCESS;
+}
+
+/**
+ *  Frees completely a message allocated through AAANewMessage()
+ * @param msg - pointer to the pointer containing the message.
+ * @returns AAA_ERR_SUCCESS 
+ */
+AAAReturnCode  AAAFreeMessage(AAAMessage **msg)
+{
+	LM_DBG("AAAFreeMessage: Freeing message (%p) %d\n",*msg,(*msg)->commandCode);
+	/* param check */
+	if (!msg || !(*msg))
+		goto done;
+
+	/* free the avp list */
+	AAAFreeAVPList(&((*msg)->avpList));
+
+	/* free the buffer (if any) */
+	if ( (*msg)->buf.s )
+		shm_free( (*msg)->buf.s );
+
+	/* free the AAA msg */
+	shm_free(*msg);
+	*msg = 0;
+
+done:
+	return AAA_ERR_SUCCESS;
+}
+
+/**
+ *  Sets the proper result_code into the Result-Code AVP; ths avp must already
+ * exists into the reply messge.
+ * @param message - the message to set the Result-Code to
+ * @param resultCode - code to set as result 
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
+ */
+AAAResultCode  AAASetMessageResultCode(
+	AAAMessage *message,
+	AAAResultCode resultCode)
+{
+	if ( !is_req(message) && message->res_code) {
+		*((unsigned int*)(message->res_code->data.s)) = htonl(resultCode);
+		return AAA_ERR_SUCCESS;
+	}
+	return AAA_ERR_FAILURE;
+}
+
+
+
+/**
+ *  This function convert message from the network format to the AAAMessage structure (decoder).
+ * @param source - the source char buffer
+ * @param sourceLen - the length of the input buffer
+ * @param attach_buf - whether to attach the input buffer to the message
+ * @returns the AAAMessage* or NULL on error
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
+ */
+AAAMessage* AAATranslateMessage( unsigned char* source, unsigned int sourceLen,
+															int attach_buf)
+{
+	unsigned char *ptr;
+	AAAMessage    *msg;
+	unsigned char version;
+	unsigned int  msg_len;
+	AAA_AVP       *avp;
+	unsigned int  avp_code;
+	unsigned char avp_flags;
+	unsigned int  avp_len;
+	unsigned int  avp_vendorID;
+	unsigned int  avp_data_len;
+
+	/* check the params */
+	if( !source || !sourceLen || sourceLen<AAA_MSG_HDR_SIZE) {
+		LM_ERR("AAATranslateMessage: invalid buffered received!\n");
+		goto error;
+	}
+
+	/* inits */
+	msg = 0;
+	avp = 0;
+	ptr = source;
+
+	/* alloc a new message structure */
+	msg = (AAAMessage*)shm_malloc(sizeof(AAAMessage));
+	if (!msg) {
+		LM_ERR("AAATranslateMessage: no more free memory!!\n");
+		goto error;
+	}
+	memset(msg,0,sizeof(AAAMessage));
+
+	/* get the version */
+	version = (unsigned char)*ptr;
+	ptr += VER_SIZE;
+	if (version!=1) {
+		LM_ERR("AAATranslateMessage: invalid version [%d]in "
+			"AAA msg\n",version);
+		goto error;
+	}
+
+	/* message length */
+	msg_len = get_3bytes( ptr );
+	ptr += MESSAGE_LENGTH_SIZE;
+	if (msg_len>sourceLen) {
+		LM_ERR("AAATranslateMessage: AAA message len [%d] bigger then"
+			" buffer len [%d]\n",msg_len,sourceLen);
+		goto error;
+	}
+
+	/* command flags */
+	msg->flags = *ptr;
+	ptr += FLAGS_SIZE;
+
+	/* command code */
+	msg->commandCode = get_3bytes( ptr );
+	ptr += COMMAND_CODE_SIZE;
+
+	/* application-Id */
+	msg->applicationId = get_4bytes( ptr );
+	ptr += APPLICATION_ID_SIZE;
+
+	/* Hop-by-Hop-Id */
+	msg->hopbyhopId = ntohl(*((unsigned int*)ptr));
+	ptr += HOP_BY_HOP_IDENTIFIER_SIZE;
+
+	/* End-to-End-Id */
+	msg->endtoendId = ntohl(*((unsigned int*)ptr));
+	ptr += END_TO_END_IDENTIFIER_SIZE;
+
+	/* start decoding the AVPS */
+	while (ptr < source+msg_len) {
+		if (ptr+AVP_HDR_SIZE(0x80)>source+msg_len){
+			LM_ERR("AAATranslateMessage: source buffer to short!! "
+				"Cannot read the whole AVP header!\n");
+			goto error;
+		}
+		/* avp code */
+		avp_code = get_4bytes( ptr );
+		ptr += AVP_CODE_SIZE;
+		/* avp flags */
+		avp_flags = (unsigned char)*ptr;
+		ptr += AVP_FLAGS_SIZE;
+		/* avp length */
+		avp_len = get_3bytes( ptr );
+		ptr += AVP_LENGTH_SIZE;
+		if (avp_len<1) {
+			LM_ERR("AAATranslateMessage: invalid AVP len [%d]\n",
+				avp_len);
+			goto error;
+		}
+		/* avp vendor-ID */
+		avp_vendorID = 0;
+		if (avp_flags&AAA_AVP_FLAG_VENDOR_SPECIFIC) {
+			avp_vendorID = get_4bytes( ptr );
+			ptr += AVP_VENDOR_ID_SIZE;
+		}
+		/* data length */
+		avp_data_len = avp_len-AVP_HDR_SIZE(avp_flags);
+		/*check the data length */
+		if ( source+msg_len<ptr+avp_data_len) {
+			LM_ERR("AAATranslateMessage: source buffer to short!! "
+				"Cannot read a whole data for AVP!\n");
+			goto error;
+		}
+
+		/* create the AVP */
+		avp = AAACreateAVP( avp_code, avp_flags, avp_vendorID, (char*) ptr,
+			avp_data_len, AVP_DONT_FREE_DATA);
+		if (!avp)
+			goto error;
+
+		/* link the avp into aaa message to the end */
+		AAAAddAVPToMessage( msg, avp, msg->avpList.tail);
+
+		ptr += to_32x_len( avp_data_len );
+	}
+
+	/* link the buffer to the message */
+	if (attach_buf) {
+		msg->buf.s = (char*) source;
+		msg->buf.len = msg_len;
+	}
+
+	msg->sessionId = AAAFindMatchingAVP(msg,0,AVP_Session_Id,0,0);
+
+	//AAAPrintMessage( msg );
+	return  msg;
+error:
+	LM_ERR("AAATranslateMessage: message conversion droped!!\n");
+	AAAFreeMessage(&msg);
+	return 0;
+}
+
+
+
+/**
+ *  print as debug all info contained by an aaa message + AVPs
+ * @param msg - the AAAMessage to print
+ * \note This function is taken from DISC http://developer.berlios.de/projects/disc/ 
+ */
+void AAAPrintMessage( AAAMessage *msg)
+{
+	char    buf[1024];
+	AAA_AVP *avp;
+
+	/* print msg info */
+	LM_DBG("AAA_MESSAGE - %p\n",msg);
+	LM_DBG("\tCode = %u\n",msg->commandCode);
+	LM_DBG("\tFlags = %x\n",msg->flags);
+
+	/*print the AVPs */
+	avp = msg->avpList.head;
+	while (avp) {
+		AAAConvertAVPToString(avp,buf,1024);
+		LM_DBG("\n%s\n",buf);
+		avp=avp->next;
+	}
+}
+
+
+

+ 480 - 0
modules/cdp/diameter_peer.c

@@ -0,0 +1,480 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <stdlib.h>
+#include <sys/wait.h> 
+#include <signal.h>
+#include <stdio.h>
+
+#include "utils.h"
+#include "diameter_peer.h"
+
+#include "config.h"
+#include "acceptor.h"
+#include "timer.h"
+#include "peermanager.h"
+#include "worker.h"
+#include "receiver.h"
+#include "api_process.h"
+#include "transaction.h"
+#include "session.h"
+
+#include "../../pt.h"
+
+dp_config *config=0;		/**< Configuration for this diameter peer 	*/
+
+int *shutdownx=0;			/**< whether a shutdown is in progress		*/
+gen_lock_t *shutdownx_lock; /**< lock used on shutdown				*/
+
+pid_t *dp_first_pid;		/**< first pid that we started from		*/
+
+pid_list_head_t *pid_list;	/**< list of local processes			*/
+gen_lock_t *pid_list_lock;	/**< lock for list of local processes	*/
+
+extern handler_list *handlers; 		/**< list of handlers */
+extern gen_lock_t *handlers_lock;	/**< lock for list of handlers */
+
+extern peer_list_t *peer_list;		/**< list of peers */
+extern gen_lock_t *peer_list_lock;	/**< lock for the list of peers */
+
+
+/**
+ * Add a pid to the local process list.
+ * @param pid newly forked pid
+ * @returns 1 on success or 0 on error
+ */
+inline int dp_add_pid(pid_t pid)
+{
+	pid_list_t *n;
+	lock_get(pid_list_lock);
+	n = shm_malloc(sizeof(pid_list_t));
+	if (!n){
+		LOG_NO_MEM("shm",sizeof(pid_list_t));
+		lock_release(pid_list_lock);
+		return 0;
+	}
+	n->pid = pid;
+	n->next = 0;
+	n->prev = pid_list->tail;
+	if (!pid_list->head) pid_list->head = n;
+	if (pid_list->tail) pid_list->tail->next = n;
+	pid_list->tail = n;
+	lock_release(pid_list_lock);
+	return 1;
+}
+
+/**
+ * Returns the last pid in the local process list.
+ */
+inline int dp_last_pid()
+{
+	int pid;
+	lock_get(pid_list_lock);
+	if (pid_list->tail)	pid = pid_list->tail->pid;
+	else pid = -1;
+	lock_release(pid_list_lock);
+	return pid;
+}
+
+/**
+ * Delete a pid from the process list
+ * @param pid - the pid to remove 
+ */
+inline void dp_del_pid(pid_t pid)
+{	
+	pid_list_t *i;
+	lock_get(pid_list_lock);
+	i = pid_list->head;
+	if (!i) {
+		lock_release(pid_list_lock);
+		return;
+	}
+	while(i && i->pid!=pid) i = i->next;
+	if (i){
+		if (i->prev) i->prev->next = i->next;
+		else pid_list->head = i->next;
+		if (i->next) i->next->prev = i->prev;
+		else pid_list->tail = i->prev;
+		shm_free(i);
+	}
+	lock_release(pid_list_lock);
+}
+
+
+/**
+ * Real initialization, called after the config is parsed
+ */
+int diameter_peer_init_real()
+{	
+	pid_list_t *i,*j;
+
+	if (!config) {
+		LM_ERR("diameter_peer_init_real(): Configuration was not parsed yet. Aborting...\n");
+		goto error;
+	}
+	log_dp_config(L_INFO,config);
+	
+	dp_first_pid = shm_malloc(sizeof(pid_t));
+	if (!dp_first_pid){
+		LOG_NO_MEM("shm",sizeof(pid_t));
+		goto error;
+	}
+	*dp_first_pid = getpid();
+	
+	shutdownx = shm_malloc(sizeof(int));
+	if (!shutdownx){
+		LOG_NO_MEM("shm",sizeof(int));
+		goto error;
+	}
+	*shutdownx = 0;
+	
+	shutdownx_lock = lock_alloc();
+	if (!shutdownx_lock){
+		LOG_NO_MEM("shm",sizeof(gen_lock_t));
+		goto error;
+	}
+	shutdownx_lock = lock_init(shutdownx_lock);
+
+	handlers_lock = lock_alloc();
+	if (!handlers_lock){
+		LOG_NO_MEM("shm",sizeof(gen_lock_t));
+		goto error;
+	}
+	handlers_lock = lock_init(handlers_lock);
+
+	handlers = shm_malloc(sizeof(handler_list));
+	if (!handlers){
+		LOG_NO_MEM("shm",sizeof(handler_list));
+		goto error;
+	}
+	handlers->head=0;
+	handlers->tail=0;
+
+	/* init the pid list */
+	pid_list = shm_malloc(sizeof(pid_list_head_t));
+	if (!pid_list){
+		LOG_NO_MEM("shm",sizeof(pid_list_head_t));
+		goto error;
+	}
+	bzero(pid_list,sizeof(pid_list_head_t));
+	pid_list_lock = lock_alloc();
+	pid_list_lock = lock_init(pid_list_lock);
+
+	/* init shared mem pointers before forking */
+	timer_cdp_init();
+	worker_init();
+
+	/* init the peer manager */
+	peer_manager_init(config);
+	
+	/* init diameter transactions */
+	cdp_trans_init();
+	
+	/* init the session */
+	if (!cdp_sessions_init(config->sessions_hash_size)) goto error;
+	
+	
+	/* add callback for messages - used to implement the API */
+	cb_add(api_callback,0);
+	
+	return 1;
+	
+error:
+	if (shutdownx) shm_free(shutdownx);
+	if (config) free_dp_config(config);
+	i = pid_list->head;
+	while(i){
+		j = i->next;
+		shm_free(i);
+		i = j;
+	}
+	shm_free(pid_list);
+	lock_get(pid_list_lock);
+	lock_destroy(pid_list_lock);
+	lock_dealloc((void*)pid_list_lock);
+	return 0;	
+
+}
+
+
+/**
+ * Initialize the CDiameterPeer from a configuration file.
+ * The file is kept as dtd. See configdtd.h for the DTD and ConfigExample.xml.
+ * @param cfg_filename - file with the configuration
+ * @returns 1 on success, 0 on error
+ */
+int diameter_peer_init(char *cfg_filename)
+{	
+	xmlDocPtr doc = parse_dp_config_file(cfg_filename);
+	config = parse_dp_config(doc);
+	if (!config) {
+		LM_ERR("init_diameter_peer(): Error loading configuration file. Aborting...\n");
+		goto error;
+	}
+	
+	return diameter_peer_init_real();
+error:
+	return 0;
+}
+
+/**
+ * Initialize the CDiameterPeer from a configuration string
+ * The file is kept as dtd. See configdtd.h for the DTD and ConfigExample.xml.
+ * @param cfg_filename - file with the configuration
+ * @returns 1 on success, 0 on error
+ */
+int diameter_peer_init_str(str config_str)
+{	
+	xmlDocPtr doc = parse_dp_config_str(config_str);
+	config = parse_dp_config(doc);
+	if (!config) {
+		LM_ERR("init_diameter_peer(): Error loading configuration file. Aborting...\n");
+		goto error;
+	}
+	
+	return diameter_peer_init_real();
+error:
+	return 0;
+}
+
+
+
+/**
+ * Start the CDiameterPeer operations.
+ * It forks all the processes required.
+ * @param blocking - if this is set, use the calling processes for the timer and never 
+ * return; else fork a new one for the timer and return
+ * @returns 1 on success, 0 on error, never if blocking
+ */ 
+int diameter_peer_start(int blocking)
+{
+	int pid;
+	int k=0;
+	peer *p;
+
+	/* fork workers */
+	for(k=0;k<config->workers;k++){
+		pid = fork_process(1001+k,"cdp_worker",1);
+		if (pid==-1){
+			LM_CRIT("init_diameter_peer(): Error on fork() for worker!\n");
+			return 0;
+		}
+		if (pid==0) {
+			srandom(time(0)*k);
+			snprintf(pt[process_no].desc, MAX_PT_DESC,"cdp worker child=%d", k );
+			worker_process(k);
+			LM_CRIT("init_diameter_peer(): worker_process finished without exit!\n");
+			exit(-1);		
+		}else{
+			dp_add_pid(pid);
+		}
+	}
+
+	/* init the fd_exchange pipes */
+	receiver_init(NULL);	
+	for(p = peer_list->head,k=0;p;p=p->next,k++)
+		receiver_init(p);
+	
+	
+	/* fork receiver for unknown peers */
+	
+	pid = fork_process(1001+k,"cdp_receiver_peer_unkown",1);
+
+	if (pid==-1){
+		LM_CRIT("init_diameter_peer(): Error on fork() for unknown peer receiver!\n");
+		return 0;
+	}
+	if (pid==0) {
+		srandom(time(0)*k);
+		snprintf(pt[process_no].desc, MAX_PT_DESC,
+				"cdp receiver peer unknown");
+		receiver_process(NULL);
+		LM_CRIT("init_diameter_peer(): receiver_process finished without exit!\n");
+		exit(-1);		
+	}else{
+		dp_add_pid(pid);
+	}
+	
+	/* fork receivers for each pre-configured peers */
+	lock_get(peer_list_lock);
+	for(p = peer_list->head,k=-1;p;p = p->next,k--){
+		pid = fork_process(1001+k,"cdp_receiver_peer",1);
+		if (pid==-1){
+			LM_CRIT("init_diameter_peer(): Error on fork() for peer receiver!\n");
+			return 0;
+		}
+		if (pid==0) {
+			srandom(time(0)*k);
+				snprintf(pt[process_no].desc, MAX_PT_DESC,
+					"cdp_receiver_peer=%.*s", p->fqdn.len,p->fqdn.s );
+			receiver_process(p);
+			LM_CRIT("init_diameter_peer(): receiver_process finished without exit!\n");
+			exit(-1);		
+		}else{
+			dp_add_pid(pid);
+		}
+	}
+	lock_release(peer_list_lock);
+	
+
+	/* Fork the acceptor process (after receivers, so it inherits all the right sockets) */
+	pid = fork_process(1000,"cdp_acceptor",1);
+
+	if (pid==-1){
+		LM_CRIT("init_diameter_peer(): Error on fork() for acceptor!\n");
+		return 0;
+	}
+	if (pid==0) {
+		acceptor_process(config);
+		LM_CRIT("init_diameter_peer(): acceptor_process finished without exit!\n");
+		exit(-1);		
+	}else{
+		dp_add_pid(pid);
+	}
+		
+	/* fork/become timer */
+	if (blocking) {
+		dp_add_pid(getpid());
+		timer_process(1);
+	}		
+	else{		
+		pid = fork_process(1001,"cdp_timer",1);
+		if (pid==-1){
+			LM_CRIT("init_diameter_peer(): Error on fork() for timer!\n");
+			return 0;
+		}
+		if (pid==0) {
+			timer_process(0);
+			LM_CRIT("init_diameter_peer(): timer_process finished without exit!\n");
+			exit(-1);		
+		}else{			
+			dp_add_pid(pid);
+		}
+	}
+	
+	
+	return 1;
+}
+
+/**
+ * Shutdown the CDiameterPeer nicely.
+ * It stops the workers, disconnects peers, drops timers and wait for all processes to exit.
+ */
+void diameter_peer_destroy()
+{
+	int pid,status;
+	handler *h;
+	
+	lock_get(shutdownx_lock);
+	if (*shutdownx) {
+		/* already other process is cleaning stuff */
+		lock_release(shutdownx_lock);			
+		return;
+	}else {
+		/* indicating that we are shuting down */
+		*shutdownx = 1;
+		lock_release(shutdownx_lock);
+	}
+
+	/* wait for all childs to clean up nicely (acceptor, receiver, timer, workers) */
+	LM_INFO("destroy_diameter_peer(): Terminating all childs...\n");
+	while(pid_list->tail){
+		pid = dp_last_pid();
+		if (pid<=0||pid==getpid()){
+			dp_del_pid(pid);
+			continue;
+		}
+		LM_INFO("destroy_diameter_peer(): Waiting for child [%d] to terminate...\n",pid);
+		if (waitpid(pid,&status,0)<0){
+			dp_del_pid(pid);
+			continue;
+		}
+		if (!WIFEXITED(status) /*|| WIFSIGNALED(status)*/){
+			sleep(1);			
+		} else {
+			dp_del_pid(pid);
+		}
+
+	}
+	LM_INFO("destroy_diameter_peer(): All processes terminated. Cleaning up.\n");
+	
+	/* clean upt the timer */
+	timer_cdp_destroy();
+	
+	/* cleaning up workers */
+	worker_destroy();
+	
+	/* cleaning peer_manager */
+	peer_manager_destroy();
+	
+	/* cleaning up sessions */
+	cdp_sessions_destroy();
+
+	/* cleaning up transactions */
+	cdp_trans_destroy();
+	
+	/* cleaning up global vars */
+/*	lock_get(pid_list_lock);*/
+	shm_free(dp_first_pid);
+	shm_free(pid_list);
+	lock_destroy(pid_list_lock);
+	lock_dealloc((void*)pid_list_lock);
+	
+	shm_free(shutdownx);
+	
+	lock_destroy(shutdownx_lock);
+	lock_dealloc((void*)shutdownx_lock);
+	
+	lock_get(handlers_lock);
+	while(handlers->head){
+		h = handlers->head->next;
+		shm_free(handlers->head);
+		handlers->head = h;
+	}
+	lock_destroy(handlers_lock);
+	lock_dealloc((void*)handlers_lock);
+	shm_free(handlers);
+		
+	free_dp_config(config);	
+	LM_CRIT("destroy_diameter_peer(): Bye Bye from C Diameter Peer test\n");
+
+}
+
+

+ 72 - 0
modules/cdp/diameter_peer.h

@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_PEER_H
+#define __DIAMETER_PEER_H
+
+#include <sys/types.h> 
+#include <unistd.h> 
+
+#include "utils.h"
+#include "diameter.h"
+#include "diameter_ims.h"
+#include "diameter_api.h"
+
+#include "worker.h"
+
+/** Element for the local pid list. */
+typedef struct _pid_list_t{
+	pid_t pid;	
+	struct _pid_list_t *next,*prev;
+} pid_list_t;
+
+/** local pid list */
+typedef struct {
+	pid_list_t *head,*tail;
+} pid_list_head_t;
+
+int diameter_peer_init_str(str config_str);
+int diameter_peer_init(char *cfg_filename);
+
+int diameter_peer_start(int blocking);
+
+void diameter_peer_destroy();
+
+#endif

+ 4 - 0
modules/cdp/doc/Makefile

@@ -0,0 +1,4 @@
+docs = cdp.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module

二进制
modules/cdp/doc/RFC3588.vsd


+ 54 - 0
modules/cdp/doc/cdp.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+	<bookinfo>
+	<title>cdp Module</title>
+	<productname class="trade">&kamailioname;</productname>
+	<authorgroup>
+		<author>
+		<firstname>Dragos</firstname>
+		<surname>Vingarzan</surname>
+		<affiliation><orgname>Fraunhofer</orgname></affiliation>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</author>
+		<editor>
+		<firstname>Jason</firstname>
+		<surname>Penton</surname>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</editor>
+		<editor>
+		<firstname>Richard</firstname>
+		<surname>Good</surname>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</editor>
+	</authorgroup>
+	<copyright>
+		<year>2006</year>
+		<holder>FhG Fokus</holder>
+	</copyright>
+	<copyright>
+		<year>2012</year>
+		<holder>Smile Communications</holder>
+	</copyright>
+	</bookinfo>
+	<toc></toc>
+	
+	<xi:include href="cdp_admin.xml"/>
+	<xi:include href="cdp_devel.xml"/>
+	<xi:include href="cdp_faq.xml"/>
+	
+</book>

+ 274 - 0
modules/cdp/doc/cdp_admin.xml

@@ -0,0 +1,274 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module User's Guide -->
+<chapter>
+  <title>&adminguide;</title>
+
+  <section>
+    <title>Overview</title>
+
+    <para>CDP (C Diameter Peer) allows Diameter communication to and from
+    sip-router/kamailio. Most of the code is inherited from DISC
+    http://developer.berlios.de/projects/disc/ and OpenIMS and modified for
+    use within Kamailio. A few improvements/new functionality has been added
+    along the way, for example, threshold reporting on Diameter calls that are
+    serviced above a certain threshold.</para>
+  </section>
+
+  <section>
+    <title>How it works</title>
+
+    <para>CDP forks the following processes:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>1 x Timer</para>
+      </listitem>
+
+      <listitem>
+        <para>1 x Acceptor</para>
+      </listitem>
+
+      <listitem>
+        <para>k x Workers (k configurable through configuration)</para>
+      </listitem>
+
+      <listitem>
+        <para>i x Receivers (one for each peer plus one for unknown
+        peers)</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>CDP is really only an API and offers all of its methods to other
+    modules. No commands are made available to the main Kamailio configuration
+    file. The exported API can be seen in mod.c. The Full Diameter API is in
+    diameter.h and diameter_api.h. IMS-specific constants can be found in
+    diameter_ims.h. The protocol coding is implemented in diameter_avp.c and
+    diameter_msg.c. Diameter state machine is implemented in
+    peerstatemachine.c - there is one of these for each peer which maintains
+    all protocol/application state for each peer. peermanager.c is responsible
+    for peer administration. Diameter transactions are implemented in
+    transaction.c.</para>
+
+    <para>There are 2 configuration areas for CDP. Firstly it must be loaded
+    and conifugred in the Kamailio.cfg file (this is the normal task
+    associated with Kamailio modules). Then, an XML file is required to
+    configure various Diameter parameters and all related peers and the
+    associated routes.</para>
+  </section>
+
+  <section>
+    <title>Dependencies</title>
+
+    <section>
+      <title>&kamailio; Modules</title>
+
+      <para>The following modules must be loaded before this module:
+      <itemizedlist>
+          <listitem>
+            <para><emphasis>None</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+
+    <section>
+      <title>External Libraries or Applications</title>
+
+      <para>The following libraries or applications must be installed before
+      running &kamailio; with this module loaded: <itemizedlist>
+          <listitem>
+            <para><emphasis>None</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+  </section>
+
+  <section>
+    <title>Parameters</title>
+
+    <section>
+      <title>config_file (string)</title>
+
+      <para>This is the location of the XML configuration file.</para>
+
+      <para><emphasis> Default value is <quote>DiameterPeer.xml</quote>.
+      </emphasis></para>
+
+      <example>
+        <title>Set <varname>config_file</varname> parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("cdp", "config_file", "/etc/kamailio/diametercfg.xml")
+...
+</programlisting>
+      </example>
+    </section>
+
+    <section>
+      <title>latency_threshold (int)</title>
+
+      <para>The time in ms above which a log error is wrtten to log file for
+      long CDP transactions.</para>
+
+      <para><emphasis> Default value is <quote>500</quote>. </emphasis></para>
+
+      <example>
+        <title>Set <varname>latency_threshold</varname> parameter</title>
+
+        <programlisting format="linespecific">...
+modparam("cdp", "latency_threshold", 1000)
+...
+</programlisting>
+      </example>
+    </section>
+  </section>
+
+  <section>
+    <title>Functions</title>
+
+    <section>
+      <para>No functions available from configuraion. See API for internal
+      functions.</para>
+    </section>
+  </section>
+
+  <section>
+    <title>Configuration Examples</title>
+
+    <section>
+      <title>DiameterPeer.xml example</title>
+
+      <para>This is an example CDP configuration file. The location of this
+      file is confiured as a CDP parameter (config_file) - See section 4.1
+      Above</para>
+
+      <example>
+        <title>DiameterPeer.xml example</title>
+
+        <programlisting format="linespecific">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
+&lt;!-- 
+
+ DiameterPeer Parameters 
+  - FQDN - FQDN of this peer, as it should apper in the Origin-Host AVP
+  - Realm - Realm of this peer, as it should apper in the Origin-Realm AVP
+  - Vendor_Id - Default Vendor-Id to appear in the Capabilities Exchange
+  - Product_Name - Product Name to appear in the Capabilities Exchange 
+  - AcceptUnknownPeers - Whether to accept (1) or deny (0) connections from peers with FQDN 
+    not configured below
+  - DropUnknownOnDisconnect - Whether to drop (1) or keep (0) and retry connections (until restart)
+    unknown peers in the list of peers after a disconnection.
+  - Tc - Value for the RFC3588 Tc timer - default 30 seconds
+  - Workers - Number of incoming messages processing workers forked processes.
+  - Queue - Length of queue of tasks for the workers:
+     - too small and the incoming messages will be blocked too often;
+     - too large and the senders of incoming messages will have a longer feedback loop to notice that
+     this Diameter peer is overloaded in processing incoming requests;
+     - a good choice is to have it about 2 times the number of workers. This will mean that each worker
+     will have about 2 tasks in the queue to process before new incoming messages will start to block.
+  - ConnectTimeout - time in seconds to wait for an outbound TCP connection to be established.
+  - TransactionTimeout - time in seconds after which the transaction timeout callback will be fired,
+    when using transactional processing.
+  - SessionsHashSize - size of the hash-table to use for the Diameter sessions. When searching for a 
+    session, the time required for this operation will be that of sequential searching in a list of 
+    NumberOfActiveSessions/SessionsHashSize. So higher the better, yet each hashslot will consume an
+    extra 2xsizeof(void*) bytes (typically 8 or 16 bytes extra).
+  - DefaultAuthSessionTimeout - default value to use when there is no Authorization Session Timeout 
+  AVP present.
+  - MaxAuthSessionTimeout - maximum Authorization Session Timeout as a cut-out measure meant to
+  enforce session refreshes.
+      
+ --&gt;
+&lt;DiameterPeer 
+        FQDN="pcscf.ims.smilecoms.com"
+        Realm="ims.smilecoms.com"
+        Vendor_Id="10415"
+        Product_Name="CDiameterPeer"
+        AcceptUnknownPeers="0"
+        DropUnknownOnDisconnect="1"
+        Tc="30"
+        Workers="4"
+        QueueLength="32"
+        ConnectTimeout="5"
+        TransactionTimeout="5"
+        SessionsHashSize="128"
+        DefaultAuthSessionTimeout="60"
+        MaxAuthSessionTimeout="300"
+&gt;
+
+        &lt;!--
+                Definition of peers to connect to and accept connections from. For each peer found in here
+                a dedicated receiver process will be forked. All other unkwnown peers will share a single
+                receiver. NB. you must have a peer definition for each peer listed in the realm routing section
+        --&gt;
+        &lt;Peer FQDN="pcrf1.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+        &lt;Peer FQDN="pcrf2.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+        &lt;Peer FQDN="pcrf3.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+        &lt;Peer FQDN="pcrf4.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+        &lt;Peer FQDN="pcrf5.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+        &lt;Peer FQDN="pcrf6.ims.smilecoms.com" Realm="ims.smilecoms.com" port="3868"/&gt;
+
+        &lt;!--
+                Definition of incoming connection acceptors. If no bind is specified, the acceptor will bind
+                on all available interfaces.
+        --&gt;
+        &lt;Acceptor port="3868"  /&gt;
+        &lt;Acceptor port="3869" bind="127.0.0.1" /&gt;
+        &lt;Acceptor port="3870" bind="192.168.1.1" /&gt;
+
+        &lt;!--
+                Definition of Auth (authorization) and Acct (accounting) supported applications. This
+                information is sent as part of the Capabilities Exchange procedures on connecting to
+                peers. If no common application is found, the peers will disconnect. Messages will only
+                be sent to a peer if that peer actually has declared support for the application id of 
+                the message.
+        --&gt;
+        &lt;Acct id="16777216" vendor="10415" /&gt;
+        &lt;Acct id="16777216" vendor="0" /&gt;
+        &lt;Auth id="16777216" vendor="10415"/&gt;
+        &lt;Auth id="16777216" vendor="0" /&gt;
+
+        &lt;!-- 
+                Supported Vendor IDs - list of values which will be sent in the CER/CEA in the
+                Supported-Vendor-ID AVPs
+        --&gt;
+        &lt;SupportedVendor vendor="10415" /&gt;
+
+        &lt;!--
+                Realm routing definition.
+                Each Realm can have a different table of peers to route towards. In case the Destination
+                Realm AVP contains a Realm not defined here, the DefaultRoute entries will be used.
+
+                Note: In case a message already contains a Destination-Host AVP, Realm Routeing will not be
+                applied.
+                Note: Routing will only happen towards connected and application id supporting peers.
+                
+                The metric is used to order the list of prefered peers, while looking for a connected and
+                application id supporting peer. In the end, of course, just one peer will be selected.
+        --&gt;
+        &lt;Realm name="ims.smilecoms.com"&gt;
+                &lt;Route FQDN="pcrf1.ims.smilecoms.com" metric="3"/&gt;
+                &lt;Route FQDN="pcrf2.ims.smilecoms.com" metric="5"/&gt;
+        &lt;/Realm&gt;
+
+        &lt;Realm name="temp.ims.smilecoms.com"&gt;
+                &lt;Route FQDN="pcrf3.ims.smilecoms.com" metric="7"/&gt;
+                &lt;Route FQDN="pcrf4.ims.smilecoms.com" metric="11"/&gt;
+        &lt;/Realm&gt;
+        &lt;DefaultRoute FQDN="pcrf5.ims.smilecoms.com" metric="15"/&gt;
+        &lt;DefaultRoute FQDN="pcrf6.ims.smilecoms.com" metric="13"/&gt;
+
+
+&lt;/DiameterPeer&gt;
+
+</programlisting>
+      </example>
+    </section>
+
+    <section/>
+  </section>
+</chapter>

+ 682 - 0
modules/cdp/doc/cdp_devel.xml

@@ -0,0 +1,682 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module Developer's Guide -->
+<chapter>
+  <title>&develguide;</title>
+
+  <section>
+    <title>Available Functions</title>
+
+    <section>
+      <title><function moreinfo="none">load_cdp(struct cdp_binds
+      *cdpb)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>struct cdp_binds *cdpb</emphasis> - structure
+          holding function pointers</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAACreateRequest(AAAApplicationId
+      app_id, AAACommandCode command_code, AAAMsgFlag flags, AAASession
+      *session)</function></title>
+
+      <para>Create a Diameter request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAApplicationId app_id</emphasis> - structure
+          holding function pointers</para>
+        </listitem>
+
+        <listitem>
+          <para>AAACommandCode command_code - command code for the
+          message</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAMsgFlag flags - flags to be set</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASession *session - session id to be set</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAACreateResponse(AAAMessage
+      *request)</function></title>
+
+      <para>Create a Diameter response to a give request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *request</emphasis> - request that this
+          response is for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAAFreeMessage(AAAMessage
+      **msg)</function></title>
+
+      <para>Free up memory used by Diameter message</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage **msg</emphasis> - pointer to the pointer
+          containing the message</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAASendMessage(AAAMessage
+      *message, AAATransactionCallback_f *callback_f, void
+      *callback_param)</function></title>
+
+      <para>Send Diameter message asynchronously</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *message</emphasis> - request message to
+          be sent</para>
+        </listitem>
+
+        <listitem>
+          <para>AAATransactionCallback_f *callback_f - When the response is
+          received, the callback_f(callback_param,...) is called</para>
+        </listitem>
+
+        <listitem>
+          <para>void *callback_param - generic param for callback</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode
+      AAASendMessageToPeer(AAAMessage *message, str *peer_id,
+      AAATransactionCallback_f *callback_f, void
+      *callback_param)</function></title>
+
+      <para>Send Diameter message to specific peer asynchronously</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *message - request message to send</para>
+        </listitem>
+
+        <listitem>
+          <para>str *peer_id - FQDN of peer to send to</para>
+        </listitem>
+
+        <listitem>
+          <para>AAATransactionCallback_f *callback_f - When the response is
+          received, the callback_f(callback_param,...) is called</para>
+        </listitem>
+
+        <listitem>
+          <para>void *callback_param - generic param for callback</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAMessage*
+      AAASendRecvMessage(AAAMessage *message)</function></title>
+
+      <para>Send Diameter message synchronously. This blocks until a response
+      is received or a transactional time-out happens.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *message - request message to be sent</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAMessage*
+      AAASendRecvMessageToPeer(AAAMessage *message, str
+      *peer_id)</function></title>
+
+      <para>Send Diameter message to specific peer synchronously. This blocks
+      until a response is received or a transactional time-out happens.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *message</emphasis> - request message to
+          send</para>
+        </listitem>
+
+        <listitem>
+          <para>str *peer_id - FQDN of peer to send to.</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAACreateSession(void
+      *generic_data)</function></title>
+
+      <para>Create a generic Diameter session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>void *generic_data - data to be save to session, useful for
+          attaching app specific data to the session</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAMakeSession(int
+      app_id,int type,str session_id)</function></title>
+
+      <para>Create a Diameter session using already known params</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>int app_id - app id to use</para>
+        </listitem>
+
+        <listitem>
+          <para>int type - type of session</para>
+        </listitem>
+
+        <listitem>
+          <para>str session_id - session ID</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAGetSession(str
+      id)</function></title>
+
+      <para>Retrieve a Diameter session. Returns with a lock on
+      AAASession-&gt;hash - Unlock when done working with result</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str id - Diameter session ID to search for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAADropSession(AAASession
+      *s)</function></title>
+
+      <para>Drop a Diameter session - deallocating all memory</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAASession *s - session to drop</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASessionLock(unsigned int
+      hash)</function></title>
+
+      <para>Lock a Diameter session (hash table row)</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>unsigned int hash - hash to lock</emphasis></para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASessionUnLock(unsigned int
+      hash)</function></title>
+
+      <para>Unlock a Diameter session (hash table row)</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>unsigned int hash - hash to unlock</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession*
+      AAACreateClientAuthSession(int is_statefull,AAASessionCallback_f
+      *cb,void *generic_data)</function></title>
+
+      <para>Creates an Authorisation session for the Client. It generate a new
+      ID and adds to the list of CDP sessions. Returns with a lock on
+      AAASession-&gt;hash</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>int is_statefull - is session stateful or
+          not</emphasis></para>
+        </listitem>
+
+        <listitem>
+          <para>AAASessionCallback_f *cb - callback function on session state
+          change</para>
+        </listitem>
+
+        <listitem>
+          <para>void *generic_data - generic callback data</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession*
+      AAACreateServerAuthSession(AAMessage *msg,int
+      is_statefull,AAASessionCallback_f *cb,void
+      *generic_data)</function></title>
+
+      <para>Create authorisation session for the Server. Generates a new ID
+      and add to CDP list of sessions. Returns with a lock on
+      AAASession-&gt;hash.</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAMessage *msg - request message from which to create server
+          session</para>
+        </listitem>
+
+        <listitem>
+          <para>int is_statefull - is session stateful or not</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASessionCallback_f *cb - callback function on session state
+          change</para>
+        </listitem>
+
+        <listitem>
+          <para>void *generic_data - generic callback data</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAASession* AAAGetAuthSession(str
+      id)</function></title>
+
+      <para>Look for an authorisation session. Returns with lock on
+      AAASession-&gt;hash</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str id - ID of Auth session to search for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAADropAuthSession(AAASession
+      *s)</function></title>
+
+      <para>Deallocates the memory taken by a Authorisation session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAASession *s</emphasis> - Session to drop and
+          deallocate memory for</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAATerminateAuthSession(AAASession
+      *s)</function></title>
+
+      <para>Sends a service terminated event to the session</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAASession *s</emphasis> - authhorisation session to
+          terminate</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAATransaction*
+      AAACreateTransaction(AAAApplicationId app_id,AAACommandCode
+      cmd_code)</function></title>
+
+      <para>Create a AAATransaction for the given request</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAApplicationId app_id - ID of the request's
+          application</para>
+        </listitem>
+
+        <listitem>
+          <para>AAACommandCode cmd_code - request's code</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int AAADropTransaction(AAATransaction
+      *trans)</function></title>
+
+      <para>Deallocates the memory taken by AAA transaction</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAATransaction *trans - transaction to free</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP* AAACreateAVP(AAA_AVPCode code,
+      AAA_AVPFlag flags, AAAVendorId vendorId, char *data, size_t length,
+      AVPDataStatus data_status)</function></title>
+
+      <para>Create new AVP and return pointer to it</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAA_AVPCode code</emphasis> - code for new
+          AVP</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPFlag flags - flags to set</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - vendor ID for AVP</para>
+        </listitem>
+
+        <listitem>
+          <para>char *data - generic payload data</para>
+        </listitem>
+
+        <listitem>
+          <para>size_t length - length of payload data</para>
+        </listitem>
+
+        <listitem>
+          <para>AVPDataStatus data_status - what to do with the payload,
+          duplicate, free with message, etc</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode
+      AAAAddAVPToMessage(AAAMessage *msg, AAA_AVP *avp, AAA_AVP
+      *position)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAMessage *msg</emphasis> - the message to add
+          to</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *avp - the AVP to add</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *position - AVP to add after. if NULL, we add at
+          beginning</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP* AAAFindMatchingAVP(AAAMessage
+      *msg, AAA_AVP *startAvp, AAA_AVPCode avpCode, AAAVendorId vendorId,
+      AAASearchType searchType)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAAMessage *msg - the message to search in</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *startAvp - at which AVP to start the search. usefull
+          for looking for more of the same name</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPCode avpCode - AVP code to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - AVP vendor ID to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASearchType searchType - look forward or backward</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP * AAAGetNextAVP(AAA_AVP
+      *avp)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP *avp - reference AVP</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAReturnCode AAAFreeAVP(AAA_AVP
+      **avp)</function></title>
+
+      <para>Find and load the CDiameterPeer function bindings</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP **avp - pointer memory to be freed</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">str AAAGroupAVPS(AAA_AVP_LIST
+      avps)</function></title>
+
+      <para>Groups a list of AVPS into a data buffer</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST avps - list of AVPS to group</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP_LIST AAAUnGroupAVPS(str
+      buf)</function></title>
+
+      <para>Ungroup a data buffer into a list of AVPs</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>str buf - payload to ungroup list from</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAA_AVP*
+      AAAFindMatchingAVPList(AAA_AVP_LIST avpList, AAA_AVP *startAvp,
+      AAA_AVPCode avpCode, AAAVendorId vendorId, AAASearchType
+      searchType)</function></title>
+
+      <para>Find an AVP in an AVP list</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST avpList - AVP list to search</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVP *startAvp - where to start the search</para>
+        </listitem>
+
+        <listitem>
+          <para>AAA_AVPCode avpCode - AVP code to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAAVendorId vendorId - vendor ID to match</para>
+        </listitem>
+
+        <listitem>
+          <para>AAASearchType searchType - forwards or backwards</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">AAAFreeAVPList(AAA_AVP_LIST
+      *avpList)</function></title>
+
+      <para>Free AVP list and all its members</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAA_AVP_LIST *avpList - list to be freed</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int
+      AAAAddRequestHandler(AAARequestHandler_f *f,void
+      *param)</function></title>
+
+      <para>add a #AAARequestHandler_f callback to request being
+      received</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para>AAARequestHandler_f *f - callback function to be called on
+          incoming requests</para>
+        </listitem>
+
+        <listitem>
+          <para>void *param - generic data passed to callback function</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+
+    <section>
+      <title><function moreinfo="none">int
+      AAAAddResponseHandler(AAAResponseHandler_f *f,void
+      *param)</function></title>
+
+      <para>add a #AAAResponseHandler_f callback to responses being
+      received</para>
+
+      <para>Meaning of the parameters is as follows:</para>
+
+      <itemizedlist>
+        <listitem>
+          <para><emphasis>AAAResponseHandler_f *f</emphasis> - callback
+          function to be called on incoming responses</para>
+        </listitem>
+
+        <listitem>
+          <para>void *param - generic data to be bassed to callback
+          function</para>
+        </listitem>
+      </itemizedlist>
+    </section>
+  </section>
+</chapter>

+ 68 - 0
modules/cdp/doc/cdp_faq.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<!-- Module FAQ -->
+
+<chapter>
+	
+	<title>&faqguide;</title>
+	<qandaset defaultlabel="number">
+	<qandaentry>
+		<question>
+		<para>Where can I find more about &kamailio;?</para>
+		</question>
+		<answer>
+		<para>
+			Take a look at &kamailiohomelink;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>Where can I post a question about this module?</para>
+		</question>
+		<answer>
+		<para>
+			First at all check if your question was already answered on one of
+			our mailing lists: 
+		</para>
+		<itemizedlist>
+			<listitem>
+			<para>User Mailing List - &kamailiouserslink;</para>
+			</listitem>
+			<listitem>
+			<para>Developer Mailing List - &kamailiodevlink;</para>
+			</listitem>
+		</itemizedlist>
+		<para>
+			E-mails regarding any stable &kamailio; release should be sent to 
+			&kamailiousersmail; and e-mails regarding development versions
+			should be sent to &kamailiodevmail;.
+		</para>
+		<para>
+			If you want to keep the mail private, send it to 
+			&kamailiohelpmail;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>How can I report a bug?</para>
+		</question>
+		<answer>
+		<para>
+			Please follow the guidelines provided at:
+			&kamailiobugslink;.
+		</para>
+		</answer>
+	</qandaentry>
+	</qandaset>
+</chapter>
+

+ 108 - 0
modules/cdp/globals.c

@@ -0,0 +1,108 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "globals.h"
+#include "utils.h"
+
+//str aaa_fqdn={"unset_fqdn",10};
+//str aaa_realm={"unset_realm",11};
+//str aaa_identity={"unset_identity",14};
+
+/** initialized the pkg and shm memory */
+int init_memory(int show_status)
+{
+#ifdef PKG_MALLOC
+	if (init_pkg_mallocs()==-1)
+		goto error;
+	if (show_status){
+		LM_DBG( "Memory status (pkg):\n");
+		pkg_status();
+	}
+#endif
+
+#ifdef SHM_MEM
+	
+	if (init_shm_mallocs(
+#ifdef SER_MOD_INTERFACE
+				1
+#endif
+		)==-1)
+		goto error;
+	if (show_status){
+		LM_DBG( "Memory status (shm):\n");
+		shm_status();
+	}
+#endif
+	return 1;
+error:
+	return 0;
+}	
+
+/** call it before exiting; if show_status==1, mem status is displayed */
+void destroy_memory(int show_status)
+{
+	/*clean-up*/
+	if (mem_lock)
+	    shm_unlock(); /* hack: force-unlock the shared memory lock in case
+	                             some process crashed and let it locked; this will
+	                             allow an almost gracious shutdown */
+#ifdef SHM_MEM
+	if (show_status){
+		LM_DBG( "Memory status (shm):\n");
+		//shm_status();
+#ifndef SER_MOD_INTERFACE
+		shm_sums();
+#endif		
+	}
+	/* zero all shmem alloc vars that we still use */
+	shm_mem_destroy();
+#endif
+#ifdef PKG_MALLOC
+	if (show_status){
+		LM_DBG( "Memory status (pkg):\n");
+		//pkg_status();
+#ifndef SER_MOD_INTERFACE
+		pkg_sums();
+#endif
+	}
+#endif
+}
+
+

+ 74 - 0
modules/cdp/globals.h

@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef _c_diameter_peer_globals_h
+#define _c_diameter_peer_globals_h
+
+#include "utils.h"
+#include <sys/types.h>
+
+#define DPNAME "CDiameterPeer"
+#define DPVERSION "0.0.2"
+
+extern int process_no;
+
+int init_memory(int show_status);
+
+void destroy_memory(int show_status);
+
+
+extern unsigned int *listening_socks;
+
+extern int *shutdownx;				/**< whether a shutdown is in progress		*/
+extern gen_lock_t *shutdownx_lock; /**< lock used on shutdown				*/
+
+extern pid_t *dp_first_pid;		/**< first pid that we started from		*/
+
+/* ANSI Terminal colors */
+#define ANSI_GRAY		"\033[01;30m"
+#define ANSI_BLINK_RED 	"\033[00;31m"
+#define ANSI_RED 		"\033[01;31m"
+#define ANSI_GREEN		"\033[01;32m"
+#define ANSI_YELLOW 	"\033[01;33m"
+#define ANSI_BLUE 		"\033[01;34m"
+#define ANSI_MAGENTA	"\033[01;35m"
+#define ANSI_CYAN		"\033[01;36m"
+#define ANSI_WHITE		"\033[01;37m"
+#endif

二进制
modules/cdp/images/RFC3588_acct_state_machine_client.png


二进制
modules/cdp/images/RFC3588_acct_state_machine_server.png


二进制
modules/cdp/images/RFC3588_auth_state_machine_client.png


二进制
modules/cdp/images/RFC3588_auth_state_machine_server.png


二进制
modules/cdp/images/RFC3588_peer_state_machine_1.png


二进制
modules/cdp/images/RFC3588_peer_state_machine_2.png


+ 211 - 0
modules/cdp/mod.c

@@ -0,0 +1,211 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "mod.h"
+
+#include "diameter_peer.h"
+#include "config.h"
+#include "cdp_load.h"
+
+MODULE_VERSION
+
+char* config_file="DiameterPeer.xml"; 	/**< default DiameterPeer configuration filename */
+unsigned int latency_threshold = 500;			/**< default threshold for Diameter calls (ms) */
+
+extern dp_config *config; 				/**< DiameterPeer configuration structure */
+
+#define EXP_FUNC(NAME) \
+		{#NAME, (cmd_function)NAME, NO_SCRIPT, 0, 0},
+/**
+ * Exported functions. This is the API available for use from other SER modules.
+ * If you require more, please add them here.
+ * <p>
+ * - load_cdp() - find and load the CDiameterPeer function bindings
+ * <p>
+ * - AAACreateRequest() - create a diameter request #AAAMessage
+ * - AAACreateResponse() - create a diameter response #AAAMessage
+ * - AAAFreeMessage() - free up the memory used in a Diameter message
+ * <p>
+ * - AAASendMessage() - asynchronously send a message
+ * - AAASendMessageToPeer() - asynchronously send a message to a forced peer
+ * - AAASendRecvMessage() - synchronously send a message and get the response
+ * - AAASendRecvMessageToPeer() - synchronously send a message and get the response to a forced peer 
+ * <p>
+ * - AAACreateSession() - create a diameter #AAASessionId
+ * - AAADropSession() - drop a diameter #AAASessionId
+ * <p>
+ * - AAACreateTransaction() - create a diameter #AAATransaction
+ * - AAADropTransaction() - drop a diameter #AAATransaction
+ * <p>
+ * - AAACreateAVP() - create an #AAA_AVP
+ * - AAAAddAVPToMessage() - add an #AAA_AVP to a #AAAMessage
+ * - AAAFindMatchingAVP() - find an #AAA_AVP inside a #AAAMessage
+ * - AAAGetNextAVP() - get the next #AAA_AVP from the #AAAMessage
+ * - AAAFreeAVP() - free the memory taken by the #AAA_AVP
+ * - AAAGroupAVPS() - group a #AAA_AVP_LIST of #AAA_AVP into a grouped #AAA_AVP 
+ * - AAAUngroupAVPS() - ungroup a grouped #AAA_AVP into a #AAA_AVP_LIST of #AAA_AVP
+ * - AAAFindMatchingAVPList() - find an #AAA_AVP inside a #AAA_AVP_LIST
+ * - AAAFreeAVPList() - free the memory taken by the all members of #AAA_AVP_LIST
+ * <p>
+ * - AAAAddRequestHandler() - add a #AAARequestHandler_f callback to request being received
+ * - AAAAddResponseHandler() - add a #AAAResponseHandler_f callback to responses being received
+ */
+static cmd_export_t cdp_cmds[] = {
+	{"load_cdp",					(cmd_function)load_cdp, 				NO_SCRIPT, 0, 0},
+	
+	EXP_FUNC(AAACreateRequest)
+	EXP_FUNC(AAACreateResponse)
+	EXP_FUNC(AAAFreeMessage)
+
+
+	EXP_FUNC(AAACreateAVP)
+	EXP_FUNC(AAAAddAVPToMessage)
+	EXP_FUNC(AAAAddAVPToList)
+	EXP_FUNC(AAAFindMatchingAVP)
+	EXP_FUNC(AAAFindMatchingAVPList)
+	EXP_FUNC(AAAGetNextAVP)
+	EXP_FUNC(AAAFreeAVP)
+	EXP_FUNC(AAAFreeAVPList)
+	EXP_FUNC(AAAGroupAVPS)
+	EXP_FUNC(AAAUngroupAVPS)
+
+	EXP_FUNC(AAASendMessage)
+	EXP_FUNC(AAASendMessageToPeer)
+	EXP_FUNC(AAASendRecvMessage)
+	EXP_FUNC(AAASendRecvMessageToPeer)
+
+
+	EXP_FUNC(AAAAddRequestHandler)
+	EXP_FUNC(AAAAddResponseHandler)
+
+
+	EXP_FUNC(AAACreateTransaction)
+	EXP_FUNC(AAADropTransaction)
+
+
+	EXP_FUNC(AAACreateSession)
+	EXP_FUNC(AAAMakeSession)
+	EXP_FUNC(AAAGetSession)
+	EXP_FUNC(AAADropSession)
+	EXP_FUNC(AAASessionsLock)
+	EXP_FUNC(AAASessionsUnlock)
+
+	EXP_FUNC(AAACreateClientAuthSession)
+	EXP_FUNC(AAACreateServerAuthSession)
+	EXP_FUNC(AAAGetAuthSession)
+	EXP_FUNC(AAADropAuthSession)
+	EXP_FUNC(AAATerminateAuthSession)
+	
+	{ 0, 0, 0, 0, 0 }
+};
+
+
+/**
+ * Exported parameters.
+ * - config_file - Configuration filename. See configdtd.h for the structure and ConfigExample.xml.
+ */
+static param_export_t cdp_params[] = {	
+	{ "config_file",		PARAM_STRING,	&config_file}, 			/**< configuration filename */
+	{ "latency_threshold", 	PARAM_INT, 		&latency_threshold},	/**<threshold above which we will log*/
+	{ 0, 0, 0 }
+};
+
+
+/**
+ * Exported module interface
+ */
+struct module_exports exports = {
+	"cdp",
+	cdp_cmds,                       		/**< Exported functions */
+	0,
+	cdp_params,                     		/**< Exported parameters */
+	cdp_init,                   			/**< Module initialization function */
+	(response_function) 0,
+	(destroy_function) cdp_exit,
+	0,
+	(child_init_function) cdp_child_init 	/**< per-child init function */
+};
+
+/** 
+ * Module init function.
+ * 
+ * - Initializes the diameter peer using the provided configuration file.
+ * - Registers with pt the required number of processes.
+ */
+static int cdp_init( void )
+{
+	LM_INFO("CDiameterPeer initializing\n");
+	if (!diameter_peer_init(config_file)){
+		LM_ERR("error initializing the diameter peer\n");
+		return 1;
+	}
+	register_procs(2+config->workers + 2 * config->peers_cnt);
+	return 0;
+}
+
+/**
+ *	Child init function.
+ * - starts the DiameterPeer by forking the processes
+ * @param rank - id of the child 
+ */
+static int cdp_child_init( int rank )
+{
+	if (rank == PROC_MAIN) { 
+		LM_INFO("CDiameterPeer child starting ...\n");
+		diameter_peer_start(0);
+		LM_INFO("... CDiameterPeer child started\n");
+	}
+	
+	return 0;
+}
+
+
+/**
+ *	Module termination function.
+ * - stop the DiameterPeer processes in a civilized manner
+ */
+static int cdp_exit( void )
+{
+	LM_INFO("CDiameterPeer child stopping ...\n");
+	diameter_peer_destroy();
+	LM_INFO("... CDiameterPeer child stoped\n");
+	return 0;
+}
+

+ 54 - 0
modules/cdp/mod.h

@@ -0,0 +1,54 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef _CDP__H
+#define _CDP__H
+
+#include "../../sr_module.h"
+
+#define M_NAME "cdp"
+
+
+static int cdp_init( void );
+static int cdp_child_init( int rank );
+static int cdp_exit( void );
+
+
+#endif

+ 109 - 0
modules/cdp/peer.c

@@ -0,0 +1,109 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <time.h>
+
+#include "peer.h"
+#include "diameter.h"
+
+/**
+ * Create a new peer.
+ * - All the memory from parameters is duplicated.
+ * @param fqdn - FQDN of the peer
+ * @param realm - Realm of the peer
+ * @param port - port of the peer to connect to
+ * @returns the new peer* if ok, NULL on error
+ */
+peer* new_peer(str fqdn,str realm,int port)
+{
+	peer *x;
+	x = shm_malloc(sizeof(peer));
+	if (!x){
+		LOG_NO_MEM("shm",sizeof(peer));
+		goto error;
+	}
+	memset(x,0,sizeof(peer));
+	shm_str_dup_macro(x->fqdn,fqdn);
+	if (!x->fqdn.s) goto error;	
+	shm_str_dup_macro(x->realm,realm);
+	if (!x->realm.s) goto error;	
+	x->port = port;
+	x->lock = lock_alloc();
+	x->lock = lock_init(x->lock);
+		
+	x->state = Closed;
+
+	x->I_sock = -1;
+	x->R_sock = -1;
+
+	x->activity = time(0)-500;	
+	
+	x->next = 0;
+	x->prev = 0;
+	
+	return x;
+error:
+	return 0;
+}
+
+/**
+ * Frees the memory taken by a peer structure.
+ * @param x - the peer to free
+ * @param locked - if the caller of this function already acquired the lock on this peer
+ */
+void free_peer(peer *x,int locked)
+{
+	if (!x) return;
+	if (!locked) lock_get(x->lock);
+	if (x->fqdn.s) shm_free(x->fqdn.s);
+	if (x->realm.s) shm_free(x->realm.s);	
+	lock_destroy(x->lock);
+	lock_dealloc((void*)x->lock);
+	shm_free(x);
+}
+
+/**
+ * "Touches" the peer by updating the last activity time to the current time.
+ * @param p - which peer to touch
+ */
+inline void touch_peer(peer *p)
+{
+	p->activity = time(0);
+}

+ 128 - 0
modules/cdp/peer.h

@@ -0,0 +1,128 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __PEER_H
+#define __PEER_H
+
+
+#include "utils.h"
+#include "config.h"
+#include "diameter.h"
+#include <sys/types.h>
+
+
+/** Peer states definition */
+typedef enum {
+	Closed 				= 0,	/**< Not connected */
+	Wait_Conn_Ack		= 1,	/**< Connecting - waiting for Ack */
+	Wait_I_CEA 			= 2,	/**< Connecting - waiting for Capabilities Exchange Answer */
+	Wait_Conn_Ack_Elect	= 3,	/**< Connecting - Acknolegded and going for Election */
+	Wait_Returns  		= 4,	/**< Connecting - done */
+	R_Open 				= 5,	/**< Connected as receiver */
+	I_Open 				= 6,	/**< Connected as initiator */
+	Closing 			= 7		/**< Closing the connection */
+} peer_state_t;
+
+
+/** Peer events definition */
+typedef enum {
+	Start			= 101,	/**< Start connection attempt */
+	Stop			= 102,	/**< Stop */
+	Timeout			= 103,	/**< Time-out */
+	Win_Election	= 104,	/**< Winning the election */
+	R_Conn_CER		= 105,	/**< Receiver - Received connection Capabilities Exchange Request */
+	I_Rcv_Conn_Ack 	= 106,	/**< Initiator - Received connection Ack */
+	I_Rcv_Conn_NAck	= 107,	/**< Initiator - Received connection NAck */
+	I_Rcv_CER		= 108,	/**< Initiator - Receiver Capabilities Exchange Request */
+	I_Rcv_CEA		= 109,	/**< Initiator - Receiver Capabilities Exchange Answer */
+	R_Rcv_CER		= 110,	/**< Receiver - Receiver Capabilities Exchange Request */
+	R_Rcv_CEA		= 111,	/**< Receiver - Receiver Capabilities Exchange Answer */
+	I_Rcv_Non_CEA	= 112,	/**< Initiator - Received non-Capabilities Exchange Answer */
+	I_Rcv_DPR		= 113,	/**< Initiator - Received Disconnect Peer Request */
+	I_Rcv_DPA		= 114,	/**< Initiator - Received Disconnect Peer Answer */
+	R_Rcv_DPR		= 115,	/**< Receiver - Received Disconnect Peer Request */
+	R_Rcv_DPA		= 116,	/**< Receiver - Received Disconnect Peer Answer */
+	I_Rcv_DWR		= 117,	/**< Initiator - Received Diameter Watch-dog Request */
+	I_Rcv_DWA		= 118,	/**< Initiator - Received Diameter Watch-dog Answer */
+	R_Rcv_DWR		= 119,	/**< Receiver - Received Diameter Watch-dog Request */
+	R_Rcv_DWA		= 120,	/**< Receiver - Received Diameter Watch-dog Answer */
+	Send_Message	= 121,	/**< Send a message */
+	I_Rcv_Message	= 122,	/**< Initiator - Received a message */
+	R_Rcv_Message	= 123,	/**< Receiver - Received a message */
+	I_Peer_Disc		= 124,	/**< Initiator - Peer disconnected */
+	R_Peer_Disc		= 125	/**< Receiver - Peer disconnected */
+} peer_event_t;
+
+/** Peer data structure */
+typedef struct _peer_t{
+	str fqdn;				/**< FQDN of the peer */
+	str realm;				/**< Realm of the peer */
+	int port;				/**< TCP Port of the peer */
+	
+	app_config *applications;/**< list of supported applications */
+	int applications_cnt;	/**< size of list of supporter applications*/
+	
+	gen_lock_t *lock;		/**< lock for operations with this peer */
+	
+	peer_state_t state;		/**< state of the peer */
+	int I_sock;				/**< socket used as initiator */
+	int R_sock;				/**< socket used as receiver */
+	
+	time_t activity;		/**< timestamp of last activity */
+	int is_dynamic;			/**< whether this peer was accepted although it was not initially configured */
+	int waitingDWA;			/**< if a Diameter Watch-dog Request was sent out and waiting for an answer */
+	
+	str send_pipe_name;		/**< pipe to signal messages to be sent out*/
+	
+	int fd_exchange_pipe_local;	/**< pipe to communicate with the receiver process and exchange a file descriptor - local end, to read from */
+	int fd_exchange_pipe;	/**< pipe to communicate with the receiver process and exchange a file descriptor */
+
+	AAAMessage *r_cer;      /**< the cer received from R-connection */
+	
+	struct _peer_t *next;	/**< next peer in the peer list */
+	struct _peer_t *prev;	/**< previous peer in the peer list */
+} peer;
+
+peer* new_peer(str fqdn,str realm,int port);
+void free_peer(peer *x,int locked);
+
+inline void touch_peer(peer *p);
+
+#endif

+ 346 - 0
modules/cdp/peermanager.c

@@ -0,0 +1,346 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "diameter.h"
+
+#include "timer.h"
+#include "peermanager.h"
+
+#include "globals.h"
+#include "peerstatemachine.h"
+
+peer_list_t *peer_list=0;		/**< list of peers */
+gen_lock_t *peer_list_lock=0;	/**< lock for the list of peers */
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+extern char *dp_states[];
+AAAMsgIdentifier *hopbyhop_id=0;/**< Current id for Hop-by-hop */
+AAAMsgIdentifier *endtoend_id=0;/**< Current id for End-to-end */
+gen_lock_t *msg_id_lock;		/**< lock for the message identifier changes */
+
+/**
+ * Initializes the Peer Manager. 
+ * The initial list of peers is taken from the configuration provided
+ * @param config - configuration for initial peers
+ * @returns 1
+ */
+int peer_manager_init(dp_config *config)
+{
+	int i;
+	peer *p;
+	LM_DBG("peer_manager_init(): Peer Manager initialization...\n");
+	peer_list = shm_malloc(sizeof(peer_list_t));
+	peer_list->head = 0; 
+	peer_list->tail = 0;
+	peer_list_lock = lock_alloc();
+	peer_list_lock = lock_init(peer_list_lock);
+	
+	hopbyhop_id = shm_malloc(sizeof(AAAMsgIdentifier));
+	endtoend_id = shm_malloc(sizeof(AAAMsgIdentifier));
+	msg_id_lock = lock_alloc();
+	msg_id_lock = lock_init(msg_id_lock);
+	
+	srand((unsigned int)time(0));
+	*hopbyhop_id = rand();
+	*endtoend_id = (time(0)&0xFFF)<<20;
+	*endtoend_id |= rand() & 0xFFFFF;	
+
+	for(i=0;i<config->peers_cnt;i++){
+		p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port);
+		if (!p) continue;
+		p->is_dynamic = 0;
+		add_peer(p);
+	}
+	
+	add_timer(1,0,&peer_timer,0);
+	
+	return 1;
+}
+
+/**
+ * Destroys the Peer Manager and disconnects all peer sockets.
+ */
+void peer_manager_destroy()
+{
+	peer *foo,*bar;
+	lock_get(peer_list_lock);
+	foo = peer_list->head;
+	while(foo){
+		if (foo->I_sock>0) close(foo->I_sock);
+		if (foo->R_sock>0) close(foo->R_sock);
+		bar = foo->next;
+		free_peer(foo,1);
+		foo = bar;
+	}
+
+/*	lock_get(msg_id_lock);	*/
+	shm_free(hopbyhop_id);
+	shm_free(endtoend_id);	
+	lock_destroy(msg_id_lock);
+	lock_dealloc((void*)msg_id_lock);
+
+	shm_free(peer_list);	
+	lock_destroy(peer_list_lock);
+	lock_dealloc((void*)peer_list_lock);
+	LM_DBG("peer_manager_init(): ...Peer Manager destroyed\n");
+}
+
+/**
+ * Logs the list of peers
+ * @param level - log level to print to
+ */
+void log_peer_list(int level)
+{
+	/* must have lock on peer_list_lock when calling this!!! */
+	peer *p;
+	int i;
+#ifdef SER_MOD_INTERFACE
+	if (!is_printable(level))
+#else		
+	if (debug<level)
+#endif
+		return;
+	
+	LOG(level,"--- Peer List: ---\n");
+	for(p = peer_list->head;p;p = p->next){
+		LOG(level,ANSI_GREEN" S["ANSI_YELLOW"%s"ANSI_GREEN"] "ANSI_BLUE"%.*s:%d"ANSI_GREEN" D["ANSI_RED"%c"ANSI_GREEN"]\n",dp_states[p->state],p->fqdn.len,p->fqdn.s,p->port,p->is_dynamic?'X':' ');
+		for(i=0;i<p->applications_cnt;i++)
+			LOG(level,ANSI_YELLOW"\t [%d,%d]"ANSI_GREEN"\n",p->applications[i].id,p->applications[i].vendor);
+	}
+	LOG(level,"------------------\n");		 
+}
+
+/**
+ * Adds a peer to the peer list
+ * @param p - peer to add
+ */
+void add_peer(peer *p)
+{
+	if (!p) return;
+	lock_get(peer_list_lock);
+	p->next = 0;
+	p->prev = peer_list->tail;
+	if (!peer_list->head) peer_list->head = p;
+	if (peer_list->tail) peer_list->tail->next = p;
+	peer_list->tail = p;
+	lock_release(peer_list_lock);
+}
+
+/**
+ * Removes a peer from the peer list
+ * @param p - the peer to remove
+ */ 
+void remove_peer(peer *p)
+{
+	peer *i;
+	if (!p) return;
+	i = peer_list->head;
+	while(i&&i!=p) i = i->next;
+	if (i){
+		if (i->prev) i->prev->next = i->next;
+		else peer_list->head = i->next;
+		if (i->next) i->next->prev = i->prev;
+		else peer_list->tail = i->prev;
+	}
+}
+
+/**
+ * Finds a peer based on the TCP socket.
+ * @param sock - socket to look for
+ * @returns the peer* or NULL if not found
+ */
+peer *get_peer_from_sock(int sock)
+{
+	peer *i;
+	lock_get(peer_list_lock);
+	
+	i = peer_list->head;
+	while(i&&i->I_sock!=sock&&i->R_sock!=sock) i = i->next;
+	lock_release(peer_list_lock);
+	return i;
+}
+
+/**
+ * Finds a peer based on the FQDN and Realm.
+ * @param fqdn - the FQDN to look for
+ * @param realm - the Realm to look for
+ * @returns the peer* or NULL if not found
+ */
+peer *get_peer_from_fqdn(str fqdn,str realm)
+{
+	peer *i;
+	lock_get(peer_list_lock);
+	i = peer_list->head;
+	while(i){
+		if (fqdn.len == i->fqdn.len && strncasecmp(fqdn.s,i->fqdn.s,fqdn.len)==0) 
+			break;
+		i = i->next;
+	}
+	lock_release(peer_list_lock);
+	if (!i&&config->accept_unknown_peers){
+		i = new_peer(fqdn,realm,3868);
+		if (i){
+			i->is_dynamic=1;
+			touch_peer(i);
+			add_peer(i);
+		}
+	}
+	return i;
+}
+
+/**
+ * Finds a peer based on the FQDN.
+ * @param fqdn - the FQDN to look for
+ * @returns the peer* or NULL if not found
+ */
+peer *get_peer_by_fqdn(str *fqdn)
+{
+	peer *i;
+	lock_get(peer_list_lock);
+	i = peer_list->head;
+	while(i){
+		if (fqdn->len == i->fqdn.len && strncasecmp(fqdn->s,i->fqdn.s,fqdn->len)==0) 
+			break;
+		i = i->next;
+	}
+	lock_release(peer_list_lock);
+	return i;
+}
+
+/**
+ * Timer function for peer management.
+ * This is registered as a timer by peer_manager_init() and gets called every
+ * #PEER_MANAGER_TIMER seconds. Then it looks on what changed and triggers events.
+ * @param now - time of call
+ * @param ptr - generic pointer for timers - not used
+ */
+int peer_timer(time_t now,void *ptr)
+{
+	peer *p,*n;
+	int i;
+	LM_DBG("peer_timer(): taking care of peers...\n");
+	lock_get(peer_list_lock);
+	p = peer_list->head;
+	while(p){
+		lock_get(p->lock);
+		n = p->next;
+		if (p->activity+config->tc<=now){
+			LM_INFO("peer_timer(): Peer %.*s \tState %d \n",p->fqdn.len,p->fqdn.s,p->state);
+			switch (p->state){
+				/* initiating connection */
+				case Closed:
+					if (p->is_dynamic && config->drop_unknown_peers){
+						remove_peer(p);
+						free_peer(p,1);
+						break;
+					}
+					touch_peer(p);
+					sm_process(p,Start,0,1,0);
+					break;
+				/* timeouts */	
+				case Wait_Conn_Ack:
+				case Wait_I_CEA:
+				case Closing:
+				case Wait_Returns:
+				case Wait_Conn_Ack_Elect:
+					touch_peer(p);
+					sm_process(p,Timeout,0,1,0);
+					break;	
+				/* inactivity detected */
+				case I_Open:
+				case R_Open:
+					if (p->waitingDWA){
+						p->waitingDWA = 0;
+						if (p->state==I_Open) sm_process(p,I_Peer_Disc,0,1,p->I_sock);
+						if (p->state==R_Open) sm_process(p,R_Peer_Disc,0,1,p->R_sock);
+					} else {
+						p->waitingDWA = 1;
+						Snd_DWR(p);
+						touch_peer(p);
+					}
+					break;
+				/* ignored states */	
+				/* unknown states */
+				default:
+					LM_ERR("peer_timer(): Peer %.*s inactive  in state %d\n",
+						p->fqdn.len,p->fqdn.s,p->state);
+			}				
+		}
+		lock_release(p->lock);
+		p = n;
+	}
+	lock_release(peer_list_lock);
+	log_peer_list(L_INFO);
+	i = config->tc/5;
+	if (i<=0) i=1;
+	return i;
+}
+
+/**
+ * Generates the next Hop-by-hop identifier.
+ * @returns the new identifier to be used in messages
+ */
+inline AAAMsgIdentifier next_hopbyhop()
+{
+	AAAMsgIdentifier x;
+	lock_get(msg_id_lock);
+	*hopbyhop_id = (*hopbyhop_id)+1;
+	x = *hopbyhop_id;
+	lock_release(msg_id_lock);
+	return x;
+}
+
+/**
+ * Generates the next End-to-end identifier.
+ * @returns the new identifier to be used in messages
+ */
+inline AAAMsgIdentifier next_endtoend()
+{
+	AAAMsgIdentifier x;
+	lock_get(msg_id_lock);
+	*endtoend_id = (*endtoend_id)+1;
+	x = *endtoend_id;
+	lock_release(msg_id_lock);
+	return x;
+}

+ 78 - 0
modules/cdp/peermanager.h

@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __MANAGER_H
+#define __MANAGER_H
+
+
+#include "utils.h"
+#include "diameter.h"
+#include "peer.h"
+#include "config.h"
+
+/** list of peers */
+typedef struct {
+	peer *head;	/**< first peer in the list */	
+	peer *tail; /**< last peer in the list */
+} peer_list_t;
+
+int peer_manager_init(dp_config *config);
+
+void peer_manager_destroy();
+
+void log_peer_list(int level);
+
+void add_peer(peer *p);
+
+void remove_peer(peer *p);
+
+peer *get_peer_from_sock(int sock);
+
+peer *get_peer_from_fqdn(str fqdn,str realm);
+
+peer *get_peer_by_fqdn(str *fqdn);
+
+int peer_timer(time_t now,void *ptr);
+
+AAAMsgIdentifier next_hopbyhop();
+AAAMsgIdentifier next_endtoend();
+
+
+#endif

+ 1240 - 0
modules/cdp/peerstatemachine.c

@@ -0,0 +1,1240 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <sys/socket.h> 
+#include <netinet/in.h>
+#include <unistd.h>
+
+#include "peerstatemachine.h"
+#include "diameter_api.h"
+#include "diameter_ims.h"
+
+#include "utils.h"
+#include "receiver.h"
+#include "peermanager.h"
+#include "config.h"
+#include "worker.h"
+#include "authstatemachine.h"
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+
+/** Strings for the peer states */
+char *dp_states[]={"Closed","Wait_Conn_Ack","Wait_I_CEA","Wait_Conn_Ack_Elect","Wait_Returns","R_Open","I_Open","Closing"};
+/** Strings for the peer events */
+char *dp_events[]={"Start","Stop","Timeout","Win_Election","R_Conn_CER","I_Rcv_Conn_Ack","I_Rcv_Conn_NAck",
+	"I_Rcv_CER","I_Rcv_CEA","R_Rcv_CER","R_Rcv_CEA","I_Rcv_Non_CEA",
+	"I_Rcv_DPR","I_Rcv_DPA","R_Rcv_DPR","R_Rcv_DPA",
+	"I_Rcv_DWR","I_Rcv_DWA","R_Rcv_DWR","R_Rcv_DWA",
+	"Send_Message","I_Rcv_Message","R_Rcv_Message","I_Peer_Disc","R_Peer_Disc"};
+
+/**
+ * Diameter base protocol state-machine processing.
+ * This function get's called for every event. It updates the states and can trigger
+ * other events.
+ * @param p - the peer for which the event happened
+ * @param event - the event that happened
+ * @param msg - if a Diameter message was received this is it, or NULL if not
+ * @param peer_locked - if the peer lock is already aquired
+ * @param sock - socket that this event happened on, or NULL if unrelated
+ * @returns 1 on success, 0 on error. Also the peer states are updated
+ */
+int sm_process(peer *p,peer_event_t event,AAAMessage *msg,int peer_locked,int sock)
+{
+	int result_code;
+	peer_event_t next_event;
+	int msg_received=0;
+		
+	if (!peer_locked) lock_get(p->lock);
+	LM_DBG("sm_process(): Peer %.*s \tState %s \tEvent %s\n",
+		p->fqdn.len,p->fqdn.s,dp_states[p->state],dp_events[event-101]);
+
+	switch (p->state){
+		case Closed:
+			switch (event){
+				case Start:
+					p->state = Wait_Conn_Ack;
+					next_event = I_Snd_Conn_Req(p);
+					if (next_event==I_Rcv_Conn_NAck)
+						sm_process(p,next_event,0,1,p->I_sock);
+					else{
+						/* wait for fd to be transmitted to the respective receiver, in order to get a send pipe opened */						
+					}
+					break;	
+				case R_Conn_CER:
+					R_Accept(p,sock);
+					result_code = Process_CER(p,msg);
+					Snd_CEA(p,msg,result_code,p->R_sock);
+					msg=0;
+					if (result_code>=2000 && result_code<3000)
+						p->state = R_Open;
+					else {
+						R_Disc(p);
+						p->state = Closed;
+					}
+					log_peer_list(L_INFO);
+					break;
+				case Stop:
+					/* just ignore this state */
+					p->state = Closed;
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;		
+		case Wait_Conn_Ack:
+			switch(event){
+				case I_Rcv_Conn_Ack:
+					I_Snd_CER(p);
+					p->state = Wait_I_CEA;
+					break;	
+				case I_Rcv_Conn_NAck:
+					Cleanup(p,p->I_sock);
+					p->state = Closed;
+					break;
+				case R_Conn_CER:
+					if (p->r_cer) AAAFreeMessage(&(p->r_cer));
+					R_Accept(p,sock);
+					result_code = Process_CER(p,msg);
+					if (result_code>=2000 && result_code<3000){
+						p->state = Wait_Conn_Ack_Elect;
+						p->r_cer = msg;
+					}
+					else {
+						p->state = Closed;
+						AAAFreeMessage(&msg);
+						R_Disc(p);
+						I_Disc(p);
+					}
+					break;
+				case Timeout:
+					Error(p,p->I_sock);
+					p->state = Closed;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;
+			
+		case Wait_I_CEA:
+			switch(event){
+				case I_Rcv_CEA:
+					result_code = Process_CEA(p,msg);
+					if (result_code>=2000 && result_code<3000)
+						p->state = I_Open; 												
+					else {
+						Cleanup(p,p->I_sock);
+						p->state = Closed;
+					}
+					log_peer_list(L_INFO);
+					break;
+				case R_Conn_CER:
+					if (p->r_cer) AAAFreeMessage(&(p->r_cer));
+					R_Accept(p,sock);
+					result_code = Process_CER(p,msg);
+					if (result_code>=2000 && result_code<3000){
+						p->state = Wait_Returns;
+						if (Elect(p,msg)){
+							// won the election = > I_Disc(), R_Send_CEA()
+							LM_INFO("sm_process():Wait_I_CEA Win Elect \n");
+							sm_process(p,Win_Election,msg,1,sock);
+						} else {
+							// lost the election => wait for I_Recv_CEA, then R_Disc()
+							LM_INFO("sm_process():Wait_I_CEA Lose Elect \n");
+							p->r_cer = msg;
+							sm_process(p,I_Peer_Disc,0,1,p->I_sock);
+						}
+					}
+					else{
+						Snd_CEA(p,msg,result_code,p->R_sock);
+						R_Disc(p);
+						I_Disc(p);
+						p->state=Closed;
+						break;
+					}					
+					break;
+				case I_Peer_Disc:
+					I_Disc(p);
+					p->state = Closed;
+					break;
+				case I_Rcv_Non_CEA:
+					Error(p,p->I_sock);
+					p->state = Closed;
+					break;
+				case Timeout:
+					Error(p,p->I_sock);
+					p->state = Closed;
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;	
+			
+		case Wait_Conn_Ack_Elect:
+			switch(event){
+				case I_Rcv_Conn_Ack:
+					I_Snd_CER(p);
+					if (p->r_cer){
+						p->state = Wait_Returns;
+						if (Elect(p,p->r_cer)){
+							// won the election = > I_Disc(), R_Send_CEA()
+							LM_INFO("sm_process():Wait_Conn_Ack_Elect Win Elect \n");
+							sm_process(p,Win_Election,p->r_cer,1,sock);
+							p->r_cer = 0;
+						} else {
+							// lost the election => wait for I_Recv_CEA, then R_Disc()
+							LM_INFO("sm_process():Wait_Conn_Ack_Elect Lose Elect \n");
+							AAAFreeMessage(&p->r_cer);
+						}
+					} else {
+						LM_ERR("sm_process():Wait_Conn_Ack_Elect, I_Rcv_Conn_Ack, No R-CER ! \n");
+						p->state = Wait_I_CEA;
+					}
+					break;
+				case I_Rcv_Conn_NAck:
+					Cleanup(p,p->I_sock);
+					if (p->r_cer){
+						result_code = Process_CER(p,p->r_cer);
+						Snd_CEA(p,p->r_cer,result_code,p->R_sock);
+						p->r_cer=0;
+						if (result_code>=2000 && result_code<3000)
+							p->state = R_Open;
+						else {
+							R_Disc(p);
+							p->state = Closed;
+						//	p->state = R_Open; /* Or maybe I should disconnect it?*/
+						}
+					}else{
+						LM_ERR("sm_process():Wait_Conn_Ack_Elect, I_Rcv_Conn_NAck No R-CER ! \n");
+					}
+					break;
+				case R_Peer_Disc:
+					R_Disc(p);
+					p->state = Wait_Conn_Ack;
+					break;
+				case R_Conn_CER:
+					R_Reject(p,sock);
+					AAAFreeMessage(&msg);
+					p->state = Wait_Conn_Ack_Elect;
+					break;
+				case Timeout:
+					if (p->I_sock>=0) Error(p,p->I_sock);
+					if (p->R_sock>=0) Error(p,p->R_sock);
+					p->state = Closed;
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;
+			
+		case Wait_Returns:
+			switch(event){
+				case Win_Election:
+					/* this is the Win Election -> I is dropped, R is kept */
+					LM_INFO("sm_process():Wait_Returns Win Elect \n");
+					I_Disc(p);
+					result_code = Process_CER(p,msg);
+					Snd_CEA(p,msg,result_code,p->R_sock);
+					if (result_code>=2000 && result_code<3000){
+						p->state = R_Open;
+					}else{
+						R_Disc(p);
+						p->state = Closed;
+					}
+					break;
+				case I_Peer_Disc:
+					I_Disc(p);
+					if (p->r_cer){
+						result_code = Process_CER(p,p->r_cer);
+						Snd_CEA(p,p->r_cer,result_code,p->R_sock);
+						p->r_cer=0;
+						if (result_code>=2000 && result_code<3000){
+							p->state = R_Open;
+						}else{
+							R_Disc(p);
+							p->state = Closed;
+						}
+					}else {
+						LM_ERR("sm_process():Wait_Returns, I_Peer_Disc No R-CER ! \n");						
+					}
+					break;
+				case I_Rcv_CEA:
+					/* this is the Lost Election -> I is kept, R dropped */
+					LM_INFO("sm_process():Wait_Returns Lost Elect \n");
+					R_Disc(p);
+					result_code = Process_CEA(p,msg);
+					if (result_code>=2000 && result_code<3000)
+						p->state = I_Open; 
+					else {
+						Cleanup(p,p->I_sock);
+						p->state = Closed;
+					}
+					break;
+				case R_Peer_Disc:
+					R_Disc(p);
+					p->state = Wait_I_CEA;
+					break;
+				case R_Conn_CER:
+					R_Reject(p,p->R_sock);
+					AAAFreeMessage(&msg);
+					p->state = Wait_Returns;
+					break;
+				case Timeout:
+					if (p->I_sock>=0) Error(p,p->I_sock);
+					if (p->R_sock>=0) Error(p,p->R_sock);
+					p->state = Closed;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;
+		case R_Open:
+			switch (event){
+				case Send_Message:
+					Snd_Message(p,msg);
+					p->state = R_Open;
+					break;
+				case R_Rcv_Message:
+					// delayed processing until out of the critical zone
+					//Rcv_Process(p,msg);
+					msg_received = 1;
+					p->state = R_Open;
+					break;
+				case R_Rcv_DWR:
+					result_code = Process_DWR(p,msg);
+					Snd_DWA(p,msg,result_code,p->R_sock);
+					p->state = R_Open;
+					break;
+				case R_Rcv_DWA:
+					Process_DWA(p,msg);
+					p->state = R_Open;
+					break;
+				case R_Conn_CER:
+					R_Reject(p,sock);
+					AAAFreeMessage(&msg);
+					p->state = R_Open;
+					break;
+				case Stop:
+					Snd_DPR(p);
+					p->state = Closing;
+					break;
+				case R_Rcv_DPR:
+					Snd_DPA(p,msg,AAA_SUCCESS,p->R_sock);
+					R_Disc(p);
+					p->state = Closed;
+					log_peer_list(L_INFO);
+					break;
+				case R_Peer_Disc:
+					R_Disc(p);
+					p->state = Closed;
+					log_peer_list(L_INFO);
+					break;
+				case R_Rcv_CER:
+					result_code = Process_CER(p,msg);
+					Snd_CEA(p,msg,result_code,p->R_sock);
+					if (result_code>=2000 && result_code<3000)
+						p->state = R_Open;
+					else {
+						/*R_Disc(p);p.state = Closed;*/
+						p->state = R_Open; /* Or maybe I should disconnect it?*/
+					}
+					break;
+				case R_Rcv_CEA:
+					result_code = Process_CEA(p,msg);
+					if (result_code>=2000 && result_code<3000)
+						p->state = R_Open;
+					else {
+						/*R_Disc(p);p.state = Closed;*/
+						p->state = R_Open; /* Or maybe I should disconnect it?*/
+					}
+					log_peer_list(L_INFO);
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;			
+		case I_Open:
+			switch (event){
+				case Send_Message:
+					Snd_Message(p,msg);
+					p->state = I_Open;
+					break;
+				case I_Rcv_Message:
+					// delayed processing until out of the critical zone
+					//Rcv_Process(p,msg);
+					msg_received = 1;
+					p->state = I_Open;
+					break;
+				case I_Rcv_DWR:
+					result_code = Process_DWR(p,msg);
+					Snd_DWA(p,msg,result_code,p->I_sock);						
+					p->state =I_Open;
+					break;
+				case I_Rcv_DWA:
+					Process_DWA(p,msg);
+					p->state =I_Open;
+					break;
+				case R_Conn_CER:
+					R_Reject(p,sock);
+					AAAFreeMessage(&msg);
+					p->state = I_Open;
+					break;
+				case Stop:
+					Snd_DPR(p);
+					p->state = Closing;
+					break;
+				case I_Rcv_DPR:
+					Snd_DPA(p,msg,2001,p->I_sock);
+					I_Disc(p);
+					p->state = Closed;
+					log_peer_list(L_INFO);
+					break;
+				case I_Peer_Disc:
+					I_Disc(p);
+					p->state = Closed;
+					log_peer_list(L_INFO);
+					break;
+				case I_Rcv_CER:
+					result_code = Process_CER(p,msg);
+					Snd_CEA(p,msg,result_code,p->I_sock);
+					if (result_code>=2000 && result_code<3000)
+						p->state = I_Open;
+					else {
+						/*I_Disc(p);p.state = Closed;*/
+						p->state = I_Open; /* Or maybe I should disconnect it?*/
+					}
+					break;
+				case I_Rcv_CEA:
+					result_code = Process_CEA(p,msg);
+					if (result_code>=2000 && result_code<3000)
+						p->state = I_Open;
+					else {
+						/*I_Disc(p);p.state = Closed;*/
+						p->state = I_Open; /* Or maybe I should disconnect it?*/
+					}
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;				
+		case Closing:
+			switch(event){
+				case I_Rcv_DPA:
+					I_Disc(p);
+					p->state = Closed;
+					break;
+				case R_Rcv_DPA:
+					R_Disc(p);
+					p->state = Closed;
+					break;
+				case Timeout:
+					if (p->I_sock>=0) Error(p,p->I_sock);
+					if (p->R_sock>=0) Error(p,p->R_sock);
+					p->state = Closed;
+					break;
+				case I_Peer_Disc:
+					I_Disc(p);
+					p->state = Closed;
+					break;
+				case R_Peer_Disc:
+					R_Disc(p);
+					p->state = Closed;
+					break;
+				default:
+					LM_ERR("sm_process(): In state %s invalid event %s\n",
+						dp_states[p->state],dp_events[event-101]);
+					goto error;
+			}
+			break;				
+	}
+	if (!peer_locked) lock_release(p->lock);
+	
+	if (msg_received)
+		Rcv_Process(p,msg);
+	
+	return 1;	
+error:
+	if (!peer_locked) lock_release(p->lock);
+	return 0;	
+}
+
+/**
+ * Initiator - Send Connection Request.
+ * Tries to connect to the remote peer's socket. If the connection is refused, the new
+ * state is I_Rcv_Conn_NAck, else I_Rcv_Conn_Ack.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer to send to
+ * @returns the new state for the peer
+ */
+peer_state_t I_Snd_Conn_Req(peer *p)
+{
+	LM_INFO("I_Snd_Conn_Req(): Peer %.*s \n",
+		p->fqdn.len,p->fqdn.s);
+
+	if (p->I_sock>0) close(p->I_sock);
+	p->I_sock = -1;
+	p->I_sock = peer_connect(p);
+	if (p->I_sock<0){
+		return I_Rcv_Conn_NAck;
+	}
+	
+	return I_Rcv_Conn_Ack;
+}
+
+/**
+ * Cleans a socket by closing it and removing the reference
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer
+ * @param sock - socket to close
+ */
+void Cleanup(peer *p,int sock)
+{
+	if (sock<0) return;
+	close(sock);
+	if (p->I_sock == sock) p->I_sock = -1;
+	if (p->R_sock == sock) p->R_sock = -1;
+}
+
+/**
+ * Error action for a peer, triggers a Cleanup action.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer
+ * @param sock - socket to close
+ */
+void Error(peer *p, int sock)
+{
+	Cleanup(p,sock);
+}
+
+/**
+ * Adds the Applications to a Capability Exchange message.
+ * \note Must be called with a lock on the peer.
+ * @param msg - the message to add to (request/answer)
+ * @param p - the peer to add applications from
+ */
+static inline void Snd_CE_add_applications(AAAMessage *msg,peer *p)
+{
+	int i;
+	app_config *app;
+	char x[4];
+	AAA_AVP *avp1,*avp2;
+	AAA_AVP_LIST list;
+	str group;
+	list.head=0;list.tail=0;
+	
+	for(i=0;i<config->applications_cnt;i++){
+		app = config->applications+i;
+		if (app->vendor==0){
+			set_4bytes(x,app->id);
+			AAACreateAndAddAVPToMessage(msg,
+				(app->type==DP_AUTHORIZATION?AVP_Auth_Application_Id:AVP_Acct_Application_Id),
+				AAA_AVP_FLAG_MANDATORY,0,x,4);
+		}else{
+			set_4bytes(x,app->vendor);
+			avp1 = AAACreateAVP(AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4, AVP_DUPLICATE_DATA);			
+			AAAAddAVPToList(&list,avp1);
+			
+			set_4bytes(x,app->id);
+			avp2 = AAACreateAVP((app->type==DP_AUTHORIZATION?AVP_Auth_Application_Id:AVP_Acct_Application_Id),
+				AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);			
+			AAAAddAVPToList(&list,avp2);
+		
+			group = AAAGroupAVPS(list);	
+			AAAFreeAVPList(&list);
+			
+			AAACreateAndAddAVPToMessage(msg,
+				AVP_Vendor_Specific_Application_Id,
+				AAA_AVP_FLAG_MANDATORY,0,group.s,group.len);
+			shm_free(group.s);
+		}
+	}
+	for(i=0;i<config->supported_vendors_cnt;i++){
+		set_4bytes(x,config->supported_vendors[i]);
+		AAACreateAndAddAVPToMessage(msg,AVP_Supported_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4);					
+	}		
+}
+
+/**
+ * Send a Capability Exchange Request.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer to send to
+ */
+void I_Snd_CER(peer *p)
+{
+	AAAMessage *cer=0;
+//	AAA_AVP *avp;
+	unsigned long ip;
+	union {
+		struct sockaddr addr;
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} addr_u ;
+	socklen_t addrlen;
+	char x[18];
+	
+	cer = AAANewMessage(Code_CE,0,0,0);
+	if (!cer) return;
+	cer->hopbyhopId = next_hopbyhop();
+	cer->endtoendId = next_endtoend();
+	addrlen = sizeof(addr_u);
+	if (getsockname(p->I_sock,&(addr_u.addr), &addrlen) == -1) { 
+		LM_ERR("I_Snd_CER(): Error on finding local host address > %s\n",strerror(errno));
+	}else{
+		switch(addr_u.addr.sa_family){
+			case AF_INET:
+				set_2bytes(x,1);
+				ip = htonl(addr_u.in.sin_addr.s_addr);
+				set_4bytes(x+2,ip);
+				AAACreateAndAddAVPToMessage(cer,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,6);
+				break;
+			case AF_INET6:
+				set_2bytes(x,2);
+				memcpy(x+2,addr_u.in6.sin6_addr.s6_addr,16);
+				AAACreateAndAddAVPToMessage(cer,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,18);
+				break;
+			default:
+				LM_ERR("I_Snd_CER(): unknown address type with family %d\n",addr_u.addr.sa_family);
+		}
+	}
+
+	set_4bytes(x,config->vendor_id);
+	AAACreateAndAddAVPToMessage(cer,AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4);
+			
+	AAACreateAndAddAVPToMessage(cer,AVP_Product_Name,AAA_AVP_FLAG_MANDATORY,0,config->product_name.s,config->product_name.len);
+
+	Snd_CE_add_applications(cer,p);
+//	peer_send(p,p->I_sock,cer,1);
+	peer_send_msg(p,cer);
+}
+
+
+void add_peer_application(peer *p, int id, int vendor, app_type type)
+{
+	int i;
+	if (!p->applications) return;
+	for(i=0;i<p->applications_cnt;i++)
+		if (p->applications[i].id == id &&
+			p->applications[i].vendor == vendor &&
+			p->applications[i].type == type) return;
+
+	p->applications[p->applications_cnt].id = id;
+	p->applications[p->applications_cnt].vendor = vendor;
+	p->applications[p->applications_cnt].type = type;
+	p->applications_cnt++;	 
+}
+
+void save_peer_applications(peer *p,AAAMessage *msg)
+{
+	int total_cnt=0;
+	AAA_AVP *avp,*avp_vendor,*avp2;
+	AAA_AVP_LIST group;
+	int id,vendor;
+
+	if (p->applications) {
+		shm_free(p->applications);
+		p->applications = 0;
+		p->applications_cnt = 0;
+	}
+	for(avp=msg->avpList.head;avp;avp = avp->next)
+		switch (avp->code){
+			case AVP_Auth_Application_Id:
+			case AVP_Acct_Application_Id:
+			case AVP_Vendor_Specific_Application_Id:				
+				total_cnt+=2;/* wasteful, but let's skip decoding */	
+				break;				
+		}
+	p->applications_cnt = 0;
+	p->applications = shm_malloc(sizeof(app_config)*total_cnt);
+	if (!p->applications){	
+		LM_ERR("save_peer_applications(): Error allocating %ld bytes! No applications saved...\n",
+			(long int)(sizeof(app_config)*total_cnt));
+		return;
+	}
+	for(avp=msg->avpList.head;avp;avp = avp->next)
+	{
+		switch (avp->code){
+			case AVP_Auth_Application_Id:
+				id = get_4bytes(avp->data.s);	
+				add_peer_application(p,id,0,DP_AUTHORIZATION);	
+				break;
+			case AVP_Acct_Application_Id:
+				id = get_4bytes(avp->data.s);	
+				add_peer_application(p,id,0,DP_ACCOUNTING);	
+				break;
+			case AVP_Vendor_Specific_Application_Id:
+				group = AAAUngroupAVPS(avp->data);
+				avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
+				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
+				if (avp_vendor&&avp2){
+					vendor = get_4bytes(avp_vendor->data.s);
+					id = get_4bytes(avp2->data.s);
+					add_peer_application(p,id,vendor,DP_AUTHORIZATION);						
+				}
+				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
+				if (avp_vendor&&avp2){
+					vendor = get_4bytes(avp_vendor->data.s);
+					id = get_4bytes(avp2->data.s);
+					add_peer_application(p,id,vendor,DP_ACCOUNTING);					
+				}
+				AAAFreeAVPList(&group);
+				break;
+				
+		}
+	}	
+}
+
+/**
+ * Process a Capability Exchange Answer.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer that the CEA was received from
+ * @param cea - the CEA message
+ * @returns the result-code from CEA or AAA_UNABLE_TO_COMPLY if no result-code found
+ */	
+int Process_CEA(peer *p,AAAMessage *cea)
+{
+	AAA_AVP *avp;
+	avp = AAAFindMatchingAVP(cea,cea->avpList.head,AVP_Result_Code,0,0);
+	save_peer_applications(p,cea);
+	AAAFreeMessage(&cea);
+	if (!avp) return AAA_UNABLE_TO_COMPLY;
+	else return get_4bytes(avp->data.s);
+}	
+
+/**
+ * Initiator - disconnect peer.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer to disconnect
+ */
+void I_Disc(peer *p)
+{
+	if (p->I_sock>=0){
+		close(p->I_sock);
+		p->I_sock = -1;
+	}
+}
+
+/**
+ * Receiver - disconnect peer.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer to disconnect
+ */
+void R_Disc(peer *p)
+{
+	if (p->R_sock>=0){
+		close(p->R_sock);
+		p->R_sock = -1;
+	}
+}
+
+/**
+ * Process a Diameter Watch-dog Request.
+ * The last activity timer is updated in the sm_process(), on any message received.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer that the DWR was received from
+ * @param dwr - the DWR message
+ * @returns AAA_SUCCESS
+ */	
+int Process_DWR(peer *p,AAAMessage *dwr)
+{
+	return AAA_SUCCESS;
+}
+
+/**
+ * Process a Diameter Watch-dog Answer.
+ * The flag for waiting a DWA is reseted.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer that the DWR was received from
+ * @param dwa - the DWA message
+ */	
+void Process_DWA(peer *p,AAAMessage *dwa)
+{
+	p->waitingDWA = 0;
+	AAAFreeMessage(&dwa);
+}
+
+/**
+ * Sends a Diameter Watch-dog Request.
+ * The flag for waiting a DWA is set.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer that the DWR was received from
+ */	
+void Snd_DWR(peer *p)
+{
+	AAAMessage *dwr=0;
+	
+	dwr = AAANewMessage(Code_DW,0,0,0);
+	if (!dwr) return;	
+	dwr->hopbyhopId = next_hopbyhop();
+	dwr->endtoendId = next_endtoend();
+	if (p->state==I_Open)
+		peer_send_msg(p,dwr);	
+	else
+		peer_send_msg(p,dwr);	
+}
+
+/**
+ * Sends a Diameter Watch-dog Answer.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer that the DWR was received from
+ * @param dwr - the DWR message
+ * @param result_code - the Result-Code to attach to DWA
+ * @param sock - socket to send on
+ */	
+void Snd_DWA(peer *p,AAAMessage *dwr,int result_code,int sock)
+{
+	AAAMessage *dwa;
+	char x[4];	
+
+	dwa = AAANewMessage(Code_DW,0,0,dwr);
+	if (!dwa) goto done;	
+
+	set_4bytes(x,result_code);
+	AAACreateAndAddAVPToMessage(dwa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
+	
+	peer_send_msg(p,dwa);
+done:	
+	AAAFreeMessage(&dwr);
+}
+
+/**
+ * Sends a Disconnect Peer Request.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer to send to
+ */
+void Snd_DPR(peer *p)
+{
+	AAAMessage *dpr=0;
+	char x[4];
+	
+	dpr = AAANewMessage(Code_DP,0,0,0);	
+	if (!dpr) return;
+	dpr->hopbyhopId = next_hopbyhop();
+	dpr->endtoendId = next_endtoend();
+
+	set_4bytes(x,0/*busy*/);
+	AAACreateAndAddAVPToMessage(dpr,AVP_Disconnect_Cause,AAA_AVP_FLAG_MANDATORY,0,x,4);
+
+	if (p->state==I_Open)
+		peer_send_msg(p,dpr);	
+	else
+		peer_send_msg(p,dpr);	
+}
+
+/**
+ * Sends a Disconnect Peer Answer.
+ * \note Must be called with a lock on the peer.
+ * @param p - the peer to send to
+ * @param dpr - the DPR message
+ * @param result_code - the Result-Code to attach to DPA
+ * @param sock - socket to send on
+ */
+void Snd_DPA(peer *p,AAAMessage *dpr,int result_code,int sock)
+{
+	AAAMessage *dpa;
+
+	dpa = AAANewMessage(Code_DP,0,0,dpr);	
+	if (dpa) peer_send_msg(p,dpa);
+	AAAFreeMessage(&dpr);
+}
+
+/**
+ * Receiver - Accept a connection.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer identification
+ * @param sock - socket to communicate through
+ */
+void R_Accept(peer *p,int sock)
+{
+	p->R_sock = sock;
+	touch_peer(p);
+}
+
+/**
+ * Receiver - Reject a connection.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer identification
+ * @param sock - socket to communicate through
+ */
+void R_Reject(peer *p,int sock)
+{
+	close(sock);
+}
+
+/**
+ * Process a Capabilities Exchange Request.
+ * Checks whether there are common applications.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer identification
+ * @param cer - the CER message
+ * @returns the Result-Code of the operation, AAA_SUCCESS or AAA_NO_COMMON_APPLICATION
+ */
+int Process_CER(peer *p,AAAMessage *cer)
+{
+	int common_app=0;
+	AAA_AVP *avp,*avp_vendor,*avp2;
+	AAA_AVP_LIST group;
+	int i,id,vendor;
+	for(avp=cer->avpList.head;avp;avp = avp->next)
+	{
+		switch (avp->code){
+			case AVP_Auth_Application_Id:
+				id = get_4bytes(avp->data.s);	
+				for(i=0;i<config->applications_cnt;i++)
+					if (id == config->applications[i].id &&
+						config->applications[i].vendor==0 &&
+						config->applications[i].type==DP_AUTHORIZATION) common_app++;	
+				break;
+			case AVP_Acct_Application_Id:
+				id = get_4bytes(avp->data.s);	
+				for(i=0;i<config->applications_cnt;i++)
+					if (id == config->applications[i].id &&
+						config->applications[i].vendor==0 &&
+						config->applications[i].type==DP_ACCOUNTING) common_app++;	
+				break;
+			case AVP_Vendor_Specific_Application_Id:
+				group = AAAUngroupAVPS(avp->data);
+				avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
+				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
+				if (avp_vendor&&avp2){
+					vendor = get_4bytes(avp_vendor->data.s);
+					id = get_4bytes(avp2->data.s);
+					for(i=0;i<config->applications_cnt;i++)
+						if (id == config->applications[i].id &&
+							config->applications[i].vendor==vendor &&
+							config->applications[i].type==DP_AUTHORIZATION) common_app++;	
+					
+				}
+				avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
+				if (avp_vendor&&avp2){
+					vendor = get_4bytes(avp_vendor->data.s);
+					id = get_4bytes(avp2->data.s);
+					for(i=0;i<config->applications_cnt;i++)
+						if (id == config->applications[i].id &&
+							config->applications[i].vendor==vendor &&
+							config->applications[i].type==DP_ACCOUNTING) common_app++;	
+					
+				}
+				AAAFreeAVPList(&group);
+				break;
+				
+		}
+	}
+	
+	if (common_app!=0){
+		save_peer_applications(p,cer);
+		return AAA_SUCCESS;
+	}else 
+		return AAA_NO_COMMON_APPLICATION;	
+}
+
+/**
+ * Send a Capabilities Exchange Answer.
+ * Checks whether there are common applications.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer identification
+ * @param cer - the CER message
+ * @param result_code - the Result-Code to send
+ * @param sock - socket to send through
+ */
+void Snd_CEA(peer *p,AAAMessage *cer,int result_code,int sock)
+{
+	AAAMessage *cea;
+	unsigned int ip;
+	union {
+		struct sockaddr addr;
+		struct sockaddr_in in;
+		struct sockaddr_in6 in6;
+	} addr_u ;
+	socklen_t addrlen;
+	char x[18];
+	
+	cea = AAANewMessage(Code_CE,0,0,cer);	
+	if (!cea) goto done;
+	
+	addrlen = sizeof(addr_u);
+	if (getsockname(sock, &(addr_u.addr), &addrlen) == -1) { 
+		LM_ERR("Snd_CEA(): Error on finding local host address > %s\n",strerror(errno));
+	}else{
+		switch(addr_u.addr.sa_family){
+			case AF_INET:
+				set_2bytes(x,1);
+				ip = htonl(addr_u.in.sin_addr.s_addr);
+				set_4bytes(x+2,ip);
+				AAACreateAndAddAVPToMessage(cea,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,6);
+				break;
+			case AF_INET6:
+				set_2bytes(x,2);
+				memcpy(x+2,addr_u.in6.sin6_addr.s6_addr,16);
+				AAACreateAndAddAVPToMessage(cea,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,18);
+				break;
+			default:
+				LM_ERR("Snd_CEA(): unknown address type with family %d\n",addr_u.addr.sa_family);
+		}
+	}
+
+	set_4bytes(x,config->vendor_id);
+	AAACreateAndAddAVPToMessage(cea,AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4);
+			
+	AAACreateAndAddAVPToMessage(cea,AVP_Product_Name,AAA_AVP_FLAG_MANDATORY,0,config->product_name.s,config->product_name.len);
+
+	set_4bytes(x,result_code);
+	AAACreateAndAddAVPToMessage(cea,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
+
+	Snd_CE_add_applications(cea,p);
+
+	peer_send(p,sock,cea,1);
+done:	
+	AAAFreeMessage(&cer);
+}
+
+/**
+ * Perform the Election mechanism.
+ * When 2 peers connect to each-other at the same moment, an election is triggered.
+ * That means that based on the alphabetical relation between the FQDNs, one peer is
+ * kept as winner on Initiator and that connection is kept, while the other keeps the same
+ * connection as Receiver and drops its Initiator connection.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer identification
+ * @param cer - the CER message
+ * @returns 1 if winning, 0 if loosing
+ */  
+int Elect(peer *p,AAAMessage *cer)
+{
+	/* returns if we win the election */
+	AAA_AVP *avp;
+	str remote,local;
+	int i,d;
+
+	if(!cer){
+		LM_ERR("Elect cer is NULL \n");
+		// return lose
+		return 0;
+	}
+	
+	local = config->fqdn;
+
+	avp = AAAFindMatchingAVP(cer,cer->avpList.head,AVP_Origin_Host,0,0);
+	if (!avp) {
+		return 1;
+	}else{
+		remote = avp->data;
+		for(i=0;i<remote.len&&i<local.len;i++){
+			d = ((unsigned char) local.s[i])-((unsigned char) remote.s[i]);
+			if (d>0) return 1;
+			if (d<0) return 0;
+		}
+		if (local.len>remote.len) return 1;
+		return 0;
+	}
+}
+
+/**
+ * Sends a message to the peer.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer to send to
+ * @param msg - message to send
+ */
+void Snd_Message(peer *p, AAAMessage *msg)
+{
+	AAASession *session=0;
+	int rcode;
+	int send_message_before_session_sm=0;
+	LM_DBG("Snd_Message called to peer [%.*s] for %s with code %d \n",
+		p->fqdn.len,p->fqdn.s,is_req(msg)?"request":"response",msg->commandCode);
+	touch_peer(p);
+	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);
+	
+	if (session){
+		LM_DBG("There is a session of type %d\n",session->type);
+		switch (session->type){
+			case AUTH_CLIENT_STATEFULL:
+				if (is_req(msg)) {
+					auth_client_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
+					session = 0;
+				}
+				else {
+					if (msg->commandCode == IMS_ASA){
+						if (!msg->res_code){
+							msg->res_code = AAAFindMatchingAVP(msg,0,AVP_Result_Code,0,0);
+						}
+						if (!msg->res_code) {
+							auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
+							session = 0;
+						}
+						else {
+							rcode = get_4bytes(msg->res_code->data.s);
+							if (rcode>=2000 && rcode<3000) {
+								peer_send_msg(p,msg);
+								send_message_before_session_sm=1;
+								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_SUCCESS,msg);
+								session = 0;
+							}
+							else {
+								auth_client_statefull_sm_process(session,AUTH_EV_SEND_ASA_UNSUCCESS,msg);
+								session = 0;
+							}
+						}
+						
+					}else {
+						auth_client_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
+						session = 0;
+					}
+				}
+				break;
+			case AUTH_SERVER_STATEFULL:
+				LM_DBG("this message is matched here to see what request or reply it is\n");
+				if (is_req(msg))
+				{
+					if (msg->commandCode== IMS_ASR)
+					{
+						LM_DBG("ASR\n");
+						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ASR,msg);
+						session = 0;
+					} else {
+						//would be a RAR but ok!
+						LM_DBG("other request\n");
+						auth_server_statefull_sm_process(session,AUTH_EV_SEND_REQ,msg);
+						session = 0;
+					}
+				} else {
+					if (msg->commandCode == IMS_STR)
+					{
+						LM_DBG("STA\n");
+						auth_server_statefull_sm_process(session,AUTH_EV_SEND_STA,msg);
+						session = 0;
+					} else {
+						LM_DBG("other reply\n");
+						auth_server_statefull_sm_process(session,AUTH_EV_SEND_ANS,msg);
+						session = 0;
+					}
+				}
+				break;				 
+			default:
+				break;
+		}
+		if (session) AAASessionsUnlock(session->hash);
+	}
+	if (!send_message_before_session_sm) peer_send_msg(p,msg);
+	
+}
+
+/**
+ * Processes an incoming message.
+ * This actually just puts the message into a message queue. One worker will pick-it-up
+ * and do the actual processing.
+ * \note Must be called with a lock on the peer.
+ * @param p - peer received from
+ * @param msg - the message received
+ */ 
+void Rcv_Process(peer *p, AAAMessage *msg)
+{
+	AAASession *session=0;
+	int nput=0;
+	if (msg->sessionId) session = cdp_get_session(msg->sessionId->data);
+
+	if (session){
+		switch (session->type){
+			case AUTH_CLIENT_STATEFULL:
+				if (is_req(msg)){
+					if (msg->commandCode==IMS_ASR)
+						auth_client_statefull_sm_process(session,AUTH_EV_RECV_ASR,msg);
+					else 
+						auth_client_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg);
+					session = 0;
+				}else {
+					if (msg->commandCode==IMS_STA)
+						nput=auth_client_statefull_sm_process(session,AUTH_EV_RECV_STA,msg);
+					else
+						auth_client_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg);
+					session = 0;
+				}
+				break;
+			 case AUTH_SERVER_STATEFULL:
+			 	if (is_req(msg))
+			 	{
+			 		if (msg->commandCode==IMS_STR)
+			 		{
+			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_STR,msg);
+			 		} else {
+			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_REQ,msg);
+			 		}
+					session = 0;			 		
+			 	}else{
+			 		if (msg->commandCode==IMS_ASA)
+			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_ASA,msg);
+			 		else
+			 			auth_server_statefull_sm_process(session,AUTH_EV_RECV_ANS,msg);
+					session = 0;			 		
+			 	}
+			 	break;
+			default:
+				AAASessionsUnlock(session->hash);
+				session =0;
+				break;			 
+		}
+	}else{
+		if (msg->sessionId){
+			if (msg->commandCode == IMS_ASR) 
+				auth_client_statefull_sm_process(0,AUTH_EV_RECV_ASR,msg);
+		} 
+				 
+	}
+	if (!nput && !put_task(p,msg)){
+		LM_ERR("Rcv_Process(): Queue refused task\n");
+		if (msg) AAAFreeMessage(&msg); 
+	}
+	//if (msg) LM_ERR("Rcv_Process(): task added to queue command %d, flags %#1x endtoend %u hopbyhop %u\n",msg->commandCode,msg->flags,msg->endtoendId,msg->hopbyhopId);
+	
+//	AAAPrintMessage(msg);
+	
+}
+
+

+ 72 - 0
modules/cdp/peerstatemachine.h

@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __STATEMACHINE_H
+#define __STATEMACHINE_H
+
+#include "utils.h"
+#include "peer.h"
+#include "diameter.h"
+
+int sm_process(peer *p,peer_event_t event,AAAMessage *msg,int peer_locked,int sock);
+
+peer_state_t I_Snd_Conn_Req(peer *p);
+void Cleanup(peer *p,int sock);
+void Error(peer *p, int sock);
+void I_Snd_CER(peer *p);
+int Process_CEA(peer *p,AAAMessage *cea);
+void I_Disc(peer *p);
+void R_Disc(peer *p);
+int Process_DWR(peer *p,AAAMessage *dwr);
+void Process_DWA(peer *p,AAAMessage *dwa);
+void Snd_DWR(peer *p);
+void Snd_DWA(peer *p,AAAMessage *dwr,int result_code,int sock);
+void Snd_DPR(peer *p);
+void Snd_DPA(peer *p,AAAMessage *dpr,int result_code,int sock);
+void R_Accept(peer *p,int sock);
+void R_Reject(peer *p,int sock);
+int Process_CER(peer *p,AAAMessage *cer);
+void Snd_CEA(peer *p,AAAMessage *cer,int result_code,int sock);
+int Elect(peer *p,AAAMessage *cer);
+
+void Snd_Message(peer *p, AAAMessage *msg);
+void Rcv_Process(peer *p, AAAMessage *msg);
+
+#endif

+ 1148 - 0
modules/cdp/receiver.c

@@ -0,0 +1,1148 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "utils.h"
+#include "globals.h"
+#include "diameter_api.h"
+#include "peerstatemachine.h"
+#include "peermanager.h"
+#include "config.h"
+
+#include "receiver.h"
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+
+int dp_add_pid(pid_t pid);
+void dp_del_pid(pid_t pid);
+
+int receive_loop(peer *original_peer);
+
+void receive_message(AAAMessage *msg,serviced_peer_t *sp);
+
+
+/** prefix for the send FIFO pipes */
+#define PIPE_PREFIX "/tmp/cdp_send_"
+
+int local_id=0;						/**< incrementing process local variable, to distinguish between different peer send pies */
+
+
+int fd_exchange_pipe_unknown_local;		/**< pipe to pass file descriptors towards the receiver process for unknown peers - local end to read from*/
+int fd_exchange_pipe_unknown;		/**< pipe to pass file descriptors towards the receiver process for unknown peers */
+
+serviced_peer_t *serviced_peers=0; 	/**< pointer to the list of peers serviced by this process */
+
+
+/**
+ * Print debug information about this receiver process
+ * @param level
+ */
+static void log_serviced_peers(int level)
+{
+	serviced_peer_t *sp;
+#ifdef SER_MOD_INTERFACE
+	if (!is_printable(level))
+#else		
+	if (debug<level)
+#endif
+		return;
+	
+	LOG(level,"--- Receiver ["ANSI_BLUE"%s"ANSI_GREEN"] Serviced Peers: ---\n", 
+			pt[process_no].desc
+			);
+	for(sp=serviced_peers;sp;sp=sp->next){
+		LOG(level,ANSI_GREEN" Peer: ["ANSI_YELLOW"%.*s"ANSI_GREEN"]  TCP Socket: ["ANSI_YELLOW"%d"ANSI_GREEN"] Recv.State: ["ANSI_YELLOW"%d"ANSI_GREEN"]\n",
+				sp->p?sp->p->fqdn.len:0,
+				sp->p?sp->p->fqdn.s:0,
+				sp->tcp_socket,
+				sp->state);
+	}
+	LOG(level,"--------------------------------------------------------\n");	
+}
+
+
+
+/**
+ * Makes a send pipe for signaling messages to send-out and attaches it to where necessary.
+ * @params sp - the serviced peer to open it for
+ * @return 1 on success or 0 on failure
+ */
+static int make_send_pipe(serviced_peer_t *sp)
+{		
+	local_id++;
+	sp->send_pipe_name.s = shm_malloc(sizeof(PIPE_PREFIX)+64);
+	sprintf(sp->send_pipe_name.s,"%s%d_%d_%d",PIPE_PREFIX,getpid(),local_id,(unsigned int) time(0));
+	sp->send_pipe_name.len = strlen(sp->send_pipe_name.s);
+		
+	if (mkfifo(sp->send_pipe_name.s, 0666)<0){
+		LM_ERR("make_send_pipe(): FIFO make failed > %s\n",strerror(errno));
+		return 0;
+	}
+	sp->send_pipe_fd = open(sp->send_pipe_name.s, O_RDONLY | O_NDELAY);
+	if (sp->send_pipe_fd<0){
+		LM_ERR("receiver_init(): FIFO open for read failed > %s\n",strerror(errno));
+		return 0;
+	}
+	// we open it for writing just to keep it alive - won't close when all other writers close it
+	sp->send_pipe_fd_out = open(sp->send_pipe_name.s, O_WRONLY);
+	if (sp->send_pipe_fd_out<0){
+		LM_ERR("receiver_init(): FIFO open for write (keep-alive) failed > %s\n",strerror(errno));
+		return 0;
+	}
+	
+	if (sp->p) 
+		sp->p->send_pipe_name=sp->send_pipe_name;
+	
+	return 1;	
+}
+
+/**
+ * Close a send pipe for signaling messages to send-out
+ * @param sp - the serviced peer to close it for
+ */
+static void close_send_pipe(serviced_peer_t *sp)
+{
+	if (sp->send_pipe_name.s) {
+		close(sp->send_pipe_fd);
+		close(sp->send_pipe_fd_out);
+		remove(sp->send_pipe_name.s);
+		shm_free(sp->send_pipe_name.s);
+		sp->send_pipe_name.s=0;
+		sp->send_pipe_name.len=0;
+		sp->send_pipe_fd = -1;
+		sp->send_pipe_fd_out = -1;
+	}	
+}
+
+
+/**
+ * Adds a peer in the list of serviced peers by this receiver process.
+ * \note This should only be called from the receiver process!!!
+ * @param p - the peer to add
+ * @returns 1 on success or 0 on error
+ */
+static serviced_peer_t* add_serviced_peer(peer *p)
+{
+	serviced_peer_t *sp;
+	LM_INFO("add_serviced_peer(): Adding serviced_peer_t to receiver for peer [%.*s]\n",
+			p?p->fqdn.len:0,
+			p?p->fqdn.s:0);
+	sp = pkg_malloc(sizeof(serviced_peer_t));
+	if (!sp){
+		LM_INFO("add_serviced_peer(): error allocating pkg mem\n");
+		return 0;
+	}
+	memset(sp,0,sizeof(serviced_peer_t));
+
+	sp->p = p;	
+	sp->tcp_socket = -1;
+	sp->prev = 0;
+	if (serviced_peers) {
+		serviced_peers->prev = sp;
+		sp->next = serviced_peers;
+	}
+	serviced_peers = sp;
+	
+	if (!make_send_pipe(sp)){
+		pkg_free(sp);
+		return 0;
+	}
+	
+	return sp;
+}
+
+/**
+ * Disconnects a serviced peer, but does not delete it from this receiver's list.
+ * Used from dedicated receivers, when the peers should be kept associated even if disconnected.
+ * @param sp - the serviced peer to operate on
+ * @param locked - if the sp->p has been previously locked
+ */
+static void disconnect_serviced_peer(serviced_peer_t *sp,int locked)
+{
+	if (!sp) return;
+	LM_INFO("drop_serviced_peer(): [%.*s] Disconnecting from peer \n",
+			sp->p?sp->p->fqdn.len:0,
+			sp->p?sp->p->fqdn.s:0);
+	if (sp->p){
+		if (!locked) lock_get(sp->p->lock);
+			if (sp->p->I_sock == sp->tcp_socket) sm_process(sp->p,I_Peer_Disc,0,1,sp->tcp_socket);
+			if (sp->p->R_sock == sp->tcp_socket) sm_process(sp->p,R_Peer_Disc,0,1,sp->tcp_socket);
+			sp->p->send_pipe_name.s = 0;
+			sp->p->send_pipe_name.len = 0;
+		if (!locked) lock_release(sp->p->lock);		
+	}
+	sp->tcp_socket = -1;
+	close_send_pipe(sp);
+}
+
+/**
+ * Drops a peer from the list of serviced peers by this receiver process
+ * \note This does not actually disconnect, but should be used for hand-overs of peers from one receiver to other
+ * \note This should only be called from the receiver process!!!
+ * @param p - the peer to drop
+ */
+static void drop_serviced_peer(serviced_peer_t *sp,int locked)
+{
+	if (!sp) return;
+	LM_INFO("drop_serviced_peer(): Dropping serviced_peer_t from receiver for peer [%.*s]\n",
+			sp->p?sp->p->fqdn.len:0,
+			sp->p?sp->p->fqdn.s:0);
+
+	sp->p=0;
+	close_send_pipe(sp);
+
+	if (sp->next) sp->next->prev = sp->prev;
+	if (sp->prev) sp->prev->next = sp->next;
+	else serviced_peers = sp->next;
+	if (sp->msg) shm_free(sp->msg);
+	sp->msg = 0;
+	pkg_free(sp);
+}
+
+
+/**
+ * Sends a file descriptor to another process through a pipe, together with a pointer to the peer that it is
+ * associated with.
+ * @param pipe_fd - pipe to send through
+ * @param fd - descriptor to send
+ * @param p - peer associated with the descriptor or null if unknown peer
+ * @returns 1 on success, 0 on failure
+ */
+static int send_fd(int pipe_fd,int fd, peer *p)
+{
+	struct msghdr msg;
+	struct iovec iov[1];
+	int ret;
+	
+#ifdef HAVE_MSGHDR_MSG_CONTROL
+	struct cmsghdr* cmsg;
+	/* make sure msg_control will point to properly aligned data */
+	union {
+		struct cmsghdr cm;
+		char control[CMSG_SPACE(sizeof(fd))];
+	}control_un;
+	
+	msg.msg_control=control_un.control;
+	/* openbsd doesn't like "more space", msg_controllen must not
+	 * include the end padding */
+	msg.msg_controllen=CMSG_LEN(sizeof(fd));
+	
+	cmsg=CMSG_FIRSTHDR(&msg);
+	cmsg->cmsg_level = SOL_SOCKET;
+	cmsg->cmsg_type = SCM_RIGHTS;
+	cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+	*(int*)CMSG_DATA(cmsg)=fd;
+	msg.msg_flags=0;
+#else
+	msg.msg_accrights=(caddr_t) &fd;
+	msg.msg_accrightslen=sizeof(fd);
+#endif
+	
+	msg.msg_name=0;
+	msg.msg_namelen=0;
+	
+	iov[0].iov_base=&p;
+	iov[0].iov_len=sizeof(peer*);
+	msg.msg_iov=iov;
+	msg.msg_iovlen=1;
+	
+again:
+	ret=sendmsg(pipe_fd, &msg, 0);
+	if (ret<0){
+		if (errno==EINTR) goto again;
+		if ((errno!=EAGAIN) && (errno!=EWOULDBLOCK)){
+			LM_CRIT( "send_fd: sendmsg failed on %d: %s\n",
+					pipe_fd, strerror(errno));
+			return 0;
+		}
+	}
+	
+	return 1;
+}
+
+
+
+/**
+ * Receive a file descriptor from another process
+ * @param pipe_fd - pipe to read from
+ * @param fd - file descriptor to fill
+ * @param p - optional pipe to fill
+ * @returns 1 on success or 0 on failure
+ */
+static int receive_fd(int pipe_fd, int* fd,peer **p)
+{
+	struct msghdr msg;
+	struct iovec iov[1];
+	int new_fd;
+	int ret;
+	
+#ifdef HAVE_MSGHDR_MSG_CONTROL
+	struct cmsghdr* cmsg;
+	union{
+		struct cmsghdr cm;
+		char control[CMSG_SPACE(sizeof(new_fd))];
+	}control_un;
+	
+	msg.msg_control=control_un.control;
+	msg.msg_controllen=sizeof(control_un.control);
+#else
+	msg.msg_accrights=(caddr_t) &new_fd;
+	msg.msg_accrightslen=sizeof(int);
+#endif
+	
+	msg.msg_name=0;
+	msg.msg_namelen=0;
+	
+	iov[0].iov_base=p;
+	iov[0].iov_len=sizeof(peer*);
+	msg.msg_iov=iov;
+	msg.msg_iovlen=1;
+	
+again:
+	ret=recvmsg(pipe_fd, &msg, MSG_DONTWAIT|MSG_WAITALL);
+	if (ret<0){
+		if (errno==EINTR) goto again;
+		if ((errno==EAGAIN)||(errno==EWOULDBLOCK)) goto error;
+		LM_CRIT( "receive_fd: recvmsg on %d failed: %s\n",
+				pipe_fd, strerror(errno));
+		goto error;
+	}
+	if (ret==0){
+		/* EOF */
+		LM_CRIT( "receive_fd: EOF on %d\n", pipe_fd);
+		goto error;
+	}
+	if (ret!=sizeof(peer *)){
+		LM_WARN("receive_fd: different number of bytes received than expected (%d from %ld)"
+				    "trying to fix...\n", ret, (long int)sizeof(peer*));
+		goto error;
+	}
+	
+#ifdef HAVE_MSGHDR_MSG_CONTROL
+	cmsg=CMSG_FIRSTHDR(&msg);
+	if ((cmsg!=0) && (cmsg->cmsg_len==CMSG_LEN(sizeof(new_fd)))){
+		if (cmsg->cmsg_type!= SCM_RIGHTS){
+			LM_ERR("receive_fd: msg control type != SCM_RIGHTS\n");
+			goto error;
+		}
+		if (cmsg->cmsg_level!= SOL_SOCKET){
+			LM_ERR("receive_fd: msg level != SOL_SOCKET\n");
+			goto error;
+		}
+		*fd=*((int*) CMSG_DATA(cmsg));
+	}else{
+		if(!cmsg)
+			LM_ERR("receive_fd: no descriptor passed, empty control message");
+		else
+			LM_ERR("receive_fd: no descriptor passed, cmsg=%p,"
+				"len=%d\n", cmsg, (unsigned)cmsg->cmsg_len); 
+		*fd=-1;
+		*p=0;
+		/* it's not really an error */
+	}
+#else
+	if (msg.msg_accrightslen==sizeof(int)){
+		*fd=new_fd;
+	}else{
+		LM_ERR("receive_fd: no descriptor passed,"
+				" accrightslen=%d\n", msg.msg_accrightslen); 
+		*fd=-1;
+	}
+#endif
+	
+	return 1;
+error:
+	return 0;
+}
+
+/**
+ * Initializes the receiver.
+ * @param p - the peer to initialize with, or NULL if to initialize as the receiver for unknown peers
+ * @return 1 on success or 0 on failure
+ */
+int receiver_init(peer *p)
+{
+	int fd_exchange_pipe[2];/**< pipe to pass file descriptors towards this process */
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd_exchange_pipe)<0){
+		 LM_ERR("receiver_init(): socketpair(fd_exchanged_pipe) failed > %s\n",strerror(errno));
+		return 0;
+	}
+	if (p) {
+		p->fd_exchange_pipe_local = fd_exchange_pipe[0];
+		p->fd_exchange_pipe = fd_exchange_pipe[1];
+	}
+	else {
+		fd_exchange_pipe_unknown_local = fd_exchange_pipe[0];
+		fd_exchange_pipe_unknown = fd_exchange_pipe[1];
+	}
+	
+	return 1;
+}
+
+/**
+ * The Receiver Process - calls the receiv_loop and it never returns.
+ * @param p - the peer it is associated with or NULL for the unknown peers receiver
+ * @returns never, when disconnected it will exit
+ */
+void receiver_process(peer *p)
+{
+	LM_INFO("receiver_process(): [%.*s] Receiver process doing init on new process...\n",
+			p?p->fqdn.len:0,p?p->fqdn.s:0);
+	if (p)	
+		if (!add_serviced_peer(p)) goto done;
+	
+	LM_INFO("receiver_process(): [%.*s] Receiver process starting up...\n",
+			p?p->fqdn.len:0,p?p->fqdn.s:0);
+
+	log_serviced_peers(L_INFO);		
+
+	if (receive_loop(p)<0){
+		LM_INFO("receiver_process(): [%.*s] receive_loop() return -1 (error)!\n",
+						p?p->fqdn.len:0,p?p->fqdn.s:0);
+				
+	}
+
+done:	
+	if (!*shutdownx){
+		LM_INFO("receiver_process(): [%.*s]... Receiver process cleaning-up - should not happen unless shuting down!\n",
+				p?p->fqdn.len:0,p?p->fqdn.s:0);
+		
+	}
+	LM_INFO("receiver_process(): [%.*s]... Receiver process cleaning-up.\n",
+			p?p->fqdn.len:0,p?p->fqdn.s:0);
+
+	while(serviced_peers){
+		disconnect_serviced_peer(serviced_peers,0);
+		drop_serviced_peer(serviced_peers,0);
+	}
+	/* remove pid from list of running processes */
+	dp_del_pid(getpid());
+	
+#ifdef CDP_FOR_SER
+			
+#else
+#ifdef PKG_MALLOC
+	#ifdef PKG_MALLOC
+		LM_DBG("Receiver[%.*s] Memory status (pkg):\n",
+				p?p->fqdn.len:0,p?p->fqdn.s:0);
+		//pkg_status();
+		#ifdef pkg_sums
+			pkg_sums();
+		#endif 
+	#endif
+#endif
+#endif		
+		
+	LM_INFO("receiver_process(): [%.*s]... Receiver process finished.\n",
+			p?p->fqdn.len:0,p?p->fqdn.s:0);
+	exit(0);
+}
+
+/**
+ * Does the actual receive operations on the Diameter TCP socket, for retrieving incoming messages.
+ * The functions is to be called iteratively, each time there is something to be read from the TCP socket. It uses
+ * a simple state machine to read first the version, then the header and then the rest of the message. When an
+ * entire message is received, it is decoded and passed to the processing functions.
+ * @param sp - the serviced peer to operate on
+ * @return 1 on success, 0 on failure
+ */
+static inline int do_receive(serviced_peer_t *sp)
+{
+	int cnt,n,version;
+	char *dst;
+	AAAMessage *dmsg;
+	
+	switch (sp->state){
+		case Receiver_Waiting:
+			n = 1; /* wait for version */
+			dst = sp->buf;
+			break;
+			
+		case Receiver_Header: 
+			n = DIAMETER_HEADER_LEN - sp->buf_len; /* waiting for rest of header */
+			dst = sp->buf+sp->buf_len;
+			break;
+			
+		case Receiver_Rest_of_Message:
+			n = sp->length - sp->msg_len;	/* waiting for the rest of the message */
+			dst = sp->msg+sp->msg_len;
+			break;
+			
+		default:
+			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
+					sp->p?sp->p->fqdn.len:0,
+					sp->p?sp->p->fqdn.s:0,
+					sp->state);			
+			goto error_and_reset;
+	}
+	
+	cnt = recv(sp->tcp_socket,dst,n,0);
+	
+	if (cnt<=0)	
+		goto error_and_reset;
+	
+	switch (sp->state){
+		case Receiver_Waiting:			
+			version = (unsigned char)(sp->buf[0]);
+			if (version!=1) {
+		  		LM_ERR("do_receive(): [%.*s] Received Unknown version [%d]\n",
+		  				sp->p->fqdn.len,
+		  				sp->p->fqdn.s,
+		  				(unsigned char)sp->buf[0]);
+				goto error_and_reset;
+			}else{
+				sp->state = Receiver_Header;
+				sp->buf_len = 1;
+			}
+			break;
+			
+		case Receiver_Header:
+			sp->buf_len+=cnt;			
+			if (sp->buf_len==DIAMETER_HEADER_LEN){
+				sp->length = get_3bytes(sp->buf+1);
+				if (sp->length>DP_MAX_MSG_LENGTH){
+					LM_ERR("do_receive(): [%.*s] Msg too big [%d] bytes\n",
+							sp->p?sp->p->fqdn.len:0,
+							sp->p?sp->p->fqdn.s:0,
+							sp->length);
+					goto error_and_reset;
+				}
+				LM_DBG("receive_loop(): [%.*s] Recv Version %d Length %d\n",
+						sp->p?sp->p->fqdn.len:0,
+						sp->p?sp->p->fqdn.s:0,
+						(unsigned char)(sp->buf[0]),
+						sp->length);
+				sp->msg = shm_malloc(sp->length);
+				if (!sp->msg) {
+					LOG_NO_MEM("shm",sp->length);
+					goto error_and_reset;
+				}
+				
+				memcpy(sp->msg,sp->buf,sp->buf_len);
+				sp->msg_len=sp->buf_len;
+				sp->state = Receiver_Rest_of_Message;
+			}
+			break;
+			
+		case Receiver_Rest_of_Message:
+			sp->msg_len+=cnt;
+			if (sp->msg_len==sp->length){
+		    	dmsg = AAATranslateMessage((unsigned char*)sp->msg,(unsigned int)sp->msg_len,1);		    	
+				if (dmsg) {
+					sp->msg = 0;
+					receive_message(dmsg,sp);
+				}
+				else {
+					shm_free(sp->msg);
+					sp->msg = 0;
+				}
+				sp->msg_len = 0;
+				sp->buf_len = 0;
+				sp->state = Receiver_Waiting;
+			}
+			break;
+			
+		default:
+			LM_ERR("do_receive(): [%.*s] Unknown state %d\n",
+					sp->p?sp->p->fqdn.len:0,
+					sp->p?sp->p->fqdn.s:0,
+					sp->state);			
+			goto error_and_reset;
+	}
+	return 1;
+error_and_reset:
+	if (sp->msg){
+		shm_free(sp->msg);
+		sp->msg = 0;
+		sp->msg_len = 0;
+		sp->buf_len = 0;
+		sp->state = Receiver_Waiting;
+	}
+	return 0;
+}
+
+/**
+ * Selects once on sockets for receiving and sending stuff.
+ * Monitors:
+ *  - the fd exchange pipe, for receiving descriptors to be handled here
+ *  - the tcp sockets of all serviced peers, triggering the incoming messages do_receive()
+ *  - the send pipes of all serviced peers, triggering the sending of outgoing messages
+ * @returns 0 on normal exit or -1 on error
+ */ 
+int receive_loop(peer *original_peer)
+{
+	fd_set rfds,efds;
+	struct timeval tv;
+	int n,max=0,cnt=0;
+	AAAMessage *msg=0;
+	serviced_peer_t *sp,*sp2;
+	peer *p;
+	int fd=-1;
+	int fd_exchange_pipe_local=0;
+
+	if (original_peer) fd_exchange_pipe_local = original_peer->fd_exchange_pipe_local;
+	else fd_exchange_pipe_local = fd_exchange_pipe_unknown_local;
+
+//	if (shutdownx) return -1;	
+	
+	while(shutdownx&&!*shutdownx){
+		n = 0;
+	
+		while(!n){
+			if (shutdownx&&*shutdownx) break;	
+	
+			log_serviced_peers(L_DBG);
+	
+			max =-1;
+	
+			FD_ZERO(&rfds);
+			FD_ZERO(&efds);
+			
+			FD_SET(fd_exchange_pipe_local,&rfds);
+			if (fd_exchange_pipe_local>max) max = fd_exchange_pipe_local;
+			
+			for(sp=serviced_peers;sp;sp=sp->next){
+				if (sp->tcp_socket>=0){
+					FD_SET(sp->tcp_socket,&rfds);
+					FD_SET(sp->tcp_socket,&efds);
+					if (sp->tcp_socket>max) max = sp->tcp_socket;
+				}
+				if (sp->send_pipe_fd>=0) {
+					FD_SET(sp->send_pipe_fd,&rfds);
+					if (sp->send_pipe_fd>max) max = sp->send_pipe_fd;
+				}			
+			}
+			
+			tv.tv_sec=1;
+			tv.tv_usec=0;
+	
+			n = select(max+1,&rfds,0,&efds,&tv);
+			if (n==-1){
+				if (shutdownx&&*shutdownx) return 0;
+				LM_ERR("select_recv(): %s\n",strerror(errno));
+				for(sp=serviced_peers;sp;sp=sp2){
+					sp2 = sp->next;
+					disconnect_serviced_peer(sp,0);
+					if (sp->p && sp->p->is_dynamic)
+						drop_serviced_peer(sp,0);
+				}
+				sleep(1);
+				break;
+			}else
+				if (n){
+					
+					if (FD_ISSET(fd_exchange_pipe_local,&rfds)){
+						/* fd exchange */
+						LM_DBG("select_recv(): There is something on the fd exchange pipe\n");
+						p = 0;
+						fd = -1;
+						if (!receive_fd(fd_exchange_pipe_local,&fd,&p)){
+							LM_ERR("select_recv(): Error reading from fd exchange pipe\n");
+						}else{	
+							LM_DBG("select_recv(): fd exchange pipe says fd [%d] for peer %p:[%.*s]\n",fd,
+									p,
+									p?p->fqdn.len:0,
+									p?p->fqdn.s:0);
+							if (p){
+								sp2=0;
+								for(sp=serviced_peers;sp;sp=sp->next)
+									if (sp->p==p){
+										sp2 = sp;
+										break;
+									}
+								if (!sp2)
+									sp2 = add_serviced_peer(p);
+								else
+									make_send_pipe(sp2);
+								if (!sp2) {
+									LM_ERR("Error on add_serviced_peer()\n");
+									continue;
+								}
+								
+								sp2->tcp_socket = fd;
+								if (p->state == Wait_Conn_Ack){
+									p->I_sock = fd;
+									sm_process(p,I_Rcv_Conn_Ack,0,0,fd);
+								}else{
+									p->R_sock = fd;								
+								}
+							}else{
+								sp2 = add_serviced_peer(NULL);
+								if (!sp2) {
+									LM_ERR("Error on add_serviced_peer()\n");
+									continue;
+								}
+								sp2->tcp_socket = fd;
+							}
+						}
+					}
+										
+					for(sp=serviced_peers;sp;){
+						if (sp->tcp_socket>=0 && FD_ISSET(sp->tcp_socket,&efds)) {
+							LM_INFO("select_recv(): [%.*s] Peer socket [%d] found on the exception list... dropping\n",
+									sp->p?sp->p->fqdn.len:0,
+									sp->p?sp->p->fqdn.s:0,
+									sp->tcp_socket);
+							goto drop_peer;
+						}
+						if (sp->send_pipe_fd>=0 && FD_ISSET(sp->send_pipe_fd,&rfds)) {					
+							/* send */
+							LM_DBG("select_recv(): There is something on the send pipe\n");
+							cnt = read(sp->send_pipe_fd,&msg,sizeof(AAAMessage *));
+							if (cnt==0){
+								//This is very stupid and might not work well - droped messages... to be fixed
+								LM_INFO("select_recv(): ReOpening pipe for read. This should not happen...\n");
+								close(sp->send_pipe_fd);
+								sp->send_pipe_fd = open(sp->send_pipe_name.s, O_RDONLY | O_NDELAY);
+								goto receive;
+							}
+							if (cnt<sizeof(AAAMessage *)){
+								if (cnt<0) LM_ERR("select_recv(): Error reading from send pipe\n");
+								goto receive;
+							}	
+							LM_DBG("select_recv(): Send pipe says [%p] %d\n",msg,cnt);
+							if (sp->tcp_socket<0){
+								LM_ERR("select_recv(): got a signal to send something, but the connection was not opened");
+							} else {
+								while( (cnt=write(sp->tcp_socket,msg->buf.s,msg->buf.len))==-1 ) {
+									if (errno==EINTR)
+										continue;
+									LM_ERR("select_recv(): [%.*s] write on socket [%d] returned error> %s... dropping\n",
+											sp->p?sp->p->fqdn.len:0,
+											sp->p?sp->p->fqdn.s:0,
+											sp->tcp_socket,
+											strerror(errno));
+									AAAFreeMessage(&msg);
+									close(sp->tcp_socket);
+									goto drop_peer;								
+								}
+														
+								if (cnt!=msg->buf.len){
+									LM_ERR("select_recv(): [%.*s] write on socket [%d] only wrote %d/%d bytes... dropping\n",
+											sp->p?sp->p->fqdn.len:0,
+											sp->p?sp->p->fqdn.s:0,
+											sp->tcp_socket,
+											cnt,
+											msg->buf.len);							
+									AAAFreeMessage(&msg);
+									close(sp->tcp_socket);								
+									goto drop_peer;			
+								}
+							}
+							AAAFreeMessage(&msg);
+							//don't return, maybe there is something to read
+						}
+	receive:
+						/* receive */
+						if (sp->tcp_socket>=0 && FD_ISSET(sp->tcp_socket,&rfds)) {
+							errno=0;
+							cnt = do_receive(sp);
+							if (cnt<=0) {
+								LM_INFO("select_recv(): [%.*s] read on socket [%d] returned %d > %s... dropping\n",
+										sp->p?sp->p->fqdn.len:0,
+										sp->p?sp->p->fqdn.s:0,
+										sp->tcp_socket,
+										cnt,
+										errno?strerror(errno):"");							
+								goto drop_peer;
+							}						
+						}
+						
+	//next_sp:			
+						/* go to next serviced peer */
+						sp=sp->next;
+						continue;
+	drop_peer:
+						/* drop this serviced peer on error */
+						sp2 = sp->next;
+						disconnect_serviced_peer(sp,0);
+						if (sp->p && sp->p->is_dynamic)
+							drop_serviced_peer(sp,0);
+						sp = sp2;					 				
+					}
+				}
+		}
+	}
+	return 0;
+}
+
+
+
+/**
+ * Initiate a connection to a peer.
+ * The obtained socket is then sent to the respective receiver.
+ * This is typically called from the timer, but otherwise it can be called from any other process.
+ * @param p - peer to connect to
+ * @returns socket if OK, -1 on error
+ */
+int peer_connect(peer *p)
+{
+	int sock;
+	unsigned int option = 1;
+	
+	struct addrinfo *ainfo=0,*res=0,hints;		
+	char buf[256],host[256],serv[256];
+	int error;
+
+	memset (&hints, 0, sizeof(hints));
+	//hints.ai_protocol = IPPROTO_SCTP;
+ 	//hints.ai_protocol = IPPROTO_TCP;
+ 	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_socktype = SOCK_STREAM;
+	
+	sprintf(buf,"%d",p->port);
+
+	error = getaddrinfo(p->fqdn.s, buf, &hints, &res);
+
+	if (error!=0){
+		LM_WARN("peer_connect(): Error opening connection to %.*s:%d >%s\n",
+			p->fqdn.len,p->fqdn.s,p->port,gai_strerror(error));
+		goto error;
+	}
+		
+	for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
+	{
+		if (getnameinfo(ainfo->ai_addr,ainfo->ai_addrlen,
+			host,256,serv,256,NI_NUMERICHOST|NI_NUMERICSERV)==0){
+				LM_WARN("peer_connect(): Trying to connect to %s port %s\n",
+					host,serv);
+		}				
+
+		if ((sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol)) == -1) {
+			LM_ERR("peer_connect(): error creating client socket to %s port %s >"
+				" %s\n",host,serv,strerror(errno));
+			continue;
+		}
+
+		{// Connect with timeout
+			int x;
+			x=fcntl(sock,F_GETFL,0);
+			fcntl(sock,F_SETFL,x | O_NONBLOCK);
+			int res = connect(sock,ainfo->ai_addr,ainfo->ai_addrlen);
+			if (res<0){
+				if (errno==EINPROGRESS){
+					  struct timeval tv={
+						  .tv_sec = config->connect_timeout,
+						  .tv_usec = 0,
+					  };
+					  fd_set myset; 
+					  FD_ZERO(&myset); 
+					  FD_SET(sock, &myset);
+					  if (select(sock+1, NULL, &myset, NULL, &tv) > 0) { 
+						  socklen_t lon = sizeof(int);
+						  int  valopt;
+						  getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon); 
+						  if (valopt) { 
+					    	  LM_WARN("peer_connect(): Error opening connection to to %s port %s >%s\n",host,serv,strerror(valopt));
+					    	  close(sock);		
+					    	  continue;
+					      } 
+					  }else{ 
+				    	  LM_WARN("peer_connect(): Timeout or error opening connection to to %s port %s >%s\n",host,serv,strerror(errno));
+				    	  close(sock);		
+				    	  continue;
+					  } 					  
+				}
+			}else{
+				LM_WARN("peer_connect(): Error opening connection to to %s port %s >%s\n",host,serv,strerror(errno));
+				close(sock);		
+				continue;
+			}
+			
+			x=fcntl(sock,F_GETFL,0);
+			fcntl(sock,F_SETFL,x & (~O_NONBLOCK));
+		}
+		setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
+	
+		LM_INFO("peer_connect(): Peer %.*s:%d connected\n",p->fqdn.len,p->fqdn.s,p->port);
+
+		if (!send_fd(p->fd_exchange_pipe,sock,p)){
+			LM_ERR("peer_connect(): [%.*s] Error sending fd to respective receiver\n",p->fqdn.len,p->fqdn.s);
+			close(sock);
+			goto error;
+		}
+		
+		if (res) freeaddrinfo(res);			
+		return sock;
+	}
+error:
+	if (res) freeaddrinfo(res);	
+	return -1;	
+}
+
+
+/**
+ * Sends a newly connected socket to the receiver process
+ * @param sock
+ * @return
+ */
+int receiver_send_socket(int sock, peer *p)
+{
+	int pipe_fd;
+	if (p)
+		pipe_fd = p->fd_exchange_pipe;
+	else
+		pipe_fd = fd_exchange_pipe_unknown;
+	
+	return send_fd(pipe_fd,sock,p);
+}
+
+
+/**
+ * Sends a message to a peer (to be called from other processes).
+ * This just writes the pointer to the message in the send pipe. The specific
+ * peer process will pick that up and send the message, as only that specific
+ * process has the id of socket (we are forking the peers dynamically and as such,
+ * the sockets are not visible between processes).
+ * @param p - the peer to send to
+ * @param msg - the message to send
+ * @returns 1 on success, 0 on failure
+ */
+int peer_send_msg(peer *p,AAAMessage *msg)
+{
+	int fd,n;
+	if (!AAABuildMsgBuffer(msg)) return 0;
+	if (!p->send_pipe_name.s) {
+		LM_ERR("peer_send_msg(): Peer %.*s has no attached send pipe\n",p->fqdn.len,p->fqdn.s);
+		return 0;
+	}
+	fd = open(p->send_pipe_name.s,O_WRONLY);
+	if (fd<0){
+		LM_ERR("peer_send_msg(): Peer %.*s error on pipe open > %s\n",p->fqdn.len,p->fqdn.s,strerror(errno));		
+		return 0;
+	}
+	LM_DBG("peer_send_msg(): Pipe push [%p]\n",msg);
+	n = write(fd,&msg,sizeof(AAAMessage *));
+	if (n<0) {
+		LM_ERR("peer_send_msg(): Peer %.*s error on pipe write > %s\n",p->fqdn.len,p->fqdn.s,strerror(errno));		
+		close(fd);
+		return 0;
+	}
+	if (n!=sizeof(AAAMessage *)) {
+		LM_ERR("peer_send_msg(): Peer %.*s error on pipe write > only %d bytes written\n",p->fqdn.len,p->fqdn.s,n);		
+		close(fd);
+		return 0;
+	}
+	close(fd);
+	return 1;
+}
+
+/**
+ * Send a message to a peer (only to be called from the receiver process).
+ * This directly writes the message on the socket. It is used for transmission during
+ * the Capability Exchange procedure, when the send pipes are not opened yet.
+ * It also sends the file descriptor to the peer's dedicated receiver if one found. 
+ * @param p - the peer to send to
+ * @param sock - the socket to send through
+ * @param msg - the message to send
+ * @param locked - whether the caller locked the peer already
+ * @returns 1 on success, 0 on error
+ */
+int peer_send(peer *p,int sock,AAAMessage *msg,int locked)
+{
+	int n;
+	serviced_peer_t *sp;
+
+	
+	if (!p||!msg||sock<0) return 0;
+	LM_DBG("peer_send(): [%.*s] sending direct message to peer\n",
+			p->fqdn.len,
+			p->fqdn.s);
+	
+	if (!AAABuildMsgBuffer(msg)) return 0;
+	
+	if (!locked) lock_get(p->lock);
+
+	while( (n=write(sock,msg->buf.s,msg->buf.len))==-1 ) {
+		if (errno==EINTR)
+			continue;
+		LM_ERR("peer_send(): write returned error: %s\n",
+			strerror(errno));
+		if (p->I_sock==sock) sm_process(p,I_Peer_Disc,0,1,p->I_sock);
+		if (p->R_sock==sock) sm_process(p,R_Peer_Disc,0,1,p->R_sock);
+		if (!locked) lock_release(p->lock);
+		AAAFreeMessage(&msg);		
+		return 0;
+	}
+
+	if (n!=msg->buf.len){
+		LM_ERR("peer_send(): only wrote %d/%d bytes\n",n,msg->buf.len);
+		if (!locked) lock_release(p->lock);
+		AAAFreeMessage(&msg);		
+		return 0;
+	}
+	if (!locked) lock_release(p->lock);
+	
+	AAAFreeMessage(&msg);
+
+	/* now switch the peer processing to its dedicated process if this is not a dynamic peer */
+	if (!p->is_dynamic){
+		LM_DBG("peer_send(): [%.*s] switching peer to own and dedicated receiver\n",
+				p->fqdn.len,
+				p->fqdn.s);
+		send_fd(p->fd_exchange_pipe,sock,p);
+		for(sp=serviced_peers;sp;sp=sp->next)
+			if (sp->p==p){
+				drop_serviced_peer(sp,locked);
+				break;
+			}
+	}
+	
+	return 1;	
+}
+
+
+/**
+ * Receives a message and does basic processing or call the sm_process().
+ * This gets called from the do_receive() for every message that is received.
+ * Basic processing, before the state machine, is done here.
+ * @param msg - the message received
+ * @param sp - the serviced peer that it was receiver on
+ */
+void receive_message(AAAMessage *msg,serviced_peer_t *sp)
+{
+	AAA_AVP *avp1,*avp2;
+	LM_DBG("receive_message(): [%.*s] Recv msg %d\n",
+			sp->p?sp->p->fqdn.len:0,
+			sp->p?sp->p->fqdn.s:0,
+			msg->commandCode);
+	
+	if (!sp->p){
+		switch (msg->commandCode){
+			case Code_CE:
+				if (is_req(msg)){
+					avp1 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Host,0,0);
+					avp2 = AAAFindMatchingAVP(msg,msg->avpList.head,AVP_Origin_Realm,0,0);
+					if (avp1&&avp2){
+						sp->p = get_peer_from_fqdn(avp1->data,avp2->data);
+					}
+					if (!sp->p) {
+						LM_ERR("receive_msg(): Received CER from unknown peer (accept unknown=%d) -ignored\n",
+							config->accept_unknown_peers);
+						AAAFreeMessage(&msg);
+					}else{
+						LM_DBG("receive_message(): [%.*s] This receiver has no peer associated\n",
+								sp->p?sp->p->fqdn.len:0,
+								sp->p?sp->p->fqdn.s:0	);						
+						//set_peer_pipe();
+						make_send_pipe(sp);
+						sm_process(sp->p,R_Conn_CER,msg,0,sp->tcp_socket);
+					}
+				}
+				else{
+					LM_ERR("receive_msg(): Received CEA from an unknown peer -ignored\n");
+					AAAFreeMessage(&msg);
+				}
+				break;
+			default:
+				LM_ERR("receive_msg(): Received non-CE from an unknown peer -ignored\n");
+				AAAFreeMessage(&msg);				
+		}
+	}else{
+		touch_peer(sp->p);
+		switch (sp->p->state){
+			case Wait_I_CEA:
+				if (msg->commandCode!=Code_CE||is_req(msg)){
+					sm_process(sp->p,I_Rcv_Non_CEA,msg,0,sp->tcp_socket);
+				}else
+					sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
+				break;
+			case I_Open:			
+				switch (msg->commandCode){
+					case Code_CE:
+						if (is_req(msg)) sm_process(sp->p,I_Rcv_CER,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,I_Rcv_CEA,msg,0,sp->tcp_socket);
+						break;
+					case Code_DW:
+						if (is_req(msg)) sm_process(sp->p,I_Rcv_DWR,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,I_Rcv_DWA,msg,0,sp->tcp_socket);
+						break;
+					case Code_DP:
+						if (is_req(msg)) sm_process(sp->p,I_Rcv_DPR,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,I_Rcv_DPA,msg,0,sp->tcp_socket);
+						break;
+					default:
+						sm_process(sp->p,I_Rcv_Message,msg,0,sp->tcp_socket);
+				}				
+				break;				
+			case R_Open:			
+				switch (msg->commandCode){
+					case Code_CE:
+						if (is_req(msg)) sm_process(sp->p,R_Rcv_CER,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,R_Rcv_CEA,msg,0,sp->tcp_socket);
+						break;
+					case Code_DW:
+						if (is_req(msg)) sm_process(sp->p,R_Rcv_DWR,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,R_Rcv_DWA,msg,0,sp->tcp_socket);
+						break;
+					case Code_DP:
+						if (is_req(msg)) sm_process(sp->p,R_Rcv_DPR,msg,0,sp->tcp_socket);	
+									else sm_process(sp->p,R_Rcv_DPA,msg,0,sp->tcp_socket);
+						break;
+					default:
+						sm_process(sp->p,R_Rcv_Message,msg,0,sp->tcp_socket);
+				}				
+				break;				
+			default:
+				LM_ERR("receive_msg(): [%.*s] Received msg while peer in state %d -ignored\n",
+						sp->p->fqdn.len,
+						sp->p->fqdn.s,
+						sp->p->state);
+				AAAFreeMessage(&msg);								
+		}
+	}
+}

+ 91 - 0
modules/cdp/receiver.h

@@ -0,0 +1,91 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __RECEIVER_H
+#define __RECEIVER_H
+
+#include "peer.h"
+#include "diameter.h"
+
+/** Maximum incoming message length */
+#define DP_MAX_MSG_LENGTH 65536
+
+#define DIAMETER_HEADER_LEN 20
+
+
+typedef enum {
+	Receiver_Waiting=0,
+	Receiver_Header=1,
+	Receiver_Rest_of_Message=2
+} receiver_state_t;
+
+/** list of receiver attached peers */
+typedef struct _serviced_peer_t {
+	peer *p;									/**< the attached peer */
+	
+	int tcp_socket;								/**< socket used for the Diameter communication */
+	
+	str send_pipe_name;							/**< name of the pipe to signal messages to be sent out */ 
+	int send_pipe_fd;							/**< reader from the pipe to signal messages to be sent out */
+	int send_pipe_fd_out;						/**< keep-alive writer for the pipe to signal messages to be sent out */
+
+	receiver_state_t state;						/**< current receiving state */
+	char buf[DIAMETER_HEADER_LEN];				/**< buffer to receive header into */
+	int buf_len;								/**< received bytes in the header */
+	int length;									/**< length of the message as written in the header */
+	char *msg;									/**< dynamic buffer for receiving one message */
+	int msg_len;								/**< received bytes in the dynamic buffer */
+		
+	
+	struct _serviced_peer_t *next;	/**< first peer in the list */	
+	struct _serviced_peer_t *prev; /**< last peer in the list */
+} serviced_peer_t;
+
+int receiver_init(peer *p);
+void receiver_process(peer *p);
+
+int receiver_send_socket(int sock,peer *p);
+
+int peer_connect(peer *p);
+int peer_send(peer *p,int sock,AAAMessage *msg,int locked);
+int peer_send_msg(peer *p,AAAMessage *msg);
+
+#endif
+

+ 182 - 0
modules/cdp/routing.c

@@ -0,0 +1,182 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "routing.h"
+#include "config.h"
+#include "peermanager.h"
+#include "diameter_api.h"
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+
+/**
+ * Returns if the peer advertised support for an Application ID
+ * @param p - the peer to check
+ * @param app_id - the application id to look for
+ * @param vendor_id - the vendor id to look for, 0 if not vendor specific 
+ * @returns 0 if not found, 1 if found
+ */ 
+int peer_handles_application(peer *p,int app_id,int vendor_id)
+{
+	int i;
+	LM_DBG("Checking if peer %.*s handles application %d for vendord %d\n",p->fqdn.len,p->fqdn.s,app_id,vendor_id);
+	if (!p || !p->applications || !p->applications_cnt) return 0;
+	for(i=0;i<p->applications_cnt;i++)
+		if (p->applications[i].id==app_id && p->applications[i].vendor==vendor_id) return 1;		
+	return 0;
+}
+
+/**
+ * Get the first peer that is connected from the list of routing entries.
+ * @param r - the list of routing entries to look into
+ * @returns - the peer or null if none connected
+ */
+peer* get_first_connected_route(routing_entry *r,int app_id,int vendor_id)
+{
+	routing_entry *i;
+	peer *p;
+	LM_DBG("get_first_connected_route in list %p for app_id %d and vendor_id %d\n",
+		r,app_id,vendor_id);
+	for(i=r;i;i=i->next){
+		p = get_peer_by_fqdn(&(i->fqdn));
+		if (!p)
+			LM_DBG("The peer %.*s does not seem to be connected or configured\n",
+				i->fqdn.len,i->fqdn.s);
+		else
+			LM_DBG("The peer %.*s state is %s\n",i->fqdn.len,i->fqdn.s,
+				(p->state==I_Open||p->state==R_Open)?"opened":"closed");
+		if (p && (p->state==I_Open || p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) {			
+			LM_DBG("The peer %.*s matches - will forward there\n",i->fqdn.len,i->fqdn.s);
+			return p;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Get the first connect peer that matches the routing mechanisms.
+ * - First the Destination-Host AVP value is tried if connected (the peer does not have to
+ * be in the routing table at all).
+ * - Then we look for a connected peer in the specific realm for the Destination-Realm AVP
+ * - Then we look for the first connected peer in the default routes
+ * @param m - the Diameter message to find the destination peer for
+ * @returns - the connected peer or null if none connected found
+ */  
+peer* get_routing_peer(AAAMessage *m)
+{
+	str destination_realm={0,0},destination_host={0,0};
+	AAA_AVP *avp,*avp_vendor,*avp2;
+	AAA_AVP_LIST group;	
+	peer *p;
+	routing_realm *rr;
+	int app_id=0,vendor_id=0;
+	
+	app_id = m->applicationId;	
+	avp = AAAFindMatchingAVP(m,0,AVP_Vendor_Specific_Application_Id,0,AAA_FORWARD_SEARCH);
+	if (avp){
+		group = AAAUngroupAVPS(avp->data);
+		avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);				
+		avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);				
+		if (avp_vendor&&avp2){
+			vendor_id = get_4bytes(avp_vendor->data.s);
+			app_id = get_4bytes(avp2->data.s);
+		}
+		avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);				
+		if (avp_vendor&&avp2){
+			vendor_id = get_4bytes(avp_vendor->data.s);
+			app_id = get_4bytes(avp2->data.s);
+		}
+		AAAFreeAVPList(&group);
+	}
+
+	avp_vendor = AAAFindMatchingAVP(m,0,AVP_Vendor_Id,0,AAA_FORWARD_SEARCH);				
+	avp = AAAFindMatchingAVP(m,0,AVP_Auth_Application_Id,0,AAA_FORWARD_SEARCH);
+	if (avp){
+		if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
+		else vendor_id = 0;
+		app_id = get_4bytes(avp->data.s);		
+	}
+	
+	avp = AAAFindMatchingAVP(m,0,AVP_Acct_Application_Id,0,AAA_FORWARD_SEARCH);
+	if (avp){
+		if (avp_vendor) vendor_id = get_4bytes(avp_vendor->data.s);
+		else vendor_id = 0;
+		app_id = get_4bytes(avp->data.s);		
+	}
+	
+	avp = AAAFindMatchingAVP(m,0,AVP_Destination_Host,0,AAA_FORWARD_SEARCH);
+	if (avp) destination_host = avp->data;
+	
+	if (destination_host.len){
+		/* There is a destination host present in the message try and route directly there */
+		p = get_peer_by_fqdn(&destination_host);
+		if (p && (p->state==I_Open || p->state==R_Open) && peer_handles_application(p,app_id,vendor_id)) return p;
+		/* the destination host peer is not connected at the moment, try a normal route then */
+	}
+	
+	avp = AAAFindMatchingAVP(m,0,AVP_Destination_Realm,0,AAA_FORWARD_SEARCH);
+	if (avp) destination_realm = avp->data;
+	
+	if (!config->r_table) {
+		LM_ERR("get_routing_peer(): Empty routing table.\n");
+		return 0;
+	}
+	
+	if (destination_realm.len){
+		/* first search for the destination realm */
+		for(rr=config->r_table->realms;rr;rr=rr->next)
+			if (rr->realm.len == destination_realm.len &&
+				strncasecmp(rr->realm.s,destination_realm.s,destination_realm.len)==0)
+					break;
+		if (rr) {
+			p = get_first_connected_route(rr->routes,app_id,vendor_id);
+			if (p) return p;
+			else LM_ERR("get_routing_peer(): No connected Route peer found for Realm <%.*s>. Trying DefaultRoutes next...\n",
+					destination_realm.len,destination_realm.s);
+		}	 
+	}
+	/* if not found in the realms or no destination_realm, 
+	 * get the first connected host in default routes */
+	p = get_first_connected_route(config->r_table->routes,app_id,vendor_id);
+	if (!p){
+		LM_ERR("get_routing_peer(): No connected DefaultRoute peer found for app_id %d and vendor id %d.\n",
+				app_id,vendor_id);
+	}
+	return p;
+}

+ 51 - 0
modules/cdp/routing.h

@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __ROUTING_H
+#define __ROUTING_H
+
+#include "peer.h"
+#include "diameter.h"
+#include "utils.h"
+
+peer* get_routing_peer(AAAMessage *m);
+
+#endif
+

+ 93 - 0
modules/cdp/sem.h

@@ -0,0 +1,93 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __SEM_H
+#define __SEM_H
+
+#ifdef SHM_MEM
+
+//	#include "../../mem/mem.h"
+//	#include "../../mem/shm_mem.h"
+	
+	#include "utils.h"
+	
+	#include <semaphore.h>
+
+	typedef sem_t gen_sem_t;
+
+	/**
+	 * Create a new unnamed semaphore and initialize it
+	 * @param value - 0 if it should be pre-locked, 1 if not, or how many locks until block
+	 * @return
+	 */
+    #define sem_new(sem_ptr,value)\
+	do {\
+		sem_ptr=shm_malloc(sizeof(gen_sem_t));\
+		if (!sem_ptr){\
+			LM_ERR("Error allocating %lx bytes of shm!\n",sizeof(gen_sem_t));\
+			goto out_of_memory;\
+		}	\
+		if (sem_init(sem_ptr, 1, value)<0) {\
+			LM_ERR("Error > %s\n",strerror(errno));\
+			goto out_of_memory;\
+		}\
+	} while(0)
+	
+    #define sem_free(sem)\
+	do {\
+		if (sem) {\
+			sem_destroy(sem);\
+			shm_free(sem);\
+			sem=0;\
+		}\
+	} while(0)
+	
+	
+	#define sem_get(sem) sem_wait(sem)
+	#define sem_tryget(sem) sem_trywait(sem)
+	#define sem_timedget(sem,abs_timeout) sem_trywait(sem,abs_timeout)
+	
+	#define sem_release(sem) sem_post(sem)
+
+#else
+	//#error "locking requires shared memory support"
+#endif
+
+#endif

+ 671 - 0
modules/cdp/session.c

@@ -0,0 +1,671 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "session.h"
+#include "diameter.h"
+#include "config.h"
+#include "authstatemachine.h"
+#include "timer.h"
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+
+gen_lock_t *session_lock;		/**< lock for session operation */
+
+int sessions_hash_size = 1024;	/**< the size of the session hash table		*/
+cdp_session_list_t *sessions;	/**< the session hash table					*/
+
+unsigned int *session_id1;		/**< counter for first part of the session id */
+unsigned int *session_id2;		/**< counter for second part of the session id */
+
+
+/**
+ * Lock a hash table row
+ */
+inline void AAASessionsLock(unsigned int hash)
+{
+	if ( hash >=0 && hash < sessions_hash_size ){
+		lock_get(sessions[hash].lock);
+	}
+	else {
+		LM_ERR("AAASessionsLock: hash :%d out of range of sessions_hash_size: %d !\n", hash, sessions_hash_size);
+	}
+}
+
+/**
+ * Unlock a hash table row
+ */
+inline void AAASessionsUnlock(unsigned int hash)
+{
+	
+	if ( hash >=0 && hash < sessions_hash_size ){
+		lock_release(sessions[hash].lock);
+	}
+	else {
+		LM_ERR("AAASessionsLock: hash :%d out of range of sessions_hash_size: %d !\n", hash, sessions_hash_size);
+	}
+}
+
+
+
+/**
+ * Free a session structure
+ */
+void free_session(cdp_session_t *x)
+{
+	if (x){
+		if (x->id.s) shm_free(x->id.s);
+		switch(x->type){
+			case UNKNOWN_SESSION:
+				if (x->u.generic_data){
+					LM_ERR("free_session(): The session->u.generic_data should be freed and reset before dropping the session!"
+						"Possible memory leak!\n");
+				}
+				break;
+			case AUTH_CLIENT_STATEFULL:
+				break;
+			case AUTH_SERVER_STATEFULL:
+				break;
+			default:
+				LM_ERR("free_session(): Unknown session type %d!\n",x->type);
+		}
+		
+		if(x->dest_host.s) shm_free(x->dest_host.s);
+		if(x->dest_realm.s) shm_free(x->dest_realm.s);
+
+		shm_free(x);
+	}
+}
+
+
+/**
+ * Initializes the session related structures.
+ */
+int cdp_sessions_init(int hash_size)
+{
+	int i;
+	session_lock = lock_alloc();
+	if (!session_lock){
+		LOG_NO_MEM("lock",sizeof(gen_lock_t));
+		goto error;
+	}
+	session_lock = lock_init(session_lock);
+	sessions_hash_size=hash_size;
+	
+	sessions = shm_malloc(sizeof(cdp_session_list_t)*hash_size);
+	if (!sessions){
+		LOG_NO_MEM("shm",sizeof(cdp_session_list_t)*hash_size);
+		goto error;
+	}
+	memset(sessions,0,sizeof(cdp_session_list_t)*hash_size);
+	
+	for(i=0;i<hash_size;i++){
+		sessions[i].lock = lock_alloc();
+		if (!sessions[i].lock){
+			LOG_NO_MEM("lock",sizeof(gen_lock_t));
+			goto error;
+		}
+		sessions[i].lock = lock_init(sessions[i].lock);
+	}
+	
+	session_id1 = shm_malloc(sizeof(unsigned int));
+	if (!session_id1){
+		LOG_NO_MEM("shm",sizeof(unsigned int));
+		goto error;
+	}
+	session_id2 = shm_malloc(sizeof(unsigned int));
+	if (!session_id2){
+		LOG_NO_MEM("shm",sizeof(unsigned int));
+		goto error;
+	}
+	srand((unsigned int)time(0));	
+	*session_id1 = rand();
+	*session_id1 <<= 16;
+	*session_id1 += time(0)&0xFFFF;
+	*session_id2 = 0;
+	
+	add_timer(1,0,cdp_sessions_timer,0);
+	return 1;
+error:
+	return 0;
+}
+
+/**
+ * Destroys the session related structures.
+ */
+int cdp_sessions_destroy()
+{
+	int i;
+	cdp_session_t *n,*x;
+	
+	if (session_lock){
+		lock_get(session_lock);
+		lock_destroy(session_lock);
+		lock_dealloc((void*)session_lock);		
+		session_lock=0;
+	}	
+	for(i=0;i<sessions_hash_size;i++){
+		AAASessionsLock(i);
+		for(x = sessions[i].head; x; x = n){
+			n = x->next;
+			free_session(x);	
+		}
+		lock_destroy(sessions[i].lock);
+		lock_dealloc((void*)sessions[i].lock);
+	}
+	shm_free(sessions);
+			
+	shm_free(session_id1);
+	shm_free(session_id2);
+	return 1;
+}
+
+
+
+
+/**
+ * Computes the hash for a string.
+ * @param aor - the aor to compute the hash on
+ * @param hash_size - value to % with
+ * @returns the hash % hash_size
+ */
+inline unsigned int get_str_hash(str x,int hash_size)
+{
+#define h_inc h+=v^(v>>3)
+   char* p;
+   register unsigned v;
+   register unsigned h;
+
+   h=0;
+   for (p=x.s; p<=(x.s+x.len-4); p+=4){
+       v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
+       h_inc;
+   }
+   v=0;
+   for (;p<(x.s+x.len); p++) {
+       v<<=8;
+       v+=*p;
+   }
+   h_inc;
+
+   h=((h)+(h>>11))+((h>>13)+(h>>23));
+   return (h)%hash_size;
+#undef h_inc 
+}
+
+/**
+ * Create a new session structure
+ * @param id - the session id string, already allocated in shm
+ * @param type - the session type
+ * @returns the new cdp_session_t on success or 0 on failure
+ */
+cdp_session_t* cdp_new_session(str id,cdp_session_type_t type)
+{
+	cdp_session_t *x=0;
+
+	x = shm_malloc(sizeof(cdp_session_t));
+	if (!x){
+		LOG_NO_MEM("shm",sizeof(cdp_session_t));
+		goto error;
+	}
+	memset(x,0,sizeof(cdp_session_t));
+	x->id = id;
+	x->type = type;
+	x->hash = get_str_hash(x->id,sessions_hash_size);
+	return x;
+error:
+	return 0;
+}
+
+/**
+ * Adds the session to the session list.
+ * \note This returns with a lock, so unlock when done
+ * @param x - the session to add
+ */
+void cdp_add_session(cdp_session_t *x)
+{
+//	unsigned int hash;
+	if (!x) return;
+//	hash = get_str_hash(x->id,sessions_hash_size);
+//	x->hash = hash;
+	LM_DBG("adding a session with id %.*s\n",x->id.len,x->id.s);
+	AAASessionsLock(x->hash);
+	x->next = 0;
+	x->prev = sessions[x->hash].tail;
+	if (sessions[x->hash].tail) sessions[x->hash].tail->next = x;
+	sessions[x->hash].tail = x;
+	if (!sessions[x->hash].head) sessions[x->hash].head = x;	
+}
+
+/**
+ * Finds a session in the session hash table.
+ * \note Returns with a lock on the sessions[x->hash].lock!!!
+ * @param id - the id of the session
+ * @returns the session if found or 0 if not
+ */
+cdp_session_t* cdp_get_session(str id)
+{
+	unsigned int hash;
+	cdp_session_t *x;
+	if (!id.len) return 0;
+	hash = get_str_hash(id,sessions_hash_size);
+	LM_DBG("called get session with id %.*s and hash %u\n",id.len,id.s,hash);
+	AAASessionsLock(hash);
+		for(x = sessions[hash].head;x;x=x->next){
+			LM_DBG("looking for |%.*s| in |%.*s|\n",id.len,id.s,x->id.len,x->id.s);
+			if (x->id.len == id.len &&
+				strncasecmp(x->id.s,id.s,id.len)==0)
+					return x;
+		}			
+	AAASessionsUnlock(hash);	
+	LM_DBG("no session found\n");
+	return 0;
+}
+
+
+/**
+ * Removes and frees a session.
+ * \note must be called with a lock on the x->hash and it will unlock on exit. Do not use x after calling this
+ * 
+ * @param x - the session to remove
+ */
+void del_session(cdp_session_t *x)
+{
+	unsigned int hash;
+
+	if (!x) return;
+
+	hash = x->hash;
+	if (hash < 0 || hash >= sessions_hash_size) {
+		LM_ERR("del_session: x->hash :%d out of range of sessions_hash_size: %d !\n",hash, sessions_hash_size);
+		return;
+	}
+
+	if (sessions[x->hash].head == x) sessions[x->hash].head = x->next;
+	else if (x->prev) x->prev->next = x->next;
+	if (sessions[x->hash].tail == x) sessions[x->hash].tail = x->prev;
+	else if (x->next) x->next->prev = x->prev;
+	
+	AAASessionsUnlock(hash);
+	
+	free_session(x);
+}
+
+
+/**
+ * Generates a new session_ID (conforming with draft-ietf-aaa-diameter-17).
+ * This function is thread safe.
+ * @returns an 1 if success or -1 if error.
+ */
+static int generate_session_id(str *id, unsigned int end_pad_len)
+{
+	unsigned int s2;
+
+	/* some checks */
+	if (!id)
+		goto error;
+
+	/* compute id's len */
+	id->len = config->identity.len +
+		1/*;*/ + 10/*high 32 bits*/ +
+		1/*;*/ + 10/*low 32 bits*/ +
+//		1/*;*/ + 8/*optional value*/ +
+		1 /* terminating \0 */ +
+		end_pad_len;
+
+	/* get some memory for it */
+	id->s = (char*)shm_malloc( id->len );
+	if (id->s==0) {
+		LM_ERR("generate_session_id: no more free memory!\n");
+		goto error;
+	}
+
+	lock_get(session_lock);
+	s2 = *session_id2 +1;
+	*session_id2 = s2;
+	lock_release(session_lock);
+	
+	/* build the sessionID */
+	sprintf(id->s,"%.*s;%u;%u",config->identity.len,config->identity.s,*session_id1,s2);
+	id->len = strlen(id->s);
+	return 1;
+error:
+	return -1;
+}
+
+void cdp_sessions_log(int level)
+{
+	int hash;
+	cdp_session_t *x;
+#ifdef SER_MOD_INTERFACE
+	if (!is_printable(level))
+#else		
+	if (debug<level)
+#endif
+		return;
+	LOG(level,"------- CDP Sessions ----------------\n");
+	for(hash=0;hash<sessions_hash_size;hash++){		
+		AAASessionsLock(hash);
+		for(x = sessions[hash].head;x;x=x->next) {						
+			LOG(level," %3u. [%.*s] AppId [%d] Type [%d]\n",
+					hash,
+					x->id.len,x->id.s,
+					x->application_id,
+					x->type);
+			switch (x->type){
+				case AUTH_CLIENT_STATEFULL:
+				case AUTH_SERVER_STATEFULL:
+					LOG(level,"\tAuth State [%d] Timeout [%d] Lifetime [%d] Grace [%d] Generic [%p]\n",
+							x->u.auth.state,
+							(int)(x->u.auth.timeout-time(0)),
+							x->u.auth.lifetime?(int)(x->u.auth.lifetime-time(0)):-1,
+							(int)(x->u.auth.grace_period),
+							x->u.auth.generic_data);
+					break;
+				default:
+					break;
+			}
+		}
+		AAASessionsUnlock(hash);
+	}
+	LOG(level,"-------------------------------------\n");
+}
+
+int cdp_sessions_timer(time_t now, void* ptr)
+{
+	int hash;
+	cdp_session_t *x,*n;
+	for(hash=0;hash<sessions_hash_size;hash++){		
+		AAASessionsLock(hash);
+		for(x = sessions[hash].head;x;x=n) {
+			n = x->next;
+			switch (x->type){
+				case AUTH_CLIENT_STATEFULL:
+					if (x->u.auth.timeout>=0 && x->u.auth.timeout<=now){
+						//Session timeout
+						LM_CRIT("session TIMEOUT\n");
+						auth_client_statefull_sm_process(x,AUTH_EV_SESSION_TIMEOUT,0);
+					} else if (x->u.auth.lifetime>0 && x->u.auth.lifetime+x->u.auth.grace_period<=now){
+						//lifetime + grace timeout
+						LM_CRIT("lifetime+grace TIMEOUT\n");
+						auth_client_statefull_sm_process(x,AUTH_EV_SESSION_GRACE_TIMEOUT,0);
+					}else if (x->u.auth.lifetime>0 && x->u.auth.lifetime<=now){
+						//lifetime timeout
+						LM_CRIT("lifetime+grace TIMEOUT\n");
+						auth_client_statefull_sm_process(x,AUTH_EV_SESSION_LIFETIME_TIMEOUT,0);
+					}
+					break;
+				case AUTH_SERVER_STATEFULL:
+					if (x->u.auth.timeout>=0 && x->u.auth.timeout<=now){
+						//Session timeout
+						LM_CRIT("session TIMEOUT\n");
+						auth_server_statefull_sm_process(x,AUTH_EV_SESSION_TIMEOUT,0);
+					}else if (x->u.auth.lifetime>0 && x->u.auth.lifetime+x->u.auth.grace_period<=now){
+						//lifetime + grace timeout
+						LM_CRIT("lifetime+grace TIMEOUT\n");
+						auth_server_statefull_sm_process(x,AUTH_EV_SESSION_GRACE_TIMEOUT,0);
+					}else if (x->u.auth.lifetime>0 && x->u.auth.lifetime<=now){
+						//lifetime timeout
+						LM_CRIT("lifetime+grace TIMEOUT\n");
+						auth_server_statefull_sm_process(x,AUTH_EV_SESSION_LIFETIME_TIMEOUT,0);
+					}
+					break;
+				default:
+					break;
+					
+			}
+		}
+		AAASessionsUnlock(hash);
+	}
+	if (now%5==0)cdp_sessions_log(L_DBG);
+	return 1;
+}
+
+
+
+/****************************** API FUNCTIONS ********************************/
+
+/**
+ * Creates a Generic Session.
+ */
+AAASession* AAACreateSession(void *generic_data)
+{
+	AAASession *s;
+	str id;
+	
+	generate_session_id(&id,0);
+	s = cdp_new_session(id,UNKNOWN_SESSION);
+	if (s) {
+		s->u.generic_data = generic_data;
+		cdp_add_session(s);
+	}
+	return s;
+}
+
+/**
+ * Make a session based on already known parameters.
+ * \Note This should be used to recover saved sessions after a restart.
+ * @param app_id
+ * @param type
+ * @param session_id - will be duplicated to shm
+ * @return
+ */
+AAASession* AAAMakeSession(int app_id,int type,str session_id)
+{
+	AAASession *s;
+	str id;
+	
+	id.s = shm_malloc(session_id.len);
+	if (!id.s){
+		LM_ERR("Error allocating %d bytes!\n",session_id.len);
+		return 0;
+	}
+	memcpy(id.s,session_id.s,session_id.len);
+	id.len = session_id.len;
+	s = cdp_new_session(id,type);
+	s->application_id = app_id;
+	if (s) {		
+		cdp_add_session(s);
+	}
+	return s;
+}
+/**
+ * Deallocates the memory taken by a Generic Session
+ */
+void AAADropSession(AAASession *s)
+{
+	// first give a chance to the cb to free the generic param
+	if (s&&s->cb) 
+		(s->cb)(AUTH_EV_SESSION_DROP,s);
+	del_session(s);
+}
+
+
+AAASession* cdp_new_auth_session(str id,int is_client,int is_statefull)
+{
+	AAASession *s;
+	cdp_session_type_t type;
+	
+	if (is_client){
+		if (is_statefull) type = AUTH_CLIENT_STATEFULL;
+		else type = AUTH_CLIENT_STATELESS;
+	}else{
+		if (is_statefull) type = AUTH_SERVER_STATEFULL;
+		else type = AUTH_SERVER_STATELESS;		
+	}
+	s = cdp_new_session(id,type);
+	if (s) {
+		s->u.auth.timeout=time(0)+config->default_auth_session_timeout; 
+		s->u.auth.lifetime=0;
+		s->u.auth.grace_period=0;
+		cdp_add_session(s);
+	}
+	return s;
+}
+
+/**
+ * Creates a Authorization Session for the Client.
+ * It generates a new id and adds the session to the cdp list of sessions
+ * \note Returns with a lock on AAASession->hash. Unlock when done working with the result
+ * @returns the new AAASession or null on error
+ */
+AAASession* AAACreateClientAuthSession(int is_statefull,AAASessionCallback_f *cb,void *generic_data)
+{
+	AAASession *s;
+	str id;
+	
+	generate_session_id(&id,0);
+
+	s = cdp_new_auth_session(id,1,is_statefull);
+	if (s) {
+		s->u.auth.generic_data = generic_data;
+		s->cb = cb;
+		if (s->cb)
+			(s->cb)(AUTH_EV_SESSION_CREATED,s);
+	}
+	return s;
+}
+/**
+ * Creates a Authorization Session for the Server, from the application specific Session starting request
+ * It generates a new id and adds the session to the cdp list of sessions
+ * \note Returns with a lock on AAASession->hash. Unlock when done working with the result
+ * @returns the new AAASession or null on error
+ */
+AAASession* AAACreateServerAuthSession(AAAMessage *msg,int is_statefull,AAASessionCallback_f *cb,void *generic_data)
+{
+	AAASession *s;
+	str id;
+	
+	if (!msg||!msg->sessionId||!msg->sessionId->data.len){
+		LM_ERR("Error retrieving the Session-Id from the message.\n");
+		return 0;
+	}
+	id.s = shm_malloc(msg->sessionId->data.len);
+	if (!id.s){
+		LM_ERR("Error allocating %d bytes of shm!\n",msg->sessionId->data.len);
+		return 0;
+	}else{
+		id.len = msg->sessionId->data.len;
+		memcpy(id.s,msg->sessionId->data.s,id.len);
+		s=cdp_new_auth_session(id,0,is_statefull);
+		if (s) {
+			s->u.auth.generic_data = generic_data;
+			s->cb = cb;
+			if (s->cb)
+				(s->cb)(AUTH_EV_SESSION_CREATED,s);
+			update_auth_session_timers(&(s->u.auth),msg);
+			auth_server_statefull_sm_process(s,AUTH_EV_RECV_REQ,msg);	
+			// this is a special exception where the session lock is not released 
+			//s=0;
+		}
+	}
+	return s;
+}
+
+/**
+ * Looks for a session with a given id and returns it if found
+ * \note Returns with a lock on AAASession->hash. Unlock when done working with the result
+ * @returns the new AAASession or null on error
+ */
+AAASession* AAAGetSession(str id)
+{
+	return cdp_get_session(id);
+}
+
+/**
+ * Looks for an Auth session with a given id and returns it if found
+ * \note Returns with a lock on AAASession->hash. Unlock when done working with the result
+ * @returns the new AAASession or null on error
+ */
+AAASession* AAAGetAuthSession(str id)
+{
+	AAASession *x=cdp_get_session(id);
+	if (x){
+		switch (x->type){
+			case AUTH_CLIENT_STATEFULL:
+			case AUTH_CLIENT_STATELESS:
+			case AUTH_SERVER_STATEFULL:
+			case AUTH_SERVER_STATELESS:
+				return x;
+			default:
+				AAASessionsUnlock(x->hash);
+				return 0;
+		}
+	}
+	return 0;
+}
+
+/**
+ * Sends a Service terminated event to the session
+ */
+void AAATerminateAuthSession(AAASession *s)
+{
+	if (s->type==AUTH_CLIENT_STATEFULL) {
+		auth_client_statefull_sm_process(s,AUTH_EV_SERVICE_TERMINATED,0);
+	}
+}
+
+/**
+ * Deallocates the memory taken by a Authorization Session
+ * \note Must be called with a lock on the s->hash - will unlock it, so don't use the session after this
+ */
+void AAADropAuthSession(AAASession *s)
+{
+	AAADropSession(s);
+}
+
+/**
+ * Creates an Accounting Session.
+ */
+AAASession* AAACreateAccSession(void *generic_data)
+{
+	return 0;
+}
+
+/**
+ * Deallocates the memory taken by a Accounting Session
+ */
+void AAADropAccSession(AAASession *s)
+{
+	free_session(s);
+}

+ 253 - 0
modules/cdp/session.h

@@ -0,0 +1,253 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __DIAMETER_SESSION_H
+#define __DIAMETER_SESSION_H
+
+
+//#include "diameter_api.h"
+#include "utils.h"
+#include "diameter.h"
+
+/** Function for callback on session events: timeout, etc. */
+typedef void (AAASessionCallback_f)(int event,void *session);
+
+/** Types of sessions */
+typedef enum {
+	UNKNOWN_SESSION			= 0,
+	
+	AUTH_CLIENT_STATELESS	= 1,
+	AUTH_SERVER_STATELESS	= 2,
+	AUTH_CLIENT_STATEFULL	= 3,
+	AUTH_SERVER_STATEFULL	= 4,
+	
+	ACCT_CLIENT				= 5,
+	ACCT_SERVER_STATELESS	= 6,
+	ACCT_SERVER_STATEFULL	= 7,
+		
+} cdp_session_type_t;
+
+/** auth session states */
+typedef enum {
+	AUTH_ST_IDLE,
+	AUTH_ST_PENDING,
+	AUTH_ST_OPEN,
+	AUTH_ST_DISCON
+} cdp_auth_state;
+
+/** auth session event */
+typedef enum {
+	AUTH_EV_START						=0,
+	AUTH_EV_SEND_REQ 					=1,
+	AUTH_EV_SEND_ANS					=2,	
+	AUTH_EV_SEND_ANS_SUCCESS			=3,
+	AUTH_EV_SEND_ANS_UNSUCCESS			=4,
+	AUTH_EV_RECV_ASR					=5,
+	AUTH_EV_RECV_REQ					=6,
+	AUTH_EV_RECV_ANS					=7,
+	AUTH_EV_RECV_ANS_SUCCESS			=8,
+	AUTH_EV_RECV_ANS_UNSUCCESS			=9,
+	AUTH_EV_SEND_ASR					=10,
+	AUTH_EV_SEND_ASA_SUCCESS			=11,
+	AUTH_EV_SEND_ASA_UNSUCCESS			=12,
+	AUTH_EV_SEND_STA					=13,
+	AUTH_EV_RECV_ASA					=14,
+	AUTH_EV_RECV_ASA_SUCCESS			=15,
+	AUTH_EV_RECV_ASA_UNSUCCESS			=16,
+	AUTH_EV_RECV_STA					=17,
+	AUTH_EV_RECV_STR					=18,
+	AUTH_EV_SESSION_LIFETIME_TIMEOUT	=19,
+	AUTH_EV_SESSION_GRACE_TIMEOUT		=20,
+	AUTH_EV_SESSION_TIMEOUT				=21,
+	AUTH_EV_SERVICE_TERMINATED			=22,
+	AUTH_EV_SESSION_CREATED				=23,
+	AUTH_EV_SESSION_MODIFIED			=24,
+	AUTH_EV_SESSION_DROP				=25,
+} cdp_auth_event;
+	
+/** structure for auth session */
+typedef struct _cdp_auth_session_t {
+	cdp_auth_state state;	/**< current state */
+	
+	time_t timeout;			/**< absolute time for session timeout  -1 means forever */
+	time_t lifetime;		/**< absolute time for auth lifetime -1 means forever */
+	time_t grace_period;	/**< grace_period in seconds 	*/ 
+	void* generic_data;			
+} cdp_auth_session_t;
+
+/** Accounting states definition */
+typedef enum {
+	ACC_ST_IDLE			= 0,	/**< Idle */
+	ACC_ST_PENDING_S	= 1,	/**< Pending Session */
+	ACC_ST_PENDING_E	= 2,	/**< Pending Event */
+	ACC_ST_PENDING_B	= 3,	/**< Pending Buffered */
+	ACC_ST_OPEN	  		= 4,	/**< Open */
+	ACC_ST_PENDING_I	= 5,	/**< Pending Interim */
+	ACC_ST_PENDING_L	= 6		/**< PendingL - sent accounting stop */
+} cdp_acc_state_t;
+
+
+/** Accounting events definition */
+typedef enum {
+	ACC_EV_START					= 101,	/**< Client or device "requests access" (SIP session establishment) */
+	ACC_EV_EVENT					= 102,	/**< Client or device requests a one-time service (e.g. SIP MESSAGE) */
+	ACC_EV_BUFFEREDSTART			= 103,	/**< Records in storage */
+	ACC_EV_RCV_SUC_ACA_START		= 104,	/**< Successful accounting start answer received */
+	ACC_EV_SNDFAIL					= 105,	/**< Failure to send */
+	ACC_EV_RCV_FAILED_ACA_START		= 106,	/**< Failed accounting start answer received */
+	ACC_EV_STOP						= 107,	/**< User service terminated */
+	ACC_EV_INTERIM					= 108,	/**< Interim interval elapses */
+	ACC_EV_RCV_SUC_ACA_INTERIM		= 109,	/**< Successful accounting interim answer received */
+	ACC_EV_RCV_FAILED_ACA_INTERIM	=110,	/**< Failed accounting interim answer received */
+	ACC_EV_RCV_SUC_ACA_EVENT		= 111,	/**< Successful accounting event answer received */
+	ACC_EV_RCV_FAILED_ACA_EVENT		= 112,	/**< Failed accounting event answer received */
+	ACC_EV_RCV_SUC_ACA_STOP			= 113,	/**< Successful accounting stop answer received */
+	ACC_EV_RCV_FAILED_ACA_STOP		= 114,	/**< Failed accounting stop answer received */
+} cdp_acc_event_t;
+
+
+/** Structure for accounting sessions */
+typedef struct _acc_session {
+
+	cdp_acc_state_t state;						/**< current state */
+	
+	str dlgid;       						/**< application-level identifier, combines application session (e.g. SIP dialog) or event with diameter accounting session */
+	
+	unsigned int acct_record_number; 		/**< number of last accounting record within this session */
+	time_t aii;	 							/**< expiration of Acct-Interim-Interval (seconds) */
+	time_t timeout;							/**< session timeout (seconds) */
+	
+	
+	void* generic_data;			
+	
+} cdp_acc_session_t;
+
+
+
+
+/** Structure for session identification */
+typedef struct _cdp_session_t {
+	unsigned int hash;
+	str id;                             /**< session-ID as string */
+	unsigned int application_id;		/**< specific application id associated with this session */	
+	unsigned int vendor_id;				/**< specific vendor id for this session */
+	cdp_session_type_t type;
+	str dest_host, dest_realm; /*the destination host and realm, used only for auth, for the moment*/	
+	union {
+		cdp_auth_session_t auth;
+		cdp_acc_session_t acc;
+		void *generic_data;
+	} u;
+	 
+	AAASessionCallback_f *cb;			/**< session callback function */
+	
+	struct _cdp_session_t *next,*prev; 	
+} cdp_session_t;
+
+/** Session list structure */
+typedef struct _cdp_session_list_t {		
+	gen_lock_t *lock;				/**< lock for list operations */
+	cdp_session_t *head,*tail;		/**< first, last sessions in the list */ 
+} cdp_session_list_t;
+
+
+
+int cdp_sessions_init(int hash_size);
+int cdp_sessions_destroy();
+void cdp_sessions_log(int level);
+int cdp_sessions_timer(time_t now, void* ptr);
+
+cdp_session_t* cdp_get_session(str id);
+cdp_session_t* cdp_new_session(str id,cdp_session_type_t type); //this function is needed in the peerstatemachine
+void cdp_add_session(cdp_session_t *x);
+cdp_session_t* cdp_new_auth_session(str id,int is_client,int is_statefull);
+
+
+/*           API Exported */
+
+typedef cdp_session_t AAASession;
+
+
+AAASession* AAACreateSession(void *generic_data);
+typedef AAASession* (*AAACreateSession_f)(void *generic_data);
+
+AAASession* AAAMakeSession(int app_id,int type,str session_id);
+typedef AAASession* (*AAAMakeSession_f)(int app_id,int type,str session_id);
+
+AAASession* AAAGetSession(str id);
+typedef AAASession* (*AAAGetSession_f)(str id);
+
+void AAADropSession(AAASession *s);
+typedef void (*AAADropSession_f)(AAASession *s);
+
+void AAASessionsUnlock(unsigned int hash);
+typedef void (*AAASessionsUnlock_f) (unsigned int hash);
+
+void AAASessionsLock(unsigned int hash);
+typedef void (*AAASessionsLock_f) (unsigned int hash);
+
+
+
+
+AAASession* AAACreateClientAuthSession(int is_statefull,AAASessionCallback_f *cb,void *generic_data);
+typedef AAASession* (*AAACreateClientAuthSession_f)(int is_statefull,AAASessionCallback_f *cb,void *generic_data);
+
+AAASession* AAACreateServerAuthSession(AAAMessage *msg,int is_statefull,AAASessionCallback_f *cb,void *generic_data);
+typedef AAASession* (*AAACreateServerAuthSession_f)(AAAMessage *msg,int is_statefull,AAASessionCallback_f *cb,void *generic_data);
+
+AAASession* AAAGetAuthSession(str id);
+typedef AAASession* (*AAAGetAuthSession_f)(str id);
+
+void AAADropAuthSession(AAASession *s);
+typedef void (*AAADropAuthSession_f)(AAASession *s);
+
+void AAATerminateAuthSession(AAASession *s);
+typedef void (*AAATerminateAuthSession_f)(AAASession *s);
+
+
+
+
+AAASession* AAACreateAccSession(void *generic_data);
+void AAADropAccSession(AAASession *s);
+
+
+
+
+#endif

+ 236 - 0
modules/cdp/tcp_accept.c

@@ -0,0 +1,236 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "utils.h"
+#include "globals.h"
+#include "tcp_accept.h"
+#include "receiver.h"
+
+/* defined in ../diameter_peer.c */
+int dp_add_pid(pid_t pid);
+
+
+unsigned int *listening_socks=0;	/**< array of sockets listening for connections */
+
+
+extern int h_errno;
+
+/**
+ * Creates a socket and binds it.
+ * @param listen_port - port to listen to
+ * @param bind_to - IP address to bind to - if empty, will bind to :: (0.0.0.0) (all)
+ * @param sock - socket to be update with the identifier of the opened one
+ * @returns 1 on success, 0 on error
+ */
+int create_socket(int listen_port,str bind_to,unsigned int *sock)
+{
+	unsigned int server_sock=-1;
+	struct addrinfo *ainfo=0,*res=0,hints;
+	char buf[256],host[256],serv[256];
+	int error=0;
+	unsigned int option;
+	
+	memset (&hints, 0, sizeof(hints));
+	//hints.ai_protocol = IPPROTO_SCTP;
+ 	//hints.ai_protocol = IPPROTO_TCP;
+ 	hints.ai_flags = AI_PASSIVE|AI_ADDRCONFIG;
+	hints.ai_socktype = SOCK_STREAM;
+
+	sprintf(buf,"%d",listen_port);
+	
+	if (bind_to.len){
+		error = getaddrinfo(bind_to.s, buf, &hints, &res);
+		if (error!=0){
+			LM_WARN("create_socket(): Error opening %.*s port %d while doing gethostbyname >%s\n",
+				bind_to.len,bind_to.s,listen_port,gai_strerror(error));
+			goto error;
+		}
+	}else{
+		error = getaddrinfo(NULL, buf, &hints, &res);
+		if (error!=0){
+			LM_WARN("create_socket(): Error opening ANY port %d while doing gethostbyname >%s\n",
+				listen_port,gai_strerror(error));
+			goto error;
+		}
+	}
+		
+	LM_DBG("create_sockets: create socket and bind for IPv4...\n");
+
+	for(ainfo = res;ainfo;ainfo = ainfo->ai_next)
+	{
+		if (getnameinfo(ainfo->ai_addr,ainfo->ai_addrlen,
+			host,256,serv,256,NI_NUMERICHOST|NI_NUMERICSERV)==0){
+				LM_WARN("create_socket(): Trying to open/bind/listen on %s port %s\n",
+					host,serv);
+		}				
+
+		if ((server_sock = socket(ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol)) == -1) {
+			LM_ERR("create_socket(): error creating server socket on %s port %s >"
+				" %s\n",host,serv,strerror(errno));
+			goto error;
+		}
+		option = 1;
+		setsockopt(server_sock,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option));
+		
+		if (bind( 	server_sock,ainfo->ai_addr,ainfo->ai_addrlen)==-1 ) {
+			LM_ERR("create_socket(): error binding on %s port %s >"
+				" %s\n",host,serv,strerror(errno));
+			goto error;
+		}
+	
+		if (listen( server_sock, 5) == -1) {
+			LM_ERR("create_socket(): error listening on %s port %s > %s\n",host,serv,strerror(errno) );
+			goto error;
+		}
+	
+		*sock = server_sock;	
+		
+		LM_WARN("create_socket(): Successful socket open/bind/listen on %s port %s\n",
+					host,serv);
+	}
+	if (res) freeaddrinfo(res);	
+	return 1;
+error:
+	if (res) freeaddrinfo(res);
+	if (server_sock!=-1) close(server_sock);
+	return 0;
+	
+}
+
+/**
+ * Accepts an incoming connection by forking a receiver process.
+ * @param server_sock - socket that this connection came in to
+ * @param new_sock - socket to be update with the value of the accepter socket
+ * @returns 1 on success, 0 on error
+ */
+inline static int accept_connection(int server_sock,int *new_sock)
+{
+	unsigned int length;
+	struct sockaddr_in remote;
+		
+	/* do accept */
+	length = sizeof( struct sockaddr_in);
+	*new_sock = accept( server_sock, (struct sockaddr*)&remote, &length);
+
+	if (*new_sock==-1) {
+		LM_ERR("accept_connection(): accept failed!\n");
+		goto error;
+	} else {
+		LM_INFO("accept_connection(): new tcp connection accepted!\n");
+		
+	}
+	
+	receiver_send_socket(*new_sock,0);
+	
+	return 1;
+error:
+	return 0;
+}
+
+/**
+ * Accept loop that listens for incoming connections on all listening sockets.
+ * When a connection is received, accept_connection() is called.
+ * @returns only on shutdown
+ */
+void accept_loop()
+{
+	fd_set listen_set;
+	struct timeval timeout;
+	int i=0,max_sock=0,nready;
+	int new_sock;
+	
+
+	while(listening_socks[i]){
+		if (listening_socks[i]>max_sock) max_sock=listening_socks[i];
+		i++;
+	}
+
+	while(1){
+		if (shutdownx && *shutdownx) break;
+		
+		timeout.tv_sec=2;
+		timeout.tv_usec=0;	
+		FD_ZERO(&listen_set);
+		i=0;
+		while(listening_socks[i]){
+			FD_SET(listening_socks[i],&listen_set);					
+			i++;
+		}
+
+		nready = select( max_sock+1, &listen_set, 0, 0, &timeout);
+		if (nready == 0){
+			LM_DBG("accept_loop(): No connection attempts\n");
+			continue;
+		}
+		if (nready == -1) {
+			if (errno == EINTR) {
+				continue;
+			} else {
+				LM_ERR("accept_loop(): select fails: %s\n",
+					strerror(errno));
+				sleep(2);
+				continue;
+			}
+		}
+
+		i=0;
+		while(listening_socks[i]){
+			if (FD_ISSET(listening_socks[i],&listen_set)){
+				accept_connection(listening_socks[i],&new_sock);
+			}
+			i++;
+		}
+	}
+}
+

+ 51 - 0
modules/cdp/tcp_accept.h

@@ -0,0 +1,51 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __TCP_ACCEPT_H
+#define __TCP_ACCEPT_H
+
+
+
+int create_socket(int listen_port,str bind_to,unsigned int *sock);
+
+void accept_loop();
+
+#endif
+

+ 221 - 0
modules/cdp/timer.c

@@ -0,0 +1,221 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <time.h> 
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "utils.h"
+#include "globals.h"
+#include "worker.h"
+
+#include "timer.h"
+
+
+/* defined in ../diameter_peer.c */
+int dp_add_pid(pid_t pid);
+void dp_del_pid(pid_t pid);
+
+
+timer_cb_list_t *timers=0;	/**< list of timers */
+gen_lock_t *timers_lock=0;	/**< lock for the list of timers */
+
+/** how many seconds to sleep on each timer iteration */
+#define TIMER_RESOLUTION 1
+
+/**
+ * Loop that checks every #TIMER_RESOLUTION seconds if some timer expired.
+ * On expires, the callback is called. The callback should return rapidly
+ * in order to avoid blocking the timer process. If the timer is "one_time",
+ * then it is removed from the timers list.
+ * @returns on shutdown
+ */
+void timer_loop()
+{
+	time_t now;
+	timer_cb_t *i;
+	callback_f cb=0;
+	void *ptr=0;
+	int interval=0;
+	
+	while(1){
+		if (shutdownx && *shutdownx) break;
+		now = time(0);
+	
+		do {
+			cb = 0;
+			lock_get(timers_lock);
+				i = timers->head;
+				while(i && i->expires>now) i = i->next;
+				if (i){
+					cb = i->cb;
+					ptr = *(i->ptr);
+					if (i->one_time){
+						if (i->prev) i->prev->next = i->next;
+						else timers->head = i->next;
+						if (i->next) i->next->prev = i->prev;
+						else timers->tail = i->next;
+						shm_free(i);
+						i=0;
+					}
+				}
+			lock_release(timers_lock);
+	
+			if (cb) { 
+				interval = cb(now,ptr);
+				if (i){
+					lock_get(timers_lock);
+						i->expires = now + interval;
+					lock_release(timers_lock);
+				}
+			}
+	
+		} while(cb);
+				
+		sleep(TIMER_RESOLUTION);
+	}
+}
+
+/**
+ * Adds a timer to the timer list.
+ * @param expires_in - time until expiration in seconds
+ * @param one_time - if after expiration it should be removed or kept in the timers list
+ * @param cb - callback function to be called on expiration
+ * @param ptr - generic pointer to pass to the callback on expiration
+ * @returns 1 on success or 0 on failure
+ */
+int add_timer(int expires_in,int one_time,callback_f cb,void *ptr)
+{
+	timer_cb_t *n;
+	if (expires_in==0){
+		LM_ERR("add_timer(): Minimum expiration time is 1 second!\n");
+		return 0;
+	}
+	n = shm_malloc(sizeof(timer_cb_t));
+	if (!n){
+		LOG_NO_MEM("shm",sizeof(timer_cb_t));
+		return 0;
+	}
+	n->ptr = shm_malloc(sizeof(void*));
+	if (!n){
+		LOG_NO_MEM("shm",sizeof(void*));
+		shm_free(n);
+		return 0;
+	}
+	n->expires = expires_in + time(0);
+	n->one_time = one_time;
+	//n->interval = expires_in;
+	n->cb = cb;
+	*(n->ptr) = ptr;
+
+	lock_get(timers_lock);
+		n->prev = timers->tail;
+		n->next = 0;
+		if (!timers->head) timers->head = n;
+		if (timers->tail) timers->tail->next = n;
+		timers->tail = n;
+	lock_release(timers_lock);
+	return 1;
+}
+
+/**
+ * Init the timer structures
+ */
+void timer_cdp_init()
+{
+	timers = shm_malloc(sizeof(timer_cb_list_t));
+	timers->head=0;
+	timers->tail=0;
+	timers_lock = lock_alloc();
+	timers_lock = lock_init(timers_lock);	
+}
+
+/**
+ * Destroy the timer structures
+ */
+void timer_cdp_destroy()
+{
+	timer_cb_t *n,*i;
+/*	lock_get(timers_lock);*/
+	i = timers->head;
+	while(i){
+		n = i->next;
+		if (i->ptr) shm_free(i->ptr);
+		shm_free(i);
+		i = n;
+	}
+	shm_free(timers);
+	lock_destroy(timers_lock);
+	lock_dealloc((void*)timers_lock);
+}
+
+/**
+ * Timer Process function.
+ * It calls timer_loop().
+ * @param returns - whether on shutdown this function should return or exit
+ * @returns if returns is set then on shutdown, else never and on shutdown it exits
+ */
+void timer_process(int returns)
+{
+	LM_INFO("Timer process starting up...\n");
+		
+	timer_loop();
+	
+	LM_INFO("... Timer process finished\n");
+	if (!returns) {
+#ifdef CDP_FOR_SER
+#else
+#ifdef PKG_MALLOC
+	#ifdef PKG_MALLOC
+		LM_DBG("Timer Memory status (pkg):\n");
+		//pkg_status();
+		#ifdef pkg_sums
+			pkg_sums();
+		#endif 
+	#endif
+#endif
+		dp_del_pid(getpid());		
+#endif		
+		
+		exit(0);
+	}
+}
+
+

+ 78 - 0
modules/cdp/timer.h

@@ -0,0 +1,78 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __TIMERCDP_H
+#define __TIMERCDP_H
+
+#include "worker.h"
+
+/** callback function for timer event */
+typedef int (*callback_f)(time_t now,void *ptr);
+
+/** timer element */
+typedef struct _timer_cb_t{
+	time_t expires;		/**< time of expiration */
+	int one_time;		/**< if to trigger the event just one_time and then remove */
+	callback_f cb;		/**< callback function to be called on timer expiration */
+	void **ptr;			/**< generic parameter to call the callback with		*/
+	
+	struct _timer_cb_t *next;/**< next timer in the timer list */
+	struct _timer_cb_t *prev;/**< previous timer in the timer list */	
+} timer_cb_t;
+
+/** timer list */
+typedef struct {
+	timer_cb_t *head;	/**< first element in the timer list */
+	timer_cb_t *tail;	/**< last element in the timer list */
+} timer_cb_list_t;
+
+int add_timer(int expires_in,int one_time,callback_f cb,void *ptr);
+
+void timer_cdp_init();
+
+void timer_cdp_destroy();
+
+
+void timer_process(int returns);
+
+
+
+#endif
+

+ 244 - 0
modules/cdp/transaction.c

@@ -0,0 +1,244 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "transaction.h"
+
+#include "timer.h"
+#include "globals.h"
+
+
+cdp_trans_list_t *trans_list=0;		/**< list of transactions */
+
+/**
+ * Initializes the transaction structure.
+ * Also adds a timer callback for checking the transaction statuses
+ * @returns 1 if success or 0 on error
+ */
+int cdp_trans_init()
+{
+	trans_list = shm_malloc(sizeof(cdp_trans_list_t));
+	if (!trans_list){
+		LOG_NO_MEM("shm",sizeof(cdp_trans_list_t));
+		return 0;
+	}
+	trans_list->head = 0;
+	trans_list->tail = 0;
+	trans_list->lock = lock_alloc();
+	trans_list->lock = lock_init(trans_list->lock);
+
+	add_timer(1,0,cdp_trans_timer,0);
+	return 1;
+}
+
+int cdp_trans_destroy()
+{
+	cdp_trans_t *t=0;
+	if (trans_list){
+		lock_get(trans_list->lock);
+		while(trans_list->head){
+			t = trans_list->head;
+			trans_list->head = t->next;
+			cdp_free_trans(t);
+		}		
+		lock_destroy(trans_list->lock);
+		lock_dealloc((void*)trans_list->lock);
+		shm_free(trans_list);
+		trans_list = 0;
+	}
+	
+	return 1;
+}
+/**
+ * Create and add a transaction to the transaction list.
+ * @param msg - the message that this related to
+ * @param cb - callback to be called on response or time-out
+ * @param ptr - generic pointer to pass to the callback on call
+ * @param timeout - timeout time in seconds
+ * @param auto_drop - whether to auto drop the transaction on event, or let the application do it later
+ * @returns the created cdp_trans_t* or NULL on error 
+ */
+inline cdp_trans_t* cdp_add_trans(AAAMessage *msg,AAATransactionCallback_f *cb, void *ptr,int timeout,int auto_drop)
+{
+	cdp_trans_t *x;
+	x = shm_malloc(sizeof(cdp_trans_t));
+	if (!x) {
+		LOG_NO_MEM("shm",sizeof(cdp_trans_t));
+		return 0;
+	}
+	x->ptr = shm_malloc(sizeof(void*));
+	if (!x->ptr) {
+		LOG_NO_MEM("shm",sizeof(void*));
+		shm_free(x);
+		return 0;
+	}
+	x->endtoendid = msg->endtoendId;
+	x->hopbyhopid = msg->hopbyhopId;
+	x->cb = cb;
+	*(x->ptr) = ptr;
+	x->expires = timeout + time(0);
+	x->auto_drop = auto_drop;
+	x->next = 0;
+
+	lock_get(trans_list->lock);
+	x->prev = trans_list->tail;
+	if (trans_list->tail) trans_list->tail->next = x;
+	trans_list->tail = x;
+	if (!trans_list->head) trans_list->head = x;
+	lock_release(trans_list->lock);
+	return x;
+}
+
+/**
+ * Remove from the list and deallocate a transaction.
+ * @param msg - the message that relates to that particular transaction
+ */
+inline void del_trans(AAAMessage *msg)
+{
+	cdp_trans_t *x;
+	lock_get(trans_list->lock);
+	x = trans_list->head;
+	while(x&& x->endtoendid!=msg->endtoendId && x->hopbyhopid!=msg->hopbyhopId) x = x->next;
+	if (x){
+		if (x->prev) x->prev->next = x->next;
+		else trans_list->head = x->next;
+		if (x->next) x->next->prev = x->prev;
+		else trans_list->tail = x->prev;
+		cdp_free_trans(x);
+	}
+	lock_release(trans_list->lock);
+}
+
+/**
+ * Return and remove the transaction from the transaction list.
+ * @param msg - the message that this transaction relates to
+ * @returns the cdp_trans_t* if found or NULL if not
+ */
+inline cdp_trans_t* cdp_take_trans(AAAMessage *msg)
+{
+	cdp_trans_t *x;
+	lock_get(trans_list->lock);
+	x = trans_list->head;
+	while(x&& x->endtoendid!=msg->endtoendId && x->hopbyhopid!=msg->hopbyhopId) x = x->next;
+	if (x){
+		if (x->prev) x->prev->next = x->next;
+		else trans_list->head = x->next;
+		if (x->next) x->next->prev = x->prev;
+		else trans_list->tail = x->prev;
+	}
+	lock_release(trans_list->lock);
+	return x;
+}
+
+/**
+ * Deallocate the memory taken by a transaction.
+ * @param x - the transaction to deallocate
+ */
+inline void cdp_free_trans(cdp_trans_t *x)
+{
+	if (x->ptr) shm_free(x->ptr);
+	shm_free(x);
+}
+
+/**
+ * Timer callback for checking the transaction status.
+ * @param now - time of call
+ * @param ptr - generic pointer, passed to the transactional callbacks
+ */
+int cdp_trans_timer(time_t now, void* ptr)
+{
+	cdp_trans_t *x,*n;	
+	LM_DBG("trans_timer(): taking care of diameter transactions...\n");
+	lock_get(trans_list->lock);
+	x = trans_list->head;
+	while(x)
+	{
+		if (now>x->expires){
+			x->ans = 0;
+			if (x->cb){
+				(x->cb)(1,*(x->ptr),0);
+			}
+			n = x->next;
+			
+			if (x->prev) x->prev->next = x->next;
+			else trans_list->head = x->next;
+			if (x->next) x->next->prev = x->prev;
+			else trans_list->tail = x->prev;
+			if (x->auto_drop) cdp_free_trans(x);
+			
+			x = n;
+		} else 
+			x = x->next;
+	}
+	lock_release(trans_list->lock);
+	return 1;
+}
+
+
+
+/* TRANSACTIONS */
+
+/**
+* Create a AAATransaction for the given request.
+* @param app_id - id of the request's application
+* @param cmd_code - request's code
+* @returns the AAATransaction*
+*/				
+AAATransaction *AAACreateTransaction(AAAApplicationId app_id,AAACommandCode cmd_code)
+{
+	AAATransaction *t;
+	t = shm_malloc(sizeof(AAATransaction));
+	if (!t) return 0;
+	memset(t,0,sizeof(AAATransaction));	
+	t->application_id=app_id;
+	t->command_code=cmd_code;			
+	return t;
+}
+
+/**
+* Free the memory allocated for the AAATransaction.
+* @param trans - the AAATransaction to be deallocated
+* @returns 1 on success, 0 on failure
+*/
+int AAADropTransaction(AAATransaction *trans)
+{
+	if (!trans) return 0;
+	shm_free(trans);
+	return 1;
+}

+ 91 - 0
modules/cdp/transaction.h

@@ -0,0 +1,91 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __TRANSACTION_H_
+#define __TRANSACTION_H_
+
+#include <time.h>
+#include "utils.h"
+#include "diameter.h"
+#include "diameter_api.h"
+
+/** Diameter Transaction representation */
+typedef struct _cdp_trans_t{
+	AAAMsgIdentifier endtoendid;	/**< End-to-end id of the messages */
+	AAAMsgIdentifier hopbyhopid;	/**< Hop-by-hop id of the messages */
+	AAATransactionCallback_f *cb;	/**< transactional callback function */
+	void **ptr;						/**< generic pointer to pass to the callback */
+	AAAMessage *ans;				/**< answer for the transaction */
+	time_t expires;					/**< time of expiration, when a time-out event will happen */
+	int auto_drop;					/**< if to drop automatically the transaction on event or to let the app do it later */
+	struct _cdp_trans_t *next;		/**< the next transaction in the transaction list */
+	struct _cdp_trans_t *prev;		/**< the previous transaction in the transaction list */
+} cdp_trans_t;
+
+/** Diameter Transaction list */
+typedef struct {		
+	gen_lock_t *lock;				/**< lock for list operations */
+	cdp_trans_t *head,*tail;		/**< first, last transactions in the list */ 
+} cdp_trans_list_t;
+
+int cdp_trans_init();
+int cdp_trans_destroy();
+
+inline cdp_trans_t* cdp_add_trans(AAAMessage *msg,AAATransactionCallback_f *cb, void *ptr,int timeout,int auto_drop);
+void del_trans(AAAMessage *msg);
+inline cdp_trans_t* cdp_take_trans(AAAMessage *msg);
+inline void cdp_free_trans(cdp_trans_t *x);
+
+int cdp_trans_timer(time_t now, void* ptr);
+
+/*            API Exported    */
+
+/** Timeout for Diameter transactions (this is quite big, 
+ * but increase in case that you have a slow peer) */ 				
+
+AAATransaction *AAACreateTransaction(AAAApplicationId app_id,AAACommandCode cmd_code);
+typedef AAATransaction * (*AAACreateTransaction_f)(AAAApplicationId app_id,AAACommandCode cmd_code);
+
+int AAADropTransaction(AAATransaction *trans);
+typedef int (*AAADropTransaction_f)(AAATransaction *trans);
+
+
+
+#endif /*TRANSACTION_H_*/

+ 67 - 0
modules/cdp/utils.h

@@ -0,0 +1,67 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __CDP_UTILS_H_
+#define __CDP_UTILS_H_
+
+#include "../../dprint.h"
+#include "../../str.h"
+#include "../../mem/mem.h"
+#include "../../mem/shm_mem.h"
+#include "../../locking.h"
+#include "../../pt.h"
+#include "sem.h" 
+
+#ifndef LOG_NO_MEM
+	#define LOG_NO_MEM(mem_type,data_len) \
+		LM_ERR("%s:%s()[%d]: Out of %s memory allocating %lx bytes\n",\
+			__FILE__,__FUNCTION__,__LINE__, \
+			mem_type,(unsigned long)data_len);
+#endif
+
+
+#define shm_str_dup_macro(dst,src)\
+{\
+	(dst).s = shm_malloc((src).len+1);\
+	if (!(dst).s){LOG_NO_MEM("shm",(src).len+1);}\
+	else {memcpy((dst).s,(src).s,(src).len);(dst).s[(src).len]=0;(dst).len=(src).len;}\
+}
+
+#endif /*UTILS_H_*/

+ 332 - 0
modules/cdp/worker.c

@@ -0,0 +1,332 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include <time.h> 
+#include <stdlib.h>
+#include <sys/types.h> 
+#include <unistd.h> 
+#include <sys/ipc.h>
+#include <sys/sem.h>
+
+#include "utils.h"
+#include "globals.h"
+#include "config.h"
+
+#include "worker.h"
+#include "diameter_api.h"
+
+/* defined in ../diameter_peer.c */
+int dp_add_pid(pid_t pid);
+void dp_del_pid(pid_t pid);
+
+extern dp_config *config;		/**< Configuration for this diameter peer 	*/
+
+task_queue_t *tasks;			/**< queue of tasks */
+
+cdp_cb_list_t *callbacks;		/**< list of callbacks for message processing */
+
+
+
+/**
+ * Initializes the worker structures, like the task queue.
+ */
+void worker_init()
+{
+	tasks = shm_malloc(sizeof(task_queue_t));
+	
+	tasks->lock = lock_alloc();
+	tasks->lock = lock_init(tasks->lock);
+	
+	sem_new(tasks->empty,0);
+		
+	sem_new(tasks->full,1);
+		
+	tasks->start = 0;
+	tasks->end = 0;
+	tasks->max = config->queue_length;
+	tasks->queue = shm_malloc(tasks->max*sizeof(task_t));
+	if (!tasks->queue) {
+		LOG_NO_MEM("shm",tasks->max*sizeof(task_t));
+		goto out_of_memory;
+	}
+	memset(tasks->queue,0,tasks->max*sizeof(task_t));
+		
+	callbacks = shm_malloc(sizeof(cdp_cb_list_t));
+	if (!callbacks) goto out_of_memory;
+	callbacks->head = 0; 
+	callbacks->tail = 0;
+	return;
+out_of_memory:
+	if (tasks){
+		if (tasks->lock) {
+			lock_destroy(tasks->lock);
+			lock_dealloc(&(tasks->lock)); 
+		}
+		sem_free(tasks->full);
+		sem_free(tasks->empty);
+		if (tasks->queue) shm_free(tasks->queue);
+		shm_free(tasks);
+	}
+	if (callbacks) shm_free(callbacks);
+}
+
+/**
+ * Destroys the worker structures. 
+ */
+void worker_destroy()
+{
+	int i,sval=0;
+	if (callbacks){
+		while(callbacks->head)
+			cb_remove(callbacks->head);
+		shm_free(callbacks);
+	}
+
+	// to deny runing the poison queue again
+	config->workers = 0;
+	if (tasks) {
+		lock_get(tasks->lock);
+		for(i=0;i<tasks->max;i++){
+			if (tasks->queue[i].msg) AAAFreeMessage(&(tasks->queue[i].msg));
+			tasks->queue[i].msg = 0;
+			tasks->queue[i].p = 0;
+		}
+		lock_release(tasks->lock);
+
+		LM_INFO("Unlocking workers waiting on empty queue...\n");
+		for(i=0;i<config->workers;i++)
+			sem_release(tasks->empty);
+		LM_INFO("Unlocking workers waiting on full queue...\n");
+		i=0;
+		while(sem_getvalue(tasks->full,&sval)==0)			
+			if (sval<=0) {
+				sem_release(tasks->full);
+				i=1;
+			}
+			else break;
+		sleep(i);
+		
+		lock_get(tasks->lock);
+		shm_free(tasks->queue);
+		lock_destroy(tasks->lock);
+		lock_dealloc((void*)tasks->lock);
+		
+		//lock_release(tasks->empty);
+		sem_free(tasks->full);
+		sem_free(tasks->empty);
+		
+		shm_free(tasks);
+	}
+}
+
+/*unsafe*/
+int cb_add(cdp_cb_f cb,void *ptr)
+{
+	cdp_cb_t *x;
+	x = shm_malloc(sizeof(cdp_cb_t));
+	if (!x){
+		LOG_NO_MEM("shm",sizeof(cdp_cb_t));
+		return 0;
+	}
+	x->cb = cb;
+	x->ptr = shm_malloc(sizeof(void*));
+	if (!x->ptr){
+		LOG_NO_MEM("shm",sizeof(void*));
+		return 0;
+	}
+	*(x->ptr) = ptr;
+	x->next = 0;
+	x->prev = callbacks->tail;
+	if (callbacks->tail) callbacks->tail->next = x;
+	callbacks->tail = x;
+	if (!callbacks->head) callbacks->head = x;
+	return 1;	
+}
+
+/*unsafe*/
+void cb_remove(cdp_cb_t *cb)
+{
+	cdp_cb_t *x;
+	x = callbacks->head;
+	while(x && x!=cb) x = x->next;
+	if (!x) return;
+	if (x->prev) x->prev->next = x->next;
+	else callbacks->head = x->next;
+	if (x->next) x->next->prev = x->prev;
+	else callbacks->tail = x->prev;
+	
+	if (x->ptr) shm_free(x->ptr);
+	shm_free(x);
+}
+
+/**
+ * Adds a message as a task to the task queue.
+ * This blocks if the task queue is full, until there is space.
+ * @param p - the peer that the message was received from
+ * @param msg - the message
+ * @returns 1 on success, 0 on failure (eg. shutdown in progress)
+ */
+int put_task(peer *p,AAAMessage *msg)
+{
+	lock_get(tasks->lock);
+	while ((tasks->end+1)%tasks->max == tasks->start){
+		lock_release(tasks->lock);
+
+		if (*shutdownx) {
+			sem_release(tasks->full);
+			return 0;
+		}
+
+		sem_get(tasks->full);
+
+		if (*shutdownx) {
+			sem_release(tasks->full);
+			return 0;
+		}
+
+		lock_get(tasks->lock);
+	}
+	tasks->queue[tasks->end].p = p;
+	tasks->queue[tasks->end].msg = msg;
+	tasks->end = (tasks->end+1) % tasks->max;
+	if (sem_release(tasks->empty)<0)
+		LM_WARN("Error releasing tasks->empty semaphore > %s!\n",strerror(errno));
+	lock_release(tasks->lock);
+	return 1;
+}
+	
+/**
+ * Remove and return the first task from the queue (FIFO).
+ * This blocks until there is something in the queue.
+ * @returns the first task from the queue or an empty task on error (eg. shutdown in progress)
+ */
+task_t take_task()
+{
+	task_t t={0,0};
+	lock_get(tasks->lock);
+	while(tasks->start == tasks->end){
+		lock_release(tasks->lock);
+		if (*shutdownx) {
+			sem_release(tasks->empty);
+			return t;
+		}
+		sem_get(tasks->empty);
+		if (*shutdownx) {
+			sem_release(tasks->empty);
+			return t;
+		}
+		
+		lock_get(tasks->lock);
+	}
+	
+	t = tasks->queue[tasks->start];
+	tasks->queue[tasks->start].msg = 0;
+	tasks->start = (tasks->start+1) % tasks->max;
+	if (sem_release(tasks->full)<0)
+		LM_WARN("Error releasing tasks->full semaphore > %s!\n",strerror(errno));
+	lock_release(tasks->lock);
+	return t;
+}
+
+/**
+ * Poisons the worker queue.
+ * Actually it just releases the task queue locks so that the workers get to evaluate
+ * if a shutdown is in process and exit.
+ */
+void worker_poison_queue()
+{
+	int i;
+	if (config->workers&&tasks)
+	for(i=0;i<config->workers;i++)
+		if (sem_release(tasks->empty)<0)
+			LM_WARN("Error releasing tasks->empty semaphore > %s!\n",strerror(errno));
+}
+
+
+
+/**
+ * This is the main worker process.
+ * Takes tasks from the queue in a loop and processes them by calling the registered callbacks.
+ * @param id - id of the worker
+ * @returns never, exits on shutdown.
+ */
+void worker_process(int id)
+{
+	task_t t;
+	cdp_cb_t *cb;
+	int r;
+	LM_INFO("[%d] Worker process started...\n",id);	
+	/* init the application level for this child */
+	while(1){
+		if (shutdownx&&(*shutdownx)) break;
+		t = take_task();
+		if (!t.msg) {
+			if (shutdownx&&(*shutdownx)) break;
+			LM_INFO("[%d] got empty task Q(%d/%d)\n",id,tasks->start,tasks->end);
+			continue;
+		}		
+		LM_DBG("worker_process(): [%d] got task Q(%d/%d)\n",id,tasks->start,tasks->end);
+		r = is_req(t.msg);
+		for(cb = callbacks->head;cb;cb = cb->next)
+			(*(cb->cb))(t.p,t.msg,*(cb->ptr));
+		
+		if (r){
+			AAAFreeMessage(&(t.msg));
+		}else{
+			/* will be freed by the user in upper api */
+			/*AAAFreeMessage(&(t.msg));*/
+		}
+	}
+	worker_poison_queue();
+	LM_INFO("[%d]... Worker process finished\n",id);	
+#ifdef CDP_FOR_SER
+#else
+	#ifdef PKG_MALLOC
+		LM_DBG("Worker[%d] Memory status (pkg):\n",id);
+		//pkg_status();
+		#ifdef pkg_sums
+			pkg_sums();
+		#endif 
+	#endif
+	dp_del_pid(getpid());	
+#endif
+	exit(0);
+}
+

+ 102 - 0
modules/cdp/worker.h

@@ -0,0 +1,102 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __WORKER_H
+#define __WORKER_H
+
+#include "peer.h"
+#include "diameter.h"
+#include "utils.h"
+
+/** function to be called on worker initialization */
+typedef int (*worker_init_function)(int rank);
+
+/** task element */ 
+typedef struct _task_t {
+	peer *p;			/**< peer that the message was received from */
+	AAAMessage *msg;	/**< diameter message received */
+} task_t;
+
+/** task queue */
+typedef struct {
+	gen_lock_t *lock;	/**< lock for task queue operations */ 
+	int start;			/**< start position in the queue array (index of oldest task) */
+	int end;			/**< end position in the queue array (index of the youngest task) */
+	int max;			/**< size of the queue array */
+	task_t *queue;		/**< array holding the tasks */
+	gen_sem_t *empty;	/**< id of semaphore for signaling an empty queue */
+	gen_sem_t *full;	/**< id of semaphore for signaling an full queue */
+} task_queue_t;
+
+/** callback function to be called on message processing */
+typedef int (*cdp_cb_f)(peer *p,AAAMessage *msg,void* ptr);
+
+/** callback element for message processing */
+typedef struct _cdp_cb_t{
+	cdp_cb_f cb;				/**< callback function to be called on event */
+	void **ptr;					/**< generic pointer to be passed to the callback */
+	struct _cdp_cb_t *next; 	/**< next callback in the list */
+	struct _cdp_cb_t *prev;		/**< previous callback in the list */
+} cdp_cb_t;
+	
+/** list of callback elements for message processing */
+typedef struct {
+	cdp_cb_t *head;	/**< first element in the list */
+	cdp_cb_t *tail; /**< last element in the list */
+} cdp_cb_list_t;
+
+void worker_init();
+void worker_destroy();
+
+int cb_add(cdp_cb_f cb,void *ptr);
+void cb_remove(cdp_cb_t *cb);
+
+int put_task(peer *p,AAAMessage *msg);
+task_t take_task();
+
+
+void worker_poison_queue();
+
+void worker_process(int id);
+
+
+
+#endif
+

+ 10 - 0
modules/cdp_avp/Makefile

@@ -0,0 +1,10 @@
+include ../../Makefile.defs
+
+
+NAME=cdp_avp.so
+
+DEFS+=-DSER_MOD_INTERFACE
+DEFS += -I/usr/include/libxml2 
+
+include ../../Makefile.modules
+

+ 1688 - 0
modules/cdp_avp/README

@@ -0,0 +1,1688 @@
+cdp_avp Module
+
+Dragos Vingarzan
+
+   Fraunhofer
+
+Edited by
+
+Jason Penton
+
+Edited by
+
+Richard Good
+
+   Copyright © 2006 FhG Fokus
+
+   Copyright © 2012 Smile Communications
+     __________________________________________________________________
+
+   Table of Contents
+
+   1. Admin Guide
+
+        1. Overview
+        2. How it works
+        3. Dependencies
+
+              3.1. Kamailio Modules
+              3.2. External Libraries or Applications
+
+        4. Parameters
+        5. Functions
+
+   2. Developer Guide
+
+        1. How to use
+        2. Reference Functions
+
+              2.1. nasapp
+              2.2. imsapp
+              2.3. epcapp
+              2.4. ccapp
+              2.5. base
+
+   3. Frequently Asked Questions
+
+Chapter 1. Admin Guide
+
+   Table of Contents
+
+   1. Overview
+   2. How it works
+   3. Dependencies
+
+        3.1. Kamailio Modules
+        3.2. External Libraries or Applications
+
+   4. Parameters
+   5. Functions
+
+1. Overview
+
+   CDP AVP is a helper module for various applications ontop of CDP (C
+   Diameter Peer). CDP AVP modules adds support for the following
+   applications:
+     * Various base AVPs (implemented in base.h) for RFC3588 base AVPs
+     * Base AVPs (implemented in nasapp.h) for RFC4005 base AVPs
+     * Diameter Credit Control App (implemented in ccap.h) for RFC4006
+       AVPs
+     * EPC (implemented in epcapp.h) for 3GPP Rx, Gx(x) interface AVPs -
+       see TS29l061, TS29.212, TS29.214, TS29.272 and TS29.299
+     * IMS (implemented in imsapp.h) for 3GPP IMS AVPs, Cx, Dx, Sh
+       interfaces - see TS29.229 and TS29.329
+
+2. How it works
+
+   CDP AVP is a lightwieght helper module that doesn't really do much
+   other than offer a set of AVP facilitating functions for various
+   application uses. CDP AVP module is used in conjunction with CDP
+   module.
+
+3. Dependencies
+
+   3.1. Kamailio Modules
+   3.2. External Libraries or Applications
+
+3.1. Kamailio Modules
+
+   The following modules must be loaded before this module:
+     * CDP.
+
+3.2. External Libraries or Applications
+
+   The following libraries or applications must be installed before
+   running Kamailio with this module loaded:
+     * None.
+
+4. Parameters
+
+   None
+
+5. Functions
+
+   No functions available from configuraion. See API for internal
+   functions.
+
+Chapter 2. Developer Guide
+
+   Table of Contents
+
+   1. How to use
+   2. Reference Functions
+
+        2.1. nasapp
+        2.2. imsapp
+        2.3. epcapp
+        2.4. ccapp
+        2.5. base
+
+1. How to use
+
+   Listing all possible functions here would be overkill and it is left to
+   the developer to browse the varoius function prototypes in the source.
+   It may however be valuable to give a few code snippets to show how to
+   use this module. The API structure used to export the various functions
+   looks as follows:
+typedef struct {
+struct cdp_binds *cdp;
+cdp_avp_bind_basic_t basic;
+cdp_avp_bind_base_data_format_t data;
+cdp_avp_bind_base_avp_t base;
+cdp_avp_bind_ccapp_avp_t ccapp;
+cdp_avp_bind_nasapp_avp_t nasapp;
+cdp_avp_bind_imsapp_avp_t imsapp;
+cdp_avp_bind_epcapp_avp_t epcapp;
+} cdp_avp_bind_t;
+
+2. Reference Functions
+
+   2.1. nasapp
+   2.2. imsapp
+   2.3. epcapp
+   2.4. ccapp
+   2.5. base
+
+   The Following is a list of functions for the various supported
+   applications
+
+2.1. nasapp
+
+int nasapp.add_Accounting_Input_Octets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Input_Packets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Output_Octets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Output_Packets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Called_Station_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int nasapp.add_Filter_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int nasapp.add_Framed_IP_Address(AAA_AVP_LIST *list,ip_address ip);
+int nasapp.add_Framed_IPv6_Prefix(AAA_AVP_LIST *list,ip_address_prefix ip);
+int nasapp.get_Accounting_Input_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP
+**avp_ptr);
+int nasapp.get_Accounting_Input_Packets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP
+ **avp_ptr);
+int nasapp.get_Accounting_Output_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP
+ **avp_ptr);
+int nasapp.get_Accounting_Output_Packets(AAA_AVP_LIST list,uint64_t *data,AAA_AV
+P **avp_ptr);
+int nasapp.get_Called_Station_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int nasapp.get_Filter_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int nasapp.get_Framed_IP_Address(AAA_AVP_LIST list,ip_address *ip,AAA_AVP **avp_
+ptr);
+int nasapp.get_Framed_IPv6_Prefix(AAA_AVP_LIST list,ip_address_prefix *ip,AAA_AV
+P **avp_ptr);
+
+2.2. imsapp
+
+int imsapp.add_Associated_Identities(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int imsapp.add_Associated_Registered_Identities(AAA_AVP_LIST *list,AAA_AVP_LIST*
+ data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_Algorithm(AAA_AVP_LIST *list,str data,AVPDataSta
+tus data_do);
+int imsapp.add_CableLabs_Digest_Auth_Param(AAA_AVP_LIST *list,str data,AVPDataSt
+atus data_do);
+int imsapp.add_CableLabs_Digest_Domain(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int imsapp.add_CableLabs_Digest_HA1(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int imsapp.add_CableLabs_Digest_QoP(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int imsapp.add_CableLabs_Digest_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int imsapp.add_CableLabs_SIP_Digest_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST
+* data,AVPDataStatus data_do);
+int imsapp.add_Charging_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDat
+aStatus data_do);
+int imsapp.add_Confidentiality_Key(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int imsapp.add_Contact(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Current_Location(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Data_Reference(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Deregistration_Reason(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int imsapp.add_DSAI_Tag(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Algorithm(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int imsapp.add_ETSI_Digest_Auth_Param(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int imsapp.add_ETSI_Digest_CNonce(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int imsapp.add_ETSI_Digest_Domain(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int imsapp.add_ETSI_Digest_Entity_Body_Hash(AAA_AVP_LIST *list,str data,AVPDataS
+tatus data_do);
+int imsapp.add_ETSI_Digest_HA1(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_ETSI_Digest_Method(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int imsapp.add_ETSI_Digest_Nextnonce(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int imsapp.add_ETSI_Digest_Nonce(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int imsapp.add_ETSI_Digest_Nonce_Count(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int imsapp.add_ETSI_Digest_Opaque(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int imsapp.add_ETSI_Digest_QoP(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_ETSI_Digest_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int imsapp.add_ETSI_Digest_Response(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int imsapp.add_ETSI_Digest_Response_Auth(AAA_AVP_LIST *list,str data,AVPDataStat
+us data_do);
+int imsapp.add_ETSI_Digest_Stale(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int imsapp.add_ETSI_Digest_URI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_ETSI_Digest_Username(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int imsapp.add_ETSI_Line_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int imsapp.add_ETSI_SIP_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int imsapp.add_ETSI_SIP_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* dat
+a,AVPDataStatus data_do);
+int imsapp.add_ETSI_SIP_Authorization(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int imsapp.add_Expiry_Time(AAA_AVP_LIST *list,time_t data);
+int imsapp.add_Feature_List(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Feature_List_ID(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_From_SIP_Header(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_Identity_Set(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Integrity_Key(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Loose_Route_Indication(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Mandatory_Capability(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_MSISDN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Multiple_Registration_Indication(AAA_AVP_LIST *list,int32_t data)
+;
+int imsapp.add_Optional_Capability(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Originating_Request(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Path(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Primary_Charging_Collection_Function_Name(AAA_AVP_LIST *list,str
+data,AVPDataStatus data_do);
+int imsapp.add_Primary_Event_Charging_Function_Name(AAA_AVP_LIST *list,str data,
+AVPDataStatus data_do);
+int imsapp.add_Public_Identity(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_Reason_Code(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Reason_Info(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Record_Route(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Requested_Domain(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Restoration_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSta
+tus data_do);
+int imsapp.add_SCSCF_Restoration_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int imsapp.add_Secondary_Charging_Collection_Function_Name(AAA_AVP_LIST *list,st
+r data,AVPDataStatus data_do);
+int imsapp.add_Secondary_Event_Charging_Function_Name(AAA_AVP_LIST *list,str dat
+a,AVPDataStatus data_do);
+int imsapp.add_Send_Data_Indication(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Server_Assignment_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Server_Capabilities(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int imsapp.add_Server_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Service_Indication(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int imsapp.add_SIP_Auth_Data_Item(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataS
+tatus data_do);
+int imsapp.add_SIP_Authenticate(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int imsapp.add_SIP_Authentication_Context(AAA_AVP_LIST *list,str data,AVPDataSta
+tus data_do);
+int imsapp.add_SIP_Authentication_Scheme(AAA_AVP_LIST *list,str data,AVPDataStat
+us data_do);
+int imsapp.add_SIP_Authorization(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int imsapp.add_SIP_Digest_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVP
+DataStatus data_do);
+int imsapp.add_SIP_Item_Number(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_SIP_Number_Auth_Items(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Subscription_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int imsapp.add_Subs_Req_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Supported_Applications(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int imsapp.add_Supported_Features(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataS
+tatus data_do);
+int imsapp.add_Supported_Features_Group(AAA_AVP_LIST *list,uint32_t Vendor_Id,ui
+nt32_t Feature_List_ID,uint32_t Feature_List);
+int imsapp.add_To_SIP_Header(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_UAR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_User_Authorization_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_User_Data_Already_Available(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_User_Data_Cx(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_User_Data_Sh(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_User_Identity(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+ data_do);
+int imsapp.add_Visited_Network_Identifier(AAA_AVP_LIST *list,str data,AVPDataSta
+tus data_do);
+int imsapp.add_Wildcarded_IMPU(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int imsapp.add_Wildcarded_PSI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do)
+;
+int imsapp.get_Associated_Identities(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int imsapp.get_Associated_Registered_Identities(AAA_AVP_LIST list,AAA_AVP_LIST *
+data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_Algorithm(AAA_AVP_LIST list,str *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_CableLabs_Digest_Auth_Param(AAA_AVP_LIST list,str *data,AAA_AVP *
+*avp_ptr);
+int imsapp.get_CableLabs_Digest_Domain(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int imsapp.get_CableLabs_Digest_HA1(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_CableLabs_Digest_QoP(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_CableLabs_Digest_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int imsapp.get_CableLabs_SIP_Digest_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST
+*data,AAA_AVP **avp_ptr);
+int imsapp.get_Charging_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+ **avp_ptr);
+int imsapp.get_Confidentiality_Key(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int imsapp.get_Contact(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Current_Location(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_Data_Reference(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_Deregistration_Reason(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int imsapp.get_DSAI_Tag(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Algorithm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int imsapp.get_ETSI_Digest_Auth_Param(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int imsapp.get_ETSI_Digest_CNonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_ETSI_Digest_Domain(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_ETSI_Digest_Entity_Body_Hash(AAA_AVP_LIST list,str *data,AAA_AVP
+**avp_ptr);
+int imsapp.get_ETSI_Digest_HA1(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Method(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_ETSI_Digest_Nextnonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int imsapp.get_ETSI_Digest_Nonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Nonce_Count(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int imsapp.get_ETSI_Digest_Opaque(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_ETSI_Digest_QoP(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Response(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_ETSI_Digest_Response_Auth(AAA_AVP_LIST list,str *data,AAA_AVP **a
+vp_ptr);
+int imsapp.get_ETSI_Digest_Stale(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_URI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Username(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_ETSI_Line_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_ETSI_SIP_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int imsapp.get_ETSI_SIP_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data
+,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_SIP_Authorization(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int imsapp.get_Expiry_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Feature_List(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Feature_List_ID(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_From_SIP_Header(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Identity_Set(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Integrity_Key(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Loose_Route_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_Mandatory_Capability(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int imsapp.get_MSISDN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Multiple_Registration_Indication(AAA_AVP_LIST list,int32_t *data,
+AAA_AVP **avp_ptr);
+int imsapp.get_Optional_Capability(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **av
+p_ptr);
+int imsapp.get_Originating_Request(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int imsapp.get_Path(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Primary_Charging_Collection_Function_Name(AAA_AVP_LIST list,str *
+data,AAA_AVP **avp_ptr);
+int imsapp.get_Primary_Event_Charging_Function_Name(AAA_AVP_LIST list,str *data,
+AAA_AVP **avp_ptr);
+int imsapp.get_Public_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Reason_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Reason_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Record_Route(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Requested_Domain(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_Restoration_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **a
+vp_ptr);
+int imsapp.get_SCSCF_Restoration_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int imsapp.get_Secondary_Charging_Collection_Function_Name(AAA_AVP_LIST list,str
+ *data,AAA_AVP **avp_ptr);
+int imsapp.get_Secondary_Event_Charging_Function_Name(AAA_AVP_LIST list,str *dat
+a,AAA_AVP **avp_ptr);
+int imsapp.get_Send_Data_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **av
+p_ptr);
+int imsapp.get_Server_Assignment_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_Server_Capabilities(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int imsapp.get_Server_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Service_Indication(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int imsapp.get_SIP_Auth_Data_Item(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP *
+*avp_ptr);
+int imsapp.get_SIP_Authenticate(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Authentication_Context(AAA_AVP_LIST list,str *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_SIP_Authentication_Scheme(AAA_AVP_LIST list,str *data,AAA_AVP **a
+vp_ptr);
+int imsapp.get_SIP_Authorization(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Digest_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_
+AVP **avp_ptr);
+int imsapp.get_SIP_Item_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_pt
+r);
+int imsapp.get_SIP_Number_Auth_Items(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_Subscription_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_Subs_Req_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Supported_Applications(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int imsapp.get_Supported_Features(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP *
+*avp_ptr);
+int imsapp.get_Supported_Features_Group(AAA_AVP_LIST list,uint32_t *Vendor_Id,ui
+nt32_t *Feature_List_ID,uint32_t *Feature_List,AAA_AVP **avp_ptr);
+int imsapp.get_To_SIP_Header(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_UAR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Authorization_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP *
+*avp_ptr);
+int imsapp.get_User_Data_Already_Available(AAA_AVP_LIST list,int32_t *data,AAA_A
+VP **avp_ptr);
+int imsapp.get_User_Data_Cx(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Data_Sh(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Identity(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_
+ptr);
+int imsapp.get_Visited_Network_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **
+avp_ptr);
+int imsapp.get_Wildcarded_IMPU(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Wildcarded_PSI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+
+2.3. epcapp
+
+int epcapp.add_3GPP2_MEID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_AAA_Server_Name(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int epcapp.add_3GPP_Charging_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_3GPP_MS_TimeZone(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_3GPP_PDP_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_3GPP_SGSN_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int epcapp.add_3GPP_SGSN_IPv6_Address(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int epcapp.add_3GPP_SGSN_MCC_MNC(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int epcapp.add_3GPP_User_Location_Info(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_Abort_Cause(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Acceptable_Service_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVP
+DataStatus data_do);
+int epcapp.add_Access_Network_Charging_Address(AAA_AVP_LIST *list,ip_address dat
+a);
+int epcapp.add_Access_Network_Charging_Identifier(AAA_AVP_LIST *list,AAA_AVP_LIS
+T* data,AVPDataStatus data_do);
+int epcapp.add_Access_Network_Charging_Identifier_Gx(AAA_AVP_LIST *list,AAA_AVP_
+LIST* data,AVPDataStatus data_do);
+int epcapp.add_Access_Network_Charging_Identifier_Value(AAA_AVP_LIST *list,str d
+ata,AVPDataStatus data_do);
+int epcapp.add_Access_Restriction_Data(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_AF_Application_Identifier(AAA_AVP_LIST *list,str data,AVPDataStat
+us data_do);
+int epcapp.add_AF_Charging_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int epcapp.add_AF_Correlation_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,
+AVPDataStatus data_do);
+int epcapp.add_Alert_Reason(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_All_APN_Configurations_Included_Indicator(AAA_AVP_LIST *list,int3
+2_t data);
+int epcapp.add_Allocation_Retention_Priority(AAA_AVP_LIST *list,AAA_AVP_LIST* da
+ta,AVPDataStatus data_do);
+int epcapp.add_AMBR(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do)
+;
+int epcapp.add_AMBR_Group(AAA_AVP_LIST *list,uint32_t Max_Requested_Bandwidth_UL
+,uint32_t Max_Requested_Bandwidth_DL);
+int epcapp.add_AN_GW_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_ANID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_APN_Aggregate_Max_Bitrate_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_APN_Aggregate_Max_Bitrate_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_APN_Configuration(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int epcapp.add_APN_Configuration_Profile(AAA_AVP_LIST *list,AAA_AVP_LIST* data,A
+VPDataStatus data_do);
+int epcapp.add_APN_OI_Replacement(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int epcapp.add_Application_Provided_Called_Party_Address(AAA_AVP_LIST *list,str
+data,AVPDataStatus data_do);
+int epcapp.add_Application_Server(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int epcapp.add_Application_Server_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* d
+ata,AVPDataStatus data_do);
+int epcapp.add_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_Authorized_QoS(AAA_AVP_LIST *list,str data,AVPDataStatus data_do)
+;
+int epcapp.add_AUTN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Bearer_Control_Mode(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Bearer_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int epcapp.add_Bearer_Operation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Bearer_Usage(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Call_Barring_Infor_List(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVP
+DataStatus data_do);
+int epcapp.add_Called_Asserted_Identity(AAA_AVP_LIST *list,str data,AVPDataStatu
+s data_do);
+int epcapp.add_Called_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int epcapp.add_Calling_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int epcapp.add_Cancellation_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Cause_Code(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Charging_Rule_Base_Name(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_Charging_Rule_Definition(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AV
+PDataStatus data_do);
+int epcapp.add_Charging_Rule_Install(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int epcapp.add_Charging_Rule_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int epcapp.add_Charging_Rule_Remove(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDat
+aStatus data_do);
+int epcapp.add_Charging_Rule_Report(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDat
+aStatus data_do);
+int epcapp.add_Client_Identity(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_CoA_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_CoA_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Codec_Data(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Complete_Data_List_Included_Indicator(AAA_AVP_LIST *list,int32_t
+data);
+int epcapp.add_Content_Disposition(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int epcapp.add_Content_Length(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Content_Size(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Content_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Context_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_CSG_Id(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_CSG_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int epcapp.add_Default_EPS_Bearer_QoS(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int epcapp.add_DSA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_DSR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Early_Media_Description(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVP
+DataStatus data_do);
+int epcapp.add_EPS_Subscribed_QoS_Profile(AAA_AVP_LIST *list,AAA_AVP_LIST* data,
+AVPDataStatus data_do);
+int epcapp.add_Equipment_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_E_UTRAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatu
+s data_do);
+int epcapp.add_Event(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Event_Report_Indication(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVP
+DataStatus data_do);
+int epcapp.add_Event_Trigger(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Event_Type(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus da
+ta_do);
+int epcapp.add_Expiration_Date(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Expires(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_External_Client(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_Flow_Description(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_Flow_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSta
+tus data_do);
+int epcapp.add_Flow_Label(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Flow_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Flows(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do
+);
+int epcapp.add_Flow_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Flow_Usage(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_GERAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+data_do);
+int epcapp.add_GG_Enforce(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus da
+ta_do);
+int epcapp.add_GG_Enforce_Group(AAA_AVP_LIST * avpList, str imsi, ip_address ue_
+ip, ip_address gg_ip, AVPDataStatus status);
+int epcapp.add_GG_IP(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GGSN_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GMLC_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GMLC_Number(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_GMLC_Restriction(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_GPRS_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int epcapp.add_Guaranteed_Bitrate_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Guaranteed_Bitrate_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Homogenous_Support_of_IMS_Over_PS_Sessions(AAA_AVP_LIST *list,int
+32_t data);
+int epcapp.add_HPLMN_ODB(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_ICS_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_IDA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IDR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IMEI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Immediate_Response_Preferred(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IMS_Charging_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_IMS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_IMS_Voice_Over_PS_Sessions_Supported(AAA_AVP_LIST *list,int32_t d
+ata);
+int epcapp.add_Inter_Operator_Identifier(AAA_AVP_LIST *list,AAA_AVP_LIST* data,A
+VPDataStatus data_do);
+int epcapp.add_IP_CAN_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Item_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_KASME(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Kc(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Last_UE_Activity_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_LCS_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data
+_do);
+int epcapp.add_LCS_Privacy_Exception(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int epcapp.add_Local_Sequence_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Max_Requested_Bandwidth_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Max_Requested_Bandwidth_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Media_Component_Description(AAA_AVP_LIST *list,AAA_AVP_LIST* data
+,AVPDataStatus data_do);
+int epcapp.add_Media_Component_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Media_Initiator_Flag(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Media_Initiator_Party(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int epcapp.add_Media_Sub_Component(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_Media_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Message_Body(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+data_do);
+int epcapp.add_Metering_Method(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_MO_LR(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do
+);
+int epcapp.add_Network_Access_Mode(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Network_Request_Support(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Node_Functionality(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_IP_Access(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_IP_Access_APN(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_User_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataS
+tatus data_do);
+int epcapp.add_NOR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Notification_To_UE_User(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Number_Of_Requested_Vectors(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Offline(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_OMC_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Online(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Operator_Determined_Barring(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Originating_IOI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_Originator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Outgoing_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int epcapp.add_Packet_Filter_Content(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int epcapp.add_Packet_Filter_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatu
+s data_do);
+int epcapp.add_Packet_Filter_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,A
+VPDataStatus data_do);
+int epcapp.add_Packet_Filter_Operation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PCC_Rule_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDN_Connection_ID(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int epcapp.add_PDN_Gw_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_PDN_Gw_Allocation_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDN_Gw_Identity(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_PDN_Gw_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_PDN_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDP_Context(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus d
+ata_do);
+int epcapp.add_PDP_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_PLMN_Client(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Precedence(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Pre_emption_Capability(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Pre_emption_Vulnerability(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Priority_Level(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_PS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatu
+s data_do);
+int epcapp.add_PUA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_QoS_Class_Identifier(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_QoS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_QoS_Negotiation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_QoS_Profile_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_QoS_Rule_Definition(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_QoS_Rule_Install(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSta
+tus data_do);
+int epcapp.add_QoS_Rule_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Remove(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_QoS_Rule_Report(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int epcapp.add_QoS_Subscribed(AAA_AVP_LIST *list,str data,AVPDataStatus data_do)
+;
+int epcapp.add_QoS_Upgrade(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_RAI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_RAND(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_RAT_Frequency_Selection_Priority_ID(AAA_AVP_LIST *list,uint32_t d
+ata);
+int epcapp.add_RAT_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Regional_Subscription_Zone_Code(AAA_AVP_LIST *list,str data,AVPDa
+taStatus data_do);
+int epcapp.add_Reporting_Level(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Requested_EUTRAN_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_L
+IST* data,AVPDataStatus data_do);
+int epcapp.add_Requested_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_Requested_UTRAN_GERAN_Authentication_Info(AAA_AVP_LIST *list,AAA_
+AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Reservation_Priority(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Resource_Allocation_Notification(AAA_AVP_LIST *list,int32_t data)
+;
+int epcapp.add_Re_Synchronization_Info(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_Revalidation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Roaming_Restricted_Due_To_Unsupported_Feature(AAA_AVP_LIST *list,
+int32_t data);
+int epcapp.add_Role_Of_Node(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_RR_Bandwidth(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_RS_Bandwidth(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Rule_Activation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Rule_DeActivation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Rule_Failure_Code(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_SDP_Answer_TimeStamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SDP_Media_Component(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_SDP_Media_Description(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int epcapp.add_SDP_Media_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do)
+;
+int epcapp.add_SDP_Offer_TimeStamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SDP_Session_Description(AAA_AVP_LIST *list,str data,AVPDataStatus
+ data_do);
+int epcapp.add_SDP_TimeStamps(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatu
+s data_do);
+int epcapp.add_SDP_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Security_Parameter_Index(AAA_AVP_LIST *list,str data,AVPDataStatu
+s data_do);
+int epcapp.add_Served_Party_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Service_Data_Container(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPD
+ataStatus data_do);
+int epcapp.add_Service_ID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Service_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_Service_Info_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Service_Specific_Data(AAA_AVP_LIST *list,str data,AVPDataStatus d
+ata_do);
+int epcapp.add_Service_Specific_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int epcapp.add_Service_Specific_Type(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Service_Type(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+data_do);
+int epcapp.add_Service_URN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Session_Linking_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Session_Release_Cause(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Sevice_Type_Identity(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_SGSN_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_SGSN_Number(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SIP_Forking_Indication(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_SIP_Method(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SIP_Request_Timestamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SIP_Request_Timestamp_Fraction(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_SIP_Response_Timestamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SIP_Response_Timestamp_Fraction(AAA_AVP_LIST *list,uint32_t data)
+;
+int epcapp.add_Software_Version(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_Specific_Action(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Specific_APN_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int epcapp.add_SRES(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SS_Code(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SS_Status(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus dat
+a_do);
+int epcapp.add_STN_SR(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Subscriber_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int epcapp.add_Teleservice_List(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSta
+tus data_do);
+int epcapp.add_Terminal_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDat
+aStatus data_do);
+int epcapp.add_Terminating_IOI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_TFT_Filter(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_TFT_Packet_Filter_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* da
+ta,AVPDataStatus data_do);
+int epcapp.add_TGPP_RAT_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Time_First_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Time_Last_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Time_Stamps(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus d
+ata_do);
+int epcapp.add_Time_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_ToS_Traffic_Class(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int epcapp.add_Trace_Collection_Entity(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Trace_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus da
+ta_do);
+int epcapp.add_Trace_Depth(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Trace_Event_List(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int epcapp.add_Trace_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus da
+ta_do);
+int epcapp.add_Trace_Interface_List(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int epcapp.add_Trace_NE_Type_List(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int epcapp.add_Trace_Reference(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_TS_Code(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Tunnel_Header_Filter(AAA_AVP_LIST *list,str data,AVPDataStatus da
+ta_do);
+int epcapp.add_Tunnel_Header_Length(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Tunnel_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataS
+tatus data_do);
+int epcapp.add_UE_Locator(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_UE_Locator_Id_Group(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int epcapp.add_ULA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_ULR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_User_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_User_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_UTRAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+data_do);
+int epcapp.add_Visited_PLMN_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int epcapp.add_VPLMN_Dynamic_Address_Allowed(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_XRES(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.get_3GPP2_MEID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_AAA_Server_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_3GPP_Charging_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_MS_TimeZone(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_PDP_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_SGSN_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_SGSN_IPv6_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int epcapp.get_3GPP_SGSN_MCC_MNC(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_User_Location_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Abort_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Acceptable_Service_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Address(AAA_AVP_LIST list,ip_address *dat
+a,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier(AAA_AVP_LIST list,AAA_AVP_LIST
+ *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier_Gx(AAA_AVP_LIST list,AAA_AVP_L
+IST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier_Value(AAA_AVP_LIST list,str *d
+ata,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Restriction_Data(AAA_AVP_LIST list,uint32_t *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_AF_Application_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_AF_Charging_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int epcapp.get_AF_Correlation_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,A
+AA_AVP **avp_ptr);
+int epcapp.get_Alert_Reason(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_All_APN_Configurations_Included_Indicator(AAA_AVP_LIST list,int32
+_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Allocation_Retention_Priority(AAA_AVP_LIST list,AAA_AVP_LIST *dat
+a,AAA_AVP **avp_ptr);
+int epcapp.get_AMBR(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_AMBR_Group(AAA_AVP_LIST list,uint32_t *Max_Requested_Bandwidth_UL
+,uint32_t *Max_Requested_Bandwidth_DL,AAA_AVP **avp_ptr);
+int epcapp.get_AN_GW_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_ANID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_Aggregate_Max_Bitrate_DL(AAA_AVP_LIST list,uint32_t *data,AAA
+_AVP **avp_ptr);
+int epcapp.get_APN_Aggregate_Max_Bitrate_UL(AAA_AVP_LIST list,uint32_t *data,AAA
+_AVP **avp_ptr);
+int epcapp.get_APN_Configuration(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_APN_Configuration_Profile(AAA_AVP_LIST list,AAA_AVP_LIST *data,AA
+A_AVP **avp_ptr);
+int epcapp.get_APN_OI_Replacement(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Application_Provided_Called_Party_Address(AAA_AVP_LIST list,str *
+data,AAA_AVP **avp_ptr);
+int epcapp.get_Application_Server(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Application_Server_Information(AAA_AVP_LIST list,AAA_AVP_LIST *da
+ta,AAA_AVP **avp_ptr);
+int epcapp.get_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_Authorized_QoS(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_AUTN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Control_Mode(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Bearer_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Operation(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Bearer_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Call_Barring_Infor_List(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_Called_Asserted_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_Called_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Calling_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Cancellation_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Cause_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Base_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Charging_Rule_Definition(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA
+_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Install(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Charging_Rule_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Charging_Rule_Remove(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+ **avp_ptr);
+int epcapp.get_Charging_Rule_Report(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+ **avp_ptr);
+int epcapp.get_Client_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_CoA_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_CoA_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Codec_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Complete_Data_List_Included_Indicator(AAA_AVP_LIST list,int32_t *
+data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Disposition(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Content_Length(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Content_Size(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Context_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_CSG_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_CSG_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Default_EPS_Bearer_QoS(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_DSA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_DSR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Early_Media_Description(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_EPS_Subscribed_QoS_Profile(AAA_AVP_LIST list,AAA_AVP_LIST *data,A
+AA_AVP **avp_ptr);
+int epcapp.get_Equipment_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_E_UTRAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Event(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event_Report_Indication(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_Event_Trigger(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event_Type(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Expiration_Date(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Expires(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_External_Client(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_Flow_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Flow_Label(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flows(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_GERAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_GG_Enforce(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_GG_IP(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_GGSN_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_GMLC_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_GMLC_Number(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_GMLC_Restriction(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_GPRS_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_Guaranteed_Bitrate_DL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Guaranteed_Bitrate_UL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Homogenous_Support_of_IMS_Over_PS_Sessions(AAA_AVP_LIST list,int3
+2_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_HPLMN_ODB(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ICS_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IDA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IDR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IMEI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Immediate_Response_Preferred(AAA_AVP_LIST list,uint32_t *data,AAA
+_AVP **avp_ptr);
+int epcapp.get_IMS_Charging_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_IMS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_IMS_Voice_Over_PS_Sessions_Supported(AAA_AVP_LIST list,int32_t *d
+ata,AAA_AVP **avp_ptr);
+int epcapp.get_Inter_Operator_Identifier(AAA_AVP_LIST list,AAA_AVP_LIST *data,AA
+A_AVP **avp_ptr);
+int epcapp.get_IP_CAN_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Item_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_KASME(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Kc(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Last_UE_Activity_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_LCS_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_LCS_Privacy_Exception(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Local_Sequence_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Max_Requested_Bandwidth_DL(AAA_AVP_LIST list,uint32_t *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_Max_Requested_Bandwidth_UL(AAA_AVP_LIST list,uint32_t *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_Media_Component_Description(AAA_AVP_LIST list,AAA_AVP_LIST *data,
+AAA_AVP **avp_ptr);
+int epcapp.get_Media_Component_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_Media_Initiator_Flag(AAA_AVP_LIST list,int32_t *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_Media_Initiator_Party(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Media_Sub_Component(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_Media_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Message_Body(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Metering_Method(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_MO_LR(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Network_Access_Mode(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Network_Request_Support(AAA_AVP_LIST list,int32_t *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_Node_Functionality(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_
+ptr);
+int epcapp.get_Non_3GPP_IP_Access(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_
+ptr);
+int epcapp.get_Non_3GPP_IP_Access_APN(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Non_3GPP_User_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_NOR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Notification_To_UE_User(AAA_AVP_LIST list,int32_t *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_Number_Of_Requested_Vectors(AAA_AVP_LIST list,uint32_t *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_Offline(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_OMC_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Online(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Operator_Determined_Barring(AAA_AVP_LIST list,uint32_t *data,AAA_
+AVP **avp_ptr);
+int epcapp.get_Originating_IOI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Originator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Outgoing_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Packet_Filter_Content(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Packet_Filter_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_Packet_Filter_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AA
+A_AVP **avp_ptr);
+int epcapp.get_Packet_Filter_Operation(AAA_AVP_LIST list,int32_t *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_PCC_Rule_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_PDN_Connection_ID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Gw_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_PDN_Gw_Allocation_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_PDN_Gw_Identity(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_PDN_Gw_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDP_Context(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_PDP_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PLMN_Client(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Precedence(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Pre_emption_Capability(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Pre_emption_Vulnerability(AAA_AVP_LIST list,int32_t *data,AAA_AVP
+ **avp_ptr);
+int epcapp.get_Priority_Level(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_PS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_PUA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Class_Identifier(AAA_AVP_LIST list,int32_t *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_QoS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_QoS_Negotiation(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_QoS_Profile_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Definition(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_QoS_Rule_Install(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_QoS_Rule_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Remove(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_QoS_Rule_Report(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_QoS_Subscribed(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Upgrade(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAND(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAT_Frequency_Selection_Priority_ID(AAA_AVP_LIST list,uint32_t *d
+ata,AAA_AVP **avp_ptr);
+int epcapp.get_RAT_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Regional_Subscription_Zone_Code(AAA_AVP_LIST list,str *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_Reporting_Level(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Requested_EUTRAN_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LI
+ST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Requested_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Requested_UTRAN_GERAN_Authentication_Info(AAA_AVP_LIST list,AAA_A
+VP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Reservation_Priority(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Resource_Allocation_Notification(AAA_AVP_LIST list,int32_t *data,
+AAA_AVP **avp_ptr);
+int epcapp.get_Re_Synchronization_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Revalidation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Roaming_Restricted_Due_To_Unsupported_Feature(AAA_AVP_LIST list,i
+nt32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Role_Of_Node(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RR_Bandwidth(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RS_Bandwidth(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Rule_Activation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Rule_DeActivation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Rule_Failure_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_SDP_Answer_TimeStamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_SDP_Media_Component(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_SDP_Media_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_SDP_Media_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Offer_TimeStamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_
+ptr);
+int epcapp.get_SDP_Session_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_SDP_TimeStamps(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_SDP_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Security_Parameter_Index(AAA_AVP_LIST list,str *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_Served_Party_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Service_Data_Container(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_A
+VP **avp_ptr);
+int epcapp.get_Service_ID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_Service_Info_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int epcapp.get_Service_Specific_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Service_Specific_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Service_Specific_Type(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Service_Type(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Service_URN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Session_Linking_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP
+ **avp_ptr);
+int epcapp.get_Session_Release_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Sevice_Type_Identity(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_SGSN_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_SGSN_Number(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Forking_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_SIP_Method(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Request_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **av
+p_ptr);
+int epcapp.get_SIP_Request_Timestamp_Fraction(AAA_AVP_LIST list,uint32_t *data,A
+AA_AVP **avp_ptr);
+int epcapp.get_SIP_Response_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_SIP_Response_Timestamp_Fraction(AAA_AVP_LIST list,uint32_t *data,
+AAA_AVP **avp_ptr);
+int epcapp.get_Software_Version(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Specific_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Specific_APN_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_SRES(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SS_Code(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SS_Status(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_STN_SR(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Subscriber_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int epcapp.get_Teleservice_List(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Terminal_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+ **avp_ptr);
+int epcapp.get_Terminating_IOI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TFT_Filter(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TFT_Packet_Filter_Information(AAA_AVP_LIST list,AAA_AVP_LIST *dat
+a,AAA_AVP **avp_ptr);
+int epcapp.get_TGPP_RAT_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Time_First_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Time_Last_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Time_Stamps(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Time_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ToS_Traffic_Class(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Collection_Entity(AAA_AVP_LIST list,ip_address *data,AAA_AV
+P **avp_ptr);
+int epcapp.get_Trace_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Trace_Depth(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Event_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr
+);
+int epcapp.get_Trace_Interface_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Trace_NE_Type_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int epcapp.get_Trace_Reference(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TS_Code(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Tunnel_Header_Filter(AAA_AVP_LIST list,str *data,AAA_AVP **avp_pt
+r);
+int epcapp.get_Tunnel_Header_Length(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int epcapp.get_Tunnel_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP *
+*avp_ptr);
+int epcapp.get_UE_Locator(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_UE_Locator_Id_Group(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int epcapp.get_ULA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ULR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_User_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_User_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_UTRAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_p
+tr);
+int epcapp.get_Visited_PLMN_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_VPLMN_Dynamic_Address_Allowed(AAA_AVP_LIST list,int32_t *data,AAA
+_AVP **avp_ptr);
+int epcapp.get_XRES(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+
+2.4. ccapp
+
+int ccapp.add_CC_Correlation_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_d
+o);
+int ccapp.add_CC_Input_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Money(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_
+do);
+int ccapp.add_CC_Output_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Request_Number(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_CC_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_CC_Service_Specific_Units(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Session_Failover(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_CC_Sub_Session_Id(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Time(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_CC_Total_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Unit_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Check_Balance_Result(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Cost_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStat
+us data_do);
+int ccapp.add_Cost_Unit(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Credit_Control(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Credit_Control_Failure_Handling(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Currency_Code(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Direct_Debiting_Failure_Handling(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Exponent(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Final_Unit_Action(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Final_Unit_Indication(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDat
+aStatus data_do);
+int ccapp.add_Granted_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int ccapp.add_G_S_U_Pool_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_G_S_U_Pool_Reference(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPData
+Status data_do);
+int ccapp.add_Multiple_Services_Credit_Control(AAA_AVP_LIST *list,AAA_AVP_LIST*
+data,AVPDataStatus data_do);
+int ccapp.add_Multiple_Services_Indicator(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Rating_Group(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Redirect_Address_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Redirect_Server(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatu
+s data_do);
+int ccapp.add_Redirect_Server_Address(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int ccapp.add_Requested_Action(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Requested_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int ccapp.add_Restriction_Filter_Rule(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int ccapp.add_Service_Context_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_
+do);
+int ccapp.add_Service_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Service_Parameter_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDa
+taStatus data_do);
+int ccapp.add_Service_Parameter_Type(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Service_Parameter_Value(AAA_AVP_LIST *list,str data,AVPDataStatus
+data_do);
+int ccapp.add_Subscription_Id(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatu
+s data_do);
+int ccapp.add_Subscription_Id_Data(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int ccapp.add_Subscription_Id_Group(AAA_AVP_LIST *list,int32_t type,str data,AVP
+DataStatus data_do);
+int ccapp.add_Subscription_Id_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Tariff_Change_Usage(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Tariff_Time_Change(AAA_AVP_LIST *list,time_t data);
+int ccapp.add_Unit_Value(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus dat
+a_do);
+int ccapp.add_Used_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSta
+tus data_do);
+int ccapp.add_User_Equipment_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataS
+tatus data_do);
+int ccapp.add_User_Equipment_Info_Group(AAA_AVP_LIST *list,int32_t type,str data
+,AVPDataStatus data_do);
+int ccapp.add_User_Equipment_Info_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_User_Equipment_Info_Value(AAA_AVP_LIST *list,str data,AVPDataStatu
+s data_do);
+int ccapp.add_Validity_Time(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Value_Digits(AAA_AVP_LIST *list,int64_t data);
+int ccapp.get_CC_Correlation_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Input_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr
+);
+int ccapp.get_CC_Money(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Output_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_pt
+r);
+int ccapp.get_CC_Request_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_p
+tr);
+int ccapp.get_CC_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr)
+;
+int ccapp.get_CC_Service_Specific_Units(AAA_AVP_LIST list,uint64_t *data,AAA_AVP
+ **avp_ptr);
+int ccapp.get_CC_Session_Failover(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_CC_Sub_Session_Id(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_p
+tr);
+int ccapp.get_CC_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Total_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr
+);
+int ccapp.get_CC_Unit_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Check_Balance_Result(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int ccapp.get_Cost_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **av
+p_ptr);
+int ccapp.get_Cost_Unit(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Credit_Control(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Credit_Control_Failure_Handling(AAA_AVP_LIST list,int32_t *data,AA
+A_AVP **avp_ptr);
+int ccapp.get_Currency_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Direct_Debiting_Failure_Handling(AAA_AVP_LIST list,int32_t *data,A
+AA_AVP **avp_ptr);
+int ccapp.get_Exponent(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Final_Unit_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int ccapp.get_Final_Unit_Indication(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+ **avp_ptr);
+int ccapp.get_Granted_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int ccapp.get_G_S_U_Pool_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int ccapp.get_G_S_U_Pool_Reference(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP
+**avp_ptr);
+int ccapp.get_Multiple_Services_Credit_Control(AAA_AVP_LIST list,AAA_AVP_LIST *d
+ata,AAA_AVP **avp_ptr);
+int ccapp.get_Multiple_Services_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AV
+P **avp_ptr);
+int ccapp.get_Rating_Group(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Redirect_Address_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **av
+p_ptr);
+int ccapp.get_Redirect_Server(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp
+_ptr);
+int ccapp.get_Redirect_Server_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_Requested_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int ccapp.get_Requested_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int ccapp.get_Restriction_Filter_Rule(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_Service_Context_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_Service_Parameter_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AV
+P **avp_ptr);
+int ccapp.get_Service_Parameter_Type(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int ccapp.get_Service_Parameter_Value(AAA_AVP_LIST list,str *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_Subscription_Id(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp
+_ptr);
+int ccapp.get_Subscription_Id_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int ccapp.get_Subscription_Id_Group(AAA_AVP_LIST list,int32_t *type,str *data,AA
+A_AVP **avp_ptr);
+int ccapp.get_Subscription_Id_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp
+_ptr);
+int ccapp.get_Tariff_Change_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_
+ptr);
+int ccapp.get_Tariff_Time_Change(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_pt
+r);
+int ccapp.get_Unit_Value(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr)
+;
+int ccapp.get_Used_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **a
+vp_ptr);
+int ccapp.get_User_Equipment_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP *
+*avp_ptr);
+int ccapp.get_User_Equipment_Info_Group(AAA_AVP_LIST list,int32_t *type,str *dat
+a,AAA_AVP **avp_ptr);
+int ccapp.get_User_Equipment_Info_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP *
+*avp_ptr);
+int ccapp.get_User_Equipment_Info_Value(AAA_AVP_LIST list,str *data,AAA_AVP **av
+p_ptr);
+int ccapp.get_Validity_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Value_Digits(AAA_AVP_LIST list,int64_t *data,AAA_AVP **avp_ptr);
+
+2.5. base
+
+int base.add_Accounting_Realtime_Required(AAA_AVP_LIST *list,int32_t data);
+int base.add_Accounting_Record_Number(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Accounting_Record_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Accounting_Sub_Session_Id(AAA_AVP_LIST *list,uint64_t data);
+int base.add_Acct_Application_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Acct_Interim_Interval(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Acct_Multi_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int base.add_Acct_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Auth_Application_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Auth_Grace_Period(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Authorization_Lifetime(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Auth_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Auth_Session_State(AAA_AVP_LIST *list,int32_t data);
+int base.add_Class(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Destination_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do)
+;
+int base.add_Destination_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int base.add_Disconnect_Cause(AAA_AVP_LIST *list,int32_t data);
+int base.add_E2E_Sequence(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Error_Message(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Error_Reporting_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data
+_do);
+int base.add_Event_Timestamp(AAA_AVP_LIST *list,time_t data);
+int base.add_Experimental_Result(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int base.add_Experimental_Result_Code(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Experimental_Result_Group(AAA_AVP_LIST *list,uint32_t Vendor_Id,uin
+t32_t Experimental_Result_Code);
+int base.add_Failed_AVP(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data
+_do);
+int base.add_Firmware_Revision(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Host_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int base.add_Inband_Security_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_MIP6_Agent_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus
+ data_do);
+int base.add_MIP6_Feature_Vector(AAA_AVP_LIST *list,uint64_t data);
+int base.add_MIP6_Home_Link_Prefix(AAA_AVP_LIST *list,str data,AVPDataStatus dat
+a_do);
+int base.add_MIP_Home_Agent_Address(AAA_AVP_LIST *list,ip_address data);
+int base.add_MIP_Home_Agent_Host(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataSt
+atus data_do);
+int base.add_Multi_Round_Time_Out(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Origin_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Origin_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Origin_State_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Product_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Proxy_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Proxy_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data
+_do);
+int base.add_Proxy_State(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Re_Auth_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Redirect_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Redirect_Host_Usage(AAA_AVP_LIST *list,int32_t data);
+int base.add_Redirect_Max_Cache_Time(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Result_Code(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Route_Record(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Service_Selection(AAA_AVP_LIST *list,str data,AVPDataStatus data_do
+);
+int base.add_Session_Binding(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Session_Server_Failover(AAA_AVP_LIST *list,int32_t data);
+int base.add_Session_Timeout(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Supported_Vendor_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Termination_Cause(AAA_AVP_LIST *list,int32_t data);
+int base.add_User_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Vendor_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Vendor_Specific_Application_Id(AAA_AVP_LIST *list,AAA_AVP_LIST* dat
+a,AVPDataStatus data_do);
+int base.add_Vendor_Specific_Application_Id_Group(AAA_AVP_LIST *list,uint32_t ve
+ndor_id,uint32_t auth_app_id,uint32_t acct_app_id);
+int base.get_Accounting_Realtime_Required(AAA_AVP_LIST list,int32_t *data,AAA_AV
+P **avp_ptr);
+int base.get_Accounting_Record_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP *
+*avp_ptr);
+int base.get_Accounting_Record_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **av
+p_ptr);
+int base.get_Accounting_Sub_Session_Id(AAA_AVP_LIST list,uint64_t *data,AAA_AVP
+**avp_ptr);
+int base.get_Acct_Application_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_
+ptr);
+int base.get_Acct_Interim_Interval(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **av
+p_ptr);
+int base.get_Acct_Multi_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int base.get_Acct_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Auth_Application_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_
+ptr);
+int base.get_Auth_Grace_Period(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_pt
+r);
+int base.get_Authorization_Lifetime(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **a
+vp_ptr);
+int base.get_Auth_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int base.get_Auth_Session_State(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_pt
+r);
+int base.get_Class(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Destination_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Destination_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Disconnect_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr)
+;
+int base.get_E2E_Sequence(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Error_Message(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Error_Reporting_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr)
+;
+int base.get_Event_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int base.get_Experimental_Result(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int base.get_Experimental_Result_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP *
+*avp_ptr);
+int base.get_Experimental_Result_Group(AAA_AVP_LIST list,uint32_t *Vendor_Id,uin
+t32_t *Experimental_Result_Code,AAA_AVP **avp_ptr);
+int base.get_Failed_AVP(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Firmware_Revision(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_pt
+r);
+int base.get_Host_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_pt
+r);
+int base.get_Inband_Security_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_p
+tr);
+int base.get_MIP6_Agent_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_
+ptr);
+int base.get_MIP6_Feature_Vector(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_
+ptr);
+int base.get_MIP6_Home_Link_Prefix(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr
+);
+int base.get_MIP_Home_Agent_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP *
+*avp_ptr);
+int base.get_MIP_Home_Agent_Host(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **
+avp_ptr);
+int base.get_Multi_Round_Time_Out(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp
+_ptr);
+int base.get_Origin_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Origin_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Origin_State_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr)
+;
+int base.get_Product_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_State(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Re_Auth_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_
+ptr);
+int base.get_Redirect_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Redirect_Host_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_p
+tr);
+int base.get_Redirect_Max_Cache_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **
+avp_ptr);
+int base.get_Result_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Route_Record(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Service_Selection(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Session_Binding(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr)
+;
+int base.get_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Session_Server_Failover(AAA_AVP_LIST list,int32_t *data,AAA_AVP **a
+vp_ptr);
+int base.get_Session_Timeout(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr)
+;
+int base.get_Supported_Vendor_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_
+ptr);
+int base.get_Termination_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr
+);
+int base.get_User_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Vendor_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Vendor_Specific_Application_Id(AAA_AVP_LIST list,AAA_AVP_LIST *data
+,AAA_AVP **avp_ptr);
+int base.get_Vendor_Specific_Application_Id_example(AAA_AVP_LIST list,uint32_t *
+vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id);
+
+Chapter 3. Frequently Asked Questions
+
+   3.1. Where can I find more about Kamailio?
+   3.2. Where can I post a question about this module?
+   3.3. How can I report a bug?
+
+   3.1.
+
+       Where can I find more about Kamailio?
+
+       Take a look at http://www.kamailio.org/.
+
+   3.2.
+
+       Where can I post a question about this module?
+
+       First at all check if your question was already answered on one of our
+       mailing lists:
+         * User Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
+         * Developer Mailing List -
+           http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
+
+       E-mails regarding any stable Kamailio release should be sent to
+       <[email protected]> and e-mails regarding development
+       versions should be sent to <[email protected]>.
+
+       If you want to keep the mail private, send it to
+       <[email protected]>.
+
+   3.3.
+
+       How can I report a bug?
+
+       Please follow the guidelines provided at:
+       http://sip-router.org/tracker.

+ 134 - 0
modules/cdp_avp/avp_add.c

@@ -0,0 +1,134 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_add.h"
+#include "avp_new.h"
+
+extern struct cdp_binds *cdp;
+
+
+/**
+ * Adds a new AVP to a list
+ * @param list
+ * @param d
+ * @param len
+ * @param avp_code
+ * @param avp_flags
+ * @param avp_vendorid
+ * @param data_do
+ * @return
+ */
+inline int cdp_avp_add_new_to_list(AAA_AVP_LIST *list,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	AAA_AVP *avp = cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+	if (!list){
+		LOG(L_ERR,"Failed adding to NULL list AVP with Code [%d] Flags [%d] VendorID [%d] from data of length [%d]!\n",
+			avp_code,avp_flags,avp_vendorid,data.len);
+		if (avp) cdp->AAAFreeAVP(&avp);
+		return 0;
+	}
+	if (!avp){
+		LOG(L_ERR,"Error creating AVP with Code [%d] Flags [%d] VendorID [%d] from data of length [%d]!\n",
+			avp_code,avp_flags,avp_vendorid,data.len);
+		return 0;
+	}
+	cdp->AAAAddAVPToList(list,avp);
+	return 1;			
+}
+
+/**
+ * Adds a new AVP to a message
+ * @param msg
+ * @param d
+ * @param len
+ * @param avp_code
+ * @param avp_flags
+ * @param avp_vendorid
+ * @param data_do
+ * @return 1 on success or 0 on failure
+ */
+inline int cdp_avp_add_new_to_msg(AAAMessage *msg,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	if (!msg){
+		LOG(L_ERR,"Failed adding to NULL message AVP with Code [%d] Flags [%d] VendorID [%d] from data of length [%d]!\n",
+			avp_code,avp_flags,avp_vendorid,data.len);
+		return 0;
+	}
+	return cdp_avp_add_new_to_list(&(msg->avpList),avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+/**
+ * Adds an AVP to a list
+ * \Note The avp should no longer be used after this operation. If multiple additions are required, duplicate before
+ * @param list
+ * @param avp
+ * @return 1 on success or 0 on failure
+ */
+inline int cdp_avp_add_to_list(AAA_AVP_LIST *list,AAA_AVP *avp)
+{
+	if (!avp){
+		LOG(L_ERR,"Can not add NULL AVP to list!\n");
+		return 0;
+	}	
+	if (!list){
+		LOG(L_ERR,"Failed adding to NULL list AVP with Code [%d] Flags [%d] VendorID [%d] from data of length [%d]!\n",
+			avp->code,avp->flags,avp->vendorId,avp->data.len);
+		return 0;
+	}
+	cdp->AAAAddAVPToList(list,avp);
+	return 1;			
+}
+
+/**
+ * Adds an AVP to a message
+ * \Note The avp should no longer be used after this operation. If multiple additions are required, duplicate before
+ * @param msg
+ * @param avp
+ * @return 1 on success or 0 on failure
+ */
+inline int cdp_avp_add_to_msg(AAAMessage *msg,AAA_AVP *avp)
+{
+	if (!msg){
+		LOG(L_ERR,"Failed adding to NULL message AVP with Code [%d] Flags [%d] VendorID [%d] from data of length [%d]!\n",
+			avp->code,avp->flags,avp->vendorId,avp->data.len);
+		return 0;
+	}
+	return cdp_avp_add_to_list(&(msg->avpList),avp);
+}

+ 73 - 0
modules/cdp_avp/avp_add.h

@@ -0,0 +1,73 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AVP_ADD_H
+#define __AVP_ADD_H
+
+#ifndef CDP_AVP_REFERENCE
+
+	#include "../cdp/cdp_load.h"
+
+	int cdp_avp_add_new_to_list(AAA_AVP_LIST *list,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef int (*cdp_avp_add_new_to_list_f)(AAA_AVP_LIST *list,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+
+	int cdp_avp_add_new_to_msg(AAAMessage *msg,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef int (*cdp_avp_add_new_to_msg_f)(AAAMessage *msg,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+
+	int cdp_avp_add_to_list(AAA_AVP_LIST *list,AAA_AVP *avp);
+	typedef int (*cdp_avp_add_to_list_f)(AAA_AVP_LIST *list,AAA_AVP *avp);
+
+	int cdp_avp_add_to_msg(AAAMessage *msg,AAA_AVP *avp);
+	typedef int (*cdp_avp_add_to_msg_f)(AAAMessage *msg,AAA_AVP *avp);
+
+#else
+	
+	int basic.add_new_to_list(AAA_AVP_LIST *list,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+
+	int basic.add_new_to_msg(AAAMessage *msg,int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+
+	int basic.add_to_list(AAA_AVP_LIST *list,AAA_AVP *avp);
+
+	int basic.add_to_msg(AAAMessage *msg,AAA_AVP *avp);
+	
+#endif
+
+
+#endif /* __AVP_NEW_H */

+ 114 - 0
modules/cdp_avp/avp_get.c

@@ -0,0 +1,114 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_get.h"
+
+extern struct cdp_binds *cdp;
+
+/**
+ * Iteratively find an AVP matching in a list
+ *  Should be called subsequently with the old result, unless it was null (which would cause a restart of the search).
+ * @param msg
+ * @param avp_code
+ * @param avp_vendor_id
+ * @param start_avp - avp where to resume. A null value will trigger a restart of the search.
+ * @return the AAA_AVP* or NULL if not found (anymore)
+ */
+inline AAA_AVP* cdp_avp_get_next_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id,AAA_AVP *start_avp)
+{
+	AAA_AVP *avp;
+	if (!start_avp)	start_avp = list.head;
+	else start_avp = start_avp->next;
+	LOG(L_DBG,"Looking for AVP with code %d vendor id %d startin at avp %p\n",
+			avp_code,avp_vendor_id,start_avp);
+	
+	if (!start_avp){
+		LOG(L_DBG,"Failed finding AVP with Code %d and VendorId %d - Empty list or at end of list\n",avp_code,avp_vendor_id);
+		return 0;
+	}
+	avp = cdp->AAAFindMatchingAVPList(list,start_avp,avp_code,avp_vendor_id,AAA_FORWARD_SEARCH);
+	if (avp==0){
+		LOG(L_DBG,"Failed finding AVP with Code %d and VendorId %d - at end of list\n",avp_code,avp_vendor_id);
+		return 0;
+	}
+
+	return avp;
+}
+
+/**
+ * Iteratively find an AVP matching in a message
+ * @param msg
+ * @param avp_code
+ * @param avp_vendor_id
+ * @param start_avp
+ * @return the AAA_AVP* or NULL if not found (anymore)
+ */
+inline AAA_AVP* cdp_avp_get_next_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id,AAA_AVP *start_avp)
+{
+	return cdp_avp_get_next_from_list(msg->avpList,avp_code,avp_vendor_id,start_avp);
+}
+
+/**
+ * Find the first matching AVP in a list and return it 
+ * @param list
+ * @param avp_code
+ * @param avp_vendor_id
+ * @return the AAA_AVP* or null if not found
+ */
+inline AAA_AVP* cdp_avp_get_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id)
+{
+	return cdp_avp_get_next_from_list(list,avp_code,avp_vendor_id,0);
+}
+
+/**
+ * Find the first AVP matching in the message and return it
+ * @param msg
+ * @param avp_code
+ * @param avp_vendor_id
+ * @return the AAA_AVP* or null if not found
+ */
+inline AAA_AVP* cdp_avp_get_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id)
+{
+	if (!msg){
+		LOG(L_ERR,"Failed finding AVP with Code %d and VendorId %d in NULL message!\n",avp_code,avp_vendor_id);
+		return 0;
+	}
+	return cdp_avp_get_from_list(msg->avpList,avp_code,avp_vendor_id);
+}

+ 74 - 0
modules/cdp_avp/avp_get.h

@@ -0,0 +1,74 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AVP_GET_H
+#define __AVP_GET_H
+
+#ifndef CDP_AVP_REFERENCE
+
+	#include "../cdp/cdp_load.h"
+
+	AAA_AVP* cdp_avp_get_next_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+	typedef AAA_AVP* (*cdp_avp_get_next_from_list_f)(AAA_AVP_LIST list,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+	
+	AAA_AVP* cdp_avp_get_next_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+	typedef AAA_AVP* (*cdp_avp_get_next_from_msg_f)(AAAMessage *msg,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+	
+	AAA_AVP* cdp_avp_get_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id);
+	typedef AAA_AVP* (*cdp_avp_get_from_list_f)(AAA_AVP_LIST list,int avp_code,int avp_vendor_id);
+	
+	AAA_AVP* cdp_avp_get_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id);
+	typedef AAA_AVP* (*cdp_avp_get_from_msg_f)(AAAMessage *msg,int avp_code,int avp_vendor_id);
+
+#else
+
+	AAA_AVP* basic.get_next_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+
+	AAA_AVP* basic.get_next_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id,AAA_AVP *start_avp);
+
+	AAA_AVP* basic.get_from_list(AAA_AVP_LIST list,int avp_code,int avp_vendor_id);
+
+	AAA_AVP* basic.get_from_msg(AAAMessage *msg,int avp_code,int avp_vendor_id);
+
+#endif
+
+
+
+#endif /* __AVP_NEW_H */

+ 244 - 0
modules/cdp_avp/avp_get_base_data_format.c

@@ -0,0 +1,244 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_get_base_data_format.h"
+
+extern struct cdp_binds *cdp;
+
+/* 
+ * RFC 3588 Basic AVP Data Types
+ * 
+ * http://tools.ietf.org/html/rfc3588#section-4.2
+ * 
+ */
+
+inline int cdp_avp_get_OctetString(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+
+inline int cdp_avp_get_Integer32(AAA_AVP *avp,int32_t *data)
+{
+	int32_t x=0;
+	if (avp->data.len<4) {
+		LOG(L_ERR,"Error decoding Integer32 from data len < 4 bytes!\n");
+		return 0;
+	}
+	x = get_4bytes(avp->data.s);
+	if (data) *data = x;
+	return 1;
+}
+
+inline int cdp_avp_get_Integer64(AAA_AVP *avp,int64_t *data)
+{
+	int64_t x=0;
+	int i;
+	if (avp->data.len<8) {
+		LOG(L_ERR,"Error decoding Integer64 from data len < 8 bytes!\n");
+		return 0;
+	}
+	for(i=0;i<8;i++)
+		x = (x*256) + avp->data.s[i];
+	if (data) *data = x;
+	return 1;	
+}
+
+
+inline int cdp_avp_get_Unsigned32(AAA_AVP *avp,uint32_t *data)
+{
+	if (avp->data.len<4) {
+		LOG(L_ERR,"Error decoding Unsigned32 from data len < 4 bytes!\n");
+		return 0;
+	}
+	if (data) *data = ntohl(*((uint32_t*)avp->data.s));
+	return 1;
+}
+
+
+inline int cdp_avp_get_Unsigned64(AAA_AVP *avp,uint64_t *data)
+{
+	uint64_t x=0;
+	int i;
+	if (avp->data.len<8) {
+		LOG(L_ERR,"Error decoding Unsigned64 from data len < 8 bytes!\n");
+		return 0;
+	}
+	for(i=0;i<8;i++)
+		x = (x*256) + avp->data.s[i];
+	if (data) *data = x;
+	return 1;
+}
+
+
+inline int cdp_avp_get_Float32(AAA_AVP *avp,float *data)
+{
+	float x;
+	uint32_t y;
+	if (avp->data.len<4) {
+		LOG(L_ERR,"Error decoding Float32 from data len < 4 bytes!\n");
+		return 0;
+	}
+	y = cdp_avp_get_Unsigned32(avp,(uint32_t*)data);//TODO - check if this is correct
+	memcpy(&x,&y,sizeof(uint32_t));
+	//*((uint32_t*)&x)=y;
+	if (data) *data = y;
+	return 1;
+}
+
+
+inline int cdp_avp_get_Float64(AAA_AVP *avp,double *data)
+{
+	double x;
+	uint64_t y;
+	if (avp->data.len<8) {
+		LOG(L_ERR,"Error decoding Float64 from data len < 8 bytes!\n");
+		return 0;
+	}
+	y = cdp_avp_get_Unsigned64(avp,(uint64_t*)data);//TODO - check if this is correct
+	memcpy(&x,&y,sizeof(uint64_t));
+	if (data) *data = y;
+	return 1;
+}
+
+inline int cdp_avp_get_Grouped(AAA_AVP *avp,AAA_AVP_LIST *data)
+{
+	if (data) *data = cdp->AAAUngroupAVPS(avp->data);
+	return 1;
+}
+
+inline void cdp_avp_free_Grouped(AAA_AVP_LIST *data)
+{
+	if (data) cdp->AAAFreeAVPList(data);
+}
+
+/*
+ * RFC 3588 Derived AVP Data Formats
+ * 
+ * http://tools.ietf.org/html/rfc3588#section-4.3
+ * 
+ */
+
+inline int cdp_avp_get_Address(AAA_AVP *avp,ip_address *data)
+{
+	ip_address x;
+	bzero(&x,sizeof(ip_address));
+	if (avp->data.len<6){
+		LOG(L_ERR,"Error decoding Address from AVP data of length %d < 6",avp->data.len);
+		goto error;
+	}
+	x.ai_family = (avp->data.s[0]<<8) | avp->data.s[1]; 
+	switch (x.ai_family){
+		case 1:
+			x.ai_family = AF_INET;
+			memcpy(&(x.ip.v4.s_addr), avp->data.s+2, 4);
+			break;
+		case 2:
+			x.ai_family = AF_INET6;
+			if (avp->data.len<18){
+				LOG(L_ERR,"Error decoding Address (AF_INET6) from AVP data of length %d < 16",avp->data.len);
+				goto error;
+			}
+			memcpy(x.ip.v6.s6_addr,avp->data.s+2,16);
+	}
+	if (data) *data = x;
+	return 1;
+error:
+	bzero(&x,sizeof(ip_address));
+	if (data) *data = x;
+	return 0;
+}
+
+inline int cdp_avp_get_Time(AAA_AVP *avp,time_t *data)
+{
+	if (avp->data.len<4) {
+		LOG(L_ERR,"Error decoding Time from data len < 4 bytes!\n");
+		return 0;
+	}
+	if (data) *data = ntohl(*((uint32_t*)avp->data.s))-EPOCH_UNIX_TO_EPOCH_NTP;
+	return 1;
+}
+
+inline int cdp_avp_get_UTF8String(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+
+inline int cdp_avp_get_DiameterIdentity(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+
+
+inline int cdp_avp_get_DiameterURI(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+
+
+inline int cdp_avp_get_Enumerated(AAA_AVP *avp,int32_t *data)
+{
+	int32_t x=0;
+	if (!avp || avp->data.len<4) {
+		LOG(L_ERR,"Error decoding Enumerated from data len < 4 bytes!\n");
+		return 0;
+	}
+	x = get_4bytes(avp->data.s);
+	if (data) *data = x;
+	return 1;
+}
+
+
+inline int cdp_avp_get_IPFilterRule(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+
+
+inline int cdp_avp_get_QoSFilterRule(AAA_AVP *avp,str *data)
+{
+	if (data) *data = avp->data;
+	return 1;
+}
+

+ 123 - 0
modules/cdp_avp/avp_get_base_data_format.h

@@ -0,0 +1,123 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AVP_GET_BASE_DATA_FORMAT_H
+#define __AVP_GET_BASE_DATA_FORMAT_H
+
+	#include "../cdp/cdp_load.h"
+	#include "avp_new_base_data_format.h"
+
+	#define EPOCH_UNIX_TO_EPOCH_NTP 2208988800u // according to http://www.cis.udel.edu/~mills/y2k.html
+	
+	/* 
+	 * RFC 3588 Basic AVP Data Types
+	 * 
+	 * http://tools.ietf.org/html/rfc3588#section-4.2
+	 * 
+	 */
+	
+	int cdp_avp_get_OctetString(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_OctetString_f)(AAA_AVP *avp,str *data);
+	
+	
+	int cdp_avp_get_Integer32(AAA_AVP *avp,int32_t *data);
+	typedef int (*cdp_avp_get_Integer32_f)(AAA_AVP *avp,int32_t *data);
+	
+	
+	int cdp_avp_get_Integer64(AAA_AVP *avp,int64_t *data);
+	typedef int (*cdp_avp_get_Integer64_f)(AAA_AVP *avp,int64_t *data);
+	
+	
+	int cdp_avp_get_Unsigned32(AAA_AVP *avp,uint32_t *data);
+	typedef int (*cdp_avp_get_Unsigned32_f)(AAA_AVP *avp,uint32_t *data);
+	
+	
+	int cdp_avp_get_Unsigned64(AAA_AVP *avp,uint64_t *data);
+	typedef int (*cdp_avp_get_Unsigned64_f)(AAA_AVP *avp,uint64_t *data);
+	
+	
+	int cdp_avp_get_Float32(AAA_AVP *avp,float *data);
+	typedef int (*cdp_avp_get_Float32_f)(AAA_AVP *avp,float *data);
+	
+	
+	int cdp_avp_get_Float64(AAA_AVP *avp,double *data);
+	typedef int (*cdp_avp_get_Float64_f)(AAA_AVP *avp,double *data);
+	
+	
+	int cdp_avp_get_Grouped(AAA_AVP *avp,AAA_AVP_LIST *data);
+	typedef int (*cdp_avp_get_Grouped_f)(AAA_AVP *avp,AAA_AVP_LIST *data);
+	
+	
+	void cdp_avp_free_Grouped(AAA_AVP_LIST *list);
+	typedef void (*cdp_avp_free_Grouped_f)(AAA_AVP_LIST *list);
+	
+	/*
+	 * RFC 3588 Derived AVP Data Formats
+	 * 
+	 * http://tools.ietf.org/html/rfc3588#section-4.3
+	 * 
+	 */
+	
+	int cdp_avp_get_Address(AAA_AVP *avp,ip_address *data);
+	typedef int (*cdp_avp_get_Address_f)(AAA_AVP *avp,ip_address *data);
+	
+	int cdp_avp_get_Time(AAA_AVP *avp,time_t *data);
+	typedef int (*cdp_avp_get_Time_f)(AAA_AVP *avp,time_t *data);
+	
+	int cdp_avp_get_UTF8String(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_UTF8String_f)(AAA_AVP *avp,str *data);
+	
+	int cdp_avp_get_DiameterIdentity(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_DiameterIdentity_f)(AAA_AVP *avp,str *data);
+	
+	int cdp_avp_get_DiameterURI(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_DiameterURI_f)(AAA_AVP *avp,str *data);
+	
+	int cdp_avp_get_Enumerated(AAA_AVP *avp,int32_t *data);
+	typedef int (*cdp_avp_get_Enumerated_f)(AAA_AVP *avp,int32_t *data);
+	
+	int cdp_avp_get_IPFilterRule(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_IPFilterRule_f)(AAA_AVP *avp,str *data);
+	
+	int cdp_avp_get_QoSFilterRule(AAA_AVP *avp,str *data);
+	typedef int (*cdp_avp_get_QoSFilterRule_f)(AAA_AVP *avp,str *data);
+	
+
+#endif /* __AVP_GET_DATA_FORMAT_H */

+ 60 - 0
modules/cdp_avp/avp_new.c

@@ -0,0 +1,60 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new.h"
+
+extern struct cdp_binds *cdp;
+
+/**
+ * Just create an AVP and return it
+ * @param d - buffer with the encoded data
+ * @param len - length of the data
+ * @param avp_code - code of the avp
+ * @param avp_flags - flags for the avp
+ * @param avp_vendorid - vendorid for the avp
+ * @param data_do - what to do with the data next 
+ * @return ptr to the new avp or null on error
+ */
+inline AAA_AVP *cdp_avp_new(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	if (avp_vendorid!=0) avp_flags |= AAA_AVP_FLAG_VENDOR_SPECIFIC;
+	return cdp->AAACreateAVP(avp_code,avp_flags,avp_vendorid,data.s,data.len,data_do);	
+}
+

+ 58 - 0
modules/cdp_avp/avp_new.h

@@ -0,0 +1,58 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AVP_NEW_H
+#define __AVP_NEW_H
+
+#ifndef CDP_AVP_REFERENCE
+
+	#include "../cdp/cdp_load.h"
+
+	AAA_AVP* cdp_avp_new(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+
+#else
+	
+	AAA_AVP* basic.new(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+#endif
+
+
+#endif /* __AVP_NEW_H */

+ 217 - 0
modules/cdp_avp/avp_new_base_data_format.c

@@ -0,0 +1,217 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new_base_data_format.h"
+
+#include "avp_new.h"
+
+extern struct cdp_binds *cdp;
+
+
+/* 
+ * RFC 3588 Basic AVP Data Types
+ * 
+ * http://tools.ietf.org/html/rfc3588#section-4.2
+ * 
+ */
+
+inline AAA_AVP *cdp_avp_new_OctetString(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+inline AAA_AVP *cdp_avp_new_Integer32(int avp_code,int avp_flags,int avp_vendorid,int32_t data)
+{
+	char x[4];
+	str s={x,4};
+	set_4bytes(x,data);
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+
+inline AAA_AVP *cdp_avp_new_Integer64(int avp_code,int avp_flags,int avp_vendorid,int64_t data)
+{
+	char x[8];
+	str s={x,8};
+	int i;
+	for(i=7;i>=0;i--){
+		x[i] = data%256;
+		data /= 256;
+	}					//TODO - check if this is correct
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);	
+}
+
+inline AAA_AVP *cdp_avp_new_Unsigned32(int avp_code,int avp_flags,int avp_vendorid,uint32_t data)
+{
+	char x[4];
+	str s={x,4};
+	uint32_t ndata=htonl(data);
+	memcpy(x,&ndata,sizeof(uint32_t));
+	//*((uint32_t*)x) = htonl(data);
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+inline AAA_AVP *cdp_avp_new_Unsigned64(int avp_code,int avp_flags,int avp_vendorid,uint64_t data)
+{
+	char x[8];
+	str s={x,8};
+	int i;
+	for(i=7;i>=0;i--){
+		x[i] = data%256;
+		data /= 256;
+	}
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+inline AAA_AVP *cdp_avp_new_Float32(int avp_code,int avp_flags,int avp_vendorid,float data)
+{
+	uint32_t udata;
+	memcpy(&udata,&data,sizeof(uint32_t));
+	return cdp_avp_new_Unsigned32(avp_code,avp_flags,avp_vendorid,udata);//TODO - check if this is correct
+}
+
+inline AAA_AVP *cdp_avp_new_Float64(int avp_code,int avp_flags,int avp_vendorid,double data)
+{
+	uint64_t udata;
+	memcpy(&udata,&data,sizeof(uint32_t));	
+	return cdp_avp_new_Unsigned64(avp_code,avp_flags,avp_vendorid,udata);//TODO - check if this is correct
+}
+
+/**
+ * Creates a grouped AVP from a list
+ * @param avp_code
+ * @param avp_flags
+ * @param avp_vendorid
+ * @param list
+ * @param list_do - if this is AVP_FREE_DATA then the list will aso be freed
+ * @return
+ */
+inline AAA_AVP *cdp_avp_new_Grouped(int avp_code,int avp_flags,int avp_vendorid,AAA_AVP_LIST *list,AVPDataStatus list_do)
+{
+	str grp;
+	if (!list){
+		LOG(L_ERR,"The AAA_AVP_LIST was NULL!\n");
+		return 0;
+	}
+	grp = cdp->AAAGroupAVPS(*list);
+	if (!grp.len){
+		LOG(L_ERR,"The AAA_AVP_LIST provided was empty! (AVP Code %d VendorId %d)\n",avp_code,avp_vendorid);
+		return 0;
+	}
+	if (list_do==AVP_FREE_DATA)
+		cdp->AAAFreeAVPList(list);
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,grp,AVP_FREE_DATA);
+}
+
+/*
+ * RFC 3588 Derived AVP Data Formats
+ * 
+ * http://tools.ietf.org/html/rfc3588#section-4.3
+ * 
+ */
+
+inline AAA_AVP* cdp_avp_new_Address(int avp_code,int avp_flags,int avp_vendorid,ip_address data)
+{
+	char x[18];
+	str s;
+	s.s = x;
+	s.len = 0;
+
+	switch (data.ai_family){
+		case AF_INET:
+			x[0]=0;
+			x[1]=1;
+			memcpy(x+2, (char*)(&data.ip.v4.s_addr), 4);
+			s.len=6;
+			break;
+		case AF_INET6:
+			x[0]=0;
+			x[1]=2;
+			s.len=18;
+			memcpy(x+2,data.ip.v6.s6_addr,16);
+			break;
+		default:
+			LOG(L_ERR,"Unimplemented for ai_family %d! (AVP Code %d Vendor-Id %d)\n",data.ai_family,avp_code,avp_vendorid);
+			return 0;
+	}
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+inline AAA_AVP* cdp_avp_new_Time(int avp_code,int avp_flags,int avp_vendorid,time_t data)
+{
+	char x[4];
+	str s={x,4};
+	uint32_t ntime = htonl(data+EPOCH_UNIX_TO_EPOCH_NTP);
+	memcpy(x,&ntime,sizeof(uint32_t));	
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+inline AAA_AVP *cdp_avp_new_UTF8String(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+inline AAA_AVP* cdp_avp_new_DiameterIdentity(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+inline AAA_AVP* cdp_avp_new_DiameterURI(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+inline AAA_AVP* cdp_avp_new_Enumerated(int avp_code,int avp_flags,int avp_vendorid,int32_t data)
+{
+	char x[4];
+	str s={x,4};
+	set_4bytes(x,data);
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,s,AVP_DUPLICATE_DATA);
+}
+
+inline AAA_AVP* cdp_avp_new_IPFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}
+
+inline AAA_AVP* cdp_avp_new_QoSFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do)
+{
+	return cdp_avp_new(avp_code,avp_flags,avp_vendorid,data,data_do);
+}

+ 174 - 0
modules/cdp_avp/avp_new_base_data_format.h

@@ -0,0 +1,174 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef __AVP_NEW_BASE_DATA_FORMAT_H
+#define __AVP_NEW_BASE_DATA_FORMAT_H
+
+#ifndef CDP_AVP_REFERENCE
+
+	#include "../cdp/cdp_load.h"
+
+		#include <inttypes.h>
+		#include <netinet/ip6.h>
+
+		typedef struct {
+			uint16_t ai_family;
+			union{
+				struct in_addr v4;
+				struct in6_addr v6;
+			} ip;
+		} ip_address;
+	
+		typedef struct {
+			uint8_t prefix;
+			ip_address addr;	
+		} ip_address_prefix;
+		
+
+	#define EPOCH_UNIX_TO_EPOCH_NTP 2208988800u // according to http://www.cis.udel.edu/~mills/y2k.html
+	
+	
+	/* 
+	 * RFC 3588 Basic AVP Data Types
+	 * 
+	 * http://tools.ietf.org/html/rfc3588#section-4.2
+	 * 
+	 */
+	
+	AAA_AVP* cdp_avp_new_OctetString(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_OctetString_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* cdp_avp_new_Integer32(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Integer32_f)(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	
+	
+	AAA_AVP* cdp_avp_new_Integer64(int avp_code,int avp_flags,int avp_vendorid,int64_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Integer64_f)(int avp_code,int avp_flags,int avp_vendorid,int64_t data);
+	
+	
+	AAA_AVP* cdp_avp_new_Unsigned32(int avp_code,int avp_flags,int avp_vendorid,uint32_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Unsigned32_f)(int avp_code,int avp_flags,int avp_vendorid,uint32_t data);
+	
+	
+	AAA_AVP* cdp_avp_new_Unsigned64(int avp_code,int avp_flags,int avp_vendorid,uint64_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Unsigned64_f)(int avp_code,int avp_flags,int avp_vendorid,uint64_t data);
+	
+	
+	AAA_AVP* cdp_avp_new_Float32(int avp_code,int avp_flags,int avp_vendorid,float data);
+	typedef AAA_AVP* (*cdp_avp_new_Float32_f)(int avp_code,int avp_flags,int avp_vendorid,float data);
+	
+	
+	AAA_AVP* cdp_avp_new_Float64(int avp_code,int avp_flags,int avp_vendorid,double data);
+	typedef AAA_AVP* (*cdp_avp_new_Float64_f)(int avp_code,int avp_flags,int avp_vendorid,double data);
+	
+	
+	AAA_AVP* cdp_avp_new_Grouped(int avp_code,int avp_flags,int avp_vendorid,AAA_AVP_LIST *list,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_Grouped_f)(int avp_code,int avp_flags,int avp_vendorid,AAA_AVP_LIST *list,AVPDataStatus data_do);
+	
+	
+	/*
+	 * RFC 3588 Derived AVP Data Formats
+	 * 
+	 * http://tools.ietf.org/html/rfc3588#section-4.3
+	 * 
+	 */
+	
+	AAA_AVP* cdp_avp_new_Address(int avp_code,int avp_flags,int avp_vendorid,ip_address data);
+	typedef AAA_AVP* (*cdp_avp_new_Address_f)(int avp_code,int avp_flags,int avp_vendorid,ip_address data);
+	
+	AAA_AVP* cdp_avp_new_Time(int avp_code,int avp_flags,int avp_vendorid,time_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Time_f)(int avp_code,int avp_flags,int avp_vendorid,time_t data);
+	
+	AAA_AVP* cdp_avp_new_UTF8String(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_UTF8String_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* cdp_avp_new_DiameterIdentity(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_DiameterIdentity_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* cdp_avp_new_DiameterURI(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_DiameterURI_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* cdp_avp_new_Enumerated(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	typedef AAA_AVP* (*cdp_avp_new_Enumerated_f)(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	
+	AAA_AVP* cdp_avp_new_IPFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_IPFilterRule_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* cdp_avp_new_QoSFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	typedef AAA_AVP* (*cdp_avp_new_QoSFilterRule_f)(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+
+#else
+		
+	AAA_AVP* basic.new_OctetString(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* basic.new_Integer32(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	
+	AAA_AVP* basic.new_Integer64(int avp_code,int avp_flags,int avp_vendorid,int64_t data);
+	
+	AAA_AVP* basic.new_Unsigned32(int avp_code,int avp_flags,int avp_vendorid,uint32_t data);
+	
+	AAA_AVP* basic.new_Unsigned64(int avp_code,int avp_flags,int avp_vendorid,uint64_t data);
+	
+	AAA_AVP* basic.new_Float32(int avp_code,int avp_flags,int avp_vendorid,float data);
+	
+	AAA_AVP* basic.new_Float64(int avp_code,int avp_flags,int avp_vendorid,double data);
+	
+	AAA_AVP* basic.new_Grouped(int avp_code,int avp_flags,int avp_vendorid,AAA_AVP_LIST *list,AVPDataStatus data_do);
+		
+	AAA_AVP* basic.new_Address(int avp_code,int avp_flags,int avp_vendorid,ip_address data);
+	
+	AAA_AVP* basic.new_Time(int avp_code,int avp_flags,int avp_vendorid,time_t data);
+	
+	AAA_AVP* basic.new_UTF8String(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* basic.new_DiameterIdentity(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* basic.new_DiameterURI(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* basic.new_Enumerated(int avp_code,int avp_flags,int avp_vendorid,int32_t data);
+	
+	AAA_AVP* basic.new_IPFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+	
+	AAA_AVP* basic.new_QoSFilterRule(int avp_code,int avp_flags,int avp_vendorid,str data,AVPDataStatus data_do);
+#endif
+
+
+#endif /* __AVP_NEW_DATA_FORMAT_H */

+ 63 - 0
modules/cdp_avp/base.c

@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new.h"
+#include "avp_new_base_data_format.h"
+#include "avp_add.h"
+#include "avp_get.h"
+#include "avp_get_base_data_format.h"
+
+extern struct cdp_binds *cdp;
+
+
+#include "../cdp/cdp_load.h"
+
+
+#include "base.h"
+
+
+#define CDP_AVP_DEFINITION
+
+	#include "base.h"
+
+#undef CDP_AVP_DEFINITION
+
+
+

+ 430 - 0
modules/cdp_avp/base.h

@@ -0,0 +1,430 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+
+/* 
+ * RFC 3588 Base AVPs
+ * 
+ * http://tools.ietf.org/html/rfc3588
+ * 
+ */
+
+#include "macros.h"
+
+#undef CDP_AVP_MODULE
+#define CDP_AVP_MODULE base
+
+#if !defined(CDP_AVP_DECLARATION) && !defined(CDP_AVP_EXPORT) && !defined(CDP_AVP_INIT) && !defined(CDP_AVP_REFERENCE)
+	#ifndef _CDP_AVP_BASE_H_1
+	#define _CDP_AVP_BASE_H_1
+
+		#include "../cdp/cdp_load.h"
+
+	#else
+
+		/* undo the macros definition if this was re-included */
+		#define CDP_AVP_EMPTY_MACROS
+			#include "macros.h"
+		#undef CDP_AVP_EMPTY_MACROS
+
+	#endif
+#endif //_CDP_AVP_BASE_H_1	
+
+/*
+ * The list of AVPs must be declared in the following format:
+ * 
+ * 		cdp_avp_add(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or
+ * 		cdp_avp_add_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * 		cdp_avp_get(<avp_name>.<vendor_id>,<avp_type>,<data_type>)
+ * 
+ * or, to add both add and get at once:
+ * 
+ * 		cdp_avp(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or 
+ * 		cdp_avp_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * The add macros ending in _ptr will generate function with the extra AVPDataStatus data_do parameter
+ * 
+ * Parameters:
+ *  - avp_name - a value of AVP_<avp_name> must resolve to the AVP code
+ *  - vendor_id - an int value
+ *  - flags	- AVP Flags to add to the AVP
+ *  - avp_type - an avp type for which a function was defined a
+ * 				int cdp_avp_get_<avp_type>(AAA_AVP *avp,<data_type> *data)
+ * 		Some valid suggestions (and the data_type):		
+ *  
+ *  			OctetString 	- str
+ *  			Integer32		- int32_t
+ *  			Integer64 		- int64_t
+ *  			Unsigned32 		- uint32_t
+ *  			Unsigned64 		- uint64_t
+ *  			Float32 		- float
+ *  			Float64 		- double
+ *  			Grouped 		- AAA_AVP_LIST
+ *  
+ *  			Address 		- ip_address
+ *  			Time 			- time_t
+ *  			UTF8String 		- str
+ *  			DiameterIdentity- str
+ *  			DiameterURI		- str
+ *  			Enumerated		- int32_t
+ *  			IPFilterRule	- str
+ *  			QoSFilterRule	- str
+ *  - data_type - the respective data type for the avp_type defined above
+ *  
+ *  The functions generated will return 1 on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>(AAA_AVP_LIST list,<data_type> *data,AAA_AVP **avp_ptr)
+ * 
+ * 
+ *  
+ *  For Grouped AVPs with 2 or 3 known inside AVPs, you can define a shortcut function which will find the group and
+ *  also extract the 2 or 3 AVPs. 
+ *  Do not define both 2 and 3 for the same type!
+ * 
+ * 
+ *		cdp_avp_add2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp_get2(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  	
+ *		cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ *  	cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ * 
+ * 	 or, to add both add and get at once:
+ * 
+ *		cdp_avp2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  
+ *  avp_name_group - a value of AVP_<avp_name_group> must resolve to the AVP code of the group
+ *  
+ *  vendor_id_group - an int value
+ *  
+ *  avp_name_N	- the name of the Nth parameter. 
+ *  	Previously, a cdp_avp_get(<avp_name_N>,<vendor_id_N>,<avp_type_N>,<data_type_N>) must be defined!
+ *  
+ *  data_type_N	- the respective data type for avp_type_N (same as <data_type_N) 
+ *  
+ *  The functions generated will return the number of found AVPs inside on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>_Group(AAA_AVP_LIST list,<data_type_1> *avp_name_1,<data_type_2> *avp_name_2[,<data_type_3> *avp_name_3],AAA_AVP **avp_ptr)
+ *  
+ *  Note - generally, all data of type str will need to be defined with ..._ptr
+ *  Note - Groups must be defined with:
+ *  	 cdp_avp_add_ptr(...) and data_type AAA_AVP_LIST*
+ *  	 cdp_avp_get(...) and data_type AAA_AVP_LIST 	
+ */
+
+cdp_avp_add		(Vendor_Id,						0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+cdp_avp_get		(Vendor_Id,						0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Firmware_Revision,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Host_IP_Address,				0,	AAA_AVP_FLAG_MANDATORY,	Address,			ip_address)
+
+cdp_avp			(Supported_Vendor_Id,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(Product_Name,					0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Disconnect_Cause,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_ptr		(Origin_Host,					0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Origin_Realm,					0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Destination_Host,				0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Destination_Realm,				0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Route_Record,					0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Proxy_Host,					0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_ptr		(Proxy_State,					0,	AAA_AVP_FLAG_MANDATORY,	OctetString,		str)
+
+cdp_avp_add_ptr	(Proxy_Info,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Proxy_Info,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(Auth_Application_Id,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Acct_Application_Id,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Inband_Security_Id,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_add_ptr	(Vendor_Specific_Application_Id,0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Vendor_Specific_Application_Id,0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+cdp_avp_get3	(Vendor_Specific_Application_Id,0,	AAA_AVP_FLAG_MANDATORY,	Vendor_Id, uint32_t, Auth_Application_Id,	 	uint32_t, Acct_Application_Id,	uint32_t)
+
+cdp_avp_ptr		(Redirect_Host,					0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp			(Redirect_Host_Usage,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Redirect_Max_Cache_Time,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(E2E_Sequence,					0,	AAA_AVP_FLAG_MANDATORY,	OctetString,		str)
+
+cdp_avp			(Result_Code,					0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(Error_Message,					0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp_ptr		(Error_Reporting_Host,			0,	AAA_AVP_FLAG_MANDATORY,	DiameterIdentity,	str)
+
+cdp_avp_add_ptr	(Failed_AVP,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Failed_AVP,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(Experimental_Result_Code,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_add_ptr	(Experimental_Result,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Experimental_Result,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+cdp_avp2		(Experimental_Result,			0,	AAA_AVP_FLAG_MANDATORY,	Vendor_Id, uint32_t, Experimental_Result_Code,	uint32_t)
+
+cdp_avp			(Auth_Request_Type,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_ptr		(Session_Id,					0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Authorization_Lifetime,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Auth_Grace_Period,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Auth_Session_State,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Re_Auth_Request_Type,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Session_Timeout,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(User_Name,						0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Termination_Cause,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Origin_State_Id,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Session_Binding,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Session_Server_Failover,		0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Multi_Round_Time_Out,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(Class,							0,	AAA_AVP_FLAG_MANDATORY,	OctetString,		str)
+
+cdp_avp			(Event_Timestamp,				0,	AAA_AVP_FLAG_MANDATORY,	Time,				time_t)
+
+cdp_avp			(Accounting_Record_Type,		0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Acct_Interim_Interval,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Accounting_Record_Number,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(Acct_Session_Id,				0,	AAA_AVP_FLAG_MANDATORY,	OctetString,		str)
+
+cdp_avp_ptr		(Acct_Multi_Session_Id,			0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Accounting_Sub_Session_Id,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp			(Accounting_Realtime_Required,	0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_add_ptr	(MIP6_Agent_Info,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(MIP6_Agent_Info,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(MIP_Home_Agent_Address,		0,	AAA_AVP_FLAG_MANDATORY,	Address,			ip_address)
+
+cdp_avp_add_ptr	(MIP_Home_Agent_Host,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(MIP_Home_Agent_Host,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_ptr		(MIP6_Home_Link_Prefix,			0,	AAA_AVP_FLAG_MANDATORY,	OctetString,		str)
+
+cdp_avp			(MIP6_Feature_Vector,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp_ptr		(Service_Selection,				0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+
+
+/*
+ * From here-on you can define/export/init/declare functions which can not be generate with the macros
+ */
+
+#if defined(CDP_AVP_DEFINITION)
+
+	/*
+	 * Put here your supplimentary definitions. Typically:
+	 * 
+	 * int <function1>(param1)
+	 * {
+	 *   code1
+	 * }
+	 * 
+	 * 
+	 */
+	
+	int cdp_avp_add_Vendor_Specific_Application_Id_Group(AAA_AVP_LIST *list,uint32_t vendor_id,uint32_t auth_app_id,uint32_t acct_app_id)
+	{
+		AAA_AVP_LIST list_grp={0,0};   
+		if (!cdp_avp_add_Vendor_Id(&list_grp,vendor_id)) goto error;
+		if (auth_app_id && !cdp_avp_add_Auth_Application_Id(&list_grp,auth_app_id)) goto error;
+		if (acct_app_id && !cdp_avp_add_Acct_Application_Id(&list_grp,acct_app_id)) goto error;
+			return cdp_avp_add_to_list(list,
+						cdp_avp_new_Grouped(
+								AVP_Vendor_Specific_Application_Id,
+								AAA_AVP_FLAG_MANDATORY,
+								0,
+								&list_grp,
+								AVP_FREE_DATA));       
+	error:
+		cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+
+	/**
+	 * http://tools.ietf.org/html/rfc3588#section-6.11
+	 * @param list
+	 * @param data
+	 * @return
+	 */
+	int cdp_avp_get_Vendor_Specific_Application_Id_example(AAA_AVP_LIST list,uint32_t *vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id)
+	{
+		AAA_AVP_LIST list_grp={0,0};
+		AAA_AVP *avp = cdp_avp_get_from_list(list,
+				AVP_Vendor_Specific_Application_Id,
+				0);
+		if (!avp) goto error;
+		cdp_avp_get_Grouped(avp,&list_grp);
+		if (!cdp_avp_get_Vendor_Id(list_grp,vendor_id,0)) goto error;
+		cdp_avp_get_Auth_Application_Id(list_grp,auth_app_id,0);	
+		cdp_avp_get_Acct_Application_Id(list_grp,acct_app_id,0);	
+		cdp->AAAFreeAVPList(&list_grp);
+		return 1;
+	error:
+		if (vendor_id) *vendor_id = 0;
+		if (auth_app_id) *auth_app_id = 0;
+		if (acct_app_id) *acct_app_id = 0;
+		cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+	
+
+
+#elif defined(CDP_AVP_EXPORT)
+
+	/*
+	 * Put here your supplimentary exports in the format: 
+	 * 	<function_type1> <nice_function_name1>; 
+	 *  <function_type2> <nice_function_name1>;
+	 *  ...
+	 *  
+	 */
+
+	cdp_avp_add_Vendor_Specific_Application_Id_Group_f	add_Vendor_Specific_Application_Id_Group;
+
+	cdp_avp_get_Vendor_Specific_Application_Id_example_f	get_Vendor_Specific_Application_Id_example;
+	
+
+#elif defined(CDP_AVP_INIT)
+
+	/*
+	 * Put here your supplimentary inits in the format: 
+	 * 	<function1>,
+	 *  <function2>,
+	 *  ...
+	 * 
+	 * Make sure you keep the same order as in export!
+	 * 
+	 */
+
+	cdp_avp_add_Vendor_Specific_Application_Id_Group,
+	
+	cdp_avp_get_Vendor_Specific_Application_Id_example,
+	
+
+
+#elif defined(CDP_AVP_REFERENCE)
+	/*
+	 * Put here what you want to get in the reference. Typically:
+	 * <function1>
+	 * <function2>
+	 * ... 
+	 * 
+	 */
+	int CDP_AVP_MODULE.add_Vendor_Specific_Application_Id_Group(AAA_AVP_LIST *list,uint32_t vendor_id,uint32_t auth_app_id,uint32_t acct_app_id);
+	
+	int CDP_AVP_MODULE.get_Vendor_Specific_Application_Id_example(AAA_AVP_LIST list,uint32_t *vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id);
+	
+#elif defined(CDP_AVP_EMPTY_MACROS)
+	
+	/* this should be left blank */
+	
+#else
+
+	/*
+	 * Put here your definitions according to the declarations, exports, init, etc above. Typically:
+	 * 
+	 * int <function1(params1);>
+	 * typedef int <*function_type1>(params1);
+	 * 
+	 * int <function2(param2);>
+	 * typedef int <*function_type2>(params2);
+	 * 
+	 * ...
+	 *  
+	 */
+	
+	#ifndef _CDP_AVP_BASE_H_2
+	#define _CDP_AVP_BASE_H_2
+
+	int cdp_avp_add_Vendor_Specific_Application_Id_Group(AAA_AVP_LIST *list,uint32_t vendor_id,uint32_t auth_app_id,uint32_t acct_app_id);
+	typedef int (*cdp_avp_add_Vendor_Specific_Application_Id_Group_f)(AAA_AVP_LIST *list,uint32_t vendor_id,uint32_t auth_app_id,uint32_t acct_app_id);
+	
+	int cdp_avp_get_Vendor_Specific_Application_Id_example(AAA_AVP_LIST list,uint32_t *vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id);
+	typedef int (*cdp_avp_get_Vendor_Specific_Application_Id_example_f)(AAA_AVP_LIST list,uint32_t *vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id);
+	
+
+	#endif //_CDP_AVP_BASE_H_2
+	
+#endif
+
+
+
+#define CDP_AVP_UNDEF_MACROS
+	#include "macros.h"
+#undef CDP_AVP_UNDEF_MACROS
+	
+
+
+

+ 63 - 0
modules/cdp_avp/ccapp.c

@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new.h"
+#include "avp_new_base_data_format.h"
+#include "avp_add.h"
+#include "avp_get.h"
+#include "avp_get_base_data_format.h"
+
+extern struct cdp_binds *cdp;
+
+
+#include "../cdp/cdp_load.h"
+
+
+#include "ccapp.h"
+
+
+#define CDP_AVP_DEFINITION
+
+	#include "ccapp.h"
+
+#undef CDP_AVP_DEFINITION
+
+
+

+ 463 - 0
modules/cdp_avp/ccapp.h

@@ -0,0 +1,463 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+/* 
+ * RFC 4006 Diameter Credit Control Application
+ * 
+ * http://tools.ietf.org/html/rfc4006
+ * 
+ */
+
+#include "macros.h"
+
+#undef CDP_AVP_MODULE
+#define CDP_AVP_MODULE ccapp
+
+#if !defined(CDP_AVP_DECLARATION) && !defined(CDP_AVP_EXPORT) && !defined(CDP_AVP_INIT) && !defined(CDP_AVP_REFERENCE)
+	#ifndef _CDP_AVP_CCAPP_H_1
+	#define _CDP_AVP_CCAPP_H_1
+
+		#include "../cdp/cdp_load.h"
+
+	#else
+
+		/* undo the macros definition if this was re-included */
+		#define CDP_AVP_EMPTY_MACROS
+			#include "macros.h"
+		#undef CDP_AVP_EMPTY_MACROS
+
+	#endif
+#endif //_CDP_AVP_CCAPP_H_1	
+
+/*
+ * The list of AVPs must be declared in the following format:
+ * 
+ * 		cdp_avp_add(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or
+ * 		cdp_avp_add_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * 		cdp_avp_get(<avp_name>.<vendor_id>,<avp_type>,<data_type>)
+ * 
+ * or, to add both add and get at once:
+ * 
+ * 		cdp_avp(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or 
+ * 		cdp_avp_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * The add macros ending in _ptr will generate function with the extra AVPDataStatus data_do parameter
+ * 
+ * Parameters:
+ *  - avp_name - a value of AVP_<avp_name> must resolve to the AVP code
+ *  - vendor_id - an int value
+ *  - flags	- AVP Flags to add to the AVP
+ *  - avp_type - an avp type for which a function was defined a
+ * 				int cdp_avp_get_<avp_type>(AAA_AVP *avp,<data_type> *data)
+ * 		Some valid suggestions (and the data_type):		
+ *  
+ *  			OctetString 	- str
+ *  			Integer32		- int32_t
+ *  			Integer64 		- int64_t
+ *  			Unsigned32 		- uint32_t
+ *  			Unsigned64 		- uint64_t
+ *  			Float32 		- float
+ *  			Float64 		- double
+ *  			Grouped 		- AAA_AVP_LIST
+ *  
+ *  			Address 		- ip_address
+ *  			Time 			- time_t
+ *  			UTF8String 		- str
+ *  			DiameterIdentity- str
+ *  			DiameterURI		- str
+ *  			Enumerated		- int32_t
+ *  			IPFilterRule	- str
+ *  			QoSFilterRule	- str
+ *  - data_type - the respective data type for the avp_type defined above
+ *  
+ *  The functions generated will return 1 on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>(AAA_AVP_LIST list,<data_type> *data,AAA_AVP **avp_ptr)
+ * 
+ * 
+ *  
+ *  For Grouped AVPs with 2 or 3 known inside AVPs, you can define a shortcut function which will find the group and
+ *  also extract the 2 or 3 AVPs. 
+ *  Do not define both 2 and 3 for the same type!
+ * 
+ * 
+ *		cdp_avp_add2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp_get2(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  	
+ *		cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ *  	cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ * 
+ * 	 or, to add both add and get at once:
+ * 
+ *		cdp_avp2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  
+ *  avp_name_group - a value of AVP_<avp_name_group> must resolve to the AVP code of the group
+ *  
+ *  vendor_id_group - an int value
+ *  
+ *  avp_name_N	- the name of the Nth parameter. 
+ *  	Previously, a cdp_avp_get(<avp_name_N>,<vendor_id_N>,<avp_type_N>,<data_type_N>) must be defined!
+ *  
+ *  data_type_N	- the respective data type for avp_type_N (same as <data_type_N) 
+ *  
+ *  The functions generated will return the number of found AVPs inside on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>_Group(AAA_AVP_LIST list,<data_type_1> *avp_name_1,<data_type_2> *avp_name_2[,<data_type_3> *avp_name_3],AAA_AVP **avp_ptr)
+ *  
+ *  Note - generally, all data of type str will need to be defined with ..._ptr
+ *  Note - Groups must be defined with:
+ *  	 cdp_avp_add_ptr(...) and data_type AAA_AVP_LIST*
+ *  	 cdp_avp_get(...) and data_type AAA_AVP_LIST 	
+ */
+
+
+cdp_avp_ptr		(CC_Correlation_Id,				0,	0,						OctetString,		str)
+
+cdp_avp			(CC_Input_Octets,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp_add_ptr	(CC_Money,						0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(CC_Money,						0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(CC_Output_Octets,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp			(CC_Request_Number,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(CC_Request_Type,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(CC_Service_Specific_Units,		0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp			(CC_Session_Failover,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(CC_Sub_Session_Id,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp			(CC_Time,						0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(CC_Total_Octets,				0,	AAA_AVP_FLAG_MANDATORY,	Unsigned64,			uint64_t)
+
+cdp_avp			(CC_Unit_Type,					0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Check_Balance_Result,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_add_ptr	(Cost_Information,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Cost_Information,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_ptr		(Cost_Unit,						0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Credit_Control,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Credit_Control_Failure_Handling,0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Currency_Code,					0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Direct_Debiting_Failure_Handling,0,AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Exponent,						0,	AAA_AVP_FLAG_MANDATORY,	Integer32,			int32_t)
+
+cdp_avp			(Final_Unit_Action,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_add_ptr	(Final_Unit_Indication,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Final_Unit_Indication,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Granted_Service_Unit,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Granted_Service_Unit,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(G_S_U_Pool_Identifier,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_add_ptr	(G_S_U_Pool_Reference,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(G_S_U_Pool_Reference,			0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Multiple_Services_Credit_Control,0,AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Multiple_Services_Credit_Control,0,AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(Multiple_Services_Indicator,	0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Rating_Group,					0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp			(Redirect_Address_Type,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_add_ptr	(Redirect_Server,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Redirect_Server,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_ptr		(Redirect_Server_Address,		0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Requested_Action,				0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp_add_ptr	(Requested_Service_Unit,		0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Requested_Service_Unit,		0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_ptr		(Restriction_Filter_Rule,		0,	AAA_AVP_FLAG_MANDATORY,	IPFilterRule,		str)
+
+cdp_avp_ptr		(Service_Context_Id,			0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Service_Identifier,			0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+cdp_avp_add_ptr	(Service_Parameter_Info,		0,	0,						Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Service_Parameter_Info,		0,	0,						Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(Service_Parameter_Type,		0,	0,						Unsigned32,			uint32_t)
+
+cdp_avp_ptr		(Service_Parameter_Value,		0,	0,						OctetString,		str)
+
+cdp_avp_add_ptr	(Subscription_Id,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Subscription_Id,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_ptr		(Subscription_Id_Data,			0,	AAA_AVP_FLAG_MANDATORY,	UTF8String,			str)
+
+cdp_avp			(Subscription_Id_Type,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Tariff_Change_Usage,			0,	AAA_AVP_FLAG_MANDATORY,	Enumerated,			int32_t)
+
+cdp_avp			(Tariff_Time_Change,			0,	AAA_AVP_FLAG_MANDATORY,	Time,				time_t)
+
+cdp_avp_add_ptr	(Unit_Value,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Unit_Value,					0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Used_Service_Unit,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(Used_Service_Unit,				0,	AAA_AVP_FLAG_MANDATORY,	Grouped,			AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(User_Equipment_Info,			0,	0,						Grouped,			AAA_AVP_LIST*)
+cdp_avp_get		(User_Equipment_Info,			0,	0,						Grouped,			AAA_AVP_LIST)
+
+cdp_avp			(User_Equipment_Info_Type,		0,	0,						Enumerated,			int32_t)
+
+cdp_avp_ptr		(User_Equipment_Info_Value,		0,	0,						OctetString,		str)
+
+cdp_avp			(Value_Digits,					0,	AAA_AVP_FLAG_MANDATORY, Integer64,			int64_t)
+
+cdp_avp			(Validity_Time,					0,	AAA_AVP_FLAG_MANDATORY,	Unsigned32,			uint32_t)
+
+/*
+ * From here-on you can define/export/init/declare functions which can not be generate with the macros
+ */
+
+#if defined(CDP_AVP_DEFINITION)
+
+	/*
+	 * Put here your supplimentary definitions. Typically:
+	 * 
+	 * int <function1>(param1)
+	 * {
+	 *   code1
+	 * }
+	 * 
+	 * 
+	 */
+	
+	int cdp_avp_add_Subscription_Id_Group(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do)
+	{
+		AAA_AVP_LIST list_grp={0,0};	
+		if (!cdp_avp_add_Subscription_Id_Type(&list_grp,type)) goto error;
+		if (!cdp_avp_add_Subscription_Id_Data(&list_grp,data,data_do)) goto error;
+		return cdp_avp_add_to_list(list,
+				cdp_avp_new_Grouped(
+						AVP_Subscription_Id,
+						AAA_AVP_FLAG_MANDATORY,
+						0,
+						&list_grp,
+						AVP_FREE_DATA));	
+		error:
+			if (data_do==AVP_FREE_DATA && data.s) shm_free(data.s);
+			cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+
+	int cdp_avp_get_Subscription_Id_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr)
+	{
+		AAA_AVP_LIST list_grp={0,0};
+		AAA_AVP *avp = cdp_avp_get_next_from_list(list,
+				AVP_Subscription_Id,
+				0,
+				avp_ptr?*avp_ptr:0);
+		if (avp_ptr) *avp_ptr= avp; 
+		if (!avp) goto error;
+		if (!cdp_avp_get_Grouped(avp,&list_grp)) goto error;
+		if (!cdp_avp_get_Subscription_Id_Type(list_grp,type,0)) goto error;
+		if (!cdp_avp_get_Subscription_Id_Data(list_grp,data,0)) goto error;
+		cdp->AAAFreeAVPList(&list_grp);
+		return 1;
+	error:
+		if (type) *type = 0;
+		if (data) {data->s=0;data->len=0;}
+		cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+
+
+	int cdp_avp_add_User_Equipment_Info_Group(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do)
+	{
+		AAA_AVP_LIST list_grp={0,0};	
+		if (!cdp_avp_add_User_Equipment_Info_Type(&list_grp,type)) goto error;
+		if (!cdp_avp_add_User_Equipment_Info_Value(&list_grp,data,data_do)) goto error;
+		return cdp_avp_add_to_list(list,
+				cdp_avp_new_Grouped(
+						AVP_User_Equipment_Info,
+						AAA_AVP_FLAG_MANDATORY,
+						0,
+						&list_grp,
+						AVP_FREE_DATA));	
+	error:
+		if (data_do==AVP_FREE_DATA && data.s) shm_free(data.s);
+		cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+
+	int cdp_avp_get_User_Equipment_Info_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr)
+	{
+		AAA_AVP_LIST list_grp={0,0};
+		AAA_AVP *avp = cdp_avp_get_next_from_list(list,
+				AVP_User_Equipment_Info,
+				0,
+				avp_ptr?*avp_ptr:0);
+		if (avp_ptr) *avp_ptr= avp;  
+		if (!avp) goto error;
+		if (!cdp_avp_get_Grouped(avp,&list_grp)) goto error;
+		if (!cdp_avp_get_User_Equipment_Info_Type(list_grp,type,0)) goto error;
+		if (!cdp_avp_get_User_Equipment_Info_Value(list_grp,data,0)) goto error;
+		cdp->AAAFreeAVPList(&list_grp);
+		return 1;
+	error:
+		if (type) *type = 0;
+		if (data) {data->s=0;data->len=0;}
+		cdp->AAAFreeAVPList(&list_grp);
+		return 0;
+	}
+	
+#elif defined(CDP_AVP_EXPORT)
+
+	/*
+	 * Put here your supplimentary exports in the format: 
+	 * 	<function_type1> <nice_function_name1>; 
+	 *  <function_type2> <nice_function_name1>;
+	 *  ...
+	 *  
+	 */
+	cdp_avp_add_Subscription_Id_Group_f		add_Subscription_Id_Group;
+	cdp_avp_get_Subscription_Id_Group_f		get_Subscription_Id_Group;
+	
+	cdp_avp_add_User_Equipment_Info_Group_f		add_User_Equipment_Info_Group;
+	cdp_avp_get_User_Equipment_Info_Group_f		get_User_Equipment_Info_Group;
+	
+#elif defined(CDP_AVP_INIT)
+
+	/*
+	 * Put here your supplimentary inits in the format: 
+	 * 	<function1>,
+	 *  <function2>,
+	 *  ...
+	 * 
+	 * Make sure you keep the same order as in export!
+	 * 
+	 */
+	cdp_avp_add_Subscription_Id_Group,
+	cdp_avp_get_Subscription_Id_Group,
+
+	cdp_avp_add_User_Equipment_Info_Group,
+	cdp_avp_get_User_Equipment_Info_Group,
+	
+#elif defined(CDP_AVP_REFERENCE)
+	/*
+	 * Put here what you want to get in the reference. Typically:
+	 * <function1>
+	 * <function2>
+	 * ... 
+	 * 
+	 */
+int CDP_AVP_MODULE.add_Subscription_Id_Group(AAA_AVP_LIST *list,int32_t type,str data,AVPDataStatus data_do);
+int CDP_AVP_MODULE.get_Subscription_Id_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+		
+int CDP_AVP_MODULE.add_User_Equipment_Info_Group(AAA_AVP_LIST *list,int32_t type,str data,AVPDataStatus data_do);
+int CDP_AVP_MODULE.get_User_Equipment_Info_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+	
+#elif defined(CDP_AVP_EMPTY_MACROS)
+	
+	/* this should be left blank */
+	
+#else
+
+	/*
+	 * Put here your definitions according to the declarations, exports, init, etc above. Typically:
+	 * 
+	 * int <function1(params1);>
+	 * typedef int <*function_type1>(params1);
+	 * 
+	 * int <function2(param2);>
+	 * typedef int <*function_type2>(params2);
+	 * 
+	 * ...
+	 *  
+	 */
+
+	
+	#ifndef _CDP_AVP_CCAPP_H_2
+	#define _CDP_AVP_CCAPP_H_2
+
+	
+		int cdp_avp_add_Subscription_Id_Group(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do);
+		typedef int (*cdp_avp_add_Subscription_Id_Group_f)(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do);
+
+		int cdp_avp_get_Subscription_Id_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+		typedef int (*cdp_avp_get_Subscription_Id_Group_f)(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+		
+
+		int cdp_avp_add_User_Equipment_Info_Group(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do);
+		typedef int (*cdp_avp_add_User_Equipment_Info_Group_f)(AAA_AVP_LIST *list,int32_t type, str data,AVPDataStatus data_do);
+
+		int cdp_avp_get_User_Equipment_Info_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+		typedef int (*cdp_avp_get_User_Equipment_Info_Group_f)(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+		
+	#endif //_CDP_AVP_CCAPP_H_2
+	
+#endif
+
+
+
+#define CDP_AVP_UNDEF_MACROS
+	#include "macros.h"
+#undef CDP_AVP_UNDEF_MACROS
+	
+
+
+

+ 4 - 0
modules/cdp_avp/doc/Makefile

@@ -0,0 +1,4 @@
+docs = cdp_avp.xml
+
+docbook_dir = ../../../docbook
+include $(docbook_dir)/Makefile.module

+ 54 - 0
modules/cdp_avp/doc/cdp_avp.xml

@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<book xmlns:xi="http://www.w3.org/2001/XInclude">
+	<bookinfo>
+	<title>cdp_avp Module</title>
+	<productname class="trade">&kamailioname;</productname>
+	<authorgroup>
+		<author>
+		<firstname>Dragos</firstname>
+		<surname>Vingarzan</surname>
+		<affiliation><orgname>Fraunhofer</orgname></affiliation>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</author>
+		<editor>
+		<firstname>Jason</firstname>
+		<surname>Penton</surname>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</editor>
+		<editor>
+		<firstname>Richard</firstname>
+		<surname>Good</surname>
+		<address>
+			<email>[email protected]</email>
+		</address>
+		</editor>
+	</authorgroup>
+	<copyright>
+		<year>2006</year>
+		<holder>FhG Fokus</holder>
+	</copyright>
+	<copyright>
+		<year>2012</year>
+		<holder>Smile Communications</holder>
+	</copyright>
+	</bookinfo>
+	<toc></toc>
+	
+	<xi:include href="cdp_avp_admin.xml"/>
+	<xi:include href="cdp_avp_devel.xml"/>
+	<xi:include href="cdp_avp_faq.xml"/>
+	
+</book>

+ 93 - 0
modules/cdp_avp/doc/cdp_avp_admin.xml

@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module User's Guide -->
+<chapter>
+  <title>&adminguide;</title>
+
+  <section>
+    <title>Overview</title>
+
+    <para>CDP AVP is a helper module for various applications ontop of CDP (C
+    Diameter Peer). CDP AVP modules adds support for the following
+    applications:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>Various base AVPs (implemented in base.h) for RFC3588 base
+        AVPs</para>
+      </listitem>
+
+      <listitem>
+        <para>Base AVPs (implemented in nasapp.h) for RFC4005 base AVPs</para>
+      </listitem>
+
+      <listitem>
+        <para>Diameter Credit Control App (implemented in ccap.h) for RFC4006
+        AVPs</para>
+      </listitem>
+
+      <listitem>
+        <para>EPC (implemented in epcapp.h) for 3GPP Rx, Gx(x) interface AVPs
+        - see TS29l061, TS29.212, TS29.214, TS29.272 and TS29.299</para>
+      </listitem>
+
+      <listitem>
+        <para>IMS (implemented in imsapp.h) for 3GPP IMS AVPs, Cx, Dx, Sh
+        interfaces - see TS29.229 and TS29.329</para>
+      </listitem>
+    </itemizedlist>
+  </section>
+
+  <section>
+    <title>How it works</title>
+
+    <para>CDP AVP is a lightwieght helper module that doesn't really do much
+    other than offer a set of AVP facilitating functions for various
+    application uses. CDP AVP module is used in conjunction with CDP
+    module.</para>
+  </section>
+
+  <section>
+    <title>Dependencies</title>
+
+    <section>
+      <title>&kamailio; Modules</title>
+
+      <para>The following modules must be loaded before this module:
+      <itemizedlist>
+          <listitem>
+            <para><emphasis>CDP</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+
+    <section>
+      <title>External Libraries or Applications</title>
+
+      <para>The following libraries or applications must be installed before
+      running &kamailio; with this module loaded: <itemizedlist>
+          <listitem>
+            <para><emphasis>None</emphasis>.</para>
+          </listitem>
+        </itemizedlist></para>
+    </section>
+  </section>
+
+  <section>
+    <title>Parameters</title>
+
+    <para>None</para>
+  </section>
+
+  <section>
+    <title>Functions</title>
+
+    <para>No functions available from configuraion. See API for internal
+    functions.</para>
+  </section>
+</chapter>

+ 1018 - 0
modules/cdp_avp/doc/cdp_avp_devel.xml

@@ -0,0 +1,1018 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+]>
+<!-- Module Developer's Guide -->
+<chapter>
+  <title>&develguide;</title>
+
+  <section>
+    <title>How to use</title>
+
+    <para>Listing all possible functions here would be overkill and it is left
+    to the developer to browse the varoius function prototypes in the source.
+    It may however be valuable to give a few code snippets to show how to use
+    this module. The API structure used to export the various functions looks
+    as follows:</para>
+
+    <programlisting>typedef struct {
+struct cdp_binds *cdp;
+cdp_avp_bind_basic_t basic;
+cdp_avp_bind_base_data_format_t data;
+cdp_avp_bind_base_avp_t base;
+cdp_avp_bind_ccapp_avp_t ccapp;
+cdp_avp_bind_nasapp_avp_t nasapp;
+cdp_avp_bind_imsapp_avp_t imsapp;
+cdp_avp_bind_epcapp_avp_t epcapp;
+} cdp_avp_bind_t;</programlisting>
+  </section>
+
+  <section>
+    <title>Reference Functions</title>
+
+    <para>The Following is a list of functions for the various supported
+    applications</para>
+
+    <section>
+      <title>nasapp</title>
+
+      <para><programlisting>int nasapp.add_Accounting_Input_Octets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Input_Packets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Output_Octets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Accounting_Output_Packets(AAA_AVP_LIST *list,uint64_t data);
+int nasapp.add_Called_Station_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int nasapp.add_Filter_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int nasapp.add_Framed_IP_Address(AAA_AVP_LIST *list,ip_address ip);
+int nasapp.add_Framed_IPv6_Prefix(AAA_AVP_LIST *list,ip_address_prefix ip);
+int nasapp.get_Accounting_Input_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int nasapp.get_Accounting_Input_Packets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int nasapp.get_Accounting_Output_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int nasapp.get_Accounting_Output_Packets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int nasapp.get_Called_Station_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int nasapp.get_Filter_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int nasapp.get_Framed_IP_Address(AAA_AVP_LIST list,ip_address *ip,AAA_AVP **avp_ptr);
+int nasapp.get_Framed_IPv6_Prefix(AAA_AVP_LIST list,ip_address_prefix *ip,AAA_AVP **avp_ptr);
+</programlisting></para>
+    </section>
+
+    <section>
+      <title>imsapp</title>
+
+      <para><programlisting>int imsapp.add_Associated_Identities(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Associated_Registered_Identities(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_Algorithm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_Auth_Param(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_Domain(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_HA1(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_QoP(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_Digest_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_CableLabs_SIP_Digest_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Charging_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Confidentiality_Key(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Contact(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Current_Location(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Data_Reference(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Deregistration_Reason(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_DSAI_Tag(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Algorithm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Auth_Param(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_CNonce(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Domain(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Entity_Body_Hash(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_HA1(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Method(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Nextnonce(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Nonce(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Nonce_Count(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Opaque(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_QoP(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Response(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Response_Auth(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Stale(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_URI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Digest_Username(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_Line_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_ETSI_SIP_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_ETSI_SIP_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_ETSI_SIP_Authorization(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Expiry_Time(AAA_AVP_LIST *list,time_t data);
+int imsapp.add_Feature_List(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Feature_List_ID(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_From_SIP_Header(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Identity_Set(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Integrity_Key(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Loose_Route_Indication(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Mandatory_Capability(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_MSISDN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Multiple_Registration_Indication(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Optional_Capability(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Originating_Request(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Path(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Primary_Charging_Collection_Function_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Primary_Event_Charging_Function_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Public_Identity(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Reason_Code(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Reason_Info(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Record_Route(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Requested_Domain(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Restoration_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_SCSCF_Restoration_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Secondary_Charging_Collection_Function_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Secondary_Event_Charging_Function_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Send_Data_Indication(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Server_Assignment_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Server_Capabilities(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Server_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Service_Indication(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_SIP_Auth_Data_Item(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_SIP_Authenticate(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_SIP_Authentication_Context(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_SIP_Authentication_Scheme(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_SIP_Authorization(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_SIP_Digest_Authenticate(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_SIP_Item_Number(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_SIP_Number_Auth_Items(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_Subscription_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Subs_Req_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_Supported_Applications(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Supported_Features(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Supported_Features_Group(AAA_AVP_LIST *list,uint32_t Vendor_Id,uint32_t Feature_List_ID,uint32_t Feature_List);
+int imsapp.add_To_SIP_Header(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_UAR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int imsapp.add_User_Authorization_Type(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_User_Data_Already_Available(AAA_AVP_LIST *list,int32_t data);
+int imsapp.add_User_Data_Cx(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_User_Data_Sh(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_User_Identity(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int imsapp.add_Visited_Network_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Wildcarded_IMPU(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.add_Wildcarded_PSI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int imsapp.get_Associated_Identities(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Associated_Registered_Identities(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_Algorithm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_Auth_Param(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_Domain(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_HA1(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_QoP(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_Digest_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_CableLabs_SIP_Digest_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Charging_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Confidentiality_Key(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Contact(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Current_Location(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Data_Reference(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Deregistration_Reason(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_DSAI_Tag(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Algorithm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Auth_Param(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_CNonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Domain(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Entity_Body_Hash(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_HA1(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Method(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Nextnonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Nonce(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Nonce_Count(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Opaque(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_QoP(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Response(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Response_Auth(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Stale(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_URI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Digest_Username(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_Line_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_SIP_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_SIP_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_ETSI_SIP_Authorization(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Expiry_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Feature_List(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Feature_List_ID(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_From_SIP_Header(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Identity_Set(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Integrity_Key(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Loose_Route_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Mandatory_Capability(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_MSISDN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Multiple_Registration_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Optional_Capability(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Originating_Request(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Path(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Primary_Charging_Collection_Function_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Primary_Event_Charging_Function_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Public_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Reason_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Reason_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Record_Route(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Requested_Domain(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Restoration_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_SCSCF_Restoration_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Secondary_Charging_Collection_Function_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Secondary_Event_Charging_Function_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Send_Data_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Server_Assignment_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Server_Capabilities(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Server_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Service_Indication(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Auth_Data_Item(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Authenticate(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Authentication_Context(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Authentication_Scheme(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Authorization(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Digest_Authenticate(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Item_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_SIP_Number_Auth_Items(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Subscription_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Subs_Req_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_Supported_Applications(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Supported_Features(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Supported_Features_Group(AAA_AVP_LIST list,uint32_t *Vendor_Id,uint32_t *Feature_List_ID,uint32_t *Feature_List,AAA_AVP **avp_ptr);
+int imsapp.get_To_SIP_Header(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_UAR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Authorization_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Data_Already_Available(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Data_Cx(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Data_Sh(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_User_Identity(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int imsapp.get_Visited_Network_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Wildcarded_IMPU(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int imsapp.get_Wildcarded_PSI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+</programlisting></para>
+    </section>
+
+    <section>
+      <title>epcapp</title>
+
+      <para><programlisting>int epcapp.add_3GPP2_MEID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_AAA_Server_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_Charging_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_MS_TimeZone(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_PDP_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_3GPP_SGSN_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_SGSN_IPv6_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_SGSN_MCC_MNC(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_3GPP_User_Location_Info(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Abort_Cause(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Acceptable_Service_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Access_Network_Charging_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Access_Network_Charging_Identifier(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Access_Network_Charging_Identifier_Gx(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Access_Network_Charging_Identifier_Value(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Access_Restriction_Data(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_AF_Application_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_AF_Charging_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_AF_Correlation_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Alert_Reason(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_All_APN_Configurations_Included_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Allocation_Retention_Priority(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_AMBR(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_AMBR_Group(AAA_AVP_LIST *list,uint32_t Max_Requested_Bandwidth_UL,uint32_t Max_Requested_Bandwidth_DL);
+int epcapp.add_AN_GW_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_ANID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_APN_Aggregate_Max_Bitrate_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_APN_Aggregate_Max_Bitrate_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_APN_Configuration(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_APN_Configuration_Profile(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_APN_OI_Replacement(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Application_Provided_Called_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Application_Server(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Application_Server_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Authorized_QoS(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_AUTN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Bearer_Control_Mode(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Bearer_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Bearer_Operation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Bearer_Usage(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Call_Barring_Infor_List(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Called_Asserted_Identity(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Called_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Calling_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Cancellation_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Cause_Code(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Charging_Rule_Base_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Charging_Rule_Definition(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Charging_Rule_Install(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Charging_Rule_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Charging_Rule_Remove(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Charging_Rule_Report(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Client_Identity(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_CoA_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_CoA_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Codec_Data(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Complete_Data_List_Included_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Content_Disposition(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Content_Length(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Content_Size(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Content_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Context_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_CSG_Id(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_CSG_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Default_EPS_Bearer_QoS(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_DSA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_DSR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Early_Media_Description(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_EPS_Subscribed_QoS_Profile(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Equipment_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_E_UTRAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Event(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Event_Report_Indication(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Event_Trigger(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Event_Type(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Expiration_Date(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Expires(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_External_Client(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Flow_Description(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Flow_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Flow_Label(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Flow_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Flows(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Flow_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Flow_Usage(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_GERAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_GG_Enforce(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_GG_Enforce_Group(AAA_AVP_LIST * avpList, str imsi, ip_address ue_ip, ip_address gg_ip, AVPDataStatus status);
+int epcapp.add_GG_IP(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GGSN_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GMLC_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_GMLC_Number(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_GMLC_Restriction(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_GPRS_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Guaranteed_Bitrate_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Guaranteed_Bitrate_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Homogenous_Support_of_IMS_Over_PS_Sessions(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_HPLMN_ODB(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_ICS_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_IDA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IDR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IMEI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Immediate_Response_Preferred(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_IMS_Charging_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_IMS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_IMS_Voice_Over_PS_Sessions_Supported(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Inter_Operator_Identifier(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_IP_CAN_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Item_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_KASME(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Kc(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Last_UE_Activity_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_LCS_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_LCS_Privacy_Exception(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Local_Sequence_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Max_Requested_Bandwidth_DL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Max_Requested_Bandwidth_UL(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Media_Component_Description(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Media_Component_Number(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Media_Initiator_Flag(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Media_Initiator_Party(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Media_Sub_Component(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Media_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Message_Body(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Metering_Method(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_MO_LR(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Network_Access_Mode(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Network_Request_Support(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Node_Functionality(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_IP_Access(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_IP_Access_APN(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Non_3GPP_User_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_NOR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Notification_To_UE_User(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Number_Of_Requested_Vectors(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Offline(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_OMC_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Online(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Operator_Determined_Barring(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Originating_IOI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Originator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Outgoing_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Packet_Filter_Content(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Packet_Filter_Identifier(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Packet_Filter_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Packet_Filter_Operation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PCC_Rule_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDN_Connection_ID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_PDN_Gw_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_PDN_Gw_Allocation_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDN_Gw_Identity(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_PDN_Gw_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_PDN_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_PDP_Context(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_PDP_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_PLMN_Client(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Precedence(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Pre_emption_Capability(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Pre_emption_Vulnerability(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Priority_Level(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_PS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_PUA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_QoS_Class_Identifier(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_QoS_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_QoS_Negotiation(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_QoS_Profile_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Definition(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Install(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Remove(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_QoS_Rule_Report(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_QoS_Subscribed(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_QoS_Upgrade(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_RAI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_RAND(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_RAT_Frequency_Selection_Priority_ID(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_RAT_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Regional_Subscription_Zone_Code(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Reporting_Level(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Requested_EUTRAN_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Requested_Party_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Requested_UTRAN_GERAN_Authentication_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Reservation_Priority(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Resource_Allocation_Notification(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Re_Synchronization_Info(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Revalidation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Roaming_Restricted_Due_To_Unsupported_Feature(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Role_Of_Node(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_RR_Bandwidth(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_RS_Bandwidth(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Rule_Activation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Rule_DeActivation_Time(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Rule_Failure_Code(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_SDP_Answer_TimeStamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SDP_Media_Component(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_SDP_Media_Description(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SDP_Media_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SDP_Offer_TimeStamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SDP_Session_Description(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SDP_TimeStamps(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_SDP_Type(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Security_Parameter_Index(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Served_Party_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Service_Data_Container(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Service_ID(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Service_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Service_Info_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Service_Specific_Data(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Service_Specific_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Service_Specific_Type(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Service_Type(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Service_URN(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Session_Linking_Indicator(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Session_Release_Cause(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Sevice_Type_Identity(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_SGSN_Address(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_SGSN_Number(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SIP_Forking_Indication(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_SIP_Method(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SIP_Request_Timestamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SIP_Request_Timestamp_Fraction(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_SIP_Response_Timestamp(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_SIP_Response_Timestamp_Fraction(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Software_Version(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Specific_Action(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Specific_APN_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_SRES(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SS_Code(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_SS_Status(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_STN_SR(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Subscriber_Status(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Subscription_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Teleservice_List(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Terminal_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Terminating_IOI(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_TFT_Filter(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_TFT_Packet_Filter_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_TGPP_RAT_Type(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Time_First_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Time_Last_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_Time_Stamps(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Time_Usage(AAA_AVP_LIST *list,time_t data);
+int epcapp.add_ToS_Traffic_Class(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Trace_Collection_Entity(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_Trace_Data(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Trace_Depth(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_Trace_Event_List(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Trace_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Trace_Interface_List(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Trace_NE_Type_List(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Trace_Reference(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_TS_Code(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Tunnel_Header_Filter(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_Tunnel_Header_Length(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_Tunnel_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_UE_Locator(AAA_AVP_LIST *list,ip_address data);
+int epcapp.add_UE_Locator_Id_Group(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_ULA_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_ULR_Flags(AAA_AVP_LIST *list,uint32_t data);
+int epcapp.add_User_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_User_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_UTRAN_Vector(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int epcapp.add_Visited_PLMN_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.add_VPLMN_Dynamic_Address_Allowed(AAA_AVP_LIST *list,int32_t data);
+int epcapp.add_XRES(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int epcapp.get_3GPP2_MEID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_AAA_Server_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_Charging_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_MS_TimeZone(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_PDP_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_SGSN_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_SGSN_IPv6_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_SGSN_MCC_MNC(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_3GPP_User_Location_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Abort_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Acceptable_Service_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier_Gx(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Network_Charging_Identifier_Value(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Access_Restriction_Data(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_AF_Application_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_AF_Charging_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_AF_Correlation_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Alert_Reason(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_All_APN_Configurations_Included_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Allocation_Retention_Priority(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_AMBR(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_AMBR_Group(AAA_AVP_LIST list,uint32_t *Max_Requested_Bandwidth_UL,uint32_t *Max_Requested_Bandwidth_DL,AAA_AVP **avp_ptr);
+int epcapp.get_AN_GW_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_ANID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_Aggregate_Max_Bitrate_DL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_Aggregate_Max_Bitrate_UL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_Configuration(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_Configuration_Profile(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_APN_OI_Replacement(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Application_Provided_Called_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Application_Server(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Application_Server_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Authorized_QoS(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_AUTN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Control_Mode(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Operation(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Bearer_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Call_Barring_Infor_List(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Called_Asserted_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Called_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Calling_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Cancellation_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Cause_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Base_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Definition(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Install(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Remove(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Charging_Rule_Report(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Client_Identity(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_CoA_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_CoA_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_Codec_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Complete_Data_List_Included_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Disposition(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Length(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Size(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Content_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Context_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_CSG_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_CSG_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Default_EPS_Bearer_QoS(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_DSA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_DSR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Early_Media_Description(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_EPS_Subscribed_QoS_Profile(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Equipment_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_E_UTRAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event_Report_Indication(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event_Trigger(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Event_Type(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Expiration_Date(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Expires(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_External_Client(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Label(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flows(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Flow_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_GERAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_GG_Enforce(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_GG_IP(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_GGSN_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_GMLC_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_GMLC_Number(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_GMLC_Restriction(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_GPRS_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Guaranteed_Bitrate_DL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Guaranteed_Bitrate_UL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Homogenous_Support_of_IMS_Over_PS_Sessions(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_HPLMN_ODB(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ICS_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IDA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IDR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IMEI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Immediate_Response_Preferred(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_IMS_Charging_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_IMS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_IMS_Voice_Over_PS_Sessions_Supported(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Inter_Operator_Identifier(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_IP_CAN_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Item_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_KASME(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Kc(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Last_UE_Activity_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_LCS_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_LCS_Privacy_Exception(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Local_Sequence_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Max_Requested_Bandwidth_DL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Max_Requested_Bandwidth_UL(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Component_Description(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Component_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Initiator_Flag(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Initiator_Party(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Sub_Component(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Media_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Message_Body(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Metering_Method(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_MO_LR(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Network_Access_Mode(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Network_Request_Support(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Node_Functionality(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Non_3GPP_IP_Access(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Non_3GPP_IP_Access_APN(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Non_3GPP_User_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_NOR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Notification_To_UE_User(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Number_Of_Requested_Vectors(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Offline(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_OMC_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Online(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Operator_Determined_Barring(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Originating_IOI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Originator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Outgoing_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Packet_Filter_Content(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Packet_Filter_Identifier(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Packet_Filter_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Packet_Filter_Operation(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PCC_Rule_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Connection_ID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Gw_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Gw_Allocation_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Gw_Identity(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Gw_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDN_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDP_Context(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_PDP_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_PLMN_Client(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Precedence(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Pre_emption_Capability(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Pre_emption_Vulnerability(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Priority_Level(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_PS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_PUA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Class_Identifier(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Negotiation(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Profile_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Definition(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Install(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Remove(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Rule_Report(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Subscribed(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_QoS_Upgrade(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAND(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAT_Frequency_Selection_Priority_ID(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RAT_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Regional_Subscription_Zone_Code(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Reporting_Level(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Requested_EUTRAN_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Requested_Party_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Requested_UTRAN_GERAN_Authentication_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Reservation_Priority(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Resource_Allocation_Notification(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Re_Synchronization_Info(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Revalidation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Roaming_Restricted_Due_To_Unsupported_Feature(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Role_Of_Node(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RR_Bandwidth(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_RS_Bandwidth(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Rule_Activation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Rule_DeActivation_Time(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Rule_Failure_Code(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Answer_TimeStamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Media_Component(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Media_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Media_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Offer_TimeStamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Session_Description(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_TimeStamps(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_SDP_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Security_Parameter_Index(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Served_Party_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Data_Container(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_ID(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Info_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Specific_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Specific_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Specific_Type(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_Type(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Service_URN(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Session_Linking_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Session_Release_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Sevice_Type_Identity(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SGSN_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_SGSN_Number(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Forking_Indication(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Method(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Request_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Request_Timestamp_Fraction(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Response_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_SIP_Response_Timestamp_Fraction(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Software_Version(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Specific_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Specific_APN_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_SRES(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SS_Code(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_SS_Status(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_STN_SR(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Subscriber_Status(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Subscription_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Teleservice_List(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Terminal_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Terminating_IOI(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TFT_Filter(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TFT_Packet_Filter_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_TGPP_RAT_Type(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Time_First_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Time_Last_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Time_Stamps(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Time_Usage(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ToS_Traffic_Class(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Collection_Entity(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Data(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Depth(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Event_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Interface_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_NE_Type_List(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Trace_Reference(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_TS_Code(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Tunnel_Header_Filter(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_Tunnel_Header_Length(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_Tunnel_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_UE_Locator(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int epcapp.get_UE_Locator_Id_Group(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_ULA_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_ULR_Flags(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_User_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_User_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_UTRAN_Vector(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int epcapp.get_Visited_PLMN_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int epcapp.get_VPLMN_Dynamic_Address_Allowed(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int epcapp.get_XRES(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+</programlisting></para>
+    </section>
+
+    <section>
+      <title>ccapp</title>
+
+      <para><programlisting>int ccapp.add_CC_Correlation_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_CC_Input_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Money(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_CC_Output_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Request_Number(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_CC_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_CC_Service_Specific_Units(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Session_Failover(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_CC_Sub_Session_Id(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Time(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_CC_Total_Octets(AAA_AVP_LIST *list,uint64_t data);
+int ccapp.add_CC_Unit_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Check_Balance_Result(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Cost_Information(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Cost_Unit(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Credit_Control(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Credit_Control_Failure_Handling(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Currency_Code(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Direct_Debiting_Failure_Handling(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Exponent(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Final_Unit_Action(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Final_Unit_Indication(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Granted_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_G_S_U_Pool_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_G_S_U_Pool_Reference(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Multiple_Services_Credit_Control(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Multiple_Services_Indicator(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Rating_Group(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Redirect_Address_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Redirect_Server(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Redirect_Server_Address(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Requested_Action(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Requested_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Restriction_Filter_Rule(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Service_Context_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Service_Identifier(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Service_Parameter_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Service_Parameter_Type(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Service_Parameter_Value(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Subscription_Id(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Subscription_Id_Data(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Subscription_Id_Group(AAA_AVP_LIST *list,int32_t type,str data,AVPDataStatus data_do);
+int ccapp.add_Subscription_Id_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Tariff_Change_Usage(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_Tariff_Time_Change(AAA_AVP_LIST *list,time_t data);
+int ccapp.add_Unit_Value(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_Used_Service_Unit(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_User_Equipment_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int ccapp.add_User_Equipment_Info_Group(AAA_AVP_LIST *list,int32_t type,str data,AVPDataStatus data_do);
+int ccapp.add_User_Equipment_Info_Type(AAA_AVP_LIST *list,int32_t data);
+int ccapp.add_User_Equipment_Info_Value(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int ccapp.add_Validity_Time(AAA_AVP_LIST *list,uint32_t data);
+int ccapp.add_Value_Digits(AAA_AVP_LIST *list,int64_t data);
+int ccapp.get_CC_Correlation_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Input_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Money(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Output_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Request_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Service_Specific_Units(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Session_Failover(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Sub_Session_Id(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Total_Octets(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_CC_Unit_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Check_Balance_Result(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Cost_Information(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Cost_Unit(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Credit_Control(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Credit_Control_Failure_Handling(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Currency_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Direct_Debiting_Failure_Handling(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Exponent(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Final_Unit_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Final_Unit_Indication(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Granted_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_G_S_U_Pool_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_G_S_U_Pool_Reference(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Multiple_Services_Credit_Control(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Multiple_Services_Indicator(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Rating_Group(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Redirect_Address_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Redirect_Server(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Redirect_Server_Address(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Requested_Action(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Requested_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Restriction_Filter_Rule(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Context_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Identifier(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Parameter_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Parameter_Type(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Service_Parameter_Value(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Subscription_Id(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Subscription_Id_Data(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Subscription_Id_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Subscription_Id_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Tariff_Change_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Tariff_Time_Change(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Unit_Value(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_Used_Service_Unit(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_User_Equipment_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int ccapp.get_User_Equipment_Info_Group(AAA_AVP_LIST list,int32_t *type,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_User_Equipment_Info_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_User_Equipment_Info_Value(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int ccapp.get_Validity_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int ccapp.get_Value_Digits(AAA_AVP_LIST list,int64_t *data,AAA_AVP **avp_ptr);
+</programlisting></para>
+    </section>
+
+    <section>
+      <title>base</title>
+
+      <para><programlisting>int base.add_Accounting_Realtime_Required(AAA_AVP_LIST *list,int32_t data);
+int base.add_Accounting_Record_Number(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Accounting_Record_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Accounting_Sub_Session_Id(AAA_AVP_LIST *list,uint64_t data);
+int base.add_Acct_Application_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Acct_Interim_Interval(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Acct_Multi_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Acct_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Auth_Application_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Auth_Grace_Period(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Authorization_Lifetime(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Auth_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Auth_Session_State(AAA_AVP_LIST *list,int32_t data);
+int base.add_Class(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Destination_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Destination_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Disconnect_Cause(AAA_AVP_LIST *list,int32_t data);
+int base.add_E2E_Sequence(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Error_Message(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Error_Reporting_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Event_Timestamp(AAA_AVP_LIST *list,time_t data);
+int base.add_Experimental_Result(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_Experimental_Result_Code(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Experimental_Result_Group(AAA_AVP_LIST *list,uint32_t Vendor_Id,uint32_t Experimental_Result_Code);
+int base.add_Failed_AVP(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_Firmware_Revision(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Host_IP_Address(AAA_AVP_LIST *list,ip_address data);
+int base.add_Inband_Security_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_MIP6_Agent_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_MIP6_Feature_Vector(AAA_AVP_LIST *list,uint64_t data);
+int base.add_MIP6_Home_Link_Prefix(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_MIP_Home_Agent_Address(AAA_AVP_LIST *list,ip_address data);
+int base.add_MIP_Home_Agent_Host(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_Multi_Round_Time_Out(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Origin_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Origin_Realm(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Origin_State_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Product_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Proxy_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Proxy_Info(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_Proxy_State(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Re_Auth_Request_Type(AAA_AVP_LIST *list,int32_t data);
+int base.add_Redirect_Host(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Redirect_Host_Usage(AAA_AVP_LIST *list,int32_t data);
+int base.add_Redirect_Max_Cache_Time(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Result_Code(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Route_Record(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Service_Selection(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Session_Binding(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Session_Id(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Session_Server_Failover(AAA_AVP_LIST *list,int32_t data);
+int base.add_Session_Timeout(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Supported_Vendor_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Termination_Cause(AAA_AVP_LIST *list,int32_t data);
+int base.add_User_Name(AAA_AVP_LIST *list,str data,AVPDataStatus data_do);
+int base.add_Vendor_Id(AAA_AVP_LIST *list,uint32_t data);
+int base.add_Vendor_Specific_Application_Id(AAA_AVP_LIST *list,AAA_AVP_LIST* data,AVPDataStatus data_do);
+int base.add_Vendor_Specific_Application_Id_Group(AAA_AVP_LIST *list,uint32_t vendor_id,uint32_t auth_app_id,uint32_t acct_app_id);
+int base.get_Accounting_Realtime_Required(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Accounting_Record_Number(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Accounting_Record_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Accounting_Sub_Session_Id(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int base.get_Acct_Application_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Acct_Interim_Interval(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Acct_Multi_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Acct_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Auth_Application_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Auth_Grace_Period(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Authorization_Lifetime(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Auth_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Auth_Session_State(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Class(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Destination_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Destination_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Disconnect_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_E2E_Sequence(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Error_Message(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Error_Reporting_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Event_Timestamp(AAA_AVP_LIST list,time_t *data,AAA_AVP **avp_ptr);
+int base.get_Experimental_Result(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Experimental_Result_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Experimental_Result_Group(AAA_AVP_LIST list,uint32_t *Vendor_Id,uint32_t *Experimental_Result_Code,AAA_AVP **avp_ptr);
+int base.get_Failed_AVP(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Firmware_Revision(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Host_IP_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int base.get_Inband_Security_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_MIP6_Agent_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_MIP6_Feature_Vector(AAA_AVP_LIST list,uint64_t *data,AAA_AVP **avp_ptr);
+int base.get_MIP6_Home_Link_Prefix(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_MIP_Home_Agent_Address(AAA_AVP_LIST list,ip_address *data,AAA_AVP **avp_ptr);
+int base.get_MIP_Home_Agent_Host(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Multi_Round_Time_Out(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Origin_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Origin_Realm(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Origin_State_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Product_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_Info(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Proxy_State(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Re_Auth_Request_Type(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Redirect_Host(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Redirect_Host_Usage(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Redirect_Max_Cache_Time(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Result_Code(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Route_Record(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Service_Selection(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Session_Binding(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Session_Id(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Session_Server_Failover(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_Session_Timeout(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Supported_Vendor_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Termination_Cause(AAA_AVP_LIST list,int32_t *data,AAA_AVP **avp_ptr);
+int base.get_User_Name(AAA_AVP_LIST list,str *data,AAA_AVP **avp_ptr);
+int base.get_Vendor_Id(AAA_AVP_LIST list,uint32_t *data,AAA_AVP **avp_ptr);
+int base.get_Vendor_Specific_Application_Id(AAA_AVP_LIST list,AAA_AVP_LIST *data,AAA_AVP **avp_ptr);
+int base.get_Vendor_Specific_Application_Id_example(AAA_AVP_LIST list,uint32_t *vendor_id,uint32_t *auth_app_id,uint32_t *acct_app_id);
+</programlisting></para>
+    </section>
+  </section>
+</chapter>

+ 68 - 0
modules/cdp_avp/doc/cdp_avp_faq.xml

@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding='ISO-8859-1'?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd" [
+
+<!-- Include general documentation entities -->
+<!ENTITY % docentities SYSTEM "../../../docbook/entities.xml">
+%docentities;
+
+]>
+
+<!-- Module FAQ -->
+
+<chapter>
+	
+	<title>&faqguide;</title>
+	<qandaset defaultlabel="number">
+	<qandaentry>
+		<question>
+		<para>Where can I find more about &kamailio;?</para>
+		</question>
+		<answer>
+		<para>
+			Take a look at &kamailiohomelink;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>Where can I post a question about this module?</para>
+		</question>
+		<answer>
+		<para>
+			First at all check if your question was already answered on one of
+			our mailing lists: 
+		</para>
+		<itemizedlist>
+			<listitem>
+			<para>User Mailing List - &kamailiouserslink;</para>
+			</listitem>
+			<listitem>
+			<para>Developer Mailing List - &kamailiodevlink;</para>
+			</listitem>
+		</itemizedlist>
+		<para>
+			E-mails regarding any stable &kamailio; release should be sent to 
+			&kamailiousersmail; and e-mails regarding development versions
+			should be sent to &kamailiodevmail;.
+		</para>
+		<para>
+			If you want to keep the mail private, send it to 
+			&kamailiohelpmail;.
+		</para>
+		</answer>
+	</qandaentry>
+	<qandaentry>
+		<question>
+		<para>How can I report a bug?</para>
+		</question>
+		<answer>
+		<para>
+			Please follow the guidelines provided at:
+			&kamailiobugslink;.
+		</para>
+		</answer>
+	</qandaentry>
+	</qandaset>
+</chapter>
+

+ 100 - 0
modules/cdp_avp/epcapp.c

@@ -0,0 +1,100 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new.h"
+#include "avp_new_base_data_format.h"
+#include "avp_add.h"
+#include "avp_get.h"
+#include "avp_get_base_data_format.h"
+
+extern struct cdp_binds *cdp;
+
+
+#include "../cdp/cdp_load.h"
+
+
+#include "epcapp.h"
+#include "ccapp.h"
+
+
+#define CDP_AVP_DEFINITION
+
+	#include "epcapp.h"
+	int cdp_avp_add_GG_Enforce_Group(AAA_AVP_LIST * avpList, 
+		int32_t type, str id, 
+		ip_address ue_ip, ip_address gg_ip, 
+		uint32_t interval,
+		AVPDataStatus status){
+
+		AAA_AVP_LIST        avp_list = {0,0}, avp_list2 = {0,0};
+
+		if(!cdp_avp_add_UE_Locator(&avp_list, ue_ip))
+			goto error;
+
+		if(id.len && id.s){
+			if(!cdp_avp_add_Subscription_Id_Group(&avp_list,
+					type,
+					id,
+					AVP_DUPLICATE_DATA))
+				goto error;
+		}
+
+		if(!cdp_avp_add_UE_Locator_Id_Group(&avp_list2, 
+				&avp_list, AVP_FREE_DATA))
+			goto error;
+
+		if(!cdp_avp_add_GG_IP(&avp_list2, gg_ip))
+			goto error;
+	
+		if(!cdp_avp_add_GG_Enforce(avpList, &avp_list2,AVP_FREE_DATA)){
+			LOG(L_ERR, "could not find the GG_Enforce AVP\n");
+			goto error;
+		}
+		return 1;
+	error:
+		LOG(L_ERR, "error while adding the GG change AVPs\n");
+		return 0;
+	}
+
+#undef CDP_AVP_DEFINITION
+
+
+
+

+ 931 - 0
modules/cdp_avp/epcapp.h

@@ -0,0 +1,931 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+/*
+ * TS 29.061  (partly)
+ * http://www.3gpp.org/ftp/Specs/html-info/29061.htm
+
+ * TS 29.212  Gx/Gxx
+ * http://www.3gpp.org/ftp/Specs/html-info/29212.htm
+ * 
+ * TS 29.214  Rx
+ * http://www.3gpp.org/ftp/Specs/html-info/29214.htm
+ * 
+ * TS 29.272  
+ * http://www.3gpp.org/ftp/Specs/html-info/29272.htm
+ *
+ * TS 29.299
+ * http://www.3gpp.org/ftp/Specs/html-info/29299.htm
+ *
+ */
+
+#include "macros.h"
+
+#undef CDP_AVP_MODULE
+#define CDP_AVP_MODULE epcapp
+
+#if !defined(CDP_AVP_DECLARATION) && !defined(CDP_AVP_EXPORT) && !defined(CDP_AVP_INIT) && !defined(CDP_AVP_REFERENCE)
+	#ifndef _CDP_AVP_EPCAPP_H_1
+	#define _CDP_AVP_EPCAPP_H_1
+
+		#include "../cdp/cdp_load.h"
+
+	#else
+
+		/* undo the macros definition if this was re_included */
+		#define CDP_AVP_EMPTY_MACROS
+			#include "macros.h"
+		#undef CDP_AVP_EMPTY_MACROS
+
+	#endif
+#endif //_CDP_AVP_NASAPP_H_1	
+
+/*
+ * The list of AVPs must be declared in the following format:
+ * 
+ * 		cdp_avp_add(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or
+ * 		cdp_avp_add_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * 		cdp_avp_get(<avp_name>.<vendor_id>,<avp_type>,<data_type>)
+ * 
+ * or, to add both add and get at once:
+ * 
+ * 		cdp_avp(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or 
+ * 		cdp_avp_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * The add macros ending in _ptr will generate function with the extra AVPDataStatus data_do parameter
+ * 
+ * Parameters:
+ *  - avp_name - a value of AVP_<avp_name> must resolve to the AVP code
+ *  - vendor_id - an int value
+ *  - flags	- AVP Flags to add to the AVP
+ *  - avp_type - an avp type for which a function was defined a
+ * 				int cdp_avp_get_<avp_type>(AAA_AVP *avp,<data_type> *data)
+ * 		Some valid suggestions (and the data_type):		
+ *  
+ *  			OctetString 	_ str
+ *  			Integer32		_ int32_t
+ *  			Integer64 		_ int64_t
+ *  			Unsigned32 		_ uint32_t
+ *  			Unsigned64 		_ uint64_t
+ *  			Float32 		_ float
+ *  			Float64 		_ double
+ *  			Grouped 		_ AAA_AVP_LIST
+ *  
+ *  			Address 		_ ip_address
+ *  			Time 			_ time_t
+ *  			UTF8String 		_ str
+ *  			DiameterIdentity_ str
+ *  			DiameterURI		_ str
+ *  			Enumerated		_ int32_t
+ *  			IPFilterRule	_ str
+ *  			QoSFilterRule	_ str
+ *  - data_type - the respective data type for the avp_type defined above
+ *  
+ *  The functions generated will return 1 on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>(AAA_AVP_LIST list,<data_type> *data,AAA_AVP **avp_ptr)
+ * 
+ * 
+ *  
+ *  For Grouped AVPs with 2 or 3 known inside AVPs, you can define a shortcut function which will find the group and
+ *  also extract the 2 or 3 AVPs. 
+ *  Do not define both 2 and 3 for the same type!
+ * 
+ * 
+ *		cdp_avp_add2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp_get2(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  	
+ *		cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ *  	cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ * 
+ * 	 or, to add both add and get at once:
+ * 
+ *		cdp_avp2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  
+ *  - avp_name_group - a value of AVP_<avp_name_group> must resolve to the AVP code of the group
+ *  
+ *  - vendor_id_group - an int value
+ *  
+ *  - avp_name_N	- the name of the Nth parameter. 
+ *  	Previously, a cdp_avp_get(<avp_name_N>,<vendor_id_N>,<avp_type_N>,<data_type_N>) must be defined!
+ *  
+ *  - data_type_N	- the respective data type for avp_type_N (same as <data_type_N) 
+ *  
+ *  The functions generated will return the number of found AVPs inside on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>_Group(AAA_AVP_LIST list,<data_type_1> *avp_name_1,<data_type_2> *avp_name_2[,<data_type_3> *avp_name_3],AAA_AVP **avp_ptr)
+ *  
+ *  Note - generally, all data of type str will need to be defined with ..._ptr
+ *  Note - Groups must be defined with:
+ *  	 cdp_avp_add_ptr(...) and data_type AAA_AVP_LIST*
+ *  	 cdp_avp_get(...) and data_type AAA_AVP_LIST 	
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_EPC_##avp_name
+
+/*
+ * TS 29.212
+ */
+
+cdp_avp_add_ptr	(Access_Network_Charging_Identifier_Gx,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Access_Network_Charging_Identifier_Gx,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Allocation_Retention_Priority,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Allocation_Retention_Priority,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(AN_GW_Address,							EPC_vendor_id_3GPP,	0,							Address,		ip_address)	
+
+cdp_avp			(APN_Aggregate_Max_Bitrate_DL,			EPC_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp			(APN_Aggregate_Max_Bitrate_UL,			EPC_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp			(Bearer_Control_Mode,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Bearer_Identifier,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Bearer_Operation,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Bearer_Usage,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(Charging_Rule_Install,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Charging_Rule_Install,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Charging_Rule_Remove,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Charging_Rule_Remove,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Charging_Rule_Definition,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Charging_Rule_Definition,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Charging_Rule_Base_Name,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Charging_Rule_Name,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(Charging_Rule_Report,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Charging_Rule_Report,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(CoA_IP_Address,						EPC_vendor_id_3GPP,	0,							Address,		ip_address)	
+
+cdp_avp_add_ptr	(CoA_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(CoA_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Default_EPS_Bearer_QoS,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Default_EPS_Bearer_QoS,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Event_Report_Indication,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Event_Report_Indication,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Event_Trigger,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(Flow_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Flow_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Flow_Label,							EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp			(IP_CAN_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Guaranteed_Bitrate_DL,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Guaranteed_Bitrate_UL,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Metering_Method,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Network_Request_Support,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Offline,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Online,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Packet_Filter_Content,					EPC_vendor_id_3GPP,	0,							IPFilterRule,	str)	
+
+cdp_avp_ptr		(Packet_Filter_Identifier,				EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_add_ptr	(Packet_Filter_Information,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Packet_Filter_Information,				EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Packet_Filter_Operation,				EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp_ptr		(PDN_Connection_ID,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Precedence,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Pre_emption_Capability,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Pre_emption_Vulnerability,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Priority_Level,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Reporting_Level,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(PCC_Rule_Status,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Session_Release_Cause,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(QoS_Class_Identifier,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(QoS_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(QoS_Information,						EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(QoS_Negotiation,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(QoS_Rule_Install,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(QoS_Rule_Install,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(QoS_Rule_Remove,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(QoS_Rule_Remove,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(QoS_Rule_Definition,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(QoS_Rule_Definition,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(QoS_Rule_Name,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(QoS_Rule_Report,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(QoS_Rule_Report,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+
+cdp_avp			(QoS_Upgrade,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Resource_Allocation_Notification,		EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp			(Rule_Failure_Code,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Security_Parameter_Index,				EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(TFT_Filter,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		IPFilterRule,	str)	
+
+cdp_avp_add_ptr	(TFT_Packet_Filter_Information,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(TFT_Packet_Filter_Information,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(ToS_Traffic_Class,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Tunnel_Header_Filter,					EPC_vendor_id_3GPP,	0,							IPFilterRule,	str)	
+
+cdp_avp			(Tunnel_Header_Length,					EPC_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Tunnel_Information,					EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Tunnel_Information,					EPC_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(RAT_Type,								EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)
+
+cdp_avp_ptr		(TGPP_RAT_Type,								EPC_vendor_id_3GPP,	0,							OctetString,		str)	
+
+cdp_avp			(Revalidation_Time,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)	
+
+cdp_avp			(Rule_Activation_Time,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)	
+
+cdp_avp			(Rule_DeActivation_Time,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)	
+
+cdp_avp			(Session_Linking_Indicator,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+/*
+ * TS 29.061 Gi/SGi
+ */
+
+cdp_avp_ptr		(3GPP_Charging_Id,						EPC_vendor_id_3GPP,	0,							OctetString,	str)
+
+cdp_avp_ptr		(3GPP_SGSN_Address,						EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(3GPP_SGSN_IPv6_Address,				EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(3GPP_SGSN_MCC_MNC,						EPC_vendor_id_3GPP,	0,							UTF8String,		str)	
+
+cdp_avp_ptr		(3GPP_User_Location_Info,				EPC_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(RAI,									EPC_vendor_id_3GPP,	0,							UTF8String,		str)	
+
+cdp_avp_ptr		(3GPP_MS_TimeZone,						EPC_vendor_id_3GPP,	0,							OctetString,	str)
+
+cdp_avp			(3GPP_PDP_Type,							EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)
+
+/*
+ * TS 29.214 Rx
+ */
+
+cdp_avp			(Abort_Cause,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Access_Network_Charging_Address,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+cdp_avp_add_ptr	(Access_Network_Charging_Identifier,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Access_Network_Charging_Identifier,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(Access_Network_Charging_Identifier_Value,EPC_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,	OctetString,	str)	
+
+cdp_avp_add_ptr	(Acceptable_Service_Info,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Acceptable_Service_Info,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(AF_Application_Identifier,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(AF_Charging_Identifier,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Codec_Data,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Flow_Description,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		IPFilterRule,	str)	
+
+cdp_avp			(Flow_Number,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Flows,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Flows,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Flow_Status,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Flow_Usage,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Service_URN,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Specific_Action,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Max_Requested_Bandwidth_DL,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Max_Requested_Bandwidth_UL,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Media_Component_Description,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Media_Component_Description,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Media_Component_Number,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Media_Sub_Component,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Media_Sub_Component,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Media_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(RR_Bandwidth,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(RS_Bandwidth,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Service_Info_Status,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(SIP_Forking_Indication,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+
+/*
+ * TS 29.272  
+ * http://www.3gpp.org/ftp/Specs/html-info/29272.htm
+ */
+
+cdp_avp_add_ptr	(Subscription_Data,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Subscription_Data,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Terminal_Information,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Terminal_Information,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(IMEI,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Software_Version,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(QoS_Subscribed,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(ULR_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(ULA_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_ptr		(Visited_PLMN_Id,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(Requested_EUTRAN_Authentication_Info,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Requested_EUTRAN_Authentication_Info,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Requested_UTRAN_GERAN_Authentication_Info,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,	Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Requested_UTRAN_GERAN_Authentication_Info,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,	Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Number_Of_Requested_Vectors,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_ptr		(Re_Synchronization_Info,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Immediate_Response_Preferred,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Authentication_Info,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Authentication_Info,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(E_UTRAN_Vector,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(E_UTRAN_Vector,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(UTRAN_Vector,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(UTRAN_Vector,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(GERAN_Vector,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(GERAN_Vector,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Network_Access_Mode,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(HPLMN_ODB,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Item_Number,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Cancellation_Type,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(DSR_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(DSA_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Context_Identifier,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Subscriber_Status,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Operator_Determined_Barring,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Access_Restriction_Data,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_ptr		(APN_OI_Replacement,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(All_APN_Configurations_Included_Indicator,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,	Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(APN_Configuration_Profile,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(APN_Configuration_Profile,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(APN_Configuration,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(APN_Configuration,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(EPS_Subscribed_QoS_Profile,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(EPS_Subscribed_QoS_Profile,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(VPLMN_Dynamic_Address_Allowed,			EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(STN_SR,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Alert_Reason,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(AMBR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_add2	(AMBR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Max_Requested_Bandwidth_UL,	uint32_t,	Max_Requested_Bandwidth_DL,	uint32_t)	
+cdp_avp_get		(AMBR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+cdp_avp_get2	(AMBR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Max_Requested_Bandwidth_UL,	uint32_t,	Max_Requested_Bandwidth_DL,	uint32_t)	
+
+cdp_avp_add_ptr	(CSG_Subscription_Data,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(CSG_Subscription_Data,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(CSG_Id,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(PDN_Gw_Allocation_Type,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Expiration_Date,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)
+
+cdp_avp			(RAT_Frequency_Selection_Priority_ID,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(IDA_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(PUA_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(NOR_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_ptr		(User_Id,								EPC_vendor_id_3GPP,	0,							UTF8String,		str)	
+
+cdp_avp			(Equipment_Status,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Regional_Subscription_Zone_Code,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(RAND,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(XRES,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(AUTN,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(KASME,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Trace_Collection_Entity,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)
+
+cdp_avp_ptr		(Kc,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(SRES,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(PDN_Type,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Roaming_Restricted_Due_To_Unsupported_Feature,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,	Enumerated,	int32_t)	
+
+cdp_avp_add_ptr	(Trace_Data,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Trace_Data,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(Trace_Reference,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Trace_Depth,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Trace_NE_Type_List,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Trace_Interface_List,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Trace_Event_List,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(OMC_Id,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(GPRS_Subscription_Data,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(GPRS_Subscription_Data,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Complete_Data_List_Included_Indicator,	EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(PDP_Context,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(PDP_Context,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(PDP_Type,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(3GPP2_MEID,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(Specific_APN_Info,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Specific_APN_Info,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(LCS_Info,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(LCS_Info,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(GMLC_Number,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(LCS_Privacy_Exception,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(LCS_Privacy_Exception,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(SS_Code,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(SS_Status,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SS_Status,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Notification_To_UE_User,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(External_Client,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(External_Client,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(Client_Identity,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(GMLC_Restriction,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(PLMN_Client,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(Service_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Service_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Sevice_Type_Identity,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(MO_LR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(MO_LR,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Teleservice_List,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Teleservice_List,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(TS_Code,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(Call_Barring_Infor_List,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Call_Barring_Infor_List,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(SGSN_Number,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(IDR_Flags,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(ICS_Indicator,							EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp			(IMS_Voice_Over_PS_Sessions_Supported,	EPC_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp			(Homogenous_Support_of_IMS_Over_PS_Sessions, EPC_vendor_id_3GPP, 0, 					Enumerated,		int32_t)	
+
+cdp_avp			(Last_UE_Activity_Time,					EPC_vendor_id_3GPP,	0,							Time,			time_t)
+
+
+
+cdp_avp			(PDN_Gw_Address,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+
+cdp_avp_ptr		(PDN_Gw_Name,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(PDN_Gw_Identity,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(PDN_Gw_Identity,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+
+/*
+ * TS 29.173  
+ * http://www.3gpp.org/ftp/Specs/html-info/29173.htm
+ */
+cdp_avp			(GMLC_Address,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+
+
+/*
+ * TS 32.299  
+ * http://www.3gpp.org/ftp/Specs/html-info/32299.htm
+ */
+
+cdp_avp_add_ptr	(AF_Correlation_Information,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)
+cdp_avp_get		(AF_Correlation_Information,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_ptr		(Application_Provided_Called_Party_Address,EPC_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,	UTF8String,		str)	
+
+cdp_avp_ptr		(Application_Server,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Application_Server_Information,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Application_Server_Information,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Authorized_QoS,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Called_Asserted_Identity,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Called_Party_Address,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Calling_Party_Address,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(Cause_Code,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Integer32,		int32_t)	
+
+cdp_avp_ptr		(Content_Disposition,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(Content_Length,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Content_Size,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_ptr		(Content_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Early_Media_Description,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Early_Media_Description,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Event,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Event_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Event_Type,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Expires,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(GGSN_Address,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)
+
+cdp_avp_ptr		(IMS_Charging_Identifier,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(IMS_Information,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(IMS_Information,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(Local_Sequence_Number,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(PS_Information,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(PS_Information,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp_add_ptr (Service_Data_Container,                                                EPC_vendor_id_3GPP,     AAA_AVP_FLAG_MANDATORY,         Grouped,                AAA_AVP_LIST*)
+cdp_avp_get             (Service_Data_Container,                                                EPC_vendor_id_3GPP,     AAA_AVP_FLAG_MANDATORY,         Grouped,                AAA_AVP_LIST)
+
+cdp_avp_add_ptr	(Inter_Operator_Identifier,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Inter_Operator_Identifier,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Media_Initiator_Flag,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Media_Initiator_Party,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Message_Body,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Message_Body,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Node_Functionality,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Originating_IOI,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(Originator,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Outgoing_Session_Id,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(Role_Of_Node,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Requested_Party_Address,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(SDP_Answer_TimeStamp,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)
+
+cdp_avp_add_ptr	(SDP_Media_Component,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SDP_Media_Component,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(SDP_Media_Description,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(SDP_Media_Name,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(SDP_Offer_TimeStamp,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)
+
+cdp_avp_ptr		(SDP_Session_Description,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(SDP_TimeStamps,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SDP_TimeStamps,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(SDP_Type,								EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Served_Party_IP_Address,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+cdp_avp_ptr		(Service_ID,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Service_Information,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Service_Information,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Service_Specific_Data,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Service_Specific_Info,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Service_Specific_Info,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Service_Specific_Type,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(SGSN_Address,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)
+
+cdp_avp_ptr		(SIP_Method,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(SIP_Request_Timestamp_Fraction,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(SIP_Request_Timestamp,					EPC_vendor_id_3GPP,	0,							Time,			time_t)
+
+cdp_avp			(SIP_Response_Timestamp_Fraction,		EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(SIP_Response_Timestamp,				EPC_vendor_id_3GPP,	0,							Time,			time_t)
+
+cdp_avp_ptr		(Terminating_IOI,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp			(Time_First_Usage,						EPC_vendor_id_3GPP,	0,							Time,			time_t)
+cdp_avp			(Time_Last_Usage,						EPC_vendor_id_3GPP,	0,							Time,			time_t)
+cdp_avp			(Time_Usage,						EPC_vendor_id_3GPP,	0,							Time,			time_t)
+
+cdp_avp_add_ptr	(Time_Stamps,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Time_Stamps,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(User_Session_Id,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+
+
+/*
+ *	http://tools.ietf.org/html/rfc5778#section-6.2
+ */
+
+cdp_avp_ptr		(QoS_Profile_Name,						EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+/*
+ * Generic Gateway related AVPs
+ */
+
+cdp_avp_add_ptr	(GG_Enforce,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+
+cdp_avp_get		(GG_Enforce,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+cdp_avp			(GG_IP,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+cdp_avp 		(UE_Locator,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Address,		ip_address)	
+
+cdp_avp_add_ptr	(UE_Locator_Id_Group,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+
+cdp_avp_get 	(UE_Locator_Id_Group,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)
+
+/*
+ * 3GPP TS 29.273 EPS AAA
+ *  http://www.3gpp.org/ftp/Specs/html-info/29273.htm
+ */
+
+cdp_avp_add_ptr	(Non_3GPP_User_Data,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Non_3GPP_User_Data,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Non_3GPP_IP_Access,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Non_3GPP_IP_Access_APN,				EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)
+
+cdp_avp_ptr		(ANID,									EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Trace_Info,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Trace_Info,							EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+/*
+ * 3GPP TS 29.234 
+ *  http://www.3gpp.org/ftp/Specs/html-info/29234.htm
+ */
+
+cdp_avp_ptr		(3GPP_AAA_Server_Name,					EPC_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		DiameterIdentity,		str)	
+
+
+/*
+ * ETSI TS 183 017?
+ * 
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_ETSI_##avp_name
+
+
+cdp_avp			(Reservation_Priority,					IMS_vendor_id_ETSI,	0,							Unsigned32,		uint32_t)
+
+
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_##avp_name
+
+
+/*
+ * From here-on you can define/export/init/declare functions which can not be generate with the macros
+ */
+
+#if defined(CDP_AVP_DEFINITION)
+
+	/*
+	 * Put here your supplimentary definitions. Typically:
+	 * 
+	 * int <function1>(param1)
+	 * {
+	 *   code1
+	 * }
+	 * 
+	 * 
+	 */
+
+
+
+#elif defined(CDP_AVP_EXPORT)
+
+	/*
+	 * Put here your supplementary exports in the format: 
+	 * 	<function_type1> <nice_function_name1>; 
+	 *  <function_type2> <nice_function_name1>;
+	 *  ...
+	 *  
+	 */
+
+	cdp_avp_add_GG_Enforce_Group_f		add_GG_Enforce_Group;	
+#elif defined(CDP_AVP_INIT)
+
+	/*
+	 * Put here your supplementary inits in the format: 
+	 * 	<function1>,
+	 *  <function2>,
+	 *  ...
+	 * 
+	 * Make sure you keep the same order as in export!
+	 * 
+	 */
+
+	cdp_avp_add_GG_Enforce_Group,
+#elif defined(CDP_AVP_REFERENCE)
+	/*
+	 * Put here what you want to get in the reference. Typically:
+	 * <function1>
+	 * <function2>
+	 * ... 
+	 * 
+	 */
+
+	int CDP_AVP_MODULE.add_GG_Enforce_Group(AAA_AVP_LIST * avpList, str imsi, ip_address ue_ip, ip_address gg_ip, AVPDataStatus status);
+	
+#elif defined(CDP_AVP_EMPTY_MACROS)
+	
+	/* this should be left blank */
+	
+#else
+
+	/*
+	 * Put here your definitions according to the declarations, exports, init, etc above. Typically:
+	 * 
+	 * int <function1(params1);>
+	 * typedef int <*function_type1>(params1);
+	 * 
+	 * int <function2(param2);>
+	 * typedef int <*function_type2>(params2);
+	 * 
+	 * ...
+	 *  
+	 */
+
+	
+	#ifndef _CDP_AVP_EPCAPP_H_2
+	#define _CDP_AVP_EPCAPP_H_2
+
+		int cdp_avp_add_GG_Enforce_Group(AAA_AVP_LIST * avpList, int32_t type, str id, 
+				ip_address ue_ip, ip_address gg_ip, uint32_t interval,
+				AVPDataStatus status);
+		typedef int (*cdp_avp_add_GG_Enforce_Group_f) (AAA_AVP_LIST * avpList, int32_t type, str id, 
+				ip_address ue_ip, ip_address gg_ip, uint32_t interval,
+				AVPDataStatus status);
+
+
+	#endif //_CDP_AVP_EPCAPP_H_2
+	
+#endif
+
+
+
+#define CDP_AVP_UNDEF_MACROS
+	#include "macros.h"
+#undef CDP_AVP_UNDEF_MACROS
+	
+
+
+

+ 69 - 0
modules/cdp_avp/get_reference.h

@@ -0,0 +1,69 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+/**
+ * \file
+ * 
+ * The purpose of this file is solely to make the get_reference.sh script work easily
+ * 
+ * All headers that are reference important should be included here
+ * 
+ * 
+ *  \author Dragos Vingarzan dragos dot vingarzan -at- fokus dot fraunhofer dot de
+ * 
+ */ 
+
+#undef CDP_AVP_REFERENCE
+#define CDP_AVP_REFERENCE
+
+
+#include "avp_new.h"
+#include "avp_add.h"
+#include "avp_get.h"
+
+#include "avp_new_base_data_format.h"
+#include "avp_get_base_data_format.h"
+
+#include "base.h"
+#include "nasapp.h"
+#include "ccapp.h"
+#include "imsapp.h"
+#include "epcapp.h"
+

+ 7 - 0
modules/cdp_avp/get_reference.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+#
+# CDiameter AVP Help reference generator
+#
+
+gcc -E -DCDP_AVP_REFERENCE get_reference.h | tr '|' '\n' |  egrep "$1" |grep -v -e "^$" -e "#" -e "typedef" | awk '{gsub(/^[ \t]+|[ \t]+$/,"")};1' | sort
+

+ 64 - 0
modules/cdp_avp/imsapp.c

@@ -0,0 +1,64 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#include "avp_new.h"
+#include "avp_new_base_data_format.h"
+#include "avp_add.h"
+#include "avp_get.h"
+#include "avp_get_base_data_format.h"
+
+extern struct cdp_binds *cdp;
+
+
+#include "../cdp/cdp_load.h"
+
+
+#include "imsapp.h"
+
+#include "base.h"
+
+#define CDP_AVP_DEFINITION
+
+	#include "imsapp.h"
+
+#undef CDP_AVP_DEFINITION
+
+
+

+ 486 - 0
modules/cdp_avp/imsapp.h

@@ -0,0 +1,486 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+/*
+ * TS 29.229 - Cx
+ *
+ * http://www.3gpp.org/ftp/Specs/html-info/29229.htm
+ * 
+ * + ETSI, CableLabs Cx additions
+ *
+ *
+ * TS 29.329 - Sh
+ *
+ * http://www.3gpp.org/ftp/Specs/html-info/29329.htm
+ *
+ */
+
+#include "macros.h"
+
+
+#undef CDP_AVP_MODULE
+#define CDP_AVP_MODULE imsapp
+
+#if !defined(CDP_AVP_DECLARATION) && !defined(CDP_AVP_EXPORT) && !defined(CDP_AVP_INIT) && !defined(CDP_AVP_REFERENCE)
+	#ifndef _CDP_AVP_IMSAPP_H_1
+	#define _CDP_AVP_IMSAPP_H_1
+
+		#include "../cdp/cdp_load.h"
+
+	#else
+
+		/* undo the macros definition if this was re-included */
+		#define CDP_AVP_EMPTY_MACROS
+			#include "macros.h"
+		#undef CDP_AVP_EMPTY_MACROS
+
+	#endif
+#endif //_CDP_AVP_NASAPP_H_1	
+
+/*
+ * The list of AVPs must be declared in the following format:
+ * 
+ * 		cdp_avp_add(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or
+ * 		cdp_avp_add_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * 		cdp_avp_get(<avp_name>.<vendor_id>,<avp_type>,<data_type>)
+ * 
+ * or, to add both add and get at once:
+ * 
+ * 		cdp_avp(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 		or 
+ * 		cdp_avp_ptr(<avp_name>.<vendor_id>,<flags>,<avp_type>,<data_type>)
+ * 
+ * The add macros ending in _ptr will generate function with the extra AVPDataStatus data_do parameter
+ * 
+ * Parameters:
+ *  - avp_name - a value of AVP_<avp_name> must resolve to the AVP code
+ *  - vendor_id - an int value
+ *  - flags	- AVP Flags to add to the AVP
+ *  - avp_type - an avp type for which a function was defined a
+ * 				int cdp_avp_get_<avp_type>(AAA_AVP *avp,<data_type> *data)
+ * 		Some valid suggestions (and the data_type):		
+ *  
+ *  			OctetString 	- str
+ *  			Integer32		- int32_t
+ *  			Integer64 		- int64_t
+ *  			Unsigned32 		- uint32_t
+ *  			Unsigned64 		- uint64_t
+ *  			Float32 		- float
+ *  			Float64 		- double
+ *  			Grouped 		- AAA_AVP_LIST
+ *  
+ *  			Address 		- ip_address
+ *  			Time 			- time_t
+ *  			UTF8String 		- str
+ *  			DiameterIdentity- str
+ *  			DiameterURI		- str
+ *  			Enumerated		- int32_t
+ *  			IPFilterRule	- str
+ *  			QoSFilterRule	- str
+ *  - data_type - the respective data type for the avp_type defined above
+ *  
+ *  The functions generated will return 1 on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>(AAA_AVP_LIST list,<data_type> *data,AAA_AVP **avp_ptr)
+ * 
+ * 
+ *  
+ *  For Grouped AVPs with 2 or 3 known inside AVPs, you can define a shortcut function which will find the group and
+ *  also extract the 2 or 3 AVPs. 
+ *  Do not define both 2 and 3 for the same type!
+ * 
+ * 
+ *		cdp_avp_add2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp_get2(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  	
+ *		cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ *  	cdp_avp_get3(<avp_name_group>.<vendor_id_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>,<avp_name_3>,<data_type_3>)
+ * 
+ * 	 or, to add both add and get at once:
+ * 
+ *		cdp_avp2(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ * 		cdp_avp3(<avp_name_group>.<vendor_id_group>,<flags_group>,<avp_name_1>,<data_type_1>,<avp_name_2>,<data_type_2>)
+ *  
+ *  avp_name_group - a value of AVP_<avp_name_group> must resolve to the AVP code of the group
+ *  
+ *  vendor_id_group - an int value
+ *  
+ *  avp_name_N	- the name of the Nth parameter. 
+ *  	Previously, a cdp_avp_get(<avp_name_N>,<vendor_id_N>,<avp_type_N>,<data_type_N>) must be defined!
+ *  
+ *  data_type_N	- the respective data type for avp_type_N (same as <data_type_N) 
+ *  
+ *  The functions generated will return the number of found AVPs inside on success or 0 on error or not found
+ *  The prototype of the function will be:
+ *  
+ *  	int cdp_avp_get_<avp_name_group>_Group(AAA_AVP_LIST list,<data_type_1> *avp_name_1,<data_type_2> *avp_name_2[,<data_type_3> *avp_name_3],AAA_AVP **avp_ptr)
+ *  
+ *  Note - generally, all data of type str will need to be defined with ..._ptr
+ *  Note - Groups must be defined with:
+ *  	 cdp_avp_add_ptr(...) and data_type AAA_AVP_LIST*
+ *  	 cdp_avp_get(...) and data_type AAA_AVP_LIST 	
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_IMS_##avp_name
+
+cdp_avp_ptr		(Visited_Network_Identifier,	IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Public_Identity,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(Server_Name,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Server_Capabilities,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Server_Capabilities,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Mandatory_Capability,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)	
+
+cdp_avp			(Optional_Capability,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)	
+
+cdp_avp_ptr		(User_Data_Cx,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(SIP_Number_Auth_Items,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)	
+
+cdp_avp_ptr		(SIP_Authentication_Scheme,		IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_ptr		(SIP_Authenticate,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(SIP_Authorization,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(SIP_Authentication_Context,	IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(SIP_Auth_Data_Item,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SIP_Auth_Data_Item,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(SIP_Item_Number,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Unsigned32,		uint32_t)
+
+cdp_avp			(Server_Assignment_Type,		IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(Deregistration_Reason,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get 	(Deregistration_Reason,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Reason_Code,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Reason_Info,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		UTF8String,		str)	
+
+cdp_avp_add_ptr	(Charging_Information,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Charging_Information,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Primary_Event_Charging_Function_Name,IMS_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,DiameterURI,	str)	
+
+cdp_avp_ptr		(Secondary_Event_Charging_Function_Name,IMS_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,DiameterURI,	str)	
+
+cdp_avp_ptr		(Primary_Charging_Collection_Function_Name,IMS_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,DiameterURI,str)	
+
+cdp_avp_ptr		(Secondary_Charging_Collection_Function_Name,IMS_vendor_id_3GPP,AAA_AVP_FLAG_MANDATORY,DiameterURI,	str)	
+
+cdp_avp			(User_Authorization_Type,		IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(User_Data_Already_Available,	IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Confidentiality_Key,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(Integrity_Key,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_add_ptr	(Supported_Features,			IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_add3	(Supported_Features,			IMS_vendor_id_3GPP,	0,	Vendor_Id,	uint32_t,	Feature_List_ID,	uint32_t, Feature_List, uint32_t)	
+cdp_avp_get		(Supported_Features,			IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+cdp_avp_get3	(Supported_Features,			IMS_vendor_id_3GPP,	0,	Vendor_Id,	uint32_t,	Feature_List_ID,	uint32_t, Feature_List, uint32_t)	
+
+cdp_avp			(Feature_List_ID,				IMS_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp			(Feature_List,					IMS_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp_add_ptr	(Supported_Applications,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Supported_Applications,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(Associated_Identities,			IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Associated_Identities,			IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Originating_Request,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Wildcarded_PSI,				IMS_vendor_id_3GPP,	0,							UTF8String,		str)	
+
+cdp_avp_add_ptr	(SIP_Digest_Authenticate,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SIP_Digest_Authenticate,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Wildcarded_IMPU,				IMS_vendor_id_3GPP,	0,							UTF8String,		str)	
+
+cdp_avp			(UAR_Flags,						IMS_vendor_id_3GPP,	0,							Unsigned32,		uint32_t)
+
+cdp_avp			(Loose_Route_Indication,		IMS_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(SCSCF_Restoration_Info,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(SCSCF_Restoration_Info,		IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(Path,							IMS_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(Contact,						IMS_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_add_ptr	(Subscription_Info,				IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Subscription_Info,				IMS_vendor_id_3GPP,	0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(From_SIP_Header,				IMS_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(To_SIP_Header,					IMS_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_ptr		(Record_Route,					IMS_vendor_id_3GPP,	0,							OctetString,	str)	
+
+cdp_avp_add_ptr	(Associated_Registered_Identities,IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Associated_Registered_Identities,IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST)	
+
+cdp_avp			(Multiple_Registration_Indication,IMS_vendor_id_3GPP,0,							Enumerated,		int32_t)	
+
+cdp_avp_add_ptr	(Restoration_Info,				IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(Restoration_Info,				IMS_vendor_id_3GPP,0,							Grouped,		AAA_AVP_LIST)	
+
+
+/*
+ * ETSI something, that probably does not exist anymore
+ * 
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_##avp_name
+
+cdp_avp_ptr		(ETSI_Line_Identifier,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_add_ptr	(ETSI_SIP_Authenticate,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(ETSI_SIP_Authenticate,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(ETSI_SIP_Authorization,		IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(ETSI_SIP_Authorization,		IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_add_ptr	(ETSI_SIP_Authentication_Info,	IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(ETSI_SIP_Authentication_Info,	IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(ETSI_Digest_Realm,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Nonce,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Domain,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Opaque,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Stale,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Algorithm,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_QoP,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_HA1,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Auth_Param,		IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Username,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_URI,				IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Response,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_CNonce,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Nonce_Count,		IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Method,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Entity_Body_Hash,	IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Nextnonce,			IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+cdp_avp_ptr		(ETSI_Digest_Response_Auth,		IMS_vendor_id_ETSI,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)
+
+
+/*
+ * CableLabs 29.229
+ * 
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_##avp_name
+
+cdp_avp_add_ptr	(CableLabs_SIP_Digest_Authenticate,IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	Grouped,	AAA_AVP_LIST*)	
+cdp_avp_get		(CableLabs_SIP_Digest_Authenticate,IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	Grouped,	AAA_AVP_LIST)	
+
+cdp_avp_ptr		(CableLabs_Digest_Realm,		IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+cdp_avp_ptr		(CableLabs_Digest_Domain,		IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+cdp_avp_ptr		(CableLabs_Digest_Algorithm,	IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+cdp_avp_ptr		(CableLabs_Digest_QoP,			IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+cdp_avp_ptr		(CableLabs_Digest_HA1,			IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+cdp_avp_ptr		(CableLabs_Digest_Auth_Param,	IMS_vendor_id_CableLabs,	AAA_AVP_FLAG_MANDATORY,	OctetString,str)
+
+/*
+ * TS 29.329
+ *
+ */
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_IMS_##avp_name
+
+cdp_avp_add_ptr	(User_Identity,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST*)	
+cdp_avp_get		(User_Identity,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Grouped,		AAA_AVP_LIST)	
+
+cdp_avp_ptr		(MSISDN,						IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp_ptr		(User_Data_Sh,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Data_Reference,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp_ptr		(Service_Indication,			IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+cdp_avp			(Subs_Req_Type,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Requested_Domain,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Current_Location,				IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Identity_Set,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Enumerated,		int32_t)	
+
+cdp_avp			(Expiry_Time,					IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		Time,			time_t)	
+
+cdp_avp			(Send_Data_Indication,			IMS_vendor_id_3GPP,	0,							Enumerated,		int32_t)	
+
+cdp_avp_ptr		(DSAI_Tag,						IMS_vendor_id_3GPP,	AAA_AVP_FLAG_MANDATORY,		OctetString,	str)	
+
+
+
+
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_##avp_name
+
+
+
+
+
+/*
+ * From here-on you can define/export/init/declare functions which can not be generate with the macros
+ */
+
+#if defined(CDP_AVP_DEFINITION)
+
+	/*
+	 * Put here your supplementary definitions. Typically:
+	 * 
+	 * int <function1>(param1)
+	 * {
+	 *   code1
+	 * }
+	 * 
+	 * 
+	 */
+
+
+#elif defined(CDP_AVP_EXPORT)
+
+	/*
+	 * Put here your supplimentary exports in the format: 
+	 * 	<function_type1> <nice_function_name1>; 
+	 *  <function_type2> <nice_function_name1>;
+	 *  ...
+	 *  
+	 */
+
+
+#elif defined(CDP_AVP_INIT)
+
+	/*
+	 * Put here your supplementary inits in the format: 
+	 * 	<function1>,
+	 *  <function2>,
+	 *  ...
+	 * 
+	 * Make sure you keep the same order as in export!
+	 * 
+	 */
+
+
+#elif defined(CDP_AVP_REFERENCE)
+	/*
+	 * Put here what you want to get in the reference. Typically:
+	 * <function1>
+	 * <function2>
+	 * ... 
+	 * 
+	 */
+
+	
+#elif defined(CDP_AVP_EMPTY_MACROS)
+	
+	/* this should be left blank */
+	
+#else
+
+	/*
+	 * Put here your definitions according to the declarations, exports, init, etc above. Typically:
+	 * 
+	 * int <function1(params1);>
+	 * typedef int <*function_type1>(params1);
+	 * 
+	 * int <function2(param2);>
+	 * typedef int <*function_type2>(params2);
+	 * 
+	 * ...
+	 *  
+	 */
+
+	
+	#ifndef _CDP_AVP_IMSAPP_H_2
+	#define _CDP_AVP_IMSAPP_H_2
+
+
+
+
+	#endif //_CDP_AVP_IMSAPP_H_2
+	
+#endif
+
+
+
+#define CDP_AVP_UNDEF_MACROS
+	#include "macros.h"
+#undef CDP_AVP_UNDEF_MACROS
+	
+
+
+

+ 440 - 0
modules/cdp_avp/macros.h

@@ -0,0 +1,440 @@
+/*
+ * $Id$
+ *
+ * The initial version of this code was written by Dragos Vingarzan
+ * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
+ * Fruanhofer Institute. It was and still is maintained in a separate
+ * branch of the original SER. We are therefore migrating it to
+ * Kamailio/SR and look forward to maintaining it from here on out.
+ * 2011/2012 Smile Communications, Pty. Ltd.
+ * ported/maintained/improved by 
+ * Jason Penton (jason(dot)penton(at)smilecoms.com and
+ * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
+ * effort to add full IMS support to Kamailio/SR using a new and
+ * improved architecture
+ * 
+ * NB: Alot of this code was originally part of OpenIMSCore,
+ * FhG Focus. Thanks for great work! This is an effort to 
+ * break apart the various CSCF functions into logically separate
+ * components. We hope this will drive wider use. We also feel
+ * that in this way the architecture is more complete and thereby easier
+ * to manage in the Kamailio/SR environment
+ *
+ * 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 
+ * along with this program; if not, write to the Free Software 
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * 
+ */
+
+#ifndef CDP_AVP_MODULE
+	#define CDP_AVP_MODULE cdp_avp
+#endif
+
+#undef CDP_AVP_NAME
+#define CDP_AVP_NAME(avp_name) AVP_##avp_name
+
+
+#if defined(CDP_AVP_UNDEF_MACROS)
+
+	#undef cdp_avp_add
+	#undef cdp_avp_add_ptr
+	#undef cdp_avp_add2
+	#undef cdp_avp_add3
+
+	#undef cdp_avp_get
+	#undef cdp_avp_get2
+	#undef cdp_avp_get3
+
+	#undef cdp_avp
+	#undef cdp_avp_ptr
+	#undef cdp_avp2
+	#undef cdp_avp3
+
+#elif defined(CDP_AVP_DEFINITION)
+
+	/*
+	 * This is the definition of the function, so this needs to generate the .c file
+	 */
+	
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)\
+	int cdp_avp_add_##avp_name(AAA_AVP_LIST *list,data_type data) \
+	{															\
+		return cdp_avp_add_to_list(list,						\
+					cdp_avp_new_##avp_type(						\
+							CDP_AVP_NAME(avp_name),				\
+							flags,								\
+							vendor_id,							\
+							data));								\
+	}
+
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)				\
+	int cdp_avp_add_##avp_name(AAA_AVP_LIST *list,data_type data,AVPDataStatus data_do) \
+	{															\
+		return cdp_avp_add_to_list(list,						\
+					cdp_avp_new_##avp_type(						\
+							CDP_AVP_NAME(avp_name),				\
+							flags,								\
+							vendor_id,							\
+							data,								\
+							data_do));							\
+	}
+
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+	int cdp_avp_add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2) \
+	{																					\
+		AAA_AVP_LIST list_grp={0,0};													\
+		if (!cdp_avp_add_##avp_name_1(&list_grp,avp_name_1)||							\
+			!cdp_avp_add_##avp_name_2(&list_grp,avp_name_2)) {							\
+				cdp->AAAFreeAVPList(&list_grp);											\
+				return 0;																\
+		}																				\
+		return cdp_avp_add_to_list(list,												\
+				cdp_avp_new_Grouped(													\
+						CDP_AVP_NAME(avp_name),											\
+						flags,															\
+						vendor_id,														\
+						&list_grp,														\
+						AVP_FREE_DATA));												\
+	}
+
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+	int cdp_avp_add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2,data_type_3 avp_name_3) \
+	{																					\
+		AAA_AVP_LIST list_grp={0,0};													\
+		if (!cdp_avp_add_##avp_name_1(&list_grp,avp_name_1)||							\
+			!cdp_avp_add_##avp_name_2(&list_grp,avp_name_2)||							\
+			!cdp_avp_add_##avp_name_3(&list_grp,avp_name_3)) {							\
+				cdp->AAAFreeAVPList(&list_grp);											\
+				return 0;																\
+		}																				\
+		return cdp_avp_add_to_list(list,												\
+				cdp_avp_new_Grouped(													\
+						CDP_AVP_NAME(avp_name),											\
+						flags,															\
+						vendor_id,														\
+						&list_grp,														\
+						AVP_FREE_DATA));												\
+	}
+
+
+
+
+
+
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int cdp_avp_get_##avp_name(AAA_AVP_LIST list,data_type *data,AAA_AVP **avp_ptr) \
+	{															\
+		AAA_AVP *avp = cdp_avp_get_next_from_list(list,			\
+				CDP_AVP_NAME(avp_name),							\
+				vendor_id,										\
+				avp_ptr?*avp_ptr:0);							\
+		if (avp_ptr) *avp_ptr = avp;							\
+		if (!avp) {												\
+			if (data) bzero(data,sizeof(data_type));			\
+			return 0;											\
+		}														\
+		return cdp_avp_get_##avp_type(avp,data);				\
+	}
+
+	
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+	int cdp_avp_get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,AAA_AVP **avp_ptr) \
+	{															\
+		int cnt=0;												\
+		AAA_AVP_LIST list_grp={0,0};							\
+		AAA_AVP *avp = cdp_avp_get_next_from_list(list,			\
+				CDP_AVP_NAME(avp_name),							\
+				vendor_id,										\
+				avp_ptr?*avp_ptr:0);							\
+		if (avp_ptr) *avp_ptr = avp;							\
+		if (!avp||!cdp_avp_get_Grouped(avp,&list_grp)) {		\
+			if (avp_name_1) bzero(avp_name_1,sizeof(data_type_1));		\
+			if (avp_name_2) bzero(avp_name_2,sizeof(data_type_2));		\
+			return 0;											\
+		}														\
+		cnt += cdp_avp_get_##avp_name_1(list_grp,avp_name_1,0);		\
+		cnt += cdp_avp_get_##avp_name_2(list_grp,avp_name_2,0);		\
+		cdp->AAAFreeAVPList(&list_grp);							\
+		return cnt;												\
+	}
+
+	
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+	int cdp_avp_get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,data_type_3 *avp_name_3,AAA_AVP **avp_ptr) \
+	{															\
+		int cnt=0;												\
+		AAA_AVP_LIST list_grp={0,0};							\
+		AAA_AVP *avp = cdp_avp_get_next_from_list(list,			\
+				CDP_AVP_NAME(avp_name),							\
+				vendor_id,										\
+				avp_ptr?*avp_ptr:0);							\
+		if (avp_ptr) *avp_ptr = avp;							\
+		if (!avp||!cdp_avp_get_Grouped(avp,&list_grp)) {		\
+			if (avp_name_1) bzero(avp_name_1,sizeof(data_type_1));		\
+			if (avp_name_2) bzero(avp_name_2,sizeof(data_type_2));		\
+			if (avp_name_3) bzero(avp_name_3,sizeof(data_type_3));		\
+			return 0;											\
+		}														\
+		cnt += cdp_avp_get_##avp_name_1(list_grp,avp_name_1,0);		\
+		cnt += cdp_avp_get_##avp_name_2(list_grp,avp_name_2,0);		\
+		cnt += cdp_avp_get_##avp_name_3(list_grp,avp_name_3,0);		\
+		cdp->AAAFreeAVPList(&list_grp);							\
+		return cnt;												\
+	}
+
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+
+#elif defined(CDP_AVP_EXPORT)
+
+	/*
+	 * This is the export of the functions in the module, so this needs to generate the mod_export.h lists
+	 */
+	
+	
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)		\
+		cdp_avp_add_##avp_name##_f		add_##avp_name;
+	
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add_##avp_name##_f		add_##avp_name;
+
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+		cdp_avp_add_##avp_name##_Group_f	add_##avp_name##_Group;  	
+	
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+		cdp_avp_add_##avp_name##_Group_f	add_##avp_name##_Group;  	
+
+
+
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		\
+		cdp_avp_get_##avp_name##_f		get_##avp_name;
+		
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+		cdp_avp_get_##avp_name##_Group_f	get_##avp_name##_Group;  	
+
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+		cdp_avp_get_##avp_name##_Group_f	get_##avp_name##_Group;  	
+
+
+
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+
+#elif defined(CDP_AVP_INIT)
+
+	/*
+	 * This is the initialization of the exported binding in the module, so this needs to generate the list of functions
+	 */
+
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)		\
+		cdp_avp_add_##avp_name,
+
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)		\
+		cdp_avp_add_##avp_name,
+
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+		cdp_avp_add_##avp_name##_Group,  	
+	
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+		cdp_avp_add_##avp_name##_Group,  	
+
+
+
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		\
+			cdp_avp_get_##avp_name,
+
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+		cdp_avp_get_##avp_name##_Group,  	
+	
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+		cdp_avp_get_##avp_name##_Group,  	
+
+
+
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) 
+		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) 
+
+
+#elif defined(CDP_AVP_REFERENCE)
+
+	/*
+	 * This is for generating a function reference for documentation
+	 */
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int CDP_AVP_MODULE.add_##avp_name(AAA_AVP_LIST *list,data_type data); 
+	
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int CDP_AVP_MODULE.add_##avp_name(AAA_AVP_LIST *list,data_type data,AVPDataStatus data_do); 
+	
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+	int CDP_AVP_MODULE.add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2); 
+	
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+	int CDP_AVP_MODULE.add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2,data_type_3 avp_name_3);
+		
+		
+		
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int CDP_AVP_MODULE.get_##avp_name(AAA_AVP_LIST list,data_type *data,AAA_AVP **avp_ptr); 
+
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+	int CDP_AVP_MODULE.get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,AAA_AVP **avp_ptr); 
+
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+	int CDP_AVP_MODULE.get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,data_type_3 *avp_name_3,AAA_AVP **avp_ptr);
+
+
+
+
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	\
+		|cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)	
+		
+	
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type) \
+		cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type) \
+		|cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		
+	
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		|cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		|cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+		
+
+#elif defined(CDP_AVP_EMPTY_MACROS)
+
+	/*
+	 * This is for ensuring that the templates won't actually output anything 
+	 */
+
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+	
+
+
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type)	
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+		
+#else
+
+	/*
+	 * This is the declaration of the functions, so this needs to generate the normal .h header file 
+	 */
+
+	#define cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int cdp_avp_add_##avp_name(AAA_AVP_LIST *list,data_type data);			\
+	typedef int (*cdp_avp_add_##avp_name##_f)(AAA_AVP_LIST *list,data_type data); 
+	
+	#define cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)		\
+	int cdp_avp_add_##avp_name(AAA_AVP_LIST *list,data_type data,AVPDataStatus data_do); \
+	typedef int (*cdp_avp_add_##avp_name##_f)(AAA_AVP_LIST *list,data_type data,AVPDataStatus data_do); 
+	
+	#define cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+	int cdp_avp_add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2);  \
+	typedef int (*cdp_avp_add_##avp_name##_Group_f)(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2);
+	
+	#define cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+	int cdp_avp_add_##avp_name##_Group(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2,data_type_3 avp_name_3); \
+	typedef int (*cdp_avp_add_##avp_name##_Group_f)(AAA_AVP_LIST *list,data_type_1 avp_name_1,data_type_2 avp_name_2,data_type_3 avp_name_3);
+
+
+
+	#define cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)		\
+		int cdp_avp_get_##avp_name(AAA_AVP_LIST list,data_type *data,AAA_AVP **avp_ptr); \
+		typedef	int (*cdp_avp_get_##avp_name##_f)(AAA_AVP_LIST list,data_type *data,AAA_AVP **avp_ptr); 
+
+	#define cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)	\
+		int cdp_avp_get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,AAA_AVP **avp_ptr); \
+		typedef int (*cdp_avp_get_##avp_name##_Group_f)(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,AAA_AVP **avp_ptr);
+
+	#define cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)	\
+		int cdp_avp_get_##avp_name##_Group(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,data_type_3 *avp_name_3,AAA_AVP **avp_ptr); \
+		typedef int (*cdp_avp_get_##avp_name##_Group_f)(AAA_AVP_LIST list,data_type_1 *avp_name_1,data_type_2 *avp_name_2,data_type_3 *avp_name_3,AAA_AVP **avp_ptr);
+
+
+
+
+	#define cdp_avp(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_add_ptr(avp_name,vendor_id,flags,avp_type,data_type)	\
+		cdp_avp_get(avp_name,vendor_id,flags,avp_type,data_type)
+	
+	#define cdp_avp2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_add2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2) \
+		cdp_avp_get2(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2)
+		
+	#define cdp_avp3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_add3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3) \
+		cdp_avp_get3(avp_name,vendor_id,flags,avp_name_1,data_type_1,avp_name_2,data_type_2,avp_name_3,data_type_3)
+#endif
+
+

部分文件因为文件数量过多而无法显示