comparison lib/socket-connect-getaddrinfo.c @ 952:a490d94a5b8e

2008-03-28 Brian Masney <masneyb@gftp.org> * lib/Makefile.am lib/misc.c lib/socket-connect.c lib/socket-connect-getaddrinfo.c lib/socket-connect-gethostbyname.c lib/sockutils.c lib/gftp.h - cleaned up more of the socket functions and split them up into their own files. Cleanups and bug fixes to the DNS lookup code.
author masneyb
date Fri, 28 Mar 2008 11:44:36 +0000
parents
children
comparison
equal deleted inserted replaced
951:99f8858bbf02 952:a490d94a5b8e
1 /*****************************************************************************/
2 /* socket-connect-getaddrinfo.c - uses getaddrinfo for connections */
3 /* Copyright (C) 1998-2008 Brian Masney <masneyb@gftp.org> */
4 /* */
5 /* This program 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 2 of the License, or */
8 /* (at your option) any later version. */
9 /* */
10 /* This program 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 this program; if not, write to the Free Software */
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
18 /*****************************************************************************/
19
20 #include "gftp.h"
21 static const char cvsid[] = "$Id: protocols.c 952 2008-01-24 23:31:26Z masneyb $";
22
23 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
24
25 static int
26 get_port (struct addrinfo *addr)
27 {
28 struct sockaddr_in * saddr;
29 int port;
30
31 if (addr->ai_family == AF_INET)
32 {
33 saddr = (struct sockaddr_in *) addr->ai_addr;
34 port = ntohs (saddr->sin_port);
35 }
36 else
37 port = 0;
38
39 return (port);
40 }
41
42
43 struct addrinfo *
44 lookup_host_with_getaddrinfo (gftp_request *request, char *service,
45 char *proxy_hostname, int proxy_port)
46 {
47 struct addrinfo hints, *hostp;
48 intptr_t enable_ipv6;
49 char serv[8], *connect_host;
50 int ret, connect_port;
51
52 if (request->use_proxy)
53 {
54 connect_host = proxy_hostname;
55 connect_port = proxy_port;
56 }
57 else
58 {
59 connect_host = request->hostname;
60 connect_port = request->port;
61 }
62
63 gftp_lookup_request_option (request, "enable_ipv6", &enable_ipv6);
64
65 memset (&hints, 0, sizeof (hints));
66 hints.ai_flags = AI_CANONNAME;
67
68 hints.ai_family = enable_ipv6 ? PF_UNSPEC : AF_INET;
69 hints.ai_socktype = SOCK_STREAM;
70
71 if (connect_port == 0)
72 strcpy (serv, service);
73 else
74 snprintf (serv, sizeof (serv), "%d", connect_port);
75
76 request->logging_function (gftp_logging_misc, request,
77 _("Looking up %s\n"), connect_host);
78 if ((ret = getaddrinfo (connect_host, serv, &hints,
79 &hostp)) != 0)
80 {
81 request->logging_function (gftp_logging_error, request,
82 _("Cannot look up hostname %s: %s\n"),
83 connect_host, gai_strerror (ret));
84 return (NULL);
85 }
86
87 return (hostp);
88 }
89
90
91 int
92 gftp_connect_server_with_getaddrinfo (gftp_request * request, char *service,
93 char *proxy_hostname,
94 unsigned int proxy_port)
95 {
96 struct addrinfo *res, *hostp, *current_hostp;
97 unsigned int port;
98 int sock = -1;
99
100 hostp = lookup_host_with_getaddrinfo (request, service, proxy_hostname,
101 proxy_port);
102 if (hostp == NULL)
103 return (GFTP_ERETRYABLE);
104
105 for (res = hostp; res != NULL; res = res->ai_next)
106 {
107 port = get_port (res);
108 if (!request->use_proxy)
109 request->port = port;
110
111 if ((sock = socket (res->ai_family, res->ai_socktype,
112 res->ai_protocol)) < 0)
113 {
114 request->logging_function (gftp_logging_error, request,
115 _("Failed to create a socket: %s\n"),
116 g_strerror (errno));
117 continue;
118 }
119
120 request->logging_function (gftp_logging_misc, request,
121 _("Trying %s:%d\n"), res[0].ai_canonname,
122 port);
123
124 if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
125 {
126 request->logging_function (gftp_logging_error, request,
127 _("Cannot connect to %s: %s\n"),
128 res[0].ai_canonname, g_strerror (errno));
129 close (sock);
130 continue;
131 }
132
133 current_hostp = res;
134 request->ai_family = res->ai_family;
135 break;
136 }
137
138 if (res == NULL)
139 {
140 if (hostp != NULL)
141 freeaddrinfo (hostp);
142
143 return (GFTP_ERETRYABLE);
144 }
145
146 request->remote_addr_len = current_hostp->ai_addrlen;
147 request->remote_addr = g_malloc0 (request->remote_addr_len);
148 memcpy (request->remote_addr, &((struct sockaddr_in *) current_hostp->ai_addr)->sin_addr,
149 request->remote_addr_len);
150
151 request->logging_function (gftp_logging_misc, request,
152 _("Connected to %s:%d\n"), res[0].ai_canonname,
153 port);
154
155 return (sock);
156 }
157
158 #endif