1 /*- 2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: server.c,v 1.16.2.13 1998/04/07 00:54:17 brian Exp $ 27 */ 28 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <netinet/in_systm.h> 34 #include <netinet/ip.h> 35 36 #include <errno.h> 37 #include <stdio.h> 38 #include <string.h> 39 #include <sys/stat.h> 40 #include <sys/un.h> 41 #include <termios.h> 42 #include <unistd.h> 43 44 #include "mbuf.h" 45 #include "log.h" 46 #include "defs.h" 47 #include "descriptor.h" 48 #include "server.h" 49 #include "id.h" 50 #include "prompt.h" 51 #include "timer.h" 52 #include "lqr.h" 53 #include "hdlc.h" 54 #include "fsm.h" 55 #include "lcp.h" 56 #include "ccp.h" 57 #include "throughput.h" 58 #include "link.h" 59 #include "mp.h" 60 #include "iplist.h" 61 #include "slcompress.h" 62 #include "ipcp.h" 63 #include "filter.h" 64 #include "bundle.h" 65 66 static int 67 server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 68 { 69 struct server *s = descriptor2server(d); 70 71 if (r && s->fd >= 0) { 72 if (*n < s->fd + 1) 73 *n = s->fd + 1; 74 FD_SET(s->fd, r); 75 return 1; 76 } 77 return 0; 78 } 79 80 static int 81 server_IsSet(struct descriptor *d, const fd_set *fdset) 82 { 83 struct server *s = descriptor2server(d); 84 return s->fd >= 0 && FD_ISSET(s->fd, fdset); 85 } 86 87 #define IN_SIZE sizeof(struct sockaddr_in) 88 #define UN_SIZE sizeof(struct sockaddr_in) 89 #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 90 91 static char *rm; 92 93 static void 94 server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 95 { 96 struct server *s = descriptor2server(d); 97 char hisaddr[ADDRSZ]; 98 struct sockaddr *sa = (struct sockaddr *)hisaddr; 99 struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr; 100 int ssize = ADDRSZ, wfd; 101 struct prompt *p; 102 103 wfd = accept(s->fd, sa, &ssize); 104 if (wfd < 0) { 105 LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 106 return; 107 } 108 109 switch (sa->sa_family) { 110 case AF_LOCAL: 111 LogPrintf(LogPHASE, "Connected to local client.\n"); 112 break; 113 114 case AF_INET: 115 if (ntohs(sin->sin_port) < 1024) { 116 LogPrintf(LogALERT, "Rejected client connection from %s:%u" 117 "(invalid port number) !\n", 118 inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 119 close(wfd); 120 return; 121 } 122 LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 123 inet_ntoa(sin->sin_addr), sin->sin_port); 124 break; 125 126 default: 127 write(wfd, "Unrecognised access !\n", 22); 128 close(wfd); 129 return; 130 } 131 132 if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 133 write(wfd, "Connection refused.\n", 20); 134 close(wfd); 135 } else { 136 switch (sa->sa_family) { 137 case AF_LOCAL: 138 snprintf(p->who, sizeof p->who, "local (%s)", rm); 139 break; 140 case AF_INET: 141 snprintf(p->who, sizeof p->who, "TCP (%s:%u)", 142 inet_ntoa(sin->sin_addr), sin->sin_port); 143 break; 144 } 145 prompt_TtyCommandMode(p); 146 prompt_Required(p); 147 } 148 } 149 150 static void 151 server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 152 { 153 /* We never want to write here ! */ 154 LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n"); 155 } 156 157 struct server server = { 158 { 159 SERVER_DESCRIPTOR, 160 NULL, 161 server_UpdateSet, 162 server_IsSet, 163 server_Read, 164 server_Write 165 }, 166 -1 167 }; 168 169 static struct sockaddr_un ifsun; 170 171 int 172 ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask) 173 { 174 int s; 175 176 memset(&ifsun, '\0', sizeof ifsun); 177 ifsun.sun_len = strlen(name); 178 if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 179 LogPrintf(LogERROR, "Local: %s: Path too long\n", name); 180 return 2; 181 } 182 ifsun.sun_family = AF_LOCAL; 183 strcpy(ifsun.sun_path, name); 184 185 s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 186 if (s < 0) { 187 LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno)); 188 return 3; 189 } 190 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 191 if (mask != (mode_t)-1) 192 mask = umask(mask); 193 if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) { 194 if (mask != (mode_t)-1) 195 umask(mask); 196 LogPrintf(LogWARN, "Local: bind: %s\n", strerror(errno)); 197 close(s); 198 return 4; 199 } 200 if (mask != (mode_t)-1) 201 umask(mask); 202 if (listen(s, 5) != 0) { 203 LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 204 close(s); 205 ID0unlink(name); 206 return 5; 207 } 208 ServerClose(bundle); 209 server.fd = s; 210 rm = ifsun.sun_path; 211 LogPrintf(LogPHASE, "Listening at local socket %s.\n", name); 212 return 0; 213 } 214 215 int 216 ServerTcpOpen(struct bundle *bundle, int port) 217 { 218 struct sockaddr_in ifsin; 219 int s; 220 221 s = ID0socket(PF_INET, SOCK_STREAM, 0); 222 if (s < 0) { 223 LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 224 return 7; 225 } 226 memset(&ifsin, '\0', sizeof ifsin); 227 ifsin.sin_family = AF_INET; 228 ifsin.sin_addr.s_addr = INADDR_ANY; 229 ifsin.sin_port = htons(port); 230 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 231 if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 232 LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 233 close(s); 234 return 8; 235 } 236 if (listen(s, 5) != 0) { 237 LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 238 close(s); 239 return 9; 240 } 241 ServerClose(bundle); 242 server.fd = s; 243 LogPrintf(LogPHASE, "Listening at port %d.\n", port); 244 return 0; 245 } 246 247 int 248 ServerClose(struct bundle *bundle) 249 { 250 if (server.fd >= 0) { 251 close(server.fd); 252 if (rm) { 253 ID0unlink(rm); 254 rm = 0; 255 } 256 server.fd = -1; 257 /* Drop associated prompts */ 258 bundle_DelPromptDescriptors(bundle, &server); 259 return 1; 260 } 261 return 0; 262 } 263