00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: ident.c,v 1.7 2007-09-13 22:20:55 sven Exp $";
00022 #endif
00023
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <ctype.h>
00028 #include <eggdrop/eggdrop.h>
00029
00030 typedef struct _ident_info {
00031 struct _ident_info *next;
00032 int id;
00033 char *ip;
00034 int their_port, our_port;
00035 int idx;
00036 int timeout;
00037 ident_callback_t *callback;
00038 void *client_data;
00039 event_owner_t *owner;
00040 } ident_info_t;
00041
00042 static int ident_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00043 static int ident_on_read(void *client_data, int idx, char *data, int len);
00044 static int ident_on_eof(void *client_data, int idx, int err, const char *errmsg);
00045 static int ident_result(ident_info_t *ident_info, const char *ident);
00046
00047 static sockbuf_handler_t ident_handler = {
00048 "ident",
00049 ident_on_connect, ident_on_eof, NULL,
00050 ident_on_read, NULL
00051 };
00052
00053 static ident_info_t *ident_head = NULL;
00054
00055
00056
00057 int egg_ident_lookup(const char *ip, int their_port, int our_port, int timeout, ident_callback_t *callback, void *client_data, event_owner_t *owner)
00058 {
00059 static int ident_id = 0;
00060 int idx;
00061 ident_info_t *ident_info;
00062
00063 idx = egg_connect(ip, 113, -1);
00064 if (idx < 0) {
00065 callback(client_data, ip, their_port, NULL);
00066 if (owner && owner->on_delete) owner->on_delete(owner, client_data);
00067 return(-1);
00068 }
00069 ident_info = calloc(1, sizeof(*ident_info));
00070 ident_info->ip = strdup(ip);
00071 ident_info->their_port = their_port;
00072 ident_info->our_port = our_port;
00073 ident_info->timeout = timeout;
00074 ident_info->callback = callback;
00075 ident_info->client_data = client_data;
00076 ident_info->owner = owner;
00077 ident_info->idx = idx;
00078 ident_info->id = ident_id++;
00079 ident_info->next = ident_head;
00080 ident_head = ident_info;
00081 sockbuf_set_handler(idx, &ident_handler, ident_info, NULL);
00082 return(ident_info->id);
00083 }
00084
00085
00086 int egg_ident_cancel(int id, int issue_callback)
00087 {
00088 ident_info_t *ptr, *prev;
00089
00090 prev = NULL;
00091 for (ptr = ident_head; ptr; ptr = ptr->next) {
00092 if (ptr->id == id) break;
00093 prev = ptr;
00094 }
00095 if (!ptr) return(-1);
00096 if (prev) prev->next = ptr->next;
00097 else ident_head = ptr->next;
00098 sockbuf_delete(ptr->idx);
00099 if (issue_callback) {
00100 ptr->callback(ptr->client_data, ptr->ip, ptr->their_port, NULL);
00101 }
00102 if (ptr->owner && ptr->owner->on_delete) ptr->owner->on_delete(ptr->owner, ptr->client_data);
00103 free(ptr->ip);
00104 free(ptr);
00105 return(0);
00106 }
00107
00108 int egg_ident_cancel_by_owner(egg_module_t *module, void *script)
00109 {
00110 int removed = 0;
00111 ident_info_t *ptr, *prev = NULL, *next;
00112
00113 for (ptr = ident_head; ptr; ptr = next) {
00114 next = ptr->next;
00115 if (!ptr->owner || ptr->owner->module != module || (script && ptr->owner->client_data != script)) {
00116 prev = ptr;
00117 continue;
00118 }
00119 if (prev) prev->next = ptr->next;
00120 else ident_head = ptr->next;
00121 ++removed;
00122 sockbuf_delete(ptr->idx);
00123 if (ptr->owner && ptr->owner->on_delete) ptr->owner->on_delete(ptr->owner, ptr->client_data);
00124 free(ptr->ip);
00125 free(ptr);
00126 }
00127 return removed;
00128 }
00129
00130 static int ident_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
00131 {
00132 ident_info_t *ident_info = client_data;
00133
00134 egg_iprintf(idx, "%d,%d\r\n", ident_info->their_port, ident_info->our_port);
00135 return(0);
00136 }
00137
00138 static int ident_on_read(void *client_data, int idx, char *data, int len)
00139 {
00140 char *colon, *ident;
00141 int i;
00142
00143 colon = strchr(data, ':');
00144 if (!colon) goto ident_error;
00145
00146
00147 colon++;
00148 while (isspace(*colon)) colon++;
00149 if (strncasecmp(colon, "USERID", 6)) goto ident_error;
00150
00151
00152 colon = strchr(colon, ':');
00153 if (!colon) goto ident_error;
00154 colon++;
00155
00156
00157 ident = strchr(colon, ':');
00158 if (!ident) goto ident_error;
00159 ident++;
00160 while (*ident && isspace(*ident)) ident++;
00161
00162
00163 len = strlen(ident);
00164 for (i = 0; i < len; i++) {
00165 if (ident[i] == '\r' || ident[i] == '\n') {
00166 ident[i] = 0;
00167 break;
00168 }
00169 if (!isalnum(ident[i]) && ident[i] != '_') ident[i] = 'x';
00170 }
00171 if (!*ident) goto ident_error;
00172 if (len > 20) ident[20] = 0;
00173 ident_result(client_data, ident);
00174 return(0);
00175
00176 ident_error:
00177 ident_result(client_data, NULL);
00178 return(0);
00179 }
00180
00181 static int ident_on_eof(void *client_data, int idx, int err, const char *errmsg)
00182 {
00183 ident_result(client_data, NULL);
00184 return(0);
00185 }
00186
00187 static int ident_result(ident_info_t *ident_info, const char *ident)
00188 {
00189 ident_info_t *ptr, *prev = NULL;
00190
00191 for (ptr = ident_head; ptr; ptr = ptr->next) {
00192 if (ptr == ident_info) break;
00193 prev = ptr;
00194 }
00195
00196 if (prev) prev->next = ptr->next;
00197 else ident_head = ptr->next;
00198
00199 sockbuf_delete(ident_info->idx);
00200 ident_info->callback(ident_info->client_data, ident_info->ip, ident_info->their_port, ident);
00201 if (ident_info->owner && ident_info->owner->on_delete) ident_info->owner->on_delete(ident_info->owner, ident_info->client_data);
00202 free(ident_info->ip);
00203 free(ident_info);
00204 return(0);
00205 }