1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "server.h"
#include "socktool.h"
#include "connection.h"
#include <arpa/inet.h>
#include <errno.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
int ras_server_init (
RasServer* server, RasConnPerm perm, int domain,
const char* log_file, int id) {
/* chain up to parent constructor */
int rval =
ras_conn_init (RAS_CONN (server), perm, domain, "ras-server", log_file, id);
if (rval < 0) {
return rval;
}
return 0;
}
void ras_server_destroy (RasServer* server) {
if (RAS_CONN (server)->domain == AF_LOCAL) {
unlink (SOCKADDR_UN (&server->addr)->sun_path);
}
/* chain up to parent destructor */
ras_conn_destroy (RAS_CONN (server));
}
int ras_server_listen (RasServer* server, const char* addr, int arg) {
/* domain == AC_LOCAL => arg == mode
* domain == AC_INET => arg == port
* domain == AC_INET6 => arg == port */
int len, fd;
struct sockaddr_storage sock;
socklen_t socklen;
memset (&sock, 0, sizeof (sock));
switch (RAS_CONN (server)->domain) {
case AF_LOCAL:
socklen = sizeof (struct sockaddr_un);
len = socklen - offsetof (struct sockaddr_un, sun_path) - 1;
SOCKADDR_UN (&sock)->sun_family = AF_LOCAL;
strncpy (SOCKADDR_UN (&sock)->sun_path, addr, len);
ras_server_log (server, "addr = %s, mode = %o", addr, arg);
break;
case AF_INET:
socklen = sizeof (struct sockaddr_in);
SOCKADDR_IN (&sock)->sin_family = AF_INET;
SOCKADDR_IN (&sock)->sin_port = htons (arg);
if (addr == NULL) {
SOCKADDR_IN (&sock)->sin_addr.s_addr = htonl (INADDR_ANY);
addr = "any";
} else {
if (inet_pton (AF_INET, addr, &(SOCKADDR_IN (&sock)->sin_addr)) <= 0) {
ras_server_log (server, "unknown IPv4 address: %s", addr);
return -1;
}
}
ras_server_log (server, "addr = %s, port = %d", addr, arg);
break;
case AF_INET6:
socklen = sizeof (struct sockaddr_in6);
SOCKADDR_IN6 (&sock)->sin6_family = AF_INET6;
SOCKADDR_IN6 (&sock)->sin6_port = htons (arg);
if (addr == NULL) {
SOCKADDR_IN6 (&sock)->sin6_addr = in6addr_any;
addr = "any";
} else {
if (inet_pton (AF_INET6, addr, &(SOCKADDR_IN6 (&sock)->sin6_addr)) <= 0) {
ras_server_log (server, "unknown IPv6 address: %s", addr);
return -1;
}
}
ras_server_log (server, "addr = %s, port = %d", addr, arg);
break;
default:
return -1;
}
fd = socket (RAS_CONN (server)->domain, SOCK_STREAM, 0);
if (fd < 0) {
ras_server_log (server, "socket: %s", strerror (errno));
goto fd_opened;
}
if (RAS_CONN (server)->domain == AF_INET6) {
int yes = 1;
setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &yes, sizeof (yes));
}
if (RAS_CONN (server)->domain == AF_LOCAL) {
fchmod (fd, arg);
}
if (bind (fd, SOCKADDR (&sock), socklen)) {
ras_server_log (server, "bind: %s", strerror (errno));
goto fd_opened;
}
if (listen (fd, SOMAXCONN)) {
ras_server_log (server, "listen: %s", strerror (errno));
goto fd_opened;
}
RAS_CONN (server)->fd = fd;
RAS_CONN (server)->fd_is_set = true;
server->addr = sock;
server->addrlen = socklen;
return 0;
fd_opened:
close (fd);
return -1;
}
|