Skip to content

Commit

Permalink
chan_dahdi: Fix buggy and missing Caller ID parameters
Browse files Browse the repository at this point in the history
There are several things wrong with analog Caller ID
handling that are fixed by this commit:

callerid.c's Caller ID generation function contains the
logic to use the presentation to properly send the proper
Caller ID. However, currently, DAHDI does not pass any
presentation information to the Caller ID module, which
means that presentation is completely ignored on all calls.
This means that lines could be getting Caller ID information
they aren't supposed to.

Part of the reason this has been obscured is because the
simple switch logic for handling the built in *67 and *82
is completely wrong. Rather than modifying the presentation
for the call accordingly (which is what it's supposed to do),
it simply blanks out the Caller ID or fills it in. This is
wrong, so wrong that it makes a mockery of the specification.
Additionally, it would leave to the "UNAVAILABLE" disposition
being used for Caller ID generation as opposed to the "PRIVATE"
disposition that it should have been using. This is now fixed
to only update the presentation and not modify the number and
name, so that the simple switch *67/*82 work correctly.

Next, sig_analog currently only copies over the name and number,
nothing else, when it is filling in a duplicated caller id
structure. Thus, we also now copy over the presentation
information so that is available for the Caller ID spill.
Additionally, this meant that "valid" was implicitly 0,
and as such presentation would always fail to "Unavailable".
The validity is therefore also copied over so it can be used
by ast_party_id_presentation.

As part of this fix, new API is added so that all the relevant
Caller ID information can be passed in to the Caller ID generation
functions. Parameters that are also completely missing from the
Caller ID spill have also been added, to enhance the compatibility,
correctness, and completeness of the Asterisk Caller ID implementation.

ASTERISK-29991 #close

Change-Id: Icc44a5e09979916f4c18a440f96e10dc1c76ae15
  • Loading branch information
InterLinked1 authored and gtjoseph committed Jul 14, 2022
1 parent be6a03f commit f2f397c
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 16 deletions.
14 changes: 12 additions & 2 deletions channels/chan_dahdi.c
Expand Up @@ -1642,19 +1642,29 @@ static int my_send_callerid(void *pvt, int cwcid, struct ast_party_caller *calle
}

if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
int pres = ast_party_id_presentation(&caller->id);
if (cwcid == 0) {
p->cidlen = ast_callerid_generate(p->cidspill,
p->cidlen = ast_callerid_full_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
NULL,
-1,
pres,
0,
CID_TYPE_MDMF,
AST_LAW(p));
} else {
ast_verb(3, "CPE supports Call Waiting Caller*ID. Sending '%s/%s'\n",
caller->id.name.str, caller->id.number.str);
p->callwaitcas = 0;
p->cidcwexpire = 0;
p->cidlen = ast_callerid_callwaiting_generate(p->cidspill,
p->cidlen = ast_callerid_callwaiting_full_generate(p->cidspill,
caller->id.name.str,
caller->id.number.str,
NULL,
-1,
pres,
0,
AST_LAW(p));
p->cidlen += READ_SIZE * 4;
}
Expand Down
13 changes: 8 additions & 5 deletions channels/sig_analog.c
Expand Up @@ -1089,6 +1089,10 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest
if (p->use_callerid) {
p->caller.id.name.str = p->lastcid_name;
p->caller.id.number.str = p->lastcid_num;
p->caller.id.name.valid = ast_channel_connected(ast)->id.name.valid;
p->caller.id.number.valid = ast_channel_connected(ast)->id.number.valid;
p->caller.id.name.presentation = ast_channel_connected(ast)->id.name.presentation;
p->caller.id.number.presentation = ast_channel_connected(ast)->id.number.presentation;
}

ast_setstate(ast, AST_STATE_RINGING);
Expand Down Expand Up @@ -2264,10 +2268,8 @@ static void *__analog_ss_thread(void *data)
ast_verb(3, "Disabling Caller*ID on %s\n", ast_channel_name(chan));
/* Disable Caller*ID if enabled */
p->hidecallerid = 1;
ast_party_number_free(&ast_channel_caller(chan)->id.number);
ast_party_number_init(&ast_channel_caller(chan)->id.number);
ast_party_name_free(&ast_channel_caller(chan)->id.name);
ast_party_name_init(&ast_channel_caller(chan)->id.name);
ast_channel_caller(chan)->id.number.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
ast_channel_caller(chan)->id.name.presentation = AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED;
res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
Expand Down Expand Up @@ -2353,7 +2355,8 @@ static void *__analog_ss_thread(void *data)
ast_verb(3, "Enabling Caller*ID on %s\n", ast_channel_name(chan));
/* Enable Caller*ID if enabled */
p->hidecallerid = 0;
ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
ast_channel_caller(chan)->id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
ast_channel_caller(chan)->id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
res = analog_play_tone(p, idx, ANALOG_TONE_DIALRECALL);
if (res) {
ast_log(LOG_WARNING, "Unable to do dial recall on channel %s: %s\n",
Expand Down
51 changes: 50 additions & 1 deletion include/asterisk/callerid.h
Expand Up @@ -55,6 +55,7 @@
#define CID_UNKNOWN_NUMBER (1 << 3)
#define CID_MSGWAITING (1 << 4)
#define CID_NOMSGWAITING (1 << 5)
#define CID_QUALIFIER (1 << 6)

#define CID_SIG_BELL 1
#define CID_SIG_V23 2
Expand All @@ -67,6 +68,12 @@
#define CID_START_POLARITY_IN 3
#define CID_START_DTMF_NOALERT 4

/* Caller ID message formats */
/*! SDMF - number only */
#define CID_TYPE_SDMF 0x00
/*! MDMF - name, number, etc. */
#define CID_TYPE_MDMF 0x01

/* defines dealing with message waiting indication generation */
/*! MWI SDMF format */
#define CID_MWI_TYPE_SDMF 0x00
Expand Down Expand Up @@ -101,7 +108,26 @@ void callerid_init(void);
* \return It returns the size
* (in bytes) of the data (if it returns a size of 0, there is probably an error)
*/
int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec);
int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec);

/*! \brief Generates a CallerID FSK stream in ulaw format suitable for transmission.
* \param buf Buffer to use. If "buf" is supplied, it will use that buffer instead of allocating its own.
* "buf" must be at least 32000 bytes in size of you want to be sure you don't have an overrun.
* \param number Use NULL for no number or "P" for "private"
* \param name name to be used
* \param ddn Dialable Directory Number (or NULL)
* \param redirecting Redirecting reason
* \param flags passed flags
* \param format Message format
* \param callwaiting callwaiting flag
* \param codec -- either AST_FORMAT_ULAW or AST_FORMAT_ALAW
* \details
* This function creates a stream of callerid (a callerid spill) data in ulaw format.
* \return It returns the size
* (in bytes) of the data (if it returns a size of 0, there is probably an error)
*/
int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting,
int flags, int format, int callwaiting, struct ast_format *codec);

