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 * 260bdcbcbeSBrian Somers * $Id: server.c,v 1.22 1998/06/27 14:18:10 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> 331fa665f5SBrian Somers #include <sys/un.h> 3475240ed1SBrian Somers 354ef16f24SBrian Somers #include <errno.h> 3675240ed1SBrian Somers #include <stdio.h> 3775240ed1SBrian Somers #include <string.h> 3875240ed1SBrian Somers #include <sys/stat.h> 3985b542cfSBrian Somers #include <termios.h> 404ef16f24SBrian Somers #include <unistd.h> 4175240ed1SBrian Somers 424ef16f24SBrian Somers #include "log.h" 4377ff88adSBrian Somers #include "descriptor.h" 444ef16f24SBrian Somers #include "server.h" 455106c671SBrian Somers #include "id.h" 4685b542cfSBrian Somers #include "prompt.h" 474ef16f24SBrian Somers 4877ff88adSBrian Somers static int 4977ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 5077ff88adSBrian Somers { 5177ff88adSBrian Somers struct server *s = descriptor2server(d); 520f2f3eb3SBrian Somers struct prompt *p; 530f2f3eb3SBrian Somers int sets; 5475240ed1SBrian Somers 550f2f3eb3SBrian Somers sets = 0; 56b6dec9f0SBrian Somers if (r && s->fd >= 0) { 5777ff88adSBrian Somers if (*n < s->fd + 1) 5877ff88adSBrian Somers *n = s->fd + 1; 5985b542cfSBrian Somers FD_SET(s->fd, r); 6024989c68SBrian Somers log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 610f2f3eb3SBrian Somers sets++; 6277ff88adSBrian Somers } 630f2f3eb3SBrian Somers 640f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 650f2f3eb3SBrian Somers sets += descriptor_UpdateSet(&p->desc, r, w, e, n); 660f2f3eb3SBrian Somers 670f2f3eb3SBrian Somers return sets; 6877ff88adSBrian Somers } 6977ff88adSBrian Somers 7077ff88adSBrian Somers static int 712f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset) 7277ff88adSBrian Somers { 7377ff88adSBrian Somers struct server *s = descriptor2server(d); 740f2f3eb3SBrian Somers struct prompt *p; 750f2f3eb3SBrian Somers 760f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) 770f2f3eb3SBrian Somers return 1; 780f2f3eb3SBrian Somers 790f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 800f2f3eb3SBrian Somers if (descriptor_IsSet(&p->desc, fdset)) 810f2f3eb3SBrian Somers return 1; 820f2f3eb3SBrian Somers 830f2f3eb3SBrian Somers return 0; 8477ff88adSBrian Somers } 8577ff88adSBrian Somers 8677ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in) 8777ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in) 8877ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 8977ff88adSBrian Somers 9077ff88adSBrian Somers static void 91b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 9277ff88adSBrian Somers { 9377ff88adSBrian Somers struct server *s = descriptor2server(d); 9477ff88adSBrian Somers char hisaddr[ADDRSZ]; 9577ff88adSBrian Somers struct sockaddr *sa = (struct sockaddr *)hisaddr; 96cdbbb6b5SBrian Somers struct sockaddr_in *in = (struct sockaddr_in *)hisaddr; 9777ff88adSBrian Somers int ssize = ADDRSZ, wfd; 98b6217683SBrian Somers struct prompt *p; 9977ff88adSBrian Somers 1000f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { 10177ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 1020f2f3eb3SBrian Somers if (wfd < 0) 103dd7e2610SBrian Somers log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 1040f2f3eb3SBrian Somers } else 1050f2f3eb3SBrian Somers wfd = -1; 10677ff88adSBrian Somers 1070f2f3eb3SBrian Somers if (wfd >= 0) 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); 1190f2f3eb3SBrian Somers wfd = -1; 1200f2f3eb3SBrian Somers break; 12177ff88adSBrian Somers } 122dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 123cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 12477ff88adSBrian Somers break; 12577ff88adSBrian Somers 12677ff88adSBrian Somers default: 12777ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 12877ff88adSBrian Somers close(wfd); 1290f2f3eb3SBrian Somers wfd = -1; 1300f2f3eb3SBrian Somers break; 13177ff88adSBrian Somers } 13277ff88adSBrian Somers 1330f2f3eb3SBrian Somers if (wfd >= 0) { 134b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 135b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 13677ff88adSBrian Somers close(wfd); 13777ff88adSBrian Somers } else { 138b6217683SBrian Somers switch (sa->sa_family) { 139b6217683SBrian Somers case AF_LOCAL: 140565e35e5SBrian Somers p->src.type = "local"; 141565e35e5SBrian Somers strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 142565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 143b6217683SBrian Somers break; 144b6217683SBrian Somers case AF_INET: 145565e35e5SBrian Somers p->src.type = "tcp"; 146565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 147cdbbb6b5SBrian Somers inet_ntoa(in->sin_addr), in->sin_port); 148b6217683SBrian Somers break; 149b6217683SBrian Somers } 150b6217683SBrian Somers prompt_TtyCommandMode(p); 151b6217683SBrian Somers prompt_Required(p); 15277ff88adSBrian Somers } 15377ff88adSBrian Somers } 15477ff88adSBrian Somers 1550bdcbcbeSBrian Somers log_PromptListChanged = 0; 1560f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 1570bdcbcbeSBrian Somers if (descriptor_IsSet(&p->desc, fdset)) { 1580f2f3eb3SBrian Somers descriptor_Read(&p->desc, bundle, fdset); 1590bdcbcbeSBrian Somers if (log_PromptListChanged) 1600bdcbcbeSBrian Somers break; 1610bdcbcbeSBrian Somers } 1620f2f3eb3SBrian Somers } 1630f2f3eb3SBrian Somers 1641af29a6eSBrian Somers static int 165f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 16677ff88adSBrian Somers { 16777ff88adSBrian Somers /* We never want to write here ! */ 168a33b2ef7SBrian Somers log_Printf(LogALERT, "server_Write: Internal error: Bad call !\n"); 1691af29a6eSBrian Somers return 0; 17077ff88adSBrian Somers } 17177ff88adSBrian Somers 17277ff88adSBrian Somers struct server server = { 17377ff88adSBrian Somers { 17477ff88adSBrian Somers SERVER_DESCRIPTOR, 17577ff88adSBrian Somers server_UpdateSet, 17677ff88adSBrian Somers server_IsSet, 17777ff88adSBrian Somers server_Read, 17877ff88adSBrian Somers server_Write 17977ff88adSBrian Somers }, 18077ff88adSBrian Somers -1 18177ff88adSBrian Somers }; 1824ef16f24SBrian Somers 1834ef16f24SBrian Somers int 184dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 1854ef16f24SBrian Somers { 1864ef16f24SBrian Somers int s; 1874ef16f24SBrian Somers 188565e35e5SBrian Somers if (server.rm && !strcmp(server.rm, name)) { 189565e35e5SBrian Somers if (chmod(server.rm, mask)) 190dd7e2610SBrian Somers log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 191565e35e5SBrian Somers return 0; 192683cef3cSBrian Somers } 193683cef3cSBrian Somers 194565e35e5SBrian Somers memset(&server.ifsun, '\0', sizeof server.ifsun); 195565e35e5SBrian Somers server.ifsun.sun_len = strlen(name); 196565e35e5SBrian Somers if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 197dd7e2610SBrian Somers log_Printf(LogERROR, "Local: %s: Path too long\n", name); 198683cef3cSBrian Somers return 2; 1994ef16f24SBrian Somers } 200565e35e5SBrian Somers server.ifsun.sun_family = AF_LOCAL; 201565e35e5SBrian Somers strcpy(server.ifsun.sun_path, name); 2024ef16f24SBrian Somers 2035106c671SBrian Somers s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 2044ef16f24SBrian Somers if (s < 0) { 205dd7e2610SBrian Somers log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 206683cef3cSBrian Somers return 3; 2074ef16f24SBrian Somers } 2084ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2098ea8442cSBrian Somers if (mask != (mode_t)-1) 21001ec2511SBrian Somers mask = umask(mask); 211565e35e5SBrian Somers if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) { 2128ea8442cSBrian Somers if (mask != (mode_t)-1) 21301ec2511SBrian Somers umask(mask); 214dd7e2610SBrian Somers log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2154ef16f24SBrian Somers close(s); 216683cef3cSBrian Somers return 4; 2174ef16f24SBrian Somers } 2188ea8442cSBrian Somers if (mask != (mode_t)-1) 21901ec2511SBrian Somers umask(mask); 2204ef16f24SBrian Somers if (listen(s, 5) != 0) { 221dd7e2610SBrian Somers log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 2224ef16f24SBrian Somers close(s); 2235106c671SBrian Somers ID0unlink(name); 224683cef3cSBrian Somers return 5; 2254ef16f24SBrian Somers } 226dd7e2610SBrian Somers server_Close(bundle); 22777ff88adSBrian Somers server.fd = s; 228565e35e5SBrian Somers server.rm = server.ifsun.sun_path; 229dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 2304ef16f24SBrian Somers return 0; 2314ef16f24SBrian Somers } 2324ef16f24SBrian Somers 2334ef16f24SBrian Somers int 234dd7e2610SBrian Somers server_TcpOpen(struct bundle *bundle, int port) 2354ef16f24SBrian Somers { 2364ef16f24SBrian Somers struct sockaddr_in ifsin; 2374ef16f24SBrian Somers int s; 2384ef16f24SBrian Somers 239565e35e5SBrian Somers if (server.port == port) 240565e35e5SBrian Somers return 0; 241d40f8a5aSBrian Somers 2425106c671SBrian Somers s = ID0socket(PF_INET, SOCK_STREAM, 0); 2434ef16f24SBrian Somers if (s < 0) { 244dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 245683cef3cSBrian Somers return 7; 2464ef16f24SBrian Somers } 2472e14bb46SBrian Somers memset(&ifsin, '\0', sizeof ifsin); 2484ef16f24SBrian Somers ifsin.sin_family = AF_INET; 2494ef16f24SBrian Somers ifsin.sin_addr.s_addr = INADDR_ANY; 2504ef16f24SBrian Somers ifsin.sin_port = htons(port); 2514ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 25270ee81ffSBrian Somers if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 253dd7e2610SBrian Somers log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 2544ef16f24SBrian Somers close(s); 255683cef3cSBrian Somers return 8; 2564ef16f24SBrian Somers } 2574ef16f24SBrian Somers if (listen(s, 5) != 0) { 258dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 2594ef16f24SBrian Somers close(s); 260683cef3cSBrian Somers return 9; 2614ef16f24SBrian Somers } 262dd7e2610SBrian Somers server_Close(bundle); 26377ff88adSBrian Somers server.fd = s; 264565e35e5SBrian Somers server.port = port; 265dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at port %d.\n", port); 2664ef16f24SBrian Somers return 0; 2674ef16f24SBrian Somers } 2684ef16f24SBrian Somers 26977ff88adSBrian Somers int 270dd7e2610SBrian Somers server_Close(struct bundle *bundle) 2714ef16f24SBrian Somers { 27277ff88adSBrian Somers if (server.fd >= 0) { 27377ff88adSBrian Somers close(server.fd); 274565e35e5SBrian Somers if (server.rm) { 275565e35e5SBrian Somers ID0unlink(server.rm); 276565e35e5SBrian Somers server.rm = NULL; 2774ef16f24SBrian Somers } 27877ff88adSBrian Somers server.fd = -1; 279565e35e5SBrian Somers server.port = 0; 280b6217683SBrian Somers /* Drop associated prompts */ 2810f2f3eb3SBrian Somers log_DestroyPrompts(&server); 28277ff88adSBrian Somers return 1; 2834ef16f24SBrian Somers } 28477ff88adSBrian Somers return 0; 2854ef16f24SBrian Somers } 286