+ /* Set the buffers */
+ apr_file_buffer_set(infile, inbuffer, READ_BUF_SIZE);
+ apr_file_buffer_set(outfile, outbuffer, WRITE_BUF_SIZE);
+
+ cache = apr_hash_make(pool);
+ if (apr_pool_create(&pline, pool) != APR_SUCCESS) {
+ return 1;
+ }
+
+ while (apr_file_gets(line, LINE_BUF_SIZE, infile) == APR_SUCCESS) {
+ char *hostname;
+ char *space;
+ apr_sockaddr_t *ip;
+ apr_sockaddr_t *ipdouble;
+ char dummy[] = " " APR_EOL_STR;
+
+ if (line[0] == '\0') {
+ continue;
+ }
+
+ /* Count our log entries */
+ entries++;
+
+ /* Check if this could even be an IP address */
+ if (!apr_isxdigit(line[0]) && line[0] != ':') {
+ withname++;
+ apr_file_puts(line, outfile);
+ continue;
+ }
+
+ /* Terminate the line at the next space */
+ if ((space = strchr(line, ' ')) != NULL) {
+ *space = '\0';
+ }
+ else {
+ space = dummy;
+ }
+
+ /* See if we have it in our cache */
+ hostname = (char *) apr_hash_get(cache, line, APR_HASH_KEY_STRING);
+ if (hostname) {
+ apr_file_printf(outfile, "%s %s", hostname, space + 1);
+ cachehits++;
+ continue;
+ }
+
+ /* Parse the IP address */
+ status = apr_sockaddr_info_get(&ip, line, APR_UNSPEC, 0, 0, pline);
+ if (status != APR_SUCCESS) {
+ /* Not an IP address */
+ withname++;
+ *space = ' ';
+ apr_file_puts(line, outfile);
+ continue;
+ }
+
+ /* This does not make much sense, but historically "resolves" means
+ * "parsed as an IP address". It does not mean we actually resolved
+ * the IP address into a hostname.
+ */
+ resolves++;
+
+ /* From here on our we cache each result, even if it was not
+ * successful
+ */
+ cachesize++;
+
+ /* Try and perform a reverse lookup */
+ status = apr_getnameinfo(&hostname, ip, 0) != APR_SUCCESS;
+ if (status || hostname == NULL) {
+ /* Could not perform a reverse lookup */
+ *space = ' ';
+ apr_file_puts(line, outfile);
+ noreverse++;
+
+ /* Add to cache */
+ *space = '\0';
+ apr_hash_set(cache, line, APR_HASH_KEY_STRING,
+ apr_pstrdup(apr_hash_pool_get(cache), line));
+ continue;
+ }
+
+ /* Perform a double lookup */
+ if (doublelookups) {
+ /* Do a forward lookup on our hostname, and see if that matches our
+ * original IP address.
+ */
+ status = apr_sockaddr_info_get(&ipdouble, hostname, ip->family, 0,
+ 0, pline);
+ if (status == APR_SUCCESS ||
+ memcmp(ipdouble->ipaddr_ptr, ip->ipaddr_ptr, ip->ipaddr_len)) {
+ /* Double-lookup failed */
+ *space = ' ';
+ apr_file_puts(line, outfile);
+ doublefailed++;
+
+ /* Add to cache */
+ *space = '\0';
+ apr_hash_set(cache, line, APR_HASH_KEY_STRING,
+ apr_pstrdup(apr_hash_pool_get(cache), line));
+ continue;
+ }
+ }
+
+ /* Outout the resolved name */
+ apr_file_printf(outfile, "%s %s", hostname, space + 1);
+
+ /* Store it in the cache */
+ apr_hash_set(cache, line, APR_HASH_KEY_STRING,
+ apr_pstrdup(apr_hash_pool_get(cache), hostname));
+
+ apr_pool_clear(pline);
+ }