r26402: Require a talloc context in libnetif.
[jelmer/samba4-debian.git] / source / 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 3 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, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "lib/socket/socket.h"
24 #include "libcli/resolve/resolve.h"
25 #include "system/network.h"
26 #include "lib/socket/netif.h"
27 #include "librpc/gen_ndr/ndr_nbt.h"
28 #include "torture/torture.h"
29 #include "torture/nbt/proto.h"
30 #include "param/param.h"
31
32 #define CHECK_VALUE(tctx, v, correct) \
33         torture_assert_int_equal(tctx, v, correct, "Incorrect value")
34
35 #define CHECK_STRING(tctx, v, correct) \
36         torture_assert_casestr_equal(tctx, v, correct, "Incorrect value")
37
38 #define CHECK_NAME(tctx, _name, correct) do { \
39         CHECK_STRING(tctx, (_name).name, (correct).name); \
40         CHECK_VALUE(tctx, (uint8_t)(_name).type, (uint8_t)(correct).type); \
41         CHECK_STRING(tctx, (_name).scope, (correct).scope); \
42 } while (0)
43
44
45 /*
46   test operations against a WINS server
47 */
48 static bool nbt_test_wins_name(struct torture_context *tctx, const char *address,
49                                struct nbt_name *name, uint16_t nb_flags)
50 {
51         struct nbt_name_register_wins io;
52         struct nbt_name_query query;
53         struct nbt_name_refresh_wins refresh;
54         struct nbt_name_release release;
55         NTSTATUS status;
56         struct nbt_name_socket *nbtsock = nbt_name_socket_init(tctx, NULL);
57         const char *myaddress;
58         struct socket_address *socket_address;
59         struct interface *ifaces;
60
61         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
62
63         myaddress = talloc_strdup(tctx, iface_best_ip(ifaces, address));
64
65         socket_address = socket_address_from_strings(tctx, 
66                                                      nbtsock->sock->backend_name,
67                                                      myaddress, 0);
68         torture_assert(tctx, socket_address != NULL, 
69                                    "Error getting address");
70
71         /* we do the listen here to ensure the WINS server receives the packets from
72            the right IP */
73         status = socket_listen(nbtsock->sock, socket_address, 0, 0);
74         torture_assert_ntstatus_ok(tctx, status, 
75                                                            "socket_listen for WINS failed");
76         talloc_free(socket_address);
77
78         torture_comment(tctx, "Testing name registration to WINS with name %s at %s nb_flags=0x%x\n", 
79                nbt_name_string(tctx, name), myaddress, nb_flags);
80
81         torture_comment(tctx, "release the name\n");
82         release.in.name = *name;
83         release.in.dest_addr = address;
84         release.in.address = myaddress;
85         release.in.nb_flags = nb_flags;
86         release.in.broadcast = false;
87         release.in.timeout = 3;
88         release.in.retries = 0;
89
90         status = nbt_name_release(nbtsock, tctx, &release);
91         torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
92         CHECK_VALUE(tctx, release.out.rcode, 0);
93
94         torture_comment(tctx, "register the name\n");
95         io.in.name = *name;
96         io.in.wins_servers = str_list_make(tctx, address, NULL);
97         io.in.addresses = str_list_make(tctx, myaddress, NULL);
98         io.in.nb_flags = nb_flags;
99         io.in.ttl = 300000;
100         
101         status = nbt_name_register_wins(nbtsock, tctx, &io);
102         torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name register", address));
103         
104         CHECK_STRING(tctx, io.out.wins_server, address);
105         CHECK_VALUE(tctx, io.out.rcode, 0);
106
107         if (name->type != NBT_NAME_MASTER &&
108             name->type != NBT_NAME_LOGON && 
109             name->type != NBT_NAME_BROWSER && 
110             (nb_flags & NBT_NM_GROUP)) {
111                 torture_comment(tctx, "Try to register as non-group\n");
112                 io.in.nb_flags &= ~NBT_NM_GROUP;
113                 status = nbt_name_register_wins(nbtsock, tctx, &io);
114                 torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name register\n",
115                         address));
116                 CHECK_VALUE(tctx, io.out.rcode, NBT_RCODE_ACT);
117         }
118
119         torture_comment(tctx, "query the name to make sure its there\n");
120         query.in.name = *name;
121         query.in.dest_addr = address;
122         query.in.dest_port = lp_nbt_port(tctx->lp_ctx);
123         query.in.broadcast = false;
124         query.in.wins_lookup = true;
125         query.in.timeout = 3;
126         query.in.retries = 0;
127
128         status = nbt_name_query(nbtsock, tctx, &query);
129         if (name->type == NBT_NAME_MASTER) {
130                 torture_assert_ntstatus_equal(
131                           tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, 
132                           talloc_asprintf(tctx, "Bad response from %s for name query", address));
133                 return true;
134         }
135         torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
136         
137         CHECK_NAME(tctx, query.out.name, *name);
138         CHECK_VALUE(tctx, query.out.num_addrs, 1);
139         if (name->type != NBT_NAME_LOGON &&
140             (nb_flags & NBT_NM_GROUP)) {
141                 CHECK_STRING(tctx, query.out.reply_addrs[0], "255.255.255.255");
142         } else {
143                 CHECK_STRING(tctx, query.out.reply_addrs[0], myaddress);
144         }
145
146
147         query.in.name.name = strupper_talloc(tctx, name->name);
148         if (query.in.name.name &&
149             strcmp(query.in.name.name, name->name) != 0) {
150                 torture_comment(tctx, "check case sensitivity\n");
151                 status = nbt_name_query(nbtsock, tctx, &query);
152                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, talloc_asprintf(tctx, "Bad response from %s for name query", address));
153         }
154
155         query.in.name = *name;
156         if (name->scope) {
157                 query.in.name.scope = strupper_talloc(tctx, name->scope);
158         }
159         if (query.in.name.scope &&
160             strcmp(query.in.name.scope, name->scope) != 0) {
161                 torture_comment(tctx, "check case sensitivity on scope\n");
162                 status = nbt_name_query(nbtsock, tctx, &query);
163                 torture_assert_ntstatus_equal(tctx, status, NT_STATUS_OBJECT_NAME_NOT_FOUND, talloc_asprintf(tctx, "Bad response from %s for name query", address));
164         }
165
166         torture_comment(tctx, "refresh the name\n");
167         refresh.in.name = *name;
168         refresh.in.wins_servers = str_list_make(tctx, address, NULL);
169         refresh.in.addresses = str_list_make(tctx, myaddress, NULL);
170         refresh.in.nb_flags = nb_flags;
171         refresh.in.ttl = 12345;
172         
173         status = nbt_name_refresh_wins(nbtsock, tctx, &refresh);
174         torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name refresh", address));
175         
176         CHECK_STRING(tctx, refresh.out.wins_server, address);
177         CHECK_VALUE(tctx, refresh.out.rcode, 0);
178
179         torture_comment(tctx, "release the name\n");
180         release.in.name = *name;
181         release.in.dest_addr = address;
182         release.in.address = myaddress;
183         release.in.nb_flags = nb_flags;
184         release.in.broadcast = false;
185         release.in.timeout = 3;
186         release.in.retries = 0;
187
188         status = nbt_name_release(nbtsock, tctx, &release);
189         torture_assert_ntstatus_ok(tctx, status, talloc_asprintf(tctx, "Bad response from %s for name query", address));
190         
191         CHECK_NAME(tctx, release.out.name, *name);
192         CHECK_VALUE(tctx, release.out.rcode, 0);
193
194         torture_comment(tctx, "release again\n");
195         status = nbt_name_release(nbtsock, tctx, &release);
196         torture_assert_ntstatus_ok(tctx, status, 
197                                 talloc_asprintf(tctx, "Bad response from %s for name query",
198                        address));
199         
200         CHECK_NAME(tctx, release.out.name, *name);
201         CHECK_VALUE(tctx, release.out.rcode, 0);
202
203
204         torture_comment(tctx, "query the name to make sure its gone\n");
205         query.in.name = *name;
206         status = nbt_name_query(nbtsock, tctx, &query);
207         if (name->type != NBT_NAME_LOGON &&
208             (nb_flags & NBT_NM_GROUP)) {
209                 torture_assert_ntstatus_ok(tctx, status, 
210                                 "ERROR: Name query failed after group release");
211         } else {
212                 torture_assert_ntstatus_equal(tctx, status, 
213                                                                           NT_STATUS_OBJECT_NAME_NOT_FOUND,
214                                 "Incorrect response to name query");
215         }
216         
217         return true;
218 }
219
220
221
222 /*
223   test operations against a WINS server
224 */
225 static bool nbt_test_wins(struct torture_context *tctx)
226 {
227         struct nbt_name name;
228         uint32_t r = (uint32_t)(random() % (100000));
229         const char *address;
230         bool ret = true;
231
232         if (!torture_nbt_get_name(tctx, &name, &address))
233                 return false;
234
235         name.name = talloc_asprintf(tctx, "_TORTURE-%5u", r);
236
237         name.type = NBT_NAME_CLIENT;
238         name.scope = NULL;
239         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
240
241         name.type = NBT_NAME_MASTER;
242         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
243
244         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
245
246         name.type = NBT_NAME_SERVER;
247         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
248
249         name.type = NBT_NAME_LOGON;
250         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
251
252         name.type = NBT_NAME_BROWSER;
253         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
254
255         name.type = NBT_NAME_PDC;
256         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
257
258         name.type = 0xBF;
259         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
260
261         name.type = 0xBE;
262         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
263
264         name.scope = "example";
265         name.type = 0x72;
266         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
267
268         name.scope = "example";
269         name.type = 0x71;
270         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H | NBT_NM_GROUP);
271
272         name.scope = "foo.example.com";
273         name.type = 0x72;
274         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
275
276         name.name = talloc_asprintf(tctx, "_T\01-%5u.foo", r);
277         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
278
279         name.name = "";
280         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
281
282         name.name = talloc_asprintf(tctx, ".");
283         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
284
285         name.name = talloc_asprintf(tctx, "%5u-\377\200\300FOO", r);
286         ret &= nbt_test_wins_name(tctx, address, &name, NBT_NODE_H);
287
288         return ret;
289 }
290
291 /*
292   test WINS operations
293 */
294 struct torture_suite *torture_nbt_wins(TALLOC_CTX *mem_ctx)
295 {
296         struct torture_suite *suite = torture_suite_create(mem_ctx, "WINS");
297
298         torture_suite_add_simple_test(suite, "wins", nbt_test_wins);
299
300         return suite;
301 }