ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/m_knock.c
Revision: 30
Committed: Sun Oct 2 20:03:27 2005 UTC (18 years, 5 months ago) by adx
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/m_knock.c
File size: 10106 byte(s)
Log Message:
- imported sources
- can be moved later according to the directory/branching scheme,
  but we need the svn up

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     * $Id: m_knock.c,v 1.73 2005/07/31 05:32:36 adx Exp $
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: 1.73 $";
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 "Id Revision"