📄 main.c
字号:
/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2005, Andreas T鴑nesen(andreto@olsr.org) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of olsr.org, olsrd nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: main.c,v 1.28 2007/08/02 10:20:25 bernd67 Exp $ *//* olsrd host-switch daemon */#include "olsr_host_switch.h"#include "link_rules.h"#include "ohs_cmd.h"#include <sys/types.h>#include <sys/socket.h>#include <errno.h>#include <signal.h>#include <netinet/in.h>#include <arpa/inet.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <time.h>#ifdef WIN32#undef errno#define errno WSAGetLastError()#undef strerror#define strerror(x) StrError(x)#define close(x) closesocket(x)#else#include <sys/wait.h>#endifstatic int srv_socket;#define OHS_BUFSIZE 1500static olsr_u8_t data_buffer[OHS_BUFSIZE];struct ohs_connection *ohs_conns;static int ip_version;int ipsize;static char ipv6_buf[100]; /* for address coversion */olsr_u32_t logbits;/* local functions */static intohs_init_new_connection(int);static intohs_route_data(struct ohs_connection *);static intohs_init_connect_sockets(void);static intohs_configure(void);static voidohs_listen_loop(void);const char *olsr_ip_to_string(const union olsr_ip_addr *addr){ static int index = 0; static char buff[4][100]; const char *ret; struct in_addr in; if(ip_version == AF_INET) { in.s_addr=addr->v4; ret = inet_ntoa(in); } else { /* IPv6 */ ret = inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf)); } strncpy(buff[index], ret, 100); ret = buff[index]; index = (index + 1) & 3; return ret;}#ifdef WIN32int __stdcallohs_close(unsigned long signal __attribute__((unused)))#elsevoidohs_close(int signal __attribute__((unused)))#endif{ printf("OHS: exit\n"); close(srv_socket); exit(0);}struct ohs_connection *get_client_by_addr(union olsr_ip_addr *adr){ struct ohs_connection *oc = ohs_conns; while(oc) { if(COMP_IP(adr, &oc->ip_addr)) return oc; oc = oc->next; } return NULL;}static intohs_init_new_connection(int s){ struct ohs_connection *oc; olsr_u8_t new_addr[4]; int i; if(logbits & LOG_CONNECT) printf("ohs_init_new_connection\n"); /* Create new client node */ oc = malloc(sizeof(struct ohs_connection)); if(!oc) OHS_OUT_OF_MEMORY("New connection"); memset(oc, 0, sizeof(oc)); oc->socket = s; oc->links = NULL; oc->rx = 0; oc->tx = 0; oc->linkcnt = 0; // hack alert: WSAEventSelect makes sockets non-blocking, so the // recv() may return without having read anything on Windows; hence // re-try for 2 seconds on Windows; shouldn't harm Linux et al. /* Get "fake IP" */ for (i = 0; i < 20; i++) { if (recv(oc->socket, new_addr, 4, 0) == 4) break;#if defined WIN32 Sleep(100);#endif } if (i == 20) { printf("Failed to fetch IP address! (%s)\n", strerror(errno)); return -1; } memcpy(&oc->ip_addr, new_addr, 4); oc->ip_addr.v4 = ntohl(oc->ip_addr.v4); if(logbits & LOG_CONNECT) printf("IP: %s\n", olsr_ip_to_string(&oc->ip_addr)); if(get_client_by_addr(&oc->ip_addr)) { if(logbits & LOG_CONNECT) printf("IP: %s DUPLICATE! Disconecting client!\n", olsr_ip_to_string(&oc->ip_addr)); close(s); return -1; } /* Queue */ oc->next = ohs_conns; ohs_conns = oc; return 1;}intohs_delete_connection(struct ohs_connection *oc){ if(!oc) return -1; /* Close the socket */ close(oc->socket); if(logbits & LOG_CONNECT) printf("Removing entry %s\n", olsr_ip_to_string(&oc->ip_addr)); /* De-queue */ if(oc == ohs_conns) { ohs_conns = ohs_conns->next; } else { struct ohs_connection *curr_entry, *prev_entry; curr_entry = ohs_conns->next; prev_entry = ohs_conns; while(curr_entry) { if(curr_entry == oc) { prev_entry->next = curr_entry->next; break; } prev_entry = curr_entry; curr_entry = curr_entry->next; } } ohs_delete_all_related_links(oc); /* Free */ free(oc); return 0;}static intohs_route_data(struct ohs_connection *oc){ struct ohs_connection *ohs_cs; ssize_t len; int cnt = 0; oc->tx++; /* Read data */ if((len = recv(oc->socket, data_buffer, OHS_BUFSIZE, 0)) <= 0) return -1; if(logbits & LOG_FORWARD) printf("Received %d bytes from %s\n", (int)len, olsr_ip_to_string(&oc->ip_addr)); /* Loop trough clients */ for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next) { /* Check that the link is active open */ if(ohs_check_link(oc, &ohs_cs->ip_addr) && oc->socket != ohs_cs->socket) { ssize_t sent; /* Send link addr */ if(send(ohs_cs->socket, oc->ip_addr.v6.s6_addr, ipsize, 0) != ipsize) { printf("Error sending link address!\n"); } /* Send data */ if(logbits & LOG_FORWARD) printf("Sending %d bytes %s=>%s\n", (int)len, olsr_ip_to_string(&oc->ip_addr), olsr_ip_to_string(&ohs_cs->ip_addr)); if((sent = send(ohs_cs->socket, data_buffer, len, 0)) != len) { printf("Error sending(buf %d != sent %d)\n", (int)len, (int)sent); } ohs_cs->rx++; cnt++; } } return cnt;}static intohs_init_connect_sockets(void){ olsr_u32_t yes = 1; struct sockaddr_in sin; printf("Initiating socket TCP port %d\n", OHS_TCP_PORT); if((srv_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("Could not initialize socket(%d): %s\n", srv_socket, strerror(errno)); exit(0); } if(setsockopt(srv_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&yes, sizeof(yes)) < 0) { printf("SO_REUSEADDR failed for socket: %s\n", strerror(errno)); close(srv_socket); exit(0); } /* complete the socket structure */ memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons(OHS_TCP_PORT); /* bind the socket to the port number */ if (bind(srv_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) { printf("bind failed for socket: %s\n", strerror(errno)); close(srv_socket); exit(0); } /* show that we are willing to listen */ if (listen(srv_socket, 5) == -1) { printf("listen failed for socket: %s\n", strerror(errno)); close(srv_socket); exit(0); } return 1;}static intohs_configure(void){ return 1;}static void accept_handler(void){ struct sockaddr_in pin; socklen_t addrlen = sizeof(pin); int s; memset(&pin, 0 , sizeof(pin)); if((s = accept(srv_socket, (struct sockaddr *)&pin, &addrlen)) < 0) { printf("accept failed socket: %s\n", strerror(errno)); } else { /* Create new node */ ohs_init_new_connection(s); }}static void stdin_handler(void){ ohs_parse_command();}static void read_handler(struct ohs_connection *con){ if (ohs_route_data(con) < 0) ohs_delete_connection(con);}static voidohs_listen_loop(void){#if !defined WIN32 int n; fd_set ibits; int fn_stdin = fileno(stdin); while(1) { int high; struct ohs_connection *ohs_cs; high = 0; FD_ZERO(&ibits); /* Add server socket */ high = srv_socket; FD_SET(srv_socket, &ibits); if(fn_stdin > high) high = fn_stdin; FD_SET(fn_stdin, &ibits); /* Add clients */ for(ohs_cs = ohs_conns; ohs_cs; ohs_cs = ohs_cs->next) { if(ohs_cs->socket > high) high = ohs_cs->socket; FD_SET(ohs_cs->socket, &ibits); } /* block */ n = select(high + 1, &ibits, 0, 0, NULL); if(n == 0) continue; /* Did somethig go wrong? */ if (n < 0) { if(errno == EINTR) continue; printf("Error select: %s", strerror(errno)); continue; } /* Check server socket */ if(FD_ISSET(srv_socket, &ibits)) accept_handler(); /* Loop trough clients */ ohs_cs = ohs_conns; while(ohs_cs) { struct ohs_connection *ohs_tmp = ohs_cs; ohs_cs = ohs_cs->next; if(FD_ISSET(ohs_tmp->socket, &ibits)) read_handler(ohs_tmp); } if(FD_ISSET(fn_stdin, &ibits)) stdin_handler(); }#else HANDLE Objects[2]; WSANETWORKEVENTS NetEvents; struct ohs_connection *Walker, *TmpWalker; unsigned int Res; Objects[0] = GetStdHandle(STD_INPUT_HANDLE); Objects[1] = WSACreateEvent(); if (WSAEventSelect(srv_socket, Objects[1], FD_ACCEPT) == SOCKET_ERROR) { fprintf(stderr, "WSAEventSelect failed (1): %s\n", strerror(errno)); return; } while (1) { for (Walker = ohs_conns; Walker != NULL; Walker = Walker->next) { if (WSAEventSelect(Walker->socket, Objects[1], FD_READ | FD_CLOSE) == SOCKET_ERROR) { fprintf(stderr, "WSAEventSelect failed (2): %s\n", strerror(errno)); Sleep(1000); continue; } } Res = WaitForMultipleObjects(2, Objects, FALSE, INFINITE); if (Res == WAIT_FAILED) { fprintf(stderr, "WaitForMultipleObjects failed: %s\n", strerror(GetLastError())); Sleep(1000); continue; } if (Res == WAIT_OBJECT_0) stdin_handler(); else if (Res == WAIT_OBJECT_0 + 1) { if (WSAEnumNetworkEvents(srv_socket, Objects[1], &NetEvents) == SOCKET_ERROR) fprintf(stderr, "WSAEnumNetworkEvents failed (1): %s\n", strerror(errno)); else { if ((NetEvents.lNetworkEvents & FD_ACCEPT) != 0) accept_handler(); } for (Walker = ohs_conns; Walker != NULL; Walker = TmpWalker) { TmpWalker = Walker->next; if (WSAEnumNetworkEvents(Walker->socket, Objects[1], &NetEvents) == SOCKET_ERROR) fprintf(stderr, "WSAEnumNetworkEvents failed (2): %s\n", strerror(errno)); else { if ((NetEvents.lNetworkEvents & (FD_READ | FD_CLOSE)) != 0) read_handler(Walker); } } } } #endif}intmain(void){#ifdef WIN32 WSADATA WsaData; if (WSAStartup(0x0202, &WsaData)) { fprintf(stderr, "Could not initialize WinSock.\n"); exit(EXIT_FAILURE); } SetConsoleCtrlHandler(ohs_close, OLSR_TRUE);#else signal(SIGINT, ohs_close); signal(SIGTERM, ohs_close); /* Avoid zombie children */ signal(SIGCHLD, SIG_IGN);#endif printf("olsrd host-switch daemon version %s starting\n", OHS_VERSION); logbits = LOG_DEFAULT; ip_version = AF_INET; ipsize = 4; srand((unsigned int)time(NULL)); ohs_set_olsrd_path(OHS_DEFAULT_OLSRD_PATH); ohs_init_connect_sockets(); ohs_configure(); printf("OHS command interpreter reading from STDIN\n"); printf("\n> "); fflush(stdout); ohs_listen_loop(); ohs_close(0); return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -