*** socket.c.org Fri Mar 21 19:27:25 1997 --- socket.c Mon Sep 27 17:21:46 1999 *************** *** 74,82 **** void sock_host(request) struct request_info *request; { ! static struct sockaddr_in client; ! static struct sockaddr_in server; ! int len; char buf[BUFSIZ]; int fd = request->fd; --- 74,81 ---- void sock_host(request) struct request_info *request; { ! static struct sockaddr_gen client; ! static struct sockaddr_gen server; char buf[BUFSIZ]; int fd = request->fd; *************** *** 91,102 **** * broken library code. */ ! len = sizeof(client); ! if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) { request->sink = sock_sink; ! len = sizeof(client); if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK, ! (struct sockaddr *) & client, &len) < 0) { tcpd_warn("can't get client address: %m"); return; /* give up */ } --- 90,102 ---- * broken library code. */ ! client.sg_len = sizeof(client.sg_addr); ! if (getpeername(fd, (struct sockaddr *) ADDRP(client), ! &client.sg_len) < 0) { request->sink = sock_sink; ! client.sg_len = sizeof(client.sg_addr); if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK, ! (struct sockaddr *) ADDRP(client), &client.sg_len) < 0) { tcpd_warn("can't get client address: %m"); return; /* give up */ } *************** *** 104,110 **** memset(buf, 0 sizeof(buf)); #endif } ! request->client->sin = &client; /* * Determine the server binding. This is used for client username --- 104,111 ---- memset(buf, 0 sizeof(buf)); #endif } ! sockgen_simplify(&client); ! request->client->sag = &client; /* * Determine the server binding. This is used for client username *************** *** 112,123 **** * address or name. */ ! len = sizeof(server); ! if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) { tcpd_warn("getsockname: %m"); return; } ! request->server->sin = &server; } /* sock_hostaddr - map endpoint address to printable form */ --- 113,126 ---- * address or name. */ ! server.sg_len = sizeof(server.sg_addr); ! if (getsockname(fd, (struct sockaddr *) ADDRP(server), ! &server.sg_len) < 0) { tcpd_warn("getsockname: %m"); return; } ! sockgen_simplify(&server); ! request->server->sag = &server; } /* sock_hostaddr - map endpoint address to printable form */ *************** *** 125,134 **** void sock_hostaddr(host) struct host_info *host; { ! struct sockaddr_in *sin = host->sin; ! if (sin != 0) ! STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr)); } /* sock_hostname - map endpoint address to host name */ --- 128,142 ---- void sock_hostaddr(host) struct host_info *host; { ! struct sockaddr_gen *sag = host->sag; ! if (sag != 0) ! #ifdef HAVE_IPV6 ! ! (void) inet_ntop(FAMILY(*sag), FADDRP(*sag), host->addr, sizeof(host->addr)); ! #else ! STRN_CPY(host->addr, inet_ntoa(sag->sg_sin.sin_addr), sizeof(host->addr)); ! #endif } /* sock_hostname - map endpoint address to host name */ *************** *** 136,142 **** void sock_hostname(host) struct host_info *host; { ! struct sockaddr_in *sin = host->sin; struct hostent *hp; int i; --- 144,150 ---- void sock_hostname(host) struct host_info *host; { ! struct sockaddr_gen *sag = host->sag; struct hostent *hp; int i; *************** *** 146,155 **** * not work the other way around: gethostbyname("INADDR_ANY") fails. We * have to special-case 0.0.0.0, in order to avoid false alerts from the * host name/address checking code below. */ ! if (sin != 0 && sin->sin_addr.s_addr != 0 ! && (hp = gethostbyaddr((char *) &(sin->sin_addr), ! sizeof(sin->sin_addr), AF_INET)) != 0) { STRN_CPY(host->name, hp->h_name, sizeof(host->name)); --- 154,165 ---- * not work the other way around: gethostbyname("INADDR_ANY") fails. We * have to special-case 0.0.0.0, in order to avoid false alerts from the * host name/address checking code below. + * + * We assume this works correctly in the INET6 case. */ ! if (sag != 0 ! && (FAMILY(*sag) != AF_INET || sag->sg_sin.sin_addr.s_addr != 0) ! && (hp = gethostbyaddr(FADDRP(*sag), FSIZE(*sag), FAMILY(*sag))) != 0) { STRN_CPY(host->name, hp->h_name, sizeof(host->name)); *************** *** 166,172 **** * we're in big trouble anyway. */ ! if ((hp = gethostbyname(host->name)) == 0) { /* * Unable to verify that the host name matches the address. This --- 176,188 ---- * we're in big trouble anyway. */ ! #ifdef HAVE_IPV6 ! if (FAMILY(*sag) != AF_INET) ! hp = getipnodebyname(host->name, FAMILY(*sag), AI_DEFAULT, 0); ! else ! #endif ! hp = gethostbyname(host->name); ! if (hp == 0) { /* * Unable to verify that the host name matches the address. This *************** *** 189,194 **** --- 205,213 ---- host->name, STRING_LENGTH, hp->h_name); } else { + #ifdef HAVE_IPV6 + char buf[INET6_ADDRSTRLEN]; + #endif /* * The address should be a member of the address list returned by *************** *** 199,207 **** for (i = 0; hp->h_addr_list[i]; i++) { if (memcmp(hp->h_addr_list[i], ! (char *) &sin->sin_addr, ! sizeof(sin->sin_addr)) == 0) return; /* name is good, keep it */ } /* --- 218,231 ---- for (i = 0; hp->h_addr_list[i]; i++) { if (memcmp(hp->h_addr_list[i], ! (char *) FADDRP(*sag), ! FSIZE(*sag)) == 0) { ! #ifdef HAVE_IPV6 ! if (hp != 0 && FAMILY(*sag) != AF_INET) ! freehostent(hp); ! #endif return; /* name is good, keep it */ + } } /* *************** *** 209,218 **** * someone has messed up. Perhaps someone compromised a name * server. */ - tcpd_warn("host name/address mismatch: %s != %.*s", ! inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name); } strcpy(host->name, paranoid); /* name is bad, clobber it */ } } --- 233,250 ---- * someone has messed up. Perhaps someone compromised a name * server. */ tcpd_warn("host name/address mismatch: %s != %.*s", ! #ifdef HAVE_IPV6 ! inet_ntop(FAMILY(*sag), FADDRP(*sag), buf, sizeof(buf)), ! #else ! inet_ntoa(sag->sg_sin.sin_addr), ! #endif ! STRING_LENGTH, hp->h_name); } + #ifdef HAVE_IPV6 + if (hp != 0 && FAMILY(*sag) != AF_INET) + freehostent(hp); + #endif strcpy(host->name, paranoid); /* name is bad, clobber it */ } } *************** *** 232,235 **** --- 264,290 ---- */ (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size); + } + + void sockgen_simplify(sg) + sockaddr_gen *sg; + { + #ifdef HAVE_IPV6 + if (sg->sg_family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&sg->sg_sin6.sin6_addr)) { + struct sockaddr_in v4_addr; + + #ifdef IN6_V4MAPPED_TO_INADDR + IN6_V4MAPPED_TO_INADDR(&sg->sg_sin6.sin6_addr, &v4_addr.sin_addr); + #else + IN6_MAPPED_TO_V4(&sg->sg_sin6.sin6_addr, &v4_addr.sin_addr); + #endif + v4_addr.sin_port = sg->sg_sin6.sin6_port; + v4_addr.sin_family = AF_INET; + memcpy(&sg->sg_sin,&v4_addr, sizeof(v4_addr)); + sg->sg_len = sizeof(struct in_addr); + } + #else + return; + #endif }