xref: /freebsd/usr.sbin/ppp/server.c (revision 1fa665f5b363853f2e5ebdf453e9af3b7e752729)
11ae349f5Scvs2svn /*-
21ae349f5Scvs2svn  * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
31ae349f5Scvs2svn  * All rights reserved.
41ae349f5Scvs2svn  *
51ae349f5Scvs2svn  * Redistribution and use in source and binary forms, with or without
61ae349f5Scvs2svn  * modification, are permitted provided that the following conditions
71ae349f5Scvs2svn  * are met:
81ae349f5Scvs2svn  * 1. Redistributions of source code must retain the above copyright
91ae349f5Scvs2svn  *    notice, this list of conditions and the following disclaimer.
101ae349f5Scvs2svn  * 2. Redistributions in binary form must reproduce the above copyright
111ae349f5Scvs2svn  *    notice, this list of conditions and the following disclaimer in the
121ae349f5Scvs2svn  *    documentation and/or other materials provided with the distribution.
131ae349f5Scvs2svn  *
141ae349f5Scvs2svn  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151ae349f5Scvs2svn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161ae349f5Scvs2svn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171ae349f5Scvs2svn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181ae349f5Scvs2svn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191ae349f5Scvs2svn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201ae349f5Scvs2svn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211ae349f5Scvs2svn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221ae349f5Scvs2svn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231ae349f5Scvs2svn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241ae349f5Scvs2svn  * SUCH DAMAGE.
251ae349f5Scvs2svn  *
261fa665f5SBrian Somers  *	$Id: server.c,v 1.16.2.16 1998/04/18 01:01:28 brian Exp $
271ae349f5Scvs2svn  */
281ae349f5Scvs2svn 
292764b86aSBrian Somers #include <sys/types.h>
301ae349f5Scvs2svn #include <sys/socket.h>
311ae349f5Scvs2svn #include <netinet/in.h>
321ae349f5Scvs2svn #include <arpa/inet.h>
331ae349f5Scvs2svn #include <netinet/in_systm.h>
34b6217683SBrian Somers #include <netinet/ip.h>
351fa665f5SBrian Somers #include <sys/un.h>
361ae349f5Scvs2svn 
371ae349f5Scvs2svn #include <errno.h>
381ae349f5Scvs2svn #include <stdio.h>
391ae349f5Scvs2svn #include <string.h>
401ae349f5Scvs2svn #include <sys/stat.h>
4185b542cfSBrian Somers #include <termios.h>
421ae349f5Scvs2svn #include <unistd.h>
431ae349f5Scvs2svn 
441ae349f5Scvs2svn #include "mbuf.h"
451ae349f5Scvs2svn #include "log.h"
461ae349f5Scvs2svn #include "defs.h"
4777ff88adSBrian Somers #include "descriptor.h"
481ae349f5Scvs2svn #include "server.h"
491ae349f5Scvs2svn #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"
651ae349f5Scvs2svn 
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);
7077ff88adSBrian Somers 
71b6dec9f0SBrian Somers   if (r && s->fd >= 0) {
7277ff88adSBrian Somers     if (*n < s->fd + 1)
7377ff88adSBrian Somers       *n = s->fd + 1;
7485b542cfSBrian Somers     FD_SET(s->fd, r);
7577ff88adSBrian Somers     return 1;
7677ff88adSBrian Somers   }
7777ff88adSBrian Somers   return 0;
7877ff88adSBrian Somers }
7977ff88adSBrian Somers 
8077ff88adSBrian Somers static int
812f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset)
8277ff88adSBrian Somers {
8377ff88adSBrian Somers   struct server *s = descriptor2server(d);
8477ff88adSBrian Somers   return s->fd >= 0 && FD_ISSET(s->fd, fdset);
8577ff88adSBrian Somers }
8677ff88adSBrian Somers 
8777ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in)
8877ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in)
8977ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
9077ff88adSBrian Somers 
9177ff88adSBrian Somers static void
92b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
9377ff88adSBrian Somers {
9477ff88adSBrian Somers   struct server *s = descriptor2server(d);
9577ff88adSBrian Somers   char hisaddr[ADDRSZ];
9677ff88adSBrian Somers   struct sockaddr *sa = (struct sockaddr *)hisaddr;
97cdbbb6b5SBrian Somers   struct sockaddr_in *in = (struct sockaddr_in *)hisaddr;
9877ff88adSBrian Somers   int ssize = ADDRSZ, wfd;
99b6217683SBrian Somers   struct prompt *p;
10077ff88adSBrian Somers 
10177ff88adSBrian Somers   wfd = accept(s->fd, sa, &ssize);
10277ff88adSBrian Somers   if (wfd < 0) {
10377ff88adSBrian Somers     LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno));
10477ff88adSBrian Somers     return;
10577ff88adSBrian Somers   }
10677ff88adSBrian Somers 
10777ff88adSBrian Somers   switch (sa->sa_family) {
10877ff88adSBrian Somers     case AF_LOCAL:
10977ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to local client.\n");
11077ff88adSBrian Somers       break;
11177ff88adSBrian Somers 
11277ff88adSBrian Somers     case AF_INET:
113cdbbb6b5SBrian Somers       if (ntohs(in->sin_port) < 1024) {
11477ff88adSBrian Somers         LogPrintf(LogALERT, "Rejected client connection from %s:%u"
11577ff88adSBrian Somers                   "(invalid port number) !\n",
116cdbbb6b5SBrian Somers                   inet_ntoa(in->sin_addr), ntohs(in->sin_port));
11777ff88adSBrian Somers         close(wfd);
11877ff88adSBrian Somers         return;
11977ff88adSBrian Somers       }
12077ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to client from %s:%u\n",
121cdbbb6b5SBrian Somers                 inet_ntoa(in->sin_addr), in->sin_port);
12277ff88adSBrian Somers       break;
12377ff88adSBrian Somers 
12477ff88adSBrian Somers     default:
12577ff88adSBrian Somers       write(wfd, "Unrecognised access !\n", 22);
12677ff88adSBrian Somers       close(wfd);
12777ff88adSBrian Somers       return;
12877ff88adSBrian Somers   }
12977ff88adSBrian Somers 
130b6217683SBrian Somers   if ((p = prompt_Create(s, bundle, wfd)) == NULL) {
131b6217683SBrian Somers     write(wfd, "Connection refused.\n", 20);
13277ff88adSBrian Somers     close(wfd);
13377ff88adSBrian Somers   } else {
134b6217683SBrian Somers     switch (sa->sa_family) {
135b6217683SBrian Somers       case AF_LOCAL:
136565e35e5SBrian Somers         p->src.type = "local";
137565e35e5SBrian Somers         strncpy(p->src.from, s->rm, sizeof p->src.from - 1);
138565e35e5SBrian Somers         p->src.from[sizeof p->src.from - 1] = '\0';
139b6217683SBrian Somers         break;
140b6217683SBrian Somers       case AF_INET:
141565e35e5SBrian Somers         p->src.type = "tcp";
142565e35e5SBrian Somers         snprintf(p->src.from, sizeof p->src.from, "%s:%u",
143cdbbb6b5SBrian Somers                  inet_ntoa(in->sin_addr), in->sin_port);
144b6217683SBrian Somers         break;
145b6217683SBrian Somers     }
146b6217683SBrian Somers     prompt_TtyCommandMode(p);
147b6217683SBrian Somers     prompt_Required(p);
14877ff88adSBrian Somers   }
14977ff88adSBrian Somers }
15077ff88adSBrian Somers 
15177ff88adSBrian Somers static void
152f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
15377ff88adSBrian Somers {
15477ff88adSBrian Somers   /* We never want to write here ! */
15577ff88adSBrian Somers   LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n");
15677ff88adSBrian Somers }
15777ff88adSBrian Somers 
15877ff88adSBrian Somers struct server server = {
15977ff88adSBrian Somers   {
16077ff88adSBrian Somers     SERVER_DESCRIPTOR,
16177ff88adSBrian Somers     NULL,
16277ff88adSBrian Somers     server_UpdateSet,
16377ff88adSBrian Somers     server_IsSet,
16477ff88adSBrian Somers     server_Read,
16577ff88adSBrian Somers     server_Write
16677ff88adSBrian Somers   },
16777ff88adSBrian Somers   -1
16877ff88adSBrian Somers };
1691ae349f5Scvs2svn 
1701ae349f5Scvs2svn int
171b6217683SBrian Somers ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask)
1721ae349f5Scvs2svn {
1731ae349f5Scvs2svn   int s;
1741ae349f5Scvs2svn 
175565e35e5SBrian Somers   if (server.rm && !strcmp(server.rm, name)) {
176565e35e5SBrian Somers     if (chmod(server.rm, mask))
177565e35e5SBrian Somers       LogPrintf(LogERROR, "Local: chmod: %s\n", strerror(errno));
178565e35e5SBrian Somers     return 0;
179565e35e5SBrian Somers   }
180565e35e5SBrian Somers 
181565e35e5SBrian Somers   memset(&server.ifsun, '\0', sizeof server.ifsun);
182565e35e5SBrian Somers   server.ifsun.sun_len = strlen(name);
183565e35e5SBrian Somers   if (server.ifsun.sun_len > sizeof server.ifsun.sun_path - 1) {
1841ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
1851ae349f5Scvs2svn     return 2;
1861ae349f5Scvs2svn   }
187565e35e5SBrian Somers   server.ifsun.sun_family = AF_LOCAL;
188565e35e5SBrian Somers   strcpy(server.ifsun.sun_path, name);
1891ae349f5Scvs2svn 
1901ae349f5Scvs2svn   s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
1911ae349f5Scvs2svn   if (s < 0) {
1921ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
1931ae349f5Scvs2svn     return 3;
1941ae349f5Scvs2svn   }
1951ae349f5Scvs2svn   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
1961ae349f5Scvs2svn   if (mask != (mode_t)-1)
1971ae349f5Scvs2svn     mask = umask(mask);
198565e35e5SBrian Somers   if (bind(s, (struct sockaddr *)&server.ifsun, sizeof server.ifsun) < 0) {
1991ae349f5Scvs2svn     if (mask != (mode_t)-1)
2001ae349f5Scvs2svn       umask(mask);
201b6217683SBrian Somers     LogPrintf(LogWARN, "Local: bind: %s\n", strerror(errno));
2021ae349f5Scvs2svn     close(s);
2031ae349f5Scvs2svn     return 4;
2041ae349f5Scvs2svn   }
2051ae349f5Scvs2svn   if (mask != (mode_t)-1)
2061ae349f5Scvs2svn     umask(mask);
2071ae349f5Scvs2svn   if (listen(s, 5) != 0) {
2087a6f8720SBrian Somers     LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n");
2091ae349f5Scvs2svn     close(s);
2101ae349f5Scvs2svn     ID0unlink(name);
2111ae349f5Scvs2svn     return 5;
2121ae349f5Scvs2svn   }
213b6217683SBrian Somers   ServerClose(bundle);
21477ff88adSBrian Somers   server.fd = s;
215565e35e5SBrian Somers   server.rm = server.ifsun.sun_path;
2161ae349f5Scvs2svn   LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
2171ae349f5Scvs2svn   return 0;
2181ae349f5Scvs2svn }
2191ae349f5Scvs2svn 
2201ae349f5Scvs2svn int
221b6217683SBrian Somers ServerTcpOpen(struct bundle *bundle, int port)
2221ae349f5Scvs2svn {
2231ae349f5Scvs2svn   struct sockaddr_in ifsin;
2241ae349f5Scvs2svn   int s;
2251ae349f5Scvs2svn 
226565e35e5SBrian Somers   if (server.port == port)
227565e35e5SBrian Somers     return 0;
228565e35e5SBrian Somers 
2291ae349f5Scvs2svn   s = ID0socket(PF_INET, SOCK_STREAM, 0);
2301ae349f5Scvs2svn   if (s < 0) {
2311ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
2321ae349f5Scvs2svn     return 7;
2331ae349f5Scvs2svn   }
2341ae349f5Scvs2svn   memset(&ifsin, '\0', sizeof ifsin);
2351ae349f5Scvs2svn   ifsin.sin_family = AF_INET;
2361ae349f5Scvs2svn   ifsin.sin_addr.s_addr = INADDR_ANY;
2371ae349f5Scvs2svn   ifsin.sin_port = htons(port);
2381ae349f5Scvs2svn   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
2391ae349f5Scvs2svn   if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
240b6217683SBrian Somers     LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
2411ae349f5Scvs2svn     close(s);
2421ae349f5Scvs2svn     return 8;
2431ae349f5Scvs2svn   }
2441ae349f5Scvs2svn   if (listen(s, 5) != 0) {
2457a6f8720SBrian Somers     LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
2461ae349f5Scvs2svn     close(s);
2471ae349f5Scvs2svn     return 9;
2481ae349f5Scvs2svn   }
249b6217683SBrian Somers   ServerClose(bundle);
25077ff88adSBrian Somers   server.fd = s;
251565e35e5SBrian Somers   server.port = port;
2521ae349f5Scvs2svn   LogPrintf(LogPHASE, "Listening at port %d.\n", port);
2531ae349f5Scvs2svn   return 0;
2541ae349f5Scvs2svn }
2551ae349f5Scvs2svn 
25677ff88adSBrian Somers int
257b6217683SBrian Somers ServerClose(struct bundle *bundle)
2581ae349f5Scvs2svn {
25977ff88adSBrian Somers   if (server.fd >= 0) {
26077ff88adSBrian Somers     close(server.fd);
261565e35e5SBrian Somers     if (server.rm) {
262565e35e5SBrian Somers       ID0unlink(server.rm);
263565e35e5SBrian Somers       server.rm = NULL;
2641ae349f5Scvs2svn     }
26577ff88adSBrian Somers     server.fd = -1;
266565e35e5SBrian Somers     server.port = 0;
267b6217683SBrian Somers     /* Drop associated prompts */
268b6217683SBrian Somers     bundle_DelPromptDescriptors(bundle, &server);
26977ff88adSBrian Somers     return 1;
2701ae349f5Scvs2svn   }
27177ff88adSBrian Somers   return 0;
2721ae349f5Scvs2svn }
273