ircu2.10.12 pk910 fork
[ircu2.10.12-pk.git] / ircd / m_create.c
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  *
23  * $Id: m_create.c 1744 2007-01-13 18:45:08Z entrope $
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  */
106 int 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    */
129   if (!IsBurstOrBurstAck(sptr) && 0 != chanTS)
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 (%s)", cli_name(sptr), chptr->chname);
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 &&
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 three 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               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).
193             */
194            !(chptr->users == 0 && !chptr->mode.apass[0]))) {
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);
217       }
218     }
219     else /* Channel doesn't exist: create it */
220       chptr = get_channel(sptr, name, CGT_CREATE);
221
222     if (!badop) {
223       /* Set (or correct) our copy of the TS */
224       chptr->creationtime = chanTS;
225       joinbuf_join(&create, chptr, CHFL_CHANOP);
226     }
227   }
228
229   joinbuf_flush(&join); /* flush out the joins and creates */
230   joinbuf_flush(&create);
231
232   return 0;
233 }