2992e8d2f3f03e58150610e995c965fd504a2345
[bcm963xx.git] / userapps / opensource / atm2684 / atm / lane / lecs.c
1 /*
2  *
3  * LECS main code
4  *
5  * $Id: lecs.c,v 1.1.1.1 2005/04/29 01:44:51 echo Exp $
6  *
7  */
8
9 /* Standard includes*/
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <getopt.h>
13 #include <signal.h>
14 #include <errno.h>
15 #include <string.h>
16 #include <netinet/in.h>
17 #include <unistd.h>
18 #include <sys/types.h>
19 #include <sys/time.h>
20
21 /* ATM includes */
22 #include <atm.h>
23
24 /* Local includes */
25 #include "lecs_load.h"
26 #include "ldb.h"
27 #include "mem_lecs.h"
28 #include "lecs.h"
29 #include "atm_lecs.h"
30
31 /* Protos */
32 static void sig_reset(int foobar);
33 static void sig_kill(int foobar);
34 static void usage(const char *progname);
35 int send_response(int fd, unsigned char *buffer, int len);
36
37 /* Local data */
38 #define COMP_NAME "MAIN"
39 #define MAX_FD 32
40 #define P_SIZE 1024
41 static int stay_alive = 1;
42 static int reset = 0;
43
44 #define DUMP_PACKETS 0
45
46 static void
47 usage(const char *progname)
48 {
49   printf("Usage: %s [-f configuration_file][-l listen_address][-d]\n",
50          progname);
51 }
52
53 static void
54 sig_reset(int foobar)
55 {
56   reset = 1;
57 }
58
59 static void
60 sig_kill(int foobar)
61 {
62   stay_alive = 0;
63 }
64
65 int 
66 send_response(int fd, unsigned char *buffer, int len)
67 {
68   LaneControl_t *dp;
69   Elan_t *elan;
70   unsigned short response;
71 #ifdef DUMP_PACKETS
72   int i;
73 #endif
74
75   if (len < sizeof(LaneControl_t))
76     return -1;
77
78   dp = (LaneControl_t *)buffer;
79
80   if (dp->marker != htons(LE_MARKER) ||
81       dp->protocol != LE_PROTOCOL ||
82       dp->version != LE_VERSION ||
83       dp->opcode != htons(LE_CONFIGURE_REQUEST)) {
84     return -1;
85   }
86   dp->opcode = htons(LE_CONFIGURE_RESPONSE);
87   elan = find_elan(dp->source_atm, dp->lan_type, dp->max_frame,
88                    (char*)dp->elan_name, dp->elan_name_size, &response);
89   if (!elan) {
90     dp->status = htons(response);
91   } else {
92     dp->status = htons(LE_STATUS_SUCCESS);
93     dp->lan_type = elan->type;
94     dp->max_frame = elan->max_frame;
95     memcpy(dp->elan_name, elan->elan_name, elan->elan_name_size);
96     dp->elan_name_size = elan->elan_name_size;
97     memcpy(dp->target_atm, elan->les_addr, ATM_ESA_LEN);
98   }
99 #ifdef DUMP_PACKETS
100   for(i=0;i<len;i++) {
101     printf("%2.2x ",0xff&buffer[i]);
102   }
103   printf("\n");
104 #endif
105   return write(fd, buffer, len);
106 }
107
108 int main(int argc, char **argv)
109 {
110   int i =0;
111   char *config_file =NULL;
112   char *listen_addr = NULL;
113   int fd_arr[MAX_FD];
114   int no_fds=1;
115   int just_dump=0;
116   fd_set fds;
117   struct sockaddr_atmsvc client;
118   int len;
119   unsigned char buffer[P_SIZE];
120
121   while(i!=-1) {
122     i = getopt(argc, argv, "f:l:d");
123     switch(i) {
124     case 'd':
125       printf("Dumping databasefile\n");
126       just_dump=1;
127       break;
128     case 'f':
129       if (config_file) {
130         usage(argv[0]);
131         exit(-1);
132       }
133       config_file = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
134       if (!config_file) {
135         exit(-1);
136       }
137       memcpy(config_file, optarg, strlen(optarg)+1);
138       break;
139     case 'l':
140       if (listen_addr) {
141         usage(argv[0]);
142         exit(-1);
143       }
144       listen_addr = (char*)mem_alloc(COMP_NAME, strlen(optarg)+1);
145       if (!listen_addr)
146         exit(-1);
147       memcpy(listen_addr, optarg, strlen(optarg)+1);
148       break;
149     case -1:
150       break;
151     default:
152       usage(argv[0]);
153       exit(-1);
154     }
155   }
156   if (argc != optind) {
157     usage(argv[0]);
158     exit(-1);
159   }
160   /* Following gets run in the beginning or when lecs is restarted */
161   while (stay_alive) {
162
163     /* Read configuration file */
164     if (config_file) {
165       if (load_db(config_file)<0)
166         exit(-1);
167     } else {
168       if (load_db(DEFAULT_CONFIG)<0)
169         exit(-1);
170     }
171     if (just_dump) {
172       dump_db(NULL);
173       exit(0);
174     }
175
176     /* Reserve signals */
177     signal(SIGHUP, sig_reset);
178     signal(SIGINT, sig_kill);
179     signal(SIGQUIT, sig_kill);
180     signal(SIGABRT, sig_kill);
181     signal(SIGTERM, sig_kill);
182     signal(SIGSEGV, sig_kill);
183     
184     /* CHANGE: First parameter, then configuration file! */
185     fd_arr[0] = atm_create_socket(CONFIGURATION_DIRECT, 
186                                   get_lecs_addr());
187     no_fds=1;
188     if (fd_arr[0] <0) {
189       stay_alive=0; /* No need to go on */
190     }
191     while(!reset && stay_alive) {
192       FD_ZERO(&fds);
193       for(i=0;i<no_fds;i++) {
194         FD_SET(fd_arr[i],&fds);
195       }
196       
197       if (select(MAX_FD, &fds, NULL, NULL, NULL)<0) {
198         perror("select(MAX_FD,...)");
199         stay_alive=0;
200       } else {
201         if (FD_ISSET(fd_arr[0],&fds)) { /* Incoming call */
202           if (no_fds == MAX_FD) {
203             close(fd_arr[1]); /* Oldest */
204             memmove(&fd_arr[1], &fd_arr[2], sizeof(int)*(MAX_FD-2));
205             no_fds--;
206           }
207           len = sizeof(client);
208           fd_arr[no_fds] = accept(fd_arr[0], (struct sockaddr*)&client,
209                                   &len);
210           if (fd_arr[no_fds]<0) {
211             if (errno==ENETRESET)
212               reset=1;
213             if (errno==EUNATCH)
214               stay_alive=1;
215           } else {
216             no_fds++;
217           }
218         }
219         for(i=1;i<no_fds;i++) {
220           if (FD_ISSET(fd_arr[i],&fds)) {
221             len = read(fd_arr[i], buffer, P_SIZE);
222             if (len <0 && (errno == ENETRESET || errno == EUNATCH)) {
223               reset=0;
224             }
225             if (len<=0) {
226               close(fd_arr[i]);
227               memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
228               i--;
229             } else {
230               if(send_response(fd_arr[i], buffer, len)<0) {
231                 close(fd_arr[i]);
232                 memmove(&fd_arr[i], &fd_arr[i+1], sizeof(int)*(--no_fds -i));
233               }
234             }
235           }
236         }
237       }
238     }
239     /* This gets done if a signal has been caught, or if
240        network resets/becomes unavailable */
241     reset=0;
242     for(i=0;i<no_fds;i++)
243       close(fd_arr[i]);
244     no_fds=0;
245     reset_db();
246   }
247   return 0;
248 }