diff --git a/CHANGES b/CHANGES index 91df249f755bd0379f3b0164c4aba120ef4c2bfe..3b00468056fcaa5488de9fc0809ae45b3549fe55 100644 --- a/CHANGES +++ b/CHANGES @@ -346,6 +346,7 @@ libpri channel driver (chan_dahdi) DAHDI changes * Added the ability to send and receive ETSI Advice-Of-Charge messages. * Added the ability to support call waiting calls. (The SETUP has no B channel assigned.) + * Added Malicious Call ID (MCID) event to the AMI call event class. Asterisk Manager Interface -------------------------- diff --git a/channels/sig_pri.c b/channels/sig_pri.c index 92f4cf926aea1ff4bbbebb660147772747af63e6..8955c670b79a72cf6c650e82e8250c0c35a938a4 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -1644,6 +1644,98 @@ static int sig_pri_msn_match(const char *msn_patterns, const char *exten) return 0; } +#if defined(HAVE_PRI_MCID) +/*! + * \internal + * \brief Append the given party id to the event string. + * \since 1.8 + * + * \param msg Event message string being built. + * \param prefix Prefix to add to the party id lines. + * \param party Party information to encode. + * + * \return Nothing + */ +static void sig_pri_event_party_id(struct ast_str **msg, const char *prefix, struct ast_party_id *party) +{ + ast_str_append(msg, 0, "%sPres: %d (%s)\r\n", prefix, + party->number_presentation, + ast_describe_caller_presentation(party->number_presentation)); + ast_str_append(msg, 0, "%sNum: %s\r\n", prefix, S_OR(party->number, "")); + ast_str_append(msg, 0, "%ston: %d\r\n", prefix, party->number_type); + ast_str_append(msg, 0, "%sName: %s\r\n", prefix, S_OR(party->name, "")); +#if defined(HAVE_PRI_SUBADDR) + if (party->subaddress.valid) { + static const char subaddress[] = "Subaddr"; + + ast_str_append(msg, 0, "%s%s: %s\r\n", prefix, subaddress, + S_OR(party->subaddress.str, "")); + ast_str_append(msg, 0, "%s%sType: %d\r\n", prefix, subaddress, + party->subaddress.type); + ast_str_append(msg, 0, "%s%sOdd: %d\r\n", prefix, subaddress, + party->subaddress.odd_even_indicator); + } +#endif /* defined(HAVE_PRI_SUBADDR) */ +} +#endif /* defined(HAVE_PRI_MCID) */ + +#if defined(HAVE_PRI_MCID) +/*! + * \internal + * \brief Handle the MCID event. + * \since 1.8 + * + * \param pri sig_pri PRI control structure. + * \param mcid MCID event parameters. + * \param owner Asterisk channel associated with the call. + * NULL if Asterisk no longer has the ast_channel struct. + * + * \note Assumes the pri->lock is already obtained. + * \note Assumes the owner channel lock is already obtained if still present. + * + * \return Nothing + */ +static void sig_pri_mcid_event(struct sig_pri_pri *pri, const struct pri_subcmd_mcid_req *mcid, struct ast_channel *owner) +{ + struct ast_channel *chans[1]; + struct ast_str *msg; + struct ast_party_id party; + + msg = ast_str_create(4096); + if (!msg) { + return; + } + + if (owner) { + /* The owner channel is present. */ + ast_str_append(&msg, 0, "Channel: %s\r\n", owner->name); + ast_str_append(&msg, 0, "UniqueID: %s\r\n", owner->uniqueid); + + sig_pri_event_party_id(&msg, "CallerID", &owner->connected.id); + } else { + /* + * Since we no longer have an owner channel, + * we have to use the caller information supplied by libpri. + */ + ast_party_id_init(&party); + sig_pri_party_id_convert(&party, &mcid->originator, pri); + sig_pri_event_party_id(&msg, "CallerID", &party); + ast_party_id_free(&party); + } + + /* Always use libpri's called party information. */ + ast_party_id_init(&party); + sig_pri_party_id_convert(&party, &mcid->answerer, pri); + sig_pri_event_party_id(&msg, "ConnectedID", &party); + ast_party_id_free(&party); + + chans[0] = owner; + ast_manager_event_multichan(EVENT_FLAG_CALL, "MCID", owner ? 1 : 0, chans, "%s", + ast_str_buffer(msg)); + ast_free(msg); +} +#endif /* defined(HAVE_PRI_MCID) */ + #if defined(HAVE_PRI_CALL_HOLD) || defined(HAVE_PRI_TRANSFER) /*! * \internal @@ -3640,6 +3732,21 @@ static void sig_pri_handle_subcmds(struct sig_pri_pri *pri, int chanpos, int eve } break; #endif /* defined(HAVE_PRI_AOC_EVENTS) */ +#if defined(HAVE_PRI_MCID) + case PRI_SUBCMD_MCID_REQ: + sig_pri_lock_owner(pri, chanpos); + owner = pri->pvts[chanpos]->owner; + sig_pri_mcid_event(pri, &subcmd->u.mcid_req, owner); + if (owner) { + ast_channel_unlock(owner); + } + break; +#endif /* defined(HAVE_PRI_MCID) */ +#if defined(HAVE_PRI_MCID) + case PRI_SUBCMD_MCID_RSP: + /* Ignore for now. */ + break; +#endif /* defined(HAVE_PRI_MCID) */ default: ast_debug(2, "Unknown call subcommand(%d) in %s event on channel %d/%d on span %d.\n", @@ -6451,6 +6558,9 @@ int sig_pri_start_pri(struct sig_pri_pri *pri) #if defined(HAVE_PRI_CALL_WAITING) pri_connect_ack_enable(pri->pri, 1); #endif /* defined(HAVE_PRI_CALL_WAITING) */ +#if defined(HAVE_PRI_MCID) + pri_mcid_enable(pri->pri, 1); +#endif /* defined(HAVE_PRI_MCID) */ pri->resetpos = -1; if (ast_pthread_create_background(&pri->master, NULL, pri_dchannel, pri)) { diff --git a/configure b/configure index 3da55a7adea2f84f432ff391b7f84d79764fee46..124d6c840ef6ad73d3924f0ab5df5c1b71e3d2d5 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Revision: 267008 . +# From configure.ac Revision: 267261 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.63 for asterisk 1.6. # @@ -870,6 +870,10 @@ PBX_PRI_CALL_WAITING PRI_CALL_WAITING_DIR PRI_CALL_WAITING_INCLUDE PRI_CALL_WAITING_LIB +PBX_PRI_MCID +PRI_MCID_DIR +PRI_MCID_INCLUDE +PRI_MCID_LIB PBX_PRI PRI_DIR PRI_INCLUDE @@ -10093,6 +10097,25 @@ fi +PRI_MCID_DESCRIP="ISDN PRI Malicious Call ID" +PRI_MCID_OPTION=pri + +for i in ${ac_mandatory_list}; do + if test "xPRI" = "x$i"; then + ac_mandatory_list="${ac_mandatory_list} PRI_MCID" + break + fi +done + +PBX_PRI_MCID=0 + + + + + + + + PRI_CALL_WAITING_DESCRIP="ISDN PRI call waiting supplementary service" PRI_CALL_WAITING_OPTION=pri @@ -35508,6 +35531,273 @@ fi +if test "x${PBX_PRI_MCID}" != "x1" -a "${USE_PRI_MCID}" != "no"; then + pbxlibdir="" + # if --with-PRI_MCID=DIR has been specified, use it. + if test "x${PRI_MCID_DIR}" != "x"; then + if test -d ${PRI_MCID_DIR}/lib; then + pbxlibdir="-L${PRI_MCID_DIR}/lib" + else + pbxlibdir="-L${PRI_MCID_DIR}" + fi + fi + pbxfuncname="pri_mcid_enable" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_PRI_MCID_FOUND=yes + else + ast_ext_lib_check_save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} " + as_ac_Lib=`$as_echo "ac_cv_lib_pri_${pbxfuncname}" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for ${pbxfuncname} in -lpri" >&5 +$as_echo_n "checking for ${pbxfuncname} in -lpri... " >&6; } +if { as_var=$as_ac_Lib; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpri ${pbxlibdir} $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_Lib=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_Lib=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +ac_res=`eval 'as_val=${'$as_ac_Lib'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +as_val=`eval 'as_val=${'$as_ac_Lib'} + $as_echo "$as_val"'` + if test "x$as_val" = x""yes; then + AST_PRI_MCID_FOUND=yes +else + AST_PRI_MCID_FOUND=no +fi + + CFLAGS="${ast_ext_lib_check_save_CFLAGS}" + fi + + # now check for the header. + if test "${AST_PRI_MCID_FOUND}" = "yes"; then + PRI_MCID_LIB="${pbxlibdir} -lpri " + # if --with-PRI_MCID=DIR has been specified, use it. + if test "x${PRI_MCID_DIR}" != "x"; then + PRI_MCID_INCLUDE="-I${PRI_MCID_DIR}/include" + fi + PRI_MCID_INCLUDE="${PRI_MCID_INCLUDE} " + if test "xlibpri.h" = "x" ; then # no header, assume found + PRI_MCID_HEADER_FOUND="1" + else # check for the header + ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${PRI_MCID_INCLUDE}" + if test "${ac_cv_header_libpri_h+set}" = set; then + { $as_echo "$as_me:$LINENO: checking for libpri.h" >&5 +$as_echo_n "checking for libpri.h... " >&6; } +if test "${ac_cv_header_libpri_h+set}" = set; then + $as_echo_n "(cached) " >&6 +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5 +$as_echo "$ac_cv_header_libpri_h" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking libpri.h usability" >&5 +$as_echo_n "checking libpri.h usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <libpri.h> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking libpri.h presence" >&5 +$as_echo_n "checking libpri.h presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <libpri.h> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: libpri.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: libpri.h: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: libpri.h: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: libpri.h: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: libpri.h: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: libpri.h: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: libpri.h: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: libpri.h: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: libpri.h: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------- ## +## Report this to www.asterisk.org ## +## ------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for libpri.h" >&5 +$as_echo_n "checking for libpri.h... " >&6; } +if test "${ac_cv_header_libpri_h+set}" = set; then + $as_echo_n "(cached) " >&6 +else + ac_cv_header_libpri_h=$ac_header_preproc +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_libpri_h" >&5 +$as_echo "$ac_cv_header_libpri_h" >&6; } + +fi +if test "x$ac_cv_header_libpri_h" = x""yes; then + PRI_MCID_HEADER_FOUND=1 +else + PRI_MCID_HEADER_FOUND=0 +fi + + + CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}" + fi + if test "x${PRI_MCID_HEADER_FOUND}" = "x0" ; then + PRI_MCID_LIB="" + PRI_MCID_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + PRI_MCID_LIB="" + fi + PBX_PRI_MCID=1 + cat >>confdefs.h <<_ACEOF +#define HAVE_PRI_MCID 1 +_ACEOF + + fi + fi +fi + + + if test "x${PBX_PRI_CALL_WAITING}" != "x1" -a "${USE_PRI_CALL_WAITING}" != "no"; then pbxlibdir="" # if --with-PRI_CALL_WAITING=DIR has been specified, use it. diff --git a/configure.ac b/configure.ac index c0cc266263edb077c4eb8280f6136ec6a9447949..f5ac507e0f9bda71b4e14ed2a722988cf83c4e71 100644 --- a/configure.ac +++ b/configure.ac @@ -341,6 +341,7 @@ AST_EXT_LIB_SETUP([PGSQL], [PostgreSQL], [postgres]) AST_EXT_LIB_SETUP([POPT], [popt], [popt]) AST_EXT_LIB_SETUP([PORTAUDIO], [PortAudio], [portaudio]) AST_EXT_LIB_SETUP([PRI], [ISDN PRI], [pri]) +AST_EXT_LIB_SETUP_DEPENDENT([PRI_MCID], [ISDN PRI Malicious Call ID], [PRI], [pri]) AST_EXT_LIB_SETUP_DEPENDENT([PRI_CALL_WAITING], [ISDN PRI call waiting supplementary service], [PRI], [pri]) AST_EXT_LIB_SETUP_DEPENDENT([PRI_AOC_EVENTS], [ISDN PRI advice of charge supplementary service events], [PRI], [pri]) AST_EXT_LIB_SETUP_DEPENDENT([PRI_TRANSFER], [ISDN PRI call transfer supplementary service], [PRI], [pri]) @@ -1593,6 +1594,7 @@ AST_EXT_LIB_CHECK([POPT], [popt], [poptStrerror], [popt.h]) AST_EXT_LIB_CHECK([PORTAUDIO], [portaudio], [Pa_GetDeviceCount], [portaudio.h]) AST_EXT_LIB_CHECK([PRI], [pri], [pri_connected_line_update], [libpri.h]) +AST_EXT_LIB_CHECK([PRI_MCID], [pri], [pri_mcid_enable], [libpri.h]) AST_EXT_LIB_CHECK([PRI_CALL_WAITING], [pri], [pri_connect_ack_enable], [libpri.h]) AST_EXT_LIB_CHECK([PRI_AOC_EVENTS], [pri], [pri_aoc_events_enable], [libpri.h]) AST_EXT_LIB_CHECK([PRI_TRANSFER], [pri], [pri_transfer_enable], [libpri.h]) diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index fe13b2502287b8120d3ee4881b964061a7af327c..a97017a60a1916f964e0d1dbebdb5a3160a087f9 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -557,6 +557,9 @@ /* Define to 1 if you have the ISDN PRI set_inbanddisconnect library. */ #undef HAVE_PRI_INBANDDISCONNECT +/* Define to 1 if you have the ISDN PRI Malicious Call ID library. */ +#undef HAVE_PRI_MCID + /* Define to 1 if you have the ISDN progress with cause library. */ #undef HAVE_PRI_PROG_W_CAUSE diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index f5eaeeb1264725f72873e8ffe846247774dd5660..5cf0d11db6349d30148e70331e046f2191a9824e 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -2461,6 +2461,26 @@ void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct as */ void ast_party_subaddress_free(struct ast_party_subaddress *doomed); +/*! + * \brief Initialize the given party id structure. + * \since 1.8 + * + * \param init Party id structure to initialize. + * + * \return Nothing + */ +void ast_party_id_init(struct ast_party_id *init); + +/*! + * \brief Destroy the party id contents + * \since 1.8 + * + * \param doomed The party id to destroy. + * + * \return Nothing + */ +void ast_party_id_free(struct ast_party_id *doomed); + /*! * \since 1.8 * \brief Initialize the given caller structure. diff --git a/main/channel.c b/main/channel.c index 3057fae9d5c82beb89c15a171b1c31e6d5fd4f39..42d42fb1b0a43e0e511916c854e16e8dc4a5fb13 100644 --- a/main/channel.c +++ b/main/channel.c @@ -1652,15 +1652,7 @@ void ast_party_subaddress_free(struct ast_party_subaddress *doomed) } } -/*! - * \internal - * \brief Initialize the given party id structure. - * - * \param init Party id structure to initialize. - * - * \return Nothing - */ -static void ast_party_id_init(struct ast_party_id *init) +void ast_party_id_init(struct ast_party_id *init) { init->number = NULL; init->name = NULL; @@ -1775,15 +1767,7 @@ static void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_i ast_party_subaddress_set(&dest->subaddress, &src->subaddress); } -/*! - * \internal - * \brief Destroy the party id contents - * - * \param doomed The party id to destroy. - * - * \return Nothing - */ -static void ast_party_id_free(struct ast_party_id *doomed) +void ast_party_id_free(struct ast_party_id *doomed) { if (doomed->number) { ast_free(doomed->number);