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