Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[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.2 2003/06/17 04:29:55 dillon 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 *uni_str(int code)
374 {
375         static char *tbl[] = {
376                 "BOOLEAN",
377                 "INTEGER",
378                 "BIT STRING",
379                 "OCTET STRING",
380                 "NULL",
381                 "OBJECT IDENTIFIER",
382                 "OBJECT DESCRIPTOR",
383                 "EXTERNAL",
384                 "REAL",
385                 "ENUMERATED",
386                 "RESERVED11",
387                 "RESERVED12",
388                 "RESERVED13",
389                 "RESERVED14",
390                 "RESERVED15",
391                 "SEQUENCE",
392                 "SET",
393                 "NUMERIC STRING",
394                 "PRINTABLE STRING",
395                 "TELETEX STRING",
396                 "ISO646 STRING",
397                 "IA5 STRING",
398                 "GRAPHIC STRING",
399                 "GENERAL STRING"
400         };
401
402         if(code >= 1 && code <= FAC_CODEUNI_GNSTR)
403                 return(tbl[code-1]);
404         else
405                 return("ERROR, Value out of Range!");
406 }
407
408 /*---------------------------------------------------------------------------*
409  *      print operation value 
410  *---------------------------------------------------------------------------*/
411 static char *opval_str(int val)
412 {
413         static char buffer[80];
414         char *r;
415         
416         switch(val)
417         {
418                 case FAC_OPVAL_UUS:
419                         r = "uUs";
420                         break;
421                 case FAC_OPVAL_CUG:
422                         r = "cUGCall";
423                         break;
424                 case FAC_OPVAL_MCID:
425                         r = "mCIDRequest";
426                         break;
427                 case FAC_OPVAL_BTPY:
428                         r = "beginTPY";
429                         break;
430                 case FAC_OPVAL_ETPY:
431                         r = "endTPY";
432                         break;
433                 case FAC_OPVAL_ECT:
434                         r = "eCTRequest";
435                         break;
436                 case FAC_OPVAL_DIV_ACT:
437                         r = "activationDiversion";
438                         break;
439                 case FAC_OPVAL_DIV_DEACT:
440                         r = "deactivationDiversion";
441                         break;
442                 case FAC_OPVAL_DIV_ACTSN:
443                         r = "activationStatusNotificationDiv";
444                         break;
445                 case FAC_OPVAL_DIV_DEACTSN:
446                         r = "deactivationStatusNotificationDiv";
447                         break;
448                 case FAC_OPVAL_DIV_INTER:
449                         r = "interrogationDiversion";
450                         break;
451                 case FAC_OPVAL_DIV_INFO:
452                         r = "diversionInformation";
453                         break;
454                 case FAC_OPVAL_DIV_CALLDEF:
455                         r = "callDeflection";
456                         break;
457                 case FAC_OPVAL_DIV_CALLRER:
458                         r = "callRerouting";
459                         break;
460                 case FAC_OPVAL_DIV_LINF2:
461                         r = "divertingLegInformation2";
462                         break;
463                 case FAC_OPVAL_DIV_INVS:
464                         r = "invokeStatus";
465                         break;
466                 case FAC_OPVAL_DIV_INTER1:
467                         r = "interrogationDiversion1";
468                         break;
469                 case FAC_OPVAL_DIV_LINF1:
470                         r = "divertingLegInformation1";
471                         break;
472                 case FAC_OPVAL_DIV_LINF3:
473                         r = "divertingLegInformation3";
474                         break;
475                 case FAC_OPVAL_ER_CRCO:
476                         r = "explicitReservationCreationControl";
477                         break;
478                 case FAC_OPVAL_ER_MGMT:
479                         r = "explicitReservationManagement";
480                         break;
481                 case FAC_OPVAL_ER_CANC:
482                         r = "explicitReservationCancel";
483                         break;
484                 case FAC_OPVAL_MLPP_QUERY:
485                         r = "mLPP lfb Query";
486                         break;
487                 case FAC_OPVAL_MLPP_CALLR:
488                         r = "mLPP Call Request";
489                         break;
490                 case FAC_OPVAL_MLPP_CALLP:
491                         r = "mLPP Call Preemption";
492                         break;
493                 case FAC_OPVAL_AOC_REQ:
494                         r = "chargingRequest";
495                         break;
496                 case FAC_OPVAL_AOC_S_CUR:
497                         r = "aOCSCurrency";
498                         break;
499                 case FAC_OPVAL_AOC_S_SPC:
500                         r = "aOCSSpecialArrangement";
501                         break;
502                 case FAC_OPVAL_AOC_D_CUR:
503                         r = "aOCDCurrency";
504                         break;
505                 case FAC_OPVAL_AOC_D_UNIT:
506                         r = "aOCDChargingUnit";
507                         break;
508                 case FAC_OPVAL_AOC_E_CUR:
509                         r = "aOCECurrency";
510                         break;
511                 case FAC_OPVAL_AOC_E_UNIT:
512                         r = "aOCEChargingUnit";
513                         break;
514                 case FAC_OPVAL_AOC_IDOFCRG:
515                         r = "identificationOfCharge";
516                         break;
517                 case FAC_OPVAL_CONF_BEG:
518                         r = "beginConf";
519                         break;
520                 case FAC_OPVAL_CONF_ADD:
521                         r = "addConf";
522                         break;
523                 case FAC_OPVAL_CONF_SPLIT:
524                         r = "splitConf";
525                         break;
526                 case FAC_OPVAL_CONF_DROP:
527                         r = "dropConf";
528                         break;
529                 case FAC_OPVAL_CONF_ISOLATE:
530                         r = "isolateConf";
531                         break;
532                 case FAC_OPVAL_CONF_REATT:
533                         r = "reattachConf";
534                         break;
535                 case FAC_OPVAL_CONF_PDISC:
536                         r = "partyDISC";
537                         break;
538                 case FAC_OPVAL_CONF_FCONF:
539                         r = "floatConf";
540                         break;
541                 case FAC_OPVAL_CONF_END:
542                         r = "endConf";
543                         break;
544                 case FAC_OPVAL_CONF_IDCFE:
545                         r = "indentifyConferee";
546                         break;
547                 case FAC_OPVAL_REVC_REQ:
548                         r = "requestREV";
549                         break;
550                 default:
551                         sprintf(buffer, "unknown operation value %d!", val);
552                         r = buffer;
553         }
554         return(r);
555 }
556
557 /*---------------------------------------------------------------------------*
558  *      billing id string
559  *---------------------------------------------------------------------------*/
560 static char *bid_str(int val)
561 {
562         static char buffer[80];
563         char *r;
564         
565         switch(val)
566         {
567                 case 0:
568                         r = "normalCharging";
569                         break;
570                 case 1:
571                         r = "reverseCharging";
572                         break;
573                 case 2:
574                         r = "creditCardCharging";
575                         break;
576                 case 3:
577                         r = "callForwardingUnconditional";
578                         break;
579                 case 4:
580                         r = "callForwardingBusy";
581                         break;
582                 case 5:
583                         r = "callForwardingNoReply";
584                         break;
585                 case 6:
586                         r = "callDeflection";
587                         break;
588                 case 7:
589                         r = "callTransfer";
590                         break;
591                 default:
592                         sprintf(buffer, "unknown billing-id value %d!", val);
593                         r = buffer;
594         }
595         return(r);
596 }
597
598 /*---------------------------------------------------------------------------*
599  *      invoke component
600  *---------------------------------------------------------------------------*/
601 static void
602 F_1_1(char *pbuf, int val)
603 {
604 #ifdef ST_DEBUG
605         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_1, val = %d\n", val);
606 #endif
607         if(val == -1)
608         {
609                 sprintf((pbuf+strlen(pbuf)), "\t          invokeComponent\n");
610                 state = ST_EXP_INV_ID;
611         }
612 }
613
614 /*---------------------------------------------------------------------------*
615  *      return result
616  *---------------------------------------------------------------------------*/
617 static void
618 F_1_2(char *pbuf, int val)
619 {
620 #ifdef ST_DEBUG
621         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_2, val = %d\n", val);
622 #endif
623         if(val == -1)
624         {
625                 sprintf((pbuf+strlen(pbuf)), "\t          returnResult\n");
626                 state = ST_EXP_RR_INV_ID;
627         }
628 }
629 /*---------------------------------------------------------------------------*
630  *      return error
631  *---------------------------------------------------------------------------*/
632 static void
633 F_1_3(char *pbuf, int val)
634 {
635 #ifdef ST_DEBUG
636         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_3, val = %d\n", val);
637 #endif
638         if(val == -1)
639         {
640                 sprintf((pbuf+strlen(pbuf)), "\t          returnError\n");
641                 state = ST_EXP_NIX;
642         }
643 }
644 /*---------------------------------------------------------------------------*
645  *      reject
646  *---------------------------------------------------------------------------*/
647 static void
648 F_1_4(char *pbuf, int val)
649 {
650 #ifdef ST_DEBUG
651         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_4, val = %d\n", val);
652 #endif
653         if(val == -1)
654         {
655                 sprintf((pbuf+strlen(pbuf)), "\t          reject\n");
656                 state = ST_EXP_REJ_INV_ID;
657         }
658 }
659
660 /*---------------------------------------------------------------------------*
661  *      return result: invoke id
662  *---------------------------------------------------------------------------*/
663 static void
664 F_RJ2(char *pbuf, int val)
665 {
666 #ifdef ST_DEBUG
667         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ2, val = %d\n", val);
668 #endif
669         if(val != -1)
670         {
671                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);
672                 state = ST_EXP_REJ_OP_VAL;
673         }
674 }
675
676 /*---------------------------------------------------------------------------*
677  *      reject, general problem
678  *---------------------------------------------------------------------------*/
679 static void
680 F_RJ30(char *pbuf, int val)
681 {
682 #ifdef ST_DEBUG
683         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ30, val = %d\n", val);
684 #endif
685         if(val == -1)
686         {
687                 sprintf((pbuf+strlen(pbuf)), "\t          General problem\n");
688         }
689         else
690         {
691                 switch(val)
692                 {
693                         case 0:
694                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized component\n");
695                                 break;
696                         case 1:
697                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped component\n");
698                                 break;
699                         case 2:
700                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = badly structured component\n");
701                                 break;
702                         default:
703                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
704                                 break;
705                 }
706                 state = ST_EXP_NIX;
707         }
708 }
709
710 /*---------------------------------------------------------------------------*
711  *      reject, invoke problem
712  *---------------------------------------------------------------------------*/
713 static void
714 F_RJ31(char *pbuf, int val)
715 {
716 #ifdef ST_DEBUG
717         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ31, val = %d\n", val);
718 #endif
719         if(val == -1)
720         {
721                 sprintf((pbuf+strlen(pbuf)), "\t          Invoke problem\n");
722         }
723         else
724         {
725                 switch(val)
726                 {
727                         case 0:
728                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = duplicate invocation\n");
729                                 break;
730                         case 1:
731                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized operation\n");
732                                 break;
733                         case 2:
734                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped argument\n");
735                                 break;
736                         case 3:
737                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = resource limitation\n");
738                                 break;
739                         case 4:
740                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = initiator releasing\n");
741                                 break;
742                         case 5:
743                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized linked identifier\n");
744                                 break;
745                         case 6:
746                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = linked resonse unexpected\n");
747                                 break;
748                         case 7:
749                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unexpected child operation\n");
750                                 break;
751                         default:
752                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
753                                 break;
754                 }
755                 state = ST_EXP_NIX;
756         }
757 }
758
759 /*---------------------------------------------------------------------------*
760  *      reject, return result problem
761  *---------------------------------------------------------------------------*/
762 static void
763 F_RJ32(char *pbuf, int val)
764 {
765 #ifdef ST_DEBUG
766         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ32, val = %d\n", val);
767 #endif
768         if(val == -1)
769         {
770                 sprintf((pbuf+strlen(pbuf)), "\t          Return result problem\n");
771         }
772         else
773         {
774                 switch(val)
775                 {
776                         case 0:
777                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized invocation\n");
778                                 break;
779                         case 1:
780                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = return response unexpected\n");
781                                 break;
782                         case 2:
783                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped result\n");
784                                 break;
785                         default:
786                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
787                                 break;
788                 }
789                 state = ST_EXP_NIX;
790         }
791 }
792
793 /*---------------------------------------------------------------------------*
794  *      reject, return error problem
795  *---------------------------------------------------------------------------*/
796 static void
797 F_RJ33(char *pbuf, int val)
798 {
799 #ifdef ST_DEBUG
800         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RJ33, val = %d\n", val);
801 #endif
802         if(val == -1)
803         {
804                 sprintf((pbuf+strlen(pbuf)), "\t          Return error problem\n");
805         }
806         else
807         {
808                 switch(val)
809                 {
810                         case 0:
811                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized invocation\n");
812                                 break;
813                         case 1:
814                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = error response unexpected\n");
815                                 break;
816                         case 2:
817                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unrecognized error\n");
818                                 break;
819                         case 3:
820                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unexpected error\n");
821                                 break;
822                         case 4:
823                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = mistyped parameter\n");
824                                 break;
825                         default:
826                                 sprintf((pbuf+strlen(pbuf)), "\t          problem = unknown problem code 0x%x\n", val);
827                                 break;
828                 }
829                 state = ST_EXP_NIX;
830         }
831 }
832
833 /*---------------------------------------------------------------------------*
834  *      invoke component: invoke id
835  *---------------------------------------------------------------------------*/
836 static void
837 F_2(char *pbuf, int val)
838 {
839 #ifdef ST_DEBUG
840         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_2, val = %d\n", val);
841 #endif
842         if(val != -1)
843         {
844                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);               
845                 state = ST_EXP_OP_VAL;
846         }
847 }
848
849 /*---------------------------------------------------------------------------*
850  *      return result: invoke id
851  *---------------------------------------------------------------------------*/
852 static void
853 F_RR2(char *pbuf, int val)
854 {
855 #ifdef ST_DEBUG
856         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR2, val = %d\n", val);
857 #endif
858         if(val != -1)
859         {
860                 sprintf((pbuf+strlen(pbuf)), "\t          InvokeIdentifier = %d\n", val);
861                 state = ST_EXP_RR_OP_VAL;
862         }
863 }
864
865 /*---------------------------------------------------------------------------*
866  *      invoke component: operation value
867  *---------------------------------------------------------------------------*/
868 static void
869 F_3(char *pbuf, int val)
870 {
871 #ifdef ST_DEBUG
872         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_3, val = %d\n", val);
873 #endif
874         if(val != -1)
875         {
876                 sprintf((pbuf+strlen(pbuf)), "\t          Operation Value = %s (%d)\n", opval_str(val), val);
877                 state = ST_EXP_INFO;
878         }
879 }
880
881 /*---------------------------------------------------------------------------*
882  *      return result: operation value
883  *---------------------------------------------------------------------------*/
884 static void
885 F_RR3(char *pbuf, int val)
886 {
887 #ifdef ST_DEBUG
888         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR3, val = %d\n", val);
889 #endif
890         if(val != -1)
891         {
892                 sprintf((pbuf+strlen(pbuf)), "\t          Operation Value = %s (%d)\n", opval_str(val), val);
893                 state = ST_EXP_RR_RESULT;
894         }
895 }
896
897 /*---------------------------------------------------------------------------*
898  *      return result: RESULT
899  *---------------------------------------------------------------------------*/
900 static void
901 F_RRR(char *pbuf, int val)
902 {
903 #ifdef ST_DEBUG
904         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RRR, val = %d\n", val);
905 #endif
906         state = ST_EXP_NIX;
907 }
908
909 /*---------------------------------------------------------------------------*
910  *
911  *---------------------------------------------------------------------------*/
912 static void
913 F_4(char *pbuf, int val)
914 {
915 #ifdef ST_DEBUG
916         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4, val = %d\n", val);  
917 #endif
918         if(val == -1)
919         {
920                 sprintf((pbuf+strlen(pbuf)), "\t          specificChargingUnits\n");
921                 state = ST_EXP_RUL;
922         }
923 }
924
925 /*---------------------------------------------------------------------------*
926  *
927  *---------------------------------------------------------------------------*/
928 static void
929 F_4_1(char *pbuf, int val)
930 {
931 #ifdef ST_DEBUG
932         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_1, val = %d\n", val);        
933 #endif
934         if(val == -1)
935         {
936                 sprintf((pbuf+strlen(pbuf)), "\t          freeOfCharge\n");
937                 state = ST_EXP_NIX;
938         }
939 }
940
941 /*---------------------------------------------------------------------------*
942  *
943  *---------------------------------------------------------------------------*/
944 static void
945 F_4_2(char *pbuf, int val)
946 {
947 #ifdef ST_DEBUG
948         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_2, val = %d\n", val);        
949 #endif
950         if(val == -1)
951         {
952                 sprintf((pbuf+strlen(pbuf)), "\t          chargeNotAvailable\n");
953                 state = ST_EXP_NIX;
954         }
955 }
956
957 /*---------------------------------------------------------------------------*
958  *
959  *---------------------------------------------------------------------------*/
960 static void
961 F_5(char *pbuf, int val)
962 {
963 #ifdef ST_DEBUG
964         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_5, val = %d\n", val);  
965 #endif
966         if(val == -1)
967         {
968                 sprintf((pbuf+strlen(pbuf)), "\t          recordedUnitsList [1]\n");
969                 state = ST_EXP_RU;
970         }
971 }
972
973 /*---------------------------------------------------------------------------*
974  *
975  *---------------------------------------------------------------------------*/
976 static void
977 F_6(char *pbuf, int val)
978 {
979 #ifdef ST_DEBUG
980         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_6, val = %d\n", val);  
981 #endif
982         if(val == -1)
983         {
984                 sprintf((pbuf+strlen(pbuf)), "\t          RecordedUnits\n");
985                 state = ST_EXP_RNOU;
986         }
987 }
988
989 /*---------------------------------------------------------------------------*
990  *
991  *---------------------------------------------------------------------------*/
992 static void
993 F_7(char *pbuf, int val)
994 {
995 #ifdef ST_DEBUG
996         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_7, val = %d\n", val);  
997 #endif
998         if(val != -1)
999         {
1000                 sprintf((pbuf+strlen(pbuf)), "\t          NumberOfUnits = %d\n", val);
1001                 state = ST_EXP_TOCI;
1002         }
1003 }
1004
1005 /*---------------------------------------------------------------------------*
1006  *
1007  *---------------------------------------------------------------------------*/
1008 static void
1009 F_8(char *pbuf, int val)
1010 {
1011 #ifdef ST_DEBUG
1012         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_8, val = %d\n", val);  
1013 #endif
1014         if(val != -1)
1015         {
1016                 sprintf((pbuf+strlen(pbuf)), "\t          typeOfChargingInfo = %s\n", val == 0 ? "subTotal" : "total");
1017                 state = ST_EXP_DBID;
1018         }
1019 }
1020
1021 /*---------------------------------------------------------------------------*
1022  *
1023  *---------------------------------------------------------------------------*/
1024 static void
1025 F_9(char *pbuf, int val)
1026 {
1027 #ifdef ST_DEBUG
1028         sprintf((pbuf+strlen(pbuf)), "next_state: exec F_9, val = %d\n", val);  
1029 #endif
1030         if(val != -1)
1031         {
1032                 sprintf((pbuf+strlen(pbuf)), "\t          AOCDBillingId = %s (%d)\n", bid_str(val), val);
1033                 state = ST_EXP_NIX;
1034         }
1035 }
1036
1037 /*---------------------------------------------------------------------------*
1038  *      state table
1039  *---------------------------------------------------------------------------*/
1040 static struct statetab {
1041         int currstate;                  /* input: current state we are in */
1042         int form;                       /* input: current tag form */
1043         int class;                      /* input: current tag class */
1044         int code;                       /* input: current tag code */
1045         void (*func)(char *,int);       /* output: func to exec */
1046 } statetab[] = {
1047
1048 /*       current state          tag form                tag class               tag code                function        */
1049 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
1050
1051 /* invoke */
1052
1053         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_1_1           },
1054         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       2,                      F_1_2           },
1055         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       3,                      F_1_3           },
1056         {ST_EXP_COMP_TYP,       FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       4,                      F_1_4           },
1057         {ST_EXP_INV_ID,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_2             },
1058         {ST_EXP_OP_VAL,         FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_3             },
1059         {ST_EXP_INFO,           FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_4             },
1060         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_NULL,       F_4_1           },
1061         {ST_EXP_INFO,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_4_2           },
1062         {ST_EXP_RUL,            FAC_TAGFORM_CON,        FAC_TAGCLASS_COS,       1,                      F_5             },
1063         {ST_EXP_RU,             FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SEQ,        F_6             },
1064         {ST_EXP_RNOU,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_7             },
1065         {ST_EXP_TOCI,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_8             },
1066         {ST_EXP_DBID,           FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_9             },
1067
1068 /* return result */
1069         
1070         {ST_EXP_RR_INV_ID,      FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RR2           },
1071         {ST_EXP_RR_OP_VAL,      FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RR3           },
1072         {ST_EXP_RR_RESULT,      FAC_TAGFORM_CON,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_SET,        F_RRR           },
1073
1074 /*       current state          tag form                tag class               tag code                function        */
1075 /*       ---------------------  ----------------------  ----------------------  ----------------------  ----------------*/
1076 /* reject */
1077         
1078         {ST_EXP_REJ_INV_ID,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_UNI,       FAC_CODEUNI_INT,        F_RJ2           },
1079         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       0,                      F_RJ30          },
1080         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       1,                      F_RJ31          },
1081         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       2,                      F_RJ32          },
1082         {ST_EXP_REJ_OP_VAL,     FAC_TAGFORM_PRI,        FAC_TAGCLASS_COS,       3,                      F_RJ33          },
1083
1084 /* end */
1085         
1086         {-1,                    -1,                     -1,                     -1,                     NULL            }
1087 };      
1088         
1089 /*---------------------------------------------------------------------------*
1090  *      state decode for do_component
1091  *---------------------------------------------------------------------------*/
1092 static void
1093 next_state(char *pbuf, int class, int form, int code, int val)
1094 {
1095         int i;
1096
1097 #ifdef ST_DEBUG
1098         sprintf((pbuf+strlen(pbuf)), "next_state: class=%d, form=%d, code=%d, val=%d\n", class, form, code, val);
1099 #endif
1100
1101         for(i=0; ; i++)
1102         {
1103                 if((statetab[i].currstate > state) ||
1104                    (statetab[i].currstate == -1))
1105                 {
1106                         break;
1107                 }
1108
1109                 if((statetab[i].currstate == state)     &&
1110                    (statetab[i].form == form)           &&
1111                    (statetab[i].class == class)         &&
1112                    (statetab[i].code == code))
1113                 {
1114                         (*statetab[i].func)(pbuf, val);
1115                         break;
1116                 }
1117         }
1118 }
1119
1120 /*---------------------------------------------------------------------------*
1121  *      decode OBJECT IDENTIFIER
1122  *---------------------------------------------------------------------------*/
1123 static void
1124 object_id(int comp_length, unsigned char *pbuf)
1125 {
1126         int x;
1127         int i;
1128         int j = 0;
1129         int id_org = 0;
1130         int etsi = 0;
1131         
1132         sprintf((pbuf+strlen(pbuf)), "\t");
1133         
1134         for(i = comp_length-1; i >= 0; i--, j++)
1135         {
1136                 sprintf((pbuf+strlen(pbuf)), "0x%02x = %d", *byte_buf, *byte_buf);
1137
1138                 if(j == 0)
1139                 {
1140                         x = *byte_buf;
1141
1142                         if(x >= 0 && x <= 39)
1143                         {
1144                                 sprintf((pbuf+strlen(pbuf)), " ccitt/itu-t (0)");
1145                                 switch(x)
1146                                 {
1147                                         case 0:
1148                                                 sprintf((pbuf+strlen(pbuf)), " recommendation (0)");
1149                                                 break;
1150                                         case 1:
1151                                                 sprintf((pbuf+strlen(pbuf)), " question (1)");
1152                                                 break;
1153                                         case 2:
1154                                                 sprintf((pbuf+strlen(pbuf)), " administration (2)");
1155                                                 break;
1156                                         case 3:
1157                                                 sprintf((pbuf+strlen(pbuf)), " network-operator (3)");
1158                                                 break;
1159                                         case 4:
1160                                                 sprintf((pbuf+strlen(pbuf)), " identified-organization (4)");
1161                                                 id_org = 1;
1162                                                 break;
1163                                         default:
1164                                                 sprintf((pbuf+strlen(pbuf)), " error: undefined-identifier (%d)", x);
1165                                                 break;
1166                                 }
1167                         }
1168                         else if(x >= 40 && x <= 79)
1169                         {
1170                                 sprintf((pbuf+strlen(pbuf)), " iso (1)");
1171                                 x -= 40;
1172                                 switch(x)
1173                                 {
1174                                         case 0:
1175                                                 sprintf((pbuf+strlen(pbuf)), " standard (0)");
1176                                                 break;
1177                                         case 1:
1178                                                 sprintf((pbuf+strlen(pbuf)), " registration-authority (1)");
1179                                                 break;
1180                                         case 2:
1181                                                 sprintf((pbuf+strlen(pbuf)), " member-body (2)");
1182                                                 break;
1183                                         case 3:
1184                                                 sprintf((pbuf+strlen(pbuf)), " identified-organization (3)");
1185                                                 id_org = 1;
1186                                                 break;
1187                                         default:
1188                                                 sprintf((pbuf+strlen(pbuf)), " error: undefined-identifier (%d)", x);
1189                                                 break;
1190                                 }
1191                         }
1192                         else
1193                         {
1194                                 x -= 80;                        
1195                                 sprintf((pbuf+strlen(pbuf)), " joint-iso-ccitt (3) ??? (%d)", x);
1196                         }
1197                 }
1198
1199                 if(j == 1)
1200                 {
1201                         if(id_org == 1)
1202                         {
1203                                 if(*byte_buf == 0)
1204                                 {
1205                                         sprintf((pbuf+strlen(pbuf)), " etsi (0)");
1206                                         etsi = 1;
1207                                 }
1208                         }
1209                 }
1210
1211                 if(j == 2)
1212                 {
1213                         if(etsi == 1)
1214                         {
1215                                 if(*byte_buf == 0)
1216                                 {
1217                                         sprintf((pbuf+strlen(pbuf)), " mobileDomain (0)");
1218                                 }
1219                                 if(*byte_buf == 1)
1220                                 {
1221                                         sprintf((pbuf+strlen(pbuf)), " inDomain (1)");
1222                                 }
1223                         }
1224                 }
1225                                 
1226                 byte_buf++;
1227                 byte_len++;
1228                 
1229                 if(i)
1230                         sprintf((pbuf+strlen(pbuf)), "\n\t");
1231                 else
1232                         sprintf((pbuf+strlen(pbuf)), "\n");
1233         }
1234 }
1235
1236 /* EOF */
1237