xref: /freebsd/usr.sbin/ppp/server.c (revision 85b542cf4f3d3d3338529aad0f9f006cdaeef9a8)
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  *
2685b542cfSBrian Somers  *	$Id: server.c,v 1.16.2.3 1998/02/10 03:22:05 brian Exp $
271ae349f5Scvs2svn  */
281ae349f5Scvs2svn 
291ae349f5Scvs2svn #include <sys/param.h>
301ae349f5Scvs2svn #include <sys/socket.h>
311ae349f5Scvs2svn #include <netinet/in.h>
321ae349f5Scvs2svn #include <arpa/inet.h>
331ae349f5Scvs2svn #include <netinet/in_systm.h>
341ae349f5Scvs2svn 
351ae349f5Scvs2svn #include <errno.h>
361ae349f5Scvs2svn #include <stdio.h>
371ae349f5Scvs2svn #include <string.h>
381ae349f5Scvs2svn #include <sys/stat.h>
391ae349f5Scvs2svn #include <sys/un.h>
4085b542cfSBrian Somers #include <termios.h>
411ae349f5Scvs2svn #include <unistd.h>
421ae349f5Scvs2svn 
431ae349f5Scvs2svn #include "command.h"
441ae349f5Scvs2svn #include "mbuf.h"
451ae349f5Scvs2svn #include "log.h"
461ae349f5Scvs2svn #include "loadalias.h"
471ae349f5Scvs2svn #include "defs.h"
481ae349f5Scvs2svn #include "vars.h"
4977ff88adSBrian Somers #include "descriptor.h"
501ae349f5Scvs2svn #include "server.h"
511ae349f5Scvs2svn #include "id.h"
5285b542cfSBrian Somers #include "prompt.h"
531ae349f5Scvs2svn 
5477ff88adSBrian Somers static int
5577ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
5677ff88adSBrian Somers {
5777ff88adSBrian Somers   struct server *s = descriptor2server(d);
5877ff88adSBrian Somers 
5977ff88adSBrian Somers   LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s);
6077ff88adSBrian Somers   if (s->fd >= 0) {
6177ff88adSBrian Somers     if (*n < s->fd + 1)
6277ff88adSBrian Somers       *n = s->fd + 1;
6385b542cfSBrian Somers     FD_SET(s->fd, r);
6477ff88adSBrian Somers     return 1;
6577ff88adSBrian Somers   }
6677ff88adSBrian Somers   return 0;
6777ff88adSBrian Somers }
6877ff88adSBrian Somers 
6977ff88adSBrian Somers static int
7077ff88adSBrian Somers server_IsSet(struct descriptor *d, fd_set *fdset)
7177ff88adSBrian Somers {
7277ff88adSBrian Somers   struct server *s = descriptor2server(d);
7377ff88adSBrian Somers 
7477ff88adSBrian Somers   LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s);
7577ff88adSBrian Somers   return s->fd >= 0 && FD_ISSET(s->fd, fdset);
7677ff88adSBrian Somers }
7777ff88adSBrian Somers 
7877ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in)
7977ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in)
8077ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
8177ff88adSBrian Somers 
8277ff88adSBrian Somers static void
83b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
8477ff88adSBrian Somers {
8577ff88adSBrian Somers   struct server *s = descriptor2server(d);
8677ff88adSBrian Somers   char hisaddr[ADDRSZ];
8777ff88adSBrian Somers   struct sockaddr *sa = (struct sockaddr *)hisaddr;
8877ff88adSBrian Somers   struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr;
8977ff88adSBrian Somers   int ssize = ADDRSZ, wfd;
9077ff88adSBrian Somers 
9177ff88adSBrian Somers   LogPrintf(LogDEBUG, "descriptor2server; %p -> %p\n", d, s);
9277ff88adSBrian Somers 
9377ff88adSBrian Somers   wfd = accept(s->fd, sa, &ssize);
9477ff88adSBrian Somers   if (wfd < 0) {
9577ff88adSBrian Somers     LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno));
9677ff88adSBrian Somers     return;
9777ff88adSBrian Somers   }
9877ff88adSBrian Somers 
9977ff88adSBrian Somers   switch (sa->sa_family) {
10077ff88adSBrian Somers     case AF_LOCAL:
10177ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to local client.\n");
10277ff88adSBrian Somers       break;
10377ff88adSBrian Somers 
10477ff88adSBrian Somers     case AF_INET:
10577ff88adSBrian Somers       if (ntohs(sin->sin_port) < 1024) {
10677ff88adSBrian Somers         LogPrintf(LogALERT, "Rejected client connection from %s:%u"
10777ff88adSBrian Somers                   "(invalid port number) !\n",
10877ff88adSBrian Somers                   inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
10977ff88adSBrian Somers         close(wfd);
11077ff88adSBrian Somers         return;
11177ff88adSBrian Somers       }
11277ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to client from %s:%u\n",
11377ff88adSBrian Somers                 inet_ntoa(sin->sin_addr), sin->sin_port);
11477ff88adSBrian Somers       break;
11577ff88adSBrian Somers 
11677ff88adSBrian Somers     default:
11777ff88adSBrian Somers       write(wfd, "Unrecognised access !\n", 22);
11877ff88adSBrian Somers       close(wfd);
11977ff88adSBrian Somers       return;
12077ff88adSBrian Somers   }
12177ff88adSBrian Somers 
12285b542cfSBrian Somers   if (!prompt_Init(&prompt, wfd)) {
12377ff88adSBrian Somers     write(wfd, "Connection already in use.\n", 27);
12477ff88adSBrian Somers     close(wfd);
12577ff88adSBrian Somers   } else {
12677ff88adSBrian Somers     LocalAuthInit();
12777ff88adSBrian Somers     IsInteractive(1);
12885b542cfSBrian Somers     prompt_Display(&prompt, bundle);
12977ff88adSBrian Somers   }
13077ff88adSBrian Somers }
13177ff88adSBrian Somers 
13277ff88adSBrian Somers static void
133b77776a7SBrian Somers server_Write(struct descriptor *d, const fd_set *fdset)
13477ff88adSBrian Somers {
13577ff88adSBrian Somers   /* We never want to write here ! */
13677ff88adSBrian Somers   LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n");
13777ff88adSBrian Somers }
13877ff88adSBrian Somers 
13977ff88adSBrian Somers struct server server = {
14077ff88adSBrian Somers   {
14177ff88adSBrian Somers     SERVER_DESCRIPTOR,
14277ff88adSBrian Somers     NULL,
14377ff88adSBrian Somers     server_UpdateSet,
14477ff88adSBrian Somers     server_IsSet,
14577ff88adSBrian Somers     server_Read,
14677ff88adSBrian Somers     server_Write
14777ff88adSBrian Somers   },
14877ff88adSBrian Somers   -1
14977ff88adSBrian Somers };
1501ae349f5Scvs2svn 
1511ae349f5Scvs2svn static struct sockaddr_un ifsun;
1521ae349f5Scvs2svn static char *rm;
1531ae349f5Scvs2svn 
1541ae349f5Scvs2svn int
1551ae349f5Scvs2svn ServerLocalOpen(const char *name, mode_t mask)
1561ae349f5Scvs2svn {
1571ae349f5Scvs2svn   int s;
1581ae349f5Scvs2svn 
1591ae349f5Scvs2svn   if (VarLocalAuth == LOCAL_DENY) {
1601ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: Can't open socket %s: No password "
1611ae349f5Scvs2svn 	      "in ppp.secret\n", name);
1621ae349f5Scvs2svn     return 1;
1631ae349f5Scvs2svn   }
1641ae349f5Scvs2svn 
1651ae349f5Scvs2svn   if (mode & MODE_INTER) {
1661ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: Can't open socket in interactive mode\n");
1671ae349f5Scvs2svn     return 1;
1681ae349f5Scvs2svn   }
1691ae349f5Scvs2svn 
1701ae349f5Scvs2svn   memset(&ifsun, '\0', sizeof ifsun);
1711ae349f5Scvs2svn   ifsun.sun_len = strlen(name);
1721ae349f5Scvs2svn   if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
1731ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
1741ae349f5Scvs2svn     return 2;
1751ae349f5Scvs2svn   }
1761ae349f5Scvs2svn   ifsun.sun_family = AF_LOCAL;
1771ae349f5Scvs2svn   strcpy(ifsun.sun_path, name);
1781ae349f5Scvs2svn 
1791ae349f5Scvs2svn   s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
1801ae349f5Scvs2svn   if (s < 0) {
1811ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
1821ae349f5Scvs2svn     return 3;
1831ae349f5Scvs2svn   }
1841ae349f5Scvs2svn   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
1851ae349f5Scvs2svn   if (mask != (mode_t)-1)
1861ae349f5Scvs2svn     mask = umask(mask);
1871ae349f5Scvs2svn   if (bind(s, (struct sockaddr *)&ifsun, sizeof ifsun) < 0) {
1881ae349f5Scvs2svn     if (mask != (mode_t)-1)
1891ae349f5Scvs2svn       umask(mask);
1901ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno));
19185b542cfSBrian Somers     if (errno == EADDRINUSE)
19285b542cfSBrian Somers       prompt_Printf(&prompt, "Wait for a while, then try again.\n");
1931ae349f5Scvs2svn     close(s);
1941ae349f5Scvs2svn     return 4;
1951ae349f5Scvs2svn   }
1961ae349f5Scvs2svn   if (mask != (mode_t)-1)
1971ae349f5Scvs2svn     umask(mask);
1981ae349f5Scvs2svn   if (listen(s, 5) != 0) {
1997a6f8720SBrian Somers     LogPrintf(LogERROR, "Local: Unable to listen to socket - BUNDLE overload?\n");
2001ae349f5Scvs2svn     close(s);
2011ae349f5Scvs2svn     ID0unlink(name);
2021ae349f5Scvs2svn     return 5;
2031ae349f5Scvs2svn   }
2041ae349f5Scvs2svn   ServerClose();
20577ff88adSBrian Somers   server.fd = s;
2061ae349f5Scvs2svn   rm = ifsun.sun_path;
2071ae349f5Scvs2svn   LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
2081ae349f5Scvs2svn   return 0;
2091ae349f5Scvs2svn }
2101ae349f5Scvs2svn 
2111ae349f5Scvs2svn int
2121ae349f5Scvs2svn ServerTcpOpen(int port)
2131ae349f5Scvs2svn {
2141ae349f5Scvs2svn   struct sockaddr_in ifsin;
2151ae349f5Scvs2svn   int s;
2161ae349f5Scvs2svn 
2171ae349f5Scvs2svn   if (VarLocalAuth == LOCAL_DENY) {
2181ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: Can't open socket %d: No password "
2191ae349f5Scvs2svn 	      "in ppp.secret\n", port);
2201ae349f5Scvs2svn     return 6;
2211ae349f5Scvs2svn   }
2221ae349f5Scvs2svn 
2231ae349f5Scvs2svn   if (mode & MODE_INTER) {
2241ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: Can't open socket in interactive mode\n");
2251ae349f5Scvs2svn     return 6;
2261ae349f5Scvs2svn   }
2271ae349f5Scvs2svn 
2281ae349f5Scvs2svn   s = ID0socket(PF_INET, SOCK_STREAM, 0);
2291ae349f5Scvs2svn   if (s < 0) {
2301ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
2311ae349f5Scvs2svn     return 7;
2321ae349f5Scvs2svn   }
2331ae349f5Scvs2svn   memset(&ifsin, '\0', sizeof ifsin);
2341ae349f5Scvs2svn   ifsin.sin_family = AF_INET;
2351ae349f5Scvs2svn   ifsin.sin_addr.s_addr = INADDR_ANY;
2361ae349f5Scvs2svn   ifsin.sin_port = htons(port);
2371ae349f5Scvs2svn   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
2381ae349f5Scvs2svn   if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
2391ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno));
24085b542cfSBrian Somers     if (errno == EADDRINUSE)
24185b542cfSBrian Somers       prompt_Printf(&prompt, "Wait for a while, then try again.\n");
2421ae349f5Scvs2svn     close(s);
2431ae349f5Scvs2svn     return 8;
2441ae349f5Scvs2svn   }
2451ae349f5Scvs2svn   if (listen(s, 5) != 0) {
2467a6f8720SBrian Somers     LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
2471ae349f5Scvs2svn     close(s);
2481ae349f5Scvs2svn     return 9;
2491ae349f5Scvs2svn   }
2501ae349f5Scvs2svn   ServerClose();
25177ff88adSBrian Somers   server.fd = s;
2521ae349f5Scvs2svn   LogPrintf(LogPHASE, "Listening at port %d.\n", port);
2531ae349f5Scvs2svn   return 0;
2541ae349f5Scvs2svn }
2551ae349f5Scvs2svn 
25677ff88adSBrian Somers int
2571ae349f5Scvs2svn ServerClose()
2581ae349f5Scvs2svn {
25977ff88adSBrian Somers   if (server.fd >= 0) {
26077ff88adSBrian Somers     close(server.fd);
2611ae349f5Scvs2svn     if (rm) {
2621ae349f5Scvs2svn       ID0unlink(rm);
2631ae349f5Scvs2svn       rm = 0;
2641ae349f5Scvs2svn     }
26577ff88adSBrian Somers     server.fd = -1;
26677ff88adSBrian Somers     return 1;
2671ae349f5Scvs2svn   }
26877ff88adSBrian Somers   return 0;
2691ae349f5Scvs2svn }
270