Mercurial > gftp.yaz
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 |