1/*
2 * hostapd / Wi-Fi Simple Configuration
3 * Code copied from Intel SDK
4 * Copyright (C) 2010, Broadcom Corporation. All Rights Reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
13 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
15 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
16 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * $Id: UdpLib.c,v 1.8 2008/11/11 07:17:53 Exp $
18 * Copyright (c) 2005 Intel Corporation. All rights reserved.
19 * Contact Information: Harsha Hegde  <harsha.hegde@intel.com>
20 *
21 * This program is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License version 2 as
23 * published by the Free Software Foundation.
24 *
25 * Alternatively, this software may be distributed under the terms of BSD
26 * license.
27 *
28 * See README, README_WSC and COPYING for more details.
29 */
30
31#include <stdio.h>
32#include <stdarg.h>
33#include <unistd.h>
34#include <errno.h>
35
36#include <sys/types.h>
37#include <sys/socket.h>
38
39
40/* Linux/eCos/NetBSD specific headers */
41#if defined(linux) || defined(__ECOS) || defined(__NetBSD__)
42#include <sys/time.h>
43#endif /* linux */
44
45#include <netinet/in.h>
46#include <UdpLib.h>
47
48/* Comment out the next line if debug strings are not needed */
49/* #define U_DEBUG */
50
51void DEBUGF(char *, ...);
52
53
54/*
55 * udp_open()
56 *
57 * This function opens a UDP socket and returns the socket to the calling
58 * application. The application will use this socket in any subsequent calls.
59 *
60 * Returns socket handle on success or -1 if there is an error.
61 */
62int udp_open()
63{
64	int        new_sock;     /* temporary socket handle */
65#ifdef _WIN32_REAL
66	int           retval;
67	WSADATA       wsa_data;
68#endif // _WIN32_REAL
69
70	DEBUGF("Entered udp_open\n");
71
72#ifdef _WIN32_REAL
73	retval = WSAStartup(MAKEWORD(2, 0), &wsa_data);
74	if (retval != 0)
75	{
76		DEBUGF("WSAStartup call failed.\n");
77		return -1;
78	}
79#endif /*  _WIN32_REAL */
80
81	/* create INTERNET, udp datagram socket */
82	new_sock = (int) socket(AF_INET, SOCK_DGRAM, 0);
83
84	if (new_sock < 0) {
85		DEBUGF("socket call failed.\n");
86		return -1;
87	}
88
89	DEBUGF("Socket open successful, sd: %d\n", new_sock);
90
91	return new_sock;
92}
93
94
95/*
96 * udp_bind(int fd, int portno)
97 *
98 * This call is used typically by the server application to establish a
99 * well known port.
100 *
101 * Returns 1 if succeeds and returns -1 in case of an error.
102*/
103int udp_bind(int fd, int portno)
104{
105	struct sockaddr_in binder;
106
107	DEBUGF("Entered udp_bind\n");
108
109	binder.sin_family = AF_INET;
110	binder.sin_addr.s_addr = INADDR_ANY;
111	binder.sin_port = htons(portno);
112
113	/* bind protocol to socket */
114	if (bind(fd, (struct sockaddr *)&binder, sizeof(binder)))
115	{
116		DEBUGF("bind call for socket [%d] failed.\n", fd);
117		return -1;
118	}
119
120	DEBUGF("Binding successful for socket [%d]\n", fd);
121
122	return 1;
123}
124
125
126/*
127 * udp_close(int fd)
128 *
129 * Closes a UDP session. Closes the socket and returns.
130 */
131void udp_close(int fd)
132{
133	DEBUGF("Entered udp_close\n");
134
135#ifdef _WIN32_REAL
136	WSACleanup();
137	closesocket(fd);
138#endif // _WIN32_REAL
139
140#if defined(__linux__) || defined(__ECOS)
141	close(fd);
142#endif
143
144	return;
145}
146
147
148/*
149 * udp_write(int fd, char * buf, int len, struct sockaddr_in * to)
150 *
151 * This function is called by the application to send data.
152 * fd - socket handle
153 * buf - data buffer
154 * len - byte count of data in buf
155 * to - socket address structure that contains remote ip address and port
156 *      where the data is to be sent
157 *
158 * Returns bytesSent if succeeded. If there is an error -1 is returned
159 */
160int udp_write(int fd, char * buf, int len, struct sockaddr_in * to)
161{
162	int            bytes_sent;
163
164	DEBUGF("Entered udp_write: len %d\n", len);
165	bytes_sent = sendto(fd, buf, len, 0,
166	                    (struct sockaddr *) to,
167	                    sizeof(struct sockaddr_in));
168	if (bytes_sent < 0)
169	{
170		DEBUGF("sendto on socket %d failed\n", fd);
171		return -1;
172	}
173	return bytes_sent;
174}
175
176
177/*
178 * udp_read(int fd, char * buf, int len, struct sockaddr_in * from)
179 *
180 * This function is called by the application to receive data.
181 * fd - socket handle
182 * buf - data buffer in which the received data will be put
183 * len - size of buf in bytes
184 * from - socket address structure that contains remote ip address and port
185 *        from where the data is received
186 *
187 * Returns bytes received if succeeded. If there is an error -1 is returned
188 */
189int udp_read(int fd, char * buf, int len, struct sockaddr_in * from)
190{
191	int bytes_recd = 0;
192	unsigned int fromlen = 0;
193	fd_set        fdvar;
194	int            sel_ret;
195
196	DEBUGF("Entered udp_read\n");
197
198	FD_ZERO(&fdvar);
199	/* we have to wait for only one descriptor */
200	FD_SET(fd, &fdvar);
201
202	sel_ret = select(fd + 1, &fdvar, (fd_set *) 0, (fd_set *) 0, NULL);
203
204	/* if select returns negative value, system error */
205	if (sel_ret < 0)
206	{
207		DEBUGF("select call failed; system error\n");
208		return -1;
209	}
210
211	/* Otherwise Read notification might has come, since we are
212	   waiting for only one fd we need not check the bit. Go ahead
213	   and read the packet
214	*/
215	fromlen = sizeof(struct sockaddr_in);
216	bytes_recd = recvfrom(fd, buf, len, 0,
217	                      (struct sockaddr *)from, &fromlen);
218	if (bytes_recd < 0)
219	{
220		DEBUGF("recvfrom on socket %d failed\n", fd);
221		return -1;
222	}
223
224	DEBUGF("Read %d bytes\n", bytes_recd);
225
226	return bytes_recd;
227}
228
229/*
230 * udp_read_timed(int fd, char * buf, int len,
231 *                 struct sockaddr_in * from, int timeout)
232 *
233 * This function is called by the application to receive data.
234 * fd - socket handle
235 * buf - data buffer in which the received data will be put
236 * len - size of buf in bytes
237 * from - socket address structure that contains remote ip address and port
238 *        from where the data is received
239 * timeout - wait time in seconds
240 *
241 * Returns bytes received if succeeded. If there is an error -1 is returned
242 */
243
244int udp_read_timed(int fd, char * buf, int len,
245                   struct sockaddr_in * from, int timeout)
246{
247	int bytes_recd = 0;
248	unsigned int fromlen = 0;
249	fd_set        fdvar;
250	int            sel_ret;
251	struct timeval tv;
252
253	DEBUGF("Entered udp_read\n");
254
255	tv.tv_sec = timeout;
256	tv.tv_usec = 0;
257
258	FD_ZERO(&fdvar);
259	/* we have to wait for only one descriptor */
260	FD_SET(fd, &fdvar);
261	sel_ret = select(fd + 1, &fdvar, (fd_set *) 0, (fd_set *) 0, &tv);
262	/* if select returns negative value, system error */
263	if (sel_ret < 0)
264	{
265		DEBUGF("select call failed; system error\n");
266		return -1;
267	}
268	else if (sel_ret == 0)
269	{
270		DEBUGF("select call timed out\n");
271		return -1;
272	}
273
274	/* Otherwise Read notification might has come, since we are
275	   waiting for only one fd we need not check the bit. Go ahead
276	   and read the packet
277	*/
278	fromlen = sizeof(struct sockaddr_in);
279	bytes_recd = recvfrom(fd, buf, len, 0,
280	                      (struct sockaddr *)from, &fromlen);
281	if (bytes_recd < 0)
282	{
283		DEBUGF("recvfrom on socket %d failed\n", fd);
284		return -1;
285	}
286
287	DEBUGF("Read %d bytes\n", bytes_recd);
288
289	return bytes_recd;
290}
291
292void DEBUGF(char * strFormat, ...)
293{
294#ifdef U_DEBUG
295	char     szTraceMsg[1000];
296	va_list  lpArgv;
297
298	va_start(lpArgv, strFormat);
299	vsprintf(szTraceMsg, strFormat, lpArgv);
300	va_end(lpArgv);
301
302	fprintf(stdout, "UdpLib: %s", szTraceMsg);
303#endif
304}
305