diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index deca8f3de5fa8e0a05c4d0feeb7067761d0270c0..7fb5f6fea47f6faee7c78ed835634a5eeeea8ccd 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -169,17 +169,30 @@ static int pickup_by_channel(struct ast_channel *chan, char *pickup)
 	return res;
 }
 
+struct pickup_criteria {
+	const char *exten;
+	const char *context;
+};
+
+static int find_by_exten(struct ast_channel *c, void *data)
+{
+	struct pickup_criteria *info = data;
+
+	return (!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
+		!strcasecmp(c->dialcontext, info->context) &&
+		can_pickup(c);
+}
+
 /* Attempt to pick up specified extension with context */
 static int pickup_by_exten(struct ast_channel *chan, const char *exten, const char *context)
 {
-	auto int find_by_exten(struct ast_channel *c);
-	int find_by_exten(struct ast_channel *c) {
-		return (!strcasecmp(c->macroexten, exten) || !strcasecmp(c->exten, exten)) &&
-			!strcasecmp(c->dialcontext, context) &&
-			can_pickup(c);
-	}
+	struct ast_channel *target = NULL;
+	struct pickup_criteria search = {
+		.exten = exten,
+		.context = context,
+	};
 
-	struct ast_channel *target = ast_channel_search_locked(find_by_exten);
+	target = ast_channel_search_locked(find_by_exten, &search);
 
 	if (target) {
 		int res = pickup_do(chan, target);
@@ -191,18 +204,20 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
 	return -1;
 }
 
+static int find_by_mark(struct ast_channel *c, void *data)
+{
+	const char *mark = data;
+	const char *tmp;
+
+	return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
+		!strcasecmp(tmp, mark) &&
+		can_pickup(c);
+}
+
 /* Attempt to pick up specified mark */
 static int pickup_by_mark(struct ast_channel *chan, const char *mark)
 {
-	auto int find_by_mark(struct ast_channel *);
-	int find_by_mark(struct ast_channel *c) {
-		const char *tmp;
-		return (tmp = pbx_builtin_getvar_helper(c, PICKUPMARK)) &&
-			!strcasecmp(tmp, mark) &&
-			can_pickup(c);
-	}	
-
-	struct ast_channel *target = ast_channel_search_locked(find_by_mark);
+	struct ast_channel *target = ast_channel_search_locked(find_by_mark, (char *) mark);
 
 	if (target) {
 		int res = pickup_do(chan, target);
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 06d8d6f3ce9e2effe8084769edf9128fca03edd4..d3d79fd08686abd6e36b12426d0be6a1d0e1454c 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -4421,6 +4421,26 @@ static struct sip_peer *realtime_peer(const char *newpeername, struct sockaddr_i
 	return peer;
 }
 
+/* Function to assist finding peers by name only */
+static int find_by_name(void *obj, void *arg, void *data, int flags)
+{
+	struct sip_peer *search = obj, *match = arg;
+	int *forcenamematch = data;
+
+	/* Usernames in SIP uri's are case sensitive. Domains are not */
+	if (strcmp(search->name, match->name)) {
+		return 0;
+	}
+
+	/* If we're only looking for name matches, we should avoid type=peer devices,
+	   since these should not match on any name-based search */
+	if (*forcenamematch && search->onlymatchonip) {
+		return 0;
+	}
+
+	return CMP_MATCH | CMP_STOP;
+}
+
 /*! \brief Locate device by name or ip address 
  *	This is used on find matching device on name or ip/port.
 	If the device was declared as type=peer, we don't match on peer name on incoming INVITEs.
@@ -4433,31 +4453,10 @@ static struct sip_peer *find_peer(const char *peer, struct sockaddr_in *sin, int
 {
 	struct sip_peer *p = NULL;
 	struct sip_peer tmp_peer;
-	
-	/* Inline function to assist finding peers by name only */
-	auto int find_by_name(void *obj, void *arg, void *data, int flags);
-
-	int find_by_name(void *obj, void *arg, void *data, int flags)
-	{
-		struct sip_peer *search = obj, *match = arg;
-
-		/* Usernames in SIP uri's are case sensitive. Domains are not */
-		if (strcmp(search->name, match->name)) {
-			return 0;
-		}
-
-		/* If we're only looking for name matches, we should avoid type=peer devices,
-		   since these should not match on any name-based search */
-		if (forcenamematch && search->onlymatchonip) {
-			return 0;
-		}
-
-		return CMP_MATCH | CMP_STOP;
-	}
 
 	if (peer) {
 		ast_copy_string(tmp_peer.name, peer, sizeof(tmp_peer.name));
-		p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &tmp_peer, NULL, "ao2_find in peers table");
+		p = ao2_t_callback(peers, OBJ_POINTER, find_by_name, &tmp_peer, &forcenamematch, "ao2_find in peers table");
 	} else if (sin) { /* search by addr? */
 		tmp_peer.addr.sin_addr.s_addr = sin->sin_addr.s_addr;
 		tmp_peer.addr.sin_port = sin->sin_port;
@@ -9870,10 +9869,23 @@ static int __sip_subscribe_mwi_do(struct sip_subscription_mwi *mwi)
 	
 	/* Actually send the packet */
 	transmit_invite(mwi->call, SIP_SUBSCRIBE, 0, 2);
-	
+
 	return 0;
 }
 
+struct caller_criteria {
+	const char *exten;
+	const char *context;
+};
+
+static int find_calling_channel(struct ast_channel *c, void *data) {
+	struct caller_criteria *info = data;
+
+	return (c->pbx &&
+			(!strcasecmp(c->macroexten, info->exten) || !strcasecmp(c->exten, info->exten)) &&
+			!strcasecmp(c->context, info->context));
+}
+
 /*! \brief Used in the SUBSCRIBE notification subsystem (RFC3265) */
 static int transmit_state_notify(struct sip_pvt *p, int state, int full, int timeout)
 {
@@ -10039,14 +10051,13 @@ static int transmit_state_notify(struct sip_pvt *p, int state, int full, int tim
 			   callee must be dialing the same extension that is being monitored.  Simply dialing
 			   the hint'd device is not sufficient. */
 			if (global_notifycid) {
-				auto int find_calling_channel(struct ast_channel *c);
-				int find_calling_channel(struct ast_channel *c) {
-					return (c->pbx &&
-							(!strcasecmp(c->macroexten, p->exten) || !strcasecmp(c->exten, p->exten)) &&
-							!strcasecmp(c->context, p->context));
-				}
+				struct ast_channel *caller = NULL;
+				struct caller_criteria data = {
+					.exten = p->exten,
+					.context = p->context,
+				};
 
-				struct ast_channel *caller = ast_channel_search_locked(find_calling_channel);
+				caller = ast_channel_search_locked(find_calling_channel, &data);
 
 				if (caller) {
 					local_display = ast_strdupa(caller->cid.cid_name);
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index c1423462eba93effe12899a9bdb6f766f1df8323..64aaca069dda47a71010a8e237b21db68892a8e6 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1185,9 +1185,10 @@ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *c
  * return 0 if there is no match, and non-zero if there is.
  * \param is_match callback executed on each channel until non-zero is returned, or we
  *        run out of channels to search.
+ * \param data data passed to the is_match callback during each invocation.
  * \return Returns the matched channel, or NULL if no channel was matched.
  */
-struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *));
+struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data);
 
 /*! ! \brief Waits for a digit
  * \param c channel to wait for a digit on
diff --git a/main/channel.c b/main/channel.c
index ec253ae0466f19de1e3b9680dec973c2471a81d0..b5a4054a4589ffff400288fdb9dc7dc326bbeb8b 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -1227,14 +1227,14 @@ struct ast_channel *ast_walk_channel_by_exten_locked(const struct ast_channel *c
 }
 
 /*! \brief Search for a channel based on the passed channel matching callback (first match) and return it, locked */
-struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *))
+struct ast_channel *ast_channel_search_locked(int (*is_match)(struct ast_channel *, void *), void *data)
 {
 	struct ast_channel *c = NULL;
 
 	AST_RWLIST_RDLOCK(&channels);
 	AST_RWLIST_TRAVERSE(&channels, c, chan_list) {
 		ast_channel_lock(c);
-		if (is_match(c)) {
+		if (is_match(c, data)) {
 			break;
 		}
 		ast_channel_unlock(c);
diff --git a/main/features.c b/main/features.c
index ed13ee4fc74fc50a38dcce52568d860b15688e85..932f1b8a122ec878ef56154c0e1dcac10d4300c3 100644
--- a/main/features.c
+++ b/main/features.c
@@ -3987,6 +3987,18 @@ static int manager_park(struct mansession *s, const struct message *m)
 	return 0;
 }
 
+static int find_channel_by_group(struct ast_channel *c, void *data) {
+	struct ast_channel *chan = data;
+
+	return !c->pbx &&
+		/* Accessing 'chan' here is safe without locking, because there is no way for
+		   the channel do disappear from under us at this point.  pickupgroup *could*
+		   change while we're here, but that isn't a problem. */
+		(c != chan) &&
+		(chan->pickupgroup & c->callgroup) &&
+		((c->_state == AST_STATE_RINGING) || (c->_state == AST_STATE_RING));
+}
+
 /*!
  * \brief Pickup a call
  * \param chan channel that initiated pickup.
@@ -3997,15 +4009,7 @@ static int manager_park(struct mansession *s, const struct message *m)
 */
 int ast_pickup_call(struct ast_channel *chan)
 {
-	auto int find_channel_by_group(struct ast_channel *);
-	int find_channel_by_group(struct ast_channel *c) {
-		return !c->pbx &&
-			(c != chan) &&
-			(chan->pickupgroup & c->callgroup) &&
-			((c->_state == AST_STATE_RINGING) ||
-			 (c->_state == AST_STATE_RING));
-	}
-	struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group);
+	struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
 
 	if (cur) {
 		int res = -1;