]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/icmp/net_db.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / icmp / net_db.cc
index 4df0c0beaf167890a113a409a650976b90fb8f21..2e9d84381e33cdef88f2022503a06aae187c229d 100644 (file)
@@ -1,35 +1,13 @@
 /*
- * DEBUG: section 38    Network Measurement Database
- * AUTHOR: Duane Wessels
- *
- * SQUID Web Proxy Cache          http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- *  Squid is the result of efforts by numerous individuals from
- *  the Internet community; see the CONTRIBUTORS file for full
- *  details.   Many organizations have provided support for Squid's
- *  development; see the SPONSORS file for full details.  Squid is
- *  Copyrighted (C) 2001 by the Regents of the University of
- *  California; see the COPYRIGHT file for full details.  Squid
- *  incorporates software developed and/or copyrighted by other
- *  sources; see the CREDITS file for full details.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
  *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
  */
 
+/* DEBUG: section 38    Network Measurement Database */
+
 /*
  * XXX XXX XXX
  *
 #include "squid.h"
 #include "CachePeer.h"
 #include "cbdata.h"
-#include "disk.h"
 #include "event.h"
 #include "fde.h"
-#include "forward.h"
+#include "fs_io.h"
+#include "FwdState.h"
 #include "HttpReply.h"
-#include "HttpRequest.h"
 #include "icmp/net_db.h"
 #include "internal.h"
 #include "ip/Address.h"
 #include "log/File.h"
-#include "Mem.h"
 #include "MemObject.h"
 #include "mgr/Registration.h"
 #include "mime_header.h"
 #include "neighbors.h"
+#include "SquidConfig.h"
 #include "SquidTime.h"
 #include "Store.h"
 #include "StoreClient.h"
-#include "SwapDir.h"
 #include "tools.h"
-#include "URL.h"
 #include "wordlist.h"
 
 #if HAVE_SYS_STAT_H
@@ -73,7 +48,7 @@
 #include "ipcache.h"
 #include "StoreClient.h"
 
-#define        NETDB_REQBUF_SZ 4096
+#define NETDB_REQBUF_SZ 4096
 
 typedef enum {
     STATE_NONE,
@@ -81,17 +56,39 @@ typedef enum {
     STATE_BODY
 } netdb_conn_state_t;
 
-typedef struct {
-    CachePeer *p;
-    StoreEntry *e;
-    store_client *sc;
-    HttpRequest *r;
-    int64_t used;
-    size_t buf_sz;
+class netdbExchangeState
+{
+    CBDATA_CLASS(netdbExchangeState);
+
+public:
+    netdbExchangeState(CachePeer *aPeer, const HttpRequestPointer &theReq) :
+        p(aPeer),
+        r(theReq)
+    {
+        *buf = 0;
+        assert(r);
+        // TODO: check if we actually need to do this. should be implicit
+        r->http_ver = Http::ProtocolVersion();
+    }
+
+    ~netdbExchangeState() {
+        debugs(38, 3, e->url());
+        storeUnregister(sc, e, this);
+        e->unlock("netdbExchangeDone");
+    }
+
+    CbcPointer<CachePeer> p;
+    StoreEntry *e = nullptr;
+    store_client *sc = nullptr;
+    HttpRequestPointer r;
+    int64_t used = 0;
+    size_t buf_sz = NETDB_REQBUF_SZ;
     char buf[NETDB_REQBUF_SZ];
-    int buf_ofs;
-    netdb_conn_state_t connstate;
-} netdbExchangeState;
+    int buf_ofs = 0;
+    netdb_conn_state_t connstate = STATE_HEADER;
+};
+
+CBDATA_CLASS_INIT(netdbExchangeState);
 
 static hash_table *addr_table = NULL;
 static hash_table *host_table = NULL;
@@ -109,13 +106,9 @@ static net_db_peer *netdbPeerByName(const netdbEntry * n, const char *);
 static net_db_peer *netdbPeerAdd(netdbEntry * n, CachePeer * e);
 static const char *netdbPeerName(const char *name);
 static IPH netdbSendPing;
-static QS sortPeerByRtt;
-static QS sortByRtt;
-static QS netdbLRU;
 static FREE netdbFreeNameEntry;
 static FREE netdbFreeNetdbEntry;
 static STCB netdbExchangeHandleReply;
-static void netdbExchangeDone(void *);
 
 /* We have to keep a local list of CachePeer names.  The Peers structure
  * gets freed during a reconfigure.  We want this database to
@@ -126,10 +119,10 @@ static wordlist *peer_names = NULL;
 static void
 netdbHashInsert(netdbEntry * n, Ip::Address &addr)
 {
-    networkFromInaddr(addr).NtoA(n->network, MAX_IPSTRLEN);
-    n->hash.key = n->network;
+    networkFromInaddr(addr).toStr(n->network, MAX_IPSTRLEN);
+    n->key = n->network;
     assert(hash_lookup(addr_table, n->network) == NULL);
-    hash_join(addr_table, &n->hash);
+    hash_join(addr_table, n);
 }
 
 static void
@@ -145,30 +138,35 @@ netdbHashDelete(const char *key)
     hash_remove_link(addr_table, hptr);
 }
 
+net_db_name::net_db_name(const char *hostname, netdbEntry *e) :
+    next(e ? e->hosts : nullptr),
+    net_db_entry(e)
+{
+    key = xstrdup(hostname);
+    if (e) {
+        e->hosts = this;
+        ++ e->link_count;
+    }
+}
+
 static void
 netdbHostInsert(netdbEntry * n, const char *hostname)
 {
-    net_db_name *x = (net_db_name *)memAllocate(MEM_NET_DB_NAME);
-    x->hash.key = xstrdup(hostname);
-    x->next = n->hosts;
-    n->hosts = x;
-    x->net_db_entry = n;
+    net_db_name *x = new net_db_name(hostname, n);
     assert(hash_lookup(host_table, hostname) == NULL);
-    hash_join(host_table, &x->hash);
-    ++ n->link_count;
+    hash_join(host_table, x);
 }
 
 static void
 netdbHostDelete(const net_db_name * x)
 {
-    netdbEntry *n;
-    net_db_name **X;
     assert(x != NULL);
     assert(x->net_db_entry != NULL);
-    n = x->net_db_entry;
+
+    netdbEntry *n = x->net_db_entry;
     -- n->link_count;
 
-    for (X = &n->hosts; *X; X = &(*X)->next) {
+    for (auto **X = &n->hosts; *X; X = &(*X)->next) {
         if (*X == x) {
             *X = x->next;
             break;
@@ -176,8 +174,7 @@ netdbHostDelete(const net_db_name * x)
     }
 
     hash_remove_link(host_table, (hash_link *) x);
-    xfree(x->hash.key);
-    memFree((void *) x, MEM_NET_DB_NAME);
+    delete x;
 }
 
 static netdbEntry *
@@ -206,7 +203,7 @@ netdbRelease(netdbEntry * n)
 
     if (n->link_count == 0) {
         netdbHashDelete(n->network);
-        memFree(n, MEM_NETDBENTRY);
+        delete n;
     }
 }
 
@@ -233,11 +230,11 @@ netdbPurgeLRU(void)
     int k = 0;
     int list_count = 0;
     int removed = 0;
-    list = (netdbEntry **)xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *));
+    list = (netdbEntry **)xcalloc(netdbEntry::UseCount(), sizeof(netdbEntry *));
     hash_first(addr_table);
 
     while ((n = (netdbEntry *) hash_next(addr_table))) {
-        assert(list_count < memInUse(MEM_NETDBENTRY));
+        assert(list_count < netdbEntry::UseCount());
         *(list + list_count) = n;
         ++list_count;
     }
@@ -248,7 +245,7 @@ netdbPurgeLRU(void)
           netdbLRU);
 
     for (k = 0; k < list_count; ++k) {
-        if (memInUse(MEM_NETDBENTRY) < Config.Netdb.low)
+        if (netdbEntry::UseCount() < Config.Netdb.low)
             break;
 
         netdbRelease(*(list + k));
@@ -264,7 +261,7 @@ netdbLookupAddr(const Ip::Address &addr)
 {
     netdbEntry *n;
     char *key = new char[MAX_IPSTRLEN];
-    networkFromInaddr(addr).NtoA(key,MAX_IPSTRLEN);
+    networkFromInaddr(addr).toStr(key,MAX_IPSTRLEN);
     n = (netdbEntry *) hash_lookup(addr_table, key);
     delete[] key;
     return n;
@@ -275,11 +272,11 @@ netdbAdd(Ip::Address &addr)
 {
     netdbEntry *n;
 
-    if (memInUse(MEM_NETDBENTRY) > Config.Netdb.high)
+    if (netdbEntry::UseCount() > Config.Netdb.high)
         netdbPurgeLRU();
 
     if ((n = netdbLookupAddr(addr)) == NULL) {
-        n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
+        n = new netdbEntry;
         netdbHashInsert(n, addr);
     }
 
@@ -287,7 +284,7 @@ netdbAdd(Ip::Address &addr)
 }
 
 static void
-netdbSendPing(const ipcache_addrs *ia, const DnsLookupDetails &, void *data)
+netdbSendPing(const ipcache_addrs *ia, const Dns::LookupDetails &, void *data)
 {
     Ip::Address addr;
     char *hostname = NULL;
@@ -302,7 +299,7 @@ netdbSendPing(const ipcache_addrs *ia, const DnsLookupDetails &, void *data)
         return;
     }
 
-    addr = ia->in_addrs[ia->cur];
+    addr = ia->current();
 
     if ((n = netdbLookupHost(hostname)) == NULL) {
         n = netdbAdd(addr);
@@ -362,8 +359,8 @@ networkFromInaddr(const Ip::Address &in)
     out = in;
 
     /* in IPv6 the 'network' should be the routing section. */
