ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 33
Committed: Sun Oct 2 20:50:00 2005 UTC (21 years ago) by knight
Content type: text/x-csrc
Original Path: ircd-hybrid/modules/core/m_server.c
File size: 27925 byte(s)
Error occurred while calculating annotation data.
Log Message:
- svn:keywords

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 "tools.h"
27 #include "handlers.h" /* m_server prototype */
28 #include "client.h" /* client struct */
29 #include "common.h" /* TRUE bleah */
30 #include "event.h"
31 #include "hash.h" /* add_to_client_hash_table */
32 #include "irc_string.h"
33 #include "ircd.h" /* me */
34 #include "list.h" /* make_server */
35 #include "numeric.h" /* ERR_xxx */
36 #include "s_conf.h" /* struct AccessItem */
37 #include "s_log.h" /* log level defines */
38 #include "s_serv.h" /* server_estab, check_server, my_name_for_link */
39 #include "s_stats.h" /* ServerStats */
40 #include "send.h" /* sendto_one */
41 #include "motd.h"
42 #include "msg.h"
43 #include "parse.h"
44 #include "modules.h"
45
46
47 static void mr_server(struct Client *, struct Client *, int, char **);
48 static void ms_server(struct Client *, struct Client *, int, char **);
49 static void ms_sid(struct Client *, struct Client *, int, char **);
50
51 static int bogus_host(char *host);
52 static void set_server_gecos(struct Client *, char *);
53 static struct Client *server_exists(char *);
54
55 struct Message server_msgtab = {
56 "SERVER", 0, 0, 4, 0, MFLG_SLOW | MFLG_UNREG, 0,
57 {mr_server, m_registered, ms_server, m_ignore, m_registered, m_ignore}
58 };
59
60 struct Message sid_msgtab = {
61 "SID", 0, 0, 5, 0, MFLG_SLOW, 0,
62 {m_error, m_ignore, ms_sid, m_ignore, m_ignore, m_ignore}
63 };
64
65 #ifndef STATIC_MODULES
66 void
67 _modinit(void)
68 {
69 mod_add_cmd(&server_msgtab);
70 mod_add_cmd(&sid_msgtab);
71 }
72
73 void
74 _moddeinit(void)
75 {
76 mod_del_cmd(&server_msgtab);
77 mod_del_cmd(&sid_msgtab);
78 }
79
80 const char *_version = "$Revision$";
81 #endif
82
83
84 /* mr_server()
85 * parv[0] = sender prefix
86 * parv[1] = servername
87 * parv[2] = serverinfo/hopcount
88 * parv[3] = serverinfo
89 */
90 static void
91 mr_server(struct Client *client_p, struct Client *source_p,
92 int parc, char *parv[])
93 {
94 char info[REALLEN + 1];
95 char *name;
96 struct Client *target_p;
97 int hop;
98
99 if (parc < 4)
100 {
101 sendto_one(client_p, "ERROR :No servername");
102 exit_client(client_p, client_p, "Wrong number of args");
103 return;
104 }
105
106 name = parv[1];
107 hop = atoi(parv[2]);
108 strlcpy(info, parv[3], sizeof(info));
109
110 /* Reject a direct nonTS server connection if we're TS_ONLY -orabidoo
111 */
112 if (!DoesTS(client_p))
113 {
114 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Link %s dropped, non-TS server",
115 get_client_name(client_p, HIDE_IP));
116 sendto_realops_flags(UMODE_ALL, L_OPER, "Link %s dropped, non-TS server",
117 get_client_name(client_p, MASK_IP));
118 exit_client(client_p, client_p, "Non-TS server");
119 return;
120 }
121
122 if (bogus_host(name))
123 {
124 exit_client(client_p, client_p, "Bogus server name");
125 return;
126 }
127
128 /* Now we just have to call check_server and everything should
129 * be check for us... -A1kmm.
130 */
131 switch (check_server(name, client_p, CHECK_SERVER_NOCRYPTLINK))
132 {
133 case -1:
134 if (ConfigFileEntry.warn_no_nline)
135 {
136 sendto_realops_flags(UMODE_ALL, L_ADMIN,
137 "Unauthorized server connection attempt from %s: No entry for "
138 "servername %s", get_client_name(client_p, HIDE_IP), name);
139
140 sendto_realops_flags(UMODE_ALL, L_OPER,
141 "Unauthorized server connection attempt from %s: No entry for "
142 "servername %s", get_client_name(client_p, MASK_IP), name);
143 }
144
145 exit_client(client_p, client_p, "Invalid servername.");
146 return;
147 /* NOT REACHED */
148 break;
149
150 case -2:
151 sendto_realops_flags(UMODE_ALL, L_ADMIN,
152 "Unauthorized server connection attempt from %s: Bad password "
153 "for server %s", get_client_name(client_p, HIDE_IP), name);
154
155 sendto_realops_flags(UMODE_ALL, L_OPER,
156 "Unauthorized server connection attempt from %s: Bad password "
157 "for server %s", get_client_name(client_p, MASK_IP), name);
158
159 exit_client(client_p, client_p, "Invalid password.");
160 return;
161 /* NOT REACHED */
162 break;
163
164 case -3:
165 sendto_realops_flags(UMODE_ALL, L_ADMIN,
166 "Unauthorized server connection attempt from %s: Invalid host "
167 "for server %s", get_client_name(client_p, HIDE_IP), name);
168
169 sendto_realops_flags(UMODE_ALL, L_OPER,
170 "Unauthorized server connection attempt from %s: Invalid host "
171 "for server %s", get_client_name(client_p, MASK_IP), name);
172
173 exit_client(client_p, client_p, "Invalid host.");
174 return;
175 /* NOT REACHED */
176 break;
177
178 /* servername is > HOSTLEN */
179 case -4:
180 sendto_realops_flags(UMODE_ALL, L_ADMIN,
181 "Invalid servername %s from %s",
182 name, get_client_name(client_p, HIDE_IP));
183 sendto_realops_flags(UMODE_ALL, L_OPER,
184 "Invalid servername %s from %s",
185 name, get_client_name(client_p, MASK_IP));
186
187 exit_client(client_p, client_p, "Invalid servername.");
188 return;
189 /* NOT REACHED */
190 break;
191 }
192
193 if ((me.id[0] && client_p->id[0] && (target_p = hash_find_id(client_p->id)))
194 || (target_p = server_exists(name)))
195 {
196 /* This link is trying feed me a server that I already have
197 * access through another path -- multiple paths not accepted
198 * currently, kill this link immediately!!
199 *
200 * Rather than KILL the link which introduced it, KILL the
201 * youngest of the two links. -avalon
202 *
203 * Definitely don't do that here. This is from an unregistered
204 * connect - A1kmm.
205 */
206 sendto_realops_flags(UMODE_ALL, L_ADMIN,
207 "Attempt to re-introduce server %s SID %s from %s",
208 name, client_p->id,
209 get_client_name(client_p, HIDE_IP));
210 sendto_realops_flags(UMODE_ALL, L_OPER,
211 "Attempt to re-introduce server %s SID %s from %s",
212 name, client_p->id,
213 get_client_name(client_p, MASK_IP));
214 sendto_one(client_p, "ERROR :Server ID already exists.");
215 exit_client(client_p, client_p, "Server ID Exists");
216 return;
217 }
218
219 /* XXX If somehow there is a connect in progress and
220 * a connect comes in with same name toss the pending one,
221 * but only if it's not the same client! - Dianora
222 */
223 if ((target_p = find_servconn_in_progress(name)))
224 if (target_p != client_p)
225 exit_client(target_p, &me, "Overridden");
226
227 if (ServerInfo.hub && IsCapable(client_p, CAP_LL))
228 {
229 if (IsCapable(client_p, CAP_HUB))
230 {
231 ClearCap(client_p, CAP_LL);
232 sendto_realops_flags(UMODE_ALL, L_ALL,
233 "*** LazyLinks to a hub from a hub, that's a no-no.");
234 }
235 else
236 {
237 client_p->localClient->serverMask = nextFreeMask();
238
239 if (!client_p->localClient->serverMask)
240 {
241 sendto_realops_flags(UMODE_ALL, L_ALL, "serverMask is full!");
242 /* try and negotiate a non LL connect */
243 ClearCap(client_p, CAP_LL);
244 }
245 }
246 }
247 else if (IsCapable(client_p, CAP_LL))
248 {
249 if (!IsCapable(client_p, CAP_HUB))
250 {
251 ClearCap(client_p, CAP_LL);
252 sendto_realops_flags(UMODE_ALL, L_ALL,
253 "*** LazyLinks to a leaf from a leaf, that's a no-no.");
254 }
255 }
256
257 /* if we are connecting (Handshake), we already have the name from the
258 * connect{} block in client_p->name
259 */
260 strlcpy(client_p->name, name, sizeof(client_p->name));
261 set_server_gecos(client_p, info);
262 client_p->hopcount = hop;
263 server_estab(client_p);
264 }
265
266 /* ms_server()
267 * parv[0] = sender prefix
268 * parv[1] = servername
269 * parv[2] = serverinfo/hopcount
270 * parv[3] = serverinfo
271 */
272 static void
273 ms_server(struct Client *client_p, struct Client *source_p,
274 int parc, char *parv[])
275 {
276 char info[REALLEN + 1];
277 char *name;
278 struct Client *target_p;
279 struct Client *bclient_p;
280 struct ConfItem *conf;
281 struct MatchItem *match_item;
282 int hop;
283 int hlined = 0;
284 int llined = 0;
285 dlink_node *ptr, *ptr_next;
286
287 /* Just to be sure -A1kmm. */
288 if (!IsServer(source_p))
289 return;
290
291 if (parc < 4)
292 {
293 sendto_one(client_p, "ERROR :No servername");
294 return;
295 }
296
297 name = parv[1];
298 hop = atoi(parv[2]);
299 strlcpy(info, parv[3], sizeof(info));
300
301 if ((target_p = server_exists(name)))
302 {
303 /* This link is trying feed me a server that I already have
304 * access through another path -- multiple paths not accepted
305 * currently, kill this link immediately!!
306 *
307 * Rather than KILL the link which introduced it, KILL the
308 * youngest of the two links. -avalon
309 *
310 * I think that we should exit the link itself, not the introducer,
311 * and we should always exit the most recently received(i.e. the
312 * one we are receiving this SERVER for. -A1kmm
313 *
314 * You *cant* do this, if you link somewhere, it bursts you a server
315 * that already exists, then sends you a client burst, you squit the
316 * server, but you keep getting the burst of clients on a server that
317 * doesnt exist, although ircd can handle it, its not a realistic
318 * solution.. --fl_
319 */
320 /* It is behind a host-masked server. Completely ignore the
321 * server message(don't propagate or we will delink from whoever
322 * we propagate to). -A1kmm
323 */
324 if (irccmp(target_p->name, name) && target_p->from == client_p)
325 return;
326
327 sendto_one(client_p, "ERROR :Server %s already exists", name);
328 sendto_realops_flags(UMODE_ALL, L_ADMIN,
329 "Link %s cancelled, server %s already exists",
330 get_client_name(client_p, SHOW_IP), name);
331 sendto_realops_flags(UMODE_ALL, L_OPER,
332 "Link %s cancelled, server %s already exists",
333 client_p->name, name);
334 exit_client(client_p, &me, "Server Exists");
335 return;
336 }
337
338 /* XXX If somehow there is a connect in progress and
339 * a connect comes in with same name toss the pending one,
340 * but only if it's not the same client! - Dianora
341 */
342 if ((target_p = find_servconn_in_progress(name)))
343 if (target_p != client_p)
344 exit_client(target_p, &me, "Overridden");
345
346 /* User nicks never have '.' in them and server names
347 * must always have '.' in them.
348 */
349 if (strchr(name, '.') == NULL)
350 {
351 /* Server trying to use the same name as a person. Would
352 * cause a fair bit of confusion. Enough to make it hellish
353 * for a while and servers to send stuff to the wrong place.
354 */
355 sendto_one(client_p,"ERROR :Nickname %s already exists!", name);
356 sendto_realops_flags(UMODE_ALL, L_ADMIN,
357 "Link %s cancelled: Server/nick collision on %s",
358 /* inpath */ get_client_name(client_p, HIDE_IP), name);
359 sendto_realops_flags(UMODE_ALL, L_OPER,
360 "Link %s cancelled: Server/nick collision on %s",
361 get_client_name(client_p, MASK_IP), name);
362 exit_client(client_p, client_p, "Nick as Server");
363 return;
364 }
365
366 if (strlen(name) > HOSTLEN)
367 {
368 sendto_realops_flags(UMODE_ALL, L_ADMIN,
369 "Link %s introduced server with invalid servername %s",
370 get_client_name(client_p, HIDE_IP), name);
371 sendto_realops_flags(UMODE_ALL, L_OPER,
372 "Link %s introduced server with invalid servername %s",
373 client_p->name, name);
374 exit_client(client_p, &me, "Invalid servername introduced.");
375 return;
376 }
377
378 /* Server is informing about a new server behind
379 * this link. Create REMOTE server structure,
380 * add it to list and propagate word to my other
381 * server links...
382 */
383 if (parc == 1 || info[0] == '\0')
384 {
385 sendto_one(client_p, "ERROR :No server info specified for %s", name);
386 return;
387 }
388
389 /* See if the newly found server is behind a guaranteed
390 * leaf. If so, close the link.
391 */
392 DLINK_FOREACH(ptr, leaf_items.head)
393 {
394 conf = ptr->data;
395
396 if (match(conf->name, client_p->name))
397 {
398 match_item = (struct MatchItem *)map_to_conf(conf);
399 if (match(match_item->host, name))
400 llined++;
401 }
402 }
403
404 DLINK_FOREACH(ptr, hub_items.head)
405 {
406 conf = ptr->data;
407
408 if (match(conf->name, client_p->name))
409 {
410 match_item = (struct MatchItem *)map_to_conf(conf);
411
412 if (match(match_item->host, name))
413 hlined++;
414 }
415 }
416
417 /* Ok, this way this works is
418 *
419 * A server can have a CONF_HUB allowing it to introduce servers
420 * behind it.
421 *
422 * connect {
423 * name = "irc.bighub.net";
424 * hub_mask="*";
425 * ...
426 *
427 * That would allow "irc.bighub.net" to introduce anything it wanted..
428 *
429 * However
430 *
431 * connect {
432 * name = "irc.somehub.fi";
433 * hub_mask="*";
434 * leaf_mask="*.edu";
435 *...
436 * Would allow this server in finland to hub anything but
437 * .edu's
438 */
439
440 /* Ok, check client_p can hub the new server, and make sure it's not a LL */
441 if (!hlined || (IsCapable(client_p, CAP_LL) && !IsCapable(client_p, CAP_HUB)))
442 {
443 /* OOOPs nope can't HUB */
444 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
445 get_client_name(client_p, HIDE_IP), name);
446 sendto_realops_flags(UMODE_ALL, L_OPER, "Non-Hub link %s introduced %s.",
447 get_client_name(client_p, MASK_IP), name);
448 exit_client(source_p, &me, "No matching hub_mask.");
449 return;
450 }
451
452 /* Check for the new server being leafed behind this HUB */
453 if (llined)
454 {
455 /* OOOPs nope can't HUB this leaf */
456 sendto_realops_flags(UMODE_ALL, L_ADMIN,
457 "Link %s introduced leafed server %s.",
458 get_client_name(client_p, HIDE_IP), name);
459 sendto_realops_flags(UMODE_ALL, L_OPER,
460 "Link %s introduced leafed server %s.",
461 client_p->name, name);
462 /* If it is new, we are probably misconfigured, so split the
463 * non-hub server introducing this. Otherwise, split the new
464 * server. -A1kmm.
465 */
466 /* wastes too much bandwidth, generates too many errors on
467 * larger networks, dont bother. --fl_
468 */
469 exit_client(client_p, &me, "Leafed Server.");
470 return;
471 }
472
473 target_p = make_client(client_p);
474 make_server(target_p);
475 target_p->hopcount = hop;
476
477 strlcpy(target_p->name, name, sizeof(target_p->name));
478
479 set_server_gecos(target_p, info);
480
481 target_p->servptr = source_p;
482
483 SetServer(target_p);
484
485 if ((target_p->node.prev != NULL) || (target_p->node.next != NULL))
486 {
487 sendto_realops_flags(UMODE_ALL, L_OPER,
488 "already linked %s at %s:%d", target_p->name,
489 __FILE__, __LINE__);
490 ilog(L_ERROR, "already linked client %s at %s:%d", target_p->name,
491 __FILE__, __LINE__);
492 assert(0==1);
493 }
494 else
495 {
496 dlinkAdd(target_p, &target_p->node, &global_client_list);
497 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
498 }
499
500 hash_add_client(target_p);
501 /* XXX test that target_p->lnode.prev and .next are NULL as well? */
502 if ((target_p->lnode.prev != NULL) || (target_p->lnode.next != NULL))
503 {
504 sendto_realops_flags(UMODE_ALL, L_OPER,
505 "already lnode linked %s at %s:%d", target_p->name,
506 __FILE__, __LINE__);
507 ilog(L_ERROR, "already lnode linked %s at %s:%d", target_p->name,
508 __FILE__, __LINE__);
509 assert(0==2);
510 }
511 else
512 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers);
513
514 client_p->serv->dep_servers++;
515
516 /* Old sendto_serv_but_one() call removed because we now
517 * need to send different names to different servers
518 * (domain name matching)
519 */
520 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
521 {
522 bclient_p = ptr->data;
523
524 if (bclient_p == client_p)
525 continue;
526
527 if ((conf = bclient_p->serv->sconf) == NULL)
528 {
529 sendto_realops_flags(UMODE_ALL, L_ADMIN,
530 "Lost connect{} block for %s on %s. Closing",
531 get_client_name(client_p, HIDE_IP), name);
532 sendto_realops_flags(UMODE_ALL, L_OPER,
533 "Lost connect{} block for %s on %s. Closing",
534 get_client_name(client_p, MASK_IP), name);
535 exit_client(client_p, client_p, "Lost connect{} block");
536 continue;
537 }
538
539 if (match(my_name_for_link(conf), target_p->name))
540 continue;
541
542 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
543 ID_or_name(source_p, bclient_p), target_p->name, hop + 1,
544 IsHidden(target_p) ? "(H) " : "",
545 target_p->info);
546 }
547
548 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
549 "Server %s being introduced by %s",
550 target_p->name, source_p->name);
551 }
552
553 /* ms_sid()
554 * parv[0] = sender prefix
555 * parv[1] = servername
556 * parv[2] = serverinfo/hopcount
557 * parv[3] = sid of new server
558 * parv[4] = serverinfo
559 */
560 static void
561 ms_sid(struct Client *client_p, struct Client *source_p,
562 int parc, char *parv[])
563 {
564 char info[REALLEN + 1];
565 struct Client *target_p;
566 struct Client *bclient_p;
567 struct ConfItem *conf;
568 struct MatchItem *match_item;
569 int hlined = 0;
570 int llined = 0;
571 dlink_node *ptr, *ptr_next;
572 int hop;
573 #define SID_NAME parv[1]
574 #define SID_HOP parv[2]
575 #define SID_SID parv[3]
576 #define SID_GECOS parv[4]
577
578 hop = atoi(SID_HOP);
579
580 /* Just to be sure -A1kmm. */
581 if (!IsServer(source_p))
582 return;
583
584 strlcpy(info, SID_GECOS, sizeof(info));
585
586 /* collision on SID? */
587 if ((target_p = hash_find_id(SID_SID)) != NULL)
588 {
589 sendto_one(client_p, "ERROR :SID %s already exists", SID_SID);
590 sendto_realops_flags(UMODE_ALL, L_ADMIN,
591 "Link %s cancelled, SID %s already exists",
592 get_client_name(client_p, SHOW_IP), SID_SID);
593 sendto_realops_flags(UMODE_ALL, L_OPER,
594 "Link %s cancelled, SID %s already exists",
595 client_p->name, SID_SID);
596 exit_client(client_p, &me, "Server Exists");
597 return;
598 }
599
600 /* collision on name? */
601 if ((target_p = server_exists(SID_NAME)) != NULL)
602 {
603 sendto_one(client_p, "ERROR :Server %s already exists", SID_NAME);
604 sendto_realops_flags(UMODE_ALL, L_ADMIN,
605 "Link %s cancelled, server %s already exists",
606 get_client_name(client_p, SHOW_IP), SID_NAME);
607 sendto_realops_flags(UMODE_ALL, L_OPER,
608 "Link %s cancelled, server %s already exists",
609 client_p->name, SID_NAME);
610 exit_client(client_p, &me, "Server Exists");
611 return;
612 }
613
614 /* XXX If somehow there is a connect in progress and
615 * a connect comes in with same name toss the pending one,
616 * but only if it's not the same client! - Dianora
617 */
618 if ((target_p = find_servconn_in_progress(SID_NAME)))
619 if (target_p != client_p)
620 exit_client(target_p, &me, "Overridden");
621
622 /* User nicks never have '.' in them and server names
623 * must always have '.' in them.
624 */
625 if (strchr(SID_NAME, '.') == NULL || /* servernames must have a '.' and nicks must not */
626 strlen(SID_NAME) > HOSTLEN) /* ensure the name of the server is not too long */
627 {
628 /* Server trying to use the same name as a person. Would
629 * cause a fair bit of confusion. Enough to make it hellish
630 * for a while and servers to send stuff to the wrong place.
631 */
632 sendto_one(client_p, "ERROR :Invalid servername");
633 sendto_realops_flags(UMODE_ALL, L_ADMIN,
634 "Link %s cancelled: servername name %s invalid",
635 get_client_name(client_p, SHOW_IP), SID_NAME);
636 sendto_realops_flags(UMODE_ALL, L_OPER,
637 "Link %s cancelled: servername name %s invalid",
638 get_client_name(client_p, MASK_IP), SID_NAME);
639 exit_client(client_p, client_p, "Nick as Server");
640 return;
641 }
642
643 /* Server is informing about a new server behind
644 * this link. Create REMOTE server structure,
645 * add it to list and propagate word to my other
646 * server links...
647 */
648 if (parc == 1 || info[0] == '\0')
649 {
650 sendto_one(client_p, "ERROR :No server info specified for %s", SID_NAME);
651 return;
652 }
653
654 /* See if the newly found server is behind a guaranteed
655 * leaf. If so, close the link.
656 */
657 DLINK_FOREACH(ptr, leaf_items.head)
658 {
659 conf = ptr->data;
660
661 if (match(conf->name, client_p->name))
662 {
663 match_item = (struct MatchItem *)map_to_conf(conf);
664 if (match(match_item->host, SID_NAME))
665 llined++;
666 }
667 }
668
669 DLINK_FOREACH(ptr, hub_items.head)
670 {
671 conf = ptr->data;
672
673 if (match(conf->name, client_p->name))
674 {
675 match_item = (struct MatchItem *)map_to_conf(conf);
676
677 if (match(match_item->host, SID_NAME))
678 hlined++;
679 }
680 }
681
682 /* Ok, this way this works is
683 *
684 * A server can have a CONF_HUB allowing it to introduce servers
685 * behind it.
686 *
687 * connect {
688 * name = "irc.bighub.net";
689 * hub_mask="*";
690 * ...
691 *
692 * That would allow "irc.bighub.net" to introduce anything it wanted..
693 *
694 * However
695 *
696 * connect {
697 * name = "irc.somehub.fi";
698 * hub_mask="*";
699 * leaf_mask="*.edu";
700 *...
701 * Would allow this server in finland to hub anything but
702 * .edu's
703 */
704
705 /* Ok, check client_p can hub the new server, and make sure it's not a LL */
706 if (!hlined || (IsCapable(client_p, CAP_LL) && !IsCapable(client_p, CAP_HUB)))
707 {
708 /* OOOPs nope can't HUB */
709 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
710 get_client_name(client_p, SHOW_IP), SID_NAME);
711 sendto_realops_flags(UMODE_ALL, L_OPER, "Non-Hub link %s introduced %s.",
712 get_client_name(client_p, MASK_IP), SID_NAME);
713 exit_client(source_p, &me, "No matching hub_mask.");
714 return;
715 }
716
717 /* Check for the new server being leafed behind this HUB */
718 if (llined)
719 {
720 /* OOOPs nope can't HUB this leaf */
721 sendto_realops_flags(UMODE_ALL, L_ADMIN,
722 "Link %s introduced leafed server %s.",
723 get_client_name(client_p, SHOW_IP), SID_NAME);
724 sendto_realops_flags(UMODE_ALL, L_OPER,
725 "Link %s introduced leafed server %s.",
726 client_p->name, SID_NAME);
727 exit_client(client_p, &me, "Leafed Server.");
728 return;
729 }
730
731 target_p = make_client(client_p);
732 make_server(target_p);
733 target_p->hopcount = hop;
734
735 strlcpy(target_p->name, SID_NAME, sizeof(target_p->name));
736 strlcpy(target_p->id, SID_SID, sizeof(target_p->id));
737
738 set_server_gecos(target_p, info);
739
740 target_p->servptr = source_p;
741
742 SetServer(target_p);
743
744 if ((target_p->node.prev != NULL) || (target_p->node.next != NULL))
745 {
746 sendto_realops_flags(UMODE_ALL, L_ADMIN,
747 "already linked %s at %s:%d", target_p->name,
748 __FILE__, __LINE__);
749 ilog(L_ERROR, "already linked %s at %s:%d", target_p->name,
750 __FILE__, __LINE__);
751 assert(0==3);
752 }
753 else
754 {
755 dlinkAdd(target_p, &target_p->node, &global_client_list);
756 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
757 }
758
759 hash_add_client(target_p);
760 /* XXX test that target_p->lnode.prev and next are NULL as well? */
761 if ((target_p->lnode.prev != NULL) || (target_p->lnode.next != NULL))
762 {
763 sendto_realops_flags(UMODE_ALL, L_OPER,
764 "already lnode linked %s at %s:%d", target_p->name,
765 __FILE__, __LINE__);
766 ilog(L_ERROR, "already lnode linked %s at %s:%d", target_p->name,
767 __FILE__, __LINE__);
768 assert(0==4);
769 }
770 else
771 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers);
772
773 hash_add_id(target_p);
774
775 client_p->serv->dep_servers++;
776
777 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
778 {
779 bclient_p = ptr->data;
780
781 if (bclient_p == client_p)
782 continue;
783
784 if ((conf = bclient_p->serv->sconf) == NULL)
785 {
786 sendto_realops_flags(UMODE_ALL, L_ADMIN,
787 "Lost connect{} block for %s on %s. Closing",
788 get_client_name(client_p, HIDE_IP), SID_NAME);
789 sendto_realops_flags(UMODE_ALL, L_OPER,
790 "Lost connect{} block for %s on %s. Closing",
791 get_client_name(client_p, MASK_IP), SID_NAME);
792 exit_client(client_p, client_p, "Lost connect{} block");
793 continue;
794 }
795
796 if (match(my_name_for_link(conf), target_p->name))
797 continue;
798
799 if (IsCapable(bclient_p, CAP_TS6))
800 sendto_one(bclient_p, ":%s SID %s %d %s :%s%s",
801 ID_or_name(source_p, client_p), target_p->name, hop + 1,
802 SID_SID, IsHidden(target_p) ? "(H) " : "",
803 target_p->info);
804 else
805 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
806 source_p->name, target_p->name, hop + 1,
807 IsHidden(target_p) ? "(H) " : "",
808 target_p->info);
809 }
810
811 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
812 "Server %s being introduced by %s",
813 target_p->name, source_p->name);
814 }
815
816 /* set_server_gecos()
817 *
818 * input - pointer to client
819 * output - NONE
820 * side effects - servers gecos field is set
821 */
822 static void
823 set_server_gecos(struct Client *client_p, char *info)
824 {
825 /* check the info for [IP] */
826 if (info[0])
827 {
828 char *p;
829 char *s;
830 char *t;
831
832 s = info;
833
834 /* we should only check the first word for an ip */
835 if ((p = strchr(s, ' ')) != NULL)
836 *p = '\0';
837
838 /* check for a ] which would symbolise an [IP] */
839 if ((t = strchr(s, ']')) != NULL)
840 {
841 /* set s to after the first space */
842 if (p)
843 s = ++p;
844 else
845 s = NULL;
846 }
847 /* no ], put the space back */
848 else if (p)
849 *p = ' ';
850
851 /* p may have been set to a trailing space, so check s exists and that
852 * it isnt \0 */
853 if (s && (*s != '\0'))
854 {
855 /* a space? if not (H) could be the last part of info.. */
856 if ((p = strchr(s, ' ')))
857 *p = '\0';
858
859 /* check for (H) which is a hidden server */
860 if (!strcmp(s, "(H)"))
861 {
862 SetHidden(client_p);
863
864 /* if there was no space.. theres nothing to set info to */
865 if (p)
866 s = ++p;
867 else
868 s = NULL;
869 }
870 else if (p)
871 *p = ' ';
872
873 /* if there was a trailing space, s could point to \0, so check */
874 if (s && (*s != '\0'))
875 strlcpy(client_p->info, s, sizeof(client_p->info));
876 else
877 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
878 }
879 else
880 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
881 }
882 else
883 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
884 }
885
886 /* bogus_host()
887 *
888 * inputs - hostname
889 * output - 1 if a bogus hostname input,
890 * - 0 if its valid
891 * side effects - none
892 */
893 static int
894 bogus_host(char *host)
895 {
896 unsigned int dots = 0;
897 char *s;
898
899 for (s = host; *s; s++)
900 {
901 if (!IsServChar(*s))
902 return(1);
903
904 if ('.' == *s)
905 ++dots;
906 }
907
908 return(!dots);
909 }
910
911 /* server_exists()
912 *
913 * inputs - servername
914 * output - 1 if server exists, 0 if doesnt exist
915 */
916 static struct Client *
917 server_exists(char *servername)
918 {
919 struct Client *target_p;
920 dlink_node *ptr;
921
922 DLINK_FOREACH(ptr, global_serv_list.head)
923 {
924 target_p = ptr->data;
925
926 if (match(target_p->name, servername) ||
927 match(servername, target_p->name))
928 return(target_p);
929 }
930
931 return(NULL);
932 }

Properties

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