]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer3/i4b_q932fac.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / layer3 / i4b_q932fac.c
1 /*-
2  * Copyright (c) 1997, 2002 Hellmuth Michaelis. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /*---------------------------------------------------------------------------
27  *
28  *      i4b_q932fac.c - Q932 facility handling
29  *      --------------------------------------
30  *      last edit-date: [Sat Mar  9 19:37:29 2002]
31  *
32  *---------------------------------------------------------------------------*/
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/mbuf.h>
40
41 #include <i4b/include/i4b_debug.h>
42 #include <i4b/include/i4b_ioctl.h>
43
44 #include <i4b/include/i4b_l3l4.h>
45
46 #include <i4b/layer3/i4b_l3.h>
47 #include <i4b/layer3/i4b_q932fac.h>
48
49 static int do_component(int length);
50 static void next_state(int class, int form, int code, int val);
51
52 static int byte_len;
53 static unsigned char *byte_buf;
54 static int state;
55
56 static int units;
57 static int operation_value;
58
59 /*---------------------------------------------------------------------------*
60  *      decode Q.931/Q.932 facility info element
61  *---------------------------------------------------------------------------*/
62 int
63 i4b_aoc(unsigned char *buf, call_desc_t *cd)
64 {
65         int len;
66
67         cd->units_type = CHARGE_INVALID;
68         cd->units = -1;                 
69         
70         buf++;          /* length */
71
72         len = *buf;
73
74         buf++;          /* protocol profile */
75
76         switch(*buf & 0x1f)
77         {
78                 case FAC_PROTO_ROP:
79                         break;
80
81                 case FAC_PROTO_CMIP:
82                         NDBGL3(L3_A_MSG, "CMIP Protocol (Q.941), UNSUPPORTED");
83                         return(-1);
84                         break;
85
86                 case FAC_PROTO_ACSE:
87                         NDBGL3(L3_A_MSG, "ACSE Protocol (X.217/X.227), UNSUPPORTED!");
88                         return(-1);
89                         break;
90
91                 default:
92                         NDBGL3(L3_A_ERR, "Unknown Protocol, UNSUPPORTED!");
93                         return(-1);
94                         break;
95         }
96
97         NDBGL3(L3_A_MSG, "Remote Operations Protocol");
98
99         /* next byte */
100         
101         buf++;
102         len--;
103
104         /* initialize variables for do_component */
105         
106         byte_len = 0;
107         byte_buf = buf;
108         state = ST_EXP_COMP_TYP;        
109
110         /* decode facility */
111         
112         do_component(len);
113
114         switch(operation_value)
115         {
116                 case FAC_OPVAL_AOC_D_CUR:
117                         cd->units_type = CHARGE_AOCD;
118                         cd->units = 0;
119                         return(0);
120                         break;
121                         
122                 case FAC_OPVAL_AOC_D_UNIT:
123                         cd->units_type = CHARGE_AOCD;
124                         cd->units = units;
125                         return(0);
126                         break;
127                         
128                 case FAC_OPVAL_AOC_E_CUR:
129                         cd->units_type = CHARGE_AOCE;
130                         cd->units = 0;
131                         return(0);
132                         break;
133                         
134                 case FAC_OPVAL_AOC_E_UNIT:
135                         cd->units_type = CHARGE_AOCE;
136                         cd->units = units;
137                         return(0);
138                         break;
139
140                 default:
141                         cd->units_type = CHARGE_INVALID;
142                         cd->units = -1;
143                         return(-1);
144                         break;
145         }
146         return(-1);     
147 }
148
149 /*---------------------------------------------------------------------------*
150  *      handle a component recursively
151  *---------------------------------------------------------------------------*/
152 static int
153 do_component(int length)
154 {
155         int comp_tag_class;     /* component tag class */
156         int comp_tag_form;      /* component form: constructor or primitive */
157         int comp_tag_code;      /* component code depending on class */
158         int comp_length = 0;    /* component length */
159
160 again:
161
162         /*----------------------------------------*/
163         /* first component element: component tag */
164         /*----------------------------------------*/
165         
166         /* tag class bits */
167
168         comp_tag_class = (*byte_buf & 0xc0) >> 6;
169         
170         switch(comp_tag_class)
171         {
172                 case FAC_TAGCLASS_UNI:
173                         break;
174                 case FAC_TAGCLASS_APW:
175                         break;
176                 case FAC_TAGCLASS_COS:
177                         break;
178                 case FAC_TAGCLASS_PRU:
179                         break;
180         }
181
182         /* tag form bit */
183
184         comp_tag_form = (*byte_buf & 0x20) > 5;
185         
186         /* tag code bits */
187
188         comp_tag_code = *byte_buf & 0x1f;
189         
190         if(comp_tag_code == 0x1f)
191         {
192                 comp_tag_code = 0;
193                 
194                 byte_buf++;
195                 byte_len++;
196
197                 while(*byte_buf & 0x80)
198                 {
199                         comp_tag_code += (*byte_buf & 0x7f);
200                         byte_buf++;
201                         byte_len++;
202                 }
203                 comp_tag_code += (*byte_buf & 0x7f);
204         }
205         else
206         {
207                 comp_tag_code = (*byte_buf & 0x1f);
208         }
209
210         byte_buf++;
211         byte_len++;
212         
213         /*--------------------------------------------*/
214         /* second component element: component length */
215         /*--------------------------------------------*/
216         
217         comp_length = 0;
218         
219         if(*byte_buf & 0x80)
220         {
221                 int i = *byte_buf & 0x7f;
222
223                 byte_len += i;
224                 
225                 for(;i > 0;i++)
226                 {
227                         byte_buf++;
228                         comp_length += (*byte_buf * (i*256));
229                 }       
230         }
231         else
232         {
233                 comp_length = *byte_buf & 0x7f;
234         }
235
236         next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1);
237         
238         byte_len++;
239         byte_buf++;
240         
241         /*---------------------------------------------*/
242         /* third component element: component contents */
243         /*---------------------------------------------*/
244
245         if(comp_tag_form)       /* == constructor */
246         {
247                 do_component(comp_length);
248         }
249         else 
250         {
251                 int val = 0;            
252                 if(comp_tag_class == FAC_TAGCLASS_UNI)
253                 {
254                         switch(comp_tag_code)
255                         {
256                                 case FAC_CODEUNI_INT:
257                                 case FAC_CODEUNI_ENUM:
258                                 case FAC_CODEUNI_BOOL:                          
259                                         if(comp_length)
260                                         {
261                                                 int i;
262                                 
263                                                 for(i = comp_length-1; i >= 0; i--)
264                                                 {
265                                                         val += (*byte_buf + (i*255));
266                                                         byte_buf++;
267                                                         byte_len++;
268                                                 }
269                                         }
270                                         break;
271                                 default:        
272                                         if(comp_length)
273                                         {
274                                                 int i;
275                                 
276                                                 for(i = comp_length-1; i >= 0; i--)
277                                                 {
278                                                         byte_buf++;
279                                                         byte_len++;
280                                                 }
281                                         }
282                                         break;
283                         }
284                 }
285
286                 else    /* comp_tag_class != FAC_TAGCLASS_UNI */
287                 {
288                         if(comp_length)
289                         {
290                                 int i;
291                 
292                                 for(i = comp_length-1; i >= 0; i--)
293                                 {
294                                         val += (*byte_buf + (i*255)); 
295                                         byte_buf++;
296                                         byte_len++;
297                                 }
298                         }
299                 }
300                 next_state(comp_tag_class, comp_tag_form, comp_tag_code, val);
301         }
302
303         if(byte_len < length)
304                 goto again;
305
306         return(byte_len);
307 }
308
309 /*---------------------------------------------------------------------------*
310  *      invoke component
311  *---------------------------------------------------------------------------*/
312 static void
313 F_1_1(int val)
314 {
315         if(val == -1)
316         {
317                 state = ST_EXP_INV_ID;
318         }
319 }
320
321 /*---------------------------------------------------------------------------*
322  *      return result
323  *---------------------------------------------------------------------------*/
324 static void
325 F_1_2(int val)
326 {
327         if(val == -1)
328                 state = ST_EXP_NIX;
329 }
330 /*---------------------------------------------------------------------------*
331  *      return error
332  *---------------------------------------------------------------------------*/
333 static void
334 F_1_3(int val)
335 {
336         if(val == -1)
337                 state = ST_EXP_NIX;
338 }
339 /*---------------------------------------------------------------------------*
340  *      reject
341  *---------------------------------------------------------------------------*/
342 static void
343 F_1_4(int val)
344 {
345         if(val == -1)
346                 state = ST_EXP_NIX;
347 }
348
349 /*---------------------------------------------------------------------------*
350  *      invoke id
351  *---------------------------------------------------------------------------*/
352 static void
353 F_2(int val)
354 {
355         if(val != -1)
356         {
357                 NDBGL3(L3_A_MSG, "Invoke ID = %d", val);
358                 state = ST_EXP_OP_VAL;
359         }
360 }
361
362 /*---------------------------------------------------------------------------*
363  *      operation value
364  *---------------------------------------------------------------------------*/
365 static void
366 F_3(int val)
367 {
368         if(val != -1)
369         {
370                 NDBGL3(L3_A_MSG, "Operation Value = %d", val);
371         
372                 operation_value = val;
373                 
374                 if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT))
375                 {
376                         units = 0;
377                         state = ST_EXP_INFO;
378                 }
379                 else
380                 {
381                         state = ST_EXP_NIX;
382                 }
383         }
384 }
385
386 /*---------------------------------------------------------------------------*
387  *      specific charging units
388  *---------------------------------------------------------------------------*/
389 static void
390 F_4(int val)
391 {
392         if(val == -1)
393                 state = ST_EXP_RUL;
394 }
395
396 /*---------------------------------------------------------------------------*
397  *      free of charge
398  *---------------------------------------------------------------------------*/
399 static void
400 F_4_1(int val)
401 {
402         if(val == -1)
403         {
404                 NDBGL3(L3_A_MSG, "Free of Charge");
405                 /* units = 0; XXXX */
406                 state = ST_EXP_NIX;
407         }
408 }
409
410 /*---------------------------------------------------------------------------*
411  *      charge not available
412  *---------------------------------------------------------------------------*/
413 static void
414 F_4_2(int val)
415 {
416         if(val == -1)
417         {
418                 NDBGL3(L3_A_MSG, "Charge not available");
419                 /* units = -1;  XXXXXX ??? */
420                 state = ST_EXP_NIX;
421         }
422 }
423
424 /*---------------------------------------------------------------------------*
425  *      recorded units list
426  *---------------------------------------------------------------------------*/
427 static void
428 F_5(int val)
429 {
430         if(val == -1)
431                 state = ST_EXP_RU;
432 }
433
434 /*---------------------------------------------------------------------------*
435  *      recorded units
436  *---------------------------------------------------------------------------*/
437 static void
438 F_6(int val)
439 {
440         if(val == -1)
441                 state = ST_EXP_RNOU;
442 }
443
444 /*---------------------------------------------------------------------------*
445  *      number of units
446  *---------------------------------------------------------------------------*/
447 static void
448 F_7(int val)
449 {
450         if(val != -1)
451         {
452                 NDBGL3(L3_A_MSG, "Number of Units = %d", val);
453                 units = val;
454                 state = ST_EXP_TOCI;
455         }
456 }
457
458 /*---------------------------------------------------------------------------*
459  *      subtotal/total
460  *---------------------------------------------------------------------------*/
461 static void
462 F_8(int val)
463 {
464         if(val != -1)
465         {
466                 NDBGL3(L3_A_MSG, "Subtotal/Total = %d", val);
467                 /* type_of_charge = val; */
468                 state = ST_EXP_DBID;
469         }
470 }
471
472 /*---------------------------------------------------------------------------*
473  *      billing_id
474  *---------------------------------------------------------------------------*/
475 static void
476 F_9(int val)
477 {
478         if(val != -1)
479         {
480                 NDBGL3(L3_A_MSG, "Billing ID = %d", val);
481                 /* billing_id = val; */
482                 state = ST_EXP_NIX;
483         }
484 }
485
486 /*---------------------------------------------------------------------------*
487  *
488  *---------------------------------------------------------------------------*/
489 static struct statetab {
490         int currstate;          /* input: current state we are in */
491         int form;               /* input: current tag form */
492         int class;              /* input: current tag class */
493         int code;               /* input: current tag code */
494         void (*func)(int);      /* output: func to exec */
495 } statetab[] = {
496
497 /*       current state          tag form                tag class               tag code                function        */
498 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
499         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_1_1           },
500         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       2,                      F_1_2           },
501         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       3,                      F_1_3           },
502         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       4,                      F_1_4           },
503         {ST_EXP_INV_ID,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_2             },
504         {ST_EXP_OP_VAL,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_3             },
505         {ST_EXP_INFO,           FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_4             },
506         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_NULL,       F_4_1           },
507         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_4_2           },
508         {ST_EXP_RUL,            FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_5             },
509         {ST_EXP_RU,             FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_6             },
510         {ST_EXP_RNOU,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_7             },
511         {ST_EXP_TOCI,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_8             },
512         {ST_EXP_DBID,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_9             },
513         {-1,                    -1,                     -1,                     -1,                     NULL            }
514 };      
515         
516 /*---------------------------------------------------------------------------*
517  *      state decode for do_component
518  *---------------------------------------------------------------------------*/
519 static void
520 next_state(int class, int form, int code, int val)
521 {
522         int i;
523
524         for(i=0; ; i++)
525         {
526                 if((statetab[i].currstate > state) ||
527                    (statetab[i].currstate == -1))
528                 {
529                         break;
530                 }
531
532                 if((statetab[i].currstate == state)     &&
533                    (statetab[i].form == form)           &&
534                    (statetab[i].class == class)         &&
535                    (statetab[i].code == code))
536                 {
537                         (*statetab[i].func)(val);
538                         break;
539                 }
540         }
541 }