1 /* 2 * Copyright 2016 Jakub Klama <jceel@FreeBSD.org> 3 * All rights reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted providing 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 ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 * 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, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 * Copyright 2021 Joyent, Inc. 27 */ 28 29 #include <stdlib.h> 30 #include <errno.h> 31 #include <string.h> 32 #include <unistd.h> 33 #include <pthread.h> 34 #include <assert.h> 35 #include <sys/types.h> 36 #ifdef __APPLE__ 37 # include "../apple_endian.h" 38 #elif __illumos__ 39 # include <sys/param.h> 40 # include <port.h> 41 # include "../illumos_endian.h" 42 #else 43 # include <sys/endian.h> 44 #endif 45 #include <sys/socket.h> 46 #ifndef __illumos__ 47 # include <sys/event.h> 48 #endif 49 #include <sys/uio.h> 50 #include <netdb.h> 51 #include "../lib9p.h" 52 #include "../lib9p_impl.h" 53 #include "../log.h" 54 #include "socket.h" 55 56 struct l9p_socket_softc 57 { 58 struct l9p_connection *ls_conn; 59 struct sockaddr ls_sockaddr; 60 socklen_t ls_socklen; 61 pthread_t ls_thread; 62 int ls_fd; 63 }; 64 65 #ifdef __FreeBSD__ 66 struct event_svr { 67 struct kevent *ev_kev; 68 struct kevent *ev_event; 69 int ev_kq; 70 }; 71 #elif __illumos__ 72 struct event_svr { 73 port_event_t *ev_pe; 74 int ev_port; 75 }; 76 #else 77 #error "No event server defined" 78 #endif 79 80 static int l9p_init_event_svr(struct event_svr *, uint_t); 81 static uint_t l9p_get_server_addrs(const char *, const char *, 82 struct addrinfo **); 83 static uint_t l9p_bind_addrs(struct event_svr *, struct addrinfo *, uint_t, 84 int **); 85 static int l9p_event_get(struct l9p_server *, struct event_svr *, uint_t, 86 void (*cb)(struct l9p_server *, int)); 87 static int l9p_socket_readmsg(struct l9p_socket_softc *, void **, size_t *); 88 static int l9p_socket_get_response_buffer(struct l9p_request *, 89 struct iovec *, size_t *, void *); 90 static int l9p_socket_send_response(struct l9p_request *, const struct iovec *, 91 const size_t, const size_t, void *); 92 static void l9p_socket_drop_response(struct l9p_request *, const struct iovec *, 93 size_t, void *); 94 static void *l9p_socket_thread(void *); 95 static ssize_t xread(int, void *, size_t); 96 static ssize_t xwrite(int, void *, size_t); 97 98 int 99 l9p_start_server(struct l9p_server *server, const char *host, const char *port) 100 { 101 struct addrinfo *res = NULL; 102 int *sockets = NULL; 103 uint_t naddrs = 0; 104 uint_t nsockets = 0; 105 uint_t i; 106 struct event_svr esvr; 107 108 naddrs = l9p_get_server_addrs(host, port, &res); 109 if (naddrs == 0) 110 return (-1); 111 112 if (l9p_init_event_svr(&esvr, naddrs) != 0) { 113 freeaddrinfo(res); 114 return (-1); 115 } 116 117 nsockets = l9p_bind_addrs(&esvr, res, naddrs, &sockets); 118 119 /* 120 * We don't need res, after this, so free it and NULL it to prevent 121 * any possible use after free. 122 */ 123 freeaddrinfo(res); 124 res = NULL; 125 126 if (nsockets == 0) 127 goto fail; 128 129 for (;;) { 130 if (l9p_event_get(server, &esvr, nsockets, 131 l9p_socket_accept) < 0) 132 break; 133 } 134 135 /* We get here if something failed */ 136 for (i = 0; i < nsockets; i++) 137 close(sockets[i]); 138 139 fail: 140 free(sockets); 141 142 #ifdef __FreeBSD__ 143 close(esvr.ev_kq); 144 free(esvr.ev_kev); 145 free(esvr.ev_event); 146 #elif __illumos__ 147 close(esvr.ev_port); 148 free(esvr.ev_pe); 149 #else 150 #error "Port me" 151 #endif 152 153 return (-1); 154 } 155 156 static uint_t 157 l9p_get_server_addrs(const char *host, const char *port, struct addrinfo **resp) 158 { 159 struct addrinfo *res, hints; 160 uint_t naddrs; 161 int rc; 162 163 memset(&hints, 0, sizeof(hints)); 164 hints.ai_family = PF_UNSPEC; 165 hints.ai_socktype = SOCK_STREAM; 166 rc = getaddrinfo(host, port, &hints, resp); 167 if (rc > 0) { 168 L9P_LOG(L9P_ERROR, "getaddrinfo(): %s", gai_strerror(rc)); 169 return (0); 170 } 171 172 naddrs = 0; 173 for (res = *resp; res != NULL; res = res->ai_next) 174 naddrs++; 175 176 if (naddrs == 0) { 177 L9P_LOG(L9P_ERROR, "no addresses found for %s:%s", host, port); 178 } 179 180 return (naddrs); 181 } 182 183 #ifdef __FreeBSD__ 184 static int 185 l9p_init_event_svr(struct event_svr *svr, uint_t nsockets) 186 { 187 svr->ev_kev = calloc(nsockets, sizeof(struct kevent)); 188 if (svr->ev_kev == NULL) { 189 L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno)); 190 return (-1); 191 } 192 193 svr->ev_event = calloc(nsockets, sizeof(struct kevent)); 194 if (svr->ev_event == NULL) { 195 L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno)); 196 free(svr->ev_key); 197 svr->ev_key = NULL; 198 return (-1); 199 } 200 201 svr->ev_kq = kqueue(); 202 if (svr->ev_kq == -1) { 203 L9P_LOG(L9P_ERROR, "kqueue(): %s", strerror(errno)); 204 free(svr->ev_kev); 205 free(svr->ev_event); 206 svr->ev_kev = NULL; 207 svr->ev_event = NULL; 208 return (-1); 209 } 210 211 return (0); 212 } 213 #elif __illumos__ 214 static int 215 l9p_init_event_svr(struct event_svr *svr, uint_t nsockets) 216 { 217 svr->ev_pe = calloc(nsockets, sizeof(port_event_t)); 218 if (svr->ev_pe == NULL) { 219 L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno)); 220 return (-1); 221 } 222 223 svr->ev_port = port_create(); 224 if (svr->ev_port == -1) { 225 L9P_LOG(L9P_ERROR, "port_create(): %s", strerror(errno)); 226 return (-1); 227 } 228 229 return (0); 230 } 231 #else 232 #error "No event server defined" 233 #endif 234 235 static uint_t 236 l9p_bind_addrs(struct event_svr *svr, struct addrinfo *addrs, uint_t naddrs, 237 int **socketsp) 238 { 239 struct addrinfo *addr; 240 uint_t i, j; 241 242 *socketsp = calloc(naddrs, sizeof(int)); 243 if (*socketsp == NULL) { 244 L9P_LOG(L9P_ERROR, "calloc(): %s", strerror(errno)); 245 return (0); 246 } 247 248 for (i = 0, addr = addrs; addr != NULL; addr = addr->ai_next) { 249 int s; 250 int val = 1; 251 252 s = socket(addr->ai_family, addr->ai_socktype, 253 addr->ai_protocol); 254 if (s == -1) { 255 L9P_LOG(L9P_ERROR, "socket(): %s", strerror(errno)); 256 continue; 257 } 258 259 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &val, 260 sizeof(val)) < 0) { 261 L9P_LOG(L9P_ERROR, "setsockopt(): %s", strerror(errno)); 262 close(s); 263 continue; 264 } 265 266 if (bind(s, addr->ai_addr, addr->ai_addrlen) < 0) { 267 L9P_LOG(L9P_ERROR, "bind(): %s", strerror(errno)); 268 close(s); 269 continue; 270 } 271 272 if (listen(s, 10) < 0) { 273 L9P_LOG(L9P_ERROR, "listen(): %s", strerror(errno)); 274 close(s); 275 continue; 276 } 277 278 #ifdef __FreeBSD__ 279 EV_SET(&svr->ev_kev[i], s, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 280 0, 0); 281 #elif __illumos__ 282 if (port_associate(svr->ev_port, PORT_SOURCE_FD, s, 283 POLLIN|POLLHUP, NULL) < 0) { 284 L9P_LOG(L9P_ERROR, "port_associate(%d): %s", s, 285 strerror(errno)); 286 close(s); 287 continue; 288 } 289 #else 290 #error "Port me" 291 #endif 292 293 *socketsp[i++] = s; 294 } 295 296 if (i < 1) { 297 free(*socketsp); 298 *socketsp = NULL; 299 return (0); 300 } 301 302 for (j = i; j < naddrs; j++) 303 *socketsp[j++] = -1; 304 305 #ifdef __FreeBSD__ 306 if (kevent(svr->ev_kq, svr->ev_kev, i, NULL, 0, NULL) < 0) { 307 L9P_LOG(L9P_ERROR, "kevent(): %s", strerror(errno)); 308 309 for (j = 0; j < i; j++) 310 close(j); 311 312 free(*socketsp); 313 *socketsp = NULL; 314 315 return (0); 316 } 317 #endif 318 319 return (i); 320 } 321 322 #ifdef __FreeBSD__ 323 static int 324 l9p_event_get(struct l9p_server *l9svr, struct event_svr *esvr, uint_t nsockets, 325 void (*cb)(struct l9p_server *, int)) 326 { 327 int i, evs; 328 329 evs = kevent(esvr->ev_kq, NULL, 0, esvr->ev_event, nsockets, NULL); 330 if (evs < 0) { 331 if (errno == EINTR) 332 return (0); 333 L9P_LOG(L9P_ERROR, "kevent(): %s", strerror(errno)); 334 return (-1); 335 } 336 337 for (i = 0; i < evs; i++) 338 cb(l9svr, (int)sevr->ev_event[i].ident); 339 340 return (0); 341 } 342 #elif __illumos__ 343 static int 344 l9p_event_get(struct l9p_server *l9svr, struct event_svr *esvr, uint_t nsockets, 345 void (*cb)(struct l9p_server *, int)) 346 { 347 uint_t evs = 1; 348 int i; 349 350 if (port_getn(esvr->ev_port, esvr->ev_pe, nsockets, &evs, NULL) < 0) { 351 if (errno == EINTR) 352 return (0); 353 L9P_LOG(L9P_ERROR, "port_getn(): %s", strerror(errno)); 354 return (-1); 355 } 356 357 for (i = 0; i < evs; i++) { 358 if (esvr->ev_pe[i].portev_source != PORT_SOURCE_FD) 359 continue; 360 361 cb(l9svr, (int)esvr->ev_pe[i].portev_object); 362 } 363 364 return (0); 365 } 366 #else 367 #error "Port me" 368 #endif 369 370 void 371 l9p_socket_accept(struct l9p_server *server, int svr_fd) 372 { 373 struct l9p_socket_softc *sc; 374 struct l9p_connection *conn; 375 char host[NI_MAXHOST + 1]; 376 char serv[NI_MAXSERV + 1]; 377 struct sockaddr client_addr; 378 socklen_t client_addr_len = sizeof(client_addr); 379 int conn_fd, err; 380 381 conn_fd = accept(svr_fd, &client_addr, &client_addr_len); 382 if (conn_fd < 0) { 383 L9P_LOG(L9P_WARNING, "accept(): %s", strerror(errno)); 384 return; 385 } 386 387 err = getnameinfo(&client_addr, client_addr_len, host, NI_MAXHOST, 388 serv, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); 389 390 if (err != 0) { 391 L9P_LOG(L9P_WARNING, "cannot look up client name: %s", 392 gai_strerror(err)); 393 } else { 394 L9P_LOG(L9P_INFO, "new connection from %s:%s", host, serv); 395 } 396 397 if (l9p_connection_init(server, &conn) != 0) { 398 L9P_LOG(L9P_ERROR, "cannot create new connection"); 399 return; 400 } 401 402 sc = l9p_calloc(1, sizeof(*sc)); 403 sc->ls_conn = conn; 404 sc->ls_fd = conn_fd; 405 406 /* 407 * Fill in transport handler functions and aux argument. 408 */ 409 conn->lc_lt.lt_aux = sc; 410 conn->lc_lt.lt_get_response_buffer = l9p_socket_get_response_buffer; 411 conn->lc_lt.lt_send_response = l9p_socket_send_response; 412 conn->lc_lt.lt_drop_response = l9p_socket_drop_response; 413 414 err = pthread_create(&sc->ls_thread, NULL, l9p_socket_thread, sc); 415 if (err) { 416 L9P_LOG(L9P_ERROR, 417 "pthread_create (for connection from %s:%s): error %s", 418 host, serv, strerror(err)); 419 l9p_connection_close(sc->ls_conn); 420 free(sc); 421 } 422 } 423 424 static void * 425 l9p_socket_thread(void *arg) 426 { 427 struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg; 428 struct iovec iov; 429 void *buf; 430 size_t length; 431 432 for (;;) { 433 if (l9p_socket_readmsg(sc, &buf, &length) != 0) 434 break; 435 436 iov.iov_base = buf; 437 iov.iov_len = length; 438 l9p_connection_recv(sc->ls_conn, &iov, 1, NULL); 439 free(buf); 440 } 441 442 L9P_LOG(L9P_INFO, "connection closed"); 443 l9p_connection_close(sc->ls_conn); 444 free(sc); 445 return (NULL); 446 } 447 448 static int 449 l9p_socket_readmsg(struct l9p_socket_softc *sc, void **buf, size_t *size) 450 { 451 uint32_t msize; 452 size_t toread; 453 ssize_t ret; 454 void *buffer; 455 int fd = sc->ls_fd; 456 457 assert(fd > 0); 458 459 buffer = l9p_malloc(sizeof(uint32_t)); 460 461 ret = xread(fd, buffer, sizeof(uint32_t)); 462 if (ret < 0) { 463 L9P_LOG(L9P_ERROR, "read(): %s", strerror(errno)); 464 return (-1); 465 } 466 467 if (ret != sizeof(uint32_t)) { 468 if (ret == 0) { 469 L9P_LOG(L9P_DEBUG, "%p: EOF", (void *)sc->ls_conn); 470 } else { 471 L9P_LOG(L9P_ERROR, 472 "short read: %zd bytes of %zd expected", 473 ret, sizeof(uint32_t)); 474 } 475 return (-1); 476 } 477 478 msize = le32toh(*(uint32_t *)buffer); 479 toread = msize - sizeof(uint32_t); 480 buffer = l9p_realloc(buffer, msize); 481 482 ret = xread(fd, (char *)buffer + sizeof(uint32_t), toread); 483 if (ret < 0) { 484 L9P_LOG(L9P_ERROR, "read(): %s", strerror(errno)); 485 return (-1); 486 } 487 488 if (ret != (ssize_t)toread) { 489 L9P_LOG(L9P_ERROR, "short read: %zd bytes of %zd expected", 490 ret, toread); 491 return (-1); 492 } 493 494 *size = msize; 495 *buf = buffer; 496 L9P_LOG(L9P_INFO, "%p: read complete message, buf=%p size=%d", 497 (void *)sc->ls_conn, buffer, msize); 498 499 return (0); 500 } 501 502 static int 503 l9p_socket_get_response_buffer(struct l9p_request *req, struct iovec *iov, 504 size_t *niovp, void *arg __unused) 505 { 506 size_t size = req->lr_conn->lc_msize; 507 void *buf; 508 509 buf = l9p_malloc(size); 510 iov[0].iov_base = buf; 511 iov[0].iov_len = size; 512 513 *niovp = 1; 514 return (0); 515 } 516 517 static int 518 l9p_socket_send_response(struct l9p_request *req __unused, 519 const struct iovec *iov, const size_t niov __unused, const size_t iolen, 520 void *arg) 521 { 522 struct l9p_socket_softc *sc = (struct l9p_socket_softc *)arg; 523 524 assert(sc->ls_fd >= 0); 525 526 L9P_LOG(L9P_DEBUG, "%p: sending reply, buf=%p, size=%d", arg, 527 iov[0].iov_base, iolen); 528 529 if (xwrite(sc->ls_fd, iov[0].iov_base, iolen) != (int)iolen) { 530 L9P_LOG(L9P_ERROR, "short write: %s", strerror(errno)); 531 return (-1); 532 } 533 534 free(iov[0].iov_base); 535 return (0); 536 } 537 538 static void 539 l9p_socket_drop_response(struct l9p_request *req __unused, 540 const struct iovec *iov, size_t niov __unused, void *arg) 541 { 542 543 L9P_LOG(L9P_DEBUG, "%p: drop buf=%p", arg, iov[0].iov_base); 544 free(iov[0].iov_base); 545 } 546 547 static ssize_t 548 xread(int fd, void *buf, size_t count) 549 { 550 size_t done = 0; 551 ssize_t ret; 552 553 while (done < count) { 554 ret = read(fd, (char *)buf + done, count - done); 555 if (ret < 0) { 556 if (errno == EINTR) 557 continue; 558 559 return (-1); 560 } 561 562 if (ret == 0) 563 return ((ssize_t)done); 564 565 done += (size_t)ret; 566 } 567 568 return ((ssize_t)done); 569 } 570 571 static ssize_t 572 xwrite(int fd, void *buf, size_t count) 573 { 574 size_t done = 0; 575 ssize_t ret; 576 577 while (done < count) { 578 ret = write(fd, (char *)buf + done, count - done); 579 if (ret < 0) { 580 if (errno == EINTR) 581 continue; 582 583 return (-1); 584 } 585 586 if (ret == 0) 587 return ((ssize_t)done); 588 589 done += (size_t)ret; 590 } 591 592 return ((ssize_t)done); 593 } 594