Split Tracking, v0.13 Idea of split tracking is to remember channels for as long as they exist on every server, with an assumption that channel exists on splitted server as well. Hence it will not be possible to hack ops by splitting the server. Let's assume we have pure 2.11, as we will not do split tracking for pre 2.11 anyway. All channels will have additional linked list of servers (either simply numbers (sids converted base36) or pointers to an exact position in a table or LL of all sids known to the server from the start (in such a table we could keep more information, like when it last split etc.), which were lost in netsplit having any (opped or not) clients on this channel. Example 1: A --- B #ab: a1, a2, b1, b2 / \ / \ #a: a1, a2 a1 a2 b1 b2 #b: b1, b2 Split occurs. Situation on server A: i. server A sees that server B is lost, users b1 and b2 are gone; must have a look at channels these users were on and mark them as split ii. in this case, channels #ab and #b get marked iii. this means that cycling or joining these channels will not have any effect, ie. gaining op; random +r reop must not work; reop with +R should not be a problem iv. channels marked split when they get empty (either via split or last client leaving) will be locked (no user can enter) and all their modes removed[1] v. users can join new channels (non-existant before split) and get op [1] We could either keep existing modes and allow whoever is allowed to join, no op of course (eats memory a little and introduces all these modes back to network, which may be considered bad) OR not keep existing modes at all, which requires to lock the channel completely, so abusers would not be able to snoop after split ends who is on the channel. What's better? For now we choose locking empty channel. Situation on server B: as above, only split are channels #ab and #a Split ends. (This of course means EOBACK received.) Situation on server A: i. we have to go through all channels and remove server B from list of split servers ii. if such list for a channel gets empty, we get back to normal, else the split for this channel is on-going (could be forever, if server does not come back) Example 2: A --- B --- C #ab: a1, a2, b1, b2, c1 / \ / \ / \ #a: a1, a2 a1 a2 b1 b2 c1 c2 #b: b1, b2, c2 Split occurs between B and C. Overview of the situation: Channels #b and #ab are marked split on servers A, B and C. Channel #a empty, locked and marked split on server C. Another split occurs, between A and B. Situation: I. Server A i. #a not marked split ii. #b empty, locked and marked split with B, C iii. #ab marked split with B, C II. Server B i. #a empty, locked and marked split with A ii. #b marked split with C iii. #ab marked split with A, C II. Server C i. #a empty, locked and marked split with A ii. #b marked split with B iii. #ab marked split with A, B Split ends between B and C. As C sees B coming back (but not A) it clears split mark of B from all channels. And vice versa. Situation: I. Server A i. #a not marked split ii. #b empty, locked and marked split with B, C iii. #ab marked split with B, C II. Server B i. #a empty, locked and marked split with A ii. #b not marked split iii. #ab marked split with A II. Server C i. #a empty, locked and marked split with A ii. #b not marked split iii. #ab marked split with A Users on server B and C cannot join #a (ERR_UNAVAILRESOURCE), they can freely cycle #b and can normally use (except random +r) channel #ab, unless all clients from that channel leave (then it'd be like with #a). Users on server A can freely use, even cycle channel #a, cannot join #b and can use #ab like clients on servers B and C. Problem 1. New (or restarted) servers. While they may or may not accept client connections before joining the network, they must not allow clients to join any channel (well, except &local and !channels) before synching with the network. We have to send them current state of network, ie. all channels along with split list. We need a new command for that, say SRVSPLIT. (Better name? SJOIN? SMISS? SPLIT?) Servers sending should be only directly connected (bursting). Servers receiving should propagate it to their other links (removing their own sid from the list first). Example 3: A --- B #ab: a1, a2, b1, b2 / \ / \ #a: a1, a2 a1 a2 b1 b2 #b: b1, b2 Split occurs. Server C connects to A. A --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Server A must tell server C: :A NJOIN #ab: a1, a2 :A SRVSPLIT #ab: B :A NJOIN #a: a1, a2 :A SRVSPLIT #b: B Now both A and C know, that channels #ab and #b are split until B comes back. At #ab, however, they can normally operate (possible attack vector: DoS to split the server, put clones, op clones, wait for reconnect, fight with more clones) unless they leave the channel empty, and #a is completely free for manipulation. Problem 2. Servers lost for good. These must broadcast (new) DIE command, which would tell the network that this server is going down and its clients are not coming back, hence are not subject to split tracking. Should any server go down permanently without DIE, it would require oper intervention (manually introducing server and DIEing it) or channels that had users on that servers would be forever marked split and, when empty, also locked. Problem 3. Two servers restarted. A --- B --- C #ab: a1, a2, b1, b2, c1 / \ / \ / \ #a: a1, a2 a1 a2 b1 b2 c1 c2 #b: b1, b2, c2 Servers B and C split away. A #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Problem 3a. Normal way They get to send DIE broadcast. The rest of the network knows their clients are not coming back. Channel #b ceases to exist, channels #ab and #a operate with no further problems. Problem 3b. Bad way. Servers did not send DIE command. The rest of the network thinks their clients are coming back. Their channels are protected: #a normal, #ab split B, C, #b locked, split B, C. Servers B and C are coming back online and connect to each other first. B --- C Now we have a problem. EOBACKs were received, but no network state, no channels. We should consider it "not in the network" state. (Hm, back to MIN_SERV_SPLIT defines?) Otherwise, channels are in danger. Problem 3a. cont. A --- B --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 Server A sends all its channels and SRVSPLIT. Clients on B and C can use it normally from now on. (Observe, how #b is not existent.) Problem 3b. cont. A --- B --- C #ab: a1, a2 / \ #a: a1, a2 a1 a2 #b: Server A sends all its channels and SRVSPLIT, including: #ab B, C #b B, C Which would lead to 3a, after servers B and C remove already visible servers B and C from split marks. Clients on B and C can use it normally from now on. Problem N. What scenario have we *not* thought about? ------------- Note 1. PRO CONTRA keeping modes allows users to use the reintroduces old modes back channel, even get reop, if to network; they match +R; uses a bit more memory; allows to break MAXBAN requires to keep modes forever, limits :> even if users are gone; locking channel prone to abusers, noone user unfriendly (channel is out can get on the channel; of use once it gets empty); uses a bit less memory; does not reintroduce modes back to network;