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