ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_server.c
Revision: 442
Committed: Sat Feb 11 23:14:21 2006 UTC (18 years, 1 month ago) by adx
Content type: text/x-csrc
File size: 26300 byte(s)
Log Message:
+ massive rewrite of module init/deinit/version headers,
  we are introducing a new module manager which deals with static
  and dynamic modules exactly the same way. (New possibilities
  include loading/unloading statically compiled modules and
  mixing static/dynamic ones in one build.)

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

Properties

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