ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 6387
Committed: Sat Aug 22 17:36:03 2015 UTC (10 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 27597 byte(s)
Log Message:
- m_server.c:server_estab(): removed comment that's outdated for 24 years now

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 5347 * Copyright (c) 1997-2015 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_server.c
23     * \brief Includes required functions for processing the SERVER/SID command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 michael 2820 #include "client.h"
30 adx 30 #include "event.h"
31 michael 2820 #include "hash.h"
32 michael 6161 #include "id.h"
33 michael 2820 #include "irc_string.h"
34     #include "ircd.h"
35     #include "numeric.h"
36     #include "conf.h"
37     #include "log.h"
38 michael 3347 #include "misc.h"
39     #include "server.h"
40     #include "user.h"
41 michael 2820 #include "send.h"
42 adx 30 #include "parse.h"
43 michael 3303 #include "memory.h"
44 adx 30 #include "modules.h"
45    
46    
47 michael 3303 /*
48     * send_tb
49     *
50     * inputs - pointer to Client
51     * - pointer to channel
52     * output - NONE
53     * side effects - Called on a server burst when
54 michael 6354 * server is CAPAB_TBURST capable
55 michael 3303 */
56     static void
57 michael 4755 send_tb(struct Client *client_p, const struct Channel *chptr)
58 michael 3303 {
59     /*
60     * We may also send an empty topic here, but only if topic_time isn't 0,
61     * i.e. if we had a topic that got unset. This is required for syncing
62     * topics properly.
63     *
64     * Imagine the following scenario: Our downlink introduces a channel
65     * to us with a TS that is equal to ours, but the channel topic on
66     * their side got unset while the servers were in splitmode, which means
67     * their 'topic' is newer. They simply wanted to unset it, so we have to
68     * deal with it in a more sophisticated fashion instead of just resetting
69     * it to their old topic they had before. Read m_tburst.c:ms_tburst
70     * for further information -Michael
71     */
72     if (chptr->topic_time)
73     sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s", me.id,
74 michael 4818 (unsigned long)chptr->creationtime, chptr->name,
75 michael 3303 (unsigned long)chptr->topic_time,
76     chptr->topic_info,
77     chptr->topic);
78     }
79    
80     /* sendnick_TS()
81     *
82     * inputs - client (server) to send nick towards
83     * - client to send nick for
84     * output - NONE
85     * side effects - NICK message is sent towards given client_p
86     */
87 michael 3306 static void
88 michael 3303 sendnick_TS(struct Client *client_p, struct Client *target_p)
89     {
90 michael 5551 dlink_node *node = NULL;
91 michael 3303 char ubuf[IRCD_BUFSIZE] = "";
92    
93     if (!IsClient(target_p))
94     return;
95    
96 michael 4020 send_umode(NULL, target_p, 0, ubuf);
97 michael 3303
98     if (ubuf[0] == '\0')
99     {
100     ubuf[0] = '+';
101     ubuf[1] = '\0';
102     }
103    
104 michael 6354 if (IsCapable(client_p, CAPAB_SVS))
105 michael 5784 sendto_one(client_p, ":%s UID %s %u %lu %s %s %s %s %s %s :%s",
106 michael 3303 target_p->servptr->id,
107     target_p->name, target_p->hopcount + 1,
108     (unsigned long) target_p->tsinfo,
109     ubuf, target_p->username, target_p->host,
110 michael 4966 target_p->sockhost, target_p->id,
111 michael 4819 target_p->account, target_p->info);
112 michael 3303 else
113 michael 5784 sendto_one(client_p, ":%s UID %s %u %lu %s %s %s %s %s :%s",
114 michael 3303 target_p->servptr->id,
115     target_p->name, target_p->hopcount + 1,
116     (unsigned long) target_p->tsinfo,
117     ubuf, target_p->username, target_p->host,
118 michael 4966 target_p->sockhost, target_p->id, target_p->info);
119 michael 3303
120     if (!EmptyString(target_p->certfp))
121     sendto_one(client_p, ":%s CERTFP %s", target_p->id, target_p->certfp);
122    
123     if (target_p->away[0])
124     sendto_one(client_p, ":%s AWAY :%s", target_p->id, target_p->away);
125    
126 michael 5551
127     DLINK_FOREACH(node, target_p->svstags.head)
128     {
129     const struct ServicesTag *svstag = node->data;
130 michael 5558 char *m = ubuf;
131 michael 5551
132 michael 5558 for (const struct user_modes *tab = umode_tab; tab->c; ++tab)
133     if (svstag->umodes & tab->flag)
134     *m++ = tab->c;
135     *m = '\0';
136    
137     sendto_one(client_p, ":%s SVSTAG %s %lu %u +%s :%s", me.id, target_p->id,
138     target_p->tsinfo, svstag->numeric, ubuf, svstag->tag);
139 michael 5551 }
140 michael 3303 }
141    
142     /* burst_members()
143     *
144     * inputs - pointer to server to send members to
145     * - dlink_list pointer to membership list to send
146     * output - NONE
147     * side effects -
148     */
149     static void
150     burst_members(struct Client *client_p, struct Channel *chptr)
151     {
152     struct Client *target_p;
153 michael 4815 struct Membership *member;
154     dlink_node *node = NULL;
155 michael 3303
156 michael 4815 DLINK_FOREACH(node, chptr->members.head)
157 michael 3303 {
158 michael 4815 member = node->data;
159     target_p = member->client_p;
160 michael 3303
161     if (!HasFlag(target_p, FLAGS_BURSTED))
162     {
163     AddFlag(target_p, FLAGS_BURSTED);
164    
165     if (target_p->from != client_p)
166     sendnick_TS(client_p, target_p);
167     }
168     }
169     }
170    
171     /* burst_all()
172     *
173     * inputs - pointer to server to send burst to
174     * output - NONE
175     * side effects - complete burst of channels/nicks is sent to client_p
176     */
177     static void
178     burst_all(struct Client *client_p)
179     {
180 michael 4815 dlink_node *node = NULL;
181 michael 3303
182 michael 4815 DLINK_FOREACH(node, channel_list.head)
183 michael 3303 {
184 michael 4815 struct Channel *chptr = node->data;
185 michael 3303
186     if (dlink_list_length(&chptr->members))
187     {
188     burst_members(client_p, chptr);
189 michael 6373 channel_send_modes(client_p, chptr);
190 michael 3303
191 michael 6354 if (IsCapable(client_p, CAPAB_TBURST))
192 michael 3303 send_tb(client_p, chptr);
193     }
194     }
195    
196     /* also send out those that are not on any channel
197     */
198 michael 4815 DLINK_FOREACH(node, global_client_list.head)
199 michael 3303 {
200 michael 4815 struct Client *target_p = node->data;
201 michael 3303
202     if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
203     sendnick_TS(client_p, target_p);
204    
205     DelFlag(target_p, FLAGS_BURSTED);
206     }
207     }
208    
209     /* server_burst()
210     *
211     * inputs - struct Client pointer server
212     * -
213     * output - none
214     * side effects - send a server burst
215     * bugs - still too long
216     */
217     static void
218     server_burst(struct Client *client_p)
219     {
220     /* Send it in the shortened format with the TS, if
221     ** it's a TS server; walk the list of channels, sending
222     ** all the nicks that haven't been sent yet for each
223     ** channel, then send the channel itself -- it's less
224     ** obvious than sending all nicks first, but on the
225     ** receiving side memory will be allocated more nicely
226     ** saving a few seconds in the handling of a split
227     ** -orabidoo
228     */
229    
230     burst_all(client_p);
231    
232     /* EOB stuff is now in burst_all */
233     /* Always send a PING after connect burst is done */
234     sendto_one(client_p, "PING :%s", me.id);
235     }
236    
237     /* server_estab()
238     *
239     * inputs - pointer to a struct Client
240     * output -
241     * side effects -
242     */
243 michael 3306 static void
244 michael 3303 server_estab(struct Client *client_p)
245     {
246     struct MaskItem *conf = NULL;
247 michael 4815 dlink_node *node = NULL;
248 michael 4247 #if defined(HAVE_LIBCRYPTO) && !defined(OPENSSL_NO_COMP)
249 michael 3303 const COMP_METHOD *compression = NULL, *expansion = NULL;
250     #endif
251    
252 michael 4595 if ((conf = find_conf_name(&client_p->connection->confs, client_p->name, CONF_SERVER))
253 michael 3303 == NULL)
254     {
255     /* This shouldn't happen, better tell the ops... -A1kmm */
256 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
257 michael 3303 "Warning: Lost connect{} block "
258 michael 4595 "for server %s(this shouldn't happen)!", client_p->name);
259 michael 3303 exit_client(client_p, "Lost connect{} block!");
260     return;
261     }
262    
263 michael 4588 MyFree(client_p->connection->password);
264     client_p->connection->password = NULL;
265 michael 3303
266 michael 4612 if (!ConfigServerInfo.hub && dlink_list_length(&local_server_list))
267 michael 3303 {
268 michael 4612 ++ServerStats.is_ref;
269     exit_client(client_p, "I'm a leaf not a hub");
270     return;
271 michael 3303 }
272    
273     if (IsUnknown(client_p))
274     {
275     sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
276    
277 michael 5796 send_capabilities(client_p);
278 michael 3303
279     sendto_one(client_p, "SERVER %s 1 :%s%s",
280     me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
281     }
282    
283 michael 4009 sendto_one(client_p, ":%s SVINFO %d %d 0 :%lu", me.id, TS_CURRENT, TS_MIN,
284 michael 3303 (unsigned long)CurrentTime);
285    
286     /* *WARNING*
287     ** In the following code in place of plain server's
288     ** name we send what is returned by get_client_name
289     ** which may add the "sockhost" after the name. It's
290     ** *very* *important* that there is a SPACE between
291     ** the name and sockhost (if present). The receiving
292     ** server will start the information field from this
293     ** first blank and thus puts the sockhost into info.
294     ** ...a bit tricky, but you have been warned, besides
295     ** code is more neat this way... --msa
296     */
297     client_p->servptr = &me;
298    
299     if (IsClosing(client_p))
300     return;
301    
302     SetServer(client_p);
303    
304     /* Some day, all these lists will be consolidated *sigh* */
305     dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
306    
307     assert(dlinkFind(&unknown_list, client_p));
308    
309 michael 4588 dlink_move_node(&client_p->connection->lclient_node,
310 michael 4213 &unknown_list, &local_server_list);
311 michael 3303
312     Count.myserver++;
313    
314 michael 4189 dlinkAdd(client_p, &client_p->node, &global_client_list);
315 michael 4209 dlinkAdd(client_p, make_dlink_node(), &global_server_list);
316 michael 3303 hash_add_client(client_p);
317     hash_add_id(client_p);
318    
319 michael 4581 /* Doesn't duplicate client_p->serv if allocated this struct already */
320 michael 3303 make_server(client_p);
321    
322 michael 4581 /* Fixing eob timings.. -gnp */
323 michael 4588 client_p->connection->firsttime = CurrentTime;
324 michael 3303
325     if (find_matching_name_conf(CONF_SERVICE, client_p->name, NULL, NULL, 0))
326     AddFlag(client_p, FLAGS_SERVICE);
327    
328     /* Show the real host/IP to admins */
329     #ifdef HAVE_LIBCRYPTO
330 michael 4588 if (client_p->connection->fd.ssl)
331 michael 3303 {
332 michael 4247 #ifndef OPENSSL_NO_COMP
333 michael 4588 compression = SSL_get_current_compression(client_p->connection->fd.ssl);
334     expansion = SSL_get_current_expansion(client_p->connection->fd.ssl);
335 michael 4247 #endif
336 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
337 michael 3303 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
338 michael 4605 get_client_name(client_p, SHOW_IP), ssl_get_cipher(client_p->connection->fd.ssl),
339 michael 4247 #ifndef OPENSSL_NO_COMP
340 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
341     expansion ? SSL_COMP_get_name(expansion) : "NONE",
342 michael 4247 #else
343     "NONE", "NONE",
344     #endif
345 michael 3303 show_capabilities(client_p));
346     /* Now show the masked hostname/IP to opers */
347 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
348 michael 3303 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
349 michael 4605 get_client_name(client_p, MASK_IP), ssl_get_cipher(client_p->connection->fd.ssl),
350 michael 4247 #ifndef OPENSSL_NO_COMP
351 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
352     expansion ? SSL_COMP_get_name(expansion) : "NONE",
353 michael 4247 #else
354     "NONE", "NONE",
355     #endif
356 michael 3303 show_capabilities(client_p));
357     ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
358 michael 4605 get_client_name(client_p, SHOW_IP), ssl_get_cipher(client_p->connection->fd.ssl),
359 michael 4247 #ifndef OPENSSL_NO_COMP
360 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
361     expansion ? SSL_COMP_get_name(expansion) : "NONE",
362 michael 4247 #else
363     "NONE", "NONE",
364     #endif
365 michael 3303 show_capabilities(client_p));
366     }
367     else
368     #endif
369     {
370 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
371 michael 3303 "Link with %s established: (Capabilities: %s)",
372 michael 4605 get_client_name(client_p, SHOW_IP), show_capabilities(client_p));
373 michael 3303 /* Now show the masked hostname/IP to opers */
374 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
375 michael 3303 "Link with %s established: (Capabilities: %s)",
376 michael 4605 get_client_name(client_p, MASK_IP), show_capabilities(client_p));
377 michael 3303 ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
378 michael 4605 get_client_name(client_p, SHOW_IP), show_capabilities(client_p));
379 michael 3303 }
380    
381 michael 4588 fd_note(&client_p->connection->fd, "Server: %s", client_p->name);
382 michael 3303
383 michael 4962 sendto_server(client_p, 0, 0, ":%s SID %s 2 %s :%s%s",
384 michael 3303 me.id, client_p->name, client_p->id,
385     IsHidden(client_p) ? "(H) " : "", client_p->info);
386    
387     /*
388     * Pass on my client information to the new server
389     *
390     * First, pass only servers (idea is that if the link gets
391     * cancelled beacause the server was already there,
392     * there are no NICK's to be cancelled...). Of course,
393     * if cancellation occurs, all this info is sent anyway,
394     * and I guess the link dies when a read is attempted...? --msa
395     *
396     * Note: Link cancellation to occur at this point means
397     * that at least two servers from my fragment are building
398     * up connection this other fragment at the same time, it's
399     * a race condition, not the normal way of operation...
400     */
401 michael 4815 DLINK_FOREACH_PREV(node, global_server_list.tail)
402 michael 3303 {
403 michael 4815 struct Client *target_p = node->data;
404 michael 3303
405     /* target_p->from == target_p for target_p == client_p */
406     if (IsMe(target_p) || target_p->from == client_p)
407     continue;
408    
409 michael 5784 sendto_one(client_p, ":%s SID %s %u %s :%s%s",
410 michael 3303 target_p->servptr->id, target_p->name, target_p->hopcount+1,
411     target_p->id, IsHidden(target_p) ? "(H) " : "",
412     target_p->info);
413     }
414    
415     server_burst(client_p);
416 michael 4711
417 michael 6354 if (IsCapable(client_p, CAPAB_EOB))
418 michael 4711 {
419 michael 4815 DLINK_FOREACH_PREV(node, global_server_list.tail)
420 michael 4711 {
421 michael 4815 struct Client *target_p = node->data;
422 michael 4711
423     if (target_p->from == client_p)
424     continue;
425    
426     if (IsMe(target_p) || HasFlag(target_p, FLAGS_EOB))
427     sendto_one(client_p, ":%s EOB", target_p->id);
428     }
429     }
430 michael 3303 }
431    
432 michael 1997 /* set_server_gecos()
433     *
434     * input - pointer to client
435     * output - NONE
436     * side effects - servers gecos field is set
437     */
438     static void
439     set_server_gecos(struct Client *client_p, const char *info)
440     {
441     const char *s = info;
442 adx 30
443 michael 1997 /* check for (H) which is a hidden server */
444     if (!strncmp(s, "(H) ", 4))
445     {
446 michael 6313 AddFlag(client_p, FLAGS_HIDDEN);
447 michael 1997 s = s + 4;
448     }
449    
450     if (!EmptyString(s))
451     strlcpy(client_p->info, s, sizeof(client_p->info));
452     else
453     strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
454     }
455    
456 adx 30 /* mr_server()
457 michael 3096 * parv[0] = command
458 adx 30 * parv[1] = servername
459 michael 3139 * parv[2] = hopcount
460 adx 30 * parv[3] = serverinfo
461     */
462 michael 2820 static int
463 michael 3156 mr_server(struct Client *source_p, int parc, char *parv[])
464 adx 30 {
465 michael 4755 const char *name = parv[1];
466 michael 3246 struct Client *target_p = NULL;
467 adx 30
468 michael 4659 if (EmptyString(parv[parc - 1]))
469 adx 30 {
470 michael 4611 exit_client(source_p, "No server description supplied");
471 michael 2820 return 0;
472 adx 30 }
473    
474 michael 1118 if (!valid_servname(name))
475 adx 30 {
476 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
477 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
478 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
479 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
480 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
481 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
482 michael 3171 exit_client(source_p, "Bogus server name");
483 michael 2820 return 0;
484 adx 30 }
485    
486 michael 3156 if (!valid_sid(source_p->id))
487 michael 3148 {
488 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
489 michael 3148 "Link %s introduced server with bogus server ID %s",
490 michael 3156 get_client_name(source_p, SHOW_IP), source_p->id);
491 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
492 michael 3148 "Link %s introduced server with bogus server ID %s",
493 michael 3156 get_client_name(source_p, MASK_IP), source_p->id);
494 michael 4572 exit_client(source_p, "Bogus server ID introduced");
495 michael 3148 return 0;
496     }
497    
498 adx 30 /* Now we just have to call check_server and everything should
499     * be check for us... -A1kmm.
500     */
501 michael 3156 switch (check_server(name, source_p))
502 adx 30 {
503     case -1:
504 michael 4340 if (ConfigGeneral.warn_no_connect_block)
505 adx 30 {
506 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
507 adx 30 "Unauthorized server connection attempt from %s: No entry for "
508 michael 3156 "servername %s", get_client_name(source_p, HIDE_IP), name);
509 adx 30
510 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
511 adx 30 "Unauthorized server connection attempt from %s: No entry for "
512 michael 3156 "servername %s", get_client_name(source_p, MASK_IP), name);
513 adx 30 }
514    
515 michael 4611 exit_client(source_p, "No connect {} block.");
516 michael 2820 return 0;
517 adx 30 /* NOT REACHED */
518     break;
519    
520     case -2:
521 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
522 adx 30 "Unauthorized server connection attempt from %s: Bad password "
523 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
524 adx 30
525 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
526 adx 30 "Unauthorized server connection attempt from %s: Bad password "
527 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
528 adx 30
529 michael 3171 exit_client(source_p, "Invalid password.");
530 michael 2820 return 0;
531 adx 30 /* NOT REACHED */
532     break;
533    
534     case -3:
535 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
536 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
537 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
538 adx 30
539 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
540 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
541 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
542 adx 30
543 michael 3171 exit_client(source_p, "Invalid host.");
544 michael 2820 return 0;
545 michael 2228 case -4:
546 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
547 michael 2228 "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
548 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
549 michael 2228
550 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
551 michael 2228 "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
552 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
553 michael 2228
554 michael 3171 exit_client(source_p, "Invalid certificate fingerprint.");
555 michael 2820 return 0;
556 adx 30 /* NOT REACHED */
557     break;
558     }
559    
560 michael 2976 if ((target_p = hash_find_server(name)))
561 adx 30 {
562     /* This link is trying feed me a server that I already have
563     * access through another path -- multiple paths not accepted
564     * currently, kill this link immediately!!
565     *
566     * Rather than KILL the link which introduced it, KILL the
567     * youngest of the two links. -avalon
568     *
569     * Definitely don't do that here. This is from an unregistered
570     * connect - A1kmm.
571     */
572 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
573 michael 2976 "Attempt to re-introduce server %s from %s",
574 michael 3156 name, get_client_name(source_p, HIDE_IP));
575 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
576 michael 2976 "Attempt to re-introduce server %s from %s",
577 michael 3156 name, get_client_name(source_p, MASK_IP));
578 michael 3171 exit_client(source_p, "Server already exists");
579 michael 2976 return 0;
580     }
581    
582 michael 3156 if ((target_p = hash_find_id(source_p->id)))
583 michael 2976 {
584 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
585 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
586 michael 3156 name, source_p->id,
587     get_client_name(source_p, HIDE_IP));
588 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
589 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
590 michael 3156 name, source_p->id,
591     get_client_name(source_p, MASK_IP));
592 michael 3171 exit_client(source_p, "Server ID already exists");
593 michael 2820 return 0;
594 adx 30 }
595    
596     /* XXX If somehow there is a connect in progress and
597     * a connect comes in with same name toss the pending one,
598     * but only if it's not the same client! - Dianora
599     */
600     if ((target_p = find_servconn_in_progress(name)))
601 michael 3156 if (target_p != source_p)
602 michael 3171 exit_client(target_p, "Overridden");
603 adx 30
604     /* if we are connecting (Handshake), we already have the name from the
605 michael 3156 * connect{} block in source_p->name
606 adx 30 */
607 michael 3156 strlcpy(source_p->name, name, sizeof(source_p->name));
608 michael 4659 set_server_gecos(source_p, parv[parc - 1]);
609 michael 3190 source_p->hopcount = atoi(parv[2]);
610 michael 3156 server_estab(source_p);
611 michael 2820 return 0;
612 adx 30 }
613    
614     /* ms_sid()
615 michael 3096 * parv[0] = command
616 adx 30 * parv[1] = servername
617 michael 3139 * parv[2] = hopcount
618 adx 30 * parv[3] = sid of new server
619     * parv[4] = serverinfo
620     */
621 michael 2820 static int
622 michael 3156 ms_sid(struct Client *source_p, int parc, char *parv[])
623 adx 30 {
624 michael 4815 dlink_node *node = NULL;
625 michael 3139 struct Client *target_p = NULL;
626 michael 3156 struct Client *client_p = source_p->from; /* XXX */
627 michael 3139 const struct MaskItem *conf = NULL;
628 adx 30 int hlined = 0;
629     int llined = 0;
630    
631     /* Just to be sure -A1kmm. */
632     if (!IsServer(source_p))
633 michael 2820 return 0;
634 adx 30
635 michael 4659 if (EmptyString(parv[parc - 1]))
636 michael 1118 {
637 michael 4611 exit_client(client_p, "No server description supplied");
638 michael 2820 return 0;
639 michael 1118 }
640 adx 30
641 michael 1118 if (!valid_servname(parv[1]))
642     {
643 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
644 michael 1118 "Link %s introduced server with bogus server name %s",
645     get_client_name(client_p, SHOW_IP), parv[1]);
646 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
647 michael 1118 "Link %s introduced server with bogus server name %s",
648     get_client_name(client_p, MASK_IP), parv[1]);
649 michael 4572 exit_client(client_p, "Bogus server name introduced");
650 michael 2820 return 0;
651 michael 1118 }
652    
653     if (!valid_sid(parv[3]))
654     {
655 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
656 michael 1118 "Link %s introduced server with bogus server ID %s",
657     get_client_name(client_p, SHOW_IP), parv[3]);
658 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
659 michael 1118 "Link %s introduced server with bogus server ID %s",
660     get_client_name(client_p, MASK_IP), parv[3]);
661 michael 4572 exit_client(client_p, "Bogus server ID introduced");
662 michael 2820 return 0;
663 michael 1118 }
664    
665 adx 30 /* collision on SID? */
666 michael 1118 if ((target_p = hash_find_id(parv[3])))
667 adx 30 {
668 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
669 michael 4611 "Link %s cancelled, server ID %s already exists",
670 michael 1118 get_client_name(client_p, SHOW_IP), parv[3]);
671 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
672 michael 4611 "Link %s cancelled, server ID %s already exists",
673 michael 1118 client_p->name, parv[3]);
674 michael 4611 exit_client(client_p, "Link cancelled, server ID already exists");
675 michael 2820 return 0;
676 adx 30 }
677    
678     /* collision on name? */
679 michael 1169 if ((target_p = hash_find_server(parv[1])))
680 adx 30 {
681 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
682 michael 2820 "Link %s cancelled, server %s already exists",
683 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
684 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
685 michael 2820 "Link %s cancelled, server %s already exists",
686 michael 1118 client_p->name, parv[1]);
687 michael 4611 exit_client(client_p, "Server exists");
688 michael 2820 return 0;
689 adx 30 }
690    
691     /* XXX If somehow there is a connect in progress and
692     * a connect comes in with same name toss the pending one,
693     * but only if it's not the same client! - Dianora
694     */
695 michael 1118 if ((target_p = find_servconn_in_progress(parv[1])))
696 adx 30 if (target_p != client_p)
697 michael 3171 exit_client(target_p, "Overridden");
698 adx 30
699 michael 4588 conf = client_p->connection->confs.head->data;
700 michael 1384
701 adx 30 /* See if the newly found server is behind a guaranteed
702     * leaf. If so, close the link.
703     */
704 michael 4815 DLINK_FOREACH(node, conf->leaf_list.head)
705 michael 3139 {
706 michael 4815 if (!match(node->data, parv[1]))
707 michael 1529 {
708     llined = 1;
709     break;
710     }
711 michael 3139 }
712 adx 30
713 michael 4815 DLINK_FOREACH(node, conf->hub_list.head)
714 michael 3139 {
715 michael 4815 if (!match(node->data, parv[1]))
716 michael 1529 {
717     hlined = 1;
718     break;
719     }
720 michael 3139 }
721 michael 1118
722 adx 30 /* Ok, this way this works is
723     *
724     * A server can have a CONF_HUB allowing it to introduce servers
725     * behind it.
726     *
727     * connect {
728     * name = "irc.bighub.net";
729     * hub_mask="*";
730     * ...
731 michael 2820 *
732 adx 30 * That would allow "irc.bighub.net" to introduce anything it wanted..
733     *
734     * However
735     *
736     * connect {
737     * name = "irc.somehub.fi";
738     * hub_mask="*";
739     * leaf_mask="*.edu";
740     *...
741     * Would allow this server in finland to hub anything but
742     * .edu's
743     */
744    
745     /* Ok, check client_p can hub the new server, and make sure it's not a LL */
746 michael 885 if (!hlined)
747 adx 30 {
748     /* OOOPs nope can't HUB */
749 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
750 michael 1618 "Non-Hub link %s introduced %s.",
751 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
752 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
753 michael 1618 "Non-Hub link %s introduced %s.",
754 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
755 michael 3171 exit_client(source_p, "No matching hub_mask.");
756 michael 2820 return 0;
757 adx 30 }
758    
759     /* Check for the new server being leafed behind this HUB */
760     if (llined)
761     {
762     /* OOOPs nope can't HUB this leaf */
763 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
764 michael 2820 "Link %s introduced leafed server %s.",
765 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
766 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
767 michael 2820 "Link %s introduced leafed server %s.",
768 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
769 michael 4611 exit_client(client_p, "Leafed server.");
770 michael 2820 return 0;
771 adx 30 }
772    
773     target_p = make_client(client_p);
774     make_server(target_p);
775 michael 3190 target_p->hopcount = atoi(parv[2]);
776 michael 1118 target_p->servptr = source_p;
777 adx 30
778 michael 1118 strlcpy(target_p->name, parv[1], sizeof(target_p->name));
779     strlcpy(target_p->id, parv[3], sizeof(target_p->id));
780 adx 30
781 michael 4659 set_server_gecos(target_p, parv[parc - 1]);
782 adx 30 SetServer(target_p);
783    
784 michael 4638 if (find_matching_name_conf(CONF_SERVICE, target_p->name, NULL, NULL, 0))
785 michael 1219 AddFlag(target_p, FLAGS_SERVICE);
786 michael 1157
787 michael 1118 dlinkAdd(target_p, &target_p->node, &global_client_list);
788 michael 4209 dlinkAdd(target_p, make_dlink_node(), &global_server_list);
789 michael 1118 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
790 adx 30
791     hash_add_client(target_p);
792     hash_add_id(target_p);
793    
794 michael 5784 sendto_server(client_p, 0, 0, ":%s SID %s %u %s :%s%s",
795 michael 3192 source_p->id, target_p->name, target_p->hopcount + 1,
796 michael 1527 target_p->id, IsHidden(target_p) ? "(H) " : "", target_p->info);
797 michael 1618 sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
798 michael 1118 "Server %s being introduced by %s",
799 adx 30 target_p->name, source_p->name);
800 michael 2820 return 0;
801 adx 30 }
802    
803 michael 2820 static struct Message server_msgtab =
804     {
805 michael 5881 .cmd = "SERVER",
806     .args_min = 4,
807     .args_max = MAXPARA,
808     .handlers[UNREGISTERED_HANDLER] = mr_server,
809     .handlers[CLIENT_HANDLER] = m_registered,
810     .handlers[SERVER_HANDLER] = m_ignore,
811     .handlers[ENCAP_HANDLER] = m_ignore,
812     .handlers[OPER_HANDLER] = m_registered
813 michael 1230 };
814    
815 michael 2820 static struct Message sid_msgtab =
816     {
817 michael 5881 .cmd = "SID",
818     .args_min = 5,
819     .args_max = MAXPARA,
820     .handlers[UNREGISTERED_HANDLER] = m_ignore,
821     .handlers[CLIENT_HANDLER] = m_ignore,
822     .handlers[SERVER_HANDLER] = ms_sid,
823     .handlers[ENCAP_HANDLER] = m_ignore,
824     .handlers[OPER_HANDLER] = m_ignore
825 michael 1230 };
826    
827     static void
828     module_init(void)
829     {
830     mod_add_cmd(&sid_msgtab);
831     mod_add_cmd(&server_msgtab);
832     }
833    
834     static void
835     module_exit(void)
836     {
837     mod_del_cmd(&sid_msgtab);
838     mod_del_cmd(&server_msgtab);
839     }
840    
841 michael 2820 struct module module_entry =
842     {
843 michael 1230 .version = "$Revision$",
844     .modinit = module_init,
845     .modexit = module_exit,
846     .flags = MODULE_FLAG_CORE
847     };

Properties

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