ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 4605
Committed: Sat Aug 30 18:18:59 2014 UTC (12 years, 1 month ago) by michael
Content type: text/x-csrc
File size: 28119 byte(s)
Log Message:
- m_server.c:server_estab(): cleaned up 'inpath', 'inpath_ip' mess

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2820 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2820 * Copyright (c) 1997-2014 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2820 /*! \file m_server.c
23     * \brief Includes required functions for processing the SERVER/SID command.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 1011 #include "list.h"
29 michael 2820 #include "client.h"
30 adx 30 #include "event.h"
31 michael 2820 #include "hash.h"
32     #include "irc_string.h"
33     #include "ircd.h"
34     #include "numeric.h"
35     #include "conf.h"
36     #include "log.h"
37 michael 3347 #include "misc.h"
38     #include "server.h"
39     #include "user.h"
40 michael 2820 #include "send.h"
41 adx 30 #include "parse.h"
42 michael 3303 #include "memory.h"
43 adx 30 #include "modules.h"
44    
45    
46 michael 3303 /*
47     * send_tb
48     *
49     * inputs - pointer to Client
50     * - pointer to channel
51     * output - NONE
52     * side effects - Called on a server burst when
53     * server is CAP_TBURST capable
54     */
55     static void
56     send_tb(struct Client *client_p, struct Channel *chptr)
57     {
58     /*
59     * We may also send an empty topic here, but only if topic_time isn't 0,
60     * i.e. if we had a topic that got unset. This is required for syncing
61     * topics properly.
62     *
63     * Imagine the following scenario: Our downlink introduces a channel
64     * to us with a TS that is equal to ours, but the channel topic on
65     * their side got unset while the servers were in splitmode, which means
66     * their 'topic' is newer. They simply wanted to unset it, so we have to
67     * deal with it in a more sophisticated fashion instead of just resetting
68     * it to their old topic they had before. Read m_tburst.c:ms_tburst
69     * for further information -Michael
70     */
71     if (chptr->topic_time)
72     sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s", me.id,
73     (unsigned long)chptr->channelts, chptr->chname,
74     (unsigned long)chptr->topic_time,
75     chptr->topic_info,
76     chptr->topic);
77     }
78    
79     /* sendnick_TS()
80     *
81     * inputs - client (server) to send nick towards
82     * - client to send nick for
83     * output - NONE
84     * side effects - NICK message is sent towards given client_p
85     */
86 michael 3306 static void
87 michael 3303 sendnick_TS(struct Client *client_p, struct Client *target_p)
88     {
89     char ubuf[IRCD_BUFSIZE] = "";
90    
91     if (!IsClient(target_p))
92     return;
93    
94 michael 4020 send_umode(NULL, target_p, 0, ubuf);
95 michael 3303
96     if (ubuf[0] == '\0')
97     {
98     ubuf[0] = '+';
99     ubuf[1] = '\0';
100     }
101    
102     if (IsCapable(client_p, CAP_SVS))
103     sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s %s :%s",
104     target_p->servptr->id,
105     target_p->name, target_p->hopcount + 1,
106     (unsigned long) target_p->tsinfo,
107     ubuf, target_p->username, target_p->host,
108     (MyClient(target_p) && IsIPSpoof(target_p)) ?
109     "0" : target_p->sockhost, target_p->id,
110     target_p->svid, target_p->info);
111     else
112     sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s :%s",
113     target_p->servptr->id,
114     target_p->name, target_p->hopcount + 1,
115     (unsigned long) target_p->tsinfo,
116     ubuf, target_p->username, target_p->host,
117     (MyClient(target_p) && IsIPSpoof(target_p)) ?
118     "0" : target_p->sockhost, target_p->id, target_p->info);
119    
120     if (!EmptyString(target_p->certfp))
121     sendto_one(client_p, ":%s CERTFP %s", target_p->id, target_p->certfp);
122    
123     if (target_p->away[0])
124     sendto_one(client_p, ":%s AWAY :%s", target_p->id, target_p->away);
125    
126     }
127    
128     /* burst_members()
129     *
130     * inputs - pointer to server to send members to
131     * - dlink_list pointer to membership list to send
132     * output - NONE
133     * side effects -
134     */
135     static void
136     burst_members(struct Client *client_p, struct Channel *chptr)
137     {
138     struct Client *target_p;
139     struct Membership *ms;
140     dlink_node *ptr;
141    
142     DLINK_FOREACH(ptr, chptr->members.head)
143     {
144     ms = ptr->data;
145     target_p = ms->client_p;
146    
147     if (!HasFlag(target_p, FLAGS_BURSTED))
148     {
149     AddFlag(target_p, FLAGS_BURSTED);
150    
151     if (target_p->from != client_p)
152     sendnick_TS(client_p, target_p);
153     }
154     }
155     }
156    
157     /* burst_all()
158     *
159     * inputs - pointer to server to send burst to
160     * output - NONE
161     * side effects - complete burst of channels/nicks is sent to client_p
162     */
163     static void
164     burst_all(struct Client *client_p)
165     {
166     dlink_node *ptr = NULL;
167    
168 michael 3944 DLINK_FOREACH(ptr, channel_list.head)
169 michael 3303 {
170     struct Channel *chptr = ptr->data;
171    
172     if (dlink_list_length(&chptr->members))
173     {
174     burst_members(client_p, chptr);
175     send_channel_modes(client_p, chptr);
176    
177     if (IsCapable(client_p, CAP_TBURST))
178     send_tb(client_p, chptr);
179     }
180     }
181    
182     /* also send out those that are not on any channel
183     */
184     DLINK_FOREACH(ptr, global_client_list.head)
185     {
186     struct Client *target_p = ptr->data;
187    
188     if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
189     sendnick_TS(client_p, target_p);
190    
191     DelFlag(target_p, FLAGS_BURSTED);
192     }
193    
194     if (IsCapable(client_p, CAP_EOB))
195     sendto_one(client_p, ":%s EOB", me.id);
196     }
197    
198     /* server_burst()
199     *
200     * inputs - struct Client pointer server
201     * -
202     * output - none
203     * side effects - send a server burst
204     * bugs - still too long
205     */
206     static void
207     server_burst(struct Client *client_p)
208     {
209     /* Send it in the shortened format with the TS, if
210     ** it's a TS server; walk the list of channels, sending
211     ** all the nicks that haven't been sent yet for each
212     ** channel, then send the channel itself -- it's less
213     ** obvious than sending all nicks first, but on the
214     ** receiving side memory will be allocated more nicely
215     ** saving a few seconds in the handling of a split
216     ** -orabidoo
217     */
218    
219     burst_all(client_p);
220    
221     /* EOB stuff is now in burst_all */
222     /* Always send a PING after connect burst is done */
223     sendto_one(client_p, "PING :%s", me.id);
224     }
225    
226     /* server_estab()
227     *
228     * inputs - pointer to a struct Client
229     * output -
230     * side effects -
231     */
232 michael 3306 static void
233 michael 3303 server_estab(struct Client *client_p)
234     {
235     struct MaskItem *conf = NULL;
236     dlink_node *ptr;
237 michael 4247 #if defined(HAVE_LIBCRYPTO) && !defined(OPENSSL_NO_COMP)
238 michael 3303 const COMP_METHOD *compression = NULL, *expansion = NULL;
239     #endif
240    
241     assert(client_p);
242    
243 michael 4595 if ((conf = find_conf_name(&client_p->connection->confs, client_p->name, CONF_SERVER))
244 michael 3303 == NULL)
245     {
246     /* This shouldn't happen, better tell the ops... -A1kmm */
247     sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
248     "Warning: Lost connect{} block "
249 michael 4595 "for server %s(this shouldn't happen)!", client_p->name);
250 michael 3303 exit_client(client_p, "Lost connect{} block!");
251     return;
252     }
253    
254 michael 4588 MyFree(client_p->connection->password);
255     client_p->connection->password = NULL;
256 michael 3303
257 michael 4298 /* Its got identd, since it's a server */
258 michael 3303 SetGotId(client_p);
259    
260     /* If there is something in the serv_list, it might be this
261     * connecting server..
262     */
263 michael 4340 if (!ConfigServerInfo.hub && local_server_list.head)
264 michael 3303 {
265 michael 4213 if (client_p != local_server_list.head->data || local_server_list.head->next)
266 michael 3303 {
267     ++ServerStats.is_ref;
268     sendto_one(client_p, "ERROR :I'm a leaf not a hub");
269     exit_client(client_p, "I'm a leaf");
270     return;
271     }
272     }
273    
274     if (IsUnknown(client_p))
275     {
276     sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
277    
278     send_capabilities(client_p, 0);
279    
280     sendto_one(client_p, "SERVER %s 1 :%s%s",
281     me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
282     }
283    
284 michael 4009 sendto_one(client_p, ":%s SVINFO %d %d 0 :%lu", me.id, TS_CURRENT, TS_MIN,
285 michael 3303 (unsigned long)CurrentTime);
286    
287     /* XXX Does this ever happen? I don't think so -db */
288     detach_conf(client_p, CONF_OPER);
289    
290     /* *WARNING*
291     ** In the following code in place of plain server's
292     ** name we send what is returned by get_client_name
293     ** which may add the "sockhost" after the name. It's
294     ** *very* *important* that there is a SPACE between
295     ** the name and sockhost (if present). The receiving
296     ** server will start the information field from this
297     ** first blank and thus puts the sockhost into info.
298     ** ...a bit tricky, but you have been warned, besides
299     ** code is more neat this way... --msa
300     */
301     client_p->servptr = &me;
302    
303     if (IsClosing(client_p))
304     return;
305    
306     SetServer(client_p);
307    
308     /* Some day, all these lists will be consolidated *sigh* */
309     dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
310    
311     assert(dlinkFind(&unknown_list, client_p));
312    
313 michael 4588 dlink_move_node(&client_p->connection->lclient_node,
314 michael 4213 &unknown_list, &local_server_list);
315 michael 3303
316     Count.myserver++;
317    
318 michael 4189 dlinkAdd(client_p, &client_p->node, &global_client_list);
319 michael 4209 dlinkAdd(client_p, make_dlink_node(), &global_server_list);
320 michael 3303 hash_add_client(client_p);
321     hash_add_id(client_p);
322    
323 michael 4581 /* Doesn't duplicate client_p->serv if allocated this struct already */
324 michael 3303 make_server(client_p);
325    
326 michael 4581 /* Fixing eob timings.. -gnp */
327 michael 4588 client_p->connection->firsttime = CurrentTime;
328 michael 3303
329     if (find_matching_name_conf(CONF_SERVICE, client_p->name, NULL, NULL, 0))
330     AddFlag(client_p, FLAGS_SERVICE);
331    
332     /* Show the real host/IP to admins */
333     #ifdef HAVE_LIBCRYPTO
334 michael 4588 if (client_p->connection->fd.ssl)
335 michael 3303 {
336 michael 4247 #ifndef OPENSSL_NO_COMP
337 michael 4588 compression = SSL_get_current_compression(client_p->connection->fd.ssl);
338     expansion = SSL_get_current_expansion(client_p->connection->fd.ssl);
339 michael 4247 #endif
340 michael 3303 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
341     "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
342 michael 4605 get_client_name(client_p, SHOW_IP), ssl_get_cipher(client_p->connection->fd.ssl),
343 michael 4247 #ifndef OPENSSL_NO_COMP
344 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
345     expansion ? SSL_COMP_get_name(expansion) : "NONE",
346 michael 4247 #else
347     "NONE", "NONE",
348     #endif
349 michael 3303 show_capabilities(client_p));
350     /* Now show the masked hostname/IP to opers */
351     sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
352     "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
353 michael 4605 get_client_name(client_p, MASK_IP), ssl_get_cipher(client_p->connection->fd.ssl),
354 michael 4247 #ifndef OPENSSL_NO_COMP
355 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
356     expansion ? SSL_COMP_get_name(expansion) : "NONE",
357 michael 4247 #else
358     "NONE", "NONE",
359     #endif
360 michael 3303 show_capabilities(client_p));
361     ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
362 michael 4605 get_client_name(client_p, SHOW_IP), ssl_get_cipher(client_p->connection->fd.ssl),
363 michael 4247 #ifndef OPENSSL_NO_COMP
364 michael 3303 compression ? SSL_COMP_get_name(compression) : "NONE",
365     expansion ? SSL_COMP_get_name(expansion) : "NONE",
366 michael 4247 #else
367     "NONE", "NONE",
368     #endif
369 michael 3303 show_capabilities(client_p));
370     }
371     else
372     #endif
373     {
374     sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
375     "Link with %s established: (Capabilities: %s)",
376 michael 4605 get_client_name(client_p, SHOW_IP), show_capabilities(client_p));
377 michael 3303 /* Now show the masked hostname/IP to opers */
378     sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
379     "Link with %s established: (Capabilities: %s)",
380 michael 4605 get_client_name(client_p, MASK_IP), show_capabilities(client_p));
381 michael 3303 ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
382 michael 4605 get_client_name(client_p, SHOW_IP), show_capabilities(client_p));
383 michael 3303 }
384    
385 michael 4588 fd_note(&client_p->connection->fd, "Server: %s", client_p->name);
386 michael 3303
387     sendto_server(client_p, NOCAPS, NOCAPS, ":%s SID %s 2 %s :%s%s",
388     me.id, client_p->name, client_p->id,
389     IsHidden(client_p) ? "(H) " : "", client_p->info);
390    
391     /*
392     * Pass on my client information to the new server
393     *
394     * First, pass only servers (idea is that if the link gets
395     * cancelled beacause the server was already there,
396     * there are no NICK's to be cancelled...). Of course,
397     * if cancellation occurs, all this info is sent anyway,
398     * and I guess the link dies when a read is attempted...? --msa
399     *
400     * Note: Link cancellation to occur at this point means
401     * that at least two servers from my fragment are building
402     * up connection this other fragment at the same time, it's
403     * a race condition, not the normal way of operation...
404     *
405     * ALSO NOTE: using the get_client_name for server names--
406     * see previous *WARNING*!!! (Also, original inpath
407     * is destroyed...)
408     */
409 michael 4209 DLINK_FOREACH_PREV(ptr, global_server_list.tail)
410 michael 3303 {
411     struct Client *target_p = ptr->data;
412    
413     /* target_p->from == target_p for target_p == client_p */
414     if (IsMe(target_p) || target_p->from == client_p)
415     continue;
416    
417     sendto_one(client_p, ":%s SID %s %d %s :%s%s",
418     target_p->servptr->id, target_p->name, target_p->hopcount+1,
419     target_p->id, IsHidden(target_p) ? "(H) " : "",
420     target_p->info);
421     }
422    
423     server_burst(client_p);
424     }
425    
426 michael 1997 /* set_server_gecos()
427     *
428     * input - pointer to client
429     * output - NONE
430     * side effects - servers gecos field is set
431     */
432     static void
433     set_server_gecos(struct Client *client_p, const char *info)
434     {
435     const char *s = info;
436 adx 30
437 michael 1997 /* check for (H) which is a hidden server */
438     if (!strncmp(s, "(H) ", 4))
439     {
440     SetHidden(client_p);
441     s = s + 4;
442     }
443    
444     if (!EmptyString(s))
445     strlcpy(client_p->info, s, sizeof(client_p->info));
446     else
447     strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
448     }
449    
450 adx 30 /* mr_server()
451 michael 3096 * parv[0] = command
452 adx 30 * parv[1] = servername
453 michael 3139 * parv[2] = hopcount
454 adx 30 * parv[3] = serverinfo
455     */
456 michael 2820 static int
457 michael 3156 mr_server(struct Client *source_p, int parc, char *parv[])
458 adx 30 {
459 michael 3246 char *name = NULL;
460     struct Client *target_p = NULL;
461 adx 30
462 michael 1178 if (EmptyString(parv[3]))
463 adx 30 {
464 michael 3156 sendto_one(source_p, "ERROR :No servername");
465 michael 3171 exit_client(source_p, "Wrong number of args");
466 michael 2820 return 0;
467 adx 30 }
468    
469     name = parv[1];
470    
471 michael 1118 /*
472     * Reject a direct nonTS server connection if we're TS_ONLY -orabidoo
473 adx 30 */
474 michael 3156 if (!DoesTS(source_p))
475 adx 30 {
476 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
477 michael 1118 "Unauthorized server connection attempt from %s: Non-TS server "
478 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
479 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
480 michael 1118 "Unauthorized server connection attempt from %s: Non-TS server "
481 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
482 michael 3171 exit_client(source_p, "Non-TS server");
483 michael 2820 return 0;
484 adx 30 }
485    
486 michael 1118 if (!valid_servname(name))
487 adx 30 {
488 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
489 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
490 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
491 michael 1624 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
492 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
493 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
494 michael 3171 exit_client(source_p, "Bogus server name");
495 michael 2820 return 0;
496 adx 30 }
497    
498 michael 3156 if (!valid_sid(source_p->id))
499 michael 3148 {
500     sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
501     "Link %s introduced server with bogus server ID %s",
502 michael 3156 get_client_name(source_p, SHOW_IP), source_p->id);
503 michael 3148 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
504     "Link %s introduced server with bogus server ID %s",
505 michael 3156 get_client_name(source_p, MASK_IP), source_p->id);
506     sendto_one(source_p, "ERROR :Bogus server ID introduced");
507 michael 4572 exit_client(source_p, "Bogus server ID introduced");
508 michael 3148 return 0;
509     }
510    
511 adx 30 /* Now we just have to call check_server and everything should
512     * be check for us... -A1kmm.
513     */
514 michael 3156 switch (check_server(name, source_p))
515 adx 30 {
516     case -1:
517 michael 4340 if (ConfigGeneral.warn_no_connect_block)
518 adx 30 {
519 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
520 adx 30 "Unauthorized server connection attempt from %s: No entry for "
521 michael 3156 "servername %s", get_client_name(source_p, HIDE_IP), name);
522 adx 30
523 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
524 adx 30 "Unauthorized server connection attempt from %s: No entry for "
525 michael 3156 "servername %s", get_client_name(source_p, MASK_IP), name);
526 adx 30 }
527    
528 michael 3171 exit_client(source_p, "No connect{} block.");
529 michael 2820 return 0;
530 adx 30 /* NOT REACHED */
531     break;
532    
533     case -2:
534 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
535 adx 30 "Unauthorized server connection attempt from %s: Bad password "
536 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
537 adx 30
538 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
539 adx 30 "Unauthorized server connection attempt from %s: Bad password "
540 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
541 adx 30
542 michael 3171 exit_client(source_p, "Invalid password.");
543 michael 2820 return 0;
544 adx 30 /* NOT REACHED */
545     break;
546    
547     case -3:
548 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
549 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
550 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
551 adx 30
552 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
553 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
554 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
555 adx 30
556 michael 3171 exit_client(source_p, "Invalid host.");
557 michael 2820 return 0;
558 michael 2228 case -4:
559     sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
560     "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
561 michael 3156 "for server %s", get_client_name(source_p, HIDE_IP), name);
562 michael 2228
563     sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
564     "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
565 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
566 michael 2228
567 michael 3171 exit_client(source_p, "Invalid certificate fingerprint.");
568 michael 2820 return 0;
569 adx 30 /* NOT REACHED */
570     break;
571     }
572    
573 michael 2976 if ((target_p = hash_find_server(name)))
574 adx 30 {
575     /* This link is trying feed me a server that I already have
576     * access through another path -- multiple paths not accepted
577     * currently, kill this link immediately!!
578     *
579     * Rather than KILL the link which introduced it, KILL the
580     * youngest of the two links. -avalon
581     *
582     * Definitely don't do that here. This is from an unregistered
583     * connect - A1kmm.
584     */
585 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
586 michael 2976 "Attempt to re-introduce server %s from %s",
587 michael 3156 name, get_client_name(source_p, HIDE_IP));
588 michael 2976 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
589     "Attempt to re-introduce server %s from %s",
590 michael 3156 name, get_client_name(source_p, MASK_IP));
591     sendto_one(source_p, "ERROR :Server already exists.");
592 michael 3171 exit_client(source_p, "Server already exists");
593 michael 2976 return 0;
594     }
595    
596 michael 3156 if ((target_p = hash_find_id(source_p->id)))
597 michael 2976 {
598     sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
599 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
600 michael 3156 name, source_p->id,
601     get_client_name(source_p, HIDE_IP));
602 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
603 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
604 michael 3156 name, source_p->id,
605     get_client_name(source_p, MASK_IP));
606     sendto_one(source_p, "ERROR :Server ID already exists.");
607 michael 3171 exit_client(source_p, "Server ID already exists");
608 michael 2820 return 0;
609 adx 30 }
610    
611     /* XXX If somehow there is a connect in progress and
612     * a connect comes in with same name toss the pending one,
613     * but only if it's not the same client! - Dianora
614     */
615     if ((target_p = find_servconn_in_progress(name)))
616 michael 3156 if (target_p != source_p)
617 michael 3171 exit_client(target_p, "Overridden");
618 adx 30
619     /* if we are connecting (Handshake), we already have the name from the
620 michael 3156 * connect{} block in source_p->name
621 adx 30 */
622 michael 3156 strlcpy(source_p->name, name, sizeof(source_p->name));
623     set_server_gecos(source_p, parv[3]);
624 michael 3190 source_p->hopcount = atoi(parv[2]);
625 michael 3156 server_estab(source_p);
626 michael 2820 return 0;
627 adx 30 }
628    
629     /* ms_sid()
630 michael 3096 * parv[0] = command
631 adx 30 * parv[1] = servername
632 michael 3139 * parv[2] = hopcount
633 adx 30 * parv[3] = sid of new server
634     * parv[4] = serverinfo
635     */
636 michael 2820 static int
637 michael 3156 ms_sid(struct Client *source_p, int parc, char *parv[])
638 adx 30 {
639 michael 3139 dlink_node *ptr = NULL;
640     struct Client *target_p = NULL;
641 michael 3156 struct Client *client_p = source_p->from; /* XXX */
642 michael 3139 const struct MaskItem *conf = NULL;
643 adx 30 int hlined = 0;
644     int llined = 0;
645    
646     /* Just to be sure -A1kmm. */
647     if (!IsServer(source_p))
648 michael 2820 return 0;
649 adx 30
650 michael 1178 if (EmptyString(parv[4]))
651 michael 1118 {
652     sendto_one(client_p, "ERROR :No servername");
653 michael 2820 return 0;
654 michael 1118 }
655 adx 30
656 michael 1118 if (!valid_servname(parv[1]))
657     {
658 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
659 michael 1118 "Link %s introduced server with bogus server name %s",
660     get_client_name(client_p, SHOW_IP), parv[1]);
661 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
662 michael 1118 "Link %s introduced server with bogus server name %s",
663     get_client_name(client_p, MASK_IP), parv[1]);
664     sendto_one(client_p, "ERROR :Bogus server name introduced");
665 michael 4572 exit_client(client_p, "Bogus server name introduced");
666 michael 2820 return 0;
667 michael 1118 }
668    
669     if (!valid_sid(parv[3]))
670     {
671 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
672 michael 1118 "Link %s introduced server with bogus server ID %s",
673     get_client_name(client_p, SHOW_IP), parv[3]);
674 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
675 michael 1118 "Link %s introduced server with bogus server ID %s",
676     get_client_name(client_p, MASK_IP), parv[3]);
677     sendto_one(client_p, "ERROR :Bogus server ID introduced");
678 michael 4572 exit_client(client_p, "Bogus server ID introduced");
679 michael 2820 return 0;
680 michael 1118 }
681    
682 adx 30 /* collision on SID? */
683 michael 1118 if ((target_p = hash_find_id(parv[3])))
684 adx 30 {
685 michael 1118 sendto_one(client_p, "ERROR :SID %s already exists", parv[3]);
686 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
687 michael 2820 "Link %s cancelled, SID %s already exists",
688 michael 1118 get_client_name(client_p, SHOW_IP), parv[3]);
689 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
690 michael 2820 "Link %s cancelled, SID %s already exists",
691 michael 1118 client_p->name, parv[3]);
692 michael 3171 exit_client(client_p, "SID Exists");
693 michael 2820 return 0;
694 adx 30 }
695    
696     /* collision on name? */
697 michael 1169 if ((target_p = hash_find_server(parv[1])))
698 adx 30 {
699 michael 1118 sendto_one(client_p, "ERROR :Server %s already exists", parv[1]);
700 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
701 michael 2820 "Link %s cancelled, server %s already exists",
702 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
703 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
704 michael 2820 "Link %s cancelled, server %s already exists",
705 michael 1118 client_p->name, parv[1]);
706 michael 3171 exit_client(client_p, "Server Exists");
707 michael 2820 return 0;
708 adx 30 }
709    
710     /* XXX If somehow there is a connect in progress and
711     * a connect comes in with same name toss the pending one,
712     * but only if it's not the same client! - Dianora
713     */
714 michael 1118 if ((target_p = find_servconn_in_progress(parv[1])))
715 adx 30 if (target_p != client_p)
716 michael 3171 exit_client(target_p, "Overridden");
717 adx 30
718 michael 4588 conf = client_p->connection->confs.head->data;
719 michael 1384
720 adx 30 /* See if the newly found server is behind a guaranteed
721     * leaf. If so, close the link.
722     */
723 michael 1632 DLINK_FOREACH(ptr, conf->leaf_list.head)
724 michael 3139 {
725 michael 1652 if (!match(ptr->data, parv[1]))
726 michael 1529 {
727     llined = 1;
728     break;
729     }
730 michael 3139 }
731 adx 30
732 michael 1632 DLINK_FOREACH(ptr, conf->hub_list.head)
733 michael 3139 {
734 michael 1652 if (!match(ptr->data, parv[1]))
735 michael 1529 {
736     hlined = 1;
737     break;
738     }
739 michael 3139 }
740 michael 1118
741 adx 30 /* Ok, this way this works is
742     *
743     * A server can have a CONF_HUB allowing it to introduce servers
744     * behind it.
745     *
746     * connect {
747     * name = "irc.bighub.net";
748     * hub_mask="*";
749     * ...
750 michael 2820 *
751 adx 30 * That would allow "irc.bighub.net" to introduce anything it wanted..
752     *
753     * However
754     *
755     * connect {
756     * name = "irc.somehub.fi";
757     * hub_mask="*";
758     * leaf_mask="*.edu";
759     *...
760     * Would allow this server in finland to hub anything but
761     * .edu's
762     */
763    
764     /* Ok, check client_p can hub the new server, and make sure it's not a LL */
765 michael 885 if (!hlined)
766 adx 30 {
767     /* OOOPs nope can't HUB */
768 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
769     "Non-Hub link %s introduced %s.",
770 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
771 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
772     "Non-Hub link %s introduced %s.",
773 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
774 michael 3171 exit_client(source_p, "No matching hub_mask.");
775 michael 2820 return 0;
776 adx 30 }
777    
778     /* Check for the new server being leafed behind this HUB */
779     if (llined)
780     {
781     /* OOOPs nope can't HUB this leaf */
782 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
783 michael 2820 "Link %s introduced leafed server %s.",
784 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
785 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
786 michael 2820 "Link %s introduced leafed server %s.",
787 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
788 michael 3171 exit_client(client_p, "Leafed Server.");
789 michael 2820 return 0;
790 adx 30 }
791    
792     target_p = make_client(client_p);
793     make_server(target_p);
794 michael 3190 target_p->hopcount = atoi(parv[2]);
795 michael 1118 target_p->servptr = source_p;
796 adx 30
797 michael 1118 strlcpy(target_p->name, parv[1], sizeof(target_p->name));
798     strlcpy(target_p->id, parv[3], sizeof(target_p->id));
799 adx 30
800 michael 1533 set_server_gecos(target_p, parv[4]);
801 adx 30 SetServer(target_p);
802    
803 michael 1632 if (HasFlag(source_p, FLAGS_SERVICE) || find_matching_name_conf(CONF_SERVICE, target_p->name, NULL, NULL, 0))
804 michael 1219 AddFlag(target_p, FLAGS_SERVICE);
805 michael 1157
806 michael 1118 dlinkAdd(target_p, &target_p->node, &global_client_list);
807 michael 4209 dlinkAdd(target_p, make_dlink_node(), &global_server_list);
808 michael 1118 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
809 adx 30
810     hash_add_client(target_p);
811     hash_add_id(target_p);
812    
813 michael 3135 sendto_server(client_p, NOCAPS, NOCAPS, ":%s SID %s %d %s :%s%s",
814 michael 3192 source_p->id, target_p->name, target_p->hopcount + 1,
815 michael 1527 target_p->id, IsHidden(target_p) ? "(H) " : "", target_p->info);
816 michael 1618 sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
817 michael 1118 "Server %s being introduced by %s",
818 adx 30 target_p->name, source_p->name);
819 michael 2820 return 0;
820 adx 30 }
821    
822 michael 2820 static struct Message server_msgtab =
823     {
824 michael 4545 "SERVER", NULL, 0, 0, 4, MAXPARA, MFLG_SLOW, 0,
825 michael 3135 { mr_server, m_registered, m_ignore, m_ignore, m_registered, m_ignore }
826 michael 1230 };
827    
828 michael 2820 static struct Message sid_msgtab =
829     {
830 michael 4545 "SID", NULL, 0, 0, 5, MAXPARA, MFLG_SLOW, 0,
831 michael 2820 { m_ignore, m_ignore, ms_sid, m_ignore, m_ignore, m_ignore }
832 michael 1230 };
833    
834     static void
835     module_init(void)
836     {
837     mod_add_cmd(&sid_msgtab);
838     mod_add_cmd(&server_msgtab);
839     }
840    
841     static void
842     module_exit(void)
843     {
844     mod_del_cmd(&sid_msgtab);
845     mod_del_cmd(&server_msgtab);
846     }
847    
848 michael 2820 struct module module_entry =
849     {
850 michael 1230 .node = { NULL, NULL, NULL },
851     .name = NULL,
852     .version = "$Revision$",
853     .handle = NULL,
854     .modinit = module_init,
855     .modexit = module_exit,
856     .flags = MODULE_FLAG_CORE
857     };

Properties

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