blob: 586a1b21d4ddff088fc79e867c4c7e67c80c0080 [file] [log] [blame]
Manuel Pégourié-Gonnardcb4137b2014-09-04 14:55:28 +02001/*
2 * UDP proxy: emulate an unreliable UDP connexion for DTLS testing
3 *
4 * Copyright (C) 2006-2014, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#if !defined(POLARSSL_CONFIG_FILE)
27#include "polarssl/config.h"
28#else
29#include POLARSSL_CONFIG_FILE
30#endif
31
32#if !defined(POLARSSL_NET_C)
33#include <stdio.h>
34int main( void )
35{
36 printf( "POLARSSL_NET_C not defined.\n" );
37 return( 0 );
38}
39#else
40
41#include "polarssl/net.h"
42#include "polarssl/error.h"
43
44#include <stdio.h>
45#include <stdlib.h>
46
47/* For select() */
48#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
49 !defined(EFI32)
50#include <winsock2.h>
51#include <windows.h>
52#if defined(_MSC_VER)
53#if defined(_WIN32_WCE)
54#pragma comment( lib, "ws2.lib" )
55#else
56#pragma comment( lib, "ws2_32.lib" )
57#endif
58#endif /* _MSC_VER */
59#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
60#include <sys/time.h>
61#include <sys/types.h>
62#include <unistd.h>
63#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
64
65#define MAX_MSG_SIZE 18445 /* 2^14 + 2048 + 13 */
66
67#define DFL_SERVER_ADDR "localhost"
68#define DFL_SERVER_PORT 4433
69#define DFL_LISTEN_ADDR "localhost"
70#define DFL_LISTEN_PORT 5556
71
72/*
73 * global options
74 */
75struct options
76{
77 const char *server_addr; /* address to forward packets to */
78 int server_port; /* port to forward packets to */
79 const char *listen_addr; /* address for accepting client connections */
80 int listen_port; /* port for accepting client connections */
81} opt;
82
83#define USAGE \
84 "\n usage: udp_proxy param=<>...\n" \
85 "\n acceptable parameters:\n" \
86 " server_addr=%%d default: localhost\n" \
87 " server_port=%%d default: 4433\n" \
88 " listen_addr=%%d default: localhost\n" \
89 " listen_port=%%d default: 4433\n" \
90 "\n"
91
92static void exit_usage( void )
93{
94 printf( USAGE );
95 exit( 1 );
96}
97
98static void get_options( int argc, char *argv[] )
99{
100 int i;
101 char *p, *q;
102
103 opt.server_addr = DFL_SERVER_ADDR;
104 opt.server_port = DFL_SERVER_PORT;
105 opt.listen_addr = DFL_LISTEN_ADDR;
106 opt.listen_port = DFL_LISTEN_PORT;
107
108 for( i = 1; i < argc; i++ )
109 {
110 p = argv[i];
111 if( ( q = strchr( p, '=' ) ) == NULL )
112 exit_usage();
113 *q++ = '\0';
114
115 if( strcmp( p, "server_addr" ) == 0 )
116 opt.server_addr = q;
117 else if( strcmp( p, "server_port" ) == 0 )
118 {
119 opt.server_port = atoi( q );
120 if( opt.server_port < 1 || opt.server_port > 65535 )
121 exit_usage();
122 }
123 else if( strcmp( p, "listen_addr" ) == 0 )
124 opt.listen_addr = q;
125 else if( strcmp( p, "listen_port" ) == 0 )
126 {
127 opt.listen_port = atoi( q );
128 if( opt.listen_port < 1 || opt.listen_port > 65535 )
129 exit_usage();
130 }
131 else
132 exit_usage();
133 }
134}
135
136int handle_message( const char *way, int dst, int src )
137{
138 unsigned char buf[MAX_MSG_SIZE] = { 0 };
139 int ret;
140 size_t len;
141
142 if( ( ret = net_recv( &src, buf, sizeof( buf ) ) ) <= 0 )
143 {
144 printf( " ! net_recv returned %d\n", ret );
145 return( ret );
146 }
147
148 printf( " .. %s: %d bytes forwarded\n", way, ret );
149
150 len = (size_t) ret;
151
152 if( ( ret = net_send( &dst, buf, len ) ) <= 0 )
153 {
154 printf( " ! net_send returned %d\n", ret );
155 return( ret );
156 }
157
158 fflush( stdout );
159 return( 0 );
160}
161
162int main( int argc, char *argv[] )
163{
164 int ret;
165
166 int listen_fd = -1;
167 int client_fd = -1;
168 int server_fd = -1;
169
170 int nb_fds;
171 fd_set read_fds;
172
173 get_options( argc, argv );
174
175 /*
176 * 0. Connect to the server
177 */
178 printf( " . Connect to server on UDP/%s/%d ...",
179 opt.server_addr, opt.server_port );
180 fflush( stdout );
181
182 if( ( ret = net_connect( &server_fd, opt.server_addr, opt.server_port,
183 NET_PROTO_UDP ) ) != 0 )
184 {
185 printf( " failed\n ! net_connect returned %d\n\n", ret );
186 goto exit;
187 }
188
189 printf( " ok\n" );
190
191 /*
192 * 1. Setup the "listening" UDP socket
193 */
194 printf( " . Bind on UDP/%s/%d ...",
195 opt.listen_addr, opt.listen_port );
196 fflush( stdout );
197
198 if( ( ret = net_bind( &listen_fd, opt.listen_addr, opt.listen_port,
199 NET_PROTO_UDP ) ) != 0 )
200 {
201 printf( " failed\n ! net_bind returned %d\n\n", ret );
202 goto exit;
203 }
204
205 printf( " ok\n" );
206
207 /*
208 * 2. Wait until a client connects
209 */
210 printf( " . Waiting for a remote connection ..." );
211 fflush( stdout );
212
213 if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
214 {
215 printf( " failed\n ! net_accept returned %d\n\n", ret );
216 goto exit;
217 }
218
219 printf( " ok\n" );
220 fflush( stdout );
221
222 /*
223 * 3. Forward packets forever (kill the process to terminate it)
224 */
225 nb_fds = ( client_fd > server_fd ? client_fd : server_fd ) + 1;
226
227 while( 1 )
228 {
229 FD_ZERO( &read_fds );
230 FD_SET( server_fd, &read_fds );
231 FD_SET( client_fd, &read_fds );
232
233 if( ( ret = select( nb_fds, &read_fds, NULL, NULL, NULL ) ) <= 0 )
234 {
235 perror( "select" );
236 goto exit;
237 }
238
239 if( FD_ISSET( client_fd, &read_fds ) )
240 {
241 if( ( ret = handle_message( "c2s", server_fd, client_fd ) ) != 0 )
242 goto exit;
243 }
244
245 if( FD_ISSET( server_fd, &read_fds ) )
246 {
247 if( ( ret = handle_message( "s2c", client_fd, server_fd ) ) != 0 )
248 goto exit;
249 }
250 }
251
252exit:
253
254#ifdef POLARSSL_ERROR_C
255 if( ret != 0 )
256 {
257 char error_buf[100];
258 polarssl_strerror( ret, error_buf, 100 );
259 printf( "Last error was: -0x%04X - %s\n\n", - ret, error_buf );
260 fflush( stdout );
261 }
262#endif
263
264 if( client_fd != -1 )
265 net_close( client_fd );
266
267 if( listen_fd != -1 )
268 net_close( listen_fd );
269
270#if defined(_WIN32)
271 printf( " Press Enter to exit this program.\n" );
272 fflush( stdout ); getchar();
273#endif
274
275 return( ret != 0 );
276}
277
278#endif /* POLARSSL_NET_C */