NetBSD/usr.sbin/isdn/isdntrace/1tr6.c

757 lines
17 KiB
C

/*
* Copyright (c) 1997, 1999 Hellmuth Michaelis. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*---------------------------------------------------------------------------
*
* 1tr6.c - print 1TR6 protocol traces
* -----------------------------------
*
* $Id: 1tr6.c,v 1.3 2003/10/06 09:43:28 itojun Exp $
*
* $FreeBSD$
*
* last edit-date: [Mon Dec 13 21:55:31 1999]
*
*---------------------------------------------------------------------------*/
#include "trace.h"
static int p_1tr6address(char *pbuf, unsigned char buf[]);
static int p_1tr6cause(char *pbuf, unsigned char buf[]);
/*---------------------------------------------------------------------------*
* decode the (german) national specific 1TR6 protocol
*---------------------------------------------------------------------------*/
void
decode_1tr6(char *pbuf, int n, int off, unsigned char *buf, int raw)
{
int codeset = 0;
int oldcodeset = 0;
int codelock = 0;
int pd;
int len;
int j;
int i;
if (n <= 0)
return;
*pbuf = '\0';
if (raw)
{
for (i = 0; i < n; i += 16)
{
sprintf((pbuf+strlen(pbuf)),"Dump:%.3d ", i+off);
for (j = 0; j < 16; j++)
if (i + j < n)
sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]);
else
sprintf((pbuf+strlen(pbuf))," ");
sprintf((pbuf+strlen(pbuf))," ");
for (j = 0; j < 16 && i + j < n; j++)
if (isprint(buf[i + j]))
sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]);
else
sprintf((pbuf+strlen(pbuf)),".");
sprintf((pbuf+strlen(pbuf)),"\n");
}
}
sprintf((pbuf+strlen(pbuf)), "1TR6: ");
/* protocol discriminator */
i = 0;
pd = buf[i];
switch (pd)
{
case 0x40:
sprintf((pbuf+strlen(pbuf)), "pd=N0, ");
break;
case 0x41:
sprintf((pbuf+strlen(pbuf)), "pd=N1, ");
break;
default:
sprintf((pbuf+strlen(pbuf)), "pd=UNDEF (0x%02x), ",pd);
break;
}
/* call reference */
i++;
len = buf[i] & 0x0f;
switch (len)
{
case 1:
sprintf((pbuf+strlen(pbuf)), "cr=0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+1] & 0x80) ? "(from destination)" : "(from origination)");
break;
default:
sprintf((pbuf+strlen(pbuf)), "cr: LEN=%d %s 0x%02x 0x%02x, ", len, (buf[i+1] & 0x80) ? "org" : "dst", (buf[i+1] & 0x7f), (buf[i+2] & 0x7f));
break;
}
i += (len+1);
/* message type */
sprintf((pbuf+strlen(pbuf)), "message=");
if (pd == 0x40) /* protocol discriminator N0 */
{
switch (buf[i])
{
case 0x61:
sprintf((pbuf+strlen(pbuf)), "REGISTER INDICATION: ");
break;
case 0x62:
sprintf((pbuf+strlen(pbuf)), "CANCEL INDICATION: ");
break;
case 0x63:
sprintf((pbuf+strlen(pbuf)), "FACILITY STATUS: ");
break;
case 0x64:
sprintf((pbuf+strlen(pbuf)), "STATUS ACKNOWLEDGE: ");
break;
case 0x65:
sprintf((pbuf+strlen(pbuf)), "STATUS REJECT: ");
break;
case 0x66:
sprintf((pbuf+strlen(pbuf)), "FACILITY INFORMATION: ");
break;
case 0x67:
sprintf((pbuf+strlen(pbuf)), "INFORMATION ACKNOWLEDGE: ");
break;
case 0x68:
sprintf((pbuf+strlen(pbuf)), "INFORMATION REJECT: ");
break;
case 0x75:
sprintf((pbuf+strlen(pbuf)), "CLOSE: ");
break;
case 0x77:
sprintf((pbuf+strlen(pbuf)), "CLOSE ACKNOWLEDGE: ");
break;
default:
sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x40 MSG=0x%02x, ", buf[i]);
break;
}
}
else if (pd == 0x41)
{
switch (buf[i])
{
case 0x00:
sprintf((pbuf+strlen(pbuf)), "ESCAPE: ");
break;
case 0x01:
sprintf((pbuf+strlen(pbuf)), "ALERT: ");
break;
case 0x02:
sprintf((pbuf+strlen(pbuf)), "CALL SENT: ");
break;
case 0x07:
sprintf((pbuf+strlen(pbuf)), "CONNECT: ");
break;
case 0x0f:
sprintf((pbuf+strlen(pbuf)), "CONNECT ACKNOWLEDGE: ");
break;
case 0x05:
sprintf((pbuf+strlen(pbuf)), "SETUP: ");
break;
case 0x0d:
sprintf((pbuf+strlen(pbuf)), "SETUP ACKNOWLEDGE: ");
break;
case 0x26:
sprintf((pbuf+strlen(pbuf)), "RESUME: ");
break;
case 0x2e:
sprintf((pbuf+strlen(pbuf)), "RESUME ACKNOWLEDGE: ");
break;
case 0x22:
sprintf((pbuf+strlen(pbuf)), "RESUME REJECT: ");
break;
case 0x25:
sprintf((pbuf+strlen(pbuf)), "SUSPEND: ");
break;
case 0x2d:
sprintf((pbuf+strlen(pbuf)), "SUSPEND ACKNOWLEDGE: ");
break;
case 0x21:
sprintf((pbuf+strlen(pbuf)), "SUSPEND REJECT: ");
break;
case 0x20:
sprintf((pbuf+strlen(pbuf)), "USER INFORMATION: ");
break;
case 0x40:
sprintf((pbuf+strlen(pbuf)), "DETACH");
break;
case 0x45:
sprintf((pbuf+strlen(pbuf)), "DISCONNECT: ");
break;
case 0x4d:
sprintf((pbuf+strlen(pbuf)), "RELEASE: ");
break;
case 0x5a:
sprintf((pbuf+strlen(pbuf)), "RELEASE ACKNOWLEDGE");
break;
case 0x6e:
sprintf((pbuf+strlen(pbuf)), "CANCEL ACKNOWLEDGE: ");
break;
case 0x67:
sprintf((pbuf+strlen(pbuf)), "CANCEL REJECT: ");
break;
case 0x69:
sprintf((pbuf+strlen(pbuf)), "CONGESTION CONTROL: ");
break;
case 0x60:
sprintf((pbuf+strlen(pbuf)), "FACILITY: ");
break;
case 0x68:
sprintf((pbuf+strlen(pbuf)), "FACILITY ACKNOWLEDGE: ");
break;
case 0x66:
sprintf((pbuf+strlen(pbuf)), "FACILITY CANCEL: ");
break;
case 0x64:
sprintf((pbuf+strlen(pbuf)), "FACILITY REGISTER: ");
break;
case 0x65:
sprintf((pbuf+strlen(pbuf)), "FACILITY REJECT: ");
break;
case 0x6d:
sprintf((pbuf+strlen(pbuf)), "INFORMATION: ");
break;
case 0x6c:
sprintf((pbuf+strlen(pbuf)), "REGISTER ACKNOWLEDGE: ");
break;
case 0x6f:
sprintf((pbuf+strlen(pbuf)), "REGISTER REJECT: ");
break;
case 0x63:
sprintf((pbuf+strlen(pbuf)), "STATUS: ");
break;
default:
sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x41 MSG=0x%02x, ", buf[i]);
break;
}
}
else
{
sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x%02x MSG=0x%02x, ", pd, buf[i]);
}
/* other information elements */
i++;
for (; i < n;)
{
sprintf((pbuf+strlen(pbuf)), "\n ");
if (buf[i] & 0x80)
{
/* single octett info element */
switch (buf[i] & 0x70)
{
case 0x00: /* reserved */
sprintf((pbuf+strlen(pbuf)), "[reserved single octett info]");
break;
case 0x10: /* shift */
oldcodeset = codeset;
codeset = buf[i] & 0x07;
if (buf[i] & 0x08)
codelock = 0;
else
codelock = 1;
sprintf((pbuf+strlen(pbuf)), "[shift: codeset=%d lock=%d]", codeset, codelock);
break;
case 0x20: /* more data */
sprintf((pbuf+strlen(pbuf)), "[more data]");
break;
case 0x30: /* congestion level */
sprintf((pbuf+strlen(pbuf)), "[congestion level = %d]", buf[i] & 0x0f);
break;
default:
sprintf((pbuf+strlen(pbuf)), "[UNDEF SINGLE OCTET ELEMENT 0x%02x]", buf[i]);
break;
}
i++; /* next */
}
else
{
/* variable length info element */
if (codeset == 0)
{
switch (buf[i])
{
case 0x08:
sprintf((pbuf+strlen(pbuf)), "[cause: ");
i += p_1tr6cause(pbuf, &buf[i]);
goto next;
break;
case 0x0c:
sprintf((pbuf+strlen(pbuf)), "[connected address: ");
i += p_1tr6address(pbuf, &buf[i]);
goto next;
break;
case 0x10:
sprintf((pbuf+strlen(pbuf)), "[call identity: ");
break;
case 0x18:
sprintf((pbuf+strlen(pbuf)), "[channel id: channel=");
i += 2;
switch (buf[i] & 0x03)
{
case 0:
sprintf((pbuf+strlen(pbuf)), "no channel");
break;
case 1:
sprintf((pbuf+strlen(pbuf)), "B-1");
break;
case 2:
sprintf((pbuf+strlen(pbuf)), "B-2");
break;
case 3:
sprintf((pbuf+strlen(pbuf)), "any channel");
break;
}
if (buf[i] & 0x08)
sprintf((pbuf+strlen(pbuf)), " (exclusive)]");
else
sprintf((pbuf+strlen(pbuf)), " (preferred)]");
i++;
goto next;
break;
case 0x20:
sprintf((pbuf+strlen(pbuf)), "[network specific facilities: ");
i++;
len = buf[i];
i+=2;
switch (buf[i])
{
case 1:
sprintf((pbuf+strlen(pbuf)), "Sperre");
break;
case 2:
sprintf((pbuf+strlen(pbuf)), "AWS 1");
break;
case 3:
sprintf((pbuf+strlen(pbuf)), "AWS 2");
break;
case 0xe:
sprintf((pbuf+strlen(pbuf)), "Konferenz");
break;
case 0xf:
sprintf((pbuf+strlen(pbuf)), "B-Kan uebern.");
break;
case 0x10:
sprintf((pbuf+strlen(pbuf)), "aktvrg. ghlt. Vbdg.");
break;
case 0x11:
sprintf((pbuf+strlen(pbuf)), "3er Konf");
break;
case 0x12:
sprintf((pbuf+strlen(pbuf)), "1seitg D/G Wechsel");
break;
case 0x13:
sprintf((pbuf+strlen(pbuf)), "2seitig D/G Wechsel");
break;
case 0x14:
sprintf((pbuf+strlen(pbuf)), "Rufnr. identifiz.");
break;
case 0x15:
sprintf((pbuf+strlen(pbuf)), "GBG");
break;
case 0x17:
sprintf((pbuf+strlen(pbuf)), "ueberg. Ruf");
break;
case 0x1a:
sprintf((pbuf+strlen(pbuf)), "um/weitergel. Ruf");
break;
case 0x1b:
sprintf((pbuf+strlen(pbuf)), "unterdr. A-Rufnr.");
break;
case 0x1e:
sprintf((pbuf+strlen(pbuf)), "Verbdg. deaktivieren");
break;
case 0x1d:
sprintf((pbuf+strlen(pbuf)), "Verbdg. aktivieren");
break;
case 0x1f:
sprintf((pbuf+strlen(pbuf)), "SPV");
break;
case 0x23:
sprintf((pbuf+strlen(pbuf)), "Rueckw. 2seitg. DW");
break;
case 0x24:
sprintf((pbuf+strlen(pbuf)), "Anrufumltg. priv. Netz");
break;
default:
sprintf((pbuf+strlen(pbuf)), "undefined");
break;
}
i++;
sprintf((pbuf+strlen(pbuf)), ", serv=%d", buf[i]);
i++;
sprintf((pbuf+strlen(pbuf)), ", ainfo=%d", buf[i]);
i++;
len-=4;
for (j = 0; j < len; j++)
{
sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]);
}
sprintf((pbuf+strlen(pbuf)),"]");
i += j;
goto next;
break;
case 0x28:
sprintf((pbuf+strlen(pbuf)), "[display: ");
break;
case 0x2c:
sprintf((pbuf+strlen(pbuf)), "[keypad: ");
break;
case 0x6c:
sprintf((pbuf+strlen(pbuf)), "[origination address: ");
i += p_1tr6address(pbuf, &buf[i]);
goto next;
break;
case 0x70:
sprintf((pbuf+strlen(pbuf)), "[destination address: ");
i += p_1tr6address(pbuf, &buf[i]);
goto next;
break;
case 0x7e:
sprintf((pbuf+strlen(pbuf)), "[user-user information: ");
break;
case 0x7f:
sprintf((pbuf+strlen(pbuf)), "[reserved: ");
break;
default:
sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID");
break;
}
}
else if (codeset == 6)
{
switch (buf[i])
{
case 0x01:
sprintf((pbuf+strlen(pbuf)), "[service ind: serv=");
i+= 2;
switch (buf[i])
{
case 0x01:
sprintf((pbuf+strlen(pbuf)), "phone");
break;
case 0x02:
sprintf((pbuf+strlen(pbuf)), "a/b");
break;
case 0x03:
sprintf((pbuf+strlen(pbuf)), "X.21");
break;
case 0x04:
sprintf((pbuf+strlen(pbuf)), "fax g4");
break;
case 0x05:
sprintf((pbuf+strlen(pbuf)), "btx");
break;
case 0x07:
sprintf((pbuf+strlen(pbuf)), "64k data");
break;
case 0x08:
sprintf((pbuf+strlen(pbuf)), "X.25");
break;
case 0x09:
sprintf((pbuf+strlen(pbuf)), "teletex");
break;
case 0x0a:
sprintf((pbuf+strlen(pbuf)), "mixed");
break;
case 0x0d:
sprintf((pbuf+strlen(pbuf)), "temex");
break;
case 0x0e:
sprintf((pbuf+strlen(pbuf)), "picturephone");
break;
case 0x0f:
sprintf((pbuf+strlen(pbuf)), "btx (new)");
break;
case 0x10:
sprintf((pbuf+strlen(pbuf)), "videophone");
break;
default:
sprintf((pbuf+strlen(pbuf)), "undefined");
break;
}
i++;
sprintf((pbuf+strlen(pbuf)), ", ainfo=0x%02x]", buf[i]);
i++;
goto next;
break;
case 0x02:
sprintf((pbuf+strlen(pbuf)), "[charging information: ");
break;
case 0x03:
sprintf((pbuf+strlen(pbuf)), "[date: ");
i++;
len = buf[i];
i++;
for (j = 0; j < len; j++)
{
sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]);
}
sprintf((pbuf+strlen(pbuf)),"]");
i += j;
goto next;
break;
case 0x05:
sprintf((pbuf+strlen(pbuf)), "[facility select: ");
break;
case 0x06:
sprintf((pbuf+strlen(pbuf)), "[status of facilities: ");
break;
case 0x07:
sprintf((pbuf+strlen(pbuf)), "[status of called party: ");
i+=2;
switch (buf[i])
{
case 1:
sprintf((pbuf+strlen(pbuf)), "no information]");
break;
case 2:
sprintf((pbuf+strlen(pbuf)), "is being called]");
break;
default:
sprintf((pbuf+strlen(pbuf)), "undefined (0x%02x)]", buf[i]);
break;
}
i++;
goto next;
break;
case 0x08:
sprintf((pbuf+strlen(pbuf)), "[additional tx attributes: ");
i++;
len = buf[i];
i++;
for (j = 0; j < len; j++)
{
switch (buf[j+i] &0x70)
{
case 0:
sprintf((pbuf+strlen(pbuf)), "no satellite link");
break;
case 1:
sprintf((pbuf+strlen(pbuf)), "one satellite link");
break;
case 2:
sprintf((pbuf+strlen(pbuf)), "two satellite links");
break;
case 3:
sprintf((pbuf+strlen(pbuf)), "three satellite links");
break;
default:
sprintf((pbuf+strlen(pbuf)), "undefined value");
break;
}
if (buf[j+i] & 0x80)
sprintf((pbuf+strlen(pbuf)),"(flag=req)]");
else
sprintf((pbuf+strlen(pbuf)),"(flag=ind)]");
}
i += j;
goto next;
break;
default:
sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID");
break;
}
}
else
{
sprintf((pbuf+strlen(pbuf)), "[ILLEGAL CODESET = 0x%02x", codeset);
}
i++; /* index -> length */
len = buf[i];
i++; /* index -> 1st param */
for (j = 0; j < len; j++)
{
sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]);
}
sprintf((pbuf+strlen(pbuf)),"]");
i += len;
next:
if (!codelock && (codeset != oldcodeset))
codeset = oldcodeset;
}
}
sprintf((pbuf+strlen(pbuf)),"\n");
}
/*---------------------------------------------------------------------------*
* decode and print the cause
*---------------------------------------------------------------------------*/
static int
p_1tr6cause(char *pbuf, unsigned char buf[])
{
int j;
int len;
int i = 0;
i++; /* index -> length */
len = buf[i];
switch (len)
{
case 0:
sprintf((pbuf+strlen(pbuf)), "%s", print_cause_1tr6(0));
break;
case 1:
i++;
sprintf((pbuf+strlen(pbuf)), "%s", print_cause_1tr6(buf[i] & 0x7f));
break;
case 2:
i++;
sprintf((pbuf+strlen(pbuf)), "%s, location: ", print_cause_1tr6(buf[i] & 0x7f));
i++;
switch (buf[i] & 0x0f)
{
case 0x04:
sprintf((pbuf+strlen(pbuf)), "public network");
break;
case 0x05:
sprintf((pbuf+strlen(pbuf)), "private network");
break;
case 0x0f:
sprintf((pbuf+strlen(pbuf)), "no information");
break;
default:
sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f);
break;
}
break;
default:
i++; /* index -> length */
len = buf[i];
i++; /* index -> 1st param */
for (j = 0; j < len; j++)
{
sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]);
}
break;
}
i++;
sprintf((pbuf+strlen(pbuf)),"]");
return(i);
}
/*---------------------------------------------------------------------------*
* decode and print the ISDN (telephone) number
*---------------------------------------------------------------------------*/
static int
p_1tr6address(char *pbuf, unsigned char buf[])
{
int j;
int len;
int i = 0;
int tp;
i++; /* index -> length */
len = buf[i];
i++; /* index -> 1st param */
tp = buf[i];
i++;
len--;
for (j = 0; j < len; j++)
{
sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]);
}
switch ((tp & 0x70) >> 4)
{
case 0:
sprintf((pbuf+strlen(pbuf)), " (type=unknown, ");
break;
case 1:
sprintf((pbuf+strlen(pbuf)), " (type=international, ");
break;
case 2:
sprintf((pbuf+strlen(pbuf)), " (type=national, ");
break;
default:
sprintf((pbuf+strlen(pbuf)), " (type=%d, ", ((tp & 0x70) >> 4));
break;
}
switch (tp & 0x0f)
{
case 0:
sprintf((pbuf+strlen(pbuf)), "plan=unknown)");
break;
case 1:
sprintf((pbuf+strlen(pbuf)), "plan=ISDN)");
break;
default:
sprintf((pbuf+strlen(pbuf)), "plan=%d)", (tp & 0x0f));
break;
}
sprintf((pbuf+strlen(pbuf)),"]");
i += j;
return(i);
}
/* EOF */