xref: /freebsd/usr.sbin/ppp/server.c (revision b6217683dc0269a53b799399522dbdfb5a4919cc)
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  *
26b6217683SBrian Somers  *	$Id: server.c,v 1.16.2.10 1998/04/03 19:21:51 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>
34b6217683SBrian Somers #include <netinet/ip.h>
351ae349f5Scvs2svn 
361ae349f5Scvs2svn #include <errno.h>
371ae349f5Scvs2svn #include <stdio.h>
381ae349f5Scvs2svn #include <string.h>
391ae349f5Scvs2svn #include <sys/stat.h>
401ae349f5Scvs2svn #include <sys/un.h>
4185b542cfSBrian Somers #include <termios.h>
421ae349f5Scvs2svn #include <unistd.h>
431ae349f5Scvs2svn 
441ae349f5Scvs2svn #include "command.h"
451ae349f5Scvs2svn #include "mbuf.h"
461ae349f5Scvs2svn #include "log.h"
471ae349f5Scvs2svn #include "loadalias.h"
481ae349f5Scvs2svn #include "defs.h"
491ae349f5Scvs2svn #include "vars.h"
5077ff88adSBrian Somers #include "descriptor.h"
511ae349f5Scvs2svn #include "server.h"
521ae349f5Scvs2svn #include "id.h"
5385b542cfSBrian Somers #include "prompt.h"
543006ec67SBrian Somers #include "timer.h"
553006ec67SBrian Somers #include "auth.h"
56b6217683SBrian Somers #include "lqr.h"
57b6217683SBrian Somers #include "hdlc.h"
58b6217683SBrian Somers #include "fsm.h"
59b6217683SBrian Somers #include "lcp.h"
60b6217683SBrian Somers #include "ccp.h"
61b6217683SBrian Somers #include "throughput.h"
62b6217683SBrian Somers #include "link.h"
63b6217683SBrian Somers #include "mp.h"
64b6217683SBrian Somers #include "iplist.h"
65b6217683SBrian Somers #include "slcompress.h"
66b6217683SBrian Somers #include "ipcp.h"
67b6217683SBrian Somers #include "filter.h"
68b6217683SBrian Somers #include "bundle.h"
691ae349f5Scvs2svn 
7077ff88adSBrian Somers static int
7177ff88adSBrian Somers server_UpdateSet(struct descriptor *d, fd_set *r, fd_set *w, fd_set *e, int *n)
7277ff88adSBrian Somers {
7377ff88adSBrian Somers   struct server *s = descriptor2server(d);
7477ff88adSBrian Somers 
75b6dec9f0SBrian Somers   if (r && s->fd >= 0) {
7677ff88adSBrian Somers     if (*n < s->fd + 1)
7777ff88adSBrian Somers       *n = s->fd + 1;
7885b542cfSBrian Somers     FD_SET(s->fd, r);
7977ff88adSBrian Somers     return 1;
8077ff88adSBrian Somers   }
8177ff88adSBrian Somers   return 0;
8277ff88adSBrian Somers }
8377ff88adSBrian Somers 
8477ff88adSBrian Somers static int
852f786681SBrian Somers server_IsSet(struct descriptor *d, const fd_set *fdset)
8677ff88adSBrian Somers {
8777ff88adSBrian Somers   struct server *s = descriptor2server(d);
8877ff88adSBrian Somers   return s->fd >= 0 && FD_ISSET(s->fd, fdset);
8977ff88adSBrian Somers }
9077ff88adSBrian Somers 
9177ff88adSBrian Somers #define IN_SIZE sizeof(struct sockaddr_in)
9277ff88adSBrian Somers #define UN_SIZE sizeof(struct sockaddr_in)
9377ff88adSBrian Somers #define ADDRSZ (IN_SIZE > UN_SIZE ? IN_SIZE : UN_SIZE)
9477ff88adSBrian Somers 
95b6217683SBrian Somers static char *rm;
96b6217683SBrian Somers 
9777ff88adSBrian Somers static void
98b77776a7SBrian Somers server_Read(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
9977ff88adSBrian Somers {
10077ff88adSBrian Somers   struct server *s = descriptor2server(d);
10177ff88adSBrian Somers   char hisaddr[ADDRSZ];
10277ff88adSBrian Somers   struct sockaddr *sa = (struct sockaddr *)hisaddr;
10377ff88adSBrian Somers   struct sockaddr_in *sin = (struct sockaddr_in *)hisaddr;
10477ff88adSBrian Somers   int ssize = ADDRSZ, wfd;
105b6217683SBrian Somers   struct prompt *p;
10677ff88adSBrian Somers 
10777ff88adSBrian Somers   wfd = accept(s->fd, sa, &ssize);
10877ff88adSBrian Somers   if (wfd < 0) {
10977ff88adSBrian Somers     LogPrintf(LogERROR, "server_Read: accept(): %s\n", strerror(errno));
11077ff88adSBrian Somers     return;
11177ff88adSBrian Somers   }
11277ff88adSBrian Somers 
11377ff88adSBrian Somers   switch (sa->sa_family) {
11477ff88adSBrian Somers     case AF_LOCAL:
11577ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to local client.\n");
11677ff88adSBrian Somers       break;
11777ff88adSBrian Somers 
11877ff88adSBrian Somers     case AF_INET:
11977ff88adSBrian Somers       if (ntohs(sin->sin_port) < 1024) {
12077ff88adSBrian Somers         LogPrintf(LogALERT, "Rejected client connection from %s:%u"
12177ff88adSBrian Somers                   "(invalid port number) !\n",
12277ff88adSBrian Somers                   inet_ntoa(sin->sin_addr), ntohs(sin->sin_port));
12377ff88adSBrian Somers         close(wfd);
12477ff88adSBrian Somers         return;
12577ff88adSBrian Somers       }
12677ff88adSBrian Somers       LogPrintf(LogPHASE, "Connected to client from %s:%u\n",
12777ff88adSBrian Somers                 inet_ntoa(sin->sin_addr), sin->sin_port);
12877ff88adSBrian Somers       break;
12977ff88adSBrian Somers 
13077ff88adSBrian Somers     default:
13177ff88adSBrian Somers       write(wfd, "Unrecognised access !\n", 22);
13277ff88adSBrian Somers       close(wfd);
13377ff88adSBrian Somers       return;
13477ff88adSBrian Somers   }
13577ff88adSBrian Somers 
136b6217683SBrian Somers   if ((p = prompt_Create(s, bundle, wfd)) == NULL) {
137b6217683SBrian Somers     write(wfd, "Connection refused.\n", 20);
13877ff88adSBrian Somers     close(wfd);
13977ff88adSBrian Somers   } else {
140b6217683SBrian Somers     switch (sa->sa_family) {
141b6217683SBrian Somers       case AF_LOCAL:
142b6217683SBrian Somers         snprintf(p->who, sizeof p->who, "local (%s)", rm);
143b6217683SBrian Somers         break;
144b6217683SBrian Somers       case AF_INET:
145b6217683SBrian Somers         snprintf(p->who, sizeof p->who, "TCP (%s:%u)",
146b6217683SBrian Somers                  inet_ntoa(sin->sin_addr), sin->sin_port);
147b6217683SBrian Somers         break;
148b6217683SBrian Somers     }
149b6217683SBrian Somers     IsInteractive(p);
150b6217683SBrian Somers     prompt_TtyCommandMode(p);
151b6217683SBrian Somers     prompt_Required(p);
15277ff88adSBrian Somers   }
15377ff88adSBrian Somers }
15477ff88adSBrian Somers 
15577ff88adSBrian Somers static void
156f4768038SBrian Somers server_Write(struct descriptor *d, struct bundle *bundle, const fd_set *fdset)
15777ff88adSBrian Somers {
15877ff88adSBrian Somers   /* We never want to write here ! */
15977ff88adSBrian Somers   LogPrintf(LogERROR, "server_Write: Internal error: Bad call !\n");
16077ff88adSBrian Somers }
16177ff88adSBrian Somers 
16277ff88adSBrian Somers struct server server = {
16377ff88adSBrian Somers   {
16477ff88adSBrian Somers     SERVER_DESCRIPTOR,
16577ff88adSBrian Somers     NULL,
16677ff88adSBrian Somers     server_UpdateSet,
16777ff88adSBrian Somers     server_IsSet,
16877ff88adSBrian Somers     server_Read,
16977ff88adSBrian Somers     server_Write
17077ff88adSBrian Somers   },
17177ff88adSBrian Somers   -1
17277ff88adSBrian Somers };
1731ae349f5Scvs2svn 
1741ae349f5Scvs2svn static struct sockaddr_un ifsun;
1751ae349f5Scvs2svn 
1761ae349f5Scvs2svn int
177b6217683SBrian Somers ServerLocalOpen(struct bundle *bundle, const char *name, mode_t mask)
1781ae349f5Scvs2svn {
1791ae349f5Scvs2svn   int s;
1801ae349f5Scvs2svn 
1811ae349f5Scvs2svn   memset(&ifsun, '\0', sizeof ifsun);
1821ae349f5Scvs2svn   ifsun.sun_len = strlen(name);
1831ae349f5Scvs2svn   if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
1841ae349f5Scvs2svn     LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
1851ae349f5Scvs2svn     return 2;
1861ae349f5Scvs2svn   }
1871ae349f5Scvs2svn   ifsun.sun_family = AF_LOCAL;
1881ae349f5Scvs2svn   strcpy(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);
1981ae349f5Scvs2svn   if (bind(s, (struct sockaddr *)&ifsun, sizeof 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;
2151ae349f5Scvs2svn   rm = 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 
2261ae349f5Scvs2svn   s = ID0socket(PF_INET, SOCK_STREAM, 0);
2271ae349f5Scvs2svn   if (s < 0) {
2281ae349f5Scvs2svn     LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
2291ae349f5Scvs2svn     return 7;
2301ae349f5Scvs2svn   }
2311ae349f5Scvs2svn   memset(&ifsin, '\0', sizeof ifsin);
2321ae349f5Scvs2svn   ifsin.sin_family = AF_INET;
2331ae349f5Scvs2svn   ifsin.sin_addr.s_addr = INADDR_ANY;
2341ae349f5Scvs2svn   ifsin.sin_port = htons(port);
2351ae349f5Scvs2svn   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
2361ae349f5Scvs2svn   if (bind(s, (struct sockaddr *)&ifsin, sizeof ifsin) < 0) {
237b6217683SBrian Somers     LogPrintf(LogWARN, "Tcp: bind: %s\n", strerror(errno));
2381ae349f5Scvs2svn     close(s);
2391ae349f5Scvs2svn     return 8;
2401ae349f5Scvs2svn   }
2411ae349f5Scvs2svn   if (listen(s, 5) != 0) {
2427a6f8720SBrian Somers     LogPrintf(LogERROR, "Tcp: Unable to listen to socket - BUNDLE overload?\n");
2431ae349f5Scvs2svn     close(s);
2441ae349f5Scvs2svn     return 9;
2451ae349f5Scvs2svn   }
246b6217683SBrian Somers   ServerClose(bundle);
24777ff88adSBrian Somers   server.fd = s;
2481ae349f5Scvs2svn   LogPrintf(LogPHASE, "Listening at port %d.\n", port);
2491ae349f5Scvs2svn   return 0;
2501ae349f5Scvs2svn }
2511ae349f5Scvs2svn 
25277ff88adSBrian Somers int
253b6217683SBrian Somers ServerClose(struct bundle *bundle)
2541ae349f5Scvs2svn {
25577ff88adSBrian Somers   if (server.fd >= 0) {
25677ff88adSBrian Somers     close(server.fd);
2571ae349f5Scvs2svn     if (rm) {
2581ae349f5Scvs2svn       ID0unlink(rm);
2591ae349f5Scvs2svn       rm = 0;
2601ae349f5Scvs2svn     }
26177ff88adSBrian Somers     server.fd = -1;
262b6217683SBrian Somers     /* Drop associated prompts */
263b6217683SBrian Somers     bundle_DelPromptDescriptors(bundle, &server);
26477ff88adSBrian Somers     return 1;
2651ae349f5Scvs2svn   }
26677ff88adSBrian Somers   return 0;
2671ae349f5Scvs2svn }
268