diff --git a/CHANGES b/CHANGES
index 4c3d8dbfc47bda8d720784f999a9caddf941f153..ad16a4008ffdf9012033b0e2afc86c04cbb10b74 100644
--- a/CHANGES
+++ b/CHANGES
@@ -68,6 +68,12 @@ app_originate
    created channel using options parameter (like app_dial) B() and b().  This
    allows for adding variables to newly created channel or, e.g. setting callerid.
 
+CLI Commands
+------------------
+ * 'dialplan show' output will now show [config_file:line_number] instead of
+   [registrar] when that information is available. Currently only extensions
+   registered by pbx_config when loading/reloading will use this format.
+
 ------------------------------------------------------------------------------
 --- Functionality changes from Asterisk 14.2.0 to Asterisk 14.3.0 ------------
 ------------------------------------------------------------------------------
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 00ca4acbefd0d1ec723336db36a28d9ccb501cde..386f3c38bc948a666a4f2efe8dedec24bc6bd95c 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -505,11 +505,15 @@ int ast_add_extension(const char *context, int replace, const char *extension,
 /*!
  * \brief Add an extension to an extension context, this time with an ast_context *.
  *
- * \note For details about the arguments, check ast_add_extension()
+ * \param registrar_file optional configuration file that defines this extension
+ * \param registrar_line optional line number of configuration file that defines extension
+ *
+ * \note For details about the other arguments, check ast_add_extension()
  */
 int ast_add_extension2(struct ast_context *con, int replace, const char *extension,
 	int priority, const char *label, const char *callerid,
-	const char *application, void *data, void (*datad)(void *), const char *registrar);
+	const char *application, void *data, void (*datad)(void *), const char *registrar,
+	const char *registrar_file, int registrar_line);
 
 /*!
  * \brief Same as ast_add_extension2, but assumes you have already locked context
@@ -520,7 +524,8 @@ int ast_add_extension2(struct ast_context *con, int replace, const char *extensi
  */
 int ast_add_extension2_nolock(struct ast_context *con, int replace, const char *extension,
 	int priority, const char *label, const char *callerid,
-	const char *application, void *data, void (*datad)(void *), const char *registrar);
+	const char *application, void *data, void (*datad)(void *), const char *registrar,
+	const char *registrar_file, int registrar_line);
 
 /*!
  * \brief Map devstate to an extension state.
@@ -1266,6 +1271,23 @@ const char *ast_get_ignorepat_registrar(const struct ast_ignorepat *ip);
 const char *ast_get_switch_registrar(const struct ast_sw *sw);
 /*! @} */
 
+/*!
+ * \brief Get name of configuration file used by registrar to register this extension
+ *
+ * \retval NULL if registrar did not indicate config file when registering the extension
+ * \retval name of the file used to register the extension
+ */
+const char *ast_get_extension_registrar_file(struct ast_exten *e);
+
+/*!
+ * \brief Get line number of configuration file used by registrar to register this extension
+ *
+ * \retval 0 if the line wasn't indicated when the extension was registered
+ * \retval positive integer indicating what line in the config file was responsible for
+ *         registering the extension.
+ */
+int ast_get_extension_registrar_line(struct ast_exten *e);
+
 /*! @name Walking functions ... */
 /*! @{ */
 struct ast_context *ast_walk_contexts(struct ast_context *con);
diff --git a/main/pbx.c b/main/pbx.c
index 208c2308b952b7685917e1a36748ed29eb47d950..3e35a3a14c52cc0174440713de24ce964fa3b030 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -251,6 +251,8 @@ struct ast_exten {
 	struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
 	struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
 	const char *registrar;		/*!< Registrar */
+	const char *registrar_file;     /*!< File name used to register extension */
+	int registrar_line;             /*!< Line number the extension was registered in text */
 	struct ast_exten *next;		/*!< Extension with a greater ID */
 	char stuff[0];
 };
