/* * Copyright 1997 Niels Provos * All rights reserved. * * Parts derived from code by Angelos D. Keromytis, kermit@forthnet.gr * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Niels Provos. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ /* * server.c: * SERVER handling functions */ #ifndef lint static char rcsid[] = "$Id: server.c,v 1.2 1997/07/22 11:18:25 provos Exp $"; #endif #define _SERVER_C_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _AIX #include #endif #include #include "config.h" #include "photuris.h" #include "server.h" #include "api.h" #include "packet.h" #include "schedule.h" #include "errlog.h" #include "buffer.h" #ifdef IPSEC #include "spi.h" #include "kernel.h" #endif int init_server(void) { struct sockaddr_in sin, *sin2; struct protoent *proto; struct stat sb; int sock, d, i, ip, on = 1; struct ifconf ifconf; char buf[1024]; #ifndef PHOTURIS_PORT struct servent *ser; if ((ser = getservbyname("photuris", "udp")) == (struct servent *) NULL) crit_error(1, "getservbyname() in init_server()"); global_port = ser->s_port; #else global_port = PHOTURIS_PORT; #endif if ((proto = getprotobyname("udp")) == (struct protoent *) NULL) crit_error(1, "getprotobyname() in init_server()"); if ((global_socket = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) < 0) crit_error(1, "socket() in init_server()"); setsockopt(global_socket, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); /* get the local addresses */ ifconf.ifc_len = 1024; ifconf.ifc_buf = buf; bzero(buf, 1024); if (ioctl(global_socket, SIOCGIFCONF, &ifconf) == -1) crit_error(1, "ioctl() in init_server()"); sin.sin_port = htons(global_port); sin.sin_addr.s_addr = INADDR_ANY; sin.sin_family = AF_INET; if (bind(global_socket, (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) crit_error(1, "bind() in init_server()"); /* Save interfaces addresses here */ addresses = (char **) calloc(1+1, sizeof(char *)); if (addresses == (char **) NULL) crit_error(1, "calloc() in init_server()"); addresses[1] = (char *) NULL; sockets = (int *) calloc(1+1, sizeof(int)); if (sockets == (int *) NULL) crit_error(1, "calloc() in init_server()"); sockets[1] = -1; if (lstat(PHOTURIS_FIFO, &sb) == -1) { if (errno != ENOENT) crit_error(1, "stat() in init_server()"); if (mkfifo(PHOTURIS_FIFO, 0660) == -1) crit_error(1, "mkfifo() in init_server()"); } else if (!(sb.st_mode & S_IFIFO)) log_error(0, "%s is not a FIFO in init_server()", PHOTURIS_FIFO); /* We listen on a named pipe */ if ((sockets[0] = open(PHOTURIS_FIFO, O_RDONLY | O_NONBLOCK, 0)) == -1) crit_error(1, "open() in init_server()"); i = 1; /* One interface already */ #ifdef IPSEC /* We also listen on PF_ENCAP for notify messages */ addresses = (char **) realloc(addresses, (i + 2) * sizeof(char *)); if (addresses == (char **) NULL) crit_error(1, "realloc() in init_server()"); addresses[i + 1] = (char *) NULL; sockets = (int *) realloc(sockets, (i + 2)* sizeof(int)); if (sockets == (int *) NULL) crit_error(1, "realloc() in init_server()"); sockets[i] = kernel_get_socket(); sockets[i+1] = -1; i++; /* Next interface */ #endif for (ip = 0, d = 0; d < ifconf.ifc_len; d += IFNAMSIZ + #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(_AIX) buf[IFNAMSIZ + d] #else sizeof(struct sockaddr) #endif , i++, ip++) { sin2 = (struct sockaddr_in *) &buf[IFNAMSIZ + d]; if (sin2->sin_family != AF_INET) { i--; ip--; continue; } addresses = (char **) realloc(addresses, (i + 2) * sizeof(char *)); if (addresses == (char **) NULL) crit_error(1, "realloc() in init_server()"); addresses[i] = strdup(inet_ntoa(sin2->sin_addr)); if (addresses[i] == (char *) NULL) crit_error(1, "strdup() in init_server()"); addresses[i + 1] = (char *) NULL; sockets = (int *) realloc(sockets, (i + 2)* sizeof(int)); if (sockets == (int *) NULL) crit_error(1, "realloc() in init_server()"); sockets[i+1] = -1; if ((sock = socket(PF_INET, SOCK_DGRAM, proto->p_proto)) < 0) crit_error(1, "socket() in init_server()"); setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); sockets[i] = sock; #ifdef DEBUG printf("Local interface %s, address %s.\n", buf + d, addresses[i]); #endif bzero((void *)&sin, sizeof(sin)); sin.sin_port = htons(global_port); sin.sin_addr.s_addr = inet_addr(addresses[i]); sin.sin_family = AF_INET; if (bind(sockets[i], (struct sockaddr *)&sin, sizeof(struct sockaddr)) < 0) crit_error(1, "bind() in init_server()"); } num_ifs = i; #ifdef DEBUG printf("%d local interfaces supporting IP found.\n", ip); #endif return 1; } int server(void) { struct sockaddr_in sin; struct timeval timeout; fd_set readfds, normfds; int i, d; setvbuf(stdout, (char *)NULL, _IOLBF, 0); FD_ZERO(&normfds); for (i=0; i