212 lines
5.3 KiB
C
Executable File
212 lines
5.3 KiB
C
Executable File
/* atm2text.c - Converts binary encoding of ATM address to textual
|
|
representation */
|
|
|
|
/* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "atm.h"
|
|
#include "atmres.h"
|
|
|
|
|
|
static int put_item(char **buffer,int *length,int value)
|
|
{
|
|
char *walk,*scan;
|
|
char tmp;
|
|
|
|
if (!*length) return FATAL;
|
|
if (value <= 0) {
|
|
if (!value) *(*buffer)++ = '0';
|
|
else if (value == ATM_VCI_ANY) *(*buffer)++ = '*';
|
|
else if (value == ATM_VCI_UNSPEC) *(*buffer)++ = '?';
|
|
else return FATAL;
|
|
/* ATM_*_ANY and ATM_*_UNSPEC have all the same value,
|
|
respectively */
|
|
(*length)--;
|
|
return 0;
|
|
}
|
|
for (walk = *buffer; value; value /= 10) {
|
|
if (!(*length)--) return FATAL;
|
|
*walk++ = '0'+(value % 10);
|
|
}
|
|
for (scan = walk-1; scan > *buffer; (*buffer)++) {
|
|
tmp = *scan;
|
|
*scan-- = **buffer;
|
|
**buffer = tmp;
|
|
}
|
|
*buffer = walk;
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int do_pvc(char *buffer,int length,const struct sockaddr_atmpvc *addr,
|
|
int flags)
|
|
{
|
|
int orig_len;
|
|
|
|
orig_len = length;
|
|
if (put_item(&buffer,&length,addr->sap_addr.itf)) return FATAL;
|
|
if (!length--) return FATAL;
|
|
*buffer++ = '.';
|
|
if (put_item(&buffer,&length,addr->sap_addr.vpi)) return FATAL;
|
|
if (!length--) return FATAL;
|
|
*buffer++ = '.';
|
|
if (put_item(&buffer,&length,addr->sap_addr.vci)) return FATAL;
|
|
if (!length) return FATAL;
|
|
*buffer = 0;
|
|
return orig_len-length;
|
|
}
|
|
|
|
|
|
static int do_svc(char *buffer,int length,const struct sockaddr_atmsvc *addr,
|
|
int flags)
|
|
{
|
|
static int pure[] = { 20 };
|
|
static int bin[] = { 1,2,10,6,1 };
|
|
static int local[] = { 1,12,6,1 };
|
|
static int e164[] = { 4,6,1 };
|
|
|
|
int orig_len,len,i,left,value;
|
|
int *fmt;
|
|
|
|
orig_len = length;
|
|
if (!*addr->sas_addr.pub && !*addr->sas_addr.prv) return FATAL;
|
|
if (*addr->sas_addr.pub) {
|
|
len = strlen(addr->sas_addr.pub);
|
|
if (!*addr->sas_addr.prv && length >= len+2) {
|
|
*buffer++ = '+';
|
|
length--;
|
|
}
|
|
if (length < len+1) return FATAL;
|
|
strcpy(buffer,addr->sas_addr.pub);
|
|
buffer += len;
|
|
length -= len;
|
|
if (*addr->sas_addr.prv) {
|
|
if (!length--) return FATAL;
|
|
*buffer++ = '+';
|
|
}
|
|
}
|
|
if (*addr->sas_addr.prv) {
|
|
fmt = pure;
|
|
i = 0;
|
|
if (flags & A2T_PRETTY)
|
|
switch (*addr->sas_addr.prv) {
|
|
case ATM_AFI_DCC:
|
|
case ATM_AFI_ICD:
|
|
case ATM_AFI_DCC_GROUP:
|
|
case ATM_AFI_ICD_GROUP:
|
|
fmt = bin;
|
|
break;
|
|
case ATM_AFI_LOCAL:
|
|
case ATM_AFI_LOCAL_GROUP:
|
|
fmt = local;
|
|
break;
|
|
case ATM_AFI_E164:
|
|
case ATM_AFI_E164_GROUP:
|
|
for (i = 2; i < 17; i++)
|
|
if (addr->sas_addr.prv[i >> 1] & (0xf0 >> 4*(i & 1)))
|
|
break;
|
|
while (i < 17) {
|
|
value = (addr->sas_addr.prv[i >> 1] >> 4*(1-(i & 1))) &
|
|
0xf;
|
|
if (value > 9) return FATAL;
|
|
if (!length--) return FATAL;
|
|
*buffer++ = '0'+value;
|
|
i++;
|
|
}
|
|
if (!length--) return FATAL;
|
|
*buffer++ = ':';
|
|
i = 9;
|
|
fmt = e164;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
for (left = *fmt++; i < ATM_ESA_LEN; i++) {
|
|
if (!left--) {
|
|
if (!length--) return FATAL;
|
|
*buffer++ = '.';
|
|
left = *fmt++-1;
|
|
}
|
|
if (length < 2) return FATAL;
|
|
sprintf(buffer,"%02X",addr->sas_addr.prv[i]);
|
|
length -= 2;
|
|
buffer += 2;
|
|
}
|
|
}
|
|
if (!length) return FATAL;
|
|
*buffer = 0;
|
|
return orig_len-length;
|
|
}
|
|
|
|
|
|
static int search(FILE *file,char *buffer,int length,
|
|
const struct sockaddr *addr,int flags)
|
|
{
|
|
struct sockaddr_atmsvc temp;
|
|
char line[MAX_ATM_NAME_LEN+1];
|
|
const char *here;
|
|
|
|
while (fgets(line,MAX_ATM_NAME_LEN,file)) {
|
|
if (!(here = strtok(line,"\t\n "))) continue;
|
|
if (text2atm(here,(struct sockaddr *) &temp,sizeof(temp),flags) < 0)
|
|
continue;
|
|
if (temp.sas_family != addr->sa_family) continue;
|
|
if (temp.sas_family == AF_ATMPVC) {
|
|
if (((const struct sockaddr_atmpvc *) addr)->sap_addr.itf !=
|
|
((struct sockaddr_atmpvc *) &temp)->sap_addr.itf ||
|
|
((const struct sockaddr_atmpvc *) addr)->sap_addr.vpi !=
|
|
((struct sockaddr_atmpvc *) &temp)->sap_addr.vpi ||
|
|
((const struct sockaddr_atmpvc *) addr)->sap_addr.vci !=
|
|
((struct sockaddr_atmpvc *) &temp)->sap_addr.vci) continue;
|
|
}
|
|
else if (!atm_equal(addr,(struct sockaddr *) &temp,0,0)) continue;
|
|
while ((here = strtok(NULL,"\t\n ")))
|
|
if (strlen(here) < length) {
|
|
strcpy(buffer,here);
|
|
return 0;
|
|
}
|
|
return FATAL;
|
|
}
|
|
return TRY_OTHER;
|
|
}
|
|
|
|
|
|
static int try_name(char *buffer,int length,const struct sockaddr *addr)
|
|
{
|
|
FILE *file;
|
|
int result;
|
|
|
|
if (!(file = fopen(HOSTS_ATM,"r"))) return TRY_OTHER;
|
|
result = search(file,buffer,length,addr,addr->sa_family == AF_ATMPVC ?
|
|
T2A_PVC : T2A_SVC);
|
|
(void) fclose(file);
|
|
return result;
|
|
}
|
|
|
|
|
|
int atm2text(char *buffer,int length,const struct sockaddr *addr,int flags)
|
|
{
|
|
int result;
|
|
|
|
if (addr->sa_family != AF_ATMPVC && addr->sa_family != AF_ATMSVC)
|
|
return -1;
|
|
if (!length) return -1;
|
|
if (flags & A2T_NAME) {
|
|
result = try_name(buffer,length,addr);
|
|
if (result == TRY_OTHER && !(flags & A2T_LOCAL))
|
|
result = ans_byaddr(buffer,length,
|
|
(const struct sockaddr_atmsvc *) addr,flags);
|
|
if (result == FATAL) return FATAL;
|
|
if (result != TRY_OTHER) return strlen(buffer);
|
|
}
|
|
if (addr->sa_family == AF_ATMPVC)
|
|
return do_pvc(buffer,length,(const struct sockaddr_atmpvc *) addr,
|
|
flags);
|
|
else return do_svc(buffer,length,(const struct sockaddr_atmsvc *) addr,
|
|
flags);
|
|
return -1;
|
|
}
|