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