ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 4755
Committed: Sat Oct 18 18:57:36 2014 UTC (11 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 27619 byte(s)
Error occurred while calculating annotation data.
Log Message:
- m_server.c, m_stats.c: constification

File Contents

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

Properties

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