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