ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/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
Original Path: ircd-hybrid-7.2/modules/core/m_server.c
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

# 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     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 michael 946 {rfc1459_command_send_error, m_ignore, ms_sid, m_ignore, m_ignore, m_ignore}
61 adx 30 };
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 knight 31 const char *_version = "$Revision$";
79 adx 30 #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 michael 885 /* Ok, check client_p can hub the new server */
409     if (!hlined)
410 adx 30 {
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 michael 889 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
481 adx 30
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 michael 885 if (!hlined)
673 adx 30 {
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 michael 889 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
738 adx 30
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