Index: channels/chan_sip.c
===================================================================
--- channels/chan_sip.c	(revision 195045)
+++ channels/chan_sip.c	(working copy)
@@ -2531,6 +2531,8 @@
 /*--- Internal UA client handling (outbound registrations) */
 static void ast_sip_ouraddrfor(struct in_addr *them, struct sockaddr_in *us);
 static void sip_registry_destroy(struct sip_registry *reg);
+static int remote_sip_register(enum sip_transport transport, const char *uname, const char *domain, const char *sec,
+	const char *auth, int port, const char *exten, int add_registration);
 static int sip_register(const char *value, int lineno);
 static const char *regstate2str(enum sipregistrystate regstate) attribute_const;
 static int sip_reregister(const void *data);
@@ -7070,6 +7072,149 @@
 	return NULL;
 }
 
+
+/*!
+ * \internal
+ * \brief Add or remove a SIP registration.
+ * \param cmd Set it to 0 to add a registration or to 1 to remove a SIP registration.
+ */
+static int remote_sip_register(enum sip_transport transport, const char *uname, const char *domain, const char *sec, 
+	const char *auth, int port, const char *exten, int add_registration)
+{
+	struct sip_registry *reg = NULL;
+
+	if (add_registration) {
+		/* Similar to int sip_register */
+		if (!(reg = ast_calloc(1, sizeof(*reg)))) {
+			return -1;
+		}
+
+		if (ast_string_field_init(reg, 256)) {
+			ast_free(reg);
+			return -1;
+		}
+
+		regobjs++;
+		ASTOBJ_INIT(reg);
+		ast_string_field_set(reg, callback, exten);
+		ast_string_field_set(reg, username, uname);
+		if (domain) {
+			ast_string_field_set(reg, hostname, domain);
+		}
+		if (auth) {
+			ast_string_field_set(reg, authuser, auth);
+		}
+		if (sec) {
+			ast_string_field_set(reg, secret, sec);
+		}
+		reg->expire = -1;
+		reg->timeout = -1;
+		reg->refresh = default_expiry;
+		reg->portno = port;
+		reg->callid_valid = FALSE;
+		reg->ocseq = INITIAL_CSEQ;
+		ASTOBJ_CONTAINER_LINK(&regl, reg);	/* Add the new registry entry to the list */
+		__sip_do_register(reg);
+	} else {
+		ASTOBJ_CONTAINER_TRAVERSE(&regl, 1, do {
+			ASTOBJ_RDLOCK(iterator);
+			if (!strcmp(iterator->username, uname) && !strcmp(iterator->hostname, domain)) {
+				ast_log(LOG_DEBUG, "Deleting Registration for:  %s@%s\n", uname, domain);
+				iterator->expire = 0;
+				__sip_do_register(iterator);
+				ASTOBJ_CONTAINER_UNLINK(&regl, iterator);
+				sip_registry_destroy(iterator);
+			}
+			ASTOBJ_UNLOCK(iterator);
+		} while(0));
+	}
+
+	return 0;
+}
+
+/*! \brief  Description for Manager action SIPregister */
+static char mandescr_sipregister[] =
+"Description: Add a SIP Registration to another server\n"
+"Variables: (headers marked with * are required)\n"
+"       Transport: (tls | tcp | udp (default))\n"
+"       *Username: username of sip uri\n"
+"       Secret: password\n"
+"       Authuser: Authorization username\n"
+"       *Domain: domain to register to\n"
+"       Port: port\n"
+"       Exten: internal extension mapping for this user\n";
+
+/*! \brief  Description for Manager action SIPunregister */
+static char mandescr_sipunregister[] =
+"Description: Remove a SIP Registration to another server\n"
+"Variables: (headers marked with * are required)\n"
+"       Transport: (tls | tcp | udp (default))\n"
+"       *Username: username of sip uri\n"
+"       Secret: password\n"
+"       Authuser: Authorization username\n"
+"       *Domain: domain to register to\n"
+"       Port: port\n"
+"       Exten: internal extension mapping for this user\n";
+
+static int manager_handle_register(struct mansession *s, const struct message *m, int add_registration)
+{
+	int ret, portnum;
+	enum sip_transport transport = SIP_TRANSPORT_UDP;
+	const char *username = astman_get_header(m, "Username");
+	const char *secret = astman_get_header(m, "Secret");
+	const char *authuser = astman_get_header(m, "AuthUser");
+	const char *domain = astman_get_header(m, "Domain");
+	const char *port = astman_get_header(m, "Port");
+	const char *exten = astman_get_header(m, "Exten");
+	const char *transport_s = astman_get_header(m, "Transport");
+
+	if (ast_strlen_zero(username) || ast_strlen_zero(domain)) {
+		astman_send_error(s, m, "Invalid Format (missing parameters)");
+		return 0;
+	}
+
+	if (!ast_strlen_zero(transport_s)) {
+		if (!strncasecmp(transport_s, "tcp", 3)) {
+			transport = SIP_TRANSPORT_TCP;
+		} else if (!strncasecmp(transport_s, "tls", 3)) {
+			transport = SIP_TRANSPORT_TLS;
+		} else if (!strncasecmp(transport_s, "udp", 3)) {
+			transport = SIP_TRANSPORT_UDP;
+		}
+	}
+
+	if (ast_strlen_zero(port)) {
+		/* set default port numbers based on SIP transport. */
+		if (transport & SIP_TRANSPORT_TLS) {
+			portnum = STANDARD_TLS_PORT;
+		} else {
+			portnum = STANDARD_SIP_PORT;
+		}
+	} else {
+		portnum = atoi(port);
+		if (!portnum) {
+			ast_log(LOG_ERROR, "Invalid port number: %d\n", portnum);
+			return -1;
+		}
+	}
+
+	ret = remote_sip_register(transport, username, domain, secret, authuser, portnum, S_OR(exten, "s"), add_registration);
+
+	return ret;
+}
+
+/*! \brief  Manger API Action to register a client remotely */
+static int manager_act_register(struct mansession *s, const struct message *m)
+{
+	return manager_handle_register(s, m, 1);
+}
+
+/*! \brief  Manger API Action to un-register a client remotely */
+static int manager_act_unregister(struct mansession *s, const struct message *m)
+{
+	return manager_handle_register(s, m, 0);
+}
+
 /*! \brief Parse register=> line in sip.conf and add to registry */
 static int sip_register(const char *value, int lineno)
 {
@@ -25278,6 +25423,10 @@
 			"Show SIP registrations (text format)", mandescr_show_registry);
 	ast_manager_register2("SIPnotify", EVENT_FLAG_SYSTEM, manager_sipnotify,
 			"Send a SIP notify", mandescr_sipnotify);
+	ast_manager_register2("SIPregister", EVENT_FLAG_SYSTEM, manager_act_register, 
+			"Register User", mandescr_sipregister);
+	ast_manager_register2("SIPunregister", EVENT_FLAG_SYSTEM, manager_act_unregister, 
+			"Un-Register User", mandescr_sipunregister);
 	sip_poke_all_peers();	
 	sip_send_all_registers();
 	sip_send_all_mwi_subscriptions();
@@ -25339,6 +25488,8 @@
 	ast_manager_unregister("SIPqualifypeer");
 	ast_manager_unregister("SIPshowregistry");
 	ast_manager_unregister("SIPnotify");
+	ast_manager_unregister("SIPregister");
+	ast_manager_unregister("SIPunregister");
 	
 	/* Kill TCP/TLS server threads */
 	if (sip_tcp_desc.master)
