~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/icp_v2.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2009-09-24 14:51:06 UTC
  • mfrom: (1.1.12 upstream)
  • mto: (20.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 21.
  • Revision ID: james.westby@ubuntu.com-20090924145106-38jgrzmj0d73pha5
Tags: 3.1.0.13-1
* Upload to experimental

* New upstream release
  - Fixes Follow-X-Forwarded-For support (Closes: #523943)
  - Adds IPv6 support (Closes: #432351)

* debian/rules
  - Removed obsolete configuration options
  - Enable db and radius basic authentication modules

* debian/patches/01-cf.data.debian
  - Adapted to new upstream version

* debian/patches/02-makefile-defaults
  - Adapted to new upstream version

* debian/{squid.postinst,squid.rc,README.Debian,watch}
  - Updated references to squid 3.1

* debian/squid3.install
  - Install CSS file for error pages
  - Install manual pages for new authentication modules

* debian/squid3-common.install
  - Install documented version of configuration file in /usr/share/doc/squid3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
1
/*
3
 
 * $Id: icp_v2.cc,v 1.101 2007/11/15 16:47:35 wessels Exp $
4
 
 *
5
 
 * DEBUG: section 12    Internet Cache Protocol
 
2
 * DEBUG: section 12    Internet Cache Protocol (ICP)
6
3
 * AUTHOR: Duane Wessels
7
4
 *
8
5
 * SQUID Web Proxy Cache          http://www.squid-cache.org/
21
18
 *  it under the terms of the GNU General Public License as published by
22
19
 *  the Free Software Foundation; either version 2 of the License, or
23
20
 *  (at your option) any later version.
24
 
 *  
 
21
 *
25
22
 *  This program is distributed in the hope that it will be useful,
26
23
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
27
24
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
25
 *  GNU General Public License for more details.
29
 
 *  
 
26
 *
30
27
 *  You should have received a copy of the GNU General Public License
31
28
 *  along with this program; if not, write to the Free Software
32
29
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33
30
 *
34
31
 */
35
32
 
 
33
/**
 
34
 \defgroup ServerProtocolICPInternal2 ICPv2 Internals
 
35
 \ingroup ServerProtocolICPAPI
 
36
 */
 
37
 
36
38
#include "squid.h"
37
39
#include "Store.h"
38
40
#include "comm.h"
39
41
#include "ICP.h"
40
42
#include "HttpRequest.h"
41
 
#include "ACLChecklist.h"
42
 
#include "ACL.h"
 
43
#include "acl/FilledChecklist.h"
 
44
#include "acl/Acl.h"
43
45
#include "AccessLogEntry.h"
44
46
#include "wordlist.h"
45
47
#include "SquidTime.h"
46
48
#include "SwapDir.h"
47
 
 
48
 
static void icpLogIcp(struct IN_ADDR, log_type, int, const char *, int);
49
 
 
50
 
static void icpHandleIcpV2(int, struct sockaddr_in, char *, int);
 
49
#include "icmp/net_db.h"
 
50
#include "ip/IpAddress.h"
 
51
 
 
52
/// \ingroup ServerProtocolICPInternal2
 
53
static void icpLogIcp(const IpAddress &, log_type, int, const char *, int);
 
54
 
 
55
/// \ingroup ServerProtocolICPInternal2
 
56
static void icpHandleIcpV2(int, IpAddress &, char *, int);
 
57
 
 
58
/// \ingroup ServerProtocolICPInternal2
51
59
static void icpCount(void *, int, size_t, int);
52
60
 
53
 
/*
 
61
/**
 
62
 \ingroup ServerProtocolICPInternal2
54
63
 * IcpQueueHead is global so comm_incoming() knows whether or not
55
64
 * to call icpUdpSendQueue.
56
65
 */
 
66
static icpUdpData *IcpQueueHead = NULL;
 
67
/// \ingroup ServerProtocolICPInternal2
57
68
static icpUdpData *IcpQueueTail = NULL;
58
 
static icpUdpData *IcpQueueHead = NULL;
 
69
 
 
70
/// \ingroup ServerProtocolICPInternal2
 
71
IpAddress theOutICPAddr;
59
72
 
60
73
/* icp_common_t */
61
74
_icp_common_t::_icp_common_t() : opcode(ICP_INVALID), version(0), length(0), reqnum(0), flags(0), pad(0), shostid(0)
90
103
 
91
104
/* ICPState */
92
105
 
93
 
ICPState:: ICPState(icp_common_t & aHeader, HttpRequest *aRequest):
94
 
        header(aHeader),
95
 
        request(HTTPMSGLOCK(aRequest)),
 
106
ICPState::ICPState(icp_common_t &aHeader, HttpRequest *aRequest):
 
107
        header(aHeader),
 
108
        request(HTTPMSGLOCK(aRequest)),
96
109
        fd(-1),
97
110
        url(NULL)
98
111
{}
108
121
 
109
122
/* ICP2State */
110
123
 
111
 
class ICP2State:public ICPState, public StoreClient
 
124
/// \ingroup ServerProtocolICPInternal2
 
125
class ICP2State : public ICPState, public StoreClient
112
126
{
113
127
 
114
128
public:
115
129
    ICP2State(icp_common_t & aHeader, HttpRequest *aRequest):
116
 
        ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0)
117
 
    {}
 
130
            ICPState(aHeader, aRequest),rtt(0),src_rtt(0),flags(0) {}
118
131
 
119
132
    ~ICP2State();
120
133
    void created(StoreEntry * newEntry);
124
137
    u_int32_t flags;
125
138
};
126
139
 
127
 
ICP2State::~ICP2State ()
 
140
ICP2State::~ICP2State()
128
141
{}
129
142
 
130
143
void
131
 
ICP2State::created (StoreEntry *newEntry)
 
144
ICP2State::created(StoreEntry *newEntry)
132
145
{
133
146
    StoreEntry *entry = newEntry->isNull () ? NULL : newEntry;
134
147
    debugs(12, 5, "icpHandleIcpV2: OPCODE " << icp_opcode_str[header.opcode]);
137
150
    if (icpCheckUdpHit(entry, request)) {
138
151
        codeToSend = ICP_HIT;
139
152
    } else {
 
153
#if USE_ICMP
140
154
        if (Config.onoff.test_reachability && rtt == 0) {
141
 
            if ((rtt = netdbHostRtt(request->host)) == 0)
142
 
                netdbPingSite(request->host);
 
155
            if ((rtt = netdbHostRtt(request->GetHost())) == 0)
 
156
                netdbPingSite(request->GetHost());
143
157
        }
 
158
#endif /* USE_ICMP */
144
159
 
145
160
        if (icpGetCommonOpcode() != ICP_ERR)
146
161
            codeToSend = icpGetCommonOpcode();
150
165
            codeToSend = ICP_MISS;
151
166
    }
152
167
 
153
 
    icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, &from);
 
168
    icpCreateAndSend(codeToSend, flags, url, header.reqnum, src_rtt, fd, from);
154
169
    delete this;
155
170
}
156
171
 
157
172
/* End ICP2State */
158
173
 
 
174
/// \ingroup ServerProtocolICPInternal2
159
175
static void
160
 
 
161
 
icpLogIcp(struct IN_ADDR caddr, log_type logcode, int len, const char *url, int delay)
 
176
icpLogIcp(const IpAddress &caddr, log_type logcode, int len, const char *url, int delay)
162
177
{
163
178
    AccessLogEntry al;
164
179
 
188
203
    accessLogLog(&al, NULL);
189
204
}
190
205
 
 
206
/// \ingroup ServerProtocolICPInternal2
191
207
void
192
208
icpUdpSendQueue(int fd, void *unused)
193
209
{
198
214
    while ((q = IcpQueueHead) != NULL) {
199
215
        delay = tvSubUsec(q->queue_time, current_time);
200
216
        /* increment delay to prevent looping */
201
 
        x = icpUdpSend(fd, &q->address, (icp_common_t *) q->msg, q->logcode, ++delay);
 
217
        x = icpUdpSend(fd, q->address, (icp_common_t *) q->msg, q->logcode, ++delay);
202
218
        IcpQueueHead = q->next;
203
219
        safe_free(q);
204
220
 
240
256
 
241
257
    headerp->pad = htonl(pad);
242
258
 
243
 
    headerp->shostid = theOutICPAddr.s_addr;
 
259
    theOutICPAddr.GetInAddr( *((struct in_addr*)&headerp->shostid) );
244
260
 
245
261
    urloffset = buf + sizeof(icp_common_t);
246
262
 
254
270
 
255
271
int
256
272
icpUdpSend(int fd,
257
 
 
258
 
           const struct sockaddr_in *to,
 
273
           const IpAddress &to,
259
274
           icp_common_t * msg,
260
275
           log_type logcode,
261
276
           int delay)
265
280
    int len;
266
281
    len = (int) ntohs(msg->length);
267
282
    debugs(12, 5, "icpUdpSend: FD " << fd << " sending " <<
268
 
           icp_opcode_str[msg->opcode] << ", " << len << " bytes to " <<
269
 
           inet_ntoa(to->sin_addr) << ":" << ntohs(to->sin_port));
270
 
 
271
 
    x = comm_udp_sendto(fd, to, sizeof(*to), msg, len);
272
 
 
273
 
    if (x >= 0)
274
 
    {
 
283
           icp_opcode_str[msg->opcode] << ", " << len << " bytes to " << to);
 
284
 
 
285
    x = comm_udp_sendto(fd, to, msg, len);
 
286
 
 
287
    if (x >= 0) {
275
288
        /* successfully written */
276
 
        icpLogIcp(to->sin_addr, logcode, len, (char *) (msg + 1), delay);
 
289
        icpLogIcp(to, logcode, len, (char *) (msg + 1), delay);
277
290
        icpCount(msg, SENT, (size_t) len, delay);
278
291
        safe_free(msg);
279
 
    } else if (0 == delay)
280
 
    {
 
292
    } else if (0 == delay) {
281
293
        /* send failed, but queue it */
282
294
        queue = (icpUdpData *) xcalloc(1, sizeof(icpUdpData));
283
 
        queue->address = *to;
 
295
        queue->address = to;
284
296
        queue->msg = msg;
285
297
        queue->len = (int) ntohs(msg->length);
286
298
        queue->queue_time = current_time;
299
311
 
300
312
        commSetSelect(fd, COMM_SELECT_WRITE, icpUdpSendQueue, NULL, 0);
301
313
        statCounter.icp.replies_queued++;
302
 
    } else
303
 
    {
 
314
    } else {
304
315
        /* don't queue it */
305
316
        statCounter.icp.replies_dropped++;
306
317
    }
326
337
    return 1;
327
338
}
328
339
 
329
 
/* ICP_ERR means no opcode selected here
330
 
 *
 
340
/**
331
341
 * This routine selects an ICP opcode for ICP misses.
 
342
 *
 
343
 \retval ICP_ERR            no opcode selected here
 
344
 \retval ICP_MISS_NOFETCH   store is rebuilding, no fetch is possible yet
332
345
 */
333
346
icp_opcode
334
347
icpGetCommonOpcode()
367
380
}
368
381
 
369
382
void
370
 
 
371
 
icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const struct sockaddr_in *from)
 
