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
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "macros.h"
#include "network.h"
const char *addr_to_str(struct sockaddr *sa, socklen_t len) {
const int family = sa->sa_family;
static char ip[INET6_ADDRSTRLEN];
char *str = ip;
switch (family) {
case AF_INET6 : inet_ntop(family, &((struct sockaddr_in6 *)sa)->sin6_addr, ip, len); break;
case AF_INET : inet_ntop(family, &((struct sockaddr_in *)sa)->sin_addr, ip, len); break;
case AF_UNIX : str = ((struct sockaddr_un *)sa)->sun_path; break;
}
return str;
}
struct sockaddr *get_sock_addr(int socket) {
struct sockaddr *sa;
socklen_t sock_len = sizeof(struct sockaddr);
getsockname(socket, NULL, &sock_len);
sa = calloc(1, sock_len);
getsockname(socket, sa, &sock_len);
return sa;
}
int create_socket(struct sockaddr *sa, size_t sock_len) {
const int one = 1;
const int fd = socket(sa->sa_family, SOCK_SEQPACKET, IPPROTO_SCTP);
const char *addr_str = addr_to_str(sa, sock_len);
int ret = fd;
if (fd < 0) {
log_reason(LOG_ERR, "Failed to create listen socket for addresss \"%s\".", addr_str, strerror(errno));
return -1;
}
if (sa->sa_family == AF_INET6) {
int set = 1;
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &set, sizeof(set));
}
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
log_reason(LOG_ERR, "Failed to enable SO_REUSEADDR for socket %i.", fd, strerror(errno));
ret = -1;
}
if (ret >= 0 && bind(fd, sa, sock_len) < 0) {
log_reason(LOG_ERR, "Failed to bind listen socket %i with address \"%s\".", fd, addr_str, strerror(errno));
ret = -1;
}
if (ret >= 0 && listen(fd, 20) < 0) {
log_reason(LOG_ERR, "Failed to listen to socket %i.", fd, strerror(errno));
ret = -1;
}
if (ret < 0) {
close(fd);
if (sa->sa_family == AF_UNIX) {
struct sockaddr_un *sa_un = (struct sockaddr_un *)sa;
unlink(sa_un->sun_path);
}
log_reason(LOG_ERR, "Failed to create socket for address \"%s\".", addr_str, strerror(errno));
} else {
log(LOG_INFO, "Successfully created socket descriptor %i for address \"%s\".", fd, addr_str);
}
return ret;
}
|