diff -ru asterisk-1.4.19/channels/chan_sip.c asterisk-1.4.19-qualifier/channels/chan_sip.c
--- asterisk-1.4.19/channels/chan_sip.c	2008-03-26 14:04:35.000000000 -0500
+++ asterisk-1.4.19-qualifier/channels/chan_sip.c	2008-04-25 09:13:15.000000000 -0500
@@ -1345,7 +1345,7 @@
 static int cb_extensionstate(char *context, char* exten, int state, void *data);
 static int sip_devicestate(void *data);
 static int sip_poke_noanswer(const void *data);
-static int sip_poke_peer(struct sip_peer *peer);
+static int sip_poke_peer(struct sip_peer *peer, int force);
 static void sip_poke_all_peers(void);
 static void sip_peer_hold(struct sip_pvt *p, int hold);
 
@@ -1368,6 +1368,8 @@
 static int sip_show_domains(int fd, int argc, char *argv[]);
 static int _sip_show_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]);
 static int sip_show_peer(int fd, int argc, char *argv[]);
+static int _sip_qualify_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[]);
+static int sip_qualify_peer(int fd, int argc, char *argv[]);
 static int sip_show_user(int fd, int argc, char *argv[]);
 static int sip_show_registry(int fd, int argc, char *argv[]);
 static int sip_show_settings(int fd, int argc, char *argv[]);
@@ -1380,6 +1382,7 @@
 static char *complete_sipch(const char *line, const char *word, int pos, int state);
 static char *complete_sip_peer(const char *word, int state, int flags2);
 static char *complete_sip_show_peer(const char *line, const char *word, int pos, int state);
+static char *complete_sip_qualify_peer(const char *line, const char *word, int pos, int state);
 static char *complete_sip_debug_peer(const char *line, const char *word, int pos, int state);
 static char *complete_sip_user(const char *word, int state, int flags2);
 static char *complete_sip_show_user(const char *line, const char *word, int pos, int state);
@@ -1422,7 +1425,7 @@
 static int update_call_counter(struct sip_pvt *fup, int event);
 static void sip_destroy_peer(struct sip_peer *peer);
 static void sip_destroy_user(struct sip_user *user);
-static int sip_poke_peer(struct sip_peer *peer);
+static int sip_poke_peer(struct sip_peer *peer, int force);
 static int sip_poke_peer_s(const void *data);
 static void set_peer_defaults(struct sip_peer *peer);
 static struct sip_peer *temp_peer(const char *name);
@@ -7918,7 +7921,7 @@
 	struct sip_peer *peer = (struct sip_peer *)data;
 
 	peer->pokeexpire = -1;
-	sip_poke_peer(peer);
+	sip_poke_peer(peer, 0);
 	return 0;
 }
 
@@ -7974,7 +7977,7 @@
 		AST_SCHED_DEL(sched, peer->pokeexpire);
 		peer->pokeexpire = ast_sched_add(sched, ast_random() % 5000 + 1, sip_poke_peer_s, peer);
 	} else
-		sip_poke_peer(peer);
+		sip_poke_peer(peer, 0);
 	AST_SCHED_DEL(sched, peer->expire);
 	peer->expire = ast_sched_add(sched, (expiry + 10) * 1000, expire_register, peer);
 	register_peer_exten(peer, TRUE);
@@ -8191,7 +8194,7 @@
 
 	/* Is this a new IP address for us? */
 	if (inaddrcmp(&peer->addr, &oldsin)) {
-		sip_poke_peer(peer);
+		sip_poke_peer(peer, 0);
 		if (option_verbose > 2)
 			ast_verbose(VERBOSE_PREFIX_3 "Registered SIP '%s' at %s port %d expires %d\n", peer->name, ast_inet_ntoa(peer->addr.sin_addr), ntohs(peer->addr.sin_port), expiry);
 		register_peer_exten(peer, 1);
@@ -10340,8 +10343,6 @@
 	return ret;
 }
 
-
-
 /*! \brief Show one peer in detail */
 static int sip_show_peer(int fd, int argc, char *argv[])
 {
@@ -10560,6 +10561,42 @@
 	return RESULT_SUCCESS;
 }
 
