fix fd leak on connection failure
[rofl0r-microsocks.git] / server.c
blob53195101e727b1e3dc9f8d684e221604122f0d25
1 #include "server.h"
2 #include <stdio.h>
3 #include <string.h>
4 #include <unistd.h>
6 int resolve(const char *host, unsigned short port, struct addrinfo** addr) {
7 struct addrinfo hints = {
8 .ai_family = AF_UNSPEC,
9 .ai_socktype = SOCK_STREAM,
10 .ai_flags = AI_PASSIVE,
12 char port_buf[8];
13 snprintf(port_buf, sizeof port_buf, "%u", port);
14 return getaddrinfo(host, port_buf, &hints, addr);
17 int server_bindtoip(const struct server *server, int fd) {
18 if(server->bindaddr.v4.sin_family != AF_UNSPEC)
19 return bind(fd, (struct sockaddr*) &server->bindaddr, server->bindaddrsz);
20 return 0;
23 int server_waitclient(struct server *server, struct client* client) {
24 socklen_t clen = sizeof client->addr;
25 return ((client->fd = accept(server->fd, (void*)&client->addr, &clen)) == -1)*-1;
28 int server_setup(struct server *server, const char* listenip, unsigned short port) {
29 struct addrinfo *ainfo = 0;
30 if(resolve(listenip, port, &ainfo)) return -1;
31 struct addrinfo* p;
32 int listenfd;
33 for(p = ainfo; p; p = p->ai_next) {
34 if((listenfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
35 continue;
36 int yes = 1;
37 setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
38 if(bind(listenfd, p->ai_addr, p->ai_addrlen) < 0) {
39 close(listenfd);
40 listenfd = -1;
41 continue;
43 break;
45 if(listenfd < 0) return -2;
46 freeaddrinfo(ainfo);
47 if(listen(listenfd, SOMAXCONN) < 0) {
48 close(listenfd);
49 return -3;
51 server->fd = listenfd;
52 if(!resolve(listenip, 0, &ainfo)) {
53 server->bindaddrsz = ainfo->ai_addrlen;
54 memcpy(&server->bindaddr, ainfo->ai_addr, ainfo->ai_addrlen);
55 freeaddrinfo(ainfo);
56 } else server->bindaddr.v4.sin_family = AF_UNSPEC;
57 return 0;