[Asterisk-code-review] chan_dahdi: Fix buggy and missing Caller ID parameters (asterisk[19])

Friendly Automation asteriskteam at digium.com
Thu Jul 14 07:11:26 CDT 2022


Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/18804 )

Change subject: chan_dahdi: Fix buggy and missing Caller ID parameters
......................................................................

chan_dahdi: Fix buggy and missing Caller ID parameters

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
---
M channels/chan_dahdi.c
M channels/sig_analog.c
M include/asterisk/callerid.h
M main/callerid.c
4 files changed, 160 insertions(+), 16 deletions(-)

Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit



diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 38290b0..e6f8c62 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -1613,19 +1613,29 @@
 	}
 
 	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;
 		}
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index bd16d35..76ee645 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -1089,6 +1089,10 @@
 		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);
@@ -2264,10 +2268,8 @@
 				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",
@@ -2353,7 +2355,8 @@
 				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",
diff --git a/include/asterisk/callerid.h b/include/asterisk/callerid.h
index 460f105..16a3df1 100644
--- a/include/asterisk/callerid.h
+++ b/include/asterisk/callerid.h
@@ -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
@@ -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
@@ -101,7 +108,26 @@
  * \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
@@ -177,6 +203,23 @@
  */
 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
@@ -198,6 +241,12 @@
  */
 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.
diff --git a/main/callerid.c b/main/callerid.c
index 4d6186b..c6c29a0 100644
--- a/main/callerid.c
+++ b/main/callerid.c
@@ -736,7 +736,8 @@
 	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;
@@ -754,6 +755,7 @@
 				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");
@@ -779,6 +781,11 @@
 		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");
@@ -803,8 +810,44 @@
 		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,
@@ -824,7 +867,7 @@
 		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;
@@ -897,6 +940,12 @@
 
 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;
 	int len;
@@ -906,7 +955,7 @@
 	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++)
@@ -1051,23 +1100,56 @@
 	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)

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/18804
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 19
Gerrit-Change-Id: Icc44a5e09979916f4c18a440f96e10dc1c76ae15
Gerrit-Change-Number: 18804
Gerrit-PatchSet: 2
Gerrit-Owner: N A <mail at interlinked.x10host.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220714/b2977160/attachment-0001.html>


More information about the asterisk-code-review mailing list