mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 18:55:19 +00:00 
			
		
		
		
	git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7413 65c4cc65-6c06-0410-ace0-fbb531ad65f3
		
			
				
	
	
		
			314 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			314 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
 | |
| #include "isdn_lib_intern.h"
 | |
| #include "isdn_lib.h"
 | |
| 
 | |
| #include "string.h"
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| #define CENTREX_ID      0xa1
 | |
| #define CALLDEFLECT_ID      0xa1
 | |
| 
 | |
| /**
 | |
|    This file covers the encoding and decoding of facility messages and
 | |
|    facility information elements.
 | |
| 
 | |
|    There will be 2 Functions as Interface:
 | |
|    
 | |
|    fac_enc( char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
 | |
|    fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc);
 | |
| 
 | |
|    Those will either read the union facility or fill it.
 | |
| 
 | |
|    internally, we will have deconding and encoding functions for each facility
 | |
|    IE.
 | |
|    
 | |
| **/
 | |
| 
 | |
| 
 | |
| /* support stuff */
 | |
| static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
 | |
| {
 | |
| 	if (len > dst_len-1)
 | |
| 		len = dst_len-1;
 | |
| 	strncpy((char *)dest, (char *)src, len);
 | |
| 	dest[len] = '\0';
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /**********************/
 | |
| /*** FACILITY STUFF ***/
 | |
| /**********************/
 | |
| 
 | |
| 
 | |
| /* IE_FACILITY */
 | |
| void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	unsigned char *p;
 | |
| 	Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
 | |
| 	int l;
 | |
| 
 | |
| 
 | |
| 	if (!facility || facility_len<=0)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	
 | |
| 	l = facility_len;
 | |
| 	p = msg_put(msg, l+2);
 | |
| 	if (nt)
 | |
| 		*ntmode = p+1;
 | |
| 	else
 | |
| 		qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t);
 | |
| 	p[0] = IE_FACILITY;
 | |
| 	p[1] = l;
 | |
| 	memcpy(p+2, facility, facility_len);
 | |
| }
 | |
| 
 | |
| 
 | |
| /* facility for siemens CENTEX (known parts implemented only) */
 | |
| void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	unsigned char centrex[256];
 | |
| 	int i = 0;
 | |
| 
 | |
| 	if (!cnip)
 | |
| 		return;
 | |
| 
 | |
| 	/* centrex facility */
 | |
| 	centrex[i++] = FACILITY_CENTREX;
 | |
| 	centrex[i++] = CENTREX_ID;
 | |
| 
 | |
| 	/* cnip */
 | |
| 	if (strlen((char *)cnip) > 15)
 | |
| 	{
 | |
| /* 		if (options.deb & DEBUG_PORT) */
 | |
| 		cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
 | |
| 		cnip[15] = '\0';
 | |
| 	}
 | |
| 	/*  dunno what the 8 bytes mean */
 | |
| 	if (setup)
 | |
| 	{
 | |
| 		centrex[i++] = 0x17;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x44;
 | |
| 		centrex[i++] = 0x18;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x01;
 | |
| 		centrex[i++] = 0x09;
 | |
| 	} else
 | |
| 	{
 | |
| 		centrex[i++] = 0x18;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x81;
 | |
| 		centrex[i++] = 0x09;
 | |
| 		centrex[i++] = 0x02;
 | |
| 		centrex[i++] = 0x01;
 | |
| 		centrex[i++] = 0x0a;
 | |
| 	}
 | |
| 
 | |
| 	centrex[i++] = 0x80;
 | |
| 	centrex[i++] = strlen((char *)cnip);
 | |
| 	strcpy((char *)(¢rex[i]), (char *)cnip);
 | |
| 	i += strlen((char *)cnip);
 | |
| 	cb_log(4,0,"    cnip='%s'\n", cnip);
 | |
| 
 | |
| 	/* encode facility */
 | |
| 	enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
 | |
| }
 | |
| 
 | |
| void dec_ie_facility_centrex(unsigned char *p, Q931_info_t *qi, unsigned char *centrex, int facility_len, unsigned char *cnip, int cnip_len, int nt, struct misdn_bchannel *bc)
 | |