/*! \brief Create a callerID state machine
* \param cid_signalling Type of signalling in use
Expand Down Expand Up @@ -177,6 +203,23 @@ void callerid_free(struct callerid_state *cid);
*/
int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec);

/*! \brief Generate Caller-ID spill from the "callerid" field of asterisk (in e-mail address like format)
* \param buf buffer for output samples. See callerid_generate() for details regarding buffer.
* \param name Caller-ID Name
* \param number Caller-ID Number
* \param ddn Dialable Directory Number (or NULL)
* \param redirecting Redirecting Reason (-1 if N/A)
* \param pres Presentation (0 for default)
* \param qualifier Call Qualifier (0 for no, 1 for yes)
* \param format Message Format
* \param codec Asterisk codec (either AST_FORMAT_ALAW or AST_FORMAT_ULAW)
*
* \details
* Like ast_callerid_generate but with additional parameters.
*/
int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number,
const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec);

/*!
* \brief Generate message waiting indicator
* \param buf
Expand All @@ -198,6 +241,12 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct
*/
int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec);

/*! \brief Generate Caller-ID spill but in a format suitable for Call Waiting(tm)'s Caller*ID(tm)
* \see ast_callerid_generate() for other details
*/
int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number,
const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec);

/*! \brief Destructively parse inbuf into name and location (or number)
* \details
* Parses callerid stream from inbuf and changes into useable form, outputted in name and location.
Expand Down
98 changes: 90 additions & 8 deletions main/callerid.c
Expand Up @@ -736,7 +736,8 @@ void callerid_free(struct callerid_state *cid)
ast_free(cid);
}

static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags)
static int callerid_genmsg(char *msg, int size, const char *number, const char *name, int flags, int format,
const char *ddn, int redirecting)
{
struct timeval now = ast_tvnow();
struct ast_tm tm;
Expand All @@ -754,6 +755,7 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char *
tm.tm_mday, tm.tm_hour, tm.tm_min);
size -= res;
ptr += res;

if (ast_strlen_zero(number) || (flags & CID_UNKNOWN_NUMBER)) {
/* Indicate number not known */
res = snprintf(ptr, size, "\004\001O");
Expand All @@ -779,6 +781,11 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char *
size -= i;
}

if (format == CID_TYPE_SDMF) { /* If Simple Data Message Format, we're done. */
/* (some older Caller ID units only support SDMF. If they get an MDMF spill, it's useless.) */
return (ptr - msg);
}

