ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/modules/core/m_server.c
Revision: 9063
Committed: Sat Aug 10 15:54:36 2019 UTC (6 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 26239 byte(s)
Log Message:
- m_server.c: stylistic changes

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

Properties

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