ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 5881
Committed: Sun May 3 16:04:15 2015 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 27478 byte(s)
Log Message:
- Use C99-style initializers in all struct Message items
- Removed MFLG_SLOW
- Removed DUMMY_HANDLER

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

Properties

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