\File{proto.c},{20:40},{Feb  4 1997}
\L{\LB{}}
\L{\LB{\C{}\/*}}
\L{\LB{ * \$Id: proto.c,v 1.3 1997\/01\/08 04:56:52 marthag Exp \$}}
\L{\LB{ *}}
\L{\LB{ * DEBUG: section 17    Neighbor Selection}}
\L{\LB{ * AUTHOR: Harvest Derived}}
\L{\LB{ *}}
\L{\LB{ * SQUID Internet Object Cache  http:\/\/squid.nlanr.net\/Squid\/}}
\L{\LB{ * \-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-}}
\L{\LB{ *}}
\L{\LB{ *  Squid is the result of efforts by numerous individuals from the}}
\L{\LB{ *  Internet community.  Development is led by Duane Wessels of the}}
\L{\LB{ *  National Laboratory for Applied Network Research and funded by}}
\L{\LB{ *  the National Science Foundation.}}
\L{\LB{ *}}
\L{\LB{ *  This program is free software; you can redistribute it and\/or modify}}
\L{\LB{ *  it under the terms of the GNU General Public License as published by}}
\L{\LB{ *  the Free Software Foundation; either version 2 of the License, or}}
\L{\LB{ *  (at your option) any later version.}}
\L{\LB{ *  }}
\L{\LB{ *  This program is distributed in the hope that it will be useful,}}
\L{\LB{ *  but WITHOUT ANY WARRANTY; without even the implied warranty of}}
\L{\LB{ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the}}
\L{\LB{ *  GNU General Public License for more details.}}
\L{\LB{ *  }}
\L{\LB{ *  You should have received a copy of the GNU General Public License}}
\L{\LB{ *  along with this program; if not, write to the Free Software}}
\L{\LB{ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.}}
\L{\LB{ *  }}
\L{\LB{ *\/\CE{}}}
\L{\LB{}}
\L{\LB{\C{}\/*}}
\L{\LB{ * Copyright (c) 1994, 1995.  All rights reserved.}}
\L{\LB{ *  }}
\L{\LB{ *   The Harvest software was developed by the Internet Research Task}}
\L{\LB{ *   Force Research Group on Resource Discovery (IRTF\-RD):}}
\L{\LB{ *  }}
\L{\LB{ *         Mic Bowman of Transarc Corporation.}}
\L{\LB{ *         Peter Danzig of the University of Southern California.}}
\L{\LB{ *         Darren R. Hardy of the University of Colorado at Boulder.}}
\L{\LB{ *         Udi Manber of the University of Arizona.}}
\L{\LB{ *         Michael F. Schwartz of the University of Colorado at Boulder.}}
\L{\LB{ *         Duane Wessels of the University of Colorado at Boulder.}}
\L{\LB{ *  }}
\L{\LB{ *   This copyright notice applies to software in the Harvest}}
\L{\LB{ *   ``src\/\'\' directory only.  Users should consult the individual}}
\L{\LB{ *   copyright notices in the ``components\/\'\' subdirectories for}}
\L{\LB{ *   copyright information about other software bundled with the}}
\L{\LB{ *   Harvest source code distribution.}}
\L{\LB{ *  }}
\L{\LB{ * TERMS OF USE}}
\L{\LB{ *   }}
\L{\LB{ *   The Harvest software may be used and re\-distributed without}}
\L{\LB{ *   charge, provided that the software origin and research team are}}
\L{\LB{ *   cited in any use of the system.  Most commonly this is}}
\L{\LB{ *   accomplished by including a link to the Harvest Home Page}}
\L{\LB{ *   (http:\/\/harvest.cs.colorado.edu\/) from the query page of any}}
\L{\LB{ *   Broker you deploy, as well as in the query result pages.  These}}
\L{\LB{ *   links are generated automatically by the standard Broker}}
\L{\LB{ *   software distribution.}}
\L{\LB{ *   }}
\L{\LB{ *   The Harvest software is provided ``as is\'\', without express or}}
\L{\LB{ *   implied warranty, and with no support nor obligation to assist}}
\L{\LB{ *   in its use, correction, modification or enhancement.  We assume}}
\L{\LB{ *   no liability with respect to the infringement of copyrights,}}
\L{\LB{ *   trade secrets, or any patents, and are not responsible for}}
\L{\LB{ *   consequential damages.  Proper use of the Harvest software is}}
\L{\LB{ *   entirely the responsibility of the user.}}
\L{\LB{ *  }}
\L{\LB{ * DERIVATIVE WORKS}}
\L{\LB{ *  }}
\L{\LB{ *   Users may make derivative works from the Harvest software, subject }}
\L{\LB{ *   to the following constraints:}}
\L{\LB{ *  }}
\L{\LB{ *     \- You must include the above copyright notice and these }}
\L{\LB{ *       accompanying paragraphs in all forms of derivative works, }}
\L{\LB{ *       and any documentation and other materials related to such }}
\L{\LB{ *       distribution and use acknowledge that the software was }}
\L{\LB{ *       developed at the above institutions.}}
\L{\LB{ *  }}
\L{\LB{ *     \- You must notify IRTF\-RD regarding your distribution of }}
\L{\LB{ *       the derivative work.}}
\L{\LB{ *  }}
\L{\LB{ *     \- You must clearly notify users that your are distributing }}
\L{\LB{ *       a modified version and not the original Harvest software.}}
\L{\LB{ *  }}
\L{\LB{ *     \- Any derivative product is also subject to these copyright }}
\L{\LB{ *       and use restrictions.}}
\L{\LB{ *  }}
\L{\LB{ *   Note that the Harvest software is NOT in the public domain.  We}}
\L{\LB{ *   retain copyright, as specified above.}}
\L{\LB{ *  }}
\L{\LB{ * HISTORY OF FREE SOFTWARE STATUS}}
\L{\LB{ *  }}
\L{\LB{ *   Originally we required sites to license the software in cases}}
\L{\LB{ *   where they were going to build commercial products\/services}}
\L{\LB{ *   around Harvest.  In June 1995 we changed this policy.  We now}}
\L{\LB{ *   allow people to use the core Harvest software (the code found in}}
\L{\LB{ *   the Harvest ``src\/\'\' directory) for free.  We made this change}}
\L{\LB{ *   in the interest of encouraging the widest possible deployment of}}
\L{\LB{ *   the technology.  The Harvest software is really a reference}}
\L{\LB{ *   implementation of a set of protocols and formats, some of which}}
\L{\LB{ *   we intend to standardize.  We encourage commercial}}
\L{\LB{ *   re\-implementations of code complying to this set of standards.  }}
\L{\LB{ *\/\CE{}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{\#include} \S{}\"squid.h\"\SE{}}}
\L{\LB{}}
\L{\LB{\K{static} \K{int} matchLocalDomain \_PARAMS((const \K{char} *));}}
\L{\LB{\K{static} \K{int} protoCantFetchObject \_PARAMS((\K{int}, StoreEntry *, \K{char} *));}}
\L{\LB{\K{static} \K{int} protoNotImplemented \_PARAMS((\K{int}, const \K{char} *, StoreEntry *));}}
\L{\LB{\K{static} \K{int} protoDNSError \_PARAMS((\K{int}, StoreEntry *));}}
\L{\LB{\K{static} \K{void} protoDataFree \_PARAMS((\K{int}, protodispatch\_data *));}}
\L{\LB{\K{static} \K{void} protoDispatchDNSHandle \_PARAMS((\K{int}, const ipcache\_addrs *, \K{void} *));}}
\L{\LB{}}
\L{\LB{\K{\#define} OUTSIDE\_FIREWALL 0}}
\L{\LB{\K{\#define} INSIDE\_FIREWALL  1}}
\L{\LB{\K{\#define} NO\_FIREWALL      2}}
\L{\LB{}}
\L{\LB{\C{}\/* for debugging *\/\CE{}}}
\L{\LB{\K{static} \K{char} *firewall\_desc\_str[] =}}
\L{\LB{\{}}
\L{\LB{    \S{}\"OUTSIDE\_FIREWALL\"\SE{},}}
\L{\LB{    \S{}\"INSIDE\_FIREWALL\"\SE{},}}
\L{\LB{    \S{}\"NO\_FIREWALL\"\SE{}}}
\L{\LB{\};}}
\L{\LB{}}
\L{\LB{\K{char} *IcpOpcodeStr[] =}}
\L{\LB{\{}}
\L{\LB{    \S{}\"ICP\_INVALID\"\SE{},}}
\L{\LB{    \S{}\"ICP\_QUERY\"\SE{},}}
\L{\LB{    \S{}\"ICP\_HIT\"\SE{},}}
\L{\LB{    \S{}\"ICP\_MISS\"\SE{},}}
\L{\LB{    \S{}\"ICP\_ERR\"\SE{},}}
\L{\LB{    \S{}\"ICP\_SEND\"\SE{},}}
\L{\LB{    \S{}\"ICP\_SENDA\"\SE{},}}
\L{\LB{    \S{}\"ICP\_DATABEG\"\SE{},}}
\L{\LB{    \S{}\"ICP\_DATA\"\SE{},}}
\L{\LB{    \S{}\"ICP\_DATAEND\"\SE{},}}
\L{\LB{    \S{}\"ICP\_SECHO\"\SE{},}}
\L{\LB{    \S{}\"ICP\_DECHO\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED0\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED1\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED2\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED3\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED4\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED5\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED6\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED7\"\SE{},}}
\L{\LB{    \S{}\"ICP\_OP\_UNUSED8\"\SE{},}}
\L{\LB{    \S{}\"ICP\_RELOADING\"\SE{},}\Tab{32}{\C{}\/* access denied while store is reloading *\/\CE{}}}
\L{\LB{    \S{}\"ICP\_DENIED\"\SE{},}}
\L{\LB{    \S{}\"ICP\_HIT\_OBJ\"\SE{},}}
\L{\LB{    \S{}\"ICP\_END\"\SE{}}}
\L{\LB{\};}}
\L{\LB{}}
\L{\LB{\K{\#if} DELAY\_HACK}}
\L{\LB{\K{extern} \K{int} \_delay\_fetch;}}
\L{\LB{\K{\#endif}}}
\L{\LB{}}
\L{\LB{\K{static} \K{void}}}
\L{\LB{\Proc{protoDataFree}protoDataFree(\K{int} fdunused, protodispatch\_data * protoData)}}
\L{\LB{\{}}
\L{\LB{    requestUnlink(protoData\-\>request);}}
\L{\LB{    safe\_free(protoData);}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\C{}\/* called when DNS lookup is done by ipcache. *\/\CE{}}}
\L{\LB{\K{static} \K{void}}}
\L{\LB{\Proc{protoDispatchDNSHandle}protoDispatchDNSHandle(\K{int} unused1, const ipcache\_addrs * ia, \K{void} *data)}}
\L{\LB{\{}}
\L{\LB{    edge *e = NULL;}}
\L{\LB{    \K{struct} in\_addr srv\_addr;}}
\L{\LB{    protodispatch\_data *protoData = (protodispatch\_data *) data;}}
\L{\LB{    StoreEntry *entry = protoData\-\>entry;}}
\L{\LB{    request\_t *req = protoData\-\>request;}}
\L{\LB{}}
\L{\LB{    \C{}\/* NOTE: We get here after a DNS lookup, whether or not the}}
\L{\LB{     * lookup was successful.  Even if the URL hostname is bad,}}
\L{\LB{     * we might still ping the hierarchy *\/\CE{}}}
\L{\LB{}}
\L{\LB{    BIT\_RESET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}}
\L{\LB{    \K{if} (protoData\-\>direct\_fetch == DIRECT\_YES) \{}}
\L{\LB{}\Tab{8}{\K{if} (ia == NULL) \{}}
\L{\LB{}\Tab{8}{    protoDNSError(protoData\-\>fd, entry);}}
\L{\LB{}\Tab{8}{    \K{return};}}
\L{\LB{}\Tab{8}{\}}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_DIRECT, 0, req\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, NULL, req);}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    \K{if} (protoData\-\>direct\_fetch == DIRECT\_MAYBE \&\& (Config.local\_ip\_list \|\| Config.firewall\_ip\_list)) \{}}
\L{\LB{}\Tab{8}{\K{if} (ia == NULL) \{}}
\L{\LB{}\Tab{8}{    debug(17, 3, \S{}\"Unknown host: \%s\!n\"\SE{}, req\-\>host);}}
\L{\LB{}\Tab{8}{    protoData\-\>direct\_fetch = DIRECT\_NO;}}
\L{\LB{}\Tab{8}{\} \K{else} \K{if} (Config.firewall\_ip\_list) \{}}
\L{\LB{}\Tab{8}{    srv\_addr = ia\-\>in\_addrs[ia\-\>cur];}}
\L{\LB{}\Tab{8}{    \K{if} (ip\_access\_check(srv\_addr, Config.firewall\_ip\_list) == IP\_DENY) \{}}
\L{\LB{}\Tab{16}{hierarchyNote(req, HIER\_LOCAL\_IP\_DIRECT, 0, req\-\>host);}}
\L{\LB{}\Tab{16}{protoStart(protoData\-\>fd, entry, NULL, req);}}
\L{\LB{}\Tab{16}{\K{return};}}
\L{\LB{}\Tab{8}{    \} \K{else} \{}}
\L{\LB{}\Tab{16}{protoData\-\>direct\_fetch = DIRECT\_NO;}}
\L{\LB{}\Tab{8}{    \}}}
\L{\LB{}\Tab{8}{\} \K{else} \K{if} (Config.local\_ip\_list) \{}}
\L{\LB{}\Tab{8}{    srv\_addr = ia\-\>in\_addrs[ia\-\>cur];}}
\L{\LB{}\Tab{8}{    \K{if} (ip\_access\_check(srv\_addr, Config.local\_ip\_list) == IP\_DENY) \{}}
\L{\LB{}\Tab{16}{hierarchyNote(req, HIER\_LOCAL\_IP\_DIRECT, 0, req\-\>host);}}
\L{\LB{}\Tab{16}{protoStart(protoData\-\>fd, entry, NULL, req);}}
\L{\LB{}\Tab{16}{\K{return};}}
\L{\LB{}\Tab{8}{    \}}}
\L{\LB{}\Tab{8}{\}}}
\L{\LB{    \}}}
\L{\LB{    \K{if} ((e = protoData\-\>single\_parent) \&\&}}
\L{\LB{}\Tab{8}{(Config.singleParentBypass \|\| protoData\-\>direct\_fetch == DIRECT\_NO)) \{}}
\L{\LB{}\Tab{8}{\C{}\/* Only one parent for this host, and okay to skip pinging stuff *\/\CE{}}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_SINGLE\_PARENT, 0, e\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, e, req);}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    \K{if} (protoData\-\>n\_edges == 0 \&\& protoData\-\>direct\_fetch == DIRECT\_NO) \{}}
\L{\LB{}\Tab{8}{\K{if} ((e = protoData\-\>default\_parent)) \{}}
\L{\LB{}\Tab{8}{    hierarchyNote(req, HIER\_DEFAULT\_PARENT, 0, e\-\>host);}}
\L{\LB{}\Tab{8}{    protoStart(protoData\-\>fd, entry, e, req);}}
\L{\LB{}\Tab{8}{\} \K{else} \{}}
\L{\LB{}\Tab{8}{    hierarchyNote(req, HIER\_NO\_DIRECT\_FAIL, 0, req\-\>host);}}
\L{\LB{}\Tab{8}{    protoCantFetchObject(protoData\-\>fd, entry, \S{}\"No neighbors or parents to query and the host is beyond your firewall.\"\SE{});}}
\L{\LB{}\Tab{8}{\}}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    \K{if} (!neighbors\_do\_private\_keys \&\& !protoData\-\>query\_neighbors \&\&}}
\L{\LB{}\Tab{8}{(e = getFirstUpParent(req))) \{}}
\L{\LB{}\Tab{8}{\C{}\/* for private objects we should just fetch directly (because}}
\L{\LB{}\Tab{8}{ * icpHandleUdp() won\'t properly deal with the ICP replies). *\/\CE{}}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_FIRSTUP\_PARENT, 0, e\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, e, req);}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \} \K{else} \K{if} (protoData\-\>direct\_fetch == DIRECT\_MAYBE \&\& ia}}
\L{\LB{}\Tab{8}{\&\& netdbHops(ia\-\>in\_addrs[ia\-\>cur]) \<= Config.minDirectHops) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_DIRECT, 0, req\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, NULL, req);}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \} \K{else} \K{if} (neighborsUdpPing(protoData)) \{}}
\L{\LB{}\Tab{8}{\C{}\/* call neighborUdpPing and start timeout routine *\/\CE{}}}
\L{\LB{}\Tab{8}{\K{if} (entry\-\>ping\_status != PING\_NONE)}}
\L{\LB{}\Tab{8}{    fatal\_dump(\S{}\"protoDispatchDNSHandle: bad ping\_status\"\SE{});}}
\L{\LB{}\Tab{8}{\K{if} (entry\-\>store\_status != STORE\_PENDING)}}
\L{\LB{}\Tab{8}{    fatal\_dump(\S{}\"protoDispatchDNSHandle: bad store\_status\"\SE{});}}
\L{\LB{}\Tab{8}{\K{if} (entry\-\>swap\_status != NO\_SWAP)}}
\L{\LB{}\Tab{8}{    fatal\_dump(\S{}\"protoDispatchDNSHandle: bad swap\_status\"\SE{});}}
\L{\LB{}\Tab{8}{entry\-\>ping\_status = PING\_WAITING;}}
\L{\LB{}\Tab{8}{commSetSelect(protoData\-\>fd,}}
\L{\LB{}\Tab{8}{    COMM\_SELECT\_TIMEOUT,}}
\L{\LB{}\Tab{8}{    (PF) getFromDefaultSource,}}
\L{\LB{}\Tab{8}{    (\K{void} *) entry,}}
\L{\LB{}\Tab{8}{    Config.neighborTimeout);}}
\L{\LB{\K{\#ifdef} DELAY\_HACK}}
\L{\LB{}\Tab{8}{\K{if} (protoData\-\>delay\_fetch \&\& entry\-\>mem\_obj)}}
\L{\LB{}\Tab{8}{    entry\-\>mem\_obj\-\>e\_pings\_n\_pings++;}}
\L{\LB{\K{\#endif}}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    \K{if} ((e = protoData\-\>default\_parent)) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_DEFAULT\_PARENT, protoData\-\>fd, e\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, e, req);}}
\L{\LB{    \} \K{else} \K{if} (protoData\-\>direct\_fetch == DIRECT\_NO) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_NO\_DIRECT\_FAIL, 0, req\-\>host);}}
\L{\LB{}\Tab{8}{protoCantFetchObject(protoData\-\>fd, entry,}}
\L{\LB{}\Tab{8}{    \S{}\"No neighbors or parents were queried and the host is beyond your firewall.\"\SE{});}}
\L{\LB{    \} \K{else} \K{if} (ia == NULL) \{}}
\L{\LB{}\Tab{8}{protoDNSError(protoData\-\>fd, entry);}}
\L{\LB{    \} \K{else} \{}}
\L{\LB{}\Tab{8}{hierarchyNote(req, HIER\_DIRECT, 0, req\-\>host);}}
\L{\LB{}\Tab{8}{protoStart(protoData\-\>fd, entry, NULL, req);}}
\L{\LB{    \}}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{int}}}
\L{\LB{\Proc{protoDispatch}protoDispatch(\K{int} fd, \K{char} *url, StoreEntry * entry, request\_t * request)}}
\L{\LB{\{}}
\L{\LB{    protodispatch\_data *protoData = NULL;}}
\L{\LB{    const \K{char} *method;}}
\L{\LB{    \K{char} *request\_hdr;}}
\L{\LB{}}
\L{\LB{    method = RequestMethodStr[request\-\>method];}}
\L{\LB{    request\_hdr = entry\-\>mem\_obj\-\>mime\_hdr;}}
\L{\LB{}}
\L{\LB{    debug(17, 5, \S{}\"protoDispatch: \%s URL: \%s\!n\"\SE{}, method, url);}}
\L{\LB{    debug(17, 10, \S{}\"request\_hdr: \%s\!n\"\SE{}, request\_hdr);}}
\L{\LB{}}
\L{\LB{    \K{if} (request\-\>protocol == PROTO\_CACHEOBJ)}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, NULL, request);}}
\L{\LB{    \K{if} (request\-\>protocol == PROTO\_WAIS)}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, NULL, request);}}
\L{\LB{}}
\L{\LB{    protoData = xcalloc(1, \K{sizeof}(protodispatch\_data));}}
\L{\LB{    protoData\-\>fd = fd;}}
\L{\LB{    protoData\-\>url = url;}}
\L{\LB{    protoData\-\>entry = entry;}}
\L{\LB{    protoData\-\>request = requestLink(request);}}
\L{\LB{    entry\-\>mem\_obj\-\>request = requestLink(request);}}
\L{\LB{    comm\_add\_close\_handler(fd,}}
\L{\LB{}\Tab{8}{(PF) protoDataFree,}}
\L{\LB{}\Tab{8}{(\K{void} *) protoData);}}
\L{\LB{}}
\L{\LB{    protoData\-\>inside\_firewall = matchInsideFirewall(request\-\>host);}}
\L{\LB{    protoData\-\>query\_neighbors = BIT\_TEST(entry\-\>flag, HIERARCHICAL);}}
\L{\LB{    \C{}\/* begin DH changes *\/\CE{}}}
\L{\LB{    \K{if} (!opt\_dynamic\_hierarchy) \{}}
\L{\LB{      protoData\-\>single\_parent = getSingleParent(request);}}
\L{\LB{      protoData\-\>default\_parent = getDefaultParent(request);}}
\L{\LB{      protoData\-\>n\_edges = neighborsCount(request);}}
\L{\LB{    \}}}
\L{\LB{    \K{else} \{}}
\L{\LB{      \K{struct} \_edge * dhparent = dhGetParent(url);}}
\L{\LB{      protoData\-\>single\_parent = dhparent;}}
\L{\LB{      protoData\-\>default\_parent = dhparent;}}
\L{\LB{      protoData\-\>n\_edges = dhNeighborsCount(dhparent);}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* end DH changes *\/\CE{}}}
\L{\LB{\K{\#ifdef} DELAY\_HACK}}
\L{\LB{    protoData\-\>delay\_fetch = \_delay\_fetch;}}
\L{\LB{\K{\#endif}}}
\L{\LB{}}
\L{\LB{    debug(17, 2, \S{}\"protoDispatch: inside\_firewall = \%d (\%s)\!n\"\SE{},}}
\L{\LB{}\Tab{8}{protoData\-\>inside\_firewall,}}
\L{\LB{}\Tab{8}{firewall\_desc\_str[protoData\-\>inside\_firewall]);}}
\L{\LB{    debug(17, 2, \S{}\"protoDispatch: query\_neighbors = \%d\!n\"\SE{}, protoData\-\>query\_neighbors);}}
\L{\LB{    debug(17, 2, \S{}\"protoDispatch:         n\_edges = \%d\!n\"\SE{}, protoData\-\>n\_edges);}}
\L{\LB{    debug(17, 2, \S{}\"protoDispatch:   single\_parent = \%s\!n\"\SE{},}}
\L{\LB{}\Tab{8}{protoData\-\>single\_parent ? protoData\-\>single\_parent\-\>host : \S{}\"N\/A\"\SE{});}}
\L{\LB{    debug(17, 2, \S{}\"protoDispatch:  default\_parent = \%s\!n\"\SE{},}}
\L{\LB{}\Tab{8}{protoData\-\>default\_parent ? protoData\-\>default\_parent\-\>host : \S{}\"N\/A\"\SE{});}}
\L{\LB{}}
\L{\LB{    \K{if} (Config.firewall\_ip\_list) \{}}
\L{\LB{}\Tab{8}{\C{}\/* Have to look up the url address so we can compare it *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>source\_ping = Config.sourcePing;}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_MAYBE;}}
\L{\LB{}\Tab{8}{BIT\_SET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}\Tab{8}{ipcache\_nbgethostbyname(request\-\>host,}}
\L{\LB{}\Tab{8}{    fd,}}
\L{\LB{}\Tab{8}{    protoDispatchDNSHandle,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \K{if} (!protoData\-\>inside\_firewall) \{}}
\L{\LB{}\Tab{8}{\C{}\/* There are firewall restrictsions, and this host is outside. *\/\CE{}}}
\L{\LB{}\Tab{8}{\C{}\/* No DNS lookups, call protoDispatchDNSHandle() directly *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>source\_ping = 0;}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_NO;}}
\L{\LB{}\Tab{8}{protoDispatchDNSHandle(fd,}}
\L{\LB{}\Tab{8}{    NULL,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \K{if} (matchLocalDomain(request\-\>host) \|\| !protoData\-\>query\_neighbors) \{}}
\L{\LB{}\Tab{8}{\C{}\/* will fetch from source *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_YES;}}
\L{\LB{}\Tab{8}{BIT\_SET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}\Tab{8}{ipcache\_nbgethostbyname(request\-\>host,}}
\L{\LB{}\Tab{8}{    fd,}}
\L{\LB{}\Tab{8}{    protoDispatchDNSHandle,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \K{if} (protoData\-\>n\_edges == 0) \{}}
\L{\LB{}\Tab{8}{\C{}\/* will fetch from source *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_YES;}}
\L{\LB{}\Tab{8}{BIT\_SET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}\Tab{8}{ipcache\_nbgethostbyname(request\-\>host,}}
\L{\LB{}\Tab{8}{    fd,}}
\L{\LB{}\Tab{8}{    protoDispatchDNSHandle,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \K{if} (Config.local\_ip\_list) \{}}
\L{\LB{}\Tab{8}{\C{}\/* Have to look up the url address so we can compare it *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>source\_ping = Config.sourcePing;}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_MAYBE;}}
\L{\LB{}\Tab{8}{BIT\_SET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}\Tab{8}{ipcache\_nbgethostbyname(request\-\>host,}}
\L{\LB{}\Tab{8}{    fd,}}
\L{\LB{}\Tab{8}{    protoDispatchDNSHandle,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \K{if} (protoData\-\>single\_parent \&\& Config.singleParentBypass \&\&}}
\L{\LB{}\Tab{8}{!(protoData\-\>source\_ping = Config.sourcePing)) \{}}
\L{\LB{}\Tab{8}{\C{}\/* will fetch from single parent *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_MAYBE;}}
\L{\LB{}\Tab{8}{protoDispatchDNSHandle(fd,}}
\L{\LB{}\Tab{8}{    NULL,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \} \K{else} \{}}
\L{\LB{}\Tab{8}{\C{}\/* will use ping resolution *\/\CE{}}}
\L{\LB{}\Tab{8}{protoData\-\>source\_ping = Config.sourcePing;}}
\L{\LB{}\Tab{8}{protoData\-\>direct\_fetch = DIRECT\_MAYBE;}}
\L{\LB{}\Tab{8}{BIT\_SET(entry\-\>flag, IP\_LOOKUP\_PENDING);}}
\L{\LB{}\Tab{8}{ipcache\_nbgethostbyname(request\-\>host,}}
\L{\LB{}\Tab{8}{    fd,}}
\L{\LB{}\Tab{8}{    protoDispatchDNSHandle,}}
\L{\LB{}\Tab{8}{    (\K{void} *) protoData);}}
\L{\LB{    \}}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{int}}}
\L{\LB{\Proc{protoUnregister}protoUnregister(\K{int} fd, StoreEntry * entry, request\_t * request, \K{struct} in\_addr src\_addr)}}
\L{\LB{\{}}
\L{\LB{    \K{char} *url = entry ? entry\-\>url : NULL;}}
\L{\LB{    \K{char} *host = request ? request\-\>host : NULL;}}
\L{\LB{    protocol\_t proto = request ? request\-\>protocol : PROTO\_NONE;}}
\L{\LB{    debug(17, 5, \S{}\"protoUnregister FD \%d \'\%s\'\!n\"\SE{}, fd, url ? url : \S{}\"NULL\"\SE{});}}
\L{\LB{    \K{if} (proto == PROTO\_CACHEOBJ)}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    \K{if} (url)}}
\L{\LB{}\Tab{8}{redirectUnregister(url, fd);}}
\L{\LB{    \K{if} (src\_addr.s\_addr != inaddr\_none)}}
\L{\LB{}\Tab{8}{fqdncacheUnregister(src\_addr, fd);}}
\L{\LB{    \K{if} (host)}}
\L{\LB{}\Tab{8}{ipcache\_unregister(host, fd);}}
\L{\LB{    \K{if} (entry == NULL)}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    \K{if} (BIT\_TEST(entry\-\>flag, ENTRY\_DISPATCHED))}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    \K{if} (entry\-\>mem\_status != NOT\_IN\_MEMORY)}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    \K{if} (entry\-\>store\_status != STORE\_PENDING)}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    protoCancelTimeout(fd, entry);}}
\L{\LB{    squid\_error\_entry(entry, ERR\_CLIENT\_ABORT, NULL);}}
\L{\LB{    \K{return} 1;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{void}}}
\L{\LB{\Proc{protoCancelTimeout}protoCancelTimeout(\K{int} fd, StoreEntry * entry)}}
\L{\LB{\{}}
\L{\LB{    \C{}\/* If fd = 0 then this thread was called from neighborsUdpAck and}}
\L{\LB{     * we must look up the FD in the pending list. *\/\CE{}}}
\L{\LB{    \K{if} (!fd)}}
\L{\LB{}\Tab{8}{fd = storeFirstClientFD(entry\-\>mem\_obj);}}
\L{\LB{    \K{if} (fd \< 1) \{}}
\L{\LB{}\Tab{8}{debug(17, 1, \S{}\"protoCancelTimeout: No client for \'\%s\'\!n\"\SE{}, entry\-\>url);}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    debug(17, 2, \S{}\"protoCancelTimeout: FD \%d \'\%s\'\!n\"\SE{}, fd, entry\-\>url);}}
\L{\LB{    \K{if} (fdstatGetType(fd) != FD\_SOCKET) \{}}
\L{\LB{}\Tab{8}{debug\_trap(\S{}\"protoCancelTimeout: called on non\-socket\"\SE{});}}
\L{\LB{}\Tab{8}{\K{return};}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* cancel the timeout handler *\/\CE{}}}
\L{\LB{    commSetSelect(fd,}}
\L{\LB{}\Tab{8}{COMM\_SELECT\_TIMEOUT,}}
\L{\LB{}\Tab{8}{NULL,}}
\L{\LB{}\Tab{8}{NULL,}}
\L{\LB{}\Tab{8}{0);}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\C{}\/*}}
\L{\LB{ *  Called from comm\_select() if neighbor pings timeout}}
\L{\LB{ *  or from neighborsUdpAck() if all neighbors miss.}}
\L{\LB{ *\/\CE{}}}
\L{\LB{\K{int}}}
\L{\LB{\Proc{getFromDefaultSource}getFromDefaultSource(\K{int} fd, StoreEntry * entry)}}
\L{\LB{\{}}
\L{\LB{    edge *e = NULL;}}
\L{\LB{    \K{char} *url = NULL;}}
\L{\LB{    request\_t *request = entry\-\>mem\_obj\-\>request;}}
\L{\LB{}}
\L{\LB{    url = entry\-\>url;}}
\L{\LB{}}
\L{\LB{    \C{}\/* if fd != 0 then we were called from comm\_select() because the}}
\L{\LB{     * timeout occured.  Otherwise we were called from neighborsUdpAck(). *\/\CE{}}}
\L{\LB{}}
\L{\LB{    \K{if} (fd) \{}}
\L{\LB{}\Tab{8}{entry\-\>ping\_status = PING\_TIMEOUT;}}
\L{\LB{}\Tab{8}{debug(17, 5, \S{}\"getFromDefaultSource: Timeout occured pinging for \'\%s\'\!n\"\SE{},}}
\L{\LB{}\Tab{8}{    url);}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* Check if someone forgot to disable the read timer *\/\CE{}}}
\L{\LB{    \K{if} (BIT\_TEST(entry\-\>flag, ENTRY\_DISPATCHED))}}
\L{\LB{}\Tab{8}{fatal\_dump(\S{}\"getFromDefaultSource: object already being fetched\"\SE{});}}
\L{\LB{    \K{if} ((e = entry\-\>mem\_obj\-\>e\_pings\_first\_miss)) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(request, HIER\_FIRST\_PARENT\_MISS, fd, e\-\>host);}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, e, request);}}
\L{\LB{    \}}}
\L{\LB{    \K{if} (matchInsideFirewall(request\-\>host)) \{}}
\L{\LB{}\Tab{8}{\K{if} (ipcache\_gethostbyname(request\-\>host, 0) == NULL)}}
\L{\LB{}\Tab{8}{    \K{return} protoDNSError(fd, entry);}}
\L{\LB{}\Tab{8}{hierarchyNote(request, HIER\_DIRECT, fd, request\-\>host);}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, NULL, request);}}
\L{\LB{    \}}}
\L{\LB{    \K{if} ((e = getDefaultParent(request))) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(request, HIER\_DEFAULT\_PARENT, fd, e\-\>host);}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, e, request);}}
\L{\LB{    \}}}
\L{\LB{    \K{if} ((e = getSingleParent(request))) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(request, HIER\_SINGLE\_PARENT, fd, e\-\>host);}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, e, request);}}
\L{\LB{    \}}}
\L{\LB{    \K{if} ((e = getFirstUpParent(request))) \{}}
\L{\LB{}\Tab{8}{hierarchyNote(request, HIER\_FIRSTUP\_PARENT, fd, e\-\>host);}}
\L{\LB{}\Tab{8}{\K{return} protoStart(fd, entry, e, request);}}
\L{\LB{    \}}}
\L{\LB{    hierarchyNote(request, HIER\_NO\_DIRECT\_FAIL, fd, request\-\>host);}}
\L{\LB{    protoCancelTimeout(fd, entry);}}
\L{\LB{    protoCantFetchObject(fd, entry,}}
\L{\LB{}\Tab{8}{\S{}\"No ICP replies received and the host is beyond the firewall.\"\SE{});}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{int}}}
\L{\LB{\Proc{protoStart}protoStart(\K{int} fd, StoreEntry * entry, edge * e, request\_t * request)}}
\L{\LB{\{}}
\L{\LB{    \K{char} *url = entry\-\>url;}}
\L{\LB{    \K{char} *request\_hdr = entry\-\>mem\_obj\-\>mime\_hdr;}}
\L{\LB{    \K{int} request\_hdr\_sz = entry\-\>mem\_obj\-\>mime\_hdr\_sz;}}
\L{\LB{    debug(17, 5, \S{}\"protoStart: FD \%d: Fetching \'\%s \%s\' from \%s\!n\"\SE{},}}
\L{\LB{}\Tab{8}{fd,}}
\L{\LB{}\Tab{8}{RequestMethodStr[request\-\>method],}}
\L{\LB{}\Tab{8}{entry\-\>url,}}
\L{\LB{}\Tab{8}{e ? e\-\>host : \S{}\"source\"\SE{});}}
\L{\LB{    \K{if} (BIT\_TEST(entry\-\>flag, ENTRY\_DISPATCHED))}}
\L{\LB{}\Tab{8}{fatal\_dump(\S{}\"protoStart: object already being fetched\"\SE{});}}
\L{\LB{    BIT\_SET(entry\-\>flag, ENTRY\_DISPATCHED);}}
\L{\LB{    protoCancelTimeout(fd, entry);}}
\L{\LB{    netdbPingSite(request\-\>host);}}
\L{\LB{    \K{if} (e) \{}}
\L{\LB{}\Tab{8}{e\-\>stats.fetches++;}}
\L{\LB{}\Tab{8}{\K{return} proxyhttpStart(url, request, entry, e);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>protocol == PROTO\_HTTP) \{}}
\L{\LB{}\Tab{8}{\K{return} httpStart(url, request, request\_hdr, request\_hdr\_sz, entry);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>protocol == PROTO\_GOPHER) \{}}
\L{\LB{}\Tab{8}{\K{return} gopherStart(fd, url, entry);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>protocol == PROTO\_FTP) \{}}
\L{\LB{}\Tab{8}{\K{return} ftpStart(fd, url, request, entry);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>protocol == PROTO\_WAIS) \{}}
\L{\LB{}\Tab{8}{\K{return} waisStart(fd, url, request\-\>method, request\_hdr, entry);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>protocol == PROTO\_CACHEOBJ) \{}}
\L{\LB{}\Tab{8}{\K{return} objcacheStart(fd, url, entry);}}
\L{\LB{    \} \K{else} \K{if} (request\-\>method == METHOD\_CONNECT) \{}}
\L{\LB{}\Tab{8}{fatal\_dump(\S{}\"protoStart() should not be handling CONNECT\"\SE{});}}
\L{\LB{}\Tab{8}{\K{return} 0;}}
\L{\LB{    \} \K{else} \{}}
\L{\LB{}\Tab{8}{\K{return} protoNotImplemented(fd, url, entry);}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* NOTREACHED *\/\CE{}}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{}}
\L{\LB{\K{static} \K{int}}}
\L{\LB{\Proc{protoNotImplemented}protoNotImplemented(\K{int} fd, const \K{char} *url, StoreEntry * entry)}}
\L{\LB{\{}}
\L{\LB{    LOCAL\_ARRAY(\K{char}, buf, 256);}}
\L{\LB{}}
\L{\LB{    debug(17, 1, \S{}\"protoNotImplemented: Cannot retrieve \'\%s\'\!n\"\SE{}, url);}}
\L{\LB{}}
\L{\LB{    buf[0] = \S{}\'\!0\'\SE{};}}
\L{\LB{    \K{if} (httpd\_accel\_mode)}}
\L{\LB{}\Tab{8}{strcpy(buf, \S{}\"cached is running in HTTPD accelerator mode, so it does not allow the normal URL syntax.\"\SE{});}}
\L{\LB{    \K{else}}}
\L{\LB{}\Tab{8}{sprintf(buf, \S{}\"Your URL may be incorrect: \'\%s\'\!n\"\SE{}, url);}}
\L{\LB{}}
\L{\LB{    squid\_error\_entry(entry, ERR\_NOT\_IMPLEMENTED, NULL);}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{static} \K{int}}}
\L{\LB{\Proc{protoCantFetchObject}protoCantFetchObject(\K{int} fd, StoreEntry * entry, \K{char} *reason)}}
\L{\LB{\{}}
\L{\LB{    LOCAL\_ARRAY(\K{char}, buf, 2048);}}
\L{\LB{}}
\L{\LB{    debug(17, 1, \S{}\"protoCantFetchObject: FD \%d \%s\!n\"\SE{}, fd, reason);}}
\L{\LB{    debug(17, 1, \S{}\"\-\-\> \'\%s\'\!n\"\SE{}, entry\-\>url);}}
\L{\LB{}}
\L{\LB{    buf[0] = \S{}\'\!0\'\SE{};}}
\L{\LB{    sprintf(buf, \S{}\"\%s\!n\!nThe cache administrator may need to double\-check the cache configuration.\"\SE{},}}
\L{\LB{}\Tab{8}{reason);}}
\L{\LB{    squid\_error\_entry(entry, ERR\_CANNOT\_FETCH, buf);}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{static} \K{int}}}
\L{\LB{\Proc{protoDNSError}protoDNSError(\K{int} fd, StoreEntry * entry)}}
\L{\LB{\{}}
\L{\LB{    debug(17, 2, \S{}\"protoDNSError: FD \%d \'\%s\'\!n\"\SE{}, fd, entry\-\>url);}}
\L{\LB{    protoCancelTimeout(fd, entry);}}
\L{\LB{    squid\_error\_entry(entry, ERR\_DNS\_FAIL, dns\_error\_message);}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\C{}\/*}}
\L{\LB{ * return 0 if the host is outside the firewall (no domains matched), and}}
\L{\LB{ * return 1 if the host is inside the firewall or no domains at all.}}
\L{\LB{ *\/\CE{}}}
\L{\LB{\K{int}}}
\L{\LB{\Proc{matchInsideFirewall}matchInsideFirewall(const \K{char} *host)}}
\L{\LB{\{}}
\L{\LB{    const wordlist *s = Config.inside\_firewall\_list;}}
\L{\LB{    const \K{char} *key = NULL;}}
\L{\LB{    \K{int} result = NO\_FIREWALL;}}
\L{\LB{    \K{struct} in\_addr addr;}}
\L{\LB{    \K{if} (!s)}}
\L{\LB{}\Tab{8}{\C{}\/* no domains, all hosts are \"inside\" the firewall *\/\CE{}}}
\L{\LB{}\Tab{8}{\K{return} NO\_FIREWALL;}}
\L{\LB{    \K{for} (; s; s = s\-\>next) \{}}
\L{\LB{}\Tab{8}{key = s\-\>key;}}
\L{\LB{}\Tab{8}{\K{if} (!strcasecmp(key, \S{}\"none\"\SE{}))}}
\L{\LB{}\Tab{8}{    \C{}\/* no domains are inside the firewall, all domains are outside *\/\CE{}}}
\L{\LB{}\Tab{8}{    \K{return} OUTSIDE\_FIREWALL;}}
\L{\LB{}\Tab{8}{\K{if} (*key == \S{}\'!\'\SE{}) \{}}
\L{\LB{}\Tab{8}{    key++;}}
\L{\LB{}\Tab{8}{    result = OUTSIDE\_FIREWALL;}}
\L{\LB{}\Tab{8}{\} \K{else} \{}}
\L{\LB{}\Tab{8}{    result = INSIDE\_FIREWALL;}}
\L{\LB{}\Tab{8}{\}}}
\L{\LB{}\Tab{8}{\K{if} (matchDomainName(key, host))}}
\L{\LB{}\Tab{8}{    \K{return} result;}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* Check for dotted\-quads *\/\CE{}}}
\L{\LB{    \K{if} (Config.firewall\_ip\_list) \{}}
\L{\LB{}\Tab{8}{\K{if} ((addr.s\_addr = inet\_addr(host)) != inaddr\_none) \{}}
\L{\LB{}\Tab{8}{    \K{if} (ip\_access\_check(addr, Config.firewall\_ip\_list) == IP\_DENY)}}
\L{\LB{}\Tab{16}{\K{return} INSIDE\_FIREWALL;}}
\L{\LB{}\Tab{8}{\}}}
\L{\LB{    \}}}
\L{\LB{    \C{}\/* all through the list and no domains matched, this host must}}
\L{\LB{     * not be inside the firewall, it must be outside *\/\CE{}}}
\L{\LB{    \K{return} OUTSIDE\_FIREWALL;}}
\L{\LB{\}}}
\L{\LB{}}
\L{\LB{\K{static} \K{int}}}
\L{\LB{\Proc{matchLocalDomain}matchLocalDomain(const \K{char} *host)}}
\L{\LB{\{}}
\L{\LB{    const wordlist *s = NULL;}}
\L{\LB{    \K{for} (s = Config.local\_domain\_list; s; s = s\-\>next) \{}}
\L{\LB{}\Tab{8}{\K{if} (matchDomainName(s\-\>key, host))}}
\L{\LB{}\Tab{8}{    \K{return} 1;}}
\L{\LB{    \}}}
\L{\LB{    \K{return} 0;}}
\L{\LB{\}}}
