Initial import from FreeBSD RELENG_4:
[games.git] / usr.sbin / i4b / isdndecode / facility.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  *      facility.c - decode Q.932 facilities
28  *      ------------------------------------
29  *
30  *      $Id: facility.c,v 1.5 2000/02/21 15:17:17 hm Exp $
31  *
32  * $FreeBSD: src/usr.sbin/i4b/isdndecode/facility.c,v 1.6.2.1 2001/08/01 17:45:05 obrien Exp $
33  *
34  *      last edit-date: [Mon Feb 21 16:15:43 2000]
35  *
36  *---------------------------------------------------------------------------
37  *
38  *      - Q.932 (03/93) Generic Procedures for the Control of
39  *              ISDN Supplementaty Services
40  *      - Q.950 (03/93) Supplementary Services Protocols, Structure and
41  *              General Principles
42  *      - ETS 300 179 (10/92) Advice Of Charge: charging information during
43  *              the call (AOC-D) supplementary service Service description
44  *      - ETS 300 180 (10/92) Advice Of Charge: charging information at the
45  *              end of call (AOC-E) supplementary service Service description
46  *      - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service
47  *              Functional capabilities and information flows
48  *      - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service
49  *              Digital Subscriber Signalling System No. one (DSS1) protocol
50  *      - X.208 Specification of Abstract Syntax Notation One (ASN.1)
51  *      - X.209 Specification of Basic Encoding Rules for
52  *              Abstract Syntax Notation One (ASN.1) 
53  *      - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag
54  *              1992, 3rd Edition (ISBN 3-89238-062-7) (german !)
55  *
56  *---------------------------------------------------------------------------*/
57
58 #include "decode.h"
59 #include "facility.h"
60
61 static int do_component(int length, char *pbuf);
62 static char *uni_str(int code);
63 static char *opval_str(int val);
64 static char *bid_str(int val);
65 static void next_state(char *pbuf, int class, int form, int code, int val);
66
67 static int byte_len;
68 static unsigned char *byte_buf;
69 static int state;
70
71 /*---------------------------------------------------------------------------*
72  *      decode Q.931/Q.932 facility info element
73  *---------------------------------------------------------------------------*/
74 int
75 q932_facility(char *pbuf, unsigned char *buf)
76 {
77         int len;
78
79         sprintf((pbuf+strlen(pbuf)), "[facility (Q.932): ");
80         
81         buf++;          /* length */
82
83         len = *buf;
84
85         buf++;          /* protocol profile */
86
87         sprintf((pbuf+strlen(pbuf)), "Protocol=");
88         
89         switch(*buf & 0x1f)
90         {
91                 case FAC_PROTO_ROP:
92                         sprintf((pbuf+strlen(pbuf)), "Remote Operations Protocol\n");
93                         break;
94
95                 case FAC_PROTO_CMIP:
96                         sprintf((pbuf+strlen(pbuf)), "CMIP Protocol (Q.941), UNSUPPORTED!\n");
97                         return(len+2);
98                         break;
99
100                 case FAC_PROTO_ACSE:
101                         sprintf((pbuf+strlen(pbuf)), "ACSE Protocol (X.217/X.227), UNSUPPORTED!\n");
102                         return(len+2);
103                         break;
104
105                 default:
106                         sprintf((pbuf+strlen(pbuf)), "Unknown Protocol (val = 0x%x), UNSUPPORTED!\n", *buf & 0x1f);
107                         return(len+2);
108                         break;
109         }
110
111         /* next byte */
112         
113         buf++;
114         len--;
115
116         /* initialize variables for do_component */
117         
118         byte_len = 0;
119         byte_buf = buf;
120         state = ST_EXP_COMP_TYP;        
121
122         /* decode facility */
123         
124         do_component(len, pbuf);
125
126         sprintf((pbuf+(strlen(pbuf)-1)), "]");  /* XXX replace last newline */
127
128         return(len+3);
129 }
130
131 /*---------------------------------------------------------------------------*
132  *      handle a component recursively
133  *---------------------------------------------------------------------------*/
134 static int
135 do_component(int length, char *pbuf)
136 {
137         int comp_tag_class;     /* component tag class */
138         int comp_tag_form;      /* component form: constructor or primitive */
139         int comp_tag_code;      /* component code depending on class */
140         int comp_length = 0;    /* component length */
141
142 #ifdef FAC_DEBUG
143         sprintf((pbuf+strlen(pbuf)), "ENTER - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length);   
144 #endif
145
146 again:
147
148 #ifdef FAC_DEBUG
149         sprintf((pbuf+strlen(pbuf)), "AGAIN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length);
150 #endif
151
152         /*----------------------------------------*/
153         /* first component element: component tag */
154         /*----------------------------------------*/
155         
156         /* tag class bits */
157
158         sprintf((pbuf+strlen(pbuf)), "\t0x%02x Tag: ", *byte_buf);      
159
160         comp_tag_class = (*byte_buf & 0xc0) >> 6;
161         
162         switch(comp_tag_class)
163         {
164                 case FAC_TAGCLASS_UNI:
165                         sprintf((pbuf+strlen(pbuf)), "Universal");
166                         break;
167                 case FAC_TAGCLASS_APW:
168                         sprintf((pbuf+strlen(pbuf)), "Applic-wide");
169                         break;
170                 case FAC_TAGCLASS_COS:
171                         sprintf((pbuf+strlen(pbuf)), "Context-spec");
172                         break;
173                 case FAC_TAGCLASS_PRU:
174                         sprintf((pbuf+strlen(pbuf)), "Private");
175                         break;
176         }
177
178         /* tag form bit */
179
180         comp_tag_form = (*byte_buf & 0x20) > 5;
181         
182         sprintf((pbuf+strlen(pbuf)), ", ");
183
184         if(comp_tag_form == FAC_TAGFORM_CON)
185         {
186                 sprintf((pbuf+strlen(pbuf)), "Constructor");
187         }
188         else
189         {
190                 sprintf((pbuf+strlen(pbuf)), "Primitive");
191         }
192
193         /* tag code bits */
194
195         comp_tag_code = *byte_buf & 0x1f;
196         
197         sprintf((pbuf+strlen(pbuf)), ", ");     
198
199         if(comp_tag_code == 0x1f)
200         {
201                 comp_tag_code = 0;
202                 
203                 byte_buf++;
204                 byte_len++;
205
206                 while(*byte_buf & 0x80)
207                 {
208                         comp_tag_code += (*byte_buf & 0x7f);
209                         byte_buf++;
210                         byte_len++;
211                 }
212                 comp_tag_code += (*byte_buf & 0x7f);
213                 sprintf((pbuf+strlen(pbuf)), "%d (ext)\n", comp_tag_code);
214         }
215         else
216         {
217                 comp_tag_code = (*byte_buf & 0x1f);
218
219                 if(comp_tag_class == FAC_TAGCLASS_UNI)
220                 {
221                         sprintf((pbuf+strlen(pbuf)), "%s (%d)\n", uni_str(comp_tag_code), comp_tag_code);
222                 }
223                 else 
224                 {
225                         sprintf((pbuf+strlen(pbuf)), "code = %d\n", comp_tag_code);
226                 }
227         }
228
229         byte_buf++;
230         byte_len++;
231         
232         /*--------------------------------------------*/
233         /* second component element: component length */
234         /*--------------------------------------------*/
235         
236         sprintf((pbuf+strlen(pbuf)), "\t0x%02x Len: ", *byte_buf);
237
238         comp_length = 0;
239         
240         if(*byte_buf & 0x80)
241         {
242                 int i = *byte_buf & 0x7f;
243
244                 byte_len += i;
245                 
246                 for(;i > 0;i++)
247                 {
248                         byte_buf++;
249                         comp_length += (*byte_buf * (i*256));
250                 }       
251                 sprintf((pbuf+strlen(pbuf)), "%d (long form)\n", comp_length);
252         }
253         else
254         {
255                 comp_length = *byte_buf & 0x7f;
256                 sprintf((pbuf+strlen(pbuf)), "%d (short form)\n", comp_length);
257         }
258
259         next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, -1);
260         
261         byte_len++;
262         byte_buf++;
263         
264         if(comp_length)
265         {
266
267                 /*---------------------------------------------*/
268                 /* third component element: component contents */
269                 /*---------------------------------------------*/
270                         
271                 if(comp_tag_form)       /* == constructor */
272                 {
273                         do_component(comp_length, pbuf);
274                 }
275                 else 
276                 {
277                         int val = 0;            
278                         if(comp_tag_class == FAC_TAGCLASS_UNI)
279                         {
280                                 switch(comp_tag_code)
281                                 {
282                                         case FAC_CODEUNI_INT:
283                                         case FAC_CODEUNI_ENUM:
284                                         case FAC_CODEUNI_BOOL:
285                                                 if(comp_length)
286                                                 {
287                                                         int i;
288                                         
289                                                         sprintf((pbuf+strlen(pbuf)), "\t");
290                                                         
291                                                         for(i = comp_length-1; i >= 0; i--)
292                                                         {
293                                                                 sprintf((pbuf+strlen(pbuf)), "0x%02x ", *byte_buf);
294                                                                 val += (*byte_buf + (i*255));
295                                                                 byte_buf++;
296                                                                 byte_len++;
297                                                                 if(i)
298                                                                         sprintf((pbuf+strlen(pbuf)), "\n\t");
299                                                         }
300                                                         sprintf((pbuf+strlen(pbuf)), "Val: %d\n", val);
301                                                 }
302                                                 break;
303                                         default:        
304                                                 if(comp_length)
305                                                 {
306                                                         int i;
307                                         
308                                                         sprintf((pbuf+strlen(pbuf)), "\t");
309                                                         
310                                                         for(i = comp_length-1; i >= 0; i--)
311                                                         {
312                                                                 sprintf((pbuf+strlen(pbuf)), "0x%02x = %d", *byte_buf, *byte_buf);
313                                                                 if(isprint(*byte_buf))
314                                                                         sprintf((pbuf+strlen(pbuf)), " = '%c'", *byte_buf);
315                                                                 byte_buf++;
316                                                                 byte_len++;
317                                                                 if(i)
318                                                                         sprintf((pbuf+strlen(pbuf)), "\n\t");
319                                                         }
320                                                 }
321                                                 break;
322                                 }
323                         }
324         
325                         else    /* comp_tag_class != FAC_TAGCLASS_UNI */
326                         {
327                                 if(comp_length)
328                                 {
329                                         int i;
330                         
331                                         sprintf((pbuf+strlen(pbuf)), "\t");
332                                         
333                                         for(i = comp_length-1; i >= 0; i--)
334                                         {
335                                                 sprintf((pbuf+strlen(pbuf)), "0x%02x", *byte_buf);
336                                                 val += (*byte_buf + (i*255)); 
337                                                 byte_buf++;
338                                                 byte_len++;
339                                                 if(i)
340                                                         sprintf((pbuf+strlen(pbuf)), "\n\t");
341                                         }
342                                         sprintf((pbuf+strlen(pbuf)), "\n");
343                                 }
344                         }
345                         next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, val);
346                 }
347         }
348         
349 #ifdef FAC_DEBUG
350         sprintf((pbuf+strlen(pbuf)), "PREGOTO - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length);
351 #endif  
352         if(byte_len < length)
353                 goto again;
354 #ifdef FAC_DEBUG
355         sprintf((pbuf+strlen(pbuf)), "RETURN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length);          
356 #endif
357         return(byte_len);
358 }
359
360 /*---------------------------------------------------------------------------*
361  *      print universal id type
362  *---------------------------------------------------------------------------*/
363 static char *uni_str(int code)
364 {
365         static char *tbl[] = {
366                 "BOOLEAN",
367                 "INTEGER",
368                 "BIT STRING",
369                 "OCTET STRING",
370                 "NULL",
371                 "OBJECT IDENTIFIER",
372                 "OBJECT DESCRIPTOR",
373                 "EXTERNAL",
374                 "REAL",
375                 "ENUMERATED",
376                 "RESERVED11",
377                 "RESERVED12",
378                 "RESERVED13",
379                 "RESERVED14",
380                 "RESERVED15",
381                 "SEQUENCE",
382                 "SET",
383                 "NUMERIC STRING",
384                 "PRINTABLE STRING",
385                 "TELETEX STRING",
386                 "ISO646 STRING",
387                 "IA5 STRING",
388                 "GRAPHIC STRING",
389                 "GENERAL STRING"
390         };
391
392         if(code >= 1 && code <= FAC_CODEUNI_GNSTR)
393                 return(tbl[code-1]);
394         else
395                 return("ERROR, Value out of Range!");
396 }
397
398 /*---------------------------------------------------------------------------*
399  *      print operation value 
400  *---------------------------------------------------------------------------*/
401 static char *opval_str(int val)
402 {
403         static char buffer[80];
404         char *r;
405         
406         switch(val)
407         {
408                 case FAC_OPVAL_UUS:
409                         r = "uUs";
410                         break;
411                 case FAC_OPVAL_CUG:
412                         r = "cUGCall";
413                         break;
414                 case FAC_OPVAL_MCID:
415                         r = "mCIDRequest";
416                         break;
417                 case FAC_OPVAL_BTPY:
418                         r = "beginTPY";
419                         break;
420                 case FAC_OPVAL_ETPY:
421                         r = "endTPY";
422                         break;
423                 case FAC_OPVAL_ECT:
424                         r = "eCTRequest";
425                         break;
426                 case FAC_OPVAL_DIV_ACT:
427                         r = "activationDiversion";
428                         break;
429                 case FAC_OPVAL_DIV_DEACT:
430                         r = "deactivationDiversion";
431                         break;
432                 case FAC_OPVAL_DIV_ACTSN:
433                         r = "activationStatusNotificationDiv";
434                         break;
435                 case FAC_OPVAL_DIV_DEACTSN:
436                         r = "deactivationStatusNotificationDiv";
437                         break;
438                 case FAC_OPVAL_DIV_INTER:
439                         r = "interrogationDiversion";
440                         break;
441                 case FAC_OPVAL_DIV_INFO:
442                         r = "diversionInformation";
443                         break;
444                 case FAC_OPVAL_DIV_CALLDEF:
445                         r = "callDeflection";
446                         break;
447                 case FAC_OPVAL_DIV_CALLRER:
448                         r = "callRerouting";
449                         break;
450                 case FAC_OPVAL_DIV_LINF2:
451                         r = "divertingLegInformation2";
452                         break;
453                 case FAC_OPVAL_DIV_INVS:
454                         r = "invokeStatus";
455                         break;
456                 case FAC_OPVAL_DIV_INTER1:
457                         r = "interrogationDiversion1";
458                         break;
459                 case FAC_OPVAL_DIV_LINF1:
460                         r = "divertingLegInformation1";
461                         break;
462                 case FAC_OPVAL_DIV_LINF3:
463                         r = "divertingLegInformation3";
464                         break;
465                 case FAC_OPVAL_ER_CRCO:
466                         r = "explicitReservationCreationControl";
467                         break;
468                 case FAC_OPVAL_ER_MGMT:
469                         r = "explicitReservationManagement";
470                         break;
471                 case FAC_OPVAL_ER_CANC:
472                         r = "explicitReservationCancel";
473                         break;
474                 case FAC_OPVAL_MLPP_QUERY:
475                         r = "mLPP lfb Query";
476                         break;
477                 case FAC_OPVAL_MLPP_CALLR:
478                         r = "mLPP Call Request";
479                         break;
480                 case FAC_OPVAL_MLPP_CALLP:
481                         r = "mLPP Call Preemption";
482                         break;
483                 case FAC_OPVAL_AOC_REQ:
484                         r = "chargingRequest";
485                         break;
486                 case FAC_OPVAL_AOC_S_CUR:
487                         r = "aOCSCurrency";
488                         break;
489                 case FAC_OPVAL_AOC_S_SPC:
490                         r = "aOCSSpecialArrangement";
491                         break;
492                 case FAC_OPVAL_AOC_D_CUR:
493                         r = "aOCDCurrency";
494                         break;
495                 case FAC_OPVAL_AOC_D_UNIT:
496                         r = "aOCDChargingUnit";
497                         break;
498                 case FAC_OPVAL_AOC_E_CUR:
499                         r = "aOCECurrency";
500                         break;
501                 case FAC_OPVAL_AOC_E_UNIT:
502                         r = "aOCEChargingUnit";
503                         break;
504                 case FAC_OPVAL_AOC_IDOFCRG:
505                         r = "identificationOfCharge";
506                         break;
507                 case FAC_OPVAL_CONF_BEG:
508                         r = "beginConf";
509                         break;
510                 case FAC_OPVAL_CONF_ADD:
511                         r = "addConf";
512                         break;
513                 case FAC_OPVAL_CONF_SPLIT:
514                         r = "splitConf";
515                         break;
516                 case FAC_OPVAL_CONF_DROP:
517                         r = "dropConf";
518                         break;
519                 case FAC_OPVAL_CONF_ISOLATE:
520                         r = "isolateConf";
521                         break;
522                 case FAC_OPVAL_CONF_REATT:
523                         r = "reattachConf";
524                         break;
525                 case FAC_OPVAL_CONF_PDISC:
526                         r = "partyDISC";
527                         break;
528                 case FAC_OPVAL_CONF_FCONF:
529                         r = "floatConf";
530                         break;
531                 case FAC_OPVAL_CONF_END:
532                         r = "endConf";
533                         break;
534                 case FAC_OPVAL_CONF_IDCFE:
535                         r = "indentifyConferee";
536                         break;
537                 case FAC_OPVAL_REVC_REQ:
538                         r = "requestREV";
539                         break;
540                 default:
541                         sprintf(buffer, "unknown operation value %d!", val);
542                         r = buffer;
543         }
544         return(r);
545 }
546
547 /*---------------------------------------------------------------------------*
548  *      billing id string
549  *---------------------------------------------------------------------------*/
550 static char *bid_str(int val)
551 {
552         static char buffer[80];
553         char *r;
554         
555         switch(val)
556         {
557                 case 0:
558                         r = "normalCharging";
559                         break;
560                 case 1:
561                         r = "reverseCharging";
562                         break;
563                 case 2:
564                         r = "creditCardCharging";
565                         break;
566                 case 3:
567                         r = "callForwardingUnconditional";
568                         break;
569                 case 4:
570                         r = "callForwardingBusy";
571                         break;
572                 case 5:
573                         r = "callForwardingNoReply";
574                         break;
575                 case 6:
576                         r = "callDeflection";
577                         break;
578                 case 7:
579                         r = "callTransfer";
580                         break;
581                 default:
582                         sprintf(buffer, "unknown billing-id value %d!", val);
583                         r = buffer;
584         }
585         return(r);
586 }
587
588 /*---------------------------------------------------------------------------*
589  *      invoke component
590  *---------------------------------------------------------------------------*/
591 static void
592 F_1_1(char *pbuf, int val)
593 {
594 #ifdef ST_DEBUG
595         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_1, val = %d\n", val);
596 #endif
597         if(val == -1)
598         {
599                 sprintf((pbuf+strlen(pbuf)), "\t          invokeComponent\n");
600                 state = ST_EXP_INV_ID;
601         }
602 }
603
604 /*---------------------------------------------------------------------------*
605  *      return result
606  *---------------------------------------------------------------------------*/
607 static void
608 F_1_2(char *pbuf, int val)
609 {
610 #ifdef ST_DEBUG
611         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_2, val = %d\n", val);
612 #endif
613         if(val == -1)
614         {
615                 sprintf((pbuf+strlen(pbuf)), "\t          returnResult\n");
616                 state = ST_EXP_RR_INV_ID;
617         }
618 }
619 /*---------------------------------------------------------------------------*
620  *      return error
621  *---------------------------------------------------------------------------*/
622 static void
623 F_1_3(char *pbuf, int val)
624 {
625 #ifdef ST_DEBUG
626         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_3, val = %d\n", val);
627 #endif
628         if(val == -1)
629         {
630                 sprintf((pbuf+strlen(pbuf)), "\t          returnError\n");
631                 state = ST_EXP_NIX;
632         }
633 }
634 /*---------------------------------------------------------------------------*
635  *      reject
636  *---------------------------------------------------------------------------*/
637 static void
638 F_1_4(char *pbuf, int val)
639 {
640 #ifdef ST_DEBUG
641         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_4, val = %d\n", val);
642 #endif
643         if(val == -1)
644         {
645                 sprintf((pbuf+strlen(pbuf)), "\t          reject\n");
646                 state = ST_EXP_REJ_INV_ID;
647         }
648 }
649
650 /*---------------------------------------------------------------------------*
651  *      return result: invoke id
652  *---------------------------------------------------------------------------*/
653 static void
654 F_RJ2(char *pbuf, int val)
655 {
656 #ifdef ST_DEBUG
657         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ2, val = %d\n", val);
658 #endif
659         if(val != -1)
660         {
661                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);
662                 state = ST_EXP_REJ_OP_VAL;
663         }
664 }
665
666 /*---------------------------------------------------------------------------*
667  *      reject, general problem
668  *---------------------------------------------------------------------------*/
669 static void
670 F_RJ30(char *pbuf, int val)
671 {
672 #ifdef ST_DEBUG
673         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ30, val = %d\n", val);
674 #endif
675         if(val == -1)
676         {
677                 sprintf((pbuf+strlen(pbuf)), "\t          General problem\n");
678         }
679         else
680         {
681                 switch(val)
682                 {
683                         case 0:
684                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized component\n");
685                                 break;
686                         case 1:
687                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped component\n");
688                                 break;
689                         case 2:
690                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = badly structured component\n");
691                                 break;
692                         default:
693                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
694                                 break;
695                 }
696                 state = ST_EXP_NIX;
697         }
698 }
699
700 /*---------------------------------------------------------------------------*
701  *      reject, invoke problem
702  *---------------------------------------------------------------------------*/
703 static void
704 F_RJ31(char *pbuf, int val)
705 {
706 #ifdef ST_DEBUG
707         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ31, val = %d\n", val);
708 #endif
709         if(val == -1)
710         {
711                 sprintf((pbuf+strlen(pbuf)), "\t          Invoke problem\n");
712         }
713         else
714         {
715                 switch(val)
716                 {
717                         case 0:
718                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = duplicate invocation\n");
719                                 break;
720                         case 1:
721                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized operation\n");
722                                 break;
723                         case 2:
724                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped argument\n");
725                                 break;
726                         case 3:
727                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = resource limitation\n");
728                                 break;
729                         case 4:
730                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = initiator releasing\n");
731                                 break;
732                         case 5:
733                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized linked identifier\n");
734                                 break;
735                         case 6:
736                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = linked resonse unexpected\n");
737                                 break;
738                         case 7:
739                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unexpected child operation\n");
740                                 break;
741                         default:
742                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
743                                 break;
744                 }
745                 state = ST_EXP_NIX;
746         }
747 }
748
749 /*---------------------------------------------------------------------------*
750  *      reject, return result problem
751  *---------------------------------------------------------------------------*/
752 static void
753 F_RJ32(char *pbuf, int val)
754 {
755 #ifdef ST_DEBUG
756         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ32, val = %d\n", val);
757 #endif
758         if(val == -1)
759         {
760                 sprintf((pbuf+strlen(pbuf)), "\t          Return result problem\n");
761         }
762         else
763         {
764                 switch(val)
765                 {
766                         case 0:
767                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized invocation\n");
768                                 break;
769                         case 1:
770                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = return response unexpected\n");
771                                 break;
772                         case 2:
773                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped result\n");
774                                 break;
775                         default:
776                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
777                                 break;
778                 }
779                 state = ST_EXP_NIX;
780         }
781 }
782
783 /*---------------------------------------------------------------------------*
784  *      reject, return error problem
785  *---------------------------------------------------------------------------*/
786 static void
787 F_RJ33(char *pbuf, int val)
788 {
789 #ifdef ST_DEBUG
790         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ33, val = %d\n", val);
791 #endif
792         if(val == -1)
793         {
794                 sprintf((pbuf+strlen(pbuf)), "\t          Return error problem\n");
795         }
796         else
797         {
798                 switch(val)
799                 {
800                         case 0:
801                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized invocation\n");
802                                 break;
803                         case 1:
804                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = error response unexpected\n");
805                                 break;
806                         case 2:
807                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized error\n");
808                                 break;
809                         case 3:
810                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unexpected error\n");
811                                 break;
812                         case 4:
813                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped parameter\n");
814                                 break;
815                         default:
816                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
817                                 break;
818                 }
819                 state = ST_EXP_NIX;
820         }
821 }
822
823 /*---------------------------------------------------------------------------*
824  *      invoke component: invoke id
825  *---------------------------------------------------------------------------*/
826 static void
827 F_2(char *pbuf, int val)
828 {
829 #ifdef ST_DEBUG
830         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_2, val = %d\n", val);
831 #endif
832         if(val != -1)
833         {
834                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);               
835                 state = ST_EXP_OP_VAL;
836         }
837 }
838
839 /*---------------------------------------------------------------------------*
840  *      return result: invoke id
841  *---------------------------------------------------------------------------*/
842 static void
843 F_RR2(char *pbuf, int val)
844 {
845 #ifdef ST_DEBUG
846         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR2, val = %d\n", val);
847 #endif
848         if(val != -1)
849         {
850                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);
851                 state = ST_EXP_RR_OP_VAL;
852         }
853 }
854
855 /*---------------------------------------------------------------------------*
856  *      invoke component: operation value
857  *---------------------------------------------------------------------------*/
858 static void
859 F_3(char *pbuf, int val)
860 {
861 #ifdef ST_DEBUG
862         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_3, val = %d\n", val);
863 #endif
864         if(val != -1)
865         {
866                 sprintf((pbuf+strlen(pbuf)), "\t          Operation Value = %s (%d)\n", opval_str(val), val);
867                 state = ST_EXP_INFO;
868         }
869 }
870
871 /*---------------------------------------------------------------------------*
872  *      return result: operation value
873  *---------------------------------------------------------------------------*/
874 static void
875 F_RR3(char *pbuf, int val)
876 {
877 #ifdef ST_DEBUG
878         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR3, val = %d\n", val);
879 #endif
880         if(val != -1)
881         {
882                 sprintf((pbuf+strlen(pbuf)), "\t          Operation Value = %s (%d)\n", opval_str(val), val);
883                 state = ST_EXP_RR_RESULT;
884         }
885 }
886
887 /*---------------------------------------------------------------------------*
888  *      return result: RESULT
889  *---------------------------------------------------------------------------*/
890 static void
891 F_RRR(char *pbuf, int val)
892 {
893 #ifdef ST_DEBUG
894         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RRR, val = %d\n", val);
895 #endif
896         state = ST_EXP_NIX;
897 }
898
899 /*---------------------------------------------------------------------------*
900  *
901  *---------------------------------------------------------------------------*/
902 static void
903 F_4(char *pbuf, int val)
904 {
905 #ifdef ST_DEBUG
906         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4, val = %d\n", val);  
907 #endif
908         if(val == -1)
909         {
910                 sprintf((pbuf+strlen(pbuf)), "\t          specificChargingUnits\n");
911                 state = ST_EXP_RUL;
912         }
913 }
914
915 /*---------------------------------------------------------------------------*
916  *
917  *---------------------------------------------------------------------------*/
918 static void
919 F_4_1(char *pbuf, int val)
920 {
921 #ifdef ST_DEBUG
922         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_1, val = %d\n", val);        
923 #endif
924         if(val == -1)
925         {
926                 sprintf((pbuf+strlen(pbuf)), "\t          freeOfCharge\n");
927                 state = ST_EXP_NIX;
928         }
929 }
930
931 /*---------------------------------------------------------------------------*
932  *
933  *---------------------------------------------------------------------------*/
934 static void
935 F_4_2(char *pbuf, int val)
936 {
937 #ifdef ST_DEBUG
938         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_2, val = %d\n", val);        
939 #endif
940         if(val == -1)
941         {
942                 sprintf((pbuf+strlen(pbuf)), "\t          chargeNotAvailable\n");
943                 state = ST_EXP_NIX;
944         }
945 }
946
947 /*---------------------------------------------------------------------------*
948  *
949  *---------------------------------------------------------------------------*/
950 static void
951 F_5(char *pbuf, int val)
952 {
953 #ifdef ST_DEBUG
954         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_5, val = %d\n", val);  
955 #endif
956         if(val == -1)
957         {
958                 sprintf((pbuf+strlen(pbuf)), "\t          recordedUnitsList [1]\n");
959                 state = ST_EXP_RU;
960         }
961 }
962
963 /*---------------------------------------------------------------------------*
964  *
965  *---------------------------------------------------------------------------*/
966 static void
967 F_6(char *pbuf, int val)
968 {
969 #ifdef ST_DEBUG
970         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_6, val = %d\n", val);  
971 #endif
972         if(val == -1)
973         {
974                 sprintf((pbuf+strlen(pbuf)), "\t          RecordedUnits\n");
975                 state = ST_EXP_RNOU;
976         }
977 }
978
979 /*---------------------------------------------------------------------------*
980  *
981  *---------------------------------------------------------------------------*/
982 static void
983 F_7(char *pbuf, int val)
984 {
985 #ifdef ST_DEBUG
986         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_7, val = %d\n", val);  
987 #endif
988         if(val != -1)
989         {
990                 sprintf((pbuf+strlen(pbuf)), "\t          NumberOfUnits = %d\n", val);
991                 state = ST_EXP_TOCI;
992         }
993 }
994
995 /*---------------------------------------------------------------------------*
996  *
997  *---------------------------------------------------------------------------*/
998 static void
999 F_8(char *pbuf, int val)
1000 {
1001 #ifdef ST_DEBUG
1002         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_8, val = %d\n", val);  
1003 #endif
1004         if(val != -1)
1005         {
1006                 sprintf((pbuf+strlen(pbuf)), "\t          typeOfChargingInfo = %s\n", val == 0 ? "subTotal" : "total");
1007                 state = ST_EXP_DBID;
1008         }
1009 }
1010
1011 /*---------------------------------------------------------------------------*
1012  *
1013  *---------------------------------------------------------------------------*/
1014 static void
1015 F_9(char *pbuf, int val)
1016 {
1017 #ifdef ST_DEBUG
1018         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_9, val = %d\n", val);  
1019 #endif
1020         if(val != -1)
1021         {
1022                 sprintf((pbuf+strlen(pbuf)), "\t          AOCDBillingId = %s (%d)\n", bid_str(val), val);
1023                 state = ST_EXP_NIX;
1024         }
1025 }
1026
1027 /*---------------------------------------------------------------------------*
1028  *      state table
1029  *---------------------------------------------------------------------------*/
1030 static struct statetab {
1031         int currstate;                  /* input: current state we are in */
1032         int form;                       /* input: current tag form */
1033         int class;                      /* input: current tag class */
1034         int code;                       /* input: current tag code */
1035         void (*func)(char *,int);       /* output: func to exec */
1036 } statetab[] = {
1037
1038 /*       current state          tag form                tag class               tag code                function        */
1039 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
1040
1041 /* invoke */
1042
1043         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_1_1           },
1044         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       2,                      F_1_2           },
1045         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       3,                      F_1_3           },
1046         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       4,                      F_1_4           },
1047         {ST_EXP_INV_ID,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_2             },
1048         {ST_EXP_OP_VAL,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_3             },
1049         {ST_EXP_INFO,           FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_4             },
1050         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_NULL,       F_4_1           },
1051         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_4_2           },
1052         {ST_EXP_RUL,            FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_5             },
1053         {ST_EXP_RU,             FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_6             },
1054         {ST_EXP_RNOU,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_7             },
1055         {ST_EXP_TOCI,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_8             },
1056         {ST_EXP_DBID,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_9             },
1057
1058 /* return result */
1059         
1060         {ST_EXP_RR_INV_ID,      FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RR2           },
1061         {ST_EXP_RR_OP_VAL,      FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RR3           },
1062         {ST_EXP_RR_RESULT,      FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SET,        F_RRR           },
1063
1064 /*       current state          tag form                tag class               tag code                function        */
1065 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
1066 /* reject */
1067         
1068         {ST_EXP_REJ_INV_ID,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RJ2           },
1069         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       0,                      F_RJ30          },
1070         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_RJ31          },
1071         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_RJ32          },
1072         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_RJ33          },
1073
1074 /* end */
1075         
1076         {-1,                    -1,                     -1,                     -1,                     NULL            }
1077 };      
1078         
1079 /*---------------------------------------------------------------------------*
1080  *      state decode for do_component
1081  *---------------------------------------------------------------------------*/
1082 static void
1083 next_state(char *pbuf, int class, int form, int code, int val)
1084 {
1085         int i;
1086
1087 #ifdef ST_DEBUG
1088         sprintf((pbuf+strlen(pbuf)), "next_state: class=%d, form=%d, code=%d, val=%d\n", class, form, code, val);
1089 #endif
1090
1091         for(i=0; ; i++)
1092         {
1093                 if((statetab[i].currstate > state) ||
1094                    (statetab[i].currstate == -1))
1095                 {
1096                         break;
1097                 }
1098
1099                 if((statetab[i].currstate == state)     &&
1100                    (statetab[i].form == form)           &&
1101                    (statetab[i].class == class)         &&
1102                    (statetab[i].code == code))
1103                 {
1104                         (*statetab[i].func)(pbuf, val);
1105                         break;
1106                 }
1107         }
1108 }
1109
1110 /* EOF */
1111