-    if ( in.IsIPv6() ) {
-        out.ApplyMask(64, AF_INET6);
+    if ( in.isIPv6() ) {
+        out.applyMask(64, AF_INET6);
         debugs(14, 5, "networkFromInaddr : Masked IPv6 Address to " << in << "/64 routing part.");
         return out;
     }
@@ -371,7 +368,7 @@ networkFromInaddr(const Ip::Address &in)
 #if USE_CLASSFUL
     struct in_addr b;
 
-    in.GetInAddr(b);
+    in.getInAddr(b);
 
     if (IN_CLASSC(b.s_addr))
         b.s_addr &= IN_CLASSC_NET;
@@ -387,7 +384,7 @@ networkFromInaddr(const Ip::Address &in)
     debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << out << "/24.");
 
     /* use /24 for everything under IPv4 */
-    out.ApplyMask(24, AF_INET);
+    out.applyMask(24, AF_INET);
     debugs(14, 5, "networkFromInaddr : Masked IPv4 Address to " << in << "/24.");
 
     return out;
@@ -494,8 +491,9 @@ netdbSaveState(void *foo)
     unlink(Config.netdbFilename);
     lf = logfileOpen(Config.netdbFilename, 4096, 0);
 
-    if (NULL == lf) {
-        debugs(50, DBG_IMPORTANT, "netdbSaveState: " << Config.netdbFilename << ": " << xstrerror());
+    if (lf) {
+        int xerrno = errno;
+        debugs(50, DBG_IMPORTANT, MYNAME << Config.netdbFilename << ": " << xstrerr(xerrno));
         return;
     }
 
@@ -515,7 +513,7 @@ netdbSaveState(void *foo)
                       (int) n->last_use_time);
 
         for (x = n->hosts; x; x = x->next)
