a8002d027dd8ee06bda9cf588824c9cd03ac1b8c
[tor-status] / src / torcontrol-socket.c
1 /* This file is part of libtorcontrol.
2  *
3  * Copyright (C) 2010 Philipp Zabel
4  *
5  * libtorcontrol is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libtorcontrol is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with libtorcontrol. If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <errno.h>
20 #include <glib.h>
21 #include <netdb.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27
28 int tor_control_open_socket (int port, GError **error);
29
30 int tor_control_open_socket (int port, GError **error) {
31         int status;
32         char *service;
33         struct addrinfo hints;
34         struct addrinfo *result, *rp;
35         int sockfd;
36         int fd;
37
38         memset (&hints, 0, sizeof hints);
39         hints.ai_family = AF_UNSPEC;
40         hints.ai_socktype = SOCK_STREAM;
41         hints.ai_flags = AI_PASSIVE;
42
43         service = g_strdup_printf ("%d", port);
44
45         status = getaddrinfo (NULL, service, &hints, &result);
46
47         g_free (service);
48
49         if (status != 0) {
50                 g_set_error (error,
51                              /* domain: */ g_quark_from_string ("TORCTLERR"), /* code: */ 1,
52                              "getaddrinfo error: %s", gai_strerror (status));
53                 return -1;
54         }
55
56         for (rp = result; rp != NULL; rp = rp->ai_next) {
57                 sockfd = socket (result->ai_family, result->ai_socktype,
58                                  result->ai_protocol);
59                 if (sockfd == -1)
60                         continue;
61
62                 status = connect (sockfd, result->ai_addr, result->ai_addrlen);
63                 if (status != -1)
64                         break;
65
66                 close (sockfd);
67         }
68
69         freeaddrinfo (result);
70
71         if (rp == NULL) {
72                 g_set_error (error,
73                              /* domain: */ g_quark_from_string ("TORCTLERR"), /* code: */ 2,
74                              "socket/connect error: %s", strerror (errno));
75                 return -1;
76         }
77
78         return sockfd;
79 }
80