ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/m_knock.c
Revision: 227
Committed: Thu Nov 3 18:29:22 2005 UTC (20 years, 9 months ago) by db
Content type: text/x-csrc
File size: 9985 byte(s)
Log Message:
- replace all MODE_PRIVATE with MODE_PARANOID
- Can't use make_dlink_node() too early in startup or it will core


File Contents

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

Properties

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