383
icpCreateAndSend(icp_opcode opcode, int flags, char const *url, int reqnum, int pad, int fd, const IpAddress &from)
372
384
{
373
385
    icp_common_t *reply = _icp_common_t::createMessage(opcode, flags, url, reqnum, pad);
374
386
    icpUdpSend(fd, from, reply, icpLogFromICPCode(opcode), 0);
375
387
}
376
388
 
377
389
void
378
 
 
379
 
icpDenyAccess(struct sockaddr_in *from, char *url, int reqnum, int fd)
 
390
icpDenyAccess(IpAddress &from, char *url, int reqnum, int fd)
380
391
{
381
 
    debugs(12, 2, "icpDenyAccess: Access Denied for " << inet_ntoa(from->sin_addr) << " by " << AclMatchedName << ".");
 
392
    debugs(12, 2, "icpDenyAccess: Access Denied for " << from << " by " << AclMatchedName << ".");
382
393
 
383
 
    if (clientdbCutoffDenied(from->sin_addr))
384
 
    {
 
394
    if (clientdbCutoffDenied(from)) {
385
395
        /*
386
396
         * count this DENIED query in the clientdb, even though
387
397
         * we're not sending an ICP reply...
388
398
         */
389
 
        clientdbUpdate(from->sin_addr, LOG_UDP_DENIED, PROTO_ICP, 0);
390
 
    } else
391
 
    {
 
399
        clientdbUpdate(from, LOG_UDP_DENIED, PROTO_ICP, 0);
 
400
    } else {
392
401
        icpCreateAndSend(ICP_DENIED, 0, url, reqnum, 0, fd, from);
393
402
    }
394
403
}
395
404
 
396
405
int
397
 
 
398
 
icpAccessAllowed(struct sockaddr_in *from, HttpRequest * icp_request)
 
406
icpAccessAllowed(IpAddress &from, HttpRequest * icp_request)
399
407
{
400
 
    ACLChecklist checklist;
401
 
    checklist.src_addr = from->sin_addr;
402
 
    checklist.my_addr = no_addr;
403
 
    checklist.request = HTTPMSGLOCK(icp_request);
404
 
    checklist.accessList = cbdataReference(Config.accessList.icp);
405
 
    /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
 
408
    /* absent an explicit allow, we deny all */
 
409
    if (!Config.accessList.icp)
 
410
        return 0;
 
411
 
 
412
    ACLFilledChecklist checklist(Config.accessList.icp, icp_request, NULL);
 
413
    checklist.src_addr = from;
 
414
    checklist.my_addr.SetNoAddr();
406
415
    int result = checklist.fastCheck();
407
416
    return result;
408
417
}
417
426
}
418
427
 
