ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/modules/core/m_server.c
Revision: 1115
Committed: Tue Dec 21 14:42:54 2010 UTC (13 years, 3 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-7.3/modules/core/m_server.c
File size: 26442 byte(s)
Log Message:
- Rename bogus_host() found in several modules to check_servname() and move
  it to s_serv.c
- serverinfo::sid is now mandatory and must be specified.
  ircd won't start otherwise

File Contents

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

Properties

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