]> git.ipfire.org Git - thirdparty/squid.git/blame - src/ident.cc
SQUID_2_2 branch merge
[thirdparty/squid.git] / src / ident.cc
CommitLineData
a47b9029 1
f1443bd9 2/*
b6a2f15e 3 * $Id: ident.cc,v 1.50 1999/04/15 06:15:59 wessels Exp $
632e2027 4 *
3c66d057 5 * DEBUG: section 30 Ident (RFC 931)
632e2027 6 * AUTHOR: Duane Wessels
7 *
42c04c16 8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
e25c139f 9 * ----------------------------------------------------------
632e2027 10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
e25c139f 13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * 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 {
50 char *key;
51 struct _IdentStateData *next;
52 int fd; /* IDENT fd */
53 struct sockaddr_in me;
54 struct sockaddr_in peer;
55 IdentClient *clients;
56} IdentStateData;
f1443bd9 57
582b6456 58static PF identReadReply;
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)) {
74 state->clients = client->next;
75 if (cbdataValid(client->callback_data))
76 client->callback(result, client->callback_data);
77 cbdataUnlock(client->callback_data);
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,
05832ae1 97 inet_ntoa(state->peer.sin_addr));
86cf9987 98 comm_close(fd);
99}
100
e5f6c5c2 101static void
102identConnectDone(int fd, int status, void *data)
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 /*
113 * see if our clients still care
114 */
115 for (c = state->clients; c; c = c->next) {
116 if (cbdataValid(c->callback_data))
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",
05832ae1 126 ntohs(state->peer.sin_port),
127 ntohs(state->me.sin_port));
128 comm_write_mbuf(fd, mb, NULL, state);
129 commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
130 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
f1443bd9 131}
132
b8d8561b 133static void
582b6456 134identReadReply(int fd, void *data)
f1443bd9 135{
05832ae1 136 IdentStateData *state = data;
95d659f0 137 LOCAL_ARRAY(char, buf, BUFSIZ);
05832ae1 138 char *ident = NULL;
f1443bd9 139 char *t = NULL;
140 int len = -1;
f1443bd9 141 buf[0] = '\0';
886f2785 142 Counter.syscalls.sock.reads++;
e42d5181 143 len = read(fd, buf, BUFSIZ - 1);
4f92c80c 144 fd_bytes(fd, len, FD_READ);
05832ae1 145 if (len <= 0) {
146 comm_close(fd);
147 return;
148 }
149 /*
150 * XXX This isn't really very tolerant. It should read until EOL
151 * or EOF and then decode the answer... If the reply is fragmented
152 * then this will fail
153 */
154 buf[len] = '\0';
155 if ((t = strchr(buf, '\r')))
156 *t = '\0';
157 if ((t = strchr(buf, '\n')))
158 *t = '\0';
159 debug(30, 5) ("identReadReply: FD %d: Read '%s'\n", fd, buf);
160 if (strstr(buf, "USERID")) {
161 if ((ident = strrchr(buf, ':'))) {
b6a2f15e 162 while (xisspace(*++ident));
05832ae1 163 identCallback(state, ident);
f1443bd9 164 }
165 }
166 comm_close(fd);
ba1d2afa 167}
168
05832ae1 169
ba1d2afa 170static void
05832ae1 171identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
172{
173 IdentClient *c = xcalloc(1, sizeof(*c));
174 IdentClient **C;
175 c->callback = callback;
176 c->callback_data = callback_data;
177 cbdataLock(callback_data);
178 for (C = &state->clients; *C; C = &(*C)->next);
179 *C = c;
180}
181
182/**** PUBLIC FUNCTIONS ****/
183
184/*
185 * start a TCP connection to the peer host on port 113
186 */
187void
188identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *data)
189{
190 IdentStateData *state;
191 int fd;
192 char key1[IDENT_KEY_SZ];
193 char key2[IDENT_KEY_SZ];
194 char key[IDENT_KEY_SZ];
195 snprintf(key1, IDENT_KEY_SZ, "%s:%d",
196 inet_ntoa(me->sin_addr),
197 ntohs(me->sin_port));
198 snprintf(key2, IDENT_KEY_SZ, "%s:%d",
199 inet_ntoa(peer->sin_addr),
200 ntohs(peer->sin_port));
201 snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
202 if ((state = hash_lookup(ident_hash, key)) != NULL) {
203 identClientAdd(state, callback, data);
204 return;
205 }
206 fd = comm_open(SOCK_STREAM,
207 0,
208 me->sin_addr,
209 0,
210 COMM_NONBLOCKING,
211 "ident");
212 if (fd == COMM_ERROR) {
213 /* Failed to get a local socket */
214 callback(NULL, data);
215 return;
216 }
217 state = xcalloc(1, sizeof(IdentStateData));
218 cbdataAdd(state, cbdataXfree, 0);
219 state->key = xstrdup(key);
220 state->fd = fd;
221 state->me = *me;
222 state->peer = *peer;
223 identClientAdd(state, callback, data);
224 hash_join(ident_hash, (hash_link *) state);
225 comm_add_close_handler(fd,
226 identClose,
227 state);
228 commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
229 commConnectStart(fd,
230 inet_ntoa(state->peer.sin_addr),
231 IDENT_PORT,
232 identConnectDone,
233 state);
234}
235
236void
237identInit(void)
ba1d2afa 238{
05832ae1 239 ident_hash = hash_create((HASHCMP *) strcmp,
240 hashPrime(Squid_MaxFD / 8),
241 hash4);
f1443bd9 242}
3898f57f 243
244#endif