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