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: dccparty.c,v 1.17 2007-11-06 00:05:40 sven Exp $";
00022 #endif
00023
00024 #include <eggdrop/eggdrop.h>
00025
00026 #include "dccparty.h"
00027
00028 dcc_config_t dcc_config = {0};
00029
00030 static config_var_t dcc_config_vars[] = {
00031 {"vhost", &dcc_config.vhost, CONFIG_STRING},
00032 {"port", &dcc_config.port, CONFIG_INT},
00033 {"stealth", &dcc_config.stealth, CONFIG_INT},
00034 {"max_retries", &dcc_config.max_retries, CONFIG_INT},
00035
00036 {0}
00037 };
00038
00039 EXPORT_SCOPE int dccparty_LTX_start(egg_module_t *modinfo);
00040 static int dccparty_close(int why);
00041
00042
00043 extern partyline_event_t dcc_party_handler;
00044
00045 static int got_chat_request(char *nick, char *uhost, user_t *u, char *type, char *ip, int port);
00046
00047 static int dcc_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port);
00048 static int dcc_on_read(void *client_data, int idx, char *data, int len);
00049 static int dcc_on_eof(void *client_data, int idx, int err, const char *errmsg);
00050 static int dcc_on_delete(event_owner_t *owner, void *client_data);
00051 static int dcc_pm_delete(event_owner_t *owner, void *client_data);
00052
00053 static int ident_result(void *client_data, const char *ip, int port, const char *reply);
00054 static int dns_result(void *client_data, const char *ip, char **hosts);
00055 static int process_results(dcc_session_t *session);
00056
00057 static event_owner_t dcc_generic_owner = {
00058 "dccparty", 0,
00059 0, 0,
00060 0
00061 };
00062
00063 static event_owner_t dcc_pm_owner = {
00064 "dccparty", 0,
00065 0, 0,
00066 dcc_pm_delete
00067 };
00068
00069 static event_owner_t dcc_sock_owner = {
00070 "dccparty", 0,
00071 0, 0,
00072 dcc_on_delete
00073 };
00074
00075 static sockbuf_handler_t dcc_handler = {
00076 "dcc",
00077 dcc_on_connect, dcc_on_eof, NULL,
00078 dcc_on_read, NULL
00079 };
00080
00081 int dcc_init()
00082 {
00083 bind_add_simple("dcc_chat", NULL, "*", got_chat_request);
00084 return(0);
00085 }
00086
00087 static void kill_session(dcc_session_t *session)
00088 {
00089 if (session->ident_id != -1) egg_ident_cancel(session->ident_id, 0);
00090 if (session->dns_id != -1) egg_dns_cancel(session->dns_id, 0);
00091 if (session->ip) free(session->ip);
00092 if (session->host) free(session->host);
00093 if (session->ident) free(session->ident);
00094 if (session->nick) free(session->nick);
00095 free(session);
00096 }
00097
00098 static int got_chat_request(char *nick, char *uhost, user_t *u, char *type, char *ip, int port)
00099 {
00100 int idx;
00101 dcc_session_t *session;
00102
00103
00104 if (!u) {
00105 putlog(LOG_MISC, "*", _("Ignoring chat request from %s (user unknown)."), nick);
00106 return(0);
00107 }
00108
00109 idx = egg_connect(ip, port, 0);
00110
00111 session = calloc(1, sizeof(*session));
00112 session->nick = strdup(nick);
00113 session->idx = idx;
00114
00115 sockbuf_set_handler(idx, &dcc_handler, session, &dcc_sock_owner);
00116 linemode_on(idx);
00117 socktimer_on(idx, 60, 0, NULL, NULL, &dcc_generic_owner);
00118 return(0);
00119 }
00120
00121 static int dcc_on_connect(void *client_data, int idx, const char *peer_ip, int peer_port)
00122 {
00123 dcc_session_t *session = client_data;
00124 int sock, our_port = 0;
00125
00126 sock = sockbuf_get_sock(idx);
00127 socket_get_name(sock, NULL, &our_port);
00128 session->ip = strdup(peer_ip);
00129 session->port = peer_port;
00130 egg_iprintf(idx, "Hello %s/%d!\r\n\r\n", peer_ip, peer_port);
00131 egg_iprintf(idx, "Please enter your nickname.\r\n");
00132 session->state = STATE_NICKNAME;
00133 session->count = 0;
00134
00135
00136 session->ident_id = egg_ident_lookup(peer_ip, peer_port, our_port, -1, ident_result, session, &dcc_generic_owner);
00137 session->dns_id = egg_dns_reverse(peer_ip, -1, dns_result, session, &dcc_generic_owner);
00138
00139 return(0);
00140 }
00141
00142 static int ident_result(void *client_data, const char *ip, int port, const char *reply)
00143 {
00144 dcc_session_t *session = client_data;
00145
00146 session->ident_id = -1;
00147 if (reply) session->ident = strdup(reply);
00148 else session->ident = strdup("~dcc");
00149 process_results(session);
00150 return(0);
00151 }
00152
00153 static int dns_result(void *client_data, const char *ip, char **hosts)
00154 {
00155 dcc_session_t *session = client_data;
00156 const char *host;
00157
00158 session->dns_id = -1;
00159 if (!hosts || !hosts[0]) host = ip;
00160 else host = hosts[0];
00161
00162 session->host = strdup(host);
00163 process_results(session);
00164 return(0);
00165 }
00166
00167 static int process_results(dcc_session_t *session)
00168 {
00169 char fakehost[512];
00170
00171 if (!session->ident || !session->host) return(0);
00172
00173 if (session->state == STATE_PARTYLINE) {
00174 partyline_update_info(session->party, session->ident, session->host);
00175 return(0);
00176 }
00177 if (session->flags & STEALTH_LOGIN) {
00178 snprintf(fakehost, sizeof(fakehost), "-dcc!%s@%s", session->ident, session->host);
00179 fakehost[sizeof(fakehost)-1] = 0;
00180 if (!user_lookup_by_irchost(fakehost)) {
00181 sockbuf_delete(session->idx);
00182 return(0);
00183 }
00184 egg_iprintf(session->idx, "\r\nPlease enter your nickname.\r\n");
00185 session->state = STATE_NICKNAME;
00186 }
00187 return(0);
00188 }
00189
00190 static int dcc_on_read(void *client_data, int idx, char *data, int len)
00191 {
00192 dcc_session_t *session = client_data;
00193
00194 switch (session->state) {
00195 case STATE_PARTYLINE:
00196 partyline_on_input(NULL, session->party, data, len);
00197 break;
00198 case STATE_NICKNAME:
00199 session->nick = strdup(data);
00200 session->state = STATE_PASSWORD;
00201 sockbuf_write(session->idx, "Please enter your password.\r\n", -1);
00202 break;
00203 case STATE_PASSWORD:
00204 session->user = user_lookup_authed(session->nick, data);
00205 if (!session->user) {
00206 sockbuf_write(session->idx, "Invalid username/password.\r\n\r\n", -1);
00207 session->count++;
00208 if (session->count > dcc_config.max_retries) {
00209 sockbuf_delete(session->idx);
00210 break;
00211 }
00212 free(session->nick);
00213 session->nick = NULL;
00214 sockbuf_write(session->idx, "Please enter your nickname.\r\n", -1);
00215 session->state = STATE_NICKNAME;
00216 }
00217 else {
00218 session->party = partymember_new(-1, session->user, NULL, session->nick, session->ident ? session->ident : "~dcc", session->host ? session->host : session->ip, &dcc_party_handler, session, &dcc_pm_owner);
00219 session->state = STATE_PARTYLINE;
00220 egg_iprintf(idx, _("\r\nWelcome to the dcc partyline interface!\r\n"));
00221 if (session->ident) egg_iprintf(idx, _("Your ident is: %s\r\n"), session->ident);
00222 if (session->host) egg_iprintf(idx, _("Your hostname is: %s\r\n"), session->host);
00223 socktimer_off(idx);
00224
00225 partychan_join_name("*", session->party, 0);
00226 }
00227 break;
00228 }
00229 return(0);
00230 }
00231
00232 static int dcc_on_eof(void *client_data, int idx, int err, const char *errmsg)
00233 {
00234 dcc_session_t *session = client_data;
00235
00236 if (session->party) {
00237 if (!err) errmsg = "Client disconnected";
00238 else if (!errmsg) errmsg = "Unknown error";
00239 partymember_delete(session->party, NULL, errmsg);
00240
00241
00242
00243 } else {
00244 sockbuf_delete(idx);
00245 }
00246 return(0);
00247 }
00248
00249 static int dcc_pm_delete(event_owner_t *owner, void *client_data)
00250 {
00251 dcc_session_t *session = client_data;
00252
00253 session->party = NULL;
00254
00255 sockbuf_delete(session->idx);
00256
00257 return 0;
00258 }
00259
00260 static int dcc_on_delete(event_owner_t *owner, void *client_data)
00261 {
00262 dcc_session_t *session = client_data;
00263
00264 session->idx = -1;
00265 if (session->party) {
00266 partymember_delete(session->party, NULL, "Deleted!");
00267 session->party = NULL;
00268 }
00269 kill_session(session);
00270 return(0);
00271 }
00272
00273 static int dccparty_close(int why)
00274 {
00275 void *config_root;
00276
00277 config_root = config_get_root("eggdrop");
00278 config_unlink_table(dcc_config_vars, config_root, "dccparty", 0, NULL);
00279
00280 return(0);
00281 }
00282
00283 int dccparty_LTX_start(egg_module_t *modinfo)
00284 {
00285 void *config_root;
00286
00287 dcc_generic_owner.module = dcc_sock_owner.module = dcc_pm_owner.module = modinfo;
00288
00289 modinfo->name = "dccparty";
00290 modinfo->author = "eggdev";
00291 modinfo->version = "1.0.0";
00292 modinfo->description = "dcc chat support for the partyline";
00293 modinfo->close_func = dccparty_close;
00294
00295
00296 memset(&dcc_config, 0, sizeof(dcc_config));
00297 dcc_config.max_retries = 3;
00298
00299
00300 config_root = config_get_root("eggdrop");
00301 config_link_table(dcc_config_vars, config_root, "dccparty", 0, NULL);
00302 config_update_table(dcc_config_vars, config_root, "dccparty", 0, NULL);
00303
00304 dcc_init();
00305 return(0);
00306 }