1*** socket.c.org	Fri Mar 21 19:27:25 1997
2--- socket.c	Mon Sep 27 17:21:46 1999
3***************
4*** 74,82 ****
5  void    sock_host(request)
6  struct request_info *request;
7  {
8!     static struct sockaddr_in client;
9!     static struct sockaddr_in server;
10!     int     len;
11      char    buf[BUFSIZ];
12      int     fd = request->fd;
13  
14--- 74,81 ----
15  void    sock_host(request)
16  struct request_info *request;
17  {
18!     static struct sockaddr_gen client;
19!     static struct sockaddr_gen server;
20      char    buf[BUFSIZ];
21      int     fd = request->fd;
22  
23***************
24*** 91,102 ****
25       * broken library code.
26       */
27  
28!     len = sizeof(client);
29!     if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) {
30  	request->sink = sock_sink;
31! 	len = sizeof(client);
32  	if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
33! 		     (struct sockaddr *) & client, &len) < 0) {
34  	    tcpd_warn("can't get client address: %m");
35  	    return;				/* give up */
36  	}
37--- 90,102 ----
38       * broken library code.
39       */
40  
41!     client.sg_len = sizeof(client.sg_addr);
42!     if (getpeername(fd, (struct sockaddr *) ADDRP(client),
43! 	    &client.sg_len) < 0) {
44  	request->sink = sock_sink;
45! 	client.sg_len = sizeof(client.sg_addr);
46  	if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
47! 		 (struct sockaddr *) ADDRP(client), &client.sg_len) < 0) {
48  	    tcpd_warn("can't get client address: %m");
49  	    return;				/* give up */
50  	}
51***************
52*** 104,110 ****
53  	memset(buf, 0 sizeof(buf));
54  #endif
55      }
56!     request->client->sin = &client;
57  
58      /*
59       * Determine the server binding. This is used for client username
60--- 104,111 ----
61  	memset(buf, 0 sizeof(buf));
62  #endif
63      }
64!     sockgen_simplify(&client);
65!     request->client->sag = &client;
66  
67      /*
68       * Determine the server binding. This is used for client username
69***************
70*** 112,123 ****
71       * address or name.
72       */
73  
74!     len = sizeof(server);
75!     if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
76  	tcpd_warn("getsockname: %m");
77  	return;
78      }
79!     request->server->sin = &server;
80  }
81  
82  /* sock_hostaddr - map endpoint address to printable form */
83--- 113,126 ----
84       * address or name.
85       */
86  
87!     server.sg_len = sizeof(server.sg_addr);
88!     if (getsockname(fd, (struct sockaddr *) ADDRP(server), 
89! 	    &server.sg_len) < 0) {
90  	tcpd_warn("getsockname: %m");
91  	return;
92      }
93!     sockgen_simplify(&server);
94!     request->server->sag = &server;
95  }
96  
97  /* sock_hostaddr - map endpoint address to printable form */
98***************
99*** 125,134 ****
100  void    sock_hostaddr(host)
101  struct host_info *host;
102  {
103!     struct sockaddr_in *sin = host->sin;
104  
105!     if (sin != 0)
106! 	STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
107  }
108  
109  /* sock_hostname - map endpoint address to host name */
110--- 128,142 ----
111  void    sock_hostaddr(host)
112  struct host_info *host;
113  {
114!     struct sockaddr_gen *sag = host->sag;
115  
116!     if (sag != 0)
117! #ifdef HAVE_IPV6
118! 	
119! 	(void) inet_ntop(FAMILY(*sag), FADDRP(*sag), host->addr, sizeof(host->addr));
120! #else
121! 	STRN_CPY(host->addr, inet_ntoa(sag->sg_sin.sin_addr), sizeof(host->addr));
122! #endif
123  }
124  
125  /* sock_hostname - map endpoint address to host name */
126***************
127*** 136,142 ****
128  void    sock_hostname(host)
129  struct host_info *host;
130  {
131!     struct sockaddr_in *sin = host->sin;
132      struct hostent *hp;
133      int     i;
134  
135--- 144,150 ----
136  void    sock_hostname(host)
137  struct host_info *host;
138  {
139!     struct sockaddr_gen *sag = host->sag;
140      struct hostent *hp;
141      int     i;
142  
143***************
144*** 146,155 ****
145       * not work the other way around: gethostbyname("INADDR_ANY") fails. We
146       * have to special-case 0.0.0.0, in order to avoid false alerts from the
147       * host name/address checking code below.
148       */
149!     if (sin != 0 && sin->sin_addr.s_addr != 0
150! 	&& (hp = gethostbyaddr((char *) &(sin->sin_addr),
151! 			       sizeof(sin->sin_addr), AF_INET)) != 0) {
152  
153  	STRN_CPY(host->name, hp->h_name, sizeof(host->name));
154  
155--- 154,165 ----
156       * not work the other way around: gethostbyname("INADDR_ANY") fails. We
157       * have to special-case 0.0.0.0, in order to avoid false alerts from the
158       * host name/address checking code below.
159+      *
160+      * We assume this works correctly in the INET6 case.
161       */
162!     if (sag != 0
163! 	&& (FAMILY(*sag) != AF_INET || sag->sg_sin.sin_addr.s_addr != 0)
164! 	&& (hp = gethostbyaddr(FADDRP(*sag), FSIZE(*sag), FAMILY(*sag))) != 0) {
165  
166  	STRN_CPY(host->name, hp->h_name, sizeof(host->name));
167  
168***************
169*** 166,172 ****
170  	 * we're in big trouble anyway.
171  	 */
172  
173! 	if ((hp = gethostbyname(host->name)) == 0) {
174  
175  	    /*
176  	     * Unable to verify that the host name matches the address. This
177--- 176,188 ----
178  	 * we're in big trouble anyway.
179  	 */
180  
181! #ifdef HAVE_IPV6
182! 	if (FAMILY(*sag) != AF_INET)
183! 	    hp = getipnodebyname(host->name, FAMILY(*sag), AI_DEFAULT, 0);
184! 	else
185! #endif
186! 	    hp = gethostbyname(host->name);
187! 	if (hp == 0) {
188  
189  	    /*
190  	     * Unable to verify that the host name matches the address. This
191***************
192*** 189,194 ****
193--- 205,213 ----
194  		      host->name, STRING_LENGTH, hp->h_name);
195  
196  	} else {
197+ #ifdef HAVE_IPV6
198+ 	    char buf[INET6_ADDRSTRLEN];
199+ #endif
200  
201  	    /*
202  	     * The address should be a member of the address list returned by
203***************
204*** 199,207 ****
205  
206  	    for (i = 0; hp->h_addr_list[i]; i++) {
207  		if (memcmp(hp->h_addr_list[i],
208! 			   (char *) &sin->sin_addr,
209! 			   sizeof(sin->sin_addr)) == 0)
210  		    return;			/* name is good, keep it */
211  	    }
212  
213  	    /*
214--- 218,231 ----
215  
216  	    for (i = 0; hp->h_addr_list[i]; i++) {
217  		if (memcmp(hp->h_addr_list[i],
218! 			   (char *) FADDRP(*sag),
219! 			   FSIZE(*sag)) == 0) {
220! #ifdef HAVE_IPV6
221! 		    if (hp != 0 && FAMILY(*sag) != AF_INET)
222! 			freehostent(hp);
223! #endif
224  		    return;			/* name is good, keep it */
225+ 		}
226  	    }
227  
228  	    /*
229***************
230*** 209,218 ****
231  	     * someone has messed up. Perhaps someone compromised a name
232  	     * server.
233  	     */
234- 
235  	    tcpd_warn("host name/address mismatch: %s != %.*s",
236! 		      inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
237  	}
238  	strcpy(host->name, paranoid);		/* name is bad, clobber it */
239      }
240  }
241--- 233,250 ----
242  	     * someone has messed up. Perhaps someone compromised a name
243  	     * server.
244  	     */
245  	    tcpd_warn("host name/address mismatch: %s != %.*s",
246! #ifdef HAVE_IPV6
247! 		      inet_ntop(FAMILY(*sag), FADDRP(*sag), buf, sizeof(buf)),
248! #else
249! 		      inet_ntoa(sag->sg_sin.sin_addr),
250! #endif
251! 		      STRING_LENGTH, hp->h_name);
252  	}
253+ #ifdef HAVE_IPV6
254+ 	if (hp != 0 && FAMILY(*sag) != AF_INET)
255+ 	    freehostent(hp);
256+ #endif
257  	strcpy(host->name, paranoid);		/* name is bad, clobber it */
258      }
259  }
260***************
261*** 232,235 ****
262--- 264,290 ----
263       */
264  
265      (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size);
266+ }
267+ 
268+ void sockgen_simplify(sg)
269+ sockaddr_gen *sg;
270+ {
271+ #ifdef HAVE_IPV6
272+     if (sg->sg_family == AF_INET6 &&
273+ 	IN6_IS_ADDR_V4MAPPED(&sg->sg_sin6.sin6_addr)) {
274+ 	    struct sockaddr_in v4_addr;
275+ 
276+ #ifdef IN6_V4MAPPED_TO_INADDR
277+ 	    IN6_V4MAPPED_TO_INADDR(&sg->sg_sin6.sin6_addr, &v4_addr.sin_addr);
278+ #else
279+ 	    IN6_MAPPED_TO_V4(&sg->sg_sin6.sin6_addr, &v4_addr.sin_addr);
280+ #endif
281+ 	    v4_addr.sin_port = sg->sg_sin6.sin6_port;
282+ 	    v4_addr.sin_family = AF_INET;
283+ 	    memcpy(&sg->sg_sin,&v4_addr, sizeof(v4_addr));
284+ 	    sg->sg_len = sizeof(struct in_addr);
285+     }
286+ #else
287+     return;
288+ #endif
289  }
290