ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_server.c
Revision: 885
Committed: Wed Oct 31 18:09:24 2007 UTC (16 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 26955 byte(s)
Log Message:
- Removed LazyLinks in 7.2 to stop people from asking why we keep
  broken code for half a decade. LL will be implemented in a smarter
  fashion in due time

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 we are connecting (Handshake), we already have the name from the
228 * connect{} block in client_p->name
229 */
230 strlcpy(client_p->name, name, sizeof(client_p->name));
231 set_server_gecos(client_p, info);
232 client_p->hopcount = hop;
233 server_estab(client_p);
234 }
235
236 /* ms_server()
237 * parv[0] = sender prefix
238 * parv[1] = servername
239 * parv[2] = serverinfo/hopcount
240 * parv[3] = serverinfo
241 */
242 static void
243 ms_server(struct Client *client_p, struct Client *source_p,
244 int parc, char *parv[])
245 {
246 char info[REALLEN + 1];
247 char *name;
248 struct Client *target_p;
249 struct Client *bclient_p;
250 struct ConfItem *conf;
251 struct MatchItem *match_item;
252 int hop;
253 int hlined = 0;
254 int llined = 0;
255 dlink_node *ptr, *ptr_next;
256
257 /* Just to be sure -A1kmm. */
258 if (!IsServer(source_p))
259 return;
260
261 if (parc < 4)
262 {
263 sendto_one(client_p, "ERROR :No servername");
264 return;
265 }
266
267 name = parv[1];
268 hop = atoi(parv[2]);
269 strlcpy(info, parv[3], sizeof(info));
270
271 if ((target_p = server_exists(name)))
272 {
273 /* This link is trying feed me a server that I already have
274 * access through another path -- multiple paths not accepted
275 * currently, kill this link immediately!!
276 *
277 * Rather than KILL the link which introduced it, KILL the
278 * youngest of the two links. -avalon
279 *
280 * I think that we should exit the link itself, not the introducer,
281 * and we should always exit the most recently received(i.e. the
282 * one we are receiving this SERVER for. -A1kmm
283 *
284 * You *cant* do this, if you link somewhere, it bursts you a server
285 * that already exists, then sends you a client burst, you squit the
286 * server, but you keep getting the burst of clients on a server that
287 * doesnt exist, although ircd can handle it, its not a realistic
288 * solution.. --fl_
289 */
290 /* It is behind a host-masked server. Completely ignore the
291 * server message(don't propagate or we will delink from whoever
292 * we propagate to). -A1kmm
293 */
294 if (irccmp(target_p->name, name) && target_p->from == client_p)
295 return;
296
297 sendto_one(client_p, "ERROR :Server %s already exists", name);
298 sendto_realops_flags(UMODE_ALL, L_ADMIN,
299 "Link %s cancelled, server %s already exists",
300 get_client_name(client_p, SHOW_IP), name);
301 sendto_realops_flags(UMODE_ALL, L_OPER,
302 "Link %s cancelled, server %s already exists",
303 client_p->name, name);
304 exit_client(client_p, &me, "Server Exists");
305 return;
306 }
307
308 /* XXX If somehow there is a connect in progress and
309 * a connect comes in with same name toss the pending one,
310 * but only if it's not the same client! - Dianora
311 */
312 if ((target_p = find_servconn_in_progress(name)))
313 if (target_p != client_p)
314 exit_client(target_p, &me, "Overridden");
315
316 /* User nicks never have '.' in them and server names
317 * must always have '.' in them.
318 */
319 if (strchr(name, '.') == NULL)
320 {
321 /* Server trying to use the same name as a person. Would
322 * cause a fair bit of confusion. Enough to make it hellish
323 * for a while and servers to send stuff to the wrong place.
324 */
325 sendto_one(client_p,"ERROR :Nickname %s already exists!", name);
326 sendto_realops_flags(UMODE_ALL, L_ADMIN,
327 "Link %s cancelled: Server/nick collision on %s",
328 /* inpath */ get_client_name(client_p, HIDE_IP), name);
329 sendto_realops_flags(UMODE_ALL, L_OPER,
330 "Link %s cancelled: Server/nick collision on %s",
331 get_client_name(client_p, MASK_IP), name);
332 exit_client(client_p, client_p, "Nick as Server");
333 return;
334 }
335
336 if (strlen(name) > HOSTLEN)
337 {
338 sendto_realops_flags(UMODE_ALL, L_ADMIN,
339 "Link %s introduced server with invalid servername %s",
340 get_client_name(client_p, HIDE_IP), name);
341 sendto_realops_flags(UMODE_ALL, L_OPER,
342 "Link %s introduced server with invalid servername %s",
343 client_p->name, name);
344 exit_client(client_p, &me, "Invalid servername introduced.");
345 return;
346 }
347
348 /* Server is informing about a new server behind
349 * this link. Create REMOTE server structure,
350 * add it to list and propagate word to my other
351 * server links...
352 */
353 if (parc == 1 || info[0] == '\0')
354 {
355 sendto_one(client_p, "ERROR :No server info specified for %s", name);
356 return;
357 }
358
359 /* See if the newly found server is behind a guaranteed
360 * leaf. If so, close the link.
361 */
362 DLINK_FOREACH(ptr, leaf_items.head)
363 {
364 conf = ptr->data;
365
366 if (match(conf->name, client_p->name))
367 {
368 match_item = (struct MatchItem *)map_to_conf(conf);
369 if (match(match_item->host, name))
370 llined++;
371 }
372 }
373
374 DLINK_FOREACH(ptr, hub_items.head)
375 {
376 conf = ptr->data;
377
378 if (match(conf->name, client_p->name))
379 {
380 match_item = (struct MatchItem *)map_to_conf(conf);
381
382 if (match(match_item->host, name))
383 hlined++;
384 }
385 }
386
387 /* Ok, this way this works is
388 *
389 * A server can have a CONF_HUB allowing it to introduce servers
390 * behind it.
391 *
392 * connect {
393 * name = "irc.bighub.net";
394 * hub_mask="*";
395 * ...
396 *
397 * That would allow "irc.bighub.net" to introduce anything it wanted..
398 *
399 * However
400 *
401 * connect {
402 * name = "irc.somehub.fi";
403 * hub_mask="*";
404 * leaf_mask="*.edu";
405 *...
406 * Would allow this server in finland to hub anything but
407 * .edu's
408 */
409
410 /* Ok, check client_p can hub the new server */
411 if (!hlined)
412 {
413 /* OOOPs nope can't HUB */
414 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
415 get_client_name(client_p, HIDE_IP), name);
416 sendto_realops_flags(UMODE_ALL, L_OPER, "Non-Hub link %s introduced %s.",
417 get_client_name(client_p, MASK_IP), name);
418 exit_client(source_p, &me, "No matching hub_mask.");
419 return;
420 }
421
422 /* Check for the new server being leafed behind this HUB */
423 if (llined)
424 {
425 /* OOOPs nope can't HUB this leaf */
426 sendto_realops_flags(UMODE_ALL, L_ADMIN,
427 "Link %s introduced leafed server %s.",
428 get_client_name(client_p, HIDE_IP), name);
429 sendto_realops_flags(UMODE_ALL, L_OPER,
430 "Link %s introduced leafed server %s.",
431 client_p->name, name);
432 /* If it is new, we are probably misconfigured, so split the
433 * non-hub server introducing this. Otherwise, split the new
434 * server. -A1kmm.
435 */
436 /* wastes too much bandwidth, generates too many errors on
437 * larger networks, dont bother. --fl_
438 */
439 exit_client(client_p, &me, "Leafed Server.");
440 return;
441 }
442
443 target_p = make_client(client_p);
444 make_server(target_p);
445 target_p->hopcount = hop;
446
447 strlcpy(target_p->name, name, sizeof(target_p->name));
448
449 set_server_gecos(target_p, info);
450
451 target_p->servptr = source_p;
452
453 SetServer(target_p);
454
455 if ((target_p->node.prev != NULL) || (target_p->node.next != NULL))
456 {
457 sendto_realops_flags(UMODE_ALL, L_OPER,
458 "already linked %s at %s:%d", target_p->name,
459 __FILE__, __LINE__);
460 ilog(L_ERROR, "already linked client %s at %s:%d", target_p->name,
461 __FILE__, __LINE__);
462 assert(0==1);
463 }
464 else
465 {
466 dlinkAdd(target_p, &target_p->node, &global_client_list);
467 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
468 }
469
470 hash_add_client(target_p);
471 /* XXX test that target_p->lnode.prev and .next are NULL as well? */
472 if ((target_p->lnode.prev != NULL) || (target_p->lnode.next != NULL))
473 {
474 sendto_realops_flags(UMODE_ALL, L_OPER,
475 "already lnode linked %s at %s:%d", target_p->name,
476 __FILE__, __LINE__);
477 ilog(L_ERROR, "already lnode linked %s at %s:%d", target_p->name,
478 __FILE__, __LINE__);
479 assert(0==2);
480 }
481 else
482 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers);
483
484 client_p->serv->dep_servers++;
485
486 /* Old sendto_serv_but_one() call removed because we now
487 * need to send different names to different servers
488 * (domain name matching)
489 */
490 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
491 {
492 bclient_p = ptr->data;
493
494 if (bclient_p == client_p)
495 continue;
496
497 if ((conf = bclient_p->serv->sconf) == NULL)
498 {
499 sendto_realops_flags(UMODE_ALL, L_ADMIN,
500 "Lost connect{} block for %s on %s. Closing",
501 get_client_name(client_p, HIDE_IP), name);
502 sendto_realops_flags(UMODE_ALL, L_OPER,
503 "Lost connect{} block for %s on %s. Closing",
504 get_client_name(client_p, MASK_IP), name);
505 exit_client(client_p, client_p, "Lost connect{} block");
506 continue;
507 }
508
509 if (match(my_name_for_link(conf), target_p->name))
510 continue;
511
512 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
513 ID_or_name(source_p, bclient_p), target_p->name, hop + 1,
514 IsHidden(target_p) ? "(H) " : "",
515 target_p->info);
516 }
517
518 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
519 "Server %s being introduced by %s",
520 target_p->name, source_p->name);
521 }
522
523 /* ms_sid()
524 * parv[0] = sender prefix
525 * parv[1] = servername
526 * parv[2] = serverinfo/hopcount
527 * parv[3] = sid of new server
528 * parv[4] = serverinfo
529 */
530 static void
531 ms_sid(struct Client *client_p, struct Client *source_p,
532 int parc, char *parv[])
533 {
534 char info[REALLEN + 1];
535 struct Client *target_p;
536 struct Client *bclient_p;
537 struct ConfItem *conf;
538 struct MatchItem *match_item;
539 int hlined = 0;
540 int llined = 0;
541 dlink_node *ptr, *ptr_next;
542 int hop;
543 #define SID_NAME parv[1]
544 #define SID_HOP parv[2]
545 #define SID_SID parv[3]
546 #define SID_GECOS parv[4]
547
548 hop = atoi(SID_HOP);
549
550 /* Just to be sure -A1kmm. */
551 if (!IsServer(source_p))
552 return;
553
554 strlcpy(info, SID_GECOS, sizeof(info));
555
556 /* collision on SID? */
557 if ((target_p = hash_find_id(SID_SID)) != NULL)
558 {
559 sendto_one(client_p, "ERROR :SID %s already exists", SID_SID);
560 sendto_realops_flags(UMODE_ALL, L_ADMIN,
561 "Link %s cancelled, SID %s already exists",
562 get_client_name(client_p, SHOW_IP), SID_SID);
563 sendto_realops_flags(UMODE_ALL, L_OPER,
564 "Link %s cancelled, SID %s already exists",
565 client_p->name, SID_SID);
566 exit_client(client_p, &me, "Server Exists");
567 return;
568 }
569
570 /* collision on name? */
571 if ((target_p = server_exists(SID_NAME)) != NULL)
572 {
573 sendto_one(client_p, "ERROR :Server %s already exists", SID_NAME);
574 sendto_realops_flags(UMODE_ALL, L_ADMIN,
575 "Link %s cancelled, server %s already exists",
576 get_client_name(client_p, SHOW_IP), SID_NAME);
577 sendto_realops_flags(UMODE_ALL, L_OPER,
578 "Link %s cancelled, server %s already exists",
579 client_p->name, SID_NAME);
580 exit_client(client_p, &me, "Server Exists");
581 return;
582 }
583
584 /* XXX If somehow there is a connect in progress and
585 * a connect comes in with same name toss the pending one,
586 * but only if it's not the same client! - Dianora
587 */
588 if ((target_p = find_servconn_in_progress(SID_NAME)))
589 if (target_p != client_p)
590 exit_client(target_p, &me, "Overridden");
591
592 /* User nicks never have '.' in them and server names
593 * must always have '.' in them.
594 */
595 if (strchr(SID_NAME, '.') == NULL || /* servernames must have a '.' and nicks must not */
596 strlen(SID_NAME) > HOSTLEN) /* ensure the name of the server is not too long */
597 {
598 /* Server trying to use the same name as a person. Would
599 * cause a fair bit of confusion. Enough to make it hellish
600 * for a while and servers to send stuff to the wrong place.
601 */
602 sendto_one(client_p, "ERROR :Invalid servername");
603 sendto_realops_flags(UMODE_ALL, L_ADMIN,
604 "Link %s cancelled: servername name %s invalid",
605 get_client_name(client_p, SHOW_IP), SID_NAME);
606 sendto_realops_flags(UMODE_ALL, L_OPER,
607 "Link %s cancelled: servername name %s invalid",
608 get_client_name(client_p, MASK_IP), SID_NAME);
609 exit_client(client_p, client_p, "Nick as Server");
610 return;
611 }
612
613 /* Server is informing about a new server behind
614 * this link. Create REMOTE server structure,
615 * add it to list and propagate word to my other
616 * server links...
617 */
618 if (parc == 1 || info[0] == '\0')
619 {
620 sendto_one(client_p, "ERROR :No server info specified for %s", SID_NAME);
621 return;
622 }
623
624 /* See if the newly found server is behind a guaranteed
625 * leaf. If so, close the link.
626 */
627 DLINK_FOREACH(ptr, leaf_items.head)
628 {
629 conf = ptr->data;
630
631 if (match(conf->name, client_p->name))
632 {
633 match_item = (struct MatchItem *)map_to_conf(conf);
634 if (match(match_item->host, SID_NAME))
635 llined++;
636 }
637 }
638
639 DLINK_FOREACH(ptr, hub_items.head)
640 {
641 conf = ptr->data;
642
643 if (match(conf->name, client_p->name))
644 {
645 match_item = (struct MatchItem *)map_to_conf(conf);
646
647 if (match(match_item->host, SID_NAME))
648 hlined++;
649 }
650 }
651
652 /* Ok, this way this works is
653 *
654 * A server can have a CONF_HUB allowing it to introduce servers
655 * behind it.
656 *
657 * connect {
658 * name = "irc.bighub.net";
659 * hub_mask="*";
660 * ...
661 *
662 * That would allow "irc.bighub.net" to introduce anything it wanted..
663 *
664 * However
665 *
666 * connect {
667 * name = "irc.somehub.fi";
668 * hub_mask="*";
669 * leaf_mask="*.edu";
670 *...
671 * Would allow this server in finland to hub anything but
672 * .edu's
673 */
674
675 /* Ok, check client_p can hub the new server, and make sure it's not a LL */
676 if (!hlined)
677 {
678 /* OOOPs nope can't HUB */
679 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
680 get_client_name(client_p, SHOW_IP), SID_NAME);
681 sendto_realops_flags(UMODE_ALL, L_OPER, "Non-Hub link %s introduced %s.",
682 get_client_name(client_p, MASK_IP), SID_NAME);
683 exit_client(source_p, &me, "No matching hub_mask.");
684 return;
685 }
686
687 /* Check for the new server being leafed behind this HUB */
688 if (llined)
689 {
690 /* OOOPs nope can't HUB this leaf */
691 sendto_realops_flags(UMODE_ALL, L_ADMIN,
692 "Link %s introduced leafed server %s.",
693 get_client_name(client_p, SHOW_IP), SID_NAME);
694 sendto_realops_flags(UMODE_ALL, L_OPER,
695 "Link %s introduced leafed server %s.",
696 client_p->name, SID_NAME);
697 exit_client(client_p, &me, "Leafed Server.");
698 return;
699 }
700
701 target_p = make_client(client_p);
702 make_server(target_p);
703 target_p->hopcount = hop;
704
705 strlcpy(target_p->name, SID_NAME, sizeof(target_p->name));
706 strlcpy(target_p->id, SID_SID, sizeof(target_p->id));
707
708 set_server_gecos(target_p, info);
709
710 target_p->servptr = source_p;
711
712 SetServer(target_p);
713
714 if ((target_p->node.prev != NULL) || (target_p->node.next != NULL))
715 {
716 sendto_realops_flags(UMODE_ALL, L_ADMIN,
717 "already linked %s at %s:%d", target_p->name,
718 __FILE__, __LINE__);
719 ilog(L_ERROR, "already linked %s at %s:%d", target_p->name,
720 __FILE__, __LINE__);
721 assert(0==3);
722 }
723 else
724 {
725 dlinkAdd(target_p, &target_p->node, &global_client_list);
726 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
727 }
728
729 hash_add_client(target_p);
730 /* XXX test that target_p->lnode.prev and next are NULL as well? */
731 if ((target_p->lnode.prev != NULL) || (target_p->lnode.next != NULL))
732 {
733 sendto_realops_flags(UMODE_ALL, L_OPER,
734 "already lnode linked %s at %s:%d", target_p->name,
735 __FILE__, __LINE__);
736 ilog(L_ERROR, "already lnode linked %s at %s:%d", target_p->name,
737 __FILE__, __LINE__);
738 assert(0==4);
739 }
740 else
741 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->servers);
742
743 hash_add_id(target_p);
744
745 client_p->serv->dep_servers++;
746
747 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
748 {
749 bclient_p = ptr->data;
750
751 if (bclient_p == client_p)
752 continue;
753
754 if ((conf = bclient_p->serv->sconf) == NULL)
755 {
756 sendto_realops_flags(UMODE_ALL, L_ADMIN,
757 "Lost connect{} block for %s on %s. Closing",
758 get_client_name(client_p, HIDE_IP), SID_NAME);
759 sendto_realops_flags(UMODE_ALL, L_OPER,
760 "Lost connect{} block for %s on %s. Closing",
761 get_client_name(client_p, MASK_IP), SID_NAME);
762 exit_client(client_p, client_p, "Lost connect{} block");
763 continue;
764 }
765
766 if (match(my_name_for_link(conf), target_p->name))
767 continue;
768
769 if (IsCapable(bclient_p, CAP_TS6))
770 sendto_one(bclient_p, ":%s SID %s %d %s :%s%s",
771 ID_or_name(source_p, client_p), target_p->name, hop + 1,
772 SID_SID, IsHidden(target_p) ? "(H) " : "",
773 target_p->info);
774 else
775 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
776 source_p->name, target_p->name, hop + 1,
777 IsHidden(target_p) ? "(H) " : "",
778 target_p->info);
779 }
780
781 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
782 "Server %s being introduced by %s",
783 target_p->name, source_p->name);
784 }
785
786 /* set_server_gecos()
787 *
788 * input - pointer to client
789 * output - NONE
790 * side effects - servers gecos field is set
791 */
792 static void
793 set_server_gecos(struct Client *client_p, char *info)
794 {
795 /* check the info for [IP] */
796 if (info[0])
797 {
798 char *p;
799 char *s;
800 char *t;
801
802 s = info;
803
804 /* we should only check the first word for an ip */
805 if ((p = strchr(s, ' ')) != NULL)
806 *p = '\0';
807
808 /* check for a ] which would symbolise an [IP] */
809 if ((t = strchr(s, ']')) != NULL)
810 {
811 /* set s to after the first space */
812 if (p)
813 s = ++p;
814 else
815 s = NULL;
816 }
817 /* no ], put the space back */
818 else if (p)
819 *p = ' ';
820
821 /* p may have been set to a trailing space, so check s exists and that
822 * it isnt \0 */
823 if (s && (*s != '\0'))
824 {
825 /* a space? if not (H) could be the last part of info.. */
826 if ((p = strchr(s, ' ')))
827 *p = '\0';
828
829 /* check for (H) which is a hidden server */
830 if (!strcmp(s, "(H)"))
831 {
832 SetHidden(client_p);
833
834 /* if there was no space.. theres nothing to set info to */
835 if (p)
836 s = ++p;
837 else
838 s = NULL;
839 }
840 else if (p)
841 *p = ' ';
842
843 /* if there was a trailing space, s could point to \0, so check */
844 if (s && (*s != '\0'))
845 strlcpy(client_p->info, s, sizeof(client_p->info));
846 else
847 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
848 }
849 else
850 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
851 }
852 else
853 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
854 }
855
856 /* bogus_host()
857 *
858 * inputs - hostname
859 * output - 1 if a bogus hostname input,
860 * - 0 if its valid
861 * side effects - none
862 */
863 static int
864 bogus_host(char *host)
865 {
866 unsigned int dots = 0;
867 char *s;
868
869 for (s = host; *s; s++)
870 {
871 if (!IsServChar(*s))
872 return(1);
873
874 if ('.' == *s)
875 ++dots;
876 }
877
878 return(!dots);
879 }
880
881 /* server_exists()
882 *
883 * inputs - servername
884 * output - 1 if server exists, 0 if doesnt exist
885 */
886 static struct Client *
887 server_exists(char *servername)
888 {
889 struct Client *target_p;
890 dlink_node *ptr;
891
892 DLINK_FOREACH(ptr, global_serv_list.head)
893 {
894 target_p = ptr->data;
895
896 if (match(target_p->name, servername) ||
897 match(servername, target_p->name))
898 return(target_p);
899 }
900
901 return(NULL);
902 }

Properties

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