ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/m_knock.c
Revision: 32
Committed: Sun Oct 2 20:41:23 2005 UTC (18 years, 5 months ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_knock.c
File size: 10052 byte(s)
Log Message:
- svn:keywords

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_knock.c: Requests to be invited to a channel.
4 *
5 * Copyright (C) 2002 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "tools.h"
27 #include "handlers.h"
28 #include "channel.h"
29 #include "channel_mode.h"
30 #include "client.h"
31 #include "hash.h"
32 #include "irc_string.h"
33 #include "sprintf_irc.h"
34 #include "ircd.h"
35 #include "numeric.h"
36 #include "send.h"
37 #include "s_conf.h"
38 #include "msg.h"
39 #include "parse.h"
40 #include "modules.h"
41 #include "s_serv.h"
42 #include "s_user.h"
43 #include "common.h"
44
45 static void m_knock(struct Client*, struct Client*, int, char**);
46 static void ms_knock(struct Client *, struct Client *, int, char**);
47 static void me_knock(struct Client *, struct Client *, int, char**);
48
49 static void parse_knock_local(struct Client *, struct Client *,
50 int, char **, char *);
51 static void parse_knock_remote(struct Client *, struct Client *,
52 int, char **, int);
53
54 static void send_knock(struct Client *, struct Client *,
55 struct Channel *, char *, char *, int, int);
56
57 struct Message knock_msgtab = {
58 "KNOCK", 0, 0, 2, 0, MFLG_SLOW, 0,
59 {m_unregistered, m_knock, ms_knock, me_knock, m_knock, m_ignore}
60 };
61
62 struct Message knockll_msgtab = {
63 "KNOCKLL", 0, 0, 2, 0, MFLG_SLOW, 0,
64 {m_unregistered, m_ignore, m_knock, m_ignore, m_ignore, m_ignore}
65 };
66
67 #ifndef STATIC_MODULES
68
69 void
70 _modinit(void)
71 {
72 mod_add_cmd(&knock_msgtab);
73 mod_add_cmd(&knockll_msgtab);
74 add_capability("KNOCK", CAP_KNOCK, 1);
75 add_isupport("KNOCK", NULL, -1);
76 }
77
78 void
79 _moddeinit(void)
80 {
81 mod_del_cmd(&knock_msgtab);
82 mod_del_cmd(&knockll_msgtab);
83 delete_capability("KNOCK");
84 delete_isupport("KNOCK");
85 }
86
87 const char *_version = "$Revision$";
88 #endif
89
90 /* m_knock
91 * parv[0] = sender prefix
92 * parv[1] = channel
93 *
94 * The KNOCK command has the following syntax:
95 * :<sender> KNOCK <channel>
96 *
97 * If a user is not banned from the channel they can use the KNOCK
98 * command to have the server NOTICE the channel operators notifying
99 * they would like to join. Helpful if the channel is invite-only, the
100 * key is forgotten, or the channel is full (INVITE can bypass each one
101 * of these conditions. Concept by Dianora <db@db.net> and written by
102 * <anonymous>
103 *
104 * This function is also used for LL servers forwarding knock requests they
105 * dont know about, for us to answer.
106 */
107 static void
108 m_knock(struct Client *client_p, struct Client *source_p,
109 int parc, char *parv[])
110 {
111 char *sockhost = NULL;
112
113 if ((ConfigChannel.use_knock == 0) && MyClient(source_p))
114 {
115 sendto_one(source_p, form_str(ERR_KNOCKDISABLED),
116 me.name, source_p->name);
117 return;
118 }
119
120 /* a remote KNOCKLL request, check we're capable of handling it.. */
121 if (!MyConnect(source_p))
122 {
123 if (!ServerInfo.hub || !IsCapable(client_p, CAP_LL) || parc < 3)
124 return;
125 else
126 {
127 /* set sockhost to parv[2] here to save messing in parse_knock_local() */
128 sockhost = parv[2];
129
130 if(parc > 3)
131 {
132 parv[2] = parv[3];
133 parv[3] = NULL;
134 }
135 else
136 parv[2] = NULL;
137
138 parc--;
139 }
140 }
141
142 if (IsClient(source_p))
143 parse_knock_local(client_p, source_p, parc, parv, sockhost);
144 }
145
146 /*
147 * ms_knock()
148 * parv[0] = sender prefix
149 * parv[1] = channel
150 */
151
152 static void
153 ms_knock(struct Client *client_p, struct Client *source_p,
154 int parc, char *parv[])
155 {
156 if (IsClient(source_p))
157 parse_knock_remote(client_p, source_p, parc, parv, 1);
158 }
159
160 /*
161 * me_knock()
162 * parv[0] = sender prefix
163 * parv[1] = channel
164 */
165
166 static void
167 me_knock(struct Client *client_p, struct Client *source_p,
168 int parc, char *parv[])
169 {
170 if (IsClient(source_p))
171 parse_knock_remote(client_p, source_p, parc, parv, 0);
172 }
173
174 /* parse_knock_local()
175 *
176 * input - pointer to physical struct client_p
177 * - pointer to source struct source_p
178 * - number of args
179 * - pointer to array of args
180 * - clients sockhost
181 * output -
182 * side effects - sets name to name of base channel
183 * or sends failure message to source_p
184 */
185 static void
186 parse_knock_local(struct Client *client_p, struct Client *source_p,
187 int parc, char *parv[], char *sockhost)
188 {
189 /* We will cut at the first comma reached, however we will not *
190 * process anything afterwards. */
191
192 struct Channel *chptr;
193 char *p, *name, *key;
194
195 name = parv[1];
196 key = (parc > 2) ? parv[2] : NULL;
197
198 if ((p = strchr(name, ',')) != NULL)
199 *p = '\0';
200
201 if (*name == '\0')
202 {
203 sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
204 me.name, source_p->name, "KNOCK");
205 return;
206 }
207
208 if (!IsChanPrefix(*name))
209 {
210 sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
211 me.name, source_p->name, name);
212 return;
213 }
214
215 if ((chptr = hash_find_channel(name)) == NULL)
216 {
217 if (!ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL))
218 {
219 sendto_one(uplink, ":%s KNOCKLL %s %s %s",
220 ID_or_name(source_p, uplink), parv[1],
221 IsIPSpoof(source_p) ? "255.255.255.255" :
222 source_p->sockhost,
223 (parc > 2) ? parv[2] : "");
224 }
225 else
226 {
227 sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
228 me.name, source_p->name, name);
229 }
230
231 return;
232 }
233
234 /* Normal channel, just be sure they aren't on it */
235 if (IsMember(source_p, chptr))
236 {
237 sendto_one(source_p, form_str(ERR_KNOCKONCHAN),
238 me.name, source_p->name, name);
239 return;
240 }
241
242 if (!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) ||
243 (chptr->mode.limit && dlink_list_length(&chptr->members) >=
244 chptr->mode.limit)))
245 {
246 sendto_one(source_p, form_str(ERR_CHANOPEN),
247 me.name, source_p->name, name);
248 return;
249 }
250
251 /* don't allow a knock if the user is banned, or the channel is secret */
252 if ((chptr->mode.mode & MODE_PRIVATE) || is_banned(chptr, source_p))
253 {
254 sendto_one(source_p, form_str(ERR_CANNOTSENDTOCHAN),
255 me.name, source_p->name, name);
256 return;
257 }
258
259 /* flood protection:
260 * allow one knock per user per knock_delay
261 * allow one knock per channel per knock_delay_channel
262 *
263 * we only limit local requests..
264 */
265 if (MyClient(source_p) &&
266 (source_p->localClient->last_knock + ConfigChannel.knock_delay) >
267 CurrentTime)
268 {
269 sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
270 me.name, source_p->name, parv[1], "user");
271 return;
272 }
273 else if (chptr->last_knock +
274 ConfigChannel.knock_delay_channel > CurrentTime)
275 {
276 sendto_one(source_p, form_str(ERR_TOOMANYKNOCK),
277 me.name, source_p->name, parv[1], "channel");
278 return;
279 }
280
281 /* pass on the knock */
282 send_knock(client_p, source_p, chptr, name, key,
283 MyClient(source_p) ? 0 : 1, 1);
284 }
285
286 /* parse_knock_remote()
287 *
288 * input - pointer to client
289 * - pointer to source
290 * - number of args
291 * - pointer to array of args
292 * output - none
293 * side effects - knock is checked for validity, if valid send_knock() is
294 * called
295 */
296 static void
297 parse_knock_remote(struct Client *client_p, struct Client *source_p,
298 int parc, char *parv[], int prop)
299 {
300 struct Channel *chptr;
301 char *p, *name, *key;
302
303 name = parv[1];
304 key = parv[2];
305
306 if ((p = strchr(name, ',')) != NULL)
307 *p = '\0';
308
309 if (!IsChanPrefix(*name) || (chptr = hash_find_channel(name)) == NULL)
310 return;
311
312 if (IsMember(source_p, chptr))
313 return;
314
315 if (!((chptr->mode.mode & MODE_INVITEONLY) || (*chptr->mode.key) ||
316 (chptr->mode.limit && dlink_list_length(&chptr->members) >=
317 chptr->mode.limit)))
318 return;
319
320 if (chptr)
321 send_knock(client_p, source_p, chptr, name, key, 0, prop);
322 }
323
324 /* send_knock()
325 *
326 * input - pointer to physical struct client_p
327 * - pointer to source struct source_p
328 * - pointer to channel struct chptr
329 * - pointer to base channel name
330 * output -
331 * side effects - knock is sent locally (if enabled) and propagated
332 */
333 static void
334 send_knock(struct Client *client_p, struct Client *source_p,
335 struct Channel *chptr, char *name, char *key, int llclient,
336 int prop)
337 {
338 chptr->last_knock = CurrentTime;
339
340 if (MyClient(source_p))
341 {
342 source_p->localClient->last_knock = CurrentTime;
343
344 sendto_one(source_p, form_str(RPL_KNOCKDLVR),
345 me.name, source_p->name, name);
346 }
347 else if (llclient == 1)
348 sendto_one(source_p, form_str(RPL_KNOCKDLVR),
349 me.name, source_p->name, name);
350
351 if (IsClient(source_p))
352 {
353 if (ConfigChannel.use_knock)
354 sendto_channel_local(CHFL_CHANOP, NO,
355 chptr, form_str(RPL_KNOCK),
356 me.name, name, name,
357 source_p->name, source_p->username,
358 source_p->host);
359
360 if (prop)
361 {
362 sendto_server(client_p, source_p, chptr, CAP_KNOCK|CAP_TS6, NOCAPS, LL_ICLIENT,
363 ":%s KNOCK %s %s",
364 ID(source_p), name, key != NULL ? key : "");
365 sendto_server(client_p, source_p, chptr, CAP_KNOCK, CAP_TS6, LL_ICLIENT,
366 ":%s KNOCK %s %s",
367 source_p->name, name, key != NULL ? key : "");
368 }
369 }
370 }
371

Properties

Name Value
svn:eol-style native
svn:keywords Revision