419
428
HttpRequest *
420
 
 
421
 
icpGetRequest(char *url, int reqnum, int fd, struct sockaddr_in * from)
 
429
icpGetRequest(char *url, int reqnum, int fd, IpAddress &from)
422
430
{
423
 
    if (strpbrk(url, w_space))
424
 
    {
 
431
    if (strpbrk(url, w_space)) {
425
432
        url = rfc1738_escape(url);
426
433
        icpCreateAndSend(ICP_ERR, 0, rfc1738_escape(url), reqnum, 0, fd, from);
427
434
        return NULL;
437
444
}
438
445
 
439
446
static void
440
 
 
441
 
doV2Query(int fd, struct sockaddr_in from, char *buf, icp_common_t header)
 
447
doV2Query(int fd, IpAddress &from, char *buf, icp_common_t header)
442
448
{
443
449
    int rtt = 0;
444
450
    int src_rtt = 0;
445
451
    u_int32_t flags = 0;
446
452
    /* We have a valid packet */
447
453
    char *url = buf + sizeof(icp_common_t) + sizeof(u_int32_t);
448
 
    HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, &from);
 
454
    HttpRequest *icp_request = icpGetRequest(url, header.reqnum, fd, from);
449
455
 
450
456
    if (!icp_request)
451
457
        return;
452
458
 
453
459
    HTTPMSGLOCK(icp_request);
454
460
 
455
 
    if (!icpAccessAllowed(&from, icp_request))
456
 
    {
457
 
        icpDenyAccess(&from, url, header.reqnum, fd);
 
461
    if (!icpAccessAllowed(from, icp_request)) {
 
462
        icpDenyAccess(from, url, header.reqnum, fd);
458
463
        HTTPMSGUNLOCK(icp_request);
459
464
        return;
460
465
    }
461
 
 
462
 
    if (header.flags & ICP_FLAG_SRC_RTT)
463
 
    {
464
 
        rtt = netdbHostRtt(icp_request->host);
465
 
        int hops = netdbHostHops(icp_request->host);
 
466
#if USE_ICMP
 
467
    if (header.flags & ICP_FLAG_SRC_RTT) {
 
468
        rtt = netdbHostRtt(icp_request->GetHost());
 
469
        int hops = netdbHostHops(icp_request->GetHost());
466
470
        src_rtt = ((hops & 0xFFFF) << 16) | (rtt & 0xFFFF);
467
471
 
468
472
        if (rtt)
469
473
            flags |= ICP_FLAG_SRC_RTT;
470
474
    }
 
475
#endif /* USE_ICMP */
471
476
 
472
477
    /* The peer is allowed to use this cache */
473
478
    ICP2State *state = new ICP2State (header, icp_request);
490
495
}
491
496
 
492
497
void
493
 
 
494
 
_icp_common_t::handleReply(char *buf, struct sockaddr_in *from)
 
498
_icp_common_t::handleReply(char *buf, IpAddress &from)
495
499
{
496
 
    if (neighbors_do_private_keys && reqnum == 0)
497
 
    {
498
 
        debugs(12, 0, "icpHandleIcpV2: Neighbor " << inet_ntoa(from->sin_addr) << " returned reqnum = 0");
 
500
    if (neighbors_do_private_keys && reqnum == 0) {
 
501
        debugs(12, 0, "icpHandleIcpV2: Neighbor " << from << " returned reqnum = 0");
499
502
        debugs(12, 0, "icpHandleIcpV2: Disabling use of private keys");
500
503
        neighbors_do_private_keys = 0;
501
504
    }
502
505
 
503
506
    char *url = buf + sizeof(icp_common_t);
504
 
    debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << inet_ntoa(from->sin_addr) << " for '" << url << "'");
 
507
    debugs(12, 3, "icpHandleIcpV2: " << icp_opcode_str[opcode] << " from " << from << " for '" << url << "'");
505
508
 
506
509
    const cache_key *key = icpGetCacheKey(url, (int) reqnum);
507
510
    /* call neighborsUdpAck even if ping_status != PING_WAITING */
509
512
}
510
513
 
511
514
static void
512
 
 
513
 
icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len)
 
515
icpHandleIcpV2(int fd, IpAddress &from, char *buf, int len)
514
516
{
515
 
    if (len <= 0)
516
 
    {
 
517
    if (len <= 0) {
517
518
        debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
518
519
        return;
519
520
    }
523
524
     * Length field should match the number of bytes read
524
525
     */
525
526
 
526
 
    if (len != header.length)
527
 
    {
 
527
    if (len != header.length) {
528
528
        debugs(12, 3, "icpHandleIcpV2: ICP message is too small");
529
529
        return;
530
530
    }
531
531
 
532
 
    switch (header.opcode)
533
 
    {
 
532
    switch (header.opcode) {
534
533
 
535
534
    case ICP_QUERY:
536
535
        /* We have a valid packet */
538
537
        break;
539
538
 
540
539
    case ICP_HIT:
541
 
#if ALLOW_SOURCE_PING
542
 
 
543
 
    case ICP_SECHO:
544
 
#endif
545
540
 
546
541
    case ICP_DECHO:
547
542
 
550
545
    case ICP_DENIED:
551
546
 
552
547
    case ICP_MISS_NOFETCH:
553
 
        header.handleReply(buf, &from);
 
548
        header.handleReply(buf, from);
554
549
        break;
555
550
 
556
551
    case ICP_INVALID:
559
554
        break;
560
555
 
561
556
    default:
562
 
        debugs(12, 0, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << inet_ntoa(from.sin_addr));
 
557
        debugs(12, 0, "icpHandleIcpV2: UNKNOWN OPCODE: " << header.opcode << " from " << from);
563
558
 
564
559
        break;
565
560
    }
570
565
icpPktDump(icp_common_t * pkt)
571
566
{
572
567
 
573
 
    struct IN_ADDR a;
 
568
    IpAddress a;
574
569
 
575
570
    debugs(12, 9, "opcode:     " << std::setw(3) << pkt->opcode  << " " << icp_opcode_str[pkt->opcode]);
576
571
    debugs(12, 9, "version: "<< std::left << std::setw(8) << pkt->version);
577
572
    debugs(12, 9, "length:  "<< std::left << std::setw(8) << ntohs(pkt->length));
578
573
    debugs(12, 9, "reqnum:  "<< std::left << std::setw(8) << ntohl(pkt->reqnum));
579
574
    debugs(12, 9, "flags:   "<< std::left << std::hex << std::setw(8) << ntohl(pkt->flags));
580
 
    a.s_addr = pkt->shostid;
581
 
    debugs(12, 9, "shostid: " << inet_ntoa(a));
 
575
    a = (struct in_addr)pkt->shostid;
 
576
    debugs(12, 9, "shostid: " << a );
582
577
    debugs(12, 9, "payload: " << (char *) pkt + sizeof(icp_common_t));
583
578
}
584
579
 
589
584
{
590
585
    int *N = &incoming_sockets_accepted;
591
586
 
592
 
    struct sockaddr_in from;
593
 
    socklen_t from_len;
 
587
    IpAddress from;
594
588
    LOCAL_ARRAY(char, buf, SQUID_UDP_SO_RCVBUF);
595
589
    int len;
596
590
    int icp_version;
598
592
    commSetSelect(sock, COMM_SELECT_READ, icpHandleUdp, NULL, 0);
599
593
 
600
594
    while (max--) {
601
 
        from_len = sizeof(from);
602
 
        memset(&from, '\0', from_len);
603
595
        len = comm_udp_recvfrom(sock,
604
596
                                buf,
605
597
                                SQUID_UDP_SO_RCVBUF - 1,
606
598
                                0,
607
 
 
608
 
                                (struct sockaddr *) &from,
609
 
                                &from_len);
 
599
                                from);
610
600
 
611
601
        if (len == 0)
612
602
            break;
632
622
        icpCount(buf, RECV, (size_t) len, 0);
633
623
        buf[len] = '\0';
634
624
        debugs(12, 4, "icpHandleUdp: FD " << sock << ": received " <<
635
 
               (unsigned long int)len << " bytes from " <<
636
 
               inet_ntoa(from.sin_addr) << ".");
 
625
               (unsigned long int)len << " bytes from " << from);
637
626
 
638
627
#ifdef ICP_PACKET_DUMP
639
628
 
652
641
        else if (icp_version == ICP_VERSION_3)
653
642
            icpHandleIcpV3(sock, from, buf, len);
654
643
        else
655
 
        debugs(12, 1, "WARNING: Unused ICP version " << icp_version <<
656
 
               " received from " << inet_ntoa(from.sin_addr) << ":" << ntohs(from.sin_port));
 
644
            debugs(12, 1, "WARNING: Unused ICP version " << icp_version <<
 
645
                   " received from " << from);
657
646
    }
658
647
}
659
648
 
662
651
{
663
652
    u_int16_t port;
664
653
 
665
 
    struct IN_ADDR addr;
 
654
    IpAddress addr;
666
655
 
667
 
    struct sockaddr_in xaddr;
 
656
    struct addrinfo *xai = NULL;
668
657
    int x;
669
 
    socklen_t len;
670
658
    wordlist *s;
671
659
 
672
660
    if ((port = Config.Port.icp) <= 0)
674
662
 
675
663
    enter_suid();
676
664
 
677
 
    theInIcpConnection = comm_open(SOCK_DGRAM,
678
 
                                   IPPROTO_UDP,
679
 
                                   Config.Addrs.udp_incoming,
680
 
                                   port,
681
 
                                   COMM_NONBLOCKING,
682
 
                                   "ICP Socket");
683
 
 
 
665
    addr = Config.Addrs.udp_incoming;
 
666
    addr.SetPort(port);
 
667
    theInIcpConnection = comm_open_listener(SOCK_DGRAM,
 
668
                                            IPPROTO_UDP,
 
669
                                            addr,
 
670
                                            COMM_NONBLOCKING,
 
671
                                            "ICP Socket");
684
672
    leave_suid();
685
673
 
686
674
    if (theInIcpConnection < 0)
695
683
    for (s = Config.mcast_group_list; s; s = s->next)
696
684
        ipcache_nbgethostbyname(s->key, mcastJoinGroups, NULL);
697
685
 
698
 
        debugs(12, 1, "Accepting ICP messages at " <<
699
 
               inet_ntoa(Config.Addrs.udp_incoming) << ", port " << (int) port <<
700
 
               ", FD " << theInIcpConnection << ".");
701
 
 
702
 
 
703
 
    if ((addr = Config.Addrs.udp_outgoing).s_addr != no_addr.s_addr) {
 
686
    debugs(12, 1, "Accepting ICP messages at " << addr << ", FD " << theInIcpConnection << ".");
 
687
 
 
688
    addr.SetEmpty(); // clear for next use.
 
689
    addr = Config.Addrs.udp_outgoing;
 
690
    if ( !addr.IsNoAddr() ) {
704
691
        enter_suid();
705
 
        theOutIcpConnection = comm_open(SOCK_DGRAM,
706
 
                                        IPPROTO_UDP,
707
 
                                        addr,
708
 
                                        port,
709
 
                                        COMM_NONBLOCKING,
710
 
                                        "ICP Port");
 
692
        addr.SetPort(port);
 
693
        theOutIcpConnection = comm_open_listener(SOCK_DGRAM,
 
694
                              IPPROTO_UDP,
 
695
                              addr,
 
696
                              COMM_NONBLOCKING,
 
697
                              "ICP Port");
711
698
        leave_suid();
712
699
 
713
700
        if (theOutIcpConnection < 0)
719
706
                      NULL,
720
707
                      0);
721
708
 
722
 
        debugs(12, 1, "Outgoing ICP messages on port " << port << ", FD " << theOutIcpConnection << ".");
 
709
        debugs(12, 1, "Outgoing ICP messages on port " << addr.GetPort() << ", FD " << theOutIcpConnection << ".");
723
710
 
724
711
        fd_note(theOutIcpConnection, "Outgoing ICP socket");
725
712
 
728
715
        theOutIcpConnection = theInIcpConnection;
729
716
    }
730
717
 
731
 
    memset(&theOutICPAddr, '\0', sizeof(struct IN_ADDR));
732
 
 
733
 
    len = sizeof(struct sockaddr_in);
734
 
    memset(&xaddr, '\0', len);
735
 
    x = getsockname(theOutIcpConnection,
736
 
 
737
 
                    (struct sockaddr *) &xaddr, &len);
 
718
    theOutICPAddr.SetEmpty();
 
719
 
 
720
    theOutICPAddr.InitAddrInfo(xai);
 
721
 
 
722
    x = getsockname(theOutIcpConnection, xai->ai_addr, &xai->ai_addrlen);
738
723
 
739
724
    if (x < 0)
740
725
        debugs(50, 1, "theOutIcpConnection FD " << theOutIcpConnection << ": getsockname: " << xstrerror());
741
726
    else
742
 
        theOutICPAddr = xaddr.sin_addr;
 
727
        theOutICPAddr = *xai;
 
728
 
 
729
    theOutICPAddr.FreeAddrInfo(xai);
743
730
}
744
731
 
745
 
/*
746
 
 * icpConnectionShutdown only closes the 'in' socket if it is 
 
732
/**
 
733
 * icpConnectionShutdown only closes the 'in' socket if it is
747
734
 * different than the 'out' socket.
748
735
 */
749
736
void
757
744
        comm_close(theInIcpConnection);
758
745
    }
759
746
 
760
 
    /*
 
747
    /**
761
748
     * Here we set 'theInIcpConnection' to -1 even though the ICP 'in'
762
749
     * and 'out' sockets might be just one FD.  This prevents this
763
750
     * function from executing repeatedly.  When we are really ready to
765
752
     */
766
753
    theInIcpConnection = -1;
767
754
 
768
 
    /*
 
755
    /**
769
756
     * Normally we only write to the outgoing ICP socket, but
770
757
     * we also have a read handler there to catch messages sent
771
758
     * to that specific interface.  During shutdown, we must