]>
Commit | Line | Data |
---|---|---|
a9093753 JB |
1 | diff -urN cvs-1.11.2.org/src/client.c cvs-1.11.2/src/client.c |
2 | --- cvs-1.11.2.org/src/client.c Mon May 13 22:32:42 2002 | |
3 | +++ cvs-1.11.2/src/client.c Mon May 13 23:18:44 2002 | |
4 | @@ -82,7 +82,7 @@ | |
5 | /* This is needed for GSSAPI encryption. */ | |
6 | static gss_ctx_id_t gcontext; | |
7 | ||
8 | -static int connect_to_gserver PROTO((cvsroot_t *, int, struct hostent *)); | |
9 | +static int connect_to_gserver PROTO((cvsroot_t *, int, char *)); | |
10 | ||
11 | # endif /* HAVE_GSSAPI */ | |
12 | ||
13 | @@ -135,7 +135,7 @@ | |
14 | static size_t try_read_from_server PROTO ((char *, size_t)); | |
15 | ||
16 | static void auth_server PROTO ((cvsroot_t *, struct buffer *, struct buffer *, | |
17 | - int, int, struct hostent *)); | |
18 | + int, int, char *)); | |
19 | ||
20 | /* We need to keep track of the list of directories we've sent to the | |
21 | server. This list, along with the current CVSROOT, will help us | |
22 | @@ -3646,30 +3646,6 @@ | |
23 | ||
24 | ||
25 | #if defined (AUTH_CLIENT_SUPPORT) || defined (HAVE_KERBEROS) || defined (HAVE_GSSAPI) | |
26 | -static struct hostent *init_sockaddr PROTO ((struct sockaddr_in *, char *, | |
27 | - unsigned int)); | |
28 | - | |
29 | -static struct hostent * | |
30 | -init_sockaddr (name, hostname, port) | |
31 | - struct sockaddr_in *name; | |
32 | - char *hostname; | |
33 | - unsigned int port; | |
34 | -{ | |
35 | - struct hostent *hostinfo; | |
36 | - unsigned short shortport = port; | |
37 | - | |
38 | - memset (name, 0, sizeof (*name)); | |
39 | - name->sin_family = AF_INET; | |
40 | - name->sin_port = htons (shortport); | |
41 | - hostinfo = gethostbyname (hostname); | |
42 | - if (hostinfo == NULL) | |
43 | - { | |
44 | - fprintf (stderr, "Unknown host %s.\n", hostname); | |
45 | - error_exit (); | |
46 | - } | |
47 | - name->sin_addr = *(struct in_addr *) hostinfo->h_addr; | |
48 | - return hostinfo; | |
49 | -} | |
50 | ||
51 | ||
52 | ||
53 | @@ -3871,34 +3841,59 @@ | |
54 | int do_gssapi; | |
55 | { | |
56 | int sock; | |
57 | - int port_number; | |
58 | - struct sockaddr_in client_sai; | |
59 | - struct hostent *hostinfo; | |
60 | + int gerr; | |
61 | + struct addrinfo hints, *res, *res0; | |
62 | + char pbuf[32]; | |
63 | struct buffer *to_server, *from_server; | |
64 | ||
65 | - sock = socket (AF_INET, SOCK_STREAM, 0); | |
66 | - if (sock == -1) | |
67 | + sprintf (pbuf, "%u", get_cvs_port_number (root)); | |
68 | + pbuf[sizeof(pbuf)-1] = '\0'; | |
69 | + memset (&hints, 0, sizeof (hints)); | |
70 | + hints.ai_family = af; | |
71 | + hints.ai_socktype = SOCK_STREAM; | |
72 | + gerr = getaddrinfo (root->hostname, pbuf, &hints, &res0); | |
73 | + if (gerr) | |
74 | { | |
75 | - error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO)); | |
76 | + fprintf (stderr, "Unknown host %s.\n", root->hostname); | |
77 | + error_exit (); | |
78 | } | |
79 | - port_number = get_cvs_port_number (root); | |
80 | - hostinfo = init_sockaddr (&client_sai, root->hostname, port_number); | |
81 | - if (trace) | |
82 | + | |
83 | + /* Try connect to current_parsed_root->hostname using all available families */ | |
84 | + for (res = res0; res != NULL; res = res->ai_next) | |
85 | { | |
86 | - fprintf (stderr, " -> Connecting to %s(%s):%d\n", | |
87 | - root->hostname, | |
88 | - inet_ntoa (client_sai.sin_addr), port_number); | |
89 | - } | |
90 | - if (connect (sock, (struct sockaddr *) &client_sai, sizeof (client_sai)) | |
91 | - < 0) | |
92 | - error (1, 0, "connect to %s(%s):%d failed: %s", | |
93 | - root->hostname, | |
94 | - inet_ntoa (client_sai.sin_addr), | |
95 | - port_number, SOCK_STRERROR (SOCK_ERRNO)); | |
96 | + sock = socket (res->ai_family, res->ai_socktype, 0); | |
97 | + if (sock == -1) { | |
98 | + if (res->ai_next) | |
99 | + continue; | |
100 | + else { | |
101 | + char *sock_error = SOCK_STRERROR (SOCK_ERRNO); | |
102 | + freeaddrinfo(res0); | |
103 | + error (1, 0, "cannot create socket: %s", sock_error); | |
104 | + } | |
105 | + } | |
106 | + | |
107 | + if (connect (sock, res->ai_addr, res->ai_addrlen) < 0) | |
108 | + { | |
109 | + if (res->ai_next) | |
110 | + { | |
111 | + close(sock); | |
112 | + continue; | |
113 | + } | |
114 | + else | |
115 | + { | |
116 | + char *sock_error = SOCK_STRERROR (SOCK_ERRNO); | |
117 | + freeaddrinfo(res0); | |
118 | + error (1, 0, "connect to [%s]:%s failed: %s", root->hostname, | |
119 | + pbuf, sock_error); | |
120 | + } | |
121 | + } | |
122 | + /* success */ | |
123 | + break; | |
124 | + } | |
125 | ||
126 | make_bufs_from_fds (sock, sock, 0, &to_server, &from_server, 1); | |
127 | ||
128 | - auth_server (root, to_server, from_server, verify_only, do_gssapi, hostinfo); | |
129 | + auth_server (root, to_server, from_server, verify_only, do_gssapi, root->hostname); | |
130 | ||
131 | if (verify_only) | |
132 | { | |
133 | @@ -3930,13 +3925,13 @@ | |
134 | ||
135 | ||
136 | static void | |
137 | -auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostinfo) | |
138 | +auth_server (root, lto_server, lfrom_server, verify_only, do_gssapi, hostname) | |
139 | cvsroot_t *root; | |
140 | struct buffer *lto_server; | |
141 | struct buffer *lfrom_server; | |
142 | int verify_only; | |
143 | int do_gssapi; | |
144 | - struct hostent *hostinfo; | |
145 | + char *hostname; | |
146 | { | |
147 | char *username; /* the username we use to connect */ | |
148 | char no_passwd = 0; /* gets set if no password found */ | |
149 | @@ -3965,7 +3960,7 @@ | |
150 | error (1, 0, "gserver currently only enabled for socket connections"); | |
151 | } | |
152 | ||
153 | - if (! connect_to_gserver (root, fd, hostinfo)) | |
154 | + if (! connect_to_gserver (root, fd, hostname)) | |
155 | { | |
156 | error (1, 0, | |
157 | "authorization failed: server %s rejected access to %s", | |
158 | @@ -3980,7 +3975,7 @@ | |
159 | char *begin = NULL; | |
160 | char *password = NULL; | |
161 | char *end = NULL; | |
162 | - | |
163 | + | |
164 | if (verify_only) | |
165 | { | |
166 | begin = "BEGIN VERIFICATION REQUEST"; | |
167 | @@ -4117,37 +4112,76 @@ | |
168 | int s; | |
169 | const char *portenv; | |
170 | int port; | |
171 | - struct hostent *hp; | |
172 | - struct sockaddr_in sin; | |
173 | + int gerr; | |
174 | + struct addrinfo hints, *res, *res0; | |
175 | char *hname; | |
176 | - | |
177 | - s = socket (AF_INET, SOCK_STREAM, 0); | |
178 | - if (s < 0) | |
179 | - error (1, 0, "cannot create socket: %s", SOCK_STRERROR (SOCK_ERRNO)); | |
180 | + char pbuf[32], hbuf[1025]; | |
181 | ||
182 | port = get_cvs_port_number (root); | |
183 | ||
184 | - hp = init_sockaddr (&sin, root->hostname, port); | |
185 | - | |
186 | - hname = xmalloc (strlen (hp->h_name) + 1); | |
187 | - strcpy (hname, hp->h_name); | |
188 | - | |
189 | - if (trace) | |
190 | + sprintf (pbuf, "%u", port); | |
191 | + pbuf[sizeof(pbuf)-1] = '\0'; | |
192 | + memset (&hints, 0, sizeof(hints)); | |
193 | + hints.ai_family = af; | |
194 | + hints.ai_socktype = SOCK_STREAM; | |
195 | + gerr = getaddrinfo (root->hostname, pbuf, &hints, &res0); | |
196 | + if (gerr) | |
197 | { | |
198 | - fprintf (stderr, " -> Connecting to %s(%s):%d\n", | |
199 | - root->hostname, | |
200 | - inet_ntoa (sin.sin_addr), port); | |
201 | + fprintf (stderr, "Unknown host %s.\n", root->hostname); | |
202 | + error_exit (); | |
203 | } | |
204 | ||
205 | - if (connect (s, (struct sockaddr *) &sin, sizeof sin) < 0) | |
206 | - error (1, 0, "connect to %s(%s):%d failed: %s", | |
207 | - root->hostname, | |
208 | - inet_ntoa (sin.sin_addr), | |
209 | - port, SOCK_STRERROR (SOCK_ERRNO)); | |
210 | + /* Try connect to current_parsed_root->hostname using all available families */ | |
211 | + gerr = -1; | |
212 | + for (res = res0; res != NULL; res = res->ai_next) | |
213 | + { | |
214 | + s = socket (res->ai_family, res->ai_socktype, 0); | |
215 | + if (s < 0) | |
216 | + { | |
217 | + if (res->ai_next) | |
218 | + continue; | |
219 | + else | |
220 | + { | |
221 | + char *sock_error = SOCK_STRERROR (SOCK_ERRNO); | |
222 | + freeaddrinfo(res0); | |
223 | + error (1, 0, "cannot create socket: %s", sock_error); | |
224 | + } | |
225 | + } | |
226 | + if (trace) | |
227 | + { | |
228 | + char hbuf[1025]; | |
229 | + getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), | |
230 | + NULL, 0, NI_NUMERICHOST); | |
231 | + fprintf (stderr, " -> Connecting to %s(%s):%d\n", | |
232 | + root->hostname, hbuf, port); | |
233 | + } | |
234 | + | |
235 | + if (connect (s, res->ai_addr, res->ai_addrlen) < 0) | |
236 | + { | |
237 | + if (res->ai_next) | |
238 | + { | |
239 | + close(s); | |
240 | + continue; | |
241 | + } | |
242 | + else | |
243 | + { | |
244 | + char *sock_error = SOCK_STRERROR (SOCK_ERRNO); | |
245 | + freeaddrinfo(res0); | |
246 | + error (1, 0, "connect to [%s]:%s failed: %s", | |
247 | + root->hostname, pbuf, sock_error); | |
248 | + } | |
249 | + } | |
250 | + getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, 0); | |
251 | + hname = xmalloc (strlen (hbuf) + 1); | |
252 | + strcpy (hname, hbuf); | |
253 | + /* success */ | |
254 | + break; | |
255 | + } | |
256 | + freeaddrinfo(res0); | |
257 | ||
258 | { | |
259 | const char *realm; | |
260 | - struct sockaddr_in laddr; | |
261 | + struct sockaddr_storage laddr; | |
262 | int laddrlen; | |
263 | KTEXT_ST ticket; | |
264 | MSG_DAT msg_data; | |
265 | @@ -4222,10 +4256,10 @@ | |
266 | */ | |
267 | #define BUFSIZE 1024 | |
268 | static int | |
269 | -connect_to_gserver (root, sock, hostinfo) | |
270 | +connect_to_gserver (root, sock, hostname) | |
271 | cvsroot_t *root; | |
272 | int sock; | |
273 | - struct hostent *hostinfo; | |
274 | + char *hostname; | |
275 | { | |
276 | char *str; | |
277 | char buf[BUFSIZE]; | |
278 | @@ -4238,9 +4272,9 @@ | |
279 | if (send (sock, str, strlen (str), 0) < 0) | |
280 | error (1, 0, "cannot send: %s", SOCK_STRERROR (SOCK_ERRNO)); | |
281 | ||
282 | - if (strlen (hostinfo->h_name) > BUFSIZE - 5) | |
283 | + if (strlen (hostname) > BUFSIZE - 5) | |
284 | error (1, 0, "Internal error: hostname exceeds length of buffer"); | |
285 | - sprintf (buf, "cvs@%s", hostinfo->h_name); | |
286 | + sprintf (buf, "cvs@%s", hostname); | |
287 | tok_in.length = strlen (buf); | |
288 | tok_in.value = buf; | |
289 | gss_import_name (&stat_min, &tok_in, GSS_C_NT_HOSTBASED_SERVICE, | |
290 | diff -urN cvs-1.11.2.org/src/cvs.h cvs-1.11.2/src/cvs.h | |
291 | --- cvs-1.11.2.org/src/cvs.h Mon May 13 22:32:42 2002 | |
292 | +++ cvs-1.11.2/src/cvs.h Mon May 13 22:32:57 2002 | |
293 | @@ -365,6 +365,7 @@ | |
294 | extern int really_quiet, quiet; | |
295 | extern int use_editor; | |
296 | extern int cvswrite; | |
297 | +extern int af; | |
298 | extern mode_t cvsumask; | |
299 | ||
300 | ||
301 | diff -urN cvs-1.11.2.org/src/main.c cvs-1.11.2/src/main.c | |
302 | --- cvs-1.11.2.org/src/main.c Mon May 13 22:32:42 2002 | |
303 | +++ cvs-1.11.2/src/main.c Mon May 13 22:32:57 2002 | |
304 | @@ -13,6 +13,7 @@ | |
305 | */ | |
306 | ||
307 | #include <assert.h> | |
308 | +#include <sys/socket.h> | |
309 | #include "cvs.h" | |
310 | ||
311 | #ifdef HAVE_WINSOCK_H | |
312 | @@ -42,6 +43,7 @@ | |
313 | int trace = 0; | |
314 | int noexec = 0; | |
315 | int logoff = 0; | |
316 | +int af = AF_UNSPEC; | |
317 | ||
318 | /* Set if we should be writing CVSADM directories at top level. At | |
319 | least for now we'll make the default be off (the CVS 1.9, not CVS | |
320 | @@ -162,7 +164,7 @@ | |
321 | in --help as it is a rather different format from the rest. */ | |
322 | ||
323 | "Usage: %s [cvs-options] command [command-options-and-arguments]\n", | |
324 | - " where cvs-options are -q, -n, etc.\n", | |
325 | + " where cvs-options are -4, -6,-q, -n, etc.\n", | |
326 | " (specify --help-options for a list of options)\n", | |
327 | " where command is add, admin, etc.\n", | |
328 | " (specify --help-commands for a list of commands\n", | |
329 | @@ -407,7 +409,7 @@ | |
330 | int help = 0; /* Has the user asked for help? This | |
331 | lets us support the `cvs -H cmd' | |
332 | convention to give help for cmd. */ | |
333 | - static const char short_options[] = "+Qqrwtnlvb:T:e:d:Hfz:s:xa"; | |
334 | + static const char short_options[] = "+46Qqrwtnlvb:T:e:d:Hfz:s:xa"; | |
335 | static struct option long_options[] = | |
336 | { | |
337 | {"help", 0, NULL, 'H'}, | |
338 | @@ -520,6 +522,12 @@ | |
339 | /* --allow-root */ | |
340 | root_allow_add (optarg); | |
341 | break; | |
342 | + case '4': | |
343 | + af = AF_INET; | |
344 | + break; | |
345 | + case '6': | |
346 | + af = AF_INET6; | |
347 | + break; | |
348 | case 'Q': | |
349 | really_quiet = 1; | |
350 | /* FALL THROUGH */ | |
351 | diff -urN cvs-1.11.2.org/src/server.c cvs-1.11.2/src/server.c | |
352 | --- cvs-1.11.2.org/src/server.c Mon May 13 22:32:42 2002 | |
353 | +++ cvs-1.11.2/src/server.c Mon May 13 22:32:57 2002 | |
354 | @@ -5895,8 +5895,8 @@ | |
355 | { | |
356 | int status; | |
357 | char instance[INST_SZ]; | |
358 | - struct sockaddr_in peer; | |
359 | - struct sockaddr_in laddr; | |
360 | + struct sockaddr_storage peer; | |
361 | + struct sockaddr_storage laddr; | |
362 | int len; | |
363 | KTEXT_ST ticket; | |
364 | AUTH_DAT auth; | |
365 | @@ -5985,7 +5985,8 @@ | |
366 | gserver_authenticate_connection () | |
367 | { | |
368 | char hostname[MAXHOSTNAMELEN]; | |
369 | - struct hostent *hp; | |
370 | + char hbuf[1025]; | |
371 | + struct addrinfo hints, *res0; | |
372 | gss_buffer_desc tok_in, tok_out; | |
373 | char buf[1024]; | |
374 | OM_uint32 stat_min, ret; | |
375 | @@ -5995,11 +5996,16 @@ | |
376 | gss_OID mechid; | |
377 | ||
378 | gethostname (hostname, sizeof hostname); | |
379 | - hp = gethostbyname (hostname); | |
380 | - if (hp == NULL) | |
381 | + hostname[sizeof(hostname)-1] = '\0'; | |
382 | + memset (&hints, 0, sizeof(hints)); | |
383 | + hints.ai_family = af; | |
384 | + hints.ai_socktype = SOCK_STREAM; | |
385 | + hints.ai_flags = AI_CANONNAME; | |
386 | + if (getaddrinfo (hostname, NULL, &hints, &res)) | |
387 | error (1, 0, "can't get canonical hostname"); | |
388 | ||
389 | - sprintf (buf, "cvs@%s", hp->h_name); | |
390 | + sprintf (buf, "cvs@%s", res0->ai_canonname); | |
391 | + freeaddrinfo (res0); | |
392 | tok_in.value = buf; | |
393 | tok_in.length = strlen (buf); | |
394 |