diff --git a/doc/example.conf b/doc/example.conf
index c02b3c7..ba01072 100755
--- a/doc/example.conf
+++ b/doc/example.conf
@@ -478,6 +478,7 @@ general {
 	ts_max_delta = 5 minutes;
 	client_exit = yes;
 	collision_fnc = yes;
+	resv_fnc = yes;
 	global_snotices = yes;
 	dline_with_reason = yes;
 	kline_delay = 0 seconds;
diff --git a/doc/reference.conf b/doc/reference.conf
index 1e3e899..38519a9 100755
--- a/doc/reference.conf
+++ b/doc/reference.conf
@@ -1024,6 +1024,13 @@ general {
 	 */
 	collision_fnc = yes;
 
+	/* resv fnc: change a user's nick to a nick they have recently used
+	 * (or their UID, if no such nick can be found) when a resv matching
+	 * them is set by services. Only enable this if all servers on the
+	 * network allow remote nicks to start with a digit.
+	 */
+	resv_fnc = yes;
+
 	/* global snotices: send out certain snotices (most +b, +f, +y,
 	 * some +s) to other servers via ENCAP SNOTE. Received SNOTEs are
 	 * displayed unconditionally.
diff --git a/include/client.h b/include/client.h
index 3856f2f..d394103 100644
--- a/include/client.h
+++ b/include/client.h
@@ -566,6 +566,7 @@ extern void check_klines_event(void *unused);
 extern void check_klines(void);
 extern void check_dlines(void);
 extern void check_xlines(void);
+extern void resv_nick_fnc(const char *mask, const char *reason, int temp_time);
 
 extern const char *get_client_name(struct Client *client, int show_ip);
 extern const char *log_client_name(struct Client *, int);
diff --git a/include/s_conf.h b/include/s_conf.h
index 722e935..2587a42 100644
--- a/include/s_conf.h
+++ b/include/s_conf.h
@@ -220,6 +220,7 @@ struct config_file_entry
 	int throttle_duration;
 	int target_change;
 	int collision_fnc;
+	int resv_fnc;
 	int default_umodes;
 	int global_snotices;
 	int operspy_dont_care_user_info;
diff --git a/modules/m_resv.c b/modules/m_resv.c
index 97f9edb..98e61fb 100644
--- a/modules/m_resv.c
+++ b/modules/m_resv.c
@@ -361,6 +361,7 @@ parse_resv(struct Client *source_p, const char *name, const char *reason, int te
 		}
 
 		rb_dlinkAddAlloc(aconf, &resv_conf_list);
+		resv_nick_fnc(aconf->host, aconf->passwd, temp_time);
 	}
 	else
 		sendto_one_notice(source_p, ":You have specified an invalid resv: [%s]", name);
diff --git a/src/client.c b/src/client.c
index 513e941..69de37f 100644
--- a/src/client.c
+++ b/src/client.c
@@ -600,6 +600,82 @@ check_xlines(void)
 	}
 }
 
+/* resv_nick_fnc
+ *
+ * inputs		- resv, reason, time
+ * outputs		- NONE
+ * side effects	- all local clients matching resv will be FNC'd
+ */
+void
+resv_nick_fnc(const char *mask, const char *reason, int temp_time)
+{
+	struct Client *client_p, *target_p;
+	rb_dlink_node *ptr;
+	rb_dlink_node *next_ptr;
+	char *nick;
+	char note[NICKLEN+10];
+
+	if (!ConfigFileEntry.resv_fnc)
+		return;
+
+	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, lclient_list.head)
+	{
+		client_p = ptr->data;
+
+		if(IsMe(client_p) || !IsPerson(client_p) || IsExemptResv(client_p))
+			continue;
+
+		if(match_esc(mask, client_p->name))
+		{
+			nick = client_p->id;
+
+			/* Tell opers. */
+			sendto_realops_snomask(SNO_GENERAL, L_ALL,
+				"RESV forced nick change for %s!%s@%s to %s; nick matched [%s] (%s)",
+				client_p->name, client_p->username, client_p->host, nick, mask, reason);
+
+			/* Tell the user. */
+			if (temp_time > 0)
+			{
+				sendto_one_notice(client_p,
+					":*** Nick %s is temporarily unavailable on this server.",
+					client_p->name);
+			}
+			else
+			{
+				sendto_one_notice(client_p,
+					":*** Nick %s is no longer available on this server.",
+					client_p->name);
+			}
+
+			/* Do all of the nick-changing gymnastics. */
+			client_p->tsinfo = rb_current_time();
+			add_history(client_p, 1);
+
+			invalidate_bancache_user(client_p);
+
+			sendto_common_channels_local(client_p, NOCAPS, ":%s!%s@%s NICK :%s",
+				client_p->name, client_p->username, client_p->host, nick);
+			sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
+				use_id(client_p), nick, (long) client_p->tsinfo);
+
+			del_from_client_hash(client_p->name, client_p);
+			rb_strlcpy(client_p->name, nick, sizeof(client_p->name));
+			add_to_client_hash(nick, client_p);
+
+			RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
+			{
+				target_p = ptr->data;
+				rb_dlinkFindDestroy(client_p, &target_p->localClient->allow_list);
+				rb_dlinkDestroy(ptr, &client_p->on_allow_list);
+			}
+
+			rb_snprintf(note, sizeof(note), "Nick: %s", nick);
+			rb_note(client_p->localClient->F, note);
+		}
+	}
+}
+
 /*
  * update_client_exit_stats
  *
diff --git a/src/newconf.c b/src/newconf.c
index ddc9f93..9260024 100644
--- a/src/newconf.c
+++ b/src/newconf.c
@@ -2235,6 +2235,7 @@ static struct ConfEntry conf_general_table[] =
 	{ "caller_id_wait",	CF_TIME,  NULL, 0, &ConfigFileEntry.caller_id_wait	},
 	{ "client_exit",	CF_YESNO, NULL, 0, &ConfigFileEntry.client_exit		},
 	{ "collision_fnc",	CF_YESNO, NULL, 0, &ConfigFileEntry.collision_fnc	},
+	{ "resv_fnc",		CF_YESNO, NULL, 0, &ConfigFileEntry.resv_fnc		},
 	{ "connect_timeout",	CF_TIME,  NULL, 0, &ConfigFileEntry.connect_timeout	},
 	{ "default_floodcount", CF_INT,   NULL, 0, &ConfigFileEntry.default_floodcount	},
 	{ "default_ident_timeout",	CF_INT, NULL, 0, &ConfigFileEntry.default_ident_timeout		},
diff --git a/src/s_conf.c b/src/s_conf.c
index 93849e0..ca93f05 100644
--- a/src/s_conf.c
+++ b/src/s_conf.c
@@ -742,6 +742,7 @@ set_default_conf(void)
 	ConfigFileEntry.use_whois_actually = YES;
 	ConfigFileEntry.burst_away = NO;
 	ConfigFileEntry.collision_fnc = YES;
+	ConfigFileEntry.resv_fnc = YES;
 	ConfigFileEntry.global_snotices = YES;
 	ConfigFileEntry.operspy_dont_care_user_info = NO;
 	ConfigFileEntry.use_propagated_bans = YES;
