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 * 2685b542cfSBrian Somers * $Id: server.c,v 1.16.2.3 1998/02/10 03:22:05 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> 341ae349f5Scvs2svn 351ae349f5Scvs2svn #include <errno.h> 361ae349f5Scvs2svn #include <stdio.h> 371ae349f5Scvs2svn #include <string.h> 381ae349f5Scvs2svn #include <sys/stat.h> 391ae349f5Scvs2svn #include <sys/un.h> 4085b542cfSBrian Somers #include <termios.h> 411ae349f5Scvs2svn #include <unistd.h> 421ae349f5Scvs2svn 431ae349f5Scvs2svn #include "command.h" 441ae349f5Scvs2svn #include "mbuf.h" 451ae349f5Scvs2svn #include "log.h" 461ae349f5Scvs2svn #include "loadalias.h" 471ae349f5Scvs2svn #include "defs.h" 481ae349f5Scvs2svn #include "vars.h" 4977ff88adSBrian Somers #include "descriptor.h" 501ae349f5Scvs2svn #include "server.h" 511ae349f5Scvs2svn #include "id.h" 5285b542cfSBrian Somers #include "prompt.h" 531ae349f5Scvs2svn 5477ff88adSBrian Somers static int 5577ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 5677ff88adSBrian Somers { 5777ff88adSBrian Somers struct server *s = descriptor2server(d); 5877ff88adSBrian Somers 5977ff88adSBrian Somers LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s); 6077ff88adSBrian Somers if (s->fd >= 0) { 6177ff88adSBrian Somers if (*n < s->fd + 1) 6277ff88adSBrian Somers *n = s->fd + 1; 6385b542cfSBrian Somers FD_SET(s->fd, r); 6477ff88adSBrian Somers return 1; 6577ff88adSBrian Somers } 6677ff88adSBrian Somers return 0; 6777ff88adSBrian Somers } 6877ff88adSBrian Somers 6977ff88adSBrian Somers static int 7077ff88adSBrian Somers server_IsSet(struct descriptor *d, fd_set *fdset) 7177ff88adSBrian Somers { 7277ff88adSBrian Somers struct server *s = descriptor2server(d); 7377ff88adSBrian Somers 7477ff88adSBrian Somers LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s); 7577ff88adSBrian Somers return s->fd >= 0 && FD_ISSET(s->fd, fdset); 7677ff88adSBrian Somers } 7777ff88adSBrian Somers 7877ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 7977ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 8077ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 8177ff88adSBrian Somers 8277ff88adSBrian Somers static void 83b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 8477ff88adSBrian Somers { 8577ff88adSBrian Somers struct server *s = descriptor2server(d); 8677ff88adSBrian Somers char hisaddr[ADDRSZ]; 8777ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 8877ff88adSBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr; 8977ff88adSBrian Somers int ssize = ADDRSZ, wfd; 9077ff88adSBrian Somers 9177ff88adSBrian Somers LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s); 9277ff88adSBrian Somers 9377ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 9477ff88adSBrian Somers if (wfd < 0) { 9577ff88adSBrian Somers LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 9677ff88adSBrian Somers return; 9777ff88adSBrian Somers } 9877ff88adSBrian Somers 9977ff88adSBrian Somers switch (sa->sa_family) { 10077ff88adSBrian Somers case AF_LOCAL: 10177ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to local client.\n"); 10277ff88adSBrian Somers break; 10377ff88adSBrian Somers 10477ff88adSBrian Somers case AF_INET: 10577ff88adSBrian Somers if (ntohs(sin->sin_port) < 1024) { 10677ff88adSBrian Somers LogPrintf(LogALERT, "Rejected client connection from %s:%u" 10777ff88adSBrian Somers "(invalid port number) !\n", 10877ff88adSBrian Somers inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 10977ff88adSBrian Somers close(wfd); 11077ff88adSBrian Somers return; 11177ff88adSBrian Somers } 11277ff88adSBrian Somers LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 11377ff88adSBrian Somers inet_ntoa(sin->sin_addr), sin->sin_port); 11477ff88adSBrian Somers break; 11577ff88adSBrian Somers 11677ff88adSBrian Somers default: 11777ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 11877ff88adSBrian Somers close(wfd); 11977ff88adSBrian Somers return; 12077ff88adSBrian Somers } 12177ff88adSBrian Somers 12285b542cfSBrian Somers if (!prompt_Init(&prompt, wfd)) { 12377ff88adSBrian Somers write(wfd, "Connection already in use.\n", 27); 12477ff88adSBrian Somers close(wfd); 12577ff88adSBrian Somers } else { 12677ff88adSBrian Somers LocalAuthInit(); 12777ff88adSBrian Somers IsInteractive(1); 12885b542cfSBrian Somers prompt_Display(&prompt, bundle); 12977ff88adSBrian Somers } 13077ff88adSBrian Somers } 13177ff88adSBrian Somers 13277ff88adSBrian Somers static void 133b77776a7SBrian Somers server_Write(struct descriptor *d, const fd_set *fdset) 13477ff88adSBrian Somers { 13577ff88adSBrian Somers /* We never want to write here ! */ 13677ff88adSBrian Somers LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n"); 13777ff88adSBrian Somers } 13877ff88adSBrian Somers 13977ff88adSBrian Somers struct server server = { 14077ff88adSBrian Somers { 14177ff88adSBrian Somers SERVER_DESCRIPTOR, 14277ff88adSBrian Somers NULL, 14377ff88adSBrian Somers server_UpdateSet, 14477ff88adSBrian Somers server_IsSet, 14577ff88adSBrian Somers server_Read, 14677ff88adSBrian Somers server_Write 14777ff88adSBrian Somers }, 14877ff88adSBrian Somers -1 14977ff88adSBrian Somers }; 1501ae349f5Scvs2svn 1511ae349f5Scvs2svn static struct sockaddr_un ifsun; 1521ae349f5Scvs2svn static char *rm; 1531ae349f5Scvs2svn 1541ae349f5Scvs2svn int 1551ae349f5Scvs2svn ServerLocalOpen(const char *name, mode_t mask) 1561ae349f5Scvs2svn { 1571ae349f5Scvs2svn int s; 1581ae349f5Scvs2svn 1591ae349f5Scvs2svn if (VarLocalAuth == LOCAL_DENY) { 1601ae349f5Scvs2svn LogPrintf(LogERROR, "Local: Can't open socket %s: No password " 1611ae349f5Scvs2svn "in ppp.secret\n", name); 1621ae349f5Scvs2svn return 1; 1631ae349f5Scvs2svn } 1641ae349f5Scvs2svn 1651ae349f5Scvs2svn if (mode & MODE_INTER) { 1661ae349f5Scvs2svn LogPrintf(LogERROR, "Local: Can't open socket in interactive mode\n"); 1671ae349f5Scvs2svn return 1; 1681ae349f5Scvs2svn } 1691ae349f5Scvs2svn 1701ae349f5Scvs2svn memset(&ifsun, '\0', sizeof ifsun); 1711ae349f5Scvs2svn ifsun.sun_len = strlen(name); 1721ae349f5Scvs2svn if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 1731ae349f5Scvs2svn LogPrintf(LogERROR, "Local: %s: Path too long\n", name); 1741ae349f5Scvs2svn return 2; 1751ae349f5Scvs2svn } 1761ae349f5Scvs2svn ifsun.sun_family = AF_LOCAL; 1771ae349f5Scvs2svn strcpy(ifsun.sun_path, name); 1781ae349f5Scvs2svn 1791ae349f5Scvs2svn s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 1801ae349f5Scvs2svn if (s < 0) { 1811ae349f5Scvs2svn LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno)); 1821ae349f5Scvs2svn return 3; 1831ae349f5Scvs2svn } 1841ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 1851ae349f5Scvs2svn if (mask != (mode_t)-1) 1861ae349f5Scvs2svn mask = umask(mask); 1871ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) { 1881ae349f5Scvs2svn if (mask != (mode_t)-1) 1891ae349f5Scvs2svn umask(mask); 1901ae349f5Scvs2svn LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno)); 19185b542cfSBrian Somers if (errno == EADDRINUSE) 19285b542cfSBrian Somers prompt_Printf(&prompt, "Wait for a while, then try again.\n"); 1931ae349f5Scvs2svn close(s); 1941ae349f5Scvs2svn return 4; 1951ae349f5Scvs2svn } 1961ae349f5Scvs2svn if (mask != (mode_t)-1) 1971ae349f5Scvs2svn umask(mask); 1981ae349f5Scvs2svn if (listen(s, 5) != 0) { 1997a6f8720SBrian Somers LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 2001ae349f5Scvs2svn close(s); 2011ae349f5Scvs2svn ID0unlink(name); 2021ae349f5Scvs2svn return 5; 2031ae349f5Scvs2svn } 2041ae349f5Scvs2svn ServerClose(); 20577ff88adSBrian Somers server.fd = s; 2061ae349f5Scvs2svn rm = ifsun.sun_path; 2071ae349f5Scvs2svn LogPrintf(LogPHASE, "Listening at local socket %s.\n", name); 2081ae349f5Scvs2svn return 0; 2091ae349f5Scvs2svn } 2101ae349f5Scvs2svn 2111ae349f5Scvs2svn int 2121ae349f5Scvs2svn ServerTcpOpen(int port) 2131ae349f5Scvs2svn { 2141ae349f5Scvs2svn struct sockaddr_in ifsin; 2151ae349f5Scvs2svn int s; 2161ae349f5Scvs2svn 2171ae349f5Scvs2svn if (VarLocalAuth == LOCAL_DENY) { 2181ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: Can't open socket %d: No password " 2191ae349f5Scvs2svn "in ppp.secret\n", port); 2201ae349f5Scvs2svn return 6; 2211ae349f5Scvs2svn } 2221ae349f5Scvs2svn 2231ae349f5Scvs2svn if (mode & MODE_INTER) { 2241ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: Can't open socket in interactive mode\n"); 2251ae349f5Scvs2svn return 6; 2261ae349f5Scvs2svn } 2271ae349f5Scvs2svn 2281ae349f5Scvs2svn s = ID0socket(PF_INET, SOCK_STREAM, 0); 2291ae349f5Scvs2svn if (s < 0) { 2301ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 2311ae349f5Scvs2svn return 7; 2321ae349f5Scvs2svn } 2331ae349f5Scvs2svn memset(&ifsin, '\0', sizeof ifsin); 2341ae349f5Scvs2svn ifsin.sin_family = AF_INET; 2351ae349f5Scvs2svn ifsin.sin_addr.s_addr = INADDR_ANY; 2361ae349f5Scvs2svn ifsin.sin_port = htons(port); 2371ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2381ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 2391ae349f5Scvs2svn LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno)); 24085b542cfSBrian Somers if (errno == EADDRINUSE) 24185b542cfSBrian Somers prompt_Printf(&prompt, "Wait for a while, then try again.\n"); 2421ae349f5Scvs2svn close(s); 2431ae349f5Scvs2svn return 8; 2441ae349f5Scvs2svn } 2451ae349f5Scvs2svn if (listen(s, 5) != 0) { 2467a6f8720SBrian Somers LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2471ae349f5Scvs2svn close(s); 2481ae349f5Scvs2svn return 9; 2491ae349f5Scvs2svn } 2501ae349f5Scvs2svn ServerClose(); 25177ff88adSBrian Somers server.fd = s; 2521ae349f5Scvs2svn LogPrintf(LogPHASE, "Listening at port %d.\n", port); 2531ae349f5Scvs2svn return 0; 2541ae349f5Scvs2svn } 2551ae349f5Scvs2svn 25677ff88adSBrian Somers int 2571ae349f5Scvs2svn ServerClose() 2581ae349f5Scvs2svn { 25977ff88adSBrian Somers if (server.fd >= 0) { 26077ff88adSBrian Somers close(server.fd); 2611ae349f5Scvs2svn if (rm) { 2621ae349f5Scvs2svn ID0unlink(rm); 2631ae349f5Scvs2svn rm = 0; 2641ae349f5Scvs2svn } 26577ff88adSBrian Somers server.fd = -1; 26677ff88adSBrian Somers return 1; 2671ae349f5Scvs2svn } 26877ff88adSBrian Somers return 0; 2691ae349f5Scvs2svn } 270