ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_server.c
Revision: 896
Committed: Sat Nov 3 08:54:09 2007 UTC (16 years, 4 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/modules/core/m_server.c
File size: 26852 byte(s)
Log Message:
- Killed s_stats.c

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

Properties

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