fa57e15904a5021a46cd8278df3c98303e676ae0
[olsrd.git] / src / olsr_switch / main.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2005, Andreas T√łnnesen(andreto@olsr.org)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without 
8  * modification, are permitted provided that the following conditions 
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright 
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright 
14  *   notice, this list of conditions and the following disclaimer in 
15  *   the documentation and/or other materials provided with the 
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its 
18  *   contributors may be used to endorse or promote products derived 
19  *   from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  * $Id: main.c,v 1.2 2005/05/30 14:32:00 kattemat Exp $
41  */
42
43 /* olsrd host-switch daemon */
44
45 #ifdef WIN32
46 #define close(x) closesocket(x)
47 int __stdcall SignalHandler(unsigned long signal);
48 #else
49 static void
50 olsr_shutdown(int);
51 #endif
52
53 #include "olsr_host_switch.h"
54 #include "link_rules.h"
55 #include <sys/types.h>
56 #include <sys/socket.h>
57 #include <errno.h>
58 #include <signal.h>
59 #include <netinet/in.h>
60 #include <arpa/inet.h>
61 #include <stdlib.h>
62
63 static int srv_socket;
64
65 #define OHS_BUFSIZE 1500
66 static olsr_u8_t data_buffer[OHS_BUFSIZE];
67
68 static struct ohs_connection *ohs_conns;
69
70
71 static int ip_version;
72 int ipsize;
73 static char ipv6_buf[100]; /* for address coversion */
74
75 char *
76 olsr_ip_to_string(union olsr_ip_addr *addr)
77 {
78   static int index = 0;
79   static char buff[4][100];
80   char *ret;
81   struct in_addr in;
82   
83   if(ip_version == AF_INET)
84     {
85       in.s_addr=addr->v4;
86       ret = inet_ntoa(in);
87     }
88   else
89     {
90       /* IPv6 */
91       ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
92     }
93
94   strncpy(buff[index], ret, 100);
95
96   ret = buff[index];
97
98   index = (index + 1) & 3;
99
100   return ret;
101 }
102
103
104 #ifdef WIN32
105 int __stdcall
106 SignalHandler(unsigned long signal)
107 #else
108 static void
109 ohs_close(int signal)
110 #endif
111 {
112   printf("OHS: exit\n");
113
114   close(srv_socket);
115
116   exit(0);
117 }
118
119
120 int
121 ohs_init_new_connection(int s)
122 {
123   struct ohs_connection *oc;
124   olsr_u8_t new_addr[4];
125
126   printf("ohs_init_new_connection\n");
127
128   /* Create new client node */
129   oc = malloc(sizeof(struct ohs_connection));
130   if(!oc)
131     OHS_OUT_OF_MEMORY("New connection");
132
133   memset(oc, 0, sizeof(oc));
134
135   oc->socket = s;
136
137   oc->links = NULL;
138
139   /* Queue */
140   oc->next = ohs_conns;
141   ohs_conns = oc;
142
143   /* Get "fake IP" */
144   if(recv(oc->socket, new_addr, 4, 0) != 4)
145     {
146       printf("Failed to fetch IP address!\n");
147       return -1;
148     }
149   memcpy(&oc->ip_addr, new_addr, 4);
150   oc->ip_addr.v4 = ntohl(oc->ip_addr.v4);
151   printf("IP: %s\n", olsr_ip_to_string(&oc->ip_addr));
152 }
153
154 int
155 ohs_delete_connection(struct ohs_connection *oc)
156 {
157
158   /* Close the socket */
159   close(oc->socket);
160
161   printf("Removing entry %s\n", olsr_ip_to_string(&oc->ip_addr));
162   /* De-queue */
163   if(oc == ohs_conns)
164     {
165       ohs_conns = ohs_conns->next;
166     }
167   else
168     {
169       struct ohs_connection *curr_entry, *prev_entry;
170       curr_entry = ohs_conns->next;
171       prev_entry = ohs_conns;
172       
173       while(curr_entry)
174         {
175           if(curr_entry == oc)
176             {
177               prev_entry->next = curr_entry->next;
178               break;
179             }
180           prev_entry = curr_entry;
181           curr_entry = curr_entry->next;
182         }
183     }
184   /* Free */
185   free(oc);
186 }
187
188 int
189 ohs_route_data(struct ohs_connection *oc)
190 {
191   struct ohs_connection *ohs_cs;
192   ssize_t len;
193
194   /* Read data */
195   if((len = recv(oc->socket, data_buffer, OHS_BUFSIZE, 0)) <= 0)
196     return -1;
197
198   printf("Received %d bytes from %s\n", len, olsr_ip_to_string(&oc->ip_addr));
199
200   /* Loop trough clients */
201   for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next)
202     {
203       /* Check that the link is active open */
204       if(ohs_check_link(oc, &ohs_cs->ip_addr) &&
205          oc->socket != ohs_cs->socket)
206         {
207           ssize_t sent;
208
209           /* Send link addr */
210           if(send(ohs_cs->socket, oc->ip_addr.v6.s6_addr, ipsize, 0) != ipsize)
211             {
212               printf("Error sending link address!\n");
213             }
214           /* Send data */
215           printf("Sending %d bytes %s=>%s\n", len, 
216                  olsr_ip_to_string(&oc->ip_addr),
217                  olsr_ip_to_string(&ohs_cs->ip_addr));
218
219           if((sent = send(ohs_cs->socket, data_buffer, len, 0)) != len)
220             {
221               printf("Error sending(buf %d != sent %d)\n", len, sent);
222             } 
223         }
224     }
225
226
227 }
228
229 int
230 ohs_init_connect_sockets()
231 {
232   int i;
233   olsr_u32_t yes = 1;
234   struct sockaddr_in sin;
235
236   printf("Initiating socket TCP port %d\n", OHS_TCP_PORT);
237
238   if((srv_socket = socket(PF_INET, SOCK_STREAM, 0)) < 0)
239     {
240       printf("Could not initialize socket: %s\n", strerror(errno));
241       exit(0);
242     }
243
244   if(setsockopt(srv_socket, SOL_SOCKET, SO_REUSEADDR, 
245                 (char *)&yes, sizeof(yes)) < 0) 
246     {
247       printf("SO_REUSEADDR failed for socket: %s\n", strerror(errno));
248       close(srv_socket);
249       exit(0);
250     }
251
252   /* complete the socket structure */
253   memset(&sin, 0, sizeof(sin));
254   sin.sin_family = AF_INET;
255   sin.sin_addr.s_addr = INADDR_ANY;
256   sin.sin_port = htons(OHS_TCP_PORT);
257   
258   /* bind the socket to the port number */
259   if (bind(srv_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
260     {
261       printf("bind failed for socket: %s\n", strerror(errno));
262       exit(0);
263     }
264   
265   /* show that we are willing to listen */
266   if (listen(srv_socket, 5) == -1) 
267     {
268       printf("listen failed for socket: %s\n", i, strerror(errno));
269       exit(0);
270     }
271
272 }
273
274 int
275 ohs_configure()
276 {
277
278 }
279
280 void
281 ohs_listen_loop()
282 {
283   int n;
284   fd_set ibits;
285
286   printf("ohs_listen_loop\n");
287
288   while(1)
289     {
290       int i, high;
291
292       struct ohs_connection *ohs_cs;
293
294       high = 0;
295       FD_ZERO(&ibits);
296
297       /* Add server socket */
298       high = srv_socket;
299       FD_SET(srv_socket, &ibits);
300
301       /* Add clients */
302       for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next)
303         {
304           if(ohs_cs->socket > high)
305             high = ohs_cs->socket;
306       
307           FD_SET(ohs_cs->socket, &ibits);
308         }
309
310       /* block */
311       n = select(high + 1, &ibits, 0, 0, NULL);
312       
313       if(n == 0)
314         continue;
315
316       /* Did somethig go wrong? */
317       if (n < 0) 
318         {
319           if(errno == EINTR)
320             continue;
321           
322           printf("Error select: %s", strerror(errno));
323           continue;
324         }
325       
326       /* Check server socket */
327       if(FD_ISSET(srv_socket, &ibits))
328         {
329           struct sockaddr_in pin;
330           socklen_t addrlen = sizeof(pin);
331           int s;
332           
333           memset(&pin, 0 , sizeof(pin));
334
335           if((s = accept(srv_socket, (struct sockaddr *)&pin, &addrlen)) < 0)
336             {
337               printf("accept failed socket: %s\n", strerror(errno));
338             }
339           else
340             {
341               /* Create new node */
342               ohs_init_new_connection(s);
343             }
344         }
345       /* Loop trough clients */
346       ohs_cs = ohs_conns;
347       while(ohs_cs)
348         {
349           struct ohs_connection *ohs_tmp = ohs_cs;
350           ohs_cs = ohs_cs->next;
351
352           if(FD_ISSET(ohs_tmp->socket, &ibits))
353             {
354               if(ohs_route_data(ohs_tmp) < 0)
355                   ohs_delete_connection(ohs_tmp);
356             }
357         }
358       
359     }
360 }
361
362
363 int
364 main(int argc, char *argv[])
365 {
366
367   printf("olsrd host-switch daemon version %s starting\n", OHS_VERSION);
368
369   ip_version = AF_INET;
370   ipsize = 4;
371
372   ohs_init_connect_sockets();
373 #ifdef WIN32
374   SetConsoleCtrlHandler(SignalHandler, OLSR_TRUE);
375 #else
376   signal(SIGINT, ohs_close);  
377   signal(SIGTERM, ohs_close);  
378 #endif
379
380   ohs_configure();
381
382   ohs_listen_loop();
383
384   ohs_close(0);
385
386 }