+/*! \brief Show one peer in detail */
+static int sip_qualify_peer(int fd, int argc, char *argv[])
+{
+	return _sip_qualify_peer(0, fd, NULL, NULL, argc, (const char **) argv);
+}
+
+static int _sip_qualify_peer(int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
+{
+	struct sip_peer *peername;
+	int realtimepeers;
+	struct sip_peer *peer;
+
+	realtimepeers = ast_check_realtime("sippeers");
+
+	if (argc < 4)
+		return RESULT_SHOWUSAGE;
+
+	ast_log(LOG_DEBUG, "Looking for peer %s, with load_realtime of %i.\n", argv[3], realtimepeers);
+	peername = find_peer(argv[3], NULL, realtimepeers);
+	if (peername)
+	{
+		ast_cli(fd,"Sending Options ping to peer %s.\n", argv[3]);
+		peer = (struct sip_peer *)peername;
+		if(peer)
+		{
+			return sip_poke_peer(peer, 1);
+		}
+	}
+	else
+	{
+		ast_cli(fd,"Can't locate peer %s.\n", argv[3]);
+		return 0;
+	}
+	return 0;
+}
+
 /*! \brief Show one user in detail */
 static int sip_show_user(int fd, int argc, char *argv[])
 {
@@ -10887,6 +10924,15 @@
 	return result;
 }
 
+/*! \brief Support routine for 'sip qualify peer' CLI */
+static char *complete_sip_qualify_peer(const char *line, const char *word, int pos, int state)
+{
+	if (pos == 3)
+		return complete_sip_peer(word, state, 0);
+
+	return NULL;
+}
+
 /*! \brief Support routine for 'sip show peer' CLI */
 static char *complete_sip_show_peer(const char *line, const char *word, int pos, int state)
 {
@@ -12586,31 +12632,42 @@
 	 * Use some helper variables to simplify the writing
 	 * of the expressions.
 	 */
-	was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms;
-	is_reachable = pingtime <= peer->maxms;
-	statechanged = peer->lastms == 0 /* yes, unknown before */
-		|| was_reachable != is_reachable;
-
-	peer->lastms = pingtime;
-	peer->call = NULL;
-	if (statechanged) {
-		const char *s = is_reachable ? "Reachable" : "Lagged";
+	if (peer->maxms == 0)
+	{
+	        ast_log(LOG_NOTICE, "Peer %s responded in %ims\n", peer->name, pingtime);
+		is_reachable = 1;
 
-		ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
-			peer->name, s, pingtime, peer->maxms);
-		ast_device_state_changed("SIP/%s", peer->name);
-		manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
-			"Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
-			peer->name, s, pingtime);
+		AST_SCHED_DEL(sched, peer->pokeexpire);
+		/* ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	 */
 	}
+	else
+	{
+		was_reachable = peer->lastms > 0 && peer->lastms <= peer->maxms;
+		is_reachable = pingtime <= peer->maxms;
+		statechanged = peer->lastms == 0 /* yes, unknown before */
+			|| was_reachable != is_reachable;
+	
+		peer->lastms = pingtime;
+		peer->call = NULL;
+		if (statechanged) {
+			const char *s = is_reachable ? "Reachable" : "Lagged";
+	
+			ast_log(LOG_NOTICE, "Peer '%s' is now %s. (%dms / %dms)\n",
+				peer->name, s, pingtime, peer->maxms);
+			ast_device_state_changed("SIP/%s", peer->name);
+			manager_event(EVENT_FLAG_SYSTEM, "PeerStatus",
+				"Peer: SIP/%s\r\nPeerStatus: %s\r\nTime: %d\r\n",
+				peer->name, s, pingtime);
+		}
 
-	AST_SCHED_DEL(sched, peer->pokeexpire);
-	ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
-
-	/* Try again eventually */
-	peer->pokeexpire = ast_sched_add(sched,
-		is_reachable ? DEFAULT_FREQ_OK : DEFAULT_FREQ_NOTOK,
-		sip_poke_peer_s, peer);
+		AST_SCHED_DEL(sched, peer->pokeexpire);
+		ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+	
+		/* Try again eventually */
+		peer->pokeexpire = ast_sched_add(sched,
+			is_reachable ? DEFAULT_FREQ_OK : DEFAULT_FREQ_NOTOK,
+			sip_poke_peer_s, peer);
+	}
 }
 
 /*! \brief Immediately stop RTP, VRTP and UDPTL as applicable */
@@ -15780,12 +15837,18 @@
 /*! \brief Check availability of peer, also keep NAT open
 \note	This is done with the interval in qualify= configuration option
 	Default is 2 seconds */
-static int sip_poke_peer(struct sip_peer *peer)
+static int sip_poke_peer(struct sip_peer *peer, int force)
 {
 	struct sip_pvt *p;
 	int xmitres = 0;
 
-	if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
+	if (force && peer->addr.sin_addr.s_addr)
+	{
+		/* IF we have an IP, and they want to force it,
+		  we send the options ping */
+		ast_log(LOG_DEBUG, "Forcing ping of peer [%s].\n", peer->name);
+	}
+	else if (!peer->maxms || !peer->addr.sin_addr.s_addr) {
 		/* IF we have no IP, or this isn't to be monitored, return
 		  imeediately after clearing things out */
 		AST_SCHED_DEL(sched, peer->pokeexpire);
@@ -17937,6 +18000,10 @@
 	sip_show_users, "List defined SIP users",
 	show_users_usage },
 
+	{ { "sip", "qualify", "peer", NULL },
+	sip_qualify_peer, "Send an Options packet to a SIP peer",
+	notify_usage, complete_sip_qualify_peer },
+
 	{ { "sip", "notify", NULL },
 	sip_notify, "Send a notify packet to a SIP peer",
 	notify_usage, complete_sipnotify },
