committed head of chan_misdn with a lot of new features. Most important of all: chan_...
[asterisk/asterisk.git] / channels / misdn / fac.c
1
2 #include "isdn_lib_intern.h"
3 #include "isdn_lib.h"
4
5 #include "string.h"
6
7
8
9
10 #define CENTREX_ID      0xa1
11 #define CALLDEFLECT_ID      0xa1
12
13 /**
14    This file covers the encoding and decoding of facility messages and
15    facility information elements.
16
17    There will be 2 Functions as Interface:
18    
19    fac_enc( char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
20    fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc);
21
22    Those will either read the union facility or fill it.
23
24    internally, we will have deconding and encoding functions for each facility
25    IE.
26    
27 **/
28
29
30 /* support stuff */
31 static void strnncpy(unsigned char *dest, unsigned char *src, int len, int dst_len)
32 {
33         if (len > dst_len-1)
34                 len = dst_len-1;
35         strncpy((char *)dest, (char *)src, len);
36         dest[len] = '\0';
37 }
38
39
40
41
42 /**********************/
43 /*** FACILITY STUFF ***/
44 /**********************/
45
46
47 /* IE_FACILITY */
48 void enc_ie_facility(unsigned char **ntmode, msg_t *msg, unsigned char *facility, int facility_len, int nt, struct misdn_bchannel *bc)
49 {
50         unsigned char *p;
51         Q931_info_t *qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
52         int l;
53
54
55         if (!facility || facility_len<=0)
56         {
57                 return;
58         }
59
60         
61         l = facility_len;
62         p = msg_put(msg, l+2);
63         if (nt)
64                 *ntmode = p+1;
65         else
66                 qi->QI_ELEMENT(facility) = p - (unsigned char *)qi - sizeof(Q931_info_t);
67         p[0] = IE_FACILITY;
68         p[1] = l;
69         memcpy(p+2, facility, facility_len);
70 }
71
72
73 /* facility for siemens CENTEX (known parts implemented only) */
74 void enc_ie_facility_centrex(unsigned char **ntmode, msg_t *msg, unsigned char *cnip, int setup, int nt, struct misdn_bchannel *bc)
75 {
76         unsigned char centrex[256];
77         int i = 0;
78
79         if (!cnip)
80                 return;
81
82         /* centrex facility */
83         centrex[i++] = FACILITY_CENTREX;
84         centrex[i++] = CENTREX_ID;
85
86         /* cnip */
87         if (strlen((char *)cnip) > 15)
88         {
89 /*              if (options.deb & DEBUG_PORT) */
90                 cb_log(1,0,"%s: CNIP/CONP text too long (max 13 chars), cutting.\n", __FUNCTION__);
91                 cnip[15] = '\0';
92         }
93         /*  dunno what the 8 bytes mean */
94         if (setup)
95         {
96                 centrex[i++] = 0x17;
97                 centrex[i++] = 0x02;
98                 centrex[i++] = 0x02;
99                 centrex[i++] = 0x44;
100                 centrex[i++] = 0x18;
101                 centrex[i++] = 0x02;
102                 centrex[i++] = 0x01;
103                 centrex[i++] = 0x09;
104         } else
105         {
106                 centrex[i++] = 0x18;
107                 centrex[i++] = 0x02;
108                 centrex[i++] = 0x02;
109                 centrex[i++] = 0x81;
110                 centrex[i++] = 0x09;
111                 centrex[i++] = 0x02;
112                 centrex[i++] = 0x01;
113                 centrex[i++] = 0x0a;
114         }
115
116         centrex[i++] = 0x80;
117         centrex[i++] = strlen((char *)cnip);
118         strcpy((char *)(&centrex[i]), (char *)cnip);
119         i += strlen((char *)cnip);
120         cb_log(4,0,"    cnip='%s'\n", cnip);
121
122         /* encode facility */
123         enc_ie_facility(ntmode, msg, centrex, i, nt , bc);
124 }
125
126 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)
127 {
128
129         int i = 0;
130         *cnip = '\0';
131         
132         if (facility_len >= 2)
133         {
134                 if (centrex[i++] != FACILITY_CENTREX)
135                         return;
136                 if (centrex[i++] != CENTREX_ID)
137                         return;
138         }
139
140         /* loop sub IEs of facility */
141         while(facility_len > i+1)
142         {
143                 if (centrex[i+1]+i+1 > facility_len)
144                 {
145                         printf("%s: ERROR: short read of centrex facility.\n", __FUNCTION__);
146                         return;
147                 }
148                 switch(centrex[i])
149                 {
150                 case 0x80:
151                         strnncpy(cnip, &centrex[i+2], centrex[i+1], cnip_len);
152                         cb_log(4,0,"    CENTREX cnip='%s'\n", cnip);
153                         break;
154                 }
155                 i += 1+centrex[i+1];
156         }
157 }
158
159
160
161
162 /* facility for CALL Deflect (known parts implemented only) */
163 void enc_ie_facility_calldeflect(unsigned char **ntmode, msg_t *msg, unsigned char *nr, int nt, struct misdn_bchannel *bc)
164 {
165         unsigned char fac[256];
166         
167         if (!nr)
168                 return;
169
170         int len = strlen(nr);
171         /* calldeflect facility */
172         
173         /* cnip */
174         if (strlen((char *)nr) > 15)
175         {
176 /*              if (options.deb & DEBUG_PORT) */
177                 cb_log(1,0,"%s: NR text too long (max 13 chars), cutting.\n", __FUNCTION__);
178                 nr[15] = '\0';
179         }
180         
181         fac[0]=FACILITY_CALLDEFLECT;    // ..
182         fac[1]=CALLDEFLECT_ID;
183         fac[2]=0x0f + len;      // strlen destination + 15 = 26
184         fac[3]=0x02;
185         fac[4]=0x01;
186         //fac[5]=0x70;
187         fac[5]=0x09;
188         fac[6]=0x02;
189         fac[7]=0x01;
190         fac[8]=0x0d;
191         fac[9]=0x30;
192         fac[10]=0x07 + len;     // strlen destination + 7 = 18
193         fac[11]=0x30;   // ...hm 0x30
194         fac[12]=0x02+ len;      // strlen destination + 2       
195         fac[13]=0x80;   // CLIP
196         fac[14]= len;   //  strlen destination 
197         
198         memcpy((unsigned char *)fac+15,nr,len);
199         fac[15+len]=0x01; //sending complete
200         fac[16+len]=0x01;
201         fac[17+len]=0x80;
202         
203         enc_ie_facility(ntmode, msg, fac, 17+len +1 , nt , bc);
204 }
205
206
207 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)
208 {
209         *cd_nr = '\0';
210         
211         if (fac_len >= 15)
212         {
213                 if (fac[0] != FACILITY_CALLDEFLECT)
214                         return;
215                 if (fac[1] != CALLDEFLECT_ID)
216                         return;
217         } else {
218                 cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
219                 return ;
220         }
221         
222         
223         
224         {
225                 int dest_len=fac[2]-0x0f;
226                 
227                 if (dest_len <0 || dest_len > 15) {
228                         cb_log(1,bc->port, "IE is garbage: FAC_CALLDEFLECT\n");
229                         return ;
230                 }
231                 
232                 if (fac_len < 15+dest_len) {
233                         cb_log(1,bc->port, "IE too short: FAC_CALLDEFLECT\n");
234                         return ;
235                 }
236                 
237                 memcpy(cd_nr, &fac[15],dest_len);
238                 cd_nr[dest_len]=0;
239                 
240                 cb_log(5,bc->port, "--> IE CALLDEFLECT NR: %s\n",cd_nr);
241         }
242 }
243
244
245
246 void fac_enc( unsigned char **ntmsg, msg_t * msg, enum facility_type type,  union facility fac, struct misdn_bchannel *bc)
247 {
248         switch (type) {
249         case FACILITY_CENTREX:
250         {
251                 int setup=0;
252                 enc_ie_facility_centrex(ntmsg, msg, fac.cnip, setup, bc->nt, bc);
253         }
254                 break;
255         case FACILITY_CALLDEFLECT:
256                 enc_ie_facility_calldeflect(ntmsg, msg, fac.calldeflect_nr, bc->nt, bc);
257                 break;
258         default:
259                 cb_log(1,0,"Don't know how handle this facility: %d\n", type);
260         }
261 }
262
263 void fac_dec( unsigned char *p, Q931_info_t *qi, enum facility_type *type,  union facility *fac, struct misdn_bchannel *bc)
264 {
265         int i, fac_len=0;
266         unsigned char facility[256];
267         
268         if (! (bc->nt) )
269         {
270                 p = NULL;
271                 if (qi->QI_ELEMENT(facility))
272                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
273         }
274         if (!p)
275                 return;
276         
277         fac_len = p[0];
278         memcpy(facility, p+1, fac_len);
279         
280         
281         switch(facility[0]) {
282         case FACILITY_CENTREX:
283         {
284                 int cnip_len=15;
285                 
286                 dec_ie_facility_centrex(p, qi,facility, fac_len, fac->cnip, cnip_len, bc->nt, bc);
287                 
288                 *type=FACILITY_CENTREX;
289         }
290         break;
291         case FACILITY_CALLDEFLECT:
292                 dec_ie_facility_calldeflect(p, qi,facility, fac_len, fac->calldeflect_nr,  bc->nt, bc);
293                 
294                 *type=FACILITY_CALLDEFLECT;
295                 break;
296         default:
297                 cb_log(3, bc->port, "Unknown Facility received: ");
298                 i = 0;
299                 while(i < fac_len)
300                 {
301                         cb_log(3, bc->port, " %02x", facility[i]);
302                         i++;
303                 }
304                 cb_log(3, bc->port, "    facility\n");
305                 
306                 *type=FACILITY_NONE;
307         }
308         
309         
310 }
311
312 /*** FACILITY END **/
313