ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/m_connect.c
Revision: 348
Committed: Sat Dec 31 14:08:37 2005 UTC (20 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 9787 byte(s)
Log Message:
- More documentation

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * m_connect.c: Connects to a remote IRC server.
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 "client.h"
28     #include "ircd.h"
29     #include "numeric.h"
30     #include "s_conf.h"
31     #include "s_serv.h"
32     #include "send.h"
33     #include "msg.h"
34     #include "parse.h"
35     #include "hash.h"
36     #include "modules.h"
37    
38 michael 348 static void mo_connect(struct Client *, struct Client *, int, char *[]);
39     static void ms_connect(struct Client *, struct Client *, int, char *[]);
40 adx 30
41     struct Message connect_msgtab = {
42     "CONNECT", 0, 0, 2, 0, MFLG_SLOW, 0,
43 michael 348 { m_unregistered, m_not_oper, ms_connect, m_ignore, mo_connect, m_ignore }
44 adx 30 };
45    
46     #ifndef STATIC_MODULES
47     void
48     _modinit(void)
49     {
50     mod_add_cmd(&connect_msgtab);
51     }
52    
53     void
54     _moddeinit(void)
55     {
56     mod_del_cmd(&connect_msgtab);
57     }
58    
59 knight 31 const char *_version = "$Revision$";
60 adx 30 #endif
61    
62 michael 348 /*! \brief CONNECT command handler (called for operators only)
63 adx 30 *
64 michael 348 * \param client_p Pointer to allocated Client struct with physical connection
65     * to this server, i.e. with an open socket connected.
66     * \param source_p Pointer to allocated Client struct from which the message
67     * originally comes from. This can be a local or remote client.
68     * \param parc Integer holding the number of supplied arguments.
69     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
70     * pointers.
71     * \note Valid arguments for this command are:
72     * - parv[0] = sender prefix
73     * - parv[1] = servername
74     * - parv[2] = port number
75     * - parv[3] = remote server
76 adx 30 */
77     static void
78     mo_connect(struct Client* client_p, struct Client* source_p,
79     int parc, char* parv[])
80     {
81     int port;
82     int tmpport;
83     struct ConfItem *conf = NULL;
84     struct AccessItem *aconf = NULL;
85     struct Client *target_p;
86    
87     /* always privileged with handlers */
88     if (MyConnect(source_p) && !IsOperRemote(source_p) && parc > 3)
89     {
90     sendto_one(source_p, form_str(ERR_NOPRIVS),
91     me.name, source_p->name, "connect");
92     return;
93     }
94    
95 michael 348 if (hunt_server(client_p, source_p, ":%s CONNECT %s %s :%s", 3,
96     parc, parv) != HUNTED_ISME)
97 adx 30 return;
98    
99     if (*parv[1] == '\0')
100     {
101     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
102     me.name, source_p->name, "CONNECT");
103     return;
104     }
105    
106     if ((target_p = find_server(parv[1])))
107     {
108     sendto_one(source_p,
109     ":%s NOTICE %s :Connect: Server %s already exists from %s.",
110     me.name, source_p->name, parv[1], target_p->from->name);
111     return;
112     }
113    
114     /*
115     * try to find the name, then host, if both fail notify ops and bail
116     */
117     if ((conf = find_matching_name_conf(SERVER_TYPE,
118     parv[1], NULL, NULL, 0)) != NULL)
119 db 139 aconf = &conf->conf.AccessItem;
120 adx 30 else if ((conf = find_matching_name_conf(SERVER_TYPE,
121     NULL, NULL, parv[1], 0)) != NULL)
122 db 139 aconf = &conf->conf.AccessItem;
123 adx 30
124     if (conf == NULL)
125     {
126     sendto_one(source_p,
127     ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
128     me.name, source_p->name, parv[1]);
129     return;
130     }
131    
132     /* Get port number from user, if given. If not specified,
133     * use the default form configuration structure. If missing
134     * from there, then use the precompiled default.
135     */
136     tmpport = port = aconf->port;
137    
138     if (parc > 2 && !EmptyString(parv[2]))
139     {
140     if ((port = atoi(parv[2])) <= 0)
141     {
142     sendto_one(source_p, ":%s NOTICE %s :Connect: Illegal port number",
143     me.name, source_p->name);
144     return;
145     }
146     }
147     else if (port <= 0 && (port = PORTNUM) <= 0)
148     {
149     sendto_one(source_p, ":%s NOTICE %s :Connect: missing port number",
150     me.name, source_p->name);
151     return;
152     }
153    
154     if (find_servconn_in_progress(conf->name))
155     {
156     sendto_one(source_p, ":%s NOTICE %s :Connect: a connection to %s "
157     "is already in progress.", me.name, source_p->name, conf->name);
158     return;
159     }
160    
161     /*
162     * Notify all operators about remote connect requests
163     */
164     ilog(L_TRACE, "CONNECT From %s : %s %s",
165     source_p->name, parv[1], parv[2] ? parv[2] : "");
166    
167     aconf->port = port;
168    
169     /* at this point we should be calling connect_server with a valid
170     * C:line and a valid port in the C:line
171     */
172     if (serv_connect(aconf, source_p))
173     {
174     if (!ConfigServerHide.hide_server_ips && IsAdmin(source_p))
175     sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s[%s].%d",
176     me.name, source_p->name, aconf->host,
177     conf->name, aconf->port);
178     else
179     sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s.%d",
180     me.name, source_p->name, conf->name, aconf->port);
181     }
182     else
183     {
184     sendto_one(source_p, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
185     me.name, source_p->name, conf->name, aconf->port);
186     }
187    
188 michael 348 /*
189     * client is either connecting with all the data it needs or has been
190 adx 30 * destroyed
191     */
192     aconf->port = tmpport;
193     }
194    
195 michael 348 /*! \brief CONNECT command handler (called for remote clients only)
196 adx 30 *
197 michael 348 * \param client_p Pointer to allocated Client struct with physical connection
198     * to this server, i.e. with an open socket connected.
199     * \param source_p Pointer to allocated Client struct from which the message
200     * originally comes from. This can be a local or remote client.
201     * \param parc Integer holding the number of supplied arguments.
202     * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL
203     * pointers.
204     * \note Valid arguments for this command are:
205     * - parv[0] = sender prefix
206     * - parv[1] = servername
207     * - parv[2] = port number
208     * - parv[3] = remote server
209 adx 30 */
210     static void
211     ms_connect(struct Client *client_p, struct Client *source_p,
212     int parc, char *parv[])
213     {
214     int port;
215     int tmpport;
216     struct ConfItem *conf = NULL;
217     struct AccessItem *aconf = NULL;
218     struct Client *target_p;
219    
220 michael 348 if (hunt_server(client_p, source_p, ":%s CONNECT %s %s :%s", 3,
221     parc, parv) != HUNTED_ISME)
222 adx 30 return;
223    
224     if (*parv[1] == '\0')
225     {
226     sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS),
227     me.name, source_p->name, "CONNECT");
228     return;
229     }
230    
231     if ((target_p = find_server(parv[1])))
232     {
233     sendto_one(source_p,
234     ":%s NOTICE %s :Connect: Server %s already exists from %s.",
235     me.name, source_p->name, parv[1], target_p->from->name);
236     return;
237     }
238    
239     /*
240     * try to find the name, then host, if both fail notify ops and bail
241     */
242     if ((conf = find_matching_name_conf(SERVER_TYPE,
243     parv[1], NULL, NULL, 0)) != NULL)
244 db 139 aconf = &conf->conf.AccessItem;
245 adx 30 else if ((conf = find_matching_name_conf(SERVER_TYPE,
246     NULL, NULL, parv[1], 0)) != NULL)
247 db 139 aconf = &conf->conf.AccessItem;
248 adx 30
249     if (aconf == NULL)
250     {
251     sendto_one(source_p,
252     ":%s NOTICE %s :Connect: Host %s not listed in ircd.conf",
253     me.name, source_p->name, parv[1]);
254     return;
255     }
256    
257     assert(aconf != NULL);
258    
259     /* Get port number from user, if given. If not specified,
260     * use the default form configuration structure. If missing
261     * from there, then use the precompiled default.
262     */
263     tmpport = port = aconf->port;
264    
265     if (parc > 2 && !EmptyString(parv[2]))
266     {
267     port = atoi(parv[2]);
268    
269     /* if someone sends port 0, and we have a config port.. use it */
270     if (port == 0 && aconf->port)
271     port = aconf->port;
272     else if (port <= 0)
273     {
274     sendto_one(source_p, ":%s NOTICE %s :Connect: Illegal port number",
275     me.name, source_p->name);
276     return;
277     }
278     }
279     else if (port <= 0 && (port = PORTNUM) <= 0)
280     {
281     sendto_one(source_p, ":%s NOTICE %s :Connect: missing port number",
282     me.name, source_p->name);
283     return;
284     }
285    
286     if (find_servconn_in_progress(conf->name))
287     {
288     sendto_one(source_p, ":%s NOTICE %s :Connect: a connection to %s "
289     "is already in progress.", me.name, source_p->name, conf->name);
290     return;
291     }
292    
293     /*
294     * Notify all operators about remote connect requests
295     */
296     sendto_wallops_flags(UMODE_WALLOP, &me, "Remote CONNECT %s %d from %s",
297     parv[1], port, source_p->name);
298     sendto_server(NULL, NULL, NULL, NOCAPS, NOCAPS, NOFLAGS,
299     ":%s WALLOPS :Remote CONNECT %s %d from %s",
300     me.name, parv[1], port, source_p->name);
301    
302     ilog(L_TRACE, "CONNECT From %s : %s %d",
303     source_p->name, parv[1], port);
304    
305     aconf->port = port;
306    
307     /* at this point we should be calling connect_server with a valid
308     * C:line and a valid port in the C:line
309     */
310     if (serv_connect(aconf, source_p))
311     sendto_one(source_p, ":%s NOTICE %s :*** Connecting to %s.%d",
312     me.name, source_p->name, conf->name, aconf->port);
313     else
314     sendto_one(source_p, ":%s NOTICE %s :*** Couldn't connect to %s.%d",
315     me.name, source_p->name, conf->name, aconf->port);
316 michael 348
317     /*
318     * client is either connecting with all the data it needs or has been
319 adx 30 * destroyed
320     */
321     aconf->port = tmpport;
322     }

Properties

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