2 * IRC - Internet Relay Chat, ircd/m_create.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
6 * See file AUTHORS in IRC package for additional names of
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)
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.
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.
27 * m_functions execute protocol messages on this server:
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...).
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.
39 * (!IsServer(cptr)) => (cptr == sptr), because
40 * prefixes are taken *only* from servers...
43 * (sptr == cptr) => the message didn't
46 * (sptr != cptr && IsServer(sptr) means
47 * the prefix specified servername. (?)
49 * (sptr != cptr && !IsServer(sptr) means
50 * that message originated from a remote
55 * (!IsServer(sptr)) means that, sptr can safely
56 * taken as defining the target structure of the
57 * message in this server.
59 * *Always* true (if 'parse' and others are working correct):
61 * 1) sptr->from == cptr (note: cptr->from == cptr)
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 ]
68 * parc number of variable parameter strings (if zero,
69 * parv is allowed to be NULL)
71 * parv a NULL terminated list of parameter pointers,
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*
79 * note: it is guaranteed that parv[0]..parv[parc-1] are all
89 #include "ircd_reply.h"
90 #include "ircd_string.h"
99 /* #include <assert.h> -- Now using assert in ircd_log.h */
104 * ms_create - server message handler
106 int ms_create(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
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 */
118 return protocol_violation(sptr,"%s tried to CREATE a channel", cli_name(sptr));
120 /* sanity checks: Only accept CREATE messages from servers */
121 if (parc < 3 || *parv[2] == '\0')
122 return need_more_params(sptr,"CREATE");
124 chanTS = atoi(parv[2]);
126 /* A create that didn't appear during a burst has that servers idea of
127 * the current time. Use it for lag calculations.
129 if (!IsBurstOrBurstAck(sptr) && 0 != chanTS &&
130 MAGIC_REMOTE_JOIN_TS != chanTS)
131 cli_serv(cli_user(sptr)->server)->lag = TStime() - chanTS;
133 /* If this server is >1 minute fast, warn */
134 if (TStime() - chanTS<-60)
137 sendto_opmask_butone_ratelimited(0, SNO_NETWORK, &rate,
138 "Timestamp drift from %C (%is); issuing "
139 "SETTIME to correct this",
140 cli_user(sptr)->server,
142 /* Now issue a SETTIME to resync. If we're in the wrong, our
143 * (RELIABLE_CLOCK) hub will bounce a SETTIME back to us.
145 sendcmdto_prio_one(&me, CMD_SETTIME, cli_user(sptr)->server,
146 "%Tu %C", TStime(), cli_user(sptr)->server);
149 joinbuf_init(&join, sptr, cptr, JOINBUF_TYPE_JOIN, 0, 0);
150 joinbuf_init(&create, sptr, cptr, JOINBUF_TYPE_CREATE, 0, chanTS);
152 /* For each channel in the comma separated list: */
153 for (name = ircd_strtok(&p, parv[1], ","); name;
154 name = ircd_strtok(&p, 0, ",")) {
157 if (IsLocalChannel(name))
160 if ((chptr = FindChannel(name)))
162 /* Is the remote server confused? */
163 if (find_member_link(chptr, sptr)) {
164 protocol_violation(sptr, "%s tried to CREATE a channel already joined", cli_name(sptr));
168 /* Check if we need to bounce a mode */
169 if (TStime() - chanTS > TS_LAG_TIME ||
170 (chptr->creationtime && chanTS > chptr->creationtime &&
171 chptr->creationtime != MAGIC_REMOTE_JOIN_TS &&
172 /* Accept CREATE for zannels. This is only really necessary on a network
173 with servers prior to 2.10.12.02: we just accept their TS and ignore
174 the fact that it was a zannel. The influence of this on a network
175 that is completely 2.10.12.03 or higher is neglectable: Normally
176 a server only sends a CREATE after first sending a DESTRUCT. Thus,
177 by receiving a CREATE for a zannel one of two things happened:
178 1. The DESTRUCT was sent during a net.break; this could mean that
179 our zannel is at the verge of expiring too, it should have been
180 destructed. It is correct to copy the newer TS now, all modes
181 already have been reset, so it will be as if it was destructed
182 and immediately recreated. In order to avoid desyncs of modes,
183 we don't accept a CREATE for channels that have +A set.
184 2. The DESTRUCT passed, then someone created the channel on our
185 side and left it again. In this situation we have a near
186 simultaneous creation on two servers; the person on our side
187 already left within the time span of a message propagation.
188 The channel will therefore be less than 48 hours old and no
189 'protection' is necessary.
191 !(chptr->users == 0 && !chptr->mode.apass[0]))) {
192 modebuf_init(&mbuf, sptr, cptr, chptr,
193 (MODEBUF_DEST_SERVER | /* Send mode to server */
194 MODEBUF_DEST_HACK2 | /* Send a HACK(2) message */
195 MODEBUF_DEST_BOUNCE)); /* And bounce the mode */
197 modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr, MAXOPLEVEL + 1);
199 modebuf_flush(&mbuf);
204 else /* Channel doesn't exist: create it */
205 chptr = get_channel(sptr, name, CGT_CREATE);
207 if (!badop) /* Set/correct TS */
208 chptr->creationtime = chanTS;
210 joinbuf_join(badop ? &join : &create, chptr,
211 (badop ? 0 : CHFL_CHANOP));
214 joinbuf_flush(&join); /* flush out the joins and creates */
215 joinbuf_flush(&create);