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 * 261fa665f5SBrian Somers * $Id: server.c,v 1.16.2.16 1998/04/18 01:01:28 brian Exp $ 271ae349f5Scvs2svn */ 281ae349f5Scvs2svn 292764b86aSBrian Somers #include <sys/types.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> 351fa665f5SBrian Somers #include <sys/un.h> 361ae349f5Scvs2svn 371ae349f5Scvs2svn #include <errno.h> 381ae349f5Scvs2svn #include <stdio.h> 391ae349f5Scvs2svn #include <string.h> 401ae349f5Scvs2svn #include <sys/stat.h> 4185b542cfSBrian Somers #include <termios.h> 421ae349f5Scvs2svn #include <unistd.h> 431ae349f5Scvs2svn 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "defs.h" 4777ff88adSBrian Somers #include "descriptor.h" 481ae349f5Scvs2svn #include "server.h" 491ae349f5Scvs2svn #include "id.h" 5085b542cfSBrian Somers #include "prompt.h" 513006ec67SBrian Somers #include "timer.h" 52b6217683SBrian Somers #include "lqr.h" 53b6217683SBrian Somers #include "hdlc.h" 54b6217683SBrian Somers #include "fsm.h" 55b6217683SBrian Somers #include "lcp.h" 56b6217683SBrian Somers #include "ccp.h" 57b6217683SBrian Somers #include "throughput.h" 58b6217683SBrian Somers #include "link.h" 59b6217683SBrian Somers #include "mp.h" 60b6217683SBrian Somers #include "iplist.h" 61b6217683SBrian Somers #include "slcompress.h" 62b6217683SBrian Somers #include "ipcp.h" 63b6217683SBrian Somers #include "filter.h" 64b6217683SBrian Somers #include "bundle.h" 651ae349f5Scvs2svn 6677ff88adSBrian Somers static int 6777ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 6877ff88adSBrian Somers { 6977ff88adSBrian Somers struct server *s = descriptor2server(d); 7077ff88adSBrian Somers 71b6dec9f0SBrian Somers if (r && s->fd >= 0) { 7277ff88adSBrian Somers if (*n < s->fd + 1) 7377ff88adSBrian Somers *n = s->fd + 1; 7485b542cfSBrian Somers FD_SET(s->fd, r); 7577ff88adSBrian Somers return 1; 7677ff88adSBrian Somers } 7777ff88adSBrian Somers return 0; 7877ff88adSBrian Somers } 7977ff88adSBrian Somers 8077ff88adSBrian Somers static int 812f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset) 8277ff88adSBrian Somers { 8377ff88adSBrian Somers struct server *s = descriptor2server(d); 8477ff88adSBrian Somers return s->fd >= 0 && FD_ISSET(s->fd, fdset); 8577ff88adSBrian Somers } 8677ff88adSBrian Somers 8777ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 8877ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 8977ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 9077ff88adSBrian Somers 9177ff88adSBrian Somers static void 92b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 9377ff88adSBrian Somers { 9477ff88adSBrian Somers struct server *s = descriptor2server(d); 9577ff88adSBrian Somers char hisaddr[ADDRSZ]; 9677ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 97cdbbb6b5SBrian Somers struct sockaddr_in *in = (struct sockaddr_in *)hisaddr; 9877ff88adSBrian Somers int ssize = ADDRSZ, wfd; 99b6217683SBrian Somers struct prompt *p; 10077ff88adSBrian Somers 10177ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 10277ff88adSBrian Somers if (wfd < 0) { 10377ff88adSBrian Somers LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 10477ff88adSBrian Somers return; 10577ff88adSBrian Somers } 10677ff88adSBrian Somers 10777ff88adSBrian Somers switch (sa->sa_family) { 10877ff88adSBrian Somers case AF_LOCAL: 10977ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to local client.\n"); 11077ff88adSBrian Somers break; 11177ff88adSBrian Somers 11277ff88adSBrian Somers case AF_INET: 113cdbbb6b5SBrian Somers if (ntohs(in->sin_port) < 1024) { 11477ff88adSBrian Somers LogPrintf(LogALERT, "Rejected client connection from %s:%u" 11577ff88adSBrian Somers "(invalid port number) !\n", 116cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), ntohs(in->sin_port)); 11777ff88adSBrian Somers close(wfd); 11877ff88adSBrian Somers return; 11977ff88adSBrian Somers } 12077ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 121cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 12277ff88adSBrian Somers break; 12377ff88adSBrian Somers 12477ff88adSBrian Somers default: 12577ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 12677ff88adSBrian Somers close(wfd); 12777ff88adSBrian Somers return; 12877ff88adSBrian Somers } 12977ff88adSBrian Somers 130b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 131b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 13277ff88adSBrian Somers close(wfd); 13377ff88adSBrian Somers } else { 134b6217683SBrian Somers switch (sa->sa_family) { 135b6217683SBrian Somers case AF_LOCAL: 136565e35e5SBrian Somers p->src.type = "local"; 137565e35e5SBrian Somers strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 138565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 139b6217683SBrian Somers break; 140b6217683SBrian Somers case AF_INET: 141565e35e5SBrian Somers p->src.type = "tcp"; 142565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 143cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 144b6217683SBrian Somers break; 145b6217683SBrian Somers } 146b6217683SBrian Somers prompt_TtyCommandMode(p); 147b6217683SBrian Somers prompt_Required(p); 14877ff88adSBrian Somers } 14977ff88adSBrian Somers } 15077ff88adSBrian Somers 15177ff88adSBrian Somers static void 152f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 15377ff88adSBrian Somers { 15477ff88adSBrian Somers /* We never want to write here ! */ 15577ff88adSBrian Somers LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n"); 15677ff88adSBrian Somers } 15777ff88adSBrian Somers 15877ff88adSBrian Somers struct server server = { 15977ff88adSBrian Somers { 16077ff88adSBrian Somers SERVER_DESCRIPTOR, 16177ff88adSBrian Somers NULL, 16277ff88adSBrian Somers server_UpdateSet, 16377ff88adSBrian Somers server_IsSet, 16477ff88adSBrian Somers server_Read, 16577ff88adSBrian Somers server_Write 16677ff88adSBrian Somers }, 16777ff88adSBrian Somers -1 16877ff88adSBrian Somers }; 1691ae349f5Scvs2svn 1701ae349f5Scvs2svn int 171b6217683SBrian Somers ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask) 1721ae349f5Scvs2svn { 1731ae349f5Scvs2svn int s; 1741ae349f5Scvs2svn 175565e35e5SBrian Somers if (server.rm && !strcmp(server.rm, name)) { 176565e35e5SBrian Somers if (chmod(server.rm, mask)) 177565e35e5SBrian Somers LogPrintf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 178565e35e5SBrian Somers return 0; 179565e35e5SBrian Somers } 180565e35e5SBrian Somers 181565e35e5SBrian Somers memset(&server.ifsun, '\0', sizeof server.ifsun); 182565e35e5SBrian Somers server.ifsun.sun_len = strlen(name); 183565e35e5SBrian Somers if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 1841ae349f5Scvs2svn LogPrintf(LogERROR, "Local: %s: Path too long\n", name); 1851ae349f5Scvs2svn return 2; 1861ae349f5Scvs2svn } 187565e35e5SBrian Somers server.ifsun.sun_family = AF_LOCAL; 188565e35e5SBrian Somers strcpy(server.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); 198565e35e5SBrian Somers if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.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; 215565e35e5SBrian Somers server.rm = server.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 226565e35e5SBrian Somers if (server.port == port) 227565e35e5SBrian Somers return 0; 228565e35e5SBrian Somers 2291ae349f5Scvs2svn s = ID0socket(PF_INET, SOCK_STREAM, 0); 2301ae349f5Scvs2svn if (s < 0) { 2311ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 2321ae349f5Scvs2svn return 7; 2331ae349f5Scvs2svn } 2341ae349f5Scvs2svn memset(&ifsin, '\0', sizeof ifsin); 2351ae349f5Scvs2svn ifsin.sin_family = AF_INET; 2361ae349f5Scvs2svn ifsin.sin_addr.s_addr = INADDR_ANY; 2371ae349f5Scvs2svn ifsin.sin_port = htons(port); 2381ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2391ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 240b6217683SBrian Somers LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 2411ae349f5Scvs2svn close(s); 2421ae349f5Scvs2svn return 8; 2431ae349f5Scvs2svn } 2441ae349f5Scvs2svn if (listen(s, 5) != 0) { 2457a6f8720SBrian Somers LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2461ae349f5Scvs2svn close(s); 2471ae349f5Scvs2svn return 9; 2481ae349f5Scvs2svn } 249b6217683SBrian Somers ServerClose(bundle); 25077ff88adSBrian Somers server.fd = s; 251565e35e5SBrian Somers server.port = port; 2521ae349f5Scvs2svn LogPrintf(LogPHASE, "Listening at port %d.\n", port); 2531ae349f5Scvs2svn return 0; 2541ae349f5Scvs2svn } 2551ae349f5Scvs2svn 25677ff88adSBrian Somers int 257b6217683SBrian Somers ServerClose(struct bundle *bundle) 2581ae349f5Scvs2svn { 25977ff88adSBrian Somers if (server.fd >= 0) { 26077ff88adSBrian Somers close(server.fd); 261565e35e5SBrian Somers if (server.rm) { 262565e35e5SBrian Somers ID0unlink(server.rm); 263565e35e5SBrian Somers server.rm = NULL; 2641ae349f5Scvs2svn } 26577ff88adSBrian Somers server.fd = -1; 266565e35e5SBrian Somers server.port = 0; 267b6217683SBrian Somers /* Drop associated prompts */ 268b6217683SBrian Somers bundle_DelPromptDescriptors(bundle, &server); 26977ff88adSBrian Somers return 1; 2701ae349f5Scvs2svn } 27177ff88adSBrian Somers return 0; 2721ae349f5Scvs2svn } 273