137 lines
3.0 KiB
C
137 lines
3.0 KiB
C
/* atmloop.c - get/set loopback mode of ATM interfaces */
|
|
|
|
/* Written 2000 by Werner Almesberger, EPFL ICA */
|
|
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <atm.h>
|
|
#include <linux/atmdev.h>
|
|
|
|
|
|
static void usage(const char *name)
|
|
{
|
|
fprintf(stderr,"usage: %s -s [ -l level ] [ -r level ] [ itf ]\n",name);
|
|
fprintf(stderr,"%7s%s [ itf ]\n","",name);
|
|
fprintf(stderr,"%7s%s -q [ itf ]\n","",name);
|
|
fprintf(stderr,"%7s%s -V\n","",name);
|
|
fprintf(stderr," levels: aal = AAL PDU, atm = ATM cell,\n");
|
|
fprintf(stderr,"%10sphy = line (digital), analog = line (analog)\n","");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
static int text2level(const char *name,const char *s)
|
|
{
|
|
if (!strcmp(s,"aal")) return __ATM_LM_AAL;
|
|
if (!strcmp(s,"atm")) return __ATM_LM_ATM;
|
|
if (!strcmp(s,"phy")) return __ATM_LM_PHY;
|
|
if (!strcmp(s,"analog")) return __ATM_LM_ANALOG;
|
|
usage(name);
|
|
return 0; /* uh ... */
|
|
}
|
|
|
|
|
|
static const char *level2text(int level)
|
|
{
|
|
switch (level) {
|
|
case __ATM_LM_AAL:
|
|
return "aal";
|
|
case __ATM_LM_ATM:
|
|
return "atm";
|
|
case __ATM_LM_PHY:
|
|
return "phy";
|
|
case __ATM_LM_ANALOG:
|
|
return "analog";
|
|
default:
|
|
return "???";
|
|
}
|
|
}
|
|
|
|
|
|
static void print_levels(int levels,int show_none)
|
|
{
|
|
int mask;
|
|
|
|
if (!levels) {
|
|
if (show_none) printf(" (none)");
|
|
return;
|
|
}
|
|
for (mask = 1; levels; mask += mask) {
|
|
if (!(mask & levels)) continue;
|
|
printf(" %s",level2text(__ATM_LM_XTLOC(mask)));
|
|
levels &= ~mask;
|
|
}
|
|
}
|
|
|
|
|
|
int main(int argc,char **argv)
|
|
{
|
|
int local = ATM_LM_NONE,remote = ATM_LM_NONE,mode;
|
|
int set = 0,query = 0;
|
|
struct atmif_sioc req;
|
|
int s,c;
|
|
|
|
req.number = 0;
|
|
while ((c = getopt(argc,argv,"l:qr:sV")) != EOF)
|
|
switch (c) {
|
|
case 'l':
|
|
if (local) usage(*argv);
|
|
local = text2level(*argv,optarg);
|
|
break;
|
|
case 'q':
|
|
query = 1;
|
|
break;
|
|
case 'r':
|
|
if (remote) usage(*argv);
|
|
remote = text2level(*argv,optarg);
|
|
break;
|
|
case 's':
|
|
set = 1;
|
|
break;
|
|
case 'V':
|
|
printf("%s\n",VERSION);
|
|
return 0;
|
|
default:
|
|
usage(*argv);
|
|
}
|
|
if (argc > optind+1) usage(*argv);
|
|
if (argc == optind+1) {
|
|
char *end;
|
|
|
|
req.number = strtoul(argv[optind],&end,0);
|
|
if (*end) usage(*argv);
|
|
}
|
|
mode = __ATM_LM_MKLOC(local) | __ATM_LM_MKRMT(remote);
|
|
if ((mode && !set) || (set && query)) usage(*argv);
|
|
s = socket(PF_ATMPVC,SOCK_DGRAM,0);
|
|
if (s < 0) {
|
|
perror("socket");
|
|
return 1;
|
|
}
|
|
if (set) {
|
|
req.arg = (void *) mode;
|
|
req.length = 0;
|
|
if (ioctl(s,ATM_SETLOOP,&req) < 0) {
|
|
perror("ioctl ATM_SETLOOP");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
req.arg = &mode;
|
|
req.length = sizeof(mode);
|
|
if (ioctl(s,query ? ATM_QUERYLOOP : ATM_GETLOOP,&req) < 0) {
|
|
perror(query ? "ioctl ATM_QUERYLOOP" : "ioctl ATM_GETLOOP");
|
|
return 1;
|
|
}
|
|
printf("local: ");
|
|
print_levels(__ATM_LM_XTLOC(mode),query);
|
|
printf("\nremote:");
|
|
print_levels(__ATM_LM_XTRMT(mode),query);
|
|
printf("\n");
|
|
return 0;
|
|
}
|