1 diff -ur suck-4.3.2-orig/active.c suck-4.3.2/active.c
2 --- suck-4.3.2-orig/active.c 2001-09-15 00:06:40.000000000 +0200
3 +++ suck-4.3.2/active.c 2007-03-22 18:56:20.000000000 +0100
6 /* connect to localhost NNTP server */
13 do_debug("Connecting to %s on port %d\n", master->localhost, port);
16 - if((fd = connect_to_nntphost(master->localhost, &hi, NULL, port, master->local_ssl, &master->local_ssl_struct)) >= 0) {
17 + if((fd = connect_to_nntphost(master->v4only, master->localhost, NULL, port, master->local_ssl, &master->local_ssl_struct)) >= 0) {
18 /* get the announcement line */
19 if(sgetline(fd, &inbuf, master->local_ssl, master->local_ssl_struct) < 0) {
21 diff -ur suck-4.3.2-orig/both.c suck-4.3.2/both.c
22 --- suck-4.3.2-orig/both.c 2003-03-25 23:38:45.000000000 +0100
23 +++ suck-4.3.2/both.c 2007-03-22 18:57:27.000000000 +0100
29 /*---------------------------------------------*/
30 -struct hostent *get_hostent(const char *host) {
31 - struct in_addr saddr;
33 - struct hostent *hi = NULL;
34 +struct addrinfo *get_addrinfo(int family, const char *host, const char *port) {
35 + struct addrinfo *hi = NULL;
40 error_log(ERRLOG_REPORT,both_phrases[0], NULL);
45 - saddr.s_addr = inet_addr(host);
46 - hi = gethostbyaddr((char *)&saddr,sizeof(struct in_addr),AF_INET);
49 - hi = gethostbyname(host);
53 + struct addrinfo hints;
55 + memset(&hints, 0, sizeof(hints));
57 + hints.ai_family = family;
58 + hints.ai_socktype = SOCK_STREAM;
59 + hints.ai_flags = AI_CANONNAME;
62 + hints.ai_flags |= AI_ADDRCONFIG;
65 +#ifdef AI_NUMERICSERV
66 + hints.ai_flags |= AI_NUMERICSERV;
69 + if (getaddrinfo(host, port, &hints, &hi))
74 /*--------------------------------------------*/
75 -int connect_to_nntphost(const char *host, struct hostent **hi, FILE *msgs, unsigned short int portnr, int do_ssl, void **ssl) {
76 +void free_addrinfo(struct addrinfo *hi)
78 + if (hi) freeaddrinfo(hi);
80 +/*--------------------------------------------*/
81 +int connect_to_nntphost(int v4only, const char *host, FILE *msgs, unsigned short int portnr, int do_ssl, void **ssl) {
83 - struct in_addr *aptr;
84 - struct in_addr saddr;
85 - struct sockaddr_in address;
87 + char *ptr_last_colon;
88 + struct addrinfo *hi;
94 SSL *ssl_struct = NULL;
95 @@ -184,65 +199,181 @@
98 /* handle host:port type syntax */
99 - realhost = strdup(host);
100 - if(realhost == NULL) {
101 + bufhost = strdup(host);
102 + if(bufhost == NULL) {
103 MyPerror("out of memory copying host name");
106 - ptr = strchr(realhost, ':');
109 + realhost = bufhost;
111 + // first count colons
114 + ptr_last_colon = NULL;
121 + ptr_last_colon = ptr;
128 + // this may be numeric IPv6 addr
129 + // check for [addr]:port syntax
131 + if (*realhost != '[')
133 + // no such syntax -- don't interpret last colon as a port separator
134 + ptr_last_colon = NULL;
138 + // skip leading '['
141 + // find trailing ']'
142 + ptr = strchr(realhost, ']');
146 + // try to recover -- just forget about last colon (if any)
147 + ptr_last_colon = NULL;
151 + // null terminate hostname
154 + if (ptr_last_colon)
156 + // check if last colon is right after ']'
157 + if (++ptr != ptr_last_colon)
159 + // well this is not the case..
160 + // try to recover again
161 + ptr_last_colon = NULL;
168 + ptr = ptr_last_colon;
171 *ptr = '\0'; /* null terminate host name */
172 portnr = atoi(++ptr); /* get port number */
177 sprintf(sport, "%hu", portnr); /* cause print_phrases wants all strings */
178 print_phrases(msgs, both_phrases[1], sport, NULL);
180 /* Find the internet address of the NNTP server */
181 - *hi = get_hostent(realhost);
183 + hi = get_addrinfo(v4only ? PF_INET : PF_UNSPEC, realhost, sport);
186 error_log(ERRLOG_REPORT,"%v1%: ",realhost, NULL);
187 MyPerror(both_phrases[2]);
193 - print_phrases(msgs, both_phrases[3], (*hi)->h_name, NULL);
194 - while((ptr = *((*hi)->h_aliases)) != NULL) {
195 - print_phrases(msgs, both_phrases[4], ptr, NULL );
196 - (*hi)->h_aliases++;
198 - if((*hi)->h_addrtype != AF_INET) {
199 - error_log(ERRLOG_REPORT, both_phrases[5], NULL);
202 + int supported_pf = 0;
203 + char *canonname = hi->ai_canonname ? hi->ai_canonname : realhost;
205 + struct addrinfo *hi_ptr = hi;
207 + char *vhost = NULL;
208 + struct addrinfo *hi_vhost = NULL;
210 + print_phrases(msgs, both_phrases[3], canonname, NULL);
214 + // init IPv6 virtual host functionality.
216 + // if the VHOST environment variable is set, try to use its value
217 + // as the local address for the outgoing connection.
219 + vhost = getenv("VHOST");
223 + hi_vhost = get_addrinfo(PF_INET6, vhost, NULL);
227 + print_phrases(msgs, "Invalid VHOST: %v1%\n", vhost, NULL);
232 - while((aptr = (struct in_addr *)*((*hi)->h_addr_list)++) != NULL) {
234 - print_phrases(msgs, both_phrases[17], inet_ntoa(*aptr), NULL);
237 - /* Create a socket */
238 - if((sockfd = socket( AF_INET, SOCK_STREAM, SOCKET_PROTOCOL)) == -1) {
239 - MyPerror(both_phrases[6]);
242 - address.sin_family = AF_INET;
243 - address.sin_port = htons(portnr); /* NNTP port */
244 - address.sin_addr= saddr;
246 - /* Establish a connection */
247 - if(connect(sockfd, (struct sockaddr *)&address, sizeof address ) == -1) {
248 - MyPerror(both_phrases[7]);
254 + if ((hi_ptr->ai_family == PF_INET) || (hi_ptr->ai_family == PF_INET6))
256 + char num_host[NI_MAXHOST];
260 + if (!getnameinfo(hi_ptr->ai_addr, hi_ptr->ai_addrlen, num_host, sizeof(num_host), NULL, 0, NI_NUMERICHOST))
261 + print_phrases(msgs, both_phrases[17], num_host, NULL);
263 + /* Create a socket */
264 + if ((sockfd = socket(hi_ptr->ai_family, SOCK_STREAM, SOCKET_PROTOCOL)) < 0)
266 + MyPerror(both_phrases[6]);
269 - print_phrases(msgs,both_phrases[8], (*hi)->h_name, NULL);
272 + if ((hi_ptr->ai_family == PF_INET6) && (hi_vhost))
274 + // IPv6 virtual host in action:
275 + // explicitly bind() the socket to the specified local address
277 + if (bind(sockfd, hi_vhost->ai_addr, hi_vhost->ai_addrlen) < 0)
279 + print_phrases(msgs, "Invalid VHOST: %v1%\n", vhost, NULL);
283 + print_phrases(msgs, "VHOST: %v1%\n", vhost, NULL);
287 + /* Establish a connection */
288 + if (connect(sockfd, hi_ptr->ai_addr, hi_ptr->ai_addrlen) < 0)
290 + MyPerror(both_phrases[7]);
296 + print_phrases(msgs, both_phrases[8], canonname, NULL);
303 + hi_ptr = hi_ptr->ai_next;
308 + error_log(ERRLOG_REPORT, both_phrases[5], NULL);
313 + free_addrinfo(hi_vhost);
316 if(sockfd > -1 && do_ssl == TRUE) {
317 if((ssl_struct = SSL_new(test1)) == NULL) {
318 diff -ur suck-4.3.2-orig/both.h suck-4.3.2/both.h
319 --- suck-4.3.2-orig/both.h 2002-08-28 00:54:34.000000000 +0200
320 +++ suck-4.3.2/both.h 2007-03-22 18:56:20.000000000 +0100
323 int sgetline(int fd, char **sbuf, int, void *);
324 int sputline(int fd, const char *outbuf, int, void *);
325 -int connect_to_nntphost(const char *host, struct hostent **, FILE *, unsigned short int, int, void **);
326 +int connect_to_nntphost(int v4only, const char *host, FILE *, unsigned short int, int, void **);
327 void disconnect_from_nntphost(int, int, void **);
328 char *number(char *sp, int *intPtr);
329 char *get_long(char *, long *);
330 -struct hostent *get_hostent(const char *host);
331 +struct addrinfo *get_addrinfo(int family, const char *host, const char *port);
332 +void free_addrinfo(struct addrinfo *hi);
333 void signal_block(int);
334 void error_log(int mode, const char *fmt, ...);
335 void MyPerror(const char *);
336 diff -ur suck-4.3.2-orig/rpost.c suck-4.3.2/rpost.c
337 --- suck-4.3.2-orig/rpost.c 2003-03-25 23:50:00.000000000 +0100
338 +++ suck-4.3.2/rpost.c 2007-03-22 18:56:20.000000000 +0100
341 PerlInterpreter *perl_int;
346 /* function declarations */
348 int main(int argc, char *argv[], char *env[]) {
350 int response, retval, loop, fargc, i;
351 - struct hostent *hi;
353 char **args, **fargs;
357 myargs.perl_int = NULL;
359 + myargs.v4only = FALSE;
361 /* have to do this next so if set on cmd line, overrides this */
362 #ifdef N_PHRASES /* in case someone nukes def */
365 do_debug("TimeOut = %d\n", TimeOut);
367 + do_debug("myargs.v4 = %d\n", myargs.v4only);
368 do_debug("myargs.debug = TRUE\n");
372 retval = RETVAL_ERROR;
375 - myargs.sockfd = connect_to_nntphost( myargs.host, &hi, myargs.status_fptr, myargs.portnr, myargs.do_ssl, &myargs.ssl_struct);
376 + myargs.sockfd = connect_to_nntphost(myargs.v4only, myargs.host, myargs.status_fptr, myargs.portnr, myargs.do_ssl, &myargs.ssl_struct);
377 if(myargs.sockfd < 0) {
378 retval = RETVAL_ERROR;
381 retval = do_article(&myargs, stdin);
384 - print_phrases(myargs.status_fptr, rpost_phrases[4], hi->h_name, NULL);
385 + print_phrases(myargs.status_fptr, rpost_phrases[4], myargs.host, NULL);
386 if(myargs.debug == TRUE) {
387 do_debug("Sending quit");
390 myargs->portnr = DEFAULT_SSL_PORT;
394 + myargs->v4only = TRUE;
397 error_log(ERRLOG_REPORT, rpost_phrases[30], argv[loop],NULL);
399 diff -ur suck-4.3.2-orig/suck.c suck-4.3.2/suck.c
400 --- suck-4.3.2-orig/suck.c 2003-03-28 20:24:54.000000000 +0100
401 +++ suck-4.3.2/suck.c 2007-03-22 18:56:20.000000000 +0100
403 ARG_HIST_FILE, ARG_HEADER_ONLY, ARG_ACTIVE_LASTREAD, ARG_USEXOVER, ARG_RESETCOUNTER, \
404 ARG_LOW_READ, ARG_SHOW_GROUP, ARG_USE_SSL, ARG_LOCAL_SSL, ARG_BATCH_POST_NR, \
409 typedef struct Arglist{
411 {"W", "wait", 2, ARG_WAIT, 46},
412 {"X", "no_xover", 0, ARG_XOVER, -1},
413 {"Z", "use_xover", 0, ARG_USEXOVER, -1},
414 + {"4", "v4", 0, ARG_V4_ONLY, -1},
419 master.local_ssl_struct = NULL;
420 master.batch_post_nr = 0;
421 master.passwd_env = FALSE;
422 + master.v4only = FALSE;
424 /* have to do this next so if set on cmd line, overrides this */
427 do_debug("master.local_ssl = %s\n", true_str(master.local_ssl));
428 do_debug("master.batch_post_nr = %d\n",master.batch_post_nr);
429 do_debug("master.passwd_env = %s\n", true_str(master.passwd_env));
430 + do_debug("master.v4 = %d\n", master.v4only);
432 do_debug("TimeOut = %d\n", TimeOut);
437 int nr, resp, retval = RETVAL_OK;
438 - struct hostent *hi;
444 fp = (which_time == CONNECT_FIRST) ? master->msgs : NULL;
446 - master->sockfd = connect_to_nntphost( master->host, &hi, fp, master->portnr, master->do_ssl, &master->ssl_struct);
447 + master->sockfd = connect_to_nntphost(master->v4only, master->host, fp, master->portnr, master->do_ssl, &master->ssl_struct);
449 if(master->sockfd < 0 ) {
450 retval = RETVAL_ERROR;
451 @@ -2132,6 +2135,9 @@
452 master->local_ssl = TRUE;
456 + master->v4only = TRUE;
461 diff -ur suck-4.3.2-orig/suck.h suck-4.3.2/suck.h
462 --- suck-4.3.2-orig/suck.h 2002-08-28 00:44:09.000000000 +0200
463 +++ suck-4.3.2/suck.h 2007-03-22 18:56:20.000000000 +0100
465 void *local_ssl_struct;
471 int get_a_chunk(PMaster, FILE *);
472 diff -ur suck-4.3.2-orig/testhost.c suck-4.3.2/testhost.c
473 --- suck-4.3.2-orig/testhost.c 2003-03-23 16:34:46.000000000 +0100
474 +++ suck-4.3.2/testhost.c 2007-03-22 18:56:20.000000000 +0100
476 int main(int argc, char *argv[]) {
478 int sockfd, response, loop, cmd, quiet, mode_reader, do_ssl, retval = RETVAL_OK;
479 - struct hostent *hi;
480 + int v4only = FALSE;
482 unsigned short int portnr;
483 FILE *fptr = stdout; /* used to print output to */
485 portnr = DEFAULT_SSL_PORT;
492 retval = RETVAL_ERROR;
493 error_log(ERRLOG_REPORT, test_phrases[7], argv[loop], NULL);
494 @@ -226,10 +229,16 @@
500 + error_log(ERRLOG_REPORT, "No host specified\n", NULL);
501 + retval = RETVAL_ERROR;
504 if(retval == RETVAL_OK) {
505 load_phrases(phrases); /* this is here so everything displays okay */
507 - sockfd = connect_to_nntphost( host, &hi, (quiet == FALSE)? fptr : NULL, portnr, do_ssl, &ssl_struct);
508 + sockfd = connect_to_nntphost(v4only, host, (quiet == FALSE)? fptr : NULL, portnr, do_ssl, &ssl_struct);
510 retval = RETVAL_ERROR;