diff -urN asterisk-1.0.2-orig/channels/chan_sip.c asterisk-1.0.2/channels/chan_sip.c
--- asterisk-1.0.2-orig/channels/chan_sip.c	2004-10-25 13:57:25.000000000 -0400
+++ asterisk-1.0.2/channels/chan_sip.c	2004-11-23 03:58:34.569029977 -0500
@@ -253,6 +253,13 @@
 	struct sip_history *next;
 };
 
+/* sip_drings: Incoming distinctive ring information */
+struct sip_drings {
+        char alert_info[3][AST_MAX_EXTENSION];
+        char context[3][AST_MAX_EXTENSION];
+};
+static struct sip_drings drings;
+
 /* sip_pvt: PVT structures are used for each SIP conversation, ie. a call  */
 static struct sip_pvt {
 	ast_mutex_t lock;			/* Channel private lock */
@@ -306,6 +313,7 @@
 	char language[MAX_LANGUAGE];		/* Default language for this call */
 	char musicclass[MAX_LANGUAGE];          /* Music on Hold class */
 	char rdnis[256];			/* Referring DNIS */
+	char alert_info[256];			/* Contents of the Alert-Info header for this call */
 	char theirtag[256];			/* Their tag */
 	char username[256];
 	char peername[256];
@@ -415,6 +423,7 @@
 #ifdef MYSQL_USERS
 	int temponly;
 #endif /* MYSQL_FRIENDS */
+	struct sip_drings drings;	/* Distinctive Ring info for this user */
 	struct sip_user *next;
 };
 
@@ -470,6 +479,7 @@
 	int selfdestruct;
 	int lastmsg;
 	int temponly;
+	struct sip_drings drings;	/* Distinctive Ring info for this peer */
 	struct sip_peer *next;
 };
 
@@ -5320,6 +5330,25 @@
 }
 
 
