]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ident/Ident.cc
4 * DEBUG: section 30 Ident (RFC 931)
5 * AUTHOR: Duane Wessels
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
40 #include "ident/Config.h"
41 #include "ident/Ident.h"
46 #define IDENT_PORT 113
47 #define IDENT_KEY_SZ 50
49 typedef struct _IdentClient
{
53 struct _IdentClient
*next
;
56 typedef struct _IdentStateData
{
57 hash_link hash
; /* must be first */
58 int fd
; /* IDENT fd */
67 // TODO: make these all a series of Async jobs. They are self-contained callbacks now.
68 static IOCB ReadReply
;
71 static CNCB ConnectDone
;
72 static hash_table
*ident_hash
= NULL
;
73 static void ClientAdd(IdentStateData
* state
, IDCB
* callback
, void *callback_data
);
74 static void identCallback(IdentStateData
* state
, char *result
);
78 Ident::IdentConfig
Ident::TheConfig
;
80 /**** PRIVATE FUNCTIONS ****/
83 Ident::identCallback(IdentStateData
* state
, char *result
)
87 if (result
&& *result
== '\0')
90 while ((client
= state
->clients
)) {
92 state
->clients
= client
->next
;
94 if (cbdataReferenceValidDone(client
->callback_data
, &cbdata
))
95 client
->callback(result
, cbdata
);
102 Ident::Close(int fdnotused
, void *data
)
104 IdentStateData
*state
= (IdentStateData
*)data
;
105 identCallback(state
, NULL
);
106 comm_close(state
->fd
);
107 hash_remove_link(ident_hash
, (hash_link
*) state
);
108 xfree(state
->hash
.key
);
113 Ident::Timeout(int fd
, void *data
)
115 IdentStateData
*state
= (IdentStateData
*)data
;
116 debugs(30, 3, "identTimeout: FD " << fd
<< ", " << state
->my_peer
);
122 Ident::ConnectDone(int fd
, comm_err_t status
, int xerrno
, void *data
)
124 IdentStateData
*state
= (IdentStateData
*)data
;
127 if (status
!= COMM_OK
) {
128 /* Failed to connect */
134 * see if any of our clients still care
136 for (c
= state
->clients
; c
; c
= c
->next
) {
137 if (cbdataReferenceValid(c
->callback_data
))
142 /* no clients care */
149 mb
.Printf("%d, %d\r\n",
150 state
->my_peer
.GetPort(),
151 state
->me
.GetPort());
152 comm_write_mbuf(fd
, &mb
, NULL
, state
);
153 comm_read(fd
, state
->buf
, BUFSIZ
, Ident::ReadReply
, state
);
154 commSetTimeout(fd
, Ident::TheConfig
.timeout
, Ident::Timeout
, state
);
158 Ident::ReadReply(int fd
, char *buf
, size_t len
, comm_err_t flag
, int xerrno
, void *data
)
160 IdentStateData
*state
= (IdentStateData
*)data
;
164 assert (buf
== state
->buf
);
166 if (flag
!= COMM_OK
|| len
<= 0) {
172 * XXX This isn't really very tolerant. It should read until EOL
173 * or EOF and then decode the answer... If the reply is fragmented
174 * then this will fail
178 if ((t
= strchr(buf
, '\r')))
181 if ((t
= strchr(buf
, '\n')))
184 debugs(30, 5, "identReadReply: FD " << fd
<< ": Read '" << buf
<< "'");
186 if (strstr(buf
, "USERID")) {
187 if ((ident
= strrchr(buf
, ':'))) {
188 while (xisspace(*++ident
));
189 Ident::identCallback(state
, ident
);
197 Ident::ClientAdd(IdentStateData
* state
, IDCB
* callback
, void *callback_data
)
199 IdentClient
*c
= (IdentClient
*)xcalloc(1, sizeof(*c
));
201 c
->callback
= callback
;
202 c
->callback_data
= cbdataReference(callback_data
);
204 for (C
= &state
->clients
; *C
; C
= &(*C
)->next
);
208 CBDATA_TYPE(IdentStateData
);
210 /**** PUBLIC FUNCTIONS ****/
213 * start a TCP connection to the peer host on port 113
216 Ident::Start(IpAddress
&me
, IpAddress
&my_peer
, IDCB
* callback
, void *data
)
218 IdentStateData
*state
;
220 char key1
[IDENT_KEY_SZ
];
221 char key2
[IDENT_KEY_SZ
];
222 char key
[IDENT_KEY_SZ
];
223 char ntoabuf
[MAX_IPSTRLEN
];
225 me
.ToURL(key1
, IDENT_KEY_SZ
);
226 my_peer
.ToURL(key2
, IDENT_KEY_SZ
);
227 snprintf(key
, IDENT_KEY_SZ
, "%s,%s", key1
, key2
);
232 if ((state
= (IdentStateData
*)hash_lookup(ident_hash
, key
)) != NULL
) {
233 ClientAdd(state
, callback
, data
);
238 addr
.SetPort(0); // NP: use random port for secure outbound to IDENT_PORT
240 fd
= comm_open_listener(SOCK_STREAM
,
246 if (fd
== COMM_ERROR
) {
247 /* Failed to get a local socket */
248 callback(NULL
, data
);
252 CBDATA_INIT_TYPE(IdentStateData
);
253 state
= cbdataAlloc(IdentStateData
);
254 state
->hash
.key
= xstrdup(key
);
257 state
->my_peer
= my_peer
;
258 ClientAdd(state
, callback
, data
);
259 hash_join(ident_hash
, &state
->hash
);
260 comm_add_close_handler(fd
, Ident::Close
, state
);
261 commSetTimeout(fd
, Ident::TheConfig
.timeout
, Ident::Timeout
, state
);
262 state
->my_peer
.NtoA(ntoabuf
,MAX_IPSTRLEN
);
263 commConnectStart(fd
, ntoabuf
, IDENT_PORT
, Ident::ConnectDone
, state
);
270 debugs(30, DBG_CRITICAL
, "WARNING: Ident already initialized.");
274 ident_hash
= hash_create((HASHCMP
*) strcmp
,
275 hashPrime(Squid_MaxFD
/ 8),
279 #endif /* USE_IDENT */