Index: channels/chan_sip.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_sip.c,v
retrieving revision 1.841
diff -u -r1.841 chan_sip.c
--- channels/chan_sip.c	7 Sep 2005 19:00:31 -0000	1.841
+++ channels/chan_sip.c	7 Sep 2005 21:38:16 -0000
@@ -516,6 +516,8 @@
 /* Call states */
 #define SIP_CALL_ONHOLD		(1 << 28)	 
 #define SIP_CALL_LIMIT		(1 << 29)
+/* Remote Party-ID Support */
+#define SIP_GENRPID		(1 << 30)
 
 /* a new page of flags for peer */
 #define SIP_PAGE2_RTCACHEFRIENDS 	(1 << 0)
@@ -592,6 +594,8 @@
 	char fullcontact[128];			/* The Contact: that the UA registers with us */
 	char accountcode[AST_MAX_ACCOUNT_CODE];	/* Account code */
 	char our_contact[256];			/* Our contact header */
+	char *rpid;				/* Our RPID header */
+	char *rpid_from;			/* Our RPID From header */
 	char realm[MAXHOSTNAMELEN];		/* Authorization realm */
 	char nonce[256];			/* Authorization nonce */
 	char opaque[256];			/* Opaque nonsense */
@@ -1546,6 +1550,14 @@
 static void sip_destroy_peer(struct sip_peer *peer)
 {
 	/* Delete it, it needs to disappear */
+	if (peer->call->rpid) {
+		free(peer->call->rpid);
+		peer->call->rpid = NULL;
+	}
+	if (peer->call->rpid_from) {
+		free(peer->call->rpid_from);
+		peer->call->rpid_from = NULL;
+	}
 	if (peer->call)
 		sip_destroy(peer->call);
 	if (peer->chanvars) {
@@ -4399,6 +4411,87 @@
 		snprintf(p->our_contact, sizeof(p->our_contact), "<sip:%s%s%s>", p->exten, ast_strlen_zero(p->exten) ? "" : "@", ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip));
 }
 
+/*--- build_rpid: Build the Remote Party-ID & From using callingpres options ---*/
+static void build_rpid(struct sip_pvt *p)
+{
+	int allowtags = 1;
+	char privacy[5];
+	char screen[5];
+	char rpid[256];
+	char rpid_from[256];
+	char *clid = default_callerid;
+	char *clin = NULL;
+	char iabuf[INET_ADDRSTRLEN];
+
+	if(!p->rpid && !p->rpid_from) {		
+		if (p->owner && p->owner->cid.cid_num) {
+			clid = strdup(p->owner->cid.cid_num);
+		} 
+		
+		if (p->owner && p->owner->cid.cid_name) {
+			clin = strdup(p->owner->cid.cid_name);
+		}
+		if (!clin || ast_strlen_zero(clin))
+			clin = clid;
+		
+		switch (p->callingpres)
+			{
+			case AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED:
+				strcpy(privacy, "off");
+				strcpy(screen, "no");
+				break;
+			case AST_PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN:
+				strcpy(privacy, "off");
+				strcpy(screen, "pass");
+				break;
+			case AST_PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN:
+				strcpy(privacy, "off");
+				strcpy(screen, "fail");
+				break;
+			case AST_PRES_ALLOWED_NETWORK_NUMBER:
+				strcpy(privacy, "off");
+				strcpy(screen, "yes");
+				break;
+			case AST_PRES_PROHIB_USER_NUMBER_NOT_SCREENED:
+				strcpy(privacy, "full");
+				strcpy(screen, "no");
+				break;
+			case AST_PRES_PROHIB_USER_NUMBER_PASSED_SCREEN:
+				strcpy(privacy, "full");
+				strcpy(screen, "pass");
+				break;
+			case AST_PRES_PROHIB_USER_NUMBER_FAILED_SCREEN:
+				strcpy(privacy, "full");
+				strcpy(screen, "fail");
+				break;
+			case AST_PRES_PROHIB_NETWORK_NUMBER:
+				strcpy(privacy, "full");
+				strcpy(screen, "fail");
+				break;
+			case AST_PRES_NUMBER_NOT_AVAILABLE:
+				allowtags = 0;
+				break;
+			default:
+				ast_log(LOG_WARNING, "Badly encoded callingpres (%d)\n", p->callingpres);
+				if ((p->callingpres & AST_PRES_RESTRICTION) != AST_PRES_ALLOWED) {
+					strcpy(privacy, "full");
+				} else {
+					strcpy(privacy, "off");
+					strcpy(screen, "no");
+				}
+			}
+		
+		if (allowtags) {
+			snprintf(rpid, sizeof(rpid), "\"%s\" <sip:%s@%s>;privacy=%s;screen=%s", clin, clid, ast_strlen_zero(p->fromdomain) ? ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip) : p->fromdomain, privacy, screen);
+		} else {
+			snprintf(rpid, sizeof(rpid), "\"%s\" <sip:%s@%s>", clin, clid, ast_strlen_zero(p->fromdomain) ? ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip) : p->fromdomain);
+		}
+		snprintf(rpid_from, sizeof(rpid_from), "\"%s\" <sip:%s@%s>;tag=as%08x", clin, ast_strlen_zero(p->fromuser) ? clid : p->fromuser, ast_strlen_zero(p->fromdomain) ? ast_inet_ntoa(iabuf, sizeof(iabuf), p->ourip) : p->fromdomain, p->tag);
+		p->rpid = strdup(rpid);
+		p->rpid_from = strdup(rpid_from);
+	}
+}
+
 /*--- initreqprep: Initiate new SIP request to peer/user ---*/
 static void initreqprep(struct sip_request *req, struct sip_pvt *p, int sipmethod)
 {
@@ -4518,7 +4611,12 @@
 	add_header(req, "Via", p->via);
 	/* SLD: FIXME?: do Route: here too?  I think not cos this is the first request.
 	 * OTOH, then we won't have anything in p->route anyway */
-	add_header(req, "From", from);
+	/* Build Remote Party-ID and From */
+	if (!ast_test_flag(p, SIP_GENRPID)) {
+		build_rpid(p);
+		add_header(req, "From", p->rpid_from);
+	} else
+		add_header(req, "From", from);
 	ast_copy_string(p->exten, l, sizeof(p->exten));
 	build_contact(p);
 	add_header(req, "To", to);
@@ -4526,6 +4624,8 @@
 	add_header(req, "Call-ID", p->callid);
 	add_header(req, "CSeq", tmp);
 	add_header(req, "User-Agent", default_useragent);
+	if (!ast_test_flag(p, SIP_GENRPID))
+		add_header(req, "Remote-Party-ID", p->rpid);
 }
 
 /*--- transmit_invite: Build REFER/INVITE/OPTIONS message and transmit it ---*/
@@ -11787,6 +11887,8 @@
 			}
 		} else if (!strcasecmp(v->name, "callevents")) {
 			callevents = ast_true(v->value);
+		} else if (!strcasecmp(v->name, "generaterpid")) {
+			ast_set2_flag((&global_flags), ast_true(v->value), SIP_GENRPID);
 		}
 		/* else if (strcasecmp(v->name,"type"))
 		 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
