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