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