1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * (c) by the OLSR project
5  *
6  * See our Git repository to find out who worked on this file
7  * and thus is a copyright holder on it.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  *   notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above copyright
18  *   notice, this list of conditions and the following disclaimer in
19  *   the documentation and/or other materials provided with the
20  *   distribution.
21  * * Neither the name of olsr.org, olsrd nor the names of its
22  *   contributors may be used to endorse or promote products derived
23  *   from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Visit http://www.olsr.org for more information.
39  *
40  * If you find this software useful feel free to make a donation
41  * to the project. For more information see the website or contact
42  * the copyright holders.
43  *
44  */
45 
46 /* olsrd host-switch daemon */
47 
48 #include "olsr_host_switch.h"
49 #include "link_rules.h"
50 #include "ohs_cmd.h"
51 #include "ipcalc.h"
52 
53 #include <sys/types.h>
54 #include <sys/socket.h>
55 #include <errno.h>
56 #include <signal.h>
57 #include <netinet/in.h>
58 #include <arpa/inet.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <string.h>
62 #include <unistd.h>
63 #include <time.h>
64 
65 #ifdef _WIN32
66 #undef errno
67 #define errno WSAGetLastError()
68 #undef strerror
69 #define strerror(x) StrError(x)
70 #define close(x) closesocket(x)
71 #else /* _WIN32 */
72 #include <sys/wait.h>
73 #endif /* _WIN32 */
74 
75 static int srv_socket;
76 
77 #define OHS_BUFSIZE 1500
78 static uint8_t data_buffer[OHS_BUFSIZE];
79 
80 struct ohs_connection *ohs_conns;
81 
82 //static int ip_version;
83 //int ipsize;
84 static struct olsrd_config olsr_cnf_data;
85 struct olsrd_config *olsr_cnf = &olsr_cnf_data;
86 
87 uint32_t logbits;
88 
89 /* local functions */
90 static int ohs_init_new_connection(int);
91 
92 static int ohs_route_data(struct ohs_connection *);
93 
94 static int ohs_init_connect_sockets(void);
95 
96 static int ohs_configure(void);
97 
98 #if !defined _WIN32
99 static void ohs_listen_loop(void) __attribute__ ((noreturn));
100 #else /* !defined _WIN32 */
101 static void ohs_listen_loop(void);
102 #endif /* !defined _WIN32 */
103 
104 #ifdef _WIN32
105 int __stdcall
ohs_close(unsigned long signo)106 ohs_close(unsigned long signo __attribute__ ((unused)))
107 #else /* _WIN32 */
108 void
109 ohs_close(int signo __attribute__ ((unused)))
110 #endif /* _WIN32 */
111 {
112 #ifndef _WIN32
113   int errNr = errno;
114 #endif
115   printf("OHS: exit\n");
116   close(srv_socket);
117 #ifndef _WIN32
118   errno = errNr;
119 #endif
120   exit(EXIT_SUCCESS);
121 }
122 
123 struct ohs_connection *
get_client_by_addr(const union olsr_ip_addr * adr)124 get_client_by_addr(const union olsr_ip_addr *adr)
125 {
126   struct ohs_connection *oc;
127   for (oc = ohs_conns; oc != NULL; oc = oc->next) {
128     if (ipequal(adr, &oc->ip_addr)) {
129       return oc;
130     }
131   }
132   return NULL;
133 }
134 
135 static int
ohs_init_new_connection(int s)136 ohs_init_new_connection(int s)
137 {
138   struct ohs_connection *oc;
139   int i;
140   uint32_t addr[4];
141 
142   if (logbits & LOG_CONNECT) {
143     printf("ohs_init_new_connection\n");
144   }
145   /* Create new client node */
146   oc = calloc(1, sizeof(struct ohs_connection));
147   if (!oc) {
148     OHS_OUT_OF_MEMORY("New connection");
149   }
150 
151   oc->socket = s;
152   oc->links = NULL;
153   oc->rx = 0;
154   oc->tx = 0;
155   oc->linkcnt = 0;
156 
157   // hack alert: WSAEventSelect makes sockets non-blocking, so the
158   // recv() may return without having read anything on Windows; hence
159   // re-try for 2 seconds on Windows; shouldn't harm Linux et al.
160 
161   /* Get "fake IP" */
162   for (i = 0; i < 20; i++) {
163     /* Win32 needs that cast. */
164     if (recv(oc->socket, (void *)addr, olsr_cnf->ipsize, 0) == (int)olsr_cnf->ipsize) {
165       break;
166     }
167 #if defined _WIN32
168     Sleep(100);
169 #endif /* defined _WIN32 */
170   }
171 
172   if (i == 20) {
173     printf("Failed to fetch IP address! (%s)\n", strerror(errno));
174     free(oc);
175     return -1;
176   }
177 
178   addr[0] = ntohl(addr[0]);
179   addr[1] = ntohl(addr[1]);
180   addr[2] = ntohl(addr[2]);
181   addr[3] = ntohl(addr[3]);
182   memcpy(oc->ip_addr.v6.s6_addr, addr, olsr_cnf->ipsize);
183 
184   if (logbits & LOG_CONNECT) {
185     struct ipaddr_str addrstr;
186     printf("IP: %s\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
187   }
188   if (get_client_by_addr(&oc->ip_addr)) {
189     if (logbits & LOG_CONNECT) {
190       struct ipaddr_str addrstr;
191       printf("IP: %s DUPLICATE! Disconecting client!\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
192     }
193     close(s);
194     free(oc);
195     return -1;
196   }
197 
198   /* Queue */
199   oc->next = ohs_conns;
200   ohs_conns = oc;
201   return 1;
202 }
203 
204 int
ohs_delete_connection(struct ohs_connection * oc)205 ohs_delete_connection(struct ohs_connection *oc)
206 {
207   if (!oc) {
208     return -1;
209   }
210   /* Close the socket */
211   close(oc->socket);
212 
213   if (logbits & LOG_CONNECT) {
214     struct ipaddr_str addrstr;
215     printf("Removing entry %s\n", olsr_ip_to_string(&addrstr, &oc->ip_addr));
216   }
217   /* De-queue */
218   if (oc == ohs_conns) {
219     ohs_conns = ohs_conns->next;
220   } else {
221     struct ohs_connection *curr_entry = ohs_conns->next;
222     struct ohs_connection *prev_entry = ohs_conns;
223 
224     while (curr_entry != NULL) {
225       if (curr_entry == oc) {
226         prev_entry->next = curr_entry->next;
227         break;
228       }
229       prev_entry = curr_entry;
230       curr_entry = curr_entry->next;
231     }
232   }
233   ohs_delete_all_related_links(oc);
234 
235   free(oc);
236   return 0;
237 }
238 
239 static int
ohs_route_data(struct ohs_connection * oc)240 ohs_route_data(struct ohs_connection *oc)
241 {
242   struct ohs_connection *ohs_cs;
243   ssize_t len;
244   int cnt = 0;
245 
246   oc->tx++;
247   /* Read data */
248   if ((len = recv(oc->socket, (void *)data_buffer, OHS_BUFSIZE, 0)) <= 0)
249     return -1;
250 
251   if (logbits & LOG_FORWARD) {
252     struct ipaddr_str addrstr;
253     printf("Received %ld bytes from %s\n", (long)len, olsr_ip_to_string(&addrstr, &oc->ip_addr));
254   }
255   /* Loop trough clients */
256   for (ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next) {
257     /* Check that the link is active open */
258     if (ohs_check_link(oc, &ohs_cs->ip_addr) && oc->socket != ohs_cs->socket) {
259       ssize_t sent;
260 
261       /* Send link addr */
262       if (send(ohs_cs->socket, (const void *)&oc->ip_addr, olsr_cnf->ipsize, 0) != (int)olsr_cnf->ipsize) {
263         printf("Error sending link address!\n");
264       }
265       /* Send data */
266       if (logbits & LOG_FORWARD) {
267         struct ipaddr_str addrstr, addrstr2;
268         printf("Sending %d bytes %s=>%s\n", (int)len, olsr_ip_to_string(&addrstr, &oc->ip_addr),
269                olsr_ip_to_string(&addrstr2, &ohs_cs->ip_addr));
270       }
271 
272       sent = send(ohs_cs->socket, (void*)data_buffer, len, 0);
273       if (sent != len) {
274         printf("Error sending(buf %d != sent %d)\n", (int)len, (int)sent);
275       }
276       ohs_cs->rx++;
277       cnt++;
278     }
279   }
280   return cnt;
281 }
282 
283 static int
ohs_init_connect_sockets(void)284 ohs_init_connect_sockets(void)
285 {
286   uint32_t yes = 1;
287   struct sockaddr_in sin;
288 
289   printf("Initiating socket TCP port %d\n", OHS_TCP_PORT);
290 
291   if ((srv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
292     printf("Could not initialize socket(%d): %s\n", srv_socket, strerror(errno));
293     exit(EXIT_FAILURE);
294   }
295 
296   if (setsockopt(srv_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) {
297     printf("SO_REUSEADDR failed for socket: %s\n", strerror(errno));
298     close(srv_socket);
299     exit(EXIT_FAILURE);
300   }
301 
302   /* complete the socket structure */
303   memset(&sin, 0, sizeof(sin));
304   sin.sin_family = AF_INET;
305   sin.sin_addr.s_addr = INADDR_ANY;
306   sin.sin_port = htons(OHS_TCP_PORT);
307 
308   /* bind the socket to the port number */
309   if (bind(srv_socket, (struct sockaddr *)&sin, sizeof(sin)) == -1) {
310     printf("bind failed for socket: %s\n", strerror(errno));
311     close(srv_socket);
312     exit(EXIT_FAILURE);
313   }
314 
315   /* show that we are willing to listen */
316   if (listen(srv_socket, 5) == -1) {
317     printf("listen failed for socket: %s\n", strerror(errno));
318     close(srv_socket);
319     exit(EXIT_FAILURE);
320   }
321   return 1;
322 }
323 
324 static int
ohs_configure(void)325 ohs_configure(void)
326 {
327 
328   return 1;
329 }
330 
331 static void
accept_handler(void)332 accept_handler(void)
333 {
334   struct sockaddr_in pin;
335   socklen_t addrlen = sizeof(pin);
336   int s;
337 
338   memset(&pin, 0, sizeof(pin));
339 
340   if ((s = accept(srv_socket, (struct sockaddr *)&pin, &addrlen)) < 0) {
341     printf("accept failed socket: %s\n", strerror(errno));
342   } else {
343     /* Create new node */
344     ohs_init_new_connection(s);
345   }
346 }
347 
348 static void
stdin_handler(void)349 stdin_handler(void)
350 {
351   ohs_parse_command();
352 }
353 
354 static void
read_handler(struct ohs_connection * con)355 read_handler(struct ohs_connection *con)
356 {
357   if (ohs_route_data(con) < 0)
358     ohs_delete_connection(con);
359 }
360 
361 static void
ohs_listen_loop(void)362 ohs_listen_loop(void)
363 {
364 #if !defined _WIN32
365   int n;
366   fd_set ibits;
367   int fn_stdin = fileno(stdin);
368 
369   while (1) {
370     int high;
371 
372     struct ohs_connection *ohs_cs;
373 
374     high = 0;
375     FD_ZERO(&ibits);
376 
377     /* Add server socket */
378     high = srv_socket;
379     FD_SET(srv_socket, &ibits);
380 
381     if (fn_stdin > high)
382       high = fn_stdin;
383 
384     FD_SET(fn_stdin, &ibits);
385 
386     /* Add clients */
387     for (ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next) {
388       if (ohs_cs->socket > high)
389         high = ohs_cs->socket;
390 
391       FD_SET(ohs_cs->socket, &ibits);
392     }
393 
394     /* block */
395     n = select(high + 1, &ibits, 0, 0, NULL);
396 
397     if (n == 0)
398       continue;
399 
400     /* Did somethig go wrong? */
401     if (n < 0) {
402       if (errno == EINTR)
403         continue;
404 
405       printf("Error select: %s", strerror(errno));
406       continue;
407     }
408 
409     /* Check server socket */
410     if (FD_ISSET(srv_socket, &ibits))
411       accept_handler();
412 
413     /* Loop trough clients */
414     ohs_cs = ohs_conns;
415     while (ohs_cs) {
416       struct ohs_connection *ohs_tmp = ohs_cs;
417       ohs_cs = ohs_cs->next;
418 
419       if (FD_ISSET(ohs_tmp->socket, &ibits))
420         read_handler(ohs_tmp);
421     }
422 
423     if (FD_ISSET(fn_stdin, &ibits))
424       stdin_handler();
425 
426   }
427 #else /* !defined _WIN32 */
428   HANDLE Objects[2];
429   WSANETWORKEVENTS NetEvents;
430   struct ohs_connection *Walker, *TmpWalker;
431   unsigned int Res;
432 
433   Objects[0] = GetStdHandle(STD_INPUT_HANDLE);
434   Objects[1] = WSACreateEvent();
435 
436   if (WSAEventSelect(srv_socket, Objects[1], FD_ACCEPT) == SOCKET_ERROR) {
437     fprintf(stderr, "WSAEventSelect failed (1): %s\n", strerror(errno));
438     return;
439   }
440 
441   while (1) {
442     for (Walker = ohs_conns; Walker != NULL; Walker = Walker->next) {
443       if (WSAEventSelect(Walker->socket, Objects[1], FD_READ | FD_CLOSE) == SOCKET_ERROR) {
444         fprintf(stderr, "WSAEventSelect failed (2): %s\n", strerror(errno));
445         Sleep(1000);
446         continue;
447       }
448     }
449 
450     Res = WaitForMultipleObjects(2, Objects, FALSE, INFINITE);
451 
452     if (Res == WAIT_FAILED) {
453       fprintf(stderr, "WaitForMultipleObjects failed: %s\n", strerror(GetLastError()));
454       Sleep(1000);
455       continue;
456     }
457 
458     if (Res == WAIT_OBJECT_0)
459       stdin_handler();
460 
461     else if (Res == WAIT_OBJECT_0 + 1) {
462       if (WSAEnumNetworkEvents(srv_socket, Objects[1], &NetEvents) == SOCKET_ERROR)
463         fprintf(stderr, "WSAEnumNetworkEvents failed (1): %s\n", strerror(errno));
464 
465       else {
466         if ((NetEvents.lNetworkEvents & FD_ACCEPT) != 0)
467           accept_handler();
468       }
469 
470       for (Walker = ohs_conns; Walker != NULL; Walker = TmpWalker) {
471         TmpWalker = Walker->next;
472 
473         if (WSAEnumNetworkEvents(Walker->socket, Objects[1], &NetEvents) == SOCKET_ERROR)
474           fprintf(stderr, "WSAEnumNetworkEvents failed (2): %s\n", strerror(errno));
475 
476         else {
477           if ((NetEvents.lNetworkEvents & (FD_READ | FD_CLOSE)) != 0)
478             read_handler(Walker);
479         }
480       }
481     }
482   }
483 
484 #endif /* !defined _WIN32 */
485 }
486 
487 int
main(void)488 main(void)
489 {
490 
491 #ifdef _WIN32
492   WSADATA WsaData;
493 
494   if (WSAStartup(0x0202, &WsaData)) {
495     fprintf(stderr, "Could not initialize WinSock.\n");
496     exit(EXIT_FAILURE);
497   }
498 
499   SetConsoleCtrlHandler(ohs_close, true);
500 
501 #else /* _WIN32 */
502   signal(SIGINT, ohs_close);
503   signal(SIGTERM, ohs_close);
504 
505   /* Avoid zombie children */
506   signal(SIGCHLD, SIG_IGN);
507 #endif /* _WIN32 */
508 
509   printf("olsrd host-switch daemon version %s starting\n", OHS_VERSION);
510 
511   logbits = LOG_DEFAULT;
512   olsr_cnf->ip_version = AF_INET;
513   olsr_cnf->ipsize = sizeof(struct in_addr);
514 
515   srand((unsigned int)time(NULL));
516 
517   ohs_set_olsrd_path(OHS_DEFAULT_OLSRD_PATH);
518 
519   ohs_init_connect_sockets();
520 
521   ohs_configure();
522 
523   printf("OHS command interpreter reading from STDIN\n");
524   printf("\n> ");
525   fflush(stdout);
526 
527   ohs_listen_loop();
528 
529   ohs_close(0);
530 
531   return 1;
532 }
533 
534 /*
535  * Local Variables:
536  * c-basic-offset: 2
537  * indent-tabs-mode: nil
538  * End:
539  */
540