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