11ae349f5Scvs2svn /*- 21ae349f5Scvs2svn * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 31ae349f5Scvs2svn * All rights reserved. 41ae349f5Scvs2svn * 51ae349f5Scvs2svn * Redistribution and use in source and binary forms, with or without 61ae349f5Scvs2svn * modification, are permitted provided that the following conditions 71ae349f5Scvs2svn * are met: 81ae349f5Scvs2svn * 1. Redistributions of source code must retain the above copyright 91ae349f5Scvs2svn * notice, this list of conditions and the following disclaimer. 101ae349f5Scvs2svn * 2. Redistributions in binary form must reproduce the above copyright 111ae349f5Scvs2svn * notice, this list of conditions and the following disclaimer in the 121ae349f5Scvs2svn * documentation and/or other materials provided with the distribution. 131ae349f5Scvs2svn * 141ae349f5Scvs2svn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 151ae349f5Scvs2svn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 161ae349f5Scvs2svn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 171ae349f5Scvs2svn * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 181ae349f5Scvs2svn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 191ae349f5Scvs2svn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 201ae349f5Scvs2svn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 211ae349f5Scvs2svn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 221ae349f5Scvs2svn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 231ae349f5Scvs2svn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 241ae349f5Scvs2svn * SUCH DAMAGE. 251ae349f5Scvs2svn * 26b6217683SBrian Somers * $Id: server.c,v 1.16.2.10 1998/04/03 19:21:51 brian Exp $ 271ae349f5Scvs2svn */ 281ae349f5Scvs2svn 291ae349f5Scvs2svn #include <sys/param.h> 301ae349f5Scvs2svn #include <sys/socket.h> 311ae349f5Scvs2svn #include <netinet/in.h> 321ae349f5Scvs2svn #include <arpa/inet.h> 331ae349f5Scvs2svn #include <netinet/in_systm.h> 34b6217683SBrian Somers #include <netinet/ip.h> 351ae349f5Scvs2svn 361ae349f5Scvs2svn #include <errno.h> 371ae349f5Scvs2svn #include <stdio.h> 381ae349f5Scvs2svn #include <string.h> 391ae349f5Scvs2svn #include <sys/stat.h> 401ae349f5Scvs2svn #include <sys/un.h> 4185b542cfSBrian Somers #include <termios.h> 421ae349f5Scvs2svn #include <unistd.h> 431ae349f5Scvs2svn 441ae349f5Scvs2svn #include "command.h" 451ae349f5Scvs2svn #include "mbuf.h" 461ae349f5Scvs2svn #include "log.h" 471ae349f5Scvs2svn #include "loadalias.h" 481ae349f5Scvs2svn #include "defs.h" 491ae349f5Scvs2svn #include "vars.h" 5077ff88adSBrian Somers #include "descriptor.h" 511ae349f5Scvs2svn #include "server.h" 521ae349f5Scvs2svn #include "id.h" 5385b542cfSBrian Somers #include "prompt.h" 543006ec67SBrian Somers #include "timer.h" 553006ec67SBrian Somers #include "auth.h" 56b6217683SBrian Somers #include "lqr.h" 57b6217683SBrian Somers #include "hdlc.h" 58b6217683SBrian Somers #include "fsm.h" 59b6217683SBrian Somers #include "lcp.h" 60b6217683SBrian Somers #include "ccp.h" 61b6217683SBrian Somers #include "throughput.h" 62b6217683SBrian Somers #include "link.h" 63b6217683SBrian Somers #include "mp.h" 64b6217683SBrian Somers #include "iplist.h" 65b6217683SBrian Somers #include "slcompress.h" 66b6217683SBrian Somers #include "ipcp.h" 67b6217683SBrian Somers #include "filter.h" 68b6217683SBrian Somers #include "bundle.h" 691ae349f5Scvs2svn 7077ff88adSBrian Somers static int 7177ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 7277ff88adSBrian Somers { 7377ff88adSBrian Somers struct server *s = descriptor2server(d); 7477ff88adSBrian Somers 75b6dec9f0SBrian Somers if (r && s->fd >= 0) { 7677ff88adSBrian Somers if (*n < s->fd + 1) 7777ff88adSBrian Somers *n = s->fd + 1; 7885b542cfSBrian Somers FD_SET(s->fd, r); 7977ff88adSBrian Somers return 1; 8077ff88adSBrian Somers } 8177ff88adSBrian Somers return 0; 8277ff88adSBrian Somers } 8377ff88adSBrian Somers 8477ff88adSBrian Somers static int 852f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset) 8677ff88adSBrian Somers { 8777ff88adSBrian Somers struct server *s = descriptor2server(d); 8877ff88adSBrian Somers return s->fd >= 0 && FD_ISSET(s->fd, fdset); 8977ff88adSBrian Somers } 9077ff88adSBrian Somers 9177ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 9277ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 9377ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 9477ff88adSBrian Somers 95b6217683SBrian Somers static char *rm; 96b6217683SBrian Somers 9777ff88adSBrian Somers static void 98b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 9977ff88adSBrian Somers { 10077ff88adSBrian Somers struct server *s = descriptor2server(d); 10177ff88adSBrian Somers char hisaddr[ADDRSZ]; 10277ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 10377ff88adSBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr; 10477ff88adSBrian Somers int ssize = ADDRSZ, wfd; 105b6217683SBrian Somers struct prompt *p; 10677ff88adSBrian Somers 10777ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 10877ff88adSBrian Somers if (wfd < 0) { 10977ff88adSBrian Somers LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 11077ff88adSBrian Somers return; 11177ff88adSBrian Somers } 11277ff88adSBrian Somers 11377ff88adSBrian Somers switch (sa->sa_family) { 11477ff88adSBrian Somers case AF_LOCAL: 11577ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to local client.\n"); 11677ff88adSBrian Somers break; 11777ff88adSBrian Somers 11877ff88adSBrian Somers case AF_INET: 11977ff88adSBrian Somers if (ntohs(sin->sin_port) < 1024) { 12077ff88adSBrian Somers LogPrintf(LogALERT, "Rejected client connection from %s:%u" 12177ff88adSBrian Somers "(invalid port number) !\n", 12277ff88adSBrian Somers inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 12377ff88adSBrian Somers close(wfd); 12477ff88adSBrian Somers return; 12577ff88adSBrian Somers } 12677ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 12777ff88adSBrian Somers inet_ntoa(sin->sin_addr), sin->sin_port); 12877ff88adSBrian Somers break; 12977ff88adSBrian Somers 13077ff88adSBrian Somers default: 13177ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 13277ff88adSBrian Somers close(wfd); 13377ff88adSBrian Somers return; 13477ff88adSBrian Somers } 13577ff88adSBrian Somers 136b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 137b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 13877ff88adSBrian Somers close(wfd); 13977ff88adSBrian Somers } else { 140b6217683SBrian Somers switch (sa->sa_family) { 141b6217683SBrian Somers case AF_LOCAL: 142b6217683SBrian Somers snprintf(p->who, sizeof p->who, "local (%s)", rm); 143b6217683SBrian Somers break; 144b6217683SBrian Somers case AF_INET: 145b6217683SBrian Somers snprintf(p->who, sizeof p->who, "TCP (%s:%u)", 146b6217683SBrian Somers inet_ntoa(sin->sin_addr), sin->sin_port); 147b6217683SBrian Somers break; 148b6217683SBrian Somers } 149b6217683SBrian Somers IsInteractive(p); 150b6217683SBrian Somers prompt_TtyCommandMode(p); 151b6217683SBrian Somers prompt_Required(p); 15277ff88adSBrian Somers } 15377ff88adSBrian Somers } 15477ff88adSBrian Somers 15577ff88adSBrian Somers static void 156f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 15777ff88adSBrian Somers { 15877ff88adSBrian Somers /* We never want to write here ! */ 15977ff88adSBrian Somers LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n"); 16077ff88adSBrian Somers } 16177ff88adSBrian Somers 16277ff88adSBrian Somers struct server server = { 16377ff88adSBrian Somers { 16477ff88adSBrian Somers SERVER_DESCRIPTOR, 16577ff88adSBrian Somers NULL, 16677ff88adSBrian Somers server_UpdateSet, 16777ff88adSBrian Somers server_IsSet, 16877ff88adSBrian Somers server_Read, 16977ff88adSBrian Somers server_Write 17077ff88adSBrian Somers }, 17177ff88adSBrian Somers -1 17277ff88adSBrian Somers }; 1731ae349f5Scvs2svn 1741ae349f5Scvs2svn static struct sockaddr_un ifsun; 1751ae349f5Scvs2svn 1761ae349f5Scvs2svn int 177b6217683SBrian Somers ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask) 1781ae349f5Scvs2svn { 1791ae349f5Scvs2svn int s; 1801ae349f5Scvs2svn 1811ae349f5Scvs2svn memset(&ifsun, '\0', sizeof ifsun); 1821ae349f5Scvs2svn ifsun.sun_len = strlen(name); 1831ae349f5Scvs2svn if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 1841ae349f5Scvs2svn LogPrintf(LogERROR, "Local: %s: Path too long\n", name); 1851ae349f5Scvs2svn return 2; 1861ae349f5Scvs2svn } 1871ae349f5Scvs2svn ifsun.sun_family = AF_LOCAL; 1881ae349f5Scvs2svn strcpy(ifsun.sun_path, name); 1891ae349f5Scvs2svn 1901ae349f5Scvs2svn s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 1911ae349f5Scvs2svn if (s < 0) { 1921ae349f5Scvs2svn LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno)); 1931ae349f5Scvs2svn return 3; 1941ae349f5Scvs2svn } 1951ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 1961ae349f5Scvs2svn if (mask != (mode_t)-1) 1971ae349f5Scvs2svn mask = umask(mask); 1981ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) { 1991ae349f5Scvs2svn if (mask != (mode_t)-1) 2001ae349f5Scvs2svn umask(mask); 201b6217683SBrian Somers LogPrintf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2021ae349f5Scvs2svn close(s); 2031ae349f5Scvs2svn return 4; 2041ae349f5Scvs2svn } 2051ae349f5Scvs2svn if (mask != (mode_t)-1) 2061ae349f5Scvs2svn umask(mask); 2071ae349f5Scvs2svn if (listen(s, 5) != 0) { 2087a6f8720SBrian Somers LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 2091ae349f5Scvs2svn close(s); 2101ae349f5Scvs2svn ID0unlink(name); 2111ae349f5Scvs2svn return 5; 2121ae349f5Scvs2svn } 213b6217683SBrian Somers ServerClose(bundle); 21477ff88adSBrian Somers server.fd = s; 2151ae349f5Scvs2svn rm = ifsun.sun_path; 2161ae349f5Scvs2svn LogPrintf(LogPHASE, "Listening at local socket %s.\n", name); 2171ae349f5Scvs2svn return 0; 2181ae349f5Scvs2svn } 2191ae349f5Scvs2svn 2201ae349f5Scvs2svn int 221b6217683SBrian Somers ServerTcpOpen(struct bundle *bundle, int port) 2221ae349f5Scvs2svn { 2231ae349f5Scvs2svn struct sockaddr_in ifsin; 2241ae349f5Scvs2svn int s; 2251ae349f5Scvs2svn 2261ae349f5Scvs2svn s = ID0socket(PF_INET, SOCK_STREAM, 0); 2271ae349f5Scvs2svn if (s < 0) { 2281ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 2291ae349f5Scvs2svn return 7; 2301ae349f5Scvs2svn } 2311ae349f5Scvs2svn memset(&ifsin, '\0', sizeof ifsin); 2321ae349f5Scvs2svn ifsin.sin_family = AF_INET; 2331ae349f5Scvs2svn ifsin.sin_addr.s_addr = INADDR_ANY; 2341ae349f5Scvs2svn ifsin.sin_port = htons(port); 2351ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2361ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 237b6217683SBrian Somers LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 2381ae349f5Scvs2svn close(s); 2391ae349f5Scvs2svn return 8; 2401ae349f5Scvs2svn } 2411ae349f5Scvs2svn if (listen(s, 5) != 0) { 2427a6f8720SBrian Somers LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2431ae349f5Scvs2svn close(s); 2441ae349f5Scvs2svn return 9; 2451ae349f5Scvs2svn } 246b6217683SBrian Somers ServerClose(bundle); 24777ff88adSBrian Somers server.fd = s; 2481ae349f5Scvs2svn LogPrintf(LogPHASE, "Listening at port %d.\n", port); 2491ae349f5Scvs2svn return 0; 2501ae349f5Scvs2svn } 2511ae349f5Scvs2svn 25277ff88adSBrian Somers int 253b6217683SBrian Somers ServerClose(struct bundle *bundle) 2541ae349f5Scvs2svn { 25577ff88adSBrian Somers if (server.fd >= 0) { 25677ff88adSBrian Somers close(server.fd); 2571ae349f5Scvs2svn if (rm) { 2581ae349f5Scvs2svn ID0unlink(rm); 2591ae349f5Scvs2svn rm = 0; 2601ae349f5Scvs2svn } 26177ff88adSBrian Somers server.fd = -1; 262b6217683SBrian Somers /* Drop associated prompts */ 263b6217683SBrian Somers bundle_DelPromptDescriptors(bundle, &server); 26477ff88adSBrian Somers return 1; 2651ae349f5Scvs2svn } 26677ff88adSBrian Somers return 0; 2671ae349f5Scvs2svn } 268