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> 334ef16f24SBrian Somers #include <arpa/inet.h> 341fa665f5SBrian Somers #include <sys/un.h> 3575240ed1SBrian Somers 364ef16f24SBrian Somers #include <errno.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" 465106c671SBrian Somers #include "id.h" 4785b542cfSBrian Somers #include "prompt.h" 4830949fd4SBrian Somers #include "ncpaddr.h" 491a2b4e4aSBrian Somers #include "probe.h" 504ef16f24SBrian Somers 5177ff88adSBrian Somers static int 52f013f33eSBrian Somers server_UpdateSet(struct fdescriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n) 5377ff88adSBrian Somers { 5477ff88adSBrian Somers struct server *s = descriptor2server(d); 550f2f3eb3SBrian Somers struct prompt *p; 560f2f3eb3SBrian Somers int sets; 5775240ed1SBrian Somers 580f2f3eb3SBrian Somers sets = 0; 59b6dec9f0SBrian Somers if (r && s->fd >= 0) { 6077ff88adSBrian Somers if (*n < s->fd + 1) 6177ff88adSBrian Somers *n = s->fd + 1; 6285b542cfSBrian Somers FD_SET(s->fd, r); 6324989c68SBrian Somers log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd); 640f2f3eb3SBrian Somers sets++; 6577ff88adSBrian Somers } 660f2f3eb3SBrian Somers 670f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 680f2f3eb3SBrian Somers sets += descriptor_UpdateSet(&p->desc, r, w, e, n); 690f2f3eb3SBrian Somers 700f2f3eb3SBrian Somers return sets; 7177ff88adSBrian Somers } 7277ff88adSBrian Somers 7377ff88adSBrian Somers static int 74f013f33eSBrian Somers server_IsSet(struct fdescriptor *d, const fd_set *fdset) 7577ff88adSBrian Somers { 7677ff88adSBrian Somers struct server *s = descriptor2server(d); 770f2f3eb3SBrian Somers struct prompt *p; 780f2f3eb3SBrian Somers 790f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) 800f2f3eb3SBrian Somers return 1; 810f2f3eb3SBrian Somers 820f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 830f2f3eb3SBrian Somers if (descriptor_IsSet(&p->desc, fdset)) 840f2f3eb3SBrian Somers return 1; 850f2f3eb3SBrian Somers 860f2f3eb3SBrian Somers return 0; 8777ff88adSBrian Somers } 8877ff88adSBrian Somers 8977ff88adSBrian Somers static void 90f013f33eSBrian Somers server_Read(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 9177ff88adSBrian Somers { 9277ff88adSBrian Somers struct server *s = descriptor2server(d); 9330949fd4SBrian Somers struct sockaddr_storage ss; 9430949fd4SBrian Somers struct sockaddr *sa = (struct sockaddr *)&ss; 9530949fd4SBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 9630949fd4SBrian Somers #ifndef NOINET6 9730949fd4SBrian Somers struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 9830949fd4SBrian Somers #endif 9930949fd4SBrian Somers int ssize = sizeof ss, wfd; 100b6217683SBrian Somers struct prompt *p; 10130949fd4SBrian Somers struct ncpaddr addr; 10277ff88adSBrian Somers 1030f2f3eb3SBrian Somers if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) { 10477ff88adSBrian Somers wfd = accept(s->fd, sa, &ssize); 1050f2f3eb3SBrian Somers if (wfd < 0) 106dd7e2610SBrian Somers log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno)); 1076d110b1bSBrian Somers else if (sa->sa_len == 0) { 1086d110b1bSBrian Somers close(wfd); 1096d110b1bSBrian Somers wfd = -1; 1106d110b1bSBrian Somers } 1110f2f3eb3SBrian Somers } else 1120f2f3eb3SBrian Somers wfd = -1; 11377ff88adSBrian Somers 1140f2f3eb3SBrian Somers if (wfd >= 0) 11577ff88adSBrian Somers switch (sa->sa_family) { 11677ff88adSBrian Somers case AF_LOCAL: 117dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to local client.\n"); 11877ff88adSBrian Somers break; 11977ff88adSBrian Somers 12077ff88adSBrian Somers case AF_INET: 12130949fd4SBrian Somers ncpaddr_setsa(&addr, sa); 12230949fd4SBrian Somers if (ntohs(sin->sin_port) < 1024) { 123dd7e2610SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 12477ff88adSBrian Somers "(invalid port number) !\n", 12530949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 12677ff88adSBrian Somers close(wfd); 1270f2f3eb3SBrian Somers wfd = -1; 1280f2f3eb3SBrian Somers break; 12977ff88adSBrian Somers } 130dd7e2610SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 13130949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 13277ff88adSBrian Somers break; 13377ff88adSBrian Somers 13430949fd4SBrian Somers #ifndef NOINET6 13530949fd4SBrian Somers case AF_INET6: 13630949fd4SBrian Somers ncpaddr_setsa(&addr, sa); 13730949fd4SBrian Somers if (ntohs(sin6->sin6_port) < 1024) { 13830949fd4SBrian Somers log_Printf(LogALERT, "Rejected client connection from %s:%u" 13930949fd4SBrian Somers "(invalid port number) !\n", 14030949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 14130949fd4SBrian Somers close(wfd); 14230949fd4SBrian Somers wfd = -1; 14330949fd4SBrian Somers break; 14430949fd4SBrian Somers } 14530949fd4SBrian Somers log_Printf(LogPHASE, "Connected to client from %s:%u\n", 14630949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 14730949fd4SBrian Somers break; 14830949fd4SBrian Somers #endif 14930949fd4SBrian Somers 15077ff88adSBrian Somers default: 15177ff88adSBrian Somers write(wfd, "Unrecognised access !\n", 22); 15277ff88adSBrian Somers close(wfd); 1530f2f3eb3SBrian Somers wfd = -1; 1540f2f3eb3SBrian Somers break; 15577ff88adSBrian Somers } 15677ff88adSBrian Somers 1570f2f3eb3SBrian Somers if (wfd >= 0) { 158b6217683SBrian Somers if ((p = prompt_Create(s, bundle, wfd)) == NULL) { 159b6217683SBrian Somers write(wfd, "Connection refused.\n", 20); 16077ff88adSBrian Somers close(wfd); 16177ff88adSBrian Somers } else { 162b6217683SBrian Somers switch (sa->sa_family) { 163b6217683SBrian Somers case AF_LOCAL: 164565e35e5SBrian Somers p->src.type = "local"; 16574457d3dSBrian Somers strncpy(p->src.from, s->cfg.sockname, sizeof p->src.from - 1); 166565e35e5SBrian Somers p->src.from[sizeof p->src.from - 1] = '\0'; 167b6217683SBrian Somers break; 168b6217683SBrian Somers case AF_INET: 16930949fd4SBrian Somers p->src.type = "ip"; 170565e35e5SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 17130949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin->sin_port)); 172b6217683SBrian Somers break; 17330949fd4SBrian Somers #ifndef NOINET6 17430949fd4SBrian Somers case AF_INET6: 17530949fd4SBrian Somers p->src.type = "ip6"; 17630949fd4SBrian Somers snprintf(p->src.from, sizeof p->src.from, "%s:%u", 17730949fd4SBrian Somers ncpaddr_ntoa(&addr), ntohs(sin6->sin6_port)); 17830949fd4SBrian Somers break; 17930949fd4SBrian Somers #endif 180b6217683SBrian Somers } 181b6217683SBrian Somers prompt_TtyCommandMode(p); 182b6217683SBrian Somers prompt_Required(p); 18377ff88adSBrian Somers } 18477ff88adSBrian Somers } 18577ff88adSBrian Somers 1860bdcbcbeSBrian Somers log_PromptListChanged = 0; 1870f2f3eb3SBrian Somers for (p = log_PromptList(); p; p = p->next) 1880bdcbcbeSBrian Somers if (descriptor_IsSet(&p->desc, fdset)) { 1890f2f3eb3SBrian Somers descriptor_Read(&p->desc, bundle, fdset); 1900bdcbcbeSBrian Somers if (log_PromptListChanged) 1910bdcbcbeSBrian Somers break; 1920bdcbcbeSBrian Somers } 1930f2f3eb3SBrian Somers } 1940f2f3eb3SBrian Somers 1951af29a6eSBrian Somers static int 196f013f33eSBrian Somers server_Write(struct fdescriptor *d, struct bundle *bundle, const fd_set *fdset) 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 }, 21177ff88adSBrian Somers -1 21277ff88adSBrian Somers }; 2134ef16f24SBrian Somers 21474457d3dSBrian Somers enum server_stat 21574457d3dSBrian Somers server_Reopen(struct bundle *bundle) 21674457d3dSBrian Somers { 21774457d3dSBrian Somers char name[sizeof server.cfg.sockname]; 21837b8a5c7SBrian Somers struct stat st; 21974457d3dSBrian Somers u_short port; 22074457d3dSBrian Somers mode_t mask; 22174457d3dSBrian Somers enum server_stat ret; 22274457d3dSBrian Somers 22374457d3dSBrian Somers if (server.cfg.sockname[0] != '\0') { 22474457d3dSBrian Somers strcpy(name, server.cfg.sockname); 22574457d3dSBrian Somers mask = server.cfg.mask; 22674457d3dSBrian Somers server_Close(bundle); 22737b8a5c7SBrian Somers if (server.cfg.sockname[0] != '\0' && stat(server.cfg.sockname, &st) == 0) 22837b8a5c7SBrian Somers if (!(st.st_mode & S_IFSOCK) || unlink(server.cfg.sockname) != 0) 22937b8a5c7SBrian Somers return SERVER_FAILED; 23074457d3dSBrian Somers ret = server_LocalOpen(bundle, name, mask); 23174457d3dSBrian Somers } else if (server.cfg.port != 0) { 23274457d3dSBrian Somers port = server.cfg.port; 23374457d3dSBrian Somers server_Close(bundle); 23474457d3dSBrian Somers ret = server_TcpOpen(bundle, port); 23574457d3dSBrian Somers } else 23674457d3dSBrian Somers ret = SERVER_UNSET; 23774457d3dSBrian Somers 23874457d3dSBrian Somers return ret; 23974457d3dSBrian Somers } 24074457d3dSBrian Somers 24174457d3dSBrian Somers enum server_stat 242dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask) 2434ef16f24SBrian Somers { 24474457d3dSBrian Somers struct sockaddr_un ifsun; 24574457d3dSBrian Somers mode_t oldmask; 2464ef16f24SBrian Somers int s; 2474ef16f24SBrian Somers 24874457d3dSBrian Somers oldmask = (mode_t)-1; /* Silence compiler */ 249683cef3cSBrian Somers 25074457d3dSBrian Somers if (server.cfg.sockname && !strcmp(server.cfg.sockname, name)) 25174457d3dSBrian Somers server_Close(bundle); 25274457d3dSBrian Somers 25374457d3dSBrian Somers memset(&ifsun, '\0', sizeof ifsun); 25474457d3dSBrian Somers ifsun.sun_len = strlen(name); 25574457d3dSBrian Somers if (ifsun.sun_len > sizeof ifsun.sun_path - 1) { 256dd7e2610SBrian Somers log_Printf(LogERROR, "Local: %s: Path too long\n", name); 25774457d3dSBrian Somers return SERVER_INVALID; 2584ef16f24SBrian Somers } 25974457d3dSBrian Somers ifsun.sun_family = AF_LOCAL; 26074457d3dSBrian Somers strcpy(ifsun.sun_path, name); 2614ef16f24SBrian Somers 26274457d3dSBrian Somers s = socket(PF_LOCAL, SOCK_STREAM, 0); 2634ef16f24SBrian Somers if (s < 0) { 264dd7e2610SBrian Somers log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno)); 26574457d3dSBrian Somers goto failed; 2664ef16f24SBrian Somers } 2674ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 2688ea8442cSBrian Somers if (mask != (mode_t)-1) 26974457d3dSBrian Somers oldmask = umask(mask); 27074457d3dSBrian Somers if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) { 2718ea8442cSBrian Somers if (mask != (mode_t)-1) 27274457d3dSBrian Somers umask(oldmask); 273dd7e2610SBrian Somers log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno)); 2744ef16f24SBrian Somers close(s); 27574457d3dSBrian Somers goto failed; 2764ef16f24SBrian Somers } 2778ea8442cSBrian Somers if (mask != (mode_t)-1) 27874457d3dSBrian Somers umask(oldmask); 2794ef16f24SBrian Somers if (listen(s, 5) != 0) { 2809b996792SBrian Somers log_Printf(LogERROR, "Local: Unable to listen to socket -" 2819b996792SBrian Somers " BUNDLE overload?\n"); 2824ef16f24SBrian Somers close(s); 28374457d3dSBrian Somers unlink(name); 28474457d3dSBrian Somers goto failed; 2854ef16f24SBrian Somers } 286661a0e90SBrian Somers server_Close(bundle); 28777ff88adSBrian Somers server.fd = s; 28874457d3dSBrian Somers server.cfg.port = 0; 28974457d3dSBrian Somers strncpy(server.cfg.sockname, ifsun.sun_path, sizeof server.cfg.sockname - 1); 29074457d3dSBrian Somers server.cfg.sockname[sizeof server.cfg.sockname - 1] = '\0'; 29174457d3dSBrian Somers server.cfg.mask = mask; 292dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at local socket %s.\n", name); 29374457d3dSBrian Somers 29474457d3dSBrian Somers return SERVER_OK; 29574457d3dSBrian Somers 29674457d3dSBrian Somers failed: 29774457d3dSBrian Somers if (server.fd == -1) { 29874457d3dSBrian Somers server.fd = -1; 29974457d3dSBrian Somers server.cfg.port = 0; 30074457d3dSBrian Somers strncpy(server.cfg.sockname, ifsun.sun_path, 30174457d3dSBrian Somers sizeof server.cfg.sockname - 1); 30274457d3dSBrian Somers server.cfg.sockname[sizeof server.cfg.sockname - 1] = '\0'; 30374457d3dSBrian Somers server.cfg.mask = mask; 30474457d3dSBrian Somers } 30574457d3dSBrian Somers return SERVER_FAILED; 3064ef16f24SBrian Somers } 3074ef16f24SBrian Somers 30874457d3dSBrian Somers enum server_stat 30974457d3dSBrian Somers server_TcpOpen(struct bundle *bundle, u_short port) 3104ef16f24SBrian Somers { 31130949fd4SBrian Somers struct sockaddr_storage ss; 31230949fd4SBrian Somers struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 3131a2b4e4aSBrian Somers #ifndef NOINET6 31430949fd4SBrian Somers struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 31530949fd4SBrian Somers #endif 31630949fd4SBrian Somers int s, sz; 3174ef16f24SBrian Somers 31874457d3dSBrian Somers if (server.cfg.port == port) 31974457d3dSBrian Somers server_Close(bundle); 320d40f8a5aSBrian Somers 32174457d3dSBrian Somers if (port == 0) 32274457d3dSBrian Somers return SERVER_INVALID; 32374457d3dSBrian Somers 32430949fd4SBrian Somers memset(&ss, '\0', sizeof ss); 3251a2b4e4aSBrian Somers #ifndef NOINET6 3261a2b4e4aSBrian Somers if (probe.ipv6_available) { 3271a2b4e4aSBrian Somers sin6->sin6_family = AF_INET6; 3281a2b4e4aSBrian Somers sin6->sin6_port = htons(port); 3291a2b4e4aSBrian Somers sin6->sin6_len = sizeof ss; 3301a2b4e4aSBrian Somers sz = sizeof *sin6; 3311a2b4e4aSBrian Somers s = socket(PF_INET6, SOCK_STREAM, 0); 3321a2b4e4aSBrian Somers } else 3331a2b4e4aSBrian Somers #endif 3341a2b4e4aSBrian Somers { 33530949fd4SBrian Somers sin->sin_family = AF_INET; 33630949fd4SBrian Somers sin->sin_port = htons(port); 33730949fd4SBrian Somers sin->sin_len = sizeof ss; 33830949fd4SBrian Somers sin->sin_addr.s_addr = INADDR_ANY; 33930949fd4SBrian Somers sz = sizeof *sin; 34074457d3dSBrian Somers s = socket(PF_INET, SOCK_STREAM, 0); 3411a2b4e4aSBrian Somers } 3421a2b4e4aSBrian Somers 3434ef16f24SBrian Somers if (s < 0) { 344dd7e2610SBrian Somers log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno)); 34574457d3dSBrian Somers goto failed; 3464ef16f24SBrian Somers } 34730949fd4SBrian Somers 3484ef16f24SBrian Somers setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s); 34930949fd4SBrian Somers if (bind(s, (struct sockaddr *)&ss, sz) < 0) { 350dd7e2610SBrian Somers log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno)); 3514ef16f24SBrian Somers close(s); 35274457d3dSBrian Somers goto failed; 3534ef16f24SBrian Somers } 3544ef16f24SBrian Somers if (listen(s, 5) != 0) { 355661a0e90SBrian Somers log_Printf(LogERROR, "Tcp: Unable to listen to socket: %s\n", 356661a0e90SBrian Somers strerror(errno)); 3574ef16f24SBrian Somers close(s); 35874457d3dSBrian Somers goto failed; 3594ef16f24SBrian Somers } 360dd7e2610SBrian Somers server_Close(bundle); 36177ff88adSBrian Somers server.fd = s; 36274457d3dSBrian Somers server.cfg.port = port; 36374457d3dSBrian Somers *server.cfg.sockname = '\0'; 36474457d3dSBrian Somers server.cfg.mask = 0; 365dd7e2610SBrian Somers log_Printf(LogPHASE, "Listening at port %d.\n", port); 36674457d3dSBrian Somers return SERVER_OK; 36774457d3dSBrian Somers 36874457d3dSBrian Somers failed: 36974457d3dSBrian Somers if (server.fd == -1) { 37074457d3dSBrian Somers server.fd = -1; 37174457d3dSBrian Somers server.cfg.port = port; 37274457d3dSBrian Somers *server.cfg.sockname = '\0'; 37374457d3dSBrian Somers server.cfg.mask = 0; 37474457d3dSBrian Somers } 37574457d3dSBrian Somers return SERVER_FAILED; 3764ef16f24SBrian Somers } 3774ef16f24SBrian Somers 37877ff88adSBrian Somers int 379dd7e2610SBrian Somers server_Close(struct bundle *bundle) 3804ef16f24SBrian Somers { 38177ff88adSBrian Somers if (server.fd >= 0) { 38274457d3dSBrian Somers if (*server.cfg.sockname != '\0') { 383661a0e90SBrian Somers struct sockaddr_un un; 384661a0e90SBrian Somers int sz = sizeof un; 385661a0e90SBrian Somers 386661a0e90SBrian Somers if (getsockname(server.fd, (struct sockaddr *)&un, &sz) == 0 && 387661a0e90SBrian Somers un.sun_family == AF_LOCAL && sz == sizeof un) 38874457d3dSBrian Somers unlink(un.sun_path); 3894ef16f24SBrian Somers } 390661a0e90SBrian Somers close(server.fd); 39177ff88adSBrian Somers server.fd = -1; 392b6217683SBrian Somers /* Drop associated prompts */ 3930f2f3eb3SBrian Somers log_DestroyPrompts(&server); 39474457d3dSBrian Somers 39577ff88adSBrian Somers return 1; 3964ef16f24SBrian Somers } 39774457d3dSBrian Somers 39877ff88adSBrian Somers return 0; 3994ef16f24SBrian Somers } 40074457d3dSBrian Somers 40174457d3dSBrian Somers int 40274457d3dSBrian Somers server_Clear(struct bundle *bundle) 40374457d3dSBrian Somers { 40474457d3dSBrian Somers int ret; 40574457d3dSBrian Somers 40674457d3dSBrian Somers ret = server_Close(bundle); 40774457d3dSBrian Somers 40874457d3dSBrian Somers server.fd = -1; 40974457d3dSBrian Somers server.cfg.port = 0; 41074457d3dSBrian Somers *server.cfg.sockname = '\0'; 41174457d3dSBrian Somers server.cfg.mask = 0; 41274457d3dSBrian Somers 41374457d3dSBrian Somers return ret; 41474457d3dSBrian Somers } 415