xref: /freebsd/usr.sbin/ppp/server.c (revision 1af29a6e96b99bd1e9f72777906f4b8ce9bd1d17)
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  *
261af29a6eSBrian Somers  *	$Id: server.c,v 1.20 1998/06/16 19:40:41 brian Exp $
2775240ed1SBrian Somers  */
2875240ed1SBrian Somers 
292764b86aSBrian Somers #include <sys/types.h>
304ef16f24SBrian Somers #include <sys/socket.h>
314ef16f24SBrian Somers #include <netinet/in.h>
324ef16f24SBrian Somers #include <arpa/inet.h>
334ef16f24SBrian Somers #include <netinet/in_systm.h>
34b6217683SBrian Somers #include <netinet/ip.h>
351fa665f5SBrian Somers #include <sys/un.h>
3675240ed1SBrian Somers 
374ef16f24SBrian Somers #include <errno.h>
3875240ed1SBrian Somers #include <stdio.h>
3975240ed1SBrian Somers #include <string.h>
4075240ed1SBrian Somers #include <sys/stat.h>
4185b542cfSBrian Somers #include <termios.h>
424ef16f24SBrian Somers #include <unistd.h>
4375240ed1SBrian Somers 
444ef16f24SBrian Somers #include "mbuf.h"
454ef16f24SBrian Somers #include "log.h"
4686e02934SBrian Somers #include "defs.h"
4777ff88adSBrian Somers #include "descriptor.h"
484ef16f24SBrian Somers #include "server.h"
495106c671SBrian Somers #include "id.h"
5085b542cfSBrian Somers #include "prompt.h"
513006ec67SBrian Somers #include "timer.h"
52b6217683SBrian Somers #include "lqr.h"
53b6217683SBrian Somers #include "hdlc.h"
54b6217683SBrian Somers #include "fsm.h"
55b6217683SBrian Somers #include "lcp.h"
56b6217683SBrian Somers #include "ccp.h"
57b6217683SBrian Somers #include "throughput.h"
58b6217683SBrian Somers #include "link.h"
59b6217683SBrian Somers #include "mp.h"
60b6217683SBrian Somers #include "iplist.h"
61b6217683SBrian Somers #include "slcompress.h"
62b6217683SBrian Somers #include "ipcp.h"
63b6217683SBrian Somers #include "filter.h"
64b6217683SBrian Somers #include "bundle.h"
654ef16f24SBrian Somers 
6677ff88adSBrian Somers static int
6777ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
6877ff88adSBrian Somers {
6977ff88adSBrian Somers   struct server *s = descriptor2server(d);
700f2f3eb3SBrian Somers   struct prompt *p;
710f2f3eb3SBrian Somers   int sets;
7275240ed1SBrian Somers 
730f2f3eb3SBrian Somers   sets = 0;
74b6dec9f0SBrian Somers   if (r && s->fd >= 0) {
7577ff88adSBrian Somers     if (*n < s->fd + 1)
7677ff88adSBrian Somers       *n = s->fd + 1;
7785b542cfSBrian Somers     FD_SET(s->fd, r);
7824989c68SBrian Somers     log_Printf(LogTIMER, "server: fdset(r) %d\n", s->fd);
790f2f3eb3SBrian Somers     sets++;
8077ff88adSBrian Somers   }
810f2f3eb3SBrian Somers 
820f2f3eb3SBrian Somers   for (p = log_PromptList(); p; p = p->next)
830f2f3eb3SBrian Somers     sets += descriptor_UpdateSet(&p->desc, r, w, e, n);
840f2f3eb3SBrian Somers 
850f2f3eb3SBrian Somers   return sets;
8677ff88adSBrian Somers }
8777ff88adSBrian Somers 
8877ff88adSBrian Somers static int
892f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset)
9077ff88adSBrian Somers {
9177ff88adSBrian Somers   struct server *s = descriptor2server(d);
920f2f3eb3SBrian Somers   struct prompt *p;
930f2f3eb3SBrian Somers 
940f2f3eb3SBrian Somers   if (s->fd >= 0 && FD_ISSET(s->fd, fdset))
950f2f3eb3SBrian Somers     return 1;
960f2f3eb3SBrian Somers 
970f2f3eb3SBrian Somers   for (p = log_PromptList(); p; p = p->next)
980f2f3eb3SBrian Somers     if (descriptor_IsSet(&p->desc, fdset))
990f2f3eb3SBrian Somers       return 1;
1000f2f3eb3SBrian Somers 
1010f2f3eb3SBrian Somers   return 0;
10277ff88adSBrian Somers }
10377ff88adSBrian Somers 
10477ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in)
10577ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in)
10677ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
10777ff88adSBrian Somers 
10877ff88adSBrian Somers static void
109b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
11077ff88adSBrian Somers {
11177ff88adSBrian Somers   struct server *s = descriptor2server(d);
11277ff88adSBrian Somers   char hisaddr[ADDRSZ];
11377ff88adSBrian Somers   struct sockaddr *sa = (struct sockaddr *)hisaddr;
114cdbbb6b5SBrian Somers   struct sockaddr_in *in = (struct sockaddr_in *)hisaddr;
11577ff88adSBrian Somers   int ssize = ADDRSZ, wfd;
116b6217683SBrian Somers   struct prompt *p;
11777ff88adSBrian Somers 
1180f2f3eb3SBrian Somers   if (s->fd >= 0 && FD_ISSET(s->fd, fdset)) {
11977ff88adSBrian Somers     wfd = accept(s->fd, sa, &ssize);
1200f2f3eb3SBrian Somers     if (wfd < 0)
121dd7e2610SBrian Somers       log_Printf(LogERROR, "server_Read: accept(): %s\n", strerror(errno));
1220f2f3eb3SBrian Somers   } else
1230f2f3eb3SBrian Somers     wfd = -1;
12477ff88adSBrian Somers 
1250f2f3eb3SBrian Somers   if (wfd >= 0)
12677ff88adSBrian Somers     switch (sa->sa_family) {
12777ff88adSBrian Somers       case AF_LOCAL:
128dd7e2610SBrian Somers         log_Printf(LogPHASE, "Connected to local client.\n");
12977ff88adSBrian Somers         break;
13077ff88adSBrian Somers 
13177ff88adSBrian Somers       case AF_INET:
132cdbbb6b5SBrian Somers         if (ntohs(in->sin_port) < 1024) {
133dd7e2610SBrian Somers           log_Printf(LogALERT, "Rejected client connection from %s:%u"
13477ff88adSBrian Somers                     "(invalid port number) !\n",
135cdbbb6b5SBrian Somers                     inet_ntoa(in->sin_addr), ntohs(in->sin_port));
13677ff88adSBrian Somers           close(wfd);
1370f2f3eb3SBrian Somers           wfd = -1;
1380f2f3eb3SBrian Somers           break;
13977ff88adSBrian Somers         }
140dd7e2610SBrian Somers         log_Printf(LogPHASE, "Connected to client from %s:%u\n",
141cdbbb6b5SBrian Somers                   inet_ntoa(in->sin_addr), in->sin_port);
14277ff88adSBrian Somers         break;
14377ff88adSBrian Somers 
14477ff88adSBrian Somers       default:
14577ff88adSBrian Somers         write(wfd, "Unrecognised access !\n", 22);
14677ff88adSBrian Somers         close(wfd);
1470f2f3eb3SBrian Somers         wfd = -1;
1480f2f3eb3SBrian Somers         break;
14977ff88adSBrian Somers     }
15077ff88adSBrian Somers 
1510f2f3eb3SBrian Somers   if (wfd >= 0) {
152b6217683SBrian Somers     if ((p = prompt_Create(s, bundle, wfd)) == NULL) {
153b6217683SBrian Somers       write(wfd, "Connection refused.\n", 20);
15477ff88adSBrian Somers       close(wfd);
15577ff88adSBrian Somers     } else {
156b6217683SBrian Somers       switch (sa->sa_family) {
157b6217683SBrian Somers         case AF_LOCAL:
158565e35e5SBrian Somers           p->src.type = "local";
159565e35e5SBrian Somers           strncpy(p->src.from, s->rm, sizeof p->src.from - 1);
160565e35e5SBrian Somers           p->src.from[sizeof p->src.from - 1] = '\0';
161b6217683SBrian Somers           break;
162b6217683SBrian Somers         case AF_INET:
163565e35e5SBrian Somers           p->src.type = "tcp";
164565e35e5SBrian Somers           snprintf(p->src.from, sizeof p->src.from, "%s:%u",
165cdbbb6b5SBrian Somers                    inet_ntoa(in->sin_addr), in->sin_port);
166b6217683SBrian Somers           break;
167b6217683SBrian Somers       }
168b6217683SBrian Somers       prompt_TtyCommandMode(p);
169b6217683SBrian Somers       prompt_Required(p);
17077ff88adSBrian Somers     }
17177ff88adSBrian Somers   }
17277ff88adSBrian Somers 
1730f2f3eb3SBrian Somers   for (p = log_PromptList(); p; p = p->next)
1740f2f3eb3SBrian Somers     if (descriptor_IsSet(&p->desc, fdset))
1750f2f3eb3SBrian Somers       descriptor_Read(&p->desc, bundle, fdset);
1760f2f3eb3SBrian Somers }
1770f2f3eb3SBrian Somers 
1781af29a6eSBrian Somers static int
179f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
18077ff88adSBrian Somers {
18177ff88adSBrian Somers   /* We never want to write here ! */
182a33b2ef7SBrian Somers   log_Printf(LogALERT, "server_Write: Internal error: Bad call !\n");
1831af29a6eSBrian Somers   return 0;
18477ff88adSBrian Somers }
18577ff88adSBrian Somers 
18677ff88adSBrian Somers struct server server = {
18777ff88adSBrian Somers   {
18877ff88adSBrian Somers     SERVER_DESCRIPTOR,
18977ff88adSBrian Somers     server_UpdateSet,
19077ff88adSBrian Somers     server_IsSet,
19177ff88adSBrian Somers     server_Read,
19277ff88adSBrian Somers     server_Write
19377ff88adSBrian Somers   },
19477ff88adSBrian Somers   -1
19577ff88adSBrian Somers };
1964ef16f24SBrian Somers 
1974ef16f24SBrian Somers int
198dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask)
1994ef16f24SBrian Somers {
2004ef16f24SBrian Somers   int s;
2014ef16f24SBrian Somers 
202565e35e5SBrian Somers   if (server.rm && !strcmp(server.rm, name)) {
203565e35e5SBrian Somers     if (chmod(server.rm, mask))
204dd7e2610SBrian Somers       log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno));
205565e35e5SBrian Somers     return 0;
206683cef3cSBrian Somers   }
207683cef3cSBrian Somers 
208565e35e5SBrian Somers   memset(&server.ifsun, '\0', sizeof server.ifsun);
209565e35e5SBrian Somers   server.ifsun.sun_len = strlen(name);
210565e35e5SBrian Somers   if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) {
211dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: %s: Path too long\n", name);
212683cef3cSBrian Somers     return 2;
2134ef16f24SBrian Somers   }
214565e35e5SBrian Somers   server.ifsun.sun_family = AF_LOCAL;
215565e35e5SBrian Somers   strcpy(server.ifsun.sun_path, name);
2164ef16f24SBrian Somers 
2175106c671SBrian Somers   s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
2184ef16f24SBrian Somers   if (s < 0) {
219dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno));
220683cef3cSBrian Somers     return 3;
2214ef16f24SBrian Somers   }
2224ef16f24SBrian Somers   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
2238ea8442cSBrian Somers   if (mask != (mode_t)-1)
22401ec2511SBrian Somers     mask = umask(mask);
225565e35e5SBrian Somers   if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) {
2268ea8442cSBrian Somers     if (mask != (mode_t)-1)
22701ec2511SBrian Somers       umask(mask);
228dd7e2610SBrian Somers     log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno));
2294ef16f24SBrian Somers     close(s);
230683cef3cSBrian Somers     return 4;
2314ef16f24SBrian Somers   }
2328ea8442cSBrian Somers   if (mask != (mode_t)-1)
23301ec2511SBrian Somers     umask(mask);
2344ef16f24SBrian Somers   if (listen(s, 5) != 0) {
235dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n");
2364ef16f24SBrian Somers     close(s);
2375106c671SBrian Somers     ID0unlink(name);
238683cef3cSBrian Somers     return 5;
2394ef16f24SBrian Somers   }
240dd7e2610SBrian Somers   server_Close(bundle);
24177ff88adSBrian Somers   server.fd = s;
242565e35e5SBrian Somers   server.rm = server.ifsun.sun_path;
243dd7e2610SBrian Somers   log_Printf(LogPHASE, "Listening at local socket %s.\n", name);
2444ef16f24SBrian Somers   return 0;
2454ef16f24SBrian Somers }
2464ef16f24SBrian Somers 
2474ef16f24SBrian Somers int
248dd7e2610SBrian Somers server_TcpOpen(struct bundle *bundle, int port)
2494ef16f24SBrian Somers {
2504ef16f24SBrian Somers   struct sockaddr_in ifsin;
2514ef16f24SBrian Somers   int s;
2524ef16f24SBrian Somers 
253565e35e5SBrian Somers   if (server.port == port)
254565e35e5SBrian Somers     return 0;
255d40f8a5aSBrian Somers 
2565106c671SBrian Somers   s = ID0socket(PF_INET, SOCK_STREAM, 0);
2574ef16f24SBrian Somers   if (s < 0) {
258dd7e2610SBrian Somers     log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
259683cef3cSBrian Somers     return 7;
2604ef16f24SBrian Somers   }
2612e14bb46SBrian Somers   memset(&ifsin, '\0', sizeof ifsin);
2624ef16f24SBrian Somers   ifsin.sin_family = AF_INET;
2634ef16f24SBrian Somers   ifsin.sin_addr.s_addr = INADDR_ANY;
2644ef16f24SBrian Somers   ifsin.sin_port = htons(port);
2654ef16f24SBrian Somers   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
26670ee81ffSBrian Somers   if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
267dd7e2610SBrian Somers     log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
2684ef16f24SBrian Somers     close(s);
269683cef3cSBrian Somers     return 8;
2704ef16f24SBrian Somers   }
2714ef16f24SBrian Somers   if (listen(s, 5) != 0) {
272dd7e2610SBrian Somers     log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
2734ef16f24SBrian Somers     close(s);
274683cef3cSBrian Somers     return 9;
2754ef16f24SBrian Somers   }
276dd7e2610SBrian Somers   server_Close(bundle);
27777ff88adSBrian Somers   server.fd = s;
278565e35e5SBrian Somers   server.port = port;
279dd7e2610SBrian Somers   log_Printf(LogPHASE, "Listening at port %d.\n", port);
2804ef16f24SBrian Somers   return 0;
2814ef16f24SBrian Somers }
2824ef16f24SBrian Somers 
28377ff88adSBrian Somers int
284dd7e2610SBrian Somers server_Close(struct bundle *bundle)
2854ef16f24SBrian Somers {
28677ff88adSBrian Somers   if (server.fd >= 0) {
28777ff88adSBrian Somers     close(server.fd);
288565e35e5SBrian Somers     if (server.rm) {
289565e35e5SBrian Somers       ID0unlink(server.rm);
290565e35e5SBrian Somers       server.rm = NULL;
2914ef16f24SBrian Somers     }
29277ff88adSBrian Somers     server.fd = -1;
293565e35e5SBrian Somers     server.port = 0;
294b6217683SBrian Somers     /* Drop associated prompts */
2950f2f3eb3SBrian Somers     log_DestroyPrompts(&server);
29677ff88adSBrian Somers     return 1;
2974ef16f24SBrian Somers   }
29877ff88adSBrian Somers   return 0;
2994ef16f24SBrian Somers }
300