server.c revision 29252
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <sys/socket.h>
4#include <netinet/in.h>
5#include <sys/un.h>
6#include <arpa/inet.h>
7#include <netinet/in_systm.h>
8#include <netinet/ip.h>
9#include <string.h>
10#include <stdio.h>
11#include <errno.h>
12#include <unistd.h>
13#include "mbuf.h"
14#include "log.h"
15#include "loadalias.h"
16#include "vars.h"
17#include "server.h"
18#include "defs.h"
19
20int server = UNKNOWN_SERVER;
21static struct sockaddr_un ifsun;
22static char *rm;
23
24int
25ServerLocalOpen(const char *name, mode_t mask)
26{
27  int s;
28
29  if (VarLocalAuth == LOCAL_DENY) {
30    LogPrintf(LogERROR, "Local: Can't open socket %s: No password "
31	      "in ppp.secret\n", name);
32    return 1;
33  }
34
35  if (!(mode&(MODE_AUTO|MODE_DEDICATED|MODE_DIRECT))) {
36    LogPrintf(LogERROR, "Local: Can't open socket in interactive mode\n");
37    return 1;
38  }
39
40  ifsun.sun_len = strlen(name);
41  if (ifsun.sun_len > sizeof ifsun.sun_path - 1) {
42    LogPrintf(LogERROR, "Local: %s: Path too long\n", name);
43    return 2;
44  }
45  ifsun.sun_family = AF_LOCAL;
46  strcpy(ifsun.sun_path, name);
47
48  s = socket(PF_LOCAL, SOCK_STREAM, 0);
49  if (s < 0) {
50    LogPrintf(LogERROR, "Local: socket: %s\n", strerror(errno));
51    return 3;
52  }
53  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
54  mask = umask(mask);
55  if (bind(s, (struct sockaddr *) & ifsun, sizeof(ifsun)) < 0) {
56    umask(mask);
57    LogPrintf(LogERROR, "Local: bind: %s\n", strerror(errno));
58    if (errno == EADDRINUSE && VarTerm)
59      fprintf(VarTerm, "Wait for a while, then try again.\n");
60    close(s);
61    unlink(name);
62    return 4;
63  }
64  umask(mask);
65  if (listen(s, 5) != 0) {
66    LogPrintf(LogERROR, "Local: Unable to listen to socket - OS overload?\n");
67    close(s);
68    unlink(name);
69    return 5;
70  }
71  ServerClose();
72  server = s;
73  rm = ifsun.sun_path;
74  LogPrintf(LogPHASE, "Listening at local socket %s.\n", name);
75  return 0;
76}
77
78int
79ServerTcpOpen(int port)
80{
81  struct sockaddr_in ifsin;
82  int s;
83
84  if (VarLocalAuth == LOCAL_DENY) {
85    LogPrintf(LogERROR, "Tcp: Can't open socket %d: No password "
86	      "in ppp.secret\n", port);
87    return 6;
88  }
89
90  if (!(mode&(MODE_AUTO|MODE_DEDICATED|MODE_DIRECT))) {
91    LogPrintf(LogERROR, "Tcp: Can't open socket in interactive mode\n");
92    return 6;
93  }
94
95  s = socket(PF_INET, SOCK_STREAM, 0);
96  if (s < 0) {
97    LogPrintf(LogERROR, "Tcp: socket: %s\n", strerror(errno));
98    return 7;
99  }
100  ifsin.sin_family = AF_INET;
101  ifsin.sin_addr.s_addr = INADDR_ANY;
102  ifsin.sin_port = htons(port);
103  setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &s, sizeof s);
104  if (bind(s, (struct sockaddr *) & ifsin, sizeof(ifsin)) < 0) {
105    LogPrintf(LogERROR, "Tcp: bind: %s\n", strerror(errno));
106    if (errno == EADDRINUSE && VarTerm)
107      fprintf(VarTerm, "Wait for a while, then try again.\n");
108    close(s);
109    return 8;
110  }
111  if (listen(s, 5) != 0) {
112    LogPrintf(LogERROR, "Tcp: Unable to listen to socket - OS overload?\n");
113    close(s);
114    return 9;
115  }
116  ServerClose();
117  server = s;
118  LogPrintf(LogPHASE, "Listening at port %d.\n", port);
119  return 0;
120}
121
122void
123ServerClose()
124{
125  if (server >= 0) {
126    close(server);
127    if (rm) {
128      unlink(rm);
129      rm = 0;
130    }
131  }
132  server = -1;
133}
134
135int
136ServerType()
137{
138  if (server == UNKNOWN_SERVER)
139    return UNKNOWN_SERVER;
140  else if (server == NO_SERVER)
141    return NO_SERVER;
142  else if (rm)
143    return LOCAL_SERVER;
144  else
145    return INET_SERVER;
146}
147