xref: /freebsd/usr.sbin/ppp/server.c (revision a33b2ef772181930eb0cd97c51cd8b058fecbf70)
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  *
26a33b2ef7SBrian Somers  *	$Id: server.c,v 1.19 1998/05/23 22:24:50 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 
17877ff88adSBrian Somers static void
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");
18377ff88adSBrian Somers }
18477ff88adSBrian Somers 
18577ff88adSBrian Somers struct server server = {
18677ff88adSBrian Somers   {
18777ff88adSBrian Somers     SERVER_DESCRIPTOR,
18877ff88adSBrian Somers     server_UpdateSet,
18977ff88adSBrian Somers     server_IsSet,
19077ff88adSBrian Somers     server_Read,
19177ff88adSBrian Somers     server_Write
19277ff88adSBrian Somers   },
19377ff88adSBrian Somers   -1
19477ff88adSBrian Somers };
1954ef16f24SBrian Somers 
1964ef16f24SBrian Somers int
197dd7e2610SBrian Somers server_LocalOpen(struct bundle *bundle, const char *name, mode_t mask)
1984ef16f24SBrian Somers {
1994ef16f24SBrian Somers   int s;
2004ef16f24SBrian Somers 
201565e35e5SBrian Somers   if (server.rm && !strcmp(server.rm, name)) {
202565e35e5SBrian Somers     if (chmod(server.rm, mask))
203dd7e2610SBrian Somers       log_Printf(LogERROR, "Local: chmod: %s\n", strerror(errno));
204565e35e5SBrian Somers     return 0;
205683cef3cSBrian Somers   }
206683cef3cSBrian Somers 
207565e35e5SBrian Somers   memset(&server.ifsun, '\0', sizeof server.ifsun);
208565e35e5SBrian Somers   server.ifsun.sun_len = strlen(name);
209565e35e5SBrian Somers   if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) {
210dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: %s: Path too long\n", name);
211683cef3cSBrian Somers     return 2;
2124ef16f24SBrian Somers   }
213565e35e5SBrian Somers   server.ifsun.sun_family = AF_LOCAL;
214565e35e5SBrian Somers   strcpy(server.ifsun.sun_path, name);
2154ef16f24SBrian Somers 
2165106c671SBrian Somers   s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
2174ef16f24SBrian Somers   if (s < 0) {
218dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: socket: %s\n", strerror(errno));
219683cef3cSBrian Somers     return 3;
2204ef16f24SBrian Somers   }
2214ef16f24SBrian Somers   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
2228ea8442cSBrian Somers   if (mask != (mode_t)-1)
22301ec2511SBrian Somers     mask = umask(mask);
224565e35e5SBrian Somers   if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) {
2258ea8442cSBrian Somers     if (mask != (mode_t)-1)
22601ec2511SBrian Somers       umask(mask);
227dd7e2610SBrian Somers     log_Printf(LogWARN, "Local: bind: %s\n", strerror(errno));
2284ef16f24SBrian Somers     close(s);
229683cef3cSBrian Somers     return 4;
2304ef16f24SBrian Somers   }
2318ea8442cSBrian Somers   if (mask != (mode_t)-1)
23201ec2511SBrian Somers     umask(mask);
2334ef16f24SBrian Somers   if (listen(s, 5) != 0) {
234dd7e2610SBrian Somers     log_Printf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n");
2354ef16f24SBrian Somers     close(s);
2365106c671SBrian Somers     ID0unlink(name);
237683cef3cSBrian Somers     return 5;
2384ef16f24SBrian Somers   }
239dd7e2610SBrian Somers   server_Close(bundle);
24077ff88adSBrian Somers   server.fd = s;
241565e35e5SBrian Somers   server.rm = server.ifsun.sun_path;
242dd7e2610SBrian Somers   log_Printf(LogPHASE, "Listening at local socket %s.\n", name);
2434ef16f24SBrian Somers   return 0;
2444ef16f24SBrian Somers }
2454ef16f24SBrian Somers 
2464ef16f24SBrian Somers int
247dd7e2610SBrian Somers server_TcpOpen(struct bundle *bundle, int port)
2484ef16f24SBrian Somers {
2494ef16f24SBrian Somers   struct sockaddr_in ifsin;
2504ef16f24SBrian Somers   int s;
2514ef16f24SBrian Somers 
252565e35e5SBrian Somers   if (server.port == port)
253565e35e5SBrian Somers     return 0;
254d40f8a5aSBrian Somers 
2555106c671SBrian Somers   s = ID0socket(PF_INET, SOCK_STREAM, 0);
2564ef16f24SBrian Somers   if (s < 0) {
257dd7e2610SBrian Somers     log_Printf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
258683cef3cSBrian Somers     return 7;
2594ef16f24SBrian Somers   }
2602e14bb46SBrian Somers   memset(&ifsin, '\0', sizeof ifsin);
2614ef16f24SBrian Somers   ifsin.sin_family = AF_INET;
2624ef16f24SBrian Somers   ifsin.sin_addr.s_addr = INADDR_ANY;
2634ef16f24SBrian Somers   ifsin.sin_port = htons(port);
2644ef16f24SBrian Somers   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
26570ee81ffSBrian Somers   if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
266dd7e2610SBrian Somers     log_Printf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
2674ef16f24SBrian Somers     close(s);
268683cef3cSBrian Somers     return 8;
2694ef16f24SBrian Somers   }
2704ef16f24SBrian Somers   if (listen(s, 5) != 0) {
271dd7e2610SBrian Somers     log_Printf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
2724ef16f24SBrian Somers     close(s);
273683cef3cSBrian Somers     return 9;
2744ef16f24SBrian Somers   }
275dd7e2610SBrian Somers   server_Close(bundle);
27677ff88adSBrian Somers   server.fd = s;
277565e35e5SBrian Somers   server.port = port;
278dd7e2610SBrian Somers   log_Printf(LogPHASE, "Listening at port %d.\n", port);
2794ef16f24SBrian Somers   return 0;
2804ef16f24SBrian Somers }
2814ef16f24SBrian Somers 
28277ff88adSBrian Somers int
283dd7e2610SBrian Somers server_Close(struct bundle *bundle)
2844ef16f24SBrian Somers {
28577ff88adSBrian Somers   if (server.fd >= 0) {
28677ff88adSBrian Somers     close(server.fd);
287565e35e5SBrian Somers     if (server.rm) {
288565e35e5SBrian Somers       ID0unlink(server.rm);
289565e35e5SBrian Somers       server.rm = NULL;
2904ef16f24SBrian Somers     }
29177ff88adSBrian Somers     server.fd = -1;
292565e35e5SBrian Somers     server.port = 0;
293b6217683SBrian Somers     /* Drop associated prompts */
2940f2f3eb3SBrian Somers     log_DestroyPrompts(&server);
29577ff88adSBrian Somers     return 1;
2964ef16f24SBrian Somers   }
29777ff88adSBrian Somers   return 0;
2984ef16f24SBrian Somers }
299