]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ident.cc
More IDENT C typecasts
[thirdparty/squid.git] / src / ident.cc
CommitLineData
a47b9029 1
f1443bd9 2/*
d4cb310b 3 * $Id: ident.cc,v 1.62 2002/10/21 14:00:02 adrian 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"
37
3898f57f 38#if USE_IDENT
39
f1443bd9 40#define IDENT_PORT 113
05832ae1 41#define IDENT_KEY_SZ 50
42
43typedef struct _IdentClient {
44 IDCB *callback;
45 void *callback_data;
46 struct _IdentClient *next;
47} IdentClient;
48
49typedef struct _IdentStateData {
186477c1 50 hash_link hash; /* must be first */
05832ae1 51 int fd; /* IDENT fd */
52 struct sockaddr_in me;
d20b1cd0 53 struct sockaddr_in my_peer;
05832ae1 54 IdentClient *clients;
c4b7a5a9 55 char buf[4096];
05832ae1 56} IdentStateData;
f1443bd9 57
c4b7a5a9 58static IOCB identReadReply;
582b6456 59static PF identClose;
86cf9987 60static PF identTimeout;
4f92c80c 61static CNCB identConnectDone;
05832ae1 62static hash_table *ident_hash = NULL;
63static void identClientAdd(IdentStateData *, IDCB *, void *);
64
65/**** PRIVATE FUNCTIONS ****/
66
67static void
68identCallback(IdentStateData * state, char *result)
69{
70 IdentClient *client;
71 if (result && *result == '\0')
72 result = NULL;
73 while ((client = state->clients)) {
fa80a8ef 74 void *cbdata;
05832ae1 75 state->clients = client->next;
fa80a8ef 76 if (cbdataReferenceValidDone(client->callback_data, &cbdata))
77 client->callback(result, cbdata);
05832ae1 78 xfree(client);
79 }
80}
f1443bd9 81
b8d8561b 82static void
79d39a72 83identClose(int fdnotused, void *data)
f1443bd9 84{
05832ae1 85 IdentStateData *state = data;
86 identCallback(state, NULL);
87 comm_close(state->fd);
88 hash_remove_link(ident_hash, (hash_link *) state);
89 cbdataFree(state);
f1443bd9 90}
91
86cf9987 92static void
93identTimeout(int fd, void *data)
94{
05832ae1 95 IdentStateData *state = data;
1afe05c5 96 debug(30, 3) ("identTimeout: FD %d, %s\n", fd,
d20b1cd0 97 inet_ntoa(state->my_peer.sin_addr));
86cf9987 98 comm_close(fd);
99}
100
e5f6c5c2 101static void
3d7e9d7c 102identConnectDone(int fd, comm_err_t status, void *data)
e5f6c5c2 103{
05832ae1 104 IdentStateData *state = data;
105 IdentClient *c;
137ee196 106 MemBuf mb;
9e975e4e 107 if (status != COMM_OK) {
05832ae1 108 /* Failed to connect */
e5f6c5c2 109 comm_close(fd);
ba1d2afa 110 return;
f1443bd9 111 }
05832ae1 112 /*
fa80a8ef 113 * see if any of our clients still care
05832ae1 114 */
115 for (c = state->clients; c; c = c->next) {
fa80a8ef 116 if (cbdataReferenceValid(c->callback_data))
05832ae1 117 break;
118 }
ac2a30fc 119 if (c == NULL) {
120 /* no clients care */
05832ae1 121 comm_close(fd);
ac2a30fc 122 return;
123 }
137ee196 124 memBufDefInit(&mb);
125 memBufPrintf(&mb, "%d, %d\r\n",
d20b1cd0 126 ntohs(state->my_peer.sin_port),
05832ae1 127 ntohs(state->me.sin_port));
d4cb310b 128 comm_old_write_mbuf(fd, mb, NULL, state);
c4b7a5a9 129 comm_read(fd, state->buf, BUFSIZ, identReadReply, state);
05832ae1 130 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
f1443bd9 131}
132
b8d8561b 133static void
c4b7a5a9 134identReadReply(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
f1443bd9 135{
05832ae1 136 IdentStateData *state = data;
05832ae1 137 char *ident = NULL;
f1443bd9 138 char *t = NULL;
c4b7a5a9 139
140 assert (buf == state->buf);
141
142 if (if (flag != COMM_OK || len <= 0) {
05832ae1 143 comm_close(fd);
144 return;
145 }
146 /*
147 * XXX This isn't really very tolerant. It should read until EOL
148 * or EOF and then decode the answer... If the reply is fragmented
149 * then this will fail
150 */
151 buf[len] = '\0';
152 if ((t = strchr(buf, '\r')))
153 *t = '\0';
154 if ((t = strchr(buf, '\n')))
155 *t = '\0';
156 debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
157 if (strstr(buf, "USERID")) {
158 if ((ident = strrchr(buf, ':'))) {
b6a2f15e 159 while (xisspace(*++ident));
05832ae1 160 identCallback(state, ident);
f1443bd9 161 }
162 }
163 comm_close(fd);
ba1d2afa 164}
165
05832ae1 166
ba1d2afa 167static void
05832ae1 168identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
169{
170 IdentClient *c = xcalloc(1, sizeof(*c));
171 IdentClient **C;
172 c->callback = callback;
fa80a8ef 173 c->callback_data = cbdataReference(callback_data);
05832ae1 174 for (C = &state->clients; *C; C = &(*C)->next);
175 *C = c;
176}
177
28c60158 178CBDATA_TYPE(IdentStateData);
179
05832ae1 180/**** PUBLIC FUNCTIONS ****/
181
182/*
183 * start a TCP connection to the peer host on port 113
184 */
185void
d20b1cd0 186identStart(struct sockaddr_in *me, struct sockaddr_in *my_peer, IDCB * callback, void *data)
05832ae1 187{
188 IdentStateData *state;
189 int fd;
190 char key1[IDENT_KEY_SZ];
191 char key2[IDENT_KEY_SZ];
192 char key[IDENT_KEY_SZ];
193 snprintf(key1, IDENT_KEY_SZ, "%s:%d",
194 inet_ntoa(me->sin_addr),
195 ntohs(me->sin_port));
196 snprintf(key2, IDENT_KEY_SZ, "%s:%d",
d20b1cd0 197 inet_ntoa(my_peer->sin_addr),
198 ntohs(my_peer->sin_port));
05832ae1 199 snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
200 if ((state = hash_lookup(ident_hash, key)) != NULL) {
201 identClientAdd(state, callback, data);
202 return;
203 }
204 fd = comm_open(SOCK_STREAM,
205 0,
206 me->sin_addr,
207 0,
208 COMM_NONBLOCKING,
209 "ident");
210 if (fd == COMM_ERROR) {
211 /* Failed to get a local socket */
212 callback(NULL, data);
213 return;
214 }
28c60158 215 CBDATA_INIT_TYPE(IdentStateData);
72711e31 216 state = cbdataAlloc(IdentStateData);
186477c1 217 state->hash.key = xstrdup(key);
05832ae1 218 state->fd = fd;
219 state->me = *me;
d20b1cd0 220 state->my_peer = *my_peer;
05832ae1 221 identClientAdd(state, callback, data);
186477c1 222 hash_join(ident_hash, &state->hash);
05832ae1 223 comm_add_close_handler(fd,
224 identClose,
225 state);
226 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
227 commConnectStart(fd,
d20b1cd0 228 inet_ntoa(state->my_peer.sin_addr),
05832ae1 229 IDENT_PORT,
230 identConnectDone,
231 state);
232}
233
234void
235identInit(void)
ba1d2afa 236{
05832ae1 237 ident_hash = hash_create((HASHCMP *) strcmp,
238 hashPrime(Squid_MaxFD / 8),
239 hash4);
f1443bd9 240}
3898f57f 241
242#endif