/[svn]/ircd-hybrid-8/modules/core/m_server.c
ViewVC logotype

Contents of /ircd-hybrid-8/modules/core/m_server.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1529 - (show annotations)
Sun Sep 16 10:27:19 2012 UTC (8 years, 4 months ago) by michael
File MIME type: text/x-chdr
File size: 21241 byte(s)
- removed server hostmasking leftovers

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

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28