ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-7.2/modules/core/m_server.c
Revision: 1011
Committed: Fri Sep 18 10:14:09 2009 UTC (14 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 26827 byte(s)
Log Message:
- move list manipulation routines from tools.c to list.c
- mem_frob() goes to memory.c
- sort out redundant/unneeded header includes

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

Properties

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