9a29ef0fec65ce89c6e9387aadb95a50e4c43429
[bbaumbach/samba-autobuild/.git] / source4 / torture / local / socket.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    local testing of socket routines.
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 #include "lib/events/events.h"
26 #include "system/network.h"
27 #include "netif/netif.h"
28 #include "torture/torture.h"
29
30 #define CHECK_STATUS(status, correct) do { \
31         if (!NT_STATUS_EQUAL(status, correct)) { \
32                 printf("(%s) Incorrect status %s - should be %s\n", \
33                        __location__, nt_errstr(status), nt_errstr(correct)); \
34                 ret = False; \
35                 goto done; \
36         }} while (0)
37
38
39 /*
40   basic testing of udp routines
41 */
42 static BOOL test_udp(TALLOC_CTX *mem_ctx)
43 {
44         struct socket_context *sock1, *sock2;
45         NTSTATUS status;
46         struct socket_address *srv_addr, *from_addr, *localhost;
47         size_t size = 100 + (random() % 100);
48         DATA_BLOB blob, blob2;
49         size_t sent, nread;
50         BOOL ret = True;
51
52         printf("TESTING UDP SOCKETS\n");
53
54         status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock1, 0);
55         CHECK_STATUS(status, NT_STATUS_OK);
56         talloc_steal(mem_ctx, sock1);
57
58         status = socket_create("ip", SOCKET_TYPE_DGRAM, &sock2, 0);
59         CHECK_STATUS(status, NT_STATUS_OK);
60         talloc_steal(mem_ctx, sock2);
61
62         localhost = socket_address_from_strings(sock1, sock1->backend_name, 
63                                                 iface_best_ip("127.0.0.1"), 0);
64         if (!localhost) {
65                 return False;
66         }
67
68         status = socket_listen(sock1, localhost, 0, 0);
69         CHECK_STATUS(status, NT_STATUS_OK);
70
71         srv_addr = socket_get_my_addr(sock1, mem_ctx);
72         if (srv_addr == NULL || strcmp(srv_addr->addr, iface_best_ip("127.0.0.1")) != 0) {
73                 printf("Expected server address of %s but got %s\n",
74                        iface_best_ip("127.0.0.1"), srv_addr ? srv_addr->addr : NULL);
75                 return False;
76         }
77
78         printf("server port is %d\n", srv_addr->port);
79
80         blob  = data_blob_talloc(mem_ctx, NULL, size);
81         blob2 = data_blob_talloc(mem_ctx, NULL, size);
82         generate_random_buffer(blob.data, blob.length);
83
84         sent = size;
85         status = socket_sendto(sock2, &blob, &sent, 0, srv_addr);
86         CHECK_STATUS(status, NT_STATUS_OK);
87
88         status = socket_recvfrom(sock1, blob2.data, size, &nread, 0, 
89                                  sock1, &from_addr);
90         CHECK_STATUS(status, NT_STATUS_OK);
91
92         if (strcmp(from_addr->addr, srv_addr->addr) != 0) {
93                 printf("Unexpected recvfrom addr %s\n", from_addr->addr);
94                 ret = False;
95         }
96         if (nread != size) {
97                 printf("Unexpected recvfrom size %d should be %d\n", (int)nread, (int)size);
98                 ret = False;
99         }
100
101         if (memcmp(blob2.data, blob.data, size) != 0) {
102                 printf("Bad data in recvfrom\n");
103                 ret = False;
104         }
105
106         generate_random_buffer(blob.data, blob.length);
107         status = socket_sendto(sock1, &blob, &sent, 0, from_addr);
108         CHECK_STATUS(status, NT_STATUS_OK);
109
110         status = socket_recvfrom(sock2, blob2.data, size, &nread, 0, 
111                                  sock2, &from_addr);
112         CHECK_STATUS(status, NT_STATUS_OK);
113         if (strcmp(from_addr->addr, srv_addr->addr) != 0) {
114                 printf("Unexpected recvfrom addr %s\n", from_addr->addr);
115                 ret = False;
116         }
117         if (nread != size) {
118                 printf("Unexpected recvfrom size %d should be %d\n", (int)nread, (int)size);
119                 ret = False;
120         }
121         if (from_addr->port != srv_addr->port) {
122                 printf("Unexpected recvfrom port %d should be %d\n", 
123                        from_addr->port, srv_addr->port);
124                 ret = False;
125         }
126         if (memcmp(blob2.data, blob.data, size) != 0) {
127                 printf("Bad data in recvfrom\n");
128                 ret = False;
129         }
130
131 done:
132         talloc_free(sock1);
133         talloc_free(sock2);
134
135         return ret;
136 }
137
138 /*
139   basic testing of tcp routines
140 */
141 static BOOL test_tcp(TALLOC_CTX *mem_ctx)
142 {
143         struct socket_context *sock1, *sock2, *sock3;
144         NTSTATUS status;
145         struct socket_address *srv_addr, *from_addr, *localhost;
146         size_t size = 100 + (random() % 100);
147         DATA_BLOB blob, blob2;
148         size_t sent, nread;
149         BOOL ret = True;
150         struct event_context *ev = event_context_init(mem_ctx);
151
152         printf("TESTING TCP SOCKETS\n");
153
154         status = socket_create("ip", SOCKET_TYPE_STREAM, &sock1, 0);
155         CHECK_STATUS(status, NT_STATUS_OK);
156         talloc_steal(mem_ctx, sock1);
157
158         status = socket_create("ip", SOCKET_TYPE_STREAM, &sock2, 0);
159         CHECK_STATUS(status, NT_STATUS_OK);
160         talloc_steal(mem_ctx, sock2);
161
162         localhost = socket_address_from_strings(sock1, sock1->backend_name, 
163                                                 iface_best_ip("127.0.0.1"), 0);
164         if (!localhost) {
165                 return False;
166         }
167
168         status = socket_listen(sock1, localhost, 0, 0);
169         CHECK_STATUS(status, NT_STATUS_OK);
170
171         srv_addr = socket_get_my_addr(sock1, mem_ctx);
172         if (srv_addr == NULL || !srv_addr->addr) {
173                 printf("Unexpected socket_get_my_addr NULL\n");
174                 return False;
175         }
176
177         if (strcmp(srv_addr->addr, iface_best_ip("127.0.0.1")) != 0) {
178                 printf("Expected server address of %s but got %s\n",
179                        iface_best_ip("127.0.0.1"), srv_addr ? srv_addr->addr : NULL);
180                 return False;
181         }
182
183         printf("server port is %d\n", srv_addr->port);
184
185         status = socket_connect_ev(sock2, NULL, srv_addr, 0, ev);
186         CHECK_STATUS(status, NT_STATUS_OK);
187
188         status = socket_accept(sock1, &sock3);
189         CHECK_STATUS(status, NT_STATUS_OK);
190         talloc_steal(mem_ctx, sock3);
191         talloc_free(sock1);
192
193         blob  = data_blob_talloc(mem_ctx, NULL, size);
194         blob2 = data_blob_talloc(mem_ctx, NULL, size);
195         generate_random_buffer(blob.data, blob.length);
196
197         sent = size;
198         status = socket_send(sock2, &blob, &sent, 0);
199         CHECK_STATUS(status, NT_STATUS_OK);
200
201         status = socket_recv(sock3, blob2.data, size, &nread, 0);
202         CHECK_STATUS(status, NT_STATUS_OK);
203
204         from_addr = socket_get_peer_addr(sock3, mem_ctx);
205
206         if (!from_addr || !from_addr->addr) {
207                 printf("Unexpected recvfrom addr NULL\n");
208                 return False;
209         }
210         if (strcmp(from_addr->addr, srv_addr->addr) != 0) {
211                 printf("Unexpected recvfrom addr %s\n", from_addr ? from_addr->addr : NULL);
212                 ret = False;
213         }
214         if (nread != size) {
215                 printf("Unexpected recvfrom size %d should be %d\n", (int)nread, (int)size);
216                 ret = False;
217         }
218
219         if (memcmp(blob2.data, blob.data, size) != 0) {
220                 printf("Bad data in recvfrom\n");
221                 ret = False;
222         }
223
224         generate_random_buffer(blob.data, blob.length);
225         status = socket_send(sock3, &blob, &sent, 0);
226         CHECK_STATUS(status, NT_STATUS_OK);
227
228         status = socket_recv(sock2, blob2.data, size, &nread, 0);
229         CHECK_STATUS(status, NT_STATUS_OK);
230
231         from_addr = socket_get_peer_addr(sock2, mem_ctx);
232
233         if (!from_addr || !from_addr->addr) {
234                 printf("Unexpected recvfrom addr NULL\n");
235                 return False;
236         }
237         if (strcmp(from_addr->addr, srv_addr->addr) != 0) {
238                 printf("Unexpected recvfrom addr %s\n", from_addr ? from_addr->addr : NULL);
239                 ret = False;
240         }
241         if (nread != size) {
242                 printf("Unexpected recvfrom size %d should be %d\n", (int)nread, (int)size);
243                 ret = False;
244         }
245         if (from_addr->port != srv_addr->port) {
246                 printf("Unexpected recvfrom port %d should be %d\n", 
247                        from_addr->port, srv_addr->port);
248                 ret = False;
249         }
250         if (memcmp(blob2.data, blob.data, size) != 0) {
251                 printf("Bad data in recvfrom\n");
252                 ret = False;
253         }
254
255 done:
256
257         return ret;
258 }
259
260 BOOL torture_local_socket(struct torture_context *torture) 
261 {
262         BOOL ret = True;
263         TALLOC_CTX *mem_ctx = talloc_new(NULL);
264
265         ret &= test_udp(mem_ctx);
266         ret &= test_tcp(mem_ctx);
267
268         return ret;
269 }