]> jfr.im git - irc/quakenet/snircd.git/blame - ircd/m_create.c
import of 2.10.12.05
[irc/quakenet/snircd.git] / ircd / m_create.c
CommitLineData
189935b1 1/*
2 * IRC - Internet Relay Chat, ircd/m_create.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
5 *
6 * See file AUTHORS in IRC package for additional names of
7 * the programmers.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 1, or (at your option)
12 * any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
052b069e 23 * $Id: m_create.c,v 1.18.2.2 2005/12/23 17:12:06 klmitch Exp $
189935b1 24 */
25
26/*
27 * m_functions execute protocol messages on this server:
28 *
29 * cptr is always NON-NULL, pointing to a *LOCAL* client
30 * structure (with an open socket connected!). This
31 * identifies the physical socket where the message
32 * originated (or which caused the m_function to be
33 * executed--some m_functions may call others...).
34 *
35 * sptr is the source of the message, defined by the
36 * prefix part of the message if present. If not
37 * or prefix not found, then sptr==cptr.
38 *
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
41 *
42 * (IsServer(cptr))
43 * (sptr == cptr) => the message didn't
44 * have the prefix.
45 *
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
48 *
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
51 * user (not local).
52 *
53 * combining
54 *
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
58 *
59 * *Always* true (if 'parse' and others are working correct):
60 *
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
62 *
63 * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr
64 * *cannot* be a local connection, unless it's
65 * actually cptr!). [MyConnect(x) should probably
66 * be defined as (x == x->from) --msa ]
67 *
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
70 *
71 * parv a NULL terminated list of parameter pointers,
72 *
73 * parv[0], sender (prefix string), if not present
74 * this points to an empty string.
75 * parv[1]...parv[parc-1]
76 * pointers to additional parameters
77 * parv[parc] == NULL, *always*
78 *
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
80 * non-NULL pointers.
81 */
82#include "config.h"
83
84#include "channel.h"
85#include "client.h"
86#include "hash.h"
87#include "ircd.h"
88#include "ircd_log.h"
89#include "ircd_reply.h"
90#include "ircd_string.h"
91#include "msg.h"
92#include "numeric.h"
93#include "numnicks.h"
94#include "s_debug.h"
95#include "s_misc.h"
96#include "s_user.h"
97#include "send.h"
98
99/* #include <assert.h> -- Now using assert in ircd_log.h */
100#include <stdlib.h>
101#include <string.h>
102
103/*
104 * ms_create - server message handler
105 */
106int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
107{
108 time_t chanTS; /* channel creation time */
109 char *p; /* strtok state */
110 char *name; /* channel name */
111 struct Channel *chptr; /* channel */
112 struct JoinBuf join; /* join and create buffers */
113 struct JoinBuf create;
114 struct ModeBuf mbuf; /* a mode buffer */
115 int badop; /* a flag */
116
117 if (IsServer(sptr))
118 return protocol_violation(sptr,"%s tried to CREATE a channel", cli_name(sptr));
119
120 /* sanity checks: Only accept CREATE messages from servers */
121 if (parc < 3 || *parv[2] == '\0')
122 return need_more_params(sptr,"CREATE");
123
124 chanTS = atoi(parv[2]);
125
126 /* A create that didn't appear during a burst has that servers idea of
127 * the current time. Use it for lag calculations.
128 */
052b069e 129 if (!IsBurstOrBurstAck(sptr) && 0 != chanTS)
189935b1 130 cli_serv(cli_user(sptr)->server)->lag = TStime() - chanTS;
131
132 /* If this server is >1 minute fast, warn */
133 if (TStime() - chanTS<-60)
134 {
135 static time_t rate;
136 sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate,
137 "Timestamp drift from %C (%is); issuing "
138 "SETTIME to correct this",
139 cli_user(sptr)->server,
140 chanTS - TStime());
141 /* Now issue a SETTIME to resync. If we're in the wrong, our
142 * (RELIABLE_CLOCK) hub will bounce a SETTIME back to us.
143 */
144 sendcmdto_prio_one(&me, CMD_SETTIME, cli_user(sptr)->server,
145 "%Tu %C", TStime(), cli_user(sptr)->server);
146 }
147
148 joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
149 joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, chanTS);
150
151 /* For each channel in the comma separated list: */
152 for (name = ircd_strtok(&p, parv[1], ","); name;
153 name = ircd_strtok(&p, 0, ",")) {
154 badop = 0;
155
156 if (IsLocalChannel(name))
157 continue;
158
159 if ((chptr = FindChannel(name)))
160 {
161 /* Is the remote server confused? */
162 if (find_member_link(chptr, sptr)) {
163 protocol_violation(sptr, "%s tried to CREATE a channel already joined", cli_name(sptr));
164 continue;
165 }
166
167 /* Check if we need to bounce a mode */
168 if (TStime() - chanTS > TS_LAG_TIME ||
169 (chptr->creationtime && chanTS > chptr->creationtime &&
052b069e 170 /* Accept CREATE for zannels. This is only really necessary on a network
171 with servers prior to 2.10.12.02: we just accept their TS and ignore
172 the fact that it was a zannel. The influence of this on a network
173 that is completely 2.10.12.03 or higher is neglectable: Normally
174 a server only sends a CREATE after first sending a DESTRUCT. Thus,
175 by receiving a CREATE for a zannel one of two things happened:
176 1. The DESTRUCT was sent during a net.break; this could mean that
177 our zannel is at the verge of expiring too, it should have been
178 destructed. It is correct to copy the newer TS now, all modes
179 already have been reset, so it will be as if it was destructed
180 and immediately recreated. In order to avoid desyncs of modes,
181 we don't accept a CREATE for channels that have +A set.
182 2. The DESTRUCT passed, then someone created the channel on our
183 side and left it again. In this situation we have a near
184 simultaneous creation on two servers; the person on our side
185 already left within the time span of a message propagation.
186 The channel will therefore be less than 48 hours old and no
187 'protection' is necessary.
188 */
189 !(chptr->users == 0 && !chptr->mode.apass[0]))) {
189935b1 190 modebuf_init(&mbuf, sptr, cptr, chptr,
191 (MODEBUF_DEST_SERVER | /* Send mode to server */
192 MODEBUF_DEST_HACK2 | /* Send a HACK(2) message */
193 MODEBUF_DEST_BOUNCE)); /* And bounce the mode */
194
195 modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr, MAXOPLEVEL + 1);
196
197 modebuf_flush(&mbuf);
198
199 badop = 1;
200 }
201 }
202 else /* Channel doesn't exist: create it */
203 chptr = get_channel(sptr, name, CGT_CREATE);
204
205 if (!badop) /* Set/correct TS */
206 chptr->creationtime = chanTS;
207
208 joinbuf_join(badop ? &join : &create, chptr,
209 (badop ? 0 : CHFL_CHANOP));
210 }
211
212 joinbuf_flush(&join); /* flush out the joins and creates */
213 joinbuf_flush(&create);
214
215 return 0;
216}