1c39934eaSBrian Somers /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
4c39934eaSBrian Somers * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5c39934eaSBrian Somers * All rights reserved.
6c39934eaSBrian Somers *
7c39934eaSBrian Somers * Redistribution and use in source and binary forms, with or without
8c39934eaSBrian Somers * modification, are permitted provided that the following conditions
9c39934eaSBrian Somers * are met:
10c39934eaSBrian Somers * 1. Redistributions of source code must retain the above copyright
11c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer.
12c39934eaSBrian Somers * 2. Redistributions in binary form must reproduce the above copyright
13c39934eaSBrian Somers * notice, this list of conditions and the following disclaimer in the
14c39934eaSBrian Somers * documentation and/or other materials provided with the distribution.
15c39934eaSBrian Somers *
16c39934eaSBrian Somers * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17c39934eaSBrian Somers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18c39934eaSBrian Somers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19c39934eaSBrian Somers * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20c39934eaSBrian Somers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21c39934eaSBrian Somers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22c39934eaSBrian Somers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23c39934eaSBrian Somers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c39934eaSBrian Somers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c39934eaSBrian Somers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c39934eaSBrian Somers * SUCH DAMAGE.
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
server_UpdateSet(struct fdescriptor * d,fd_set * r,fd_set * w,fd_set * e,int * n)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
server_IsSet(struct fdescriptor * d,const fd_set * fdset)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
server_Read(struct fdescriptor * d,struct bundle * bundle,const fd_set * fdset)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
server_Write(struct fdescriptor * d __unused,struct bundle * bundle __unused,const fd_set * fdset __unused)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
server_Reopen(struct bundle * bundle)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
server_LocalOpen(struct bundle * bundle,const char * name,mode_t mask)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
2519304cfd0SDimitry 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
server_TcpOpen(struct bundle * bundle,u_short port)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
server_Close(struct bundle * bundle __unused)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
server_Clear(struct bundle * bundle)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