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 * $FreeBSD$ 27 */ 28 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <sys/un.h> 34 35 #include <errno.h> 36 #include <stdio.h> 37 #include <string.h> 38 #include <sys/stat.h> 39 #include <termios.h> 40 #include <unistd.h> 41 42 #include "log.h" 43 #include "descriptor.h" 44 #include "server.h" 45 #include "id.h" 46 #include "prompt.h" 47 48 static int 49 server_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 50 { 51 struct server *s = descriptor2server(d); 52 struct prompt *p; 53 int sets; 54 55 sets = 0; 56 if (r && s->fd >= 0) { 57 if (*n < s->fd + 1) 58 *n = s->fd + 1; 59 FD_SET(s->fd, r); 60 log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 61 sets++; 62 } 63 64 for (p = log_PromptList(); p; p = p->next) 65 sets += descriptor_UpdateSet(&p->desc, r, w, e, n); 66 67 return sets; 68 } 69 70 static int 71 server_IsSet(struct fdescriptor *d, const fd_set *fdset) 72 { 73 struct server *s = descriptor2server(d); 74 struct prompt *p; 75 76 if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) 77 return 1; 78 79 for (p = log_PromptList(); p; p = p->next) 80 if (descriptor_IsSet(&p->desc, fdset)) 81 return 1; 82 83 return 0; 84 } 85 86 #define IN_SIZE sizeof(struct sockaddr_in) 87 #define UN_SIZE sizeof(struct sockaddr_un) 88 #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE) 89 90 static void 91 server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 92 { 93 struct server *s = descriptor2server(d); 94 char hisaddr[ADDRSZ]; 95 struct sockaddr *sa = (struct sockaddr *)hisaddr; 96 struct sockaddr_in *in = (struct sockaddr_in *)hisaddr; 97 int ssize = ADDRSZ, wfd; 98 struct prompt *p; 99 100 if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { 101 wfd = accept(s->fd, sa, &ssize); 102 if (wfd < 0) 103 log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 104 } else 105 wfd = -1; 106 107 if (wfd >= 0) 108 switch (sa->sa_family) { 109 case AF_LOCAL: 110 log_Printf(LogPHASE, "Connected to local client.\n"); 111 break; 112 113 case AF_INET: 114 if (ntohs(in->sin_port) < 1024) { 115 log_Printf(LogALERT, "Rejected client connection from %s:%u" 116 "(invalid port number) !\n", 117 inet_ntoa(in->sin_addr), ntohs(in->sin_port)); 118 close(wfd); 119 wfd = -1; 120 break; 121 } 122 log_Printf(LogPHASE, "Connected to client from %s:%u\n", 123 inet_ntoa(in->sin_addr), in->sin_port); 124 break; 125 126 default: 127 write(wfd, "Unrecognised access !\n", 22); 128 close(wfd); 129 wfd = -1; 130 break; 131 } 132 133 if (wfd >= 0) { 134 if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 135 write(wfd, "Connection refused.\n", 20); 136 close(wfd); 137 } else { 138 switch (sa->sa_family) { 139 case AF_LOCAL: 140 p->src.type = "local"; 141 strncpy(p->src.from, s->rm, sizeof p->src.from - 1); 142 p->src.from[sizeof p->src.from - 1] = '\0'; 143 break; 144 case AF_INET: 145 p->src.type = "tcp"; 146 snprintf(p->src.from, sizeof p->src.from, "%s:%u", 147 inet_ntoa(in->sin_addr), in->sin_port); 148 break; 149 } 150 prompt_TtyCommandMode(p); 151 prompt_Required(p); 152 } 153 } 154 155 log_PromptListChanged = 0; 156 for (p = log_PromptList(); p; p = p->next) 157 if (descriptor_IsSet(&p->desc, fdset)) { 158 descriptor_Read(&p->desc, bundle, fdset); 159 if (log_PromptListChanged) 160 break; 161 } 162 } 163 164 static int 165 server_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 166 { 167 /* We never want to write here ! */ 168 log_Printf(LogALERT, "server_Write: Internal error: Bad call !\n"); 169 return 0; 170 } 171 172 struct server server = { 173 { 174 SERVER_DESCRIPTOR, 175 server_UpdateSet, 176 server_IsSet, 177 server_Read, 178 server_Write 179 }, 180 -1 181 }; 182 183 int 184 server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 185 { 186 int s; 187 188 if (server.rm && !strcmp(server.rm, name)) { 189 if (chmod(server.rm, 0777 & ~mask)) 190 log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno)); 191 return 0; 192 } 193 194 memset(&server.ifsun, '\0', sizeof server.ifsun); 195 server.ifsun.sun_len = strlen(name); 196 if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) { 197 log_Printf(LogERROR, "Local: %s: Path too long\n", name); 198 return 2; 199 } 200 server.ifsun.sun_family = AF_LOCAL; 201 strcpy(server.ifsun.sun_path, name); 202 203 s = ID0socket(PF_LOCAL, SOCK_STREAM, 0); 204 if (s < 0) { 205 log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 206 return 3; 207 } 208 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 209 if (mask != (mode_t)-1) 210 mask = umask(mask); 211 if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) { 212 if (mask != (mode_t)-1) 213 umask(mask); 214 log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 215 close(s); 216 return 4; 217 } 218 if (mask != (mode_t)-1) 219 umask(mask); 220 if (listen(s, 5) != 0) { 221 log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n"); 222 close(s); 223 ID0unlink(name); 224 return 5; 225 } 226 server_Close(bundle); 227 server.fd = s; 228 server.rm = server.ifsun.sun_path; 229 log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 230 return 0; 231 } 232 233 int 234 server_TcpOpen(struct bundle *bundle, int port) 235 { 236 struct sockaddr_in ifsin; 237 int s; 238 239 if (server.port == port) 240 return 0; 241 242 s = ID0socket(PF_INET, SOCK_STREAM, 0); 243 if (s < 0) { 244 log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 245 return 7; 246 } 247 memset(&ifsin, '\0', sizeof ifsin); 248 ifsin.sin_family = AF_INET; 249 ifsin.sin_addr.s_addr = INADDR_ANY; 250 ifsin.sin_port = htons(port); 251 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 252 if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) { 253 log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 254 close(s); 255 return 8; 256 } 257 if (listen(s, 5) != 0) { 258 log_Printf(LogERROR, "Tcp: Unable to listen to socket: %s\n", 259 strerror(errno)); 260 close(s); 261 return 9; 262 } 263 server_Close(bundle); 264 server.fd = s; 265 server.port = port; 266 log_Printf(LogPHASE, "Listening at port %d.\n", port); 267 return 0; 268 } 269 270 int 271 server_Close(struct bundle *bundle) 272 { 273 if (server.fd >= 0) { 274 if (server.rm) { 275 struct sockaddr_un un; 276 int sz = sizeof un; 277 278 if (getsockname(server.fd, (struct sockaddr *)&un, &sz) == 0 && 279 un.sun_family == AF_LOCAL && sz == sizeof un) 280 ID0unlink(un.sun_path); 281 server.rm = NULL; 282 } 283 close(server.fd); 284 server.fd = -1; 285 server.port = 0; 286 /* Drop associated prompts */ 287 log_DestroyPrompts(&server); 288 return 1; 289 } 290 return 0; 291 } 292