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

249 lines
5.3 KiB
C
Executable File

/*
*
* LECS main code
*
* $Id: //BBN_Linux/Branch/Branch_for_Rel_TP_ASEAN_20161216/tclinux_phoenix/apps/public/linux-atm/lane/lecs.c#1 $
*
*/
/* Standard includes*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include <netinet/in.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
/* ATM includes */
#include <atm.h>
/* Local includes */
#include "lecs_load.h"
#include "ldb.h"
#include "mem_lecs.h"
#include "lecs.h"
#include "atm_lecs.h"
/* Protos */
static void sig_reset(int foobar);
static void sig_kill(int foobar);
static void usage(const char *progname);
int send_response(int fd, unsigned char *buffer, int len);
/* Local data */
#define COMP_NAME "MAIN"
#define MAX_FD 32
#define P_SIZE 1024
static int stay_alive = 1;
static int reset = 0;
#define DUMP_PACKETS 0
static void
usage(const char *progname)
{
printf("Usage: %s [-f configuration_file][-l listen_address][-d]\n",
progname);
}
static void
sig_reset(int foobar)
{
reset = 1;
}
static void
sig_kill(int foobar)
{
stay_alive = 0;
}
int
send_response(int fd, unsigned char *buffer, int len)
{
LaneControl_t *dp;
Elan_t *elan;
unsigned short response;
#ifdef DUMP_PACKETS
int i;
#endif
if (len < sizeof(LaneControl_t))
return -1;
dp = (LaneControl_t *)buffer;
if (dp->marker != htons(LE_MARKER) ||
dp->protocol != LE_PROTOCOL ||
dp->version != LE_VERSION ||
dp->opcode != htons(LE_CONFIGURE_REQUEST)) {
return -1;
}
dp->opcode = htons(LE_CONFIGURE_RESPONSE);
elan = find_elan(dp->source_atm, dp->lan_type, dp->max_frame,
(char*)dp->elan_name, dp->elan_name_size, &response);
if (!elan) {
dp->status = htons(response);
} else {
dp->status = htons(LE_STATUS_SUCCESS);
dp->lan_type = elan->type;
dp->max_frame = elan->max_frame;
memcpy(dp->elan_name, elan->elan_name, elan->elan_name_size);
dp->elan_name_size = elan->elan_name_size;
memcpy(dp->target_atm, elan->les_addr, ATM_ESA_LEN);
}
#ifdef DUMP_PACKETS
for(i=0;i<len;i++) {
printf("%2.2x ",0xff&buffer[i]);
}
printf("\n");
#endif
return write(fd, buffer, len);
}
int main(int argc, char **argv)
{
int i =0;
char *config_file =NULL;
char *listen_addr = NULL;
int fd_arr[MAX_FD];
int no_fds=1;
int just_dump=0;
fd_set fds;
struct sockaddr_atmsvc client;
int len;
unsigned char buffer[P_SIZE];
while(i!=-1) {
i = getopt(argc, argv, "f:l:d");
switch(i) {
case 'd':
printf("Dumping databasefile\n");
just_dump=1;
break;
case 'f':
if (config_file) {
usage(argv[0]);
exit(-1);
}
config_file = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
if (!config_file) {
exit(-1);
}
memcpy(config_file, optarg, strlen(optarg)+1);
break;
case 'l':
if (listen_addr) {
usage(argv[0]);
exit(-1);
}
listen_addr = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
if (!listen_addr)
exit(-1);
memcpy(listen_addr, optarg, strlen(optarg)+1);
break;
case -1:
break;
default:
usage(argv[0]);
exit(-1);
}
}
if (argc != optind) {
usage(argv[0]);
exit(-1);
}
/* Following gets run in the beginning or when lecs is restarted */
while (stay_alive) {
/* Read configuration file */
if (config_file) {
if (load_db(config_file)<0)
exit(-1);
} else {
if (load_db(DEFAULT_CONFIG)<0)
exit(-1);
}
if (just_dump) {
dump_db(NULL);
exit(0);
}
/* Reserve signals */
signal(SIGHUP, sig_reset);
signal(SIGINT, sig_kill);
signal(SIGQUIT, sig_kill);
signal(SIGABRT, sig_kill);
signal(SIGTERM, sig_kill);
signal(SIGSEGV, sig_kill);
/* CHANGE: First parameter, then configuration file! */
fd_arr[0] = atm_create_socket(CONFIGURATION_DIRECT,
get_lecs_addr());
no_fds=1;
if (fd_arr[0] <0) {
stay_alive=0; /* No need to go on */
}
while(!reset && stay_alive) {
FD_ZERO(&fds);
for(i=0;i<no_fds;i++) {
FD_SET(fd_arr[i],&fds);
}
if (select(MAX_FD, &fds, NULL, NULL, NULL)<0) {
perror("select(MAX_FD,...)");
stay_alive=0;
} else {
if (FD_ISSET(fd_arr[0],&fds)) { /* Incoming call */
if (no_fds == MAX_FD) {
close(fd_arr[1]); /* Oldest */
memmove(&fd_arr[1], &fd_arr[2], sizeof(int)*(MAX_FD-2));
no_fds--;
}
len = sizeof(client);
fd_arr[no_fds] = accept(fd_arr[0], (struct sockaddr*)&client,
&len);
if (fd_arr[no_fds]<0) {
if (errno==ENETRESET)
reset=1;
if (errno==EUNATCH)
stay_alive=1;
} else {
no_fds++;
}
}
for(i=1;i<no_fds;i++) {
if (FD_ISSET(fd_arr[i],&fds)) {
len = read(fd_arr[i], buffer, P_SIZE);
if (len <0 && (errno == ENETRESET || errno == EUNATCH)) {
reset=0;
}
if (len<=0) {
close(fd_arr[i]);
memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
i--;
} else {
if(send_response(fd_arr[i], buffer, len)<0) {
close(fd_arr[i]);
memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
}
}
}
}
}
}
/* This gets done if a signal has been caught, or if
network resets/becomes unavailable */
reset=0;
for(i=0;i<no_fds;i++)
close(fd_arr[i]);
no_fds=0;
reset_db();
}
return 0;
}