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

88 lines
2.6 KiB
C

/* atmequal.c - Compares ATM addresses for equality */
/* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include "atm.h"
static int atm_equal_pvc(const struct sockaddr_atmpvc *a,
const struct sockaddr_atmpvc *b,int flags)
{
int wc = flags & AXE_WILDCARD;
#define EQ(field,any) \
(a->sap_addr.field == b->sap_addr.field || \
(wc && (a->sap_addr.field == any || b->sap_addr.field == any)))
return EQ(itf,ATM_ITF_ANY) && EQ(vpi,ATM_VPI_ANY) && EQ(vci,ATM_VCI_ANY);
#undef EQ
}
static int atm_equal_svc(const struct sockaddr_atmsvc *a,
const struct sockaddr_atmsvc *b,int len,int flags)
{
const unsigned char *a_prv,*b_prv;
int len_a,len_b;
if (!(flags & AXE_WILDCARD)) len = ATM_ESA_LEN*8;
assert(len >= 0 && len <= ATM_ESA_LEN*8);
if (*a->sas_addr.prv && *b->sas_addr.prv) {
a_prv = a->sas_addr.prv;
b_prv = b->sas_addr.prv;
if ((flags & AXE_WILDCARD) && len >= 8 && *a_prv == ATM_AFI_E164 &&
*b_prv == ATM_AFI_E164) {
if (len < 68) return 0; /* no comparison possible */
else {
int a_pos,b_pos;
unsigned char a_val,b_val;
for (a_pos = 2; !a_prv[a_pos/2]; a_pos += 2);
if (!(a_prv[a_pos/2] & 0xf0)) a_pos++;
for (b_pos = 2; !b_prv[b_pos/2]; b_pos += 2);
if (!(b_prv[b_pos/2] & 0xf0)) b_pos++;
while (1) {
a_val = (a_prv[a_pos/2] >> (((~a_pos) & 1)*4)) & 0xf;
b_val = (b_prv[b_pos/2] >> (((~b_pos) & 1)*4)) & 0xf;
if (a_val == 15 || b_val == 15) break;
if (a_val != b_val) return 0;
a_pos++;
b_pos++;
}
a_prv += 9;
b_prv += 9;
if ((len -= 72) < 0) len = 0;
}
}
if (memcmp(a_prv,b_prv,len/8)) return 0;
if ((len & 7) && (a_prv[len/8+1]^b_prv[len/8+1]) &
(0xff00 >> (len & 7))) return 0;
return 1;
}
if ((*a->sas_addr.prv || *b->sas_addr.prv) && !(flags & AXE_PRVOPT))
return 0;
if (!*a->sas_addr.pub || !*b->sas_addr.pub) return 0;
len_a = strlen(a->sas_addr.pub);
len_b = strlen(b->sas_addr.pub);
if (len_a != len_b && !(flags & AXE_WILDCARD)) return 0;
return !strncmp(a->sas_addr.pub,b->sas_addr.pub,len_a < len_b ? len_a :
len_b);
}
int atm_equal(const struct sockaddr *a,const struct sockaddr *b,int len,
int flags)
{
assert((a->sa_family == AF_ATMPVC && b->sa_family == AF_ATMPVC) ||
(a->sa_family == AF_ATMSVC && b->sa_family == AF_ATMSVC));
if (a->sa_family == AF_ATMPVC)
return atm_equal_pvc((const struct sockaddr_atmpvc *) a,
(const struct sockaddr_atmpvc *) b,flags);
return atm_equal_svc((const struct sockaddr_atmsvc *) a,
(const struct sockaddr_atmsvc *) b,len,flags);
}