@@ -650,7 +652,8 @@ static int ast_add_extension_nolock(const char *context, int replace, const char
 static int ast_add_extension2_lockopt(struct ast_context *con,
 	int replace, const char *extension, int priority, const char *label, const char *callerid,
 	const char *application, void *data, void (*datad)(void *),
-	const char *registrar, int lock_context);
+	const char *registrar, const char *registrar_file, int registrar_line,
+	int lock_context);
 static struct ast_context *find_context_locked(const char *context);
 static struct ast_context *find_context(const char *context);
 static void get_device_state_causing_channels(struct ao2_container *c);
@@ -5438,6 +5441,21 @@ static void print_ext(struct ast_exten *e, char * buf, int buflen)
 	}
 }
 
+/*! \brief Writes CLI output of a single extension for show dialplan */
+static void show_dialplan_helper_extension_output(int fd, char *buf1, char *buf2, struct ast_exten *exten)
+{
+	if (ast_get_extension_registrar_file(exten)) {
+		ast_cli(fd, "  %-17s %-45s [%s:%d]\n",
+			buf1, buf2,
+			ast_get_extension_registrar_file(exten),
+			ast_get_extension_registrar_line(exten));
+		return;
+	}
+
+	ast_cli(fd, "  %-17s %-45s [%s]\n",
+		buf1, buf2, ast_get_extension_registrar(exten));
+}
+
 /* XXX not verified */
 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, const struct ast_include *rinclude, int includecount, const char *includes[])
 {
@@ -5515,8 +5533,7 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
 
 			print_ext(e, buf2, sizeof(buf2));
 
-			ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
-				ast_get_extension_registrar(e));
+			show_dialplan_helper_extension_output(fd, buf, buf2, e);
 
 			dpc->total_exten++;
 			/* walk next extension peers */
@@ -5530,8 +5547,7 @@ static int show_dialplan_helper(int fd, const char *context, const char *exten,
 					buf[0] = '\0';
 				print_ext(p, buf2, sizeof(buf2));
 
-				ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
-					ast_get_extension_registrar(p));
+				show_dialplan_helper_extension_output(fd, buf, buf2, p);
 			}
 		}
 
@@ -6356,7 +6372,8 @@ static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *
 				dupdstr = ast_strdup(prio_item->data);
 
 				res1 = ast_add_extension2(new, 0, prio_item->name, prio_item->priority, prio_item->label,
-										  prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar);
+										  prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, ast_free_ptr, prio_item->registrar,
+										  prio_item->registrar_file, prio_item->registrar_line);
 				if (!res1 && new_exten_item && new_prio_item){
 					ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
 							context->name, prio_item->name, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
@@ -6867,7 +6884,7 @@ static int ast_add_extension_nolock(const char *context, int replace, const char
 	c = find_context(context);
 	if (c) {
 		ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
-			application, data, datad, registrar, 1);
+			application, data, datad, registrar, NULL, 0, 1);
 	}
 
 	return ret;
@@ -6887,7 +6904,7 @@ int ast_add_extension(const char *context, int replace, const char *extension,
 	c = find_context_locked(context);
 	if (c) {
 		ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
-			application, data, datad, registrar);
+			application, data, datad, registrar, NULL, 0);
 		ast_unlock_contexts();
 	}
 
@@ -7190,19 +7207,19 @@ static int add_priority(struct ast_context *con, struct ast_exten *tmp,
 int ast_add_extension2(struct ast_context *con,
 	int replace, const char *extension, int priority, const char *label, const char *callerid,
 	const char *application, void *data, void (*datad)(void *),
-	const char *registrar)
+	const char *registrar, const char *registrar_file, int registrar_line)
 {
 	return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
-		application, data, datad, registrar, 1);
+		application, data, datad, registrar, registrar_file, registrar_line, 1);
 }
 
 int ast_add_extension2_nolock(struct ast_context *con,
 	int replace, const char *extension, int priority, const char *label, const char *callerid,
 	const char *application, void *data, void (*datad)(void *),
-	const char *registrar)
+	const char *registrar, const char *registrar_file, int registrar_line)
 {
 	return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
-		application, data, datad, registrar, 0);
+		application, data, datad, registrar, registrar_file, registrar_line, 0);
 }
 
 
