r24670: Use torture functions for settings.
[kai/samba.git] / source4 / torture / nbt / winsreplication.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    WINS replication testing
5
6    Copyright (C) Andrew Tridgell        2005
7    Copyright (C) Stefan Metzmacher      2005
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 3 of the License, or
12    (at your option) 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, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libcli/wrepl/winsrepl.h"
25 #include "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "libcli/resolve/resolve.h"
28 #include "system/network.h"
29 #include "lib/socket/netif.h"
30 #include "librpc/gen_ndr/ndr_nbt.h"
31 #include "torture/torture.h"
32 #include "torture/nbt/proto.h"
33
34 #define CHECK_STATUS(tctx, status, correct) \
35         torture_assert_ntstatus_equal(tctx, status, correct, \
36                                                                   "Incorrect status")
37
38 #define CHECK_VALUE(tctx, v, correct) \
39         torture_assert(tctx, (v) == (correct), \
40                                    talloc_asprintf(tctx, "Incorrect value %s=%d - should be %d\n", \
41                        #v, v, correct))
42
43 #define CHECK_VALUE_UINT64(tctx, v, correct) \
44         torture_assert(tctx, (v) == (correct), \
45                 talloc_asprintf(tctx, "Incorrect value %s=%llu - should be %llu\n", \
46                        #v, (long long)v, (long long)correct))
47
48 #define CHECK_VALUE_STRING(tctx, v, correct) \
49         torture_assert_str_equal(tctx, v, correct, "Invalid value")
50
51 #define _NBT_NAME(n,t,s) {\
52         .name   = n,\
53         .type   = t,\
54         .scope  = s\
55 }
56
57 static const char *wrepl_name_type_string(enum wrepl_name_type type)
58 {
59         switch (type) {
60         case WREPL_TYPE_UNIQUE: return "UNIQUE";
61         case WREPL_TYPE_GROUP: return "GROUP";
62         case WREPL_TYPE_SGROUP: return "SGROUP";
63         case WREPL_TYPE_MHOMED: return "MHOMED";
64         }
65         return "UNKNOWN_TYPE";
66 }
67
68 static const char *wrepl_name_state_string(enum wrepl_name_state state)
69 {
70         switch (state) {
71         case WREPL_STATE_ACTIVE: return "ACTIVE";
72         case WREPL_STATE_RELEASED: return "RELEASED";
73         case WREPL_STATE_TOMBSTONE: return "TOMBSTONE";
74         case WREPL_STATE_RESERVED: return "RESERVED";
75         }
76         return "UNKNOWN_STATE";
77 }
78
79 /*
80   test how assoc_ctx's are only usable on the connection
81   they are created on.
82 */
83 static bool test_assoc_ctx1(struct torture_context *tctx)
84 {
85         bool ret = true;
86         struct wrepl_request *req;
87         struct wrepl_socket *wrepl_socket1;
88         struct wrepl_associate associate1;
89         struct wrepl_socket *wrepl_socket2;
90         struct wrepl_associate associate2;
91         struct wrepl_pull_table pull_table;
92         struct wrepl_packet packet;
93         struct wrepl_send_ctrl ctrl;
94         struct wrepl_packet *rep_packet;
95         struct wrepl_associate_stop assoc_stop;
96         NTSTATUS status;
97         struct nbt_name name;
98         const char *address;
99
100         if (!torture_setting_bool(tctx, "dangerous", false)) {
101                 torture_skip(tctx, "winsrepl: cross connection assoc_ctx usage disabled - enable dangerous tests to use");
102         }
103
104         if (!torture_nbt_get_name(tctx, &name, &address))
105                 return false;
106
107         torture_comment(tctx, "Test if assoc_ctx is only valid on the conection it was created on\n");
108
109         wrepl_socket1 = wrepl_socket_init(tctx, NULL);
110         wrepl_socket2 = wrepl_socket_init(tctx, NULL);
111
112         torture_comment(tctx, "Setup 2 wrepl connections\n");
113         status = wrepl_connect(wrepl_socket1, NULL, address);
114         CHECK_STATUS(tctx, status, NT_STATUS_OK);
115
116         status = wrepl_connect(wrepl_socket2, NULL, address);
117         CHECK_STATUS(tctx, status, NT_STATUS_OK);
118
119         torture_comment(tctx, "Send a start association request (conn1)\n");
120         status = wrepl_associate(wrepl_socket1, &associate1);
121         CHECK_STATUS(tctx, status, NT_STATUS_OK);
122
123         torture_comment(tctx, "association context (conn1): 0x%x\n", associate1.out.assoc_ctx);
124
125         torture_comment(tctx, "Send a start association request (conn2)\n");
126         status = wrepl_associate(wrepl_socket2, &associate2);
127         CHECK_STATUS(tctx, status, NT_STATUS_OK);
128
129         torture_comment(tctx, "association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
130
131         torture_comment(tctx, "Send a replication table query, with assoc 1 (conn2), the anwser should be on conn1\n");
132         ZERO_STRUCT(packet);
133         packet.opcode                      = WREPL_OPCODE_BITS;
134         packet.assoc_ctx                   = associate1.out.assoc_ctx;
135         packet.mess_type                   = WREPL_REPLICATION;
136         packet.message.replication.command = WREPL_REPL_TABLE_QUERY;
137         ZERO_STRUCT(ctrl);
138         ctrl.send_only = true;
139         req = wrepl_request_send(wrepl_socket2, &packet, &ctrl);
140         status = wrepl_request_recv(req, tctx, &rep_packet);
141         CHECK_STATUS(tctx, status, NT_STATUS_OK);
142
143         torture_comment(tctx, "Send a association request (conn2), to make sure the last request was ignored\n");
144         status = wrepl_associate(wrepl_socket2, &associate2);
145         CHECK_STATUS(tctx, status, NT_STATUS_OK);
146
147         torture_comment(tctx, "Send a replication table query, with invalid assoc (conn1), receive answer from conn2\n");
148         pull_table.in.assoc_ctx = 0;
149         req = wrepl_pull_table_send(wrepl_socket1, &pull_table);
150         status = wrepl_request_recv(req, tctx, &rep_packet);
151         CHECK_STATUS(tctx, status, NT_STATUS_OK);
152
153         torture_comment(tctx, "Send a association request (conn1), to make sure the last request was handled correct\n");
154         status = wrepl_associate(wrepl_socket1, &associate2);
155         CHECK_STATUS(tctx, status, NT_STATUS_OK);
156
157         assoc_stop.in.assoc_ctx = associate1.out.assoc_ctx;
158         assoc_stop.in.reason    = 4;
159         torture_comment(tctx, "Send a association stop request (conn1), reson: %u\n", assoc_stop.in.reason);
160         status = wrepl_associate_stop(wrepl_socket1, &assoc_stop);
161         CHECK_STATUS(tctx, status, NT_STATUS_END_OF_FILE);
162
163         assoc_stop.in.assoc_ctx = associate2.out.assoc_ctx;
164         assoc_stop.in.reason    = 0;
165         torture_comment(tctx, "Send a association stop request (conn2), reson: %u\n", assoc_stop.in.reason);
166         status = wrepl_associate_stop(wrepl_socket2, &assoc_stop);
167         CHECK_STATUS(tctx, status, NT_STATUS_OK);
168
169         torture_comment(tctx, "Close 2 wrepl connections\n");
170         talloc_free(wrepl_socket1);
171         talloc_free(wrepl_socket2);
172         return ret;
173 }
174
175 /*
176   test if we always get back the same assoc_ctx
177 */
178 static bool test_assoc_ctx2(struct torture_context *tctx)
179 {
180         struct wrepl_socket *wrepl_socket;
181         struct wrepl_associate associate;
182         uint32_t assoc_ctx1;
183         struct nbt_name name;
184         NTSTATUS status;
185         const char *address;
186
187         if (!torture_nbt_get_name(tctx, &name, &address))
188                 return false;
189
190         torture_comment(tctx, "Test if we always get back the same assoc_ctx\n");
191
192         wrepl_socket = wrepl_socket_init(tctx, NULL);
193         
194         torture_comment(tctx, "Setup wrepl connections\n");
195         status = wrepl_connect(wrepl_socket, NULL, address);
196         CHECK_STATUS(tctx, status, NT_STATUS_OK);
197
198         torture_comment(tctx, "Send 1st start association request\n");
199         status = wrepl_associate(wrepl_socket, &associate);
200         CHECK_STATUS(tctx, status, NT_STATUS_OK);
201         assoc_ctx1 = associate.out.assoc_ctx;
202         torture_comment(tctx, "1st association context: 0x%x\n", associate.out.assoc_ctx);
203
204         torture_comment(tctx, "Send 2nd start association request\n");
205         status = wrepl_associate(wrepl_socket, &associate);
206         torture_assert_ntstatus_ok(tctx, status, "2nd start association failed");
207         torture_assert(tctx, associate.out.assoc_ctx == assoc_ctx1, 
208                                    "Different context returned");
209         torture_comment(tctx, "2nd association context: 0x%x\n", associate.out.assoc_ctx);
210
211         torture_comment(tctx, "Send 3rd start association request\n");
212         status = wrepl_associate(wrepl_socket, &associate);
213         torture_assert(tctx, associate.out.assoc_ctx == assoc_ctx1, 
214                                    "Different context returned");
215         CHECK_STATUS(tctx, status, NT_STATUS_OK);
216         torture_comment(tctx, "3rd association context: 0x%x\n", associate.out.assoc_ctx);
217
218         torture_comment(tctx, "Close wrepl connections\n");
219         talloc_free(wrepl_socket);
220         return true;
221 }
222
223
224 /*
225   display a replication entry
226 */
227 static void display_entry(TALLOC_CTX *tctx, struct wrepl_name *name)
228 {
229         int i;
230
231         torture_comment(tctx, "%s\n", nbt_name_string(tctx, &name->name));
232         torture_comment(tctx, "\tTYPE:%u STATE:%u NODE:%u STATIC:%u VERSION_ID: %llu\n",
233                 name->type, name->state, name->node, name->is_static, (long long)name->version_id);
234         torture_comment(tctx, "\tRAW_FLAGS: 0x%08X OWNER: %-15s\n",
235                 name->raw_flags, name->owner);
236         for (i=0;i<name->num_addresses;i++) {
237                 torture_comment(tctx, "\tADDR: %-15s OWNER: %-15s\n", 
238                         name->addresses[i].address, name->addresses[i].owner);
239         }
240 }
241
242 /*
243   test a full replication dump from a WINS server
244 */
245 static bool test_wins_replication(struct torture_context *tctx)
246 {
247         struct wrepl_socket *wrepl_socket;
248         NTSTATUS status;
249         int i, j;
250         struct wrepl_associate associate;
251         struct wrepl_pull_table pull_table;
252         struct wrepl_pull_names pull_names;
253         struct nbt_name name;
254         const char *address;
255
256         if (!torture_nbt_get_name(tctx, &name, &address))
257                 return false;
258
259         torture_comment(tctx, "Test one pull replication cycle\n");
260
261         wrepl_socket = wrepl_socket_init(tctx, NULL);
262         
263         torture_comment(tctx, "Setup wrepl connections\n");
264         status = wrepl_connect(wrepl_socket, NULL, address);
265         CHECK_STATUS(tctx, status, NT_STATUS_OK);
266
267         torture_comment(tctx, "Send a start association request\n");
268
269         status = wrepl_associate(wrepl_socket, &associate);
270         CHECK_STATUS(tctx, status, NT_STATUS_OK);
271
272         torture_comment(tctx, "association context: 0x%x\n", associate.out.assoc_ctx);
273
274         torture_comment(tctx, "Send a replication table query\n");
275         pull_table.in.assoc_ctx = associate.out.assoc_ctx;
276
277         status = wrepl_pull_table(wrepl_socket, tctx, &pull_table);
278         if (NT_STATUS_EQUAL(NT_STATUS_NETWORK_ACCESS_DENIED,status)) {
279                 struct wrepl_packet packet;
280                 struct wrepl_request *req;
281
282                 ZERO_STRUCT(packet);
283                 packet.opcode                      = WREPL_OPCODE_BITS;
284                 packet.assoc_ctx                   = associate.out.assoc_ctx;
285                 packet.mess_type                   = WREPL_STOP_ASSOCIATION;
286                 packet.message.stop.reason         = 0;
287
288                 req = wrepl_request_send(wrepl_socket, &packet, NULL);
289                 talloc_free(req);
290
291                 torture_fail(tctx, "We are not a valid pull partner for the server");
292         }
293         CHECK_STATUS(tctx, status, NT_STATUS_OK);
294
295         torture_comment(tctx, "Found %d replication partners\n", pull_table.out.num_partners);
296
297         for (i=0;i<pull_table.out.num_partners;i++) {
298                 struct wrepl_wins_owner *partner = &pull_table.out.partners[i];
299                 torture_comment(tctx, "%s   max_version=%6llu   min_version=%6llu type=%d\n",
300                        partner->address, 
301                        (long long)partner->max_version, 
302                        (long long)partner->min_version, 
303                        partner->type);
304
305                 pull_names.in.assoc_ctx = associate.out.assoc_ctx;
306                 pull_names.in.partner = *partner;
307                 
308                 status = wrepl_pull_names(wrepl_socket, tctx, &pull_names);
309                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
310
311                 torture_comment(tctx, "Received %d names\n", pull_names.out.num_names);
312
313                 for (j=0;j<pull_names.out.num_names;j++) {
314                         display_entry(tctx, &pull_names.out.names[j]);
315                 }
316         }
317
318         torture_comment(tctx, "Close wrepl connections\n");
319         talloc_free(wrepl_socket);
320         return true;
321 }
322
323 struct test_wrepl_conflict_conn {
324         const char *address;
325         struct wrepl_socket *pull;
326         uint32_t pull_assoc;
327
328 #define TEST_OWNER_A_ADDRESS "127.65.65.1"
329 #define TEST_ADDRESS_A_PREFIX "127.0.65"
330 #define TEST_OWNER_B_ADDRESS "127.66.66.1"
331 #define TEST_ADDRESS_B_PREFIX "127.0.66"
332 #define TEST_OWNER_X_ADDRESS "127.88.88.1"
333 #define TEST_ADDRESS_X_PREFIX "127.0.88"
334
335         struct wrepl_wins_owner a, b, c, x;
336
337         struct socket_address *myaddr;
338         struct socket_address *myaddr2;
339         struct nbt_name_socket *nbtsock;
340         struct nbt_name_socket *nbtsock2;
341
342         struct nbt_name_socket *nbtsock_srv;
343         struct nbt_name_socket *nbtsock_srv2;
344
345         uint32_t addresses_best_num;
346         struct wrepl_ip *addresses_best;
347
348         uint32_t addresses_best2_num;
349         struct wrepl_ip *addresses_best2;
350
351         uint32_t addresses_all_num;
352         struct wrepl_ip *addresses_all;
353
354         uint32_t addresses_mhomed_num;
355         struct wrepl_ip *addresses_mhomed;
356 };
357
358 static const struct wrepl_ip addresses_A_1[] = {
359         {
360         .owner  = TEST_OWNER_A_ADDRESS,
361         .ip     = TEST_ADDRESS_A_PREFIX".1"
362         }
363 };
364 static const struct wrepl_ip addresses_A_2[] = {
365         {
366         .owner  = TEST_OWNER_A_ADDRESS,
367         .ip     = TEST_ADDRESS_A_PREFIX".2"
368         }
369 };
370 static const struct wrepl_ip addresses_A_3_4[] = {
371         {
372         .owner  = TEST_OWNER_A_ADDRESS,
373         .ip     = TEST_ADDRESS_A_PREFIX".3"
374         },
375         {
376         .owner  = TEST_OWNER_A_ADDRESS,
377         .ip     = TEST_ADDRESS_A_PREFIX".4"
378         }
379 };
380 static const struct wrepl_ip addresses_A_3_4_X_3_4[] = {
381         {
382         .owner  = TEST_OWNER_A_ADDRESS,
383         .ip     = TEST_ADDRESS_A_PREFIX".3"
384         },
385         {
386         .owner  = TEST_OWNER_A_ADDRESS,
387         .ip     = TEST_ADDRESS_A_PREFIX".4"
388         },
389         {
390         .owner  = TEST_OWNER_X_ADDRESS,
391         .ip     = TEST_ADDRESS_X_PREFIX".3"
392         },
393         {
394         .owner  = TEST_OWNER_X_ADDRESS,
395         .ip     = TEST_ADDRESS_X_PREFIX".4"
396         }
397 };
398 static const struct wrepl_ip addresses_A_3_4_B_3_4[] = {
399         {
400         .owner  = TEST_OWNER_A_ADDRESS,
401         .ip     = TEST_ADDRESS_A_PREFIX".3"
402         },
403         {
404         .owner  = TEST_OWNER_A_ADDRESS,
405         .ip     = TEST_ADDRESS_A_PREFIX".4"
406         },
407         {
408         .owner  = TEST_OWNER_B_ADDRESS,
409         .ip     = TEST_ADDRESS_B_PREFIX".3"
410         },
411         {
412         .owner  = TEST_OWNER_B_ADDRESS,
413         .ip     = TEST_ADDRESS_B_PREFIX".4"
414         }
415 };
416 static const struct wrepl_ip addresses_A_3_4_OWNER_B[] = {
417         {
418         .owner  = TEST_OWNER_B_ADDRESS,
419         .ip     = TEST_ADDRESS_A_PREFIX".3"
420         },
421         {
422         .owner  = TEST_OWNER_B_ADDRESS,
423         .ip     = TEST_ADDRESS_A_PREFIX".4"
424         }
425 };
426 static const struct wrepl_ip addresses_A_3_4_X_3_4_OWNER_B[] = {
427         {
428         .owner  = TEST_OWNER_B_ADDRESS,
429         .ip     = TEST_ADDRESS_A_PREFIX".3"
430         },
431         {
432         .owner  = TEST_OWNER_B_ADDRESS,
433         .ip     = TEST_ADDRESS_A_PREFIX".4"
434         },
435         {
436         .owner  = TEST_OWNER_B_ADDRESS,
437         .ip     = TEST_ADDRESS_X_PREFIX".3"
438         },
439         {
440         .owner  = TEST_OWNER_B_ADDRESS,
441         .ip     = TEST_ADDRESS_X_PREFIX".4"
442         }
443 };
444
445 static const struct wrepl_ip addresses_A_3_4_X_1_2[] = {
446         {
447         .owner  = TEST_OWNER_A_ADDRESS,
448         .ip     = TEST_ADDRESS_A_PREFIX".3"
449         },
450         {
451         .owner  = TEST_OWNER_A_ADDRESS,
452         .ip     = TEST_ADDRESS_A_PREFIX".4"
453         },
454         {
455         .owner  = TEST_OWNER_X_ADDRESS,
456         .ip     = TEST_ADDRESS_X_PREFIX".1"
457         },
458         {
459         .owner  = TEST_OWNER_X_ADDRESS,
460         .ip     = TEST_ADDRESS_X_PREFIX".2"
461         }
462 };
463
464 static const struct wrepl_ip addresses_B_1[] = {
465         {
466         .owner  = TEST_OWNER_B_ADDRESS,
467         .ip     = TEST_ADDRESS_B_PREFIX".1"
468         }
469 };
470 static const struct wrepl_ip addresses_B_2[] = {
471         {
472         .owner  = TEST_OWNER_B_ADDRESS,
473         .ip     = TEST_ADDRESS_B_PREFIX".2"
474         }
475 };
476 static const struct wrepl_ip addresses_B_3_4[] = {
477         {
478         .owner  = TEST_OWNER_B_ADDRESS,
479         .ip     = TEST_ADDRESS_B_PREFIX".3"
480         },
481         {
482         .owner  = TEST_OWNER_B_ADDRESS,
483         .ip     = TEST_ADDRESS_B_PREFIX".4"
484         }
485 };
486 static const struct wrepl_ip addresses_B_3_4_X_3_4[] = {
487         {
488         .owner  = TEST_OWNER_B_ADDRESS,
489         .ip     = TEST_ADDRESS_B_PREFIX".3"
490         },
491         {
492         .owner  = TEST_OWNER_B_ADDRESS,
493         .ip     = TEST_ADDRESS_B_PREFIX".4"
494         },
495         {
496         .owner  = TEST_OWNER_X_ADDRESS,
497         .ip     = TEST_ADDRESS_X_PREFIX".3"
498         },
499         {
500         .owner  = TEST_OWNER_X_ADDRESS,
501         .ip     = TEST_ADDRESS_X_PREFIX".4"
502         }
503 };
504 static const struct wrepl_ip addresses_B_3_4_X_1_2[] = {
505         {
506         .owner  = TEST_OWNER_B_ADDRESS,
507         .ip     = TEST_ADDRESS_B_PREFIX".3"
508         },
509         {
510         .owner  = TEST_OWNER_B_ADDRESS,
511         .ip     = TEST_ADDRESS_B_PREFIX".4"
512         },
513         {
514         .owner  = TEST_OWNER_X_ADDRESS,
515         .ip     = TEST_ADDRESS_X_PREFIX".1"
516         },
517         {
518         .owner  = TEST_OWNER_X_ADDRESS,
519         .ip     = TEST_ADDRESS_X_PREFIX".2"
520         }
521 };
522
523 static const struct wrepl_ip addresses_X_1_2[] = {
524         {
525         .owner  = TEST_OWNER_X_ADDRESS,
526         .ip     = TEST_ADDRESS_X_PREFIX".1"
527         },
528         {
529         .owner  = TEST_OWNER_X_ADDRESS,
530         .ip     = TEST_ADDRESS_X_PREFIX".2"
531         }
532 };
533 static const struct wrepl_ip addresses_X_3_4[] = {
534         {
535         .owner  = TEST_OWNER_X_ADDRESS,
536         .ip     = TEST_ADDRESS_X_PREFIX".3"
537         },
538         {
539         .owner  = TEST_OWNER_X_ADDRESS,
540         .ip     = TEST_ADDRESS_X_PREFIX".4"
541         }
542 };
543
544 static struct test_wrepl_conflict_conn *test_create_conflict_ctx(TALLOC_CTX *tctx,
545                                                                  const char *address)
546 {
547         struct test_wrepl_conflict_conn *ctx;
548         struct wrepl_associate associate;
549         struct wrepl_pull_table pull_table;
550         struct socket_address *nbt_srv_addr;
551         NTSTATUS status;
552         uint32_t i;
553
554         ctx = talloc_zero(tctx, struct test_wrepl_conflict_conn);
555         if (!ctx) return NULL;
556
557         ctx->address    = address;
558         ctx->pull       = wrepl_socket_init(ctx, NULL);
559         if (!ctx->pull) return NULL;
560
561         torture_comment(tctx, "Setup wrepl conflict pull connection\n");
562         status = wrepl_connect(ctx->pull, NULL, ctx->address);
563         if (!NT_STATUS_IS_OK(status)) return NULL;
564
565         status = wrepl_associate(ctx->pull, &associate);
566         if (!NT_STATUS_IS_OK(status)) return NULL;
567
568         ctx->pull_assoc = associate.out.assoc_ctx;
569
570         ctx->a.address          = TEST_OWNER_A_ADDRESS;
571         ctx->a.max_version      = 0;
572         ctx->a.min_version      = 0;
573         ctx->a.type             = 1;
574
575         ctx->b.address          = TEST_OWNER_B_ADDRESS;
576         ctx->b.max_version      = 0;
577         ctx->b.min_version      = 0;
578         ctx->b.type             = 1;
579
580         ctx->x.address          = TEST_OWNER_X_ADDRESS;
581         ctx->x.max_version      = 0;
582         ctx->x.min_version      = 0;
583         ctx->x.type             = 1;
584
585         ctx->c.address          = address;
586         ctx->c.max_version      = 0;
587         ctx->c.min_version      = 0;
588         ctx->c.type             = 1;
589
590         pull_table.in.assoc_ctx = ctx->pull_assoc;
591         status = wrepl_pull_table(ctx->pull, ctx->pull, &pull_table);
592         if (!NT_STATUS_IS_OK(status)) return NULL;
593
594         for (i=0; i < pull_table.out.num_partners; i++) {
595                 if (strcmp(TEST_OWNER_A_ADDRESS,pull_table.out.partners[i].address)==0) {
596                         ctx->a.max_version      = pull_table.out.partners[i].max_version;
597                         ctx->a.min_version      = pull_table.out.partners[i].min_version;
598                 }
599                 if (strcmp(TEST_OWNER_B_ADDRESS,pull_table.out.partners[i].address)==0) {
600                         ctx->b.max_version      = pull_table.out.partners[i].max_version;
601                         ctx->b.min_version      = pull_table.out.partners[i].min_version;
602                 }
603                 if (strcmp(TEST_OWNER_X_ADDRESS,pull_table.out.partners[i].address)==0) {
604                         ctx->x.max_version      = pull_table.out.partners[i].max_version;
605                         ctx->x.min_version      = pull_table.out.partners[i].min_version;
606                 }
607                 if (strcmp(address,pull_table.out.partners[i].address)==0) {
608                         ctx->c.max_version      = pull_table.out.partners[i].max_version;
609                         ctx->c.min_version      = pull_table.out.partners[i].min_version;
610                 }
611         }
612
613         talloc_free(pull_table.out.partners);
614
615         ctx->nbtsock = nbt_name_socket_init(ctx, NULL);
616         if (!ctx->nbtsock) return NULL;
617
618         ctx->myaddr = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_best_ip(address), 0);
619         if (!ctx->myaddr) return NULL;
620
621         for (i = 0; i < iface_count(); i++) {
622                 if (strcmp(ctx->myaddr->addr, iface_n_ip(i)) == 0) continue;
623                 ctx->myaddr2 = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_n_ip(i), 0);
624                 if (!ctx->myaddr2) return NULL;
625                 break;
626         }
627
628         status = socket_listen(ctx->nbtsock->sock, ctx->myaddr, 0, 0);
629         if (!NT_STATUS_IS_OK(status)) return NULL;
630
631         ctx->nbtsock_srv = nbt_name_socket_init(ctx, NULL);
632         if (!ctx->nbtsock_srv) return NULL;
633
634         /* Make a port 137 version of ctx->myaddr */
635         nbt_srv_addr = socket_address_from_strings(tctx, ctx->nbtsock_srv->sock->backend_name, ctx->myaddr->addr, lp_nbt_port());
636         if (!nbt_srv_addr) return NULL;
637
638         /* And if possible, bind to it.  This won't work unless we are root or in sockewrapper */
639         status = socket_listen(ctx->nbtsock_srv->sock, nbt_srv_addr, 0, 0);
640         talloc_free(nbt_srv_addr);
641         if (!NT_STATUS_IS_OK(status)) {
642                 /* this isn't fatal */
643                 talloc_free(ctx->nbtsock_srv);
644                 ctx->nbtsock_srv = NULL;
645         }
646
647         if (ctx->myaddr2 && ctx->nbtsock_srv) {
648                 ctx->nbtsock2 = nbt_name_socket_init(ctx, NULL);
649                 if (!ctx->nbtsock2) return NULL;
650
651                 status = socket_listen(ctx->nbtsock2->sock, ctx->myaddr2, 0, 0);
652                 if (!NT_STATUS_IS_OK(status)) return NULL;
653
654                 ctx->nbtsock_srv2 = nbt_name_socket_init(ctx, ctx->nbtsock_srv->event_ctx);
655                 if (!ctx->nbtsock_srv2) return NULL;
656
657                 /* Make a port 137 version of ctx->myaddr2 */
658                 nbt_srv_addr = socket_address_from_strings(tctx, 
659                                                            ctx->nbtsock_srv->sock->backend_name, 
660                                                            ctx->myaddr2->addr, lp_nbt_port());
661                 if (!nbt_srv_addr) return NULL;
662
663                 /* And if possible, bind to it.  This won't work unless we are root or in sockewrapper */
664                 status = socket_listen(ctx->nbtsock_srv2->sock, ctx->myaddr2, 0, 0);
665                 talloc_free(nbt_srv_addr);
666                 if (!NT_STATUS_IS_OK(status)) {
667                         /* this isn't fatal */
668                         talloc_free(ctx->nbtsock_srv2);
669                         ctx->nbtsock_srv2 = NULL;
670                 }
671         }
672
673         ctx->addresses_best_num = 1;
674         ctx->addresses_best = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best_num);
675         if (!ctx->addresses_best) return NULL;
676         ctx->addresses_best[0].owner    = ctx->b.address;
677         ctx->addresses_best[0].ip       = ctx->myaddr->addr;
678
679         ctx->addresses_all_num = iface_count();
680         ctx->addresses_all = talloc_array(ctx, struct wrepl_ip, ctx->addresses_all_num);
681         if (!ctx->addresses_all) return NULL;
682         for (i=0; i < ctx->addresses_all_num; i++) {
683                 ctx->addresses_all[i].owner     = ctx->b.address;
684                 ctx->addresses_all[i].ip        = talloc_strdup(ctx->addresses_all, iface_n_ip(i));
685                 if (!ctx->addresses_all[i].ip) return NULL;
686         }
687
688         if (ctx->nbtsock_srv2) {
689                 ctx->addresses_best2_num = 1;
690                 ctx->addresses_best2 = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best2_num);
691                 if (!ctx->addresses_best2) return NULL;
692                 ctx->addresses_best2[0].owner   = ctx->b.address;
693                 ctx->addresses_best2[0].ip      = ctx->myaddr2->addr;
694
695                 ctx->addresses_mhomed_num = 2;
696                 ctx->addresses_mhomed = talloc_array(ctx, struct wrepl_ip, ctx->addresses_mhomed_num);
697                 if (!ctx->addresses_mhomed) return NULL;
698                 ctx->addresses_mhomed[0].owner  = ctx->b.address;
699                 ctx->addresses_mhomed[0].ip     = ctx->myaddr->addr;
700                 ctx->addresses_mhomed[1].owner  = ctx->b.address;
701                 ctx->addresses_mhomed[1].ip     = ctx->myaddr2->addr;
702         }
703
704         return ctx;
705 }
706
707 static bool test_wrepl_update_one(struct torture_context *tctx, 
708                                                                   struct test_wrepl_conflict_conn *ctx,
709                                   const struct wrepl_wins_owner *owner,
710                                   const struct wrepl_wins_name *name)
711 {
712         struct wrepl_socket *wrepl_socket;
713         struct wrepl_associate associate;
714         struct wrepl_packet update_packet, repl_send;
715         struct wrepl_table *update;
716         struct wrepl_wins_owner wrepl_wins_owners[1];
717         struct wrepl_packet *repl_recv;
718         struct wrepl_wins_owner *send_request;
719         struct wrepl_send_reply *send_reply;
720         struct wrepl_wins_name wrepl_wins_names[1];
721         uint32_t assoc_ctx;
722         NTSTATUS status;
723
724         wrepl_socket = wrepl_socket_init(ctx, NULL);
725
726         status = wrepl_connect(wrepl_socket, NULL, ctx->address);
727         CHECK_STATUS(tctx, status, NT_STATUS_OK);
728
729         status = wrepl_associate(wrepl_socket, &associate);
730         CHECK_STATUS(tctx, status, NT_STATUS_OK);
731         assoc_ctx = associate.out.assoc_ctx;
732
733         /* now send a WREPL_REPL_UPDATE message */
734         ZERO_STRUCT(update_packet);
735         update_packet.opcode                    = WREPL_OPCODE_BITS;
736         update_packet.assoc_ctx                 = assoc_ctx;
737         update_packet.mess_type                 = WREPL_REPLICATION;
738         update_packet.message.replication.command       = WREPL_REPL_UPDATE;
739         update  = &update_packet.message.replication.info.table;
740
741         update->partner_count   = ARRAY_SIZE(wrepl_wins_owners);
742         update->partners        = wrepl_wins_owners;
743         update->initiator       = "0.0.0.0";
744
745         wrepl_wins_owners[0]    = *owner;
746
747         status = wrepl_request(wrepl_socket, wrepl_socket,
748                                &update_packet, &repl_recv);
749         CHECK_STATUS(tctx, status, NT_STATUS_OK);
750         CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_REPLICATION);
751         CHECK_VALUE(tctx, repl_recv->message.replication.command, WREPL_REPL_SEND_REQUEST);
752         send_request = &repl_recv->message.replication.info.owner;
753
754         ZERO_STRUCT(repl_send);
755         repl_send.opcode                        = WREPL_OPCODE_BITS;
756         repl_send.assoc_ctx                     = assoc_ctx;
757         repl_send.mess_type                     = WREPL_REPLICATION;
758         repl_send.message.replication.command   = WREPL_REPL_SEND_REPLY;
759         send_reply = &repl_send.message.replication.info.reply;
760
761         send_reply->num_names   = ARRAY_SIZE(wrepl_wins_names);
762         send_reply->names       = wrepl_wins_names;
763
764         wrepl_wins_names[0]     = *name;
765
766         status = wrepl_request(wrepl_socket, wrepl_socket,
767                                &repl_send, &repl_recv);
768         CHECK_STATUS(tctx, status, NT_STATUS_OK);
769         CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_STOP_ASSOCIATION);
770         CHECK_VALUE(tctx, repl_recv->message.stop.reason, 0);
771
772         talloc_free(wrepl_socket);
773         return true;
774 }
775
776 static bool test_wrepl_is_applied(struct torture_context *tctx, 
777                                                                   struct test_wrepl_conflict_conn *ctx,
778                                   const struct wrepl_wins_owner *owner,
779                                   const struct wrepl_wins_name *name,
780                                   bool expected)
781 {
782         NTSTATUS status;
783         struct wrepl_pull_names pull_names;
784         struct wrepl_name *names;
785
786         pull_names.in.assoc_ctx = ctx->pull_assoc;
787         pull_names.in.partner   = *owner;
788         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
789                 
790         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
791         CHECK_STATUS(tctx, status, NT_STATUS_OK);
792         torture_assert(tctx, pull_names.out.num_names == (expected?1:0), 
793                        talloc_asprintf(tctx, "Invalid number of records returned - expected %d got %d", expected, pull_names.out.num_names));
794
795         names = pull_names.out.names;
796
797         if (expected) {
798                 uint32_t flags = WREPL_NAME_FLAGS(names[0].type,
799                                                   names[0].state,
800                                                   names[0].node,
801                                                   names[0].is_static);
802                 CHECK_VALUE(tctx, names[0].name.type, name->name->type);
803                 CHECK_VALUE_STRING(tctx, names[0].name.name, name->name->name);
804                 CHECK_VALUE_STRING(tctx, names[0].name.scope, name->name->scope);
805                 CHECK_VALUE(tctx, flags, name->flags);
806                 CHECK_VALUE_UINT64(tctx, names[0].version_id, name->id);
807
808                 if (flags & 2) {
809                         CHECK_VALUE(tctx, names[0].num_addresses,
810                                     name->addresses.addresses.num_ips);
811                 } else {
812                         CHECK_VALUE(tctx, names[0].num_addresses, 1);
813                         CHECK_VALUE_STRING(tctx, names[0].addresses[0].address,
814                                            name->addresses.ip);
815                 }
816         }
817         talloc_free(pull_names.out.names);
818         return true;
819 }
820
821 static bool test_wrepl_mhomed_merged(struct torture_context *tctx, 
822                                                                          struct test_wrepl_conflict_conn *ctx,
823                                      const struct wrepl_wins_owner *owner1,
824                                      uint32_t num_ips1, const struct wrepl_ip *ips1,
825                                      const struct wrepl_wins_owner *owner2,
826                                      uint32_t num_ips2, const struct wrepl_ip *ips2,
827                                      const struct wrepl_wins_name *name2)
828 {
829         NTSTATUS status;
830         struct wrepl_pull_names pull_names;
831         struct wrepl_name *names;
832         uint32_t flags;
833         uint32_t i, j;
834         uint32_t num_ips = num_ips1 + num_ips2;
835
836         for (i = 0; i < num_ips2; i++) {
837                 for (j = 0; j < num_ips1; j++) {
838                         if (strcmp(ips2[i].ip,ips1[j].ip) == 0) {
839                                 num_ips--;
840                                 break;
841                         }
842                 } 
843         }
844
845         pull_names.in.assoc_ctx = ctx->pull_assoc;
846         pull_names.in.partner   = *owner2;
847         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
848
849         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
850         CHECK_STATUS(tctx, status, NT_STATUS_OK);
851         CHECK_VALUE(tctx, pull_names.out.num_names, 1);
852
853         names = pull_names.out.names;
854
855         flags = WREPL_NAME_FLAGS(names[0].type,
856                                  names[0].state,
857                                  names[0].node,
858                                  names[0].is_static);
859         CHECK_VALUE(tctx, names[0].name.type, name2->name->type);
860         CHECK_VALUE_STRING(tctx, names[0].name.name, name2->name->name);
861         CHECK_VALUE_STRING(tctx, names[0].name.scope, name2->name->scope);
862         CHECK_VALUE(tctx, flags, name2->flags | WREPL_TYPE_MHOMED);
863         CHECK_VALUE_UINT64(tctx, names[0].version_id, name2->id);
864
865         CHECK_VALUE(tctx, names[0].num_addresses, num_ips);
866
867         for (i = 0; i < names[0].num_addresses; i++) {
868                 const char *addr = names[0].addresses[i].address; 
869                 const char *owner = names[0].addresses[i].owner;
870                 bool found = false;
871
872                 for (j = 0; j < num_ips2; j++) {
873                         if (strcmp(addr, ips2[j].ip) == 0) {
874                                 found = true;
875                                 CHECK_VALUE_STRING(tctx, owner, owner2->address);
876                                 break;
877                         }
878                 }
879
880                 if (found) continue;
881
882                 for (j = 0; j < num_ips1; j++) {
883                         if (strcmp(addr, ips1[j].ip) == 0) {
884                                 found = true;
885                                 CHECK_VALUE_STRING(tctx, owner, owner1->address);
886                                 break;
887                         }
888                 }
889
890                 if (found) continue;
891
892                 CHECK_VALUE_STRING(tctx, addr, "not found in address list");
893         }
894         talloc_free(pull_names.out.names);
895         return true;
896 }
897
898 static bool test_wrepl_sgroup_merged(struct torture_context *tctx, 
899                                                                          struct test_wrepl_conflict_conn *ctx,
900                                      struct wrepl_wins_owner *merge_owner,
901                                      struct wrepl_wins_owner *owner1,
902                                      uint32_t num_ips1, const struct wrepl_ip *ips1,
903                                      struct wrepl_wins_owner *owner2,
904                                      uint32_t num_ips2, const struct wrepl_ip *ips2,
905                                      const struct wrepl_wins_name *name2)
906 {
907         NTSTATUS status;
908         struct wrepl_pull_names pull_names;
909         struct wrepl_name *names;
910         struct wrepl_name *name = NULL;
911         uint32_t flags;
912         uint32_t i, j;
913         uint32_t num_ips = num_ips1 + num_ips2;
914
915         if (!merge_owner) {
916                 merge_owner = &ctx->c;
917         }
918
919         for (i = 0; i < num_ips1; i++) {
920                 if (owner1 != &ctx->c && strcmp(ips1[i].owner,owner2->address) == 0) {
921                         num_ips--;
922                         continue;
923                 }
924                 for (j = 0; j < num_ips2; j++) {
925                         if (strcmp(ips1[i].ip,ips2[j].ip) == 0) {
926                                 num_ips--;
927                                 break;
928                         }
929                 }
930         }
931
932
933         pull_names.in.assoc_ctx = ctx->pull_assoc;
934         pull_names.in.partner   = *merge_owner;
935         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
936         pull_names.in.partner.max_version = 0;
937
938         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
939         CHECK_STATUS(tctx, status, NT_STATUS_OK);
940
941         names = pull_names.out.names;
942         
943         for (i = 0; i < pull_names.out.num_names; i++) {
944                 if (names[i].name.type != name2->name->type)    continue;
945                 if (!names[i].name.name) continue;
946                 if (strcmp(names[i].name.name, name2->name->name) != 0) continue;
947                 if (names[i].name.scope) continue;
948
949                 name = &names[i];
950         }
951
952         if (pull_names.out.num_names > 0) {
953                 merge_owner->max_version        = names[pull_names.out.num_names-1].version_id;
954         }
955
956         if (!name) {
957                 torture_comment(tctx, "%s: Name '%s' not found\n", __location__, nbt_name_string(ctx, name2->name));
958                 return false;
959         }
960
961         flags = WREPL_NAME_FLAGS(name->type,
962                                  name->state,
963                                  name->node,
964                                  name->is_static);
965         CHECK_VALUE(tctx, name->name.type, name2->name->type);
966         CHECK_VALUE_STRING(tctx, name->name.name, name2->name->name);
967         CHECK_VALUE_STRING(tctx, name->name.scope, name2->name->scope);
968         CHECK_VALUE(tctx, flags, name2->flags);
969
970         CHECK_VALUE(tctx, name->num_addresses, num_ips);
971
972         for (i = 0; i < name->num_addresses; i++) {
973                 const char *addr = name->addresses[i].address; 
974                 const char *owner = name->addresses[i].owner;
975                 bool found = false;
976
977                 for (j = 0; j < num_ips2; j++) {
978                         if (strcmp(addr, ips2[j].ip) == 0) {
979                                 found = true;
980                                 CHECK_VALUE_STRING(tctx, owner, ips2[j].owner);
981                                 break;
982                         }
983                 }
984
985                 if (found) continue;
986
987                 for (j = 0; j < num_ips1; j++) {
988                         if (strcmp(addr, ips1[j].ip) == 0) {
989                                 found = true;
990                                 if (owner1 == &ctx->c) {
991                                         CHECK_VALUE_STRING(tctx, owner, owner1->address);
992                                 } else {
993                                         CHECK_VALUE_STRING(tctx, owner, ips1[j].owner);
994                                 }
995                                 break;
996                         }
997                 }
998
999                 if (found) continue;
1000
1001                 CHECK_VALUE_STRING(tctx, addr, "not found in address list");
1002         }
1003         talloc_free(pull_names.out.names);
1004         return true;
1005 }
1006
1007 static bool test_conflict_same_owner(struct torture_context *tctx, 
1008                                                                          struct test_wrepl_conflict_conn *ctx)
1009 {
1010         static bool ret = true;
1011         struct nbt_name name;
1012         struct wrepl_wins_name wins_name1;
1013         struct wrepl_wins_name wins_name2;
1014         struct wrepl_wins_name *wins_name_tmp;
1015         struct wrepl_wins_name *wins_name_last;
1016         struct wrepl_wins_name *wins_name_cur;
1017         uint32_t i,j;
1018         uint8_t types[] = { 0x00, 0x1C };
1019         struct {
1020                 enum wrepl_name_type type;
1021                 enum wrepl_name_state state;
1022                 enum wrepl_name_node node;
1023                 bool is_static;
1024                 uint32_t num_ips;
1025                 const struct wrepl_ip *ips;
1026         } records[] = {
1027                 {
1028                 .type           = WREPL_TYPE_GROUP,
1029                 .state          = WREPL_STATE_ACTIVE,
1030                 .node           = WREPL_NODE_B,
1031                 .is_static      = false,
1032                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1033                 .ips            = addresses_A_1,
1034                 },{
1035                 .type           = WREPL_TYPE_UNIQUE,
1036                 .state          = WREPL_STATE_ACTIVE,
1037                 .node           = WREPL_NODE_B,
1038                 .is_static      = false,
1039                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1040                 .ips            = addresses_A_1,
1041                 },{
1042                 .type           = WREPL_TYPE_UNIQUE,
1043                 .state          = WREPL_STATE_ACTIVE,
1044                 .node           = WREPL_NODE_B,
1045                 .is_static      = false,
1046                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1047                 .ips            = addresses_A_2,
1048                 },{
1049                 .type           = WREPL_TYPE_UNIQUE,
1050                 .state          = WREPL_STATE_ACTIVE,
1051                 .node           = WREPL_NODE_B,
1052                 .is_static      = true,
1053                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1054                 .ips            = addresses_A_1,
1055                 },{
1056                 .type           = WREPL_TYPE_UNIQUE,
1057                 .state          = WREPL_STATE_ACTIVE,
1058                 .node           = WREPL_NODE_B,
1059                 .is_static      = false,
1060                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1061                 .ips            = addresses_A_2,
1062                 },{
1063                 .type           = WREPL_TYPE_SGROUP,
1064                 .state          = WREPL_STATE_TOMBSTONE,
1065                 .node           = WREPL_NODE_B,
1066                 .is_static      = false,
1067                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1068                 .ips            = addresses_A_2,
1069                 },{
1070                 .type           = WREPL_TYPE_MHOMED,
1071                 .state          = WREPL_STATE_TOMBSTONE,
1072                 .node           = WREPL_NODE_B,
1073                 .is_static      = false,
1074                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1075                 .ips            = addresses_A_1,
1076                 },{
1077                 .type           = WREPL_TYPE_MHOMED,
1078                 .state          = WREPL_STATE_RELEASED,
1079                 .node           = WREPL_NODE_B,
1080                 .is_static      = false,
1081                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1082                 .ips            = addresses_A_2,
1083                 },{
1084                 .type           = WREPL_TYPE_SGROUP,
1085                 .state          = WREPL_STATE_ACTIVE,
1086                 .node           = WREPL_NODE_B,
1087                 .is_static      = false,
1088                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1089                 .ips            = addresses_A_1,
1090                 },{
1091                 .type           = WREPL_TYPE_SGROUP,
1092                 .state          = WREPL_STATE_ACTIVE,
1093                 .node           = WREPL_NODE_B,
1094                 .is_static      = false,
1095                 .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1096                 .ips            = addresses_A_3_4,
1097                 },{
1098                 .type           = WREPL_TYPE_SGROUP,
1099                 .state          = WREPL_STATE_TOMBSTONE,
1100                 .node           = WREPL_NODE_B,
1101                 .is_static      = false,
1102                 .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1103                 .ips            = addresses_B_3_4,
1104                 },{
1105                 /* the last one should always be a unique,tomstone record! */
1106                 .type           = WREPL_TYPE_UNIQUE,
1107                 .state          = WREPL_STATE_TOMBSTONE,
1108                 .node           = WREPL_NODE_B,
1109                 .is_static      = false,
1110                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1111                 .ips            = addresses_A_1,
1112                 }
1113         };
1114
1115         name.name       = "_SAME_OWNER_A";
1116         name.type       = 0;
1117         name.scope      = NULL;
1118
1119         wins_name_tmp   = NULL;
1120         wins_name_last  = &wins_name2;
1121         wins_name_cur   = &wins_name1;
1122
1123         for (j=0; ret && j < ARRAY_SIZE(types); j++) {
1124                 name.type = types[j];
1125                 torture_comment(tctx, "Test Replica Conflicts with same owner[%s] for %s\n",
1126                         nbt_name_string(ctx, &name), ctx->a.address);
1127
1128                 for(i=0; ret && i < ARRAY_SIZE(records); i++) {
1129                         wins_name_tmp   = wins_name_last;
1130                         wins_name_last  = wins_name_cur;
1131                         wins_name_cur   = wins_name_tmp;
1132
1133                         if (i > 0) {
1134                                 torture_comment(tctx, "%s,%s%s vs. %s,%s%s with %s ip(s) => %s\n",
1135                                         wrepl_name_type_string(records[i-1].type),
1136                                         wrepl_name_state_string(records[i-1].state),
1137                                         (records[i-1].is_static?",static":""),
1138                                         wrepl_name_type_string(records[i].type),
1139                                         wrepl_name_state_string(records[i].state),
1140                                         (records[i].is_static?",static":""),
1141                                         (records[i-1].ips==records[i].ips?"same":"different"),
1142                                         "REPLACE");
1143                         }
1144
1145                         wins_name_cur->name     = &name;
1146                         wins_name_cur->flags    = WREPL_NAME_FLAGS(records[i].type,
1147                                                                    records[i].state,
1148                                                                    records[i].node,
1149                                                                    records[i].is_static);
1150                         wins_name_cur->id       = ++ctx->a.max_version;
1151                         if (wins_name_cur->flags & 2) {
1152                                 wins_name_cur->addresses.addresses.num_ips = records[i].num_ips;
1153                                 wins_name_cur->addresses.addresses.ips     = discard_const(records[i].ips);
1154                         } else {
1155                                 wins_name_cur->addresses.ip = records[i].ips[0].ip;
1156                         }
1157                         wins_name_cur->unknown  = "255.255.255.255";
1158
1159                         ret &= test_wrepl_update_one(tctx, ctx, &ctx->a,wins_name_cur);
1160                         if (records[i].state == WREPL_STATE_RELEASED) {
1161                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_last, false);
1162                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_cur, false);
1163                         } else {
1164                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_cur, true);
1165                         }
1166
1167                         /* the first one is a cleanup run */
1168                         if (!ret && i == 0) ret = true;
1169
1170                         if (!ret) {
1171                                 torture_comment(tctx, "conflict handled wrong or record[%u]: %s\n", i, __location__);
1172                                 return ret;
1173                         }
1174                 }
1175         }
1176         return ret;
1177 }
1178
1179 static bool test_conflict_different_owner(struct torture_context *tctx, 
1180                                                                                   struct test_wrepl_conflict_conn *ctx)
1181 {
1182         bool ret = true;
1183         struct wrepl_wins_name wins_name1;
1184         struct wrepl_wins_name wins_name2;
1185         struct wrepl_wins_name *wins_name_r1;
1186         struct wrepl_wins_name *wins_name_r2;
1187         uint32_t i;
1188         struct {
1189                 const char *line; /* just better debugging */
1190                 struct nbt_name name;
1191                 const char *comment;
1192                 bool extra; /* not the worst case, this is an extra test */
1193                 bool cleanup;
1194                 struct {
1195                         struct wrepl_wins_owner *owner;
1196                         enum wrepl_name_type type;
1197                         enum wrepl_name_state state;
1198                         enum wrepl_name_node node;
1199                         bool is_static;
1200                         uint32_t num_ips;
1201                         const struct wrepl_ip *ips;
1202                         bool apply_expected;
1203                         bool sgroup_merge;
1204                         struct wrepl_wins_owner *merge_owner;
1205                         bool sgroup_cleanup;
1206                 } r1, r2;
1207         } records[] = {
1208         /* 
1209          * NOTE: the first record and the last applied one
1210          *       needs to be from the same owner,
1211          *       to not conflict in the next smbtorture run!!!
1212          */
1213         {
1214                 .line   = __location__,
1215                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1216                 .cleanup= true,
1217                 .r1     = {
1218                         .owner          = &ctx->b,
1219                         .type           = WREPL_TYPE_UNIQUE,
1220                         .state          = WREPL_STATE_TOMBSTONE,
1221                         .node           = WREPL_NODE_B,
1222                         .is_static      = false,
1223                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1224                         .ips            = addresses_B_1,
1225                         .apply_expected = true /* ignored */
1226                 },
1227                 .r2     = {
1228                         .owner          = &ctx->a,
1229                         .type           = WREPL_TYPE_UNIQUE,
1230                         .state          = WREPL_STATE_TOMBSTONE,
1231                         .node           = WREPL_NODE_B,
1232                         .is_static      = false,
1233                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1234                         .ips            = addresses_A_1,
1235                         .apply_expected = true /* ignored */
1236                 }
1237         },
1238
1239 /*
1240  * unique vs unique section
1241  */
1242         /* 
1243          * unique,active vs. unique,active
1244          * => should be replaced
1245          */
1246         {
1247                 .line   = __location__,
1248                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1249                 .r1     = {
1250                         .owner          = &ctx->a,
1251                         .type           = WREPL_TYPE_UNIQUE,
1252                         .state          = WREPL_STATE_ACTIVE,
1253                         .node           = WREPL_NODE_B,
1254                         .is_static      = false,
1255                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1256                         .ips            = addresses_A_1,
1257                         .apply_expected = true
1258                 },
1259                 .r2     = {
1260                         .owner          = &ctx->b,
1261                         .type           = WREPL_TYPE_UNIQUE,
1262                         .state          = WREPL_STATE_ACTIVE,
1263                         .node           = WREPL_NODE_B,
1264                         .is_static      = false,
1265                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1266                         .ips            = addresses_B_1,
1267                         .apply_expected = true
1268                 }
1269         },
1270
1271         /* 
1272          * unique,active vs. unique,tombstone
1273          * => should NOT be replaced
1274          */
1275         {
1276                 .line   = __location__,
1277                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1278                 .r1     = {
1279                         .owner          = &ctx->b,
1280                         .type           = WREPL_TYPE_UNIQUE,
1281                         .state          = WREPL_STATE_ACTIVE,
1282                         .node           = WREPL_NODE_B,
1283                         .is_static      = false,
1284                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1285                         .ips            = addresses_B_1,
1286                         .apply_expected = true
1287                 },
1288                 .r2     = {
1289                         .owner          = &ctx->a,
1290                         .type           = WREPL_TYPE_UNIQUE,
1291                         .state          = WREPL_STATE_TOMBSTONE,
1292                         .node           = WREPL_NODE_B,
1293                         .is_static      = false,
1294                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1295                         .ips            = addresses_B_1,
1296                         .apply_expected = false
1297                 }
1298         },
1299
1300         /* 
1301          * unique,released vs. unique,active
1302          * => should be replaced
1303          */
1304         {
1305                 .line   = __location__,
1306                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1307                 .r1     = {
1308                         .owner          = &ctx->b,
1309                         .type           = WREPL_TYPE_UNIQUE,
1310                         .state          = WREPL_STATE_RELEASED,
1311                         .node           = WREPL_NODE_B,
1312                         .is_static      = false,
1313                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1314                         .ips            = addresses_B_1,
1315                         .apply_expected = false
1316                 },
1317                 .r2     = {
1318                         .owner          = &ctx->a,
1319                         .type           = WREPL_TYPE_UNIQUE,
1320                         .state          = WREPL_STATE_ACTIVE,
1321                         .node           = WREPL_NODE_B,
1322                         .is_static      = false,
1323                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1324                         .ips            = addresses_A_1,
1325                         .apply_expected = true
1326                 }
1327         },
1328
1329         /* 
1330          * unique,released vs. unique,tombstone
1331          * => should be replaced
1332          */
1333         {
1334                 .line   = __location__,
1335                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1336                 .r1     = {
1337                         .owner          = &ctx->a,
1338                         .type           = WREPL_TYPE_UNIQUE,
1339                         .state          = WREPL_STATE_RELEASED,
1340                         .node           = WREPL_NODE_B,
1341                         .is_static      = false,
1342                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1343                         .ips            = addresses_A_1,
1344                         .apply_expected = false
1345                 },
1346                 .r2     = {
1347                         .owner          = &ctx->b,
1348                         .type           = WREPL_TYPE_UNIQUE,
1349                         .state          = WREPL_STATE_TOMBSTONE,
1350                         .node           = WREPL_NODE_B,
1351                         .is_static      = false,
1352                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1353                         .ips            = addresses_B_1,
1354                         .apply_expected = true
1355                 }
1356         },
1357
1358         /* 
1359          * unique,tombstone vs. unique,active
1360          * => should be replaced
1361          */
1362         {
1363                 .line   = __location__,
1364                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1365                 .r1     = {
1366                         .owner          = &ctx->b,
1367                         .type           = WREPL_TYPE_UNIQUE,
1368                         .state          = WREPL_STATE_TOMBSTONE,
1369                         .node           = WREPL_NODE_B,
1370                         .is_static      = false,
1371                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1372                         .ips            = addresses_B_1,
1373                         .apply_expected = true
1374                 },
1375                 .r2     = {
1376                         .owner          = &ctx->a,
1377                         .type           = WREPL_TYPE_UNIQUE,
1378                         .state          = WREPL_STATE_ACTIVE,
1379                         .node           = WREPL_NODE_B,
1380                         .is_static      = false,
1381                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1382                         .ips            = addresses_A_1,
1383                         .apply_expected = true
1384                 }
1385         },
1386
1387         /* 
1388          * unique,tombstone vs. unique,tombstone
1389          * => should be replaced
1390          */
1391         {
1392                 .line   = __location__,
1393                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1394                 .r1     = {
1395                         .owner          = &ctx->a,
1396                         .type           = WREPL_TYPE_UNIQUE,
1397                         .state          = WREPL_STATE_TOMBSTONE,
1398                         .node           = WREPL_NODE_B,
1399                         .is_static      = false,
1400                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1401                         .ips            = addresses_A_1,
1402                         .apply_expected = true
1403                 },
1404                 .r2     = {
1405                         .owner          = &ctx->b,
1406                         .type           = WREPL_TYPE_UNIQUE,
1407                         .state          = WREPL_STATE_TOMBSTONE,
1408                         .node           = WREPL_NODE_B,
1409                         .is_static      = false,
1410                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1411                         .ips            = addresses_B_1,
1412                         .apply_expected = true
1413                 }
1414         },
1415
1416
1417 /*
1418  * unique vs normal groups section,
1419  */
1420         /* 
1421          * unique,active vs. group,active
1422          * => should be replaced
1423          */
1424         {
1425                 .line   = __location__,
1426                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1427                 .r1     = {
1428                         .owner          = &ctx->b,
1429                         .type           = WREPL_TYPE_UNIQUE,
1430                         .state          = WREPL_STATE_ACTIVE,
1431                         .node           = WREPL_NODE_B,
1432                         .is_static      = false,
1433                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1434                         .ips            = addresses_B_1,
1435                         .apply_expected = true
1436                 },
1437                 .r2     = {
1438                         .owner          = &ctx->a,
1439                         .type           = WREPL_TYPE_GROUP,
1440                         .state          = WREPL_STATE_ACTIVE,
1441                         .node           = WREPL_NODE_B,
1442                         .is_static      = false,
1443                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1444                         .ips            = addresses_A_1,
1445                         .apply_expected = true
1446                 }
1447         },
1448
1449         /* 
1450          * unique,active vs. group,tombstone
1451          * => should NOT be replaced
1452          */
1453         {
1454                 .line   = __location__,
1455                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1456                 .r1     = {
1457                         .owner          = &ctx->a,
1458                         .type           = WREPL_TYPE_UNIQUE,
1459                         .state          = WREPL_STATE_ACTIVE,
1460                         .node           = WREPL_NODE_B,
1461                         .is_static      = false,
1462                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1463                         .ips            = addresses_A_1,
1464                         .apply_expected = true
1465                 },
1466                 .r2     = {
1467                         .owner          = &ctx->b,
1468                         .type           = WREPL_TYPE_GROUP,
1469                         .state          = WREPL_STATE_TOMBSTONE,
1470                         .node           = WREPL_NODE_B,
1471                         .is_static      = false,
1472                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1473                         .ips            = addresses_A_1,
1474                         .apply_expected = false
1475                 }
1476         },
1477
1478         /* 
1479          * unique,released vs. group,active
1480          * => should be replaced
1481          */
1482         {
1483                 .line   = __location__,
1484                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1485                 .r1     = {
1486                         .owner          = &ctx->a,
1487                         .type           = WREPL_TYPE_UNIQUE,
1488                         .state          = WREPL_STATE_RELEASED,
1489                         .node           = WREPL_NODE_B,
1490                         .is_static      = false,
1491                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1492                         .ips            = addresses_A_1,
1493                         .apply_expected = false
1494                 },
1495                 .r2     = {
1496                         .owner          = &ctx->b,
1497                         .type           = WREPL_TYPE_GROUP,
1498                         .state          = WREPL_STATE_ACTIVE,
1499                         .node           = WREPL_NODE_B,
1500                         .is_static      = false,
1501                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1502                         .ips            = addresses_B_1,
1503                         .apply_expected = true
1504                 }
1505         },
1506
1507         /* 
1508          * unique,released vs. group,tombstone
1509          * => should be replaced
1510          */
1511         {
1512                 .line   = __location__,
1513                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1514                 .r1     = {
1515                         .owner          = &ctx->b,
1516                         .type           = WREPL_TYPE_UNIQUE,
1517                         .state          = WREPL_STATE_RELEASED,
1518                         .node           = WREPL_NODE_B,
1519                         .is_static      = false,
1520                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1521                         .ips            = addresses_B_1,
1522                         .apply_expected = false
1523                 },
1524                 .r2     = {
1525                         .owner          = &ctx->a,
1526                         .type           = WREPL_TYPE_GROUP,
1527                         .state          = WREPL_STATE_TOMBSTONE,
1528                         .node           = WREPL_NODE_B,
1529                         .is_static      = false,
1530                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1531                         .ips            = addresses_A_1,
1532                         .apply_expected = true
1533                 }
1534         },
1535
1536         /* 
1537          * unique,tombstone vs. group,active
1538          * => should be replaced
1539          */
1540         {
1541                 .line   = __location__,
1542                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1543                 .r1     = {
1544                         .owner          = &ctx->a,
1545                         .type           = WREPL_TYPE_UNIQUE,
1546                         .state          = WREPL_STATE_TOMBSTONE,
1547                         .node           = WREPL_NODE_B,
1548                         .is_static      = false,
1549                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1550                         .ips            = addresses_A_1,
1551                         .apply_expected = true
1552                 },
1553                 .r2     = {
1554                         .owner          = &ctx->b,
1555                         .type           = WREPL_TYPE_GROUP,
1556                         .state          = WREPL_STATE_ACTIVE,
1557                         .node           = WREPL_NODE_B,
1558                         .is_static      = false,
1559                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1560                         .ips            = addresses_B_1,
1561                         .apply_expected = true
1562                 }
1563         },
1564
1565         /* 
1566          * unique,tombstone vs. group,tombstone
1567          * => should be replaced
1568          */
1569         {
1570                 .line   = __location__,
1571                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1572                 .r1     = {
1573                         .owner          = &ctx->b,
1574                         .type           = WREPL_TYPE_UNIQUE,
1575                         .state          = WREPL_STATE_TOMBSTONE,
1576                         .node           = WREPL_NODE_B,
1577                         .is_static      = false,
1578                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1579                         .ips            = addresses_B_1,
1580                         .apply_expected = true
1581                 },
1582                 .r2     = {
1583                         .owner          = &ctx->a,
1584                         .type           = WREPL_TYPE_GROUP,
1585                         .state          = WREPL_STATE_TOMBSTONE,
1586                         .node           = WREPL_NODE_B,
1587                         .is_static      = false,
1588                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1589                         .ips            = addresses_A_1,
1590                         .apply_expected = true
1591                 }
1592         },
1593
1594 /*
1595  * unique vs special groups section,
1596  */
1597         /* 
1598          * unique,active vs. sgroup,active
1599          * => should NOT be replaced
1600          */
1601         {
1602                 .line   = __location__,
1603                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1604                 .r1     = {
1605                         .owner          = &ctx->a,
1606                         .type           = WREPL_TYPE_UNIQUE,
1607                         .state          = WREPL_STATE_ACTIVE,
1608                         .node           = WREPL_NODE_B,
1609                         .is_static      = false,
1610                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1611                         .ips            = addresses_A_1,
1612                         .apply_expected = true
1613                 },
1614                 .r2     = {
1615                         .owner          = &ctx->b,
1616                         .type           = WREPL_TYPE_SGROUP,
1617                         .state          = WREPL_STATE_ACTIVE,
1618                         .node           = WREPL_NODE_B,
1619                         .is_static      = false,
1620                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1621                         .ips            = addresses_A_1,
1622                         .apply_expected = false
1623                 }
1624         },
1625
1626         /* 
1627          * unique,active vs. sgroup,tombstone
1628          * => should NOT be replaced
1629          */
1630         {
1631                 .line   = __location__,
1632                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1633                 .r1     = {
1634                         .owner          = &ctx->a,
1635                         .type           = WREPL_TYPE_UNIQUE,
1636                         .state          = WREPL_STATE_ACTIVE,
1637                         .node           = WREPL_NODE_B,
1638                         .is_static      = false,
1639                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1640                         .ips            = addresses_A_1,
1641                         .apply_expected = true
1642                 },
1643                 .r2     = {
1644                         .owner          = &ctx->b,
1645                         .type           = WREPL_TYPE_SGROUP,
1646                         .state          = WREPL_STATE_TOMBSTONE,
1647                         .node           = WREPL_NODE_B,
1648                         .is_static      = false,
1649                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1650                         .ips            = addresses_A_1,
1651                         .apply_expected = false
1652                 }
1653         },
1654
1655         /* 
1656          * unique,released vs. sgroup,active
1657          * => should be replaced
1658          */
1659         {
1660                 .line   = __location__,
1661                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1662                 .r1     = {
1663                         .owner          = &ctx->a,
1664                         .type           = WREPL_TYPE_UNIQUE,
1665                         .state          = WREPL_STATE_RELEASED,
1666                         .node           = WREPL_NODE_B,
1667                         .is_static      = false,
1668                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1669                         .ips            = addresses_A_1,
1670                         .apply_expected = false
1671                 },
1672                 .r2     = {
1673                         .owner          = &ctx->b,
1674                         .type           = WREPL_TYPE_SGROUP,
1675                         .state          = WREPL_STATE_ACTIVE,
1676                         .node           = WREPL_NODE_B,
1677                         .is_static      = false,
1678                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1679                         .ips            = addresses_B_3_4,
1680                         .apply_expected = true
1681                 }
1682         },
1683
1684         /* 
1685          * unique,released vs. sgroup,tombstone
1686          * => should be replaced
1687          */
1688         {
1689                 .line   = __location__,
1690                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1691                 .r1     = {
1692                         .owner          = &ctx->b,
1693                         .type           = WREPL_TYPE_UNIQUE,
1694                         .state          = WREPL_STATE_RELEASED,
1695                         .node           = WREPL_NODE_B,
1696                         .is_static      = false,
1697                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1698                         .ips            = addresses_B_1,
1699                         .apply_expected = false
1700                 },
1701                 .r2     = {
1702                         .owner          = &ctx->a,
1703                         .type           = WREPL_TYPE_SGROUP,
1704                         .state          = WREPL_STATE_TOMBSTONE,
1705                         .node           = WREPL_NODE_B,
1706                         .is_static      = false,
1707                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1708                         .ips            = addresses_A_3_4,
1709                         .apply_expected = true
1710                 }
1711         },
1712
1713         /* 
1714          * unique,tombstone vs. sgroup,active
1715          * => should be replaced
1716          */
1717         {
1718                 .line   = __location__,
1719                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1720                 .r1     = {
1721                         .owner          = &ctx->a,
1722                         .type           = WREPL_TYPE_UNIQUE,
1723                         .state          = WREPL_STATE_TOMBSTONE,
1724                         .node           = WREPL_NODE_B,
1725                         .is_static      = false,
1726                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1727                         .ips            = addresses_A_1,
1728                         .apply_expected = true
1729                 },
1730                 .r2     = {
1731                         .owner          = &ctx->b,
1732                         .type           = WREPL_TYPE_SGROUP,
1733                         .state          = WREPL_STATE_ACTIVE,
1734                         .node           = WREPL_NODE_B,
1735                         .is_static      = false,
1736                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1737                         .ips            = addresses_B_3_4,
1738                         .apply_expected = true
1739                 }
1740         },
1741
1742         /* 
1743          * unique,tombstone vs. sgroup,tombstone
1744          * => should be replaced
1745          */
1746         {
1747                 .line   = __location__,
1748                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1749                 .r1     = {
1750                         .owner          = &ctx->b,
1751                         .type           = WREPL_TYPE_UNIQUE,
1752                         .state          = WREPL_STATE_TOMBSTONE,
1753                         .node           = WREPL_NODE_B,
1754                         .is_static      = false,
1755                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1756                         .ips            = addresses_B_1,
1757                         .apply_expected = true
1758                 },
1759                 .r2     = {
1760                         .owner          = &ctx->a,
1761                         .type           = WREPL_TYPE_SGROUP,
1762                         .state          = WREPL_STATE_TOMBSTONE,
1763                         .node           = WREPL_NODE_B,
1764                         .is_static      = false,
1765                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1766                         .ips            = addresses_A_3_4,
1767                         .apply_expected = true
1768                 }
1769         },
1770
1771 /*
1772  * unique vs multi homed section,
1773  */
1774         /* 
1775          * unique,active vs. mhomed,active
1776          * => should be replaced
1777          */
1778         {
1779                 .line   = __location__,
1780                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1781                 .r1     = {
1782                         .owner          = &ctx->a,
1783                         .type           = WREPL_TYPE_UNIQUE,
1784                         .state          = WREPL_STATE_ACTIVE,
1785                         .node           = WREPL_NODE_B,
1786                         .is_static      = false,
1787                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1788                         .ips            = addresses_A_1,
1789                         .apply_expected = true
1790                 },
1791                 .r2     = {
1792                         .owner          = &ctx->b,
1793                         .type           = WREPL_TYPE_MHOMED,
1794                         .state          = WREPL_STATE_ACTIVE,
1795                         .node           = WREPL_NODE_B,
1796                         .is_static      = false,
1797                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1798                         .ips            = addresses_B_3_4,
1799                         .apply_expected = true
1800                 }
1801         },
1802
1803         /* 
1804          * unique,active vs. mhomed,tombstone
1805          * => should NOT be replaced
1806          */
1807         {
1808                 .line   = __location__,
1809                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1810                 .r1     = {
1811                         .owner          = &ctx->b,
1812                         .type           = WREPL_TYPE_UNIQUE,
1813                         .state          = WREPL_STATE_ACTIVE,
1814                         .node           = WREPL_NODE_B,
1815                         .is_static      = false,
1816                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1817                         .ips            = addresses_B_3_4,
1818                         .apply_expected = true
1819                 },
1820                 .r2     = {
1821                         .owner          = &ctx->a,
1822                         .type           = WREPL_TYPE_MHOMED,
1823                         .state          = WREPL_STATE_TOMBSTONE,
1824                         .node           = WREPL_NODE_B,
1825                         .is_static      = false,
1826                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1827                         .ips            = addresses_B_3_4,
1828                         .apply_expected = false
1829                 }
1830         },
1831
1832         /* 
1833          * unique,released vs. mhomed,active
1834          * => should be replaced
1835          */
1836         {
1837                 .line   = __location__,
1838                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1839                 .r1     = {
1840                         .owner          = &ctx->b,
1841                         .type           = WREPL_TYPE_UNIQUE,
1842                         .state          = WREPL_STATE_RELEASED,
1843                         .node           = WREPL_NODE_B,
1844                         .is_static      = false,
1845                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1846                         .ips            = addresses_B_1,
1847                         .apply_expected = false
1848                 },
1849                 .r2     = {
1850                         .owner          = &ctx->a,
1851                         .type           = WREPL_TYPE_MHOMED,
1852                         .state          = WREPL_STATE_ACTIVE,
1853                         .node           = WREPL_NODE_B,
1854                         .is_static      = false,
1855                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1856                         .ips            = addresses_A_3_4,
1857                         .apply_expected = true
1858                 }
1859         },
1860
1861         /* 
1862          * unique,released vs. mhomed,tombstone
1863          * => should be replaced
1864          */
1865         {
1866                 .line   = __location__,
1867                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1868                 .r1     = {
1869                         .owner          = &ctx->a,
1870                         .type           = WREPL_TYPE_UNIQUE,
1871                         .state          = WREPL_STATE_RELEASED,
1872                         .node           = WREPL_NODE_B,
1873                         .is_static      = false,
1874                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1875                         .ips            = addresses_A_1,
1876                         .apply_expected = false
1877                 },
1878                 .r2     = {
1879                         .owner          = &ctx->b,
1880                         .type           = WREPL_TYPE_MHOMED,
1881                         .state          = WREPL_STATE_TOMBSTONE,
1882                         .node           = WREPL_NODE_B,
1883                         .is_static      = false,
1884                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1885                         .ips            = addresses_B_3_4,
1886                         .apply_expected = true
1887                 }
1888         },
1889
1890         /* 
1891          * unique,tombstone vs. mhomed,active
1892          * => should be replaced
1893          */
1894         {
1895                 .line   = __location__,
1896                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1897                 .r1     = {
1898                         .owner          = &ctx->b,
1899                         .type           = WREPL_TYPE_UNIQUE,
1900                         .state          = WREPL_STATE_TOMBSTONE,
1901                         .node           = WREPL_NODE_B,
1902                         .is_static      = false,
1903                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1904                         .ips            = addresses_B_1,
1905                         .apply_expected = true
1906                 },
1907                 .r2     = {
1908                         .owner          = &ctx->a,
1909                         .type           = WREPL_TYPE_MHOMED,
1910                         .state          = WREPL_STATE_ACTIVE,
1911                         .node           = WREPL_NODE_B,
1912                         .is_static      = false,
1913                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1914                         .ips            = addresses_A_3_4,
1915                         .apply_expected = true
1916                 }
1917         },
1918
1919         /* 
1920          * unique,tombstone vs. mhomed,tombstone
1921          * => should be replaced
1922          */
1923         {
1924                 .line   = __location__,
1925                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1926                 .r1     = {
1927                         .owner          = &ctx->a,
1928                         .type           = WREPL_TYPE_UNIQUE,
1929                         .state          = WREPL_STATE_TOMBSTONE,
1930                         .node           = WREPL_NODE_B,
1931                         .is_static      = false,
1932                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1933                         .ips            = addresses_A_1,
1934                         .apply_expected = true
1935                 },
1936                 .r2     = {
1937                         .owner          = &ctx->b,
1938                         .type           = WREPL_TYPE_MHOMED,
1939                         .state          = WREPL_STATE_TOMBSTONE,
1940                         .node           = WREPL_NODE_B,
1941                         .is_static      = false,
1942                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1943                         .ips            = addresses_B_3_4,
1944                         .apply_expected = true
1945                 }
1946         },
1947
1948 /*
1949  * normal groups vs unique section,
1950  */
1951         /* 
1952          * group,active vs. unique,active
1953          * => should NOT be replaced
1954          */
1955         {
1956                 .line   = __location__,
1957                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1958                 .r1     = {
1959                         .owner          = &ctx->a,
1960                         .type           = WREPL_TYPE_GROUP,
1961                         .state          = WREPL_STATE_ACTIVE,
1962                         .node           = WREPL_NODE_B,
1963                         .is_static      = false,
1964                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1965                         .ips            = addresses_A_1,
1966                         .apply_expected = true
1967                 },
1968                 .r2     = {
1969                         .owner          = &ctx->b,
1970                         .type           = WREPL_TYPE_UNIQUE,
1971                         .state          = WREPL_STATE_ACTIVE,
1972                         .node           = WREPL_NODE_B,
1973                         .is_static      = false,
1974                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1975                         .ips            = addresses_A_1,
1976                         .apply_expected = false
1977                 }
1978         },
1979
1980         /* 
1981          * group,active vs. unique,tombstone
1982          * => should NOT be replaced
1983          */
1984         {
1985                 .line   = __location__,
1986                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1987                 .r1     = {
1988                         .owner          = &ctx->a,
1989                         .type           = WREPL_TYPE_GROUP,
1990                         .state          = WREPL_STATE_ACTIVE,
1991                         .node           = WREPL_NODE_B,
1992                         .is_static      = false,
1993                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1994                         .ips            = addresses_A_1,
1995                         .apply_expected = true
1996                 },
1997                 .r2     = {
1998                         .owner          = &ctx->b,
1999                         .type           = WREPL_TYPE_UNIQUE,
2000                         .state          = WREPL_STATE_TOMBSTONE,
2001                         .node           = WREPL_NODE_B,
2002                         .is_static      = false,
2003                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2004                         .ips            = addresses_A_1,
2005                         .apply_expected = false
2006                 }
2007         },
2008
2009         /* 
2010          * group,released vs. unique,active
2011          * => should NOT be replaced
2012          */
2013         {
2014                 .line   = __location__,
2015                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2016                 .r1     = {
2017                         .owner          = &ctx->a,
2018                         .type           = WREPL_TYPE_GROUP,
2019                         .state          = WREPL_STATE_RELEASED,
2020                         .node           = WREPL_NODE_B,
2021                         .is_static      = false,
2022                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2023                         .ips            = addresses_A_1,
2024                         .apply_expected = false
2025                 },
2026                 .r2     = {
2027                         .owner          = &ctx->b,
2028                         .type           = WREPL_TYPE_UNIQUE,
2029                         .state          = WREPL_STATE_ACTIVE,
2030                         .node           = WREPL_NODE_B,
2031                         .is_static      = false,
2032                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2033                         .ips            = addresses_A_1,
2034                         .apply_expected = false
2035                 }
2036         },
2037
2038         /* 
2039          * group,released vs. unique,tombstone
2040          * => should NOT be replaced
2041          */
2042         {
2043                 .line   = __location__,
2044                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2045                 .r1     = {
2046                         .owner          = &ctx->a,
2047                         .type           = WREPL_TYPE_GROUP,
2048                         .state          = WREPL_STATE_RELEASED,
2049                         .node           = WREPL_NODE_B,
2050                         .is_static      = false,
2051                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2052                         .ips            = addresses_A_1,
2053                         .apply_expected = false
2054                 },
2055                 .r2     = {
2056                         .owner          = &ctx->b,
2057                         .type           = WREPL_TYPE_UNIQUE,
2058                         .state          = WREPL_STATE_TOMBSTONE,
2059                         .node           = WREPL_NODE_B,
2060                         .is_static      = false,
2061                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2062                         .ips            = addresses_A_1,
2063                         .apply_expected = false
2064                 }
2065         },
2066
2067         /* 
2068          * group,tombstone vs. unique,active
2069          * => should NOT be replaced
2070          */
2071         {
2072                 .line   = __location__,
2073                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2074                 .r1     = {
2075                         .owner          = &ctx->a,
2076                         .type           = WREPL_TYPE_GROUP,
2077                         .state          = WREPL_STATE_TOMBSTONE,
2078                         .node           = WREPL_NODE_B,
2079                         .is_static      = false,
2080                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2081                         .ips            = addresses_A_1,
2082                         .apply_expected = true
2083                 },
2084                 .r2     = {
2085                         .owner          = &ctx->b,
2086                         .type           = WREPL_TYPE_UNIQUE,
2087                         .state          = WREPL_STATE_ACTIVE,
2088                         .node           = WREPL_NODE_B,
2089                         .is_static      = false,
2090                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2091                         .ips            = addresses_A_1,
2092                         .apply_expected = false
2093                 }
2094         },
2095
2096         /* 
2097          * group,tombstone vs. unique,tombstone
2098          * => should NOT be replaced
2099          */
2100         {
2101                 .line   = __location__,
2102                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2103                 .r1     = {
2104                         .owner          = &ctx->a,
2105                         .type           = WREPL_TYPE_GROUP,
2106                         .state          = WREPL_STATE_TOMBSTONE,
2107                         .node           = WREPL_NODE_B,
2108                         .is_static      = false,
2109                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2110                         .ips            = addresses_A_1,
2111                         .apply_expected = true
2112                 },
2113                 .r2     = {
2114                         .owner          = &ctx->b,
2115                         .type           = WREPL_TYPE_UNIQUE,
2116                         .state          = WREPL_STATE_TOMBSTONE,
2117                         .node           = WREPL_NODE_B,
2118                         .is_static      = false,
2119                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2120                         .ips            = addresses_A_1,
2121                         .apply_expected = false
2122                 }
2123         },
2124
2125 /*
2126  * normal groups vs normal groups section,
2127  */
2128         /* 
2129          * group,active vs. group,active
2130          * => should NOT be replaced
2131          */
2132         {
2133                 .line   = __location__,
2134                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2135                 .r1     = {
2136                         .owner          = &ctx->a,
2137                         .type           = WREPL_TYPE_GROUP,
2138                         .state          = WREPL_STATE_ACTIVE,
2139                         .node           = WREPL_NODE_B,
2140                         .is_static      = false,
2141                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2142                         .ips            = addresses_A_1,
2143                         .apply_expected = true
2144                 },
2145                 .r2     = {
2146                         .owner          = &ctx->b,
2147                         .type           = WREPL_TYPE_GROUP,
2148                         .state          = WREPL_STATE_ACTIVE,
2149                         .node           = WREPL_NODE_B,
2150                         .is_static      = false,
2151                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2152                         .ips            = addresses_A_1,
2153                         .apply_expected = false
2154                 }
2155         },
2156
2157         /* 
2158          * group,active vs. group,tombstone
2159          * => should NOT be replaced
2160          */
2161         {
2162                 .line   = __location__,
2163                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2164                 .r1     = {
2165                         .owner          = &ctx->a,
2166                         .type           = WREPL_TYPE_GROUP,
2167                         .state          = WREPL_STATE_ACTIVE,
2168                         .node           = WREPL_NODE_B,
2169                         .is_static      = false,
2170                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2171                         .ips            = addresses_A_1,
2172                         .apply_expected = true
2173                 },
2174                 .r2     = {
2175                         .owner          = &ctx->b,
2176                         .type           = WREPL_TYPE_GROUP,
2177                         .state          = WREPL_STATE_TOMBSTONE,
2178                         .node           = WREPL_NODE_B,
2179                         .is_static      = false,
2180                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2181                         .ips            = addresses_A_1,
2182                         .apply_expected = false
2183                 }
2184         },
2185
2186         /* 
2187          * group,released vs. group,active
2188          * => should be replaced
2189          */
2190         {
2191                 .line   = __location__,
2192                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2193                 .r1     = {
2194                         .owner          = &ctx->a,
2195                         .type           = WREPL_TYPE_GROUP,
2196                         .state          = WREPL_STATE_RELEASED,
2197                         .node           = WREPL_NODE_B,
2198                         .is_static      = false,
2199                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2200                         .ips            = addresses_A_1,
2201                         .apply_expected = false
2202                 },
2203                 .r2     = {
2204                         .owner          = &ctx->b,
2205                         .type           = WREPL_TYPE_GROUP,
2206                         .state          = WREPL_STATE_ACTIVE,
2207                         .node           = WREPL_NODE_B,
2208                         .is_static      = false,
2209                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2210                         .ips            = addresses_B_1,
2211                         .apply_expected = true
2212                 }
2213         },
2214
2215         /* 
2216          * group,released vs. group,tombstone
2217          * => should be replaced
2218          */
2219         {
2220                 .line   = __location__,
2221                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2222                 .r1     = {
2223                         .owner          = &ctx->a,
2224                         .type           = WREPL_TYPE_GROUP,
2225                         .state          = WREPL_STATE_RELEASED,
2226                         .node           = WREPL_NODE_B,
2227                         .is_static      = false,
2228                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2229                         .ips            = addresses_A_1,
2230                         .apply_expected = false
2231                 },
2232                 .r2     = {
2233                         .owner          = &ctx->b,
2234                         .type           = WREPL_TYPE_GROUP,
2235                         .state          = WREPL_STATE_TOMBSTONE,
2236                         .node           = WREPL_NODE_B,
2237                         .is_static      = false,
2238                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2239                         .ips            = addresses_B_1,
2240                         .apply_expected = true
2241                 }
2242         },
2243
2244         /* 
2245          * group,tombstone vs. group,active
2246          * => should be replaced
2247          */
2248         {
2249                 .line   = __location__,
2250                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2251                 .r1     = {
2252                         .owner          = &ctx->b,
2253                         .type           = WREPL_TYPE_GROUP,
2254                         .state          = WREPL_STATE_TOMBSTONE,
2255                         .node           = WREPL_NODE_B,
2256                         .is_static      = false,
2257                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2258                         .ips            = addresses_B_1,
2259                         .apply_expected = true
2260                 },
2261                 .r2     = {
2262                         .owner          = &ctx->a,
2263                         .type           = WREPL_TYPE_GROUP,
2264                         .state          = WREPL_STATE_ACTIVE,
2265                         .node           = WREPL_NODE_B,
2266                         .is_static      = false,
2267                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2268                         .ips            = addresses_A_1,
2269                         .apply_expected = true
2270                 }
2271         },
2272
2273         /* 
2274          * group,tombstone vs. group,tombstone
2275          * => should be replaced
2276          */
2277         {
2278                 .line   = __location__,
2279                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2280                 .r1     = {
2281                         .owner          = &ctx->a,
2282                         .type           = WREPL_TYPE_GROUP,
2283                         .state          = WREPL_STATE_TOMBSTONE,
2284                         .node           = WREPL_NODE_B,
2285                         .is_static      = false,
2286                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2287                         .ips            = addresses_A_1,
2288                         .apply_expected = true
2289                 },
2290                 .r2     = {
2291                         .owner          = &ctx->b,
2292                         .type           = WREPL_TYPE_GROUP,
2293                         .state          = WREPL_STATE_TOMBSTONE,
2294                         .node           = WREPL_NODE_B,
2295                         .is_static      = false,
2296                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2297                         .ips            = addresses_B_1,
2298                         .apply_expected = true
2299                 }
2300         },
2301
2302 /*
2303  * normal groups vs special groups section,
2304  */
2305         /* 
2306          * group,active vs. sgroup,active
2307          * => should NOT be replaced
2308          */
2309         {
2310                 .line   = __location__,
2311                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2312                 .r1     = {
2313                         .owner          = &ctx->b,
2314                         .type           = WREPL_TYPE_GROUP,
2315                         .state          = WREPL_STATE_ACTIVE,
2316                         .node           = WREPL_NODE_B,
2317                         .is_static      = false,
2318                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2319                         .ips            = addresses_B_1,
2320                         .apply_expected = true
2321                 },
2322                 .r2     = {
2323                         .owner          = &ctx->a,
2324                         .type           = WREPL_TYPE_SGROUP,
2325                         .state          = WREPL_STATE_ACTIVE,
2326                         .node           = WREPL_NODE_B,
2327                         .is_static      = false,
2328                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2329                         .ips            = addresses_B_1,
2330                         .apply_expected = false
2331                 }
2332         },
2333
2334         /* 
2335          * group,active vs. sgroup,tombstone
2336          * => should NOT be replaced
2337          */
2338         {
2339                 .line   = __location__,
2340                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2341                 .r1     = {
2342                         .owner          = &ctx->b,
2343                         .type           = WREPL_TYPE_GROUP,
2344                         .state          = WREPL_STATE_ACTIVE,
2345                         .node           = WREPL_NODE_B,
2346                         .is_static      = false,
2347                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2348                         .ips            = addresses_B_1,
2349                         .apply_expected = true
2350                 },
2351                 .r2     = {
2352                         .owner          = &ctx->a,
2353                         .type           = WREPL_TYPE_SGROUP,
2354                         .state          = WREPL_STATE_TOMBSTONE,
2355                         .node           = WREPL_NODE_B,
2356                         .is_static      = false,
2357                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2358                         .ips            = addresses_B_1,
2359                         .apply_expected = false
2360                 }
2361         },
2362
2363         /* 
2364          * group,released vs. sgroup,active
2365          * => should be replaced
2366          */
2367         {
2368                 .line   = __location__,
2369                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2370                 .r1     = {
2371                         .owner          = &ctx->a,
2372                         .type           = WREPL_TYPE_GROUP,
2373                         .state          = WREPL_STATE_RELEASED,
2374                         .node           = WREPL_NODE_B,
2375                         .is_static      = false,
2376                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2377                         .ips            = addresses_A_1,
2378                         .apply_expected = false
2379                 },
2380                 .r2     = {
2381                         .owner          = &ctx->b,
2382                         .type           = WREPL_TYPE_SGROUP,
2383                         .state          = WREPL_STATE_ACTIVE,
2384                         .node           = WREPL_NODE_B,
2385                         .is_static      = false,
2386                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2387                         .ips            = addresses_B_1,
2388                         .apply_expected = true
2389                 }
2390         },
2391
2392         /* 
2393          * group,released vs. sgroup,tombstone
2394          * => should NOT be replaced
2395          */
2396         {
2397                 .line   = __location__,
2398                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2399                 .r1     = {
2400                         .owner          = &ctx->b,
2401                         .type           = WREPL_TYPE_GROUP,
2402                         .state          = WREPL_STATE_RELEASED,
2403                         .node           = WREPL_NODE_B,
2404                         .is_static      = false,
2405                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2406                         .ips            = addresses_B_1,
2407                         .apply_expected = false
2408                 },
2409                 .r2     = {
2410                         .owner          = &ctx->a,
2411                         .type           = WREPL_TYPE_SGROUP,
2412                         .state          = WREPL_STATE_TOMBSTONE,
2413                         .node           = WREPL_NODE_B,
2414                         .is_static      = false,
2415                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2416                         .ips            = addresses_B_1,
2417                         .apply_expected = false
2418                 }
2419         },
2420
2421         /* 
2422          * group,tombstone vs. sgroup,active
2423          * => should be replaced
2424          */
2425         {
2426                 .line   = __location__,
2427                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2428                 .r1     = {
2429                         .owner          = &ctx->b,
2430                         .type           = WREPL_TYPE_GROUP,
2431                         .state          = WREPL_STATE_TOMBSTONE,
2432                         .node           = WREPL_NODE_B,
2433                         .is_static      = false,
2434                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2435                         .ips            = addresses_B_1,
2436                         .apply_expected = true
2437                 },
2438                 .r2     = {
2439                         .owner          = &ctx->a,
2440                         .type           = WREPL_TYPE_SGROUP,
2441                         .state          = WREPL_STATE_ACTIVE,
2442                         .node           = WREPL_NODE_B,
2443                         .is_static      = false,
2444                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2445                         .ips            = addresses_A_1,
2446                         .apply_expected = true
2447                 }
2448         },
2449
2450         /* 
2451          * group,tombstone vs. sgroup,tombstone
2452          * => should be replaced
2453          */
2454         {
2455                 .line   = __location__,
2456                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2457                 .r1     = {
2458                         .owner          = &ctx->a,
2459                         .type           = WREPL_TYPE_GROUP,
2460                         .state          = WREPL_STATE_TOMBSTONE,
2461                         .node           = WREPL_NODE_B,
2462                         .is_static      = false,
2463                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2464                         .ips            = addresses_A_1,
2465                         .apply_expected = true
2466                 },
2467                 .r2     = {
2468                         .owner          = &ctx->b,
2469                         .type           = WREPL_TYPE_SGROUP,
2470                         .state          = WREPL_STATE_TOMBSTONE,
2471                         .node           = WREPL_NODE_B,
2472                         .is_static      = false,
2473                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2474                         .ips            = addresses_B_1,
2475                         .apply_expected = true
2476                 }
2477         },
2478
2479 /*
2480  * normal groups vs multi homed section,
2481  */
2482         /* 
2483          * group,active vs. mhomed,active
2484          * => should NOT be replaced
2485          */
2486         {
2487                 .line   = __location__,
2488                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2489                 .r1     = {
2490                         .owner          = &ctx->b,
2491                         .type           = WREPL_TYPE_GROUP,
2492                         .state          = WREPL_STATE_ACTIVE,
2493                         .node           = WREPL_NODE_B,
2494                         .is_static      = false,
2495                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2496                         .ips            = addresses_B_1,
2497                         .apply_expected = true
2498                 },
2499                 .r2     = {
2500                         .owner          = &ctx->a,
2501                         .type           = WREPL_TYPE_MHOMED,
2502                         .state          = WREPL_STATE_ACTIVE,
2503                         .node           = WREPL_NODE_B,
2504                         .is_static      = false,
2505                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2506                         .ips            = addresses_B_1,
2507                         .apply_expected = false
2508                 }
2509         },
2510
2511         /* 
2512          * group,active vs. mhomed,tombstone
2513          * => should NOT be replaced
2514          */
2515         {
2516                 .line   = __location__,
2517                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2518                 .r1     = {
2519                         .owner          = &ctx->b,
2520                         .type           = WREPL_TYPE_GROUP,
2521                         .state          = WREPL_STATE_ACTIVE,
2522                         .node           = WREPL_NODE_B,
2523                         .is_static      = false,
2524                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2525                         .ips            = addresses_B_1,
2526                         .apply_expected = true
2527                 },
2528                 .r2     = {
2529                         .owner          = &ctx->a,
2530                         .type           = WREPL_TYPE_MHOMED,
2531                         .state          = WREPL_STATE_TOMBSTONE,
2532                         .node           = WREPL_NODE_B,
2533                         .is_static      = false,
2534                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2535                         .ips            = addresses_B_1,
2536                         .apply_expected = false
2537                 }
2538         },
2539
2540         /* 
2541          * group,released vs. mhomed,active
2542          * => should NOT be replaced
2543          */
2544         {
2545                 .line   = __location__,
2546                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2547                 .r1     = {
2548                         .owner          = &ctx->b,
2549                         .type           = WREPL_TYPE_GROUP,
2550                         .state          = WREPL_STATE_RELEASED,
2551                         .node           = WREPL_NODE_B,
2552                         .is_static      = false,
2553                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2554                         .ips            = addresses_B_1,
2555                         .apply_expected = false
2556                 },
2557                 .r2     = {
2558                         .owner          = &ctx->a,
2559                         .type           = WREPL_TYPE_MHOMED,
2560                         .state          = WREPL_STATE_ACTIVE,
2561                         .node           = WREPL_NODE_B,
2562                         .is_static      = false,
2563                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2564                         .ips            = addresses_B_1,
2565                         .apply_expected = false
2566                 }
2567         },
2568
2569         /* 
2570          * group,released vs. mhomed,tombstone
2571          * => should NOT be replaced
2572          */
2573         {
2574                 .line   = __location__,
2575                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2576                 .r1     = {
2577                         .owner          = &ctx->b,
2578                         .type           = WREPL_TYPE_GROUP,
2579                         .state          = WREPL_STATE_RELEASED,
2580                         .node           = WREPL_NODE_B,
2581                         .is_static      = false,
2582                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2583                         .ips            = addresses_B_1,
2584                         .apply_expected = false
2585                 },
2586                 .r2     = {
2587                         .owner          = &ctx->a,
2588                         .type           = WREPL_TYPE_MHOMED,
2589                         .state          = WREPL_STATE_TOMBSTONE,
2590                         .node           = WREPL_NODE_B,
2591                         .is_static      = false,
2592                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2593                         .ips            = addresses_B_1,
2594                         .apply_expected = false
2595                 }
2596         },
2597
2598         /* 
2599          * group,tombstone vs. mhomed,active
2600          * => should be replaced
2601          */
2602         {
2603                 .line   = __location__,
2604                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2605                 .r1     = {
2606                         .owner          = &ctx->b,
2607                         .type           = WREPL_TYPE_GROUP,
2608                         .state          = WREPL_STATE_TOMBSTONE,
2609                         .node           = WREPL_NODE_B,
2610                         .is_static      = false,
2611                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2612                         .ips            = addresses_B_1,
2613                         .apply_expected = true
2614                 },
2615                 .r2     = {
2616                         .owner          = &ctx->a,
2617                         .type           = WREPL_TYPE_MHOMED,
2618                         .state          = WREPL_STATE_ACTIVE,
2619                         .node           = WREPL_NODE_B,
2620                         .is_static      = false,
2621                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2622                         .ips            = addresses_A_1,
2623                         .apply_expected = true
2624                 }
2625         },
2626
2627         /* 
2628          * group,tombstone vs. mhomed,tombstone
2629          * => should be replaced
2630          */
2631         {
2632                 .line   = __location__,
2633                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2634                 .r1     = {
2635                         .owner          = &ctx->a,
2636                         .type           = WREPL_TYPE_GROUP,
2637                         .state          = WREPL_STATE_TOMBSTONE,
2638                         .node           = WREPL_NODE_B,
2639                         .is_static      = false,
2640                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2641                         .ips            = addresses_A_1,
2642                         .apply_expected = true
2643                 },
2644                 .r2     = {
2645                         .owner          = &ctx->b,
2646                         .type           = WREPL_TYPE_MHOMED,
2647                         .state          = WREPL_STATE_TOMBSTONE,
2648                         .node           = WREPL_NODE_B,
2649                         .is_static      = false,
2650                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2651                         .ips            = addresses_B_1,
2652                         .apply_expected = true
2653                 }
2654         },
2655
2656 /*
2657  * special groups vs unique section,
2658  */
2659         /* 
2660          * sgroup,active vs. unique,active
2661          * => should NOT be replaced
2662          */
2663         {
2664                 .line   = __location__,
2665                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2666                 .r1     = {
2667                         .owner          = &ctx->b,
2668                         .type           = WREPL_TYPE_SGROUP,
2669                         .state          = WREPL_STATE_ACTIVE,
2670                         .node           = WREPL_NODE_B,
2671                         .is_static      = false,
2672                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2673                         .ips            = addresses_B_1,
2674                         .apply_expected = true
2675                 },
2676                 .r2     = {
2677                         .owner          = &ctx->a,
2678                         .type           = WREPL_TYPE_UNIQUE,
2679                         .state          = WREPL_STATE_ACTIVE,
2680                         .node           = WREPL_NODE_B,
2681                         .is_static      = false,
2682                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2683                         .ips            = addresses_B_1,
2684                         .apply_expected = false
2685                 }
2686         },
2687
2688         /* 
2689          * sgroup,active vs. unique,tombstone
2690          * => should NOT be replaced
2691          */
2692         {
2693                 .line   = __location__,
2694                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2695                 .r1     = {
2696                         .owner          = &ctx->b,
2697                         .type           = WREPL_TYPE_SGROUP,
2698                         .state          = WREPL_STATE_ACTIVE,
2699                         .node           = WREPL_NODE_B,
2700                         .is_static      = false,
2701                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2702                         .ips            = addresses_B_1,
2703                         .apply_expected = true
2704                 },
2705                 .r2     = {
2706                         .owner          = &ctx->a,
2707                         .type           = WREPL_TYPE_UNIQUE,
2708                         .state          = WREPL_STATE_TOMBSTONE,
2709                         .node           = WREPL_NODE_B,
2710                         .is_static      = false,
2711                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2712                         .ips            = addresses_B_1,
2713                         .apply_expected = false
2714                 }
2715         },
2716
2717         /* 
2718          * sgroup,released vs. unique,active
2719          * => should be replaced
2720          */
2721         {
2722                 .line   = __location__,
2723                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2724                 .r1     = {
2725                         .owner          = &ctx->b,
2726                         .type           = WREPL_TYPE_SGROUP,
2727                         .state          = WREPL_STATE_RELEASED,
2728                         .node           = WREPL_NODE_B,
2729                         .is_static      = false,
2730                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2731                         .ips            = addresses_B_1,
2732                         .apply_expected = false
2733                 },
2734                 .r2     = {
2735                         .owner          = &ctx->a,
2736                         .type           = WREPL_TYPE_UNIQUE,
2737                         .state          = WREPL_STATE_ACTIVE,
2738                         .node           = WREPL_NODE_B,
2739                         .is_static      = false,
2740                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2741                         .ips            = addresses_A_1,
2742                         .apply_expected = true
2743                 }
2744         },
2745
2746         /* 
2747          * sgroup,released vs. unique,tombstone
2748          * => should be replaced
2749          */
2750         {
2751                 .line   = __location__,
2752                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2753                 .r1     = {
2754                         .owner          = &ctx->a,
2755                         .type           = WREPL_TYPE_SGROUP,
2756                         .state          = WREPL_STATE_RELEASED,
2757                         .node           = WREPL_NODE_B,
2758                         .is_static      = false,
2759                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2760                         .ips            = addresses_A_1,
2761                         .apply_expected = false
2762                 },
2763                 .r2     = {
2764                         .owner          = &ctx->b,
2765                         .type           = WREPL_TYPE_UNIQUE,
2766                         .state          = WREPL_STATE_TOMBSTONE,
2767                         .node           = WREPL_NODE_B,
2768                         .is_static      = false,
2769                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2770                         .ips            = addresses_B_1,
2771                         .apply_expected = true