root/drivers/isdn/teles/q931.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. findie
  2. iecpy
  3. getcallref
  4. prbits
  5. skipext
  6. prcause
  7. prchident
  8. prcalled
  9. prcalling
  10. prbearer
  11. general
  12. display
  13. prfacility
  14. hexdump
  15. dlogframe

   1 /*
   2  * q931.c               code to decode ITU Q.931 call control messages
   3  * 
   4  * Author               Jan den Ouden
   5  * 
   6  * Changelog
   7  * 
   8  * Pauline Middelink    general improvements
   9  * 
  10  * Beat Doebeli         cause texts, display information element
  11  * 
  12  */
  13 
  14 
  15 #define __NO_VERSION__
  16 #include "teles.h"
  17 
  18 byte           *
  19 findie(byte * p, int size, byte ie, int wanted_set)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21         int             l, codeset, maincodeset;
  22         byte           *pend = p + size;
  23 
  24         /* skip protocol discriminator, callref and message type */
  25         p++;
  26         l = (*p++) & 0xf;
  27         p += l;
  28         p++;
  29         codeset = 0;
  30         maincodeset = 0;
  31         /* while there are bytes left... */
  32         while (p < pend) {
  33                 if ((*p & 0xf0) == 0x90) {
  34                         codeset = *p & 0x07;
  35                         if (!(*p & 0x08))
  36                                 maincodeset = codeset;
  37                 }
  38                 if (*p & 0x80)
  39                         p++;
  40                 else {
  41                         if (codeset == wanted_set) {
  42                                 if (*p == ie)
  43                                         return (p);
  44                                 if (*p > ie)
  45                                         return (NULL);
  46                         }
  47                         p++;
  48                         l = *p++;
  49                         p += l;
  50                         codeset = maincodeset;
  51                 }
  52         }
  53         return (NULL);
  54 }
  55 
  56 void
  57 iecpy(byte * dest, byte * iestart, int ieoffset)
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         byte           *p;
  60         int             l;
  61 
  62         p = iestart + ieoffset + 2;
  63         l = iestart[1] - ieoffset;
  64         while (l--)
  65                 *dest++ = *p++;
  66         *dest++ = '\0';
  67 }
  68 
  69 int
  70 getcallref(byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         p++;                    /* prot discr */
  73         p++;                    /* callref length */
  74         return (*p);            /* assuming one-byte callref */
  75 }
  76 
  77 /*
  78  * According to Table 4-2/Q.931
  79  */
  80 static
  81 struct MessageType {
  82         byte            nr;
  83         char           *descr;
  84 } mtlist[] = {
  85 
  86         {
  87                 0x1, "ALERTING"
  88         },
  89         {
  90                 0x2, "CALL PROCEEDING"
  91         },
  92         {
  93                 0x7, "CONNECT"
  94         },
  95         {
  96                 0xf, "CONNECT ACKNOWLEDGE"
  97         },
  98         {
  99                 0x3, "PROGRESS"
 100         },
 101         {
 102                 0x5, "SETUP"
 103         },
 104         {
 105                 0xd, "SETUP ACKNOWLEDGE"
 106         },
 107         {
 108                 0x26, "RESUME"
 109         },
 110         {
 111                 0x2e, "RESUME ACKNOWLEDGE"
 112         },
 113         {
 114                 0x22, "RESUME REJECT"
 115         },
 116         {
 117                 0x25, "SUSPEND"
 118         },
 119         {
 120                 0x2d, "SUSPEND ACKNOWLEDGE"
 121         },
 122         {
 123                 0x21, "SUSPEND REJECT"
 124         },
 125         {
 126                 0x20, "USER INFORMATION"
 127         },
 128         {
 129                 0x45, "DISCONNECT"
 130         },
 131         {
 132                 0x4d, "RELEASE"
 133         },
 134         {
 135                 0x5a, "RELEASE COMPLETE"
 136         },
 137         {
 138                 0x46, "RESTART"
 139         },
 140         {
 141                 0x4e, "RESTART ACKNOWLEDGE"
 142         },
 143         {
 144                 0x60, "SEGMENT"
 145         },
 146         {
 147                 0x79, "CONGESTION CONTROL"
 148         },
 149         {
 150                 0x7b, "INFORMATION"
 151         },
 152         {
 153                 0x62, "FACILITY"
 154         },
 155         {
 156                 0x6e, "NOTIFY"
 157         },
 158         {
 159                 0x7d, "STATUS"
 160         },
 161         {
 162                 0x75, "STATUS ENQUIRY"
 163         }
 164 };
 165 
 166 #define MTSIZE sizeof(mtlist)/sizeof(struct MessageType)
 167 
 168 
 169 static
 170 int
 171 prbits(char *dest, byte b, int start, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         char           *dp = dest;
 174 
 175         b = b << (8 - start);
 176         while (len--) {
 177                 if (b & 0x80)
 178                         *dp++ = '1';
 179                 else
 180                         *dp++ = '0';
 181                 b = b << 1;
 182         }
 183         return (dp - dest);
 184 }
 185 
 186 static
 187 byte           *
 188 skipext(byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 189 {
 190         while (!(*p++ & 0x80));
 191         return (p);
 192 }
 193 
 194 /*
 195  * Cause Values According to Q.850
 196  * edescr: English description
 197  * ddescr: German description used by Swissnet II (Swiss Telecom
 198  *         not yet written...
 199  */
 200 
 201 static
 202 struct CauseValue {
 203         byte            nr;
 204         char           *edescr;
 205         char           *ddescr;
 206 } cvlist[] = {
 207 
 208         {
 209                 0x01, "Unallocated (unassigned) number", "Nummer nicht zugeteilt"
 210         },
 211         {
 212                 0x02, "No route to specified transit network", ""
 213         },
 214         {
 215                 0x03, "No route to destination", ""
 216         },
 217         {
 218                 0x04, "Send special information tone", ""
 219         },
 220         {
 221                 0x05, "Misdialled trunk prefix", ""
 222         },
 223         {
 224                 0x06, "Channel unacceptable", "Kanal nicht akzeptierbar"
 225         },
 226         {
 227                 0x07, "Channel awarded and being delivered in an established channel", ""
 228         },
 229         {
 230                 0x08, "Preemption", ""
 231         },
 232         {
 233                 0x09, "Preemption - circuit reserved for reuse", ""
 234         },
 235         {
 236                 0x10, "Normal call clearing", "Normale Ausloesung"
 237         },
 238         {
 239                 0x11, "User busy", "TNB besetzt"
 240         },
 241         {
 242                 0x12, "No user responding", ""
 243         },
 244         {
 245                 0x13, "No answer from user (user alerted)", ""
 246         },
 247         {
 248                 0x14, "Subscriber absent", ""
 249         },
 250         {
 251                 0x15, "Call rejected", ""
 252         },
 253         {
 254                 0x16, "Number changed", ""
 255         },
 256         {
 257                 0x1a, "non-selected user clearing", ""
 258         },
 259         {
 260                 0x1b, "Destination out of order", ""
 261         },
 262         {
 263                 0x1c, "Invalid number format (address incomplete)", ""
 264         },
 265         {
 266                 0x1d, "Facility rejected", ""
 267         },
 268         {
 269                 0x1e, "Response to Status enuiry", ""
 270         },
 271         {
 272                 0x1f, "Normal, unspecified", ""
 273         },
 274         {
 275                 0x22, "No circuit/channel available", ""
 276         },
 277         {
 278                 0x26, "Network out of order", ""
 279         },
 280         {
 281                 0x27, "Permanent frame mode connection out-of-service", ""
 282         },
 283         {
 284                 0x28, "Permanent frame mode connection operational", ""
 285         },
 286         {
 287                 0x29, "Temporary failure", ""
 288         },
 289         {
 290                 0x2a, "Switching equipment congestion", ""
 291         },
 292         {
 293                 0x2b, "Access information discarded", ""
 294         },
 295         {
 296                 0x2c, "Requested circuit/channel not available", ""
 297         },
 298         {
 299                 0x2e, "Precedence call blocked", ""
 300         },
 301         {
 302                 0x2f, "Resource unavailable, unspecified", ""
 303         },
 304         {
 305                 0x31, "Quality of service unavailable", ""
 306         },
 307         {
 308                 0x32, "Requested facility not subscribed", ""
 309         },
 310         {
 311                 0x35, "Outgoing calls barred within CUG", ""
 312         },
 313         {
 314                 0x37, "Incoming calls barred within CUG", ""
 315         },
 316         {
 317                 0x39, "Bearer capability not auhorized", ""
 318         },
 319         {
 320                 0x3a, "Bearer capability not presently available", ""
 321         },
 322         {
 323                 0x3e, "Inconsistency in designated outgoing access information and subscriber class ", " "
 324         },
 325         {
 326                 0x3f, "Service or option not available, unspecified", ""
 327         },
 328         {
 329                 0x41, "Bearer capability not implemented", ""
 330         },
 331         {
 332                 0x42, "Channel type not implemented", ""
 333         },
 334         {
 335                 0x43, "Requested facility not implemented", ""
 336         },
 337         {
 338                 0x44, "Only restricted digital information bearer capability is available", ""
 339         },
 340         {
 341                 0x4f, "Service or option not implemented", ""
 342         },
 343         {
 344                 0x51, "Invalid call reference value", ""
 345         },
 346         {
 347                 0x52, "Identified channel does not exist", ""
 348         },
 349         {
 350                 0x53, "A suspended call exists, but this call identity does not", ""
 351         },
 352         {
 353                 0x54, "Call identity in use", ""
 354         },
 355         {
 356                 0x55, "No call suspended", ""
 357         },
 358         {
 359                 0x56, "Call having the requested call identity has been cleared", ""
 360         },
 361         {
 362                 0x57, "User not member of CUG", ""
 363         },
 364         {
 365                 0x58, "Incompatible destination", ""
 366         },
 367         {
 368                 0x5a, "Non-existent CUG", ""
 369         },
 370         {
 371                 0x5b, "Invalid transit network selection", ""
 372         },
 373         {
 374                 0x5f, "Invalid message, unspecified", ""
 375         },
 376         {
 377                 0x60, "Mandatory information element is missing", ""
 378         },
 379         {
 380                 0x61, "Message type non-existent or not implemented", ""
 381         },
 382         {
 383                 0x62, "Message not compatible with call state or message type non-existent or not implemented ", " "
 384         },
 385         {
 386                 0x63, "Information element/parameter non-existent or not implemented", ""
 387         },
 388         {
 389                 0x64, "Invalid information element contents", ""
 390         },
 391         {
 392                 0x65, "Message not compatible with call state", ""
 393         },
 394         {
 395                 0x66, "Recovery on timer expiry", ""
 396         },
 397         {
 398                 0x67, "Parameter non-existent or not implemented - passed on", ""
 399         },
 400         {
 401                 0x6e, "Message with unrecognized parameter discarded", ""
 402         },
 403         {
 404                 0x6f, "Protocol error, unspecified", ""
 405         },
 406         {
 407                 0x7f, "Interworking, unspecified", ""
 408         },
 409 };
 410 
 411 #define CVSIZE sizeof(cvlist)/sizeof(struct CauseValue)
 412 
 413 static
 414 int
 415 prcause(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 416 {
 417         byte           *end;
 418         char           *dp = dest;
 419         int             i, cause;
 420 
 421         end = p + p[1] + 1;
 422         p += 2;
 423         dp += sprintf(dp, "    coding ");
 424         dp += prbits(dp, *p, 7, 2);
 425         dp += sprintf(dp, " location ");
 426         dp += prbits(dp, *p, 4, 4);
 427         *dp++ = '\n';
 428         p = skipext(p);
 429 
 430         cause = 0x7f & *p++;
 431 
 432         /* locate cause value */
 433         for (i = 0; i < CVSIZE; i++)
 434                 if (cvlist[i].nr == cause)
 435                         break;
 436 
 437         /* display cause value if it exists */
 438         if (i == CVSIZE)
 439                 dp += sprintf(dp, "Unknown cause type %x!\n", cause);
 440         else
 441                 dp += sprintf(dp, "  cause value %x : %s \n", cause, cvlist[i].edescr);
 442 
 443 
 444 #if 0
 445         dp += sprintf(dp,"    cause value ");
 446         dp += prbits(dp,*p++,7,7);
 447         *dp++ = '\n';
 448 #endif
 449         while (!0) {
 450                 if (p > end)
 451                         break;
 452                 dp += sprintf(dp, "    diag attribute %d ", *p++ & 0x7f);
 453                 dp += sprintf(dp, " rej %d ", *p & 0x7f);
 454                 if (*p & 0x80) {
 455                         *dp++ = '\n';
 456                         break;
 457                 } else
 458                         dp += sprintf(dp, " av %d\n", (*++p) & 0x7f);
 459         }
 460         return (dp - dest);
 461 
 462 }
 463 
 464 static
 465 int
 466 prchident(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 467 {
 468         char           *dp = dest;
 469 
 470         p += 2;
 471         dp += sprintf(dp, "    octet 3 ");
 472         dp += prbits(dp, *p, 8, 8);
 473         *dp++ = '\n';
 474         return (dp - dest);
 475 }
 476 static
 477 int
 478 prcalled(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 479 {
 480         int             l;
 481         char           *dp = dest;
 482 
 483         p++;
 484         l = *p++ - 1;
 485         dp += sprintf(dp, "    octet 3 ");
 486         dp += prbits(dp, *p++, 8, 8);
 487         *dp++ = '\n';
 488         dp += sprintf(dp, "    number digits ");
 489         while (l--)
 490                 *dp++ = *p++;
 491         *dp++ = '\n';
 492         return (dp - dest);
 493 }
 494 static
 495 int
 496 prcalling(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 497 {
 498         int             l;
 499         char           *dp = dest;
 500 
 501         p++;
 502         l = *p++ - 1;
 503         dp += sprintf(dp, "    octet 3 ");
 504         dp += prbits(dp, *p, 8, 8);
 505         *dp++ = '\n';
 506         if (!(*p & 0x80)) {
 507                 dp += sprintf(dp, "    octet 3a ");
 508                 dp += prbits(dp, *++p, 8, 8);
 509                 *dp++ = '\n';
 510                 l--;
 511         };
 512 
 513         p++;
 514 
 515         dp += sprintf(dp, "    number digits ");
 516         while (l--)
 517                 *dp++ = *p++;
 518         *dp++ = '\n';
 519         return (dp - dest);
 520 }
 521 
 522 static
 523 int
 524 prbearer(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 525 {
 526         char           *dp = dest, ch;
 527 
 528         p += 2;
 529         dp += sprintf(dp, "    octet 3  ");
 530         dp += prbits(dp, *p++, 8, 8);
 531         *dp++ = '\n';
 532         dp += sprintf(dp, "    octet 4  ");
 533         dp += prbits(dp, *p, 8, 8);
 534         *dp++ = '\n';
 535         if ((*p++ & 0x1f) == 0x18) {
 536                 dp += sprintf(dp, "    octet 4.1 ");
 537                 dp += prbits(dp, *p++, 8, 8);
 538                 *dp++ = '\n';
 539         }
 540         /* check for user information layer 1 */
 541         if ((*p & 0x60) == 0x20) {
 542                 ch = ' ';
 543                 do {
 544                         dp += sprintf(dp, "    octet 5%c ", ch);
 545                         dp += prbits(dp, *p, 8, 8);
 546                         *dp++ = '\n';
 547                         if (ch == ' ')
 548                                 ch = 'a';
 549                         else
 550                                 ch++;
 551                 }
 552                 while (!(*p++ & 0x80));
 553         }
 554         /* check for user information layer 2 */
 555         if ((*p & 0x60) == 0x40) {
 556                 dp += sprintf(dp, "    octet 6  ");
 557                 dp += prbits(dp, *p++, 8, 8);
 558                 *dp++ = '\n';
 559         }
 560         /* check for user information layer 3 */
 561         if ((*p & 0x60) == 0x60) {
 562                 dp += sprintf(dp, "    octet 7  ");
 563                 dp += prbits(dp, *p++, 8, 8);
 564                 *dp++ = '\n';
 565         }
 566         return (dp - dest);
 567 }
 568 
 569 static
 570 int
 571 general(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 572 {
 573         char           *dp = dest;
 574         char            ch = ' ';
 575         int             l, octet = 3;
 576 
 577         p++;
 578         l = *p++;
 579         /* Iterate over all octets in the information element */
 580         while (l--) {
 581                 dp += sprintf(dp, "    octet %d%c ", octet, ch);
 582                 dp += prbits(dp, *p++, 8, 8);
 583                 *dp++ = '\n';
 584 
 585                 /* last octet in group? */
 586                 if (*p & 0x80) {
 587                         octet++;
 588                         ch = ' ';
 589                 } else if (ch == ' ')
 590                         ch = 'a';
 591 
 592                 else
 593                         ch++;
 594         }
 595         return (dp - dest);
 596 }
 597 
 598 static
 599 int
 600 display(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 601 {
 602         char           *dp = dest;
 603         char            ch = ' ';
 604         int             l, octet = 3;
 605 
 606         p++;
 607         l = *p++;
 608         /* Iterate over all octets in the * display-information element */
 609         dp += sprintf(dp, "   \"");
 610         while (l--) {
 611                 dp += sprintf(dp, "%c", *p++);
 612 
 613                 /* last octet in group? */
 614                 if (*p & 0x80) {
 615                         octet++;
 616                         ch = ' ';
 617                 } else if (ch == ' ')
 618                         ch = 'a';
 619 
 620                 else
 621                         ch++;
 622         }
 623         *dp++ = '\"';
 624         *dp++ = '\n';
 625         return (dp - dest);
 626 }
 627 
 628 int
 629 prfacility(char *dest, byte * p)
     /* [previous][next][first][last][top][bottom][index][help] */
 630 {
 631         char           *dp = dest;
 632         int             l, l2;
 633 
 634         p++;
 635         l = *p++;
 636         dp += sprintf(dp, "    octet 3 ");
 637         dp += prbits(dp, *p++, 8, 8);
 638         dp += sprintf(dp, "\n");
 639         l -= 1;
 640 
 641         while (l > 0) {
 642                 dp += sprintf(dp, "   octet 4 ");
 643                 dp += prbits(dp, *p++, 8, 8);
 644                 dp += sprintf(dp, "\n");
 645                 dp += sprintf(dp, "   octet 5 %d\n", l2 = *p++ & 0x7f);
 646                 l -= 2;
 647                 dp += sprintf(dp, "   contents ");
 648                 while (l2--) {
 649                         dp += sprintf(dp, "%2x ", *p++);
 650                         l--;
 651                 }
 652                 dp += sprintf(dp, "\n");
 653         }
 654 
 655         return (dp - dest);
 656 }
 657 
 658 static
 659 struct InformationElement {
 660         byte            nr;
 661         char           *descr;
 662         int             (*f) (char *, byte *);
 663 } ielist[] = {
 664 
 665         {
 666                 0x00, "Segmented message", general
 667         },
 668         {
 669                 0x04, "Bearer capability", prbearer
 670         },
 671         {
 672                 0x08, "Cause", prcause
 673         },
 674         {
 675                 0x10, "Call identity", general
 676         },
 677         {
 678                 0x14, "Call state", general
 679         },
 680         {
 681                 0x18, "Channel identification", prchident
 682         },
 683         {
 684                 0x1c, "Facility", prfacility
 685         },
 686         {
 687                 0x1e, "Progress indicator", general
 688         },
 689         {
 690                 0x20, "Network-specific facilities", general
 691         },
 692         {
 693                 0x27, "Notification indicator", general
 694         },
 695         {
 696                 0x28, "Display", display
 697         },
 698         {
 699                 0x29, "Date/Time", general
 700         },
 701         {
 702                 0x2c, "Keypad facility", general
 703         },
 704         {
 705                 0x34, "Signal", general
 706         },
 707         {
 708                 0x40, "Information rate", general
 709         },
 710         {
 711                 0x42, "End-to-end delay", general
 712         },
 713         {
 714                 0x43, "Transit delay selection and indication", general
 715         },
 716         {
 717                 0x44, "Packet layer binary parameters", general
 718         },
 719         {
 720                 0x45, "Packet layer window size", general
 721         },
 722         {
 723                 0x46, "Packet size", general
 724         },
 725         {
 726                 0x47, "Closed user group", general
 727         },
 728         {
 729                 0x4a, "Reverse charge indication", general
 730         },
 731         {
 732                 0x6c, "Calling party number", prcalling
 733         },
 734         {
 735                 0x6d, "Calling party subaddress", general
 736         },
 737         {
 738                 0x70, "Called party number", prcalled
 739         },
 740         {
 741                 0x71, "Called party subaddress", general
 742         },
 743         {
 744                 0x74, "Redirecting number", general
 745         },
 746         {
 747                 0x78, "Transit network selection", general
 748         },
 749         {
 750                 0x79, "Restart indicator", general
 751         },
 752         {
 753                 0x7c, "Low layer compatibility", general
 754         },
 755         {
 756                 0x7d, "High layer compatibility", general
 757         },
 758         {
 759                 0x7e, "User-user", general
 760         },
 761         {
 762                 0x7f, "Escape for extension", general
 763         },
 764 };
 765 
 766 #define IESIZE sizeof(ielist)/sizeof(struct InformationElement)
 767 
 768 #ifdef FRITZDEBUG
 769 void
 770 hexdump(byte * buf, int len, char *comment)
     /* [previous][next][first][last][top][bottom][index][help] */
 771 {
 772         static char     dbuf[1024];
 773         char           *p = dbuf;
 774 
 775         p += sprintf(p, "%s: ", comment);
 776         while (len) {
 777                 p += sprintf(p, "%02x ", *p++);
 778                 len--;
 779         }
 780         p += sprintf(p, "\n");
 781 
 782         teles_putstatus(dbuf);
 783 }
 784 #endif
 785 
 786 void
 787 dlogframe(struct IsdnCardState *sp, byte * buf, int size, char *comment)
     /* [previous][next][first][last][top][bottom][index][help] */
 788 {
 789         byte           *bend = buf + size;
 790         char           *dp;
 791         int             i;
 792 
 793         /* display header */
 794         dp = sp->dlogspace;
 795         dp += sprintf(dp, "%s\n", comment);
 796 
 797         {
 798                 byte           *p = buf;
 799 
 800                 dp += sprintf(dp, "hex: ");
 801                 while (p < bend)
 802                         dp += sprintf(dp, "%02x ", *p++);
 803                 dp += sprintf(dp, "\n");
 804                 teles_putstatus(sp->dlogspace);
 805                 dp = sp->dlogspace;
 806         }
 807         /* locate message type */
 808         for (i = 0; i < MTSIZE; i++)
 809                 if (mtlist[i].nr == buf[3])
 810                         break;
 811 
 812         /* display message type iff it exists */
 813         if (i == MTSIZE)
 814                 dp += sprintf(dp, "Unknown message type %x!\n", buf[3]);
 815         else
 816                 dp += sprintf(dp, "call reference %d size %d message type %s\n",
 817                               buf[2], size, mtlist[i].descr);
 818 
 819         /* display each information element */
 820         buf += 4;
 821         while (buf < bend) {
 822                 /* Is it a single octet information element? */
 823                 if (*buf & 0x80) {
 824                         switch ((*buf >> 4) & 7) {
 825                           case 1:
 826                                   dp += sprintf(dp, "  Shift %x\n", *buf & 0xf);
 827                                   break;
 828                           case 3:
 829                                   dp += sprintf(dp, "  Congestion level %x\n", *buf & 0xf);
 830                                   break;
 831                           case 5:
 832                                   dp += sprintf(dp, "  Repeat indicator %x\n", *buf & 0xf);
 833                                   break;
 834                           case 2:
 835                                   if (*buf == 0xa0) {
 836                                           dp += sprintf(dp, "  More data\n");
 837                                           break;
 838                                   }
 839                                   if (*buf == 0xa1) {
 840                                           dp += sprintf(dp, "  Sending complete\n");
 841                                   }
 842                                   break;
 843                                   /* fall through */
 844                           default:
 845                                   dp += sprintf(dp, "  Reserved %x\n", *buf);
 846                                   break;
 847                         }
 848                         buf++;
 849                         continue;
 850                 }
 851                 /* No, locate it in the table */
 852                 for (i = 0; i < IESIZE; i++)
 853                         if (*buf == ielist[i].nr)
 854                                 break;
 855 
 856                 /* When not found, give apropriate msg */
 857                 if (i != IESIZE) {
 858                         dp += sprintf(dp, "  %s\n", ielist[i].descr);
 859                         dp += ielist[i].f(dp, buf);
 860                 } else
 861                         dp += sprintf(dp, "  attribute %x attribute size %d\n", *buf, buf[1]);
 862 
 863                 /* Skip to next element */
 864                 buf += buf[1] + 2;
 865         }
 866 
 867         dp += sprintf(dp, "\n");
 868         teles_putstatus(sp->dlogspace);
 869 }

/* [previous][next][first][last][top][bottom][index][help] */