ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 1997
Committed: Sat May 11 17:35:07 2013 UTC (13 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 20357 byte(s)
Error occurred while calculating annotation data.
Log Message:
- Mostly style cleanups & whitespace changes

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_server.c: Introduces a 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 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h"
27 #include "client.h" /* client struct */
28 #include "event.h"
29 #include "hash.h" /* add_to_client_hash_table */
30 #include "irc_string.h"
31 #include "ircd.h" /* me */
32 #include "numeric.h" /* ERR_xxx */
33 #include "conf.h" /* struct MaskItem */
34 #include "log.h" /* log level defines */
35 #include "s_serv.h" /* server_estab, check_server */
36 #include "s_user.h"
37 #include "send.h" /* sendto_one */
38 #include "parse.h"
39 #include "modules.h"
40
41
42 /* set_server_gecos()
43 *
44 * input - pointer to client
45 * output - NONE
46 * side effects - servers gecos field is set
47 */
48 static void
49 set_server_gecos(struct Client *client_p, const char *info)
50 {
51 const char *s = info;
52
53 /* check for (H) which is a hidden server */
54 if (!strncmp(s, "(H) ", 4))
55 {
56 SetHidden(client_p);
57 s = s + 4;
58 }
59
60 if (!EmptyString(s))
61 strlcpy(client_p->info, s, sizeof(client_p->info));
62 else
63 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
64 }
65
66 /* mr_server()
67 * parv[0] = sender prefix
68 * parv[1] = servername
69 * parv[2] = serverinfo/hopcount
70 * parv[3] = serverinfo
71 */
72 static void
73 mr_server(struct Client *client_p, struct Client *source_p,
74 int parc, char *parv[])
75 {
76 char *name;
77 struct Client *target_p;
78 int hop;
79
80 if (EmptyString(parv[3]))
81 {
82 sendto_one(client_p, "ERROR :No servername");
83 exit_client(client_p, client_p, "Wrong number of args");
84 return;
85 }
86
87 name = parv[1];
88 hop = atoi(parv[2]);
89
90 /*
91 * Reject a direct nonTS server connection if we're TS_ONLY -orabidoo
92 */
93 if (!DoesTS(client_p))
94 {
95 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
96 "Unauthorized server connection attempt from %s: Non-TS server "
97 "for server %s", get_client_name(client_p, HIDE_IP), name);
98 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
99 "Unauthorized server connection attempt from %s: Non-TS server "
100 "for server %s", get_client_name(client_p, MASK_IP), name);
101 exit_client(client_p, client_p, "Non-TS server");
102 return;
103 }
104
105 if (!valid_servname(name))
106 {
107 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
108 "Unauthorized server connection attempt from %s: Bogus server name "
109 "for server %s", get_client_name(client_p, HIDE_IP), name);
110 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
111 "Unauthorized server connection attempt from %s: Bogus server name "
112 "for server %s", get_client_name(client_p, MASK_IP), name);
113 exit_client(client_p, client_p, "Bogus server name");
114 return;
115 }
116
117 /* Now we just have to call check_server and everything should
118 * be check for us... -A1kmm.
119 */
120 switch (check_server(name, client_p))
121 {
122 case -1:
123 if (ConfigFileEntry.warn_no_nline)
124 {
125 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
126 "Unauthorized server connection attempt from %s: No entry for "
127 "servername %s", get_client_name(client_p, HIDE_IP), name);
128
129 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
130 "Unauthorized server connection attempt from %s: No entry for "
131 "servername %s", get_client_name(client_p, MASK_IP), name);
132 }
133
134 exit_client(client_p, client_p, "Invalid servername.");
135 return;
136 /* NOT REACHED */
137 break;
138
139 case -2:
140 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
141 "Unauthorized server connection attempt from %s: Bad password "
142 "for server %s", get_client_name(client_p, HIDE_IP), name);
143
144 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
145 "Unauthorized server connection attempt from %s: Bad password "
146 "for server %s", get_client_name(client_p, MASK_IP), name);
147
148 exit_client(client_p, client_p, "Invalid password.");
149 return;
150 /* NOT REACHED */
151 break;
152
153 case -3:
154 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
155 "Unauthorized server connection attempt from %s: Invalid host "
156 "for server %s", get_client_name(client_p, HIDE_IP), name);
157
158 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
159 "Unauthorized server connection attempt from %s: Invalid host "
160 "for server %s", get_client_name(client_p, MASK_IP), name);
161
162 exit_client(client_p, client_p, "Invalid host.");
163 return;
164 /* NOT REACHED */
165 break;
166 }
167
168 if ((client_p->id[0] && (target_p = hash_find_id(client_p->id)))
169 || (target_p = hash_find_server(name)))
170 {
171 /* This link is trying feed me a server that I already have
172 * access through another path -- multiple paths not accepted
173 * currently, kill this link immediately!!
174 *
175 * Rather than KILL the link which introduced it, KILL the
176 * youngest of the two links. -avalon
177 *
178 * Definitely don't do that here. This is from an unregistered
179 * connect - A1kmm.
180 */
181 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
182 "Attempt to re-introduce server %s SID %s from %s",
183 name, client_p->id,
184 get_client_name(client_p, HIDE_IP));
185 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
186 "Attempt to re-introduce server %s SID %s from %s",
187 name, client_p->id,
188 get_client_name(client_p, MASK_IP));
189 sendto_one(client_p, "ERROR :Server ID already exists.");
190 exit_client(client_p, client_p, "Server ID Exists");
191 return;
192 }
193
194 /* XXX If somehow there is a connect in progress and
195 * a connect comes in with same name toss the pending one,
196 * but only if it's not the same client! - Dianora
197 */
198 if ((target_p = find_servconn_in_progress(name)))
199 if (target_p != client_p)
200 exit_client(target_p, &me, "Overridden");
201
202 /* if we are connecting (Handshake), we already have the name from the
203 * connect{} block in client_p->name
204 */
205 strlcpy(client_p->name, name, sizeof(client_p->name));
206 set_server_gecos(client_p, parv[3]);
207 client_p->hopcount = hop;
208 server_estab(client_p);
209 }
210
211 /* ms_server()
212 * parv[0] = sender prefix
213 * parv[1] = servername
214 * parv[2] = serverinfo/hopcount
215 * parv[3] = serverinfo
216 */
217 static void
218 ms_server(struct Client *client_p, struct Client *source_p,
219 int parc, char *parv[])
220 {
221 char *name;
222 struct Client *target_p;
223 struct MaskItem *conf = NULL;
224 int hop;
225 int hlined = 0;
226 int llined = 0;
227 dlink_node *ptr = NULL;
228
229 /* Just to be sure -A1kmm. */
230 if (!IsServer(source_p))
231 return;
232
233 if (EmptyString(parv[3]))
234 {
235 sendto_one(client_p, "ERROR :No servername");
236 return;
237 }
238
239 name = parv[1];
240 hop = atoi(parv[2]);
241
242 if (!valid_servname(name))
243 {
244 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
245 "Link %s introduced server with bogus server name %s",
246 get_client_name(client_p, SHOW_IP), name);
247 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
248 "Link %s introduced server with bogus server name %s",
249 get_client_name(client_p, MASK_IP), name);
250 sendto_one(client_p, "ERROR :Bogus server name introduced");
251 exit_client(client_p, &me, "Bogus server name intoduced");
252 return;
253 }
254
255 if ((target_p = hash_find_server(name)))
256 {
257 /* This link is trying feed me a server that I already have
258 * access through another path -- multiple paths not accepted
259 * currently, kill this link immediately!!
260 *
261 * Rather than KILL the link which introduced it, KILL the
262 * youngest of the two links. -avalon
263 *
264 * I think that we should exit the link itself, not the introducer,
265 * and we should always exit the most recently received(i.e. the
266 * one we are receiving this SERVER for. -A1kmm
267 *
268 * You *cant* do this, if you link somewhere, it bursts you a server
269 * that already exists, then sends you a client burst, you squit the
270 * server, but you keep getting the burst of clients on a server that
271 * doesnt exist, although ircd can handle it, its not a realistic
272 * solution.. --fl_
273 */
274 sendto_one(client_p, "ERROR :Server %s already exists", name);
275 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
276 "Link %s cancelled, server %s already exists",
277 get_client_name(client_p, SHOW_IP), name);
278 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
279 "Link %s cancelled, server %s already exists",
280 client_p->name, name);
281 exit_client(client_p, &me, "Server Exists");
282 return;
283 }
284
285 /* XXX If somehow there is a connect in progress and
286 * a connect comes in with same name toss the pending one,
287 * but only if it's not the same client! - Dianora
288 */
289 if ((target_p = find_servconn_in_progress(name)))
290 if (target_p != client_p)
291 exit_client(target_p, &me, "Overridden");
292
293 conf = client_p->localClient->confs.head->data;
294
295 /* See if the newly found server is behind a guaranteed
296 * leaf. If so, close the link.
297 */
298 DLINK_FOREACH(ptr, conf->leaf_list.head)
299 if (!match(ptr->data, name))
300 {
301 llined = 1;
302 break;
303 }
304
305 DLINK_FOREACH(ptr, conf->hub_list.head)
306 if (!match(ptr->data, name))
307 {
308 hlined = 1;
309 break;
310 }
311
312 /* Ok, this way this works is
313 *
314 * A server can have a CONF_HUB allowing it to introduce servers
315 * behind it.
316 *
317 * connect {
318 * name = "irc.bighub.net";
319 * hub_mask="*";
320 * ...
321 *
322 * That would allow "irc.bighub.net" to introduce anything it wanted..
323 *
324 * However
325 *
326 * connect {
327 * name = "irc.somehub.fi";
328 * hub_mask="*";
329 * leaf_mask="*.edu";
330 *...
331 * Would allow this server in finland to hub anything but
332 * .edu's
333 */
334
335 /* Ok, check client_p can hub the new server */
336 if (!hlined)
337 {
338 /* OOOPs nope can't HUB */
339 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
340 "Non-Hub link %s introduced %s.",
341 get_client_name(client_p, HIDE_IP), name);
342 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
343 "Non-Hub link %s introduced %s.",
344 get_client_name(client_p, MASK_IP), name);
345 exit_client(source_p, &me, "No matching hub_mask.");
346 return;
347 }
348
349 /* Check for the new server being leafed behind this HUB */
350 if (llined)
351 {
352 /* OOOPs nope can't HUB this leaf */
353 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
354 "Link %s introduced leafed server %s.",
355 get_client_name(client_p, HIDE_IP), name);
356 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
357 "Link %s introduced leafed server %s.",
358 get_client_name(client_p, MASK_IP), name);
359 /* If it is new, we are probably misconfigured, so split the
360 * non-hub server introducing this. Otherwise, split the new
361 * server. -A1kmm.
362 */
363 /* wastes too much bandwidth, generates too many errors on
364 * larger networks, dont bother. --fl_
365 */
366 exit_client(client_p, &me, "Leafed Server.");
367 return;
368 }
369
370 target_p = make_client(client_p);
371 make_server(target_p);
372 target_p->hopcount = hop;
373 target_p->servptr = source_p;
374
375 strlcpy(target_p->name, name, sizeof(target_p->name));
376
377 set_server_gecos(target_p, parv[3]);
378 SetServer(target_p);
379
380 if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_SERVICE, target_p->name, NULL, NULL, 0))
381 AddFlag(target_p, FLAGS_SERVICE);
382
383 dlinkAdd(target_p, &target_p->node, &global_client_list);
384 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
385 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
386
387 hash_add_client(target_p);
388
389 sendto_server(client_p, NOCAPS, NOCAPS, ":%s SERVER %s %d :%s%s",
390 source_p->name, target_p->name, hop + 1,
391 IsHidden(target_p) ? "(H) " : "", target_p->info);
392
393 sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
394 "Server %s being introduced by %s",
395 target_p->name, source_p->name);
396 }
397
398 /* ms_sid()
399 * parv[0] = sender prefix
400 * parv[1] = servername
401 * parv[2] = serverinfo/hopcount
402 * parv[3] = sid of new server
403 * parv[4] = serverinfo
404 */
405 static void
406 ms_sid(struct Client *client_p, struct Client *source_p,
407 int parc, char *parv[])
408 {
409 struct Client *target_p;
410 struct MaskItem *conf = NULL;
411 int hlined = 0;
412 int llined = 0;
413 dlink_node *ptr = NULL;
414 int hop;
415
416 /* Just to be sure -A1kmm. */
417 if (!IsServer(source_p))
418 return;
419
420 if (EmptyString(parv[4]))
421 {
422 sendto_one(client_p, "ERROR :No servername");
423 return;
424 }
425
426 hop = atoi(parv[2]);
427
428 if (!valid_servname(parv[1]))
429 {
430 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
431 "Link %s introduced server with bogus server name %s",
432 get_client_name(client_p, SHOW_IP), parv[1]);
433 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
434 "Link %s introduced server with bogus server name %s",
435 get_client_name(client_p, MASK_IP), parv[1]);
436 sendto_one(client_p, "ERROR :Bogus server name introduced");
437 exit_client(client_p, &me, "Bogus server name intoduced");
438 return;
439 }
440
441 if (!valid_sid(parv[3]))
442 {
443 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
444 "Link %s introduced server with bogus server ID %s",
445 get_client_name(client_p, SHOW_IP), parv[3]);
446 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
447 "Link %s introduced server with bogus server ID %s",
448 get_client_name(client_p, MASK_IP), parv[3]);
449 sendto_one(client_p, "ERROR :Bogus server ID introduced");
450 exit_client(client_p, &me, "Bogus server ID intoduced");
451 return;
452 }
453
454 /* collision on SID? */
455 if ((target_p = hash_find_id(parv[3])))
456 {
457 sendto_one(client_p, "ERROR :SID %s already exists", parv[3]);
458 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
459 "Link %s cancelled, SID %s already exists",
460 get_client_name(client_p, SHOW_IP), parv[3]);
461 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
462 "Link %s cancelled, SID %s already exists",
463 client_p->name, parv[3]);
464 exit_client(client_p, &me, "SID Exists");
465 return;
466 }
467
468 /* collision on name? */
469 if ((target_p = hash_find_server(parv[1])))
470 {
471 sendto_one(client_p, "ERROR :Server %s already exists", parv[1]);
472 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
473 "Link %s cancelled, server %s already exists",
474 get_client_name(client_p, SHOW_IP), parv[1]);
475 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
476 "Link %s cancelled, server %s already exists",
477 client_p->name, parv[1]);
478 exit_client(client_p, &me, "Server Exists");
479 return;
480 }
481
482 /* XXX If somehow there is a connect in progress and
483 * a connect comes in with same name toss the pending one,
484 * but only if it's not the same client! - Dianora
485 */
486 if ((target_p = find_servconn_in_progress(parv[1])))
487 if (target_p != client_p)
488 exit_client(target_p, &me, "Overridden");
489
490 conf = client_p->localClient->confs.head->data;
491
492 /* See if the newly found server is behind a guaranteed
493 * leaf. If so, close the link.
494 */
495 DLINK_FOREACH(ptr, conf->leaf_list.head)
496 if (!match(ptr->data, parv[1]))
497 {
498 llined = 1;
499 break;
500 }
501
502 DLINK_FOREACH(ptr, conf->hub_list.head)
503 if (!match(ptr->data, parv[1]))
504 {
505 hlined = 1;
506 break;
507 }
508
509
510 /* Ok, this way this works is
511 *
512 * A server can have a CONF_HUB allowing it to introduce servers
513 * behind it.
514 *
515 * connect {
516 * name = "irc.bighub.net";
517 * hub_mask="*";
518 * ...
519 *
520 * That would allow "irc.bighub.net" to introduce anything it wanted..
521 *
522 * However
523 *
524 * connect {
525 * name = "irc.somehub.fi";
526 * hub_mask="*";
527 * leaf_mask="*.edu";
528 *...
529 * Would allow this server in finland to hub anything but
530 * .edu's
531 */
532
533 /* Ok, check client_p can hub the new server, and make sure it's not a LL */
534 if (!hlined)
535 {
536 /* OOOPs nope can't HUB */
537 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
538 "Non-Hub link %s introduced %s.",
539 get_client_name(client_p, SHOW_IP), parv[1]);
540 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
541 "Non-Hub link %s introduced %s.",
542 get_client_name(client_p, MASK_IP), parv[1]);
543 exit_client(source_p, &me, "No matching hub_mask.");
544 return;
545 }
546
547 /* Check for the new server being leafed behind this HUB */
548 if (llined)
549 {
550 /* OOOPs nope can't HUB this leaf */
551 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
552 "Link %s introduced leafed server %s.",
553 get_client_name(client_p, SHOW_IP), parv[1]);
554 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
555 "Link %s introduced leafed server %s.",
556 get_client_name(client_p, MASK_IP), parv[1]);
557 exit_client(client_p, &me, "Leafed Server.");
558 return;
559 }
560
561 target_p = make_client(client_p);
562 make_server(target_p);
563 target_p->hopcount = hop;
564 target_p->servptr = source_p;
565
566 strlcpy(target_p->name, parv[1], sizeof(target_p->name));
567 strlcpy(target_p->id, parv[3], sizeof(target_p->id));
568
569 set_server_gecos(target_p, parv[4]);
570 SetServer(target_p);
571
572 if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_SERVICE, target_p->name, NULL, NULL, 0))
573 AddFlag(target_p, FLAGS_SERVICE);
574
575 dlinkAdd(target_p, &target_p->node, &global_client_list);
576 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
577 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
578
579 hash_add_client(target_p);
580 hash_add_id(target_p);
581
582 sendto_server(client_p, CAP_TS6, NOCAPS, ":%s SID %s %d %s :%s%s",
583 ID_or_name(source_p, client_p), target_p->name, hop + 1,
584 target_p->id, IsHidden(target_p) ? "(H) " : "", target_p->info);
585 sendto_server(client_p, NOCAPS, CAP_TS6, ":%s SERVER %s %d :%s%s",
586 source_p->name, target_p->name, hop + 1,
587 IsHidden(target_p) ? "(H) " : "", target_p->info);
588
589 sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
590 "Server %s being introduced by %s",
591 target_p->name, source_p->name);
592 }
593
594 static struct Message server_msgtab = {
595 "SERVER", 0, 0, 4, MAXPARA, MFLG_SLOW, 0,
596 {mr_server, m_registered, ms_server, m_ignore, m_registered, m_ignore}
597 };
598
599 static struct Message sid_msgtab = {
600 "SID", 0, 0, 5, MAXPARA, MFLG_SLOW, 0,
601 {rfc1459_command_send_error, m_ignore, ms_sid, m_ignore, m_ignore, m_ignore}
602 };
603
604 static void
605 module_init(void)
606 {
607 mod_add_cmd(&sid_msgtab);
608 mod_add_cmd(&server_msgtab);
609 }
610
611 static void
612 module_exit(void)
613 {
614 mod_del_cmd(&sid_msgtab);
615 mod_del_cmd(&server_msgtab);
616 }
617
618 struct module module_entry = {
619 .node = { NULL, NULL, NULL },
620 .name = NULL,
621 .version = "$Revision$",
622 .handle = NULL,
623 .modinit = module_init,
624 .modexit = module_exit,
625 .flags = MODULE_FLAG_CORE
626 };

Properties

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