2 * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
26 * $FreeBSD: src/usr.sbin/ppp/server.c,v 1.28.2.6 2002/09/01 02:12:32 brian Exp $
27 * $DragonFly: src/usr.sbin/ppp/server.c,v 1.2 2003/06/17 04:30:01 dillon Exp $
30 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
45 #include "descriptor.h"
52 server_UpdateSet(struct fdescriptor
*d
, fd_set
*r
, fd_set
*w
, fd_set
*e
, int *n
)
54 struct server
*s
= descriptor2server(d
);
59 if (r
&& s
->fd
>= 0) {
63 log_Printf(LogTIMER
, "server: fdset(r) %d\n", s
->fd
);
67 for (p
= log_PromptList(); p
; p
= p
->next
)
68 sets
+= descriptor_UpdateSet(&p
->desc
, r
, w
, e
, n
);
74 server_IsSet(struct fdescriptor
*d
, const fd_set
*fdset
)
76 struct server
*s
= descriptor2server(d
);
79 if (s
->fd
>= 0 && FD_ISSET(s
->fd
, fdset
))
82 for (p
= log_PromptList(); p
; p
= p
->next
)
83 if (descriptor_IsSet(&p
->desc
, fdset
))
90 server_Read(struct fdescriptor
*d
, struct bundle
*bundle
, const fd_set
*fdset
)
92 struct server
*s
= descriptor2server(d
);
93 struct sockaddr_storage ss
;
94 struct sockaddr
*sa
= (struct sockaddr
*)&ss
;
95 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ss
;
97 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&ss
;
99 int ssize
= sizeof ss
, wfd
;
103 if (s
->fd
>= 0 && FD_ISSET(s
->fd
, fdset
)) {
104 wfd
= accept(s
->fd
, sa
, &ssize
);
106 log_Printf(LogERROR
, "server_Read: accept(): %s\n", strerror(errno
));
107 else if (sa
->sa_len
== 0) {
115 switch (sa
->sa_family
) {
117 log_Printf(LogPHASE
, "Connected to local client.\n");
121 ncpaddr_setsa(&addr
, sa
);
122 if (ntohs(sin
->sin_port
) < 1024) {
123 log_Printf(LogALERT
, "Rejected client connection from %s:%u"
124 "(invalid port number) !\n",
125 ncpaddr_ntoa(&addr
), ntohs(sin
->sin_port
));
130 log_Printf(LogPHASE
, "Connected to client from %s:%u\n",
131 ncpaddr_ntoa(&addr
), ntohs(sin
->sin_port
));
136 ncpaddr_setsa(&addr
, sa
);
137 if (ntohs(sin6
->sin6_port
) < 1024) {
138 log_Printf(LogALERT
, "Rejected client connection from %s:%u"
139 "(invalid port number) !\n",
140 ncpaddr_ntoa(&addr
), ntohs(sin6
->sin6_port
));
145 log_Printf(LogPHASE
, "Connected to client from %s:%u\n",
146 ncpaddr_ntoa(&addr
), ntohs(sin6
->sin6_port
));
151 write(wfd
, "Unrecognised access !\n", 22);
158 if ((p
= prompt_Create(s
, bundle
, wfd
)) == NULL
) {
159 write(wfd
, "Connection refused.\n", 20);
162 switch (sa
->sa_family
) {
164 p
->src
.type
= "local";
165 strncpy(p
->src
.from
, s
->cfg
.sockname
, sizeof p
->src
.from
- 1);
166 p
->src
.from
[sizeof p
->src
.from
- 1] = '\0';
170 snprintf(p
->src
.from
, sizeof p
->src
.from
, "%s:%u",
171 ncpaddr_ntoa(&addr
), ntohs(sin
->sin_port
));
176 snprintf(p
->src
.from
, sizeof p
->src
.from
, "%s:%u",
177 ncpaddr_ntoa(&addr
), ntohs(sin6
->sin6_port
));
181 prompt_TtyCommandMode(p
);
186 log_PromptListChanged
= 0;
187 for (p
= log_PromptList(); p
; p
= p
->next
)
188 if (descriptor_IsSet(&p
->desc
, fdset
)) {
189 descriptor_Read(&p
->desc
, bundle
, fdset
);
190 if (log_PromptListChanged
)
196 server_Write(struct fdescriptor
*d
, struct bundle
*bundle
, const fd_set
*fdset
)
198 /* We never want to write here ! */
199 log_Printf(LogALERT
, "server_Write: Internal error: Bad call !\n");
203 struct server server
= {
215 server_Reopen(struct bundle
*bundle
)
217 char name
[sizeof server
.cfg
.sockname
];
221 enum server_stat ret
;
223 if (server
.cfg
.sockname
[0] != '\0') {
224 strcpy(name
, server
.cfg
.sockname
);
225 mask
= server
.cfg
.mask
;
226 server_Close(bundle
);
227 if (server
.cfg
.sockname
[0] != '\0' && stat(server
.cfg
.sockname
, &st
) == 0)
228 if (!(st
.st_mode
& S_IFSOCK
) || unlink(server
.cfg
.sockname
) != 0)
229 return SERVER_FAILED
;
230 ret
= server_LocalOpen(bundle
, name
, mask
);
231 } else if (server
.cfg
.port
!= 0) {
232 port
= server
.cfg
.port
;
233 server_Close(bundle
);
234 ret
= server_TcpOpen(bundle
, port
);
242 server_LocalOpen(struct bundle
*bundle
, const char *name
, mode_t mask
)
244 struct sockaddr_un ifsun
;
248 oldmask
= (mode_t
)-1; /* Silence compiler */
250 if (server
.cfg
.sockname
&& !strcmp(server
.cfg
.sockname
, name
))
251 server_Close(bundle
);
253 memset(&ifsun
, '\0', sizeof ifsun
);
254 ifsun
.sun_len
= strlen(name
);
255 if (ifsun
.sun_len
> sizeof ifsun
.sun_path
- 1) {
256 log_Printf(LogERROR
, "Local: %s: Path too long\n", name
);
257 return SERVER_INVALID
;
259 ifsun
.sun_family
= AF_LOCAL
;
260 strcpy(ifsun
.sun_path
, name
);
262 s
= socket(PF_LOCAL
, SOCK_STREAM
, 0);
264 log_Printf(LogERROR
, "Local: socket: %s\n", strerror(errno
));
267 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &s
, sizeof s
);
268 if (mask
!= (mode_t
)-1)
269 oldmask
= umask(mask
);
270 if (bind(s
, (struct sockaddr
*)&ifsun
, sizeof ifsun
) < 0) {
271 if (mask
!= (mode_t
)-1)
273 log_Printf(LogWARN
, "Local: bind: %s\n", strerror(errno
));
277 if (mask
!= (mode_t
)-1)
279 if (listen(s
, 5) != 0) {
280 log_Printf(LogERROR
, "Local: Unable to listen to socket -"
281 " BUNDLE overload?\n");
286 server_Close(bundle
);
289 strncpy(server
.cfg
.sockname
, ifsun
.sun_path
, sizeof server
.cfg
.sockname
- 1);
290 server
.cfg
.sockname
[sizeof server
.cfg
.sockname
- 1] = '\0';
291 server
.cfg
.mask
= mask
;
292 log_Printf(LogPHASE
, "Listening at local socket %s.\n", name
);
297 if (server
.fd
== -1) {
300 strncpy(server
.cfg
.sockname
, ifsun
.sun_path
,
301 sizeof server
.cfg
.sockname
- 1);
302 server
.cfg
.sockname
[sizeof server
.cfg
.sockname
- 1] = '\0';
303 server
.cfg
.mask
= mask
;
305 return SERVER_FAILED
;
309 server_TcpOpen(struct bundle
*bundle
, u_short port
)
311 struct sockaddr_storage ss
;
312 struct sockaddr_in
*sin
= (struct sockaddr_in
*)&ss
;
314 struct sockaddr_in6
*sin6
= (struct sockaddr_in6
*)&ss
;
318 if (server
.cfg
.port
== port
)
319 server_Close(bundle
);
322 return SERVER_INVALID
;
324 memset(&ss
, '\0', sizeof ss
);
326 if (probe
.ipv6_available
) {
327 sin6
->sin6_family
= AF_INET6
;
328 sin6
->sin6_port
= htons(port
);
329 sin6
->sin6_len
= (u_int8_t
)sizeof ss
;
331 s
= socket(PF_INET6
, SOCK_STREAM
, 0);
335 sin
->sin_family
= AF_INET
;
336 sin
->sin_port
= htons(port
);
337 sin
->sin_len
= (u_int8_t
)sizeof ss
;
338 sin
->sin_addr
.s_addr
= INADDR_ANY
;
340 s
= socket(PF_INET
, SOCK_STREAM
, 0);
344 log_Printf(LogERROR
, "Tcp: socket: %s\n", strerror(errno
));
348 setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
, &s
, sizeof s
);
349 if (bind(s
, (struct sockaddr
*)&ss
, sz
) < 0) {
350 log_Printf(LogWARN
, "Tcp: bind: %s\n", strerror(errno
));
354 if (listen(s
, 5) != 0) {
355 log_Printf(LogERROR
, "Tcp: Unable to listen to socket: %s\n",
360 server_Close(bundle
);
362 server
.cfg
.port
= port
;
363 *server
.cfg
.sockname
= '\0';
365 log_Printf(LogPHASE
, "Listening at port %d.\n", port
);
369 if (server
.fd
== -1) {
371 server
.cfg
.port
= port
;
372 *server
.cfg
.sockname
= '\0';
375 return SERVER_FAILED
;
379 server_Close(struct bundle
*bundle
)
381 if (server
.fd
>= 0) {
382 if (*server
.cfg
.sockname
!= '\0') {
383 struct sockaddr_un un
;
386 if (getsockname(server
.fd
, (struct sockaddr
*)&un
, &sz
) == 0 &&
387 un
.sun_family
== AF_LOCAL
&& sz
== sizeof un
)
392 /* Drop associated prompts */
393 log_DestroyPrompts(&server
);
402 server_Clear(struct bundle
*bundle
)
406 ret
= server_Close(bundle
);
410 *server
.cfg
.sockname
= '\0';