1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Files
2024-07-22 01:58:46 -03:00

170 lines
4.1 KiB
C

/* atmdump.c - ATM raw cell dumper */
/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h> /* for htonl and ntohl */
#include <atm.h>
static const char *pti[] = { "Data SDU 0","Data SDU 1","Data SDU 0, CE",
"Data SDU 1, CE","Segment OAM F5","End-to-end OAM F5","Reserved (RM)",
"Reserved" };
static int interval = 0; /* display absolute time by default */
#define GET(item) ((*cell & ATM_HDR_##item##_MASK) >> ATM_HDR_##item##_SHIFT)
static void analyze(unsigned long *cell,struct timeval stamp)
{
static struct timeval last;
static int first = 1;
int i;
if (first || !interval) {
printf("%2d:%02d:%02d",(int) ((stamp.tv_sec/3600) % 24),
(int) ((stamp.tv_sec/60) % 60),(int) (stamp.tv_sec % 60));
if (interval) {
first = 0;
last = stamp;
}
}
else {
struct timeval diff;
diff.tv_sec = stamp.tv_sec-last.tv_sec;
diff.tv_usec = stamp.tv_usec-last.tv_usec;
while (diff.tv_usec < 0) {
diff.tv_usec += 1000000;
diff.tv_sec--;
}
last = stamp;
printf("%8ld",(long) diff.tv_sec);
}
printf(".%06ld: VPI=%ld VCI=%ld, GFC=0x%lx, CLP=%ld, %s (PTI %ld)\n",
(long) stamp.tv_usec,GET(VPI),GET(VCI),GET(GFC),*cell & ATM_HDR_CLP,
pti[GET(PTI)],GET(PTI));
for (i = 0; i < ATM_CELL_PAYLOAD; i++) {
if (!(i & 15)) printf(" ");
printf("%02x ",((unsigned char *) cell)[i+4]);
if ((i & 15) == 15) putchar('\n');
}
}
static void usage(const char *name)
{
int i;
fprintf(stderr,"usage: %s [ -i ] [ -t type [ -g gfc ] [ -c ] ] "
"[itf.]vpi.vci\n",name);
for (i = 0; i < 8; i++)
fprintf(stderr," %-6s %d %s\n",i ? "" : "type",i,pti[i]);
fprintf(stderr," gfc 0-15, default 0\n");
exit(1);
}
int main(int argc,char **argv)
{
unsigned long buf[13]; /* ugly */
struct sockaddr_atmpvc addr;
struct atm_qos qos;
char *name,*end;
int type,gfc,clp;
int c,s,size;
type = -1;
gfc = clp = 0; /* for GCC */
name = argv[0];
while ((c = getopt(argc,argv,"t:g:c")) != EOF)
switch (c) {
case 'i':
interval = 1;
break;
case 't':
type = strtol(optarg,&end,0);
if (*end || type < 0 || type > 7) usage(name);
break;
case 'g':
gfc = strtol(optarg,&end,0);
if (*end || gfc < 0 || gfc > 15) usage(name);
break;
case 'c':
clp = 1;
break;
default:
usage(name);
}
if (argc != optind+1) usage(name);
if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) {
perror("socket");
return 1;
}
memset(&addr,0,sizeof(addr));
if (text2atm(argv[optind],(struct sockaddr *) &addr,sizeof(addr),T2A_PVC)
< 0) usage(name);
memset(&qos,0,sizeof(qos));
qos.aal = ATM_AAL0;
if (type == -1) {
qos.rxtp.traffic_class = ATM_UBR;
qos.rxtp.max_sdu = 52;
}
else {
qos.txtp.traffic_class = ATM_UBR;
qos.txtp.max_sdu = 52;
}
if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) {
perror("setsockopt SO_ATMQOS");
return 1;
}
if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
return 1;
}
if (type == -1) {
while ((size = read(s,buf,52)) == 52) {
struct timeval stamp;
if (ioctl(s,SIOCGSTAMP,&stamp) < 0) {
perror("ioctl SIOCGSTAMP");
return 1;
}
analyze(buf,stamp);
fflush(stdout);
}
if (size < 0) perror("read");
else fprintf(stderr,"short read (%d bytes)\n",size);
return 1;
}
if ((size = read(0,buf+1,ATM_CELL_PAYLOAD)) < 0) {
perror("read stdin");
return 1;
}
if (size < ATM_CELL_PAYLOAD)
memset((unsigned char *) (buf+1)+size,0,ATM_CELL_PAYLOAD-size);
*buf = (gfc << ATM_HDR_GFC_SHIFT) |
(addr.sap_addr.vpi << ATM_HDR_VPI_SHIFT) |
(addr.sap_addr.vci << ATM_HDR_VCI_SHIFT) |
(type << ATM_HDR_PTI_SHIFT) | clp;
if ((size = write(s,buf,ATM_CELL_SIZE-1)) < 0) {
perror("write to network");
return 1;
}
if (size < ATM_CELL_SIZE-1) {
fprintf(stderr,"short write (%d bytes)\n",size);
return 1;
}
return 0;
}