1 |
/* Copyright (C) 2003, 2004 Stephane Thiell |
2 |
* |
3 |
* This file is part of pxyservd (from pxys) |
4 |
* |
5 |
* This program is free software; you can redistribute it and/or |
6 |
* modify it under the terms of the GNU General Public License |
7 |
* as published by the Free Software Foundation; either version 2 |
8 |
* of the License, or (at your option) any later version. |
9 |
* |
10 |
* This program is distributed in the hope that it will be useful, |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
* GNU General Public License for more details. |
14 |
* |
15 |
* You should have received a copy of the GNU General Public License |
16 |
* along with this program; if not, write to the Free Software |
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 |
* |
19 |
*/ |
20 |
#define RCSID "$Id: irc_client.c,v 1.6 2004/01/17 19:44:29 mbuna Exp $" |
21 |
|
22 |
#include "irc_client.h" |
23 |
#include <assert.h> |
24 |
#include <stdlib.h> |
25 |
#include <sys/types.h> |
26 |
#include <sys/socket.h> |
27 |
#include <netinet/in.h> |
28 |
#include <arpa/inet.h> |
29 |
#include <stdio.h> |
30 |
#include <string.h> |
31 |
|
32 |
#include <peak/peak.h> |
33 |
|
34 |
#include "cfgloader.h" |
35 |
#include "debug.h" |
36 |
#include "irc_channel.h" |
37 |
#include "irc_cmd.h" |
38 |
#include "irc_membership.h" |
39 |
#include "irc_msg.h" |
40 |
#include "irc_network.h" |
41 |
#include "irc_numnicks.h" |
42 |
#include "irc_send.h" |
43 |
#include "irc_struct.h" |
44 |
#include "irc_userbase.h" |
45 |
#include "pxyservd_log.h" |
46 |
|
47 |
#if NICKLEN > 9 |
48 |
#define MYNICKLEN 9 |
49 |
#else |
50 |
#define MYNICKLEN NICKLEN |
51 |
#endif |
52 |
|
53 |
extern time_t gBirthTime; |
54 |
|
55 |
peak_dict cmds_map; |
56 |
|
57 |
static void irc_client_nick_change_timer_cb(peak_timer ti, void *context); |
58 |
static void randnick_gen(char *nickbuf, size_t nicklen); |
59 |
|
60 |
static char my_netnum[6]; |
61 |
|
62 |
static const peak_dict_init_entry my_commands[] = |
63 |
{ |
64 |
{ "evreg", cmd_evreg }, |
65 |
{ "evshow", cmd_evshow }, |
66 |
{ "grem", cmd_grem }, |
67 |
{ "help", cmd_help }, |
68 |
{ "info", cmd_info }, |
69 |
{ "inv", cmd_inv }, |
70 |
{ "noscan", cmd_noscan }, |
71 |
{ "proxytop", cmd_proxytop }, |
72 |
{ "pxstats", cmd_pxstats }, |
73 |
{ "recheck", cmd_recheck }, |
74 |
{ "servers", cmd_servers }, |
75 |
{ "showcmds", cmd_showcmds }, |
76 |
{ "stats", cmd_stats }, |
77 |
{ "status", cmd_status } |
78 |
}; |
79 |
|
80 |
void |
81 |
irc_client_init() |
82 |
{ |
83 |
cmds_map = peak_dict_create(&peak_dict_stringcase_key_ops, |
84 |
&peak_dict_null_value_ops, |
85 |
my_commands, |
86 |
PEAK_DICT_INIT_ENTRY_COUNT(my_commands)); |
87 |
assert(cmds_map != NULL); |
88 |
|
89 |
if (gConfig->client.nick_change_delay > 0) |
90 |
peak_task_timer_add(peak_task_self(), |
91 |
peak_timer_create(gConfig->client.nick_change_delay, |
92 |
gConfig->client.nick_change_delay, |
93 |
irc_client_nick_change_timer_cb, |
94 |
NULL)); |
95 |
} |
96 |
|
97 |
void |
98 |
irc_client_register() |
99 |
{ |
100 |
char addr64[8]; |
101 |
ClientAddr caddr; |
102 |
char *nick; |
103 |
char randnick[MYNICKLEN + 1]; |
104 |
|
105 |
inttobase64(addr64, gConfig->client.userip.s_addr, 6); |
106 |
snprintf(my_netnum, sizeof(my_netnum), "%s%s", gMe.yy, MYCLIENT_NUM64); |
107 |
|
108 |
if (gConfig->client.nick_change_delay > 0) |
109 |
{ |
110 |
strncpy(randnick, gConfig->client.nickname, MYNICKLEN); |
111 |
randnick[MYNICKLEN] = '\0'; |
112 |
randnick_gen(randnick, MYNICKLEN); |
113 |
nick = randnick; |
114 |
} |
115 |
else |
116 |
nick = gConfig->client.nickname; |
117 |
|
118 |
send_raw("%s %s %s %d %ld %s %s %s %s %s :%s" CRLF, gMe.yy, TOK_NICK, |
119 |
nick, 1, gBirthTime, |
120 |
gConfig->client.username, gConfig->client.hostname, |
121 |
gConfig->client.usermode, addr64, my_netnum, |
122 |
gConfig->client.realname); |
123 |
|
124 |
caddr.ip4 = gConfig->client.userip; |
125 |
|
126 |
irc_userbase_add(nick, |
127 |
gConfig->client.username, |
128 |
gBirthTime, |
129 |
gConfig->client.usermode, |
130 |
0, |
131 |
caddr, |
132 |
my_netnum); |
133 |
} |
134 |
|
135 |
void |
136 |
irc_client_unregister() |
137 |
{ |
138 |
irc_userbase_remove(my_netnum); |
139 |
} |
140 |
|
141 |
void |
142 |
irc_client_burst() |
143 |
{ |
144 |
struct Channel *ch; |
145 |
struct Client *me; |
146 |
|
147 |
if (!(me = irc_network_find_client(yxx_to_int(my_netnum)))) |
148 |
return; |
149 |
|
150 |
/* Burst our client on the console channel */ |
151 |
if (!(ch = irc_channel_get(gConfig->client.channel))) |
152 |
ch = irc_channel_create(gConfig->client.channel, gConfig->client.chanTS); |
153 |
|
154 |
irc_membership_add(ch, me); |
155 |
|
156 |
/* Send something concrete to our uplink */ |
157 |
send_raw("%s %s %s %ld %s %s%s:o" CRLF, gMe.yy, TOK_BURST, |
158 |
gConfig->client.channel, gConfig->client.chanTS, |
159 |
gConfig->client.chanmode, gMe.yy, MYCLIENT_NUM64); |
160 |
} |
161 |
|
162 |
static void |
163 |
irc_client_nick_change_timer_cb(peak_timer ti, void *context) |
164 |
{ |
165 |
char new_nick[MYNICKLEN + 1]; |
166 |
char nn[6]; |
167 |
|
168 |
/* Find an available nickname */ |
169 |
do |
170 |
{ |
171 |
strncpy(new_nick, gConfig->client.nickname, MYNICKLEN); |
172 |
new_nick[MYNICKLEN] = '\0'; |
173 |
randnick_gen(new_nick, MYNICKLEN); |
174 |
} |
175 |
while (irc_userbase_get_by_nick(new_nick)); |
176 |
|
177 |
snprintf(nn, sizeof(nn), "%s%s", gMe.yy, MYCLIENT_NUM64); |
178 |
irc_userbase_nick_change(nn, new_nick); |
179 |
|
180 |
send_raw("%s%s %s %s %ld" CRLF, gMe.yy, MYCLIENT_NUM64, TOK_NICK, |
181 |
new_nick, peak_time()); |
182 |
} |
183 |
|
184 |
static void |
185 |
randnick_gen(char *nickbuf, size_t nicklen) |
186 |
{ |
187 |
size_t length; |
188 |
|
189 |
if ((length = strlen(gConfig->client.nickname)) >= nicklen) |
190 |
length = nicklen - 2; /* grr */ |
191 |
|
192 |
snprintf(nickbuf + length, nicklen - length + 1, "%lu", |
193 |
(unsigned long)rand() * (unsigned long)rand()); |
194 |
} |
195 |
|
196 |
void |
197 |
irc_client_handle_private(toktabptr ttab) |
198 |
{ |
199 |
cmd_func f; |
200 |
struct Client *cptr; |
201 |
const char *dst = ttab->tok[0]; |
202 |
const char *cmd = ttab->tok[3]; |
203 |
char ipbuf[32]; |
204 |
|
205 |
assert(cmd != NULL && ttab->size >= 4); |
206 |
if (*cmd == ':') |
207 |
cmd++; |
208 |
|
209 |
if (!*cmd) |
210 |
return; |
211 |
|
212 |
if ((cptr = irc_network_find_client(yxx_to_int(dst))) == NULL) |
213 |
return; /* doh */ |
214 |
|
215 |
if (!(cptr->flags & CLIENT_FLAG_OPER)) |
216 |
return; /* Non opers go play balls. */ |
217 |
|
218 |
if (!inet_ntop(cptr->flags & CLIENT_FLAG_IPV6 ? AF_INET6 : AF_INET, |
219 |
&cptr->addr, ipbuf, sizeof(ipbuf))) |
220 |
return; |
221 |
|
222 |
switch (ttab->size) |
223 |
{ |
224 |
case 4: |
225 |
log_write(LOGID_OPERCMDS, "<%s!%s@%s> %s", cptr->nick, cptr->user, |
226 |
ipbuf, cmd); |
227 |
break; |
228 |
case 5: |
229 |
log_write(LOGID_OPERCMDS, "<%s!%s@%s> %s %s", cptr->nick, cptr->user, |
230 |
ipbuf, cmd, ttab->tok[4]); |
231 |
break; |
232 |
case 6: |
233 |
log_write(LOGID_OPERCMDS, "<%s!%s@%s> %s %s %s", cptr->nick, cptr->user, |
234 |
ipbuf, cmd, ttab->tok[4], ttab->tok[5]); |
235 |
break; |
236 |
default: |
237 |
log_write(LOGID_OPERCMDS, "<%s!%s@%s> %s %s %s (...)", cptr->nick, |
238 |
cptr->user, ipbuf, cmd, ttab->tok[4], ttab->tok[5]); |
239 |
break; |
240 |
} |
241 |
|
242 |
/* Get client pointer here instead of in every cmd handlers.. */ |
243 |
if ((f = (cmd_func)peak_dict_get_value(cmds_map, cmd))) |
244 |
(*f)(cptr, ttab); |
245 |
else |
246 |
send_client_to_one(dst, "Sorry, command not found."); |
247 |
} |