Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
oai
freediameter
Commits
eec3ebe5
Commit
eec3ebe5
authored
Apr 30, 2010
by
Sebastien Decugis
Browse files
Added a test case for the app_acct extension
parent
5a400937
Changes
11
Hide whitespace changes
Inline
Side-by-side
extensions/app_acct/CMakeLists.txt
View file @
eec3ebe5
...
...
@@ -16,11 +16,13 @@ SET_SOURCE_FILES_PROPERTIES(lex.acct_conf.c acct_conf.tab.c PROPERTIES COMPILE_F
SET
(
APP_ACCT_SRC
app_acct.h
app_acct.c
acct_db.c
acct_records.c
)
SET
(
APP_ACCT_SRC_GEN
lex.acct_conf.c
acct_conf.tab.c
acct_conf.tab.h
acct_db.c
acct_records.c
)
# Compile as a module
...
...
extensions/app_acct/acct_db.c
View file @
eec3ebe5
...
...
@@ -50,8 +50,12 @@ const char * diam2db_types_mapping[AVP_TYPE_MAX + 1] = {
};
static
const
char
*
stmt
=
"acct_db_stmt"
;
static
PGconn
*
conn
=
NULL
;
#ifndef TEST_DEBUG
static
#endif
/* TEST_DEBUG */
PGconn
*
conn
=
NULL
;
/* Initialize the database context: connection to the DB, prepared statement to insert new records */
int
acct_db_init
(
void
)
{
struct
acct_record_list
emptyrecords
;
...
...
@@ -62,7 +66,7 @@ int acct_db_init(void)
size_t
p
;
int
idx
=
0
;
PGresult
*
res
;
#define REALLOC_SIZE 1024
#define REALLOC_SIZE 1024
/* We extend the buffer by this amount */
TRACE_ENTRY
();
CHECK_PARAMS
(
acct_config
&&
acct_config
->
conninfo
&&
acct_config
->
tablename
);
...
...
@@ -75,9 +79,14 @@ int acct_db_init(void)
fd_log_debug
(
"Connection to database failed: %s
\n
"
,
PQerrorMessage
(
conn
));
acct_db_free
();
return
EINVAL
;
}
else
{
TRACE_DEBUG
(
INFO
,
"Connection to database successfull: user:%s, db:%s, host:%s."
,
PQuser
(
conn
),
PQdb
(
conn
),
PQhost
(
conn
));
}
if
(
PQprotocolVersion
(
conn
)
<
3
)
{
fd_log_debug
(
"Database protocol version is too old, version 3 is required for prepared statements.
\n
"
);
acct_db_free
();
return
EINVAL
;
}
TRACE_DEBUG
(
FULL
,
"Connection to database successful, server version %d."
,
PQserverVersion
(
conn
));
/* Now, prepare the request object */
...
...
@@ -173,21 +182,105 @@ int acct_db_init(void)
}
PQclear
(
res
);
free
(
sql
);
acct_rec_empty
(
&
emptyrecords
);
/* Ok, ready */
return
0
;
}
/* Terminate the connection to the DB */
void
acct_db_free
(
void
)
{
if
(
conn
)
{
if
(
conn
)
{
/* Note: the prepared statement is automatically freed when the session terminates */
PQfinish
(
conn
);
conn
=
NULL
;
conn
=
NULL
;
}
}
/* When a new message has been received, insert the content of the parsed mapping into the DB (using prepared statement) */
int
acct_db_insert
(
struct
acct_record_list
*
records
)
{
return
ENOTSUP
;
char
**
val
;
int
*
val_len
;
int
*
val_isbin
;
int
idx
=
0
;
PGresult
*
res
;
struct
fd_list
*
li
;
TRACE_ENTRY
(
"%p"
,
records
);
CHECK_PARAMS
(
conn
&&
records
);
/* First, check if the connection with the DB has not staled, and eventually try to fix it */
if
(
PQstatus
(
conn
)
!=
CONNECTION_OK
)
{
/* Attempt a reset */
PQreset
(
conn
);
if
(
PQstatus
(
conn
)
!=
CONNECTION_OK
)
{
TRACE_DEBUG
(
INFO
,
"Lost connection to the database server, and attempt to reestablish it failed"
);
TODO
(
"Terminate the freeDiameter instance completly?"
);
return
ENOTCONN
;
}
}
/* Alloc the arrays of parameters */
CHECK_MALLOC
(
val
=
calloc
(
records
->
nball
,
sizeof
(
const
char
*
))
);
CHECK_MALLOC
(
val_len
=
calloc
(
records
->
nball
,
sizeof
(
const
int
))
);
CHECK_MALLOC
(
val_isbin
=
calloc
(
records
->
nball
,
sizeof
(
const
int
))
);
/* Now write all the map'd records in these arrays */
for
(
li
=
records
->
all
.
next
;
li
!=
&
records
->
all
;
li
=
li
->
next
)
{
struct
acct_record_item
*
r
=
(
struct
acct_record_item
*
)(
li
->
o
);
if
(
r
->
value
)
{
val_isbin
[
idx
]
=
1
;
/* We always pass binary parameters */
switch
(
r
->
param
->
avptype
)
{
case
AVP_TYPE_OCTETSTRING
:
val
[
idx
]
=
(
void
*
)(
r
->
value
->
os
.
data
);
val_len
[
idx
]
=
r
->
value
->
os
.
len
;
break
;
case
AVP_TYPE_INTEGER32
:
case
AVP_TYPE_UNSIGNED32
:
case
AVP_TYPE_FLOAT32
:
r
->
scalar
.
v32
=
htonl
(
r
->
value
->
u32
);
val
[
idx
]
=
&
r
->
scalar
.
c
;
val_len
[
idx
]
=
sizeof
(
uint32_t
);
break
;
case
AVP_TYPE_INTEGER64
:
case
AVP_TYPE_UNSIGNED64
:
case
AVP_TYPE_FLOAT64
:
r
->
scalar
.
v64
=
htonll
(
r
->
value
->
u64
);
val
[
idx
]
=
&
r
->
scalar
.
c
;
val_len
[
idx
]
=
sizeof
(
uint64_t
);
break
;
default:
ASSERT
(
0
);
/* detect bugs */
}
}
idx
++
;
}
/* OK, now execute the SQL statement */
res
=
PQexecPrepared
(
conn
,
stmt
,
records
->
nball
,
(
const
char
*
const
*
)
val
,
val_len
,
val_isbin
,
1
/* We actually don't care here */
);
/* Done with the parameters */
free
(
val
);
free
(
val_len
);
free
(
val_isbin
);
/* Now check the result code */
if
(
PQresultStatus
(
res
)
!=
PGRES_COMMAND_OK
)
{
TRACE_DEBUG
(
INFO
,
"An error occurred while INSERTing in the database: %s"
,
PQerrorMessage
(
conn
));
PQclear
(
res
);
return
EINVAL
;
/* It was probably a mistake in configuration file... */
}
PQclear
(
res
);
/* Ok, we are done */
return
0
;
}
extensions/app_acct/acct_records.c
View file @
eec3ebe5
...
...
@@ -73,11 +73,89 @@ int acct_rec_prepare(struct acct_record_list * records)
return
0
;
}
/* Find the AVPs from configuration inside a received message */
int
acct_rec_map
(
struct
acct_record_list
*
records
,
struct
msg
*
msg
)
{
struct
avp
*
avp
;
TRACE_ENTRY
(
"%p %p"
,
records
,
msg
);
/* For each AVP in the message, search if we have a corresponding unmap'd record */
CHECK_FCT
(
fd_msg_browse
(
msg
,
MSG_BRW_FIRST_CHILD
,
&
avp
,
NULL
)
);
while
(
avp
)
{
struct
fd_list
*
li
;
struct
dict_object
*
model
;
CHECK_FCT
(
fd_msg_model
(
avp
,
&
model
)
);
if
(
model
!=
NULL
)
{
/* we ignore the AVPs we don't recognize */
/* Search this model in the list */
for
(
li
=
records
->
unmaped
.
next
;
li
!=
&
records
->
unmaped
;
li
=
li
->
next
)
{
struct
acct_record_item
*
r
=
(
struct
acct_record_item
*
)(
li
->
o
);
if
(
r
->
param
->
avpobj
==
model
)
{
/* It matches: save the AVP value and unlink this record from the unmap'd list */
struct
avp_hdr
*
h
;
CHECK_FCT
(
fd_msg_avp_hdr
(
avp
,
&
h
)
);
r
->
value
=
h
->
avp_value
;
fd_list_unlink
(
&
r
->
unmapd
);
records
->
nbunmap
-=
1
;
break
;
}
}
/* Continue only while there are some AVPs to map */
if
(
FD_IS_LIST_EMPTY
(
&
records
->
unmaped
))
break
;
}
/* Go to next AVP in the message */
CHECK_FCT
(
fd_msg_browse
(
avp
,
MSG_BRW_NEXT
,
&
avp
,
NULL
)
);
}
return
ENOTSUP
;
/* Done */
return
0
;
}
/* Check that a mapped list is not empty and no required AVP is missing. Free the record list in case of error */
int
acct_rec_validate
(
struct
acct_record_list
*
records
)
{
struct
fd_list
*
li
;
TRACE_ENTRY
(
"%p"
,
records
);
CHECK_PARAMS
(
records
);
/* Check at least one AVP was mapped */
if
(
records
->
nball
==
records
->
nbunmap
)
{
fd_log_debug
(
"The received ACR does not contain any AVP from the configuration file.
\n
"
"This is an invalid situation. Please fix your configuration file.
\n
"
"One way to ensure this does not happen is to include Session-Id in the database.
\n
"
);
acct_rec_empty
(
records
);
return
EINVAL
;
}
/* Now, check there is no required AVP unmap'd */
for
(
li
=
records
->
unmaped
.
next
;
li
!=
&
records
->
unmaped
;
li
=
li
->
next
)
{
struct
acct_record_item
*
r
=
(
struct
acct_record_item
*
)(
li
->
o
);
if
(
r
->
param
->
required
&&
(
r
->
index
<=
1
))
{
fd_log_debug
(
"The received ACR does not contain the required AVP '%s'.
\n
"
,
r
->
param
->
avpname
);
acct_rec_empty
(
records
);
return
EINVAL
;
}
}
/* The record list is OK */
return
0
;
}
/* Free all the items in an acct_record_list returned by acct_rec_prepare */
void
acct_rec_empty
(
struct
acct_record_list
*
records
)
{
TRACE_ENTRY
(
"%p"
,
records
);
CHECK_PARAMS_DO
(
records
,
return
);
while
(
!
FD_IS_LIST_EMPTY
(
&
records
->
all
))
{
struct
acct_record_item
*
r
=
(
struct
acct_record_item
*
)(
records
->
all
.
next
);
fd_list_unlink
(
&
r
->
chain
);
fd_list_unlink
(
&
r
->
unmapd
);
free
(
r
);
}
}
extensions/app_acct/app_acct.c
View file @
eec3ebe5
...
...
@@ -37,51 +37,76 @@
#include "app_acct.h"
/* Default callback for the Accounting application. */
static
int
acct_fallback
(
struct
msg
**
msg
,
struct
avp
*
avp
,
struct
session
*
sess
,
enum
disp_action
*
act
)
{
/* This CB should never be called */
TRACE_ENTRY
(
"%p %p %p %p"
,
msg
,
avp
,
sess
,
act
);
fd_log_debug
(
"Unexpected message received!
\n
"
);
return
ENOTSUP
;
}
/* Mandatory AVPs for the Accounting-Answer */
static
struct
{
struct
dict_object
*
Accounting_Record_Number
;
struct
dict_object
*
Accounting_Record_Type
;
}
acct_dict
;
/* Callback for incoming Base Accounting Accounting-Request messages */
static
int
acct_cb
(
struct
msg
**
msg
,
struct
avp
*
avp
,
struct
session
*
sess
,
enum
disp_action
*
act
)
{
struct
msg_hdr
*
hdr
=
NULL
;
struct
msg
*
ans
,
*
qry
;
struct
msg
*
m
;
struct
avp
*
a
=
NULL
;
struct
avp_hdr
*
h
=
NULL
;
struct
avp_hdr
*
art
=
NULL
,
*
arn
=
NULL
;
/* We keep a pointer on the Accounting-Record-{Type, Number} AVPs from the query */
char
*
s
;
struct
acct_record_list
rl
;
TRACE_ENTRY
(
"%p %p %p %p"
,
msg
,
avp
,
sess
,
act
);
if
(
msg
==
NULL
)
return
EINVAL
;
qry
=
*
msg
;
/* Create the answer message, including the Session-Id AVP */
m
=
*
msg
;
/* Prepare a new record list */
CHECK_FCT
(
acct_rec_prepare
(
&
rl
)
);
/* Maps the AVPs from the query with this record list */
CHECK_FCT
(
acct_rec_map
(
&
rl
,
m
)
);
/* Check that at least one AVP was mapped */
CHECK_FCT
(
acct_rec_validate
(
&
rl
)
);
/* Now, save these mapped AVPs in the database */
CHECK_FCT
(
acct_db_insert
(
&
rl
)
);
acct_rec_empty
(
&
rl
);
/* OK, we can send a positive reply now */
/* Get Accounting-Record-{Number,Type} values */
CHECK_FCT
(
fd_msg_search_avp
(
m
,
acct_dict
.
Accounting_Record_Type
,
&
a
)
);
if
(
a
)
{
CHECK_FCT
(
fd_msg_avp_hdr
(
a
,
&
art
)
);
}
CHECK_FCT
(
fd_msg_search_avp
(
m
,
acct_dict
.
Accounting_Record_Number
,
&
a
)
);
if
(
a
)
{
CHECK_FCT
(
fd_msg_avp_hdr
(
a
,
&
arn
)
);
}
/* Create the answer message */
CHECK_FCT
(
fd_msg_new_answer_from_req
(
fd_g_config
->
cnf_dict
,
msg
,
0
)
);
ans
=
*
msg
;
m
=
*
msg
;
/* Set the Origin-Host, Origin-Realm, Result-Code AVPs */
CHECK_FCT
(
fd_msg_rescode_set
(
ans
,
"DIAMETER_SUCCESS"
,
NULL
,
NULL
,
1
)
);
fd_log_debug
(
"--------------Received the following Accounting message:--------------
\n
"
);
CHECK_FCT
(
fd_sess_getsid
(
sess
,
&
s
)
);
fd_log_debug
(
"Session: %s
\n
"
,
s
);
/* We may also dump other data from the message, such as Accounting session Id, number of packets, ... */
fd_log_debug
(
"----------------------------------------------------------------------
\n
"
);
CHECK_FCT
(
fd_msg_rescode_set
(
m
,
"DIAMETER_SUCCESS"
,
NULL
,
NULL
,
1
)
);
/* Add the mandatory AVPs in the ACA */
if
(
art
)
{
CHECK_FCT
(
fd_msg_avp_new
(
acct_dict
.
Accounting_Record_Type
,
0
,
&
a
)
);
CHECK_FCT
(
fd_msg_avp_setvalue
(
a
,
art
->
avp_value
)
);
CHECK_FCT
(
fd_msg_avp_add
(
m
,
MSG_BRW_LAST_CHILD
,
a
)
);
}
if
(
arn
)
{
CHECK_FCT
(
fd_msg_avp_new
(
acct_dict
.
Accounting_Record_Number
,
0
,
&
a
)
);
CHECK_FCT
(
fd_msg_avp_setvalue
(
a
,
arn
->
avp_value
)
);
CHECK_FCT
(
fd_msg_avp_add
(
m
,
MSG_BRW_LAST_CHILD
,
a
)
);
}
/* Send the answer */
CHECK_FCT
(
fd_msg_send
(
msg
,
NULL
,
NULL
)
);
*
act
=
DISP_ACT_SEND
;
return
0
;
}
...
...
@@ -93,18 +118,23 @@ static int acct_entry(char * conffile)
TRACE_ENTRY
(
"%p"
,
conffile
);
#ifndef TEST_DEBUG
/* We do this differently in the test scenario */
/* Initialize the configuration and parse the file */
CHECK_FCT
(
acct_conf_init
()
);
CHECK_FCT
(
acct_conf_parse
(
conffile
)
);
CHECK_FCT
(
acct_conf_check
(
conffile
)
);
#endif
/* TEST_DEBUG */
/* Now initialize the database module */
CHECK_FCT
(
acct_db_init
()
);
/* Search the AVPs we will need in this file */
CHECK_FCT
(
fd_dict_search
(
fd_g_config
->
cnf_dict
,
DICT_AVP
,
AVP_BY_NAME
,
"Accounting-Record-Number"
,
&
acct_dict
.
Accounting_Record_Number
,
ENOENT
)
);
CHECK_FCT
(
fd_dict_search
(
fd_g_config
->
cnf_dict
,
DICT_AVP
,
AVP_BY_NAME
,
"Accounting-Record-Type"
,
&
acct_dict
.
Accounting_Record_Type
,
ENOENT
)
);
/* Register the dispatch callbacks */
memset
(
&
data
,
0
,
sizeof
(
data
));
CHECK_FCT
(
fd_dict_search
(
fd_g_config
->
cnf_dict
,
DICT_APPLICATION
,
APPLICATION_BY_NAME
,
"Diameter Base Accounting"
,
&
data
.
app
,
ENOENT
)
);
CHECK_FCT
(
fd_disp_register
(
acct_fallback
,
DISP_HOW_APPID
,
&
data
,
NULL
)
);
CHECK_FCT
(
fd_dict_search
(
fd_g_config
->
cnf_dict
,
DICT_COMMAND
,
CMD_BY_NAME
,
"Accounting-Request"
,
&
data
.
command
,
ENOENT
)
);
CHECK_FCT
(
fd_disp_register
(
acct_cb
,
DISP_HOW_CC
,
&
data
,
NULL
)
);
...
...
extensions/app_acct/app_acct.h
View file @
eec3ebe5
...
...
@@ -83,6 +83,11 @@ struct acct_record_item {
struct
acct_conf_avp
*
param
;
/* the AVP entry this refers to. */
unsigned
index
;
/* in case of multi */
union
avp_value
*
value
;
/* If the AVP was found in the message, this points to its value. Otherwise, NULL */
union
{
uint32_t
v32
/* Storage area for network byte-order copy of the AVP value */
;
uint64_t
v64
;
char
c
;
/* pointer that is passed to the database */
}
scalar
;
/* for scalar AVP (all types except OCTETSTRING) we copy in this area the value in network byte order */
};
/* The sentinel for a list of acct_record_items */
...
...
@@ -111,3 +116,5 @@ void acct_db_free(void);
/* In acct_records.c */
int
acct_rec_prepare
(
struct
acct_record_list
*
records
);
int
acct_rec_map
(
struct
acct_record_list
*
records
,
struct
msg
*
msg
);
int
acct_rec_validate
(
struct
acct_record_list
*
records
);
void
acct_rec_empty
(
struct
acct_record_list
*
records
);
freeDiameter/extensions.c
View file @
eec3ebe5
...
...
@@ -152,7 +152,7 @@ int fd_ext_load()
}
/* Now unload the extensions and free the memory */
int
fd_ext_
fini
(
void
)
int
fd_ext_
term
(
void
)
{
TRACE_ENTRY
();
...
...
freeDiameter/fD.h
View file @
eec3ebe5
...
...
@@ -83,7 +83,7 @@ int fddparse(struct fd_config * conf); /* yacc generated */
int
fd_ext_add
(
char
*
filename
,
char
*
conffile
);
int
fd_ext_load
();
void
fd_ext_dump
(
void
);
int
fd_ext_
fini
(
void
);
int
fd_ext_
term
(
void
);
/* Messages */
int
fd_msg_init
(
void
);
...
...
freeDiameter/main.c
View file @
eec3ebe5
...
...
@@ -164,7 +164,7 @@ end:
CHECK_FCT_DO
(
fd_peer_fini
(),
/* Stop all connections */
);
CHECK_FCT_DO
(
fd_rtdisp_fini
(),
/* Stop routing threads and destroy routing queues */
);
CHECK_FCT_DO
(
fd_ext_
fini
(),
/* Cleanup all extensions */
);
CHECK_FCT_DO
(
fd_ext_
term
(),
/* Cleanup all extensions */
);
CHECK_FCT_DO
(
fd_rtdisp_cleanup
(),
/* destroy remaining handlers */
);
GNUTLS_TRACE
(
gnutls_global_deinit
()
);
...
...
freeDiameter/tests/CMakeLists.txt
View file @
eec3ebe5
...
...
@@ -49,11 +49,59 @@ ENDFOREACH(SRC_FILE)
# Create an archive with the daemon common files (all but main)
ADD_LIBRARY
(
fDcore STATIC
${
TEST_COMMON_SRC
}
)
##############################
# App_acct test
IF
(
BUILD_APP_ACCT
)
OPTION
(
TEST_APP_ACCT
"Test app_acct extension? (Requires a configured database, see testappacct.c for details)"
OFF
)
IF
(
TEST_APP_ACCT
)
OPTION
(
TEST_APP_ACCT_CONNINFO
"The connection string to the database"
)
IF
(
TEST_APP_ACCT_CONNINFO
)
ADD_DEFINITIONS
(
-DTEST_CONNINFO=
"
${
TEST_APP_ACCT_CONNINFO
}
"
)
ENDIF
(
TEST_APP_ACCT_CONNINFO
)
SET
(
TEST_LIST
${
TEST_LIST
}
testappacct
)
# Extension dependencies
FIND_PACKAGE
(
PostgreSQL REQUIRED
)
INCLUDE_DIRECTORIES
(
${
POSTGRESQL_INCLUDE_DIR
}
)
SET
(
testappacct_ADDITIONAL_LIB
${
POSTGRESQL_LIBRARIES
}
)
# List of source files, copied from the extension CMakeLists.
SET
(
APP_ACCT_SRC
app_acct.h
app_acct.c
acct_db.c
acct_records.c
)
SET
(
APP_ACCT_SRC_GEN
lex.acct_conf.c
acct_conf.tab.c
acct_conf.tab.h
)
# The extension headers
INCLUDE_DIRECTORIES
(
"../../extensions/app_acct"
)
SET
(
testappacct_ADDITIONAL
""
)
FOREACH
(
SRC_FILE
${
APP_ACCT_SRC
}
)
SET
(
testappacct_ADDITIONAL
${
testappacct_ADDITIONAL
}
"../../extensions/app_acct/
${
SRC_FILE
}
"
)
ENDFOREACH
(
SRC_FILE
)
FOREACH
(
SRC_FILE
${
APP_ACCT_SRC_GEN
}
)
SET
(
testappacct_ADDITIONAL
${
testappacct_ADDITIONAL
}
"
${
CMAKE_CURRENT_BINARY_DIR
}
/../../extensions/app_acct/
${
SRC_FILE
}
"
)
ENDFOREACH
(
SRC_FILE
)
ENDIF
(
TEST_APP_ACCT
)
ENDIF
(
BUILD_APP_ACCT
)
#############################
# Compile each test
FOREACH
(
TEST
${
TEST_LIST
}
)
ADD_EXECUTABLE
(
${
TEST
}
${
TEST
}
.c tests.h
)
TARGET_LINK_LIBRARIES
(
${
TEST
}
fDcore
${
FD_LIBS
}
)
ADD_EXECUTABLE
(
${
TEST
}
${
TEST
}
.c tests.h
${${
TEST
}
_ADDITIONAL
}
)
TARGET_LINK_LIBRARIES
(
${
TEST
}
fDcore
${
FD_LIBS
}
${${
TEST
}
_ADDITIONAL_LIB
}
)
ADD_TEST
(
${
TEST
}
${
EXECUTABLE_OUTPUT_PATH
}
/
${
TEST
}
)
ENDFOREACH
(
TEST
)
freeDiameter/tests/testappacct.c
0 → 100644
View file @
eec3ebe5
/*********************************************************************************************************
* Software License Agreement (BSD License) *
* Author: Sebastien Decugis <sdecugis@nict.go.jp> *
* *
* Copyright (c) 2009, WIDE Project and NICT *
* All rights reserved. *
* *
* Redistribution and use of this software in source and binary forms, with or without modification, are *
* permitted provided that the following conditions are met: *
* *
* * Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* * Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* following disclaimer in the documentation and/or other *
* materials provided with the distribution. *
* *
* * Neither the name of the WIDE Project or NICT nor the *
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission of WIDE Project and *
* NICT. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR *
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS *
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
*********************************************************************************************************/
#include "tests.h"
/* The connection string to the database */
#ifndef TEST_CONNINFO
#error "Please specify the conninfo information"
#endif
/* TEST_CONNINFO */
/* The table used for tests. This table will receive the following instructions:
DROP TABLE <table>;
CREATE TABLE <table>
(
ts timestamp with time zone NOT NULL,
"Accounting-Record-Type" integer,
"Session-Id" bytea,
"Accounting-Record-Number" integer,
"Route-Record1" bytea,
"Route-Record2" bytea,
"Route-Record3" bytea,
"Route-Record4" bytea
);
*/
#define TABLE "incoming_test"
#include "app_acct.h"
#include <libpq-fe.h>
static
int
add_avp_in_conf
(
char
*
avpname
,
int
multi
)
{
struct
acct_conf_avp
*
new
;
struct
dict_object
*
dict
;
struct
dict_avp_data
dictdata
;
/* Validate the avp name first */
CHECK_FCT
(
fd_dict_search
(
fd_g_config
->
cnf_dict
,
DICT_AVP
,
AVP_BY_NAME
,
avpname
,
&
dict
,
ENOENT
)
);
CHECK_FCT
(
fd_dict_getval
(
dict
,
&
dictdata
));
/* Create a new entry */
CHECK_MALLOC
(
new
=
malloc
(
sizeof
(
struct
acct_conf_avp
))
);
memset
(
new
,
0
,
sizeof
(
struct
acct_conf_avp
));
fd_list_init
(
&
new
->
chain
,
NULL
);
new
->
avpname
=
avpname
;
new
->
avpobj
=
dict
;
new
->
avptype
=
dictdata
.
avp_basetype
;
new
->
multi
=
multi
;
/* Add this new entry at the end of the list */
fd_list_insert_before
(
&
acct_config
->
avps
,
&
new
->
chain
);
return
0
;
}
/* Main test routine */
int
main
(
int
argc
,
char
*
argv
[])
{
extern
PGconn
*
conn
;
/* in acct_db.c */
struct
msg
*
msg
;
char
*
sess_bkp
;
struct
dict_object
*
session_id
=
NULL
;
/* First, initialize the daemon modules */
INIT_FD
();
fd_g_config
->
cnf_diamid
=
strdup
(
"test.app.acct"
);
fd_g_config
->
cnf_diamid_len
=
strlen
(
fd_g_config
->
cnf_diamid
);
fd_g_config
->
cnf_diamrlm
=
strdup
(
"app.acct"
);
fd_g_config
->
cnf_diamrlm_len
=
strlen
(
fd_g_config
->
cnf_diamrlm
);
CHECK
(
0
,
fd_queues_init
()
);
CHECK
(
0
,
fd_msg_init
()
);
CHECK
(
0
,
fd_rtdisp_init
()
);
/* Initialize the extension configuration for the test */
{
CHECK
(
0
,
acct_conf_init
()
);
acct_config
->
conninfo
=
strdup
(
TEST_CONNINFO
);
acct_config
->
tablename
=
strdup
(
TABLE
);
acct_config
->
tsfield
=
strdup
(
"ts"
);
CHECK
(
0
,
add_avp_in_conf
(
strdup
(
"Session-Id"
),
0
)
);
CHECK
(
0
,
add_avp_in_conf
(
strdup
(
"Accounting-Record-Type"
),
0
)
);
CHECK
(
0
,
add_avp_in_conf
(
strdup
(
"Accounting-Record-Number"
),
0
)
);