-            logfilePrintf(lf, " %s", hashKeyStr(&x->hash));
+            logfilePrintf(lf, " %s", hashKeyStr(x));
 
         logfilePrintf(lf, "\n");
 
@@ -591,7 +589,7 @@ netdbReloadState(void)
         if (! (addr = q) )
             continue;
 
-        if (netdbLookupAddr(addr) != NULL)     /* no dups! */
+        if (netdbLookupAddr(addr) != NULL)  /* no dups! */
             continue;
 
         if ((q = strtok(NULL, w_space)) == NULL)
@@ -632,14 +630,14 @@ netdbReloadState(void)
 
         N.last_use_time = (time_t) atoi(q);
 
-        n = (netdbEntry *)memAllocate(MEM_NETDBENTRY);
+        n = new netdbEntry;
 
         memcpy(n, &N, sizeof(netdbEntry));
 
         netdbHashInsert(n, addr);
 
         while ((q = strtok(NULL, w_space)) != NULL) {
-            if (netdbLookupHost(q) != NULL)    /* no dups! */
+            if (netdbLookupHost(q) != NULL) /* no dups! */
                 continue;
 
             netdbHostInsert(n, q);
@@ -673,15 +671,14 @@ netdbFreeNetdbEntry(void *data)
 {
     netdbEntry *n = (netdbEntry *)data;
     safe_free(n->peers);
-    memFree(n, MEM_NETDBENTRY);
+    delete n;
 }
 
 static void
 netdbFreeNameEntry(void *data)
 {
     net_db_name *x = (net_db_name *)data;
-    xfree(x->hash.key);
-    memFree(x, MEM_NET_DB_NAME);
+    delete x;
 }
 
 static void
@@ -710,18 +707,17 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
     rec_sz += 1 + sizeof(int);
     debugs(38, 3, "netdbExchangeHandleReply: " << receivedData.length << " read bytes");
 
-    if (!cbdataReferenceValid(ex->p)) {
+    if (!ex->p.valid()) {
         debugs(38, 3, "netdbExchangeHandleReply: Peer became invalid");
-        netdbExchangeDone(ex);
+        delete ex;
         return;
     }
 
     debugs(38, 3, "netdbExchangeHandleReply: for '" << ex->p->host << ":" << ex->p->http_port << "'");
 
-    if (receivedData.length == 0 &&
-            !receivedData.flags.error) {
+    if (receivedData.length == 0 && !receivedData.flags.error) {
         debugs(38, 3, "netdbExchangeHandleReply: Done");
-        netdbExchangeDone(ex);
+        delete ex;
         return;
     }
 
@@ -742,11 +738,11 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
         if ((hdr_sz = headersEnd(p, ex->buf_ofs))) {
             debugs(38, 5, "netdbExchangeHandleReply: hdr_sz = " << hdr_sz);
             rep = ex->e->getReply();
-            assert (0 != rep->sline.status);
-            debugs(38, 3, "netdbExchangeHandleReply: reply status " << rep->sline.status);
+            assert(rep->sline.status() != Http::scNone);
+            debugs(38, 3, "netdbExchangeHandleReply: reply status " << rep->sline.status());
 
-            if (HTTP_OK != rep->sline.status) {
-                netdbExchangeDone(ex);
+            if (rep->sline.status() != Http::scOkay) {
+                delete ex;
                 return;
             }
 
@@ -782,7 +778,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
 
     while (size >= rec_sz) {
         debugs(38, 5, "netdbExchangeHandleReply: in parsing loop, size = " << size);
-        addr.SetAnyAddr();
+        addr.setAnyAddr();
         hops = rtt = 0.0;
 
         for (o = 0; o < rec_sz;) {
@@ -812,13 +808,13 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
 
             default:
                 debugs(38, DBG_IMPORTANT, "netdbExchangeHandleReply: corrupt data, aborting");
-                netdbExchangeDone(ex);
+                delete ex;
                 return;
             }
         }
 
-        if (!addr.IsAnyAddr() && rtt > 0)
-            netdbExchangeUpdatePeer(addr, ex->p, rtt, hops);
+        if (!addr.isAnyAddr() && rtt > 0)
+            netdbExchangeUpdatePeer(addr, ex->p.get(), rtt, hops);
 
         assert(o == rec_sz);
 
@@ -868,7 +864,7 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
 
     if (EBIT_TEST(ex->e->flags, ENTRY_ABORTED)) {
         debugs(38, 3, "netdbExchangeHandleReply: ENTRY_ABORTED");
-        netdbExchangeDone(ex);
+        delete ex;
     } else if (ex->e->store_status == STORE_PENDING) {
         StoreIOBuffer tempBuffer;
         tempBuffer.offset = ex->used;
@@ -880,24 +876,6 @@ netdbExchangeHandleReply(void *data, StoreIOBuffer receivedData)
     }
 }
 
-static void
-netdbExchangeDone(void *data)
-{
-    netdbExchangeState *ex = (netdbExchangeState *)data;
-    debugs(38, 3, "netdbExchangeDone: " << ex->e->url()  );
-    HTTPMSGUNLOCK(ex->r);
-    storeUnregister(ex->sc, ex->e, ex);
-    ex->e->unlock();
-    cbdataReferenceDone(ex->p);
-    cbdataFree(ex);
-}
-
-static void
-netdbRegisterWithCacheManager(void)
-{
-    Mgr::RegisterAction("netdb", "Network Measurement Database", netdbDump, 0, 1);
-}
-
 #endif /* USE_ICMP */
 
 /* PUBLIC FUNCTIONS */
@@ -906,14 +884,12 @@ void
 netdbInit(void)
 {
 #if USE_ICMP
-    int n;
-
-    netdbRegisterWithCacheManager();
+    Mgr::RegisterAction("netdb", "Network Measurement Database", netdbDump, 0, 1);
 
     if (addr_table)
         return;
 
-    n = hashPrime(Config.Netdb.high / 4);
+    int n = hashPrime(Config.Netdb.high / 4);
 
     addr_table = hash_create((HASHCMP *) strcmp, n, hash_string);
 
@@ -989,23 +965,6 @@ netdbFreeMemory(void)
 #endif
 }
 
-#if 0 // AYJ: Looks to be unused code.
-int
-netdbHops(Ip::Address &addr)
-{
-#if USE_ICMP
-    netdbEntry *n = netdbLookupAddr(addr);
-
-    if (n && n->pings_recv) {
-        n->last_use_time = squid_curtime;
-        return (int) (n->hops + 0.5);
-    }
-
-#endif
-    return 256;
-}
-#endif
-
 void
 netdbDump(StoreEntry * sentry)
 {
@@ -1024,7 +983,7 @@ netdbDump(StoreEntry * sentry)
                       "RTT",
                       "Hops",
                       "Hostnames");
-    list = (netdbEntry **)xcalloc(memInUse(MEM_NETDBENTRY), sizeof(netdbEntry *));
+    list = (netdbEntry **)xcalloc(netdbEntry::UseCount(), sizeof(netdbEntry *));
     i = 0;
     hash_first(addr_table);
 
@@ -1033,9 +992,9 @@ netdbDump(StoreEntry * sentry)
         ++i;
     }
 
-    if (i != memInUse(MEM_NETDBENTRY))
+    if (i != netdbEntry::UseCount())
         debugs(38, DBG_CRITICAL, "WARNING: netdb_addrs count off, found " << i <<
-               ", expected " << memInUse(MEM_NETDBENTRY));
+               ", expected " << netdbEntry::UseCount());
 
     qsort((char *) list,
           i,
@@ -1052,7 +1011,7 @@ netdbDump(StoreEntry * sentry)
                           n->hops);
 
         for (x = n->hosts; x; x = x->next)
-            storeAppendPrintf(sentry, " %s", hashKeyStr(&x->hash));
+            storeAppendPrintf(sentry, " %s", hashKeyStr(x));
 
         storeAppendPrintf(sentry, "\n");
 
@@ -1124,18 +1083,18 @@ netdbHostData(const char *host, int *samp, int *rtt, int *hops)
 }
 
 void
-netdbUpdatePeer(HttpRequest * r, CachePeer * e, int irtt, int ihops)
+netdbUpdatePeer(const URL &url, CachePeer * e, int irtt, int ihops)
 {
 #if USE_ICMP
     netdbEntry *n;
     double rtt = (double) irtt;
     double hops = (double) ihops;
     net_db_peer *p;
-    debugs(38, 3, "netdbUpdatePeer: '" << r->GetHost() << "', " << ihops << " hops, " << irtt << " rtt");
-    n = netdbLookupHost(r->GetHost());
+    debugs(38, 3, url.host() << ", " << ihops << " hops, " << irtt << " rtt");
+    n = netdbLookupHost(url.host());
 
     if (n == NULL) {
-        debugs(38, 3, "netdbUpdatePeer: host '" << r->GetHost() << "' not found");
+        debugs(38, 3, "host " << url.host() << " not found");
         return;
     }
 
@@ -1169,7 +1128,7 @@ netdbExchangeUpdatePeer(Ip::Address &addr, CachePeer * e, double rtt, double hop
            std::setfill('0')<< std::setprecision(2) << hops << " hops, " <<
            rtt << " rtt");
 
-    if ( !addr.IsIPv4() ) {
+    if ( !addr.isIPv4() ) {
         debugs(38, 5, "netdbExchangeUpdatePeer: Aborting peer update for '" << addr << "', NetDB cannot handle IPv6.");
         return;
     }
@@ -1188,7 +1147,7 @@ netdbExchangeUpdatePeer(Ip::Address &addr, CachePeer * e, double rtt, double hop
 
     p->hops = hops;
 
-    p->expires = squid_curtime + 3600; /* XXX ? */
+    p->expires = squid_curtime + 3600;  /* XXX ? */
 
     if (n->n_peers < 2)
         return;
@@ -1232,7 +1191,7 @@ netdbBinaryExchange(StoreEntry * s)
 
     struct in_addr line_addr;
     s->buffer();
-    reply->setHeaders(HTTP_OK, "OK", NULL, -1, squid_curtime, -2);
+    reply->setHeaders(Http::scOkay, "OK", NULL, -1, squid_curtime, -2);
     s->replaceHttpReply(reply);
     rec_sz = 0;
     rec_sz += 1 + sizeof(struct in_addr);
@@ -1246,20 +1205,20 @@ netdbBinaryExchange(StoreEntry * s)
         if (0.0 == n->rtt)
             continue;
 
-        if (n->rtt > 60000)    /* RTT > 1 MIN probably bogus */
+        if (n->rtt > 60000) /* RTT > 1 MIN probably bogus */
             continue;
 
         if (! (addr = n->network) )
             continue;
 
         /* FIXME INET6 : NetDB cannot yet handle IPv6 addresses. Ensure only IPv4 get sent. */
-        if ( !addr.IsIPv4() )
+        if ( !addr.isIPv4() )
             continue;
 
         buf[i] = (char) NETDB_EX_NETWORK;
         ++i;
 
-        addr.GetInAddr(line_addr);
+        addr.getInAddr(line_addr);
         memcpy(&buf[i], &line_addr, sizeof(struct in_addr));
 
         i += sizeof(struct in_addr);
@@ -1298,7 +1257,7 @@ netdbBinaryExchange(StoreEntry * s)
     memFree(buf, MEM_4K_BUF);
 #else
 
-    reply->setHeaders(HTTP_BAD_REQUEST, "Bad Request", NULL, -1, squid_curtime, -2);
+    reply->setHeaders(Http::scBadRequest, "Bad Request", NULL, -1, squid_curtime, -2);
     s->replaceHttpReply(reply);
     storeAppendPrintf(s, "NETDB support not compiled into this Squid cache.\n");
 #endif
@@ -1306,53 +1265,41 @@ netdbBinaryExchange(StoreEntry * s)
     s->complete();
 }
 
-#if USE_ICMP
-CBDATA_TYPE(netdbExchangeState);
-#endif
-
 void
 netdbExchangeStart(void *data)
 {
 #if USE_ICMP
     CachePeer *p = (CachePeer *)data;
-    char *uri;
-    netdbExchangeState *ex;
-    StoreIOBuffer tempBuffer;
-    CBDATA_INIT_TYPE(netdbExchangeState);
-    ex = cbdataAlloc(netdbExchangeState);
-    ex->p = cbdataReference(p);
-    uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", "netdb");
-    debugs(38, 3, "netdbExchangeStart: Requesting '" << uri << "'");
-    assert(NULL != uri);
-    ex->r = HttpRequest::CreateFromUrl(uri);
-
-    if (NULL == ex->r) {
-        debugs(38, DBG_IMPORTANT, "netdbExchangeStart: Bad URI " << uri);
+    static const SBuf netDB("netdb");
+    char *uri = internalRemoteUri(p->host, p->http_port, "/squid-internal-dynamic/", netDB);
+    debugs(38, 3, "Requesting '" << uri << "'");
+    const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initIcmp);
+    HttpRequestPointer req(HttpRequest::FromUrl(uri, mx));
+
+    if (!req) {
+        debugs(38, DBG_IMPORTANT, MYNAME << ": Bad URI " << uri);
         return;
     }
 
-    HTTPMSGLOCK(ex->r);
-    assert(NULL != ex->r);
-    ex->r->http_ver = HttpVersion(1,1);
-    ex->connstate = STATE_HEADER;
+    netdbExchangeState *ex = new netdbExchangeState(p, req);
     ex->e = storeCreateEntry(uri, uri, RequestFlags(), Http::METHOD_GET);
-    ex->buf_sz = NETDB_REQBUF_SZ;
     assert(NULL != ex->e);
-    ex->sc = storeClientListAdd(ex->e, ex);
-    tempBuffer.offset = 0;
+
+    StoreIOBuffer tempBuffer;
     tempBuffer.length = ex->buf_sz;
     tempBuffer.data = ex->buf;
+
+    ex->sc = storeClientListAdd(ex->e, ex);
+
     storeClientCopy(ex->sc, ex->e, tempBuffer,
                     netdbExchangeHandleReply, ex);
-    ex->r->flags.loopDetected = 1;     /* cheat! -- force direct */
+    ex->r->flags.loopDetected = true;   /* cheat! -- force direct */
 
+    // XXX: send as Proxy-Authenticate instead
     if (p->login)
-        xstrncpy(ex->r->login, p->login, MAX_LOGIN_SZ);
-
-    urlCanonical(ex->r);
-
-    FwdState::fwdStart(Comm::ConnectionPointer(), ex->e, ex->r);
+        ex->r->url.userInfo(SBuf(p->login));
 
+    FwdState::fwdStart(Comm::ConnectionPointer(), ex->e, ex->r.getRaw());
 #endif
 }
 
@@ -1365,14 +1312,14 @@ netdbClosestParent(HttpRequest * request)
     const ipcache_addrs *ia;
     net_db_peer *h;
     int i;
-    n = netdbLookupHost(request->GetHost());
+    n = netdbLookupHost(request->url.host());
 
     if (NULL == n) {
         /* try IP addr */
-        ia = ipcache_gethostbyname(request->GetHost(), 0);
+        ia = ipcache_gethostbyname(request->url.host(), 0);
 
         if (NULL != ia)
-            n = netdbLookupAddr(ia->in_addrs[ia->cur]);
+            n = netdbLookupAddr(ia->current());
     }
 
     if (NULL == n)
@@ -1397,13 +1344,13 @@ netdbClosestParent(HttpRequest * request)
 
         p = peerFindByName(h->peername);
 
-        if (NULL == p)         /* not found */
+        if (NULL == p)      /* not found */
             continue;
 
-        if (neighborType(p, request) != PEER_PARENT)
+        if (neighborType(p, request->url) != PEER_PARENT)
             continue;
 
-        if (!peerHTTPOkay(p, request)) /* not allowed */
+        if (!peerHTTPOkay(p, request))  /* not allowed */
             continue;
 
         return p;
@@ -1412,3 +1359,4 @@ netdbClosestParent(HttpRequest * request)
 #endif
     return NULL;
 }
+