-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathnetwork.c
More file actions
115 lines (91 loc) · 2.36 KB
/
Copy pathnetwork.c
File metadata and controls
115 lines (91 loc) · 2.36 KB
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
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define LISTEN_QUEUE_LENGTH 128
int tcp_connect(char* host, char* port){
int sockfd = -1, error;
struct addrinfo hints;
struct addrinfo* head;
struct addrinfo* iter;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo(host, port, &hints, &head);
if(error){
fprintf(stderr, "getaddrinfo: %s\r\n", gai_strerror(error));
return -1;
}
for(iter = head; iter; iter = iter->ai_next){
sockfd = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol);
if(sockfd < 0){
continue;
}
error = connect(sockfd, iter->ai_addr, iter->ai_addrlen);
if(error != 0){
close(sockfd);
continue;
}
break;
}
freeaddrinfo(head);
iter = NULL;
if(sockfd < 0){
perror("socket");
return -1;
}
if(error != 0){
perror("connect");
return -1;
}
return sockfd;
}
int tcp_listener(char* bindhost, char* port){
int fd = -1, status, yes = 1;
struct addrinfo hints;
struct addrinfo* info;
struct addrinfo* addr_it;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
status = getaddrinfo(bindhost, port, &hints, &info);
if(status){
fprintf(stderr, "Failed to get socket info for %s port %s: %s\n", bindhost, port, gai_strerror(status));
return -1;
}
for(addr_it = info; addr_it != NULL; addr_it = addr_it->ai_next){
fd = socket(addr_it->ai_family, addr_it->ai_socktype, addr_it->ai_protocol);
if(fd < 0){
continue;
}
yes = config.exclusive ? 1 : 0;
if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&yes, sizeof(yes)) < 0){
fprintf(stderr, "Failed to set IPV6_V6ONLY on socket for %s port %s: %s\n", bindhost, port, strerror(errno));
}
yes = 1;
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0){
fprintf(stderr, "Failed to set SO_REUSEADDR on socket\n");
}
status = bind(fd, addr_it->ai_addr, addr_it->ai_addrlen);
if(status < 0){
close(fd);
continue;
}
break;
}
freeaddrinfo(info);
if(!addr_it){
fprintf(stderr, "Failed to create listening socket for %s port %s\n", bindhost, port);
return -1;
}
status = listen(fd, LISTEN_QUEUE_LENGTH);
if(status < 0){
perror("listen");
close(fd);
return -1;
}
return fd;
}