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

362 lines
8.1 KiB
C
Executable File

/*
*
* Configuration DB
*
* $Id: //BBN_Linux/Branch/Branch_for_Rel_TP_ASEAN_20161216/tclinux_phoenix/apps/public/linux-atm/lane/ldb.c#1 $
*
*/
/* System includes */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <atm.h>
#include <ctype.h>
/* Local includes */
#include "lecs.h"
#include "ldb.h"
#include "mem_lecs.h"
/* Local protos */
static void dump_elan(Elan_t *elan);
static int valid_char(char test);
static const char* get_type_string(char lan_type);
static const char* get_max_frame_size_string(char max_frame);
static const char* get_atm_addr_string(const unsigned char *addr);
static void dump_elan(Elan_t *elan);
static int match_addresses(Elan_t *elan, unsigned char *addr);
/* Local data */
static unsigned char *lecs_address =NULL;
static Elan_t *elan_arr[32];
static Elan_t *default_elan = NULL;
static int no_elans=0;
static char tmpbuffer[256];
#define MIN(a,b) ((a<b)?a:b)
#define COMP_NAME "LDB"
Elan_t*
new_elan(const char *name)
{
elan_arr[no_elans] = (Elan_t *)mem_alloc(COMP_NAME, sizeof(Elan_t));
if (!elan_arr[no_elans]) {
return NULL;
}
memset(elan_arr[no_elans],0,sizeof(Elan_t));
elan_arr[no_elans]->elan_name_size = MIN(32, strlen(name));
strncpy(elan_arr[no_elans]->elan_name, name,
elan_arr[no_elans]->elan_name_size);
/* Default values */
elan_arr[no_elans]->type = LE_LAN_TYPE_UNSPECIFIED;
elan_arr[no_elans]->max_frame = LE_MAX_FRAME_UNSPECIFIED;
return elan_arr[no_elans++];
}
int
add_les(Elan_t *elan, const char *addr)
{
struct sockaddr_atmsvc tmp;
assert(elan);
if (elan->les_addr[18] ||
elan->les_addr[17] ||
elan->les_addr[16] ||
elan->les_addr[15] ||
elan->les_addr[14] ||
elan->les_addr[13] ||
elan->les_addr[12]) {
printf("LES address already set for this ELAN!\n");
return 0;
}
if (text2atm(addr,(struct sockaddr *)&tmp,sizeof(tmp),T2A_SVC|T2A_NAME)<0) {
return -1;
}
memcpy(elan->les_addr, tmp.sas_addr.prv, ATM_ESA_LEN);
return 0;
}
static int
valid_char(char test)
{
return ((test >= '0' && test <= '9') || (test >= 'a' || test <= 'f') ||
(test >= 'A' && test <= 'F') || test == 'x' || test == 'X');
}
int
add_atm(Elan_t *elan, char *addr)
{
char *tmp;
char *ch;
int pos=0;
ch = addr;
assert(elan && addr);
tmp = (char*)mem_alloc(COMP_NAME, ATM_ESA_LEN*2);
if (!tmp)
return -1;
memset(tmp,0,ATM_ESA_LEN*2);
while ((*ch)!='\0' && (*(ch+1))!='\0') {
if (!valid_char(*ch)) {
mem_free(COMP_NAME, tmp);
return -1;
}
if (*(ch+1) == '.' || *(ch+1) == ':' || *(ch+1) == '-') {
tmp[pos++] = '0';
tmp[pos++] = *ch;
ch+=2;
} else if (valid_char(*(ch+1))) {
tmp[pos++] = *ch;
tmp[pos++] = *(ch+1);
ch+=2;
} else {
mem_free(COMP_NAME, tmp);
return -1;
}
if (*ch == '.' || *ch == '-' || *ch == ':')
ch++;
}
if ((*ch) != '\0' && *(ch+1) == '\0') {
tmp[pos++] = '0';
tmp[pos++] = *ch;
}
if (pos<40) {
mem_free(COMP_NAME, tmp);
return -1;
}
elan->addresses[elan->no_addresses++] = tmp;
return 0;
}
void
set_default(Elan_t *elan)
{
if (default_elan) {
printf("Warning! Default ELAN already set!\n");
return;
}
default_elan = elan;
}
static const char*
get_type_string(char lan_type)
{
switch (lan_type) {
case LE_LAN_TYPE_UNSPECIFIED:
return "<Unspecified>";
case LE_LAN_TYPE_802_3:
return "802.3";
case LE_LAN_TYPE_802_5:
return "802.5";
default:
return "UNKNOWN TYPE";
}
}
static const char*
get_max_frame_size_string(char max_frame)
{
switch (max_frame) {
case LE_MAX_FRAME_UNSPECIFIED:
return "<Unspecified>";
case LE_MAX_FRAME_1516:
return "1516";
case LE_MAX_FRAME_4544:
return "4544";
case LE_MAX_FRAME_9234:
return "9234";
case LE_MAX_FRAME_18190:
return "18190";
default:
return "UNKNOWN FRAME SIZE";
}
}
static const char*
get_atm_addr_string(const unsigned char *addr)
{
int i;
for(i=0;i<ATM_ESA_LEN-1;i++) {
sprintf(&tmpbuffer[i*3],"%2.2x.", addr[i]&0xff);
}
sprintf(&tmpbuffer[(ATM_ESA_LEN-1)*3],"%2.2x", addr[ATM_ESA_LEN-1]);
return tmpbuffer;
}
static void
dump_elan(Elan_t *elan)
{
int i;
printf("ELAN:%s (namelen:%d)\n",elan->elan_name, elan->elan_name_size);
fflush(stdout);
if (elan == default_elan) {
printf("\tDEFAULT ELAN\n");
fflush(stdout);
}
printf("\tMax frame size : %s\n",
get_max_frame_size_string(elan->max_frame));
fflush(stdout);
printf("\tELAN type : %s\n", get_type_string(elan->type));
fflush(stdout);
printf("\tLES address : %s\n", get_atm_addr_string(elan->les_addr));
fflush(stdout);
for(i=0;i<elan->no_addresses;i++)
printf("\t\t%s\n", elan->addresses[i]);
printf("\t------------------------\n");
}
void
dump_db(Elan_t *elan)
{
int i;
if (elan) {
dump_elan(elan);
return;
}
printf("Dumping whole ELAN db\n");
if (lecs_address)
printf("LECS address: %s\n", get_atm_addr_string(lecs_address));
else
printf("LECS address not set\n");
for(i=0;i<no_elans;i++) {
dump_elan(elan_arr[i]);
}
}
void
set_lecs_addr(const char *addr)
{
struct sockaddr_atmsvc tmp;
if (lecs_address) {
printf("Error: LECS address already set\n");
}
if (text2atm(addr,(struct sockaddr*)&tmp,sizeof(tmp),T2A_SVC|T2A_NAME)<0) {
printf("Couldn't get LECS address!\n");
return;
}
lecs_address=(unsigned char*)mem_alloc(COMP_NAME,ATM_ESA_LEN);
if (!lecs_address)
return;
memcpy(lecs_address, tmp.sas_addr.prv, ATM_ESA_LEN);
}
const unsigned char*
get_lecs_addr(void)
{
return lecs_address;
}
void
reset_db(void)
{
Elan_t *tmp;
int i,j;
if (lecs_address) {
mem_free(COMP_NAME, lecs_address);
lecs_address = NULL;
}
for(i=0;i<no_elans;i++) {
tmp = elan_arr[i];
for(j=0;j<tmp->no_addresses;j++)
mem_free(COMP_NAME, tmp->addresses[j]);
mem_free(COMP_NAME,tmp);
}
no_elans=0;
default_elan=NULL;
}
static int
match_addresses(Elan_t *elan, unsigned char *addr)
{
int i,j,match=0;
unsigned char tmp;
for(i=0;i<elan->no_addresses && !match;i++) {
match=1;
for(j=0;j<ATM_ESA_LEN && match;j++) {
if (elan->addresses[i][j*2] == 'x' ||
elan->addresses[i][j*2] == 'X') {
tmp = addr[j]&0xf0;
} else {
if (elan->addresses[i][j*2] >= '0' &&
elan->addresses[i][j*2] <= '9') {
tmp = (elan->addresses[i][j*2]-'0')<<4;
} else {
tmp = (tolower(elan->addresses[i][j*2])-'a'+10)<<4;
}
}
if (elan->addresses[i][j*2+1] == 'x' ||
elan->addresses[i][j*2+1] == 'X') {
tmp |= addr[j]&0xf;
} else {
if (elan->addresses[i][j*2+1] >= '0' &&
elan->addresses[i][j*2+1] <= '9') {
tmp |= 0xf&(elan->addresses[i][j*2+1]-'0');
} else {
tmp |= 0xf&(tolower(elan->addresses[i][j*2+1])-'a'+10);
}
}
if (addr[j] != tmp)
match=0;
}
}
return match;
}
/*
* Rules in finding the LES address:
* 1. If elan_name matches exactly &&
* there is an entry matching this ATM address for this ELAN.
* If elan_name matches, but ATM address is not found, reject.
* 2. Search for first ELAN which matches in type, max_frame and
* ATM address.
* 3. Return default elan
* 4. No match, reject.
*/
Elan_t*
find_elan(unsigned char *lec_addr, const char type,
const char max_frame, const char *elan_name,
const short elan_name_size, unsigned short *reason)
{
int pos;
*reason = LE_STATUS_SUCCESS;
for(pos=0;pos<no_elans;pos++) {
if (elan_name_size == elan_arr[pos]->elan_name_size &&
!memcmp(elan_name, elan_arr[pos]->elan_name, elan_name_size)) {
if (match_addresses(elan_arr[pos], lec_addr)) {
return elan_arr[pos];
} else {
*reason = LE_STATUS_NO_ACCESS;
return NULL;
}
}
}
for(pos=0;pos<no_elans;pos++) {
if ((max_frame == LE_MAX_FRAME_UNSPECIFIED ||
elan_arr[pos]->max_frame == LE_MAX_FRAME_UNSPECIFIED ||
max_frame == elan_arr[pos]->max_frame) &&
(type == LE_LAN_TYPE_UNSPECIFIED ||
elan_arr[pos]->type == LE_LAN_TYPE_UNSPECIFIED ||
type == elan_arr[pos]->type)) {
if (match_addresses(elan_arr[pos], lec_addr)) {
return elan_arr[pos];
}
}
}
if (default_elan)
return default_elan;
*reason = LE_STATUS_NO_CONFIG;
return NULL;
}