| {
 | |
| 
 | |
| 	int i = 0;
 | |
| 	*cnip = '\0';
 | |
| 	
 | |
| 	if (facility_len >= 2)
 | |
| 	{
 | |
| 		if (centrex[i++] != FACILITY_CENTREX)
 | |
| 			return;
 | |
| 		if (centrex[i++] != CENTREX_ID)
 | |
| 			return;
 | |
| 	}
 | |
| 
 | |
| 	/* loop sub IEs of facility */
 | |
| 	while(facility_len > i+1)
 | |
| 	{
 | |
| 		if (centrex[i+1]+i+1 > facility_len)
 | |
| 		{
 | |
| 			printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
 | |
| 			return;
 | |
| 		}
 | |
| 		switch(centrex[i])
 | |
| 		{
 | |
| 		case 0x80:
 | |
| 			strnncpy(cnip, ¢rex[i+2], centrex[i+1], cnip_len);
 | |
| 			cb_log(4,0,"    CENTREX cnip='%s'\n", cnip);
 | |
| 			break;
 | |
| 		}
 | |
| 		i += 1+centrex[i+1];
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| /* facility for CALL Deflect (known parts implemented only) */
 | |
| void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	unsigned char fac[256];
 | |
| 	
 | |
| 	if (!nr)
 | |
| 		return;
 | |
| 
 | |
| 	int len = strlen(nr);
 | |
| 	/* calldeflect facility */
 | |
| 	
 | |
| 	/* cnip */
 | |
| 	if (strlen((char *)nr) > 15)
 | |
| 	{
 | |
| /* 		if (options.deb & DEBUG_PORT) */
 | |
| 		cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
 | |
| 		nr[15] = '\0';
 | |
| 	}
 | |
| 	
 | |
| 	fac[0]=FACILITY_CALLDEFLECT;	// ..
 | |
| 	fac[1]=CALLDEFLECT_ID;
 | |
| 	fac[2]=0x0f + len;	// strlen destination + 15 = 26
 | |
| 	fac[3]=0x02;
 | |
| 	fac[4]=0x01;
 | |
| 	//fac[5]=0x70;
 | |
| 	fac[5]=0x09;
 | |
| 	fac[6]=0x02;
 | |
| 	fac[7]=0x01;
 | |
| 	fac[8]=0x0d;
 | |
| 	fac[9]=0x30;
 | |
| 	fac[10]=0x07 + len;	// strlen destination + 7 = 18
 | |
| 	fac[11]=0x30;	// ...hm 0x30
 | |
| 	fac[12]=0x02+ len;	// strlen destination + 2	
 | |
| 	fac[13]=0x80;	// CLIP
 | |
| 	fac[14]= len;	//  strlen destination 
 | |
| 	
 | |
| 	memcpy((unsigned char *)fac+15,nr,len);
 | |
| 	fac[15+len]=0x01; //sending complete
 | |
| 	fac[16+len]=0x01;
 | |
| 	fac[17+len]=0x80;
 | |
| 	
 | |
| 	enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc);
 | |
| }
 | |
| 
 | |
| 
 | |
| void dec_ie_facility_calldeflect(unsigned char *p, Q931_info_t *qi, unsigned char *fac, int fac_len, unsigned char *cd_nr,  int nt, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	*cd_nr = '\0';
 | |
| 	
 | |
| 	if (fac_len >= 15)
 | |
| 	{
 | |
| 		if (fac[0] != FACILITY_CALLDEFLECT)
 | |
| 			return;
 | |
| 		if (fac[1] != CALLDEFLECT_ID)
 | |
| 			return;
 | |
| 	} else {
 | |
| 		cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
 | |
| 		return ;
 | |
| 	}
 | |
| 	
 | |
| 	
 | |
| 	
 | |
| 	{
 | |
| 		int dest_len=fac[2]-0x0f;
 | |
| 		
 | |
| 		if (dest_len <0 || dest_len > 15) {
 | |
| 			cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n");
 | |
| 			return ;
 | |
| 		}
 | |
| 		
 | |
| 		if (fac_len < 15+dest_len) {
 | |
| 			cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
 | |
| 			return ;
 | |
| 		}
 | |
| 		
 | |
| 		memcpy(cd_nr, &fac[15],dest_len);
 | |
| 		cd_nr[dest_len]=0;
 | |
| 		
 | |
| 		cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	switch (type) {
 | |
| 	case FACILITY_CENTREX:
 | |
| 	{
 | |
| 		int setup=0;
 | |
| 		enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc);
 | |
| 	}
 | |
| 		break;
 | |
| 	case FACILITY_CALLDEFLECT:
 | |
| 		enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc);
 | |
| 		break;
 | |
| 	default:
 | |
| 		cb_log(1,0,"Don't know how handle this facility: %d\n", type);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc)
 | |
| {
 | |
| 	int i, fac_len=0;
 | |
| 	unsigned char facility[256];
 | |
| 	
 | |
| 	if (! (bc->nt) )
 | |
| 	{
 | |
| 		p = NULL;
 | |
| 		if (qi->QI_ELEMENT(facility))
 | |
| 			p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
 | |
| 	}
 | |
| 	if (!p)
 | |
| 		return;
 | |
| 	
 | |
| 	fac_len = p[0];
 | |
| 	memcpy(facility, p+1, fac_len);
 | |
| 	
 | |
| 	
 | |
| 	switch(facility[0]) {
 | |
| 	case FACILITY_CENTREX:
 | |
| 	{
 | |
| 		int cnip_len=15;
 | |
| 		
 | |
| 		dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc);
 | |
| 		
 | |
| 		*type=FACILITY_CENTREX;
 | |
| 	}
 | |
| 	break;
 | |
| 	case FACILITY_CALLDEFLECT:
 | |
| 		dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr,  bc->nt, bc);
 | |
| 		
 | |
| 		*type=FACILITY_CALLDEFLECT;
 | |
| 		break;
 | |
| 	default:
 | |
| 		cb_log(3, bc->port, "Unknown Facility received: ");
 | |
| 		i = 0;
 | |
| 		while(i < fac_len)
 | |
| 		{
 | |
| 			cb_log(3, bc->port, " %02x", facility[i]);
 | |
| 			i++;
 | |
| 		}
 | |
| 		cb_log(3, bc->port, "    facility\n");
 | |
| 		
 | |
| 		*type=FACILITY_NONE;
 | |
| 	}
 | |
| 	
 | |
| 	
 | |
| }
 | |
| 
 | |
| /*** FACILITY END **/
 | |
| 
 |