ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 889
Committed: Thu Nov 1 12:59:05 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: 26895 byte(s)
Log Message:
- Got rid of Serv.dep_users and Serv.dep_servers

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->server_list);
483
484 /* Old sendto_serv_but_one() call removed because we now
485 * need to send different names to different servers
486 * (domain name matching)
487 */
488 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
489 {
490 bclient_p = ptr->data;
491
492 if (bclient_p == client_p)
493 continue;
494
495 if ((conf = bclient_p->serv->sconf) == NULL)
496 {
497 sendto_realops_flags(UMODE_ALL, L_ADMIN,
498 "Lost connect{} block for %s on %s. Closing",
499 get_client_name(client_p, HIDE_IP), name);
500 sendto_realops_flags(UMODE_ALL, L_OPER,
501 "Lost connect{} block for %s on %s. Closing",
502 get_client_name(client_p, MASK_IP), name);
503 exit_client(client_p, client_p, "Lost connect{} block");
504 continue;
505 }
506
507 if (match(my_name_for_link(conf), target_p->name))
508 continue;
509
510 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
511 ID_or_name(source_p, bclient_p), target_p->name, hop + 1,
512 IsHidden(target_p) ? "(H) " : "",
513 target_p->info);
514 }
515
516 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
517 "Server %s being introduced by %s",
518 target_p->name, source_p->name);
519 }
520
521 /* ms_sid()
522 * parv[0] = sender prefix
523 * parv[1] = servername
524 * parv[2] = serverinfo/hopcount
525 * parv[3] = sid of new server
526 * parv[4] = serverinfo
527 */
528 static void
529 ms_sid(struct Client *client_p, struct Client *source_p,
530 int parc, char *parv[])
531 {
532 char info[REALLEN + 1];
533 struct Client *target_p;
534 struct Client *bclient_p;
535 struct ConfItem *conf;
536 struct MatchItem *match_item;
537 int hlined = 0;
538 int llined = 0;
539 dlink_node *ptr, *ptr_next;
540 int hop;
541 #define SID_NAME parv[1]
542 #define SID_HOP parv[2]
543 #define SID_SID parv[3]
544 #define SID_GECOS parv[4]
545
546 hop = atoi(SID_HOP);
547
548 /* Just to be sure -A1kmm. */
549 if (!IsServer(source_p))
550 return;
551
552 strlcpy(info, SID_GECOS, sizeof(info));
553
554 /* collision on SID? */
555 if ((target_p = hash_find_id(SID_SID)) != NULL)
556 {
557 sendto_one(client_p, "ERROR :SID %s already exists", SID_SID);
558 sendto_realops_flags(UMODE_ALL, L_ADMIN,
559 "Link %s cancelled, SID %s already exists",
560 get_client_name(client_p, SHOW_IP), SID_SID);
561 sendto_realops_flags(UMODE_ALL, L_OPER,
562 "Link %s cancelled, SID %s already exists",
563 client_p->name, SID_SID);
564 exit_client(client_p, &me, "Server Exists");
565 return;
566 }
567
568 /* collision on name? */
569 if ((target_p = server_exists(SID_NAME)) != NULL)
570 {
571 sendto_one(client_p, "ERROR :Server %s already exists", SID_NAME);
572 sendto_realops_flags(UMODE_ALL, L_ADMIN,
573 "Link %s cancelled, server %s already exists",
574 get_client_name(client_p, SHOW_IP), SID_NAME);
575 sendto_realops_flags(UMODE_ALL, L_OPER,
576 "Link %s cancelled, server %s already exists",
577 client_p->name, SID_NAME);
578 exit_client(client_p, &me, "Server Exists");
579 return;
580 }
581
582 /* XXX If somehow there is a connect in progress and
583 * a connect comes in with same name toss the pending one,
584 * but only if it's not the same client! - Dianora
585 */
586 if ((target_p = find_servconn_in_progress(SID_NAME)))
587 if (target_p != client_p)
588 exit_client(target_p, &me, "Overridden");
589
590 /* User nicks never have '.' in them and server names
591 * must always have '.' in them.
592 */
593 if (strchr(SID_NAME, '.') == NULL || /* servernames must have a '.' and nicks must not */
594 strlen(SID_NAME) > HOSTLEN) /* ensure the name of the server is not too long */
595 {
596 /* Server trying to use the same name as a person. Would
597 * cause a fair bit of confusion. Enough to make it hellish
598 * for a while and servers to send stuff to the wrong place.
599 */
600 sendto_one(client_p, "ERROR :Invalid servername");
601 sendto_realops_flags(UMODE_ALL, L_ADMIN,
602 "Link %s cancelled: servername name %s invalid",
603 get_client_name(client_p, SHOW_IP), SID_NAME);
604 sendto_realops_flags(UMODE_ALL, L_OPER,
605 "Link %s cancelled: servername name %s invalid",
606 get_client_name(client_p, MASK_IP), SID_NAME);
607 exit_client(client_p, client_p, "Nick as Server");
608 return;
609 }
610
611 /* Server is informing about a new server behind
612 * this link. Create REMOTE server structure,
613 * add it to list and propagate word to my other
614 * server links...
615 */
616 if (parc == 1 || info[0] == '\0')
617 {
618 sendto_one(client_p, "ERROR :No server info specified for %s", SID_NAME);
619 return;
620 }
621
622 /* See if the newly found server is behind a guaranteed
623 * leaf. If so, close the link.
624 */
625 DLINK_FOREACH(ptr, leaf_items.head)
626 {
627 conf = ptr->data;
628
629 if (match(conf->name, client_p->name))
630 {
631 match_item = (struct MatchItem *)map_to_conf(conf);
632 if (match(match_item->host, SID_NAME))
633 llined++;
634 }
635 }
636
637 DLINK_FOREACH(ptr, hub_items.head)
638 {
639 conf = ptr->data;
640
641 if (match(conf->name, client_p->name))
642 {
643 match_item = (struct MatchItem *)map_to_conf(conf);
644
645 if (match(match_item->host, SID_NAME))
646 hlined++;
647 }
648 }
649
650 /* Ok, this way this works is
651 *
652 * A server can have a CONF_HUB allowing it to introduce servers
653 * behind it.
654 *
655 * connect {
656 * name = "irc.bighub.net";
657 * hub_mask="*";
658 * ...
659 *
660 * That would allow "irc.bighub.net" to introduce anything it wanted..
661 *
662 * However
663 *
664 * connect {
665 * name = "irc.somehub.fi";
666 * hub_mask="*";
667 * leaf_mask="*.edu";
668 *...
669 * Would allow this server in finland to hub anything but
670 * .edu's
671 */
672
673 /* Ok, check client_p can hub the new server, and make sure it's not a LL */
674 if (!hlined)
675 {
676 /* OOOPs nope can't HUB */
677 sendto_realops_flags(UMODE_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
678 get_client_name(client_p, SHOW_IP), SID_NAME);
679 sendto_realops_flags(UMODE_ALL, L_OPER, "Non-Hub link %s introduced %s.",
680 get_client_name(client_p, MASK_IP), SID_NAME);
681 exit_client(source_p, &me, "No matching hub_mask.");
682 return;
683 }
684
685 /* Check for the new server being leafed behind this HUB */
686 if (llined)
687 {
688 /* OOOPs nope can't HUB this leaf */
689 sendto_realops_flags(UMODE_ALL, L_ADMIN,
690 "Link %s introduced leafed server %s.",
691 get_client_name(client_p, SHOW_IP), SID_NAME);
692 sendto_realops_flags(UMODE_ALL, L_OPER,
693 "Link %s introduced leafed server %s.",
694 client_p->name, SID_NAME);
695 exit_client(client_p, &me, "Leafed Server.");
696 return;
697 }
698
699 target_p = make_client(client_p);
700 make_server(target_p);
701 target_p->hopcount = hop;
702
703 strlcpy(target_p->name, SID_NAME, sizeof(target_p->name));
704 strlcpy(target_p->id, SID_SID, sizeof(target_p->id));
705
706 set_server_gecos(target_p, info);
707
708 target_p->servptr = source_p;
709
710 SetServer(target_p);
711
712 if ((target_p->node.prev != NULL) || (target_p->node.next != NULL))
713 {
714 sendto_realops_flags(UMODE_ALL, L_ADMIN,
715 "already linked %s at %s:%d", target_p->name,
716 __FILE__, __LINE__);
717 ilog(L_ERROR, "already linked %s at %s:%d", target_p->name,
718 __FILE__, __LINE__);
719 assert(0==3);
720 }
721 else
722 {
723 dlinkAdd(target_p, &target_p->node, &global_client_list);
724 dlinkAdd(target_p, make_dlink_node(), &global_serv_list);
725 }
726
727 hash_add_client(target_p);
728 /* XXX test that target_p->lnode.prev and next are NULL as well? */
729 if ((target_p->lnode.prev != NULL) || (target_p->lnode.next != NULL))
730 {
731 sendto_realops_flags(UMODE_ALL, L_OPER,
732 "already lnode linked %s at %s:%d", target_p->name,
733 __FILE__, __LINE__);
734 ilog(L_ERROR, "already lnode linked %s at %s:%d", target_p->name,
735 __FILE__, __LINE__);
736 assert(0==4);
737 }
738 else
739 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
740
741 hash_add_id(target_p);
742
743 DLINK_FOREACH_SAFE(ptr, ptr_next, serv_list.head)
744 {
745 bclient_p = ptr->data;
746
747 if (bclient_p == client_p)
748 continue;
749
750 if ((conf = bclient_p->serv->sconf) == NULL)
751 {
752 sendto_realops_flags(UMODE_ALL, L_ADMIN,
753 "Lost connect{} block for %s on %s. Closing",
754 get_client_name(client_p, HIDE_IP), SID_NAME);
755 sendto_realops_flags(UMODE_ALL, L_OPER,
756 "Lost connect{} block for %s on %s. Closing",
757 get_client_name(client_p, MASK_IP), SID_NAME);
758 exit_client(client_p, client_p, "Lost connect{} block");
759 continue;
760 }
761
762 if (match(my_name_for_link(conf), target_p->name))
763 continue;
764
765 if (IsCapable(bclient_p, CAP_TS6))
766 sendto_one(bclient_p, ":%s SID %s %d %s :%s%s",
767 ID_or_name(source_p, client_p), target_p->name, hop + 1,
768 SID_SID, IsHidden(target_p) ? "(H) " : "",
769 target_p->info);
770 else
771 sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
772 source_p->name, target_p->name, hop + 1,
773 IsHidden(target_p) ? "(H) " : "",
774 target_p->info);
775 }
776
777 sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
778 "Server %s being introduced by %s",
779 target_p->name, source_p->name);
780 }
781
782 /* set_server_gecos()
783 *
784 * input - pointer to client
785 * output - NONE
786 * side effects - servers gecos field is set
787 */
788 static void
789 set_server_gecos(struct Client *client_p, char *info)
790 {
791 /* check the info for [IP] */
792 if (info[0])
793 {
794 char *p;
795 char *s;
796 char *t;
797
798 s = info;
799
800 /* we should only check the first word for an ip */
801 if ((p = strchr(s, ' ')) != NULL)
802 *p = '\0';
803
804 /* check for a ] which would symbolise an [IP] */
805 if ((t = strchr(s, ']')) != NULL)
806 {
807 /* set s to after the first space */
808 if (p)
809 s = ++p;
810 else
811 s = NULL;
812 }
813 /* no ], put the space back */
814 else if (p)
815 *p = ' ';
816
817 /* p may have been set to a trailing space, so check s exists and that
818 * it isnt \0 */
819 if (s && (*s != '\0'))
820 {
821 /* a space? if not (H) could be the last part of info.. */
822 if ((p = strchr(s, ' ')))
823 *p = '\0';
824
825 /* check for (H) which is a hidden server */
826 if (!strcmp(s, "(H)"))
827 {
828 SetHidden(client_p);
829
830 /* if there was no space.. theres nothing to set info to */
831 if (p)
832 s = ++p;
833 else
834 s = NULL;
835 }
836 else if (p)
837 *p = ' ';
838
839 /* if there was a trailing space, s could point to \0, so check */
840 if (s && (*s != '\0'))
841 strlcpy(client_p->info, s, sizeof(client_p->info));
842 else
843 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
844 }
845 else
846 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
847 }
848 else
849 strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
850 }
851
852 /* bogus_host()
853 *
854 * inputs - hostname
855 * output - 1 if a bogus hostname input,
856 * - 0 if its valid
857 * side effects - none
858 */
859 static int
860 bogus_host(char *host)
861 {
862 unsigned int dots = 0;
863 char *s;
864
865 for (s = host; *s; s++)
866 {
867 if (!IsServChar(*s))
868 return(1);
869
870 if ('.' == *s)
871 ++dots;
872 }
873
874 return(!dots);
875 }
876
877 /* server_exists()
878 *
879 * inputs - servername
880 * output - 1 if server exists, 0 if doesnt exist
881 */
882 static struct Client *
883 server_exists(char *servername)
884 {
885 struct Client *target_p;
886 dlink_node *ptr;
887
888 DLINK_FOREACH(ptr, global_serv_list.head)
889 {
890 target_p = ptr->data;
891
892 if (match(target_p->name, servername) ||
893 match(servername, target_p->name))
894 return(target_p);
895 }
896
897 return(NULL);
898 }

Properties

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