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 * 2697d92980SPeter Wemm * $FreeBSD$ 2775240ed1SBrian Somers */ 2875240ed1SBrian Somers 2974457d3dSBrian Somers #include <sys/param.h> 3074457d3dSBrian Somers 314ef16f24SBrian Somers #include <sys/socket.h> 324ef16f24SBrian Somers #include <netinet/in.h> 331fa665f5SBrian Somers #include <sys/un.h> 3475240ed1SBrian Somers 354ef16f24SBrian Somers #include <errno.h> 366eafd353SBrian Somers #include <stdarg.h> 3775240ed1SBrian Somers #include <stdio.h> 3875240ed1SBrian Somers #include <string.h> 3975240ed1SBrian Somers #include <sys/stat.h> 4085b542cfSBrian Somers #include <termios.h> 414ef16f24SBrian Somers #include <unistd.h> 4275240ed1SBrian Somers 434ef16f24SBrian Somers #include "log.h" 4477ff88adSBrian Somers #include "descriptor.h" 454ef16f24SBrian Somers #include "server.h" 4685b542cfSBrian Somers #include "prompt.h" 4730949fd4SBrian Somers #include "ncpaddr.h" 481a2b4e4aSBrian Somers #include "probe.h" 494ef16f24SBrian Somers 5077ff88adSBrian Somers static int 51f013f33eSBrian Somers server_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 5277ff88adSBrian Somers { 5377ff88adSBrian Somers struct server *s = descriptor2server(d); 540f2f3eb3SBrian Somers struct prompt *p; 550f2f3eb3SBrian Somers int sets; 5675240ed1SBrian Somers 570f2f3eb3SBrian Somers sets = 0; 58b6dec9f0SBrian Somers if (r && s->fd >= 0) { 5977ff88adSBrian Somers if (*n < s->fd + 1) 6077ff88adSBrian Somers *n = s->fd + 1; 6185b542cfSBrian Somers FD_SET(s->fd, r); 6224989c68SBrian Somers log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 630f2f3eb3SBrian Somers sets++; 6477ff88adSBrian Somers } 650f2f3eb3SBrian Somers 660f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 670f2f3eb3SBrian Somers sets += descriptor_UpdateSet(&p->desc, r, w, e, n); 680f2f3eb3SBrian Somers 690f2f3eb3SBrian Somers return sets; 7077ff88adSBrian Somers } 7177ff88adSBrian Somers 7277ff88adSBrian Somers static int 73f013f33eSBrian Somers server_IsSet(struct fdescriptor *d, const fd_set *fdset) 7477ff88adSBrian Somers { 7577ff88adSBrian Somers struct server *s = descriptor2server(d); 760f2f3eb3SBrian Somers struct prompt *p; 770f2f3eb3SBrian Somers 780f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) 790f2f3eb3SBrian Somers return 1; 800f2f3eb3SBrian Somers 810f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 820f2f3eb3SBrian Somers if (descriptor_IsSet(&p->desc, fdset)) 830f2f3eb3SBrian Somers return 1; 840f2f3eb3SBrian Somers 850f2f3eb3SBrian Somers return 0; 8677ff88adSBrian Somers } 8777ff88adSBrian Somers 8877ff88adSBrian Somers static void 89f013f33eSBrian Somers server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 9077ff88adSBrian Somers { 9177ff88adSBrian Somers struct server *s = descriptor2server(d); 9230949fd4SBrian Somers struct sockaddr_storage ss; 9330949fd4SBrian Somers struct sockaddr *sa = (struct sockaddr *)&ss; 9430949fd4SBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 9530949fd4SBrian Somers #ifndef NOINET6 9630949fd4SBrian Somers struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 9730949fd4SBrian Somers #endif 9830949fd4SBrian Somers int ssize = sizeof ss, wfd; 99b6217683SBrian Somers struct prompt *p; 10030949fd4SBrian Somers struct ncpaddr addr; 10177ff88adSBrian Somers 1020f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { 10377ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 1040f2f3eb3SBrian Somers if (wfd < 0) 105dd7e2610SBrian Somers log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 1066d110b1bSBrian Somers else if (sa->sa_len == 0) { 1076d110b1bSBrian Somers close(wfd); 1086d110b1bSBrian Somers wfd = -1; 1096d110b1bSBrian Somers } 1100f2f3eb3SBrian Somers } else 1110f2f3eb3SBrian Somers wfd = -1; 11277ff88adSBrian Somers 1130f2f3eb3SBrian Somers if (wfd >= 0) 11477ff88adSBrian Somers switch (sa->sa_family) { 11577ff88adSBrian Somers case AF_LOCAL: 116dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to local client.\n"); 11777ff88adSBrian Somers break; 11877ff88adSBrian Somers 11977ff88adSBrian Somers case AF_INET: 12030949fd4SBrian Somers ncpaddr_setsa(&addr, sa); 12130949fd4SBrian Somers if (ntohs(sin->sin_port) < 1024) { 122dd7e2610SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 12377ff88adSBrian Somers "(invalid port number) !\n", 12430949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 12577ff88adSBrian Somers close(wfd); 1260f2f3eb3SBrian Somers wfd = -1; 1270f2f3eb3SBrian Somers break; 12877ff88adSBrian Somers } 129dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 13030949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 13177ff88adSBrian Somers break; 13277ff88adSBrian Somers 13330949fd4SBrian Somers #ifndef NOINET6 13430949fd4SBrian Somers case AF_INET6: 13530949fd4SBrian Somers ncpaddr_setsa(&addr, sa); 13630949fd4SBrian Somers if (ntohs(sin6->sin6_port) < 1024) { 13730949fd4SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 13830949fd4SBrian Somers "(invalid port number) !\n", 13930949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 14030949fd4SBrian Somers close(wfd); 14130949fd4SBrian Somers wfd = -1; 14230949fd4SBrian Somers break; 14330949fd4SBrian Somers } 14430949fd4SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 14530949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 14630949fd4SBrian Somers break; 14730949fd4SBrian Somers #endif 14830949fd4SBrian Somers 14977ff88adSBrian Somers default: 15077ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 15177ff88adSBrian Somers close(wfd); 1520f2f3eb3SBrian Somers wfd = -1; 1530f2f3eb3SBrian Somers break; 15477ff88adSBrian Somers } 15577ff88adSBrian Somers 1560f2f3eb3SBrian Somers if (wfd >= 0) { 157b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 158b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 15977ff88adSBrian Somers close(wfd); 16077ff88adSBrian Somers } else { 161b6217683SBrian Somers switch (sa->sa_family) { 162b6217683SBrian Somers case AF_LOCAL: 163565e35e5SBrian Somers p->src.type = "local"; 16474457d3dSBrian Somers strncpy(p->src.from, s->cfg.sockname, sizeof p->src.from - 1); 165565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 166b6217683SBrian Somers break; 167b6217683SBrian Somers case AF_INET: 16830949fd4SBrian Somers p->src.type = "ip"; 169565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 17030949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 171b6217683SBrian Somers break; 17230949fd4SBrian Somers #ifndef NOINET6 17330949fd4SBrian Somers case AF_INET6: 17430949fd4SBrian Somers p->src.type = "ip6"; 17530949fd4SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 17630949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 17730949fd4SBrian Somers break; 17830949fd4SBrian Somers #endif 179b6217683SBrian Somers } 180b6217683SBrian Somers prompt_TtyCommandMode(p); 181b6217683SBrian Somers prompt_Required(p); 18277ff88adSBrian Somers } 18377ff88adSBrian Somers } 18477ff88adSBrian Somers 1850bdcbcbeSBrian Somers log_PromptListChanged = 0; 1860f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 1870bdcbcbeSBrian Somers if (descriptor_IsSet(&p->desc, fdset)) { 1880f2f3eb3SBrian Somers descriptor_Read(&p->desc, bundle, fdset); 1890bdcbcbeSBrian Somers if (log_PromptListChanged) 1900bdcbcbeSBrian Somers break; 1910bdcbcbeSBrian Somers } 1920f2f3eb3SBrian Somers } 1930f2f3eb3SBrian Somers 1941af29a6eSBrian Somers static int 195057f1760SBrian Somers server_Write(struct fdescriptor *d __unused, struct bundle *bundle __unused, 196057f1760SBrian Somers const fd_set *fdset __unused) 19777ff88adSBrian Somers { 19877ff88adSBrian Somers /* We never want to write here ! */ 199a33b2ef7SBrian Somers log_Printf(LogALERT, "server_Write: Internal error: Bad call !\n"); 2001af29a6eSBrian Somers return 0; 20177ff88adSBrian Somers } 20277ff88adSBrian Somers 20377ff88adSBrian Somers struct server server = { 20477ff88adSBrian Somers { 20577ff88adSBrian Somers SERVER_DESCRIPTOR, 20677ff88adSBrian Somers server_UpdateSet, 20777ff88adSBrian Somers server_IsSet, 20877ff88adSBrian Somers server_Read, 20977ff88adSBrian Somers server_Write 21077ff88adSBrian Somers }, 211057f1760SBrian Somers -1, 212057f1760SBrian Somers { "", "", 0, 0 } 21377ff88adSBrian Somers }; 2144ef16f24SBrian Somers 21574457d3dSBrian Somers enum server_stat 21674457d3dSBrian Somers server_Reopen(struct bundle *bundle) 21774457d3dSBrian Somers { 21874457d3dSBrian Somers char name[sizeof server.cfg.sockname]; 21937b8a5c7SBrian Somers struct stat st; 22074457d3dSBrian Somers u_short port; 22174457d3dSBrian Somers mode_t mask; 22274457d3dSBrian Somers enum server_stat ret; 22374457d3dSBrian Somers 22474457d3dSBrian Somers if (server.cfg.sockname[0] != '\0') { 22574457d3dSBrian Somers strcpy(name, server.cfg.sockname); 22674457d3dSBrian Somers mask = server.cfg.mask; 22774457d3dSBrian Somers server_Close(bundle); 22837b8a5c7SBrian Somers if (server.cfg.sockname[0] != '\0' && stat(server.cfg.sockname, &st) == 0) 22937b8a5c7SBrian Somers if (!(st.st_mode & S_IFSOCK) || unlink(server.cfg.sockname) != 0) 23037b8a5c7SBrian Somers return SERVER_FAILED; 23174457d3dSBrian Somers ret = server_LocalOpen(bundle, name, mask); 23274457d3dSBrian Somers } else if (server.cfg.port != 0) { 23374457d3dSBrian Somers port = server.cfg.port; 23474457d3dSBrian Somers server_Close(bundle); 23574457d3dSBrian Somers ret = server_TcpOpen(bundle, port); 23674457d3dSBrian Somers } else 23774457d3dSBrian Somers ret = SERVER_UNSET; 23874457d3dSBrian Somers 23974457d3dSBrian Somers return ret; 24074457d3dSBrian Somers } 24174457d3dSBrian Somers 24274457d3dSBrian Somers enum server_stat 243dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 2444ef16f24SBrian Somers { 24574457d3dSBrian Somers struct sockaddr_un ifsun; 24674457d3dSBrian Somers mode_t oldmask; 2474ef16f24SBrian Somers int s; 2484ef16f24SBrian Somers 24974457d3dSBrian Somers oldmask = (mode_t)-1; /* Silence compiler */ 250683cef3cSBrian Somers 251*9304cfd0SDimitry Andric if (server.cfg.sockname[0] != '\0' && !strcmp(server.cfg.sockname, name)) 25274457d3dSBrian Somers server_Close(bundle); 25374457d3dSBrian Somers 25474457d3dSBrian Somers memset(&ifsun, '\0', sizeof ifsun); 25574457d3dSBrian Somers ifsun.sun_len = strlen(name); 25674457d3dSBrian Somers if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 257dd7e2610SBrian Somers log_Printf(LogERROR, "Local: %s: Path too long\n", name); 25874457d3dSBrian Somers return SERVER_INVALID; 2594ef16f24SBrian Somers } 26074457d3dSBrian Somers ifsun.sun_family = AF_LOCAL; 26174457d3dSBrian Somers strcpy(ifsun.sun_path, name); 2624ef16f24SBrian Somers 26363c6cac9SBrian Somers s = socket(PF_LOCAL, SOCK_STREAM, 0); 2644ef16f24SBrian Somers if (s < 0) { 265dd7e2610SBrian Somers log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 26674457d3dSBrian Somers goto failed; 2674ef16f24SBrian Somers } 2684ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2698ea8442cSBrian Somers if (mask != (mode_t)-1) 27074457d3dSBrian Somers oldmask = umask(mask); 27174457d3dSBrian Somers if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) { 2728ea8442cSBrian Somers if (mask != (mode_t)-1) 27374457d3dSBrian Somers umask(oldmask); 274dd7e2610SBrian Somers log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2754ef16f24SBrian Somers close(s); 27674457d3dSBrian Somers goto failed; 2774ef16f24SBrian Somers } 2788ea8442cSBrian Somers if (mask != (mode_t)-1) 27974457d3dSBrian Somers umask(oldmask); 2804ef16f24SBrian Somers if (listen(s, 5) != 0) { 2819b996792SBrian Somers log_Printf(LogERROR, "Local: Unable to listen to socket -" 2829b996792SBrian Somers " BUNDLE overload?\n"); 2834ef16f24SBrian Somers close(s); 28474457d3dSBrian Somers unlink(name); 28574457d3dSBrian Somers goto failed; 2864ef16f24SBrian Somers } 287661a0e90SBrian Somers server_Close(bundle); 28877ff88adSBrian Somers server.fd = s; 28974457d3dSBrian Somers server.cfg.port = 0; 29074457d3dSBrian Somers strncpy(server.cfg.sockname, ifsun.sun_path, sizeof server.cfg.sockname - 1); 29174457d3dSBrian Somers server.cfg.sockname[sizeof server.cfg.sockname - 1] = '\0'; 29274457d3dSBrian Somers server.cfg.mask = mask; 293dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 29474457d3dSBrian Somers 29574457d3dSBrian Somers return SERVER_OK; 29674457d3dSBrian Somers 29774457d3dSBrian Somers failed: 29874457d3dSBrian Somers if (server.fd == -1) { 29974457d3dSBrian Somers server.fd = -1; 30074457d3dSBrian Somers server.cfg.port = 0; 30174457d3dSBrian Somers strncpy(server.cfg.sockname, ifsun.sun_path, 30274457d3dSBrian Somers sizeof server.cfg.sockname - 1); 30374457d3dSBrian Somers server.cfg.sockname[sizeof server.cfg.sockname - 1] = '\0'; 30474457d3dSBrian Somers server.cfg.mask = mask; 30574457d3dSBrian Somers } 30674457d3dSBrian Somers return SERVER_FAILED; 3074ef16f24SBrian Somers } 3084ef16f24SBrian Somers 30974457d3dSBrian Somers enum server_stat 31074457d3dSBrian Somers server_TcpOpen(struct bundle *bundle, u_short port) 3114ef16f24SBrian Somers { 31230949fd4SBrian Somers struct sockaddr_storage ss; 31330949fd4SBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 3141a2b4e4aSBrian Somers #ifndef NOINET6 31530949fd4SBrian Somers struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 31630949fd4SBrian Somers #endif 31730949fd4SBrian Somers int s, sz; 3184ef16f24SBrian Somers 31974457d3dSBrian Somers if (server.cfg.port == port) 32074457d3dSBrian Somers server_Close(bundle); 321d40f8a5aSBrian Somers 32274457d3dSBrian Somers if (port == 0) 32374457d3dSBrian Somers return SERVER_INVALID; 32474457d3dSBrian Somers 32530949fd4SBrian Somers memset(&ss, '\0', sizeof ss); 3261a2b4e4aSBrian Somers #ifndef NOINET6 3271a2b4e4aSBrian Somers if (probe.ipv6_available) { 3281a2b4e4aSBrian Somers sin6->sin6_family = AF_INET6; 3291a2b4e4aSBrian Somers sin6->sin6_port = htons(port); 330260799afSBrian Somers sin6->sin6_len = (u_int8_t)sizeof ss; 3311a2b4e4aSBrian Somers sz = sizeof *sin6; 33263c6cac9SBrian Somers s = socket(PF_INET6, SOCK_STREAM, 0); 3331a2b4e4aSBrian Somers } else 3341a2b4e4aSBrian Somers #endif 3351a2b4e4aSBrian Somers { 33630949fd4SBrian Somers sin->sin_family = AF_INET; 33730949fd4SBrian Somers sin->sin_port = htons(port); 338260799afSBrian Somers sin->sin_len = (u_int8_t)sizeof ss; 33930949fd4SBrian Somers sin->sin_addr.s_addr = INADDR_ANY; 34030949fd4SBrian Somers sz = sizeof *sin; 34163c6cac9SBrian Somers s = socket(PF_INET, SOCK_STREAM, 0); 3421a2b4e4aSBrian Somers } 3431a2b4e4aSBrian Somers 3444ef16f24SBrian Somers if (s < 0) { 345dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 34674457d3dSBrian Somers goto failed; 3474ef16f24SBrian Somers } 34830949fd4SBrian Somers 349bba6dc1dSHajimu UMEMOTO #ifndef NOINET6 350bba6dc1dSHajimu UMEMOTO if (probe.ipv6_available) { 351bba6dc1dSHajimu UMEMOTO int off = 0; 352bba6dc1dSHajimu UMEMOTO setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&off, sizeof(off)); 353bba6dc1dSHajimu UMEMOTO } 354bba6dc1dSHajimu UMEMOTO #endif 355bba6dc1dSHajimu UMEMOTO 3564ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 35730949fd4SBrian Somers if (bind(s, (struct sockaddr *)&ss, sz) < 0) { 358dd7e2610SBrian Somers log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 3594ef16f24SBrian Somers close(s); 36074457d3dSBrian Somers goto failed; 3614ef16f24SBrian Somers } 3624ef16f24SBrian Somers if (listen(s, 5) != 0) { 363661a0e90SBrian Somers log_Printf(LogERROR, "Tcp: Unable to listen to socket: %s\n", 364661a0e90SBrian Somers strerror(errno)); 3654ef16f24SBrian Somers close(s); 36674457d3dSBrian Somers goto failed; 3674ef16f24SBrian Somers } 368dd7e2610SBrian Somers server_Close(bundle); 36977ff88adSBrian Somers server.fd = s; 37074457d3dSBrian Somers server.cfg.port = port; 37174457d3dSBrian Somers *server.cfg.sockname = '\0'; 37274457d3dSBrian Somers server.cfg.mask = 0; 373dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at port %d.\n", port); 37474457d3dSBrian Somers return SERVER_OK; 37574457d3dSBrian Somers 37674457d3dSBrian Somers failed: 37774457d3dSBrian Somers if (server.fd == -1) { 37874457d3dSBrian Somers server.fd = -1; 37974457d3dSBrian Somers server.cfg.port = port; 38074457d3dSBrian Somers *server.cfg.sockname = '\0'; 38174457d3dSBrian Somers server.cfg.mask = 0; 38274457d3dSBrian Somers } 38374457d3dSBrian Somers return SERVER_FAILED; 3844ef16f24SBrian Somers } 3854ef16f24SBrian Somers 38677ff88adSBrian Somers int 387057f1760SBrian Somers server_Close(struct bundle *bundle __unused) 3884ef16f24SBrian Somers { 38977ff88adSBrian Somers if (server.fd >= 0) { 39074457d3dSBrian Somers if (*server.cfg.sockname != '\0') { 391661a0e90SBrian Somers struct sockaddr_un un; 392661a0e90SBrian Somers int sz = sizeof un; 393661a0e90SBrian Somers 394661a0e90SBrian Somers if (getsockname(server.fd, (struct sockaddr *)&un, &sz) == 0 && 395661a0e90SBrian Somers un.sun_family == AF_LOCAL && sz == sizeof un) 39674457d3dSBrian Somers unlink(un.sun_path); 3974ef16f24SBrian Somers } 398661a0e90SBrian Somers close(server.fd); 39977ff88adSBrian Somers server.fd = -1; 400b6217683SBrian Somers /* Drop associated prompts */ 4010f2f3eb3SBrian Somers log_DestroyPrompts(&server); 40274457d3dSBrian Somers 40377ff88adSBrian Somers return 1; 4044ef16f24SBrian Somers } 40574457d3dSBrian Somers 40677ff88adSBrian Somers return 0; 4074ef16f24SBrian Somers } 40874457d3dSBrian Somers 40974457d3dSBrian Somers int 41074457d3dSBrian Somers server_Clear(struct bundle *bundle) 41174457d3dSBrian Somers { 41274457d3dSBrian Somers int ret; 41374457d3dSBrian Somers 41474457d3dSBrian Somers ret = server_Close(bundle); 41574457d3dSBrian Somers 41674457d3dSBrian Somers server.fd = -1; 41774457d3dSBrian Somers server.cfg.port = 0; 41874457d3dSBrian Somers *server.cfg.sockname = '\0'; 41974457d3dSBrian Somers server.cfg.mask = 0; 42074457d3dSBrian Somers 42174457d3dSBrian Somers return ret; 42274457d3dSBrian Somers } 423