ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/modules/core/m_server.c
Revision: 31
Committed: Sun Oct 2 20:34:05 2005 UTC (18 years, 6 months ago) by knight
Content type: text/x-csrc
File size: 27925 byte(s)
Log Message:
- Fix svn:keywords

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

Properties

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