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