@@ -7216,7 +7233,7 @@ int ast_add_extension2_nolock(struct ast_context *con,
 static int ast_add_extension2_lockopt(struct ast_context *con,
 	int replace, const char *extension, int priority, const char *label, const char *callerid,
 	const char *application, void *data, void (*datad)(void *),
-	const char *registrar, int lock_context)
+	const char *registrar, const char *registrar_file, int registrar_line, int lock_context)
 {
 	/*
 	 * Sort extensions (or patterns) according to the rules indicated above.
@@ -7287,6 +7304,9 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
 	} else {
 		length ++;	/* just the '\0' */
 	}
+	if (registrar_file) {
+		length += strlen(registrar_file) + 1;
+	}
 
 	/* Be optimistic:  Build the extension structure first */
 	if (!(tmp = ast_calloc(1, length)))
@@ -7326,12 +7346,22 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
 		*p++ = '\0';
 		tmp->matchcid = AST_EXT_MATCHCID_OFF;
 	}
+
+	if (registrar_file) {
+		tmp->registrar_file = p;
+		strcpy(p, registrar_file);
+		p += strlen(registrar_file) + 1;
+	} else {
+		tmp->registrar_file = NULL;
+	}
+
 	tmp->app = p;
 	strcpy(p, application);
 	tmp->parent = con;
 	tmp->data = data;
 	tmp->datad = datad;
 	tmp->registrar = registrar;
+	tmp->registrar_line = registrar_line;
 
 	if (lock_context) {
 		ast_wrlock_context(con);
@@ -8485,6 +8515,16 @@ const char *ast_get_extension_registrar(struct ast_exten *e)
 	return e ? e->registrar : NULL;
 }
 
