]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ident.cc
Import IPv6 support from squid3-ipv6 branch to 3-HEAD.
[thirdparty/squid.git] / src / ident.cc
CommitLineData
a47b9029 1
f1443bd9 2/*
cc192b50 3 * $Id: ident.cc,v 1.78 2007/12/14 23:11:47 amosjeffries Exp $
632e2027 4 *
3c66d057 5 * DEBUG: section 30 Ident (RFC 931)
632e2027 6 * AUTHOR: Duane Wessels
7 *
2b6662ba 8 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 9 * ----------------------------------------------------------
632e2027 10 *
2b6662ba 11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
632e2027 19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
cbdec147 32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 33 *
f1443bd9 34 */
35
36#include "squid.h"
a46d2c0e 37#include "comm.h"
0eb49b6d 38#include "MemBuf.h"
f1443bd9 39
40#define IDENT_PORT 113
05832ae1 41#define IDENT_KEY_SZ 50
42
62e76326 43typedef struct _IdentClient
44{
05832ae1 45 IDCB *callback;
46 void *callback_data;
62e76326 47
05832ae1 48 struct _IdentClient *next;
62e76326 49}
50
51IdentClient;
05832ae1 52
62e76326 53typedef struct _IdentStateData
54{
186477c1 55 hash_link hash; /* must be first */
05832ae1 56 int fd; /* IDENT fd */
62e76326 57
cc192b50 58 IPAddress me;
62e76326 59
cc192b50 60 IPAddress my_peer;
05832ae1 61 IdentClient *clients;
c4b7a5a9 62 char buf[4096];
62e76326 63}
64
65IdentStateData;
f1443bd9 66
c4b7a5a9 67static IOCB identReadReply;
582b6456 68static PF identClose;
86cf9987 69static PF identTimeout;
4f92c80c 70static CNCB identConnectDone;
05832ae1 71static hash_table *ident_hash = NULL;
72static void identClientAdd(IdentStateData *, IDCB *, void *);
73
74/**** PRIVATE FUNCTIONS ****/
75
76static void
77identCallback(IdentStateData * state, char *result)
78{
79 IdentClient *client;
62e76326 80
05832ae1 81 if (result && *result == '\0')
62e76326 82 result = NULL;
83
05832ae1 84 while ((client = state->clients)) {
62e76326 85 void *cbdata;
86 state->clients = client->next;
87
88 if (cbdataReferenceValidDone(client->callback_data, &cbdata))
89 client->callback(result, cbdata);
90
91 xfree(client);
05832ae1 92 }
93}
f1443bd9 94
b8d8561b 95static void
79d39a72 96identClose(int fdnotused, void *data)
f1443bd9 97{
be005338 98 IdentStateData *state = (IdentStateData *)data;
05832ae1 99 identCallback(state, NULL);
100 comm_close(state->fd);
101 hash_remove_link(ident_hash, (hash_link *) state);
6fa85d6f 102 xfree(state->hash.key);
05832ae1 103 cbdataFree(state);
f1443bd9 104}
105
86cf9987 106static void
107identTimeout(int fd, void *data)
108{
be005338 109 IdentStateData *state = (IdentStateData *)data;
cc192b50 110 debugs(30, 3, "identTimeout: FD " << fd << ", " << state->my_peer);
bf8fe701 111
86cf9987 112 comm_close(fd);
113}
114
e5f6c5c2 115static void
f3400a93 116identConnectDone(int fd, comm_err_t status, int xerrno, void *data)
e5f6c5c2 117{
be005338 118 IdentStateData *state = (IdentStateData *)data;
05832ae1 119 IdentClient *c;
62e76326 120
9e975e4e 121 if (status != COMM_OK) {
62e76326 122 /* Failed to connect */
123 comm_close(fd);
124 return;
f1443bd9 125 }
62e76326 126
05832ae1 127 /*
fa80a8ef 128 * see if any of our clients still care
05832ae1 129 */
130 for (c = state->clients; c; c = c->next) {
62e76326 131 if (cbdataReferenceValid(c->callback_data))
132 break;
05832ae1 133 }
62e76326 134
ac2a30fc 135 if (c == NULL) {
62e76326 136 /* no clients care */
137 comm_close(fd);
138 return;
ac2a30fc 139 }
62e76326 140
032785bf 141 MemBuf mb;
2fe7eff9 142 mb.init();
143 mb.Printf("%d, %d\r\n",
cc192b50 144 state->my_peer.GetPort(),
145 state->me.GetPort());
2b663917 146 comm_write_mbuf(fd, &mb, NULL, state);
c4b7a5a9 147 comm_read(fd, state->buf, BUFSIZ, identReadReply, state);
05832ae1 148 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
f1443bd9 149}
150
b8d8561b 151static void
c4b7a5a9 152identReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
f1443bd9 153{
be005338 154 IdentStateData *state = (IdentStateData *)data;
05832ae1 155 char *ident = NULL;
f1443bd9 156 char *t = NULL;
c4b7a5a9 157
158 assert (buf == state->buf);
62e76326 159
be005338 160 if (flag != COMM_OK || len <= 0) {
62e76326 161 comm_close(fd);
162 return;
05832ae1 163 }
62e76326 164
05832ae1 165 /*
166 * XXX This isn't really very tolerant. It should read until EOL
167 * or EOF and then decode the answer... If the reply is fragmented
168 * then this will fail
169 */
170 buf[len] = '\0';
62e76326 171
05832ae1 172 if ((t = strchr(buf, '\r')))
62e76326 173 *t = '\0';
174
05832ae1 175 if ((t = strchr(buf, '\n')))
62e76326 176 *t = '\0';
177
bf8fe701 178 debugs(30, 5, "identReadReply: FD " << fd << ": Read '" << buf << "'");
62e76326 179
05832ae1 180 if (strstr(buf, "USERID")) {
62e76326 181 if ((ident = strrchr(buf, ':'))) {
182 while (xisspace(*++ident))
183
184 ;
185 identCallback(state, ident);
186 }
f1443bd9 187 }
62e76326 188
f1443bd9 189 comm_close(fd);
ba1d2afa 190}
191
05832ae1 192
ba1d2afa 193static void
05832ae1 194identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
195{
be005338 196 IdentClient *c = (IdentClient *)xcalloc(1, sizeof(*c));
05832ae1 197 IdentClient **C;
198 c->callback = callback;
fa80a8ef 199 c->callback_data = cbdataReference(callback_data);
62e76326 200
201 for (C = &state->clients; *C; C = &(*C)->next)
202
203 ;
05832ae1 204 *C = c;
205}
206
28c60158 207CBDATA_TYPE(IdentStateData);
208
05832ae1 209/**** PUBLIC FUNCTIONS ****/
210
211/*
212 * start a TCP connection to the peer host on port 113
213 */
214void
cc192b50 215identStart(IPAddress &me, IPAddress &my_peer, IDCB * callback, void *data)
05832ae1 216{
217 IdentStateData *state;
218 int fd;
219 char key1[IDENT_KEY_SZ];
220 char key2[IDENT_KEY_SZ];
221 char key[IDENT_KEY_SZ];
cc192b50 222 char ntoabuf[MAX_IPSTRLEN];
223
224 me.ToURL(key1, IDENT_KEY_SZ);
225 my_peer.ToURL(key2, IDENT_KEY_SZ);
05832ae1 226 snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
62e76326 227
228 if ((state = (IdentStateData *)hash_lookup(ident_hash, key)) != NULL)
229 {
230 identClientAdd(state, callback, data);
231 return;
05832ae1 232 }
62e76326 233
05832ae1 234 fd = comm_open(SOCK_STREAM,
bdb741f4 235 IPPROTO_TCP,
cc192b50 236 me,
62e76326 237 COMM_NONBLOCKING,
238 "ident");
239
240 if (fd == COMM_ERROR)
241 {
242 /* Failed to get a local socket */
243 callback(NULL, data);
244 return;
05832ae1 245 }
62e76326 246
28c60158 247 CBDATA_INIT_TYPE(IdentStateData);
72711e31 248 state = cbdataAlloc(IdentStateData);
186477c1 249 state->hash.key = xstrdup(key);
05832ae1 250 state->fd = fd;
cc192b50 251 state->me = me;
252 state->my_peer = my_peer;
05832ae1 253 identClientAdd(state, callback, data);
186477c1 254 hash_join(ident_hash, &state->hash);
05832ae1 255 comm_add_close_handler(fd,
62e76326 256 identClose,
257 state);
05832ae1 258 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
259 commConnectStart(fd,
cc192b50 260 state->my_peer.NtoA(ntoabuf,MAX_IPSTRLEN),
62e76326 261 IDENT_PORT,
262 identConnectDone,
263 state);
05832ae1 264}
265
266void
267identInit(void)
ba1d2afa 268{
30abd221 269 ident_hash = hash_create((HASHCMP *) strcmp,
62e76326 270 hashPrime(Squid_MaxFD / 8),
271 hash4);
f1443bd9 272}