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 * 2624989c68SBrian Somers * $Id: server.c,v 1.16.2.18 1998/05/01 19:25:50 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); 7524989c68SBrian Somers log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 7677ff88adSBrian Somers return 1; 7777ff88adSBrian Somers } 7877ff88adSBrian Somers return 0; 7977ff88adSBrian Somers } 8077ff88adSBrian Somers 8177ff88adSBrian Somers static int 822f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset) 8377ff88adSBrian Somers { 8477ff88adSBrian Somers struct server *s = descriptor2server(d); 8577ff88adSBrian Somers return s->fd >= 0 && FD_ISSET(s->fd, fdset); 8677ff88adSBrian Somers } 8777ff88adSBrian Somers 8877ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 8977ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 9077ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 9177ff88adSBrian Somers 9277ff88adSBrian Somers static void 93b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 9477ff88adSBrian Somers { 9577ff88adSBrian Somers struct server *s = descriptor2server(d); 9677ff88adSBrian Somers char hisaddr[ADDRSZ]; 9777ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 98cdbbb6b5SBrian Somers struct sockaddr_in *in = (struct sockaddr_in *)hisaddr; 9977ff88adSBrian Somers int ssize = ADDRSZ, wfd; 100b6217683SBrian Somers struct prompt *p; 10177ff88adSBrian Somers 10277ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 10377ff88adSBrian Somers if (wfd < 0) { 104dd7e2610SBrian Somers log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 10577ff88adSBrian Somers return; 10677ff88adSBrian Somers } 10777ff88adSBrian Somers 10877ff88adSBrian Somers switch (sa->sa_family) { 10977ff88adSBrian Somers case AF_LOCAL: 110dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to local client.\n"); 11177ff88adSBrian Somers break; 11277ff88adSBrian Somers 11377ff88adSBrian Somers case AF_INET: 114cdbbb6b5SBrian Somers if (ntohs(in->sin_port) < 1024) { 115dd7e2610SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 11677ff88adSBrian Somers "(invalid port number) !\n", 117cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), ntohs(in->sin_port)); 11877ff88adSBrian Somers close(wfd); 11977ff88adSBrian Somers return; 12077ff88adSBrian Somers } 121dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 122cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 12377ff88adSBrian Somers break; 12477ff88adSBrian Somers 12577ff88adSBrian Somers default: 12677ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 12777ff88adSBrian Somers close(wfd); 12877ff88adSBrian Somers return; 12977ff88adSBrian Somers } 13077ff88adSBrian Somers 131b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 132b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 13377ff88adSBrian Somers close(wfd); 13477ff88adSBrian Somers } else { 135b6217683SBrian Somers switch (sa->sa_family) { 136b6217683SBrian Somers case AF_LOCAL: 137565e35e5SBrian Somers p->src.type = "local"; 138565e35e5SBrian Somers strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 139565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 140b6217683SBrian Somers break; 141b6217683SBrian Somers case AF_INET: 142565e35e5SBrian Somers p->src.type = "tcp"; 143565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 144cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 145b6217683SBrian Somers break; 146b6217683SBrian Somers } 147b6217683SBrian Somers prompt_TtyCommandMode(p); 148b6217683SBrian Somers prompt_Required(p); 14977ff88adSBrian Somers } 15077ff88adSBrian Somers } 15177ff88adSBrian Somers 15277ff88adSBrian Somers static void 153f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 15477ff88adSBrian Somers { 15577ff88adSBrian Somers /* We never want to write here ! */ 156dd7e2610SBrian Somers log_Printf(LogERROR, "server_Write: Internal error: Bad call !\n"); 15777ff88adSBrian Somers } 15877ff88adSBrian Somers 15977ff88adSBrian Somers struct server server = { 16077ff88adSBrian Somers { 16177ff88adSBrian Somers SERVER_DESCRIPTOR, 16277ff88adSBrian Somers NULL, 16377ff88adSBrian Somers server_UpdateSet, 16477ff88adSBrian Somers server_IsSet, 16577ff88adSBrian Somers server_Read, 16677ff88adSBrian Somers server_Write 16777ff88adSBrian Somers }, 16877ff88adSBrian Somers -1 16977ff88adSBrian Somers }; 1701ae349f5Scvs2svn 1711ae349f5Scvs2svn int 172dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 1731ae349f5Scvs2svn { 1741ae349f5Scvs2svn int s; 1751ae349f5Scvs2svn 176565e35e5SBrian Somers if (server.rm && !strcmp(server.rm, name)) { 177565e35e5SBrian Somers if (chmod(server.rm, mask)) 178dd7e2610SBrian Somers log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 179565e35e5SBrian Somers return 0; 180565e35e5SBrian Somers } 181565e35e5SBrian Somers 182565e35e5SBrian Somers memset(&server.ifsun, '\0', sizeof server.ifsun); 183565e35e5SBrian Somers server.ifsun.sun_len = strlen(name); 184565e35e5SBrian Somers if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 185dd7e2610SBrian Somers log_Printf(LogERROR, "Local: %s: Path too long\n", name); 1861ae349f5Scvs2svn return 2; 1871ae349f5Scvs2svn } 188565e35e5SBrian Somers server.ifsun.sun_family = AF_LOCAL; 189565e35e5SBrian Somers strcpy(server.ifsun.sun_path, name); 1901ae349f5Scvs2svn 1911ae349f5Scvs2svn s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 1921ae349f5Scvs2svn if (s < 0) { 193dd7e2610SBrian Somers log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 1941ae349f5Scvs2svn return 3; 1951ae349f5Scvs2svn } 1961ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 1971ae349f5Scvs2svn if (mask != (mode_t)-1) 1981ae349f5Scvs2svn mask = umask(mask); 199565e35e5SBrian Somers if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) { 2001ae349f5Scvs2svn if (mask != (mode_t)-1) 2011ae349f5Scvs2svn umask(mask); 202dd7e2610SBrian Somers log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2031ae349f5Scvs2svn close(s); 2041ae349f5Scvs2svn return 4; 2051ae349f5Scvs2svn } 2061ae349f5Scvs2svn if (mask != (mode_t)-1) 2071ae349f5Scvs2svn umask(mask); 2081ae349f5Scvs2svn if (listen(s, 5) != 0) { 209dd7e2610SBrian Somers log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 2101ae349f5Scvs2svn close(s); 2111ae349f5Scvs2svn ID0unlink(name); 2121ae349f5Scvs2svn return 5; 2131ae349f5Scvs2svn } 214dd7e2610SBrian Somers server_Close(bundle); 21577ff88adSBrian Somers server.fd = s; 216565e35e5SBrian Somers server.rm = server.ifsun.sun_path; 217dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 2181ae349f5Scvs2svn return 0; 2191ae349f5Scvs2svn } 2201ae349f5Scvs2svn 2211ae349f5Scvs2svn int 222dd7e2610SBrian Somers server_TcpOpen(struct bundle *bundle, int port) 2231ae349f5Scvs2svn { 2241ae349f5Scvs2svn struct sockaddr_in ifsin; 2251ae349f5Scvs2svn int s; 2261ae349f5Scvs2svn 227565e35e5SBrian Somers if (server.port == port) 228565e35e5SBrian Somers return 0; 229565e35e5SBrian Somers 2301ae349f5Scvs2svn s = ID0socket(PF_INET, SOCK_STREAM, 0); 2311ae349f5Scvs2svn if (s < 0) { 232dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 2331ae349f5Scvs2svn return 7; 2341ae349f5Scvs2svn } 2351ae349f5Scvs2svn memset(&ifsin, '\0', sizeof ifsin); 2361ae349f5Scvs2svn ifsin.sin_family = AF_INET; 2371ae349f5Scvs2svn ifsin.sin_addr.s_addr = INADDR_ANY; 2381ae349f5Scvs2svn ifsin.sin_port = htons(port); 2391ae349f5Scvs2svn setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2401ae349f5Scvs2svn if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 241dd7e2610SBrian Somers log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 2421ae349f5Scvs2svn close(s); 2431ae349f5Scvs2svn return 8; 2441ae349f5Scvs2svn } 2451ae349f5Scvs2svn if (listen(s, 5) != 0) { 246dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2471ae349f5Scvs2svn close(s); 2481ae349f5Scvs2svn return 9; 2491ae349f5Scvs2svn } 250dd7e2610SBrian Somers server_Close(bundle); 25177ff88adSBrian Somers server.fd = s; 252565e35e5SBrian Somers server.port = port; 253dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at port %d.\n", port); 2541ae349f5Scvs2svn return 0; 2551ae349f5Scvs2svn } 2561ae349f5Scvs2svn 25777ff88adSBrian Somers int 258dd7e2610SBrian Somers server_Close(struct bundle *bundle) 2591ae349f5Scvs2svn { 26077ff88adSBrian Somers if (server.fd >= 0) { 26177ff88adSBrian Somers close(server.fd); 262565e35e5SBrian Somers if (server.rm) { 263565e35e5SBrian Somers ID0unlink(server.rm); 264565e35e5SBrian Somers server.rm = NULL; 2651ae349f5Scvs2svn } 26677ff88adSBrian Somers server.fd = -1; 267565e35e5SBrian Somers server.port = 0; 268b6217683SBrian Somers /* Drop associated prompts */ 269b6217683SBrian Somers bundle_DelPromptDescriptors(bundle, &server); 27077ff88adSBrian Somers return 1; 2711ae349f5Scvs2svn } 27277ff88adSBrian Somers return 0; 2731ae349f5Scvs2svn } 274