1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468454
Description: Implement IPv6 capability for the client Finger.
Author: Mats Erik Andersson <debian@gisladisker.se>
Forwarded: no
Last-Updated: 2010-02-09
--- a/finger/finger.c
+++ b/finger/finger.c
@@ -93,7 +93,7 @@
int main(int argc, char *argv[]) {
int ch;
int err = 0;
- struct sockaddr_in sin;
+ struct sockaddr_storage sin;
socklen_t slen = sizeof(sin);
while ((ch = getopt(argc, argv, "lmps")) != EOF) {
@@ -137,6 +137,8 @@ int main(int argc, char *argv[]) {
* Also check stdin for nofinger processing, because of older
* fingerds that make stdout a pipe for CRLF handling.
*/
+ slen = sizeof(slen); /* For safety: sockaddr_in and sockaddr_in6 */
+
if (getsockname(STDIN_FILENO, (struct sockaddr *)&sin, &slen)==0) {
enable_nofinger = 1;
}
--- a/finger/net.c
+++ b/finger/net.c
@@ -53,13 +53,12 @@
int netfinger(const char *name) {
register FILE *fp;
- struct in_addr defaddr;
register int c, sawret, ateol;
- struct hostent *hp, def;
+ struct addrinfo hints, *result, *resptr;
struct servent *sp;
- struct sockaddr_in sn;
- int s;
- char *alist[1], *host;
+ struct sockaddr_storage sn;
+ int s, status;
+ char *host;
host = strrchr(name, '@');
if (!host) return 1;
@@ -72,38 +71,46 @@ int netfinger(const char *name) {
eprintf("finger: tcp/finger: unknown service\n");
return 1;
}
- sn.sin_port = sp->s_port;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME | AI_ADDRCONFIG;
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ status = getaddrinfo(host, "finger", &hints, &result);
+ if (status != 0) {
+ eprintf("finger: unknown host: %s\n", host);
+ eprintf("getaddrinfo: %s\n", gai_strerror(status));
+ return 1;
+ }
- hp = gethostbyname(host);
- if (!hp) {
- if (!inet_aton(host, &defaddr)) {
- eprintf("finger: unknown host: %s\n", host);
- return 1;
+ for ( resptr = result; resptr; resptr = resptr->ai_next) {
+
+ if ((s = socket(resptr->ai_family, resptr->ai_socktype,
+ resptr->ai_protocol)) < 0)
+ continue;
+
+
+ /* print hostname before connecting, in case it takes a while */
+ /* This should probably be removed. */
+ /* xprintf("[%s]\n", result->ai_canonname); */
+
+ if (connect(s, resptr->ai_addr, resptr->ai_addrlen) < 0) {
+ close(s);
+ continue;
}
- def.h_name = host;
- def.h_addr_list = alist;
- def.h_addr = (char *)&defaddr;
- def.h_length = sizeof(struct in_addr);
- def.h_addrtype = AF_INET;
- def.h_aliases = 0;
- hp = &def;
- }
- sn.sin_family = hp->h_addrtype;
- if (hp->h_length > (int)sizeof(sn.sin_addr)) {
- hp->h_length = sizeof(sn.sin_addr);
- }
- memcpy(&sn.sin_addr, hp->h_addr, hp->h_length);
- if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
- eprintf("finger: socket: %s\n", strerror(errno));
- return 1;
+ /* Connection is now established.
+ /* Assemble the gained information. */
+ memcpy(&sn, resptr->ai_addr, resptr->ai_addrlen);
+ break;
}
- /* print hostname before connecting, in case it takes a while */
- xprintf("[%s]\n", hp->h_name);
- if (connect(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
+ freeaddrinfo(result);
+
+ if ( resptr == NULL ) {
+ /* Last error is still providing the correct clue. */
eprintf("finger: connect: %s\n", strerror(errno));
- close(s);
return 1;
}
|