]> jfr.im git - irc/quakenet/snircd.git/blame - ircd/m_create.c
Should be unsigned long for A
[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 *
9f8856e9 23 * $Id: m_create.c,v 1.18.2.3 2006/03/18 15:52:58 entrope 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,
9f8856e9 175 by receiving a CREATE for a zannel one of three things happened:
052b069e 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.
9f8856e9 188 3. The source server sent the CREATE while linking,
189 before it got the BURST for our zannel. If this
190 happens, we should reset the channel back to the old
191 timestamp. This can be distinguished from case #1 by
192 checking IsBurstOrBurstAck(cli_user(sptr)->server).
052b069e 193 */
194 !(chptr->users == 0 && !chptr->mode.apass[0]))) {
9f8856e9 195 if (!IsBurstOrBurstAck(cli_user(sptr)->server)) {
196 modebuf_init(&mbuf, sptr, cptr, chptr,
197 (MODEBUF_DEST_SERVER | /* Send mode to server */
198 MODEBUF_DEST_HACK2 | /* Send a HACK(2) message */
199 MODEBUF_DEST_BOUNCE)); /* And bounce the mode */
200
201 modebuf_mode_client(&mbuf, MODE_ADD | MODE_CHANOP, sptr, MAXOPLEVEL + 1);
202
203 modebuf_flush(&mbuf);
204
205 badop = 1;
206 } else if (chanTS > chptr->creationtime + 4) {
207 /* If their handling of the BURST will lead to deopping the
208 * user, have the user join without getting ops (if the
209 * server's handling of the BURST keeps their ops, the channel
210 * will use our timestamp).
211 */
212 badop = 1;
213 }
214
215 if (badop)
216 joinbuf_join(&join, chptr, 0);
189935b1 217 }
218 }
219 else /* Channel doesn't exist: create it */
220 chptr = get_channel(sptr, name, CGT_CREATE);
221
9f8856e9 222 if (!badop) {
223 /* Set (or correct) our copy of the TS */
189935b1 224 chptr->creationtime = chanTS;
9f8856e9 225 joinbuf_join(&create, chptr, CHFL_CHANOP);
226 }
189935b1 227 }
228
229 joinbuf_flush(&join); /* flush out the joins and creates */
230 joinbuf_flush(&create);
231
232 return 0;
233}