if (ast_strlen_zero(name) || (flags & CID_UNKNOWN_NAME)) {
/* Indicate name not known */
res = snprintf(ptr, size, "\010\001O");
Expand All @@ -803,8 +810,44 @@ static int callerid_genmsg(char *msg, int size, const char *number, const char *
ptr += i;
size -= i;
}
return (ptr - msg);

/* Call Qualifier */
if (flags & CID_QUALIFIER) {
res = snprintf(ptr, size, "\006\001L"); /* LDC (Long Distance Call) is the only valid option */
size -= res;
ptr += res;
}

/* DDN (Dialable Directory Number) - 11 digits MAX, parameter 003 */
/* some CPE seem to display the DDN instead of the CLID, if sent */

/* Redirecting Reason */
if (redirecting >= 0) {
res = 0;
switch (redirecting) {
case AST_REDIRECTING_REASON_USER_BUSY:
res = snprintf(ptr, size, "\005\001\001");
break;
case AST_REDIRECTING_REASON_NO_ANSWER:
res = snprintf(ptr, size, "\005\001\002");
break;
case AST_REDIRECTING_REASON_UNCONDITIONAL:
res = snprintf(ptr, size, "\005\001\003");
break;
case AST_REDIRECTING_REASON_CALL_FWD_DTE:
res = snprintf(ptr, size, "\005\001\004");
break;
case AST_REDIRECTING_REASON_DEFLECTION:
res = snprintf(ptr, size, "\005\001\005");
break;
default:
break;
}
ptr += res;
size -= res;
}

return (ptr - msg);
}

int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct ast_format *codec,
Expand All @@ -824,7 +867,7 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct
msg[0] = 0x82;

/* put date, number info at the right place */
len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags);
len = callerid_genmsg(msg+2, sizeof(msg)-2, number, name, flags, CID_TYPE_MDMF, "", -1);

/* length of MDMF CLI plus Message Waiting Structure */
msg[1] = len+3;
Expand Down Expand Up @@ -896,6 +939,12 @@ int ast_callerid_vmwi_generate(unsigned char *buf, int active, int type, struct
}

int callerid_generate(unsigned char *buf, const char *number, const char *name, int flags, int callwaiting, struct ast_format *codec)
{
return callerid_full_generate(buf, number, name, NULL, -1, flags, CID_TYPE_MDMF, callwaiting, codec);
}

int callerid_full_generate(unsigned char *buf, const char *number, const char *name, const char *ddn, int redirecting,
int flags, int format, int callwaiting, struct ast_format *codec)
{
int bytes = 0;
int x, sum;
Expand All @@ -906,7 +955,7 @@ int callerid_generate(unsigned char *buf, const char *number, const char *name,
float ci = 0.0;
float scont = 0.0;
char msg[256];
len = callerid_genmsg(msg, sizeof(msg), number, name, flags);
len = callerid_genmsg(msg, sizeof(msg), number, name, flags, format, ddn, redirecting);
if (!callwaiting) {
/* Wait a half a second */
for (x = 0; x < 4000; x++)
Expand Down Expand Up @@ -1051,23 +1100,56 @@ int ast_callerid_parse(char *input_str, char **name, char **location)
return 0;
}

static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number, int callwaiting, struct ast_format *codec)
static int __ast_callerid_generate(unsigned char *buf, const char *name, const char *number,
const char *ddn, int redirecting, int pres, int qualifier, int format, int callwaiting, struct ast_format *codec)
{
int flags = 0;

ast_debug(1, "Caller ID Type %s: Number: %s, Name: %s, Redirecting No: %s, Redirecting Reason: %s, Pres: %s, Qualifier: %s, Format: %s\n",
callwaiting ? "II" : "I", number, name, ddn, ast_redirecting_reason_describe(redirecting),
ast_named_caller_presentation(pres), qualifier ? "LDC" : "None", format == CID_TYPE_MDMF ? "MDMF" : "SDMF");

if (ast_strlen_zero(name))
name = NULL;
if (ast_strlen_zero(number))
number = NULL;
return callerid_generate(buf, number, name, 0, callwaiting, codec);

if (pres & AST_PRES_RESTRICTED) {
flags |= CID_PRIVATE_NUMBER;
flags |= CID_PRIVATE_NAME;
} else if (pres & AST_PRES_UNAVAILABLE) {
flags |= CID_UNKNOWN_NUMBER;
flags |= CID_UNKNOWN_NAME;
}

if (qualifier) {
flags |= CID_QUALIFIER;
}

return callerid_full_generate(buf, number, name, ddn, redirecting, flags, format, callwaiting, codec);
}

int ast_callerid_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
{
return __ast_callerid_generate(buf, name, number, 0, codec);
return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 0, codec);
}

int ast_callerid_callwaiting_generate(unsigned char *buf, const char *name, const char *number, struct ast_format *codec)
{
return __ast_callerid_generate(buf, name, number, 1, codec);
return __ast_callerid_generate(buf, name, number, "", -1, 0, 0, CID_TYPE_MDMF, 1, codec);
}

int ast_callerid_full_generate(unsigned char *buf, const char *name, const char *number,
const char *ddn, int redirecting, int pres, int qualifier, int format, struct ast_format *codec)
{
return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, format, 0, codec);
}

int ast_callerid_callwaiting_full_generate(unsigned char *buf, const char *name, const char *number,
const char *ddn, int redirecting, int pres, int qualifier, struct ast_format *codec)
{
/* Type II Caller ID (CWCID) only uses MDMF, so format isn't an argument */
return __ast_callerid_generate(buf, name, number, ddn, redirecting, pres, qualifier, CID_TYPE_MDMF, 1, codec);
}

char *ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Expand Down

0 comments on commit f2f397c

Please sign in to comment.