ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/core/m_server.c
Revision: 7962
Committed: Mon Mar 13 18:48:59 2017 UTC (7 years ago) by michael
Content type: text/x-csrc
File size: 27521 byte(s)
Log Message:
- No longer put servers on the 'global_client_list'. This was just bad.

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 7925 * Copyright (c) 1997-2017 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 4564 * 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 michael 6160 #include "id.h"
33 michael 2820 #include "irc_string.h"
34     #include "ircd.h"
35     #include "numeric.h"
36     #include "conf.h"
37 michael 7247 #include "conf_service.h"
38 michael 2820 #include "log.h"
39 michael 3347 #include "misc.h"
40     #include "server.h"
41     #include "user.h"
42 michael 2820 #include "send.h"
43 adx 30 #include "parse.h"
44 michael 3303 #include "memory.h"
45 adx 30 #include "modules.h"
46    
47    
48 michael 7106 /*! Parses server flags to be potentially set
49     * \param client_p Pointer to server's Client structure
50     * \param flags Pointer to the flag string to be parsed
51     */
52     static void
53     server_set_flags(struct Client *client_p, const char *flags)
54     {
55     const unsigned char *p = (const unsigned char *)flags;
56    
57     if (*p != '+')
58     return;
59    
60     while (*++p)
61     {
62     switch (*p)
63     {
64     case 'h':
65     AddFlag(client_p, FLAGS_HIDDEN);
66     break;
67     default:
68     break;
69     }
70     }
71     }
72    
73 michael 3303 /*
74     * send_tb
75     *
76     * inputs - pointer to Client
77     * - pointer to channel
78     * output - NONE
79     * side effects - Called on a server burst when
80 michael 6353 * server is CAPAB_TBURST capable
81 michael 3303 */
82     static void
83 michael 7554 server_send_tburst(struct Client *client_p, const struct Channel *chptr)
84 michael 3303 {
85     /*
86     * We may also send an empty topic here, but only if topic_time isn't 0,
87     * i.e. if we had a topic that got unset. This is required for syncing
88     * topics properly.
89     *
90     * Imagine the following scenario: Our downlink introduces a channel
91     * to us with a TS that is equal to ours, but the channel topic on
92     * their side got unset while the servers were in splitmode, which means
93     * their 'topic' is newer. They simply wanted to unset it, so we have to
94     * deal with it in a more sophisticated fashion instead of just resetting
95     * it to their old topic they had before. Read m_tburst.c:ms_tburst
96     * for further information -Michael
97     */
98     if (chptr->topic_time)
99 michael 6781 sendto_one(client_p, ":%s TBURST %ju %s %ju %s :%s", me.id,
100     chptr->creationtime, chptr->name,
101     chptr->topic_time,
102 michael 3303 chptr->topic_info,
103     chptr->topic);
104     }
105    
106     /* sendnick_TS()
107     *
108     * inputs - client (server) to send nick towards
109     * - client to send nick for
110     * output - NONE
111     * side effects - NICK message is sent towards given client_p
112     */
113 michael 3306 static void
114 michael 7554 server_send_client(struct Client *client_p, struct Client *target_p)
115 michael 3303 {
116 michael 5559 dlink_node *node = NULL;
117 michael 3303 char ubuf[IRCD_BUFSIZE] = "";
118    
119 michael 7962 assert(IsClient(target_p));
120 michael 3303
121 michael 7598 send_umode(target_p, 0, 0, ubuf);
122 michael 3303
123     if (ubuf[0] == '\0')
124     {
125     ubuf[0] = '+';
126     ubuf[1] = '\0';
127     }
128    
129 michael 6921 sendto_one(client_p, ":%s UID %s %u %ju %s %s %s %s %s %s :%s",
130     target_p->servptr->id,
131     target_p->name, target_p->hopcount + 1,
132     target_p->tsinfo,
133     ubuf, target_p->username, target_p->host,
134     target_p->sockhost, target_p->id,
135     target_p->account, target_p->info);
136 michael 3303
137     if (!EmptyString(target_p->certfp))
138     sendto_one(client_p, ":%s CERTFP %s", target_p->id, target_p->certfp);
139    
140     if (target_p->away[0])
141     sendto_one(client_p, ":%s AWAY :%s", target_p->id, target_p->away);
142    
143 michael 5559
144     DLINK_FOREACH(node, target_p->svstags.head)
145     {
146     const struct ServicesTag *svstag = node->data;
147     char *m = ubuf;
148    
149     for (const struct user_modes *tab = umode_tab; tab->c; ++tab)
150     if (svstag->umodes & tab->flag)
151     *m++ = tab->c;
152     *m = '\0';
153    
154 michael 6781 sendto_one(client_p, ":%s SVSTAG %s %ju %u +%s :%s", me.id, target_p->id,
155 michael 5559 target_p->tsinfo, svstag->numeric, ubuf, svstag->tag);
156     }
157 michael 3303 }
158    
159 michael 7554 /* burst_all()
160 michael 3303 *
161 michael 7554 * inputs - pointer to server to send burst to
162 michael 3303 * output - NONE
163 michael 7554 * side effects - complete burst of channels/nicks is sent to client_p
164 michael 3303 */
165     static void
166 michael 7554 server_burst(struct Client *client_p)
167 michael 3303 {
168 michael 4816 dlink_node *node = NULL;
169 michael 3303
170 michael 7554 DLINK_FOREACH(node, global_client_list.head)
171 michael 3303 {
172 michael 7554 struct Client *target_p = node->data;
173 michael 3303
174 michael 7554 if (target_p->from != client_p)
175     server_send_client(client_p, target_p);
176 michael 3303 }
177    
178 michael 4816 DLINK_FOREACH(node, channel_list.head)
179 michael 3303 {
180 michael 4816 struct Channel *chptr = node->data;
181 michael 3303
182     if (dlink_list_length(&chptr->members))
183     {
184 michael 6374 channel_send_modes(client_p, chptr);
185 michael 3303
186 michael 6353 if (IsCapable(client_p, CAPAB_TBURST))
187 michael 7554 server_send_tburst(client_p, chptr);
188 michael 3303 }
189     }
190    
191     /* Always send a PING after connect burst is done */
192     sendto_one(client_p, "PING :%s", me.id);
193     }
194    
195     /* server_estab()
196     *
197     * inputs - pointer to a struct Client
198     * output -
199     * side effects -
200     */
201 michael 3306 static void
202 michael 3303 server_estab(struct Client *client_p)
203     {
204     struct MaskItem *conf = NULL;
205 michael 4816 dlink_node *node = NULL;
206 michael 3303
207 michael 6434 if ((conf = find_conf_name(&client_p->connection->confs, client_p->name, CONF_SERVER)) == NULL)
208 michael 3303 {
209     /* This shouldn't happen, better tell the ops... -A1kmm */
210 michael 6434 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
211     "Warning: lost connect{} block for %s",
212     get_client_name(client_p, SHOW_IP));
213     sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
214     "Warning: lost connect{} block for %s",
215     get_client_name(client_p, MASK_IP));
216 michael 3303 exit_client(client_p, "Lost connect{} block!");
217     return;
218     }
219    
220 michael 7033 xfree(client_p->connection->password);
221 michael 4589 client_p->connection->password = NULL;
222 michael 3303
223 michael 4613 if (!ConfigServerInfo.hub && dlink_list_length(&local_server_list))
224 michael 3303 {
225 michael 4613 ++ServerStats.is_ref;
226     exit_client(client_p, "I'm a leaf not a hub");
227     return;
228 michael 3303 }
229    
230     if (IsUnknown(client_p))
231     {
232 michael 7356 sendto_one(client_p, "PASS %s TS %u %s", conf->spasswd, TS_CURRENT, me.id);
233 michael 3303
234 michael 7589 sendto_one(client_p, "CAPAB :%s", get_capabilities(NULL));
235 michael 3303
236     sendto_one(client_p, "SERVER %s 1 :%s%s",
237     me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
238     }
239    
240 michael 7356 sendto_one(client_p, ":%s SVINFO %u %u 0 :%ju", me.id, TS_CURRENT, TS_MIN,
241 michael 6781 CurrentTime);
242 michael 3303
243     /* *WARNING*
244     ** In the following code in place of plain server's
245     ** name we send what is returned by get_client_name
246     ** which may add the "sockhost" after the name. It's
247     ** *very* *important* that there is a SPACE between
248     ** the name and sockhost (if present). The receiving
249     ** server will start the information field from this
250     ** first blank and thus puts the sockhost into info.
251     ** ...a bit tricky, but you have been warned, besides
252     ** code is more neat this way... --msa
253     */
254     client_p->servptr = &me;
255    
256 michael 6471 if (HasFlag(client_p, FLAGS_CLOSING))
257 michael 3303 return;
258    
259     SetServer(client_p);
260    
261     /* Some day, all these lists will be consolidated *sigh* */
262     dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
263    
264     assert(dlinkFind(&unknown_list, client_p));
265    
266 michael 4589 dlink_move_node(&client_p->connection->lclient_node,
267 michael 4212 &unknown_list, &local_server_list);
268 michael 3303
269     Count.myserver++;
270    
271 michael 7962 dlinkAdd(client_p, &client_p->node, &global_server_list);
272 michael 3303 hash_add_client(client_p);
273     hash_add_id(client_p);
274    
275 michael 4580 /* Doesn't duplicate client_p->serv if allocated this struct already */
276 michael 3303 make_server(client_p);
277    
278 michael 4580 /* Fixing eob timings.. -gnp */
279 michael 4589 client_p->connection->firsttime = CurrentTime;
280 michael 3303
281 michael 7247 if (service_find(client_p->name))
282 michael 3303 AddFlag(client_p, FLAGS_SERVICE);
283    
284     /* Show the real host/IP to admins */
285 michael 7106 if (tls_isusing(&client_p->connection->fd.ssl))
286 michael 3303 {
287 michael 7106 /* Show the real host/IP to admins */
288 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
289 michael 7106 "Link with %s established: [TLS: %s] (Capabilities: %s)",
290     get_client_name(client_p, SHOW_IP), tls_get_cipher(&client_p->connection->fd.ssl),
291 michael 7589 get_capabilities(client_p));
292 michael 7106
293 michael 3303 /* Now show the masked hostname/IP to opers */
294 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
295 michael 7106 "Link with %s established: [TLS: %s] (Capabilities: %s)",
296     get_client_name(client_p, MASK_IP), tls_get_cipher(&client_p->connection->fd.ssl),
297 michael 7589 get_capabilities(client_p));
298 michael 7106 ilog(LOG_TYPE_IRCD, "Link with %s established: [TLS: %s] (Capabilities: %s)",
299     get_client_name(client_p, SHOW_IP), tls_get_cipher(&client_p->connection->fd.ssl),
300 michael 7589 get_capabilities(client_p));
301 michael 3303 }
302     else
303     {
304 michael 7106 /* Show the real host/IP to admins */
305 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
306 michael 3303 "Link with %s established: (Capabilities: %s)",
307 michael 7589 get_client_name(client_p, SHOW_IP), get_capabilities(client_p));
308 michael 3303 /* Now show the masked hostname/IP to opers */
309 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
310 michael 3303 "Link with %s established: (Capabilities: %s)",
311 michael 7589 get_client_name(client_p, MASK_IP), get_capabilities(client_p));
312 michael 3303 ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
313 michael 7589 get_client_name(client_p, SHOW_IP), get_capabilities(client_p));
314 michael 3303 }
315    
316 michael 4589 fd_note(&client_p->connection->fd, "Server: %s", client_p->name);
317 michael 3303
318 michael 4963 sendto_server(client_p, 0, 0, ":%s SID %s 2 %s :%s%s",
319 michael 3303 me.id, client_p->name, client_p->id,
320     IsHidden(client_p) ? "(H) " : "", client_p->info);
321    
322     /*
323     * Pass on my client information to the new server
324     *
325     * First, pass only servers (idea is that if the link gets
326     * cancelled beacause the server was already there,
327     * there are no NICK's to be cancelled...). Of course,
328     * if cancellation occurs, all this info is sent anyway,
329     * and I guess the link dies when a read is attempted...? --msa
330     *
331     * Note: Link cancellation to occur at this point means
332     * that at least two servers from my fragment are building
333     * up connection this other fragment at the same time, it's
334     * a race condition, not the normal way of operation...
335     */
336 michael 4816 DLINK_FOREACH_PREV(node, global_server_list.tail)
337 michael 3303 {
338 michael 4816 struct Client *target_p = node->data;
339 michael 3303
340     /* target_p->from == target_p for target_p == client_p */
341     if (IsMe(target_p) || target_p->from == client_p)
342     continue;
343    
344 michael 5785 sendto_one(client_p, ":%s SID %s %u %s :%s%s",
345 michael 3303 target_p->servptr->id, target_p->name, target_p->hopcount+1,
346     target_p->id, IsHidden(target_p) ? "(H) " : "",
347     target_p->info);
348     }
349    
350     server_burst(client_p);
351 michael 4710
352 michael 6353 if (IsCapable(client_p, CAPAB_EOB))
353 michael 4710 {
354 michael 4816 DLINK_FOREACH_PREV(node, global_server_list.tail)
355 michael 4710 {
356 michael 4816 struct Client *target_p = node->data;
357 michael 4710
358     if (target_p->from == client_p)
359     continue;
360    
361     if (IsMe(target_p) || HasFlag(target_p, FLAGS_EOB))
362     sendto_one(client_p, ":%s EOB", target_p->id);
363     }
364     }
365 michael 3303 }
366    
367 michael 1997 /* set_server_gecos()
368     *
369     * input - pointer to client
370     * output - NONE
371     * side effects - servers gecos field is set
372     */
373     static void
374 michael 7106 server_set_gecos(struct Client *client_p, const char *info)
375 michael 1997 {
376     const char *s = info;
377 adx 30
378 michael 1997 /* check for (H) which is a hidden server */
379     if (!strncmp(s, "(H) ", 4))
380     {
381 michael 6314 AddFlag(client_p, FLAGS_HIDDEN);
382 michael 1997 s = s + 4;
383     }
384    
385     if (!EmptyString(s))
386     strlcpy(client_p->info, s, sizeof(client_p->info));
387     else
388     strlcpy(client_p->info, "(Unknown Location)", sizeof(client_p->info));
389     }
390    
391 michael 7950 static int
392     server_check(const char *name, struct Client *client_p)
393     {
394     dlink_node *node = NULL;
395     struct MaskItem *server_conf = NULL;
396     int error = -1;
397    
398     assert(client_p);
399    
400     /* Loop through looking for all possible connect items that might work */
401     DLINK_FOREACH(node, connect_items.head)
402     {
403     struct MaskItem *conf = node->data;
404    
405     if (irccmp(name, conf->name))
406     continue;
407    
408     error = -3;
409    
410     if (!irccmp(conf->host, client_p->host) ||
411     !irccmp(conf->host, client_p->sockhost))
412     {
413     error = -2;
414    
415     if (!match_conf_password(client_p->connection->password, conf))
416     return -2;
417    
418     if (!EmptyString(conf->certfp))
419     if (EmptyString(client_p->certfp) || strcasecmp(client_p->certfp, conf->certfp))
420     return -4;
421    
422     server_conf = conf;
423     }
424     }
425    
426     if (server_conf == NULL)
427     return error;
428    
429     attach_conf(client_p, server_conf);
430    
431     switch (server_conf->aftype)
432     {
433     case AF_INET6:
434     {
435     const struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)&server_conf->addr;
436    
437     if (IN6_IS_ADDR_UNSPECIFIED(&v6->sin6_addr))
438     memcpy(&server_conf->addr, &client_p->connection->ip, sizeof(struct irc_ssaddr));
439     break;
440     }
441     case AF_INET:
442     {
443     const struct sockaddr_in *v4 = (struct sockaddr_in *)&server_conf->addr;
444    
445     if (v4->sin_addr.s_addr == INADDR_NONE)
446     memcpy(&server_conf->addr, &client_p->connection->ip, sizeof(struct irc_ssaddr));
447     break;
448     }
449     }
450    
451     return 0;
452     }
453    
454 adx 30 /* mr_server()
455 michael 3096 * parv[0] = command
456 adx 30 * parv[1] = servername
457 michael 3139 * parv[2] = hopcount
458 adx 30 * parv[3] = serverinfo
459 michael 7106 *
460     * 8.3.x+:
461     * parv[0] = command
462     * parv[1] = servername
463     * parv[2] = hopcount
464     * parv[3] = sid
465     * parv[4] = string of flags starting with '+'
466     * parv[5] = serverinfo
467 adx 30 */
468 michael 2820 static int
469 michael 3156 mr_server(struct Client *source_p, int parc, char *parv[])
470 adx 30 {
471 michael 4754 const char *name = parv[1];
472 michael 7106 const char *sid = parc == 6 ? parv[3] : source_p->id; /* TBR: compatibility 'mode' */
473 michael 3246 struct Client *target_p = NULL;
474 adx 30
475 michael 4658 if (EmptyString(parv[parc - 1]))
476 adx 30 {
477 michael 4610 exit_client(source_p, "No server description supplied");
478 michael 2820 return 0;
479 adx 30 }
480    
481 michael 1118 if (!valid_servname(name))
482 adx 30 {
483 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
484 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
485 michael 6426 "for server %s", get_client_name(source_p, SHOW_IP), name);
486 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
487 michael 1118 "Unauthorized server connection attempt from %s: Bogus server name "
488 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
489 michael 3171 exit_client(source_p, "Bogus server name");
490 michael 2820 return 0;
491 adx 30 }
492    
493 michael 7106 if (!valid_sid(sid))
494 michael 3148 {
495 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
496 michael 3148 "Link %s introduced server with bogus server ID %s",
497 michael 7106 get_client_name(source_p, SHOW_IP), sid);
498 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
499 michael 3148 "Link %s introduced server with bogus server ID %s",
500 michael 7106 get_client_name(source_p, MASK_IP), sid);
501 michael 4571 exit_client(source_p, "Bogus server ID introduced");
502 michael 3148 return 0;
503     }
504    
505 michael 7950 /* Now we just have to call server_check() and everything should
506 adx 30 * be check for us... -A1kmm.
507     */
508 michael 7950 switch (server_check(name, source_p))
509 adx 30 {
510     case -1:
511 michael 4341 if (ConfigGeneral.warn_no_connect_block)
512 adx 30 {
513 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
514 adx 30 "Unauthorized server connection attempt from %s: No entry for "
515 michael 6426 "servername %s", get_client_name(source_p, SHOW_IP), name);
516 adx 30
517 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
518 adx 30 "Unauthorized server connection attempt from %s: No entry for "
519 michael 3156 "servername %s", get_client_name(source_p, MASK_IP), name);
520 adx 30 }
521    
522 michael 4610 exit_client(source_p, "No connect {} block.");
523 michael 2820 return 0;
524 adx 30 /* NOT REACHED */
525     break;
526    
527     case -2:
528 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
529 adx 30 "Unauthorized server connection attempt from %s: Bad password "
530 michael 6426 "for server %s", get_client_name(source_p, SHOW_IP), name);
531 adx 30
532 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
533 adx 30 "Unauthorized server connection attempt from %s: Bad password "
534 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
535 adx 30
536 michael 3171 exit_client(source_p, "Invalid password.");
537 michael 2820 return 0;
538 adx 30 /* NOT REACHED */
539     break;
540    
541     case -3:
542 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
543 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
544 michael 6426 "for server %s", get_client_name(source_p, SHOW_IP), name);
545 adx 30
546 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
547 adx 30 "Unauthorized server connection attempt from %s: Invalid host "
548 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
549 adx 30
550 michael 3171 exit_client(source_p, "Invalid host.");
551 michael 2820 return 0;
552 michael 2228 case -4:
553 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
554 michael 2228 "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
555 michael 6426 "for server %s", get_client_name(source_p, SHOW_IP), name);
556 michael 2228
557 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
558 michael 2228 "Unauthorized server connection attempt from %s: Invalid certificate fingerprint "
559 michael 3156 "for server %s", get_client_name(source_p, MASK_IP), name);
560 michael 2228
561 michael 3171 exit_client(source_p, "Invalid certificate fingerprint.");
562 michael 2820 return 0;
563 adx 30 /* NOT REACHED */
564     break;
565     }
566    
567 michael 2976 if ((target_p = hash_find_server(name)))
568 adx 30 {
569     /* This link is trying feed me a server that I already have
570     * access through another path -- multiple paths not accepted
571     * currently, kill this link immediately!!
572     *
573     * Rather than KILL the link which introduced it, KILL the
574     * youngest of the two links. -avalon
575     *
576     * Definitely don't do that here. This is from an unregistered
577     * connect - A1kmm.
578     */
579 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
580 michael 2976 "Attempt to re-introduce server %s from %s",
581 michael 6426 name, get_client_name(source_p, SHOW_IP));
582 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
583 michael 2976 "Attempt to re-introduce server %s from %s",
584 michael 3156 name, get_client_name(source_p, MASK_IP));
585 michael 3171 exit_client(source_p, "Server already exists");
586 michael 2976 return 0;
587     }
588    
589 michael 3156 if ((target_p = hash_find_id(source_p->id)))
590 michael 2976 {
591 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
592 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
593 michael 3156 name, source_p->id,
594 michael 6426 get_client_name(source_p, SHOW_IP));
595 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
596 michael 2820 "Attempt to re-introduce server %s SID %s from %s",
597 michael 3156 name, source_p->id,
598     get_client_name(source_p, MASK_IP));
599 michael 3171 exit_client(source_p, "Server ID already exists");
600 michael 2820 return 0;
601 adx 30 }
602    
603     /* XXX If somehow there is a connect in progress and
604     * a connect comes in with same name toss the pending one,
605     * but only if it's not the same client! - Dianora
606     */
607     if ((target_p = find_servconn_in_progress(name)))
608 michael 3156 if (target_p != source_p)
609 michael 3171 exit_client(target_p, "Overridden");
610 adx 30
611     /* if we are connecting (Handshake), we already have the name from the
612 michael 3156 * connect{} block in source_p->name
613 adx 30 */
614 michael 3156 strlcpy(source_p->name, name, sizeof(source_p->name));
615 michael 7106
616     if (parc == 6) /* TBR: compatibility 'mode' */
617     {
618     strlcpy(source_p->id, sid, sizeof(source_p->id));
619     strlcpy(source_p->info, parv[parc - 1], sizeof(source_p->info));
620     server_set_flags(source_p, parv[4]);
621     }
622     else
623     server_set_gecos(source_p, parv[parc - 1]);
624    
625 michael 3190 source_p->hopcount = atoi(parv[2]);
626 michael 3156 server_estab(source_p);
627 michael 2820 return 0;
628 adx 30 }
629    
630     /* ms_sid()
631 michael 3096 * parv[0] = command
632 adx 30 * parv[1] = servername
633 michael 3139 * parv[2] = hopcount
634 adx 30 * parv[3] = sid of new server
635     * parv[4] = serverinfo
636 michael 7106 *
637     * 8.3.x+:
638     * parv[0] = command
639     * parv[1] = servername
640     * parv[2] = hopcount
641     * parv[3] = sid of new server
642     * parv[4] = string of flags starting with '+'
643     * parv[5] = serverinfo
644 adx 30 */
645 michael 2820 static int
646 michael 3156 ms_sid(struct Client *source_p, int parc, char *parv[])
647 adx 30 {
648 michael 4816 dlink_node *node = NULL;
649 michael 3139 struct Client *target_p = NULL;
650 michael 3156 struct Client *client_p = source_p->from; /* XXX */
651 michael 3139 const struct MaskItem *conf = NULL;
652 adx 30 int hlined = 0;
653     int llined = 0;
654    
655     /* Just to be sure -A1kmm. */
656     if (!IsServer(source_p))
657 michael 2820 return 0;
658 adx 30
659 michael 4658 if (EmptyString(parv[parc - 1]))
660 michael 1118 {
661 michael 4610 exit_client(client_p, "No server description supplied");
662 michael 2820 return 0;
663 michael 1118 }
664 adx 30
665 michael 1118 if (!valid_servname(parv[1]))
666     {
667 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
668 michael 1118 "Link %s introduced server with bogus server name %s",
669     get_client_name(client_p, SHOW_IP), parv[1]);
670 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
671 michael 1118 "Link %s introduced server with bogus server name %s",
672     get_client_name(client_p, MASK_IP), parv[1]);
673 michael 4571 exit_client(client_p, "Bogus server name introduced");
674 michael 2820 return 0;
675 michael 1118 }
676    
677     if (!valid_sid(parv[3]))
678     {
679 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
680 michael 1118 "Link %s introduced server with bogus server ID %s",
681     get_client_name(client_p, SHOW_IP), parv[3]);
682 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
683 michael 1118 "Link %s introduced server with bogus server ID %s",
684     get_client_name(client_p, MASK_IP), parv[3]);
685 michael 4571 exit_client(client_p, "Bogus server ID introduced");
686 michael 2820 return 0;
687 michael 1118 }
688    
689 adx 30 /* collision on SID? */
690 michael 1118 if ((target_p = hash_find_id(parv[3])))
691 adx 30 {
692 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
693 michael 4610 "Link %s cancelled, server ID %s already exists",
694 michael 1118 get_client_name(client_p, SHOW_IP), parv[3]);
695 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
696 michael 4610 "Link %s cancelled, server ID %s already exists",
697 michael 6439 get_client_name(client_p, MASK_IP), parv[3]);
698 michael 4610 exit_client(client_p, "Link cancelled, server ID already exists");
699 michael 2820 return 0;
700 adx 30 }
701    
702     /* collision on name? */
703 michael 1169 if ((target_p = hash_find_server(parv[1])))
704 adx 30 {
705 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
706 michael 2820 "Link %s cancelled, server %s already exists",
707 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
708 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
709 michael 2820 "Link %s cancelled, server %s already exists",
710 michael 6439 get_client_name(client_p, MASK_IP), parv[1]);
711 michael 4610 exit_client(client_p, "Server exists");
712 michael 2820 return 0;
713 adx 30 }
714    
715     /* XXX If somehow there is a connect in progress and
716     * a connect comes in with same name toss the pending one,
717     * but only if it's not the same client! - Dianora
718     */
719 michael 1118 if ((target_p = find_servconn_in_progress(parv[1])))
720 adx 30 if (target_p != client_p)
721 michael 3171 exit_client(target_p, "Overridden");
722 adx 30
723 michael 4589 conf = client_p->connection->confs.head->data;
724 michael 1384
725 adx 30 /* See if the newly found server is behind a guaranteed
726     * leaf. If so, close the link.
727     */
728 michael 4816 DLINK_FOREACH(node, conf->leaf_list.head)
729 michael 3139 {
730 michael 4816 if (!match(node->data, parv[1]))
731 michael 1529 {
732     llined = 1;
733     break;
734     }
735 michael 3139 }
736 adx 30
737 michael 4816 DLINK_FOREACH(node, conf->hub_list.head)
738 michael 3139 {
739 michael 4816 if (!match(node->data, parv[1]))
740 michael 1529 {
741     hlined = 1;
742     break;
743     }
744 michael 3139 }
745 michael 1118
746 adx 30 /* Ok, this way this works is
747     *
748     * A server can have a CONF_HUB allowing it to introduce servers
749     * behind it.
750     *
751     * connect {
752     * name = "irc.bighub.net";
753     * hub_mask="*";
754     * ...
755 michael 2820 *
756 adx 30 * That would allow "irc.bighub.net" to introduce anything it wanted..
757     *
758     * However
759     *
760     * connect {
761     * name = "irc.somehub.fi";
762     * hub_mask="*";
763     * leaf_mask="*.edu";
764     *...
765     * Would allow this server in finland to hub anything but
766     * .edu's
767     */
768    
769     /* Ok, check client_p can hub the new server, and make sure it's not a LL */
770 michael 885 if (!hlined)
771 adx 30 {
772     /* OOOPs nope can't HUB */
773 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
774 michael 1618 "Non-Hub link %s introduced %s.",
775 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
776 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
777 michael 1618 "Non-Hub link %s introduced %s.",
778 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
779 michael 3171 exit_client(source_p, "No matching hub_mask.");
780 michael 2820 return 0;
781 adx 30 }
782    
783     /* Check for the new server being leafed behind this HUB */
784     if (llined)
785     {
786     /* OOOPs nope can't HUB this leaf */
787 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_ADMIN, SEND_NOTICE,
788 michael 2820 "Link %s introduced leafed server %s.",
789 michael 1118 get_client_name(client_p, SHOW_IP), parv[1]);
790 michael 6317 sendto_realops_flags(UMODE_SERVNOTICE, L_OPER, SEND_NOTICE,
791 michael 2820 "Link %s introduced leafed server %s.",
792 michael 1118 get_client_name(client_p, MASK_IP), parv[1]);
793 michael 4610 exit_client(client_p, "Leafed server.");
794 michael 2820 return 0;
795 adx 30 }
796    
797 michael 7956 target_p = client_make(client_p);
798 adx 30 make_server(target_p);
799 michael 3190 target_p->hopcount = atoi(parv[2]);
800 michael 1118 target_p->servptr = source_p;
801 adx 30
802 michael 1118 strlcpy(target_p->name, parv[1], sizeof(target_p->name));
803     strlcpy(target_p->id, parv[3], sizeof(target_p->id));
804 adx 30
805 michael 7106 if (parc == 6) /* TBR: compatibility 'mode' */
806     {
807     strlcpy(target_p->info, parv[parc - 1], sizeof(target_p->info));
808     server_set_flags(target_p, parv[4]);
809     }
810     else
811     server_set_gecos(target_p, parv[parc - 1]);
812    
813 adx 30 SetServer(target_p);
814    
815 michael 7247 if (service_find(target_p->name))
816 michael 1219 AddFlag(target_p, FLAGS_SERVICE);
817 michael 1157
818 michael 7962 dlinkAdd(target_p, &target_p->node, &global_server_list);
819 michael 1118 dlinkAdd(target_p, &target_p->lnode, &target_p->servptr->serv->server_list);
820 adx 30
821     hash_add_client(target_p);
822     hash_add_id(target_p);
823    
824 michael 5785 sendto_server(client_p, 0, 0, ":%s SID %s %u %s :%s%s",
825 michael 3192 source_p->id, target_p->name, target_p->hopcount + 1,
826 michael 1527 target_p->id, IsHidden(target_p) ? "(H) " : "", target_p->info);
827 michael 1618 sendto_realops_flags(UMODE_EXTERNAL, L_ALL, SEND_NOTICE,
828 michael 1118 "Server %s being introduced by %s",
829 adx 30 target_p->name, source_p->name);
830 michael 2820 return 0;
831 adx 30 }
832    
833 michael 2820 static struct Message server_msgtab =
834     {
835 michael 5880 .cmd = "SERVER",
836     .args_min = 4,
837     .args_max = MAXPARA,
838     .handlers[UNREGISTERED_HANDLER] = mr_server,
839     .handlers[CLIENT_HANDLER] = m_registered,
840     .handlers[SERVER_HANDLER] = m_ignore,
841     .handlers[ENCAP_HANDLER] = m_ignore,
842     .handlers[OPER_HANDLER] = m_registered
843 michael 1230 };
844    
845 michael 2820 static struct Message sid_msgtab =
846     {
847 michael 5880 .cmd = "SID",
848     .args_min = 5,
849     .args_max = MAXPARA,
850     .handlers[UNREGISTERED_HANDLER] = m_ignore,
851     .handlers[CLIENT_HANDLER] = m_ignore,
852     .handlers[SERVER_HANDLER] = ms_sid,
853     .handlers[ENCAP_HANDLER] = m_ignore,
854     .handlers[OPER_HANDLER] = m_ignore
855 michael 1230 };
856    
857     static void
858     module_init(void)
859     {
860     mod_add_cmd(&sid_msgtab);
861     mod_add_cmd(&server_msgtab);
862     }
863    
864     static void
865     module_exit(void)
866     {
867     mod_del_cmd(&sid_msgtab);
868     mod_del_cmd(&server_msgtab);
869     }
870    
871 michael 2820 struct module module_entry =
872     {
873 michael 1230 .version = "$Revision$",
874     .modinit = module_init,
875     .modexit = module_exit,
876     .flags = MODULE_FLAG_CORE
877     };

Properties

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