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.14 1998/04/07 23:46:09 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 void 92 server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 93 { 94 struct server *s = descriptor2server(d); 95 char hisaddr[ADDRSZ]; 96 struct sockaddr *sa = (struct sockaddr *)hisaddr; 97 struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr; 98 int ssize = ADDRSZ, wfd; 99 struct prompt *p; 100 101 wfd = accept(s->fd, sa, &ssize); 102 if (wfd < 0) { 103 LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 104 return; 105 } 106 107 switch (sa->sa_family) { 108 case AF_LOCAL: 109 LogPrintf(LogPHASE, "Connected to local client.\n"); 110 break; 111 112 case AF_INET: 113 if (ntohs(sin->sin_port) < 1024) { 114 LogPrintf(LogALERT, "Rejected client connection from %s:%u" 115 "(invalid port number) !\n", 116 inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); 117 close(wfd); 118 return; 119 } 120 LogPrintf(LogPHASE, "Connected to client from %s:%u\n", 121 inet_ntoa(sin->sin_addr), sin->sin_port); 122 break; 123 124 default: 125 write(wfd, "Unrecognised access !\n", 22); 126 close(wfd); 127 return; 128 } 129 130 if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 131 write(wfd, "Connection refused.\n", 20); 132 close(wfd); 133 } else { 134 switch (sa->sa_family) { 135 case AF_LOCAL: 136 p->src.type = "local"; 137 strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 138 p->src.from[sizeof p->src.from - 1] = '\0'; 139 break; 140 case AF_INET: 141 p->src.type = "tcp"; 142 snprintf(p->src.from, sizeof p->src.from, "%s:%u", 143 inet_ntoa(sin->sin_addr), sin->sin_port); 144 break; 145 } 146 prompt_TtyCommandMode(p); 147 prompt_Required(p); 148 } 149 } 150 151 static void 152 server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset) 153 { 154 /* We never want to write here ! */ 155 LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n"); 156 } 157 158 struct server server = { 159 { 160 SERVER_DESCRIPTOR, 161 NULL, 162 server_UpdateSet, 163 server_IsSet, 164 server_Read, 165 server_Write 166 }, 167 -1 168 }; 169 170 int 171 ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask) 172 { 173 int s; 174 175 if (server.rm && !strcmp(server.rm, name)) { 176 if (chmod(server.rm, mask)) 177 LogPrintf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 178 return 0; 179 } 180 181 memset(&server.ifsun, '\0', sizeof server.ifsun); 182 server.ifsun.sun_len = strlen(name); 183 if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 184 LogPrintf(LogERROR, "Local: %s: Path too long\n", name); 185 return 2; 186 } 187 server.ifsun.sun_family = AF_LOCAL; 188 strcpy(server.ifsun.sun_path, name); 189 190 s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 191 if (s < 0) { 192 LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno)); 193 return 3; 194 } 195 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 196 if (mask != (mode_t)-1) 197 mask = umask(mask); 198 if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) { 199 if (mask != (mode_t)-1) 200 umask(mask); 201 LogPrintf(LogWARN, "Local: bind: %s\n", strerror(errno)); 202 close(s); 203 return 4; 204 } 205 if (mask != (mode_t)-1) 206 umask(mask); 207 if (listen(s, 5) != 0) { 208 LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 209 close(s); 210 ID0unlink(name); 211 return 5; 212 } 213 ServerClose(bundle); 214 server.fd = s; 215 server.rm = server.ifsun.sun_path; 216 LogPrintf(LogPHASE, "Listening at local socket %s.\n", name); 217 return 0; 218 } 219 220 int 221 ServerTcpOpen(struct bundle *bundle, int port) 222 { 223 struct sockaddr_in ifsin; 224 int s; 225 226 if (server.port == port) 227 return 0; 228 229 s = ID0socket(PF_INET, SOCK_STREAM, 0); 230 if (s < 0) { 231 LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 232 return 7; 233 } 234 memset(&ifsin, '\0', sizeof ifsin); 235 ifsin.sin_family = AF_INET; 236 ifsin.sin_addr.s_addr = INADDR_ANY; 237 ifsin.sin_port = htons(port); 238 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 239 if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 240 LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 241 close(s); 242 return 8; 243 } 244 if (listen(s, 5) != 0) { 245 LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n"); 246 close(s); 247 return 9; 248 } 249 ServerClose(bundle); 250 server.fd = s; 251 server.port = port; 252 LogPrintf(LogPHASE, "Listening at port %d.\n", port); 253 return 0; 254 } 255 256 int 257 ServerClose(struct bundle *bundle) 258 { 259 if (server.fd >= 0) { 260 close(server.fd); 261 if (server.rm) { 262 ID0unlink(server.rm); 263 server.rm = NULL; 264 } 265 server.fd = -1; 266 server.port = 0; 267 /* Drop associated prompts */ 268 bundle_DelPromptDescriptors(bundle, &server); 269 return 1; 270 } 271 return 0; 272 } 273