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