Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / net / i4b / layer3 / i4b_q932fac.c
1 /*
2  * Copyright (c) 1997, 2000 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  *      i4b_q932fac.c - Q932 facility handling
28  *      --------------------------------------
29  *
30  *      $Id: i4b_q932fac.c,v 1.11 2000/08/24 11:48:58 hm Exp $ 
31  *
32  * $FreeBSD: src/sys/i4b/layer3/i4b_q932fac.c,v 1.6.2.1 2001/08/10 14:08:42 obrien Exp $
33  *
34  *      last edit-date: [Mon May 29 16:57:04 2000]
35  *
36  *---------------------------------------------------------------------------*/
37
38 #ifdef __FreeBSD__
39 #include "i4bq931.h"
40 #else
41 #define NI4BQ931        1
42 #endif
43 #if NI4BQ931 > 0
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/mbuf.h>
48
49 #if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000
50 #include <sys/callout.h>
51 #endif
52
53 #ifdef __FreeBSD__
54 #include <machine/i4b_debug.h>
55 #include <machine/i4b_ioctl.h>
56 #else
57 #include <i4b/i4b_debug.h>
58 #include <i4b/i4b_ioctl.h>
59 #endif
60
61 #include <i4b/include/i4b_l3l4.h>
62
63 #include <i4b/layer3/i4b_l3.h>
64 #include <i4b/layer3/i4b_q932fac.h>
65
66
67 static int do_component(int length);
68 static void next_state(int class, int form, int code, int val);
69
70 static int byte_len;
71 static unsigned char *byte_buf;
72 static int state;
73
74 static int units;
75 static int operation_value;
76
77 /*---------------------------------------------------------------------------*
78  *      decode Q.931/Q.932 facility info element
79  *---------------------------------------------------------------------------*/
80 int
81 i4b_aoc(unsigned char *buf, call_desc_t *cd)
82 {
83         int len;
84
85         cd->units_type = CHARGE_INVALID;
86         cd->units = -1;                 
87         
88         buf++;          /* length */
89
90         len = *buf;
91
92         buf++;          /* protocol profile */
93
94         switch(*buf & 0x1f)
95         {
96                 case FAC_PROTO_ROP:
97                         break;
98
99                 case FAC_PROTO_CMIP:
100                         NDBGL3(L3_A_MSG, "CMIP Protocol (Q.941), UNSUPPORTED");
101                         return(-1);
102                         break;
103
104                 case FAC_PROTO_ACSE:
105                         NDBGL3(L3_A_MSG, "ACSE Protocol (X.217/X.227), UNSUPPORTED!");
106                         return(-1);
107                         break;
108
109                 default:
110                         NDBGL3(L3_A_ERR, "Unknown Protocol, UNSUPPORTED!");
111                         return(-1);
112                         break;
113         }
114
115         NDBGL3(L3_A_MSG, "Remote Operations Protocol");
116
117         /* next byte */
118         
119         buf++;
120         len--;
121
122         /* initialize variables for do_component */
123         
124         byte_len = 0;
125         byte_buf = buf;
126         state = ST_EXP_COMP_TYP;        
127
128         /* decode facility */
129         
130         do_component(len);
131
132         switch(operation_value)
133         {
134                 case FAC_OPVAL_AOC_D_CUR:
135                         cd->units_type = CHARGE_AOCD;
136                         cd->units = 0;
137                         return(0);
138                         break;
139                         
140                 case FAC_OPVAL_AOC_D_UNIT:
141                         cd->units_type = CHARGE_AOCD;
142                         cd->units = units;
143                         return(0);
144                         break;
145                         
146                 case FAC_OPVAL_AOC_E_CUR:
147                         cd->units_type = CHARGE_AOCE;
148                         cd->units = 0;
149                         return(0);
150                         break;
151                         
152                 case FAC_OPVAL_AOC_E_UNIT:
153                         cd->units_type = CHARGE_AOCE;
154                         cd->units = units;
155                         return(0);
156                         break;
157
158                 default:
159                         cd->units_type = CHARGE_INVALID;
160                         cd->units = -1;
161                         return(-1);
162                         break;
163         }
164         return(-1);     
165 }
166
167 /*---------------------------------------------------------------------------*
168  *      handle a component recursively
169  *---------------------------------------------------------------------------*/
170 static int
171 do_component(int length)
172 {
173         int comp_tag_class;     /* component tag class */
174         int comp_tag_form;      /* component form: constructor or primitive */
175         int comp_tag_code;      /* component code depending on class */
176         int comp_length = 0;    /* component length */
177
178 again:
179
180         /*----------------------------------------*/
181         /* first component element: component tag */
182         /*----------------------------------------*/
183         
184         /* tag class bits */
185
186         comp_tag_class = (*byte_buf & 0xc0) >> 6;
187         
188         switch(comp_tag_class)
189         {
190                 case FAC_TAGCLASS_UNI:
191                         break;
192                 case FAC_TAGCLASS_APW:
193                         break;
194                 case FAC_TAGCLASS_COS:
195                         break;
196                 case FAC_TAGCLASS_PRU:
197                         break;
198         }
199
200         /* tag form bit */
201
202         comp_tag_form = (*byte_buf & 0x20) > 5;
203         
204         /* tag code bits */
205
206         comp_tag_code = *byte_buf & 0x1f;
207         
208         if(comp_tag_code == 0x1f)
209         {
210                 comp_tag_code = 0;
211                 
212                 byte_buf++;
213                 byte_len++;
214
215                 while(*byte_buf & 0x80)
216                 {
217                         comp_tag_code += (*byte_buf & 0x7f);
218                         byte_buf++;
219                         byte_len++;
220                 }
221                 comp_tag_code += (*byte_buf & 0x7f);
222         }
223         else
224         {
225                 comp_tag_code = (*byte_buf & 0x1f);
226         }
227
228         byte_buf++;
229         byte_len++;
230         
231         /*--------------------------------------------*/
232         /* second component element: component length */
233         /*--------------------------------------------*/
234         
235         comp_length = 0;
236         
237         if(*byte_buf & 0x80)
238         {
239                 int i = *byte_buf & 0x7f;
240
241                 byte_len += i;
242                 
243                 for(;i > 0;i++)
244                 {
245                         byte_buf++;
246                         comp_length += (*byte_buf * (i*256));
247                 }       
248         }
249         else
250         {
251                 comp_length = *byte_buf & 0x7f;
252         }
253
254         next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1);
255         
256         byte_len++;
257         byte_buf++;
258         
259         /*---------------------------------------------*/
260         /* third component element: component contents */
261         /*---------------------------------------------*/
262
263         if(comp_tag_form)       /* == constructor */
264         {
265                 do_component(comp_length);
266         }
267         else 
268         {
269                 int val = 0;            
270                 if(comp_tag_class == FAC_TAGCLASS_UNI)
271                 {
272                         switch(comp_tag_code)
273                         {
274                                 case FAC_CODEUNI_INT:
275                                 case FAC_CODEUNI_ENUM:
276                                 case FAC_CODEUNI_BOOL:                          
277                                         if(comp_length)
278                                         {
279                                                 int i;
280                                 
281                                                 for(i = comp_length-1; i >= 0; i--)
282                                                 {
283                                                         val += (*byte_buf + (i*255));
284                                                         byte_buf++;
285                                                         byte_len++;
286                                                 }
287                                         }
288                                         break;
289                                 default:        
290                                         if(comp_length)
291                                         {
292                                                 int i;
293                                 
294                                                 for(i = comp_length-1; i >= 0; i--)
295                                                 {
296                                                         byte_buf++;
297                                                         byte_len++;
298                                                 }
299                                         }
300                                         break;
301                         }
302                 }
303
304                 else    /* comp_tag_class != FAC_TAGCLASS_UNI */
305                 {
306                         if(comp_length)
307                         {
308                                 int i;
309                 
310                                 for(i = comp_length-1; i >= 0; i--)
311                                 {
312                                         val += (*byte_buf + (i*255)); 
313                                         byte_buf++;
314                                         byte_len++;
315                                 }
316                         }
317                 }
318                 next_state(comp_tag_class, comp_tag_form, comp_tag_code, val);
319         }
320
321         if(byte_len < length)
322                 goto again;
323
324         return(byte_len);
325 }
326
327 /*---------------------------------------------------------------------------*
328  *      invoke component
329  *---------------------------------------------------------------------------*/
330 static void
331 F_1_1(int val)
332 {
333         if(val == -1)
334         {
335                 state = ST_EXP_INV_ID;
336         }
337 }
338
339 /*---------------------------------------------------------------------------*
340  *      return result
341  *---------------------------------------------------------------------------*/
342 static void
343 F_1_2(int val)
344 {
345         if(val == -1)
346                 state = ST_EXP_NIX;
347 }
348 /*---------------------------------------------------------------------------*
349  *      return error
350  *---------------------------------------------------------------------------*/
351 static void
352 F_1_3(int val)
353 {
354         if(val == -1)
355                 state = ST_EXP_NIX;
356 }
357 /*---------------------------------------------------------------------------*
358  *      reject
359  *---------------------------------------------------------------------------*/
360 static void
361 F_1_4(int val)
362 {
363         if(val == -1)
364                 state = ST_EXP_NIX;
365 }
366
367 /*---------------------------------------------------------------------------*
368  *      invoke id
369  *---------------------------------------------------------------------------*/
370 static void
371 F_2(int val)
372 {
373         if(val != -1)
374         {
375                 NDBGL3(L3_A_MSG, "Invoke ID = %d", val);
376                 state = ST_EXP_OP_VAL;
377         }
378 }
379
380 /*---------------------------------------------------------------------------*
381  *      operation value
382  *---------------------------------------------------------------------------*/
383 static void
384 F_3(int val)
385 {
386         if(val != -1)
387         {
388                 NDBGL3(L3_A_MSG, "Operation Value = %d", val);
389         
390                 operation_value = val;
391                 
392                 if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT))
393                 {
394                         units = 0;
395                         state = ST_EXP_INFO;
396                 }
397                 else
398                 {
399                         state = ST_EXP_NIX;
400                 }
401         }
402 }
403
404 /*---------------------------------------------------------------------------*
405  *      specific charging units
406  *---------------------------------------------------------------------------*/
407 static void
408 F_4(int val)
409 {
410         if(val == -1)
411                 state = ST_EXP_RUL;
412 }
413
414 /*---------------------------------------------------------------------------*
415  *      free of charge
416  *---------------------------------------------------------------------------*/
417 static void
418 F_4_1(int val)
419 {
420         if(val == -1)
421         {
422                 NDBGL3(L3_A_MSG, "Free of Charge");
423                 /* units = 0; XXXX */
424                 state = ST_EXP_NIX;
425         }
426 }
427
428 /*---------------------------------------------------------------------------*
429  *      charge not available
430  *---------------------------------------------------------------------------*/
431 static void
432 F_4_2(int val)
433 {
434         if(val == -1)
435         {
436                 NDBGL3(L3_A_MSG, "Charge not available");
437                 /* units = -1;  XXXXXX ??? */
438                 state = ST_EXP_NIX;
439         }
440 }
441
442 /*---------------------------------------------------------------------------*
443  *      recorded units list
444  *---------------------------------------------------------------------------*/
445 static void
446 F_5(int val)
447 {
448         if(val == -1)
449                 state = ST_EXP_RU;
450 }
451
452 /*---------------------------------------------------------------------------*
453  *      recorded units
454  *---------------------------------------------------------------------------*/
455 static void
456 F_6(int val)
457 {
458         if(val == -1)
459                 state = ST_EXP_RNOU;
460 }
461
462 /*---------------------------------------------------------------------------*
463  *      number of units
464  *---------------------------------------------------------------------------*/
465 static void
466 F_7(int val)
467 {
468         if(val != -1)
469         {
470                 NDBGL3(L3_A_MSG, "Number of Units = %d", val);
471                 units = val;
472                 state = ST_EXP_TOCI;
473         }
474 }
475
476 /*---------------------------------------------------------------------------*
477  *      subtotal/total
478  *---------------------------------------------------------------------------*/
479 static void
480 F_8(int val)
481 {
482         if(val != -1)
483         {
484                 NDBGL3(L3_A_MSG, "Subtotal/Total = %d", val);
485                 /* type_of_charge = val; */
486                 state = ST_EXP_DBID;
487         }
488 }
489
490 /*---------------------------------------------------------------------------*
491  *      billing_id
492  *---------------------------------------------------------------------------*/
493 static void
494 F_9(int val)
495 {
496         if(val != -1)
497         {
498                 NDBGL3(L3_A_MSG, "Billing ID = %d", val);
499                 /* billing_id = val; */
500                 state = ST_EXP_NIX;
501         }
502 }
503
504 /*---------------------------------------------------------------------------*
505  *
506  *---------------------------------------------------------------------------*/
507 static struct statetab {
508         int currstate;          /* input: current state we are in */
509         int form;               /* input: current tag form */
510         int class;              /* input: current tag class */
511         int code;               /* input: current tag code */
512         void (*func)(int);      /* output: func to exec */
513 } statetab[] = {
514
515 /*       current state          tag form                tag class               tag code                function        */
516 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
517         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_1_1           },
518         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       2,                      F_1_2           },
519         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       3,                      F_1_3           },
520         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       4,                      F_1_4           },
521         {ST_EXP_INV_ID,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_2             },
522         {ST_EXP_OP_VAL,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_3             },
523         {ST_EXP_INFO,           FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_4             },
524         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_NULL,       F_4_1           },
525         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_4_2           },
526         {ST_EXP_RUL,            FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_5             },
527         {ST_EXP_RU,             FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_6             },
528         {ST_EXP_RNOU,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_7             },
529         {ST_EXP_TOCI,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_8             },
530         {ST_EXP_DBID,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_9             },
531         {-1,                    -1,                     -1,                     -1,                     NULL            }
532 };      
533         
534 /*---------------------------------------------------------------------------*
535  *      state decode for do_component
536  *---------------------------------------------------------------------------*/
537 static void
538 next_state(int class, int form, int code, int val)
539 {
540         int i;
541
542         for(i=0; ; i++)
543         {
544                 if((statetab[i].currstate > state) ||
545                    (statetab[i].currstate == -1))
546                 {
547                         break;
548                 }
549
550                 if((statetab[i].currstate == state)     &&
551                    (statetab[i].form == form)           &&
552                    (statetab[i].class == class)         &&
553                    (statetab[i].code == code))
554                 {
555                         (*statetab[i].func)(val);
556                         break;
557                 }
558         }
559 }
560
561 #endif /* NI4BQ931 > 0 */