1c39934eaSBrian Somers /*- 2c39934eaSBrian Somers * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 3c39934eaSBrian Somers * All rights reserved. 4c39934eaSBrian Somers * 5c39934eaSBrian Somers * Redistribution and use in source and binary forms, with or without 6c39934eaSBrian Somers * modification, are permitted provided that the following conditions 7c39934eaSBrian Somers * are met: 8c39934eaSBrian Somers * 1. Redistributions of source code must retain the above copyright 9c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer. 10c39934eaSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright 11c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer in the 12c39934eaSBrian Somers * documentation and/or other materials provided with the distribution. 13c39934eaSBrian Somers * 14c39934eaSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15c39934eaSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16c39934eaSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17c39934eaSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18c39934eaSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19c39934eaSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20c39934eaSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21c39934eaSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22c39934eaSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23c39934eaSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24c39934eaSBrian Somers * SUCH DAMAGE. 25c39934eaSBrian Somers * 261af29a6eSBrian Somers * $Id: server.c,v 1.20 1998/06/16 19:40:41 brian Exp $ 2775240ed1SBrian Somers */ 2875240ed1SBrian Somers 292764b86aSBrian Somers #include <sys/types.h> 304ef16f24SBrian Somers #include <sys/socket.h> 314ef16f24SBrian Somers #include <netinet/in.h> 324ef16f24SBrian Somers #include <arpa/inet.h> 334ef16f24SBrian Somers #include <netinet/in_systm.h> 34b6217683SBrian Somers #include <netinet/ip.h> 351fa665f5SBrian Somers #include <sys/un.h> 3675240ed1SBrian Somers 374ef16f24SBrian Somers #include <errno.h> 3875240ed1SBrian Somers #include <stdio.h> 3975240ed1SBrian Somers #include <string.h> 4075240ed1SBrian Somers #include <sys/stat.h> 4185b542cfSBrian Somers #include <termios.h> 424ef16f24SBrian Somers #include <unistd.h> 4375240ed1SBrian Somers 444ef16f24SBrian Somers #include "mbuf.h" 454ef16f24SBrian Somers #include "log.h" 4686e02934SBrian Somers #include "defs.h" 4777ff88adSBrian Somers #include "descriptor.h" 484ef16f24SBrian Somers #include "server.h" 495106c671SBrian Somers #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" 654ef16f24SBrian Somers 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); 700f2f3eb3SBrian Somers struct prompt *p; 710f2f3eb3SBrian Somers int sets; 7275240ed1SBrian Somers 730f2f3eb3SBrian Somers sets = 0; 74b6dec9f0SBrian Somers if (r && s->fd >= 0) { 7577ff88adSBrian Somers if (*n < s->fd + 1) 7677ff88adSBrian Somers *n = s->fd + 1; 7785b542cfSBrian Somers FD_SET(s->fd, r); 7824989c68SBrian Somers log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 790f2f3eb3SBrian Somers sets++; 8077ff88adSBrian Somers } 810f2f3eb3SBrian Somers 820f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 830f2f3eb3SBrian Somers sets += descriptor_UpdateSet(&p->desc, r, w, e, n); 840f2f3eb3SBrian Somers 850f2f3eb3SBrian Somers return sets; 8677ff88adSBrian Somers } 8777ff88adSBrian Somers 8877ff88adSBrian Somers static int 892f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset) 9077ff88adSBrian Somers { 9177ff88adSBrian Somers struct server *s = descriptor2server(d); 920f2f3eb3SBrian Somers struct prompt *p; 930f2f3eb3SBrian Somers 940f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) 950f2f3eb3SBrian Somers return 1; 960f2f3eb3SBrian Somers 970f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 980f2f3eb3SBrian Somers if (descriptor_IsSet(&p->desc, fdset)) 990f2f3eb3SBrian Somers return 1; 1000f2f3eb3SBrian Somers 1010f2f3eb3SBrian Somers return 0; 10277ff88adSBrian Somers } 10377ff88adSBrian Somers 10477ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 10577ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 10677ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 10777ff88adSBrian Somers 10877ff88adSBrian Somers static void 109b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 11077ff88adSBrian Somers { 11177ff88adSBrian Somers struct server *s = descriptor2server(d); 11277ff88adSBrian Somers char hisaddr[ADDRSZ]; 11377ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 114cdbbb6b5SBrian Somers struct sockaddr_in *in = (struct sockaddr_in *)hisaddr; 11577ff88adSBrian Somers int ssize = ADDRSZ, wfd; 116b6217683SBrian Somers struct prompt *p; 11777ff88adSBrian Somers 1180f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { 11977ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 1200f2f3eb3SBrian Somers if (wfd < 0) 121dd7e2610SBrian Somers log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 1220f2f3eb3SBrian Somers } else 1230f2f3eb3SBrian Somers wfd = -1; 12477ff88adSBrian Somers 1250f2f3eb3SBrian Somers if (wfd >= 0) 12677ff88adSBrian Somers switch (sa->sa_family) { 12777ff88adSBrian Somers case AF_LOCAL: 128dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to local client.\n"); 12977ff88adSBrian Somers break; 13077ff88adSBrian Somers 13177ff88adSBrian Somers case AF_INET: 132cdbbb6b5SBrian Somers if (ntohs(in->sin_port) < 1024) { 133dd7e2610SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 13477ff88adSBrian Somers "(invalid port number) !\n", 135cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), ntohs(in->sin_port)); 13677ff88adSBrian Somers close(wfd); 1370f2f3eb3SBrian Somers wfd = -1; 1380f2f3eb3SBrian Somers break; 13977ff88adSBrian Somers } 140dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 141cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 14277ff88adSBrian Somers break; 14377ff88adSBrian Somers 14477ff88adSBrian Somers default: 14577ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 14677ff88adSBrian Somers close(wfd); 1470f2f3eb3SBrian Somers wfd = -1; 1480f2f3eb3SBrian Somers break; 14977ff88adSBrian Somers } 15077ff88adSBrian Somers 1510f2f3eb3SBrian Somers if (wfd >= 0) { 152b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 153b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 15477ff88adSBrian Somers close(wfd); 15577ff88adSBrian Somers } else { 156b6217683SBrian Somers switch (sa->sa_family) { 157b6217683SBrian Somers case AF_LOCAL: 158565e35e5SBrian Somers p->src.type = "local"; 159565e35e5SBrian Somers strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 160565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 161b6217683SBrian Somers break; 162b6217683SBrian Somers case AF_INET: 163565e35e5SBrian Somers p->src.type = "tcp"; 164565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 165cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 166b6217683SBrian Somers break; 167b6217683SBrian Somers } 168b6217683SBrian Somers prompt_TtyCommandMode(p); 169b6217683SBrian Somers prompt_Required(p); 17077ff88adSBrian Somers } 17177ff88adSBrian Somers } 17277ff88adSBrian Somers 1730f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 1740f2f3eb3SBrian Somers if (descriptor_IsSet(&p->desc, fdset)) 1750f2f3eb3SBrian Somers descriptor_Read(&p->desc, bundle, fdset); 1760f2f3eb3SBrian Somers } 1770f2f3eb3SBrian Somers 1781af29a6eSBrian Somers static int 179f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 18077ff88adSBrian Somers { 18177ff88adSBrian Somers /* We never want to write here ! */ 182a33b2ef7SBrian Somers log_Printf(LogALERT, "server_Write: Internal error: Bad call !\n"); 1831af29a6eSBrian Somers return 0; 18477ff88adSBrian Somers } 18577ff88adSBrian Somers 18677ff88adSBrian Somers struct server server = { 18777ff88adSBrian Somers { 18877ff88adSBrian Somers SERVER_DESCRIPTOR, 18977ff88adSBrian Somers server_UpdateSet, 19077ff88adSBrian Somers server_IsSet, 19177ff88adSBrian Somers server_Read, 19277ff88adSBrian Somers server_Write 19377ff88adSBrian Somers }, 19477ff88adSBrian Somers -1 19577ff88adSBrian Somers }; 1964ef16f24SBrian Somers 1974ef16f24SBrian Somers int 198dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 1994ef16f24SBrian Somers { 2004ef16f24SBrian Somers int s; 2014ef16f24SBrian Somers 202565e35e5SBrian Somers if (server.rm && !strcmp(server.rm, name)) { 203565e35e5SBrian Somers if (chmod(server.rm, mask)) 204dd7e2610SBrian Somers log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 205565e35e5SBrian Somers return 0; 206683cef3cSBrian Somers } 207683cef3cSBrian Somers 208565e35e5SBrian Somers memset(&server.ifsun, '\0', sizeof server.ifsun); 209565e35e5SBrian Somers server.ifsun.sun_len = strlen(name); 210565e35e5SBrian Somers if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 211dd7e2610SBrian Somers log_Printf(LogERROR, "Local: %s: Path too long\n", name); 212683cef3cSBrian Somers return 2; 2134ef16f24SBrian Somers } 214565e35e5SBrian Somers server.ifsun.sun_family = AF_LOCAL; 215565e35e5SBrian Somers strcpy(server.ifsun.sun_path, name); 2164ef16f24SBrian Somers 2175106c671SBrian Somers s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 2184ef16f24SBrian Somers if (s < 0) { 219dd7e2610SBrian Somers log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 220683cef3cSBrian Somers return 3; 2214ef16f24SBrian Somers } 2224ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2238ea8442cSBrian Somers if (mask != (mode_t)-1) 22401ec2511SBrian Somers mask = umask(mask); 225565e35e5SBrian Somers if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) { 2268ea8442cSBrian Somers if (mask != (mode_t)-1) 22701ec2511SBrian Somers umask(mask); 228dd7e2610SBrian Somers log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2294ef16f24SBrian Somers close(s); 230683cef3cSBrian Somers return 4; 2314ef16f24SBrian Somers } 2328ea8442cSBrian Somers if (mask != (mode_t)-1) 23301ec2511SBrian Somers umask(mask); 2344ef16f24SBrian Somers if (listen(s, 5) != 0) { 235dd7e2610SBrian Somers log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 2364ef16f24SBrian Somers close(s); 2375106c671SBrian Somers ID0unlink(name); 238683cef3cSBrian Somers return 5; 2394ef16f24SBrian Somers } 240dd7e2610SBrian Somers server_Close(bundle); 24177ff88adSBrian Somers server.fd = s; 242565e35e5SBrian Somers server.rm = server.ifsun.sun_path; 243dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 2444ef16f24SBrian Somers return 0; 2454ef16f24SBrian Somers } 2464ef16f24SBrian Somers 2474ef16f24SBrian Somers int 248dd7e2610SBrian Somers server_TcpOpen(struct bundle *bundle, int port) 2494ef16f24SBrian Somers { 2504ef16f24SBrian Somers struct sockaddr_in ifsin; 2514ef16f24SBrian Somers int s; 2524ef16f24SBrian Somers 253565e35e5SBrian Somers if (server.port == port) 254565e35e5SBrian Somers return 0; 255d40f8a5aSBrian Somers 2565106c671SBrian Somers s = ID0socket(PF_INET, SOCK_STREAM, 0); 2574ef16f24SBrian Somers if (s < 0) { 258dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 259683cef3cSBrian Somers return 7; 2604ef16f24SBrian Somers } 2612e14bb46SBrian Somers memset(&ifsin, '\0', sizeof ifsin); 2624ef16f24SBrian Somers ifsin.sin_family = AF_INET; 2634ef16f24SBrian Somers ifsin.sin_addr.s_addr = INADDR_ANY; 2644ef16f24SBrian Somers ifsin.sin_port = htons(port); 2654ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 26670ee81ffSBrian Somers if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 267dd7e2610SBrian Somers log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 2684ef16f24SBrian Somers close(s); 269683cef3cSBrian Somers return 8; 2704ef16f24SBrian Somers } 2714ef16f24SBrian Somers if (listen(s, 5) != 0) { 272dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2734ef16f24SBrian Somers close(s); 274683cef3cSBrian Somers return 9; 2754ef16f24SBrian Somers } 276dd7e2610SBrian Somers server_Close(bundle); 27777ff88adSBrian Somers server.fd = s; 278565e35e5SBrian Somers server.port = port; 279dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at port %d.\n", port); 2804ef16f24SBrian Somers return 0; 2814ef16f24SBrian Somers } 2824ef16f24SBrian Somers 28377ff88adSBrian Somers int 284dd7e2610SBrian Somers server_Close(struct bundle *bundle) 2854ef16f24SBrian Somers { 28677ff88adSBrian Somers if (server.fd >= 0) { 28777ff88adSBrian Somers close(server.fd); 288565e35e5SBrian Somers if (server.rm) { 289565e35e5SBrian Somers ID0unlink(server.rm); 290565e35e5SBrian Somers server.rm = NULL; 2914ef16f24SBrian Somers } 29277ff88adSBrian Somers server.fd = -1; 293565e35e5SBrian Somers server.port = 0; 294b6217683SBrian Somers /* Drop associated prompts */ 2950f2f3eb3SBrian Somers log_DestroyPrompts(&server); 29677ff88adSBrian Somers return 1; 2974ef16f24SBrian Somers } 29877ff88adSBrian Somers return 0; 2994ef16f24SBrian Somers } 300