+const char *ast_get_extension_registrar_file(struct ast_exten *e)
+{
+	return e ? e->registrar_file : NULL;
+}
+
+int ast_get_extension_registrar_line(struct ast_exten *e)
+{
+	return e ? e->registrar_line : 0;
+}
+
 int ast_get_extension_matchcid(struct ast_exten *e)
 {
 	return e ? e->matchcid : 0;
diff --git a/pbx/pbx_config.c b/pbx/pbx_config.c
index 384bbc7c3297c08ba1108c983c4670df5dd3bcb5..b96914dedd39f06196c2832a2c643b2923a6b0cb 100644
--- a/pbx/pbx_config.c
+++ b/pbx/pbx_config.c
@@ -1240,7 +1240,7 @@ static int manager_dialplan_extension_add(struct mansession *s, const struct mes
 	}
 
 	if (ast_add_extension2(add_context, replace, exten, ipriority, NULL, cidmatch,
-			application, ast_strdup(application_data), ast_free_ptr, registrar)) {
+			application, ast_strdup(application_data), ast_free_ptr, registrar, NULL, 0)) {
 		ast_unlock_contexts();
 		switch (errno) {
 		case ENOMEM:
@@ -1855,6 +1855,7 @@ process_extension:
 
 				appl = ast_skip_blanks(appl);
 				if (ipri) {
+					const char *registrar_file;
 					if (plus) {
 						ipri += atoi(plus);
 					}
@@ -1864,7 +1865,14 @@ process_extension:
 							"The use of '%s' for an extension is strongly discouraged and can have unexpected behavior.  Please use '_X%c' instead at line %d of %s\n",
 							realext, realext[1], v->lineno, vfile);
 					}
-					if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, ast_strdup(data), ast_free_ptr, registrar)) {
+					/* Don't include full path if the configuration file includes slashes */
+					registrar_file = strrchr(vfile, '/');
+					if (!registrar_file) {
+						registrar_file = vfile;
+					} else {
+						registrar_file++; /* Skip past the end slash */
+					}
+					if (ast_add_extension2(con, 0, realext, ipri, label, cidmatch, appl, ast_strdup(data), ast_free_ptr, registrar, registrar_file, v->lineno)) {
 						ast_log(LOG_WARNING,
 							"Unable to register extension at line %d of %s\n",
 							v->lineno, vfile);
@@ -2031,19 +2039,19 @@ static void pbx_load_users(void)
 			}
 
 			/* Add hint */
-			ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar);
+			ast_add_extension2(con, 0, cat, -1, NULL, NULL, iface, NULL, NULL, registrar, NULL, 0);
 			/* If voicemail, use "stdexten" else use plain old dial */
 			if (hasvoicemail) {
 				if (ast_opt_stdexten_macro) {
 					/* Use legacy stdexten macro method. */
 					snprintf(tmp, sizeof(tmp), "stdexten,%s,${HINT}", cat);
-					ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", ast_strdup(tmp), ast_free_ptr, registrar);
+					ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Macro", ast_strdup(tmp), ast_free_ptr, registrar, NULL, 0);
 				} else {
 					snprintf(tmp, sizeof(tmp), "%s,stdexten(${HINT})", cat);
-					ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Gosub", ast_strdup(tmp), ast_free_ptr, registrar);
+					ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Gosub", ast_strdup(tmp), ast_free_ptr, registrar, NULL, 0);
 				}
 			} else {
-				ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", ast_strdup("${HINT}"), ast_free_ptr, registrar);
+				ast_add_extension2(con, 0, cat, 1, NULL, NULL, "Dial", ast_strdup("${HINT}"), ast_free_ptr, registrar, NULL, 0);
 			}
 			altexts = ast_variable_retrieve(cfg, cat, "alternateexts");
 			if (!ast_strlen_zero(altexts)) {
@@ -2052,7 +2060,7 @@ static void pbx_load_users(void)
 				c = altcopy;
 				ext = strsep(&c, ",");
 				while (ext) {
-					ast_add_extension2(con, 0, ext, 1, NULL, NULL, "Goto", ast_strdup(tmp), ast_free_ptr, registrar);
+					ast_add_extension2(con, 0, ext, 1, NULL, NULL, "Goto", ast_strdup(tmp), ast_free_ptr, registrar, NULL, 0);
 					ext = strsep(&c, ",");
 				}
 			}
diff --git a/pbx/pbx_lua.c b/pbx/pbx_lua.c
index 0754990d673cf1d697cbbf06fb0f0df93b786181..088b160b4ee5b5aec03df44348101a980ad10b77 100644
--- a/pbx/pbx_lua.c
+++ b/pbx/pbx_lua.c
@@ -1026,7 +1026,7 @@ static int lua_register_hints(lua_State *L)
 				continue;
 			}
 
-			if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar)) {
+			if (ast_add_extension2(con, 0, hint_name, PRIORITY_HINT, NULL, NULL, hint_value, NULL, NULL, registrar, NULL, 0)) {
 				/* remove hints table, hint name, hint value,
 				 * key copy, context name, and contex table */
 				lua_pop(L, 6);
diff --git a/res/ael/pval.c b/res/ael/pval.c
index 6803ab634ee8d2b6c12a1ff93b52075dd0954ffb..b0a04fe2f0b70c422e1ec3e2e9fe35fffed6c691 100644
--- a/res/ael/pval.c
+++ b/res/ael/pval.c
@@ -4234,7 +4234,7 @@ void add_extensions(struct ael_extension *exten)
 		pbx_substitute_variables_helper(NULL, exten->name, realext, sizeof(realext) - 1);
 		if (exten->hints) {
 			if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, PRIORITY_HINT, NULL, exten->cidmatch, 
-								  exten->hints, NULL, ast_free_ptr, registrar)) {
+								  exten->hints, NULL, ast_free_ptr, registrar, NULL, 0)) {
 				ast_log(LOG_WARNING, "Unable to add step at priority 'hint' of extension '%s'\n",
 						exten->name);
 			}