+/*--- sip_get_dring_context: Look up distinctive ring context based on alert_info ---*/
+static char *sip_get_dring_context(struct sip_drings *my_drings, char *alert_info) {
+	int i;
+	char *ret = NULL;
+
+	if (!ast_strlen_zero(alert_info)) {
+		for (i = 0; i < 3; i++) {
+			if (ast_strlen_zero(my_drings->alert_info[i]) || ast_strlen_zero(my_drings->context[i]))
+				continue;
+			if (!strncmp(my_drings->alert_info[i], alert_info, strlen(my_drings->alert_info[i]))) {
+				ret = my_drings->context[i];
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+
 /*--- check_user: Check if matching user or peer is defined ---*/
 static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd, char *uri, int reliable, struct sockaddr_in *sin, int ignore, char *mailbox, int mailboxlen)
 {
@@ -5327,6 +5356,7 @@
 	struct sip_peer *peer;
 	char *of, from[256] = "", *c;
 	char *rpid,rpid_num[50];
+	char *dcontext;
 	char iabuf[INET_ADDRSTRLEN];
 	int res = 0;
 	char *t;
@@ -5405,6 +5435,9 @@
 			sip_cancel_destroy(p);
 			if (!ast_strlen_zero(user->context))
 				strncpy(p->context, user->context, sizeof(p->context) - 1);
+			/* See if we have a user Distinctive Ring context */
+			if (NULL != (dcontext = sip_get_dring_context(&user->drings, p->alert_info)))
+				strncpy(p->context, dcontext, sizeof(p->context) - 1);
 			if (!ast_strlen_zero(user->callerid) && !ast_strlen_zero(p->callerid)) 
 				strncpy(p->callerid, user->callerid, sizeof(p->callerid) - 1);
 			strncpy(p->username, user->name, sizeof(p->username) - 1);
@@ -5498,6 +5531,9 @@
 				strncpy(p->fullcontact, peer->fullcontact, sizeof(p->fullcontact) - 1);
 				if (!ast_strlen_zero(peer->context))
 					strncpy(p->context, peer->context, sizeof(p->context) - 1);
+				/* See if we have a peer Distinctive Ring context */
+				if (NULL != (dcontext = sip_get_dring_context(&peer->drings, p->alert_info)))
+					strncpy(p->context, dcontext, sizeof(p->context) - 1);
 				strncpy(p->peersecret, peer->secret, sizeof(p->peersecret) - 1);
 				strncpy(p->peermd5secret, peer->md5secret, sizeof(p->peermd5secret) - 1);
 				p->callgroup = peer->callgroup;
@@ -5834,6 +5870,12 @@
 		ast_cli(fd, "%s\n",status);
  		ast_cli(fd, "  Useragent    : %s\n", peer->useragent);
  		ast_cli(fd, "  Full Contact : %s\n", peer->fullcontact);
+		ast_cli(fd, "  DR1 Alrt-Nfo : %s\n", peer->drings.alert_info[0]);
+		ast_cli(fd, "  DR1 Context  : %s\n", peer->drings.context[0]);
+		ast_cli(fd, "  DR2 Alrt-Nfo : %s\n", peer->drings.alert_info[1]);
+		ast_cli(fd, "  DR2 Context  : %s\n", peer->drings.context[1]);
+		ast_cli(fd, "  DR3 Alrt-Nfo : %s\n", peer->drings.alert_info[2]);
+		ast_cli(fd, "  DR3 Context  : %s\n", peer->drings.context[2]);
 		ast_cli(fd,"\n");
 	} else {
 		ast_cli(fd,"Peer %s not found.\n", argv[3]);
@@ -7072,6 +7114,7 @@
 	char *from;
 	char *e;
 	char *useragent;
+	char *alert_info;
 	struct ast_channel *c=NULL;
 	struct ast_channel *transfer_to;
 	int seqno;
@@ -7110,6 +7153,10 @@
 	useragent = get_header(req, "User-Agent");
 	strncpy(p->useragent, useragent, sizeof(p->useragent)-1);
 
+	/* Save Distinctive Ring information (Alert-Info header) */
+	alert_info = get_header(req, "Alert-Info");
+	if (!ast_strlen_zero(alert_info))
+		strncpy(p->alert_info, alert_info, sizeof(p->alert_info) - 1);
 	
 	if (strcasecmp(cmd, "SIP/2.0")) {
 		/* Request coming in */			
@@ -8109,6 +8156,13 @@
 #endif
 		/* set default context */
 		strncpy(user->context, default_context, sizeof(user->context)-1);
+		/* set default distinctive ring contexts */
+		strncpy(user->drings.alert_info[0], drings.alert_info[0], sizeof(user->drings.alert_info[0])-1);
+		strncpy(user->drings.alert_info[1], drings.alert_info[1], sizeof(user->drings.alert_info[1])-1);
+		strncpy(user->drings.alert_info[2], drings.alert_info[2], sizeof(user->drings.alert_info[2])-1);
+		strncpy(user->drings.context[0], drings.context[0], sizeof(user->drings.context[0])-1);
+		strncpy(user->drings.context[1], drings.context[1], sizeof(user->drings.context[1])-1);
+		strncpy(user->drings.context[2], drings.context[2], sizeof(user->drings.context[2])-1);
 		strncpy(user->language, default_language, sizeof(user->language)-1);
 		strncpy(user->musicclass, global_musicclass, sizeof(user->musicclass)-1);
 		while(v) {
@@ -8205,6 +8259,18 @@
 				} else
 					user->ospauth = 0;
 #endif
+			} else if (!strcasecmp(v->name, "dring1context")) {
+				strncpy(user->drings.context[0], v->value,sizeof(user->drings.context[0])-1);
+			} else if (!strcasecmp(v->name, "dring2context")) {
+				strncpy(user->drings.context[1], v->value,sizeof(user->drings.context[1])-1);
+			} else if (!strcasecmp(v->name, "dring3context")) {
+				strncpy(user->drings.context[2], v->value,sizeof(user->drings.context[2])-1);
+			} else if (!strcasecmp(v->name, "dring1")) {
+				strncpy(user->drings.alert_info[0],v->value,sizeof(user->drings.alert_info[0])-1);
+			} else if (!strcasecmp(v->name, "dring2")) {
+				strncpy(user->drings.alert_info[1],v->value,sizeof(user->drings.alert_info[1])-1);
+			} else if (!strcasecmp(v->name, "dring3")) {
+				strncpy(user->drings.alert_info[2],v->value,sizeof(user->drings.alert_info[2])-1);
 			}
 			/*else if (strcasecmp(v->name,"type"))
 			 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
@@ -8317,6 +8383,13 @@
 #ifdef OSP_SUPPORT
 		peer->ospauth = global_ospauth;
 #endif
+		/* set default distinctive ring contexts */
+		strncpy(peer->drings.alert_info[0], drings.alert_info[0], sizeof(peer->drings.alert_info[0])-1);
+		strncpy(peer->drings.alert_info[1], drings.alert_info[1], sizeof(peer->drings.alert_info[1])-1);
+		strncpy(peer->drings.alert_info[2], drings.alert_info[2], sizeof(peer->drings.alert_info[2])-1);
+		strncpy(peer->drings.context[0], drings.context[0], sizeof(peer->drings.context[0])-1);
+		strncpy(peer->drings.context[1], drings.context[1], sizeof(peer->drings.context[1])-1);
+		strncpy(peer->drings.context[2], drings.context[2], sizeof(peer->drings.context[2])-1);
 		while(v) {
 			if (!strcasecmp(v->name, "secret")) 
 				strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
@@ -8464,6 +8537,18 @@
 				} else
 					peer->ospauth = 0;
 #endif
+			} else if (!strcasecmp(v->name, "dring1context")) {
+				strncpy(peer->drings.context[0], v->value,sizeof(peer->drings.context[0])-1);
+			} else if (!strcasecmp(v->name, "dring2context")) {
+				strncpy(peer->drings.context[1], v->value,sizeof(peer->drings.context[1])-1);
+			} else if (!strcasecmp(v->name, "dring3context")) {
+				strncpy(peer->drings.context[2], v->value,sizeof(peer->drings.context[2])-1);
+			} else if (!strcasecmp(v->name, "dring1")) {
+				strncpy(peer->drings.alert_info[0], v->value,sizeof(peer->drings.alert_info[0])-1);
+			} else if (!strcasecmp(v->name, "dring2")) {
+				strncpy(peer->drings.alert_info[1], v->value,sizeof(peer->drings.alert_info[1])-1);
+			} else if (!strcasecmp(v->name, "dring3")) {
+				strncpy(peer->drings.alert_info[2], v->value,sizeof(peer->drings.alert_info[2])-1);
 			}
 			/* else if (strcasecmp(v->name,"type"))
 			 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
@@ -8492,6 +8577,7 @@
 	struct hostent *hp;
 	int format;
 	int oldport = ntohs(bindaddr.sin_port);
+	int i;
 	char iabuf[INET_ADDRSTRLEN];
 
 	global_dtmfmode = SIP_DTMF_RFC2833;
@@ -8531,6 +8617,10 @@
 	global_rtptimeout = 0;
 	global_rtpholdtimeout = 0;
 	pedanticsipchecking=0;
+	for (i = 0; i < 3; i++) {
+		drings.alert_info[i][0] = '\0';
+		drings.context[i][0] = '\0';
+	}
 	v = ast_variable_browse(cfg, "general");
 	while(v) {
 		/* Create the interface list */
@@ -8696,6 +8786,18 @@
 		} else if (!strcasecmp(v->name, "dbname")) {
 			strncpy(mydbname, v->value, sizeof(mydbname) - 1);
 #endif
+		} else if (!strcasecmp(v->name, "dring1context")) {
+			strncpy(drings.context[0], v->value,sizeof(drings.context[0])-1);
+		} else if (!strcasecmp(v->name, "dring2context")) {
+			strncpy(drings.context[1], v->value,sizeof(drings.context[1])-1);
+		} else if (!strcasecmp(v->name, "dring3context")) {
+			strncpy(drings.context[2], v->value,sizeof(drings.context[2])-1);
+		} else if (!strcasecmp(v->name, "dring1")) {
+			strncpy(drings.alert_info[0], v->value,sizeof(drings.alert_info[0])-1);
+		} else if (!strcasecmp(v->name, "dring2")) {
+			strncpy(drings.alert_info[1], v->value,sizeof(drings.alert_info[1])-1);
+		} else if (!strcasecmp(v->name, "dring3")) {
+			strncpy(drings.alert_info[2], v->value,sizeof(drings.alert_info[2])-1);
 		}
 		/* else if (strcasecmp(v->name,"type"))
 		 *	ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
