ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 7951
Committed: Thu Mar 2 17:54:43 2017 UTC (9 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 27654 byte(s)
Log Message:
- Move check_server() from server.c to m_server.c; rename it to server_check()

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

Properties

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