ident.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: ident.c,v 1.49.2.1 1999/02/12 19:38:30 wessels Exp $
  3.  *
  4.  * DEBUG: section 30    Ident (RFC 931)
  5.  * AUTHOR: Duane Wessels
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  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.
  23.  *  
  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.
  28.  *  
  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.
  32.  *
  33.  */
  34. #include "squid.h"
  35. #if USE_IDENT
  36. #define IDENT_PORT 113
  37. #define IDENT_KEY_SZ 50
  38. typedef struct _IdentClient {
  39.     IDCB *callback;
  40.     void *callback_data;
  41.     struct _IdentClient *next;
  42. } IdentClient;
  43. typedef struct _IdentStateData {
  44.     char *key;
  45.     struct _IdentStateData *next;
  46.     int fd; /* IDENT fd */
  47.     struct sockaddr_in me;
  48.     struct sockaddr_in peer;
  49.     IdentClient *clients;
  50. } IdentStateData;
  51. static PF identReadReply;
  52. static PF identClose;
  53. static PF identTimeout;
  54. static CNCB identConnectDone;
  55. static hash_table *ident_hash = NULL;
  56. static void identClientAdd(IdentStateData *, IDCB *, void *);
  57. /**** PRIVATE FUNCTIONS ****/
  58. static void
  59. identCallback(IdentStateData * state, char *result)
  60. {
  61.     IdentClient *client;
  62.     if (result && *result == '')
  63. result = NULL;
  64.     while ((client = state->clients)) {
  65. state->clients = client->next;
  66. if (cbdataValid(client->callback_data))
  67.     client->callback(result, client->callback_data);
  68. cbdataUnlock(client->callback_data);
  69. xfree(client);
  70.     }
  71. }
  72. static void
  73. identClose(int fdnotused, void *data)
  74. {
  75.     IdentStateData *state = data;
  76.     identCallback(state, NULL);
  77.     comm_close(state->fd);
  78.     hash_remove_link(ident_hash, (hash_link *) state);
  79.     cbdataFree(state);
  80. }
  81. static void
  82. identTimeout(int fd, void *data)
  83. {
  84.     IdentStateData *state = data;
  85.     debug(30, 3) ("identTimeout: FD %d, %sn", fd,
  86. inet_ntoa(state->peer.sin_addr));
  87.     comm_close(fd);
  88. }
  89. static void
  90. identConnectDone(int fd, int status, void *data)
  91. {
  92.     IdentStateData *state = data;
  93.     IdentClient *c;
  94.     MemBuf mb;
  95.     if (status != COMM_OK) {
  96. /* Failed to connect */
  97. comm_close(fd);
  98. return;
  99.     }
  100.     /*
  101.      * see if our clients still care
  102.      */
  103.     for (c = state->clients; c; c = c->next) {
  104. if (cbdataValid(c->callback_data))
  105.     break;
  106.     }
  107.     if (c == NULL) {
  108. /* no clients care */
  109. comm_close(fd);
  110. return;
  111.     }
  112.     memBufDefInit(&mb);
  113.     memBufPrintf(&mb, "%d, %drn",
  114. ntohs(state->peer.sin_port),
  115. ntohs(state->me.sin_port));
  116.     comm_write_mbuf(fd, mb, NULL, state);
  117.     commSetSelect(fd, COMM_SELECT_READ, identReadReply, state, 0);
  118.     commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
  119. }
  120. static void
  121. identReadReply(int fd, void *data)
  122. {
  123.     IdentStateData *state = data;
  124.     LOCAL_ARRAY(char, buf, BUFSIZ);
  125.     char *ident = NULL;
  126.     char *t = NULL;
  127.     int len = -1;
  128.     buf[0] = '';
  129.     Counter.syscalls.sock.reads++;
  130.     len = read(fd, buf, BUFSIZ - 1);
  131.     fd_bytes(fd, len, FD_READ);
  132.     if (len <= 0) {
  133. comm_close(fd);
  134. return;
  135.     }
  136.     /*
  137.      * XXX This isn't really very tolerant. It should read until EOL
  138.      * or EOF and then decode the answer... If the reply is fragmented
  139.      * then this will fail
  140.      */
  141.     buf[len] = '';
  142.     if ((t = strchr(buf, 'r')))
  143. *t = '';
  144.     if ((t = strchr(buf, 'n')))
  145. *t = '';
  146.     debug(30, 5) ("identReadReply: FD %d: Read '%s'n", fd, buf);
  147.     if (strstr(buf, "USERID")) {
  148. if ((ident = strrchr(buf, ':'))) {
  149.     while (xisspace(*++ident));
  150.     identCallback(state, ident);
  151. }
  152.     }
  153.     comm_close(fd);
  154. }
  155. static void
  156. identClientAdd(IdentStateData * state, IDCB * callback, void *callback_data)
  157. {
  158.     IdentClient *c = xcalloc(1, sizeof(*c));
  159.     IdentClient **C;
  160.     c->callback = callback;
  161.     c->callback_data = callback_data;
  162.     cbdataLock(callback_data);
  163.     for (C = &state->clients; *C; C = &(*C)->next);
  164.     *C = c;
  165. }
  166. /**** PUBLIC FUNCTIONS ****/
  167. /*
  168.  * start a TCP connection to the peer host on port 113
  169.  */
  170. void
  171. identStart(struct sockaddr_in *me, struct sockaddr_in *peer, IDCB * callback, void *data)
  172. {
  173.     IdentStateData *state;
  174.     int fd;
  175.     char key1[IDENT_KEY_SZ];
  176.     char key2[IDENT_KEY_SZ];
  177.     char key[IDENT_KEY_SZ];
  178.     snprintf(key1, IDENT_KEY_SZ, "%s:%d",
  179. inet_ntoa(me->sin_addr),
  180. ntohs(me->sin_port));
  181.     snprintf(key2, IDENT_KEY_SZ, "%s:%d",
  182. inet_ntoa(peer->sin_addr),
  183. ntohs(peer->sin_port));
  184.     snprintf(key, IDENT_KEY_SZ, "%s,%s", key1, key2);
  185.     if ((state = hash_lookup(ident_hash, key)) != NULL) {
  186. identClientAdd(state, callback, data);
  187. return;
  188.     }
  189.     fd = comm_open(SOCK_STREAM,
  190. 0,
  191. me->sin_addr,
  192. 0,
  193. COMM_NONBLOCKING,
  194. "ident");
  195.     if (fd == COMM_ERROR) {
  196. /* Failed to get a local socket */
  197. callback(NULL, data);
  198. return;
  199.     }
  200.     state = xcalloc(1, sizeof(IdentStateData));
  201.     cbdataAdd(state, cbdataXfree, 0);
  202.     state->key = xstrdup(key);
  203.     state->fd = fd;
  204.     state->me = *me;
  205.     state->peer = *peer;
  206.     identClientAdd(state, callback, data);
  207.     hash_join(ident_hash, (hash_link *) state);
  208.     comm_add_close_handler(fd,
  209. identClose,
  210. state);
  211.     commSetTimeout(fd, Config.Timeout.ident, identTimeout, state);
  212.     commConnectStart(fd,
  213. inet_ntoa(state->peer.sin_addr),
  214. IDENT_PORT,
  215. identConnectDone,
  216. state);
  217. }
  218. void
  219. identInit(void)
  220. {
  221.     ident_hash = hash_create((HASHCMP *) strcmp,
  222. hashPrime(Squid_MaxFD / 8),
  223. hash4);
  224. }
  225. #endif