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