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

252 lines
6.4 KiB
C

/* atmarp.c - RFC1577 ATMARP control */
/* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if_arp.h>
#include <signal.h>
#include <stdint.h>
#include <linux/atmarp.h>
#include <linux/atmclip.h>
#include "atm.h"
#include "atmd.h"
#include "atmarpd.h"
#define BUF_SIZE 4096
static int query_result(struct atmarp_req *reply)
{
unsigned char *ipp = (unsigned char *) &reply->ip;
char buf[MAX_ATM_ADDR_LEN+1];
int error;
printf("IP: %d.%d.%d.%d\n",ipp[0],ipp[1],ipp[2],ipp[3]);
if (!atmsvc_addr_in_use(reply->addr)) return 0;
error = atm2text(buf,sizeof(buf),(struct sockaddr *) &reply->addr,
A2T_PRETTY | A2T_NAME) < 0;
if (error) strcpy(buf,"<invalid>");
printf("ATM: %s\n",buf);
return error ? 1 : 0;
}
static int send_request(struct atmarp_req *req)
{
struct atmarp_req reply;
int s,len;
s = un_attach(ATMARP_SOCKET_PATH);
if (s < 0) {
perror("un_attach");
exit(1);
}
if (write(s,req,sizeof(*req)) < 0) {
perror("write");
exit(1);
}
len = read(s,&reply,sizeof(reply));
if (len < 0) {
perror("read");
exit(1);
}
if (req->type == art_query) return query_result(&reply);
if (len != sizeof(int)) {
fprintf(stderr,"bad read: %d != %d\n",len,sizeof(int));
exit(1);
}
if (*(int *) &reply < 0) {
fprintf(stderr,"atmarp: %s\n",strerror(-*(int *) &reply));
exit(1);
}
return *(int *) &reply;
}
static int print_table(void)
{
char buffer[BUF_SIZE];
int fd,size;
if ((fd = open(ATMARP_DUMP_DIR "/" ATMARP_DUMP_FILE,O_RDONLY)) < 0) {
perror("open " ATMARP_DUMP_DIR "/" ATMARP_DUMP_FILE);
return 1;
}
while ((size = read(fd,buffer,BUF_SIZE))) {
if (size < 0) {
perror("read " ATMARP_DUMP_DIR "/" ATMARP_DUMP_FILE);
return 1;
}
if (write(0,buffer,size) < 0) {
perror("write stdout");
return 1;
}
}
return 0;
}
static void usage(const char *name)
{
fprintf(stderr,"usage: %s -a\n",name);
fprintf(stderr,"%6s %s -c [[atm]N]\n","",name);
fprintf(stderr,"%6s %s -q ip_addr [qos qos_spec] [sndbuf bytes]\n","",name);
fprintf(stderr,"%6s %s -s ip_addr [itf.]vpi.vci [pcr value] [qos spec] "
"[sndbuf bytes]\n%8s [temp] [pub] [null]\n","",name,"");
fprintf(stderr,"%6s %s -s ip_addr atm_addr [pcr value] [qos spec] "
"[sndbuf bytes] [temp]\n%8s [pub] [arpsrv]\n","",name,"");
fprintf(stderr,"%6s %s -d ip_addr [arpsrv]\n","",name);
#if 0 /* undocumented */
fprintf(stderr,"%6s %s -Q ip_addr\n","",name);
#endif
fprintf(stderr,"%6s %s -V\n","",name);
exit(1);
}
int main(int argc,char **argv)
{
struct atmarp_req req;
int c,i,num;
char *here,*end;
signal(SIGHUP, SIG_IGN);
req.type = 0;
while ((c = getopt(argc,argv,"acdqQsV")) != EOF)
switch (c) {
case 'a':
if (argc != optind || req.type) usage(argv[0]);
req.type = art_table;
/* (void) send_request(&req); @@@ fix this later */
return print_table();
case 'c':
if (req.type) usage(argv[0]);
req.type = art_create;
break;
case 'd':
if (req.type) usage(argv[0]);
req.type = art_delete;
break;
case 'q':
if (req.type) usage(argv[0]);
req.type = art_qos;
break;
case 'Q':
if (req.type) usage(argv[0]);
req.type = art_query;
break;
case 's':
if (req.type) usage(argv[0]);
req.type = art_set;
break;
case 'V':
printf("%s\n",VERSION);
return 0;
default:
usage(argv[0]);
}
switch (req.type) {
case art_create:
if (argc == optind) req.itf = -1;
else {
if (argc != optind+1) usage(argv[0]);
here = argv[optind];
if (strlen(here) > 3 && !strncmp(here,"atm",3)) here += 3;
req.itf = strtoul(here,&end,10);
if (*end || (here[0] == '0' && here[1])) {
usage(argv[0]);
return 1;
}
}
num = send_request(&req);
if (req.itf == -1) printf("atm%d\n",num);
return 0;
case art_qos:
if (argc < optind+1) usage(argv[0]);
/* fall through */
case art_set:
if (argc < optind+2) usage(argv[0]);
break;
case art_query:
if (argc != optind+1) usage(argv[0]);
break;
case art_delete:
if (argc < optind+1) usage(argv[0]);
break;
default:
usage(argv[0]);
}
req.ip = text2ip(argv[optind],NULL,T2I_NAME | T2I_ERROR);
if (req.ip == INADDR_NONE) return 1;
req.flags = ATF_PERM;
if (req.type == art_qos) {
memset(&req.qos,0,sizeof(req.qos));
req.sndbuf = 0;
for (i = optind+1; i < argc; i++)
if (!strcmp(argv[i],"qos")) {
if (++i >= argc) usage(argv[0]);
if (text2qos(argv[i],&req.qos,0)) usage(argv[0]);
}
else if (!strcmp(argv[i],"sndbuf")) {
if (++i >= argc) usage(argv[0]);
req.sndbuf = strtol(argv[i],&end,0);
if (*end) usage(argv[0]);
}
else if (i != optind+1 || argc != optind+2 ||
text2qos(argv[optind+1],&req.qos,0)) usage(argv[0]);
}
if (req.type == art_set) {
memset(&req.qos,0,sizeof(req.qos));
req.sndbuf = 0;
for (i = optind+2; i < argc; i++)
if (!strcmp(argv[i],"temp")) req.flags &= ~ATF_PERM;
else if (!strcmp(argv[i],"pub")) req.flags |= ATF_PUBL;
else if (!strcmp(argv[i],"null")) req.flags |= ATF_NULL;
else if (!strcmp(argv[i],"arpsrv")) req.flags |= ATF_ARPSRV;
else if (!strcmp(argv[i],"qos")) {
if (++i >= argc) usage(argv[0]);
if (text2qos(argv[i],&req.qos,0)) usage(argv[0]);
}
else if (!strcmp(argv[i],"sndbuf")) {
if (++i >= argc) usage(argv[0]);
req.sndbuf = strtol(argv[i],&end,0);
if (*end) usage(argv[0]);
}
else if (!strcmp(argv[i],"pcr")) {
if (++i >= argc) usage(argv[0]);
req.qos.txtp.traffic_class = req.qos.rxtp.traffic_class =
ATM_CBR;
req.qos.txtp.max_pcr = req.qos.rxtp.max_pcr =
strtol(argv[i],&end,0);
if (*end) usage(argv[0]);
}
else usage(argv[0]);
if (text2atm(argv[optind+1],(struct sockaddr *) &req.addr,
sizeof(req.addr),T2A_NAME) < 0) {
fprintf(stderr,"%s: invalid ATM address\n",argv[optind+1]);
return 1;
}
}
if (req.type == art_delete && optind+1 < argc) {
if (optind+2 < argc || strcmp(argv[optind+1],"arpsrv")) usage(argv[0]);
req.flags |= ATF_ARPSRV;
}
if (!req.qos.aal) req.qos.aal = ATM_AAL5;
send_request(&req);
return 0;
}