server.c revision 31921
131921Sbrian/*-
231921Sbrian * Copyright (c) 1997 Brian Somers <brian@Awfulhak.org>
331921Sbrian * All rights reserved.
431921Sbrian *
531921Sbrian * Redistribution and use in source and binary forms, with or without
631921Sbrian * modification, are permitted provided that the following conditions
731921Sbrian * are met:
831921Sbrian * 1. Redistributions of source code must retain the above copyright
931921Sbrian *    notice, this list of conditions and the following disclaimer.
1031921Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1131921Sbrian *    notice, this list of conditions and the following disclaimer in the
1231921Sbrian *    documentation and/or other materials provided with the distribution.
1331921Sbrian *
1431921Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1531921Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1631921Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1731921Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1831921Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1931921Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2031921Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2131921Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2231921Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2331921Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2431921Sbrian * SUCH DAMAGE.
2531921Sbrian *
2631921Sbrian *	$Id$
2730715Sbrian */
2830715Sbrian
2930715Sbrian#include <sys/param.h>
3026940Sbrian#include <sys/socket.h>
3126940Sbrian#include <netinet/in.h>
3226940Sbrian#include <arpa/inet.h>
3326940Sbrian#include <netinet/in_systm.h>
3426940Sbrian#include <netinet/ip.h>
3530715Sbrian
3630715Sbrian#include <errno.h>
3730715Sbrian#include <stdio.h>
3826940Sbrian#include <string.h>
3930715Sbrian#include <sys/stat.h>
4030715Sbrian#include <sys/un.h>
4126940Sbrian#include <unistd.h>
4230715Sbrian
4331343Sbrian#include "command.h"
4426940Sbrian#include "mbuf.h"
4526940Sbrian#include "log.h"
4626940Sbrian#include "loadalias.h"
4731070Sbrian#include "defs.h"
4826940Sbrian#include "vars.h"
4926940Sbrian#include "server.h"
5031061Sbrian#include "id.h"
5126940Sbrian
5231081Sbrianint server = -1;
5330715Sbrian
5426940Sbrianstatic struct sockaddr_un ifsun;
5526940Sbrianstatic char *rm;
5626940Sbrian
5726940Sbrianint
5827089SbrianServerLocalOpen(const char *name, mode_t mask)
5926940Sbrian{
6028679Sbrian  int s;
6126940Sbrian
6229083Sbrian  if (VarLocalAuth == LOCAL_DENY) {
6329083Sbrian    LogPrintf(LogERROR, "Local: Can't open socket %s: No password "
6429083Sbrian	      "in ppp.secret\n", name);
6529083Sbrian    return 1;
6629083Sbrian  }
6729083Sbrian
6831121Sbrian  if (mode & MODE_INTER) {
6929252Sbrian    LogPrintf(LogERROR, "Local: Can't open socket in interactive mode\n");
7029252Sbrian    return 1;
7129252Sbrian  }
7229252Sbrian
7331914Sbrian  memset(&ifsun, '\0', sizeof ifsun);
7428679Sbrian  ifsun.sun_len = strlen(name);
7528679Sbrian  if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
7628679Sbrian    LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
7729083Sbrian    return 2;
7828679Sbrian  }
7928679Sbrian  ifsun.sun_family = AF_LOCAL;
8028679Sbrian  strcpy(ifsun.sun_path, name);
8126940Sbrian
8231061Sbrian  s = ID0socket(PF_LOCAL, SOCK_STREAM, 0);
8328679Sbrian  if (s < 0) {
8428679Sbrian    LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
8529083Sbrian    return 3;
8628679Sbrian  }
8728679Sbrian  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
8831081Sbrian  if (mask != (mode_t)-1)
8931081Sbrian    mask = umask(mask);
9028679Sbrian  if (bind(s, (struct sockaddr *) & ifsun, sizeof(ifsun)) < 0) {
9131081Sbrian    if (mask != (mode_t)-1)
9231081Sbrian      umask(mask);
9328679Sbrian    LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno));
9428679Sbrian    if (errno == EADDRINUSE && VarTerm)
9528679Sbrian      fprintf(VarTerm, "Wait for a while, then try again.\n");
9628679Sbrian    close(s);
9729083Sbrian    return 4;
9828679Sbrian  }
9931081Sbrian  if (mask != (mode_t)-1)
10031081Sbrian    umask(mask);
10128679Sbrian  if (listen(s, 5) != 0) {
10228679Sbrian    LogPrintf(LogERROR, "Local: Unable to listen to socket - OS overload?\n");
10328679Sbrian    close(s);
10431061Sbrian    ID0unlink(name);
10529083Sbrian    return 5;
10628679Sbrian  }
10728679Sbrian  ServerClose();
10828679Sbrian  server = s;
10928679Sbrian  rm = ifsun.sun_path;
11028679Sbrian  LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
11128679Sbrian  return 0;
11226940Sbrian}
11326940Sbrian
11426940Sbrianint
11526940SbrianServerTcpOpen(int port)
11626940Sbrian{
11728679Sbrian  struct sockaddr_in ifsin;
11828679Sbrian  int s;
11926940Sbrian
12029083Sbrian  if (VarLocalAuth == LOCAL_DENY) {
12129083Sbrian    LogPrintf(LogERROR, "Tcp: Can't open socket %d: No password "
12229083Sbrian	      "in ppp.secret\n", port);
12329083Sbrian    return 6;
12429083Sbrian  }
12529252Sbrian
12631121Sbrian  if (mode & MODE_INTER) {
12729252Sbrian    LogPrintf(LogERROR, "Tcp: Can't open socket in interactive mode\n");
12829252Sbrian    return 6;
12929252Sbrian  }
13029252Sbrian
13131061Sbrian  s = ID0socket(PF_INET, SOCK_STREAM, 0);
13228679Sbrian  if (s < 0) {
13328679Sbrian    LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
13429083Sbrian    return 7;
13528679Sbrian  }
13631914Sbrian  memset(&ifsin, '\0', sizeof ifsin);
13728679Sbrian  ifsin.sin_family = AF_INET;
13828679Sbrian  ifsin.sin_addr.s_addr = INADDR_ANY;
13928679Sbrian  ifsin.sin_port = htons(port);
14028679Sbrian  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
14128679Sbrian  if (bind(s, (struct sockaddr *) & ifsin, sizeof(ifsin)) < 0) {
14228679Sbrian    LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno));
14328679Sbrian    if (errno == EADDRINUSE && VarTerm)
14428679Sbrian      fprintf(VarTerm, "Wait for a while, then try again.\n");
14528679Sbrian    close(s);
14629083Sbrian    return 8;
14728679Sbrian  }
14828679Sbrian  if (listen(s, 5) != 0) {
14928679Sbrian    LogPrintf(LogERROR, "Tcp: Unable to listen to socket - OS overload?\n");
15028679Sbrian    close(s);
15129083Sbrian    return 9;
15228679Sbrian  }
15328679Sbrian  ServerClose();
15428679Sbrian  server = s;
15528679Sbrian  LogPrintf(LogPHASE, "Listening at port %d.\n", port);
15628679Sbrian  return 0;
15726940Sbrian}
15826940Sbrian
15926940Sbrianvoid
16026940SbrianServerClose()
16126940Sbrian{
16226940Sbrian  if (server >= 0) {
16326940Sbrian    close(server);
16426940Sbrian    if (rm) {
16531061Sbrian      ID0unlink(rm);
16626940Sbrian      rm = 0;
16726940Sbrian    }
16826940Sbrian  }
16926940Sbrian  server = -1;
17026940Sbrian}
171