@@ -4314,7 +4314,7 @@ void add_extensions(struct ael_extension *exten)
 				label = 0;
 			
 			if (ast_add_extension2(exten->context, 0 /*no replace*/, realext, pr->priority_num, (label?label:NULL), exten->cidmatch, 
-								  app, strdup(appargs), ast_free_ptr, registrar)) {
+								  app, strdup(appargs), ast_free_ptr, registrar, NULL, 0)) {
 				ast_log(LOG_WARNING, "Unable to add step at priority '%d' of extension '%s'\n", pr->priority_num, 
 						exten->name);
 			}
diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c
index 3fa7e42b31ecd9bc0d5894f70f1f24378fa5bdcc..2770233332b65a2fb1bc212739beddd79f4630d1 100644
--- a/res/parking/parking_bridge_features.c
+++ b/res/parking/parking_bridge_features.c
@@ -633,7 +633,7 @@ static int parking_duration_callback(struct ast_bridge_channel *bridge_channel,
 		ast_debug(3, "An extension for '%s@%s' was already registered by another registrar '%s'\n",
 			dial_string_flat, PARK_DIAL_CONTEXT, ast_get_extension_registrar(existing_exten));
 	} else if (ast_add_extension2_nolock(park_dial_context, 1, dial_string_flat, 1, NULL, NULL,
-			"Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR)) {
+			"Dial", duplicate_returnexten, ast_free_ptr, BASE_REGISTRAR, NULL, 0)) {
 			ast_free(duplicate_returnexten);
 		ast_log(LOG_ERROR, "Failed to create parking redial parker extension %s@%s - Dial(%s)\n",
 			dial_string_flat, PARK_DIAL_CONTEXT, returnexten);
diff --git a/res/res_parking.c b/res/res_parking.c
index 171fdce61524cb0f7fe3121a5c1bdd7c49102e0a..94cdb0e6d7844923e7f070ef694126c981d2b266 100644
--- a/res/res_parking.c
+++ b/res/res_parking.c
@@ -721,7 +721,7 @@ static int parking_add_extension(struct ast_context *context, int replace, const
 	}
 
 	if (ast_add_extension2_nolock(context, replace, extension, priority, NULL, NULL,
-			application, data_duplicate, ast_free_ptr, registrar)) {
+			application, data_duplicate, ast_free_ptr, registrar, NULL, 0)) {
 		ast_free(data_duplicate);
 		return -1;
 	}
diff --git a/res/res_pjsip_config_wizard.c b/res/res_pjsip_config_wizard.c
index 2441184a24350b660475ea575d6e3b04b3c5fe47..83e282821f1cb8db60f9fbe1e7e5684d1c9344a1 100644
--- a/res/res_pjsip_config_wizard.c
+++ b/res/res_pjsip_config_wizard.c
@@ -461,7 +461,7 @@ static int add_extension(struct ast_context *context, const char *exten,
 	}
 
 	if (ast_add_extension2_nolock(context, 0, exten, priority, NULL, NULL,
-			app, data, free_ptr, BASE_REGISTRAR)) {
+			app, data, free_ptr, BASE_REGISTRAR, NULL, 0)) {
 		ast_free(data);
 		return -1;
 	}
diff --git a/utils/conf2ael.c b/utils/conf2ael.c
index 1767d983337369169ab7382c3d959b174c49bcfb..5fdc570a0207454f5a1c7e171c1a32fa43c23050 100644
--- a/utils/conf2ael.c
+++ b/utils/conf2ael.c
@@ -561,7 +561,7 @@ void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char
 int ast_add_extension2(struct ast_context *con,
 					   int replace, const char *extension, int priority, const char *label, const char *callerid,
 					   const char *application, void *data, void (*datad)(void *),
-					   const char *registrar)
+					   const char *registrar, const char *registrar_file, int registrar_line)
 {
 	return localized_add_extension2(con, replace, extension, priority, label, callerid, application, data, datad, registrar);
 }