r12608: Remove some unused #include lines.
[kai/samba-autobuild/.git] / source4 / torture / nbt / wins.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    NBT WINS server testing
5
6    Copyright (C) Andrew Tridgell 2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/socket/socket.h"
25
26 #define CHECK_VALUE(v, correct) do { \
27         if ((v) != (correct)) { \
28                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
29                        __location__, #v, v, correct); \
30                 ret = False; \
31         }} while (0)
32
33 #define CHECK_STRING(v, correct) do { \
34         if ((v) != (correct) && \
35             ((v)==NULL || (correct)==NULL || strcasecmp_m(v, correct) != 0)) { \
36                 printf("(%s) Incorrect value %s='%s' - should be '%s'\n", \
37                        __location__, #v, v, correct); \
38                 ret = False; \
39         }} while (0)
40
41 #define CHECK_NAME(_name, correct) do { \
42         CHECK_STRING((_name).name, (correct).name); \
43         CHECK_VALUE((_name).type, (correct).type); \
44         CHECK_STRING((_name).scope, (correct).scope); \
45 } while (0)
46
47
48 /*
49   test operations against a WINS server
50 */
51 static BOOL nbt_test_wins_name(TALLOC_CTX *mem_ctx, const char *address,
52                                struct nbt_name *name, uint16_t nb_flags)
53 {
54         struct nbt_name_register_wins io;
55         struct nbt_name_query query;
56         struct nbt_name_refresh_wins refresh;
57         struct nbt_name_release release;
58         NTSTATUS status;
59         struct nbt_name_socket *nbtsock = nbt_name_socket_init(mem_ctx, NULL);
60         BOOL ret = True;
61         const char *myaddress = talloc_strdup(mem_ctx, iface_best_ip(address));
62
63         /* we do the listen here to ensure the WINS server receives the packets from
64            the right IP */
65         socket_listen(nbtsock->sock, myaddress, 0, 0, 0);
66
67         printf("Testing name registration to WINS with name %s at %s nb_flags=0x%x\n", 
68                nbt_name_string(mem_ctx, name), myaddress, nb_flags);
69
70         printf("release the name\n");
71         release.in.name = *name;
72         release.in.dest_addr = address;
73         release.in.address = myaddress;
74         release.in.nb_flags = nb_flags;
75         release.in.broadcast = False;
76         release.in.timeout = 3;
77         release.in.retries = 0;
78
79         status = nbt_name_release(nbtsock, mem_ctx, &release);
80         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
81                 printf("No response from %s for name release\n", address);
82                 return False;
83         }
84         if (!NT_STATUS_IS_OK(status)) {
85                 printf("Bad response from %s for name query - %s\n",
86                        address, nt_errstr(status));
87                 return False;
88         }
89         CHECK_VALUE(release.out.rcode, 0);
90
91         printf("register the name\n");
92         io.in.name = *name;
93         io.in.wins_servers = str_list_make(mem_ctx, address, NULL);
94         io.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
95         io.in.nb_flags = nb_flags;
96         io.in.ttl = 300000;
97         
98         status = nbt_name_register_wins(nbtsock, mem_ctx, &io);
99         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
100                 printf("No response from %s for name register\n", address);
101                 return False;
102         }
103         if (!NT_STATUS_IS_OK(status)) {
104                 printf("Bad response from %s for name register - %s\n",
105                        address, nt_errstr(status));
106                 return False;
107         }
108         
109         CHECK_STRING(io.out.wins_server, address);
110         CHECK_VALUE(io.out.rcode, 0);
111
112         if (name->type != NBT_NAME_MASTER &&
113             name->type != NBT_NAME_LOGON && 
114             name->type != NBT_NAME_BROWSER && 
115             (nb_flags & NBT_NM_GROUP)) {
116                 printf("Try to register as non-group\n");
117                 io.in.nb_flags &= ~NBT_NM_GROUP;
118                 status = nbt_name_register_wins(nbtsock, mem_ctx, &io);
119                 if (!NT_STATUS_IS_OK(status)) {
120                         printf("Bad response from %s for name register - %s\n",
121                                address, nt_errstr(status));
122                         return False;
123                 }
124                 CHECK_VALUE(io.out.rcode, NBT_RCODE_ACT);
125         }
126
127         printf("query the name to make sure its there\n");
128         query.in.name = *name;
129         query.in.dest_addr = address;
130         query.in.broadcast = False;
131         query.in.wins_lookup = True;
132         query.in.timeout = 3;
133         query.in.retries = 0;
134
135         status = nbt_name_query(nbtsock, mem_ctx, &query);
136         if (name->type == NBT_NAME_MASTER) {
137                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
138                         printf("Bad response from %s for name query - %s\n",
139                                address, nt_errstr(status));
140                         return False;
141                 }
142                 return ret;
143         }
144         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
145                 printf("No response from %s for name query\n", address);
146                 return False;
147         }
148         if (!NT_STATUS_IS_OK(status)) {
149                 printf("Bad response from %s for name query - %s\n",
150                        address, nt_errstr(status));
151                 return False;
152         }
153         
154         CHECK_NAME(query.out.name, *name);
155         CHECK_VALUE(query.out.num_addrs, 1);
156         if (name->type != NBT_NAME_LOGON &&
157             (nb_flags & NBT_NM_GROUP)) {
158                 CHECK_STRING(query.out.reply_addrs[0], "255.255.255.255");
159         } else {
160                 CHECK_STRING(query.out.reply_addrs[0], myaddress);
161         }
162
163
164         query.in.name.name = strupper_talloc(mem_ctx, name->name);
165         if (query.in.name.name &&
166             strcmp(query.in.name.name, name->name) != 0) {
167                 printf("check case sensitivity\n");
168                 status = nbt_name_query(nbtsock, mem_ctx, &query);
169                 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
170                         printf("No response from %s for name query\n", address);
171                         return False;
172                 }
173                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
174                         printf("Bad response from %s for name query - %s\n",
175                                address, nt_errstr(status));
176                         return False;
177                 }
178         }
179
180         query.in.name = *name;
181         if (name->scope) {
182                 query.in.name.scope = strupper_talloc(mem_ctx, name->scope);
183         }
184         if (query.in.name.scope &&
185             strcmp(query.in.name.scope, name->scope) != 0) {
186                 printf("check case sensitivity on scope\n");
187                 status = nbt_name_query(nbtsock, mem_ctx, &query);
188                 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
189                         printf("No response from %s for name query\n", address);
190                         return False;
191                 }
192                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
193                         printf("Bad response from %s for name query - %s\n",
194                                address, nt_errstr(status));
195                         return False;
196                 }
197         }
198
199         printf("refresh the name\n");
200         refresh.in.name = *name;
201         refresh.in.wins_servers = str_list_make(mem_ctx, address, NULL);
202         refresh.in.addresses = str_list_make(mem_ctx, myaddress, NULL);
203         refresh.in.nb_flags = nb_flags;
204         refresh.in.ttl = 12345;
205         
206         status = nbt_name_refresh_wins(nbtsock, mem_ctx, &refresh);
207         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
208                 printf("No response from %s for name refresh\n", address);
209                 return False;
210         }
211         if (!NT_STATUS_IS_OK(status)) {
212                 printf("Bad response from %s for name refresh - %s\n",
213                        address, nt_errstr(status));
214                 return False;
215         }
216         
217         CHECK_STRING(refresh.out.wins_server, address);
218         CHECK_VALUE(refresh.out.rcode, 0);
219
220         printf("release the name\n");
221         release.in.name = *name;
222         release.in.dest_addr = address;
223         release.in.address = myaddress;
224         release.in.nb_flags = nb_flags;
225         release.in.broadcast = False;
226         release.in.timeout = 3;
227         release.in.retries = 0;
228
229         status = nbt_name_release(nbtsock, mem_ctx, &release);
230         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
231                 printf("No response from %s for name release\n", address);
232                 return False;
233         }
234         if (!NT_STATUS_IS_OK(status)) {
235                 printf("Bad response from %s for name query - %s\n",
236                        address, nt_errstr(status));
237                 return False;
238         }
239         
240         CHECK_NAME(release.out.name, *name);
241         CHECK_VALUE(release.out.rcode, 0);
242
243
244         printf("release again\n");
245         status = nbt_name_release(nbtsock, mem_ctx, &release);
246         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
247                 printf("No response from %s for name release\n", address);
248                 return False;
249         }
250         if (!NT_STATUS_IS_OK(status)) {
251                 printf("Bad response from %s for name query - %s\n",
252                        address, nt_errstr(status));
253                 return False;
254         }
255         
256         CHECK_NAME(release.out.name, *name);
257         CHECK_VALUE(release.out.rcode, 0);
258
259
260         printf("query the name to make sure its gone\n");
261         query.in.name = *name;
262         status = nbt_name_query(nbtsock, mem_ctx, &query);
263         if (name->type != NBT_NAME_LOGON &&
264             (nb_flags & NBT_NM_GROUP)) {
265                 if (!NT_STATUS_IS_OK(status)) {
266                         printf("ERROR: Name query failed after group release - %s\n",
267                                nt_errstr(status));
268                         return False;
269                 }
270         } else {
271                 if (NT_STATUS_IS_OK(status)) {
272                         printf("ERROR: Name query success after release\n");
273                         return False;
274                 }
275                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
276                         printf("Incorrect response to name query - %s\n", nt_errstr(status));
277                         return False;
278                 }
279         }
280         
281         return ret;
282 }
283
284
285
286 /*
287   test operations against a WINS server
288 */
289 static BOOL nbt_test_wins(TALLOC_CTX *mem_ctx, const char *address)
290 {
291         struct nbt_name name;
292         BOOL ret = True;
293         uint32_t r = (uint32_t)(random() % (100000));
294
295         name.name = talloc_asprintf(mem_ctx, "_TORTURE-%5u", r);
296                                     
297         name.type = NBT_NAME_CLIENT;
298         name.scope = NULL;
299         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
300
301         name.type = NBT_NAME_MASTER;
302         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
303
304         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
305
306         name.type = NBT_NAME_LOGON;
307         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
308
309         name.type = NBT_NAME_BROWSER;
310         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
311
312         name.scope = "example";
313         name.type = 0x72;
314         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
315
316         name.scope = "example";
317         name.type = 0x71;
318         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
319
320         name.scope = "foo.example.com";
321         name.type = 0x72;
322         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
323
324         name.name = talloc_asprintf(mem_ctx, "_T\01-%5u.foo", r);
325         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
326
327         name.name = "";
328         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
329
330         name.name = talloc_asprintf(mem_ctx, ".");
331         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
332
333         name.name = talloc_asprintf(mem_ctx, "%5u-\377\200\300FOO", r);
334         ret &= nbt_test_wins_name(mem_ctx, address, &name, NBT_NODE_H);
335
336         return ret;
337 }
338
339 /*
340   test WINS operations
341 */
342 BOOL torture_nbt_wins(void)
343 {
344         const char *address;
345         struct nbt_name name;
346         TALLOC_CTX *mem_ctx = talloc_new(NULL);
347         NTSTATUS status;
348         BOOL ret = True;
349         
350         make_nbt_name_server(&name, lp_parm_string(-1, "torture", "host"));
351
352         /* do an initial name resolution to find its IP */
353         status = resolve_name(&name, mem_ctx, &address, NULL);
354         if (!NT_STATUS_IS_OK(status)) {
355                 printf("Failed to resolve %s - %s\n",
356                        name.name, nt_errstr(status));
357                 talloc_free(mem_ctx);
358                 return False;
359         }
360
361         ret &= nbt_test_wins(mem_ctx, address);
362
363         talloc_free(mem_ctx);
364
365         return ret;
366 }